普通文本  |  1114行  |  42.32 KB

// Copyright (c) 2012 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 <mshtmcid.h>
#include <string>

#include "base/file_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/test_file_util.h"
#include "base/win/scoped_bstr.h"
#include "base/win/scoped_variant.h"
#include "base/win/windows_version.h"
#include "chrome/common/url_constants.h"
#include "chrome_frame/test/chrome_frame_test_utils.h"
#include "chrome_frame/test/chrome_frame_ui_test_utils.h"
#include "chrome_frame/test/mock_ie_event_sink_actions.h"
#include "chrome_frame/test/mock_ie_event_sink_test.h"
#include "chrome_frame/test/simulate_input.h"

#include "testing/gmock_mutant.h"

using testing::_;
using testing::InSequence;
using testing::StrCaseEq;
using testing::StrEq;

namespace chrome_frame_test {

// This parameterized test fixture uses the MockIEEventSink and is used by
// UI-related tests.
class FullTabUITest : public MockIEEventSinkTest,
                      public testing::TestWithParam<CFInvocation> {
 public:
  FullTabUITest() {}

  virtual void SetUp() {
    ResetKeyState();

    // These are UI-related tests, so we do not care about the exact requests
    // and navigations that occur.
    server_mock_.ExpectAndServeAnyRequests(GetParam());
    ie_mock_.ExpectAnyNavigations();
  }

  virtual void TearDown() {
    ResetKeyState();
  }

  void ResetKeyState() {
    // Call this to reset the state of any current keyboard modifiers, as it has
    // been observed that these tests can leave the desktop in an invalid state
    // (e.g. thinking that the Ctrl key is held down). Send F23 as that is
    // particularly unlikely to be used by any real application.
    simulate_input::SendMnemonic(
        VK_F23,
        simulate_input::CONTROL | simulate_input::SHIFT | simulate_input::ALT,
        false,
        false,
        simulate_input::KEY_UP);
  }
};

// Instantiate each test case for the IE case and for CF meta tag case.
// It does not seem too useful to also run the CF http header case since these
// are UI, not navigation tests.
INSTANTIATE_TEST_CASE_P(IE, FullTabUITest,
                        testing::Values(CFInvocation::None()));
INSTANTIATE_TEST_CASE_P(CF, FullTabUITest,
                        testing::Values(CFInvocation::MetaTag()));

// Tests keyboard input.
TEST_P(FullTabUITest, KeyboardInput) {
  if (!GetParam().invokes_cf()) {
    LOG(ERROR) << "Test not implemented for this configuration.";
    return;
  }
  std::wstring key_event_url = GetTestUrl(L"keyevent.html");

  static const char input[] = "chrome";
  EXPECT_CALL(ie_mock_, OnLoad(GetParam().invokes_cf(), StrEq(key_event_url)))
      .WillOnce(PostKeyMessagesToRenderer(&ie_mock_, input));

  EXPECT_CALL(ie_mock_, OnMessage(StrCaseEq(UTF8ToWide(input)), _, _))
      .WillOnce(CloseBrowserMock(&ie_mock_));

  LaunchIEAndNavigate(key_event_url);
}

// Tests keyboard shortcuts for back and forward.
// http://code.google.com/p/chromium/issues/detail?id=114058
TEST_P(FullTabUITest, DISABLED_KeyboardBackForward) {
  if (IsWorkstationLocked()) {
    LOG(ERROR) << "This test cannot be run in a locked workstation.";
    return;
  }

  std::wstring page1 = GetSimplePageUrl();
  std::wstring page2 = GetLinkPageUrl();
  bool in_cf = GetParam().invokes_cf();
  InSequence expect_in_sequence_for_scope;

  // This test performs the following steps.
  // 1. Launches IE and navigates to page1
  // 2. It then navigates to page2
  // 3. Sends the VK_BACK keystroke to IE, which should navigate back to
  //    page 1
  // 4. Sends the Shift + VK_BACK keystroke to IE which should navigate
  //    forward to page2
  EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(page1)))
      .WillOnce(Navigate(&ie_mock_, page2));

  short bkspace = VkKeyScanA(VK_BACK);  // NOLINT
  EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(page2)))
      .WillOnce(testing::DoAll(
          SetFocusToRenderer(&ie_mock_),
          DelaySendScanCode(&loop_,
                            base::TimeDelta::FromSeconds(1),
                            bkspace,
                            simulate_input::NONE)));

  EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(page1)))
      .WillOnce(testing::DoAll(
          SetFocusToRenderer(&ie_mock_),
          DelaySendScanCode(&loop_,
                            base::TimeDelta::FromSeconds(1),
                            bkspace,
                            simulate_input::SHIFT)));

  EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(page2)))
      .WillOnce(CloseBrowserMock(&ie_mock_));

  LaunchIENavigateAndLoop(page1, kChromeFrameVeryLongNavigationTimeout);
}

// Tests new window behavior with ctrl+N.
TEST_P(FullTabUITest, CtrlN) {
  if (IsWorkstationLocked()) {
    LOG(ERROR) << "This test cannot be run in a locked workstation.";
    return;
  }

  bool is_cf = GetParam().invokes_cf();
  if (!is_cf) {
    LOG(ERROR) << "Test not implemented for this configuration.";
    return;
  }
  // Ideally we want to use a ie_mock_ to watch for finer grained
  // events for New Window, but for Crl+N we don't get any
  // OnNewWindowX notifications. :(
  MockWindowObserver win_observer_mock;

  const char* kNewWindowTitlePattern = "*Internet Explorer*";
  EXPECT_CALL(ie_mock_, OnLoad(is_cf, StrEq(GetSimplePageUrl())))
      .WillOnce(testing::DoAll(
          WatchWindow(&win_observer_mock, kNewWindowTitlePattern, ""),
          SetFocusToRenderer(&ie_mock_),
          DelaySendChar(&loop_,
                        base::TimeDelta::FromSeconds(1),
                        'n',
                        simulate_input::CONTROL)));

  // Watch for new window. It appears that the window close message cannot be
  // reliably delivered immediately upon receipt of the window open event.
  EXPECT_CALL(win_observer_mock, OnWindowOpen(_))
      .Times(testing::AtMost(2))
      .WillOnce(CloseBrowserMock(&ie_mock_))
      .WillOnce(testing::Return());

  EXPECT_CALL(win_observer_mock, OnWindowClose(_))
      .Times(testing::AtMost(2));

  LaunchIENavigateAndLoop(GetSimplePageUrl(),
                          kChromeFrameVeryLongNavigationTimeout);
}

