普通文本  |  210行  |  7.87 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 <string>

#include "base/file_path.h"
#include "base/path_service.h"
#include "base/stringprintf.h"
#include "chrome/browser/automation/automation_tab_helper.h"
#include "chrome/browser/automation/mock_tab_event_observer.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/common/chrome_paths.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/tab_contents/tab_contents.h"
#include "content/common/notification_details.h"
#include "content/common/notification_observer.h"
#include "content/common/notification_registrar.h"
#include "content/common/notification_service.h"
#include "content/common/notification_source.h"
#include "content/common/notification_type.h"
#include "net/base/net_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using testing::_;

class MockNotificationObserver : public NotificationObserver {
 public:
  MockNotificationObserver() { }
  virtual ~MockNotificationObserver() { }

  MOCK_METHOD3(Observe, void(NotificationType type,
                             const NotificationSource& source,
                             const NotificationDetails& details));

  void Register(NotificationType type, const NotificationSource& source) {
    registrar_.Add(this, type, source);
  }

 private:
  NotificationRegistrar registrar_;

  DISALLOW_COPY_AND_ASSIGN(MockNotificationObserver);
};

class AutomationTabHelperBrowserTest : public InProcessBrowserTest {
 public:
  AutomationTabHelperBrowserTest() {
    EnableDOMAutomation();
  }
  virtual ~AutomationTabHelperBrowserTest() { }

  void SetUpInProcessBrowserTestFixture() {
    EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_));
    test_data_dir_ = test_data_dir_.AppendASCII("automation");
  }

  // Add default expectations for a client redirection initiated by script,
  // and quit the message loop when the redirect has completed. This expects
  // that the tab receives news of the redirect before the script returns.
  void ExpectClientRedirectAndBreak(
      MockTabEventObserver* mock_tab_observer,
      MockNotificationObserver* mock_notification_observer) {
    mock_notification_observer->Register(
        NotificationType::DOM_OPERATION_RESPONSE,
        NotificationService::AllSources());

    testing::InSequence expect_in_sequence;
    EXPECT_CALL(*mock_tab_observer, OnFirstPendingLoad(_));
    EXPECT_CALL(*mock_notification_observer, Observe(
        testing::Eq(NotificationType::DOM_OPERATION_RESPONSE), _, _));
    EXPECT_CALL(*mock_tab_observer, OnNoMorePendingLoads(_))
        .WillOnce(testing::InvokeWithoutArgs(
            MessageLoopForUI::current(), &MessageLoop::Quit));
  }

  // Executes javascript to execute a given test case found in the current
  // page's script. If |wait_for_response| is true, this method will not
  // return until the javascript has been executed.
  // Use with [ASSERT|EXPECT]_NO_FATAL_FAILURE.
  void RunTestCaseInJavaScript(int test_case_number, bool wait_for_response) {
    std::string script = base::StringPrintf("runTestCase(%d);",
                                            test_case_number);
    RenderViewHost* host =
        browser()->GetSelectedTabContents()->render_view_host();
    if (wait_for_response) {
      ASSERT_TRUE(ui_test_utils::ExecuteJavaScript(
          host, L"", ASCIIToWide(script)));
    } else {
      script += "window.domAutomationController.setAutomationId(0);"
                "window.domAutomationController.send(0);";
      host->ExecuteJavascriptInWebFrame(ASCIIToUTF16(""), ASCIIToUTF16(script));
    }
  }

  // Returns the |AutomationTabHelper| for the first browser's first tab.
  AutomationTabHelper* tab_helper() {
    return browser()->GetTabContentsWrapperAt(0)->automation_tab_helper();
  }

 protected:
  FilePath test_data_dir_;
};

