summaryrefslogtreecommitdiffstats
path: root/chrome_frame
diff options
context:
space:
mode:
authoramit@chromium.org <amit@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-03 17:24:29 +0000
committeramit@chromium.org <amit@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-03 17:24:29 +0000
commit552fb601aa696cc69de9fbf69f17438ac1f6f3a9 (patch)
tree1b800a99dff7facce52bb5423a056a6e1ff4356a /chrome_frame
parent9a30588cd1081b702ade98be4eb4a7c1344bb43e (diff)
downloadchromium_src-552fb601aa696cc69de9fbf69f17438ac1f6f3a9.zip
chromium_src-552fb601aa696cc69de9fbf69f17438ac1f6f3a9.tar.gz
chromium_src-552fb601aa696cc69de9fbf69f17438ac1f6f3a9.tar.bz2
Remove cf: protocol
Well, almost. cf: is now changed to gcf: protocol. gcf: protocol now is supported only for the following cases: 1. gcf:attach_external_tabXXX urls. These are URLs used internally by Chrome Frame to implement window.open 2. gcf:about:xxx 3. gcf:view-source:xxx 4 For any other URLs ONLY if it is enabled by setting a registry value 'EnableGCFProtocol' to 1 in HKCU\Software\Google\ChromeFrame BUG=22721,23006,23175,29350 TEST=changed existing cf: tests to new gcf: tests, added a new test for cf:view-source Review URL: http://codereview.chromium.org/562008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37981 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame')
-rw-r--r--chrome_frame/chrome_active_document.cc17
-rw-r--r--chrome_frame/chrome_active_document.h4
-rw-r--r--chrome_frame/chrome_frame_activex_base.h16
-rw-r--r--chrome_frame/chrome_protocol.rgs2
-rw-r--r--chrome_frame/chrome_tab.cc26
-rw-r--r--chrome_frame/test/chrome_frame_test_utils.cc52
-rw-r--r--chrome_frame/test/chrome_frame_test_utils.h37
-rw-r--r--chrome_frame/test/chrome_frame_unittests.cc133
-rw-r--r--chrome_frame/test/data/cf_protocol.html2
-rw-r--r--chrome_frame/test/data/chrome_frame_tester_helpers.js2
-rw-r--r--chrome_frame/test/data/navigate_out.html2
-rw-r--r--chrome_frame/test/reliability/page_load_test.cc8
-rw-r--r--chrome_frame/utils.cc3
-rw-r--r--chrome_frame/utils.h4
14 files changed, 249 insertions, 59 deletions
diff --git a/chrome_frame/chrome_active_document.cc b/chrome_frame/chrome_active_document.cc
index 202128b..091f0ba 100644
--- a/chrome_frame/chrome_active_document.cc
+++ b/chrome_frame/chrome_active_document.cc
@@ -40,8 +40,7 @@
const wchar_t kChromeAttachExternalTabPrefix[] = L"attach_external_tab";
static const wchar_t kUseChromeNetworking[] = L"UseChromeNetworking";
-static const wchar_t kHandleTopLevelRequests[] =
- L"HandleTopLevelRequests";
+static const wchar_t kHandleTopLevelRequests[] = L"HandleTopLevelRequests";
DEFINE_GUID(CGID_DocHostCmdPriv, 0x000214D4L, 0, 0, 0xC0, 0, 0, 0, 0, 0, 0,
0x46);
@@ -821,6 +820,20 @@ bool ChromeActiveDocument::ParseUrl(const std::wstring& url,
return false;
}
+ if (*is_chrome_protocol) {
+ // Allow chrome protocol (gcf:) if -
+ // - explicitly enabled using registry
+ // - for gcf:attach_external_tab
+ // - for gcf:about and gcf:view-source
+ GURL crack_url(initial_url);
+ bool allow_gcf_protocol = !*is_new_navigation ||
+ GetConfigBool(false, kEnableGCFProtocol) ||
+ crack_url.SchemeIs(chrome::kAboutScheme) ||
+ crack_url.SchemeIs(chrome::kViewSourceScheme);
+ if (!allow_gcf_protocol)
+ return false;
+ }
+
*parsed_url = initial_url;
return true;
}
diff --git a/chrome_frame/chrome_active_document.h b/chrome_frame/chrome_active_document.h
index dc6511d..eed38e7 100644
--- a/chrome_frame/chrome_active_document.h
+++ b/chrome_frame/chrome_active_document.h
@@ -47,8 +47,6 @@ class ChromeActiveDocument;
// current travel log entry
#define INTERNAL_CMDID_REPLACE_CURRENT_TRAVEL_LOG_ENTRY_URL (40)
-#define INTERNAL_IE_CONTEXTMENU_VIEWSOURCE (2139)
-
#ifndef SBCMDID_MIXEDZONE
// This command is sent by the frame to allow the document to return the URL
// security zone for display.
@@ -157,7 +155,7 @@ BEGIN_EXEC_COMMAND_MAP(ChromeActiveDocument)
EXEC_COMMAND_HANDLER_GENERIC(OLECMDID_PRINT, automation_client_->PrintTab())
EXEC_COMMAND_HANDLER_NO_ARGS(OLECMDID_FIND, OnFindInPage)
EXEC_COMMAND_HANDLER_NO_ARGS(IDM_FIND, OnFindInPage)
- EXEC_COMMAND_HANDLER_NO_ARGS(INTERNAL_IE_CONTEXTMENU_VIEWSOURCE, OnViewSource)
+ EXEC_COMMAND_HANDLER_NO_ARGS(IDM_VIEWSOURCE, OnViewSource)
FORWARD_TAB_COMMAND(OLECMDID_SELECTALL, SelectAll)
FORWARD_TAB_COMMAND(OLECMDID_CUT, Cut)
FORWARD_TAB_COMMAND(OLECMDID_COPY, Copy)
diff --git a/chrome_frame/chrome_frame_activex_base.h b/chrome_frame/chrome_frame_activex_base.h
index af71a11..fe11b66 100644
--- a/chrome_frame/chrome_frame_activex_base.h
+++ b/chrome_frame/chrome_frame_activex_base.h
@@ -41,6 +41,7 @@
#include "chrome_frame/com_message_event.h"
#include "chrome_frame/com_type_info_holder.h"
#include "chrome_frame/urlmon_url_request.h"
+#include "chrome/common/url_constants.h"
#include "grit/generated_resources.h"
#include "net/base/cookie_monster.h"
@@ -387,12 +388,13 @@ END_MSG_MAP()
// Check to see if the URL uses a "view-source:" prefix, if so, open it
// using chrome frame full tab mode by using 'cf:' protocol handler.
// Also change the disposition to NEW_WINDOW since IE6 doesn't have tabs.
- if (url_to_open.has_scheme() && (url_to_open.SchemeIs("view-source") ||
- url_to_open.SchemeIs("about"))) {
- std::string chrome_url;
- chrome_url.append("cf:");
- chrome_url.append(url_to_open.spec());
- url.Set(UTF8ToWide(chrome_url).c_str());
+ if (url_to_open.has_scheme() &&
+ (url_to_open.SchemeIs(chrome::kViewSourceScheme) ||
+ url_to_open.SchemeIs(chrome::kAboutScheme))) {
+ std::wstring chrome_url;
+ chrome_url.append(kChromeProtocolPrefix);
+ chrome_url.append(UTF8ToWide(url_to_open.spec()));
+ url.Set(chrome_url.c_str());
open_disposition = NEW_WINDOW;
} else {
url.Set(UTF8ToWide(url_to_open.spec()).c_str());
@@ -506,7 +508,7 @@ END_MSG_MAP()
intptr_t cookie,
int disposition) {
std::string url;
- url = StringPrintf("cf:attach_external_tab&%d&%d",
+ url = StringPrintf("%lsattach_external_tab&%d&%d", kChromeProtocolPrefix,
cookie, disposition);
OnOpenURL(tab_handle, GURL(url), GURL(), disposition);
}
diff --git a/chrome_frame/chrome_protocol.rgs b/chrome_frame/chrome_protocol.rgs
index de6a3e2..9546973 100644
--- a/chrome_frame/chrome_protocol.rgs
+++ b/chrome_frame/chrome_protocol.rgs
@@ -29,7 +29,7 @@ HKLM {
NoRemove Classes {
NoRemove Protocols {
NoRemove Handler {
- NoRemove 'cf' {
+ 'gcf' {
val CLSID = s '{9875BFAF-B04D-445E-8A69-BE36838CDE3E}'
}
}
diff --git a/chrome_frame/chrome_tab.cc b/chrome_frame/chrome_tab.cc
index 9944f5b..301d9f8 100644
--- a/chrome_frame/chrome_tab.cc
+++ b/chrome_frame/chrome_tab.cc
@@ -40,6 +40,9 @@ static const wchar_t kBhoRegistryPath[] =
const wchar_t kInternetSettings[] =
L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
+const wchar_t kProtocolHandlers[] =
+ L"Software\\Classes\\Protocols\\Handler";
+
const wchar_t kBhoNoLoadExplorerValue[] = L"NoExplorer";
// {0562BFC3-2550-45b4-BD8E-A310583D3A6F}
@@ -236,7 +239,6 @@ HRESULT RegisterChromeTabBHO() {
DLOG(INFO) << "Registered ChromeTab BHO";
// We now add the chromeframe user agent at runtime.
- // SetClockUserAgent(L"1");
RefreshElevationPolicy();
return S_OK;
}
@@ -270,6 +272,26 @@ HRESULT UnregisterChromeTabBHO() {
return S_OK;
}
+HRESULT CleanupCFProtocol() {
+ RegKey protocol_handlers_key;
+ if (protocol_handlers_key.Open(HKEY_LOCAL_MACHINE, kProtocolHandlers,
+ KEY_READ | KEY_WRITE)) {
+ RegKey cf_protocol_key;
+ if (cf_protocol_key.Open(protocol_handlers_key.Handle(), L"cf",
+ KEY_QUERY_VALUE)) {
+ std::wstring protocol_clsid_string;
+ if (cf_protocol_key.ReadValue(L"CLSID", &protocol_clsid_string)) {
+ CLSID protocol_clsid = {0};
+ IIDFromString(protocol_clsid_string.c_str(), &protocol_clsid);
+ if (IsEqualGUID(protocol_clsid, CLSID_ChromeProtocol))
+ protocol_handlers_key.DeleteKey(L"cf");
+ }
+ }
+ }
+
+ return S_OK;
+}
+
// Used to determine whether the DLL can be unloaded by OLE
STDAPI DllCanUnloadNow() {
return _AtlModule.DllCanUnloadNow();
@@ -323,6 +345,8 @@ STDAPI DllUnregisterServer() {
hr = _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_NPAPI, FALSE);
}
+ // TODO(joshia): Remove after 2 refresh releases
+ CleanupCFProtocol();
return hr;
}
diff --git a/chrome_frame/test/chrome_frame_test_utils.cc b/chrome_frame/test/chrome_frame_test_utils.cc
index faee92a..0b8176d 100644
--- a/chrome_frame/test/chrome_frame_test_utils.cc
+++ b/chrome_frame/test/chrome_frame_test_utils.cc
@@ -690,6 +690,13 @@ _ATL_FUNC_INFO WebBrowserEventSink::kBeforeNavigate2Info = {
}
};
+_ATL_FUNC_INFO WebBrowserEventSink::kNewWindow2Info = {
+ CC_STDCALL, VT_EMPTY, 2, {
+ VT_DISPATCH | VT_BYREF,
+ VT_BOOL | VT_BYREF,
+ }
+};
+
_ATL_FUNC_INFO WebBrowserEventSink::kNewWindow3Info = {
CC_STDCALL, VT_EMPTY, 5, {
VT_DISPATCH | VT_BYREF,
@@ -711,6 +718,15 @@ _ATL_FUNC_INFO WebBrowserEventSink::kDocumentCompleteInfo = {
};
// WebBrowserEventSink member defines
+void WebBrowserEventSink::Attach(IDispatch* browser_disp) {
+ EXPECT_TRUE(NULL != browser_disp);
+ if(browser_disp) {
+ EXPECT_HRESULT_SUCCEEDED(web_browser2_.QueryFrom(browser_disp));
+ EXPECT_TRUE(S_OK == DispEventAdvise(web_browser2_,
+ &DIID_DWebBrowserEvents2));
+ }
+}
+
void WebBrowserEventSink::Uninitialize() {
DisconnectFromChromeFrame();
if (web_browser2_.get()) {
@@ -745,6 +761,34 @@ STDMETHODIMP_(void) WebBrowserEventSink::OnDocumentCompleteInternal(
OnDocumentComplete(dispatch, url);
}
+STDMETHODIMP_(void) WebBrowserEventSink::OnNewWindow3Internal(
+ IDispatch** dispatch, VARIANT_BOOL* cancel, DWORD flags, BSTR url_context,
+ BSTR url) {
+ DLOG(INFO) << __FUNCTION__;
+ if (!dispatch) {
+ NOTREACHED() << "Invalid argument - dispatch";
+ return;
+ }
+
+ // Call the OnNewWindow3 with original args
+ OnNewWindow3(dispatch, cancel, flags, url_context, url);
+
+ // Note that |dispatch| is an [in/out] argument. IE is asking listeners if
+ // they want to use a IWebBrowser2 of their choice for the new window.
+ // Since we need to listen on events on the new browser, we create one
+ // if needed.
+ if (!*dispatch) {
+ ScopedComPtr<IDispatch> new_browser;
+ HRESULT hr = new_browser.CreateInstance(CLSID_InternetExplorer, NULL,
+ CLSCTX_LOCAL_SERVER);
+ DCHECK(SUCCEEDED(hr) && new_browser);
+ *dispatch = new_browser.Detach();
+ }
+
+ if (*dispatch)
+ OnNewBrowserWindow(*dispatch, url);
+}
+
HRESULT WebBrowserEventSink::OnLoadInternal(const VARIANT* param) {
DLOG(INFO) << __FUNCTION__ << " " << param->bstrVal;
OnLoad(param->bstrVal);
@@ -788,14 +832,12 @@ HRESULT WebBrowserEventSink::Navigate(const std::wstring& navigate_url) {
}
void WebBrowserEventSink::SetFocusToChrome() {
- chrome_frame_test::SetKeyboardFocusToWindow(
- GetAttachedChromeRendererWindow(), 1, 1);
+ chrome_frame_test::SetKeyboardFocusToWindow(GetTabWindow(), 1, 1);
}
void WebBrowserEventSink::SendInputToChrome(
const std::string& input_string) {
- chrome_frame_test::SendInputToWindow(
- GetAttachedChromeRendererWindow(), input_string);
+ chrome_frame_test::SendInputToWindow(GetTabWindow(), input_string);
}
void WebBrowserEventSink::ConnectToChromeFrame() {
@@ -833,7 +875,7 @@ void WebBrowserEventSink::DisconnectFromChromeFrame() {
}
}
-HWND WebBrowserEventSink::GetAttachedChromeRendererWindow() {
+HWND WebBrowserEventSink::GetTabWindow() {
DCHECK(chrome_frame_);
HWND renderer_window = NULL;
ScopedComPtr<IOleWindow> ole_window;
diff --git a/chrome_frame/test/chrome_frame_test_utils.h b/chrome_frame/test/chrome_frame_test_utils.h
index 57e356c..1cc6e82 100644
--- a/chrome_frame/test/chrome_frame_test_utils.h
+++ b/chrome_frame/test/chrome_frame_test_utils.h
@@ -177,6 +177,7 @@ class WebBrowserEventSink
Uninitialize();
}
+ void Attach(IDispatch* browser_disp);
void Uninitialize();
// Helper function to launch IE and navigate to a URL.
@@ -205,8 +206,10 @@ BEGIN_SINK_MAP(WebBrowserEventSink)
OnNavigateComplete2Internal, &kNavigateComplete2Info)
SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_NAVIGATEERROR,
OnNavigateError, &kNavigateErrorInfo)
+ SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_NEWWINDOW2,
+ OnNewWindow2, &kNewWindow2Info)
SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_NEWWINDOW3,
- OnNewWindow3, &kNewWindow3Info)
+ OnNewWindow3Internal, &kNewWindow3Info)
SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE,
OnDocumentCompleteInternal, &kDocumentCompleteInfo)
END_SINK_MAP()
@@ -224,21 +227,11 @@ END_SINK_MAP()
return S_OK;
}
- STDMETHOD(OnBeforeNavigate2Internal)(IDispatch* dispatch, VARIANT* url,
- VARIANT* flags,
- VARIANT* target_frame_name,
- VARIANT* post_data, VARIANT* headers,
- VARIANT_BOOL* cancel);
STDMETHOD_(void, OnDownloadBegin)() {}
- STDMETHOD_(void, OnNavigateComplete2Internal)(IDispatch* dispatch,
- VARIANT* url);
STDMETHOD_(void, OnNavigateComplete2)(IDispatch* dispatch, VARIANT* url) {}
- STDMETHOD_(void, OnNewWindow3)(IDispatch** dispatch, VARIANT_BOOL* Cancel,
+ STDMETHOD_(void, OnNewWindow2)(IDispatch** dispatch, VARIANT_BOOL* cancel) {}
+ STDMETHOD_(void, OnNewWindow3)(IDispatch** dispatch, VARIANT_BOOL* cancel,
DWORD flags, BSTR url_context, BSTR url) {}
-
- STDMETHOD_(void, OnDocumentCompleteInternal)(IDispatch* dispatch,
- VARIANT* url);
-
STDMETHOD_(void, OnDocumentComplete)(IDispatch* dispatch,
VARIANT* url) {}
#ifdef _DEBUG
@@ -260,9 +253,24 @@ END_SINK_MAP()
return web_browser2_.get();
}
+ virtual void OnNewBrowserWindow(IDispatch* new_window, const wchar_t* url) {}
+
HRESULT SetWebBrowser(IWebBrowser2* web_browser2);
protected:
+ STDMETHOD(OnBeforeNavigate2Internal)(IDispatch* dispatch, VARIANT* url,
+ VARIANT* flags,
+ VARIANT* target_frame_name,
+ VARIANT* post_data, VARIANT* headers,
+ VARIANT_BOOL* cancel);
+ STDMETHOD_(void, OnNavigateComplete2Internal)(IDispatch* dispatch,
+ VARIANT* url);
+ STDMETHOD_(void, OnDocumentCompleteInternal)(IDispatch* dispatch,
+ VARIANT* url);
+ STDMETHOD_(void, OnNewWindow3Internal)(IDispatch** dispatch,
+ VARIANT_BOOL* Cancel, DWORD flags,
+ BSTR url_context, BSTR url);
+
// IChromeFrame callbacks
HRESULT OnLoadInternal(const VARIANT* param);
HRESULT OnLoadErrorInternal(const VARIANT* param);
@@ -270,7 +278,7 @@ END_SINK_MAP()
void ConnectToChromeFrame();
void DisconnectFromChromeFrame();
- HWND GetAttachedChromeRendererWindow();
+ HWND GetTabWindow();
public:
ScopedComPtr<IWebBrowser2> web_browser2_;
@@ -283,6 +291,7 @@ END_SINK_MAP()
static _ATL_FUNC_INFO kBeforeNavigate2Info;
static _ATL_FUNC_INFO kNavigateComplete2Info;
static _ATL_FUNC_INFO kNavigateErrorInfo;
+ static _ATL_FUNC_INFO kNewWindow2Info;
static _ATL_FUNC_INFO kNewWindow3Info;
static _ATL_FUNC_INFO kVoidMethodInfo;
static _ATL_FUNC_INFO kDocumentCompleteInfo;
diff --git a/chrome_frame/test/chrome_frame_unittests.cc b/chrome_frame/test/chrome_frame_unittests.cc
index f343ff2c..fa63ab6 100644
--- a/chrome_frame/test/chrome_frame_unittests.cc
+++ b/chrome_frame/test/chrome_frame_unittests.cc
@@ -9,6 +9,7 @@
// defined.
#include <mshtml.h>
#include <exdisp.h>
+#include <mshtmcid.h>
#include "base/basictypes.h"
#include "base/file_version_info.h"
@@ -24,6 +25,7 @@
#include "chrome_frame/test/chrome_frame_test_utils.h"
#include "chrome_frame/test_utils.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/url_constants.h"
#include "chrome/installer/util/install_util.h"
#include "chrome/installer/util/helper.h"
@@ -1238,11 +1240,15 @@ class MockWebBrowserEventSink : public chrome_frame_test::WebBrowserEventSink {
MOCK_METHOD5_WITH_CALLTYPE(__stdcall, OnNewWindow3,
void (IDispatch** dispatch, // NOLINT
- VARIANT_BOOL* Cancel,
+ VARIANT_BOOL* cancel,
DWORD flags,
BSTR url_context,
BSTR url));
+ MOCK_METHOD2_WITH_CALLTYPE(__stdcall, OnNewWindow2,
+ void (IDispatch** dispatch, // NOLINT
+ VARIANT_BOOL* cancel));
+
MOCK_METHOD5_WITH_CALLTYPE(__stdcall, OnNavigateError,
void (IDispatch* dispatch, // NOLINT
VARIANT* url,
@@ -1253,11 +1259,13 @@ class MockWebBrowserEventSink : public chrome_frame_test::WebBrowserEventSink {
MOCK_METHOD1(OnLoad, void (const wchar_t* url)); // NOLINT
MOCK_METHOD1(OnLoadError, void (const wchar_t* url)); // NOLINT
MOCK_METHOD1(OnMessage, void (const wchar_t* message)); // NOLINT
+ MOCK_METHOD2(OnNewBrowserWindow, void (IDispatch* dispatch, // NOLINT
+ const wchar_t* url));
};
using testing::_;
-const wchar_t kChromeFrameFileUrl[] = L"cf:file:///C:/";
+const wchar_t kChromeFrameFileUrl[] = L"gcf:file:///C:/";
TEST(ChromeFrameTest, FullTabModeIE_DisallowedUrls) {
chrome_frame_test::TimedMsgLoop loop;
@@ -1311,16 +1319,11 @@ TEST_F(ChromeFrameTestWithWebServer, FLAKY_FullTabModeIE_WindowOpenInChrome) {
chrome_frame_test::TimedMsgLoop loop;
CComObjectStackEx<MockWebBrowserEventSink> mock;
- ::testing::InSequence sequence;
- EXPECT_CALL(mock,
- OnBeforeNavigate2(
- _, testing::Field(&VARIANT::bstrVal,
- testing::StrCaseEq(kChromeFrameFullTabWindowOpenTestUrl)),
- _, _, _, _, _))
- .WillOnce(testing::Return(S_OK));
- EXPECT_CALL(mock, OnNavigateComplete2(_, _))
- .WillOnce(testing::Return());
-
+ // NOTE:
+ // Intentionally not in sequence since we have just one navigation
+ // per mock, it's OK to be not in sequence as long as all the expections
+ // are satisfied. Moreover, since the second mock expects a new window,
+ // its events happen in random order.
EXPECT_CALL(mock,
OnBeforeNavigate2(
_, testing::Field(&VARIANT::bstrVal,
@@ -1342,8 +1345,30 @@ TEST_F(ChromeFrameTestWithWebServer, FLAKY_FullTabModeIE_WindowOpenInChrome) {
&chrome_frame_test::WebBrowserEventSink::SendInputToChrome,
std::string("A")), 0))));
- EXPECT_CALL(mock,
- OnNewWindow3(_, _, _, _, _));
+ // Watch for new window
+ CComObjectStackEx<MockWebBrowserEventSink> new_window_mock;
+ // Can't really check URL here since it will be of the form gcf:attach...
+ EXPECT_CALL(mock, OnNewWindow3(_, _, _, _, _));
+ EXPECT_CALL(mock, OnNewBrowserWindow(_, _))
+ .WillOnce(testing::WithArgs<0>(
+ testing::Invoke(CreateFunctor(&new_window_mock,
+ &MockWebBrowserEventSink::Attach))));
+
+ // Expect navigations on the new mock
+ EXPECT_CALL(new_window_mock, OnBeforeNavigate2(_, _, _, _, _, _, _))
+ .Times(testing::AnyNumber()).WillOnce(testing::Return(S_OK));
+ EXPECT_CALL(new_window_mock, OnNavigateComplete2(_, _))
+ .Times(testing::AnyNumber()).WillOnce(testing::Return());
+ EXPECT_CALL(new_window_mock,
+ OnLoad(testing::StrEq(kChromeFrameFullTabWindowOpenPopupUrl)))
+ .WillOnce(testing::DoAll(
+ testing::InvokeWithoutArgs(CreateFunctor(&mock,
+ &MockWebBrowserEventSink::Uninitialize)),
+ testing::InvokeWithoutArgs(CreateFunctor(&new_window_mock,
+ &MockWebBrowserEventSink::Uninitialize)),
+ testing::IgnoreResult(testing::InvokeWithoutArgs(
+ &chrome_frame_test::CloseAllIEWindows)),
+ QUIT_LOOP_SOON(loop, 2)));
HRESULT hr = mock.LaunchIEAndNavigate(kChromeFrameFullTabWindowOpenTestUrl);
ASSERT_HRESULT_SUCCEEDED(hr);
@@ -1363,10 +1388,10 @@ const wchar_t kSubFrameUrl1[] =
L"http://localhost:1337/files/sub_frame1.html";
const wchar_t kChromeFrameAboutVersion[] =
- L"cf:about:version";
+ L"gcf:about:version";
// This test launches chrome frame in full tab mode in IE by having IE navigate
-// to cf:about:blank. It then looks for the chrome renderer window and posts
+// to gcf:about:blank. It then looks for the chrome renderer window and posts
// the WM_RBUTTONDOWN/WM_RBUTTONUP messages to it, which bring up the context
// menu. This is followed by keyboard messages sent via SendInput to select
// the About chrome frame menu option, which would then bring up a new window
@@ -1583,7 +1608,7 @@ TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_BackForward) {
}
-const wchar_t kChromeFrameAboutBlankUrl[] = L"cf:about:blank";
+const wchar_t kChromeFrameAboutBlankUrl[] = L"gcf:about:blank";
TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_ChromeFrameFocusTest) {
chrome_frame_test::TimedMsgLoop loop;
@@ -1797,6 +1822,80 @@ TEST_F(ChromeFrameTestWithWebServer, FLAKY_FullTabModeIE_BackForwardAnchor) {
chrome_frame_test::CloseAllIEWindows();
}
+// Full tab mode view source test
+// Launch and navigate chrome frame and invoke view source functionality
+TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_ViewSource) {
+ chrome_frame_test::TimedMsgLoop loop;
+ CComObjectStackEx<MockWebBrowserEventSink> mock;
+ CComObjectStackEx<MockWebBrowserEventSink> view_source_mock;
+ ::testing::InSequence sequence; // Everything in sequence
+
+ // After navigation invoke view soruce action using IWebBrowser2::ExecWB
+ EXPECT_CALL(mock, OnBeforeNavigate2(_, testing::Field(&VARIANT::bstrVal,
+ testing::StrCaseEq(kAnchorUrl)),
+ _, _, _, _, _))
+ .WillOnce(testing::Return(S_OK));
+ EXPECT_CALL(mock, OnNavigateComplete2(_, _))
+ .WillOnce(testing::Return());
+ EXPECT_CALL(mock, OnBeforeNavigate2(_, testing::Field(&VARIANT::bstrVal,
+ testing::StrCaseEq(kAnchorUrl)),
+ _, _, _, _, _))
+ .Times(testing::AnyNumber()).WillOnce(testing::Return(S_OK));
+ EXPECT_CALL(mock, OnNavigateComplete2(_, _))
+ .Times(testing::AnyNumber()).WillOnce(testing::Return());
+
+ VARIANT empty = ScopedVariant::kEmptyVariant;
+ EXPECT_CALL(mock, OnLoad(testing::StrEq(kAnchorUrl)))
+ .WillOnce(testing::IgnoreResult(testing::InvokeWithoutArgs(
+ CreateFunctor(ReceivePointer(mock.web_browser2_),
+ &IWebBrowser2::ExecWB,
+ static_cast<OLECMDID>(IDM_VIEWSOURCE),
+ OLECMDEXECOPT_DONTPROMPTUSER, &empty, &empty))));
+
+ // Expect notification for view-source window, handle new window event
+ // and attach a new mock to the received web browser
+ std::wstring view_source_url;
+ view_source_url += UTF8ToWide(chrome::kViewSourceScheme);
+ view_source_url += L":";
+ view_source_url += kAnchorUrl;
+ std::wstring url_in_new_window = kChromeProtocolPrefix;
+ url_in_new_window += view_source_url;
+
+ EXPECT_CALL(mock, OnNewWindow3(_, _, _, _,
+ testing::StrCaseEq(url_in_new_window)));
+ EXPECT_CALL(mock, OnNewBrowserWindow(_, _))
+ .WillOnce(testing::WithArgs<0>(
+ testing::Invoke(CreateFunctor(&view_source_mock,
+ &MockWebBrowserEventSink::Attach))));
+
+ // Expect navigations on the new mock
+ EXPECT_CALL(view_source_mock, OnBeforeNavigate2(_,
+ testing::Field(&VARIANT::bstrVal,
+ testing::StrCaseEq(url_in_new_window)), _, _, _, _, _))
+ .Times(testing::AnyNumber()).WillOnce(testing::Return(S_OK));
+ EXPECT_CALL(view_source_mock, OnNavigateComplete2(_, _))
+ .WillOnce(testing::Return());
+ EXPECT_CALL(view_source_mock, OnLoad(testing::StrEq(view_source_url)))
+ .WillOnce(testing::DoAll(
+ testing::InvokeWithoutArgs(CreateFunctor(&mock,
+ &MockWebBrowserEventSink::Uninitialize)),
+ testing::InvokeWithoutArgs(CreateFunctor(&view_source_mock,
+ &MockWebBrowserEventSink::Uninitialize)),
+ testing::IgnoreResult(testing::InvokeWithoutArgs(
+ &chrome_frame_test::CloseAllIEWindows)),
+ QUIT_LOOP_SOON(loop, 2)));
+
+ HRESULT hr = mock.LaunchIEAndNavigate(kAnchorUrl);
+ ASSERT_HRESULT_SUCCEEDED(hr);
+ if (hr == S_FALSE)
+ return;
+
+ ASSERT_TRUE(mock.web_browser2() != NULL);
+ loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
+ mock.Uninitialize();
+ chrome_frame_test::CloseAllIEWindows();
+}
+
const wchar_t kChromeFrameFullTabModeXMLHttpRequestTestUrl[] =
L"files/xmlhttprequest_test.html";
diff --git a/chrome_frame/test/data/cf_protocol.html b/chrome_frame/test/data/cf_protocol.html
index 0036555..bee4055 100644
--- a/chrome_frame/test/data/cf_protocol.html
+++ b/chrome_frame/test/data/cf_protocol.html
@@ -15,6 +15,6 @@
</head>
<body onLoad="setTimeout(test, 100);">
<h2>Prepare to be redirected!</h2>
- <p>Redirects the same page to its 'cf:' version</p>
+ <p>Redirects the same page to its 'gcf:' version</p>
</body>
</html>
diff --git a/chrome_frame/test/data/chrome_frame_tester_helpers.js b/chrome_frame/test/data/chrome_frame_tester_helpers.js
index f3ccd58..a6cc9c2 100644
--- a/chrome_frame/test/data/chrome_frame_tester_helpers.js
+++ b/chrome_frame/test/data/chrome_frame_tester_helpers.js
@@ -139,7 +139,7 @@ function isRunningInMSIE() {
}
function reloadUsingCFProtocol() {
- var redirect_location = "cf:";
+ var redirect_location = "gcf:";
redirect_location += window.location;
window.location = redirect_location;
}
diff --git a/chrome_frame/test/data/navigate_out.html b/chrome_frame/test/data/navigate_out.html
index 7b910b4..5f447c9 100644
--- a/chrome_frame/test/data/navigate_out.html
+++ b/chrome_frame/test/data/navigate_out.html
@@ -15,6 +15,6 @@
</head>
<body onLoad="setTimeout(test, 100);">
<h2>Prepare to be redirected!</h2>
- <p>Redirects the same page to its 'cf:' version and </p>
+ <p>Redirects the same page to its 'gcf:' version and </p>
</body>
</html>
diff --git a/chrome_frame/test/reliability/page_load_test.cc b/chrome_frame/test/reliability/page_load_test.cc
index dd869e5..21fded4 100644
--- a/chrome_frame/test/reliability/page_load_test.cc
+++ b/chrome_frame/test/reliability/page_load_test.cc
@@ -133,9 +133,9 @@ class WebBrowserEventSinkImpl : public chrome_frame_test::WebBrowserEventSink {
}
virtual HRESULT Navigate(const std::wstring& navigate_url) {
- if (StartsWith(navigate_url, L"cf:", true)) {
+ if (StartsWith(navigate_url, kChromeProtocolPrefix, true)) {
is_chrome_frame_navigation_ = true;
- url_ = navigate_url.substr(wcslen(L"cf:"));
+ url_ = navigate_url.substr(wcslen(kChromeProtocolPrefix));
} else {
url_ = navigate_url;
}
@@ -349,7 +349,7 @@ class PageLoadTest : public testing::Test {
// Every 3rd URL goes into the host browser.
if (line_index % 3 != 0) {
std::string actual_url;
- actual_url = "cf:";
+ actual_url = WideToUTF8(kChromeProtocolPrefix);
actual_url += url_str;
url_str = actual_url;
}
@@ -382,10 +382,12 @@ class PageLoadTest : public testing::Test {
}
SetConfigBool(kChromeFrameHeadlessMode, true);
+ SetConfigBool(kEnableGCFProtocol, true);
}
virtual void TearDown() {
DeleteConfigValue(kChromeFrameHeadlessMode);
+ DeleteConfigValue(kEnableGCFProtocol);
}
FilePath ConstructSavedDebugLogPath(const FilePath& debug_log_path,
diff --git a/chrome_frame/utils.cc b/chrome_frame/utils.cc
index e6632f9..ae7a0d9 100644
--- a/chrome_frame/utils.cc
+++ b/chrome_frame/utils.cc
@@ -33,11 +33,12 @@ const wchar_t kContentAttribName[] = L"content";
const wchar_t kXUACompatValue[] = L"x-ua-compatible";
const wchar_t kBodyTag[] = L"body";
const wchar_t kChromeContentPrefix[] = L"chrome=";
-const wchar_t kChromeProtocolPrefix[] = L"cf:";
+const wchar_t kChromeProtocolPrefix[] = L"gcf:";
static const wchar_t kChromeFrameConfigKey[] =
L"Software\\Google\\ChromeFrame";
static const wchar_t kChromeFrameOptinUrlsKey[] = L"OptinUrls";
+static const wchar_t kEnableGCFProtocol[] = L"EnableGCFProtocol";
static const wchar_t kChromeFrameNPAPIKey[] =
L"Software\\MozillaPlugins\\@google.com/ChromeFrame,version=1.0";
diff --git a/chrome_frame/utils.h b/chrome_frame/utils.h
index e90a0d4..2cbb277 100644
--- a/chrome_frame/utils.h
+++ b/chrome_frame/utils.h
@@ -18,6 +18,8 @@
extern const wchar_t kChromeContentPrefix[];
extern const wchar_t kChromeProtocolPrefix[];
+extern const wchar_t kChromeFrameHeadlessMode[];
+extern const wchar_t kEnableGCFProtocol[];
// This function is very similar to the AtlRegisterTypeLib function except
// that it takes a parameter that specifies whether to register the typelib
@@ -314,8 +316,6 @@ STDMETHODIMP QueryInterfaceIfDelegateSupports(void* obj, REFIID iid,
#define COM_INTERFACE_BLIND_DELEGATE() \
COM_INTERFACE_ENTRY_FUNC_BLIND(0, CheckOutgoingInterface<_ComMapClass>)
-extern const wchar_t kChromeFrameHeadlessMode[];
-
// Thread that enters STA and has a UI message loop.
class STAThread : public base::Thread {
public: