OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #ifndef CHROME_FRAME_CHROME_FRAME_PLUGIN_H_ |
| 6 #define CHROME_FRAME_CHROME_FRAME_PLUGIN_H_ |
| 7 |
| 8 #include "base/win_util.h" |
| 9 #include "chrome_frame/chrome_frame_automation.h" |
| 10 #include "chrome_frame/utils.h" |
| 11 |
| 12 #define IDC_ABOUT_CHROME_FRAME 40018 |
| 13 |
| 14 // A class to implement common functionality for all types of |
| 15 // plugins: NPAPI. ActiveX and ActiveDoc |
| 16 template <typename T> |
| 17 class ChromeFramePlugin : public ChromeFrameDelegateImpl { |
| 18 public: |
| 19 ChromeFramePlugin() |
| 20 : ignore_setfocus_(false), |
| 21 is_privileged_(false) { |
| 22 } |
| 23 ~ChromeFramePlugin() { |
| 24 Uninitialize(); |
| 25 } |
| 26 |
| 27 BEGIN_MSG_MAP(ChromeFrameActivex) |
| 28 MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) |
| 29 MESSAGE_HANDLER(WM_SIZE, OnSize) |
| 30 MESSAGE_HANDLER(WM_PARENTNOTIFY, OnParentNotify) |
| 31 END_MSG_MAP() |
| 32 |
| 33 bool Initialize() { |
| 34 DCHECK(!automation_client_.get()); |
| 35 automation_client_.reset(CreateAutomationClient()); |
| 36 if (!automation_client_.get()) { |
| 37 NOTREACHED() << "new ChromeFrameAutomationClient"; |
| 38 return false; |
| 39 } |
| 40 |
| 41 return true; |
| 42 } |
| 43 |
| 44 void Uninitialize() { |
| 45 if (automation_client_.get()) { |
| 46 automation_client_->Uninitialize(); |
| 47 automation_client_.reset(); |
| 48 } |
| 49 } |
| 50 |
| 51 bool InitializeAutomation(const std::wstring& profile_name, |
| 52 const std::wstring& extra_chrome_arguments, |
| 53 bool incognito) { |
| 54 // We don't want to do incognito when privileged, since we're |
| 55 // running in browser chrome or some other privileged context. |
| 56 bool incognito_mode = !is_privileged_ && incognito; |
| 57 return automation_client_->Initialize(this, kCommandExecutionTimeout, true, |
| 58 profile_name, extra_chrome_arguments, |
| 59 incognito_mode); |
| 60 } |
| 61 |
| 62 // ChromeFrameDelegate implementation |
| 63 virtual WindowType GetWindow() const { |
| 64 return (static_cast<const T*>(this))->m_hWnd; |
| 65 } |
| 66 |
| 67 virtual void GetBounds(RECT* bounds) { |
| 68 if (bounds) { |
| 69 if (::IsWindow(GetWindow())) { |
| 70 (static_cast<T*>(this))->GetClientRect(bounds); |
| 71 } |
| 72 } |
| 73 } |
| 74 virtual std::string GetDocumentUrl() { |
| 75 return document_url_; |
| 76 } |
| 77 virtual void OnAutomationServerReady() { |
| 78 // Issue the extension automation request if we're privileged to |
| 79 // allow this control to handle extension requests from Chrome. |
| 80 if (is_privileged_) |
| 81 automation_client_->SetEnableExtensionAutomation(true); |
| 82 } |
| 83 |
| 84 virtual bool IsValid() const { |
| 85 return automation_client_.get() != NULL; |
| 86 } |
| 87 |
| 88 protected: |
| 89 virtual void OnNavigationFailed(int tab_handle, int error_code, |
| 90 const GURL& gurl) { |
| 91 OnLoadFailed(error_code, gurl.spec()); |
| 92 } |
| 93 |
| 94 virtual void OnHandleContextMenu(int tab_handle, HANDLE menu_handle, |
| 95 int x_pos, int y_pos, int align_flags) { |
| 96 if (!menu_handle || !automation_client_.get()) { |
| 97 NOTREACHED(); |
| 98 return; |
| 99 } |
| 100 |
| 101 // TrackPopupMenuEx call will fail on IE on Vista running |
| 102 // in low integrity mode. We DO seem to be able to enumerate the menu |
| 103 // though, so just clone it and show the copy: |
| 104 HMENU copy = UtilCloneContextMenu(static_cast<HMENU>(menu_handle)); |
| 105 if (!copy) |
| 106 return; |
| 107 |
| 108 T* pThis = static_cast<T*>(this); |
| 109 if (pThis->PreProcessContextMenu(copy)) { |
| 110 UINT flags = align_flags | TPM_LEFTBUTTON | TPM_RETURNCMD | TPM_RECURSE; |
| 111 UINT selected = TrackPopupMenuEx(copy, flags, x_pos, y_pos, GetWindow(), |
| 112 NULL); |
| 113 if (selected != 0 && !pThis->HandleContextMenuCommand(selected)) { |
| 114 automation_client_->SendContextMenuCommandToChromeFrame(selected); |
| 115 } |
| 116 } |
| 117 |
| 118 DestroyMenu(copy); |
| 119 } |
| 120 |
| 121 LRESULT OnSetFocus(UINT message, WPARAM wparam, LPARAM lparam, |
| 122 BOOL& handled) { // NO_LINT |
| 123 if (!ignore_setfocus_ && automation_client_ != NULL) { |
| 124 TabProxy* tab = automation_client_->tab(); |
| 125 HWND chrome_window = automation_client_->tab_window(); |
| 126 if (tab && ::IsWindow(chrome_window)) { |
| 127 DLOG(INFO) << "Setting initial focus"; |
| 128 tab->SetInitialFocus(win_util::IsShiftPressed()); |
| 129 } |
| 130 } |
| 131 |
| 132 return 0; |
| 133 } |
| 134 |
| 135 LRESULT OnSize(UINT message, WPARAM wparam, LPARAM lparam, |
| 136 BOOL& handled) { // NO_LINT |
| 137 handled = FALSE; |
| 138 // When we get resized, we need to resize the external tab window too. |
| 139 if (automation_client_.get()) |
| 140 automation_client_->Resize(LOWORD(lparam), HIWORD(lparam), |
| 141 SWP_NOACTIVATE | SWP_NOZORDER); |
| 142 return 0; |
| 143 } |
| 144 |
| 145 LRESULT OnParentNotify(UINT message, WPARAM wparam, LPARAM lparam, |
| 146 BOOL& handled) { // NO_LINT |
| 147 switch (LOWORD(wparam)) { |
| 148 case WM_LBUTTONDOWN: |
| 149 case WM_MBUTTONDOWN: |
| 150 case WM_RBUTTONDOWN: |
| 151 case WM_XBUTTONDOWN: { |
| 152 // If we got activated via mouse click on the external tab, |
| 153 // we need to update the state of this thread and tell the |
| 154 // browser that we now have the focus. |
| 155 HWND focus = ::GetFocus(); |
| 156 HWND plugin_window = GetWindow(); |
| 157 if (focus != plugin_window && !IsChild(plugin_window, focus)) { |
| 158 ignore_setfocus_ = true; |
| 159 SetFocus(plugin_window); |
| 160 ignore_setfocus_ = false; |
| 161 } |
| 162 break; |
| 163 } |
| 164 } |
| 165 |
| 166 return 0; |
| 167 } |
| 168 |
| 169 // Return true if context menu should be displayed. The menu could be |
| 170 // modified as well (enable/disable commands, add/remove items). |
| 171 // Override in most-derived class if needed. |
| 172 bool PreProcessContextMenu(HMENU menu) { |
| 173 // Add an "About" item. |
| 174 // TODO: The string should be localized and menu should |
| 175 // be modified in ExternalTabContainer:: once we go public. |
| 176 AppendMenu(menu, MF_STRING, IDC_ABOUT_CHROME_FRAME, |
| 177 L"About Chrome Frame..."); |
| 178 return true; |
| 179 } |
| 180 |
| 181 // Return true if menu command is processed, otherwise the command will be |
| 182 // passed to Chrome for execution. Override in most-derived class if needed. |
| 183 bool HandleContextMenuCommand(UINT cmd) { |
| 184 return false; |
| 185 } |
| 186 |
| 187 // Allow overriding the type of automation client used, for unit tests. |
| 188 virtual ChromeFrameAutomationClient* CreateAutomationClient() { |
| 189 return new ChromeFrameAutomationClient; |
| 190 } |
| 191 |
| 192 protected: |
| 193 // Our gateway to chrome land |
| 194 scoped_ptr<ChromeFrameAutomationClient> automation_client_; |
| 195 |
| 196 // Url of the containing document. |
| 197 std::string document_url_; |
| 198 |
| 199 // We set this flag when we're taking the focus ourselves |
| 200 // and notifying the host browser that we're doing so. |
| 201 // When the flag is not set, we transfer the focus to chrome. |
| 202 bool ignore_setfocus_; |
| 203 |
| 204 // The plugin is privileged if it is: |
| 205 // * Invoked by a window running under the system principal in FireFox. |
| 206 // * Being hosted by a custom host exposing the SID_ChromeFramePrivileged |
| 207 // service. |
| 208 // |
| 209 // When privileged, additional interfaces are made available to the user. |
| 210 bool is_privileged_; |
| 211 }; |
| 212 |
| 213 #endif // CHROME_FRAME_CHROME_FRAME_PLUGIN_H_ |
| 214 |
OLD | NEW |