普通文本  |  844行  |  32.3 KB

// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/command_line.h"
#include "base/stringprintf.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/autocomplete/autocomplete_edit.h"
#include "chrome/browser/autocomplete/autocomplete_edit_view.h"
#include "chrome/browser/content_settings/host_content_settings_map.h"
#include "chrome/browser/instant/instant_controller.h"
#include "chrome/browser/instant/instant_loader.h"
#include "chrome/browser/instant/instant_loader_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_model.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/omnibox/location_bar.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/renderer_host/render_widget_host_view.h"
#include "content/browser/tab_contents/tab_contents.h"

#define EXPECT_STR_EQ(ascii, utf16) \
  EXPECT_EQ(ASCIIToWide(ascii), UTF16ToWide(utf16))

class InstantTest : public InProcessBrowserTest {
 public:
  InstantTest()
      : location_bar_(NULL),
        preview_(NULL) {
    set_show_window(true);
    EnableDOMAutomation();
  }

  void EnableInstant() {
    InstantController::Enable(browser()->profile());
  }

  void SetupInstantProvider(const std::string& page) {
    TemplateURLModel* model = browser()->profile()->GetTemplateURLModel();
    ASSERT_TRUE(model);

    if (!model->loaded()) {
      model->Load();
      ui_test_utils::WaitForNotification(
          NotificationType::TEMPLATE_URL_MODEL_LOADED);
    }

    ASSERT_TRUE(model->loaded());

    // TemplateURLModel takes ownership of this.
    TemplateURL* template_url = new TemplateURL();

    std::string url = StringPrintf(
        "http://%s:%d/files/instant/%s?q={searchTerms}",
        test_server()->host_port_pair().host().c_str(),
        test_server()->host_port_pair().port(),
        page.c_str());
    template_url->SetURL(url, 0, 0);
    template_url->SetInstantURL(url, 0, 0);
    template_url->set_keyword(ASCIIToUTF16("foo"));
    template_url->set_short_name(ASCIIToUTF16("foo"));

    model->Add(template_url);
    model->SetDefaultSearchProvider(template_url);
  }

  void FindLocationBar() {
    if (location_bar_)
      return;
    location_bar_ = browser()->window()->GetLocationBar();
    ASSERT_TRUE(location_bar_);
  }

  TabContentsWrapper* GetPendingPreviewContents() {
    return browser()->instant()->GetPendingPreviewContents();
  }

  // Type a character to get instant to trigger.
  void SetupLocationBar() {
    FindLocationBar();
    // "a" triggers the "about:" provider.  "b" begins the "bing.com" keyword.
    // "c" might someday trigger a "chrome:" provider.
    location_bar_->location_entry()->SetUserText(ASCIIToUTF16("d"));
  }

  // Waits for preview to be shown.
  void WaitForPreviewToNavigate(bool use_current) {
    InstantController* instant = browser()->instant();
    ASSERT_TRUE(instant);
    TabContentsWrapper* tab = use_current ?
        instant->GetPreviewContents() : GetPendingPreviewContents();
    ASSERT_TRUE(tab);
    preview_ = tab->tab_contents();
    ASSERT_TRUE(preview_);
    ui_test_utils::WaitForNavigation(&preview_->controller());
  }

  // Wait for instant to load and ensure it is in the state we expect.
  void SetupPreview() {
    // Wait for the preview to navigate.
    WaitForPreviewToNavigate(true);

    ASSERT_TRUE(browser()->instant()->IsShowingInstant());
    ASSERT_FALSE(browser()->instant()->is_displayable());
    ASSERT_TRUE(browser()->instant()->is_active());

    // When the page loads, the initial searchBox values are set and only a
    // resize will have been sent.
    ASSERT_EQ("true 0 0 0 1 d false d false 1 1",
              GetSearchStateAsString(preview_, false));
  }

  void SetLocationBarText(const std::string& text) {
    ASSERT_NO_FATAL_FAILURE(FindLocationBar());
    location_bar_->location_entry()->SetUserText(UTF8ToUTF16(text));
    ui_test_utils::WaitForNotification(
        NotificationType::INSTANT_CONTROLLER_SHOWN);
  }

