| 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 |