• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 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/ui/search/search_tab_helper.h"
6 
7 #include <set>
8 
9 #include "base/memory/scoped_ptr.h"
10 #include "base/metrics/histogram.h"
11 #include "base/strings/string16.h"
12 #include "base/strings/string_util.h"
13 #include "chrome/browser/chrome_notification_types.h"
14 #include "chrome/browser/history/most_visited_tiles_experiment.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/search/instant_service.h"
17 #include "chrome/browser/search/instant_service_factory.h"
18 #include "chrome/browser/search/search.h"
19 #include "chrome/browser/signin/signin_manager_factory.h"
20 #include "chrome/browser/sync/profile_sync_service.h"
21 #include "chrome/browser/sync/profile_sync_service_factory.h"
22 #include "chrome/browser/ui/app_list/app_list_util.h"
23 #include "chrome/browser/ui/browser_navigator.h"
24 #include "chrome/browser/ui/browser_window.h"
25 #include "chrome/browser/ui/omnibox/location_bar.h"
26 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
27 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
28 #include "chrome/browser/ui/omnibox/omnibox_view.h"
29 #include "chrome/browser/ui/search/instant_search_prerenderer.h"
30 #include "chrome/browser/ui/search/search_ipc_router_policy_impl.h"
31 #include "chrome/browser/ui/search/search_tab_helper_delegate.h"
32 #include "chrome/browser/ui/tab_contents/core_tab_helper.h"
33 #include "chrome/browser/ui/webui/ntp/ntp_user_data_logger.h"
34 #include "chrome/common/url_constants.h"
35 #include "components/signin/core/browser/signin_manager.h"
36 #include "content/public/browser/navigation_controller.h"
37 #include "content/public/browser/navigation_details.h"
38 #include "content/public/browser/navigation_entry.h"
39 #include "content/public/browser/navigation_type.h"
40 #include "content/public/browser/notification_service.h"
41 #include "content/public/browser/notification_source.h"
42 #include "content/public/browser/render_process_host.h"
43 #include "content/public/browser/user_metrics.h"
44 #include "content/public/browser/web_contents.h"
45 #include "content/public/common/page_transition_types.h"
46 #include "content/public/common/referrer.h"
47 #include "grit/generated_resources.h"
48 #include "net/base/net_errors.h"
49 #include "ui/base/l10n/l10n_util.h"
50 #include "url/gurl.h"
51 
52 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SearchTabHelper);
53 
54 namespace {
55 
56 // For reporting Cacheable NTP navigations.
57 enum CacheableNTPLoad {
58   CACHEABLE_NTP_LOAD_FAILED = 0,
59   CACHEABLE_NTP_LOAD_SUCCEEDED = 1,
60   CACHEABLE_NTP_LOAD_MAX = 2
61 };
62 
RecordCacheableNTPLoadHistogram(bool succeeded)63 void RecordCacheableNTPLoadHistogram(bool succeeded) {
64   UMA_HISTOGRAM_ENUMERATION("InstantExtended.CacheableNTPLoad",
65                             succeeded ? CACHEABLE_NTP_LOAD_SUCCEEDED :
66                                 CACHEABLE_NTP_LOAD_FAILED,
67                             CACHEABLE_NTP_LOAD_MAX);
68 }
69 
IsCacheableNTP(const content::WebContents * contents)70 bool IsCacheableNTP(const content::WebContents* contents) {
71   const content::NavigationEntry* entry =
72       contents->GetController().GetLastCommittedEntry();
73   return chrome::NavEntryIsInstantNTP(contents, entry) &&
74       entry->GetURL() != GURL(chrome::kChromeSearchLocalNtpUrl);
75 }
76 
IsNTP(const content::WebContents * contents)77 bool IsNTP(const content::WebContents* contents) {
78   // We can't use WebContents::GetURL() because that uses the active entry,
79   // whereas we want the visible entry.
80   const content::NavigationEntry* entry =
81       contents->GetController().GetVisibleEntry();
82   if (entry && entry->GetVirtualURL() == GURL(chrome::kChromeUINewTabURL))
83     return true;
84 
85   return chrome::IsInstantNTP(contents);
86 }
87 
IsSearchResults(const content::WebContents * contents)88 bool IsSearchResults(const content::WebContents* contents) {
89   return !chrome::GetSearchTerms(contents).empty();
90 }
91 
IsLocal(const content::WebContents * contents)92 bool IsLocal(const content::WebContents* contents) {
93   if (!contents)
94     return false;
95   const content::NavigationEntry* entry =
96       contents->GetController().GetVisibleEntry();
97   return entry && entry->GetURL() == GURL(chrome::kChromeSearchLocalNtpUrl);
98 }
99 
100 // Returns true if |contents| are rendered inside an Instant process.
InInstantProcess(Profile * profile,const content::WebContents * contents)101 bool InInstantProcess(Profile* profile,
102                       const content::WebContents* contents) {
103   if (!profile || !contents)
104     return false;
105 
106   InstantService* instant_service =
107       InstantServiceFactory::GetForProfile(profile);
108   return instant_service &&
109       instant_service->IsInstantProcess(
110           contents->GetRenderProcessHost()->GetID());
111 }
112 
113 // Called when an NTP finishes loading. If the load start time was noted,
114 // calculates and logs the total load time.
RecordNewTabLoadTime(content::WebContents * contents)115 void RecordNewTabLoadTime(content::WebContents* contents) {
116   CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents);
117   if (core_tab_helper->new_tab_start_time().is_null())
118     return;
119 
120   base::TimeDelta duration =
121       base::TimeTicks::Now() - core_tab_helper->new_tab_start_time();
122   UMA_HISTOGRAM_TIMES("Tab.NewTabOnload", duration);
123   core_tab_helper->set_new_tab_start_time(base::TimeTicks());
124 }
125 
126 // Returns true if the user is signed in and full history sync is enabled,
127 // and false otherwise.
IsHistorySyncEnabled(Profile * profile)128 bool IsHistorySyncEnabled(Profile* profile) {
129   ProfileSyncService* sync =
130       ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
131   return sync &&
132       sync->sync_initialized() &&
133       sync->GetActiveDataTypes().Has(syncer::HISTORY_DELETE_DIRECTIVES);
134 }
135 
136 }  // namespace
137 
SearchTabHelper(content::WebContents * web_contents)138 SearchTabHelper::SearchTabHelper(content::WebContents* web_contents)
139     : WebContentsObserver(web_contents),
140       is_search_enabled_(chrome::IsInstantExtendedAPIEnabled()),
141       web_contents_(web_contents),
142       ipc_router_(web_contents, this,
143                   make_scoped_ptr(new SearchIPCRouterPolicyImpl(web_contents))
144                       .PassAs<SearchIPCRouter::Policy>()),
145       instant_service_(NULL),
146       delegate_(NULL) {
147   if (!is_search_enabled_)
148     return;
149 
150   instant_service_ =
151       InstantServiceFactory::GetForProfile(
152           Profile::FromBrowserContext(web_contents_->GetBrowserContext()));
153   if (instant_service_)
154     instant_service_->AddObserver(this);
155 }
156 
~SearchTabHelper()157 SearchTabHelper::~SearchTabHelper() {
158   if (instant_service_)
159     instant_service_->RemoveObserver(this);
160 }
161 
InitForPreloadedNTP()162 void SearchTabHelper::InitForPreloadedNTP() {
163   UpdateMode(true, true);
164 }
165 
OmniboxInputStateChanged()166 void SearchTabHelper::OmniboxInputStateChanged() {
167   if (!is_search_enabled_)
168     return;
169 
170   UpdateMode(false, false);
171 }
172 
OmniboxFocusChanged(OmniboxFocusState state,OmniboxFocusChangeReason reason)173 void SearchTabHelper::OmniboxFocusChanged(OmniboxFocusState state,
174                                           OmniboxFocusChangeReason reason) {
175   content::NotificationService::current()->Notify(
176       chrome::NOTIFICATION_OMNIBOX_FOCUS_CHANGED,
177       content::Source<SearchTabHelper>(this),
178       content::NotificationService::NoDetails());
179 
180   ipc_router_.OmniboxFocusChanged(state, reason);
181 
182   // Don't send oninputstart/oninputend updates in response to focus changes
183   // if there's a navigation in progress. This prevents Chrome from sending
184   // a spurious oninputend when the user accepts a match in the omnibox.
185   if (web_contents_->GetController().GetPendingEntry() == NULL) {
186     ipc_router_.SetInputInProgress(IsInputInProgress());
187 
188     InstantSearchPrerenderer* prerenderer =
189         InstantSearchPrerenderer::GetForProfile(profile());
190     if (!prerenderer || !chrome::ShouldPrerenderInstantUrlOnOmniboxFocus())
191       return;
192 
193     if (state == OMNIBOX_FOCUS_NONE) {
194       prerenderer->Cancel();
195       return;
196     }
197 
198     if (!IsSearchResultsPage()) {
199       prerenderer->Init(
200           web_contents_->GetController().GetSessionStorageNamespaceMap(),
201           web_contents_->GetContainerBounds().size());
202     }
203   }
204 }
205 
NavigationEntryUpdated()206 void SearchTabHelper::NavigationEntryUpdated() {
207   if (!is_search_enabled_)
208     return;
209 
210   UpdateMode(false, false);
211 }
212 
InstantSupportChanged(bool instant_support)213 void SearchTabHelper::InstantSupportChanged(bool instant_support) {
214   if (!is_search_enabled_)
215     return;
216 
217   InstantSupportState new_state = instant_support ? INSTANT_SUPPORT_YES :
218       INSTANT_SUPPORT_NO;
219 
220   model_.SetInstantSupportState(new_state);
221 
222   content::NavigationEntry* entry =
223       web_contents_->GetController().GetLastCommittedEntry();
224   if (entry) {
225     chrome::SetInstantSupportStateInNavigationEntry(new_state, entry);
226     if (delegate_ && !instant_support)
227       delegate_->OnWebContentsInstantSupportDisabled(web_contents_);
228   }
229 }
230 
SupportsInstant() const231 bool SearchTabHelper::SupportsInstant() const {
232   return model_.instant_support() == INSTANT_SUPPORT_YES;
233 }
234 
SetSuggestionToPrefetch(const InstantSuggestion & suggestion)235 void SearchTabHelper::SetSuggestionToPrefetch(
236     const InstantSuggestion& suggestion) {
237   ipc_router_.SetSuggestionToPrefetch(suggestion);
238 }
239 
Submit(const base::string16 & text)240 void SearchTabHelper::Submit(const base::string16& text) {
241   ipc_router_.Submit(text);
242 }
243 
OnTabActivated()244 void SearchTabHelper::OnTabActivated() {
245   ipc_router_.OnTabActivated();
246 
247   OmniboxView* omnibox_view = GetOmniboxView();
248   if (chrome::ShouldPrerenderInstantUrlOnOmniboxFocus() && omnibox_view &&
249       omnibox_view->model()->has_focus()) {
250     InstantSearchPrerenderer* prerenderer =
251         InstantSearchPrerenderer::GetForProfile(profile());
252     if (prerenderer && !IsSearchResultsPage()) {
253       prerenderer->Init(
254           web_contents_->GetController().GetSessionStorageNamespaceMap(),
255           web_contents_->GetContainerBounds().size());
256     }
257   }
258 }
259 
OnTabDeactivated()260 void SearchTabHelper::OnTabDeactivated() {
261   ipc_router_.OnTabDeactivated();
262 }
263 
ToggleVoiceSearch()264 void SearchTabHelper::ToggleVoiceSearch() {
265   ipc_router_.ToggleVoiceSearch();
266 }
267 
IsSearchResultsPage()268 bool SearchTabHelper::IsSearchResultsPage() {
269   return model_.mode().is_origin_search();
270 }
271 
RenderViewCreated(content::RenderViewHost * render_view_host)272 void SearchTabHelper::RenderViewCreated(
273     content::RenderViewHost* render_view_host) {
274   ipc_router_.SetPromoInformation(IsAppLauncherEnabled());
275 }
276 
DidStartNavigationToPendingEntry(const GURL & url,content::NavigationController::ReloadType)277 void SearchTabHelper::DidStartNavigationToPendingEntry(
278     const GURL& url,
279     content::NavigationController::ReloadType /* reload_type */) {
280   if (chrome::IsNTPURL(url, profile())) {
281     // Set the title on any pending entry corresponding to the NTP. This
282     // prevents any flickering of the tab title.
283     content::NavigationEntry* entry =
284         web_contents_->GetController().GetPendingEntry();
285     if (entry)
286       entry->SetTitle(l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE));
287   }
288 }
289 
DidNavigateMainFrame(const content::LoadCommittedDetails & details,const content::FrameNavigateParams & params)290 void SearchTabHelper::DidNavigateMainFrame(
291     const content::LoadCommittedDetails& details,
292     const content::FrameNavigateParams& params) {
293   if (IsCacheableNTP(web_contents_)) {
294     if (details.http_status_code == 204 || details.http_status_code >= 400) {
295       RedirectToLocalNTP();
296       RecordCacheableNTPLoadHistogram(false);
297       return;
298     }
299     RecordCacheableNTPLoadHistogram(true);
300   }
301 
302   // Always set the title on the new tab page to be the one from our UI
303   // resources. Normally, we set the title when we begin a NTP load, but it can
304   // get reset in several places (like when you press Reload). This check
305   // ensures that the title is properly set to the string defined by the Chrome
306   // UI language (rather than the server language) in all cases.
307   //
308   // We only override the title when it's nonempty to allow the page to set the
309   // title if it really wants. An empty title means to use the default. There's
310   // also a race condition between this code and the page's SetTitle call which
311   // this rule avoids.
312   content::NavigationEntry* entry =
313       web_contents_->GetController().GetLastCommittedEntry();
314   if (entry && entry->GetTitle().empty() &&
315       (entry->GetVirtualURL() == GURL(chrome::kChromeUINewTabURL) ||
316        chrome::NavEntryIsInstantNTP(web_contents_, entry))) {
317     entry->SetTitle(l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE));
318   }
319 }
320 
DidFailProvisionalLoad(int64,const base::string16 &,bool is_main_frame,const GURL & validated_url,int error_code,const base::string16 &,content::RenderViewHost *)321 void SearchTabHelper::DidFailProvisionalLoad(
322     int64 /* frame_id */,
323     const base::string16& /* frame_unique_name */,
324     bool is_main_frame,
325     const GURL& validated_url,
326     int error_code,
327     const base::string16& /* error_description */,
328     content::RenderViewHost* /* render_view_host */) {
329   // If error_code is ERR_ABORTED means that the user has canceled this
330   // navigation so it shouldn't be redirected.
331   if (is_main_frame &&
332       error_code != net::ERR_ABORTED &&
333       validated_url != GURL(chrome::kChromeSearchLocalNtpUrl) &&
334       chrome::IsNTPURL(validated_url, profile())) {
335     RedirectToLocalNTP();
336     RecordCacheableNTPLoadHistogram(false);
337   }
338 }
339 
DidFinishLoad(int64,const GURL &,bool is_main_frame,content::RenderViewHost *)340 void SearchTabHelper::DidFinishLoad(
341     int64 /* frame_id */,
342     const GURL&  /* validated_url */,
343     bool is_main_frame,
344     content::RenderViewHost* /* render_view_host */) {
345   if (is_main_frame) {
346     if (chrome::IsInstantNTP(web_contents_))
347       RecordNewTabLoadTime(web_contents_);
348 
349     DetermineIfPageSupportsInstant();
350   }
351 }
352 
NavigationEntryCommitted(const content::LoadCommittedDetails & load_details)353 void SearchTabHelper::NavigationEntryCommitted(
354     const content::LoadCommittedDetails& load_details) {
355   if (!is_search_enabled_)
356     return;
357 
358   if (!load_details.is_main_frame)
359     return;
360 
361   if (chrome::ShouldAssignURLToInstantRenderer(web_contents_->GetURL(),
362                                                profile())) {
363     InstantService* instant_service =
364         InstantServiceFactory::GetForProfile(profile());
365     ipc_router_.SetOmniboxStartMargin(instant_service->omnibox_start_margin());
366     ipc_router_.SetDisplayInstantResults();
367   }
368 
369   UpdateMode(true, false);
370 
371   content::NavigationEntry* entry =
372       web_contents_->GetController().GetVisibleEntry();
373   DCHECK(entry);
374 
375   // Already determined the instant support state for this page, do not reset
376   // the instant support state.
377   //
378   // When we get a navigation entry committed event, there seem to be two ways
379   // to tell whether the navigation was "in-page". Ideally, when
380   // LoadCommittedDetails::is_in_page is true, we should have
381   // LoadCommittedDetails::type to be NAVIGATION_TYPE_IN_PAGE. Unfortunately,
382   // they are different in some cases. To workaround this bug, we are checking
383   // (is_in_page || type == NAVIGATION_TYPE_IN_PAGE). Please refer to
384   // crbug.com/251330 for more details.
385   if (load_details.is_in_page ||
386       load_details.type == content::NAVIGATION_TYPE_IN_PAGE) {
387     // When an "in-page" navigation happens, we will not receive a
388     // DidFinishLoad() event. Therefore, we will not determine the Instant
389     // support for the navigated page. So, copy over the Instant support from
390     // the previous entry. If the page does not support Instant, update the
391     // location bar from here to turn off search terms replacement.
392     chrome::SetInstantSupportStateInNavigationEntry(model_.instant_support(),
393                                                     entry);
394     if (delegate_ && model_.instant_support() == INSTANT_SUPPORT_NO)
395       delegate_->OnWebContentsInstantSupportDisabled(web_contents_);
396     return;
397   }
398 
399   model_.SetInstantSupportState(INSTANT_SUPPORT_UNKNOWN);
400   model_.SetVoiceSearchSupported(false);
401   chrome::SetInstantSupportStateInNavigationEntry(model_.instant_support(),
402                                                   entry);
403 
404   if (InInstantProcess(profile(), web_contents_))
405     ipc_router_.OnNavigationEntryCommitted();
406 }
407 
OnInstantSupportDetermined(bool supports_instant)408 void SearchTabHelper::OnInstantSupportDetermined(bool supports_instant) {
409   InstantSupportChanged(supports_instant);
410 }
411 
OnSetVoiceSearchSupport(bool supports_voice_search)412 void SearchTabHelper::OnSetVoiceSearchSupport(bool supports_voice_search) {
413   model_.SetVoiceSearchSupported(supports_voice_search);
414 }
415 
ThemeInfoChanged(const ThemeBackgroundInfo & theme_info)416 void SearchTabHelper::ThemeInfoChanged(const ThemeBackgroundInfo& theme_info) {
417   ipc_router_.SendThemeBackgroundInfo(theme_info);
418 }
419 
MostVisitedItemsChanged(const std::vector<InstantMostVisitedItem> & items)420 void SearchTabHelper::MostVisitedItemsChanged(
421     const std::vector<InstantMostVisitedItem>& items) {
422   std::vector<InstantMostVisitedItem> items_copy(items);
423   MaybeRemoveMostVisitedItems(&items_copy);
424   ipc_router_.SendMostVisitedItems(items_copy);
425 }
426 
OmniboxStartMarginChanged(int omnibox_start_margin)427 void SearchTabHelper::OmniboxStartMarginChanged(int omnibox_start_margin) {
428   ipc_router_.SetOmniboxStartMargin(omnibox_start_margin);
429 }
430 
MaybeRemoveMostVisitedItems(std::vector<InstantMostVisitedItem> * items)431 void SearchTabHelper::MaybeRemoveMostVisitedItems(
432     std::vector<InstantMostVisitedItem>* items) {
433   if (!delegate_)
434     return;
435 
436   if (!history::MostVisitedTilesExperiment::IsDontShowOpenURLsEnabled())
437     return;
438 
439   history::MostVisitedTilesExperiment::RemoveItemsMatchingOpenTabs(
440       delegate_->GetOpenUrls(), items);
441 }
442 
FocusOmnibox(OmniboxFocusState state)443 void SearchTabHelper::FocusOmnibox(OmniboxFocusState state) {
444 // TODO(kmadhusu): Move platform specific code from here and get rid of #ifdef.
445 #if !defined(OS_ANDROID)
446   OmniboxView* omnibox = GetOmniboxView();
447   if (!omnibox)
448     return;
449 
450   // Do not add a default case in the switch block for the following reasons:
451   // (1) Explicitly handle the new states. If new states are added in the
452   // OmniboxFocusState, the compiler will warn the developer to handle the new
453   // states.
454   // (2) An attacker may control the renderer and sends the browser process a
455   // malformed IPC. This function responds to the invalid |state| values by
456   // doing nothing instead of crashing the browser process (intentional no-op).
457   switch (state) {
458     case OMNIBOX_FOCUS_VISIBLE:
459       omnibox->SetFocus();
460       omnibox->model()->SetCaretVisibility(true);
461       break;
462     case OMNIBOX_FOCUS_INVISIBLE:
463       omnibox->SetFocus();
464       omnibox->model()->SetCaretVisibility(false);
465       // If the user clicked on the fakebox, any text already in the omnibox
466       // should get cleared when they start typing. Selecting all the existing
467       // text is a convenient way to accomplish this. It also gives a slight
468       // visual cue to users who really understand selection state about what
469       // will happen if they start typing.
470       omnibox->SelectAll(false);
471       omnibox->ShowImeIfNeeded();
472       break;
473     case OMNIBOX_FOCUS_NONE:
474       // Remove focus only if the popup is closed. This will prevent someone
475       // from changing the omnibox value and closing the popup without user
476       // interaction.
477       if (!omnibox->model()->popup_model()->IsOpen())
478         web_contents()->Focus();
479       break;
480   }
481 #endif
482 }
483 
NavigateToURL(const GURL & url,WindowOpenDisposition disposition,bool is_most_visited_item_url)484 void SearchTabHelper::NavigateToURL(const GURL& url,
485                                     WindowOpenDisposition disposition,
486                                     bool is_most_visited_item_url) {
487   if (is_most_visited_item_url) {
488     content::RecordAction(
489         base::UserMetricsAction("InstantExtended.MostVisitedClicked"));
490   }
491 
492   if (delegate_)
493     delegate_->NavigateOnThumbnailClick(url, disposition, web_contents_);
494 }
495 
OnDeleteMostVisitedItem(const GURL & url)496 void SearchTabHelper::OnDeleteMostVisitedItem(const GURL& url) {
497   DCHECK(!url.is_empty());
498   if (instant_service_)
499     instant_service_->DeleteMostVisitedItem(url);
500 }
501 
OnUndoMostVisitedDeletion(const GURL & url)502 void SearchTabHelper::OnUndoMostVisitedDeletion(const GURL& url) {
503   DCHECK(!url.is_empty());
504   if (instant_service_)
505     instant_service_->UndoMostVisitedDeletion(url);
506 }
507 
OnUndoAllMostVisitedDeletions()508 void SearchTabHelper::OnUndoAllMostVisitedDeletions() {
509   if (instant_service_)
510     instant_service_->UndoAllMostVisitedDeletions();
511 }
512 
OnLogEvent(NTPLoggingEventType event)513 void SearchTabHelper::OnLogEvent(NTPLoggingEventType event) {
514 // TODO(kmadhusu): Move platform specific code from here and get rid of #ifdef.
515 #if !defined(OS_ANDROID)
516   NTPUserDataLogger::GetOrCreateFromWebContents(
517       web_contents())->LogEvent(event);
518 #endif
519 }
520 
OnLogMostVisitedImpression(int position,const base::string16 & provider)521 void SearchTabHelper::OnLogMostVisitedImpression(
522     int position, const base::string16& provider) {
523 // TODO(kmadhusu): Move platform specific code from here and get rid of #ifdef.
524 #if !defined(OS_ANDROID)
525   NTPUserDataLogger::GetOrCreateFromWebContents(
526       web_contents())->LogMostVisitedImpression(position, provider);
527 #endif
528 }
529 
OnLogMostVisitedNavigation(int position,const base::string16 & provider)530 void SearchTabHelper::OnLogMostVisitedNavigation(
531     int position, const base::string16& provider) {
532 // TODO(kmadhusu): Move platform specific code from here and get rid of #ifdef.
533 #if !defined(OS_ANDROID)
534   NTPUserDataLogger::GetOrCreateFromWebContents(
535       web_contents())->LogMostVisitedNavigation(position, provider);
536 #endif
537 }
538 
PasteIntoOmnibox(const base::string16 & text)539 void SearchTabHelper::PasteIntoOmnibox(const base::string16& text) {
540 // TODO(kmadhusu): Move platform specific code from here and get rid of #ifdef.
541 #if !defined(OS_ANDROID)
542   OmniboxView* omnibox = GetOmniboxView();
543   if (!omnibox)
544     return;
545   // The first case is for right click to paste, where the text is retrieved
546   // from the clipboard already sanitized. The second case is needed to handle
547   // drag-and-drop value and it has to be sanitazed before setting it into the
548   // omnibox.
549   base::string16 text_to_paste = text.empty() ? omnibox->GetClipboardText() :
550       omnibox->SanitizeTextForPaste(text);
551 
552   if (text_to_paste.empty())
553     return;
554 
555   if (!omnibox->model()->has_focus())
556     omnibox->SetFocus();
557 
558   omnibox->OnBeforePossibleChange();
559   omnibox->model()->OnPaste();
560   omnibox->SetUserText(text_to_paste);
561   omnibox->OnAfterPossibleChange();
562 #endif
563 }
564 
OnChromeIdentityCheck(const base::string16 & identity)565 void SearchTabHelper::OnChromeIdentityCheck(const base::string16& identity) {
566   SigninManagerBase* manager = SigninManagerFactory::GetForProfile(profile());
567   if (manager) {
568     const base::string16 username =
569         base::UTF8ToUTF16(manager->GetAuthenticatedUsername());
570     // The identity check only passes if the user is syncing their history.
571     // TODO(beaudoin): Change this function name and related APIs now that it's
572     // checking both the identity and the user's sync state.
573     bool matches = IsHistorySyncEnabled(profile()) && identity == username;
574     ipc_router_.SendChromeIdentityCheckResult(identity, matches);
575   }
576 }
577 
UpdateMode(bool update_origin,bool is_preloaded_ntp)578 void SearchTabHelper::UpdateMode(bool update_origin, bool is_preloaded_ntp) {
579   SearchMode::Type type = SearchMode::MODE_DEFAULT;
580   SearchMode::Origin origin = SearchMode::ORIGIN_DEFAULT;
581   if (IsNTP(web_contents_) || is_preloaded_ntp) {
582     type = SearchMode::MODE_NTP;
583     origin = SearchMode::ORIGIN_NTP;
584   } else if (IsSearchResults(web_contents_)) {
585     type = SearchMode::MODE_SEARCH_RESULTS;
586     origin = SearchMode::ORIGIN_SEARCH;
587   }
588   if (!update_origin)
589     origin = model_.mode().origin;
590 
591   OmniboxView* omnibox = GetOmniboxView();
592   if (omnibox && omnibox->model()->user_input_in_progress())
593     type = SearchMode::MODE_SEARCH_SUGGESTIONS;
594 
595   SearchMode old_mode(model_.mode());
596   model_.SetMode(SearchMode(type, origin));
597   if (old_mode.is_ntp() != model_.mode().is_ntp()) {
598     ipc_router_.SetInputInProgress(IsInputInProgress());
599   }
600 }
601 
DetermineIfPageSupportsInstant()602 void SearchTabHelper::DetermineIfPageSupportsInstant() {
603   if (!InInstantProcess(profile(), web_contents_)) {
604     // The page is not in the Instant process. This page does not support
605     // instant. If we send an IPC message to a page that is not in the Instant
606     // process, it will never receive it and will never respond. Therefore,
607     // return immediately.
608     InstantSupportChanged(false);
609   } else if (IsLocal(web_contents_)) {
610     // Local pages always support Instant.
611     InstantSupportChanged(true);
612   } else {
613     ipc_router_.DetermineIfPageSupportsInstant();
614   }
615 }
616 
profile() const617 Profile* SearchTabHelper::profile() const {
618   return Profile::FromBrowserContext(web_contents_->GetBrowserContext());
619 }
620 
RedirectToLocalNTP()621 void SearchTabHelper::RedirectToLocalNTP() {
622   // Extra parentheses to declare a variable.
623   content::NavigationController::LoadURLParams load_params(
624       (GURL(chrome::kChromeSearchLocalNtpUrl)));
625   load_params.referrer = content::Referrer();
626   load_params.transition_type = content::PAGE_TRANSITION_SERVER_REDIRECT;
627   // Don't push a history entry.
628   load_params.should_replace_current_entry = true;
629   web_contents_->GetController().LoadURLWithParams(load_params);
630 }
631 
IsInputInProgress() const632 bool SearchTabHelper::IsInputInProgress() const {
633   OmniboxView* omnibox = GetOmniboxView();
634   return !model_.mode().is_ntp() && omnibox &&
635       omnibox->model()->focus_state() == OMNIBOX_FOCUS_VISIBLE;
636 }
637 
GetOmniboxView() const638 OmniboxView* SearchTabHelper::GetOmniboxView() const {
639   return delegate_ ? delegate_->GetOmniboxView() : NULL;
640 }
641