  const string16& GetSuggestion() const {
    return browser()->instant()->loader_manager_->
        current_loader()->complete_suggested_text_;
  }

  void SendKey(ui::KeyboardCode key) {
    ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
        browser(), key, false, false, false, false));
  }

  void SetSuggestionsJavascriptArgument(TabContents* tab_contents,
                                        const std::string& argument) {
    std::string script = StringPrintf(
        "window.setSuggestionsArgument = %s;", argument.c_str());
    ASSERT_TRUE(ui_test_utils::ExecuteJavaScript(
        tab_contents->render_view_host(),
        std::wstring(),
        UTF8ToWide(script)));
  }

  bool GetStringFromJavascript(TabContents* tab_contents,
                               const std::string& function,
                               std::string* result) {
    std::string script = StringPrintf(
        "window.domAutomationController.send(%s)", function.c_str());
    return ui_test_utils::ExecuteJavaScriptAndExtractString(
        tab_contents->render_view_host(),
        std::wstring(), UTF8ToWide(script), result);
  }

  bool GetIntFromJavascript(TabContents* tab_contents,
                            const std::string& function,
                            int* result) {
    std::string script = StringPrintf(
        "window.domAutomationController.send(%s)", function.c_str());
    return ui_test_utils::ExecuteJavaScriptAndExtractInt(
        tab_contents->render_view_host(),
        std::wstring(), UTF8ToWide(script), result);
  }

  bool GetBoolFromJavascript(TabContents* tab_contents,
                             const std::string& function,
                             bool* result) {
    std::string script = StringPrintf(
        "window.domAutomationController.send(%s)", function.c_str());
    return ui_test_utils::ExecuteJavaScriptAndExtractBool(
        tab_contents->render_view_host(),
        std::wstring(), UTF8ToWide(script), result);
  }

  // Returns the state of the search box as a string. This consists of the
  // following:
  // window.chrome.sv
  // window.onsubmitcalls
  // window.oncancelcalls
  // window.onchangecalls
  // window.onresizecalls
  // window.beforeLoadSearchBox.value
  // window.beforeLoadSearchBox.verbatim
  // window.chrome.searchBox.value
  // window.chrome.searchBox.verbatim
  // window.chrome.searchBox.selectionStart
  // window.chrome.searchBox.selectionEnd
  // If determining any of the values fails, the value is 'fail'.
  //
  // If |use_last| is true, then the last searchBox values are used instead of
  // the current. Set |use_last| to true when testing OnSubmit/OnCancel.
  std::string GetSearchStateAsString(TabContents* tab_contents,
                                     bool use_last) {
    bool sv = false;
    int onsubmitcalls = 0;
    int oncancelcalls = 0;
    int onchangecalls = 0;
    int onresizecalls = 0;
    int selection_start = 0;
    int selection_end = 0;
    std::string before_load_value;
    bool before_load_verbatim = false;
    std::string value;
    bool verbatim = false;

    if (!GetBoolFromJavascript(tab_contents, "window.chrome.sv", &sv) ||
        !GetIntFromJavascript(tab_contents, "window.onsubmitcalls",
                              &onsubmitcalls) ||
        !GetIntFromJavascript(tab_contents, "window.oncancelcalls",
                              &oncancelcalls) ||
        !GetIntFromJavascript(tab_contents, "window.onchangecalls",
                              &onchangecalls) ||
        !GetIntFromJavascript(tab_contents, "window.onresizecalls",
                              &onresizecalls) ||
        !GetStringFromJavascript(
            tab_contents, "window.beforeLoadSearchBox.value",
            &before_load_value) ||
        !GetBoolFromJavascript(
            tab_contents, "window.beforeLoadSearchBox.verbatim",
            &before_load_verbatim)) {
      return "fail";
    }

    if (use_last &&
        (!GetStringFromJavascript(tab_contents, "window.lastSearchBox.value",
                                  &value) ||
         !GetBoolFromJavascript(tab_contents, "window.lastSearchBox.verbatim",
                                &verbatim) ||
         !GetIntFromJavascript(tab_contents,
                               "window.lastSearchBox.selectionStart",
                               &selection_start) ||
         !GetIntFromJavascript(tab_contents,
                               "window.lastSearchBox.selectionEnd",
                               &selection_end))) {
      return "fail";
    }

    if (!use_last &&
        (!GetStringFromJavascript(tab_contents, "window.searchBox.value",
                                  &value) ||
         !GetBoolFromJavascript(tab_contents, "window.searchBox.verbatim",
                                &verbatim) ||
         !GetIntFromJavascript(tab_contents,
                               "window.searchBox.selectionStart",
                               &selection_start) ||
         !GetIntFromJavascript(tab_contents,
                               "window.searchBox.selectionEnd",
                               &selection_end))) {
      return "fail";
    }

    return StringPrintf("%s %d %d %d %d %s %s %s %s %d %d",
                        sv ? "true" : "false",
                        onsubmitcalls,
                        oncancelcalls,
                        onchangecalls,
                        onresizecalls,
                        before_load_value.c_str(),
                        before_load_verbatim ? "true" : "false",
                        value.c_str(),
                        verbatim ? "true" : "false",
                        selection_start,
                        selection_end);
  }

  void CheckStringValueFromJavascript(
      const std::string& expected,
      const std::string& function,
      TabContents* tab_contents) {
    std::string result;
    ASSERT_TRUE(GetStringFromJavascript(tab_contents, function, &result));
    ASSERT_EQ(expected, result);
  }

  void CheckBoolValueFromJavascript(
      bool expected,
      const std::string& function,
      TabContents* tab_contents) {
    bool result;
    ASSERT_TRUE(GetBoolFromJavascript(tab_contents, function, &result));
    ASSERT_EQ(expected, result);
  }

  void CheckIntValueFromJavascript(
      int expected,
      const std::string& function,
      TabContents* tab_contents) {
    int result;
    ASSERT_TRUE(GetIntFromJavascript(tab_contents, function, &result));
    ASSERT_EQ(expected, result);
  }

  // Sends a message to the renderer and waits for the response to come back to
  // the browser.
  void WaitForMessageToBeProcessedByRenderer(TabContentsWrapper* tab) {
    ASSERT_NO_FATAL_FAILURE(
        CheckBoolValueFromJavascript(true, "true", tab->tab_contents()));
  }

 protected:
  LocationBar* location_bar_;
  TabContents* preview_;
};

