OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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 // Implementation of ChromeActiveDocument | |
6 #include "chrome_frame/chrome_active_document.h" | |
7 | |
8 #include <hlink.h> | |
9 #include <htiface.h> | |
10 #include <initguid.h> | |
11 #include <mshtmcid.h> | |
12 #include <shdeprecated.h> | |
13 #include <shlguid.h> | |
14 #include <shlobj.h> | |
15 #include <shobjidl.h> | |
16 #include <tlogstg.h> | |
17 #include <urlmon.h> | |
18 #include <wininet.h> | |
19 | |
20 #include "base/command_line.h" | |
21 #include "base/debug/trace_event.h" | |
22 #include "base/logging.h" | |
23 #include "base/strings/string_util.h" | |
24 #include "base/strings/utf_string_conversions.h" | |
25 #include "base/win/scoped_variant.h" | |
26 #include "chrome/app/chrome_command_ids.h" | |
27 #include "chrome/app/chrome_dll_resource.h" | |
28 #include "chrome/common/automation_messages.h" | |
29 #include "chrome/common/chrome_constants.h" | |
30 #include "chrome/test/automation/browser_proxy.h" | |
31 #include "chrome/test/automation/tab_proxy.h" | |
32 #include "chrome_frame/bho.h" | |
33 #include "chrome_frame/bind_context_info.h" | |
34 #include "chrome_frame/buggy_bho_handling.h" | |
35 #include "chrome_frame/crash_reporting/crash_metrics.h" | |
36 #include "chrome_frame/utils.h" | |
37 #include "content/public/browser/invalidate_type.h" | |
38 #include "content/public/browser/navigation_type.h" | |
39 #include "content/public/browser/web_contents.h" | |
40 #include "content/public/common/page_zoom.h" | |
41 #include "grit/generated_resources.h" | |
42 | |
43 DEFINE_GUID(CGID_DocHostCmdPriv, 0x000214D4L, 0, 0, 0xC0, 0, 0, 0, 0, 0, 0, | |
44 0x46); | |
45 | |
46 bool g_first_launch_by_process_ = true; | |
47 | |
48 const DWORD kIEEncodingIdArray[] = { | |
49 #define DEFINE_ENCODING_ID_ARRAY(encoding_name, id, chrome_name) encoding_name, | |
50 INTERNAL_IE_ENCODINGMENU_IDS(DEFINE_ENCODING_ID_ARRAY) | |
51 #undef DEFINE_ENCODING_ID_ARRAY | |
52 0 // The Last data must be 0 to indicate the end of the encoding id array. | |
53 }; | |
54 | |
55 ChromeActiveDocument::ChromeActiveDocument() | |
56 : first_navigation_(true), | |
57 is_automation_client_reused_(false), | |
58 popup_allowed_(false), | |
59 accelerator_table_(NULL) { | |
60 TRACE_EVENT_BEGIN_ETW("chromeframe.createactivedocument", this, ""); | |
61 | |
62 url_fetcher_->set_frame_busting(false); | |
63 } | |
64 | |
65 HRESULT ChromeActiveDocument::FinalConstruct() { | |
66 // The FinalConstruct implementation in the ChromeFrameActivexBase class | |
67 // i.e. Base creates an instance of the ChromeFrameAutomationClient class | |
68 // and initializes it, which would spawn a new Chrome process, etc. | |
69 // We don't want to be doing this if we have a cached document, whose | |
70 // automation client instance can be reused. | |
71 HRESULT hr = BaseActiveX::FinalConstruct(); | |
72 if (FAILED(hr)) | |
73 return hr; | |
74 | |
75 InitializeAutomationSettings(); | |
76 | |
77 find_dialog_.Init(automation_client_.get()); | |
78 | |
79 OLECMDF flags = static_cast<OLECMDF>(OLECMDF_ENABLED | OLECMDF_SUPPORTED); | |
80 | |
81 null_group_commands_map_[OLECMDID_PRINT] = flags; | |
82 null_group_commands_map_[OLECMDID_FIND] = flags; | |
83 null_group_commands_map_[OLECMDID_CUT] = flags; | |
84 null_group_commands_map_[OLECMDID_COPY] = flags; | |
85 null_group_commands_map_[OLECMDID_PASTE] = flags; | |
86 null_group_commands_map_[OLECMDID_SELECTALL] = flags; | |
87 null_group_commands_map_[OLECMDID_SAVEAS] = flags; | |
88 | |
89 mshtml_group_commands_map_[IDM_BASELINEFONT1] = flags; | |
90 mshtml_group_commands_map_[IDM_BASELINEFONT2] = flags; | |
91 mshtml_group_commands_map_[IDM_BASELINEFONT3] = flags; | |
92 mshtml_group_commands_map_[IDM_BASELINEFONT4] = flags; | |
93 mshtml_group_commands_map_[IDM_BASELINEFONT5] = flags; | |
94 mshtml_group_commands_map_[IDM_VIEWSOURCE] = flags; | |
95 | |
96 HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase); | |
97 accelerator_table_ = | |
98 LoadAccelerators(this_module, | |
99 MAKEINTRESOURCE(IDR_CHROME_FRAME_IE_FULL_TAB)); | |
100 DCHECK(accelerator_table_ != NULL); | |
101 return S_OK; | |
102 } | |
103 | |
104 ChromeActiveDocument::~ChromeActiveDocument() { | |
105 DVLOG(1) << __FUNCTION__; | |
106 if (find_dialog_.IsWindow()) | |
107 find_dialog_.DestroyWindow(); | |
108 // ChromeFramePlugin | |
109 BaseActiveX::Uninitialize(); | |
110 | |
111 TRACE_EVENT_END_ETW("chromeframe.createactivedocument", this, ""); | |
112 } | |
113 | |
114 // Override DoVerb | |
115 STDMETHODIMP ChromeActiveDocument::DoVerb(LONG verb, | |
116 LPMSG msg, | |
117 IOleClientSite* active_site, | |
118 LONG index, | |
119 HWND parent_window, | |
120 LPCRECT pos) { | |
121 // IE will try and in-place activate us in some cases. This happens when | |
122 // the user opens a new IE window with a URL that has us as the DocObject. | |
123 // Here we refuse to be activated in-place and we will force IE to UIActivate | |
124 // us. | |
125 if (OLEIVERB_INPLACEACTIVATE == verb) | |
126 return OLEOBJ_E_INVALIDVERB; | |
127 // Check if we should activate as a docobject or not | |
128 // (client supports IOleDocumentSite) | |
129 if (doc_site_) { | |
130 switch (verb) { | |
131 case OLEIVERB_SHOW: { | |
132 base::win::ScopedComPtr<IDocHostUIHandler> doc_host_handler; | |
133 doc_host_handler.QueryFrom(doc_site_); | |
134 if (doc_host_handler.get()) | |
135 doc_host_handler->ShowUI(DOCHOSTUITYPE_BROWSE, this, this, NULL, NULL); | |
136 } | |
137 case OLEIVERB_OPEN: | |
138 case OLEIVERB_UIACTIVATE: | |
139 if (!m_bUIActive) | |
140 return doc_site_->ActivateMe(NULL); | |
141 break; | |
142 } | |
143 } | |
144 return IOleObjectImpl<ChromeActiveDocument>::DoVerb(verb, | |
145 msg, | |
146 active_site, | |
147 index, | |
148 parent_window, | |
149 pos); | |
150 } | |
151 | |
152 // Override IOleInPlaceActiveObjectImpl::OnDocWindowActivate | |
153 STDMETHODIMP ChromeActiveDocument::OnDocWindowActivate(BOOL activate) { | |
154 DVLOG(1) << __FUNCTION__; | |
155 return S_OK; | |
156 } | |
157 | |
158 STDMETHODIMP ChromeActiveDocument::TranslateAccelerator(MSG* msg) { | |
159 DVLOG(1) << __FUNCTION__; | |
160 if (msg == NULL) | |
161 return E_POINTER; | |
162 | |
163 if (msg->message == WM_KEYDOWN && msg->wParam == VK_TAB) { | |
164 HWND focus = ::GetFocus(); | |
165 if (focus != m_hWnd && !::IsChild(m_hWnd, focus)) { | |
166 // The call to SetFocus triggers a WM_SETFOCUS that makes the base class | |
167 // set focus to the correct element in Chrome. | |
168 ::SetFocus(m_hWnd); | |
169 return S_OK; | |
170 } | |
171 } | |
172 | |
173 return S_FALSE; | |
174 } | |
175 // Override IPersistStorageImpl::IsDirty | |
176 STDMETHODIMP ChromeActiveDocument::IsDirty() { | |
177 DVLOG(1) << __FUNCTION__; | |
178 return S_FALSE; | |
179 } | |
180 | |
181 void ChromeActiveDocument::OnAutomationServerReady() { | |
182 BaseActiveX::OnAutomationServerReady(); | |
183 } | |
184 | |
185 STDMETHODIMP ChromeActiveDocument::Load(BOOL fully_avalable, | |
186 IMoniker* moniker_name, | |
187 LPBC bind_context, | |
188 DWORD mode) { | |
189 if (NULL == moniker_name) | |
190 return E_INVALIDARG; | |
191 | |
192 base::win::ScopedComPtr<IOleClientSite> client_site; | |
193 if (bind_context) { | |
194 base::win::ScopedComPtr<IUnknown> site; | |
195 bind_context->GetObjectParam(SZ_HTML_CLIENTSITE_OBJECTPARAM, | |
196 site.Receive()); | |
197 if (site) | |
198 client_site.QueryFrom(site); | |
199 } | |
200 | |
201 if (client_site) { | |
202 SetClientSite(client_site); | |
203 DoQueryService(IID_INewWindowManager, client_site, | |
204 popup_manager_.Receive()); | |
205 | |
206 // See if mshtml parsed the html header for us. If so, we need to | |
207 // clear the browser service flag that we use to indicate that this | |
208 // browser instance is navigating to a CF document. | |
209 base::win::ScopedComPtr<IBrowserService> browser_service; | |
210 DoQueryService(SID_SShellBrowser, client_site, browser_service.Receive()); | |
211 if (browser_service) { | |
212 bool flagged = CheckForCFNavigation(browser_service, true); | |
213 DVLOG_IF(1, flagged) << "Cleared flagged browser service"; | |
214 } | |
215 } | |
216 | |
217 NavigationManager* mgr = NavigationManager::GetThreadInstance(); | |
218 DLOG_IF(ERROR, !mgr) << "Couldn't get instance of NavigationManager"; | |
219 | |
220 std::wstring url; | |
221 | |
222 base::win::ScopedComPtr<BindContextInfo> info; | |
223 BindContextInfo::FromBindContext(bind_context, info.Receive()); | |
224 DCHECK(info); | |
225 if (info && !info->GetUrl().empty()) { | |
226 url = info->GetUrl(); | |
227 if (mgr) { | |
228 // If the original URL contains an anchor, then the URL queried | |
229 // from the protocol sink wrapper does not contain the anchor. To | |
230 // workaround this we retrieve the anchor from the navigation manager | |
231 // and append it to the url retrieved from the protocol sink wrapper. | |
232 GURL url_for_anchor(mgr->url()); | |
233 if (url_for_anchor.has_ref()) { | |
234 url += L"#"; | |
235 url += base::UTF8ToWide(url_for_anchor.ref()); | |
236 } | |
237 } | |
238 } else { | |
239 // If the original URL contains an anchor, then the URL queried | |
240 // from the moniker does not contain the anchor. To workaround | |
241 // this we retrieve the URL from our BHO. | |
242 url = GetActualUrlFromMoniker(moniker_name, bind_context, | |
243 mgr ? mgr->url(): std::wstring()); | |
244 } | |
245 | |
246 ChromeFrameUrl cf_url; | |
247 if (!cf_url.Parse(url)) { | |
248 DLOG(WARNING) << __FUNCTION__ << " Failed to parse url:" << url; | |
249 return E_INVALIDARG; | |
250 } | |
251 | |
252 std::string referrer(mgr ? mgr->referrer() : std::string()); | |
253 RendererType renderer_type = cf_url.is_chrome_protocol() ? | |
254 RENDERER_TYPE_CHROME_GCF_PROTOCOL : RENDERER_TYPE_UNDETERMINED; | |
255 | |
256 // With CTransaction patch we have more robust way to grab the referrer for | |
257 // each top-level-switch-to-CF request by peeking at our sniffing data | |
258 // object that lives inside the bind context. We also remember the reason | |
259 // we're rendering the document in Chrome. | |
260 if (g_patch_helper.state() == PatchHelper::PATCH_PROTOCOL && info) { | |
261 scoped_refptr<ProtData> prot_data = info->get_prot_data(); | |
262 if (prot_data) { | |
263 referrer = prot_data->referrer(); | |
264 renderer_type = prot_data->renderer_type(); | |
265 } | |
266 } | |
267 | |
268 // For gcf: URLs allow only about and view-source schemes to pass through for | |
269 // further inspection. | |
270 bool is_safe_scheme = cf_url.gurl().SchemeIs(chrome::kAboutScheme) || | |
271 cf_url.gurl().SchemeIs(content::kViewSourceScheme); | |
272 if (cf_url.is_chrome_protocol() && !is_safe_scheme && | |
273 !GetConfigBool(false, kAllowUnsafeURLs)) { | |
274 DLOG(ERROR) << __FUNCTION__ << " gcf: not allowed:" << url; | |
275 return E_INVALIDARG; | |
276 } | |
277 | |
278 if (!LaunchUrl(cf_url, referrer)) { | |
279 DLOG(ERROR) << __FUNCTION__ << " Failed to launch url:" << url; | |
280 return E_INVALIDARG; | |
281 } | |
282 | |
283 if (!cf_url.is_chrome_protocol() && !cf_url.attach_to_external_tab()) | |
284 url_fetcher_->SetInfoForUrl(url.c_str(), moniker_name, bind_context); | |
285 | |
286 // Log a metric indicating why GCF is rendering in Chrome. | |
287 // (Note: we only track the renderer type when using the CTransaction patch. | |
288 // When the code for the browser service patch and for the moniker patch is | |
289 // removed, this conditional can also go away.) | |
290 if (RENDERER_TYPE_UNDETERMINED != renderer_type) { | |
291 UMA_LAUNCH_TYPE_COUNT(renderer_type); | |
292 } | |
293 | |
294 return S_OK; | |
295 } | |
296 | |
297 STDMETHODIMP ChromeActiveDocument::Save(IMoniker* moniker_name, | |
298 LPBC bind_context, | |
299 BOOL remember) { | |
300 return E_NOTIMPL; | |
301 } | |
302 | |
303 STDMETHODIMP ChromeActiveDocument::SaveCompleted(IMoniker* moniker_name, | |
304 LPBC bind_context) { | |
305 return E_NOTIMPL; | |
306 } | |
307 | |
308 STDMETHODIMP ChromeActiveDocument::GetCurMoniker(IMoniker** moniker_name) { | |
309 return E_NOTIMPL; | |
310 } | |
311 | |
312 STDMETHODIMP ChromeActiveDocument::GetClassID(CLSID* class_id) { | |
313 if (NULL == class_id) | |
314 return E_POINTER; | |
315 *class_id = GetObjectCLSID(); | |
316 return S_OK; | |
317 } | |
318 | |
319 STDMETHODIMP ChromeActiveDocument::QueryStatus(const GUID* cmd_group_guid, | |
320 ULONG number_of_commands, | |
321 OLECMD commands[], | |
322 OLECMDTEXT* command_text) { | |
323 DVLOG(1) << __FUNCTION__; | |
324 | |
325 CommandStatusMap* command_map = NULL; | |
326 | |
327 if (cmd_group_guid) { | |
328 if (IsEqualGUID(*cmd_group_guid, GUID_NULL)) { | |
329 command_map = &null_group_commands_map_; | |
330 } else if (IsEqualGUID(*cmd_group_guid, CGID_MSHTML)) { | |
331 command_map = &mshtml_group_commands_map_; | |
332 } else if (IsEqualGUID(*cmd_group_guid, CGID_Explorer)) { | |
333 command_map = &explorer_group_commands_map_; | |
334 } else if (IsEqualGUID(*cmd_group_guid, CGID_ShellDocView)) { | |
335 command_map = &shdoc_view_group_commands_map_; | |
336 } | |
337 } else { | |
338 command_map = &null_group_commands_map_; | |
339 } | |
340 | |
341 if (!command_map) { | |
342 DVLOG(1) << "unsupported command group: " << GuidToString(*cmd_group_guid); | |
343 return OLECMDERR_E_NOTSUPPORTED; | |
344 } | |
345 | |
346 for (ULONG command_index = 0; command_index < number_of_commands; | |
347 command_index++) { | |
348 DVLOG(1) << "Command id = " << commands[command_index].cmdID; | |
349 CommandStatusMap::iterator index = | |
350 command_map->find(commands[command_index].cmdID); | |
351 if (index != command_map->end()) | |
352 commands[command_index].cmdf = index->second; | |
353 } | |
354 return S_OK; | |
355 } | |
356 | |
357 STDMETHODIMP ChromeActiveDocument::Exec(const GUID* cmd_group_guid, | |
358 DWORD command_id, | |
359 DWORD cmd_exec_opt, | |
360 VARIANT* in_args, | |
361 VARIANT* out_args) { | |
362 DVLOG(1) << __FUNCTION__ << " Cmd id =" << command_id; | |
363 // Bail out if we have been uninitialized. | |
364 if (automation_client_.get() && automation_client_->tab()) { | |
365 return ProcessExecCommand(cmd_group_guid, command_id, cmd_exec_opt, | |
366 in_args, out_args); | |
367 } else if (command_id == OLECMDID_REFRESH && cmd_group_guid == NULL) { | |
368 // If the automation server has crashed and the user is refreshing the | |
369 // page, let OnRefreshPage attempt to recover. | |
370 OnRefreshPage(cmd_group_guid, command_id, cmd_exec_opt, in_args, out_args); | |
371 } | |
372 | |
373 return OLECMDERR_E_NOTSUPPORTED; | |
374 } | |
375 | |
376 STDMETHODIMP ChromeActiveDocument::LoadHistory(IStream* stream, | |
377 IBindCtx* bind_context) { | |
378 // Read notes in ChromeActiveDocument::SaveHistory | |
379 DCHECK(stream); | |
380 LARGE_INTEGER offset = {0}; | |
381 ULARGE_INTEGER cur_pos = {0}; | |
382 STATSTG statstg = {0}; | |
383 | |
384 stream->Seek(offset, STREAM_SEEK_CUR, &cur_pos); | |
385 stream->Stat(&statstg, STATFLAG_NONAME); | |
386 | |
387 DWORD url_size = statstg.cbSize.LowPart - cur_pos.LowPart; | |
388 base::win::ScopedBstr url_bstr; | |
389 DWORD bytes_read = 0; | |
390 stream->Read(url_bstr.AllocateBytes(url_size), url_size, &bytes_read); | |
391 std::wstring url(url_bstr); | |
392 | |
393 ChromeFrameUrl cf_url; | |
394 if (!cf_url.Parse(url)) { | |
395 DLOG(WARNING) << __FUNCTION__ << " Failed to parse url:" << url; | |
396 return E_INVALIDARG; | |
397 } | |
398 | |
399 if (!LaunchUrl(cf_url, std::string())) { | |
400 NOTREACHED() << __FUNCTION__ << " Failed to launch url:" << url; | |
401 return E_INVALIDARG; | |
402 } | |
403 return S_OK; | |
404 } | |
405 | |
406 STDMETHODIMP ChromeActiveDocument::SaveHistory(IStream* stream) { | |
407 return E_INVALIDARG; | |
408 } | |
409 | |
410 STDMETHODIMP ChromeActiveDocument::SetPositionCookie(DWORD position_cookie) { | |
411 return S_OK; | |
412 } | |
413 | |
414 STDMETHODIMP ChromeActiveDocument::GetPositionCookie(DWORD* position_cookie) { | |
415 return S_OK; | |
416 } | |
417 | |
418 STDMETHODIMP ChromeActiveDocument::GetUrlForEvents(BSTR* url) { | |
419 if (NULL == url) | |
420 return E_POINTER; | |
421 *url = ::SysAllocString(url_); | |
422 return S_OK; | |
423 } | |
424 | |
425 STDMETHODIMP ChromeActiveDocument::GetAddressBarUrl(BSTR* url) { | |
426 return GetUrlForEvents(url); | |
427 } | |
428 | |
429 STDMETHODIMP ChromeActiveDocument::Reset() { | |
430 next_privacy_record_ = privacy_info_.privacy_records.begin(); | |
431 return S_OK; | |
432 } | |
433 | |
434 STDMETHODIMP ChromeActiveDocument::GetSize(DWORD* size) { | |
435 if (!size) | |
436 return E_POINTER; | |
437 | |
438 *size = privacy_info_.privacy_records.size(); | |
439 return S_OK; | |
440 } | |
441 | |
442 STDMETHODIMP ChromeActiveDocument::GetPrivacyImpacted(BOOL* privacy_impacted) { | |
443 if (!privacy_impacted) | |
444 return E_POINTER; | |
445 | |
446 *privacy_impacted = privacy_info_.privacy_impacted; | |
447 return S_OK; | |
448 } | |
449 | |
450 STDMETHODIMP ChromeActiveDocument::Next(BSTR* url, BSTR* policy, | |
451 LONG* reserved, DWORD* flags) { | |
452 if (!url || !policy || !flags) | |
453 return E_POINTER; | |
454 | |
455 if (next_privacy_record_ == privacy_info_.privacy_records.end()) | |
456 return HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS); | |
457 | |
458 *url = SysAllocString(next_privacy_record_->first.c_str()); | |
459 *policy = SysAllocString(next_privacy_record_->second.policy_ref.c_str()); | |
460 *flags = next_privacy_record_->second.flags; | |
461 | |
462 next_privacy_record_++; | |
463 return S_OK; | |
464 } | |
465 | |
466 bool ChromeActiveDocument::IsSchemeAllowed(const GURL& url) { | |
467 bool allowed = BaseActiveX::IsSchemeAllowed(url); | |
468 if (allowed) | |
469 return true; | |
470 | |
471 if (url.SchemeIs(chrome::kAboutScheme)) { | |
472 if (LowerCaseEqualsASCII(url.spec(), chrome::kAboutPluginsURL)) | |
473 return true; | |
474 } | |
475 return false; | |
476 } | |
477 | |
478 HRESULT ChromeActiveDocument::GetInPlaceFrame( | |
479 IOleInPlaceFrame** in_place_frame) { | |
480 DCHECK(in_place_frame); | |
481 if (in_place_frame_) { | |
482 *in_place_frame = in_place_frame_.get(); | |
483 (*in_place_frame)->AddRef(); | |
484 return S_OK; | |
485 } else { | |
486 return S_FALSE; | |
487 } | |
488 } | |
489 | |
490 HRESULT ChromeActiveDocument::IOleObject_SetClientSite( | |
491 IOleClientSite* client_site) { | |
492 if (client_site == NULL) { | |
493 base::win::ScopedComPtr<IDocHostUIHandler> doc_host_handler; | |
494 if (doc_site_) | |
495 doc_host_handler.QueryFrom(doc_site_); | |
496 | |
497 if (doc_host_handler.get()) | |
498 doc_host_handler->HideUI(); | |
499 | |
500 doc_site_.Release(); | |
501 } | |
502 | |
503 if (client_site != m_spClientSite) | |
504 return BaseActiveX::IOleObject_SetClientSite(client_site); | |
505 | |
506 return S_OK; | |
507 } | |
508 | |
509 HRESULT ChromeActiveDocument::ActiveXDocActivate(LONG verb) { | |
510 HRESULT hr = S_OK; | |
511 m_bNegotiatedWnd = TRUE; | |
512 if (!m_bInPlaceActive) { | |
513 hr = m_spInPlaceSite->CanInPlaceActivate(); | |
514 if (FAILED(hr)) | |
515 return hr; | |
516 m_spInPlaceSite->OnInPlaceActivate(); | |
517 } | |
518 m_bInPlaceActive = TRUE; | |
519 // get location in the parent window, | |
520 // as well as some information about the parent | |
521 base::win::ScopedComPtr<IOleInPlaceUIWindow> in_place_ui_window; | |
522 frame_info_.cb = sizeof(OLEINPLACEFRAMEINFO); | |
523 HWND parent_window = NULL; | |
524 if (m_spInPlaceSite->GetWindow(&parent_window) == S_OK) { | |
525 in_place_frame_.Release(); | |
526 RECT position_rect = {0}; | |
527 RECT clip_rect = {0}; | |
528 m_spInPlaceSite->GetWindowContext(in_place_frame_.Receive(), | |
529 in_place_ui_window.Receive(), | |
530 &position_rect, | |
531 &clip_rect, | |
532 &frame_info_); | |
533 if (!m_bWndLess) { | |
534 if (IsWindow()) { | |
535 ::ShowWindow(m_hWnd, SW_SHOW); | |
536 SetFocus(); | |
537 } else { | |
538 m_hWnd = Create(parent_window, position_rect); | |
539 if (!IsWindow()) { | |
540 // This might happen if the automation server couldn't be | |
541 // instantiated. If so, a NOTREACHED() will have already been hit. | |
542 DLOG(ERROR) << "Failed to create Ax window"; | |
543 return AtlHresultFromLastError(); | |
544 } | |
545 } | |
546 } | |
547 SetObjectRects(&position_rect, &clip_rect); | |
548 } | |
549 | |
550 base::win::ScopedComPtr<IOleInPlaceActiveObject> in_place_active_object(this); | |
551 | |
552 // Gone active by now, take care of UIACTIVATE | |
553 if (DoesVerbUIActivate(verb)) { | |
554 if (!m_bUIActive) { | |
555 m_bUIActive = TRUE; | |
556 hr = m_spInPlaceSite->OnUIActivate(); | |
557 if (FAILED(hr)) | |
558 return hr; | |
559 // set ourselves up in the host | |
560 if (in_place_active_object) { | |
561 if (in_place_frame_) | |
562 in_place_frame_->SetActiveObject(in_place_active_object, NULL); | |
563 if (in_place_ui_window) | |
564 in_place_ui_window->SetActiveObject(in_place_active_object, NULL); | |
565 } | |
566 } | |
567 } | |
568 m_spClientSite->ShowObject(); | |
569 return S_OK; | |
570 } | |
571 | |
572 bool IsFindAccelerator(const MSG& msg) { | |
573 // TODO(robertshield): This may not stand up to localization. Fix if this | |
574 // is the case. | |
575 return msg.message == WM_KEYDOWN && msg.wParam == 'F' && | |
576 base::win::IsCtrlPressed() && | |
577 !(base::win::IsAltPressed() || base::win::IsShiftPressed()); | |
578 } | |
579 | |
580 void ChromeActiveDocument::OnFindInPage() { | |
581 TabProxy* tab = GetTabProxy(); | |
582 if (tab) { | |
583 if (!find_dialog_.IsWindow()) | |
584 find_dialog_.Create(m_hWnd); | |
585 | |
586 find_dialog_.ShowWindow(SW_SHOW); | |
587 } | |
588 } | |
589 | |
590 void ChromeActiveDocument::OnViewSource() { | |
591 } | |
592 | |
593 void ChromeActiveDocument::OnDetermineSecurityZone(const GUID* cmd_group_guid, | |
594 DWORD command_id, | |
595 DWORD cmd_exec_opt, | |
596 VARIANT* in_args, | |
597 VARIANT* out_args) { | |
598 // Always return URLZONE_INTERNET since that is the Chrome's behaviour. | |
599 // Correct step is to use MapUrlToZone(). | |
600 if (out_args != NULL) { | |
601 out_args->vt = VT_UI4; | |
602 out_args->ulVal = URLZONE_INTERNET; | |
603 } | |
604 } | |
605 | |
606 void ChromeActiveDocument::OnDisplayPrivacyInfo() { | |
607 privacy_info_ = url_fetcher_->privacy_info(); | |
608 Reset(); | |
609 DoPrivacyDlg(m_hWnd, url_, this, TRUE); | |
610 } | |
611 | |
612 void ChromeActiveDocument::OnGetZoomRange(const GUID* cmd_group_guid, | |
613 DWORD command_id, | |
614 DWORD cmd_exec_opt, | |
615 VARIANT* in_args, | |
616 VARIANT* out_args) { | |
617 if (out_args != NULL) { | |
618 out_args->vt = VT_I4; | |
619 out_args->lVal = 0; | |
620 } | |
621 } | |
622 | |
623 bool ChromeActiveDocument::PreProcessContextMenu(HMENU menu) { | |
624 base::win::ScopedComPtr<IBrowserService> browser_service; | |
625 base::win::ScopedComPtr<ITravelLog> travel_log; | |
626 GetBrowserServiceAndTravelLog(browser_service.Receive(), | |
627 travel_log.Receive()); | |
628 if (!browser_service || !travel_log) | |
629 return true; | |
630 | |
631 EnableMenuItem(menu, IDC_BACK, MF_BYCOMMAND | | |
632 (SUCCEEDED(travel_log->GetTravelEntry(browser_service, TLOG_BACK, | |
633 NULL)) ? | |
634 MF_ENABLED : MF_DISABLED)); | |
635 EnableMenuItem(menu, IDC_FORWARD, MF_BYCOMMAND | | |
636 (SUCCEEDED(travel_log->GetTravelEntry(browser_service, TLOG_FORE, | |
637 NULL)) ? | |
638 MF_ENABLED : MF_DISABLED)); | |
639 // Call base class (adds 'About' item) | |
640 return BaseActiveX::PreProcessContextMenu(menu); | |
641 } | |
642 | |
643 HRESULT ChromeActiveDocument::IEExec(const GUID* cmd_group_guid, | |
644 DWORD command_id, DWORD cmd_exec_opt, | |
645 VARIANT* in_args, VARIANT* out_args) { | |
646 HRESULT hr = E_FAIL; | |
647 | |
648 base::win::ScopedComPtr<IOleCommandTarget> frame_cmd_target; | |
649 | |
650 base::win::ScopedComPtr<IOleInPlaceSite> in_place_site(m_spInPlaceSite); | |
651 if (!in_place_site.get() && m_spClientSite != NULL) | |
652 in_place_site.QueryFrom(m_spClientSite); | |
653 | |
654 if (in_place_site) | |
655 hr = frame_cmd_target.QueryFrom(in_place_site); | |
656 | |
657 if (frame_cmd_target) { | |
658 hr = frame_cmd_target->Exec(cmd_group_guid, command_id, cmd_exec_opt, | |
659 in_args, out_args); | |
660 } | |
661 | |
662 return hr; | |
663 } | |
664 | |
665 bool ChromeActiveDocument::LaunchUrl(const ChromeFrameUrl& cf_url, | |
666 const std::string& referrer) { | |
667 return false; | |
668 } | |
669 | |
670 HRESULT ChromeActiveDocument::OnRefreshPage(const GUID* cmd_group_guid, | |
671 DWORD command_id, DWORD cmd_exec_opt, VARIANT* in_args, VARIANT* out_args) { | |
672 DVLOG(1) << __FUNCTION__; | |
673 popup_allowed_ = false; | |
674 if (in_args->vt == VT_I4 && | |
675 in_args->lVal & OLECMDIDF_REFRESH_PAGEACTION_POPUPWINDOW) { | |
676 popup_allowed_ = true; | |
677 | |
678 // Ask the yellow security band to change the text and icon and to remain | |
679 // visible. | |
680 IEExec(&CGID_DocHostCommandHandler, OLECMDID_PAGEACTIONBLOCKED, | |
681 0x80000000 | OLECMDIDF_WINDOWSTATE_USERVISIBLE_VALID, NULL, NULL); | |
682 } | |
683 | |
684 NavigationManager* mgr = NavigationManager::GetThreadInstance(); | |
685 DLOG_IF(ERROR, !mgr) << "Couldn't get instance of NavigationManager"; | |
686 | |
687 // If ChromeFrame was activated on this page as a result of a document | |
688 // received in response to a top level post, then we ask the user for | |
689 // permission to repost and issue a navigation with the saved post data | |
690 // which reinitates the whole sequence, i.e. the server receives the top | |
691 // level post and chrome frame will be reactivated in response. | |
692 if (mgr && mgr->post_data().type() != VT_EMPTY) { | |
693 if (MessageBox( | |
694 SimpleResourceLoader::Get(IDS_HTTP_POST_WARNING).c_str(), | |
695 SimpleResourceLoader::Get(IDS_HTTP_POST_WARNING_TITLE).c_str(), | |
696 MB_YESNO | MB_ICONEXCLAMATION) == IDYES) { | |
697 base::win::ScopedComPtr<IWebBrowser2> web_browser2; | |
698 DoQueryService(SID_SWebBrowserApp, m_spClientSite, | |
699 web_browser2.Receive()); | |
700 DCHECK(web_browser2); | |
701 VARIANT empty = base::win::ScopedVariant::kEmptyVariant; | |
702 VARIANT flags = { VT_I4 }; | |
703 V_I4(&flags) = navNoHistory; | |
704 | |
705 return web_browser2->Navigate2(base::win::ScopedVariant(url_).AsInput(), | |
706 &flags, | |
707 &empty, | |
708 const_cast<VARIANT*>(&mgr->post_data()), | |
709 const_cast<VARIANT*>(&mgr->headers())); | |
710 } else { | |
711 return S_OK; | |
712 } | |
713 } | |
714 | |
715 TabProxy* tab_proxy = GetTabProxy(); | |
716 if (tab_proxy) { | |
717 tab_proxy->ReloadAsync(); | |
718 } | |
719 | |
720 return S_OK; | |
721 } | |
722 | |
723 HRESULT ChromeActiveDocument::SetPageFontSize(const GUID* cmd_group_guid, | |
724 DWORD command_id, | |
725 DWORD cmd_exec_opt, | |
726 VARIANT* in_args, | |
727 VARIANT* out_args) { | |
728 if (!automation_client_.get()) { | |
729 NOTREACHED() << "Invalid automation client"; | |
730 return E_FAIL; | |
731 } | |
732 | |
733 switch (command_id) { | |
734 case IDM_BASELINEFONT1: | |
735 automation_client_->SetPageFontSize(SMALLEST_FONT); | |
736 break; | |
737 | |
738 case IDM_BASELINEFONT2: | |
739 automation_client_->SetPageFontSize(SMALL_FONT); | |
740 break; | |
741 | |
742 case IDM_BASELINEFONT3: | |
743 automation_client_->SetPageFontSize(MEDIUM_FONT); | |
744 break; | |
745 | |
746 case IDM_BASELINEFONT4: | |
747 automation_client_->SetPageFontSize(LARGE_FONT); | |
748 break; | |
749 | |
750 case IDM_BASELINEFONT5: | |
751 automation_client_->SetPageFontSize(LARGEST_FONT); | |
752 break; | |
753 | |
754 default: | |
755 NOTREACHED() << "Invalid font size command: " | |
756 << command_id; | |
757 return E_FAIL; | |
758 } | |
759 | |
760 // Forward the command back to IEFrame with group set to | |
761 // CGID_ExplorerBarDoc. This is probably needed to update the menu state to | |
762 // indicate that the font size was set. This currently fails with error | |
763 // 0x80040104. | |
764 // TODO(iyengar) | |
765 // Do some investigation into why this Exec call fails. | |
766 IEExec(&CGID_ExplorerBarDoc, command_id, cmd_exec_opt, NULL, NULL); | |
767 return S_OK; | |
768 } | |
769 | |
770 HRESULT ChromeActiveDocument::OnEncodingChange(const GUID* cmd_group_guid, | |
771 DWORD command_id, | |
772 DWORD cmd_exec_opt, | |
773 VARIANT* in_args, | |
774 VARIANT* out_args) { | |
775 const struct EncodingMapData { | |
776 DWORD ie_encoding_id; | |
777 const char* chrome_encoding_name; | |
778 } kEncodingTestDatas[] = { | |
779 #define DEFINE_ENCODING_MAP(encoding_name, id, chrome_name) \ | |
780 { encoding_name, chrome_name }, | |
781 INTERNAL_IE_ENCODINGMENU_IDS(DEFINE_ENCODING_MAP) | |
782 #undef DEFINE_ENCODING_MAP | |
783 }; | |
784 | |
785 if (!automation_client_.get()) { | |
786 NOTREACHED() << "Invalid automtion client"; | |
787 return E_FAIL; | |
788 } | |
789 | |
790 // Using ARRAYSIZE_UNSAFE in here is because we define the struct | |
791 // EncodingMapData inside function. | |
792 const char* chrome_encoding_name = NULL; | |
793 for (int i = 0; i < ARRAYSIZE_UNSAFE(kEncodingTestDatas); ++i) { | |
794 const struct EncodingMapData* encoding_data = &kEncodingTestDatas[i]; | |
795 if (command_id == encoding_data->ie_encoding_id) { | |
796 chrome_encoding_name = encoding_data->chrome_encoding_name; | |
797 break; | |
798 } | |
799 } | |
800 // Return E_FAIL when encountering invalid encoding id. | |
801 if (!chrome_encoding_name) | |
802 return E_FAIL; | |
803 | |
804 TabProxy* tab = GetTabProxy(); | |
805 if (!tab) { | |
806 NOTREACHED() << "Can not get TabProxy"; | |
807 return E_FAIL; | |
808 } | |
809 | |
810 if (chrome_encoding_name) | |
811 tab->OverrideEncoding(chrome_encoding_name); | |
812 | |
813 // Like we did on SetPageFontSize, we may forward the command back to IEFrame | |
814 // to update the menu state to indicate that which encoding was set. | |
815 // TODO(iyengar) | |
816 // Do some investigation into why this Exec call fails. | |
817 IEExec(&CGID_ExplorerBarDoc, command_id, cmd_exec_opt, NULL, NULL); | |
818 return S_OK; | |
819 } | |
820 HRESULT ChromeActiveDocument::GetBrowserServiceAndTravelLog( | |
821 IBrowserService** browser_service, ITravelLog** travel_log) { | |
822 DCHECK(browser_service || travel_log); | |
823 base::win::ScopedComPtr<IBrowserService> browser_service_local; | |
824 HRESULT hr = DoQueryService(SID_SShellBrowser, m_spClientSite, | |
825 browser_service_local.Receive()); | |
826 if (!browser_service_local) { | |
827 NOTREACHED() << "DoQueryService for IBrowserService failed: " << hr; | |
828 return hr; | |
829 } | |
830 | |
831 if (travel_log) { | |
832 hr = browser_service_local->GetTravelLog(travel_log); | |
833 DVLOG_IF(1, !travel_log) << "browser_service->GetTravelLog failed: " << hr; | |
834 } | |
835 | |
836 if (browser_service) | |
837 *browser_service = browser_service_local.Detach(); | |
838 | |
839 return hr; | |
840 } | |
841 | |
842 LRESULT ChromeActiveDocument::OnForward(WORD notify_code, WORD id, | |
843 HWND control_window, | |
844 BOOL& bHandled) { | |
845 base::win::ScopedComPtr<IWebBrowser2> web_browser2; | |
846 DoQueryService(SID_SWebBrowserApp, m_spClientSite, web_browser2.Receive()); | |
847 DCHECK(web_browser2); | |
848 | |
849 if (web_browser2) | |
850 web_browser2->GoForward(); | |
851 return 0; | |
852 } | |
853 | |
854 LRESULT ChromeActiveDocument::OnBack(WORD notify_code, WORD id, | |
855 HWND control_window, | |
856 BOOL& bHandled) { | |
857 base::win::ScopedComPtr<IWebBrowser2> web_browser2; | |
858 DoQueryService(SID_SWebBrowserApp, m_spClientSite, web_browser2.Receive()); | |
859 DCHECK(web_browser2); | |
860 | |
861 if (web_browser2) | |
862 web_browser2->GoBack(); | |
863 return 0; | |
864 } | |
865 | |
866 LRESULT ChromeActiveDocument::OnFirePrivacyChange(UINT message, WPARAM wparam, | |
867 LPARAM lparam, | |
868 BOOL& handled) { | |
869 if (!m_spClientSite) | |
870 return 0; | |
871 | |
872 base::win::ScopedComPtr<IWebBrowser2> web_browser2; | |
873 DoQueryService(SID_SWebBrowserApp, m_spClientSite, | |
874 web_browser2.Receive()); | |
875 if (!web_browser2) { | |
876 NOTREACHED() << "Failed to retrieve IWebBrowser2 interface."; | |
877 return 0; | |
878 } | |
879 | |
880 base::win::ScopedComPtr<IShellBrowser> shell_browser; | |
881 DoQueryService(SID_STopLevelBrowser, web_browser2, | |
882 shell_browser.Receive()); | |
883 DCHECK(shell_browser.get() != NULL); | |
884 base::win::ScopedComPtr<ITridentService2> trident_services; | |
885 trident_services.QueryFrom(shell_browser); | |
886 if (trident_services) | |
887 trident_services->FirePrivacyImpactedStateChange(wparam); | |
888 else | |
889 NOTREACHED() << "Failed to retrieve IWebBrowser2 interface."; | |
890 return 0; | |
891 } | |
892 | |
893 LRESULT ChromeActiveDocument::OnShowWindow(UINT message, WPARAM wparam, | |
894 LPARAM lparam, | |
895 BOOL& handled) { // NO_LINT | |
896 if (wparam) | |
897 SetFocus(); | |
898 return 0; | |
899 } | |
900 | |
901 LRESULT ChromeActiveDocument::OnSetFocus(UINT message, WPARAM wparam, | |
902 LPARAM lparam, | |
903 BOOL& handled) { // NO_LINT | |
904 return 0; | |
905 } | |
OLD | NEW |