OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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 #include <htiframe.h> | 5 #include <htiframe.h> |
6 #include <mshtml.h> | 6 #include <mshtml.h> |
7 | 7 |
8 #include "chrome_frame/protocol_sink_wrap.h" | 8 #include "chrome_frame/protocol_sink_wrap.h" |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 base::Lock ProtData::datamap_lock_; | 89 base::Lock ProtData::datamap_lock_; |
90 | 90 |
91 ProtocolSinkWrap::ProtocolSinkWrap() { | 91 ProtocolSinkWrap::ProtocolSinkWrap() { |
92 DVLOG(1) << __FUNCTION__ << base::StringPrintf(" 0x%08X", this); | 92 DVLOG(1) << __FUNCTION__ << base::StringPrintf(" 0x%08X", this); |
93 } | 93 } |
94 | 94 |
95 ProtocolSinkWrap::~ProtocolSinkWrap() { | 95 ProtocolSinkWrap::~ProtocolSinkWrap() { |
96 DVLOG(1) << __FUNCTION__ << base::StringPrintf(" 0x%08X", this); | 96 DVLOG(1) << __FUNCTION__ << base::StringPrintf(" 0x%08X", this); |
97 } | 97 } |
98 | 98 |
99 ScopedComPtr<IInternetProtocolSink> ProtocolSinkWrap::CreateNewSink( | 99 base::win::ScopedComPtr<IInternetProtocolSink> ProtocolSinkWrap::CreateNewSink( |
100 IInternetProtocolSink* sink, ProtData* data) { | 100 IInternetProtocolSink* sink, ProtData* data) { |
101 DCHECK(sink != NULL); | 101 DCHECK(sink != NULL); |
102 DCHECK(data != NULL); | 102 DCHECK(data != NULL); |
103 CComObject<ProtocolSinkWrap>* new_sink = NULL; | 103 CComObject<ProtocolSinkWrap>* new_sink = NULL; |
104 CComObject<ProtocolSinkWrap>::CreateInstance(&new_sink); | 104 CComObject<ProtocolSinkWrap>::CreateInstance(&new_sink); |
105 new_sink->delegate_ = sink; | 105 new_sink->delegate_ = sink; |
106 new_sink->prot_data_ = data; | 106 new_sink->prot_data_ = data; |
107 return ScopedComPtr<IInternetProtocolSink>(new_sink); | 107 return base::win::ScopedComPtr<IInternetProtocolSink>(new_sink); |
108 } | 108 } |
109 | 109 |
110 // IInternetProtocolSink methods | 110 // IInternetProtocolSink methods |
111 STDMETHODIMP ProtocolSinkWrap::Switch(PROTOCOLDATA* protocol_data) { | 111 STDMETHODIMP ProtocolSinkWrap::Switch(PROTOCOLDATA* protocol_data) { |
112 HRESULT hr = E_FAIL; | 112 HRESULT hr = E_FAIL; |
113 if (delegate_) | 113 if (delegate_) |
114 hr = delegate_->Switch(protocol_data); | 114 hr = delegate_->Switch(protocol_data); |
115 return hr; | 115 return hr; |
116 } | 116 } |
117 | 117 |
(...skipping 22 matching lines...) Expand all Loading... |
140 DVLOG(1) << "ProtocolSinkWrap::ReportResult: result: " << result | 140 DVLOG(1) << "ProtocolSinkWrap::ReportResult: result: " << result |
141 << " error: " << error | 141 << " error: " << error |
142 << " Text: " << (result_text ? result_text : L""); | 142 << " Text: " << (result_text ? result_text : L""); |
143 ExceptionBarrier barrier; | 143 ExceptionBarrier barrier; |
144 HRESULT hr = prot_data_->ReportResult(delegate_, result, error, result_text); | 144 HRESULT hr = prot_data_->ReportResult(delegate_, result, error, result_text); |
145 return hr; | 145 return hr; |
146 } | 146 } |
147 | 147 |
148 | 148 |
149 // Helpers | 149 // Helpers |
150 ScopedComPtr<IBindCtx> BindCtxFromIBindInfo(IInternetBindInfo* bind_info) { | 150 base::win::ScopedComPtr<IBindCtx> BindCtxFromIBindInfo( |
| 151 IInternetBindInfo* bind_info) { |
151 LPOLESTR bind_ctx_string = NULL; | 152 LPOLESTR bind_ctx_string = NULL; |
152 ULONG count; | 153 ULONG count; |
153 ScopedComPtr<IBindCtx> bind_ctx; | 154 base::win::ScopedComPtr<IBindCtx> bind_ctx; |
154 bind_info->GetBindString(BINDSTRING_PTR_BIND_CONTEXT, &bind_ctx_string, 1, | 155 bind_info->GetBindString(BINDSTRING_PTR_BIND_CONTEXT, &bind_ctx_string, 1, |
155 &count); | 156 &count); |
156 if (bind_ctx_string) { | 157 if (bind_ctx_string) { |
157 int bind_ctx_int; | 158 int bind_ctx_int; |
158 base::StringToInt(bind_ctx_string, &bind_ctx_int); | 159 base::StringToInt(bind_ctx_string, &bind_ctx_int); |
159 IBindCtx* pbc = reinterpret_cast<IBindCtx*>(bind_ctx_int); | 160 IBindCtx* pbc = reinterpret_cast<IBindCtx*>(bind_ctx_int); |
160 bind_ctx.Attach(pbc); | 161 bind_ctx.Attach(pbc); |
161 CoTaskMemFree(bind_ctx_string); | 162 CoTaskMemFree(bind_ctx_string); |
162 } | 163 } |
163 | 164 |
164 return bind_ctx; | 165 return bind_ctx; |
165 } | 166 } |
166 | 167 |
167 bool ShouldWrapSink(IInternetProtocolSink* sink, const wchar_t* url) { | 168 bool ShouldWrapSink(IInternetProtocolSink* sink, const wchar_t* url) { |
168 // Ignore everything that does not start with http:// or https://. | 169 // Ignore everything that does not start with http:// or https://. |
169 // |url| is already normalized (i.e. no leading spaces, capital letters in | 170 // |url| is already normalized (i.e. no leading spaces, capital letters in |
170 // protocol etc) and non-null (we check in Hook_Start). | 171 // protocol etc) and non-null (we check in Hook_Start). |
171 DCHECK(url != NULL); | 172 DCHECK(url != NULL); |
172 | 173 |
173 if (ProtocolSinkWrap::ignore_xua()) | 174 if (ProtocolSinkWrap::ignore_xua()) |
174 return false; // No need to intercept, we're ignoring X-UA-Compatible tags | 175 return false; // No need to intercept, we're ignoring X-UA-Compatible tags |
175 | 176 |
176 if ((url != StrStrW(url, L"http://")) && (url != StrStrW(url, L"https://"))) | 177 if ((url != StrStrW(url, L"http://")) && (url != StrStrW(url, L"https://"))) |
177 return false; | 178 return false; |
178 | 179 |
179 ScopedComPtr<IHttpNegotiate> http_negotiate; | 180 base::win::ScopedComPtr<IHttpNegotiate> http_negotiate; |
180 HRESULT hr = DoQueryService(GUID_NULL, sink, http_negotiate.Receive()); | 181 HRESULT hr = DoQueryService(GUID_NULL, sink, http_negotiate.Receive()); |
181 if (http_negotiate && !IsSubFrameRequest(http_negotiate)) | 182 if (http_negotiate && !IsSubFrameRequest(http_negotiate)) |
182 return true; | 183 return true; |
183 | 184 |
184 return false; | 185 return false; |
185 } | 186 } |
186 | 187 |
187 // High level helpers | 188 // High level helpers |
188 bool IsCFRequest(IBindCtx* pbc) { | 189 bool IsCFRequest(IBindCtx* pbc) { |
189 ScopedComPtr<BindContextInfo> info; | 190 base::win::ScopedComPtr<BindContextInfo> info; |
190 BindContextInfo::FromBindContext(pbc, info.Receive()); | 191 BindContextInfo::FromBindContext(pbc, info.Receive()); |
191 if (info && info->chrome_request()) | 192 if (info && info->chrome_request()) |
192 return true; | 193 return true; |
193 | 194 |
194 return false; | 195 return false; |
195 } | 196 } |
196 | 197 |
197 bool HasProtData(IBindCtx* pbc) { | 198 bool HasProtData(IBindCtx* pbc) { |
198 ScopedComPtr<BindContextInfo> info; | 199 base::win::ScopedComPtr<BindContextInfo> info; |
199 BindContextInfo::FromBindContext(pbc, info.Receive()); | 200 BindContextInfo::FromBindContext(pbc, info.Receive()); |
200 bool result = false; | 201 bool result = false; |
201 if (info) | 202 if (info) |
202 result = info->has_prot_data(); | 203 result = info->has_prot_data(); |
203 return result; | 204 return result; |
204 } | 205 } |
205 | 206 |
206 void PutProtData(IBindCtx* pbc, ProtData* data) { | 207 void PutProtData(IBindCtx* pbc, ProtData* data) { |
207 // AddRef and Release to avoid a potential leak of a ProtData instance if | 208 // AddRef and Release to avoid a potential leak of a ProtData instance if |
208 // FromBindContext fails. | 209 // FromBindContext fails. |
209 data->AddRef(); | 210 data->AddRef(); |
210 ScopedComPtr<BindContextInfo> info; | 211 base::win::ScopedComPtr<BindContextInfo> info; |
211 BindContextInfo::FromBindContext(pbc, info.Receive()); | 212 BindContextInfo::FromBindContext(pbc, info.Receive()); |
212 if (info) | 213 if (info) |
213 info->set_prot_data(data); | 214 info->set_prot_data(data); |
214 data->Release(); | 215 data->Release(); |
215 } | 216 } |
216 | 217 |
217 bool IsTextHtml(const wchar_t* status_text) { | 218 bool IsTextHtml(const wchar_t* status_text) { |
218 const std::wstring str = status_text; | 219 const std::wstring str = status_text; |
219 bool is_text_html = LowerCaseEqualsASCII(str, kTextHtmlMimeType); | 220 bool is_text_html = LowerCaseEqualsASCII(str, kTextHtmlMimeType); |
220 return is_text_html; | 221 return is_text_html; |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
411 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE: | 412 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE: |
412 SaveSuggestedMimeType(status_text); | 413 SaveSuggestedMimeType(status_text); |
413 // When Transaction is attached i.e. when existing BTS it terminated | 414 // When Transaction is attached i.e. when existing BTS it terminated |
414 // and "converted" to BTO, events will be re-fired for the new sink, | 415 // and "converted" to BTO, events will be re-fired for the new sink, |
415 // but we may skip the renderer_type_ determination since it's already | 416 // but we may skip the renderer_type_ determination since it's already |
416 // done. | 417 // done. |
417 if (renderer_type_ == RENDERER_TYPE_UNDETERMINED) { | 418 if (renderer_type_ == RENDERER_TYPE_UNDETERMINED) { |
418 // This may seem awkward. CBinding's implementation of IWinInetHttpInfo | 419 // This may seem awkward. CBinding's implementation of IWinInetHttpInfo |
419 // will forward to CTransaction that will forward to the real protocol. | 420 // will forward to CTransaction that will forward to the real protocol. |
420 // We may ask CTransaction (our protocol_ member) for IWinInetHttpInfo. | 421 // We may ask CTransaction (our protocol_ member) for IWinInetHttpInfo. |
421 ScopedComPtr<IWinInetHttpInfo> info; | 422 base::win::ScopedComPtr<IWinInetHttpInfo> info; |
422 info.QueryFrom(delegate); | 423 info.QueryFrom(delegate); |
423 renderer_type_ = DetermineRendererTypeFromMetaData(suggested_mime_type_, | 424 renderer_type_ = DetermineRendererTypeFromMetaData(suggested_mime_type_, |
424 url_, info); | 425 url_, info); |
425 } | 426 } |
426 | 427 |
427 if (IsChrome(renderer_type_)) { | 428 if (IsChrome(renderer_type_)) { |
428 // Suggested mime type is "text/html" and we have DEFAULT_RENDERER, | 429 // Suggested mime type is "text/html" and we have DEFAULT_RENDERER, |
429 // OPT_IN_URL, or RESPONSE_HEADER. | 430 // OPT_IN_URL, or RESPONSE_HEADER. |
430 DVLOG(1) << "Forwarding BINDSTATUS_MIMETYPEAVAILABLE " | 431 DVLOG(1) << "Forwarding BINDSTATUS_MIMETYPEAVAILABLE " |
431 << kChromeMimeType; | 432 << kChromeMimeType; |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 if (has_suggested_mime_type_) { | 546 if (has_suggested_mime_type_) { |
546 DVLOG(1) << "Forwarding BINDSTATUS_MIMETYPEAVAILABLE " | 547 DVLOG(1) << "Forwarding BINDSTATUS_MIMETYPEAVAILABLE " |
547 << suggested_mime_type_; | 548 << suggested_mime_type_; |
548 delegate->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, | 549 delegate->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, |
549 suggested_mime_type_); | 550 suggested_mime_type_); |
550 } | 551 } |
551 } | 552 } |
552 | 553 |
553 void ProtData::SaveReferrer(IInternetProtocolSink* delegate) { | 554 void ProtData::SaveReferrer(IInternetProtocolSink* delegate) { |
554 DCHECK(IsChrome(renderer_type_)); | 555 DCHECK(IsChrome(renderer_type_)); |
555 ScopedComPtr<IWinInetHttpInfo> info; | 556 base::win::ScopedComPtr<IWinInetHttpInfo> info; |
556 info.QueryFrom(delegate); | 557 info.QueryFrom(delegate); |
557 if (info) { | 558 if (info) { |
558 char buffer[4096] = {0}; | 559 char buffer[4096] = {0}; |
559 DWORD len = sizeof(buffer); | 560 DWORD len = sizeof(buffer); |
560 DWORD flags = 0; | 561 DWORD flags = 0; |
561 HRESULT hr = info->QueryInfo( | 562 HRESULT hr = info->QueryInfo( |
562 HTTP_QUERY_REFERER | HTTP_QUERY_FLAG_REQUEST_HEADERS, | 563 HTTP_QUERY_REFERER | HTTP_QUERY_FLAG_REQUEST_HEADERS, |
563 buffer, &len, &flags, 0); | 564 buffer, &len, &flags, 0); |
564 if (hr == S_OK && len > 0) | 565 if (hr == S_OK && len > 0) |
565 referrer_.assign(buffer); | 566 referrer_.assign(buffer); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 | 638 |
638 // IInternetProtocol/Ex hooks. | 639 // IInternetProtocol/Ex hooks. |
639 STDMETHODIMP Hook_Start(InternetProtocol_Start_Fn orig_start, | 640 STDMETHODIMP Hook_Start(InternetProtocol_Start_Fn orig_start, |
640 IInternetProtocol* protocol, LPCWSTR url, IInternetProtocolSink* prot_sink, | 641 IInternetProtocol* protocol, LPCWSTR url, IInternetProtocolSink* prot_sink, |
641 IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved) { | 642 IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved) { |
642 DCHECK(orig_start); | 643 DCHECK(orig_start); |
643 if (!url || !prot_sink || !bind_info) | 644 if (!url || !prot_sink || !bind_info) |
644 return E_INVALIDARG; | 645 return E_INVALIDARG; |
645 DVLOG_IF(1, url != NULL) << "OnStart: " << url << PiFlags2Str(flags); | 646 DVLOG_IF(1, url != NULL) << "OnStart: " << url << PiFlags2Str(flags); |
646 | 647 |
647 ScopedComPtr<IBindCtx> bind_ctx = BindCtxFromIBindInfo(bind_info); | 648 base::win::ScopedComPtr<IBindCtx> bind_ctx = BindCtxFromIBindInfo(bind_info); |
648 if (!bind_ctx) { | 649 if (!bind_ctx) { |
649 // MSHTML sometimes takes a short path, skips the creation of | 650 // MSHTML sometimes takes a short path, skips the creation of |
650 // moniker and binding, by directly grabbing protocol from InternetSession | 651 // moniker and binding, by directly grabbing protocol from InternetSession |
651 DVLOG(1) << "DirectBind for " << url; | 652 DVLOG(1) << "DirectBind for " << url; |
652 return ForwardHookStart(orig_start, protocol, url, prot_sink, bind_info, | 653 return ForwardHookStart(orig_start, protocol, url, prot_sink, bind_info, |
653 flags, reserved); | 654 flags, reserved); |
654 } | 655 } |
655 | 656 |
656 scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol); | 657 scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol); |
657 if (prot_data && !HasProtData(bind_ctx)) { | 658 if (prot_data && !HasProtData(bind_ctx)) { |
658 prot_data->Invalidate(); | 659 prot_data->Invalidate(); |
659 prot_data = NULL; | 660 prot_data = NULL; |
660 } | 661 } |
661 | 662 |
662 if (HandleAttachToExistingExternalTab(url, protocol, prot_sink, bind_ctx)) { | 663 if (HandleAttachToExistingExternalTab(url, protocol, prot_sink, bind_ctx)) { |
663 return S_OK; | 664 return S_OK; |
664 } | 665 } |
665 | 666 |
666 if (IsCFRequest(bind_ctx)) { | 667 if (IsCFRequest(bind_ctx)) { |
667 ScopedComPtr<BindContextInfo> info; | 668 base::win::ScopedComPtr<BindContextInfo> info; |
668 BindContextInfo::FromBindContext(bind_ctx, info.Receive()); | 669 BindContextInfo::FromBindContext(bind_ctx, info.Receive()); |
669 DCHECK(info); | 670 DCHECK(info); |
670 if (info) { | 671 if (info) { |
671 info->set_protocol(protocol); | 672 info->set_protocol(protocol); |
672 } | 673 } |
673 return ForwardHookStart(orig_start, protocol, url, prot_sink, bind_info, | 674 return ForwardHookStart(orig_start, protocol, url, prot_sink, bind_info, |
674 flags, reserved); | 675 flags, reserved); |
675 } | 676 } |
676 | 677 |
677 if (prot_data) { | 678 if (prot_data) { |
678 DVLOG(1) << "Found existing ProtData!"; | 679 DVLOG(1) << "Found existing ProtData!"; |
679 prot_data->UpdateUrl(url); | 680 prot_data->UpdateUrl(url); |
680 ScopedComPtr<IInternetProtocolSink> new_sink = | 681 base::win::ScopedComPtr<IInternetProtocolSink> new_sink = |
681 ProtocolSinkWrap::CreateNewSink(prot_sink, prot_data); | 682 ProtocolSinkWrap::CreateNewSink(prot_sink, prot_data); |
682 return ForwardWrappedHookStart(orig_start, protocol, url, new_sink, | 683 return ForwardWrappedHookStart(orig_start, protocol, url, new_sink, |
683 bind_info, flags, reserved); | 684 bind_info, flags, reserved); |
684 } | 685 } |
685 | 686 |
686 if (!ShouldWrapSink(prot_sink, url)) { | 687 if (!ShouldWrapSink(prot_sink, url)) { |
687 return ForwardHookStart(orig_start, protocol, url, prot_sink, bind_info, | 688 return ForwardHookStart(orig_start, protocol, url, prot_sink, bind_info, |
688 flags, reserved); | 689 flags, reserved); |
689 } | 690 } |
690 | 691 |
691 // Fresh request. | 692 // Fresh request. |
692 InternetProtocol_Read_Fn read_fun = reinterpret_cast<InternetProtocol_Read_Fn> | 693 InternetProtocol_Read_Fn read_fun = reinterpret_cast<InternetProtocol_Read_Fn> |
693 (CTransaction_PatchInfo[1].stub_->argument()); | 694 (CTransaction_PatchInfo[1].stub_->argument()); |
694 prot_data = new ProtData(protocol, read_fun, url); | 695 prot_data = new ProtData(protocol, read_fun, url); |
695 PutProtData(bind_ctx, prot_data); | 696 PutProtData(bind_ctx, prot_data); |
696 | 697 |
697 ScopedComPtr<IInternetProtocolSink> new_sink = | 698 base::win::ScopedComPtr<IInternetProtocolSink> new_sink = |
698 ProtocolSinkWrap::CreateNewSink(prot_sink, prot_data); | 699 ProtocolSinkWrap::CreateNewSink(prot_sink, prot_data); |
699 return ForwardWrappedHookStart(orig_start, protocol, url, new_sink, bind_info, | 700 return ForwardWrappedHookStart(orig_start, protocol, url, new_sink, bind_info, |
700 flags, reserved); | 701 flags, reserved); |
701 } | 702 } |
702 | 703 |
703 HRESULT ForwardHookStartEx(InternetProtocol_StartEx_Fn orig_start_ex, | 704 HRESULT ForwardHookStartEx(InternetProtocol_StartEx_Fn orig_start_ex, |
704 IInternetProtocolEx* protocol, IUri* uri, IInternetProtocolSink* prot_sink, | 705 IInternetProtocolEx* protocol, IUri* uri, IInternetProtocolSink* prot_sink, |
705 IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved) { | 706 IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved) { |
706 ExceptionBarrierReportOnlyModule barrier; | 707 ExceptionBarrierReportOnlyModule barrier; |
707 return orig_start_ex(protocol, uri, prot_sink, bind_info, flags, reserved); | 708 return orig_start_ex(protocol, uri, prot_sink, bind_info, flags, reserved); |
(...skipping 10 matching lines...) Expand all Loading... |
718 IInternetProtocolEx* protocol, IUri* uri, IInternetProtocolSink* prot_sink, | 719 IInternetProtocolEx* protocol, IUri* uri, IInternetProtocolSink* prot_sink, |
719 IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved) { | 720 IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved) { |
720 DCHECK(orig_start_ex); | 721 DCHECK(orig_start_ex); |
721 if (!uri || !prot_sink || !bind_info) | 722 if (!uri || !prot_sink || !bind_info) |
722 return E_INVALIDARG; | 723 return E_INVALIDARG; |
723 | 724 |
724 base::win::ScopedBstr url; | 725 base::win::ScopedBstr url; |
725 uri->GetPropertyBSTR(Uri_PROPERTY_ABSOLUTE_URI, url.Receive(), 0); | 726 uri->GetPropertyBSTR(Uri_PROPERTY_ABSOLUTE_URI, url.Receive(), 0); |
726 DVLOG_IF(1, url != NULL) << "OnStartEx: " << url << PiFlags2Str(flags); | 727 DVLOG_IF(1, url != NULL) << "OnStartEx: " << url << PiFlags2Str(flags); |
727 | 728 |
728 ScopedComPtr<IBindCtx> bind_ctx = BindCtxFromIBindInfo(bind_info); | 729 base::win::ScopedComPtr<IBindCtx> bind_ctx = BindCtxFromIBindInfo(bind_info); |
729 if (!bind_ctx) { | 730 if (!bind_ctx) { |
730 // MSHTML sometimes takes a short path, skips the creation of | 731 // MSHTML sometimes takes a short path, skips the creation of |
731 // moniker and binding, by directly grabbing protocol from InternetSession. | 732 // moniker and binding, by directly grabbing protocol from InternetSession. |
732 DVLOG(1) << "DirectBind for " << url; | 733 DVLOG(1) << "DirectBind for " << url; |
733 return ForwardHookStartEx(orig_start_ex, protocol, uri, prot_sink, | 734 return ForwardHookStartEx(orig_start_ex, protocol, uri, prot_sink, |
734 bind_info, flags, reserved); | 735 bind_info, flags, reserved); |
735 } | 736 } |
736 | 737 |
737 scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol); | 738 scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol); |
738 if (prot_data && !HasProtData(bind_ctx)) { | 739 if (prot_data && !HasProtData(bind_ctx)) { |
739 prot_data->Invalidate(); | 740 prot_data->Invalidate(); |
740 prot_data = NULL; | 741 prot_data = NULL; |
741 } | 742 } |
742 | 743 |
743 if (HandleAttachToExistingExternalTab(url, protocol, prot_sink, bind_ctx)) { | 744 if (HandleAttachToExistingExternalTab(url, protocol, prot_sink, bind_ctx)) { |
744 return S_OK; | 745 return S_OK; |
745 } | 746 } |
746 | 747 |
747 if (IsCFRequest(bind_ctx)) { | 748 if (IsCFRequest(bind_ctx)) { |
748 ScopedComPtr<BindContextInfo> info; | 749 base::win::ScopedComPtr<BindContextInfo> info; |
749 BindContextInfo::FromBindContext(bind_ctx, info.Receive()); | 750 BindContextInfo::FromBindContext(bind_ctx, info.Receive()); |
750 DCHECK(info); | 751 DCHECK(info); |
751 if (info) { | 752 if (info) { |
752 info->set_protocol(protocol); | 753 info->set_protocol(protocol); |
753 } | 754 } |
754 return ForwardHookStartEx(orig_start_ex, protocol, uri, prot_sink, | 755 return ForwardHookStartEx(orig_start_ex, protocol, uri, prot_sink, |
755 bind_info, flags, reserved); | 756 bind_info, flags, reserved); |
756 } | 757 } |
757 | 758 |
758 if (prot_data) { | 759 if (prot_data) { |
759 DVLOG(1) << "Found existing ProtData!"; | 760 DVLOG(1) << "Found existing ProtData!"; |
760 prot_data->UpdateUrl(url); | 761 prot_data->UpdateUrl(url); |
761 ScopedComPtr<IInternetProtocolSink> new_sink = | 762 base::win::ScopedComPtr<IInternetProtocolSink> new_sink = |
762 ProtocolSinkWrap::CreateNewSink(prot_sink, prot_data); | 763 ProtocolSinkWrap::CreateNewSink(prot_sink, prot_data); |
763 return ForwardWrappedHookStartEx(orig_start_ex, protocol, uri, new_sink, | 764 return ForwardWrappedHookStartEx(orig_start_ex, protocol, uri, new_sink, |
764 bind_info, flags, reserved); | 765 bind_info, flags, reserved); |
765 } | 766 } |
766 | 767 |
767 if (!ShouldWrapSink(prot_sink, url)) { | 768 if (!ShouldWrapSink(prot_sink, url)) { |
768 return ForwardHookStartEx(orig_start_ex, protocol, uri, prot_sink, | 769 return ForwardHookStartEx(orig_start_ex, protocol, uri, prot_sink, |
769 bind_info, flags, reserved); | 770 bind_info, flags, reserved); |
770 } | 771 } |
771 | 772 |
772 // Fresh request. | 773 // Fresh request. |
773 InternetProtocol_Read_Fn read_fun = reinterpret_cast<InternetProtocol_Read_Fn> | 774 InternetProtocol_Read_Fn read_fun = reinterpret_cast<InternetProtocol_Read_Fn> |
774 (CTransaction_PatchInfo[1].stub_->argument()); | 775 (CTransaction_PatchInfo[1].stub_->argument()); |
775 prot_data = new ProtData(protocol, read_fun, url); | 776 prot_data = new ProtData(protocol, read_fun, url); |
776 PutProtData(bind_ctx, prot_data); | 777 PutProtData(bind_ctx, prot_data); |
777 | 778 |
778 ScopedComPtr<IInternetProtocolSink> new_sink = | 779 base::win::ScopedComPtr<IInternetProtocolSink> new_sink = |
779 ProtocolSinkWrap::CreateNewSink(prot_sink, prot_data); | 780 ProtocolSinkWrap::CreateNewSink(prot_sink, prot_data); |
780 return ForwardWrappedHookStartEx(orig_start_ex, protocol, uri, new_sink, | 781 return ForwardWrappedHookStartEx(orig_start_ex, protocol, uri, new_sink, |
781 bind_info, flags, reserved); | 782 bind_info, flags, reserved); |
782 } | 783 } |
783 | 784 |
784 STDMETHODIMP Hook_Read(InternetProtocol_Read_Fn orig_read, | 785 STDMETHODIMP Hook_Read(InternetProtocol_Read_Fn orig_read, |
785 IInternetProtocol* protocol, void* buffer, ULONG size, ULONG* size_read) { | 786 IInternetProtocol* protocol, void* buffer, ULONG size, ULONG* size_read) { |
786 DCHECK(orig_read); | 787 DCHECK(orig_read); |
787 HRESULT hr = E_FAIL; | 788 HRESULT hr = E_FAIL; |
788 | 789 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
857 STDMETHOD(Abort)(HRESULT reason, DWORD options) { return S_OK; } | 858 STDMETHOD(Abort)(HRESULT reason, DWORD options) { return S_OK; } |
858 STDMETHOD(Terminate)(DWORD options) { return S_OK; } | 859 STDMETHOD(Terminate)(DWORD options) { return S_OK; } |
859 STDMETHOD(Suspend)() { return S_OK; } | 860 STDMETHOD(Suspend)() { return S_OK; } |
860 STDMETHOD(Resume)() { return S_OK; } | 861 STDMETHOD(Resume)() { return S_OK; } |
861 STDMETHOD(Read)(void *buffer, ULONG size, ULONG* size_read) { return S_OK; } | 862 STDMETHOD(Read)(void *buffer, ULONG size, ULONG* size_read) { return S_OK; } |
862 STDMETHOD(Seek)(LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER* new_pos) | 863 STDMETHOD(Seek)(LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER* new_pos) |
863 { return S_OK; } | 864 { return S_OK; } |
864 STDMETHOD(LockRequest)(DWORD options) { return S_OK; } | 865 STDMETHOD(LockRequest)(DWORD options) { return S_OK; } |
865 STDMETHOD(UnlockRequest)() { return S_OK; } | 866 STDMETHOD(UnlockRequest)() { return S_OK; } |
866 | 867 |
867 ScopedComPtr<IInternetProtocol> transaction_; | 868 base::win::ScopedComPtr<IInternetProtocol> transaction_; |
868 }; | 869 }; |
869 | 870 |
870 struct FakeFactory : public IClassFactory, | 871 struct FakeFactory : public IClassFactory, |
871 public CComObjectRootEx<CComSingleThreadModel> { | 872 public CComObjectRootEx<CComSingleThreadModel> { |
872 BEGIN_COM_MAP(FakeFactory) | 873 BEGIN_COM_MAP(FakeFactory) |
873 COM_INTERFACE_ENTRY(IClassFactory) | 874 COM_INTERFACE_ENTRY(IClassFactory) |
874 END_COM_MAP() | 875 END_COM_MAP() |
875 | 876 |
876 STDMETHOD(CreateInstance)(IUnknown *pUnkOuter, REFIID riid, void **ppvObj) { | 877 STDMETHOD(CreateInstance)(IUnknown *pUnkOuter, REFIID riid, void **ppvObj) { |
877 if (pUnkOuter) | 878 if (pUnkOuter) |
878 return CLASS_E_NOAGGREGATION; | 879 return CLASS_E_NOAGGREGATION; |
879 HRESULT hr = obj_->QueryInterface(riid, ppvObj); | 880 HRESULT hr = obj_->QueryInterface(riid, ppvObj); |
880 return hr; | 881 return hr; |
881 } | 882 } |
882 | 883 |
883 STDMETHOD(LockServer)(BOOL fLock) { | 884 STDMETHOD(LockServer)(BOOL fLock) { |
884 return S_OK; | 885 return S_OK; |
885 } | 886 } |
886 | 887 |
887 IUnknown* obj_; | 888 IUnknown* obj_; |
888 }; | 889 }; |
889 | 890 |
890 static void HookTransactionVtable(IInternetProtocol* p) { | 891 static void HookTransactionVtable(IInternetProtocol* p) { |
891 ScopedComPtr<IInternetProtocolEx> ex; | 892 base::win::ScopedComPtr<IInternetProtocolEx> ex; |
892 ex.QueryFrom(p); | 893 ex.QueryFrom(p); |
893 | 894 |
894 HRESULT hr = vtable_patch::PatchInterfaceMethods(p, CTransaction_PatchInfo); | 895 HRESULT hr = vtable_patch::PatchInterfaceMethods(p, CTransaction_PatchInfo); |
895 if (hr == S_OK && ex) { | 896 if (hr == S_OK && ex) { |
896 vtable_patch::PatchInterfaceMethods(ex.get(), CTransaction2_PatchInfo); | 897 vtable_patch::PatchInterfaceMethods(ex.get(), CTransaction2_PatchInfo); |
897 } | 898 } |
898 } | 899 } |
899 | 900 |
900 void TransactionHooks::InstallHooks() { | 901 void TransactionHooks::InstallHooks() { |
901 if (IS_PATCHED(CTransaction)) { | 902 if (IS_PATCHED(CTransaction)) { |
902 DLOG(WARNING) << __FUNCTION__ << " called more than once."; | 903 DLOG(WARNING) << __FUNCTION__ << " called more than once."; |
903 return; | 904 return; |
904 } | 905 } |
905 | 906 |
906 CComObjectStackEx<FakeProtocol> prot; | 907 CComObjectStackEx<FakeProtocol> prot; |
907 CComObjectStackEx<FakeFactory> factory; | 908 CComObjectStackEx<FakeFactory> factory; |
908 factory.obj_ = &prot; | 909 factory.obj_ = &prot; |
909 ScopedComPtr<IInternetSession> session; | 910 base::win::ScopedComPtr<IInternetSession> session; |
910 HRESULT hr = ::CoInternetGetSession(0, session.Receive(), 0); | 911 HRESULT hr = ::CoInternetGetSession(0, session.Receive(), 0); |
911 hr = session->RegisterNameSpace(&factory, CLSID_NULL, L"611", 0, 0, 0); | 912 hr = session->RegisterNameSpace(&factory, CLSID_NULL, L"611", 0, 0, 0); |
912 DLOG_IF(FATAL, FAILED(hr)) << "Failed to register namespace"; | 913 DLOG_IF(FATAL, FAILED(hr)) << "Failed to register namespace"; |
913 if (hr != S_OK) | 914 if (hr != S_OK) |
914 return; | 915 return; |
915 | 916 |
916 do { | 917 do { |
917 ScopedComPtr<IMoniker> mk; | 918 base::win::ScopedComPtr<IMoniker> mk; |
918 ScopedComPtr<IBindCtx> bc; | 919 base::win::ScopedComPtr<IBindCtx> bc; |
919 ScopedComPtr<IStream> stream; | 920 base::win::ScopedComPtr<IStream> stream; |
920 hr = ::CreateAsyncBindCtxEx(0, 0, 0, 0, bc.Receive(), 0); | 921 hr = ::CreateAsyncBindCtxEx(0, 0, 0, 0, bc.Receive(), 0); |
921 DLOG_IF(FATAL, FAILED(hr)) << "CreateAsyncBindCtxEx failed " << hr; | 922 DLOG_IF(FATAL, FAILED(hr)) << "CreateAsyncBindCtxEx failed " << hr; |
922 if (hr != S_OK) | 923 if (hr != S_OK) |
923 break; | 924 break; |
924 | 925 |
925 hr = ::CreateURLMoniker(NULL, L"611://512", mk.Receive()); | 926 hr = ::CreateURLMoniker(NULL, L"611://512", mk.Receive()); |
926 DLOG_IF(FATAL, FAILED(hr)) << "CreateURLMoniker failed " << hr; | 927 DLOG_IF(FATAL, FAILED(hr)) << "CreateURLMoniker failed " << hr; |
927 if (hr != S_OK) | 928 if (hr != S_OK) |
928 break; | 929 break; |
929 | 930 |
930 hr = mk->BindToStorage(bc, NULL, IID_IStream, | 931 hr = mk->BindToStorage(bc, NULL, IID_IStream, |
931 reinterpret_cast<void**>(stream.Receive())); | 932 reinterpret_cast<void**>(stream.Receive())); |
932 DLOG_IF(FATAL, hr != INET_E_INVALID_CERTIFICATE) << | 933 DLOG_IF(FATAL, hr != INET_E_INVALID_CERTIFICATE) << |
933 "BindToStorage failed " << hr; | 934 "BindToStorage failed " << hr; |
934 } while (0); | 935 } while (0); |
935 | 936 |
936 hr = session->UnregisterNameSpace(&factory, L"611"); | 937 hr = session->UnregisterNameSpace(&factory, L"611"); |
937 if (prot.transaction_) { | 938 if (prot.transaction_) { |
938 HookTransactionVtable(prot.transaction_); | 939 HookTransactionVtable(prot.transaction_); |
939 // Explicit release, otherwise ~CComObjectStackEx will complain about | 940 // Explicit release, otherwise ~CComObjectStackEx will complain about |
940 // outstanding reference to us, because it runs before ~FakeProtocol | 941 // outstanding reference to us, because it runs before ~FakeProtocol |
941 prot.transaction_.Release(); | 942 prot.transaction_.Release(); |
942 } | 943 } |
943 } | 944 } |
944 | 945 |
945 void TransactionHooks::RevertHooks() { | 946 void TransactionHooks::RevertHooks() { |
946 vtable_patch::UnpatchInterfaceMethods(CTransaction_PatchInfo); | 947 vtable_patch::UnpatchInterfaceMethods(CTransaction_PatchInfo); |
947 vtable_patch::UnpatchInterfaceMethods(CTransaction2_PatchInfo); | 948 vtable_patch::UnpatchInterfaceMethods(CTransaction2_PatchInfo); |
948 } | 949 } |
OLD | NEW |