IN_PROC_BROWSER_TEST_F(AutomationTabHelperBrowserTest, FormSubmission) {
  ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL(
      test_data_dir_.AppendASCII("client_redirects.html")));

  MockNotificationObserver mock_notification_observer;
  MockTabEventObserver mock_observer(tab_helper());

  ExpectClientRedirectAndBreak(&mock_observer, &mock_notification_observer);

  ASSERT_NO_FATAL_FAILURE(RunTestCaseInJavaScript(1, false));
  ui_test_utils::RunMessageLoop();
}

IN_PROC_BROWSER_TEST_F(AutomationTabHelperBrowserTest,
                       CancelFormSubmission) {
  ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL(
      test_data_dir_.AppendASCII("client_redirects.html")));

  MockNotificationObserver mock_notification_observer;
  MockTabEventObserver mock_observer(tab_helper());

  testing::InSequence expect_in_sequence;
  EXPECT_CALL(mock_observer, OnFirstPendingLoad(_)).Times(0);

  ASSERT_NO_FATAL_FAILURE(RunTestCaseInJavaScript(2, true));
}

IN_PROC_BROWSER_TEST_F(AutomationTabHelperBrowserTest,
                       JsRedirectToSite) {
  ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL(
      test_data_dir_.AppendASCII("client_redirects.html")));

  MockNotificationObserver mock_notification_observer;
  MockTabEventObserver mock_observer(tab_helper());

  ExpectClientRedirectAndBreak(&mock_observer, &mock_notification_observer);

  ASSERT_NO_FATAL_FAILURE(RunTestCaseInJavaScript(3, false));
  ui_test_utils::RunMessageLoop();
}

IN_PROC_BROWSER_TEST_F(AutomationTabHelperBrowserTest,
                       JsRedirectToUnknownSite) {
  ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL(
      test_data_dir_.AppendASCII("client_redirects.html")));

  MockNotificationObserver mock_notification_observer;
  MockTabEventObserver mock_observer(tab_helper());

  ExpectClientRedirectAndBreak(&mock_observer, &mock_notification_observer);

  ASSERT_NO_FATAL_FAILURE(RunTestCaseInJavaScript(4, false));
  ui_test_utils::RunMessageLoop();
}

IN_PROC_BROWSER_TEST_F(AutomationTabHelperBrowserTest,
                       MetaTagRedirect) {
  MockTabEventObserver mock_observer(tab_helper());

  testing::InSequence expect_in_sequence;
  EXPECT_CALL(mock_observer, OnFirstPendingLoad(_));
  EXPECT_CALL(mock_observer, OnNoMorePendingLoads(_));

  ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
      browser(),
      net::FilePathToFileURL(test_data_dir_.AppendASCII("meta_redirect.html")),
      2);
}

// Tests that the load stop event occurs after the window onload handler.
IN_PROC_BROWSER_TEST_F(AutomationTabHelperBrowserTest,
                       LoadStopComesAfterOnLoad) {
  MockNotificationObserver mock_notification_observer;
  mock_notification_observer.Register(NotificationType::DOM_OPERATION_RESPONSE,
                                      NotificationService::AllSources());
  MockTabEventObserver mock_tab_observer(tab_helper());

  EXPECT_CALL(mock_tab_observer, OnFirstPendingLoad(_));
  {
    testing::InSequence expect_in_sequence;
    EXPECT_CALL(mock_notification_observer, Observe(
        testing::Eq(NotificationType::DOM_OPERATION_RESPONSE), _, _));
    EXPECT_CALL(mock_tab_observer, OnNoMorePendingLoads(_));
  }

  ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL(
      test_data_dir_.AppendASCII("sends_message_on_load.html")));
}

// Tests that a crashed tab reports that it has stopped loading.
IN_PROC_BROWSER_TEST_F(AutomationTabHelperBrowserTest,
                       CrashedTabStopsLoading) {
  MockTabEventObserver mock_tab_observer(tab_helper());

  testing::InSequence expect_in_sequence;
  EXPECT_CALL(mock_tab_observer, OnFirstPendingLoad(_));
  EXPECT_CALL(mock_tab_observer, OnNoMorePendingLoads(_));

  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kAboutCrashURL));
}