// TODO(tonyg): Add the following tests:
// - Test that the search box API is not populated for pages other than the
//   default search provider.
// - Test resize events.

// Verify that the onchange event is dispatched upon typing in the box.
IN_PROC_BROWSER_TEST_F(InstantTest, OnChangeEvent) {
  ASSERT_TRUE(test_server()->Start());
  EnableInstant();
  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
  ASSERT_NO_FATAL_FAILURE(SetupPreview());

  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));

  ASSERT_EQ(ASCIIToUTF16("defghi"), location_bar_->location_entry()->GetText());

  // Make sure the url that will get committed when we press enter matches that
  // of the default search provider.
  const TemplateURL* default_turl =
      browser()->profile()->GetTemplateURLModel()->GetDefaultSearchProvider();
  ASSERT_TRUE(default_turl);
  ASSERT_TRUE(default_turl->url());
  EXPECT_EQ(default_turl->url()->ReplaceSearchTerms(
                *default_turl, ASCIIToUTF16("defghi"), 0, string16()),
            browser()->instant()->GetCurrentURL().spec());

  // Check that the value is reflected and onchange is called.
  EXPECT_EQ("true 0 0 1 2 d false def false 3 3",
            GetSearchStateAsString(preview_, true));
}

IN_PROC_BROWSER_TEST_F(InstantTest, SetSuggestionsArrayOfStrings) {
  ASSERT_TRUE(test_server()->Start());
  EnableInstant();
  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
  ASSERT_NO_FATAL_FAILURE(SetupPreview());

  SetSuggestionsJavascriptArgument(preview_, "['defgh', 'unused']");
  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
  EXPECT_STR_EQ("defgh", GetSuggestion());
}

IN_PROC_BROWSER_TEST_F(InstantTest, SetSuggestionsEmptyArray) {
  ASSERT_TRUE(test_server()->Start());
  EnableInstant();
  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
  ASSERT_NO_FATAL_FAILURE(SetupPreview());

  SetSuggestionsJavascriptArgument(preview_, "[]");
  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
  EXPECT_STR_EQ("", GetSuggestion());
}

