blob: 51106aba9663c592dc4154f14580a93433950a75 [file] [log] [blame]
[email protected]3b63f8f42011-03-28 01:54:151// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]f7817822009-09-24 05:11:582// 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
[email protected]bbfa9a12010-08-10 14:09:378#include <string>
9#include <vector>
10
[email protected]3b63f8f42011-03-28 01:54:1511#include "base/memory/ref_counted.h"
[email protected]a8e20582010-12-31 17:18:5012#include "base/win/win_util.h"
[email protected]f7817822009-09-24 05:11:5813#include "chrome_frame/chrome_frame_automation.h"
[email protected]bc73b4e52010-03-26 04:16:2014#include "chrome/common/chrome_paths.h"
15#include "chrome/common/chrome_paths_internal.h"
[email protected]36a26ed2010-03-24 03:09:0516#include "chrome_frame/simple_resource_loader.h"
[email protected]0753db592010-12-15 14:45:0517#include "chrome_frame/navigation_constraints.h"
[email protected]f7817822009-09-24 05:11:5818#include "chrome_frame/utils.h"
[email protected]36a26ed2010-03-24 03:09:0519#include "grit/chromium_strings.h"
20
[email protected]f7817822009-09-24 05:11:5821#define IDC_ABOUT_CHROME_FRAME 40018
22
[email protected]a22f7e02011-02-09 07:15:3523// Helper so that this file doesn't include the messages header.
24void ChromeFramePluginGetParamsCoordinates(
25 const MiniContextMenuParams& params,
26 int* x,
27 int* y);
28
[email protected]f7817822009-09-24 05:11:5829// A class to implement common functionality for all types of
[email protected]99d81e5b2011-06-29 02:29:5330// plugins: ActiveX and ActiveDoc
[email protected]f7817822009-09-24 05:11:5831template <typename T>
[email protected]0753db592010-12-15 14:45:0532class ChromeFramePlugin
33 : public ChromeFrameDelegateImpl,
34 public NavigationConstraintsImpl {
[email protected]f7817822009-09-24 05:11:5835 public:
[email protected]0753db592010-12-15 14:45:0536 ChromeFramePlugin() : ignore_setfocus_(false){
[email protected]f7817822009-09-24 05:11:5837 }
38 ~ChromeFramePlugin() {
39 Uninitialize();
40 }
41
[email protected]045229a72010-03-03 22:11:1942BEGIN_MSG_MAP(T)
[email protected]f7817822009-09-24 05:11:5843 MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
44 MESSAGE_HANDLER(WM_SIZE, OnSize)
45 MESSAGE_HANDLER(WM_PARENTNOTIFY, OnParentNotify)
46END_MSG_MAP()
47
48 bool Initialize() {
[email protected]2b9a9f162010-10-19 20:30:4549 DVLOG(1) << __FUNCTION__;
[email protected]f7817822009-09-24 05:11:5850 DCHECK(!automation_client_.get());
[email protected]b0febbf2009-11-12 17:49:3551 automation_client_ = CreateAutomationClient();
[email protected]f7817822009-09-24 05:11:5852 if (!automation_client_.get()) {
53 NOTREACHED() << "new ChromeFrameAutomationClient";
54 return false;
55 }
56
57 return true;
58 }
59
60 void Uninitialize() {
[email protected]2b9a9f162010-10-19 20:30:4561 DVLOG(1) << __FUNCTION__;
[email protected]045229a72010-03-03 22:11:1962 if (IsValid()) {
[email protected]f7817822009-09-24 05:11:5863 automation_client_->Uninitialize();
[email protected]b0febbf2009-11-12 17:49:3564 automation_client_ = NULL;
[email protected]f7817822009-09-24 05:11:5865 }
66 }
67
68 bool InitializeAutomation(const std::wstring& profile_name,
69 const std::wstring& extra_chrome_arguments,
[email protected]e150e822010-06-03 23:10:5570 bool incognito, bool is_widget_mode,
[email protected]9eeb35e2010-09-30 21:38:5071 const GURL& url, const GURL& referrer,
72 bool route_all_top_level_navigations) {
[email protected]045229a72010-03-03 22:11:1973 DCHECK(IsValid());
[email protected]bbfa9a12010-08-10 14:09:3774 DCHECK(launch_params_ == NULL);
[email protected]f7817822009-09-24 05:11:5875 // We don't want to do incognito when privileged, since we're
76 // running in browser chrome or some other privileged context.
[email protected]0753db592010-12-15 14:45:0577 bool incognito_mode = !is_privileged() && incognito;
[email protected]bc73b4e52010-03-26 04:16:2078 FilePath profile_path;
79 GetProfilePath(profile_name, &profile_path);
[email protected]1d27bbe2010-09-10 00:32:0680 // The profile name could change based on the browser version. For e.g. for
81 // IE6/7 the profile is created in a different folder whose last component
82 // is Google Chrome Frame.
83 FilePath actual_profile_name = profile_path.BaseName();
[email protected]bbfa9a12010-08-10 14:09:3784 launch_params_ = new ChromeFrameLaunchParams(url, referrer, profile_path,
[email protected]6ae3d492010-10-20 14:01:2185 actual_profile_name.value(), SimpleResourceLoader::GetLanguage(),
86 extra_chrome_arguments, incognito_mode, is_widget_mode,
87 route_all_top_level_navigations);
[email protected]bbfa9a12010-08-10 14:09:3788 return automation_client_->Initialize(this, launch_params_);
[email protected]f7817822009-09-24 05:11:5889 }
90
91 // ChromeFrameDelegate implementation
92 virtual WindowType GetWindow() const {
93 return (static_cast<const T*>(this))->m_hWnd;
94 }
95
96 virtual void GetBounds(RECT* bounds) {
97 if (bounds) {
98 if (::IsWindow(GetWindow())) {
99 (static_cast<T*>(this))->GetClientRect(bounds);
100 }
101 }
102 }
103 virtual std::string GetDocumentUrl() {
104 return document_url_;
105 }
106 virtual void OnAutomationServerReady() {
[email protected]f7817822009-09-24 05:11:58107 }
108
109 virtual bool IsValid() const {
110 return automation_client_.get() != NULL;
111 }
112
[email protected]2b19e2fe2010-02-16 02:24:18113 virtual void OnHostMoved() {
[email protected]045229a72010-03-03 22:11:19114 if (IsValid())
115 automation_client_->OnChromeFrameHostMoved();
[email protected]2b19e2fe2010-02-16 02:24:18116 }
117
[email protected]f7817822009-09-24 05:11:58118 protected:
[email protected]f5494d42010-12-23 22:15:34119 virtual void OnNavigationFailed(int error_code, const GURL& gurl) {
[email protected]f7817822009-09-24 05:11:58120 OnLoadFailed(error_code, gurl.spec());
121 }
122
[email protected]b516e2d2011-07-12 16:54:12123 virtual void OnHandleContextMenu(const ContextMenuModel& menu_model,
[email protected]35f13ab2009-12-16 23:59:17124 int align_flags,
[email protected]f5494d42010-12-23 22:15:34125 const MiniContextMenuParams& params) {
[email protected]b516e2d2011-07-12 16:54:12126 if (!automation_client_.get()) {
[email protected]f7817822009-09-24 05:11:58127 NOTREACHED();
128 return;
129 }
130
[email protected]b516e2d2011-07-12 16:54:12131 HMENU menu = BuildContextMenu(menu_model);
132 if (!menu)
[email protected]f7817822009-09-24 05:11:58133 return;
134
[email protected]4e676aa2010-02-12 18:19:07135 T* self = static_cast<T*>(this);
[email protected]b516e2d2011-07-12 16:54:12136 if (self->PreProcessContextMenu(menu)) {
[email protected]4e676aa2010-02-12 18:19:07137 // In order for the context menu to handle keyboard input, give the
138 // ActiveX window focus.
139 ignore_setfocus_ = true;
140 SetFocus(GetWindow());
141 ignore_setfocus_ = false;
[email protected]f7817822009-09-24 05:11:58142 UINT flags = align_flags | TPM_LEFTBUTTON | TPM_RETURNCMD | TPM_RECURSE;
[email protected]a22f7e02011-02-09 07:15:35143 int x, y;
144 ChromeFramePluginGetParamsCoordinates(params, &x, &y);
[email protected]b516e2d2011-07-12 16:54:12145 UINT selected = TrackPopupMenuEx(menu, flags, x, y, GetWindow(), NULL);
[email protected]4e676aa2010-02-12 18:19:07146 // Menu is over now give focus back to chrome
[email protected]1fd45692010-04-19 21:01:18147 GiveFocusToChrome(false);
[email protected]045229a72010-03-03 22:11:19148 if (IsValid() && selected != 0 &&
149 !self->HandleContextMenuCommand(selected, params)) {
[email protected]f7817822009-09-24 05:11:58150 automation_client_->SendContextMenuCommandToChromeFrame(selected);
151 }
152 }
153
[email protected]b516e2d2011-07-12 16:54:12154 DestroyMenu(menu);
[email protected]f7817822009-09-24 05:11:58155 }
156
157 LRESULT OnSetFocus(UINT message, WPARAM wparam, LPARAM lparam,
158 BOOL& handled) { // NO_LINT
[email protected]045229a72010-03-03 22:11:19159 if (!ignore_setfocus_ && IsValid()) {
[email protected]26edf1d2010-10-13 17:53:04160 // Pass false to |restore_focus_view|, because we do not want Chrome
161 // to focus the first focusable element in the current view, only the
162 // view itself.
163 GiveFocusToChrome(false);
[email protected]f7817822009-09-24 05:11:58164 }
[email protected]f7817822009-09-24 05:11:58165 return 0;
166 }
167
168 LRESULT OnSize(UINT message, WPARAM wparam, LPARAM lparam,
169 BOOL& handled) { // NO_LINT
170 handled = FALSE;
171 // When we get resized, we need to resize the external tab window too.
[email protected]045229a72010-03-03 22:11:19172 if (IsValid())
[email protected]f7817822009-09-24 05:11:58173 automation_client_->Resize(LOWORD(lparam), HIWORD(lparam),
174 SWP_NOACTIVATE | SWP_NOZORDER);
175 return 0;
176 }
177
178 LRESULT OnParentNotify(UINT message, WPARAM wparam, LPARAM lparam,
179 BOOL& handled) { // NO_LINT
180 switch (LOWORD(wparam)) {
181 case WM_LBUTTONDOWN:
182 case WM_MBUTTONDOWN:
183 case WM_RBUTTONDOWN:
184 case WM_XBUTTONDOWN: {
185 // If we got activated via mouse click on the external tab,
186 // we need to update the state of this thread and tell the
187 // browser that we now have the focus.
188 HWND focus = ::GetFocus();
189 HWND plugin_window = GetWindow();
[email protected]01e79d82010-09-07 20:34:42190
191 // The Chrome-Frame instance may have launched a popup which currently
192 // has focus. Because experimental extension popups are top-level
193 // windows, we have to check that the focus has shifted to a window
194 // that does not share the same GA_ROOTOWNER as the plugin.
195 if (focus != plugin_window &&
196 ::GetAncestor(plugin_window, GA_ROOTOWNER) !=
197 ::GetAncestor(focus, GA_ROOTOWNER)) {
[email protected]f7817822009-09-24 05:11:58198 ignore_setfocus_ = true;
199 SetFocus(plugin_window);
200 ignore_setfocus_ = false;
201 }
202 break;
203 }
204 }
205
206 return 0;
207 }
208
209 // Return true if context menu should be displayed. The menu could be
210 // modified as well (enable/disable commands, add/remove items).
211 // Override in most-derived class if needed.
212 bool PreProcessContextMenu(HMENU menu) {
[email protected]50f53162009-10-23 19:16:20213 // Add an "About" item.
[email protected]f7817822009-09-24 05:11:58214 AppendMenu(menu, MF_STRING, IDC_ABOUT_CHROME_FRAME,
[email protected]36a26ed2010-03-24 03:09:05215 SimpleResourceLoader::Get(IDS_CHROME_FRAME_MENU_ABOUT).c_str());
[email protected]f7817822009-09-24 05:11:58216 return true;
217 }
218
219 // Return true if menu command is processed, otherwise the command will be
220 // passed to Chrome for execution. Override in most-derived class if needed.
[email protected]e150e822010-06-03 23:10:55221 bool HandleContextMenuCommand(UINT cmd,
[email protected]f5494d42010-12-23 22:15:34222 const MiniContextMenuParams& params) {
[email protected]f7817822009-09-24 05:11:58223 return false;
224 }
225
226 // Allow overriding the type of automation client used, for unit tests.
227 virtual ChromeFrameAutomationClient* CreateAutomationClient() {
228 return new ChromeFrameAutomationClient;
229 }
230
[email protected]1fd45692010-04-19 21:01:18231 void GiveFocusToChrome(bool restore_focus_to_view) {
[email protected]045229a72010-03-03 22:11:19232 if (IsValid()) {
233 TabProxy* tab = automation_client_->tab();
234 HWND chrome_window = automation_client_->tab_window();
235 if (tab && ::IsWindow(chrome_window)) {
[email protected]2b9a9f162010-10-19 20:30:45236 DVLOG(1) << "Setting initial focus";
[email protected]a8e20582010-12-31 17:18:50237 tab->SetInitialFocus(base::win::IsShiftPressed(), restore_focus_to_view);
[email protected]045229a72010-03-03 22:11:19238 }
[email protected]b95f550f2009-11-19 05:35:22239 }
240 }
241
[email protected]bc73b4e52010-03-26 04:16:20242 virtual void GetProfilePath(const std::wstring& profile_name,
243 FilePath* profile_path) {
244 chrome::GetChromeFrameUserDataDirectory(profile_path);
245 *profile_path = profile_path->Append(profile_name);
[email protected]2b9a9f162010-10-19 20:30:45246 DVLOG(1) << __FUNCTION__ << ": " << profile_path->value();
[email protected]bc73b4e52010-03-26 04:16:20247 }
248
[email protected]f7817822009-09-24 05:11:58249 protected:
250 // Our gateway to chrome land
[email protected]b0febbf2009-11-12 17:49:35251 scoped_refptr<ChromeFrameAutomationClient> automation_client_;
[email protected]f7817822009-09-24 05:11:58252
[email protected]bbfa9a12010-08-10 14:09:37253 // How we launched Chrome.
254 scoped_refptr<ChromeFrameLaunchParams> launch_params_;
255
[email protected]f7817822009-09-24 05:11:58256 // Url of the containing document.
257 std::string document_url_;
258
259 // We set this flag when we're taking the focus ourselves
260 // and notifying the host browser that we're doing so.
261 // When the flag is not set, we transfer the focus to chrome.
262 bool ignore_setfocus_;
[email protected]f7817822009-09-24 05:11:58263};
264
265#endif // CHROME_FRAME_CHROME_FRAME_PLUGIN_H_