// Test that Ctrl+F opens the Find dialog.
TEST_P(FullTabUITest, CtrlF) {
  if (IsWorkstationLocked()) {
    LOG(ERROR) << "This test cannot be run in a locked workstation.";
    return;
  }

  bool is_cf = GetParam().invokes_cf();
  if (!is_cf) {
    LOG(ERROR) << "Test not implemented for this configuration.";
    return;
  }
  server_mock_.ExpectAndServeAnyRequests(CFInvocation::MetaTag());
  MockWindowObserver win_observer_mock;
  InSequence expect_in_sequence_for_scope;

  const char* kFindDialogCaption = "Find";
  EXPECT_CALL(ie_mock_, OnLoad(IN_CF, StrEq(GetSimplePageUrl())))
      .WillOnce(testing::DoAll(
          WatchWindow(&win_observer_mock, kFindDialogCaption, ""),
          SetFocusToRenderer(&ie_mock_),
          DelaySendChar(&loop_,
                        base::TimeDelta::FromMilliseconds(1500),
                        'f',
                        simulate_input::CONTROL)));

  EXPECT_CALL(win_observer_mock, OnWindowOpen(_))
      .WillOnce(CloseBrowserMock(&ie_mock_));

  LaunchIENavigateAndLoop(GetSimplePageUrl(),
                          kChromeFrameVeryLongNavigationTimeout);
}

// Test that ctrl+r does cause a refresh.
TEST_P(FullTabUITest, CtrlR) {
  if (IsWorkstationLocked()) {
    LOG(ERROR) << "This test cannot be run in a locked workstation.";
    return;
  }

  EXPECT_CALL(server_mock_, Get(_, UrlPathEq(GetSimplePageUrl()), _))
      .Times(testing::AtMost(2))
      .WillRepeatedly(SendResponse(&server_mock_, GetParam()));

  EXPECT_CALL(ie_mock_, OnLoad(GetParam().invokes_cf(),
                               StrEq(GetSimplePageUrl())))
      .Times(testing::AtMost(2))
      .WillOnce(testing::DoAll(
          SetFocusToRenderer(&ie_mock_),
          DelaySendChar(&loop_,
                        base::TimeDelta::FromSeconds(1),
                        'r',
                        simulate_input::CONTROL),
          DelayCloseBrowserMock(
              &loop_, base::TimeDelta::FromSeconds(4), &ie_mock_)))
      .WillRepeatedly(testing::Return());

  LaunchIENavigateAndLoop(GetSimplePageUrl(),
                          kChromeFrameVeryLongNavigationTimeout);
}

// Test window close with ctrl+w.
TEST_P(FullTabUITest, CtrlW) {
  if (IsWorkstationLocked()) {
    LOG(ERROR) << "This test cannot be run in a locked workstation.";
    return;
  }

  EXPECT_CALL(ie_mock_, OnLoad(GetParam().invokes_cf(),
                               StrEq(GetSimplePageUrl())))
      .WillOnce(testing::DoAll(
          SetFocusToRenderer(&ie_mock_),
          DelaySendChar(&loop_,
                        base::TimeDelta::FromSeconds(1),
                        'w',
                        simulate_input::CONTROL)));

  LaunchIENavigateAndLoop(GetSimplePageUrl(),
                          kChromeFrameVeryLongNavigationTimeout);
}

// Test address bar navigation with Alt+d and URL.
// Flaky due to TypeUrlInAddressBar; see http://crbug.com/124244.
TEST_P(FullTabUITest, DISABLED_AltD) {
  if (IsWorkstationLocked()) {
    LOG(ERROR) << "This test cannot be run in a locked workstation.";
    return;
  }

  EXPECT_CALL(ie_mock_, OnLoad(GetParam().invokes_cf(),
                               StrEq(GetSimplePageUrl())))
      .WillOnce(testing::DoAll(
          SetFocusToRenderer(&ie_mock_),
          TypeUrlInAddressBar(&loop_,
                              GetLinkPageUrl(),
                              base::TimeDelta::FromMilliseconds(1500))));

  EXPECT_CALL(ie_mock_, OnLoad(GetParam().invokes_cf(),
                               StrEq(GetLinkPageUrl())))
      .WillOnce(CloseBrowserMock(&ie_mock_));

  LaunchIENavigateAndLoop(GetSimplePageUrl(),
                          kChromeFrameVeryLongNavigationTimeout);
}

// Tests that the renderer has focus after navigation.
// Flaky, see http://crbug.com/90791 .
TEST_P(FullTabUITest, DISABLED_RendererHasFocus) {
  EXPECT_CALL(ie_mock_, OnLoad(GetParam().invokes_cf(),
                               StrEq(GetSimplePageUrl())))
      .WillOnce(testing::DoAll(
          ExpectRendererHasFocus(&ie_mock_),
          CloseBrowserMock(&ie_mock_)));

  LaunchIEAndNavigate(GetSimplePageUrl());
}

