12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_instant_controller.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/extension_web_ui.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/search/instant_service.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/search/instant_service_factory.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/search/search.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/search_engines/template_url.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/search_engines/template_url_service.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/search_engines/template_url_service_factory.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_window.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/omnibox/location_bar.h"
214311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch#include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/omnibox/omnibox_view.h"
23ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "chrome/browser/ui/search/instant_ntp.h"
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/ui/search/search_model.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/search/search_tab_helper.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/url_constants.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/user_prefs/pref_registry_syncable.h"
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/render_process_host.h"
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/user_metrics.h"
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/web_contents.h"
344311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch#include "content/public/browser/web_contents_view.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::UserMetricsAction;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BrowserInstantController, public:
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserInstantController::BrowserInstantController(Browser* browser)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : browser_(browser),
43a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      instant_(this),
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      instant_unload_handler_(browser) {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  profile_pref_registrar_.Init(profile()->GetPrefs());
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  profile_pref_registrar_.Add(
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      prefs::kDefaultSearchProviderID,
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&BrowserInstantController::OnDefaultSearchProviderChanged,
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  browser_->search_model()->AddObserver(this);
51ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
52ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  InstantService* instant_service =
53ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      InstantServiceFactory::GetForProfile(profile());
54ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  instant_service->OnBrowserInstantControllerCreated();
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserInstantController::~BrowserInstantController() {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  browser_->search_model()->RemoveObserver(this);
59ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
60ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  InstantService* instant_service =
61ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      InstantServiceFactory::GetForProfile(profile());
62ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  instant_service->OnBrowserInstantControllerDestroyed();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BrowserInstantController::MaybeSwapInInstantNTPContents(
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& url,
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::WebContents* source_contents,
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::WebContents** target_contents) {
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (url != GURL(chrome::kChromeUINewTabURL))
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL extension_url(url);
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (ExtensionWebUI::HandleChromeURLOverride(&extension_url, profile())) {
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If there is an extension overriding the NTP do not use the Instant NTP.
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
78ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  InstantService* instant_service =
79ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      InstantServiceFactory::GetForProfile(profile());
80ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<content::WebContents> instant_ntp =
81ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      instant_service->ReleaseNTPContents();
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!instant_ntp)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *target_contents = instant_ntp.get();
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (source_contents) {
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // If the Instant NTP hasn't yet committed an entry, we can't call
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // CopyStateFromAndPrune.  Instead, load the Local NTP URL directly in the
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // source contents.
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // TODO(sreeram): Always using the local URL is wrong in the case of the
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // first tab in a window where we might want to use the remote URL. Fix.
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!instant_ntp->GetController().CanPruneAllButVisible()) {
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      source_contents->GetController().LoadURL(chrome::GetLocalInstantURL(
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          profile()), content::Referrer(), content::PAGE_TRANSITION_GENERATED,
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          std::string());
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      *target_contents = source_contents;
97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      instant_ntp->GetController().CopyStateFromAndPrune(
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          &source_contents->GetController());
100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ReplaceWebContentsAt(
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          browser_->tab_strip_model()->GetIndexOfWebContents(source_contents),
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          instant_ntp.Pass());
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // If the Instant NTP hasn't yet committed an entry, we can't call
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // PruneAllButVisible.  In that case, there shouldn't be any entries to
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // prune anyway.
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (instant_ntp->GetController().CanPruneAllButVisible())
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      instant_ntp->GetController().PruneAllButVisible();
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    else
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      CHECK(!instant_ntp->GetController().GetLastCommittedEntry());
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If |source_contents| is NULL, then the caller is responsible for
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // inserting instant_ntp into the tabstrip and will take ownership.
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ignore_result(instant_ntp.release());
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool BrowserInstantController::OpenInstant(WindowOpenDisposition disposition,
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                           const GURL& url) {
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Unsupported dispositions.
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (disposition == NEW_BACKGROUND_TAB || disposition == NEW_WINDOW ||
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      disposition == NEW_FOREGROUND_TAB)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The omnibox currently doesn't use other dispositions, so we don't attempt
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to handle them. If you hit this DCHECK file a bug and I'll (sky) add
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // support for the new disposition.
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(disposition == CURRENT_TAB) << disposition;
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // If we will not be replacing search terms from this URL, don't send to
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // InstantController.
134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const string16& search_terms =
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      chrome::GetSearchTermsFromURL(browser_->profile(), url);
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (search_terms.empty())
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return instant_.SubmitQuery(search_terms);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Profile* BrowserInstantController::profile() const {
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return browser_->profile();
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BrowserInstantController::ReplaceWebContentsAt(
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int index,
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<content::WebContents> new_contents) {
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_NE(TabStripModel::kNoTab, index);
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<content::WebContents> old_contents(browser_->tab_strip_model()->
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ReplaceWebContentsAt(index, new_contents.release()));
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  instant_unload_handler_.RunUnloadListenersOrDestroy(old_contents.Pass(),
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                      index);
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1564311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdochvoid BrowserInstantController::FocusOmnibox(OmniboxFocusState state) {
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OmniboxView* omnibox_view = browser_->window()->GetLocationBar()->
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetLocationEntry();
1594311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch
1604311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  // Do not add a default case in the switch block for the following reasons:
1614311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  // (1) Explicitly handle the new states. If new states are added in the
1624311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  // OmniboxFocusState, the compiler will warn the developer to handle the new
1634311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  // states.
1644311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  // (2) An attacker may control the renderer and sends the browser process a
1654311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  // malformed IPC. This function responds to the invalid |state| values by
1664311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  // doing nothing instead of crashing the browser process (intentional no-op).
1674311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  switch (state) {
1684311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    case OMNIBOX_FOCUS_VISIBLE:
1694311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      omnibox_view->SetFocus();
1704311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      omnibox_view->model()->SetCaretVisibility(true);
1714311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      break;
1724311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    case OMNIBOX_FOCUS_INVISIBLE:
1734311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      omnibox_view->SetFocus();
1744311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      omnibox_view->model()->SetCaretVisibility(false);
1754311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      // If the user clicked on the fakebox, any text already in the omnibox
1764311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      // should get cleared when they start typing. Selecting all the existing
1774311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      // text is a convenient way to accomplish this. It also gives a slight
1784311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      // visual cue to users who really understand selection state about what
1794311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      // will happen if they start typing.
1804311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      omnibox_view->SelectAll(false);
1814311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      break;
1824311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    case OMNIBOX_FOCUS_NONE:
1834311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      // Remove focus only if the popup is closed. This will prevent someone
1844311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      // from changing the omnibox value and closing the popup without user
1854311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      // interaction.
1864311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      if (!omnibox_view->model()->popup_model()->IsOpen()) {
1874311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch        content::WebContents* contents = GetActiveWebContents();
1884311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch        if (contents)
1894311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch          contents->GetView()->Focus();
1904311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      }
1914311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      break;
1927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)content::WebContents* BrowserInstantController::GetActiveWebContents() const {
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return browser_->tab_strip_model()->GetActiveWebContents();
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BrowserInstantController::ActiveTabChanged() {
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  instant_.ActiveTabChanged();
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BrowserInstantController::TabDeactivated(content::WebContents* contents) {
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  instant_.TabDeactivated(contents);
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BrowserInstantController::OpenURL(
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& url,
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::PageTransition transition,
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WindowOpenDisposition disposition) {
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  browser_->OpenURL(content::OpenURLParams(url,
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           content::Referrer(),
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           disposition,
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           transition,
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           false));
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2184311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdochvoid BrowserInstantController::PasteIntoOmnibox(const string16& text) {
2194311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  OmniboxView* omnibox_view = browser_->window()->GetLocationBar()->
2204311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      GetLocationEntry();
2214311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  // The first case is for right click to paste, where the text is retrieved
2224311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  // from the clipboard already sanitized. The second case is needed to handle
2234311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  // drag-and-drop value and it has to be sanitazed before setting it into the
2244311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  // omnibox.
2254311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  string16 text_to_paste = text.empty() ?
2264311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      omnibox_view->GetClipboardText() :
2274311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      omnibox_view->SanitizeTextForPaste(text);
2284311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch
2294311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  if (!text_to_paste.empty()) {
2304311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    if (!omnibox_view->model()->has_focus())
2314311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      omnibox_view->SetFocus();
2324311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    omnibox_view->OnBeforePossibleChange();
2334311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    omnibox_view->model()->on_paste();
2344311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    omnibox_view->SetUserText(text_to_paste);
2354311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    omnibox_view->OnAfterPossibleChange();
2364311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  }
2374311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch}
2384311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BrowserInstantController::SetOmniboxBounds(const gfx::Rect& bounds) {
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  instant_.SetOmniboxBounds(bounds);
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void BrowserInstantController::ToggleVoiceSearch() {
244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  instant_.ToggleVoiceSearch();
245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// BrowserInstantController, SearchModelObserver implementation:
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BrowserInstantController::ModelChanged(
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const SearchModel::State& old_state,
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const SearchModel::State& new_state) {
253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (old_state.mode != new_state.mode) {
254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const SearchMode& new_mode = new_state.mode;
255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
256a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // Record some actions corresponding to the mode change. Note that to get
257a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // the full story, it's necessary to look at other UMA actions as well,
258a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // such as tab switches.
259a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (new_mode.is_search_results())
260a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      content::RecordAction(UserMetricsAction("InstantExtended.ShowSRP"));
261a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    else if (new_mode.is_ntp())
262a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      content::RecordAction(UserMetricsAction("InstantExtended.ShowNTP"));
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    instant_.SearchModeChanged(old_state.mode, new_mode);
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (old_state.instant_support != new_state.instant_support)
268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    instant_.InstantSupportChanged(new_state.instant_support);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void BrowserInstantController::OnDefaultSearchProviderChanged(
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& pref_name) {
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_EQ(pref_name, std::string(prefs::kDefaultSearchProviderID));
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Profile* browser_profile = profile();
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const TemplateURL* template_url =
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      TemplateURLServiceFactory::GetForProfile(browser_profile)->
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          GetDefaultSearchProvider();
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!template_url) {
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // A NULL |template_url| could mean either this notification is sent during
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // the browser start up operation or the user now has no default search
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // provider. There is no way for the user to reach this state using the
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Chrome settings. Only explicitly poking at the DB or bugs in the Sync
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // could cause that, neither of which we support.
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  InstantService* instant_service =
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      InstantServiceFactory::GetForProfile(browser_profile);
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!instant_service)
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TabStripModel* tab_model = browser_->tab_strip_model();
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int count = tab_model->count();
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (int index = 0; index < count; ++index) {
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    content::WebContents* contents = tab_model->GetWebContentsAt(index);
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!contents)
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      continue;
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!instant_service->IsInstantProcess(
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            contents->GetRenderProcessHost()->GetID()))
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      continue;
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Reload the contents to ensure that it gets assigned to a non-priviledged
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // renderer.
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    contents->GetController().Reload(false);
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
309