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