instant_test_utils.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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 "chrome/browser/ui/search/instant_test_utils.h"
6
7#include "base/command_line.h"
8#include "base/prefs/pref_service.h"
9#include "chrome/browser/profiles/profile.h"
10#include "chrome/browser/search_engines/template_url_service.h"
11#include "chrome/browser/search_engines/template_url_service_factory.h"
12#include "chrome/browser/ui/omnibox/omnibox_view.h"
13#include "chrome/common/chrome_notification_types.h"
14#include "chrome/common/chrome_switches.h"
15#include "chrome/common/pref_names.h"
16#include "chrome/test/base/interactive_test_utils.h"
17#include "chrome/test/base/ui_test_utils.h"
18#include "content/public/browser/notification_service.h"
19#include "content/public/browser/render_process_host.h"
20#include "content/public/browser/web_contents.h"
21#include "content/public/common/result_codes.h"
22#include "content/public/test/browser_test_utils.h"
23
24namespace {
25
26std::string WrapScript(const std::string& script) {
27  return "domAutomationController.send(" + script + ")";
28}
29
30}  // namespace
31
32// InstantTestModelObserver --------------------------------------------------
33
34InstantTestModelObserver::InstantTestModelObserver(
35    InstantOverlayModel* model,
36    SearchMode::Type expected_mode_type)
37    : model_(model),
38      expected_mode_type_(expected_mode_type),
39      observed_mode_type_(static_cast<SearchMode::Type>(-1)) {
40  model_->AddObserver(this);
41}
42
43InstantTestModelObserver::~InstantTestModelObserver() {
44  model_->RemoveObserver(this);
45}
46
47SearchMode::Type InstantTestModelObserver::WaitForExpectedOverlayState() {
48  run_loop_.Run();
49  return observed_mode_type_;
50}
51
52void InstantTestModelObserver::OverlayStateChanged(
53    const InstantOverlayModel& model) {
54  observed_mode_type_ = model.mode().mode;
55  run_loop_.Quit();
56}
57
58// InstantTestBase -----------------------------------------------------------
59
60void InstantTestBase::SetupInstant(Browser* browser) {
61  browser_ = browser;
62  TemplateURLService* service =
63      TemplateURLServiceFactory::GetForProfile(browser_->profile());
64  ui_test_utils::WaitForTemplateURLServiceToLoad(service);
65
66  TemplateURLData data;
67  // Necessary to use exact URL for both the main URL and the alternate URL for
68  // search term extraction to work in InstantExtended.
69  data.SetURL(instant_url_.spec() + "q={searchTerms}");
70  data.instant_url = instant_url_.spec();
71  data.alternate_urls.push_back(instant_url_.spec() + "#q={searchTerms}");
72  data.search_terms_replacement_key = "strk";
73
74  TemplateURL* template_url = new TemplateURL(browser_->profile(), data);
75  service->Add(template_url);  // Takes ownership of |template_url|.
76  service->SetDefaultSearchProvider(template_url);
77
78  browser_->profile()->GetPrefs()->SetBoolean(prefs::kInstantEnabled, true);
79
80  // TODO(shishir): Fix this ugly hack.
81  instant()->SetInstantEnabled(false, true);
82  instant()->SetInstantEnabled(true, false);
83}
84
85void InstantTestBase::SetInstantURL(const std::string& url) {
86  TemplateURLService* service =
87      TemplateURLServiceFactory::GetForProfile(browser_->profile());
88  ui_test_utils::WaitForTemplateURLServiceToLoad(service);
89
90  TemplateURLData data;
91  data.SetURL(url);
92  data.instant_url = url;
93
94  TemplateURL* template_url = new TemplateURL(browser_->profile(), data);
95  service->Add(template_url);  // Takes ownership of |template_url|.
96  service->SetDefaultSearchProvider(template_url);
97}
98
99void InstantTestBase::Init(const GURL& instant_url) {
100  instant_url_ = instant_url;
101}
102
103void InstantTestBase::KillInstantRenderView() {
104  base::KillProcess(
105      instant()->GetOverlayContents()->GetRenderProcessHost()->GetHandle(),
106      content::RESULT_CODE_KILLED,
107      false);
108}
109
110void InstantTestBase::FocusOmnibox() {
111  // If the omnibox already has focus, just notify Instant.
112  if (omnibox()->model()->has_focus()) {
113    instant()->OmniboxFocusChanged(OMNIBOX_FOCUS_VISIBLE,
114                                   OMNIBOX_FOCUS_CHANGE_EXPLICIT, NULL);
115  } else {
116    browser_->window()->GetLocationBar()->FocusLocation(false);
117  }
118}
119
120void InstantTestBase::FocusOmniboxAndWaitForInstantOverlaySupport() {
121  content::WindowedNotificationObserver observer(
122      chrome::NOTIFICATION_INSTANT_OVERLAY_SUPPORT_DETERMINED,
123      content::NotificationService::AllSources());
124  FocusOmnibox();
125  observer.Wait();
126}
127
128void InstantTestBase::FocusOmniboxAndWaitForInstantOverlayAndNTPSupport() {
129  content::WindowedNotificationObserver ntp_observer(
130      chrome::NOTIFICATION_INSTANT_NTP_SUPPORT_DETERMINED,
131      content::NotificationService::AllSources());
132  content::WindowedNotificationObserver overlay_observer(
133      chrome::NOTIFICATION_INSTANT_OVERLAY_SUPPORT_DETERMINED,
134      content::NotificationService::AllSources());
135  FocusOmnibox();
136  ntp_observer.Wait();
137  overlay_observer.Wait();
138}
139
140void InstantTestBase::SetOmniboxText(const std::string& text) {
141  FocusOmnibox();
142  omnibox()->SetUserText(UTF8ToUTF16(text));
143}
144
145bool InstantTestBase::SetOmniboxTextAndWaitForOverlayToShow(
146    const std::string& text) {
147  // The order of events may be:
148  //   { hide, show } or just { show } depending on the order things
149  // flow in from GWS and Chrome's response to hiding the infobar and/or
150  // bookmark bar.  Note, the GWS response is relevant because of the
151  // Instant "MANUAL_*" tests.
152  InstantTestModelObserver first_observer(
153      instant()->model(), SearchMode::MODE_DEFAULT);
154  SetOmniboxText(text);
155
156  SearchMode::Type observed = first_observer.WaitForExpectedOverlayState();
157  if (observed == SearchMode::MODE_DEFAULT) {
158    InstantTestModelObserver second_observer(
159        instant()->model(), SearchMode::MODE_SEARCH_SUGGESTIONS);
160    observed = second_observer.WaitForExpectedOverlayState();
161  }
162  EXPECT_EQ(SearchMode::MODE_SEARCH_SUGGESTIONS, observed);
163  return observed == SearchMode::MODE_SEARCH_SUGGESTIONS;
164}
165
166void InstantTestBase::SetOmniboxTextAndWaitForSuggestion(
167    const std::string& text) {
168  content::WindowedNotificationObserver observer(
169      chrome::NOTIFICATION_INSTANT_SET_SUGGESTION,
170      content::NotificationService::AllSources());
171  SetOmniboxText(text);
172  observer.Wait();
173}
174
175bool InstantTestBase::GetBoolFromJS(content::WebContents* contents,
176                                    const std::string& script,
177                                    bool* result) {
178  return content::ExecuteScriptAndExtractBool(
179      contents, WrapScript(script), result);
180}
181
182bool InstantTestBase::GetIntFromJS(content::WebContents* contents,
183                                   const std::string& script,
184                                   int* result) {
185  return content::ExecuteScriptAndExtractInt(
186      contents, WrapScript(script), result);
187}
188
189bool InstantTestBase::GetStringFromJS(content::WebContents* contents,
190                                      const std::string& script,
191                                      std::string* result) {
192  return content::ExecuteScriptAndExtractString(
193      contents, WrapScript(script), result);
194}
195
196bool InstantTestBase::ExecuteScript(const std::string& script) {
197  return content::ExecuteScript(instant()->GetOverlayContents(), script);
198}
199
200bool InstantTestBase::CheckVisibilityIs(content::WebContents* contents,
201                                        bool expected) {
202  bool actual = !expected;  // Purposely start with a mis-match.
203  // We can only use ASSERT_*() in a method that returns void, hence this
204  // convoluted check.
205  return GetBoolFromJS(contents, "!document.webkitHidden", &actual) &&
206      actual == expected;
207}
208
209bool InstantTestBase::HasUserInputInProgress() {
210  return omnibox()->model()->user_input_in_progress_;
211}
212
213bool InstantTestBase::HasTemporaryText() {
214  return omnibox()->model()->has_temporary_text_;
215}
216
217bool InstantTestBase::LoadImage(content::RenderViewHost* rvh,
218                                const std::string& image,
219                                bool* loaded) {
220  std::string js_chrome =
221      "var img = document.createElement('img');"
222      "img.onerror = function() { domAutomationController.send(false); };"
223      "img.onload  = function() { domAutomationController.send(true); };"
224      "img.src = '" + image + "';";
225  return content::ExecuteScriptAndExtractBool(rvh, js_chrome, loaded);
226}
227
228string16 InstantTestBase::GetBlueText() {
229  size_t start = 0, end = 0;
230  omnibox()->GetSelectionBounds(&start, &end);
231  if (start > end)
232    std::swap(start, end);
233  return omnibox()->GetText().substr(start, end - start);
234}
235
236string16 InstantTestBase::GetGrayText() {
237  return omnibox()->GetInstantSuggestion();
238}
239