// 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 <string>
#include "base/file_util.h"
#include "base/test/test_file_util.h"
#include "base/win/scoped_comptr.h"
#include "base/win/windows_version.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 "net/http/http_util.h"
// Needed for CreateFunctor.
#define GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING
#include "testing/gmock_mutant.h"
using testing::InSequence;
using testing::StrEq;
using testing::_;
namespace chrome_frame_test {
// Test fixture for navigation-related tests. Each test is run thrice: IE, CF
// with meta tag invocation, and CF with http header invocation. This is
// accomplished by using gTest's parameterized test.
class FullTabNavigationTest
: public MockIEEventSinkTest, public testing::TestWithParam<CFInvocation> {
public:
FullTabNavigationTest() {}
};
// Instantiate each test case. Instead of doing in one statement, it is split
// into three so gTest prints nicer names.
INSTANTIATE_TEST_CASE_P(IE, FullTabNavigationTest, testing::Values(
CFInvocation(CFInvocation::NONE)));
INSTANTIATE_TEST_CASE_P(MetaTag, FullTabNavigationTest, testing::Values(
CFInvocation(CFInvocation::META_TAG)));
INSTANTIATE_TEST_CASE_P(HttpHeader, FullTabNavigationTest, testing::Values(
CFInvocation(CFInvocation::HTTP_HEADER)));
// This tests navigation to a typed URL.
TEST_P(FullTabNavigationTest, TypeUrl) {
MockAccEventObserver acc_observer;
EXPECT_CALL(acc_observer, OnAccDocLoad(_)).Times(testing::AnyNumber());
AccObjectMatcher address_matcher(L"Address*", L"editable text");
AccObjectMatcher go_matcher(L"Go*", L"push button");
ie_mock_.ExpectNavigation(IN_IE, GetSimplePageUrl());
server_mock_.ExpectAndServeRequest(CFInvocation::None(), GetSimplePageUrl());
// Enter the new url into the address bar.
EXPECT_CALL(ie_mock_, OnLoad(IN_IE, StrEq(GetSimplePageUrl())))
.WillOnce(testing::DoAll(
AccSetValueInBrowser(&ie_mock_, address_matcher, GetAnchorPageUrl(0)),
AccWatchForOneValueChange(&acc_observer, address_matcher)));
// Click the go button once the address has changed.
EXPECT_CALL(acc_observer, OnAccValueChange(_, _, GetAnchorPageUrl(0)))
.WillOnce(AccLeftClickInBrowser(&ie_mock_, go_matcher));
bool in_cf = GetParam().invokes_cf();
ie_mock_.ExpectNavigation(in_cf, GetAnchorPageUrl(0));
server_mock_.ExpectAndServeRequest(GetParam(), GetAnchorPageUrl(0));
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetAnchorPageUrl(0))))
.WillOnce(CloseBrowserMock(&ie_mock_));
LaunchIEAndNavigate(GetSimplePageUrl());
}
// This tests navigation to a typed URL containing an fragment.
TEST_P(FullTabNavigationTest, TypeAnchorUrl) {
MockAccEventObserver acc_observer;
EXPECT_CALL(acc_observer, OnAccDocLoad(_)).Times(testing::AnyNumber());
AccObjectMatcher address_matcher(L"Address*", L"editable text");
AccObjectMatcher go_matcher(L"Go*", L"push button");
ie_mock_.ExpectNavigation(IN_IE, GetSimplePageUrl());
server_mock_.ExpectAndServeRequest(CFInvocation::None(), GetSimplePageUrl());
// Enter the new url into the address bar.
EXPECT_CALL(ie_mock_, OnLoad(IN_IE, StrEq(GetSimplePageUrl())))
.WillOnce(testing::DoAll(
AccSetValueInBrowser(&ie_mock_, address_matcher, GetAnchorPageUrl(1)),
AccWatchForOneValueChange(&acc_observer, address_matcher)));
// Click the go button once the address has changed.
EXPECT_CALL(acc_observer, OnAccValueChange(_, _, GetAnchorPageUrl(1)))
.WillOnce(AccLeftClickInBrowser(&ie_mock_, go_matcher));
bool in_cf = GetParam().invokes_cf();
ie_mock_.ExpectNavigation(in_cf, GetAnchorPageUrl(1));
server_mock_.ExpectAndServeRequest(GetParam(), GetAnchorPageUrl(1));
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetAnchorPageUrl(1))))
.WillOnce(CloseBrowserMock(&ie_mock_));
LaunchIEAndNavigate(GetSimplePageUrl());
}
// Tests refreshing causes a page load.
TEST_P(FullTabNavigationTest, Refresh) {
if (GetInstalledIEVersion() == IE_7) {
LOG(ERROR) << "Test disabled for this configuration.";
return;
}
bool in_cf = GetParam().invokes_cf();
server_mock_.ExpectAndServeAnyRequests(GetParam());
InSequence expect_in_sequence_for_scope;
ie_mock_.ExpectNavigation(IN_IE, GetSimplePageUrl());
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetSimplePageUrl())))
.WillOnce(DelayRefresh(&ie_mock_, &loop_, base::TimeDelta()));
if (in_cf) {
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetSimplePageUrl())))
.WillOnce(CloseBrowserMock(&ie_mock_));
} else {
// For some reason IE still requests the resource again, but does not
// trigger another load.
EXPECT_CALL(server_mock_, Get(_, UrlPathEq(GetSimplePageUrl()), _))
.WillOnce(CloseBrowserMock(&ie_mock_));
}
LaunchIEAndNavigate(GetSimplePageUrl());
}
// Test that multiple back and forward requests work.
// TODO(tsepez): http://crbug.com/83133
TEST_P(FullTabNavigationTest, DISABLED_MultipleBackForward) {
std::wstring page1 = GetSimplePageUrl();
std::wstring page2 = GetLinkPageUrl();
std::wstring page3 = GetAnchorPageUrl(0);
bool in_cf = GetParam().invokes_cf();
server_mock_.ExpectAndServeAnyRequests(GetParam());
InSequence expect_in_sequence_for_scope;
// Navigate to url 2 after the previous navigation is complete.
ie_mock_.ExpectNavigation(in_cf, page1);
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(page1)))
.WillOnce(testing::DoAll(
VerifyAddressBarUrl(&ie_mock_),
Navigate(&ie_mock_, page2)));
// Navigate to url 3 after the previous navigation is complete.
ie_mock_.ExpectNavigation(in_cf, page2);
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(page2)))
.WillOnce(testing::DoAll(
VerifyAddressBarUrl(&ie_mock_),
Navigate(&ie_mock_, page3)));
// We have reached url 3 and have two back entries for url 1 & 2.
// Go back to url 2 now.
ie_mock_.ExpectNavigation(in_cf, page3);
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(page3)))
.WillOnce(testing::DoAll(
VerifyAddressBarUrl(&ie_mock_),
DelayGoBack(&ie_mock_, &loop_, base::TimeDelta())));
// We have reached url 2 and have 1 back & 1 forward entries for url 1 & 3.
// Go back to url 1 now.
ie_mock_.ExpectNavigation(in_cf, page2);
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(page2)))
.WillOnce(testing::DoAll(
VerifyAddressBarUrl(&ie_mock_),
DelayGoBack(&ie_mock_, &loop_, base::TimeDelta())));
// We have reached url 1 and have 0 back & 2 forward entries for url 2 & 3.
// Go forward to url 2 now.
ie_mock_.ExpectNavigation(in_cf, page1);
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(page1)))
.WillOnce(testing::DoAll(
VerifyAddressBarUrl(&ie_mock_),
DelayGoForward(&ie_mock_, &loop_, base::TimeDelta())));
// We have reached url 2 and have 1 back & 1 forward entries for url 1 & 3.
// Go forward to url 3 now.
ie_mock_.ExpectNavigation(in_cf, page2);
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(page2)))
.WillOnce(testing::DoAll(
VerifyAddressBarUrl(&ie_mock_),
DelayGoForward(&ie_mock_, &loop_, base::TimeDelta())));
// We have reached url 2 and have 1 back & 1 forward entries for url 1 & 3.
ie_mock_.ExpectNavigation(in_cf, page3);
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(page3)))
.WillOnce(testing::DoAll(
VerifyAddressBarUrl(&ie_mock_),
CloseBrowserMock(&ie_mock_)));
LaunchIENavigateAndLoop(page1, kChromeFrameLongNavigationTimeout * 2);
}
// Test multiple back and forward operations among urls with anchors.
TEST_P(FullTabNavigationTest, BackForwardAnchor) {
std::wstring title(GetAnchorPageTitle());
bool in_cf = GetParam().invokes_cf();
ie_mock_.ExpectAnyNavigations();
server_mock_.ExpectAndServeAnyRequests(GetParam());
MockAccEventObserver acc_observer;
EXPECT_CALL(acc_observer, OnAccDocLoad(_)).Times(testing::AnyNumber());
// Navigate to anchor 1.
// Back/Forward state at this point:
// Back: 0
// Forward: 0
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetAnchorPageUrl(0))))
.Times(testing::AtMost(1));
EXPECT_CALL(acc_observer, OnAccDocLoad(TabContentsTitleEq(GetAnchorPageUrl(0),
title)))
.WillOnce(AccDoDefaultAction(AccObjectMatcher(L"*1", L"link")))
.RetiresOnSaturation();
InSequence expect_in_sequence_for_scope;
// Navigate to anchor 2 after the previous navigation is complete
// Back/Forward state at this point:
// Back: 1 (kAnchorUrl)
// Forward: 0
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetAnchorPageUrl(1))))
.WillOnce(testing::DoAll(
VerifyAddressBarUrl(&ie_mock_),
AccDoDefaultActionInRenderer(&ie_mock_,
AccObjectMatcher(L"*2", L"link"))));
// Navigate to anchor 3 after the previous navigation is complete
// Back/Forward state at this point:
// Back: 2 (kAnchorUrl, kAnchor1Url)
// Forward: 0
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetAnchorPageUrl(2))))
.WillOnce(testing::DoAll(
VerifyAddressBarUrl(&ie_mock_),
AccDoDefaultActionInRenderer(&ie_mock_,
AccObjectMatcher(L"*3", L"link"))));
// We will reach anchor 3 once the navigation is complete,
// then go back to anchor 2
// Back/Forward state at this point:
// Back: 3 (kAnchorUrl, kAnchor1Url, kAnchor2Url)
// Forward: 0
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetAnchorPageUrl(3))))
.WillOnce(testing::DoAll(
VerifyAddressBarUrl(&ie_mock_),
DelayGoBack(&ie_mock_, &loop_, base::TimeDelta())));
// We will reach anchor 2 once the navigation is complete,
// then go back to anchor 1
// Back/Forward state at this point:
// Back: 3 (kAnchorUrl, kAnchor1Url, kAnchor2Url)
// Forward: 1 (kAnchor3Url)
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetAnchorPageUrl(2))))
.WillOnce(testing::DoAll(
VerifyAddressBarUrl(&ie_mock_),
DelayGoBack(&ie_mock_, &loop_, base::TimeDelta())));
// We will reach anchor 1 once the navigation is complete,
// now go forward to anchor 2
// Back/Forward state at this point:
// Back: 2 (kAnchorUrl, kAnchor1Url)
// Forward: 2 (kAnchor2Url, kAnchor3Url)
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetAnchorPageUrl(1))))
.WillOnce(testing::DoAll(
VerifyAddressBarUrl(&ie_mock_),
DelayGoForward(&ie_mock_, &loop_, base::TimeDelta())));
// We have reached anchor 2, go forward to anchor 3 again
// Back/Forward state at this point:
// Back: 3 (kAnchorUrl, kAnchor1Url, kAnchor2Url)
// Forward: 1 (kAnchor3Url)
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetAnchorPageUrl(2))))
.WillOnce(testing::DoAll(
VerifyAddressBarUrl(&ie_mock_),
DelayGoForward(&ie_mock_, &loop_, base::TimeDelta())));
// We have gone a few steps back and forward, this should be enough for now.
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(GetAnchorPageUrl(3))))
.WillOnce(CloseBrowserMock(&ie_mock_));
LaunchIEAndNavigate(GetAnchorPageUrl(0));
}
// Test that a user cannot navigate to a restricted site and that the security
// dialog appears.
TEST_P(FullTabNavigationTest, RestrictedSite) {
// Add the server to restricted sites zone.
base::win::ScopedComPtr<IInternetSecurityManager> security_manager;
HRESULT hr = security_manager.CreateInstance(CLSID_InternetSecurityManager);
ASSERT_HRESULT_SUCCEEDED(hr);
hr = security_manager->SetZoneMapping(URLZONE_UNTRUSTED,
GetTestUrl(L"").c_str(), SZM_CREATE);
EXPECT_CALL(ie_mock_, OnFileDownload(_, _)).Times(testing::AnyNumber());
server_mock_.ExpectAndServeAnyRequests(GetParam());
MockWindowObserver win_observer_mock;
// If the page is loaded in mshtml, then IE allows the page to be loaded
// and just shows 'Restricted sites' in the status bar.
if (!GetParam().invokes_cf()) {
ie_mock_.ExpectNavigation(IN_IE, GetSimplePageUrl());
EXPECT_CALL(ie_mock_, OnLoad(IN_IE, StrEq(GetSimplePageUrl())))
.Times(1)
.WillOnce(CloseBrowserMock(&ie_mock_));
} else {
// If the page is being loaded in chrome frame then we will see
// a security dialog.
const char* kAlertDlgCaption = "Security Alert";
win_observer_mock.WatchWindow(kAlertDlgCaption, "");
EXPECT_CALL(ie_mock_, OnBeforeNavigate2(_, testing::Field(&VARIANT::bstrVal,
testing::HasSubstr(GetSimplePageUrl())), _, _, _, _, _))
.Times(testing::AtMost(2));
EXPECT_CALL(ie_mock_, OnNavigateComplete2(_,
testing::Field(&VARIANT::bstrVal, StrEq(GetSimplePageUrl()))))
.Times(testing::AtMost(1));
EXPECT_CALL(win_observer_mock, OnWindowOpen(_))
.Times(1)
.WillOnce(DoCloseWindow());
EXPECT_CALL(win_observer_mock, OnWindowClose(_))
.Times(1)
.WillOnce(CloseBrowserMock(&ie_mock_));
}
LaunchIEAndNavigate(GetSimplePageUrl());
ASSERT_HRESULT_SUCCEEDED(security_manager->SetZoneMapping(URLZONE_UNTRUSTED,
GetTestUrl(L"").c_str(), SZM_DELETE));
}
// This test checks if window.open calls with target blank issued for a
// different domain make it back to IE instead of completing the navigation
// within Chrome. We validate this by initiating a navigation to a non existent
// url which ensures we would get an error during navigation.
// Marking this disabled as it leaves behind Chrome processes, at least on
// IE 6 XP (http://crbug.com/48732).
TEST_P(FullTabNavigationTest, DISABLED_JavascriptWindowOpenDifferentDomain) {
if (!GetParam().invokes_cf() || GetInstalledIEVersion() == IE_7) {
LOG(ERROR) << "Test disabled for this configuration.";
return;
}
std::wstring parent_url = GetWindowOpenUrl(L"http://www.nonexistent.com");
MockAccEventObserver acc_observer;
MockIEEventSink new_window_mock;
ie_mock_.ExpectAnyNavigations();
new_window_mock.ExpectAnyNavigations();
server_mock_.ExpectAndServeAnyRequests(GetParam());
EXPECT_CALL(acc_observer, OnAccDocLoad(_)).Times(testing::AnyNumber());
EXPECT_CALL(ie_mock_, OnLoad(GetParam().invokes_cf(), StrEq(parent_url)));
EXPECT_CALL(acc_observer,
OnAccDocLoad(TabContentsTitleEq(parent_url,
GetWindowOpenTitle())))
.WillOnce(AccLeftClick(AccObjectMatcher()));
ie_mock_.ExpectNewWindow(&new_window_mock);
EXPECT_CALL(new_window_mock, OnNavigateError(_, _, _, _, _))
.Times(1)
.WillOnce(CloseBrowserMock(&new_window_mock));
EXPECT_CALL(new_window_mock, OnLoad(_, _))
.Times(testing::AtMost(1));
EXPECT_CALL(new_window_mock, OnQuit())
.Times(1)
.WillOnce(CloseBrowserMock(&ie_mock_));
// OnNavigateError can take a long time to fire.
LaunchIENavigateAndLoop(parent_url, kChromeFrameLongNavigationTimeout * 4);
ASSERT_TRUE(new_window_mock.event_sink()->web_browser2() != NULL);
}
// Tests that the parent window can successfully close its popup through
// the javascript close method.
TEST_P(FullTabNavigationTest, JavascriptWindowOpenCanClose) {
// 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;
}
std::wstring parent_url = GetWindowOpenUrl(L"simple.html");
MockAccEventObserver acc_observer;
MockIEEventSink new_window_mock;
ie_mock_.ExpectAnyNavigations();
new_window_mock.ExpectAnyNavigations();
server_mock_.ExpectAndServeAnyRequests(GetParam());
EXPECT_CALL(acc_observer, OnAccDocLoad(_)).Times(testing::AnyNumber());
// Tell the page to open the popup. Some versions of IE will prevent a popup
// unless a click is involved.
EXPECT_CALL(ie_mock_, OnLoad(GetParam().invokes_cf(), StrEq(parent_url)));
EXPECT_CALL(acc_observer,
OnAccDocLoad(TabContentsTitleEq(parent_url,
GetWindowOpenTitle())))
.WillOnce(AccLeftClick(AccObjectMatcher()));
ie_mock_.ExpectNewWindow(&new_window_mock);
EXPECT_CALL(new_window_mock, OnLoad(_, StrEq(GetSimplePageUrl())))
.Times(testing::AtMost(2))
.WillOnce(PostKeyMessageToRenderer(&ie_mock_, 'c')) // close the popup
.WillOnce(testing::Return());
EXPECT_CALL(new_window_mock, OnQuit())
.WillOnce(CloseBrowserMock(&ie_mock_));
LaunchIENavigateAndLoop(parent_url, kChromeFrameLongNavigationTimeout * 2);
}
// Parameter for tests using the NavigationTransitionTest fixture. Includes two
// pages, each with their own possible CF invocation.
struct NavigationTransitionTestParameter {
NavigationTransitionTestParameter(CFInvocation::Type type1,
CFInvocation::Type type2) {
page1_ = CFInvocation(type1);
page2_ = CFInvocation(type2);
}
CFInvocation page1_;
CFInvocation page2_;
};
// Parameterized test fixture for tests which test navigation transitions
// between two pages.
class NavigationTransitionTest
: public MockIEEventSinkTest,
public testing::TestWithParam<NavigationTransitionTestParameter> {
public:
NavigationTransitionTest() {}
virtual void SetUp() {
page1_ = GetParam().page1_;
page2_ = GetParam().page2_;
}
protected:
CFInvocation page1_;
CFInvocation page2_;
};
// This instantiates each parameterized test with some of the different CF
// invocation methods.
INSTANTIATE_TEST_CASE_P(
IEToIE,
NavigationTransitionTest,
testing::Values(NavigationTransitionTestParameter(
CFInvocation::NONE, CFInvocation::NONE)));
INSTANTIATE_TEST_CASE_P(
IEToMetaTag,
NavigationTransitionTest,
testing::Values(NavigationTransitionTestParameter(
CFInvocation::NONE, CFInvocation::META_TAG)));
INSTANTIATE_TEST_CASE_P(
IEToHttpHeader,
NavigationTransitionTest,
testing::Values(NavigationTransitionTestParameter(
CFInvocation::NONE, CFInvocation::HTTP_HEADER)));
INSTANTIATE_TEST_CASE_P(
CFToCF,
NavigationTransitionTest,
testing::Values(NavigationTransitionTestParameter(
CFInvocation::META_TAG, CFInvocation::META_TAG)));
INSTANTIATE_TEST_CASE_P(
CFToIE,
NavigationTransitionTest,
testing::Values(NavigationTransitionTestParameter(
CFInvocation::META_TAG, CFInvocation::NONE)));
// Test window.open calls.
TEST_P(NavigationTransitionTest, JavascriptWindowOpen) {
// 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;
}
std::wstring parent_url = GetWindowOpenUrl(L"simple.html");
std::wstring new_window_url = GetSimplePageUrl();
MockAccEventObserver acc_observer;
testing::StrictMock<MockIEEventSink> new_window_mock;
EXPECT_CALL(acc_observer, OnAccDocLoad(_)).Times(testing::AnyNumber());
ie_mock_.ExpectNavigation(page1_.invokes_cf(), parent_url);
server_mock_.ExpectAndServeRequest(page1_, parent_url);
EXPECT_CALL(ie_mock_, OnLoad(page1_.invokes_cf(), StrEq(parent_url)));
// Tell the page to open the popup. Some versions of IE will prevent a popup
// unless a click is involved.
EXPECT_CALL(acc_observer,
OnAccDocLoad(TabContentsTitleEq(parent_url,
GetWindowOpenTitle())))
.WillOnce(AccLeftClick(AccObjectMatcher()));
// If the parent window is in CF, the child should always load in CF since
// the domain is the same.
bool expect_cf = page1_.invokes_cf() || page2_.invokes_cf();
ie_mock_.ExpectNewWindow(&new_window_mock);
new_window_mock.ExpectJavascriptWindowOpenNavigation(page1_.invokes_cf(),
expect_cf,
new_window_url);
server_mock_.ExpectAndServeRequest(page2_, new_window_url);
EXPECT_CALL(new_window_mock, OnLoad(expect_cf, StrEq(new_window_url)))
.WillOnce(testing::DoAll(
ValidateWindowSize(&new_window_mock, 10, 10, 250, 250),
CloseBrowserMock(&new_window_mock)));
EXPECT_CALL(new_window_mock, OnQuit())
.WillOnce(CloseBrowserMock(&ie_mock_));
LaunchIENavigateAndLoop(parent_url, kChromeFrameLongNavigationTimeout * 2);
}
// Test redirection with window.location in Javascript.
// Disabled because crashes IE occasionally: http://crbug.com/48849.
TEST_P(NavigationTransitionTest, DISABLED_JavascriptRedirection) {
std::wstring redirect_url = GetTestUrl(L"javascript_redirect.html");
ie_mock_.ExpectNavigation(page1_.invokes_cf(), redirect_url);
server_mock_.ExpectAndServeRequest(page1_, redirect_url);
EXPECT_CALL(ie_mock_, OnLoad(page1_.invokes_cf(), StrEq(redirect_url)))
.WillOnce(VerifyAddressBarUrl(&ie_mock_));
ie_mock_.ExpectNavigation(page2_.invokes_cf(), GetSimplePageUrl());
server_mock_.ExpectAndServeRequest(page2_, GetSimplePageUrl());
EXPECT_CALL(ie_mock_, OnLoad(page2_.invokes_cf(), StrEq(GetSimplePageUrl())))
.WillOnce(testing::DoAll(
VerifyAddressBarUrl(&ie_mock_),
CloseBrowserMock(&ie_mock_)));
LaunchIEAndNavigate(redirect_url);
}
// Test following a link.
TEST_P(NavigationTransitionTest, FollowLink) {
if (page1_.invokes_cf() && page2_.invokes_cf()) {
// For some reason IE 7 and 8 send two BeforeNavigate events for the second
// page for this case. All versions do not send the OnLoad event for the
// second page if both pages are renderered in CF.
LOG(ERROR) << "Test disabled for this configuration.";
return;
}
MockAccEventObserver acc_observer;
EXPECT_CALL(acc_observer, OnAccDocLoad(_)).Times(testing::AnyNumber());
ie_mock_.ExpectNavigation(page1_.invokes_cf(), GetLinkPageUrl());
// Two requests are made when going from CF to IE, at least on Win7 IE8.
EXPECT_CALL(server_mock_, Get(_, UrlPathEq(GetLinkPageUrl()), _))
.Times(testing::Between(1, 2))
.WillRepeatedly(SendResponse(&server_mock_, page1_));
EXPECT_CALL(ie_mock_, OnLoad(page1_.invokes_cf(), StrEq(GetLinkPageUrl())));
EXPECT_CALL(acc_observer,
OnAccDocLoad(TabContentsTitleEq(GetLinkPageUrl(),
GetLinkPageTitle())))
.WillOnce(AccDoDefaultAction(AccObjectMatcher(L"", L"link")))
.RetiresOnSaturation();
ie_mock_.ExpectNavigation(page2_.invokes_cf(), GetSimplePageUrl());
server_mock_.ExpectAndServeRequest(page2_, GetSimplePageUrl());
EXPECT_CALL(ie_mock_, OnLoad(page2_.invokes_cf(), StrEq(GetSimplePageUrl())))
.WillOnce(testing::DoAll(
VerifyAddressBarUrl(&ie_mock_),
CloseBrowserMock(&ie_mock_)));
LaunchIEAndNavigate(GetLinkPageUrl());
}
// gMock matcher which tests if a url is blank.
MATCHER(BlankUrl, "is \"\" or NULL") {
return arg == NULL || wcslen(arg) == 0;
}
// Basic navigation test fixture which uses the MockIEEventSink. These tests
// are not parameterized.
class NavigationTest : public MockIEEventSinkTest, public testing::Test {
public:
NavigationTest() {}
void TestDisAllowedUrl(const wchar_t* url) {
// If a navigation fails then IE issues a navigation to an interstitial
// page. Catch this to track navigation errors as the NavigateError
// notification does not seem to fire reliably.
EXPECT_CALL(ie_mock_, OnBeforeNavigate2(_, testing::Field(&VARIANT::bstrVal,
StrEq(url)),
_, _, _, _, _));
EXPECT_CALL(ie_mock_, OnLoad(IN_IE, BlankUrl()))
.Times(testing::AtMost(1));
EXPECT_CALL(ie_mock_, OnBeforeNavigate2(_, testing::Field(&VARIANT::bstrVal,
testing::StartsWith(L"res:")),
_, _, _, _, _));
EXPECT_CALL(ie_mock_, OnFileDownload(VARIANT_TRUE, _))
.Times(testing::AnyNumber())
.WillRepeatedly(testing::Return());
EXPECT_CALL(ie_mock_, OnNavigateComplete2(_,
testing::Field(&VARIANT::bstrVal,
StrEq(url))));
// Although we expect a load event for this, we should never receive a
// corresponding GET request.
EXPECT_CALL(ie_mock_, OnLoad(IN_IE, StrEq(url)))
.WillOnce(CloseBrowserMock(&ie_mock_));
LaunchIEAndNavigate(url);
}
};
// Test navigation to a disallowed gcf: url with file scheme.
// Times out sporadically; http://crbug.com/119718.
TEST_F(NavigationTest, DISABLED_GcfProtocol1) {
// Make sure that we are not accidently enabling gcf protocol.
SetConfigBool(kAllowUnsafeURLs, false);
TestDisAllowedUrl(L"gcf:file:///C:/");
}
// Test navigation to a disallowed gcf: url with http scheme.
TEST_F(NavigationTest, GcfProtocol2) {
// Make sure that we are not accidently enabling gcf protocol.
SetConfigBool(kAllowUnsafeURLs, false);
TestDisAllowedUrl(L"gcf:http://www.google.com");
}
// Test navigation to a disallowed gcf: url with https scheme.
TEST_F(NavigationTest, GcfProtocol3) {
// Make sure that we are not accidently enabling gcf protocol.
SetConfigBool(kAllowUnsafeURLs, false);
TestDisAllowedUrl(L"gcf:https://www.google.com");
}
// NOTE: This test is currently disabled as we haven't finished implementing
// support for this yet. The test (as written) works fine for IE. CF might
// have a different set of requirements once we fully support this and hence
// the test might need some refining before being enabled.
TEST_F(NavigationTest, DISABLED_DownloadInNewWindow) {
MockIEEventSink new_window_mock;
std::wstring kDownloadFromNewWin =
GetTestUrl(L"full_tab_download_from_new_window.html");
ie_mock_.ExpectNavigation(IN_CF, kDownloadFromNewWin);
EXPECT_CALL(ie_mock_, OnNewWindow3(_, _, _, _, _));
EXPECT_CALL(ie_mock_, OnNewBrowserWindow(_, _))
.WillOnce(testing::WithArgs<0>(testing::Invoke(testing::CreateFunctor(
&new_window_mock, &MockIEEventSink::Attach))));
EXPECT_CALL(new_window_mock, OnBeforeNavigate2(_, _, _, _, _, _, _));
EXPECT_CALL(new_window_mock, OnFileDownload(VARIANT_FALSE, _))
.Times(2)
.WillRepeatedly(CloseBrowserMock(&new_window_mock));
EXPECT_CALL(new_window_mock, OnNavigateComplete2(_, _));
EXPECT_CALL(new_window_mock, OnQuit()).WillOnce(CloseBrowserMock(&ie_mock_));
LaunchIEAndNavigate(kDownloadFromNewWin);
}
// Flaky on ie6, http://crbug.com/255098.
TEST_P(FullTabNavigationTest, DISABLED_FormPostBackForward) {
bool in_cf = GetParam().invokes_cf();
// Navigate to the form-get.html page:
// - First set focus to chrome renderer window
// - Send over a character to the window.
// - This should initiate a form post which eventually navigates to the
// action.html page.
// Navigate backwards from the action.html page and then navigate forward
// from the form-get.html page.
std::wstring kFormPostUrl = GetTestUrl(L"form-get.html");
std::wstring kFormPostActionUrl =
GetTestUrl(L"action.html?field1=a&field2=b&submit=Submit");
std::wstring kFormPostTitle(L"ChromeFrame form submit test(GET method)");
MockAccEventObserver acc_observer;
server_mock_.ExpectAndServeAnyRequests(GetParam());
EXPECT_CALL(acc_observer, OnAccDocLoad(_)).Times(testing::AnyNumber());
EXPECT_CALL(acc_observer, OnAccDocLoad(TabContentsTitleEq(kFormPostUrl,
kFormPostTitle)))
.WillOnce(AccDoDefaultAction(AccObjectMatcher(L"Submit")))
.RetiresOnSaturation();
InSequence expect_in_sequence_for_scope;
ie_mock_.ExpectNavigation(in_cf, kFormPostUrl);
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(kFormPostUrl)));
ie_mock_.ExpectNavigationOptionalBefore(in_cf, kFormPostActionUrl);
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(kFormPostActionUrl)))
.WillOnce(testing::DoAll(
VerifyAddressBarUrl(&ie_mock_),
DelayGoBack(&ie_mock_, &loop_, base::TimeDelta())));
ie_mock_.ExpectNavigation(in_cf, kFormPostUrl);
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(kFormPostUrl)))
.WillOnce(testing::DoAll(
VerifyAddressBarUrl(&ie_mock_),
DelayGoForward(&ie_mock_, &loop_, base::TimeDelta())));
ie_mock_.ExpectNavigationOptionalBefore(in_cf, kFormPostActionUrl);
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(kFormPostActionUrl)))
.WillOnce(CloseBrowserMock(&ie_mock_));
LaunchIEAndNavigate(kFormPostUrl);
}
TEST_P(FullTabNavigationTest, CF_UnloadEventTest) {
bool in_cf = GetParam().invokes_cf();
if (!in_cf) {
LOG(ERROR) << "Test not yet implemented.";
return;
}
std::wstring kUnloadEventTestUrl =
GetTestUrl(L"fulltab_before_unload_event_test.html");
std::wstring kUnloadEventMainUrl =
GetTestUrl(L"fulltab_before_unload_event_main.html");
server_mock_.ExpectAndServeAnyRequests(GetParam());
InSequence expect_in_sequence_for_scope;
ie_mock_.ExpectNavigation(in_cf, kUnloadEventTestUrl);
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(kUnloadEventTestUrl)));
ie_mock_.ExpectNavigationOptionalBefore(in_cf, kUnloadEventMainUrl);
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(kUnloadEventMainUrl)));
EXPECT_CALL(ie_mock_, OnMessage(_, _, _))
.WillOnce(CloseBrowserMock(&ie_mock_));
LaunchIEAndNavigate(kUnloadEventTestUrl);
}
// Fixture for ChromeFrame download tests.
class FullTabDownloadTest
: public MockIEEventSinkTest, public testing::TestWithParam<CFInvocation> {
public:
FullTabDownloadTest() {}
};
void SaveOwnerWindow(HWND* owner_window, HWND window) {
*owner_window = GetWindow(window, GW_OWNER);
}
void CloseWindow(HWND* window) {
if (window)
PostMessage(*window, WM_CLOSE, 0, 0);
}
// See bug http://crbug.com/36694
// This test does the following:-
// Navigates IE to a URL which in ChromeFrame.
// Performs a top level form post in the document
// In response to the POST we send over an attachment via the
// content-disposition header.
// IE brings up a file open dialog in this context.
// We bring up the Save dialog via accessibility and save the file
// and validate that all is well.
TEST_F(FullTabDownloadTest, CF_DownloadFileFromPost) {
// 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) {
if (GetInstalledIEVersion() == IE_7) {
LOG(INFO) << "Not running test on Vista with IE7";
return;
} else if (GetInstalledIEVersion() == IE_9) {
LOG(INFO) << "Not running test on Vista/Windows 7 with IE9";
return;
}
}
chrome_frame_test::MockWindowObserver download_watcher;
download_watcher.WatchWindow("File Download", "");
chrome_frame_test::MockWindowObserver save_dialog_watcher;
save_dialog_watcher.WatchWindow("Save As", "");
testing::StrictMock<MockIEEventSink> download_window_mock;
EXPECT_CALL(server_mock_, Get(_, StrEq(L"/post_source.html"), _)).WillOnce(
SendFast(
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n",
"<html>"
"<head><meta http-equiv=\"x-ua-compatible\" content=\"chrome=1\" />"
" <script type=\"text/javascript\">"
" function onLoad() {"
" document.getElementById(\"myform\").submit();}</script></head>"
" <body onload=\"setTimeout(onLoad, 2000);\">"
" <form id=\"myform\" action=\"post_target.html\" method=\"POST\">"
"</form></body></html>"));
EXPECT_CALL(server_mock_, Post(_, StrEq(L"/post_target.html"), _))
.Times(2)
.WillRepeatedly(
SendFast(
"HTTP/1.1 200 OK\r\n"
"content-disposition: attachment;filename=\"hello.txt\"\r\n"
"Content-Type: application/text\r\n"
"Cache-Control: private\r\n",
"hello"));
// If you want to debug this action then you may need to
// SendMessage(parent_window, WM_NCACTIVATE, TRUE, 0);
// SendMessage(parent_window, WM_COMMAND, MAKEWPARAM(0x114B, BN_CLICKED),
// control_window);
// For the uninitiated, please debug IEFrame!CDialogActivateGuard::*
EXPECT_CALL(download_watcher, OnWindowOpen(_))
.Times(2)
.WillOnce(DelayAccDoDefaultAction(
AccObjectMatcher(L"Save", L"push button"),
1000))
.WillOnce(testing::Return());
EXPECT_CALL(download_watcher, OnWindowClose(_))
.Times(testing::AnyNumber());
std::wstring src_url = server_mock_.Resolve(L"/post_source.html");
std::wstring tgt_url = server_mock_.Resolve(L"/post_target.html");
EXPECT_CALL(ie_mock_, OnFileDownload(_, _)).Times(testing::AnyNumber());
EXPECT_CALL(ie_mock_, OnBeforeNavigate2(_,
testing::Field(&VARIANT::bstrVal,
StrEq(src_url)), _, _, _, _, _));
EXPECT_CALL(ie_mock_, OnNavigateComplete2(_,
testing::Field(&VARIANT::bstrVal,
StrEq(src_url))));
EXPECT_CALL(ie_mock_, OnLoad(true, StrEq(src_url)))
.Times(testing::AnyNumber());
ie_mock_.ExpectNewWindow(&download_window_mock);
EXPECT_CALL(ie_mock_, OnLoadError(StrEq(tgt_url)))
.Times(testing::AnyNumber());
EXPECT_CALL(download_window_mock, OnFileDownload(_, _))
.Times(testing::AnyNumber());
EXPECT_CALL(download_window_mock, OnLoadError(StrEq(tgt_url)))
.Times(testing::AtMost(1));
EXPECT_CALL(download_window_mock, OnBeforeNavigate2(_,
testing::Field(&VARIANT::bstrVal,
StrEq(tgt_url)), _, _, _, _, _));
EXPECT_CALL(download_window_mock, OnLoad(false, _));
EXPECT_CALL(download_window_mock, OnQuit()).Times(testing::AtMost(1));
base::FilePath temp_file_path;
ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
file_util::DieFileDie(temp_file_path, false);
temp_file_path = temp_file_path.ReplaceExtension(L"txt");
file_util::DieFileDie(temp_file_path, false);
AccObjectMatcher file_name_box(L"File name:", L"editable text");
HWND owner_window = NULL;
EXPECT_CALL(save_dialog_watcher, OnWindowOpen(_))
.WillOnce(testing::DoAll(
testing::Invoke(testing::CreateFunctor(
SaveOwnerWindow, &owner_window)),
AccSendCharMessage(file_name_box, L'a'),
AccSetValue(file_name_box, temp_file_path.value()),
AccDoDefaultAction(AccObjectMatcher(L"Save", L"push button"))));
EXPECT_CALL(save_dialog_watcher, OnWindowClose(_))
.WillOnce(testing::DoAll(
WaitForFileSave(temp_file_path, 3000),
testing::InvokeWithoutArgs(
testing::CreateFunctor(CloseWindow, &owner_window)),
CloseBrowserMock(&ie_mock_)));
LaunchIENavigateAndLoop(src_url, kChromeFrameVeryLongNavigationTimeout);
std::string data;
EXPECT_TRUE(base::ReadFileToString(temp_file_path, &data));
EXPECT_EQ("hello", data);
file_util::DieFileDie(temp_file_path, false);
}
// Test fixture for testing if http header works for supported content types
class HttpHeaderTest : public MockIEEventSinkTest, public testing::Test {
public:
HttpHeaderTest() {}
void HeaderTestWithData(const char* content_type, const char* data) {
const wchar_t* relative_url = L"/header_test";
const char* kHeaderFormat =
"HTTP/1.1 200 OK\r\n"
"Connection: close\r\n"
"Content-Type: %s\r\n"
"X-UA-Compatible: chrome=1\r\n";
std::string header = base::StringPrintf(kHeaderFormat, content_type);
std::wstring url = server_mock_.Resolve(relative_url);
EXPECT_CALL(server_mock_, Get(_, StrEq(relative_url), _))
.WillRepeatedly(SendFast(header, data));
InSequence expect_in_sequence_for_scope;
ie_mock_.ExpectNavigation(IN_CF, url);
EXPECT_CALL(ie_mock_, OnLoad(IN_CF, StrEq(url)))
.WillOnce(CloseBrowserMock(&ie_mock_));
LaunchIEAndNavigate(url);
}
};
const char* kXmlContent =
"<tree>"
"<node href=\"root.htm\" text=\"Root\">"
"<node href=\"child1.htm\" text=\"Child 1\" />"
"<node href=\"child2.htm\" text=\"Child 2\" />"
"</node>"
"</tree>";
TEST_F(HttpHeaderTest, ApplicationXhtml) {
HeaderTestWithData("application/xhtml+xml", kXmlContent);
}
TEST_F(HttpHeaderTest, ApplicationXml) {
HeaderTestWithData("application/xml", kXmlContent);
}
TEST_F(HttpHeaderTest, TextXml) {
HeaderTestWithData("text/xml", kXmlContent);
}
const char* kImageSvg =
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" "
"\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">"
"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"100%\" height=\"100%\">"
"<rect height=\"100\" width=\"300\" "
"style=\"fill:rgb(0,0,255);stroke-width:2;\"/>"
"</svg>";
TEST_F(HttpHeaderTest, DISABLED_ImageSvg) {
HeaderTestWithData("image/svg", kImageSvg);
}
TEST_F(HttpHeaderTest, ImageSvgXml) {
HeaderTestWithData("image/svg+xml", kImageSvg);
}
// Tests refreshing causes a page load.
TEST_P(FullTabNavigationTest, RefreshContents) {
bool in_cf = GetParam().invokes_cf();
if (!in_cf) {
VLOG(1) << "Disabled for this configuration";
return;
}
const char kHeaders[] =
"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n"
"X-UA-Compatible: chrome=1\r\nCache-control: no-cache\r\n";
const char kBody[] = "<html><body>Hi there. Got new content?"
"</body></html>";
std::wstring src_url = server_mock_.Resolve(L"/refresh_src.html");
EXPECT_CALL(server_mock_, Get(_, StrEq(L"/refresh_src.html"), _))
.Times(2)
.WillRepeatedly(SendFast(kHeaders, kBody));
EXPECT_CALL(ie_mock_, OnFileDownload(_, _)).Times(testing::AnyNumber());
EXPECT_CALL(ie_mock_,
OnBeforeNavigate2(_, testing::Field(&VARIANT::bstrVal,
StrEq(src_url)),
_, _, _, _, _));
EXPECT_CALL(ie_mock_,
OnNavigateComplete2(_, testing::Field(&VARIANT::bstrVal,
StrEq(src_url))));
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(src_url)))
.Times(2)
.WillOnce(DelayRefresh(
&ie_mock_, &loop_, base::TimeDelta::FromMilliseconds(50)))
.WillOnce(CloseBrowserMock(&ie_mock_));
LaunchIENavigateAndLoop(src_url, kChromeFrameVeryLongNavigationTimeout);
}
class FullTabSeleniumTest
: public MockIEEventSinkTest, public testing::TestWithParam<CFInvocation> {
public:
FullTabSeleniumTest()
: MockIEEventSinkTest(1337, L"127.0.0.1", GetSeleniumTestFolder()) {}
};
ACTION(VerifySeleniumCoreTestResults) {
int num_tests = 0;
int failed_tests = 0;
swscanf(arg0, L"%d/%d", &num_tests, &failed_tests);
// Currently we run total 505 tests and 8 steps fail.
// TODO(amit): send results as JSON, diagnose and eliminate failures.
EXPECT_LE(failed_tests, 15) << "Expected failures: " << 15 <<
" Actual failures: " << failed_tests;
EXPECT_GE(num_tests, 500) << "Expected to run: " << 500 << " tests." <<
" Actual number of tests run: " << num_tests;
}
// Crashes flakily: http://crbug.com/109114
// Tests refreshing causes a page load.
TEST_F(FullTabSeleniumTest, DISABLED_Core) {
// 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::HttpHeader());
std::wstring url = GetTestUrl(L"core/TestRunner.html");
// Expectations for TestRunner.html
EXPECT_CALL(ie_mock_, OnFileDownload(_, _)).Times(testing::AnyNumber());
EXPECT_CALL(ie_mock_, OnBeforeNavigate2(_,
testing::Field(&VARIANT::bstrVal,
testing::StartsWith(url)), _, _, _, _, _))
.Times(testing::AnyNumber());
EXPECT_CALL(ie_mock_, OnNavigateComplete2(_,
testing::Field(&VARIANT::bstrVal,
testing::StartsWith(url))))
.Times(testing::AnyNumber());
EXPECT_CALL(ie_mock_, OnLoad(true, testing::StartsWith(url)))
.Times(testing::AnyNumber());
// Expectation for cookie test
EXPECT_CALL(ie_mock_, OnLoadError(testing::StartsWith(url)))
.Times(testing::AtMost(3));
// Expectations for popups
std::wstring attach_url_prefix = GetTestUrl(L"?attach_external_tab&");
EXPECT_CALL(ie_mock_, OnNewWindow3(_, _, _, _,
testing::StartsWith(attach_url_prefix)))
.Times(testing::AnyNumber());
EXPECT_CALL(ie_mock_, OnNewBrowserWindow(_,
testing::StartsWith(attach_url_prefix)))
.Times(testing::AnyNumber());
// At the end the tests will post us a message. See _onTestSuiteComplete in
// ...\src\data\selenium_core\core\scripts\selenium-testrunner.js
EXPECT_CALL(ie_mock_, OnMessage(_, _, _))
.WillOnce(testing::DoAll(VerifySeleniumCoreTestResults(),
CloseBrowserMock(&ie_mock_)));
// Selenium tests take longer to finish, lets give it 2 mins.
const base::TimeDelta kSeleniumTestTimeout = base::TimeDelta::FromMinutes(2);
LaunchIENavigateAndLoop(url, kSeleniumTestTimeout);
}
// See bug http://code.google.com/p/chromium/issues/detail?id=64901
// This test does the following:-
// Navigates IE to a non ChromeFrame URL.
// Performs a top level form post in the document
// In response to the POST send over a html document containing a meta tag
// This would cause IE to switch to ChromeFrame.
// Refresh the page in ChromeFrame.
// This should bring up a confirmation dialog which we hit yes on. This should
// reissue the top level post request in response to which the html content
// containing the meta tag is sent again.
TEST_F(FullTabDownloadTest, TopLevelPostReissueFromChromeFramePage) {
chrome_frame_test::MockWindowObserver post_reissue_watcher;
post_reissue_watcher.WatchWindow("Confirm Form Resubmission", "");
EXPECT_CALL(server_mock_, Get(_, StrEq(L"/post_source.html"), _))
.WillOnce(SendFast(
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n",
"<html>"
"<head>"
" <script type=\"text/javascript\">"
" function onLoad() {"
" document.getElementById(\"myform\").submit();}</script></head>"
" <body onload=\"setTimeout(onLoad, 2000);\">"
" <form id=\"myform\" action=\"post_target.html\" method=\"POST\">"
"</form></body></html>"));
EXPECT_CALL(server_mock_, Post(_, StrEq(L"/post_target.html"), _))
.Times(2)
.WillRepeatedly(
SendFast(
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n",
"<html>"
"<head><meta http-equiv=\"x-ua-compatible\" content=\"chrome=1\" />"
"</head>"
"<body> Target page in ChromeFrame </body>"
"</html>"));
EXPECT_CALL(post_reissue_watcher, OnWindowOpen(_))
.WillOnce(DelayAccDoDefaultAction(
AccObjectMatcher(L"Yes", L"push button"),
1000));
EXPECT_CALL(post_reissue_watcher, OnWindowClose(_));
std::wstring src_url = server_mock_.Resolve(L"/post_source.html");
std::wstring tgt_url = server_mock_.Resolve(L"/post_target.html");
EXPECT_CALL(ie_mock_, OnFileDownload(_, _)).Times(testing::AnyNumber());
EXPECT_CALL(ie_mock_, OnBeforeNavigate2(_,
testing::Field(&VARIANT::bstrVal,
StrEq(src_url)), _, _, _, _, _));
EXPECT_CALL(ie_mock_, OnNavigateComplete2(_,
testing::Field(&VARIANT::bstrVal,
StrEq(src_url))));
EXPECT_CALL(ie_mock_, OnLoad(false, StrEq(src_url)));
EXPECT_CALL(ie_mock_, OnLoad(true, StrEq(tgt_url)))
.Times(2)
.WillOnce(DelayRefresh(
&ie_mock_, &loop_, base::TimeDelta::FromMilliseconds(50)))
.WillOnce(CloseBrowserMock(&ie_mock_));
EXPECT_CALL(ie_mock_, OnBeforeNavigate2(_,
testing::Field(&VARIANT::bstrVal,
StrEq(tgt_url)), _, _, _, _, _))
.Times(2);
EXPECT_CALL(ie_mock_, OnNavigateComplete2(_,
testing::Field(&VARIANT::bstrVal,
StrEq(tgt_url))))
.Times(2);
LaunchIENavigateAndLoop(src_url, kChromeFrameVeryLongNavigationTimeout);
}
MATCHER_P(UserAgentHeaderMatcher, ua_string, "") {
std::string headers = arg.headers();
StringToUpperASCII(&headers);
std::string ua_string_to_search = ua_string;
StringToUpperASCII(&ua_string_to_search);
net::HttpUtil::HeadersIterator it(headers.begin(), headers.end(),
"\r\n");
while (it.GetNext()) {
if (lstrcmpiA(it.name().c_str(), "User-Agent") == 0) {
if (it.values().find(ua_string_to_search) != std::string::npos)
return true;
}
}
return false;
}
// Tests refreshing causes a page load and that the chrome frame user agent
// string is appended to the UA in the incoming top level HTTP requests.
TEST_P(FullTabNavigationTest, RefreshContentsUATest) {
const char kBody[] = "<html><head></head>"
"<body>Hi there. Got new content?"
"</body></html>";
std::string headers = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n"
"Cache-control: no-cache\r\n";
bool in_cf = GetParam().invokes_cf();
if (in_cf) {
headers.append("X-UA-Compatible: chrome=1\r\n");
} else {
if (GetInstalledIEVersion() == IE_9) {
LOG(ERROR) << "Test disabled for IE9";
return;
}
}
std::wstring src_url = server_mock_.Resolve(L"/refresh_src.html");
if (in_cf) {
// In the case of Chrome Frame, end the test when the second OnLoad is
// fired.
EXPECT_CALL(server_mock_, Get(_, StrEq(L"/refresh_src.html"),
UserAgentHeaderMatcher("chromeframe")))
.Times(2)
.WillRepeatedly(SendFast(headers, kBody));
} else {
// In the case of IE, we never receive a second OnLoad event, so end the
// test when the second request is made on the server.
EXPECT_CALL(server_mock_, Get(_, StrEq(L"/refresh_src.html"),
UserAgentHeaderMatcher("chromeframe")))
.Times(2)
.WillOnce(SendFast(headers, kBody))
.WillOnce(testing::DoAll(
SendFast(headers, kBody),
CloseBrowserMock(&ie_mock_)));
}
EXPECT_CALL(ie_mock_, OnFileDownload(_, _)).Times(testing::AnyNumber());
EXPECT_CALL(ie_mock_,
OnBeforeNavigate2(_, testing::Field(&VARIANT::bstrVal,
StrEq(src_url)),
_, _, _, _, _));
EXPECT_CALL(ie_mock_,
OnNavigateComplete2(_, testing::Field(&VARIANT::bstrVal,
StrEq(src_url))));
if (in_cf) {
// As mentioned above, end the test once the refreshed document is loaded.
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(src_url)))
.Times(2)
.WillOnce(DelayRefresh(
&ie_mock_, &loop_, base::TimeDelta::FromMilliseconds(50)))
.WillOnce(CloseBrowserMock(&ie_mock_));
} else {
// As mentioned above, we only receive an OnLoad for the intial load, not
// for the refresh.
EXPECT_CALL(ie_mock_, OnLoad(in_cf, StrEq(src_url)))
.WillOnce(DelayRefresh(
&ie_mock_, &loop_, base::TimeDelta::FromMilliseconds(50)));
}
LaunchIENavigateAndLoop(src_url, kChromeFrameVeryLongNavigationTimeout);
}
// Link navigations in the same domain specified with the noreferrer flag
// should be opened in the host browser.
TEST_F(FullTabNavigationTest, JavascriptWindowOpenNoReferrerOpensInHost) {
// 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;
}
MockAccEventObserver acc_observer;
EXPECT_CALL(acc_observer, OnAccDocLoad(_)).Times(testing::AnyNumber());
testing::StrictMock<MockIEEventSink> new_window_mock;
testing::StrictMock<MockIEEventSink>
no_referrer_target_opener_window_mock;
std::wstring initial_url =
GetWindowOpenUrl(L"open_href_target_no_referrer.html");
std::wstring parent_url = GetTestUrl(
L"open_href_target_no_referrer.html");
std::wstring new_window_url = GetSimplePageUrl();
ie_mock_.ExpectNavigation(false, initial_url);
EXPECT_CALL(ie_mock_, OnLoad(false, StrEq(initial_url)));
EXPECT_CALL(acc_observer,
OnAccDocLoad(TabContentsTitleEq(initial_url,
GetWindowOpenTitle())))
.WillOnce(AccLeftClick(AccObjectMatcher()))
.RetiresOnSaturation();
ie_mock_.ExpectNewWindow(&no_referrer_target_opener_window_mock);
no_referrer_target_opener_window_mock.ExpectNavigation(true, parent_url);
server_mock_.ExpectAndServeRequest(CFInvocation::MetaTag(), parent_url);
server_mock_.ExpectAndServeRequest(CFInvocation::None(), new_window_url);
server_mock_.ExpectAndServeRequest(CFInvocation::None(), initial_url);
EXPECT_CALL(no_referrer_target_opener_window_mock,
OnLoad(false, StrEq(parent_url)))
.Times(testing::AnyNumber());
EXPECT_CALL(no_referrer_target_opener_window_mock,
OnLoad(true, StrEq(parent_url)))
.WillOnce(DelayAccDoDefaultActionInRenderer(
&no_referrer_target_opener_window_mock,
AccObjectMatcher(L"", L"link"), 1000));
// The parent window is in CF and opens a child window with the no referrer
// flag in which case it should open in IE.
no_referrer_target_opener_window_mock.ExpectNewWindow(&new_window_mock);
new_window_mock.ExpectNavigation(false, new_window_url);
EXPECT_CALL(new_window_mock, OnFileDownload(_, _))
.Times(testing::AnyNumber());
EXPECT_CALL(new_window_mock,
OnBeforeNavigate2(_, testing::Field(&VARIANT::bstrVal,
testing::HasSubstr(L"attach")),
_, _, _, _, _));
EXPECT_CALL(new_window_mock,
OnNavigateComplete2(_, testing::Field(&VARIANT::bstrVal,
testing::HasSubstr(L"attach"))))
.Times(testing::AtMost(1));
EXPECT_CALL(new_window_mock, OnLoad(false, StrEq(new_window_url)))
.WillOnce(CloseBrowserMock(&new_window_mock));
EXPECT_CALL(new_window_mock, OnQuit())
.WillOnce(CloseBrowserMock(
&no_referrer_target_opener_window_mock));
EXPECT_CALL(no_referrer_target_opener_window_mock, OnQuit())
.WillOnce(CloseBrowserMock(&ie_mock_));
LaunchIENavigateAndLoop(initial_url, kChromeFrameVeryLongNavigationTimeout);
}
} // namespace chrome_frame_test