Home | History | Annotate | Download | only in search
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <sstream>
      6 
      7 #include "base/command_line.h"
      8 #include "base/metrics/histogram_base.h"
      9 #include "base/metrics/histogram_samples.h"
     10 #include "base/metrics/statistics_recorder.h"
     11 #include "base/prefs/pref_service.h"
     12 #include "base/run_loop.h"
     13 #include "base/strings/string_number_conversions.h"
     14 #include "base/strings/string_util.h"
     15 #include "base/strings/stringprintf.h"
     16 #include "base/strings/utf_string_conversions.h"
     17 #include "base/time/time.h"
     18 #include "chrome/browser/autocomplete/autocomplete_controller.h"
     19 #include "chrome/browser/autocomplete/autocomplete_match.h"
     20 #include "chrome/browser/autocomplete/autocomplete_provider.h"
     21 #include "chrome/browser/autocomplete/autocomplete_result.h"
     22 #include "chrome/browser/autocomplete/search_provider.h"
     23 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
     24 #include "chrome/browser/chrome_notification_types.h"
     25 #include "chrome/browser/extensions/extension_browsertest.h"
     26 #include "chrome/browser/extensions/extension_service.h"
     27 #include "chrome/browser/favicon/favicon_tab_helper.h"
     28 #include "chrome/browser/history/history_db_task.h"
     29 #include "chrome/browser/history/history_service.h"
     30 #include "chrome/browser/history/history_service_factory.h"
     31 #include "chrome/browser/history/history_types.h"
     32 #include "chrome/browser/history/top_sites.h"
     33 #include "chrome/browser/profiles/profile.h"
     34 #include "chrome/browser/search/instant_service.h"
     35 #include "chrome/browser/search/instant_service_factory.h"
     36 #include "chrome/browser/search/search.h"
     37 #include "chrome/browser/search_engines/template_url_service.h"
     38 #include "chrome/browser/search_engines/template_url_service_factory.h"
     39 #include "chrome/browser/task_manager/task_manager.h"
     40 #include "chrome/browser/task_manager/task_manager_browsertest_util.h"
     41 #include "chrome/browser/themes/theme_service.h"
     42 #include "chrome/browser/themes/theme_service_factory.h"
     43 #include "chrome/browser/ui/browser_list.h"
     44 #include "chrome/browser/ui/browser_tabstrip.h"
     45 #include "chrome/browser/ui/omnibox/omnibox_view.h"
     46 #include "chrome/browser/ui/search/instant_tab.h"
     47 #include "chrome/browser/ui/search/instant_test_utils.h"
     48 #include "chrome/browser/ui/search/search_tab_helper.h"
     49 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     50 #include "chrome/browser/ui/webui/theme_source.h"
     51 #include "chrome/common/chrome_switches.h"
     52 #include "chrome/common/instant_types.h"
     53 #include "chrome/common/pref_names.h"
     54 #include "chrome/common/url_constants.h"
     55 #include "chrome/test/base/in_process_browser_test.h"
     56 #include "chrome/test/base/interactive_test_utils.h"
     57 #include "chrome/test/base/ui_test_utils.h"
     58 #include "components/bookmarks/browser/bookmark_utils.h"
     59 #include "components/bookmarks/test/bookmark_test_helpers.h"
     60 #include "components/google/core/browser/google_url_tracker.h"
     61 #include "components/history/core/common/thumbnail_score.h"
     62 #include "components/sessions/serialized_navigation_entry.h"
     63 #include "content/public/browser/navigation_controller.h"
     64 #include "content/public/browser/navigation_entry.h"
     65 #include "content/public/browser/notification_service.h"
     66 #include "content/public/browser/render_process_host.h"
     67 #include "content/public/browser/render_view_host.h"
     68 #include "content/public/browser/site_instance.h"
     69 #include "content/public/browser/url_data_source.h"
     70 #include "content/public/browser/web_contents.h"
     71 #include "content/public/common/bindings_policy.h"
     72 #include "content/public/test/browser_test_utils.h"
     73 #include "content/public/test/test_utils.h"
     74 #include "grit/generated_resources.h"
     75 #include "net/base/network_change_notifier.h"
     76 #include "net/http/http_status_code.h"
     77 #include "net/url_request/test_url_fetcher_factory.h"
     78 #include "net/url_request/url_fetcher_impl.h"
     79 #include "net/url_request/url_request_status.h"
     80 #include "testing/gmock/include/gmock/gmock.h"
     81 #include "third_party/skia/include/core/SkBitmap.h"
     82 #include "ui/base/l10n/l10n_util.h"
     83 
     84 using base::ASCIIToUTF16;
     85 using testing::HasSubstr;
     86 
     87 namespace {
     88 
     89 // Task used to make sure history has finished processing a request. Intended
     90 // for use with BlockUntilHistoryProcessesPendingRequests.
     91 class QuittingHistoryDBTask : public history::HistoryDBTask {
     92  public:
     93   QuittingHistoryDBTask() {}
     94 
     95   virtual bool RunOnDBThread(history::HistoryBackend* backend,
     96                              history::HistoryDatabase* db) OVERRIDE {
     97     return true;
     98   }
     99 
    100   virtual void DoneRunOnMainThread() OVERRIDE {
    101     base::MessageLoop::current()->Quit();
    102   }
    103 
    104  private:
    105   virtual ~QuittingHistoryDBTask() {}
    106 
    107   DISALLOW_COPY_AND_ASSIGN(QuittingHistoryDBTask);
    108 };
    109 
    110 class FakeNetworkChangeNotifier : public net::NetworkChangeNotifier {
    111  public:
    112   FakeNetworkChangeNotifier() : connection_type_(CONNECTION_NONE) {}
    113 
    114   virtual ConnectionType GetCurrentConnectionType() const OVERRIDE {
    115     return connection_type_;
    116   }
    117 
    118   void SetConnectionType(ConnectionType type) {
    119     connection_type_ = type;
    120     NotifyObserversOfNetworkChange(type);
    121     base::RunLoop().RunUntilIdle();
    122   }
    123 
    124   virtual ~FakeNetworkChangeNotifier() {}
    125 
    126  private:
    127   ConnectionType connection_type_;
    128   DISALLOW_COPY_AND_ASSIGN(FakeNetworkChangeNotifier);
    129 };
    130 }  // namespace
    131 
    132 class InstantExtendedTest : public InProcessBrowserTest,
    133                             public InstantTestBase {
    134  public:
    135   InstantExtendedTest()
    136       : on_most_visited_change_calls_(0),
    137         most_visited_items_count_(0),
    138         first_most_visited_item_id_(0),
    139         on_native_suggestions_calls_(0),
    140         on_change_calls_(0),
    141         submit_count_(0),
    142         on_esc_key_press_event_calls_(0),
    143         on_focus_changed_calls_(0),
    144         is_focused_(false),
    145         on_toggle_voice_search_calls_(0) {
    146   }
    147  protected:
    148   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
    149     chrome::EnableQueryExtractionForTesting();
    150     ASSERT_TRUE(https_test_server().Start());
    151     GURL instant_url = https_test_server().GetURL(
    152         "files/instant_extended.html?strk=1&");
    153     GURL ntp_url = https_test_server().GetURL(
    154         "files/instant_extended_ntp.html?strk=1&");
    155     InstantTestBase::Init(instant_url, ntp_url, false);
    156   }
    157 
    158   int64 GetHistogramCount(const char* name) {
    159     base::HistogramBase* histogram =
    160         base::StatisticsRecorder::FindHistogram(name);
    161     if (!histogram) {
    162       // If no histogram is found, it's possible that no values have been
    163       // recorded yet. Assume that the value is zero.
    164       return 0;
    165     }
    166     return histogram->SnapshotSamples()->TotalCount();
    167   }
    168 
    169   bool UpdateSearchState(content::WebContents* contents) WARN_UNUSED_RESULT {
    170     return GetIntFromJS(contents, "onMostVisitedChangedCalls",
    171                         &on_most_visited_change_calls_) &&
    172            GetIntFromJS(contents, "mostVisitedItemsCount",
    173                         &most_visited_items_count_) &&
    174            GetIntFromJS(contents, "firstMostVisitedItemId",
    175                         &first_most_visited_item_id_) &&
    176            GetIntFromJS(contents, "onNativeSuggestionsCalls",
    177                         &on_native_suggestions_calls_) &&
    178            GetIntFromJS(contents, "onChangeCalls",
    179                         &on_change_calls_) &&
    180            GetIntFromJS(contents, "submitCount",
    181                         &submit_count_) &&
    182            GetStringFromJS(contents, "apiHandle.value",
    183                            &query_value_) &&
    184            GetIntFromJS(contents, "onEscKeyPressedCalls",
    185                         &on_esc_key_press_event_calls_) &&
    186            GetIntFromJS(contents, "onFocusChangedCalls",
    187                        &on_focus_changed_calls_) &&
    188            GetBoolFromJS(contents, "isFocused",
    189                          &is_focused_) &&
    190            GetIntFromJS(contents, "onToggleVoiceSearchCalls",
    191                         &on_toggle_voice_search_calls_) &&
    192            GetStringFromJS(contents, "prefetchQuery", &prefetch_query_value_);
    193 
    194   }
    195 
    196   TemplateURL* GetDefaultSearchProviderTemplateURL() {
    197     TemplateURLService* template_url_service =
    198         TemplateURLServiceFactory::GetForProfile(browser()->profile());
    199     if (template_url_service)
    200       return template_url_service->GetDefaultSearchProvider();
    201     return NULL;
    202   }
    203 
    204   bool AddSearchToHistory(base::string16 term, int visit_count) {
    205     TemplateURL* template_url = GetDefaultSearchProviderTemplateURL();
    206     if (!template_url)
    207       return false;
    208 
    209     HistoryService* history = HistoryServiceFactory::GetForProfile(
    210         browser()->profile(), Profile::EXPLICIT_ACCESS);
    211     GURL search(template_url->url_ref().ReplaceSearchTerms(
    212         TemplateURLRef::SearchTermsArgs(term),
    213         TemplateURLServiceFactory::GetForProfile(
    214             browser()->profile())->search_terms_data()));
    215     history->AddPageWithDetails(
    216         search, base::string16(), visit_count, visit_count,
    217         base::Time::Now(), false, history::SOURCE_BROWSED);
    218     history->SetKeywordSearchTermsForURL(
    219         search, template_url->id(), term);
    220     return true;
    221   }
    222 
    223   void BlockUntilHistoryProcessesPendingRequests() {
    224     HistoryService* history = HistoryServiceFactory::GetForProfile(
    225         browser()->profile(), Profile::EXPLICIT_ACCESS);
    226     DCHECK(history);
    227     DCHECK(base::MessageLoop::current());
    228 
    229     CancelableRequestConsumer consumer;
    230     history->ScheduleDBTask(new QuittingHistoryDBTask(), &consumer);
    231     base::MessageLoop::current()->Run();
    232   }
    233 
    234   int CountSearchProviderSuggestions() {
    235     return omnibox()->model()->autocomplete_controller()->search_provider()->
    236         matches().size();
    237   }
    238 
    239   int on_most_visited_change_calls_;
    240   int most_visited_items_count_;
    241   int first_most_visited_item_id_;
    242   int on_native_suggestions_calls_;
    243   int on_change_calls_;
    244   int submit_count_;
    245   int on_esc_key_press_event_calls_;
    246   std::string query_value_;
    247   int on_focus_changed_calls_;
    248   bool is_focused_;
    249   int on_toggle_voice_search_calls_;
    250   std::string prefetch_query_value_;
    251 };
    252 
    253 class InstantExtendedPrefetchTest : public InstantExtendedTest {
    254  public:
    255   InstantExtendedPrefetchTest()
    256       : factory_(new net::URLFetcherImplFactory()),
    257         fake_factory_(new net::FakeURLFetcherFactory(factory_.get())) {
    258   }
    259 
    260   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
    261     chrome::EnableQueryExtractionForTesting();
    262     ASSERT_TRUE(https_test_server().Start());
    263     GURL instant_url = https_test_server().GetURL(
    264         "files/instant_extended.html?strk=1&");
    265     GURL ntp_url = https_test_server().GetURL(
    266         "files/instant_extended_ntp.html?strk=1&");
    267     InstantTestBase::Init(instant_url, ntp_url, true);
    268   }
    269 
    270   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    271     command_line->AppendSwitchASCII(
    272         switches::kForceFieldTrials,
    273         "EmbeddedSearch/Group11 prefetch_results_srp:1/");
    274   }
    275 
    276   net::FakeURLFetcherFactory* fake_factory() { return fake_factory_.get(); }
    277 
    278  private:
    279   // Used to instantiate FakeURLFetcherFactory.
    280   scoped_ptr<net::URLFetcherImplFactory> factory_;
    281 
    282   // Used to mock default search provider suggest response.
    283   scoped_ptr<net::FakeURLFetcherFactory> fake_factory_;
    284 
    285   DISALLOW_COPY_AND_ASSIGN(InstantExtendedPrefetchTest);
    286 };
    287 
    288 class InstantExtendedNetworkTest : public InstantExtendedTest {
    289  protected:
    290   virtual void SetUpOnMainThread() OVERRIDE {
    291     disable_for_test_.reset(new net::NetworkChangeNotifier::DisableForTest);
    292     fake_network_change_notifier_.reset(new FakeNetworkChangeNotifier);
    293     InstantExtendedTest::SetUpOnMainThread();
    294   }
    295 
    296   virtual void CleanUpOnMainThread() OVERRIDE {
    297     InstantExtendedTest::CleanUpOnMainThread();
    298     fake_network_change_notifier_.reset();
    299     disable_for_test_.reset();
    300   }
    301 
    302   void SetConnectionType(net::NetworkChangeNotifier::ConnectionType type) {
    303     fake_network_change_notifier_->SetConnectionType(type);
    304   }
    305 
    306  private:
    307   scoped_ptr<net::NetworkChangeNotifier::DisableForTest> disable_for_test_;
    308   scoped_ptr<FakeNetworkChangeNotifier> fake_network_change_notifier_;
    309 };
    310 
    311 // Test class used to verify chrome-search: scheme and access policy from the
    312 // Instant overlay.  This is a subclass of |ExtensionBrowserTest| because it
    313 // loads a theme that provides a background image.
    314 class InstantPolicyTest : public ExtensionBrowserTest, public InstantTestBase {
    315  public:
    316   InstantPolicyTest() {}
    317 
    318  protected:
    319   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
    320     ASSERT_TRUE(https_test_server().Start());
    321     GURL instant_url = https_test_server().GetURL(
    322         "files/instant_extended.html?strk=1&");
    323     GURL ntp_url = https_test_server().GetURL(
    324         "files/instant_extended_ntp.html?strk=1&");
    325     InstantTestBase::Init(instant_url, ntp_url, false);
    326   }
    327 
    328   void InstallThemeSource() {
    329     ThemeSource* theme = new ThemeSource(profile());
    330     content::URLDataSource::Add(profile(), theme);
    331   }
    332 
    333   void InstallThemeAndVerify(const std::string& theme_dir,
    334                              const std::string& theme_name) {
    335     const extensions::Extension* theme =
    336         ThemeServiceFactory::GetThemeForProfile(
    337             ExtensionBrowserTest::browser()->profile());
    338     // If there is already a theme installed, the current theme should be
    339     // disabled and the new one installed + enabled.
    340     int expected_change = theme ? 0 : 1;
    341 
    342     const base::FilePath theme_path = test_data_dir_.AppendASCII(theme_dir);
    343     ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(
    344         theme_path, expected_change, ExtensionBrowserTest::browser()));
    345     const extensions::Extension* new_theme =
    346         ThemeServiceFactory::GetThemeForProfile(
    347             ExtensionBrowserTest::browser()->profile());
    348     ASSERT_NE(static_cast<extensions::Extension*>(NULL), new_theme);
    349     ASSERT_EQ(new_theme->name(), theme_name);
    350   }
    351 
    352  private:
    353   DISALLOW_COPY_AND_ASSIGN(InstantPolicyTest);
    354 };
    355 
    356 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, SearchReusesInstantTab) {
    357   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
    358   FocusOmnibox();
    359 
    360   content::WindowedNotificationObserver observer(
    361       chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
    362       content::NotificationService::AllSources());
    363   SetOmniboxText("flowers");
    364   PressEnterAndWaitForFrameLoad();
    365   observer.Wait();
    366 
    367   // Just did a regular search.
    368   content::WebContents* active_tab =
    369       browser()->tab_strip_model()->GetActiveWebContents();
    370   ASSERT_THAT(active_tab->GetURL().spec(), HasSubstr("q=flowers"));
    371   ASSERT_TRUE(UpdateSearchState(active_tab));
    372   ASSERT_EQ(0, submit_count_);
    373 
    374   SetOmniboxText("puppies");
    375   PressEnterAndWaitForNavigation();
    376 
    377   // Should have reused the tab and sent an onsubmit message.
    378   active_tab = browser()->tab_strip_model()->GetActiveWebContents();
    379   ASSERT_THAT(active_tab->GetURL().spec(), HasSubstr("q=puppies"));
    380   ASSERT_TRUE(UpdateSearchState(active_tab));
    381   EXPECT_EQ(1, submit_count_);
    382 }
    383 
    384 IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
    385                        SearchDoesntReuseInstantTabWithoutSupport) {
    386   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
    387   FocusOmnibox();
    388 
    389   // Don't wait for the navigation to complete.
    390   SetOmniboxText("flowers");
    391   browser()->window()->GetLocationBar()->AcceptInput();
    392 
    393   SetOmniboxText("puppies");
    394   browser()->window()->GetLocationBar()->AcceptInput();
    395 
    396   // Should not have reused the tab.
    397   ASSERT_THAT(
    398       browser()->tab_strip_model()->GetActiveWebContents()->GetURL().spec(),
    399       HasSubstr("q=puppies"));
    400 }
    401 
    402 IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
    403                        TypedSearchURLDoesntReuseInstantTab) {
    404   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
    405   FocusOmnibox();
    406 
    407   // Create an observer to wait for the instant tab to support Instant.
    408   content::WindowedNotificationObserver observer_1(
    409       chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
    410       content::NotificationService::AllSources());
    411   SetOmniboxText("flowers");
    412   PressEnterAndWaitForFrameLoad();
    413   observer_1.Wait();
    414 
    415   // Just did a regular search.
    416   content::WebContents* active_tab =
    417       browser()->tab_strip_model()->GetActiveWebContents();
    418   ASSERT_THAT(active_tab->GetURL().spec(), HasSubstr("q=flowers"));
    419   ASSERT_TRUE(UpdateSearchState(active_tab));
    420   ASSERT_EQ(0, submit_count_);
    421 
    422   // Typed in a search URL "by hand".
    423   content::WindowedNotificationObserver observer_2(
    424       chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
    425       content::NotificationService::AllSources());
    426   SetOmniboxText(instant_url().Resolve("#q=puppies").spec());
    427   PressEnterAndWaitForNavigation();
    428   observer_2.Wait();
    429 
    430   // Should not have reused the tab.
    431   active_tab = browser()->tab_strip_model()->GetActiveWebContents();
    432   ASSERT_THAT(active_tab->GetURL().spec(), HasSubstr("q=puppies"));
    433 }
    434 
    435 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, OmniboxMarginSetForSearchURLs) {
    436   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
    437   FocusOmnibox();
    438 
    439   // Create an observer to wait for the instant tab to support Instant.
    440   content::WindowedNotificationObserver observer(
    441       chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
    442       content::NotificationService::AllSources());
    443 
    444   SetOmniboxText("flowers");
    445   browser()->window()->GetLocationBar()->AcceptInput();
    446   observer.Wait();
    447 
    448   const std::string& url =
    449       browser()->tab_strip_model()->GetActiveWebContents()->GetURL().spec();
    450   // Make sure we actually used search_url, not instant_url.
    451   ASSERT_THAT(url, HasSubstr("&is_search"));
    452   EXPECT_THAT(url, HasSubstr("&es_sm="));
    453 }
    454 
    455 // Test to verify that switching tabs should not dispatch onmostvisitedchanged
    456 // events.
    457 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, NoMostVisitedChangedOnTabSwitch) {
    458   // Initialize Instant.
    459   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
    460 
    461   // Open new tab.
    462   ui_test_utils::NavigateToURLWithDisposition(
    463       browser(),
    464       GURL(chrome::kChromeUINewTabURL),
    465       NEW_FOREGROUND_TAB,
    466       ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB |
    467       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
    468   EXPECT_EQ(2, browser()->tab_strip_model()->count());
    469 
    470   // Make sure new tab received the onmostvisitedchanged event once.
    471   content::WebContents* active_tab =
    472       browser()->tab_strip_model()->GetActiveWebContents();
    473   EXPECT_TRUE(UpdateSearchState(active_tab));
    474   EXPECT_EQ(1, on_most_visited_change_calls_);
    475 
    476   // Activate the previous tab.
    477   browser()->tab_strip_model()->ActivateTabAt(0, false);
    478 
    479   // Switch back to new tab.
    480   browser()->tab_strip_model()->ActivateTabAt(1, false);
    481 
    482   // Confirm that new tab got no onmostvisitedchanged event.
    483   active_tab = browser()->tab_strip_model()->GetActiveWebContents();
    484   EXPECT_TRUE(UpdateSearchState(active_tab));
    485   EXPECT_EQ(1, on_most_visited_change_calls_);
    486 }
    487 
    488 IN_PROC_BROWSER_TEST_F(InstantPolicyTest, ThemeBackgroundAccess) {
    489   InstallThemeSource();
    490   ASSERT_NO_FATAL_FAILURE(InstallThemeAndVerify("theme", "camo theme"));
    491   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
    492 
    493   // The "Instant" New Tab should have access to chrome-search: scheme but not
    494   // chrome: scheme.
    495   ui_test_utils::NavigateToURLWithDisposition(
    496       browser(),
    497       GURL(chrome::kChromeUINewTabURL),
    498       NEW_FOREGROUND_TAB,
    499       ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB |
    500       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
    501 
    502   content::RenderViewHost* rvh =
    503       browser()->tab_strip_model()->GetActiveWebContents()->GetRenderViewHost();
    504 
    505   const std::string chrome_url("chrome://theme/IDR_THEME_NTP_BACKGROUND");
    506   const std::string search_url(
    507       "chrome-search://theme/IDR_THEME_NTP_BACKGROUND");
    508   bool loaded = false;
    509   ASSERT_TRUE(LoadImage(rvh, chrome_url, &loaded));
    510   EXPECT_FALSE(loaded) << chrome_url;
    511   ASSERT_TRUE(LoadImage(rvh, search_url, &loaded));
    512   EXPECT_TRUE(loaded) << search_url;
    513 }
    514 
    515 // Flaky on all bots. http://crbug.com/335297.
    516 IN_PROC_BROWSER_TEST_F(InstantPolicyTest,
    517                        DISABLED_NoThemeBackgroundChangeEventOnTabSwitch) {
    518   InstallThemeSource();
    519   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
    520 
    521   // Install a theme.
    522   ASSERT_NO_FATAL_FAILURE(InstallThemeAndVerify("theme", "camo theme"));
    523   EXPECT_EQ(1, browser()->tab_strip_model()->count());
    524 
    525   // Open new tab.
    526   ui_test_utils::NavigateToURLWithDisposition(
    527       browser(),
    528       GURL(chrome::kChromeUINewTabURL),
    529       NEW_FOREGROUND_TAB,
    530       ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB |
    531       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
    532   EXPECT_EQ(2, browser()->tab_strip_model()->count());
    533 
    534   content::WebContents* active_tab =
    535       browser()->tab_strip_model()->GetActiveWebContents();
    536   ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
    537   int on_theme_changed_calls = 0;
    538   EXPECT_TRUE(GetIntFromJS(active_tab, "onThemeChangedCalls",
    539                            &on_theme_changed_calls));
    540   EXPECT_EQ(1, on_theme_changed_calls);
    541 
    542   // Activate the previous tab.
    543   browser()->tab_strip_model()->ActivateTabAt(0, false);
    544   ASSERT_EQ(0, browser()->tab_strip_model()->active_index());
    545 
    546   // Switch back to new tab.
    547   browser()->tab_strip_model()->ActivateTabAt(1, false);
    548   ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
    549 
    550   // Confirm that new tab got no onthemechanged event while switching tabs.
    551   active_tab = browser()->tab_strip_model()->GetActiveWebContents();
    552   on_theme_changed_calls = 0;
    553   EXPECT_TRUE(GetIntFromJS(active_tab, "onThemeChangedCalls",
    554                            &on_theme_changed_calls));
    555   EXPECT_EQ(1, on_theme_changed_calls);
    556 }
    557 
    558 // Flaky on all bots. http://crbug.com/335297, http://crbug.com/265971.
    559 IN_PROC_BROWSER_TEST_F(InstantPolicyTest,
    560                        DISABLED_SendThemeBackgroundChangedEvent) {
    561   InstallThemeSource();
    562   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
    563 
    564   // Install a theme.
    565   ASSERT_NO_FATAL_FAILURE(InstallThemeAndVerify("theme", "camo theme"));
    566 
    567   // Open new tab.
    568   ui_test_utils::NavigateToURLWithDisposition(
    569       browser(),
    570       GURL(chrome::kChromeUINewTabURL),
    571       NEW_FOREGROUND_TAB,
    572       ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB |
    573       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
    574   EXPECT_EQ(2, browser()->tab_strip_model()->count());
    575 
    576   // Make sure new tab received an onthemechanged event.
    577   content::WebContents* active_tab =
    578       browser()->tab_strip_model()->GetActiveWebContents();
    579   ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
    580   int on_theme_changed_calls = 0;
    581   EXPECT_TRUE(GetIntFromJS(active_tab, "onThemeChangedCalls",
    582                            &on_theme_changed_calls));
    583   EXPECT_EQ(1, on_theme_changed_calls);
    584 
    585   // Install a new theme.
    586   ASSERT_NO_FATAL_FAILURE(InstallThemeAndVerify("theme2", "snowflake theme"));
    587 
    588   // Confirm that new tab is notified about the theme changed event.
    589   on_theme_changed_calls = 0;
    590   EXPECT_TRUE(GetIntFromJS(active_tab, "onThemeChangedCalls",
    591                            &on_theme_changed_calls));
    592   EXPECT_EQ(2, on_theme_changed_calls);
    593 }
    594 
    595 // Flaky on Mac and Linux Tests bots.
    596 #if defined(OS_MACOSX) || defined(OS_LINUX)
    597 #define MAYBE_UpdateSearchQueryOnBackNavigation DISABLED_UpdateSearchQueryOnBackNavigation
    598 #else
    599 #define MAYBE_UpdateSearchQueryOnBackNavigation UpdateSearchQueryOnBackNavigation
    600 #endif
    601 // Test to verify that the omnibox search query is updated on browser
    602 // back button press event.
    603 IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
    604                        MAYBE_UpdateSearchQueryOnBackNavigation) {
    605   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
    606 
    607   // Focus omnibox and confirm overlay isn't shown.
    608   FocusOmnibox();
    609 
    610   // Create an observer to wait for the instant tab to support Instant.
    611   content::WindowedNotificationObserver observer(
    612       chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
    613       content::NotificationService::AllSources());
    614 
    615   SetOmniboxText("flowers");
    616   // Commit the search by pressing 'Enter'.
    617   PressEnterAndWaitForNavigation();
    618   observer.Wait();
    619 
    620   EXPECT_EQ(ASCIIToUTF16("flowers"), omnibox()->GetText());
    621 
    622   // Typing in the new search query in omnibox.
    623   SetOmniboxText("cattles");
    624   // Commit the search by pressing 'Enter'.
    625   PressEnterAndWaitForNavigation();
    626   // 'Enter' commits the query as it was typed. This creates a navigation entry
    627   // in the history.
    628   EXPECT_EQ(ASCIIToUTF16("cattles"), omnibox()->GetText());
    629 
    630   content::WebContents* active_tab =
    631       browser()->tab_strip_model()->GetActiveWebContents();
    632   EXPECT_TRUE(active_tab->GetController().CanGoBack());
    633   content::WindowedNotificationObserver load_stop_observer(
    634       content::NOTIFICATION_LOAD_STOP,
    635       content::Source<content::NavigationController>(
    636           &active_tab->GetController()));
    637   active_tab->GetController().GoBack();
    638   load_stop_observer.Wait();
    639 
    640   EXPECT_EQ(ASCIIToUTF16("flowers"), omnibox()->GetText());
    641   // Commit the search by pressing 'Enter'.
    642   FocusOmnibox();
    643   PressEnterAndWaitForNavigation();
    644   EXPECT_EQ(ASCIIToUTF16("flowers"), omnibox()->GetText());
    645 }
    646 
    647 // Flaky: crbug.com/253092.
    648 // Test to verify that the omnibox search query is updated on browser
    649 // forward button press events.
    650 IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
    651                        DISABLED_UpdateSearchQueryOnForwardNavigation) {
    652   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
    653 
    654   // Focus omnibox and confirm overlay isn't shown.
    655   FocusOmnibox();
    656 
    657   // Create an observer to wait for the instant tab to support Instant.
    658   content::WindowedNotificationObserver observer(
    659       chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
    660       content::NotificationService::AllSources());
    661 
    662   SetOmniboxText("flowers");
    663   // Commit the search by pressing 'Enter'.
    664   PressEnterAndWaitForNavigation();
    665   observer.Wait();
    666 
    667   EXPECT_EQ(ASCIIToUTF16("flowers"), omnibox()->GetText());
    668 
    669   // Typing in the new search query in omnibox.
    670   SetOmniboxText("cattles");
    671   // Commit the search by pressing 'Enter'.
    672   PressEnterAndWaitForNavigation();
    673   // 'Enter' commits the query as it was typed. This creates a navigation entry
    674   // in the history.
    675   EXPECT_EQ(ASCIIToUTF16("cattles"), omnibox()->GetText());
    676 
    677   content::WebContents* active_tab =
    678       browser()->tab_strip_model()->GetActiveWebContents();
    679   EXPECT_TRUE(active_tab->GetController().CanGoBack());
    680   content::WindowedNotificationObserver load_stop_observer(
    681       content::NOTIFICATION_LOAD_STOP,
    682       content::Source<content::NavigationController>(
    683           &active_tab->GetController()));
    684   active_tab->GetController().GoBack();
    685   load_stop_observer.Wait();
    686 
    687   EXPECT_EQ(ASCIIToUTF16("flowers"), omnibox()->GetText());
    688 
    689   active_tab = browser()->tab_strip_model()->GetActiveWebContents();
    690   EXPECT_TRUE(active_tab->GetController().CanGoForward());
    691   content::WindowedNotificationObserver load_stop_observer_2(
    692       content::NOTIFICATION_LOAD_STOP,
    693       content::Source<content::NavigationController>(
    694           &active_tab->GetController()));
    695   active_tab->GetController().GoForward();
    696   load_stop_observer_2.Wait();
    697 
    698   // Commit the search by pressing 'Enter'.
    699   FocusOmnibox();
    700   EXPECT_EQ(ASCIIToUTF16("cattles"), omnibox()->GetText());
    701   PressEnterAndWaitForNavigation();
    702   EXPECT_EQ(ASCIIToUTF16("cattles"), omnibox()->GetText());
    703 }
    704 
    705 // Flaky on all bots since re-enabled in r208032, crbug.com/253092
    706 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, DISABLED_NavigateBackToNTP) {
    707   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
    708   FocusOmnibox();
    709 
    710   // Open a new tab page.
    711   ui_test_utils::NavigateToURLWithDisposition(
    712       browser(),
    713       GURL(chrome::kChromeUINewTabURL),
    714       NEW_FOREGROUND_TAB,
    715       ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB |
    716       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
    717   EXPECT_EQ(2, browser()->tab_strip_model()->count());
    718 
    719   content::WindowedNotificationObserver observer(
    720       chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
    721       content::NotificationService::AllSources());
    722   SetOmniboxText("flowers");
    723   PressEnterAndWaitForNavigation();
    724   observer.Wait();
    725 
    726   EXPECT_EQ(ASCIIToUTF16("flowers"), omnibox()->GetText());
    727 
    728   // Typing in the new search query in omnibox.
    729   // Commit the search by pressing 'Enter'.
    730   SetOmniboxText("cattles");
    731   PressEnterAndWaitForNavigation();
    732 
    733   // 'Enter' commits the query as it was typed. This creates a navigation entry
    734   // in the history.
    735   EXPECT_EQ(ASCIIToUTF16("cattles"), omnibox()->GetText());
    736 
    737   // Navigate back to "flowers" search result page.
    738   content::WebContents* active_tab =
    739       browser()->tab_strip_model()->GetActiveWebContents();
    740   EXPECT_TRUE(active_tab->GetController().CanGoBack());
    741   content::WindowedNotificationObserver load_stop_observer(
    742       content::NOTIFICATION_LOAD_STOP,
    743       content::Source<content::NavigationController>(
    744           &active_tab->GetController()));
    745   active_tab->GetController().GoBack();
    746   load_stop_observer.Wait();
    747 
    748   EXPECT_EQ(ASCIIToUTF16("flowers"), omnibox()->GetText());
    749 
    750   // Navigate back to NTP.
    751   active_tab = browser()->tab_strip_model()->GetActiveWebContents();
    752   EXPECT_TRUE(active_tab->GetController().CanGoBack());
    753   content::WindowedNotificationObserver load_stop_observer_2(
    754       content::NOTIFICATION_LOAD_STOP,
    755       content::Source<content::NavigationController>(
    756           &active_tab->GetController()));
    757   active_tab->GetController().GoBack();
    758   load_stop_observer_2.Wait();
    759 
    760   active_tab = browser()->tab_strip_model()->GetActiveWebContents();
    761   EXPECT_TRUE(chrome::IsInstantNTP(active_tab));
    762 }
    763 
    764 // Flaky: crbug.com/267119
    765 IN_PROC_BROWSER_TEST_F(InstantExtendedTest,
    766                        DISABLED_DispatchMVChangeEventWhileNavigatingBackToNTP) {
    767   // Setup Instant.
    768   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
    769   FocusOmnibox();
    770 
    771   // Open new tab.
    772   ui_test_utils::NavigateToURLWithDisposition(
    773       browser(),
    774       GURL(chrome::kChromeUINewTabURL),
    775       NEW_FOREGROUND_TAB,
    776       ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB |
    777       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
    778 
    779   content::WebContents* active_tab =
    780       browser()->tab_strip_model()->GetActiveWebContents();
    781   EXPECT_TRUE(UpdateSearchState(active_tab));
    782   EXPECT_EQ(1, on_most_visited_change_calls_);
    783 
    784   content::WindowedNotificationObserver observer(
    785       content::NOTIFICATION_LOAD_STOP,
    786       content::NotificationService::AllSources());
    787   // Set the text and press enter to navigate from NTP.
    788   SetOmniboxText("Pen");
    789   PressEnterAndWaitForNavigation();
    790   EXPECT_EQ(ASCIIToUTF16("Pen"), omnibox()->GetText());
    791   observer.Wait();
    792 
    793   // Navigate back to NTP.
    794   content::WindowedNotificationObserver back_observer(
    795       content::NOTIFICATION_LOAD_STOP,
    796       content::NotificationService::AllSources());
    797   active_tab = browser()->tab_strip_model()->GetActiveWebContents();
    798   EXPECT_TRUE(active_tab->GetController().CanGoBack());
    799   active_tab->GetController().GoBack();
    800   back_observer.Wait();
    801 
    802   // Verify that onmostvisitedchange event is dispatched when we navigate from
    803   // SRP to NTP.
    804   active_tab = browser()->tab_strip_model()->GetActiveWebContents();
    805   EXPECT_TRUE(UpdateSearchState(active_tab));
    806   EXPECT_EQ(1, on_most_visited_change_calls_);
    807 }
    808 
    809 IN_PROC_BROWSER_TEST_F(InstantExtendedPrefetchTest, SetPrefetchQuery) {
    810   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
    811   FocusOmnibox();
    812 
    813   content::WindowedNotificationObserver new_tab_observer(
    814       content::NOTIFICATION_NAV_ENTRY_COMMITTED,
    815       content::NotificationService::AllSources());
    816   ui_test_utils::NavigateToURLWithDisposition(
    817       browser(),
    818       GURL(chrome::kChromeUINewTabURL),
    819       CURRENT_TAB,
    820       ui_test_utils::BROWSER_TEST_NONE);
    821   new_tab_observer.Wait();
    822 
    823   omnibox()->model()->autocomplete_controller()->search_provider()->
    824       kMinimumTimeBetweenSuggestQueriesMs = 0;
    825 
    826   // Set the fake response for search query.
    827   fake_factory()->SetFakeResponse(instant_url().Resolve("#q=flowers"),
    828                                   "",
    829                                   net::HTTP_OK,
    830                                   net::URLRequestStatus::SUCCESS);
    831 
    832   // Navigate to a search results page.
    833   content::WindowedNotificationObserver observer(
    834       chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
    835       content::NotificationService::AllSources());
    836   SetOmniboxText("flowers");
    837   PressEnterAndWaitForNavigation();
    838   observer.Wait();
    839 
    840   // Set the fake response for suggest request. Response has prefetch details.
    841   // Ensure that the page received the prefetch query.
    842   fake_factory()->SetFakeResponse(
    843       instant_url().Resolve("#q=pupp"),
    844       "[\"pupp\",[\"puppy\", \"puppies\"],[],[],"
    845       "{\"google:clientdata\":{\"phi\": 0},"
    846           "\"google:suggesttype\":[\"QUERY\", \"QUERY\"],"
    847           "\"google:suggestrelevance\":[1400, 9]}]",
    848       net::HTTP_OK,
    849       net::URLRequestStatus::SUCCESS);
    850 
    851   SetOmniboxText("pupp");
    852   while (!omnibox()->model()->autocomplete_controller()->done()) {
    853     content::WindowedNotificationObserver ready_observer(
    854         chrome::NOTIFICATION_AUTOCOMPLETE_CONTROLLER_RESULT_READY,
    855         content::Source<AutocompleteController>(
    856             omnibox()->model()->autocomplete_controller()));
    857     ready_observer.Wait();
    858   }
    859 
    860   ASSERT_EQ(3, CountSearchProviderSuggestions());
    861   content::WebContents* active_tab =
    862       browser()->tab_strip_model()->GetActiveWebContents();
    863   ASSERT_TRUE(UpdateSearchState(active_tab));
    864   ASSERT_TRUE(SearchProvider::ShouldPrefetch(*(
    865       omnibox()->model()->result().default_match())));
    866   ASSERT_EQ("puppy", prefetch_query_value_);
    867 }
    868 
    869 IN_PROC_BROWSER_TEST_F(InstantExtendedPrefetchTest, ClearPrefetchedResults) {
    870   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
    871   FocusOmnibox();
    872 
    873   content::WindowedNotificationObserver new_tab_observer(
    874       content::NOTIFICATION_NAV_ENTRY_COMMITTED,
    875       content::NotificationService::AllSources());
    876   ui_test_utils::NavigateToURLWithDisposition(
    877       browser(),
    878       GURL(chrome::kChromeUINewTabURL),
    879       CURRENT_TAB,
    880       ui_test_utils::BROWSER_TEST_NONE);
    881   new_tab_observer.Wait();
    882 
    883   omnibox()->model()->autocomplete_controller()->search_provider()->
    884       kMinimumTimeBetweenSuggestQueriesMs = 0;
    885 
    886   // Set the fake response for search query.
    887   fake_factory()->SetFakeResponse(instant_url().Resolve("#q=flowers"),
    888                                   "",
    889                                   net::HTTP_OK,
    890                                   net::URLRequestStatus::SUCCESS);
    891 
    892   // Navigate to a search results page.
    893   content::WindowedNotificationObserver observer(
    894       chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
    895       content::NotificationService::AllSources());
    896   SetOmniboxText("flowers");
    897   PressEnterAndWaitForNavigation();
    898   observer.Wait();
    899 
    900   // Set the fake response for suggest request. Response has no prefetch
    901   // details. Ensure that the page received a blank query to clear the
    902   // prefetched results.
    903   fake_factory()->SetFakeResponse(
    904       instant_url().Resolve("#q=dogs"),
    905       "[\"dogs\",[\"https://dogs.com\"],[],[],"
    906           "{\"google:suggesttype\":[\"NAVIGATION\"],"
    907           "\"google:suggestrelevance\":[2]}]",
    908       net::HTTP_OK,
    909       net::URLRequestStatus::SUCCESS);
    910 
    911   SetOmniboxText("dogs");
    912   while (!omnibox()->model()->autocomplete_controller()->done()) {
    913     content::WindowedNotificationObserver ready_observer(
    914         chrome::NOTIFICATION_AUTOCOMPLETE_CONTROLLER_RESULT_READY,
    915         content::Source<AutocompleteController>(
    916             omnibox()->model()->autocomplete_controller()));
    917     ready_observer.Wait();
    918   }
    919 
    920   ASSERT_EQ(2, CountSearchProviderSuggestions());
    921   ASSERT_FALSE(SearchProvider::ShouldPrefetch(*(
    922       omnibox()->model()->result().default_match())));
    923   content::WebContents* active_tab =
    924       browser()->tab_strip_model()->GetActiveWebContents();
    925   ASSERT_TRUE(UpdateSearchState(active_tab));
    926   ASSERT_EQ("", prefetch_query_value_);
    927 }
    928 
    929 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, ShowURL) {
    930   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
    931   FocusOmnibox();
    932 
    933   // Create an observer to wait for the instant tab to support Instant.
    934   content::WindowedNotificationObserver observer(
    935       chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
    936       content::NotificationService::AllSources());
    937 
    938   // Do a search and commit it.  The omnibox should show the search terms.
    939   SetOmniboxText("foo");
    940   EXPECT_EQ(ASCIIToUTF16("foo"), omnibox()->GetText());
    941   browser()->window()->GetLocationBar()->AcceptInput();
    942   observer.Wait();
    943   EXPECT_FALSE(omnibox()->model()->user_input_in_progress());
    944   EXPECT_TRUE(browser()->toolbar_model()->WouldPerformSearchTermReplacement(
    945       false));
    946   EXPECT_EQ(ASCIIToUTF16("foo"), omnibox()->GetText());
    947 
    948   // Calling ShowURL() should disable search term replacement and show the URL.
    949   omnibox()->ShowURL();
    950   EXPECT_FALSE(browser()->toolbar_model()->WouldPerformSearchTermReplacement(
    951       false));
    952   // Don't bother looking for a specific URL; ensuring we're no longer showing
    953   // the search terms is sufficient.
    954   EXPECT_NE(ASCIIToUTF16("foo"), omnibox()->GetText());
    955 }
    956 
    957 // Check that clicking on a result sends the correct referrer.
    958 IN_PROC_BROWSER_TEST_F(InstantExtendedTest, Referrer) {
    959   ASSERT_TRUE(test_server()->Start());
    960   GURL result_url =
    961       test_server()->GetURL("files/referrer_policy/referrer-policy-log.html");
    962   ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
    963   FocusOmnibox();
    964 
    965   // Type a query and press enter to get results.
    966   SetOmniboxText("query");
    967   PressEnterAndWaitForFrameLoad();
    968 
    969   // Simulate going to a result.
    970   content::WebContents* contents =
    971       browser()->tab_strip_model()->GetActiveWebContents();
    972   std::ostringstream stream;
    973   stream << "var link = document.createElement('a');";
    974   stream << "link.href = \"" << result_url.spec() << "\";";
    975   stream << "document.body.appendChild(link);";
    976   stream << "link.click();";
    977   EXPECT_TRUE(content::ExecuteScript(contents, stream.str()));
    978 
    979   content::WaitForLoadStop(contents);
    980   std::string expected_title =
    981       "Referrer is " + instant_url().GetWithEmptyPath().spec();
    982   EXPECT_EQ(ASCIIToUTF16(expected_title), contents->GetTitle());
    983 }
    984