IN_PROC_BROWSER_TEST_F(InstantTest, SetSuggestionsValidJson) {
  ASSERT_TRUE(test_server()->Start());
  EnableInstant();
  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
  ASSERT_NO_FATAL_FAILURE(SetupPreview());

  SetSuggestionsJavascriptArgument(
      preview_,
      "{suggestions:[{value:'defghij'},{value:'unused'}]}");
  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
  EXPECT_STR_EQ("defghij", GetSuggestion());
}

IN_PROC_BROWSER_TEST_F(InstantTest, SetSuggestionsInvalidSuggestions) {
  ASSERT_TRUE(test_server()->Start());
  EnableInstant();
  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
  ASSERT_NO_FATAL_FAILURE(SetupPreview());

  SetSuggestionsJavascriptArgument(
      preview_,
      "{suggestions:{value:'defghi'}}");
  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
  EXPECT_STR_EQ("", GetSuggestion());
}

IN_PROC_BROWSER_TEST_F(InstantTest, SetSuggestionsEmptyJson) {
  ASSERT_TRUE(test_server()->Start());
  EnableInstant();
  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
  ASSERT_NO_FATAL_FAILURE(SetupPreview());

  SetSuggestionsJavascriptArgument(preview_, "{}");
  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
  EXPECT_STR_EQ("", GetSuggestion());
}

IN_PROC_BROWSER_TEST_F(InstantTest, SetSuggestionsEmptySuggestions) {
  ASSERT_TRUE(test_server()->Start());
  EnableInstant();
  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
  ASSERT_NO_FATAL_FAILURE(SetupPreview());

  SetSuggestionsJavascriptArgument(preview_, "{suggestions:[]}");
  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
  EXPECT_STR_EQ("", GetSuggestion());
}

IN_PROC_BROWSER_TEST_F(InstantTest, SetSuggestionsEmptySuggestion) {
  ASSERT_TRUE(test_server()->Start());
  EnableInstant();
  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
  ASSERT_NO_FATAL_FAILURE(SetupPreview());

  SetSuggestionsJavascriptArgument(preview_, "{suggestions:[{}]}");
  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
  EXPECT_STR_EQ("", GetSuggestion());
}

// Verify instant preview is shown correctly for a non-search query.
IN_PROC_BROWSER_TEST_F(InstantTest, ShowPreviewNonSearch) {
  ASSERT_TRUE(test_server()->Start());
  EnableInstant();
  GURL url(test_server()->GetURL("files/instant/empty.html"));
  ASSERT_NO_FATAL_FAILURE(SetLocationBarText(url.spec()));
  // The preview should be active and showing.
  ASSERT_TRUE(browser()->instant()->is_active());
  ASSERT_TRUE(browser()->instant()->is_displayable());
  ASSERT_TRUE(browser()->instant()->IsCurrent());
  ASSERT_TRUE(browser()->instant()->GetPreviewContents());
  RenderWidgetHostView* rwhv =
      browser()->instant()->GetPreviewContents()->tab_contents()->
      GetRenderWidgetHostView();
  ASSERT_TRUE(rwhv);
  ASSERT_TRUE(rwhv->IsShowing());
}

