1// Copyright (c) 2011 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 "base/command_line.h"
6#include "base/stringprintf.h"
7#include "base/utf_string_conversions.h"
8#include "chrome/browser/autocomplete/autocomplete_edit.h"
9#include "chrome/browser/autocomplete/autocomplete_edit_view.h"
10#include "chrome/browser/content_settings/host_content_settings_map.h"
11#include "chrome/browser/instant/instant_controller.h"
12#include "chrome/browser/instant/instant_loader.h"
13#include "chrome/browser/instant/instant_loader_manager.h"
14#include "chrome/browser/profiles/profile.h"
15#include "chrome/browser/search_engines/template_url.h"
16#include "chrome/browser/search_engines/template_url_model.h"
17#include "chrome/browser/ui/browser.h"
18#include "chrome/browser/ui/browser_list.h"
19#include "chrome/browser/ui/browser_window.h"
20#include "chrome/browser/ui/omnibox/location_bar.h"
21#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
22#include "chrome/common/url_constants.h"
23#include "chrome/test/in_process_browser_test.h"
24#include "chrome/test/ui_test_utils.h"
25#include "content/browser/renderer_host/render_view_host.h"
26#include "content/browser/renderer_host/render_widget_host_view.h"
27#include "content/browser/tab_contents/tab_contents.h"
28
29#define EXPECT_STR_EQ(ascii, utf16) \
30  EXPECT_EQ(ASCIIToWide(ascii), UTF16ToWide(utf16))
31
32class InstantTest : public InProcessBrowserTest {
33 public:
34  InstantTest()
35      : location_bar_(NULL),
36        preview_(NULL) {
37    set_show_window(true);
38    EnableDOMAutomation();
39  }
40
41  void EnableInstant() {
42    InstantController::Enable(browser()->profile());
43  }
44
45  void SetupInstantProvider(const std::string& page) {
46    TemplateURLModel* model = browser()->profile()->GetTemplateURLModel();
47    ASSERT_TRUE(model);
48
49    if (!model->loaded()) {
50      model->Load();
51      ui_test_utils::WaitForNotification(
52          NotificationType::TEMPLATE_URL_MODEL_LOADED);
53    }
54
55    ASSERT_TRUE(model->loaded());
56
57    // TemplateURLModel takes ownership of this.
58    TemplateURL* template_url = new TemplateURL();
59
60    std::string url = StringPrintf(
61        "http://%s:%d/files/instant/%s?q={searchTerms}",
62        test_server()->host_port_pair().host().c_str(),
63        test_server()->host_port_pair().port(),
64        page.c_str());
65    template_url->SetURL(url, 0, 0);
66    template_url->SetInstantURL(url, 0, 0);
67    template_url->set_keyword(ASCIIToUTF16("foo"));
68    template_url->set_short_name(ASCIIToUTF16("foo"));
69
70    model->Add(template_url);
71    model->SetDefaultSearchProvider(template_url);
72  }
73
74  void FindLocationBar() {
75    if (location_bar_)
76      return;
77    location_bar_ = browser()->window()->GetLocationBar();
78    ASSERT_TRUE(location_bar_);
79  }
80
81  TabContentsWrapper* GetPendingPreviewContents() {
82    return browser()->instant()->GetPendingPreviewContents();
83  }
84
85  // Type a character to get instant to trigger.
86  void SetupLocationBar() {
87    FindLocationBar();
88    // "a" triggers the "about:" provider.  "b" begins the "bing.com" keyword.
89    // "c" might someday trigger a "chrome:" provider.
90    location_bar_->location_entry()->SetUserText(ASCIIToUTF16("d"));
91  }
92
93  // Waits for preview to be shown.
94  void WaitForPreviewToNavigate(bool use_current) {
95    InstantController* instant = browser()->instant();
96    ASSERT_TRUE(instant);
97    TabContentsWrapper* tab = use_current ?
98        instant->GetPreviewContents() : GetPendingPreviewContents();
99    ASSERT_TRUE(tab);
100    preview_ = tab->tab_contents();
101    ASSERT_TRUE(preview_);
102    ui_test_utils::WaitForNavigation(&preview_->controller());
103  }
104
105  // Wait for instant to load and ensure it is in the state we expect.
106  void SetupPreview() {
107    // Wait for the preview to navigate.
108    WaitForPreviewToNavigate(true);
109
110    ASSERT_TRUE(browser()->instant()->IsShowingInstant());
111    ASSERT_FALSE(browser()->instant()->is_displayable());
112    ASSERT_TRUE(browser()->instant()->is_active());
113
114    // When the page loads, the initial searchBox values are set and only a
115    // resize will have been sent.
116    ASSERT_EQ("true 0 0 0 1 d false d false 1 1",
117              GetSearchStateAsString(preview_, false));
118  }
119
120  void SetLocationBarText(const std::string& text) {
121    ASSERT_NO_FATAL_FAILURE(FindLocationBar());
122    location_bar_->location_entry()->SetUserText(UTF8ToUTF16(text));
123    ui_test_utils::WaitForNotification(
124        NotificationType::INSTANT_CONTROLLER_SHOWN);
125  }
126
127  const string16& GetSuggestion() const {
128    return browser()->instant()->loader_manager_->
129        current_loader()->complete_suggested_text_;
130  }
131
132  void SendKey(ui::KeyboardCode key) {
133    ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
134        browser(), key, false, false, false, false));
135  }
136
137  void SetSuggestionsJavascriptArgument(TabContents* tab_contents,
138                                        const std::string& argument) {
139    std::string script = StringPrintf(
140        "window.setSuggestionsArgument = %s;", argument.c_str());
141    ASSERT_TRUE(ui_test_utils::ExecuteJavaScript(
142        tab_contents->render_view_host(),
143        std::wstring(),
144        UTF8ToWide(script)));
145  }
146
147  bool GetStringFromJavascript(TabContents* tab_contents,
148                               const std::string& function,
149                               std::string* result) {
150    std::string script = StringPrintf(
151        "window.domAutomationController.send(%s)", function.c_str());
152    return ui_test_utils::ExecuteJavaScriptAndExtractString(
153        tab_contents->render_view_host(),
154        std::wstring(), UTF8ToWide(script), result);
155  }
156
157  bool GetIntFromJavascript(TabContents* tab_contents,
158                            const std::string& function,
159                            int* result) {
160    std::string script = StringPrintf(
161        "window.domAutomationController.send(%s)", function.c_str());
162    return ui_test_utils::ExecuteJavaScriptAndExtractInt(
163        tab_contents->render_view_host(),
164        std::wstring(), UTF8ToWide(script), result);
165  }
166
167  bool GetBoolFromJavascript(TabContents* tab_contents,
168                             const std::string& function,
169                             bool* result) {
170    std::string script = StringPrintf(
171        "window.domAutomationController.send(%s)", function.c_str());
172    return ui_test_utils::ExecuteJavaScriptAndExtractBool(
173        tab_contents->render_view_host(),
174        std::wstring(), UTF8ToWide(script), result);
175  }
176
177  // Returns the state of the search box as a string. This consists of the
178  // following:
179  // window.chrome.sv
180  // window.onsubmitcalls
181  // window.oncancelcalls
182  // window.onchangecalls
183  // window.onresizecalls
184  // window.beforeLoadSearchBox.value
185  // window.beforeLoadSearchBox.verbatim
186  // window.chrome.searchBox.value
187  // window.chrome.searchBox.verbatim
188  // window.chrome.searchBox.selectionStart
189  // window.chrome.searchBox.selectionEnd
190  // If determining any of the values fails, the value is 'fail'.
191  //
192  // If |use_last| is true, then the last searchBox values are used instead of
193  // the current. Set |use_last| to true when testing OnSubmit/OnCancel.
194  std::string GetSearchStateAsString(TabContents* tab_contents,
195                                     bool use_last) {
196    bool sv = false;
197    int onsubmitcalls = 0;
198    int oncancelcalls = 0;
199    int onchangecalls = 0;
200    int onresizecalls = 0;
201    int selection_start = 0;
202    int selection_end = 0;
203    std::string before_load_value;
204    bool before_load_verbatim = false;
205    std::string value;
206    bool verbatim = false;
207
208    if (!GetBoolFromJavascript(tab_contents, "window.chrome.sv", &sv) ||
209        !GetIntFromJavascript(tab_contents, "window.onsubmitcalls",
210                              &onsubmitcalls) ||
211        !GetIntFromJavascript(tab_contents, "window.oncancelcalls",
212                              &oncancelcalls) ||
213        !GetIntFromJavascript(tab_contents, "window.onchangecalls",
214                              &onchangecalls) ||
215        !GetIntFromJavascript(tab_contents, "window.onresizecalls",
216                              &onresizecalls) ||
217        !GetStringFromJavascript(
218            tab_contents, "window.beforeLoadSearchBox.value",
219            &before_load_value) ||
220        !GetBoolFromJavascript(
221            tab_contents, "window.beforeLoadSearchBox.verbatim",
222            &before_load_verbatim)) {
223      return "fail";
224    }
225
226    if (use_last &&
227        (!GetStringFromJavascript(tab_contents, "window.lastSearchBox.value",
228                                  &value) ||
229         !GetBoolFromJavascript(tab_contents, "window.lastSearchBox.verbatim",
230                                &verbatim) ||
231         !GetIntFromJavascript(tab_contents,
232                               "window.lastSearchBox.selectionStart",
233                               &selection_start) ||
234         !GetIntFromJavascript(tab_contents,
235                               "window.lastSearchBox.selectionEnd",
236                               &selection_end))) {
237      return "fail";
238    }
239
240    if (!use_last &&
241        (!GetStringFromJavascript(tab_contents, "window.searchBox.value",
242                                  &value) ||
243         !GetBoolFromJavascript(tab_contents, "window.searchBox.verbatim",
244                                &verbatim) ||
245         !GetIntFromJavascript(tab_contents,
246                               "window.searchBox.selectionStart",
247                               &selection_start) ||
248         !GetIntFromJavascript(tab_contents,
249                               "window.searchBox.selectionEnd",
250                               &selection_end))) {
251      return "fail";
252    }
253
254    return StringPrintf("%s %d %d %d %d %s %s %s %s %d %d",
255                        sv ? "true" : "false",
256                        onsubmitcalls,
257                        oncancelcalls,
258                        onchangecalls,
259                        onresizecalls,
260                        before_load_value.c_str(),
261                        before_load_verbatim ? "true" : "false",
262                        value.c_str(),
263                        verbatim ? "true" : "false",
264                        selection_start,
265                        selection_end);
266  }
267
268  void CheckStringValueFromJavascript(
269      const std::string& expected,
270      const std::string& function,
271      TabContents* tab_contents) {
272    std::string result;
273    ASSERT_TRUE(GetStringFromJavascript(tab_contents, function, &result));
274    ASSERT_EQ(expected, result);
275  }
276
277  void CheckBoolValueFromJavascript(
278      bool expected,
279      const std::string& function,
280      TabContents* tab_contents) {
281    bool result;
282    ASSERT_TRUE(GetBoolFromJavascript(tab_contents, function, &result));
283    ASSERT_EQ(expected, result);
284  }
285
286  void CheckIntValueFromJavascript(
287      int expected,
288      const std::string& function,
289      TabContents* tab_contents) {
290    int result;
291    ASSERT_TRUE(GetIntFromJavascript(tab_contents, function, &result));
292    ASSERT_EQ(expected, result);
293  }
294
295  // Sends a message to the renderer and waits for the response to come back to
296  // the browser.
297  void WaitForMessageToBeProcessedByRenderer(TabContentsWrapper* tab) {
298    ASSERT_NO_FATAL_FAILURE(
299        CheckBoolValueFromJavascript(true, "true", tab->tab_contents()));
300  }
301
302 protected:
303  LocationBar* location_bar_;
304  TabContents* preview_;
305};
306
307// TODO(tonyg): Add the following tests:
308// - Test that the search box API is not populated for pages other than the
309//   default search provider.
310// - Test resize events.
311
312// Verify that the onchange event is dispatched upon typing in the box.
313IN_PROC_BROWSER_TEST_F(InstantTest, OnChangeEvent) {
314  ASSERT_TRUE(test_server()->Start());
315  EnableInstant();
316  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
317  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
318  ASSERT_NO_FATAL_FAILURE(SetupPreview());
319
320  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
321
322  ASSERT_EQ(ASCIIToUTF16("defghi"), location_bar_->location_entry()->GetText());
323
324  // Make sure the url that will get committed when we press enter matches that
325  // of the default search provider.
326  const TemplateURL* default_turl =
327      browser()->profile()->GetTemplateURLModel()->GetDefaultSearchProvider();
328  ASSERT_TRUE(default_turl);
329  ASSERT_TRUE(default_turl->url());
330  EXPECT_EQ(default_turl->url()->ReplaceSearchTerms(
331                *default_turl, ASCIIToUTF16("defghi"), 0, string16()),
332            browser()->instant()->GetCurrentURL().spec());
333
334  // Check that the value is reflected and onchange is called.
335  EXPECT_EQ("true 0 0 1 2 d false def false 3 3",
336            GetSearchStateAsString(preview_, true));
337}
338
339IN_PROC_BROWSER_TEST_F(InstantTest, SetSuggestionsArrayOfStrings) {
340  ASSERT_TRUE(test_server()->Start());
341  EnableInstant();
342  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
343  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
344  ASSERT_NO_FATAL_FAILURE(SetupPreview());
345
346  SetSuggestionsJavascriptArgument(preview_, "['defgh', 'unused']");
347  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
348  EXPECT_STR_EQ("defgh", GetSuggestion());
349}
350
351IN_PROC_BROWSER_TEST_F(InstantTest, SetSuggestionsEmptyArray) {
352  ASSERT_TRUE(test_server()->Start());
353  EnableInstant();
354  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
355  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
356  ASSERT_NO_FATAL_FAILURE(SetupPreview());
357
358  SetSuggestionsJavascriptArgument(preview_, "[]");
359  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
360  EXPECT_STR_EQ("", GetSuggestion());
361}
362
363IN_PROC_BROWSER_TEST_F(InstantTest, SetSuggestionsValidJson) {
364  ASSERT_TRUE(test_server()->Start());
365  EnableInstant();
366  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
367  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
368  ASSERT_NO_FATAL_FAILURE(SetupPreview());
369
370  SetSuggestionsJavascriptArgument(
371      preview_,
372      "{suggestions:[{value:'defghij'},{value:'unused'}]}");
373  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
374  EXPECT_STR_EQ("defghij", GetSuggestion());
375}
376
377IN_PROC_BROWSER_TEST_F(InstantTest, SetSuggestionsInvalidSuggestions) {
378  ASSERT_TRUE(test_server()->Start());
379  EnableInstant();
380  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
381  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
382  ASSERT_NO_FATAL_FAILURE(SetupPreview());
383
384  SetSuggestionsJavascriptArgument(
385      preview_,
386      "{suggestions:{value:'defghi'}}");
387  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
388  EXPECT_STR_EQ("", GetSuggestion());
389}
390
391IN_PROC_BROWSER_TEST_F(InstantTest, SetSuggestionsEmptyJson) {
392  ASSERT_TRUE(test_server()->Start());
393  EnableInstant();
394  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
395  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
396  ASSERT_NO_FATAL_FAILURE(SetupPreview());
397
398  SetSuggestionsJavascriptArgument(preview_, "{}");
399  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
400  EXPECT_STR_EQ("", GetSuggestion());
401}
402
403IN_PROC_BROWSER_TEST_F(InstantTest, SetSuggestionsEmptySuggestions) {
404  ASSERT_TRUE(test_server()->Start());
405  EnableInstant();
406  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
407  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
408  ASSERT_NO_FATAL_FAILURE(SetupPreview());
409
410  SetSuggestionsJavascriptArgument(preview_, "{suggestions:[]}");
411  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
412  EXPECT_STR_EQ("", GetSuggestion());
413}
414
415IN_PROC_BROWSER_TEST_F(InstantTest, SetSuggestionsEmptySuggestion) {
416  ASSERT_TRUE(test_server()->Start());
417  EnableInstant();
418  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
419  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
420  ASSERT_NO_FATAL_FAILURE(SetupPreview());
421
422  SetSuggestionsJavascriptArgument(preview_, "{suggestions:[{}]}");
423  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
424  EXPECT_STR_EQ("", GetSuggestion());
425}
426
427// Verify instant preview is shown correctly for a non-search query.
428IN_PROC_BROWSER_TEST_F(InstantTest, ShowPreviewNonSearch) {
429  ASSERT_TRUE(test_server()->Start());
430  EnableInstant();
431  GURL url(test_server()->GetURL("files/instant/empty.html"));
432  ASSERT_NO_FATAL_FAILURE(SetLocationBarText(url.spec()));
433  // The preview should be active and showing.
434  ASSERT_TRUE(browser()->instant()->is_active());
435  ASSERT_TRUE(browser()->instant()->is_displayable());
436  ASSERT_TRUE(browser()->instant()->IsCurrent());
437  ASSERT_TRUE(browser()->instant()->GetPreviewContents());
438  RenderWidgetHostView* rwhv =
439      browser()->instant()->GetPreviewContents()->tab_contents()->
440      GetRenderWidgetHostView();
441  ASSERT_TRUE(rwhv);
442  ASSERT_TRUE(rwhv->IsShowing());
443}
444
445// Transition from non-search to search and make sure everything is shown
446// correctly.
447IN_PROC_BROWSER_TEST_F(InstantTest, NonSearchToSearch) {
448  ASSERT_TRUE(test_server()->Start());
449  EnableInstant();
450  GURL url(test_server()->GetURL("files/instant/empty.html"));
451  ASSERT_NO_FATAL_FAILURE(SetLocationBarText(url.spec()));
452  // The preview should be active and showing.
453  ASSERT_TRUE(browser()->instant()->is_active());
454  ASSERT_TRUE(browser()->instant()->is_displayable());
455  TabContentsWrapper* initial_tab = browser()->instant()->GetPreviewContents();
456  ASSERT_TRUE(initial_tab);
457  RenderWidgetHostView* rwhv =
458      initial_tab->tab_contents()->GetRenderWidgetHostView();
459  ASSERT_TRUE(rwhv);
460  ASSERT_TRUE(rwhv->IsShowing());
461
462  // Now type in some search text.
463  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
464  location_bar_->location_entry()->SetUserText(ASCIIToUTF16("def"));
465
466  // Wait for the preview to navigate.
467  ASSERT_NO_FATAL_FAILURE(WaitForPreviewToNavigate(false));
468
469  // The controller is still determining if the provider really supports
470  // instant. As a result the tabcontents should not have changed.
471  TabContentsWrapper* current_tab = browser()->instant()->GetPreviewContents();
472  ASSERT_EQ(current_tab, initial_tab);
473  // The preview should still be showing.
474  rwhv = current_tab->tab_contents()->GetRenderWidgetHostView();
475  ASSERT_TRUE(rwhv);
476  ASSERT_TRUE(rwhv->IsShowing());
477
478  // Use MightSupportInstant as the controller is still determining if the
479  // page supports instant and hasn't actually commited yet.
480  EXPECT_TRUE(browser()->instant()->MightSupportInstant());
481
482  // Instant should still be active.
483  EXPECT_TRUE(browser()->instant()->is_active());
484  EXPECT_TRUE(browser()->instant()->is_displayable());
485
486  // Because we're waiting on the page, instant isn't current.
487  ASSERT_FALSE(browser()->instant()->IsCurrent());
488
489  // Bounce a message to the renderer so that we know the instant has gotten a
490  // response back from the renderer as to whether the page supports instant.
491  ASSERT_NO_FATAL_FAILURE(
492      WaitForMessageToBeProcessedByRenderer(GetPendingPreviewContents()));
493
494  // Reset the user text so that the page is told the text changed. We should be
495  // able to nuke this once 66104 is fixed.
496  location_bar_->location_entry()->SetUserText(ASCIIToUTF16("defg"));
497
498  // Wait for the renderer to process it.
499  ASSERT_NO_FATAL_FAILURE(
500      WaitForMessageToBeProcessedByRenderer(GetPendingPreviewContents()));
501
502  // We should have gotten a response back from the renderer that resulted in
503  // committing.
504  ASSERT_FALSE(GetPendingPreviewContents());
505  ASSERT_TRUE(browser()->instant()->is_active());
506  ASSERT_TRUE(browser()->instant()->is_displayable());
507  TabContentsWrapper* new_tab = browser()->instant()->GetPreviewContents();
508  ASSERT_TRUE(new_tab);
509  ASSERT_NE(new_tab, initial_tab);
510  RenderWidgetHostView* new_rwhv =
511      new_tab->tab_contents()->GetRenderWidgetHostView();
512  ASSERT_TRUE(new_rwhv);
513  ASSERT_NE(new_rwhv, rwhv);
514  ASSERT_TRUE(new_rwhv->IsShowing());
515}
516
517// Makes sure that if the server doesn't support the instant API we don't show
518// anything.
519#if defined(OS_MACOSX) || defined(OS_LINUX)
520// Showing as flaky on Mac and Linux.
521// http://crbug.com/70860
522#define MAYBE_SearchServerDoesntSupportInstant \
523    DISABLED_SearchServerDoesntSupportInstant
524#else
525#define MAYBE_SearchServerDoesntSupportInstant \
526    SearchServerDoesntSupportInstant
527#endif
528IN_PROC_BROWSER_TEST_F(InstantTest, MAYBE_SearchServerDoesntSupportInstant) {
529  ASSERT_TRUE(test_server()->Start());
530  EnableInstant();
531  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("empty.html"));
532  ASSERT_NO_FATAL_FAILURE(FindLocationBar());
533  location_bar_->location_entry()->SetUserText(ASCIIToUTF16("d"));
534  ASSERT_TRUE(browser()->instant());
535  // Because we typed in a search string we should think we're showing instant
536  // results.
537  EXPECT_TRUE(browser()->instant()->IsShowingInstant());
538  // But because we're waiting to determine if the page really supports instant
539  // we shouldn't be showing the preview.
540  EXPECT_FALSE(browser()->instant()->is_displayable());
541  // But instant should still be active.
542  EXPECT_TRUE(browser()->instant()->is_active());
543
544  // When the response comes back that the page doesn't support instant the tab
545  // should be closed.
546  ui_test_utils::WaitForNotification(NotificationType::TAB_CLOSED);
547  EXPECT_FALSE(browser()->instant()->IsShowingInstant());
548  EXPECT_FALSE(browser()->instant()->is_displayable());
549  EXPECT_TRUE(browser()->instant()->is_active());
550  EXPECT_FALSE(browser()->instant()->IsCurrent());
551}
552
553// Verifies transitioning from loading a non-search string to a search string
554// with the provider not supporting instant works (meaning we don't display
555// anything).
556#if defined(OS_MACOSX) || defined(OS_LINUX)
557// Showing as flaky on Mac and Linux/ChromeOS
558// http://crbug.com/70810
559#define MAYBE_NonSearchToSearchDoesntSupportInstant \
560    DISABLED_NonSearchToSearchDoesntSupportInstant
561#else
562#define MAYBE_NonSearchToSearchDoesntSupportInstant \
563    NonSearchToSearchDoesntSupportInstant
564#endif
565IN_PROC_BROWSER_TEST_F(InstantTest,
566                       MAYBE_NonSearchToSearchDoesntSupportInstant) {
567  ASSERT_TRUE(test_server()->Start());
568  EnableInstant();
569  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("empty.html"));
570  GURL url(test_server()->GetURL("files/instant/empty.html"));
571  ASSERT_NO_FATAL_FAILURE(SetLocationBarText(url.spec()));
572  // The preview should be active and showing.
573  ASSERT_TRUE(browser()->instant()->is_displayable());
574  ASSERT_TRUE(browser()->instant()->is_active());
575  TabContentsWrapper* initial_tab = browser()->instant()->GetPreviewContents();
576  ASSERT_TRUE(initial_tab);
577  RenderWidgetHostView* rwhv =
578      initial_tab->tab_contents()->GetRenderWidgetHostView();
579  ASSERT_TRUE(rwhv);
580  ASSERT_TRUE(rwhv->IsShowing());
581
582  // Now type in some search text.
583  location_bar_->location_entry()->SetUserText(ASCIIToUTF16("d"));
584
585  // Instant should still be live.
586  ASSERT_TRUE(browser()->instant()->is_displayable());
587  ASSERT_TRUE(browser()->instant()->is_active());
588  // Because we typed in a search string we should think we're showing instant
589  // results.
590  EXPECT_TRUE(browser()->instant()->MightSupportInstant());
591  // Instant should not be current (it's still loading).
592  EXPECT_FALSE(browser()->instant()->IsCurrent());
593
594  // When the response comes back that the page doesn't support instant the tab
595  // should be closed.
596  ui_test_utils::WaitForNotification(NotificationType::TAB_CLOSED);
597  EXPECT_FALSE(browser()->instant()->IsShowingInstant());
598  EXPECT_FALSE(browser()->instant()->is_displayable());
599  // But because the omnibox is still open, instant should be active.
600  ASSERT_TRUE(browser()->instant()->is_active());
601}
602
603// Verifies the page was told a non-zero height.
604IN_PROC_BROWSER_TEST_F(InstantTest, ValidHeight) {
605  ASSERT_TRUE(test_server()->Start());
606  EnableInstant();
607  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
608  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
609  ASSERT_NO_FATAL_FAILURE(SetupPreview());
610
611  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
612
613  int height;
614
615  // searchBox height is not yet set during initial load.
616  ASSERT_TRUE(GetIntFromJavascript(preview_,
617      "window.beforeLoadSearchBox.height",
618      &height));
619  EXPECT_EQ(0, height);
620
621  // searchBox height is available by the time the page loads.
622  ASSERT_TRUE(GetIntFromJavascript(preview_,
623      "window.chrome.searchBox.height",
624      &height));
625  EXPECT_GT(height, 0);
626}
627
628// Verifies that if the server returns a 403 we don't show the preview and
629// query the host again.
630IN_PROC_BROWSER_TEST_F(InstantTest, HideOn403) {
631  ASSERT_TRUE(test_server()->Start());
632  EnableInstant();
633  GURL url(test_server()->GetURL("files/instant/403.html"));
634  ASSERT_NO_FATAL_FAILURE(FindLocationBar());
635  location_bar_->location_entry()->SetUserText(UTF8ToUTF16(url.spec()));
636  // The preview shouldn't be showing, but it should be loading.
637  ASSERT_TRUE(browser()->instant()->GetPreviewContents());
638  ASSERT_TRUE(browser()->instant()->is_active());
639  ASSERT_FALSE(browser()->instant()->is_displayable());
640
641  // When instant sees the 403, it should close the tab.
642  ui_test_utils::WaitForNotification(NotificationType::TAB_CLOSED);
643  ASSERT_FALSE(browser()->instant()->GetPreviewContents());
644  ASSERT_TRUE(browser()->instant()->is_active());
645  ASSERT_FALSE(browser()->instant()->is_displayable());
646
647  // Try loading another url on the server. Instant shouldn't create a new tab
648  // as the server returned 403.
649  GURL url2(test_server()->GetURL("files/instant/empty.html"));
650  location_bar_->location_entry()->SetUserText(UTF8ToUTF16(url2.spec()));
651  ASSERT_FALSE(browser()->instant()->GetPreviewContents());
652  ASSERT_TRUE(browser()->instant()->is_active());
653  ASSERT_FALSE(browser()->instant()->is_displayable());
654}
655
656// Verify that the onsubmit event is dispatched upon pressing enter.
657IN_PROC_BROWSER_TEST_F(InstantTest, OnSubmitEvent) {
658  ASSERT_TRUE(test_server()->Start());
659  EnableInstant();
660  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
661
662  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
663  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
664  ASSERT_NO_FATAL_FAILURE(SetupPreview());
665
666  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
667  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_RETURN));
668
669  // Check that the preview contents have been committed.
670  ASSERT_FALSE(browser()->instant()->GetPreviewContents());
671  ASSERT_FALSE(browser()->instant()->is_active());
672  TabContents* contents = browser()->GetSelectedTabContents();
673  ASSERT_TRUE(contents);
674
675  // Check that the value is reflected and onsubmit is called.
676  EXPECT_EQ("true 1 0 1 2 d false defghi true 3 3",
677            GetSearchStateAsString(preview_, true));
678
679  // Make sure the searchbox values were reset.
680  EXPECT_EQ("true 1 0 1 2 d false  false 0 0",
681            GetSearchStateAsString(preview_, false));
682}
683
684// Verify that the oncancel event is dispatched upon losing focus.
685IN_PROC_BROWSER_TEST_F(InstantTest, OnCancelEvent) {
686  ASSERT_TRUE(test_server()->Start());
687  EnableInstant();
688  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
689
690  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
691  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
692  ASSERT_NO_FATAL_FAILURE(SetupPreview());
693
694  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
695  ASSERT_NO_FATAL_FAILURE(ui_test_utils::ClickOnView(browser(),
696                                                     VIEW_ID_TAB_CONTAINER));
697
698  // Check that the preview contents have been committed.
699  ASSERT_FALSE(browser()->instant()->GetPreviewContents());
700  ASSERT_FALSE(browser()->instant()->is_active());
701  TabContents* contents = browser()->GetSelectedTabContents();
702  ASSERT_TRUE(contents);
703
704  // Check that the value is reflected and oncancel is called.
705  EXPECT_EQ("true 0 1 1 2 d false def false 3 3",
706            GetSearchStateAsString(preview_, true));
707
708  // Make sure the searchbox values were reset.
709  EXPECT_EQ("true 0 1 1 2 d false  false 0 0",
710            GetSearchStateAsString(preview_, false));
711}
712
713// Make sure about:crash is shown.
714IN_PROC_BROWSER_TEST_F(InstantTest, ShowAboutCrash) {
715  ASSERT_TRUE(test_server()->Start());
716  EnableInstant();
717
718  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
719
720  ASSERT_NO_FATAL_FAILURE(SetLocationBarText(chrome::kAboutCrashURL));
721
722  // If we get here it means the preview was shown. If we time out, it means the
723  // preview was never shown.
724}
725
726IN_PROC_BROWSER_TEST_F(InstantTest, InstantCompleteNever) {
727  ASSERT_TRUE(test_server()->Start());
728  EnableInstant();
729  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
730  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
731  ASSERT_NO_FATAL_FAILURE(SetupPreview());
732
733  SetSuggestionsJavascriptArgument(
734      preview_,
735      "{suggestions:[{value:'defghij'}],complete_behavior:'never'}");
736  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
737  EXPECT_STR_EQ("defghij", GetSuggestion());
738  AutocompleteEditModel* edit_model = location_bar_->location_entry()->model();
739  EXPECT_EQ(INSTANT_COMPLETE_NEVER, edit_model->instant_complete_behavior());
740  ASSERT_EQ(ASCIIToUTF16("def"), location_bar_->location_entry()->GetText());
741}
742
743IN_PROC_BROWSER_TEST_F(InstantTest, InstantCompleteDelayed) {
744  ASSERT_TRUE(test_server()->Start());
745  EnableInstant();
746  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
747  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
748  ASSERT_NO_FATAL_FAILURE(SetupPreview());
749
750  SetSuggestionsJavascriptArgument(
751      preview_,
752      "{suggestions:[{value:'defghij'}],complete_behavior:'delayed'}");
753  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
754  EXPECT_STR_EQ("defghij", GetSuggestion());
755  AutocompleteEditModel* edit_model = location_bar_->location_entry()->model();
756  EXPECT_EQ(INSTANT_COMPLETE_DELAYED, edit_model->instant_complete_behavior());
757  ASSERT_EQ(ASCIIToUTF16("def"), location_bar_->location_entry()->GetText());
758}
759
760// Make sure the renderer doesn't crash if javascript is blocked.
761IN_PROC_BROWSER_TEST_F(InstantTest, DontCrashOnBlockedJS) {
762  browser()->profile()->GetHostContentSettingsMap()->SetDefaultContentSetting(
763      CONTENT_SETTINGS_TYPE_JAVASCRIPT, CONTENT_SETTING_BLOCK);
764  ASSERT_TRUE(test_server()->Start());
765  EnableInstant();
766  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
767  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
768  // Wait for notification that the instant API has been determined.
769  ui_test_utils::WaitForNotification(
770      NotificationType::INSTANT_SUPPORT_DETERMINED);
771  // As long as we get the notification we're good (the renderer didn't crash).
772}
773
774IN_PROC_BROWSER_TEST_F(InstantTest, DownloadOnEnter) {
775  ASSERT_TRUE(test_server()->Start());
776  EnableInstant();
777  // Make sure the browser window is the front most window.
778  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
779  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
780  ASSERT_NO_FATAL_FAILURE(FindLocationBar());
781  GURL url(test_server()->GetURL("files/instant/empty.html"));
782  location_bar_->location_entry()->SetUserText(UTF8ToUTF16(url.spec()));
783  printf("0\n");
784  ASSERT_NO_FATAL_FAILURE(WaitForPreviewToNavigate(true));
785  url = test_server()->GetURL("files/instant/download.zip");
786  location_bar_->location_entry()->SetUserText(UTF8ToUTF16(url.spec()));
787  // Wait for the load to fail (because instant disables downloads).
788  printf("1\n");
789  ui_test_utils::WaitForNotification(
790      NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR);
791
792  printf("2\n");
793  ui_test_utils::WindowedNotificationObserver download_observer(
794      NotificationType::DOWNLOAD_INITIATED,
795      NotificationService::AllSources());
796  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_RETURN));
797  printf("3\n");
798  download_observer.Wait();
799  printf("4\n");
800
801  // And we should end up at about:blank.
802  TabContents* contents = browser()->GetSelectedTabContents();
803  ASSERT_TRUE(contents);
804  EXPECT_EQ("about:blank",
805            contents->controller().GetLastCommittedEntry()->url().spec());
806  if (contents->controller().pending_entry()) {
807    // If there is a pending entry, the url should correspond to the download.
808    EXPECT_EQ(url.spec(),
809              contents->controller().pending_entry()->url().spec());
810  }
811}
812
813// Makes sure window.chrome.searchbox doesn't persist when a new page is loaded.
814IN_PROC_BROWSER_TEST_F(InstantTest, DontPersistSearchbox) {
815  ASSERT_TRUE(test_server()->Start());
816  EnableInstant();
817  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
818
819  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
820  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
821  ASSERT_NO_FATAL_FAILURE(SetupPreview());
822
823  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
824  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_RETURN));
825
826  // Check that the preview contents have been committed.
827  ASSERT_FALSE(browser()->instant()->GetPreviewContents());
828  ASSERT_FALSE(browser()->instant()->is_active());
829
830  TabContents* contents = browser()->GetSelectedTabContents();
831  ASSERT_TRUE(contents);
832
833  // Navigate to a new URL. This should reset the searchbox values.
834  ui_test_utils::NavigateToURL(
835      browser(),
836      GURL(test_server()->GetURL("files/instant/empty.html")));
837  bool result;
838  ASSERT_TRUE(GetBoolFromJavascript(
839                  browser()->GetSelectedTabContents(),
840                  "window.chrome.searchBox.value.length == 0",
841                  &result));
842  EXPECT_TRUE(result);
843}
844