// Tests that view source works.
TEST_P(FullTabUITest, ViewSource) {
  // Please see http://code.google.com/p/chromium/issues/detail?id=60987
  // for more information on why this test is disabled for Vista with IE7.
  if (base::win::GetVersion() == base::win::VERSION_VISTA &&
      GetInstalledIEVersion() == IE_7) {
    LOG(INFO) << "Not running test on Vista with IE7";
    return;
  }

  bool in_cf = GetParam().invokes_cf();
  if (!in_cf) {
    LOG(ERROR) << "Test not implemented for this configuration.";
    return;
  }
  MockIEEventSink view_source_mock;
  view_source_mock.ExpectAnyNavigations();
  InSequence expect_in_sequence_for_scope;

  // After navigation invoke view soruce action using IWebBrowser2::ExecWB
  VARIANT empty = base::win::ScopedVariant::kEmptyVariant;
  EXPECT_CALL(ie_mock_, OnLoad(in_cf,
                               StrEq(GetSimplePageUrl())))
      .WillOnce(DelayExecCommand(
          &ie_mock_, &loop_, base::TimeDelta(), &CGID_MSHTML,
          static_cast<OLECMDID>(IDM_VIEWSOURCE),
          OLECMDEXECOPT_DONTPROMPTUSER, &empty, &empty));

  // Expect notification for view-source window, handle new window event
  // and attach a new ie_mock_ to the received web browser
  std::wstring view_source_url;
  view_source_url += UTF8ToWide(content::kViewSourceScheme);
  view_source_url += L":";
  view_source_url += GetSimplePageUrl();
  std::wstring url_in_new_window = kChromeProtocolPrefix;
  url_in_new_window += view_source_url;

  ie_mock_.ExpectNewWindow(&view_source_mock);
  // For some reason this happens occasionally at least on XP IE7.
  EXPECT_CALL(view_source_mock, OnLoad(IN_IE, StrEq(url_in_new_window)))
      .Times(testing::AtMost(1));
  EXPECT_CALL(view_source_mock, OnLoad(in_cf, StrEq(view_source_url)))
      .WillOnce(testing::DoAll(
          VerifyAddressBarUrlWithGcf(&view_source_mock),
          CloseBrowserMock(&view_source_mock)));

  EXPECT_CALL(view_source_mock, OnQuit())
      .Times(testing::AtMost(1))
      .WillOnce(CloseBrowserMock(&ie_mock_));

  LaunchIEAndNavigate(GetSimplePageUrl());
}

void NavigateToCurrentUrl(MockIEEventSink* mock) {
  IWebBrowser2* browser = mock->event_sink()->web_browser2();
  DCHECK(browser);
  base::win::ScopedBstr bstr;
  HRESULT hr = browser->get_LocationURL(bstr.Receive());
  EXPECT_HRESULT_SUCCEEDED(hr);
  if (SUCCEEDED(hr)) {
    DCHECK(bstr.Length());
    VARIANT empty = base::win::ScopedVariant::kEmptyVariant;
    hr = browser->Navigate(bstr, &empty, &empty, &empty, &empty);
    EXPECT_HRESULT_SUCCEEDED(hr);
  }
}

// Tests that Chrome gets re-instantiated after crash if we reload via
// the address bar or via a new navigation.
// Flaky on ie7, http://crbug.com/277406.
TEST_P(FullTabUITest, DISABLED_TabCrashReload) {
  using testing::DoAll;

  if (!GetParam().invokes_cf()) {
    LOG(ERROR) << "Test needs CF.";
    return;
  }

  MockPropertyNotifySinkListener prop_listener;
  InSequence expect_in_sequence_for_scope;

  EXPECT_CALL(ie_mock_, OnLoad(_, StrEq(GetSimplePageUrl())))
      .WillOnce(DoAll(
          ExpectRendererHasFocus(&ie_mock_),
          ExpectDocumentReadystate(&ie_mock_, READYSTATE_COMPLETE),
          ConnectDocPropNotifySink(&ie_mock_, &prop_listener),
          KillChromeFrameProcesses()));

  EXPECT_CALL(prop_listener, OnChanged(DISPID_READYSTATE))
      .WillOnce(DoAll(
          ExpectDocumentReadystate(&ie_mock_, READYSTATE_UNINITIALIZED),
          DelayNavigateToCurrentUrl(
              &ie_mock_, &loop_, base::TimeDelta::FromMilliseconds(10))));

  EXPECT_CALL(ie_mock_, OnLoad(_, StrEq(GetSimplePageUrl())))
      .WillOnce(CloseBrowserMock(&ie_mock_));

  LaunchIEAndNavigate(GetSimplePageUrl());
}

// Tests if Chrome gets restarted after a crash by just refreshing the document.
// DISABLED as per bug http://crbug.com/99317 (one of the failures is a
// timeout, which marking as FLAKY or FAILS won't mask).
TEST_P(FullTabUITest, DISABLED_TabCrashRefresh) {
  using testing::DoAll;

  if (!GetParam().invokes_cf()) {
    LOG(ERROR) << "Test needs CF.";
    return;
  }

  MockPropertyNotifySinkListener prop_listener;
  InSequence expect_in_sequence_for_scope;

  EXPECT_CALL(ie_mock_, OnLoad(_, StrEq(GetSimplePageUrl())))
      .WillOnce(DoAll(
          ExpectRendererHasFocus(&ie_mock_),
          ExpectDocumentReadystate(&ie_mock_, READYSTATE_COMPLETE),
          ConnectDocPropNotifySink(&ie_mock_, &prop_listener),
          KillChromeFrameProcesses()));

  VARIANT empty = base::win::ScopedVariant::kEmptyVariant;
  EXPECT_CALL(prop_listener, OnChanged(/*DISPID_READYSTATE*/_))
      .WillOnce(DoAll(
          DisconnectDocPropNotifySink(&prop_listener),
          ExpectDocumentReadystate(&ie_mock_, READYSTATE_UNINITIALIZED),
          DelayExecCommand(
              &ie_mock_, &loop_, base::TimeDelta::FromMilliseconds(10),
              static_cast<GUID*>(NULL), OLECMDID_REFRESH, 0, &empty, &empty)));

  EXPECT_CALL(ie_mock_, OnLoad(_, StrEq(GetSimplePageUrl())))
      .WillOnce(CloseBrowserMock(&ie_mock_));

  LaunchIEAndNavigate(GetSimplePageUrl());
}

// Test that window.print() on a page results in the native Windows print dialog
// appearing rather than Chrome's in-page print preview.
TEST_P(FullTabUITest, WindowPrintOpensNativePrintDialog) {
  std::wstring window_print_url(GetTestUrl(L"window_print.html"));
  std::wstring window_print_title(L"window.print");

  const bool is_cf = GetParam().invokes_cf();
  MockWindowObserver win_observer_mock;

  // When the page is loaded, start watching for the Print dialog to appear.
  EXPECT_CALL(ie_mock_, OnLoad(is_cf, StrEq(window_print_url)))
      .WillOnce(WatchWindow(&win_observer_mock, "Print", ""));

  // When the print dialog opens, close it.
  EXPECT_CALL(win_observer_mock, OnWindowOpen(_))
      .WillOnce(DoCloseWindow());

  // When the print dialog closes, close the browser.
  EXPECT_CALL(win_observer_mock, OnWindowClose(_))
      .WillOnce(CloseBrowserMock(&ie_mock_));

  // Launch IE and navigate to the window_print.html page, which will
  // window.print() immediately after loading.
  LaunchIEAndNavigate(window_print_url);
}

