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 #ifndef CHROME_BROWSER_GOOGLE_GOOGLE_URL_TRACKER_H_ 6 #define CHROME_BROWSER_GOOGLE_GOOGLE_URL_TRACKER_H_ 7 8 #include <map> 9 #include <string> 10 #include <utility> 11 12 #include "base/callback_forward.h" 13 #include "base/gtest_prod_util.h" 14 #include "base/memory/scoped_ptr.h" 15 #include "base/memory/weak_ptr.h" 16 #include "chrome/browser/google/google_url_tracker_map_entry.h" 17 #include "components/browser_context_keyed_service/browser_context_keyed_service.h" 18 #include "net/base/network_change_notifier.h" 19 #include "net/url_request/url_fetcher.h" 20 #include "net/url_request/url_fetcher_delegate.h" 21 #include "url/gurl.h" 22 23 class GoogleURLTrackerNavigationHelper; 24 class PrefService; 25 class Profile; 26 27 namespace content { 28 class NavigationController; 29 } 30 31 // This object is responsible for checking the Google URL once per network 32 // change, and if necessary prompting the user to see if they want to change to 33 // using it. The current and last prompted values are saved to prefs. 34 // 35 // Most consumers should only call GoogleURL(), which is guaranteed to 36 // synchronously return a value at all times (even during startup or in unittest 37 // mode). Consumers who need to be notified when things change should listen to 38 // the notification service for NOTIFICATION_GOOGLE_URL_UPDATED, which provides 39 // the original and updated values. 40 // 41 // To protect users' privacy and reduce server load, no updates will be 42 // performed (ever) unless at least one consumer registers interest by calling 43 // RequestServerCheck(). 44 class GoogleURLTracker : public net::URLFetcherDelegate, 45 public net::NetworkChangeNotifier::IPAddressObserver, 46 public BrowserContextKeyedService { 47 public: 48 // The contents of the Details for a NOTIFICATION_GOOGLE_URL_UPDATED. 49 typedef std::pair<GURL, GURL> UpdatedDetails; 50 51 // The constructor does different things depending on which of these values 52 // you pass it. Hopefully these are self-explanatory. 53 enum Mode { 54 NORMAL_MODE, 55 UNIT_TEST_MODE, 56 }; 57 58 // Only the GoogleURLTrackerFactory and tests should call this. No code other 59 // than the GoogleURLTracker itself should actually use 60 // GoogleURLTrackerFactory::GetForProfile(). 61 GoogleURLTracker(Profile* profile, 62 scoped_ptr<GoogleURLTrackerNavigationHelper> nav_helper, 63 Mode mode); 64 65 virtual ~GoogleURLTracker(); 66 67 // Returns the current Google URL. This will return a valid URL even if 68 // |profile| is NULL or a testing profile. 69 // 70 // This is the only function most code should ever call. 71 static GURL GoogleURL(Profile* profile); 72 73 // Requests that the tracker perform a server check to update the Google URL 74 // as necessary. If |force| is false, this will happen at most once per 75 // network change, not sooner than five seconds after startup (checks 76 // requested before that time will occur then; checks requested afterwards 77 // will occur immediately, if no other checks have been made during this run). 78 // If |force| is true, and the tracker has already performed any requested 79 // check, it will check again. 80 // 81 // When |profile| is NULL or a testing profile, this function does nothing. 82 static void RequestServerCheck(Profile* profile, bool force); 83 84 // Notifies the tracker that the user has started a Google search. 85 // If prompting is necessary, we then listen for the subsequent pending 86 // navigation to get the appropriate NavigationController. When the load 87 // commits, we'll show the infobar. 88 // 89 // When |profile| is NULL or a testing profile, this function does nothing. 90 static void GoogleURLSearchCommitted(Profile* profile); 91 92 // No one but GoogleURLTrackerInfoBarDelegate or test code should call these. 93 void AcceptGoogleURL(bool redo_searches); 94 void CancelGoogleURL(); 95 const GURL& google_url() const { return google_url_; } 96 const GURL& fetched_google_url() const { return fetched_google_url_; } 97 98 // No one but GoogleURLTrackerMapEntry should call this. 99 void DeleteMapEntryForService(const InfoBarService* infobar_service); 100 101 // Called by the navigation observer after SearchCommitted() registers 102 // listeners, to indicate that we've received the "load now pending" 103 // notification. |navigation_controller| is the NavigationController for this 104 // load; |infobar_service| is the InfoBarService of the associated tab; and 105 // |pending_id| is the unique ID of the newly pending NavigationEntry. 106 // If there is already a visible GoogleURLTracker infobar for this tab, this 107 // function resets its associated pending entry ID to the new ID. Otherwise 108 // this function creates a map entry for the associated tab. 109 virtual void OnNavigationPending( 110 content::NavigationController* navigation_controller, 111 InfoBarService* infobar_service, 112 int pending_id); 113 114 // Called by the navigation observer once a load we're watching commits. 115 // |infobar_service| is the same as for OnNavigationPending(); 116 // |search_url| is guaranteed to be valid. 117 virtual void OnNavigationCommitted(InfoBarService* infobar_service, 118 const GURL& search_url); 119 120 // Called by the navigation observer when a tab closes. 121 virtual void OnTabClosed( 122 content::NavigationController* navigation_controller); 123 124 static const char kDefaultGoogleHomepage[]; 125 static const char kSearchDomainCheckURL[]; 126 127 private: 128 friend class GoogleURLTrackerTest; 129 130 typedef std::map<const InfoBarService*, GoogleURLTrackerMapEntry*> EntryMap; 131 132 // net::URLFetcherDelegate: 133 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; 134 135 // NetworkChangeNotifier::IPAddressObserver: 136 virtual void OnIPAddressChanged() OVERRIDE; 137 138 // BrowserContextKeyedService: 139 virtual void Shutdown() OVERRIDE; 140 141 // Registers consumer interest in getting an updated URL from the server. 142 // Observe chrome::NOTIFICATION_GOOGLE_URL_UPDATED to be notified when the URL 143 // changes. 144 void SetNeedToFetch(); 145 146 // Called when the five second startup sleep has finished. Runs any pending 147 // fetch. 148 void FinishSleep(); 149 150 // Starts the fetch of the up-to-date Google URL if we actually want to fetch 151 // it and can currently do so. 152 void StartFetchIfDesirable(); 153 154 // Called each time the user performs a search. This checks whether we need 155 // to prompt the user about a domain change, and if so, starts listening for 156 // the notifications sent when the actual load is triggered. 157 void SearchCommitted(); 158 159 // Closes all map entries. If |redo_searches| is true, this also triggers 160 // each tab with an infobar to re-perform the user's search, but on the new 161 // Google TLD. 162 void CloseAllEntries(bool redo_searches); 163 164 // Unregisters any listeners for the navigation controller in |map_entry|. 165 // This sanity-DCHECKs that these are registered (or not) in the specific 166 // cases we expect. (|must_be_listening_for_commit| is used purely for this 167 // sanity-checking.) This also unregisters the global navigation pending 168 // listener if there are no remaining listeners for navigation commits, as we 169 // no longer need them until another search is committed. 170 void UnregisterForEntrySpecificNotifications( 171 const GoogleURLTrackerMapEntry& map_entry, 172 bool must_be_listening_for_commit); 173 174 Profile* profile_; 175 176 scoped_ptr<GoogleURLTrackerNavigationHelper> nav_helper_; 177 178 // Creates an infobar delegate and adds it to the provided InfoBarService. 179 // Returns the delegate pointer on success or NULL on failure. The caller 180 // does not own the returned object, the InfoBarService does. 181 base::Callback<GoogleURLTrackerInfoBarDelegate*( 182 InfoBarService*, 183 GoogleURLTracker*, 184 const GURL&)> infobar_creator_; 185 186 GURL google_url_; 187 GURL fetched_google_url_; 188 base::WeakPtrFactory<GoogleURLTracker> weak_ptr_factory_; 189 scoped_ptr<net::URLFetcher> fetcher_; 190 int fetcher_id_; 191 bool in_startup_sleep_; // True if we're in the five-second "no fetching" 192 // period that begins at browser start. 193 bool already_fetched_; // True if we've already fetched a URL once this run; 194 // we won't fetch again until after a restart. 195 bool need_to_fetch_; // True if a consumer actually wants us to fetch an 196 // updated URL. If this is never set, we won't 197 // bother to fetch anything. 198 // Consumers should observe 199 // chrome::NOTIFICATION_GOOGLE_URL_UPDATED. 200 bool need_to_prompt_; // True if the last fetched Google URL is not 201 // matched with current user's default Google URL 202 // nor the last prompted Google URL. 203 bool search_committed_; // True when we're expecting a notification of a new 204 // pending search navigation. 205 EntryMap entry_map_; 206 207 DISALLOW_COPY_AND_ASSIGN(GoogleURLTracker); 208 }; 209 210 #endif // CHROME_BROWSER_GOOGLE_GOOGLE_URL_TRACKER_H_ 211