// Transition from non-search to search and make sure everything is shown
// correctly.
IN_PROC_BROWSER_TEST_F(InstantTest, NonSearchToSearch) {
  ASSERT_TRUE(test_server()->Start());
  EnableInstant();
  GURL url(test_server()->GetURL("files/instant/empty.html"));
  ASSERT_NO_FATAL_FAILURE(SetLocationBarText(url.spec()));
  // The preview should be active and showing.
  ASSERT_TRUE(browser()->instant()->is_active());
  ASSERT_TRUE(browser()->instant()->is_displayable());
  TabContentsWrapper* initial_tab = browser()->instant()->GetPreviewContents();
  ASSERT_TRUE(initial_tab);
  RenderWidgetHostView* rwhv =
      initial_tab->tab_contents()->GetRenderWidgetHostView();
  ASSERT_TRUE(rwhv);
  ASSERT_TRUE(rwhv->IsShowing());

  // Now type in some search text.
  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
  location_bar_->location_entry()->SetUserText(ASCIIToUTF16("def"));

  // Wait for the preview to navigate.
  ASSERT_NO_FATAL_FAILURE(WaitForPreviewToNavigate(false));

  // The controller is still determining if the provider really supports
  // instant. As a result the tabcontents should not have changed.
  TabContentsWrapper* current_tab = browser()->instant()->GetPreviewContents();
  ASSERT_EQ(current_tab, initial_tab);
  // The preview should still be showing.
  rwhv = current_tab->tab_contents()->GetRenderWidgetHostView();
  ASSERT_TRUE(rwhv);
  ASSERT_TRUE(rwhv->IsShowing());

  // Use MightSupportInstant as the controller is still determining if the
  // page supports instant and hasn't actually commited yet.
  EXPECT_TRUE(browser()->instant()->MightSupportInstant());

  // Instant should still be active.
  EXPECT_TRUE(browser()->instant()->is_active());
  EXPECT_TRUE(browser()->instant()->is_displayable());

  // Because we're waiting on the page, instant isn't current.
  ASSERT_FALSE(browser()->instant()->IsCurrent());

  // Bounce a message to the renderer so that we know the instant has gotten a
  // response back from the renderer as to whether the page supports instant.
  ASSERT_NO_FATAL_FAILURE(
      WaitForMessageToBeProcessedByRenderer(GetPendingPreviewContents()));

  // Reset the user text so that the page is told the text changed. We should be
  // able to nuke this once 66104 is fixed.
  location_bar_->location_entry()->SetUserText(ASCIIToUTF16("defg"));

  // Wait for the renderer to process it.
  ASSERT_NO_FATAL_FAILURE(
      WaitForMessageToBeProcessedByRenderer(GetPendingPreviewContents()));

  // We should have gotten a response back from the renderer that resulted in
  // committing.
  ASSERT_FALSE(GetPendingPreviewContents());
  ASSERT_TRUE(browser()->instant()->is_active());
  ASSERT_TRUE(browser()->instant()->is_displayable());
  TabContentsWrapper* new_tab = browser()->instant()->GetPreviewContents();
  ASSERT_TRUE(new_tab);
  ASSERT_NE(new_tab, initial_tab);
  RenderWidgetHostView* new_rwhv =
      new_tab->tab_contents()->GetRenderWidgetHostView();
  ASSERT_TRUE(new_rwhv);
  ASSERT_NE(new_rwhv, rwhv);
  ASSERT_TRUE(new_rwhv->IsShowing());
}

// Makes sure that if the server doesn't support the instant API we don't show
// anything.
#if defined(OS_MACOSX) || defined(OS_LINUX)
// Showing as flaky on Mac and Linux.
// http://crbug.com/70860
#define MAYBE_SearchServerDoesntSupportInstant \
    DISABLED_SearchServerDoesntSupportInstant
#else
#define MAYBE_SearchServerDoesntSupportInstant \
    SearchServerDoesntSupportInstant
#endif
IN_PROC_BROWSER_TEST_F(InstantTest, MAYBE_SearchServerDoesntSupportInstant) {
  ASSERT_TRUE(test_server()->Start());
  EnableInstant();
  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("empty.html"));
  ASSERT_NO_FATAL_FAILURE(FindLocationBar());
  location_bar_->location_entry()->SetUserText(ASCIIToUTF16("d"));
  ASSERT_TRUE(browser()->instant());
  // Because we typed in a search string we should think we're showing instant
  // results.
  EXPECT_TRUE(browser()->instant()->IsShowingInstant());
  // But because we're waiting to determine if the page really supports instant
  // we shouldn't be showing the preview.
  EXPECT_FALSE(browser()->instant()->is_displayable());
  // But instant should still be active.
  EXPECT_TRUE(browser()->instant()->is_active());

  // When the response comes back that the page doesn't support instant the tab
  // should be closed.
  ui_test_utils::WaitForNotification(NotificationType::TAB_CLOSED);
  EXPECT_FALSE(browser()->instant()->IsShowingInstant());
  EXPECT_FALSE(browser()->instant()->is_displayable());
  EXPECT_TRUE(browser()->instant()->is_active());
  EXPECT_FALSE(browser()->instant()->IsCurrent());
}

