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