Index: chrome_frame/chrome_frame_plugin.h |
=================================================================== |
--- chrome_frame/chrome_frame_plugin.h (revision 0) |
+++ chrome_frame/chrome_frame_plugin.h (revision 0) |
@@ -0,0 +1,214 @@ |
+// Copyright (c) 2009 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. |
+ |
+#ifndef CHROME_FRAME_CHROME_FRAME_PLUGIN_H_ |
+#define CHROME_FRAME_CHROME_FRAME_PLUGIN_H_ |
+ |
+#include "base/win_util.h" |
+#include "chrome_frame/chrome_frame_automation.h" |
+#include "chrome_frame/utils.h" |
+ |
+#define IDC_ABOUT_CHROME_FRAME 40018 |
+ |
+// A class to implement common functionality for all types of |
+// plugins: NPAPI. ActiveX and ActiveDoc |
+template <typename T> |
+class ChromeFramePlugin : public ChromeFrameDelegateImpl { |
+ public: |
+ ChromeFramePlugin() |
+ : ignore_setfocus_(false), |
+ is_privileged_(false) { |
+ } |
+ ~ChromeFramePlugin() { |
+ Uninitialize(); |
+ } |
+ |
+BEGIN_MSG_MAP(ChromeFrameActivex) |
+ MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) |
+ MESSAGE_HANDLER(WM_SIZE, OnSize) |
+ MESSAGE_HANDLER(WM_PARENTNOTIFY, OnParentNotify) |
+END_MSG_MAP() |
+ |
+ bool Initialize() { |
+ DCHECK(!automation_client_.get()); |
+ automation_client_.reset(CreateAutomationClient()); |
+ if (!automation_client_.get()) { |
+ NOTREACHED() << "new ChromeFrameAutomationClient"; |
+ return false; |
+ } |
+ |
+ return true; |
+ } |
+ |
+ void Uninitialize() { |
+ if (automation_client_.get()) { |
+ automation_client_->Uninitialize(); |
+ automation_client_.reset(); |
+ } |
+ } |
+ |
+ bool InitializeAutomation(const std::wstring& profile_name, |
+ const std::wstring& extra_chrome_arguments, |
+ bool incognito) { |
+ // We don't want to do incognito when privileged, since we're |
+ // running in browser chrome or some other privileged context. |
+ bool incognito_mode = !is_privileged_ && incognito; |
+ return automation_client_->Initialize(this, kCommandExecutionTimeout, true, |
+ profile_name, extra_chrome_arguments, |
+ incognito_mode); |
+ } |
+ |
+ // ChromeFrameDelegate implementation |
+ virtual WindowType GetWindow() const { |
+ return (static_cast<const T*>(this))->m_hWnd; |
+ } |
+ |
+ virtual void GetBounds(RECT* bounds) { |
+ if (bounds) { |
+ if (::IsWindow(GetWindow())) { |
+ (static_cast<T*>(this))->GetClientRect(bounds); |
+ } |
+ } |
+ } |
+ virtual std::string GetDocumentUrl() { |
+ return document_url_; |
+ } |
+ virtual void OnAutomationServerReady() { |
+ // Issue the extension automation request if we're privileged to |
+ // allow this control to handle extension requests from Chrome. |
+ if (is_privileged_) |
+ automation_client_->SetEnableExtensionAutomation(true); |
+ } |
+ |
+ virtual bool IsValid() const { |
+ return automation_client_.get() != NULL; |
+ } |
+ |
+ protected: |
+ virtual void OnNavigationFailed(int tab_handle, int error_code, |
+ const GURL& gurl) { |
+ OnLoadFailed(error_code, gurl.spec()); |
+ } |
+ |
+ virtual void OnHandleContextMenu(int tab_handle, HANDLE menu_handle, |
+ int x_pos, int y_pos, int align_flags) { |
+ if (!menu_handle || !automation_client_.get()) { |
+ NOTREACHED(); |
+ return; |
+ } |
+ |
+ // TrackPopupMenuEx call will fail on IE on Vista running |
+ // in low integrity mode. We DO seem to be able to enumerate the menu |
+ // though, so just clone it and show the copy: |
+ HMENU copy = UtilCloneContextMenu(static_cast<HMENU>(menu_handle)); |
+ if (!copy) |
+ return; |
+ |
+ 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)) { |
+ automation_client_->SendContextMenuCommandToChromeFrame(selected); |
+ } |
+ } |
+ |
+ DestroyMenu(copy); |
+ } |
+ |
+ LRESULT OnSetFocus(UINT message, WPARAM wparam, LPARAM lparam, |
+ BOOL& handled) { // NO_LINT |
+ if (!ignore_setfocus_ && automation_client_ != NULL) { |
+ TabProxy* tab = automation_client_->tab(); |
+ HWND chrome_window = automation_client_->tab_window(); |
+ if (tab && ::IsWindow(chrome_window)) { |
+ DLOG(INFO) << "Setting initial focus"; |
+ tab->SetInitialFocus(win_util::IsShiftPressed()); |
+ } |
+ } |
+ |
+ return 0; |
+ } |
+ |
+ LRESULT OnSize(UINT message, WPARAM wparam, LPARAM lparam, |
+ BOOL& handled) { // NO_LINT |
+ handled = FALSE; |
+ // When we get resized, we need to resize the external tab window too. |
+ if (automation_client_.get()) |
+ automation_client_->Resize(LOWORD(lparam), HIWORD(lparam), |
+ SWP_NOACTIVATE | SWP_NOZORDER); |
+ return 0; |
+ } |
+ |
+ LRESULT OnParentNotify(UINT message, WPARAM wparam, LPARAM lparam, |
+ BOOL& handled) { // NO_LINT |
+ switch (LOWORD(wparam)) { |
+ case WM_LBUTTONDOWN: |
+ case WM_MBUTTONDOWN: |
+ case WM_RBUTTONDOWN: |
+ case WM_XBUTTONDOWN: { |
+ // If we got activated via mouse click on the external tab, |
+ // we need to update the state of this thread and tell the |
+ // browser that we now have the focus. |
+ HWND focus = ::GetFocus(); |
+ HWND plugin_window = GetWindow(); |
+ if (focus != plugin_window && !IsChild(plugin_window, focus)) { |
+ ignore_setfocus_ = true; |
+ SetFocus(plugin_window); |
+ ignore_setfocus_ = false; |
+ } |
+ break; |
+ } |
+ } |
+ |
+ return 0; |
+ } |
+ |
+ // Return true if context menu should be displayed. The menu could be |
+ // modified as well (enable/disable commands, add/remove items). |
+ // Override in most-derived class if needed. |
+ bool PreProcessContextMenu(HMENU menu) { |
+ // Add an "About" item. |
+ // TODO: The string should be localized and menu should |
+ // be modified in ExternalTabContainer:: once we go public. |
+ AppendMenu(menu, MF_STRING, IDC_ABOUT_CHROME_FRAME, |
+ L"About Chrome Frame..."); |
+ return true; |
+ } |
+ |
+ // 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) { |
+ return false; |
+ } |
+ |
+ // Allow overriding the type of automation client used, for unit tests. |
+ virtual ChromeFrameAutomationClient* CreateAutomationClient() { |
+ return new ChromeFrameAutomationClient; |
+ } |
+ |
+ protected: |
+ // Our gateway to chrome land |
+ scoped_ptr<ChromeFrameAutomationClient> automation_client_; |
+ |
+ // Url of the containing document. |
+ std::string document_url_; |
+ |
+ // We set this flag when we're taking the focus ourselves |
+ // and notifying the host browser that we're doing so. |
+ // When the flag is not set, we transfer the focus to chrome. |
+ bool ignore_setfocus_; |
+ |
+ // The plugin is privileged if it is: |
+ // * Invoked by a window running under the system principal in FireFox. |
+ // * Being hosted by a custom host exposing the SID_ChromeFramePrivileged |
+ // service. |
+ // |
+ // When privileged, additional interfaces are made available to the user. |
+ bool is_privileged_; |
+}; |
+ |
+#endif // CHROME_FRAME_CHROME_FRAME_PLUGIN_H_ |
+ |