// Verifies transitioning from loading a non-search string to a search string
// with the provider not supporting instant works (meaning we don't display
// anything).
#if defined(OS_MACOSX) || defined(OS_LINUX)
// Showing as flaky on Mac and Linux/ChromeOS
// http://crbug.com/70810
#define MAYBE_NonSearchToSearchDoesntSupportInstant \
    DISABLED_NonSearchToSearchDoesntSupportInstant
#else
#define MAYBE_NonSearchToSearchDoesntSupportInstant \
    NonSearchToSearchDoesntSupportInstant
#endif
IN_PROC_BROWSER_TEST_F(InstantTest,
                       MAYBE_NonSearchToSearchDoesntSupportInstant) {
  ASSERT_TRUE(test_server()->Start());
  EnableInstant();
  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("empty.html"));
  GURL url(test_server()->GetURL("files/instant/empty.html"));
  ASSERT_NO_FATAL_FAILURE(SetLocationBarText(url.spec()));
  // The preview should be active and showing.
  ASSERT_TRUE(browser()->instant()->is_displayable());
  ASSERT_TRUE(browser()->instant()->is_active());
  TabContentsWrapper* initial_tab = browser()->instant()->GetPreviewContents();
  ASSERT_TRUE(initial_tab);
  RenderWidgetHostView* rwhv =
      initial_tab->tab_contents()->GetRenderWidgetHostView();
  ASSERT_TRUE(rwhv);
  ASSERT_TRUE(rwhv->IsShowing());

  // Now type in some search text.
  location_bar_->location_entry()->SetUserText(ASCIIToUTF16("d"));

  // Instant should still be live.
  ASSERT_TRUE(browser()->instant()->is_displayable());
  ASSERT_TRUE(browser()->instant()->is_active());
  // Because we typed in a search string we should think we're showing instant
  // results.
  EXPECT_TRUE(browser()->instant()->MightSupportInstant());
  // Instant should not be current (it's still loading).
  EXPECT_FALSE(browser()->instant()->IsCurrent());

  // When the response comes back that the page doesn't support instant the tab
  // should be closed.
  ui_test_utils::WaitForNotification(NotificationType::TAB_CLOSED);
  EXPECT_FALSE(browser()->instant()->IsShowingInstant());
  EXPECT_FALSE(browser()->instant()->is_displayable());
  // But because the omnibox is still open, instant should be active.
  ASSERT_TRUE(browser()->instant()->is_active());
}

// Verifies the page was told a non-zero height.
IN_PROC_BROWSER_TEST_F(InstantTest, ValidHeight) {
  ASSERT_TRUE(test_server()->Start());
  EnableInstant();
  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
  ASSERT_NO_FATAL_FAILURE(SetupPreview());

  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));

  int height;

  // searchBox height is not yet set during initial load.
  ASSERT_TRUE(GetIntFromJavascript(preview_,
      "window.beforeLoadSearchBox.height",
      &height));
  EXPECT_EQ(0, height);

  // searchBox height is available by the time the page loads.
  ASSERT_TRUE(GetIntFromJavascript(preview_,
      "window.chrome.searchBox.height",
      &height));
  EXPECT_GT(height, 0);
}

// Verifies that if the server returns a 403 we don't show the preview and
// query the host again.
IN_PROC_BROWSER_TEST_F(InstantTest, HideOn403) {
  ASSERT_TRUE(test_server()->Start());
  EnableInstant();
  GURL url(test_server()->GetURL("files/instant/403.html"));
  ASSERT_NO_FATAL_FAILURE(FindLocationBar());
  location_bar_->location_entry()->SetUserText(UTF8ToUTF16(url.spec()));
  // The preview shouldn't be showing, but it should be loading.
  ASSERT_TRUE(browser()->instant()->GetPreviewContents());
  ASSERT_TRUE(browser()->instant()->is_active());
  ASSERT_FALSE(browser()->instant()->is_displayable());

  // When instant sees the 403, it should close the tab.
  ui_test_utils::WaitForNotification(NotificationType::TAB_CLOSED);
  ASSERT_FALSE(browser()->instant()->GetPreviewContents());
  ASSERT_TRUE(browser()->instant()->is_active());
  ASSERT_FALSE(browser()->instant()->is_displayable());

  // Try loading another url on the server. Instant shouldn't create a new tab
  // as the server returned 403.
  GURL url2(test_server()->GetURL("files/instant/empty.html"));
  location_bar_->location_entry()->SetUserText(UTF8ToUTF16(url2.spec()));
  ASSERT_FALSE(browser()->instant()->GetPreviewContents());
  ASSERT_TRUE(browser()->instant()->is_active());
  ASSERT_FALSE(browser()->instant()->is_displayable());
}

