diff options
author | tommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-16 23:59:17 +0000 |
---|---|---|
committer | tommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-16 23:59:17 +0000 |
commit | 35f13ab63b056a8e36c06e41655684915c183701 (patch) | |
tree | 913426da932aa18f73f44950d50b1de0398c3968 | |
parent | d65f129bee77d3a4f6ac186641fe11fd890ef077 (diff) | |
download | chromium_src-35f13ab63b056a8e36c06e41655684915c183701.zip chromium_src-35f13ab63b056a8e36c06e41655684915c183701.tar.gz chromium_src-35f13ab63b056a8e36c06e41655684915c183701.tar.bz2 |
Handle right-click->"Save Link As" in the host browser.
TEST=Right click on a link in CF and select "save link as". You should immediately get the host browser's download UI. Before there could be a significant wait before this happened.
BUG=23561
Review URL: http://codereview.chromium.org/506042
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@34783 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/external_tab_container.cc | 23 | ||||
-rw-r--r-- | chrome/test/automation/automation_messages.h | 71 | ||||
-rw-r--r-- | chrome/test/automation/automation_messages_internal.h | 7 | ||||
-rw-r--r-- | chrome_frame/chrome_active_document.cc | 5 | ||||
-rw-r--r-- | chrome_frame/chrome_active_document.h | 2 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_activex_base.h | 18 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_delegate.h | 3 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_npapi.cc | 3 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_npapi.h | 2 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_plugin.h | 11 | ||||
-rw-r--r-- | chrome_frame/test/chrome_frame_unittests.cc | 4 | ||||
-rw-r--r-- | chrome_frame/utils.cc | 19 | ||||
-rw-r--r-- | chrome_frame/utils.h | 3 |
13 files changed, 151 insertions, 20 deletions
diff --git a/chrome/browser/external_tab_container.cc b/chrome/browser/external_tab_container.cc index 2a6c237..2775960 100644 --- a/chrome/browser/external_tab_container.cc +++ b/chrome/browser/external_tab_container.cc @@ -440,11 +440,20 @@ bool ExternalTabContainer::HandleContextMenu(const ContextMenuParams& params) { POINT screen_pt = { params.x, params.y }; MapWindowPoints(GetNativeView(), HWND_DESKTOP, &screen_pt, 1); + IPC::ContextMenuParams ipc_params; + ipc_params.screen_x = screen_pt.x; + ipc_params.screen_y = screen_pt.y; + ipc_params.link_url = params.link_url; + ipc_params.unfiltered_link_url = params.unfiltered_link_url; + ipc_params.src_url = params.src_url; + ipc_params.page_url = params.page_url; + ipc_params.frame_url = params.frame_url; + bool rtl = l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT; automation_->Send( new AutomationMsg_ForwardContextMenuToExternalHost(0, tab_handle_, - external_context_menu_->GetMenuHandle(), screen_pt.x, screen_pt.y, - rtl ? TPM_RIGHTALIGN : TPM_LEFTALIGN)); + external_context_menu_->GetMenuHandle(), + rtl ? TPM_RIGHTALIGN : TPM_LEFTALIGN, ipc_params)); return true; } @@ -455,6 +464,16 @@ bool ExternalTabContainer::ExecuteContextMenuCommand(int command) { return false; } + switch (command) { + case IDS_CONTENT_CONTEXT_SAVEAUDIOAS: + case IDS_CONTENT_CONTEXT_SAVEVIDEOAS: + case IDS_CONTENT_CONTEXT_SAVEIMAGEAS: + case IDS_CONTENT_CONTEXT_SAVELINKAS: { + NOTREACHED(); // Should be handled in host. + break; + } + } + external_context_menu_->ExecuteCommand(command); return true; } diff --git a/chrome/test/automation/automation_messages.h b/chrome/test/automation/automation_messages.h index 388b6f2..b7f3013 100644 --- a/chrome/test/automation/automation_messages.h +++ b/chrome/test/automation/automation_messages.h @@ -454,6 +454,77 @@ struct ParamTraits<NavigationInfo> { } }; +// A stripped down version of ContextMenuParams in webkit/glue/context_menu.h. +struct ContextMenuParams { + // The x coordinate for displaying the menu. + int screen_x; + + // The y coordinate for displaying the menu. + int screen_y; + + // This is the URL of the link that encloses the node the context menu was + // invoked on. + GURL link_url; + + // The link URL to be used ONLY for "copy link address". We don't validate + // this field in the frontend process. + GURL unfiltered_link_url; + + // This is the source URL for the element that the context menu was + // invoked on. Example of elements with source URLs are img, audio, and + // video. + GURL src_url; + + // This is the URL of the top level page that the context menu was invoked + // on. + GURL page_url; + + // This is the URL of the subframe that the context menu was invoked on. + GURL frame_url; +}; + +// Traits for ContextMenuParams structure to pack/unpack. +template <> +struct ParamTraits<ContextMenuParams> { + typedef ContextMenuParams param_type; + static void Write(Message* m, const param_type& p) { + WriteParam(m, p.screen_x); + WriteParam(m, p.screen_y); + WriteParam(m, p.link_url); + WriteParam(m, p.unfiltered_link_url); + WriteParam(m, p.src_url); + WriteParam(m, p.page_url); + WriteParam(m, p.frame_url); + } + static bool Read(const Message* m, void** iter, param_type* p) { + return ReadParam(m, iter, &p->screen_x) && + ReadParam(m, iter, &p->screen_y) && + ReadParam(m, iter, &p->link_url) && + ReadParam(m, iter, &p->unfiltered_link_url) && + ReadParam(m, iter, &p->src_url) && + ReadParam(m, iter, &p->page_url) && + ReadParam(m, iter, &p->frame_url); + } + static void Log(const param_type& p, std::wstring* l) { + l->append(L"("); + LogParam(p.screen_x, l); + l->append(L", "); + LogParam(p.screen_y, l); + l->append(L", "); + LogParam(p.link_url, l); + l->append(L", "); + LogParam(p.unfiltered_link_url, l); + l->append(L", "); + LogParam(p.src_url, l); + l->append(L", "); + LogParam(p.page_url, l); + l->append(L", "); + LogParam(p.frame_url, l); + l->append(L")"); + } +}; + + } // namespace IPC #define MESSAGES_INTERNAL_FILE \ diff --git a/chrome/test/automation/automation_messages_internal.h b/chrome/test/automation/automation_messages_internal.h index 754c335..b90280b 100644 --- a/chrome/test/automation/automation_messages_internal.h +++ b/chrome/test/automation/automation_messages_internal.h @@ -944,12 +944,11 @@ IPC_BEGIN_MESSAGES(Automation) string16 /* chrome_locale */) #if defined(OS_WIN) - IPC_MESSAGE_ROUTED5(AutomationMsg_ForwardContextMenuToExternalHost, + IPC_MESSAGE_ROUTED4(AutomationMsg_ForwardContextMenuToExternalHost, int /* tab_handle */, HANDLE /* source menu handle */, - int /* the x coordinate for displaying the menu */, - int /* the y coordinate for displaying the menu */, - int /* align flags */) + int /* align flags */, + IPC::ContextMenuParams /* params */) IPC_MESSAGE_ROUTED2(AutomationMsg_ForwardContextMenuCommandToChrome, int /* tab_handle */, diff --git a/chrome_frame/chrome_active_document.cc b/chrome_frame/chrome_active_document.cc index d03a6f5..79253d1 100644 --- a/chrome_frame/chrome_active_document.cc +++ b/chrome_frame/chrome_active_document.cc @@ -715,7 +715,8 @@ bool ChromeActiveDocument::PreProcessContextMenu(HMENU menu) { return Base::PreProcessContextMenu(menu); } -bool ChromeActiveDocument::HandleContextMenuCommand(UINT cmd) { +bool ChromeActiveDocument::HandleContextMenuCommand(UINT cmd, + const IPC::ContextMenuParams& params) { ScopedComPtr<IWebBrowser2> web_browser2; DoQueryService(SID_SWebBrowserApp, m_spClientSite, web_browser2.Receive()); @@ -733,7 +734,7 @@ bool ChromeActiveDocument::HandleContextMenuCommand(UINT cmd) { break; default: - return Base::HandleContextMenuCommand(cmd); + return Base::HandleContextMenuCommand(cmd, params); } return true; diff --git a/chrome_frame/chrome_active_document.h b/chrome_frame/chrome_active_document.h index dbd430f..6b57f2e 100644 --- a/chrome_frame/chrome_active_document.h +++ b/chrome_frame/chrome_active_document.h @@ -236,7 +236,7 @@ END_EXEC_COMMAND_MAP() // Callbacks from ChromeFramePlugin<T> bool PreProcessContextMenu(HMENU menu); - bool HandleContextMenuCommand(UINT cmd); + bool HandleContextMenuCommand(UINT cmd, const IPC::ContextMenuParams& params); // Should connections initiated by this class try to block // responses served with the X-Frame-Options header? diff --git a/chrome_frame/chrome_frame_activex_base.h b/chrome_frame/chrome_frame_activex_base.h index 6a7183f..28ca868 100644 --- a/chrome_frame/chrome_frame_activex_base.h +++ b/chrome_frame/chrome_frame_activex_base.h @@ -40,6 +40,7 @@ #include "chrome_frame/com_message_event.h" #include "chrome_frame/com_type_info_holder.h" #include "chrome_frame/urlmon_url_request.h" +#include "grit/generated_resources.h" // Include without path to make GYP build see it. #include "chrome_tab.h" // NOLINT @@ -288,11 +289,26 @@ END_MSG_MAP() return CComControlBase::IOleObject_SetClientSite(client_site); } - bool HandleContextMenuCommand(UINT cmd) { + bool HandleContextMenuCommand(UINT cmd, + const IPC::ContextMenuParams& params) { if (cmd == IDC_ABOUT_CHROME_FRAME) { int tab_handle = automation_client_->tab()->handle(); OnOpenURL(tab_handle, GURL("about:version"), GURL(), NEW_WINDOW); return true; + } else { + switch (cmd) { + case IDS_CONTENT_CONTEXT_SAVEAUDIOAS: + case IDS_CONTENT_CONTEXT_SAVEVIDEOAS: + case IDS_CONTENT_CONTEXT_SAVEIMAGEAS: + case IDS_CONTENT_CONTEXT_SAVELINKAS: { + const GURL& referrer = params.frame_url.is_empty() ? + params.page_url : params.frame_url; + const GURL& url = (cmd == IDS_CONTENT_CONTEXT_SAVELINKAS ? + params.link_url : params.src_url); + DoFileDownloadInIE(UTF8ToWide(url.spec()).c_str()); + return true; + } + } } return false; diff --git a/chrome_frame/chrome_frame_delegate.h b/chrome_frame/chrome_frame_delegate.h index 1742ad0..49ae1c1 100644 --- a/chrome_frame/chrome_frame_delegate.h +++ b/chrome_frame/chrome_frame_delegate.h @@ -91,7 +91,8 @@ class ChromeFrameDelegateImpl : public ChromeFrameDelegate { const std::string& origin, const std::string& target) {} virtual void OnHandleContextMenu(int tab_handle, HANDLE menu_handle, - int x_pos, int y_pos, int align_flags) {} + int align_flags, + const IPC::ContextMenuParams& params) {} virtual void OnRequestStart(int tab_handle, int request_id, const IPC::AutomationURLRequest& request) {} virtual void OnRequestRead(int tab_handle, int request_id, diff --git a/chrome_frame/chrome_frame_npapi.cc b/chrome_frame/chrome_frame_npapi.cc index 509f083..d3e1f91 100644 --- a/chrome_frame/chrome_frame_npapi.cc +++ b/chrome_frame/chrome_frame_npapi.cc @@ -1605,7 +1605,8 @@ NPAPIUrlRequest* ChromeFrameNPAPI::RequestFromNotifyData( return request; } -bool ChromeFrameNPAPI::HandleContextMenuCommand(UINT cmd) { +bool ChromeFrameNPAPI::HandleContextMenuCommand(UINT cmd, + const IPC::ContextMenuParams& params) { if (cmd == IDC_ABOUT_CHROME_FRAME) { // TODO: implement "About Chrome Frame" } diff --git a/chrome_frame/chrome_frame_npapi.h b/chrome_frame/chrome_frame_npapi.h index 1d35b4c..45b4028 100644 --- a/chrome_frame/chrome_frame_npapi.h +++ b/chrome_frame/chrome_frame_npapi.h @@ -125,7 +125,7 @@ END_MSG_MAP() // Initialize string->identifier mapping, public to allow unittesting. static void InitializeIdentifiers(); - bool HandleContextMenuCommand(UINT cmd); + bool HandleContextMenuCommand(UINT cmd, const IPC::ContextMenuParams& params); protected: // Handler for accelerator messages passed on from the hosted chrome // instance. diff --git a/chrome_frame/chrome_frame_plugin.h b/chrome_frame/chrome_frame_plugin.h index 36f2fc2..0e16001 100644 --- a/chrome_frame/chrome_frame_plugin.h +++ b/chrome_frame/chrome_frame_plugin.h @@ -93,7 +93,8 @@ END_MSG_MAP() } virtual void OnHandleContextMenu(int tab_handle, HANDLE menu_handle, - int x_pos, int y_pos, int align_flags) { + int align_flags, + const IPC::ContextMenuParams& params) { if (!menu_handle || !automation_client_.get()) { NOTREACHED(); return; @@ -109,9 +110,9 @@ END_MSG_MAP() T* pThis = static_cast<T*>(this); if (pThis->PreProcessContextMenu(copy)) { UINT flags = align_flags | TPM_LEFTBUTTON | TPM_RETURNCMD | TPM_RECURSE; - UINT selected = TrackPopupMenuEx(copy, flags, x_pos, y_pos, GetWindow(), - NULL); - if (selected != 0 && !pThis->HandleContextMenuCommand(selected)) { + UINT selected = TrackPopupMenuEx(copy, flags, params.screen_x, + params.screen_y, GetWindow(), NULL); + if (selected != 0 && !pThis->HandleContextMenuCommand(selected, params)) { automation_client_->SendContextMenuCommandToChromeFrame(selected); } } @@ -175,7 +176,7 @@ END_MSG_MAP() // Return true if menu command is processed, otherwise the command will be // passed to Chrome for execution. Override in most-derived class if needed. - bool HandleContextMenuCommand(UINT cmd) { + bool HandleContextMenuCommand(UINT cmd, const IPC::ContextMenuParams& params) { return false; } diff --git a/chrome_frame/test/chrome_frame_unittests.cc b/chrome_frame/test/chrome_frame_unittests.cc index 1b4eaee..fc4fd1a 100644 --- a/chrome_frame/test/chrome_frame_unittests.cc +++ b/chrome_frame/test/chrome_frame_unittests.cc @@ -714,8 +714,8 @@ struct MockCFDelegate : public ChromeFrameDelegateImpl { const std::string& message, const std::string& origin, const std::string& target)); - MOCK_METHOD5(OnHandleContextMenu, void(int tab_handle, HANDLE menu_handle, - int x_pos, int y_pos, int align_flags)); + MOCK_METHOD4(OnHandleContextMenu, void(int tab_handle, HANDLE menu_handle, + int align_flags, const IPC::ContextMenuParams& params)); MOCK_METHOD3(OnRequestStart, void(int tab_handle, int request_id, const IPC::AutomationURLRequest& request)); MOCK_METHOD3(OnRequestRead, void(int tab_handle, int request_id, diff --git a/chrome_frame/utils.cc b/chrome_frame/utils.cc index be955bf..88b46c5 100644 --- a/chrome_frame/utils.cc +++ b/chrome_frame/utils.cc @@ -415,6 +415,25 @@ bool IsIEInPrivate() { return incognito_mode; } +HRESULT DoFileDownloadInIE(const wchar_t* url) { + DCHECK(url); + + HMODULE mod = ::GetModuleHandleA("ieframe.dll"); + if (!mod) + mod = ::GetModuleHandleA("shdocvw.dll"); + + if (!mod) { + NOTREACHED(); + return E_UNEXPECTED; + } + + typedef HRESULT (WINAPI* DoFileDownloadFn)(const wchar_t*); + DoFileDownloadFn fn = reinterpret_cast<DoFileDownloadFn>( + ::GetProcAddress(mod, "DoFileDownload")); + DCHECK(fn); + return fn ? fn(url) : E_UNEXPECTED; +} + bool GetModuleVersion(HMODULE module, uint32* high, uint32* low) { DCHECK(module != NULL) << "Please use GetModuleHandle(NULL) to get the process name"; diff --git a/chrome_frame/utils.h b/chrome_frame/utils.h index 8750794..d10b7c0 100644 --- a/chrome_frame/utils.h +++ b/chrome_frame/utils.h @@ -165,6 +165,9 @@ bool GetModuleVersion(HMODULE module, uint32* high, uint32* low); // whether current process is IEXPLORE. bool IsIEInPrivate(); +// Calls [ieframe|shdocvw]!DoFileDownload to initiate a download. +HRESULT DoFileDownloadInIE(const wchar_t* url); + // Creates a copy of a menu. We need this when original menu comes from // a process with higher integrity. HMENU UtilCloneContextMenu(HMENU original_menu); |