1 // Copyright 2014 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/notification_service_sessions_router.h" 6 7 #include "base/logging.h" 8 #include "chrome/browser/chrome_notification_types.h" 9 #include "chrome/browser/extensions/tab_helper.h" 10 #include "chrome/browser/favicon/favicon_changed_details.h" 11 #include "chrome/browser/profiles/profile.h" 12 #include "chrome/browser/sync/glue/sync_start_util.h" 13 #include "chrome/browser/sync/glue/synced_tab_delegate.h" 14 #include "chrome/browser/sync/sessions/sessions_util.h" 15 #include "chrome/browser/ui/browser.h" 16 #include "content/public/browser/navigation_controller.h" 17 #include "content/public/browser/navigation_entry.h" 18 #include "content/public/browser/notification_details.h" 19 #include "content/public/browser/notification_service.h" 20 #include "content/public/browser/notification_source.h" 21 #include "content/public/browser/web_contents.h" 22 23 #if defined(ENABLE_MANAGED_USERS) 24 #include "chrome/browser/supervised_user/supervised_user_service.h" 25 #include "chrome/browser/supervised_user/supervised_user_service_factory.h" 26 #endif 27 28 using content::NavigationController; 29 using content::WebContents; 30 31 namespace browser_sync { 32 33 NotificationServiceSessionsRouter::NotificationServiceSessionsRouter( 34 Profile* profile, const syncer::SyncableService::StartSyncFlare& flare) 35 : handler_(NULL), 36 profile_(profile), 37 flare_(flare), 38 weak_ptr_factory_(this) { 39 40 registrar_.Add(this, chrome::NOTIFICATION_TAB_PARENTED, 41 content::NotificationService::AllSources()); 42 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 43 content::NotificationService::AllSources()); 44 registrar_.Add(this, content::NOTIFICATION_NAV_LIST_PRUNED, 45 content::NotificationService::AllSources()); 46 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_CHANGED, 47 content::NotificationService::AllSources()); 48 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, 49 content::NotificationService::AllSources()); 50 registrar_.Add(this, 51 chrome::NOTIFICATION_TAB_CONTENTS_APPLICATION_EXTENSION_CHANGED, 52 content::NotificationService::AllSources()); 53 registrar_.Add(this, 54 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, 55 content::NotificationService::AllBrowserContextsAndSources()); 56 registrar_.Add(this, chrome::NOTIFICATION_FAVICON_CHANGED, 57 content::Source<Profile>(profile_)); 58 #if defined(ENABLE_MANAGED_USERS) 59 if (profile_->IsSupervised()) { 60 SupervisedUserService* supervised_user_service = 61 SupervisedUserServiceFactory::GetForProfile(profile_); 62 supervised_user_service->AddNavigationBlockedCallback( 63 base::Bind(&NotificationServiceSessionsRouter::OnNavigationBlocked, 64 weak_ptr_factory_.GetWeakPtr())); 65 } 66 #endif 67 } 68 69 NotificationServiceSessionsRouter::~NotificationServiceSessionsRouter() {} 70 71 void NotificationServiceSessionsRouter::Observe( 72 int type, 73 const content::NotificationSource& source, 74 const content::NotificationDetails& details) { 75 switch (type) { 76 case chrome::NOTIFICATION_FAVICON_CHANGED: { 77 content::Details<FaviconChangedDetails> favicon_details(details); 78 if (handler_) 79 handler_->OnFaviconPageUrlsUpdated(favicon_details->urls); 80 return; 81 } 82 // Source<WebContents>. 83 case chrome::NOTIFICATION_TAB_PARENTED: 84 case content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME: 85 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { 86 WebContents* web_contents = content::Source<WebContents>(source).ptr(); 87 SyncedTabDelegate* tab = 88 SyncedTabDelegate::ImplFromWebContents(web_contents); 89 if (!tab || tab->profile() != profile_) 90 return; 91 if (handler_) 92 handler_->OnLocalTabModified(tab); 93 if (!sessions_util::ShouldSyncTab(*tab)) 94 return; 95 break; 96 } 97 // Source<NavigationController>. 98 case content::NOTIFICATION_NAV_LIST_PRUNED: 99 case content::NOTIFICATION_NAV_ENTRY_CHANGED: 100 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: { 101 SyncedTabDelegate* tab = SyncedTabDelegate::ImplFromWebContents( 102 content::Source<NavigationController>(source).ptr()-> 103 GetWebContents()); 104 if (!tab || tab->profile() != profile_) 105 return; 106 if (handler_) 107 handler_->OnLocalTabModified(tab); 108 if (!sessions_util::ShouldSyncTab(*tab)) 109 return; 110 break; 111 } 112 case chrome::NOTIFICATION_TAB_CONTENTS_APPLICATION_EXTENSION_CHANGED: { 113 extensions::TabHelper* extension_tab_helper = 114 content::Source<extensions::TabHelper>(source).ptr(); 115 if (extension_tab_helper->web_contents()->GetBrowserContext() != 116 profile_) { 117 return; 118 } 119 if (extension_tab_helper->extension_app()) { 120 SyncedTabDelegate* tab = SyncedTabDelegate::ImplFromWebContents( 121 extension_tab_helper->web_contents()); 122 if (!tab || tab->profile() != profile_) 123 return; 124 if (handler_) 125 handler_->OnLocalTabModified(tab); 126 break; 127 } 128 return; 129 } 130 default: 131 LOG(ERROR) << "Received unexpected notification of type " << type; 132 return; 133 } 134 135 if (!flare_.is_null()) { 136 flare_.Run(syncer::SESSIONS); 137 flare_.Reset(); 138 } 139 } 140 141 void NotificationServiceSessionsRouter::OnNavigationBlocked( 142 content::WebContents* web_contents) { 143 SyncedTabDelegate* tab = 144 SyncedTabDelegate::ImplFromWebContents(web_contents); 145 if (!tab || !handler_) 146 return; 147 148 DCHECK(tab->profile() == profile_); 149 handler_->OnLocalTabModified(tab); 150 } 151 152 void NotificationServiceSessionsRouter::StartRoutingTo( 153 LocalSessionEventHandler* handler) { 154 DCHECK(!handler_); 155 handler_ = handler; 156 } 157 158 void NotificationServiceSessionsRouter::Stop() { 159 weak_ptr_factory_.InvalidateWeakPtrs(); 160 handler_ = NULL; 161 } 162 163 } // namespace browser_sync 164