// Verify that the onsubmit event is dispatched upon pressing enter.
IN_PROC_BROWSER_TEST_F(InstantTest, OnSubmitEvent) {
  ASSERT_TRUE(test_server()->Start());
  EnableInstant();
  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));

  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
  ASSERT_NO_FATAL_FAILURE(SetupPreview());

  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_RETURN));

  // Check that the preview contents have been committed.
  ASSERT_FALSE(browser()->instant()->GetPreviewContents());
  ASSERT_FALSE(browser()->instant()->is_active());
  TabContents* contents = browser()->GetSelectedTabContents();
  ASSERT_TRUE(contents);

  // Check that the value is reflected and onsubmit is called.
  EXPECT_EQ("true 1 0 1 2 d false defghi true 3 3",
            GetSearchStateAsString(preview_, true));

  // Make sure the searchbox values were reset.
  EXPECT_EQ("true 1 0 1 2 d false  false 0 0",
            GetSearchStateAsString(preview_, false));
}

// Verify that the oncancel event is dispatched upon losing focus.
IN_PROC_BROWSER_TEST_F(InstantTest, OnCancelEvent) {
  ASSERT_TRUE(test_server()->Start());
  EnableInstant();
  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));

  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
  ASSERT_NO_FATAL_FAILURE(SetupPreview());

  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
  ASSERT_NO_FATAL_FAILURE(ui_test_utils::ClickOnView(browser(),
                                                     VIEW_ID_TAB_CONTAINER));

  // Check that the preview contents have been committed.
  ASSERT_FALSE(browser()->instant()->GetPreviewContents());
  ASSERT_FALSE(browser()->instant()->is_active());
  TabContents* contents = browser()->GetSelectedTabContents();
  ASSERT_TRUE(contents);

  // Check that the value is reflected and oncancel is called.
  EXPECT_EQ("true 0 1 1 2 d false def false 3 3",
            GetSearchStateAsString(preview_, true));

  // Make sure the searchbox values were reset.
  EXPECT_EQ("true 0 1 1 2 d false  false 0 0",
            GetSearchStateAsString(preview_, false));
}

// Make sure about:crash is shown.
IN_PROC_BROWSER_TEST_F(InstantTest, ShowAboutCrash) {
  ASSERT_TRUE(test_server()->Start());
  EnableInstant();

  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));

  ASSERT_NO_FATAL_FAILURE(SetLocationBarText(chrome::kAboutCrashURL));

  // If we get here it means the preview was shown. If we time out, it means the
  // preview was never shown.
}

IN_PROC_BROWSER_TEST_F(InstantTest, InstantCompleteNever) {
  ASSERT_TRUE(test_server()->Start());
  EnableInstant();
  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
  ASSERT_NO_FATAL_FAILURE(SetupPreview());

  SetSuggestionsJavascriptArgument(
      preview_,
      "{suggestions:[{value:'defghij'}],complete_behavior:'never'}");
  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
  EXPECT_STR_EQ("defghij", GetSuggestion());
  AutocompleteEditModel* edit_model = location_bar_->location_entry()->model();
  EXPECT_EQ(INSTANT_COMPLETE_NEVER, edit_model->instant_complete_behavior());
  ASSERT_EQ(ASCIIToUTF16("def"), location_bar_->location_entry()->GetText());
}

