Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(694)

Side by Side Diff: chrome_frame/chrome_frame_activex.cc

Issue 126143005: Remove Chrome Frame code and resources. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: sync to r244038 Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome_frame/chrome_frame_activex.h ('k') | chrome_frame/chrome_frame_activex.rgs » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 #include "chrome_frame/chrome_frame_activex.h"
6
7 #include <wininet.h>
8
9 #include <algorithm>
10 #include <map>
11
12 #include "base/basictypes.h"
13 #include "base/command_line.h"
14 #include "base/debug/trace_event.h"
15 #include "base/logging.h"
16 #include "base/memory/singleton.h"
17 #include "base/path_service.h"
18 #include "base/strings/string_split.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/stringprintf.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/win/scoped_bstr.h"
23 #include "base/win/scoped_variant.h"
24 #include "chrome/common/automation_messages.h"
25 #include "chrome/common/chrome_constants.h"
26 #include "chrome/common/chrome_switches.h"
27 #include "chrome/test/automation/tab_proxy.h"
28 #include "chrome_frame/utils.h"
29 #include "url/gurl.h"
30
31 namespace {
32
33 // Class used to maintain a mapping from top-level windows to ChromeFrameActivex
34 // instances.
35 class TopLevelWindowMapping {
36 public:
37 typedef std::vector<HWND> WindowList;
38
39 static TopLevelWindowMapping* GetInstance() {
40 return Singleton<TopLevelWindowMapping>::get();
41 }
42
43 // Add |cf_window| to the set of windows registered under |top_window|.
44 void AddMapping(HWND top_window, HWND cf_window) {
45 top_window_map_lock_.Lock();
46 top_window_map_[top_window].push_back(cf_window);
47 top_window_map_lock_.Unlock();
48 }
49
50 // Return the set of Chrome-Frame instances under |window|.
51 WindowList GetInstances(HWND window) {
52 top_window_map_lock_.Lock();
53 WindowList list = top_window_map_[window];
54 top_window_map_lock_.Unlock();
55 return list;
56 }
57
58 private:
59 // Constructor is private as this class it to be used as a singleton.
60 // See static method instance().
61 TopLevelWindowMapping() {}
62
63 friend struct DefaultSingletonTraits<TopLevelWindowMapping>;
64
65 typedef std::map<HWND, WindowList> TopWindowMap;
66 TopWindowMap top_window_map_;
67
68 CComAutoCriticalSection top_window_map_lock_;
69
70 DISALLOW_COPY_AND_ASSIGN(TopLevelWindowMapping);
71 };
72
73 } // unnamed namespace
74
75 ChromeFrameActivex::ChromeFrameActivex()
76 : chrome_wndproc_hook_(NULL),
77 attaching_to_existing_cf_tab_(false) {
78 TRACE_EVENT_BEGIN_ETW("chromeframe.createactivex", this, "");
79 }
80
81 HRESULT ChromeFrameActivex::FinalConstruct() {
82 HRESULT hr = Base::FinalConstruct();
83 if (FAILED(hr))
84 return hr;
85
86 // No need to call FireOnChanged at this point since nobody will be listening.
87 ready_state_ = READYSTATE_LOADING;
88 return S_OK;
89 }
90
91 ChromeFrameActivex::~ChromeFrameActivex() {
92 // We expect these to be released during a call to SetClientSite(NULL).
93 DCHECK_EQ(0u, onmessage_.size());
94 DCHECK_EQ(0u, onloaderror_.size());
95 DCHECK_EQ(0u, onload_.size());
96 DCHECK_EQ(0u, onreadystatechanged_.size());
97 DCHECK_EQ(0u, onextensionready_.size());
98
99 if (chrome_wndproc_hook_) {
100 BOOL unhook_success = ::UnhookWindowsHookEx(chrome_wndproc_hook_);
101 DCHECK(unhook_success);
102 }
103
104 // ChromeFramePlugin::Uninitialize()
105 Base::Uninitialize();
106
107 TRACE_EVENT_END_ETW("chromeframe.createactivex", this, "");
108 }
109
110 LRESULT ChromeFrameActivex::OnCreate(UINT message, WPARAM wparam, LPARAM lparam,
111 BOOL& handled) {
112 Base::OnCreate(message, wparam, lparam, handled);
113 // Install the notification hook on the top-level window, so that we can
114 // be notified on move events. Note that the return value is not checked.
115 // This hook is installed here, as opposed to during IOleObject_SetClientSite
116 // because m_hWnd has not yet been assigned during the SetSite call.
117 InstallTopLevelHook(m_spClientSite);
118 return 0;
119 }
120
121 HRESULT ChromeFrameActivex::GetContainingDocument(IHTMLDocument2** doc) {
122 base::win::ScopedComPtr<IOleContainer> container;
123 HRESULT hr = m_spClientSite->GetContainer(container.Receive());
124 if (container)
125 hr = container.QueryInterface(doc);
126 return hr;
127 }
128
129 HRESULT ChromeFrameActivex::GetDocumentWindow(IHTMLWindow2** window) {
130 base::win::ScopedComPtr<IHTMLDocument2> document;
131 HRESULT hr = GetContainingDocument(document.Receive());
132 if (document)
133 hr = document->get_parentWindow(window);
134 return hr;
135 }
136
137 void ChromeFrameActivex::OnLoadFailed(int error_code, const std::string& url) {
138 base::win::ScopedComPtr<IDispatch> event;
139 if (SUCCEEDED(CreateDomEvent("event", url, "", event.Receive())))
140 Fire_onloaderror(event);
141
142 FireEvent(onloaderror_, url);
143 Base::OnLoadFailed(error_code, url);
144 }
145
146 bool ChromeFrameActivex::ShouldShowVersionMismatchDialog(
147 bool is_privileged,
148 IOleClientSite* client_site) {
149 if (!is_privileged) {
150 return true;
151 }
152
153 if (client_site) {
154 base::win::ScopedComPtr<IChromeFramePrivileged> service;
155 HRESULT hr = DoQueryService(SID_ChromeFramePrivileged,
156 client_site,
157 service.Receive());
158 if (SUCCEEDED(hr) && service) {
159 return (S_FALSE != service->ShouldShowVersionMismatchDialog());
160 }
161 }
162
163 NOTREACHED();
164 return true;
165 }
166
167 void ChromeFrameActivex::OnAutomationServerLaunchFailed(
168 AutomationLaunchResult reason, const std::string& server_version) {
169 Base::OnAutomationServerLaunchFailed(reason, server_version);
170
171 if (reason == AUTOMATION_VERSION_MISMATCH &&
172 ShouldShowVersionMismatchDialog(is_privileged(), m_spClientSite)) {
173 UMA_HISTOGRAM_COUNTS("ChromeFrame.VersionMismatchDisplayed", 1);
174 DisplayVersionMismatchWarning(m_hWnd, server_version);
175 }
176 }
177
178 void ChromeFrameActivex::OnChannelError() {
179 Fire_onchannelerror();
180 }
181
182 HRESULT ChromeFrameActivex::OnDraw(ATL_DRAWINFO& draw_info) { // NOLINT
183 HRESULT hr = S_OK;
184 int dc_type = ::GetObjectType(draw_info.hicTargetDev);
185 if (dc_type == OBJ_ENHMETADC) {
186 RECT print_bounds = {0};
187 print_bounds.left = draw_info.prcBounds->left;
188 print_bounds.right = draw_info.prcBounds->right;
189 print_bounds.top = draw_info.prcBounds->top;
190 print_bounds.bottom = draw_info.prcBounds->bottom;
191
192 automation_client_->Print(draw_info.hdcDraw, print_bounds);
193 } else {
194 hr = Base::OnDraw(draw_info);
195 }
196
197 return hr;
198 }
199
200 STDMETHODIMP ChromeFrameActivex::Load(IPropertyBag* bag, IErrorLog* error_log) {
201 DCHECK(bag);
202
203 const wchar_t* event_props[] = {
204 (L"onload"),
205 (L"onloaderror"),
206 (L"onmessage"),
207 (L"onreadystatechanged"),
208 };
209
210 base::win::ScopedComPtr<IHTMLObjectElement> obj_element;
211 GetObjectElement(obj_element.Receive());
212
213 base::win::ScopedBstr object_id;
214 GetObjectScriptId(obj_element, object_id.Receive());
215
216 base::win::ScopedComPtr<IHTMLElement2> element;
217 element.QueryFrom(obj_element);
218 HRESULT hr = S_OK;
219
220 for (int i = 0; SUCCEEDED(hr) && i < arraysize(event_props); ++i) {
221 base::win::ScopedBstr prop(event_props[i]);
222 base::win::ScopedVariant value;
223 if (SUCCEEDED(bag->Read(prop, value.Receive(), error_log))) {
224 if (value.type() != VT_BSTR ||
225 FAILED(hr = CreateScriptBlockForEvent(element, object_id,
226 V_BSTR(&value), prop))) {
227 DLOG(ERROR) << "Failed to create script block for " << prop
228 << base::StringPrintf(L"hr=0x%08X, vt=%i", hr,
229 value.type());
230 } else {
231 DVLOG(1) << "script block created for event " << prop
232 << base::StringPrintf(" (0x%08X)", hr) << " connections: " <<
233 ProxyDIChromeFrameEvents<ChromeFrameActivex>::m_vec.GetSize();
234 }
235 } else {
236 DVLOG(1) << "event property " << prop << " not in property bag";
237 }
238 }
239
240 base::win::ScopedVariant src;
241 if (SUCCEEDED(bag->Read(base::win::ScopedBstr(L"src"), src.Receive(),
242 error_log))) {
243 if (src.type() == VT_BSTR) {
244 hr = put_src(V_BSTR(&src));
245 DCHECK(hr != E_UNEXPECTED);
246 }
247 }
248
249 base::win::ScopedVariant use_chrome_network;
250 if (SUCCEEDED(bag->Read(base::win::ScopedBstr(L"useChromeNetwork"),
251 use_chrome_network.Receive(), error_log))) {
252 VariantChangeType(use_chrome_network.AsInput(),
253 use_chrome_network.AsInput(),
254 0, VT_BOOL);
255 if (use_chrome_network.type() == VT_BOOL) {
256 hr = put_useChromeNetwork(V_BOOL(&use_chrome_network));
257 DCHECK(hr != E_UNEXPECTED);
258 }
259 }
260
261 DLOG_IF(ERROR, FAILED(hr))
262 << base::StringPrintf("Failed to load property bag: 0x%08X", hr);
263
264 return hr;
265 }
266
267 const wchar_t g_activex_insecure_content_error[] = {
268 L"data:text/html,<html><body><b>ChromeFrame Security Error<br><br>"
269 L"Cannot navigate to HTTP url when document URL is HTTPS</body></html>"};
270
271 STDMETHODIMP ChromeFrameActivex::put_src(BSTR src) {
272 GURL document_url(GetDocumentUrl());
273 if (document_url.SchemeIsSecure()) {
274 GURL source_url(src);
275 if (!source_url.SchemeIsSecure()) {
276 Base::put_src(base::win::ScopedBstr(g_activex_insecure_content_error));
277 return E_ACCESSDENIED;
278 }
279 }
280 HRESULT hr = S_OK;
281 // If we are connecting to an existing ExternalTabContainer instance in
282 // Chrome then we should wait for Chrome to initiate the navigation.
283 if (!attaching_to_existing_cf_tab_) {
284 hr = Base::put_src(src);
285 } else {
286 url_.Reset(::SysAllocString(src));
287 attaching_to_existing_cf_tab_ = false;
288 }
289 return S_OK;
290 }
291
292 HRESULT ChromeFrameActivex::IOleObject_SetClientSite(
293 IOleClientSite* client_site) {
294 HRESULT hr = Base::IOleObject_SetClientSite(client_site);
295 if (FAILED(hr) || !client_site) {
296 EventHandlers* handlers[] = {
297 &onmessage_,
298 &onloaderror_,
299 &onload_,
300 &onreadystatechanged_,
301 &onextensionready_,
302 };
303
304 for (int i = 0; i < arraysize(handlers); ++i)
305 handlers[i]->clear();
306
307 // Drop privileged mode on uninitialization.
308 set_is_privileged(false);
309 } else {
310 base::win::ScopedComPtr<IHTMLDocument2> document;
311 GetContainingDocument(document.Receive());
312 if (document) {
313 base::win::ScopedBstr url;
314 if (SUCCEEDED(document->get_URL(url.Receive())))
315 base::WideToUTF8(url, url.Length(), &document_url_);
316 }
317
318 // Probe to see whether the host implements the privileged service.
319 base::win::ScopedComPtr<IChromeFramePrivileged> service;
320 HRESULT service_hr = DoQueryService(SID_ChromeFramePrivileged,
321 m_spClientSite,
322 service.Receive());
323 if (SUCCEEDED(service_hr) && service) {
324 // Does the host want privileged mode?
325 boolean wants_privileged = false;
326 service_hr = service->GetWantsPrivileged(&wants_privileged);
327
328 if (SUCCEEDED(service_hr) && wants_privileged)
329 set_is_privileged(true);
330
331 url_fetcher_->set_privileged_mode(is_privileged());
332 }
333
334 std::wstring profile_name(GetHostProcessName(false));
335 if (is_privileged()) {
336 base::win::ScopedBstr profile_name_arg;
337 service_hr = service->GetChromeProfileName(profile_name_arg.Receive());
338 if (S_OK == service_hr && profile_name_arg)
339 profile_name.assign(profile_name_arg, profile_name_arg.Length());
340 }
341
342 std::string utf8_url;
343 if (url_.Length()) {
344 base::WideToUTF8(url_, url_.Length(), &utf8_url);
345 }
346
347 InitializeAutomationSettings();
348
349
350 url_fetcher_->set_frame_busting(!is_privileged());
351 automation_client_->SetUrlFetcher(url_fetcher_.get());
352 if (!InitializeAutomation(profile_name, IsIEInPrivate(), true,
353 GURL(utf8_url), GURL(), false)) {
354 DLOG(ERROR) << "Failed to navigate to url:" << utf8_url;
355 return E_FAIL;
356 }
357
358 // Log a metric that Chrome Frame is being used in Widget mode
359 UMA_LAUNCH_TYPE_COUNT(RENDERER_TYPE_CHROME_WIDGET);
360 }
361
362 return hr;
363 }
364
365 HRESULT ChromeFrameActivex::GetObjectScriptId(IHTMLObjectElement* object_elem,
366 BSTR* id) {
367 DCHECK(object_elem != NULL);
368 DCHECK(id != NULL);
369
370 HRESULT hr = E_FAIL;
371 if (object_elem) {
372 base::win::ScopedComPtr<IHTMLElement> elem;
373 hr = elem.QueryFrom(object_elem);
374 if (elem) {
375 hr = elem->get_id(id);
376 }
377 }
378
379 return hr;
380 }
381
382 HRESULT ChromeFrameActivex::GetObjectElement(IHTMLObjectElement** element) {
383 DCHECK(m_spClientSite);
384 if (!m_spClientSite)
385 return E_UNEXPECTED;
386
387 base::win::ScopedComPtr<IOleControlSite> site;
388 HRESULT hr = site.QueryFrom(m_spClientSite);
389 if (site) {
390 base::win::ScopedComPtr<IDispatch> disp;
391 hr = site->GetExtendedControl(disp.Receive());
392 if (disp) {
393 hr = disp.QueryInterface(element);
394 } else {
395 DCHECK(FAILED(hr));
396 }
397 }
398
399 return hr;
400 }
401
402 HRESULT ChromeFrameActivex::CreateScriptBlockForEvent(
403 IHTMLElement2* insert_after, BSTR instance_id, BSTR script,
404 BSTR event_name) {
405 DCHECK(insert_after);
406 DCHECK_GT(::SysStringLen(event_name), 0UL); // should always have this
407
408 // This might be 0 if not specified in the HTML document.
409 if (!::SysStringLen(instance_id)) {
410 // TODO(tommi): Should we give ourselves an ID if this happens?
411 NOTREACHED() << "Need to handle this";
412 return E_INVALIDARG;
413 }
414
415 base::win::ScopedComPtr<IHTMLDocument2> document;
416 HRESULT hr = GetContainingDocument(document.Receive());
417 if (SUCCEEDED(hr)) {
418 base::win::ScopedComPtr<IHTMLElement> element, new_element;
419 document->createElement(base::win::ScopedBstr(L"script"),
420 element.Receive());
421 if (element) {
422 base::win::ScopedComPtr<IHTMLScriptElement> script_element;
423 if (SUCCEEDED(hr = script_element.QueryFrom(element))) {
424 script_element->put_htmlFor(instance_id);
425 script_element->put_event(event_name);
426 script_element->put_text(script);
427
428 hr = insert_after->insertAdjacentElement(
429 base::win::ScopedBstr(L"afterEnd"),
430 element,
431 new_element.Receive());
432 }
433 }
434 }
435
436 return hr;
437 }
438
439 void ChromeFrameActivex::FireEvent(const EventHandlers& handlers,
440 const std::string& arg) {
441 if (handlers.size()) {
442 base::win::ScopedComPtr<IDispatch> event;
443 if (SUCCEEDED(CreateDomEvent("event", arg, "", event.Receive()))) {
444 FireEvent(handlers, event);
445 }
446 }
447 }
448
449 void ChromeFrameActivex::FireEvent(const EventHandlers& handlers,
450 IDispatch* event) {
451 DCHECK(event != NULL);
452 VARIANT arg = { VT_DISPATCH };
453 arg.pdispVal = event;
454 DISPPARAMS params = { &arg, NULL, 1, 0 };
455 for (EventHandlers::const_iterator it = handlers.begin();
456 it != handlers.end();
457 ++it) {
458 HRESULT hr = (*it)->Invoke(DISPID_VALUE, IID_NULL, LOCALE_USER_DEFAULT,
459 DISPATCH_METHOD, &params, NULL, NULL, NULL);
460 // 0x80020101 == SCRIPT_E_REPORTED.
461 // When the script we're invoking has an error, we get this error back.
462 DLOG_IF(ERROR, FAILED(hr) && hr != 0x80020101)
463 << base::StringPrintf(L"Failed to invoke script: 0x%08X", hr);
464 }
465 }
466
467 void ChromeFrameActivex::FireEvent(const EventHandlers& handlers,
468 IDispatch* event, BSTR target) {
469 DCHECK(event != NULL);
470 // Arguments in reverse order to event handler function declaration,
471 // because that's what DISPPARAMS requires.
472 VARIANT args[2] = { { VT_BSTR }, { VT_DISPATCH }, };
473 args[0].bstrVal = target;
474 args[1].pdispVal = event;
475 DISPPARAMS params = { args, NULL, arraysize(args), 0 };
476 for (EventHandlers::const_iterator it = handlers.begin();
477 it != handlers.end();
478 ++it) {
479 HRESULT hr = (*it)->Invoke(DISPID_VALUE, IID_NULL, LOCALE_USER_DEFAULT,
480 DISPATCH_METHOD, &params, NULL, NULL, NULL);
481 // 0x80020101 == SCRIPT_E_REPORTED.
482 // When the script we're invoking has an error, we get this error back.
483 DLOG_IF(ERROR, FAILED(hr) && hr != 0x80020101)
484 << base::StringPrintf(L"Failed to invoke script: 0x%08X", hr);
485 }
486 }
487
488 HRESULT ChromeFrameActivex::InstallTopLevelHook(IOleClientSite* client_site) {
489 return E_FAIL;
490 }
491
492 HRESULT ChromeFrameActivex::registerBhoIfNeeded() {
493 if (!m_spUnkSite) {
494 NOTREACHED() << "Invalid client site";
495 return E_FAIL;
496 }
497
498 if (NavigationManager::GetThreadInstance() != NULL) {
499 DVLOG(1) << "BHO already loaded";
500 return S_OK;
501 }
502
503 base::win::ScopedComPtr<IWebBrowser2> web_browser2;
504 HRESULT hr = DoQueryService(SID_SWebBrowserApp, m_spUnkSite,
505 web_browser2.Receive());
506 if (FAILED(hr) || web_browser2.get() == NULL) {
507 DLOG(WARNING) << "Failed to get IWebBrowser2 from client site. Error:"
508 << base::StringPrintf(" 0x%08X", hr);
509 return hr;
510 }
511
512 wchar_t bho_class_id_as_string[MAX_PATH] = {0};
513 StringFromGUID2(CLSID_ChromeFrameBHO, bho_class_id_as_string,
514 arraysize(bho_class_id_as_string));
515
516 base::win::ScopedComPtr<IObjectWithSite> bho;
517 hr = bho.CreateInstance(CLSID_ChromeFrameBHO, NULL, CLSCTX_INPROC_SERVER);
518 if (FAILED(hr)) {
519 NOTREACHED() << "Failed to register ChromeFrame BHO. Error:"
520 << base::StringPrintf(" 0x%08X", hr);
521 return hr;
522 }
523
524 hr = UrlMkSetSessionOption(URLMON_OPTION_USERAGENT_REFRESH, NULL, 0, 0);
525 if (FAILED(hr)) {
526 DLOG(ERROR) << "Failed to refresh user agent string from registry. "
527 << "UrlMkSetSessionOption returned "
528 << base::StringPrintf("0x%08x", hr);
529 return hr;
530 }
531
532 hr = bho->SetSite(web_browser2);
533 if (FAILED(hr)) {
534 NOTREACHED() << "ChromeFrame BHO SetSite failed. Error:"
535 << base::StringPrintf(" 0x%08X", hr);
536 return hr;
537 }
538
539 web_browser2->PutProperty(base::win::ScopedBstr(bho_class_id_as_string),
540 base::win::ScopedVariant(bho));
541 return S_OK;
542 }
OLDNEW
« no previous file with comments | « chrome_frame/chrome_frame_activex.h ('k') | chrome_frame/chrome_frame_activex.rgs » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698