summaryrefslogtreecommitdiffstats
path: root/chrome_frame
diff options
context:
space:
mode:
authortommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-25 01:34:08 +0000
committertommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-25 01:34:08 +0000
commit62bb18dc11e536437972f24b6ecd6c9e33c3f88c (patch)
tree8d94039ebee95080d4bf7d152ca53f7d412aa483 /chrome_frame
parent9635b9f038bae457735d7e169125919a3f24f806 (diff)
downloadchromium_src-62bb18dc11e536437972f24b6ecd6c9e33c3f88c.zip
chromium_src-62bb18dc11e536437972f24b6ecd6c9e33c3f88c.tar.gz
chromium_src-62bb18dc11e536437972f24b6ecd6c9e33c3f88c.tar.bz2
Transfer CF downloads to the host browser.TEST=Click a download link (not via redirect) in a web page displayed by Chrome Frame. The request should be handled by the host browser.BUG=23561
Review URL: http://codereview.chromium.org/385108 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@33022 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame')
-rw-r--r--chrome_frame/chrome_active_document.cc44
-rw-r--r--chrome_frame/chrome_frame_activex_base.h38
-rw-r--r--chrome_frame/extra_system_apis.h45
-rw-r--r--chrome_frame/urlmon_url_request.cc93
-rw-r--r--chrome_frame/urlmon_url_request.h2
5 files changed, 180 insertions, 42 deletions
diff --git a/chrome_frame/chrome_active_document.cc b/chrome_frame/chrome_active_document.cc
index 2406f6e..d03a6f5 100644
--- a/chrome_frame/chrome_active_document.cc
+++ b/chrome_frame/chrome_active_document.cc
@@ -472,7 +472,7 @@ void ChromeActiveDocument::OnNavigationStateChanged(int tab_handle, int flags,
<< "Url: " << nav_info.url <<
", Title: " << nav_info.title <<
", Type: " << nav_info.navigation_type << ", Relative Offset: " <<
- nav_info.relative_offset << ", Index: " << nav_info.navigation_index;;
+ nav_info.relative_offset << ", Index: " << nav_info.navigation_index;
UpdateNavigationState(nav_info);
}
@@ -586,7 +586,7 @@ void ChromeActiveDocument::UpdateNavigationState(
ScopedComPtr<IWebBrowserEventsService> web_browser_events_svc;
DoQueryService(__uuidof(web_browser_events_svc), m_spClientSite,
web_browser_events_svc.Receive());
- DCHECK(web_browser_events_svc);
+ // web_browser_events_svc can be NULL on IE6.
if (web_browser_events_svc) {
VARIANT_BOOL should_cancel = VARIANT_FALSE;
web_browser_events_svc->FireBeforeNavigate2Event(&should_cancel);
@@ -844,28 +844,26 @@ bool ChromeActiveDocument::LaunchUrl(const std::wstring& url,
} else {
// Initiate navigation before launching chrome so that the url will be
// cached and sent with launch settings.
- if (is_new_navigation) {
- url_.Reset(::SysAllocString(url.c_str()));
- if (url_.Length()) {
- std::string utf8_url;
- WideToUTF8(url_, url_.Length(), &utf8_url);
-
- std::string referrer;
- Bho* chrome_frame_bho = Bho::GetCurrentThreadBhoInstance();
- if (chrome_frame_bho)
- referrer = chrome_frame_bho->referrer();
-
- if (!automation_client_->InitiateNavigation(utf8_url,
- referrer,
- is_privileged_)) {
- DLOG(ERROR) << "Invalid URL: " << url;
- Error(L"Invalid URL");
- url_.Reset();
- return false;
- }
-
- DLOG(INFO) << "Url is " << url_;
+ url_.Reset(::SysAllocString(url.c_str()));
+ if (url_.Length()) {
+ std::string utf8_url;
+ WideToUTF8(url_, url_.Length(), &utf8_url);
+
+ std::string referrer;
+ Bho* chrome_frame_bho = Bho::GetCurrentThreadBhoInstance();
+ if (chrome_frame_bho)
+ referrer = chrome_frame_bho->referrer();
+
+ if (!automation_client_->InitiateNavigation(utf8_url,
+ referrer,
+ is_privileged_)) {
+ DLOG(ERROR) << "Invalid URL: " << url;
+ Error(L"Invalid URL");
+ url_.Reset();
+ return false;
}
+
+ DLOG(INFO) << "Url is " << url_;
}
}
diff --git a/chrome_frame/chrome_frame_activex_base.h b/chrome_frame/chrome_frame_activex_base.h
index 09ad669..6a7183f 100644
--- a/chrome_frame/chrome_frame_activex_base.h
+++ b/chrome_frame/chrome_frame_activex_base.h
@@ -14,10 +14,10 @@
// undo the janky "#define NOMINMAX" train wreck. See:
// http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100703
#ifndef max
-#define max(a,b) (((a) > (b)) ? (a) : (b))
+#define max(a,b) (((a) > (b)) ? (a) : (b)) // NOLINT
#endif
#ifndef min
-#define min(a,b) (((a) < (b)) ? (a) : (b))
+#define min(a,b) (((a) < (b)) ? (a) : (b)) // NOLINT
#endif
#include <atlimage.h>
#undef max
@@ -99,7 +99,7 @@ class ATL_NO_VTABLE ProxyDIChromeFrameEvents
FireMethodWithParam(CF_EVENT_DISPID_ONMESSAGE, var);
}
- void Fire_onreadystatechanged(long readystate) {
+ void Fire_onreadystatechanged(long readystate) { // NOLINT
VARIANT var = { VT_I4 };
var.lVal = readystate;
FireMethodWithParam(CF_EVENT_DISPID_ONREADYSTATECHANGED, var);
@@ -117,7 +117,7 @@ class ATL_NO_VTABLE ProxyDIChromeFrameEvents
arraysize(args));
}
- void Fire_onextensionready(BSTR path, long response) {
+ void Fire_onextensionready(BSTR path, long response) { // NOLINT
// Arguments in reverse order to the function declaration, because
// that's what DISPPARAMS requires.
VARIANT args[2] = { { VT_I4, }, { VT_BSTR, } };
@@ -134,7 +134,7 @@ extern bool g_first_launch_by_process_;
// Common implementation for ActiveX and Active Document
template <class T, const CLSID& class_id>
-class ATL_NO_VTABLE ChromeFrameActivexBase :
+class ATL_NO_VTABLE ChromeFrameActivexBase : // NOLINT
public CComObjectRootEx<CComMultiThreadModel>,
public IOleControlImpl<T>,
public IOleObjectImpl<T>,
@@ -266,7 +266,7 @@ END_MSG_MAP()
}
// Called to draw our control when chrome hasn't been initialized.
- virtual HRESULT OnDraw(ATL_DRAWINFO& draw_info) { // NO_LINT
+ virtual HRESULT OnDraw(ATL_DRAWINFO& draw_info) { // NOLINT
if (NULL == draw_info.prcBounds) {
NOTREACHED();
return E_FAIL;
@@ -490,6 +490,10 @@ END_MSG_MAP()
virtual void OnDownloadRequestInHost(int tab_handle, int request_id) {
DLOG(INFO) << "TODO: Let the host browser handle this download";
+ PluginUrlRequest* request = automation_client_->LookupRequest(request_id);
+ if (request) {
+ static_cast<UrlmonUrlRequest*>(request)->TransferToHost(doc_site_);
+ }
automation_client_->RemoveRequest(request_id, false);
}
@@ -914,7 +918,7 @@ END_MSG_MAP()
// creating a "message" event.
HRESULT CreateDomEvent(const std::string& event_type, const std::string& data,
const std::string& origin, IDispatch** event) {
- DCHECK(event_type.length() > 0);
+ DCHECK(event_type.length() > 0); // NOLINT
DCHECK(event != NULL);
CComObject<ComMessageEvent>* ev = NULL;
@@ -949,7 +953,7 @@ END_MSG_MAP()
HRESULT InvokeScriptFunction(const VARIANT& script_object, VARIANT* params,
int param_count) {
- DCHECK(param_count >= 0);
+ DCHECK_GE(param_count, 0);
DCHECK(params);
if (V_VT(&script_object) != VT_DISPATCH) {
@@ -1062,15 +1066,15 @@ END_MSG_MAP()
}
protected:
- // The following functions are called to initialize and uninitialize the
- // worker thread.
- void OnWorkerStart() {
- CoInitialize(NULL);
- }
-
- void OnWorkerStop() {
- CoUninitialize();
- }
+ // The following functions are called to initialize and uninitialize the
+ // worker thread.
+ void OnWorkerStart() {
+ CoInitialize(NULL);
+ }
+
+ void OnWorkerStop() {
+ CoUninitialize();
+ }
ScopedBstr url_;
ScopedComPtr<IOleDocumentSite> doc_site_;
diff --git a/chrome_frame/extra_system_apis.h b/chrome_frame/extra_system_apis.h
index 2d78d59..2258298 100644
--- a/chrome_frame/extra_system_apis.h
+++ b/chrome_frame/extra_system_apis.h
@@ -34,6 +34,51 @@ IWebBrowserEventsUrlService : public IUnknown {
STDMETHOD(GetUrlForEvents)(BSTR* url) = 0;
};
+// Web browser methods that are used by MSHTML when navigating or
+// initiating downloads. IE6.
+class __declspec(uuid("{3050F804-98B5-11CF-BB82-00AA00BDCE0B}"))
+IWebBrowserPriv : public IUnknown {
+ public:
+ STDMETHOD(NavigateWithBindCtx)(VARIANT* uri, VARIANT* flags,
+ VARIANT* target_frame, VARIANT* post_data,
+ VARIANT* headers, IBindCtx* bind_ctx,
+ LPOLESTR url_fragment);
+ STDMETHOD(OnClose)();
+};
+
+// Web browser methods that are used by MSHTML when navigating or
+// initiating downloads. IE7.
+class __declspec(uuid("{1AF32B6C-A3BA-48B9-B24E-8AA9C41F6ECD}"))
+IWebBrowserPriv2IE7 : public IUnknown {
+ public:
+ STDMETHOD(NavigateWithBindCtx2)(IUri* uri, VARIANT* flags,
+ VARIANT* target_frame, VARIANT* post_data,
+ VARIANT* headers, IBindCtx* bind_ctx,
+ LPOLESTR url_fragment);
+ STDMETHOD(SetBrowserFrameOptions)(DWORD opt1, DWORD opt2);
+ STDMETHOD(DetachConnectionPoints)();
+};
+
+// Web browser methods that are used by MSHTML when navigating or
+// initiating downloads. IE8 uses IID {3ED72303-6FFC-4214-BA90-FAF1862DEC8A}
+// whereas the IID is {1AF32B6C-A3BA-48B9-B24E-8AA9C41F6ECD} in IE7
+class __declspec(uuid("{3ED72303-6FFC-4214-BA90-FAF1862DEC8A}"))
+IWebBrowserPriv2IE8 : public IUnknown {
+ public:
+ STDMETHOD(NavigateWithBindCtx2)(IUri* uri, VARIANT* flags,
+ VARIANT* target_frame, VARIANT* post_data,
+ VARIANT* headers, IBindCtx* bind_ctx,
+ LPOLESTR url_fragment);
+ STDMETHOD(SetBrowserFrameOptions)(DWORD opt1, DWORD opt2);
+ STDMETHOD(DetachConnectionPoints)();
+ STDMETHOD(GetProcessId)(DWORD* pid);
+ STDMETHOD(CompatAttachEditEvents)();
+ STDMETHOD(HandleOpenOptions)(IUnknown* obj, BSTR bstr, int options);
+ STDMETHOD(SetSearchTerm)(BSTR term);
+ STDMETHOD(GetSearchTerm)(BSTR* term);
+ STDMETHOD(GetCurrentDocument)(IDispatch** doc);
+};
+
// This interface is used to call FireBeforeNavigate with additional
// information like url. Available on IE7 onwards.
//
diff --git a/chrome_frame/urlmon_url_request.cc b/chrome_frame/urlmon_url_request.cc
index 6124979..e738ae1 100644
--- a/chrome_frame/urlmon_url_request.cc
+++ b/chrome_frame/urlmon_url_request.cc
@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "base/message_loop.h"
#include "chrome_frame/chrome_frame_activex_base.h"
+#include "chrome_frame/extra_system_apis.h"
#include "chrome_frame/html_utils.h"
#include "chrome_frame/urlmon_upload_data_stream.h"
#include "chrome_frame/utils.h"
@@ -132,6 +133,91 @@ bool UrlmonUrlRequest::Read(int bytes_to_read) {
return true;
}
+void UrlmonUrlRequest::TransferToHost(IUnknown* host) {
+ DCHECK_EQ(PlatformThread::CurrentId(), thread_);
+ DCHECK(host);
+
+ DCHECK(moniker_);
+ if (!moniker_)
+ return;
+
+ ScopedComPtr<IMoniker> moniker;
+ moniker.Attach(moniker_.Detach());
+
+ // Create a new bind context that's not associated with our callback.
+ // Calling RevokeBindStatusCallback doesn't disassociate the callback with
+ // the bind context in IE7. The returned bind context has the same
+ // implementation of GetRunningObjectTable as the bind context we held which
+ // basically delegates to ole32's GetRunningObjectTable. The object table
+ // is then used to determine if the moniker is already running and via
+ // that mechanism is associated with the same internet request as has already
+ // been issued.
+ ScopedComPtr<IBindCtx> bind_context;
+ CreateBindCtx(0, bind_context.Receive());
+ DCHECK(bind_context);
+
+ LPOLESTR url = NULL;
+ if (SUCCEEDED(moniker->GetDisplayName(bind_context, NULL, &url))) {
+ DLOG(INFO) << __FUNCTION__ << " " << url;
+
+ // TODO(tommi): See if we can get HlinkSimpleNavigateToMoniker to work
+ // instead. Looks like we'll need to support IHTMLDocument2 (get_URL in
+ // particular), access to IWebBrowser2 etc.
+ // HlinkSimpleNavigateToMoniker(moniker, url, NULL, host, bind_context,
+ // NULL, 0, 0);
+
+ ScopedComPtr<IWebBrowser2> wb2;
+ HRESULT hr = DoQueryService(SID_SWebBrowserApp, host, wb2.Receive());
+ DCHECK(wb2);
+ DLOG_IF(WARNING, FAILED(hr)) << StringPrintf(L"SWebBrowserApp 0x%08X", hr);
+
+ ScopedComPtr<IWebBrowserPriv> wbp;
+ ScopedComPtr<IWebBrowserPriv2IE7> wbp2_ie7;
+ ScopedComPtr<IWebBrowserPriv2IE8> wbp2_ie8;
+ if (SUCCEEDED(hr = wbp.QueryFrom(wb2))) {
+ ScopedVariant var_url(url);
+ hr = wbp->NavigateWithBindCtx(var_url.AsInput(), NULL, NULL, NULL, NULL,
+ bind_context, NULL);
+ DLOG_IF(WARNING, FAILED(hr))
+ << StringPrintf(L"NavigateWithBindCtx 0x%08X", hr);
+ } else {
+ DLOG(WARNING) << StringPrintf(L"IWebBrowserPriv 0x%08X", hr);
+ IWebBrowserPriv2IE7* common_wbp2 = NULL;
+ if (SUCCEEDED(hr = wbp2_ie7.QueryFrom(wb2))) {
+ common_wbp2 = wbp2_ie7;
+ } else if (SUCCEEDED(hr = wbp2_ie8.QueryFrom(wb2))) {
+ common_wbp2 = reinterpret_cast<IWebBrowserPriv2IE7*>(wbp2_ie8.get());
+ }
+
+ if (common_wbp2) {
+ typedef HRESULT (WINAPI* CreateUriFn)(LPCWSTR uri, DWORD flags,
+ DWORD_PTR reserved, IUri** ret);
+
+ CreateUriFn create_uri = reinterpret_cast<CreateUriFn>(
+ ::GetProcAddress(::GetModuleHandleA("urlmon"), "CreateUri"));
+ DCHECK(create_uri);
+ if (create_uri) {
+ ScopedComPtr<IUri> uri_obj;
+ hr = create_uri(url, 0, 0, uri_obj.Receive());
+ DLOG_IF(WARNING, FAILED(hr))
+ << StringPrintf(L"create_uri 0x%08X", hr);
+ hr = common_wbp2->NavigateWithBindCtx2(uri_obj, NULL, NULL, NULL,
+ NULL, bind_context, NULL);
+ DLOG_IF(WARNING, FAILED(hr))
+ << StringPrintf(L"NavigateWithBindCtx2 0x%08X", hr);
+ }
+ } else {
+ DLOG(WARNING) << StringPrintf(L"IWebBrowserPriv2 0x%08X", hr);
+ NOTREACHED();
+ }
+ }
+
+ DCHECK(wbp || wbp2_ie7 || wbp2_ie8);
+
+ ::CoTaskMemFree(url);
+ }
+}
+
void UrlmonUrlRequest::ReadAsync(int bytes_to_read) {
// Send cached data if available.
CComObjectStackEx<SendStream> send_stream;
@@ -235,8 +321,11 @@ STDMETHODIMP UrlmonUrlRequest::OnStopBinding(HRESULT result, LPCWSTR error) {
// Release these variables after reporting EndRequest since we might need to
// access their state.
- binding_ = NULL;
- bind_context_ = NULL;
+ binding_.Release();
+ if (bind_context_) {
+ ::RevokeBindStatusCallback(bind_context_, this);
+ bind_context_.Release();
+ }
return S_OK;
}
diff --git a/chrome_frame/urlmon_url_request.h b/chrome_frame/urlmon_url_request.h
index 0612f33..e52d08d 100644
--- a/chrome_frame/urlmon_url_request.h
+++ b/chrome_frame/urlmon_url_request.h
@@ -61,6 +61,8 @@ END_MSG_MAP()
virtual void Stop();
virtual bool Read(int bytes_to_read);
+ void TransferToHost(IUnknown* host);
+
// IBindStatusCallback implementation
STDMETHOD(OnStartBinding)(DWORD reserved, IBinding* binding);
STDMETHOD(GetPriority)(LONG* priority);