OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Implementation of ChromeActiveDocument | 5 // Implementation of ChromeActiveDocument |
6 #include "chrome_frame/chrome_active_document.h" | 6 #include "chrome_frame/chrome_active_document.h" |
7 | 7 |
8 #include <hlink.h> | 8 #include <hlink.h> |
9 #include <htiface.h> | 9 #include <htiface.h> |
10 #include <initguid.h> | 10 #include <initguid.h> |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 #define DEFINE_ENCODING_ID_ARRAY(encoding_name, id, chrome_name) encoding_name, | 58 #define DEFINE_ENCODING_ID_ARRAY(encoding_name, id, chrome_name) encoding_name, |
59 INTERNAL_IE_ENCODINGMENU_IDS(DEFINE_ENCODING_ID_ARRAY) | 59 INTERNAL_IE_ENCODINGMENU_IDS(DEFINE_ENCODING_ID_ARRAY) |
60 #undef DEFINE_ENCODING_ID_ARRAY | 60 #undef DEFINE_ENCODING_ID_ARRAY |
61 0 // The Last data must be 0 to indicate the end of the encoding id array. | 61 0 // The Last data must be 0 to indicate the end of the encoding id array. |
62 }; | 62 }; |
63 | 63 |
64 ChromeActiveDocument::ChromeActiveDocument() | 64 ChromeActiveDocument::ChromeActiveDocument() |
65 : first_navigation_(true), | 65 : first_navigation_(true), |
66 is_automation_client_reused_(false), | 66 is_automation_client_reused_(false), |
67 popup_allowed_(false), | 67 popup_allowed_(false), |
68 accelerator_table_(NULL), | 68 accelerator_table_(NULL) { |
69 is_new_navigation_(false) { | |
70 TRACE_EVENT_BEGIN("chromeframe.createactivedocument", this, ""); | 69 TRACE_EVENT_BEGIN("chromeframe.createactivedocument", this, ""); |
71 | 70 |
72 url_fetcher_.set_frame_busting(false); | 71 url_fetcher_.set_frame_busting(false); |
73 memset(&navigation_info_, 0, sizeof(navigation_info_)); | 72 memset(&navigation_info_, 0, sizeof(navigation_info_)); |
74 } | 73 } |
75 | 74 |
76 HRESULT ChromeActiveDocument::FinalConstruct() { | 75 HRESULT ChromeActiveDocument::FinalConstruct() { |
77 // If we have a cached ChromeActiveDocument instance in TLS, then grab | 76 // If we have a cached ChromeActiveDocument instance in TLS, then grab |
78 // ownership of the cached document's automation client. This is an | 77 // ownership of the cached document's automation client. This is an |
79 // optimization to get Chrome active documents to load faster. | 78 // optimization to get Chrome active documents to load faster. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 mshtml_group_commands_map_[IDM_BASELINEFONT2] = flags; | 117 mshtml_group_commands_map_[IDM_BASELINEFONT2] = flags; |
119 mshtml_group_commands_map_[IDM_BASELINEFONT3] = flags; | 118 mshtml_group_commands_map_[IDM_BASELINEFONT3] = flags; |
120 mshtml_group_commands_map_[IDM_BASELINEFONT4] = flags; | 119 mshtml_group_commands_map_[IDM_BASELINEFONT4] = flags; |
121 mshtml_group_commands_map_[IDM_BASELINEFONT5] = flags; | 120 mshtml_group_commands_map_[IDM_BASELINEFONT5] = flags; |
122 | 121 |
123 HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase); | 122 HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase); |
124 accelerator_table_ = | 123 accelerator_table_ = |
125 LoadAccelerators(this_module, | 124 LoadAccelerators(this_module, |
126 MAKEINTRESOURCE(IDR_CHROME_FRAME_IE_FULL_TAB)); | 125 MAKEINTRESOURCE(IDR_CHROME_FRAME_IE_FULL_TAB)); |
127 DCHECK(accelerator_table_ != NULL); | 126 DCHECK(accelerator_table_ != NULL); |
| 127 |
| 128 HRESULT hr = security_manager_.CreateInstance(CLSID_InternetSecurityManager); |
| 129 if (FAILED(hr)) { |
| 130 NOTREACHED() << __FUNCTION__ |
| 131 << " Failed to create InternetSecurityManager. Error: 0x%x" |
| 132 << hr; |
| 133 } |
| 134 |
128 return S_OK; | 135 return S_OK; |
129 } | 136 } |
130 | 137 |
131 ChromeActiveDocument::~ChromeActiveDocument() { | 138 ChromeActiveDocument::~ChromeActiveDocument() { |
132 DLOG(INFO) << __FUNCTION__; | 139 DLOG(INFO) << __FUNCTION__; |
133 if (find_dialog_.IsWindow()) | 140 if (find_dialog_.IsWindow()) |
134 find_dialog_.DestroyWindow(); | 141 find_dialog_.DestroyWindow(); |
135 // ChromeFramePlugin | 142 // ChromeFramePlugin |
136 BaseActiveX::Uninitialize(); | 143 BaseActiveX::Uninitialize(); |
137 | 144 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 if (info && !info->url().empty()) { | 260 if (info && !info->url().empty()) { |
254 url = info->url(); | 261 url = info->url(); |
255 } else { | 262 } else { |
256 // If the original URL contains an anchor, then the URL queried | 263 // If the original URL contains an anchor, then the URL queried |
257 // from the moniker does not contain the anchor. To workaround | 264 // from the moniker does not contain the anchor. To workaround |
258 // this we retrieve the URL from our BHO. | 265 // this we retrieve the URL from our BHO. |
259 url = GetActualUrlFromMoniker(moniker_name, bind_context, | 266 url = GetActualUrlFromMoniker(moniker_name, bind_context, |
260 mgr ? mgr->url(): std::wstring()); | 267 mgr ? mgr->url(): std::wstring()); |
261 } | 268 } |
262 | 269 |
263 // The is_new_navigation variable indicates if this a navigation initiated | 270 ChromeFrameUrl cf_url; |
264 // by typing in a URL for e.g. in the IE address bar, or from Chrome by | 271 if (!cf_url.Parse(url)) { |
265 // a window.open call from javascript, in which case the current IE tab | 272 DLOG(WARNING) << __FUNCTION__ << " Failed to parse url:" << url; |
266 // will attach to an existing ExternalTabContainer instance. | 273 return E_INVALIDARG; |
267 bool is_new_navigation = true; | 274 } |
268 bool is_chrome_protocol = false; | |
269 | 275 |
270 if (!ParseUrl(url, &is_new_navigation, &is_chrome_protocol, &url)) { | 276 if (!CanNavigateInFullTabMode(cf_url, security_manager_)) { |
271 DLOG(WARNING) << __FUNCTION__ << " Failed to parse url:" << url; | |
272 return E_INVALIDARG; | 277 return E_INVALIDARG; |
273 } | 278 } |
274 | 279 |
275 std::string referrer = mgr ? mgr->referrer() : EmptyString(); | 280 std::string referrer = mgr ? mgr->referrer() : EmptyString(); |
276 // With CTransaction patch we have more robust way to grab the referrer for | 281 // With CTransaction patch we have more robust way to grab the referrer for |
277 // each top-level-switch-to-CF request by peeking at our sniffing data | 282 // each top-level-switch-to-CF request by peeking at our sniffing data |
278 // object that lives inside the bind context. | 283 // object that lives inside the bind context. |
279 if (g_patch_helper.state() == PatchHelper::PATCH_PROTOCOL && info) { | 284 if (g_patch_helper.state() == PatchHelper::PATCH_PROTOCOL && info) { |
280 scoped_refptr<ProtData> prot_data = info->get_prot_data(); | 285 scoped_refptr<ProtData> prot_data = info->get_prot_data(); |
281 if (prot_data) | 286 if (prot_data) |
282 referrer = prot_data->referrer(); | 287 referrer = prot_data->referrer(); |
283 } | 288 } |
284 | 289 |
285 if (!LaunchUrl(url, referrer, is_new_navigation)) { | 290 if (!LaunchUrl(cf_url, referrer)) { |
286 NOTREACHED() << __FUNCTION__ << " Failed to launch url:" << url; | 291 NOTREACHED() << __FUNCTION__ << " Failed to launch url:" << url; |
287 return E_INVALIDARG; | 292 return E_INVALIDARG; |
288 } | 293 } |
289 | 294 |
290 if (!is_chrome_protocol) | 295 if (!cf_url.is_chrome_protocol() && !cf_url.attach_to_external_tab()) |
291 url_fetcher_.SetInfoForUrl(url, moniker_name, bind_context); | 296 url_fetcher_.SetInfoForUrl(cf_url.url(), moniker_name, bind_context); |
292 | 297 |
293 THREAD_SAFE_UMA_HISTOGRAM_CUSTOM_COUNTS("ChromeFrame.FullTabLaunchType", | 298 THREAD_SAFE_UMA_HISTOGRAM_CUSTOM_COUNTS("ChromeFrame.FullTabLaunchType", |
294 is_chrome_protocol, 0, 1, 2); | 299 cf_url.is_chrome_protocol(), |
| 300 0, 1, 2); |
295 return S_OK; | 301 return S_OK; |
296 } | 302 } |
297 | 303 |
298 STDMETHODIMP ChromeActiveDocument::Save(IMoniker* moniker_name, | 304 STDMETHODIMP ChromeActiveDocument::Save(IMoniker* moniker_name, |
299 LPBC bind_context, | 305 LPBC bind_context, |
300 BOOL remember) { | 306 BOOL remember) { |
301 return E_NOTIMPL; | 307 return E_NOTIMPL; |
302 } | 308 } |
303 | 309 |
304 STDMETHODIMP ChromeActiveDocument::SaveCompleted(IMoniker* moniker_name, | 310 STDMETHODIMP ChromeActiveDocument::SaveCompleted(IMoniker* moniker_name, |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 | 386 |
381 stream->Seek(offset, STREAM_SEEK_CUR, &cur_pos); | 387 stream->Seek(offset, STREAM_SEEK_CUR, &cur_pos); |
382 stream->Stat(&statstg, STATFLAG_NONAME); | 388 stream->Stat(&statstg, STATFLAG_NONAME); |
383 | 389 |
384 DWORD url_size = statstg.cbSize.LowPart - cur_pos.LowPart; | 390 DWORD url_size = statstg.cbSize.LowPart - cur_pos.LowPart; |
385 ScopedBstr url_bstr; | 391 ScopedBstr url_bstr; |
386 DWORD bytes_read = 0; | 392 DWORD bytes_read = 0; |
387 stream->Read(url_bstr.AllocateBytes(url_size), url_size, &bytes_read); | 393 stream->Read(url_bstr.AllocateBytes(url_size), url_size, &bytes_read); |
388 std::wstring url(url_bstr); | 394 std::wstring url(url_bstr); |
389 | 395 |
390 bool is_new_navigation = true; | 396 ChromeFrameUrl cf_url; |
391 bool is_chrome_protocol = false; | 397 if (!cf_url.Parse(url)) { |
392 | |
393 if (!ParseUrl(url, &is_new_navigation, &is_chrome_protocol, &url)) { | |
394 DLOG(WARNING) << __FUNCTION__ << " Failed to parse url:" << url; | 398 DLOG(WARNING) << __FUNCTION__ << " Failed to parse url:" << url; |
395 return E_INVALIDARG; | 399 return E_INVALIDARG; |
396 } | 400 } |
397 | 401 |
| 402 if (!CanNavigateInFullTabMode(cf_url, security_manager_)) { |
| 403 return E_INVALIDARG; |
| 404 } |
| 405 |
398 const std::string& referrer = EmptyString(); | 406 const std::string& referrer = EmptyString(); |
399 if (!LaunchUrl(url, referrer, is_new_navigation)) { | 407 if (!LaunchUrl(cf_url, referrer)) { |
400 NOTREACHED() << __FUNCTION__ << " Failed to launch url:" << url; | 408 NOTREACHED() << __FUNCTION__ << " Failed to launch url:" << url; |
401 return E_INVALIDARG; | 409 return E_INVALIDARG; |
402 } | 410 } |
403 return S_OK; | 411 return S_OK; |
404 } | 412 } |
405 | 413 |
406 STDMETHODIMP ChromeActiveDocument::SaveHistory(IStream* stream) { | 414 STDMETHODIMP ChromeActiveDocument::SaveHistory(IStream* stream) { |
407 // TODO(sanjeevr): We need to fetch the entire list of navigation entries | 415 // TODO(sanjeevr): We need to fetch the entire list of navigation entries |
408 // from Chrome and persist it in the stream. And in LoadHistory we need to | 416 // from Chrome and persist it in the stream. And in LoadHistory we need to |
409 // pass this list back to Chrome which will recreate the list. This will allow | 417 // pass this list back to Chrome which will recreate the list. This will allow |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
722 | 730 |
723 // Another case where we need to issue BeforeNavigate2 calls is as below:- | 731 // Another case where we need to issue BeforeNavigate2 calls is as below:- |
724 // We get notified after the fact, when navigations are initiated within | 732 // We get notified after the fact, when navigations are initiated within |
725 // Chrome via window.open calls. These navigations are handled by creating | 733 // Chrome via window.open calls. These navigations are handled by creating |
726 // an external tab container within chrome and then connecting to it from IE. | 734 // an external tab container within chrome and then connecting to it from IE. |
727 // We still want to update the address bar/history, etc, to ensure that | 735 // We still want to update the address bar/history, etc, to ensure that |
728 // the special URL used by Chrome to indicate this is updated correctly. | 736 // the special URL used by Chrome to indicate this is updated correctly. |
729 bool is_internal_navigation = ((new_navigation_info.navigation_index > 0) && | 737 bool is_internal_navigation = ((new_navigation_info.navigation_index > 0) && |
730 (new_navigation_info.navigation_index != | 738 (new_navigation_info.navigation_index != |
731 navigation_info_.navigation_index)) || | 739 navigation_info_.navigation_index)) || |
732 StartsWith(static_cast<BSTR>(url_), kChromeAttachExternalTabPrefix, | 740 MatchPatternWide(static_cast<BSTR>(url_), kChromeFrameAttachTabPattern); |
733 false); | |
734 | 741 |
735 if (new_navigation_info.url.is_valid()) | 742 if (new_navigation_info.url.is_valid()) |
736 url_.Allocate(UTF8ToWide(new_navigation_info.url.spec()).c_str()); | 743 url_.Allocate(UTF8ToWide(new_navigation_info.url.spec()).c_str()); |
737 | 744 |
738 if (is_internal_navigation) { | 745 if (is_internal_navigation) { |
739 ScopedComPtr<IDocObjectService> doc_object_svc; | 746 ScopedComPtr<IDocObjectService> doc_object_svc; |
740 ScopedComPtr<IWebBrowserEventsService> web_browser_events_svc; | 747 ScopedComPtr<IWebBrowserEventsService> web_browser_events_svc; |
741 | 748 |
742 buggy_bho::BuggyBhoTls bad_bho_tls; | 749 buggy_bho::BuggyBhoTls bad_bho_tls; |
743 if (GetConfigBool(true, kEnableBuggyBhoIntercept)) { | 750 if (GetConfigBool(true, kEnableBuggyBhoIntercept)) { |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
943 hr = frame_cmd_target.QueryFrom(in_place_site); | 950 hr = frame_cmd_target.QueryFrom(in_place_site); |
944 | 951 |
945 if (frame_cmd_target) { | 952 if (frame_cmd_target) { |
946 hr = frame_cmd_target->Exec(cmd_group_guid, command_id, cmd_exec_opt, | 953 hr = frame_cmd_target->Exec(cmd_group_guid, command_id, cmd_exec_opt, |
947 in_args, out_args); | 954 in_args, out_args); |
948 } | 955 } |
949 | 956 |
950 return hr; | 957 return hr; |
951 } | 958 } |
952 | 959 |
953 DWORD ChromeActiveDocument::MapUrlToZone(const wchar_t* url) { | 960 bool ChromeActiveDocument::LaunchUrl(const ChromeFrameUrl& cf_url, |
954 DWORD zone = URLZONE_INVALID; | 961 const std::string& referrer) { |
955 if (security_manager_.get() == NULL) { | 962 DCHECK(automation_client_.get() != NULL); |
956 HRESULT hr = CoCreateInstance( | 963 DCHECK(!cf_url.url().empty()); |
957 CLSID_InternetSecurityManager, | |
958 NULL, | |
959 CLSCTX_ALL, | |
960 IID_IInternetSecurityManager, | |
961 reinterpret_cast<void**>(security_manager_.Receive())); | |
962 | 964 |
963 if (FAILED(hr)) { | 965 url_.Allocate(cf_url.url().c_str()); |
964 NOTREACHED() << __FUNCTION__ | |
965 << " Failed to create InternetSecurityManager. Error: 0x%x" | |
966 << hr; | |
967 return zone; | |
968 } | |
969 } | |
970 | 966 |
971 security_manager_->MapUrlToZone(url, &zone, 0); | 967 std::string utf8_url; |
972 return zone; | 968 WideToUTF8(url_, url_.Length(), &utf8_url); |
973 } | |
974 | 969 |
975 bool ChromeActiveDocument::ParseUrl(const std::wstring& url, | 970 DLOG(INFO) << "Url is " << url_; |
976 bool* is_new_navigation, | 971 |
977 bool* is_chrome_protocol, | 972 // Initiate navigation before launching chrome so that the url will be |
978 std::wstring* parsed_url) { | 973 // cached and sent with launch settings. |
979 if (!is_new_navigation || !is_chrome_protocol|| !parsed_url) { | 974 if (cf_url.attach_to_external_tab()) { |
980 NOTREACHED() << __FUNCTION__ << " Invalid arguments"; | 975 dimensions_ = cf_url.dimensions(); |
| 976 automation_client_->AttachExternalTab(cf_url.cookie()); |
| 977 } else if (!automation_client_->InitiateNavigation(utf8_url, |
| 978 referrer, |
| 979 is_privileged_)) { |
| 980 DLOG(ERROR) << "Invalid URL: " << url_; |
| 981 Error(L"Invalid URL"); |
| 982 url_.Reset(); |
981 return false; | 983 return false; |
982 } | 984 } |
983 | 985 |
984 std::wstring initial_url = url; | |
985 | |
986 *is_chrome_protocol = StartsWith(initial_url, kChromeProtocolPrefix, | |
987 false); | |
988 | |
989 *is_new_navigation = true; | |
990 | |
991 if (*is_chrome_protocol) { | |
992 initial_url.erase(0, lstrlen(kChromeProtocolPrefix)); | |
993 *is_new_navigation = | |
994 !StartsWith(initial_url, kChromeAttachExternalTabPrefix, false); | |
995 } | |
996 | |
997 if (!IsValidUrlScheme(initial_url, is_privileged_)) { | |
998 DLOG(WARNING) << __FUNCTION__ << " Disallowing navigation to url: " | |
999 << url; | |
1000 return false; | |
1001 } | |
1002 | |
1003 if (URLZONE_UNTRUSTED == MapUrlToZone(initial_url.c_str())) { | |
1004 DLOG(WARNING) << __FUNCTION__ | |
1005 << " Disallowing navigation to restricted url: " | |
1006 << initial_url; | |
1007 return false; | |
1008 } | |
1009 | |
1010 if (*is_chrome_protocol) { | |
1011 // Allow chrome protocol (gcf:) if - | |
1012 // - explicitly enabled using registry | |
1013 // - for gcf:attach_external_tab | |
1014 // - for gcf:about and gcf:view-source | |
1015 GURL crack_url(initial_url); | |
1016 bool allow_gcf_protocol = !*is_new_navigation || | |
1017 GetConfigBool(false, kEnableGCFProtocol) || | |
1018 crack_url.SchemeIs(chrome::kAboutScheme) || | |
1019 crack_url.SchemeIs(chrome::kViewSourceScheme); | |
1020 if (!allow_gcf_protocol) | |
1021 return false; | |
1022 } | |
1023 | |
1024 *parsed_url = initial_url; | |
1025 return true; | |
1026 } | |
1027 | |
1028 bool ChromeActiveDocument::LaunchUrl(const std::wstring& url, | |
1029 const std::string& referrer, | |
1030 bool is_new_navigation) { | |
1031 DCHECK(automation_client_.get() != NULL); | |
1032 | |
1033 url_.Allocate(url.c_str()); | |
1034 | |
1035 std::string utf8_url; | |
1036 | |
1037 if (!is_new_navigation) { | |
1038 int disposition = 0; | |
1039 uint64 external_tab_cookie = 0; | |
1040 | |
1041 if (!ParseAttachExternalTabUrl(url, &external_tab_cookie, &dimensions_, | |
1042 &disposition)) { | |
1043 NOTREACHED() << "Failed to parse attach tab url:" << url; | |
1044 return false; | |
1045 } | |
1046 | |
1047 if (external_tab_cookie == 0) { | |
1048 NOTREACHED() << "invalid url for attach tab: " << url; | |
1049 return false; | |
1050 } | |
1051 | |
1052 is_new_navigation_ = false; | |
1053 automation_client_->AttachExternalTab(external_tab_cookie); | |
1054 } else { | |
1055 is_new_navigation_ = true; | |
1056 // Initiate navigation before launching chrome so that the url will be | |
1057 // cached and sent with launch settings. | |
1058 if (url_.Length()) { | |
1059 WideToUTF8(url_, url_.Length(), &utf8_url); | |
1060 if (!automation_client_->InitiateNavigation(utf8_url, | |
1061 referrer, | |
1062 is_privileged_)) { | |
1063 DLOG(ERROR) << "Invalid URL: " << url; | |
1064 Error(L"Invalid URL"); | |
1065 url_.Reset(); | |
1066 return false; | |
1067 } | |
1068 | |
1069 DLOG(INFO) << "Url is " << url_; | |
1070 } | |
1071 } | |
1072 | |
1073 if (is_automation_client_reused_) | 986 if (is_automation_client_reused_) |
1074 return true; | 987 return true; |
1075 | 988 |
1076 automation_client_->SetUrlFetcher(&url_fetcher_); | 989 automation_client_->SetUrlFetcher(&url_fetcher_); |
1077 | 990 |
1078 return InitializeAutomation(GetHostProcessName(false), L"", IsIEInPrivate(), | 991 return InitializeAutomation(GetHostProcessName(false), L"", IsIEInPrivate(), |
1079 false, GURL(utf8_url), GURL(referrer)); | 992 false, GURL(utf8_url), GURL(referrer)); |
1080 } | 993 } |
1081 | 994 |
1082 | 995 |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1293 SetFocus(); | 1206 SetFocus(); |
1294 return 0; | 1207 return 0; |
1295 } | 1208 } |
1296 | 1209 |
1297 LRESULT ChromeActiveDocument::OnSetFocus(UINT message, WPARAM wparam, | 1210 LRESULT ChromeActiveDocument::OnSetFocus(UINT message, WPARAM wparam, |
1298 LPARAM lparam, | 1211 LPARAM lparam, |
1299 BOOL& handled) { // NO_LINT | 1212 BOOL& handled) { // NO_LINT |
1300 GiveFocusToChrome(false); | 1213 GiveFocusToChrome(false); |
1301 return 0; | 1214 return 0; |
1302 } | 1215 } |
OLD | NEW |