1 // Copyright (c) 2012 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/google/google_url_tracker_navigation_helper_impl.h" 6 7 #include "chrome/browser/chrome_notification_types.h" 8 #include "chrome/browser/google/google_url_tracker.h" 9 #include "chrome/browser/infobars/infobar_service.h" 10 #include "content/public/browser/navigation_controller.h" 11 #include "content/public/browser/navigation_entry.h" 12 #include "content/public/browser/notification_service.h" 13 #include "content/public/browser/web_contents.h" 14 15 GoogleURLTrackerNavigationHelperImpl:: 16 GoogleURLTrackerNavigationHelperImpl() : tracker_(NULL) { 17 } 18 19 GoogleURLTrackerNavigationHelperImpl:: 20 ~GoogleURLTrackerNavigationHelperImpl() { 21 } 22 23 void GoogleURLTrackerNavigationHelperImpl::SetGoogleURLTracker( 24 GoogleURLTracker* tracker) { 25 DCHECK(tracker); 26 tracker_ = tracker; 27 } 28 29 void GoogleURLTrackerNavigationHelperImpl::SetListeningForNavigationStart( 30 bool listen) { 31 if (listen) { 32 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_PENDING, 33 content::NotificationService::AllBrowserContextsAndSources()); 34 } else { 35 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_PENDING, 36 content::NotificationService::AllBrowserContextsAndSources()); 37 } 38 } 39 40 bool GoogleURLTrackerNavigationHelperImpl::IsListeningForNavigationStart() { 41 return registrar_.IsRegistered(this, content::NOTIFICATION_NAV_ENTRY_PENDING, 42 content::NotificationService::AllBrowserContextsAndSources()); 43 } 44 45 void GoogleURLTrackerNavigationHelperImpl::SetListeningForNavigationCommit( 46 const content::NavigationController* nav_controller, 47 bool listen) { 48 content::NotificationSource navigation_controller_source = 49 content::Source<content::NavigationController>(nav_controller); 50 if (listen) { 51 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, 52 navigation_controller_source); 53 } else { 54 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, 55 navigation_controller_source); 56 } 57 } 58 59 bool GoogleURLTrackerNavigationHelperImpl::IsListeningForNavigationCommit( 60 const content::NavigationController* nav_controller) { 61 content::NotificationSource navigation_controller_source = 62 content::Source<content::NavigationController>(nav_controller); 63 return registrar_.IsRegistered( 64 this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, 65 navigation_controller_source); 66 } 67 68 void GoogleURLTrackerNavigationHelperImpl::SetListeningForTabDestruction( 69 const content::NavigationController* nav_controller, 70 bool listen) { 71 content::NotificationSource navigation_controller_source = 72 content::Source<content::NavigationController>(nav_controller); 73 if (listen) { 74 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 75 GetWebContentsSource(navigation_controller_source)); 76 } else { 77 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 78 GetWebContentsSource(navigation_controller_source)); 79 } 80 } 81 82 bool GoogleURLTrackerNavigationHelperImpl::IsListeningForTabDestruction( 83 const content::NavigationController* nav_controller) { 84 content::NotificationSource navigation_controller_source = 85 content::Source<content::NavigationController>(nav_controller); 86 return registrar_.IsRegistered( 87 this, 88 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 89 GetWebContentsSource(navigation_controller_source)); 90 } 91 92 content::NotificationSource 93 GoogleURLTrackerNavigationHelperImpl::GetWebContentsSource( 94 const content::NotificationSource& nav_controller_source) { 95 content::NavigationController* controller = 96 content::Source<content::NavigationController>( 97 nav_controller_source).ptr(); 98 content::WebContents* web_contents = controller->GetWebContents(); 99 return content::Source<content::WebContents>(web_contents); 100 } 101 102 void GoogleURLTrackerNavigationHelperImpl::Observe( 103 int type, 104 const content::NotificationSource& source, 105 const content::NotificationDetails& details) { 106 switch (type) { 107 case content::NOTIFICATION_NAV_ENTRY_PENDING: { 108 content::NavigationController* controller = 109 content::Source<content::NavigationController>(source).ptr(); 110 content::WebContents* web_contents = controller->GetWebContents(); 111 InfoBarService* infobar_service = 112 InfoBarService::FromWebContents(web_contents); 113 // Because we're listening to all sources, there may be no 114 // InfoBarService for some notifications, e.g. navigations in 115 // bubbles/balloons etc. 116 if (infobar_service) { 117 tracker_->OnNavigationPending( 118 controller, infobar_service, 119 controller->GetPendingEntry()->GetUniqueID()); 120 } 121 break; 122 } 123 124 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: { 125 content::NavigationController* controller = 126 content::Source<content::NavigationController>(source).ptr(); 127 // Here we're only listening to notifications where we already know 128 // there's an associated InfoBarService. 129 content::WebContents* web_contents = controller->GetWebContents(); 130 InfoBarService* infobar_service = 131 InfoBarService::FromWebContents(web_contents); 132 DCHECK(infobar_service); 133 const GURL& search_url = controller->GetActiveEntry()->GetURL(); 134 if (!search_url.is_valid()) // Not clear if this can happen. 135 tracker_->OnTabClosed(controller); 136 tracker_->OnNavigationCommitted(infobar_service, search_url); 137 break; 138 } 139 140 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { 141 content::WebContents* web_contents = 142 content::Source<content::WebContents>(source).ptr(); 143 tracker_->OnTabClosed(&web_contents->GetController()); 144 break; 145 } 146 147 default: 148 NOTREACHED() << "Unknown notification received:" << type; 149 } 150 } 151