// Test fixture for tests related to the context menu UI. Since the context
// menus for CF and IE are different, these tests are not parameterized.
class ContextMenuTest : public MockIEEventSinkTest, public testing::Test {
 public:
  ContextMenuTest(): kTextFieldInitValue(L"SomeInitializedTextValue") {}

  virtual void SetUp() {
    context_menu_page_url = GetTestUrl(L"context_menu.html");
    context_menu_page_title = L"context menu";
    // Clear clipboard to make sure there is no effect from previous tests.
    SetClipboardText(L"");
    // These are UI-related tests, so we do not care about the exact
    // navigations that occur.
    ie_mock_.ExpectAnyNavigations();
    EXPECT_CALL(ie_mock_, OnLoad(_, _)).Times(testing::AnyNumber());
    EXPECT_CALL(acc_observer_, OnAccDocLoad(_)).Times(testing::AnyNumber());
  }

  virtual void TearDown() {
    // Destroy the clipboard here because it is not destroyed automatically.
    DestroyClipboard();
  }

  // Common helper function for "Save xxx As" tests.
  void DoSaveAsTest(const wchar_t* role, const wchar_t* menu_item_name,
                    const wchar_t* file_ext) {
    server_mock_.ExpectAndServeAnyRequests(CFInvocation::MetaTag());
    MockWindowObserver win_observer_mock;
    InSequence expect_in_sequence_for_scope;

    // Open 'Save As' dialog.
    string16 initial_url(GetTestUrl(L"save_as_context_menu.html"));
    const char* kSaveDlgCaption = "Save As";
    EXPECT_CALL(acc_observer_,
                OnAccDocLoad(TabContentsTitleEq(initial_url,
                                                L"Save As download test")))
        .WillOnce(testing::DoAll(
            WatchWindow(&win_observer_mock, kSaveDlgCaption, ""),
            AccRightClick(AccObjectMatcher(L"", role))));
    EXPECT_CALL(acc_observer_, OnMenuPopup(_))
        .WillOnce(AccLeftClick(AccObjectMatcher(menu_item_name)));

    // Get safe download name using temporary file.
    base::FilePath temp_file_path;
    ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
    ASSERT_TRUE(file_util::DieFileDie(temp_file_path, false));
    temp_file_path = temp_file_path.ReplaceExtension(file_ext);

    AccObjectMatcher file_name_box(L"File name:", L"editable text");
    EXPECT_CALL(win_observer_mock, OnWindowOpen(_))
        .WillOnce(testing::DoAll(
            AccSendCharMessage(file_name_box, L'a'),
            AccSetValue(file_name_box, temp_file_path.value()),
            AccDoDefaultAction(AccObjectMatcher(L"Save", L"push button"))));

    EXPECT_CALL(win_observer_mock, OnWindowClose(_))
        .WillOnce(CloseWhenFileSaved(&ie_mock_, temp_file_path, 8000));

    LaunchIENavigateAndLoop(initial_url,
                            kChromeFrameVeryLongNavigationTimeout);
    ASSERT_TRUE(file_util::DieFileDie(temp_file_path, false));
  }

 protected:
  // Html page that holds a text field for context menu testing.
  std::wstring context_menu_page_url;
  // Title of said html page.
  std::wstring context_menu_page_title;
  // This is the text value used to test cut/copy/paste etc.
  const std::wstring kTextFieldInitValue;

  testing::NiceMock<MockAccEventObserver> acc_observer_;
};

// Test reloading from the context menu.
TEST_F(ContextMenuTest, CFReload) {
  server_mock_.ExpectAndServeAnyRequests(CFInvocation::MetaTag());
  InSequence expect_in_sequence_for_scope;

  string16 initial_url(GetSimplePageUrl());
  EXPECT_CALL(acc_observer_,
              OnAccDocLoad(TabContentsTitleEq(initial_url,
                                              GetSimplePageTitle())))
      .WillOnce(OpenContextMenuAsync());
  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
      .WillOnce(AccLeftClick(AccObjectMatcher(L"Reload")));

  EXPECT_CALL(ie_mock_, OnLoad(IN_CF, StrEq(initial_url)))
      .WillOnce(CloseBrowserMock(&ie_mock_));

  LaunchIEAndNavigate(initial_url);
}

// Test view source from the context menu.
TEST_F(ContextMenuTest, CFViewSource) {
  // Please see http://code.google.com/p/chromium/issues/detail?id=60987
  // for more information on why this test is disabled for Vista with IE7.
  if (base::win::GetVersion() == base::win::VERSION_VISTA &&
      GetInstalledIEVersion() == IE_7) {
    LOG(INFO) << "Not running test on Vista with IE7";
    return;
  }
  server_mock_.ExpectAndServeAnyRequests(CFInvocation::MetaTag());
  MockIEEventSink view_source_mock;
  view_source_mock.ExpectAnyNavigations();
  InSequence expect_in_sequence_for_scope;
  string16 initial_url(GetSimplePageUrl());

  // View the page source.
  EXPECT_CALL(acc_observer_,
              OnAccDocLoad(TabContentsTitleEq(initial_url,
                                              GetSimplePageTitle())))
      .WillOnce(OpenContextMenuAsync());
  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
      .WillOnce(AccLeftClick(AccObjectMatcher(L"View page source")));

  // Expect notification for view-source window, handle new window event
  // and attach a new ie_mock_ to the received web browser
  std::wstring view_source_url;
  view_source_url += UTF8ToWide(content::kViewSourceScheme);
  view_source_url += L":";
  view_source_url += initial_url;
  std::wstring url_in_new_window = kChromeProtocolPrefix;
  url_in_new_window += view_source_url;

  ie_mock_.ExpectNewWindow(&view_source_mock);
  // For some reason this happens occasionally at least on XP IE7 and Win7 IE8.
  EXPECT_CALL(view_source_mock, OnLoad(IN_IE, StrEq(url_in_new_window)))
      .Times(testing::AtMost(1));
  EXPECT_CALL(view_source_mock, OnLoad(IN_CF, StrEq(view_source_url)))
      .WillOnce(testing::DoAll(
          VerifyAddressBarUrlWithGcf(&view_source_mock),
          CloseBrowserMock(&view_source_mock)));
  EXPECT_CALL(view_source_mock, OnQuit())
      .Times(testing::AtMost(1))
      .WillOnce(CloseBrowserMock(&ie_mock_));

  LaunchIEAndNavigate(initial_url);
}

