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
84using base::ASCIIToUTF16;
85using testing::HasSubstr;
86
87namespace {
88
89// Task used to make sure history has finished processing a request. Intended
90// for use with BlockUntilHistoryProcessesPendingRequests.
91class 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
110class 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
132class 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
253class 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
288class 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.
314class 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
356IN_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
384IN_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
402IN_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
435IN_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.
457IN_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
488IN_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.
516IN_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.
559IN_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.
603IN_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.
650IN_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
706IN_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
765IN_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
809IN_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
869IN_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
929IN_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.
958IN_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