1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/sync/sessions/sync_sessions_router_tab_helper.h"
6 
7 #include "base/feature_list.h"
8 #include "base/memory/ptr_util.h"
9 #include "chrome/browser/sync/sessions/sync_sessions_web_contents_router.h"
10 #include "components/favicon/content/content_favicon_driver.h"
11 #include "components/language/core/common/language_experiments.h"
12 #include "components/sessions/content/session_tab_helper.h"
13 #include "components/sync_sessions/synced_tab_delegate.h"
14 #include "content/public/browser/navigation_entry.h"
15 #include "content/public/browser/navigation_handle.h"
16 #include "content/public/browser/render_frame_host.h"
17 #include "ui/gfx/image/image_skia.h"
18 
19 namespace sync_sessions {
20 
21 // static
CreateForWebContents(content::WebContents * web_contents,SyncSessionsWebContentsRouter * router)22 void SyncSessionsRouterTabHelper::CreateForWebContents(
23     content::WebContents* web_contents,
24     SyncSessionsWebContentsRouter* router) {
25   DCHECK(web_contents);
26   if (!FromWebContents(web_contents)) {
27     web_contents->SetUserData(UserDataKey(),
28                               base::WrapUnique(new SyncSessionsRouterTabHelper(
29                                   web_contents, router)));
30   }
31 }
32 
SyncSessionsRouterTabHelper(content::WebContents * web_contents,SyncSessionsWebContentsRouter * router)33 SyncSessionsRouterTabHelper::SyncSessionsRouterTabHelper(
34     content::WebContents* web_contents,
35     SyncSessionsWebContentsRouter* router)
36     : content::WebContentsObserver(web_contents), router_(router) {
37   chrome_translate_client_ =
38       ChromeTranslateClient::FromWebContents(web_contents);
39   // A translate client is not always attached to web contents (e.g. tests).
40   if (chrome_translate_client_)
41     chrome_translate_client_->translate_driver()->AddObserver(this);
42 
43   favicon_driver_ =
44       favicon::ContentFaviconDriver::FromWebContents(web_contents);
45   if (favicon_driver_)
46     favicon_driver_->AddObserver(this);
47 }
48 
~SyncSessionsRouterTabHelper()49 SyncSessionsRouterTabHelper::~SyncSessionsRouterTabHelper() {}
50 
DidFinishNavigation(content::NavigationHandle * navigation_handle)51 void SyncSessionsRouterTabHelper::DidFinishNavigation(
52     content::NavigationHandle* navigation_handle) {
53   if (navigation_handle && navigation_handle->IsInMainFrame())
54     NotifyRouter();
55 }
56 
TitleWasSet(content::NavigationEntry * entry)57 void SyncSessionsRouterTabHelper::TitleWasSet(content::NavigationEntry* entry) {
58   NotifyRouter();
59 }
60 
WebContentsDestroyed()61 void SyncSessionsRouterTabHelper::WebContentsDestroyed() {
62   NotifyRouter();
63   if (chrome_translate_client_)
64     chrome_translate_client_->translate_driver()->RemoveObserver(this);
65   if (favicon_driver_)
66     favicon_driver_->RemoveObserver(this);
67 }
68 
DidFinishLoad(content::RenderFrameHost * render_frame_host,const GURL & validated_url)69 void SyncSessionsRouterTabHelper::DidFinishLoad(
70     content::RenderFrameHost* render_frame_host,
71     const GURL& validated_url) {
72   // Only notify when the main frame finishes loading; only the main frame
73   // doesn't have a parent.
74   if (render_frame_host && !render_frame_host->GetParent())
75     NotifyRouter(true);
76 }
77 
DidOpenRequestedURL(content::WebContents * new_contents,content::RenderFrameHost * source_render_frame_host,const GURL & url,const content::Referrer & referrer,WindowOpenDisposition disposition,ui::PageTransition transition,bool started_from_context_menu,bool renderer_initiated)78 void SyncSessionsRouterTabHelper::DidOpenRequestedURL(
79     content::WebContents* new_contents,
80     content::RenderFrameHost* source_render_frame_host,
81     const GURL& url,
82     const content::Referrer& referrer,
83     WindowOpenDisposition disposition,
84     ui::PageTransition transition,
85     bool started_from_context_menu,
86     bool renderer_initiated) {
87   // TODO(crbug.com/1007969): This is a relic from when we actually did change
88   // something about the tab here. It should be safe to remove now.
89   NotifyRouter();
90 }
91 
OnLanguageDetermined(const translate::LanguageDetectionDetails & details)92 void SyncSessionsRouterTabHelper::OnLanguageDetermined(
93     const translate::LanguageDetectionDetails& details) {
94   if (base::FeatureList::IsEnabled(language::kNotifySyncOnLanguageDetermined))
95     NotifyRouter();
96 }
97 
NotifyRouter(bool page_load_completed)98 void SyncSessionsRouterTabHelper::NotifyRouter(bool page_load_completed) {
99   if (router_)
100     router_->NotifyTabModified(web_contents(), page_load_completed);
101 }
102 
OnFaviconUpdated(favicon::FaviconDriver * favicon_driver,FaviconDriverObserver::NotificationIconType notification_icon_type,const GURL & icon_url,bool icon_url_changed,const gfx::Image & image)103 void SyncSessionsRouterTabHelper::OnFaviconUpdated(
104     favicon::FaviconDriver* favicon_driver,
105     FaviconDriverObserver::NotificationIconType notification_icon_type,
106     const GURL& icon_url,
107     bool icon_url_changed,
108     const gfx::Image& image) {
109   if (icon_url_changed) {
110     NotifyRouter();
111   }
112 }
113 
114 WEB_CONTENTS_USER_DATA_KEY_IMPL(SyncSessionsRouterTabHelper)
115 
116 }  // namespace sync_sessions
117