TEST_F(ContextMenuTest, DISABLED_CFPageInfo) {
  server_mock_.ExpectAndServeAnyRequests(CFInvocation::MetaTag());
  MockWindowObserver win_observer_mock;
  InSequence expect_in_sequence_for_scope;
  string16 initial_url(GetSimplePageUrl());

  // View page information.
  EXPECT_CALL(acc_observer_,
              OnAccDocLoad(TabContentsTitleEq(initial_url,
                                              GetSimplePageTitle())))
      .WillOnce(testing::DoAll(
          WatchWindow(&win_observer_mock, "", "Chrome_WidgetWin_*"),
          OpenContextMenuAsync()));
  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
      .WillOnce(AccLeftClick(AccObjectMatcher(L"View page info")));

  EXPECT_CALL(win_observer_mock, OnWindowOpen(_)).Times(1);
  // Expect page info dialog to pop up. Dismiss the dialog with 'Esc' key
  EXPECT_CALL(win_observer_mock, OnWindowOpen(_))
      .WillOnce(DoCloseWindow());

  EXPECT_CALL(win_observer_mock, OnWindowClose(_)).Times(1);
  EXPECT_CALL(win_observer_mock, OnWindowClose(_))
    .WillOnce(CloseBrowserMock(&ie_mock_));

  LaunchIEAndNavigate(initial_url);
}

TEST_F(ContextMenuTest, CFInspector) {
  server_mock_.ExpectAndServeAnyRequests(CFInvocation::MetaTag());
  MockWindowObserver win_observer_mock;
  InSequence expect_in_sequence_for_scope;

  // Open developer tools.
  // Devtools begins life with "Untitled" caption and it changes
  // later to the 'Developer Tools - <url> form.
  const char* kPageInfoCaptionPattern = "Untitled*";
  string16 initial_url(GetSimplePageUrl());
  EXPECT_CALL(acc_observer_,
              OnAccDocLoad(TabContentsTitleEq(initial_url,
                                              GetSimplePageTitle())))
      .WillOnce(testing::DoAll(
          WatchWindow(&win_observer_mock, kPageInfoCaptionPattern, ""),
          OpenContextMenuAsync()));
  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
      .WillOnce(AccLeftClick(AccObjectMatcher(L"Inspect element")));

  EXPECT_CALL(win_observer_mock, OnWindowOpen(_))
      .WillOnce(DelayDoCloseWindow(5000));  // wait to catch possible crash
  EXPECT_CALL(win_observer_mock, OnWindowClose(_))
      .WillOnce(CloseBrowserMock(&ie_mock_));

  LaunchIENavigateAndLoop(initial_url,
                          kChromeFrameVeryLongNavigationTimeout);
}

// http://code.google.com/p/chromium/issues/detail?id=83114
TEST_F(ContextMenuTest, DISABLED_CFSavePageAs) {
  // Please see http://code.google.com/p/chromium/issues/detail?id=60987
  // for more information on why this test is disabled for Vista with IE7.
  if (base::win::GetVersion() == base::win::VERSION_VISTA &&
      GetInstalledIEVersion() == IE_7) {
    LOG(INFO) << "Not running test on Vista with IE7";
    return;
  }
  ASSERT_NO_FATAL_FAILURE(DoSaveAsTest(L"", L"Save as...", L".html"));
}

// http://code.google.com/p/chromium/issues/detail?id=83114
TEST_F(ContextMenuTest, DISABLED_CFSaveLinkAs) {
  // Please see http://code.google.com/p/chromium/issues/detail?id=60987
  // for more information on why this test is disabled for Vista with IE7.
  if (base::win::GetVersion() == base::win::VERSION_VISTA &&
      GetInstalledIEVersion() == IE_7) {
    LOG(INFO) << "Not running test on Vista with IE7";
    return;
  }
  ASSERT_NO_FATAL_FAILURE(DoSaveAsTest(L"link", L"Save link as...", L".zip"));
}

// This tests that the about:version page can be opened via the CF context menu.
TEST_F(ContextMenuTest, CFAboutVersionLoads) {
  // Please see http://code.google.com/p/chromium/issues/detail?id=60987
  // for more information on why this test is disabled for Vista with IE7.
  if (base::win::GetVersion() == base::win::VERSION_VISTA &&
      GetInstalledIEVersion() == IE_7) {
    LOG(INFO) << "Not running test on Vista with IE7";
    return;
  }
  server_mock_.ExpectAndServeAnyRequests(CFInvocation::MetaTag());
  const wchar_t* kAboutVersionUrl = L"gcf:about:version";
  const wchar_t* kAboutVersionWithoutProtoUrl = L"about:version";
  MockIEEventSink new_window_mock;
  new_window_mock.ExpectAnyNavigations();
  InSequence expect_in_sequence_for_scope;
  string16 initial_url(GetSimplePageUrl());

  EXPECT_CALL(acc_observer_,
              OnAccDocLoad(TabContentsTitleEq(initial_url,
                                              GetSimplePageTitle())))
      .WillOnce(OpenContextMenuAsync());
  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
      .WillOnce(AccLeftClick(AccObjectMatcher(L"About*")));

  ie_mock_.ExpectNewWindow(&new_window_mock);
  // For some reason this happens occasionally at least on Win7 IE8.
  EXPECT_CALL(new_window_mock, OnLoad(IN_IE, StrEq(kAboutVersionUrl)))
      .Times(testing::AtMost(1));
  EXPECT_CALL(new_window_mock,
              OnLoad(IN_CF, StrEq(kAboutVersionWithoutProtoUrl)))
      .WillOnce(testing::DoAll(
          VerifyAddressBarUrlWithGcf(&new_window_mock),
          CloseBrowserMock(&new_window_mock)));

  EXPECT_CALL(new_window_mock, OnQuit())
      .Times(testing::AtMost(1))
      .WillOnce(CloseBrowserMock(&ie_mock_));

  LaunchIEAndNavigate(initial_url);
}