IN_PROC_BROWSER_TEST_F(InstantTest, InstantCompleteDelayed) {
  ASSERT_TRUE(test_server()->Start());
  EnableInstant();
  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
  ASSERT_NO_FATAL_FAILURE(SetupPreview());

  SetSuggestionsJavascriptArgument(
      preview_,
      "{suggestions:[{value:'defghij'}],complete_behavior:'delayed'}");
  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
  EXPECT_STR_EQ("defghij", GetSuggestion());
  AutocompleteEditModel* edit_model = location_bar_->location_entry()->model();
  EXPECT_EQ(INSTANT_COMPLETE_DELAYED, edit_model->instant_complete_behavior());
  ASSERT_EQ(ASCIIToUTF16("def"), location_bar_->location_entry()->GetText());
}

// Make sure the renderer doesn't crash if javascript is blocked.
IN_PROC_BROWSER_TEST_F(InstantTest, DontCrashOnBlockedJS) {
  browser()->profile()->GetHostContentSettingsMap()->SetDefaultContentSetting(
      CONTENT_SETTINGS_TYPE_JAVASCRIPT, CONTENT_SETTING_BLOCK);
  ASSERT_TRUE(test_server()->Start());
  EnableInstant();
  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
  // Wait for notification that the instant API has been determined.
  ui_test_utils::WaitForNotification(
      NotificationType::INSTANT_SUPPORT_DETERMINED);
  // As long as we get the notification we're good (the renderer didn't crash).
}

IN_PROC_BROWSER_TEST_F(InstantTest, DownloadOnEnter) {
  ASSERT_TRUE(test_server()->Start());
  EnableInstant();
  // Make sure the browser window is the front most window.
  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));
  ASSERT_NO_FATAL_FAILURE(FindLocationBar());
  GURL url(test_server()->GetURL("files/instant/empty.html"));
  location_bar_->location_entry()->SetUserText(UTF8ToUTF16(url.spec()));
  printf("0\n");
  ASSERT_NO_FATAL_FAILURE(WaitForPreviewToNavigate(true));
  url = test_server()->GetURL("files/instant/download.zip");
  location_bar_->location_entry()->SetUserText(UTF8ToUTF16(url.spec()));
  // Wait for the load to fail (because instant disables downloads).
  printf("1\n");
  ui_test_utils::WaitForNotification(
      NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR);

  printf("2\n");
  ui_test_utils::WindowedNotificationObserver download_observer(
      NotificationType::DOWNLOAD_INITIATED,
      NotificationService::AllSources());
  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_RETURN));
  printf("3\n");
  download_observer.Wait();
  printf("4\n");

  // And we should end up at about:blank.
  TabContents* contents = browser()->GetSelectedTabContents();
  ASSERT_TRUE(contents);
  EXPECT_EQ("about:blank",
            contents->controller().GetLastCommittedEntry()->url().spec());
  if (contents->controller().pending_entry()) {
    // If there is a pending entry, the url should correspond to the download.
    EXPECT_EQ(url.spec(),
              contents->controller().pending_entry()->url().spec());
  }
}

// Makes sure window.chrome.searchbox doesn't persist when a new page is loaded.
IN_PROC_BROWSER_TEST_F(InstantTest, DontPersistSearchbox) {
  ASSERT_TRUE(test_server()->Start());
  EnableInstant();
  ASSERT_NO_FATAL_FAILURE(SetupInstantProvider("search.html"));

  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
  ASSERT_NO_FATAL_FAILURE(SetupLocationBar());
  ASSERT_NO_FATAL_FAILURE(SetupPreview());

  ASSERT_NO_FATAL_FAILURE(SetLocationBarText("def"));
  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_RETURN));

  // Check that the preview contents have been committed.
  ASSERT_FALSE(browser()->instant()->GetPreviewContents());
  ASSERT_FALSE(browser()->instant()->is_active());

  TabContents* contents = browser()->GetSelectedTabContents();
  ASSERT_TRUE(contents);

  // Navigate to a new URL. This should reset the searchbox values.
  ui_test_utils::NavigateToURL(
      browser(),
      GURL(test_server()->GetURL("files/instant/empty.html")));
  bool result;
  ASSERT_TRUE(GetBoolFromJavascript(
                  browser()->GetSelectedTabContents(),
                  "window.chrome.searchBox.value.length == 0",
                  &result));
  EXPECT_TRUE(result);
}