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"
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"
54 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SearchTabHelper
);
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
))
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
) {
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
)
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())
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
);
131 UMA_HISTOGRAM_TIMES("Tab.NewTabOnload.Other", duration
);
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
);
145 sync
->sync_initialized() &&
146 sync
->GetActiveDataTypes().Has(syncer::HISTORY_DELETE_DIRECTIVES
);
149 bool OmniboxHasFocus(OmniboxView
* omnibox
) {
150 return omnibox
&& omnibox
->model()->has_focus();
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
),
164 omnibox_has_focus_fn_(&OmniboxHasFocus
) {
165 if (!is_search_enabled_
)
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_
)
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())
211 if (state
== OMNIBOX_FOCUS_NONE
) {
212 prerenderer
->Cancel();
216 if (!IsSearchResultsPage()) {
218 web_contents_
->GetController().GetSessionStorageNamespaceMap(),
219 web_contents_
->GetContainerBounds().size());
224 void SearchTabHelper::NavigationEntryUpdated() {
225 if (!is_search_enabled_
)
228 UpdateMode(false, false);
231 void SearchTabHelper::InstantSupportChanged(bool instant_support
) {
232 if (!is_search_enabled_
)
235 InstantSupportState new_state
= instant_support
? INSTANT_SUPPORT_YES
:
238 model_
.SetInstantSupportState(new_state
);
240 content::NavigationEntry
* entry
=
241 web_contents_
->GetController().GetLastCommittedEntry();
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()) {
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(
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();
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);
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
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
,
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_
)
369 if (!load_details
.is_main_frame
)
372 if (chrome::ShouldAssignURLToInstantRenderer(web_contents_
->GetURL(),
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();
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(),
405 if (delegate_
&& model_
.instant_support() == INSTANT_SUPPORT_NO
)
406 delegate_
->OnWebContentsInstantSupportDisabled(web_contents_
);
410 model_
.SetInstantSupportState(INSTANT_SUPPORT_UNKNOWN
);
411 model_
.SetVoiceSearchSupported(false);
412 chrome::SetInstantSupportStateInNavigationEntry(model_
.instant_support(),
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();
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
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).
455 case OMNIBOX_FOCUS_VISIBLE
:
457 omnibox
->model()->SetCaretVisibility(true);
459 case OMNIBOX_FOCUS_INVISIBLE
:
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();
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
474 if (!omnibox
->model()->popup_model()->IsOpen())
475 web_contents()->Focus();
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"));
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
);
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
);
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
);
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();
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
546 base::string16 text_to_paste
= text
.empty() ? omnibox
->GetClipboardText() :
547 omnibox
->SanitizeTextForPaste(text
);
549 if (text_to_paste
.empty())
552 if (!omnibox
->model()->has_focus())
555 omnibox
->OnBeforePossibleChange();
556 omnibox
->model()->OnPaste();
557 omnibox
->SetUserText(text_to_paste
);
558 omnibox
->OnAfterPossibleChange();
562 void SearchTabHelper::OnChromeIdentityCheck(const base::string16
& identity
) {
563 SigninManagerBase
* manager
= SigninManagerFactory::GetForProfile(profile());
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
;
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);
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
;