TEST_F(ContextMenuTest, IEOpen) {
  server_mock_.ExpectAndServeAnyRequests(CFInvocation::None());
  InSequence expect_in_sequence_for_scope;
  string16 initial_url(GetLinkPageUrl());

  // Open the link through the context menu.
  EXPECT_CALL(acc_observer_,
              OnAccDocLoad(TabContentsTitleEq(initial_url, GetLinkPageTitle())))
      .WillOnce(AccRightClick(AccObjectMatcher(L"", L"link")));
  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
      .WillOnce(AccLeftClick(AccObjectMatcher(L"Open")));

  EXPECT_CALL(ie_mock_, OnLoad(IN_IE, StrEq(GetSimplePageUrl())))
      .WillOnce(testing::DoAll(
          VerifyAddressBarUrl(&ie_mock_),
          CloseBrowserMock(&ie_mock_)));

  LaunchIEAndNavigate(initial_url);
}

TEST_F(ContextMenuTest, IEOpenInNewWindow) {
  // See crbug.com/64794.
  if (GetInstalledIEVersion() == IE_7) {
    LOG(INFO) << "Not running test with IE7";
    return;
  }
  server_mock_.ExpectAndServeAnyRequests(CFInvocation::None());
  MockIEEventSink new_window_mock;
  new_window_mock.ExpectAnyNavigations();
  InSequence expect_in_sequence_for_scope;
  string16 initial_url(GetLinkPageUrl());

  // Open the link in a new window.
  EXPECT_CALL(acc_observer_,
              OnAccDocLoad(TabContentsTitleEq(initial_url, GetLinkPageTitle())))
      .WillOnce(AccRightClick(AccObjectMatcher(L"", L"link")));
  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
      .WillOnce(AccLeftClick(AccObjectMatcher(L"Open in New Window")));

  ie_mock_.ExpectNewWindow(&new_window_mock);
  EXPECT_CALL(new_window_mock, OnLoad(IN_IE, StrEq(GetSimplePageUrl())))
      // TODO(kkania): Verifying the address bar is flaky with this, at least
      // on XP ie6. Fix.
      .WillOnce(CloseBrowserMock(&new_window_mock));

  EXPECT_CALL(new_window_mock, OnQuit())
      .Times(testing::AtMost(1))
      .WillOnce(CloseBrowserMock(&ie_mock_));

  LaunchIEAndNavigate(initial_url);
}

// Test Back/Forward from context menu.
TEST_F(ContextMenuTest, IEBackForward) {
  server_mock_.ExpectAndServeAnyRequests(CFInvocation::None());
  std::wstring page1 = GetLinkPageUrl();
  std::wstring title1 = GetLinkPageTitle();
  std::wstring page2 = GetSimplePageUrl();
  std::wstring title2 = GetSimplePageTitle();
  InSequence expect_in_sequence_for_scope;

  // Navigate to second page.
  EXPECT_CALL(acc_observer_, OnAccDocLoad(TabContentsTitleEq(page1, title1)))
      .WillOnce(Navigate(&ie_mock_, page2));

  // Go back.
  EXPECT_CALL(acc_observer_, OnAccDocLoad(TabContentsTitleEq(page2, title2)))
      .WillOnce(testing::DoAll(
          VerifyPageLoad(&ie_mock_, IN_IE, page2),
          OpenContextMenuAsync()));
  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
      .WillOnce(AccLeftClick(AccObjectMatcher(L"Back")));

  // Go forward.
  EXPECT_CALL(acc_observer_, OnAccDocLoad(TabContentsTitleEq(page1, title1)))
      .WillOnce(testing::DoAll(
          VerifyPageLoad(&ie_mock_, IN_IE, page1),
          OpenContextMenuAsync()));
  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
      .WillOnce(AccLeftClick(AccObjectMatcher(L"Forward")));

  EXPECT_CALL(ie_mock_, OnLoad(IN_IE, StrEq(page2)))
      .WillOnce(CloseBrowserMock(&ie_mock_));

  LaunchIEAndNavigate(page1);
}

// Test CF link context menu - Open link in new window.
// Failing intermittently on IE6/7. See crbug.com/64794.
TEST_F(ContextMenuTest, DISABLED_CFOpenLinkInNewWindow) {
  server_mock_.ExpectAndServeAnyRequests(CFInvocation::MetaTag());
  MockIEEventSink new_window_mock;
  new_window_mock.ExpectAnyNavigations();
  string16 initial_url(GetLinkPageUrl());

  // Invoke 'Open link in new window' context menu item.
  EXPECT_CALL(acc_observer_,
              OnAccDocLoad(TabContentsTitleEq(initial_url, GetLinkPageTitle())))
      .Times(testing::AtMost(2))
      .WillOnce(AccRightClick(AccObjectMatcher(L"", L"link")))
      .WillOnce(testing::Return());
  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
      .WillOnce(AccLeftClick(AccObjectMatcher(L"Open link in new window*")));

  ie_mock_.ExpectNewWindow(&new_window_mock);
  EXPECT_CALL(new_window_mock, OnLoad(IN_CF, StrEq(GetSimplePageUrl())))
      .WillOnce(CloseBrowserMock(&new_window_mock));
  EXPECT_CALL(new_window_mock, OnQuit())
      .WillOnce(CloseBrowserMock(&ie_mock_));

  LaunchIEAndNavigate(initial_url);
}

// Test CF link context menu - Copy link address.
TEST_F(ContextMenuTest, CFCopyLinkAddress) {
  server_mock_.ExpectAndServeAnyRequests(CFInvocation::MetaTag());
  string16 initial_url(GetLinkPageUrl());

  // Invoke 'Copy link address' context menu item.
  EXPECT_CALL(acc_observer_,
              OnAccDocLoad(TabContentsTitleEq(initial_url, GetLinkPageTitle())))
      .WillOnce(AccRightClick(AccObjectMatcher(L"", L"link")));
  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
      .WillOnce(testing::DoAll(
          AccLeftClick(AccObjectMatcher(L"Copy link address*")),
          CloseBrowserMock(&ie_mock_)));

  LaunchIEAndNavigate(initial_url);

  EXPECT_STREQ(GetSimplePageUrl().c_str(), GetClipboardText().c_str());
}

