diff options
author | tommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-25 01:34:08 +0000 |
---|---|---|
committer | tommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-25 01:34:08 +0000 |
commit | 62bb18dc11e536437972f24b6ecd6c9e33c3f88c (patch) | |
tree | 8d94039ebee95080d4bf7d152ca53f7d412aa483 /chrome_frame | |
parent | 9635b9f038bae457735d7e169125919a3f24f806 (diff) | |
download | chromium_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.cc | 44 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_activex_base.h | 38 | ||||
-rw-r--r-- | chrome_frame/extra_system_apis.h | 45 | ||||
-rw-r--r-- | chrome_frame/urlmon_url_request.cc | 93 | ||||
-rw-r--r-- | chrome_frame/urlmon_url_request.h | 2 |
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); |