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