// Test CF text field context menu - cut.
// Times out sporadically http://crbug.com/119660.
TEST_F(ContextMenuTest, DISABLED_CFTxtFieldCut) {
  server_mock_.ExpectAndServeAnyRequests(CFInvocation::MetaTag());
  AccObjectMatcher txtfield_matcher(L"", L"editable text");

  // Invoke "Cut" context menu item of text field.
  EXPECT_CALL(acc_observer_,
              OnAccDocLoad(TabContentsTitleEq(context_menu_page_url,
                                              context_menu_page_title)))
      .WillOnce(testing::DoAll(
          AccRightClick(txtfield_matcher),
          AccWatchForOneValueChange(&acc_observer_, txtfield_matcher)));
  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
    .WillOnce(AccLeftClick(AccObjectMatcher(L"Cut*")));

  // Verify that text field is empty after cut operation.
  EXPECT_CALL(acc_observer_, OnAccValueChange(_, _, StrEq(L"")))
      .WillOnce(CloseBrowserMock(&ie_mock_));

  LaunchIEAndNavigate(context_menu_page_url);
  // Verify that the text value has been cut to clipboard.
  EXPECT_STREQ(kTextFieldInitValue.c_str(), GetClipboardText().c_str());
}

// Test CF text field context menu - copy.
// Times out sporadically http://crbug.com/119660.
TEST_F(ContextMenuTest, DISABLED_CFTxtFieldCopy) {
  server_mock_.ExpectAndServeAnyRequests(CFInvocation::MetaTag());
  AccObjectMatcher txtfield_matcher(L"", L"editable text");

  // Invoke "Copy" context menu item of text field.
  EXPECT_CALL(acc_observer_,
              OnAccDocLoad(TabContentsTitleEq(context_menu_page_url,
                                              context_menu_page_title)))
      .WillOnce(testing::DoAll(
          AccRightClick(txtfield_matcher),
          AccWatchForOneValueChange(&acc_observer_, txtfield_matcher)));
  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
    .WillOnce(testing::DoAll(
        AccLeftClick(AccObjectMatcher(L"Copy*")),
        CloseBrowserMock(&ie_mock_)));

  // Verify that there is no change on text field value after copy operation.
  EXPECT_CALL(acc_observer_, OnAccValueChange(_, _, _))
      .Times(testing::AtMost(0));

  LaunchIEAndNavigate(context_menu_page_url);
  // Verify that the text value has been copied to clipboard.
  EXPECT_STREQ(kTextFieldInitValue.c_str(), GetClipboardText().c_str());
}

// Test CF text field context menu - paste.
// Times out sporadically http://crbug.com/119660.
TEST_F(ContextMenuTest, DISABLED_CFTxtFieldPaste) {
  server_mock_.ExpectAndServeAnyRequests(CFInvocation::MetaTag());
  AccObjectMatcher txtfield_matcher(L"", L"editable text");

  // Invoke "Paste" context menu item of text field.
  EXPECT_CALL(acc_observer_,
              OnAccDocLoad(TabContentsTitleEq(context_menu_page_url,
                                              context_menu_page_title)))
      .WillOnce(testing::DoAll(
          AccRightClick(txtfield_matcher),
          AccWatchForOneValueChange(&acc_observer_, txtfield_matcher)));
  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
      .WillOnce(AccLeftClick(AccObjectMatcher(L"Paste*")));
  // Verify that value has been pasted to text field.
  EXPECT_CALL(acc_observer_, OnAccValueChange(_, _, StrEq(kTextFieldInitValue)))
      .WillOnce(CloseBrowserMock(&ie_mock_));

  // Set some text value to clipboard, this is to emulate the 'copy' action.
  SetClipboardText(kTextFieldInitValue);

  LaunchIEAndNavigate(context_menu_page_url);
}

// Test CF text field context menu - delete.
// Times out sporadically http://crbug.com/119660.
TEST_F(ContextMenuTest, DISABLED_CFTxtFieldDelete) {
  server_mock_.ExpectAndServeAnyRequests(CFInvocation::MetaTag());
  AccObjectMatcher txtfield_matcher(L"", L"editable text");

  // Invoke 'Delete' context menu item of text field.
  EXPECT_CALL(acc_observer_,
              OnAccDocLoad(TabContentsTitleEq(context_menu_page_url,
                                              context_menu_page_title)))
      .WillOnce(testing::DoAll(
          AccRightClick(txtfield_matcher),
          AccWatchForOneValueChange(&acc_observer_, txtfield_matcher)));
  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
      .WillOnce(AccLeftClick(AccObjectMatcher(L"Delete*")));
  // Verify that value has been deleted from text field.
  EXPECT_CALL(acc_observer_, OnAccValueChange(_, _, StrEq(L"")))
      .WillOnce(CloseBrowserMock(&ie_mock_));

  LaunchIEAndNavigate(context_menu_page_url);
}

// Test CF text field context menu - select all.
// Flaky: http://crbug.com/144664
TEST_F(ContextMenuTest, DISABLED_CFTxtFieldSelectAll) {
  server_mock_.ExpectAndServeAnyRequests(CFInvocation::MetaTag());

  // Invoke 'Select all' context menu item of text field.
  EXPECT_CALL(acc_observer_,
              OnAccDocLoad(TabContentsTitleEq(context_menu_page_url,
                                              context_menu_page_title)))
      .WillOnce(AccRightClick(AccObjectMatcher(L"", L"editable text")));
  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
      .WillOnce(testing::DoAll(
          AccLeftClick(AccObjectMatcher(L"Select all*")),
          PostMessageToCF(&ie_mock_, L"selectall")));
  // Client side script verifies that the text field value has been selected,
  // then send 'OK' message.
  EXPECT_CALL(ie_mock_, OnMessage(testing::StrCaseEq(L"OK"), _, _))
      .WillOnce(CloseBrowserMock(&ie_mock_));

  LaunchIEAndNavigate(context_menu_page_url + L"?action=selectall");
}

// Test CF text field context menu - undo.
// Times out sporadically http://crbug.com/119660.
TEST_F(ContextMenuTest, DISABLED_CFTxtFieldUndo) {
  server_mock_.ExpectAndServeAnyRequests(CFInvocation::MetaTag());
  AccObjectMatcher txtfield_matcher(L"", L"editable text");

  // Change the value of text field to 'A'.
  EXPECT_CALL(acc_observer_,
              OnAccDocLoad(TabContentsTitleEq(context_menu_page_url,
                                              context_menu_page_title)))
      .WillOnce(testing::DoAll(
          AccWatchForOneValueChange(&acc_observer_, txtfield_matcher),
          AccSendCharMessage(txtfield_matcher, L'A')));
  // Bring up the context menu once the value has changed.
  EXPECT_CALL(acc_observer_, OnAccValueChange(_, _, StrEq(L"A")))
      .WillOnce(AccRightClick(txtfield_matcher));
  // Then select "Undo".
  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
      .WillOnce(testing::DoAll(
          AccWatchForOneValueChange(&acc_observer_, txtfield_matcher),
          AccLeftClick(AccObjectMatcher(L"Undo*"))));

  // Verify that value has been reset to initial value after undo operation.
  EXPECT_CALL(acc_observer_, OnAccValueChange(_, _, StrEq(kTextFieldInitValue)))
      .WillOnce(CloseBrowserMock(&ie_mock_));

  LaunchIEAndNavigate(context_menu_page_url);
}

// Test CF text field context menu - redo.
// Times out sporadically http://crbug.com/119660.
TEST_F(ContextMenuTest, DISABLED_CFTxtFieldRedo) {
  server_mock_.ExpectAndServeAnyRequests(CFInvocation::MetaTag());
  AccObjectMatcher txtfield_matcher(L"", L"editable text");
  InSequence expect_in_sequence_for_scope;

  // Change text field from its initial value to 'A'.
  EXPECT_CALL(acc_observer_,
              OnAccDocLoad(TabContentsTitleEq(context_menu_page_url,
                                              context_menu_page_title)))
      .WillOnce(testing::DoAll(
          AccWatchForOneValueChange(&acc_observer_, txtfield_matcher),
          AccSendCharMessage(txtfield_matcher, L'A')));
  // Bring up the context menu.
  EXPECT_CALL(acc_observer_, OnAccValueChange(_, _, StrEq(L"A")))
      .WillOnce(AccRightClick(txtfield_matcher));
  // Select "Undo"
  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
      .WillOnce(testing::DoAll(
          AccWatchForOneValueChange(&acc_observer_, txtfield_matcher),
          AccLeftClick(AccObjectMatcher(L"Undo*"))));

  // After undo operation is done, bring up the context menu again.
  EXPECT_CALL(acc_observer_, OnAccValueChange(_, _, StrEq(kTextFieldInitValue)))
      .WillOnce(AccRightClick(txtfield_matcher));
  // Select "Redo"
  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
      .WillOnce(testing::DoAll(
          AccWatchForOneValueChange(&acc_observer_, txtfield_matcher),
          AccLeftClick(AccObjectMatcher(L"Redo*"))));

  // Verify that text field value is reset to its changed value 'A' and exit.
  EXPECT_CALL(acc_observer_, OnAccValueChange(_, _, StrEq(L"A")))
      .WillOnce(CloseBrowserMock(&ie_mock_));

  LaunchIEAndNavigate(context_menu_page_url);
}

// Disabled because it seems to hang, causing the test process to timeout and
// be killed; see http://crbug.com/121097.
TEST_F(ContextMenuTest, DISABLED_CFBackForward) {
  std::wstring page1 = GetLinkPageUrl();
  std::wstring title1 = GetLinkPageTitle();
  std::wstring page2 = GetSimplePageUrl();
  std::wstring title2 = GetSimplePageTitle();
  std::wstring page3 = GetTestUrl(L"anchor.html");
  std::wstring title3 = GetAnchorPageTitle();

  server_mock_.ExpectAndServeRequestWithCardinality(
      CFInvocation::MetaTag(), page1, testing::Exactly(2));

  server_mock_.ExpectAndServeRequestWithCardinality(
      CFInvocation::None(), page2, testing::Exactly(3));

  server_mock_.ExpectAndServeRequestWithCardinality(
      CFInvocation::MetaTag(), page3, testing::Exactly(2));

  InSequence expect_in_sequence_for_scope;

  // Navigate to second page.
  EXPECT_CALL(acc_observer_, OnAccDocLoad(TabContentsTitleEq(page1, title1)))
      .WillOnce(testing::DoAll(
          VerifyPageLoad(&ie_mock_, IN_CF, page1),
          Navigate(&ie_mock_, page2)));

  // Navigate to third page.
  EXPECT_CALL(acc_observer_, OnAccDocLoad(TabContentsTitleEq(page2, title2)))
      .WillOnce(testing::DoAll(
          VerifyPageLoad(&ie_mock_, IN_IE, page2),
          Navigate(&ie_mock_, page3)));

  // Go back.
  EXPECT_CALL(acc_observer_, OnAccDocLoad(TabContentsTitleEq(page3, title3)))
      .WillOnce(testing::DoAll(
          VerifyPageLoad(&ie_mock_, IN_CF, page3),
          OpenContextMenuAsync()));

  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
      .WillOnce(AccLeftClick(AccObjectMatcher(L"Back")));

  // Go back
  EXPECT_CALL(acc_observer_, OnAccDocLoad(TabContentsTitleEq(page2, title2)))
      .WillOnce(testing::DoAll(
          VerifyPageLoad(&ie_mock_, IN_IE, page2),
          OpenContextMenuAsync()));

  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
      .WillOnce(AccLeftClick(AccObjectMatcher(L"Back")));

  // Go forward.
  EXPECT_CALL(acc_observer_, OnAccDocLoad(TabContentsTitleEq(page1, title1)))
      .WillOnce(testing::DoAll(
          VerifyPageLoad(&ie_mock_, IN_CF, page1),
          OpenContextMenuAsync()));

  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
      .WillOnce(AccLeftClick(AccObjectMatcher(L"Forward")));

  // Go forward.
  EXPECT_CALL(acc_observer_, OnAccDocLoad(TabContentsTitleEq(page2, title2)))
      .WillOnce(testing::DoAll(
          VerifyPageLoad(&ie_mock_, IN_IE, page2),
          OpenContextMenuAsync()));

  EXPECT_CALL(acc_observer_, OnMenuPopup(_))
      .WillOnce(AccLeftClick(AccObjectMatcher(L"Forward")));

  EXPECT_CALL(ie_mock_, OnLoad(IN_CF, StrEq(page3)))
      .WillOnce(CloseBrowserMock(&ie_mock_));

  LaunchIENavigateAndLoop(page1, kChromeFrameVeryLongNavigationTimeout);
}

}  // namespace chrome_frame_test