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

Unified Diff: chrome_frame/protocol_sink_wrap.cc

Issue 2620001: A new way of hooking internet protocols. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome_frame/protocol_sink_wrap.h ('k') | chrome_frame/test/test_mock_with_web_server.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome_frame/protocol_sink_wrap.cc
===================================================================
--- chrome_frame/protocol_sink_wrap.cc (revision 48838)
+++ chrome_frame/protocol_sink_wrap.cc (working copy)
@@ -13,6 +13,8 @@
#include "base/singleton.h"
#include "base/string_util.h"
+#include "chrome_frame/bind_context_info.h"
+#include "chrome_frame/function_stub.h"
#include "chrome_frame/utils.h"
// BINDSTATUS_SERVER_MIMETYPEAVAILABLE == 54. Introduced in IE 8, so
@@ -29,640 +31,595 @@
static const int kInternetProtocolReadIndex = 9;
static const int kInternetProtocolStartExIndex = 13;
-// TODO(ananta)
-// We should avoid duplicate VTable declarations.
-BEGIN_VTABLE_PATCHES(IInternetProtocol)
- VTABLE_PATCH_ENTRY(kInternetProtocolStartIndex, ProtocolSinkWrap::OnStart)
- VTABLE_PATCH_ENTRY(kInternetProtocolReadIndex, ProtocolSinkWrap::OnRead)
-END_VTABLE_PATCHES()
-BEGIN_VTABLE_PATCHES(IInternetProtocolSecure)
- VTABLE_PATCH_ENTRY(kInternetProtocolStartIndex, ProtocolSinkWrap::OnStart)
- VTABLE_PATCH_ENTRY(kInternetProtocolReadIndex, ProtocolSinkWrap::OnRead)
-END_VTABLE_PATCHES()
+// IInternetProtocol/Ex patches.
+STDMETHODIMP Hook_Start(InternetProtocol_Start_Fn orig_start,
+ IInternetProtocol* protocol,
+ LPCWSTR url,
+ IInternetProtocolSink* prot_sink,
+ IInternetBindInfo* bind_info,
+ DWORD flags,
+ HANDLE_PTR reserved);
-BEGIN_VTABLE_PATCHES(IInternetProtocolEx)
- VTABLE_PATCH_ENTRY(kInternetProtocolStartIndex, ProtocolSinkWrap::OnStart)
- VTABLE_PATCH_ENTRY(kInternetProtocolReadIndex, ProtocolSinkWrap::OnRead)
- VTABLE_PATCH_ENTRY(kInternetProtocolStartExIndex, ProtocolSinkWrap::OnStartEx)
+STDMETHODIMP Hook_StartEx(InternetProtocol_StartEx_Fn orig_start_ex,
+ IInternetProtocolEx* protocol,
+ IUri* uri,
+ IInternetProtocolSink* prot_sink,
+ IInternetBindInfo* bind_info,
+ DWORD flags,
+ HANDLE_PTR reserved);
+
+STDMETHODIMP Hook_Read(InternetProtocol_Read_Fn orig_read,
+ IInternetProtocol* protocol,
+ void* buffer,
+ ULONG size,
+ ULONG* size_read);
+
+/////////////////////////////////////////////////////////////////////////////
+BEGIN_VTABLE_PATCHES(CTransaction)
+ VTABLE_PATCH_ENTRY(kInternetProtocolStartIndex, Hook_Start)
+ VTABLE_PATCH_ENTRY(kInternetProtocolReadIndex, Hook_Read)
END_VTABLE_PATCHES()
-BEGIN_VTABLE_PATCHES(IInternetProtocolExSecure)
- VTABLE_PATCH_ENTRY(kInternetProtocolStartIndex, ProtocolSinkWrap::OnStart)
- VTABLE_PATCH_ENTRY(kInternetProtocolReadIndex, ProtocolSinkWrap::OnRead)
- VTABLE_PATCH_ENTRY(kInternetProtocolStartExIndex, ProtocolSinkWrap::OnStartEx)
+BEGIN_VTABLE_PATCHES(CTransaction2)
+ VTABLE_PATCH_ENTRY(kInternetProtocolStartExIndex, Hook_StartEx)
END_VTABLE_PATCHES()
//
// ProtocolSinkWrap implementation
-//
// Static map initialization
-ProtocolSinkWrap::ProtocolSinkMap ProtocolSinkWrap::sink_map_;
-CComAutoCriticalSection ProtocolSinkWrap::sink_map_lock_;
+ProtData::ProtocolDataMap ProtData::datamap_;
+Lock ProtData::datamap_lock_;
-ProtocolSinkWrap::ProtocolSinkWrap()
- : protocol_(NULL), renderer_type_(UNDETERMINED),
- buffer_size_(0), buffer_pos_(0), is_saved_result_(false),
- result_code_(0), result_error_(0), report_data_recursiveness_(0),
- determining_renderer_type_(false) {
- memset(buffer_, 0, arraysize(buffer_));
+ProtocolSinkWrap::ProtocolSinkWrap() {
+ DLOG(INFO) << __FUNCTION__ << StringPrintf(" 0x%08X", this);
}
ProtocolSinkWrap::~ProtocolSinkWrap() {
- // This object may be destroyed before Initialize is called.
- if (protocol_ != NULL) {
- CComCritSecLock<CComAutoCriticalSection> lock(sink_map_lock_);
- DCHECK(sink_map_.end() != sink_map_.find(protocol_));
- sink_map_.erase(protocol_);
- protocol_ = NULL;
- }
- DLOG(INFO) << "ProtocolSinkWrap: active sinks: " << sink_map_.size();
+ DLOG(INFO) << __FUNCTION__ << StringPrintf(" 0x%08X", this);
}
-bool ProtocolSinkWrap::PatchProtocolHandlers() {
- HRESULT hr = PatchProtocolMethods(CLSID_HttpProtocol,
- IInternetProtocol_PatchInfo,
- IInternetProtocolEx_PatchInfo);
- if (FAILED(hr)) {
- NOTREACHED() << "Failed to patch IInternetProtocol interface."
- << " Error: " << hr;
- return false;
- }
-
- hr = PatchProtocolMethods(CLSID_HttpSProtocol,
- IInternetProtocolSecure_PatchInfo,
- IInternetProtocolExSecure_PatchInfo);
- if (FAILED(hr)) {
- NOTREACHED() << "Failed to patch IInternetProtocol secure interface."
- << " Error: " << hr;
- return false;
- }
-
- return true;
+ScopedComPtr<IInternetProtocolSink> ProtocolSinkWrap::CreateNewSink(
+ IInternetProtocolSink* sink, ProtData* data) {
+ DCHECK(sink != NULL);
+ DCHECK(data != NULL);
+ CComObject<ProtocolSinkWrap>* new_sink = NULL;
+ CComObject<ProtocolSinkWrap>::CreateInstance(&new_sink);
+ new_sink->delegate_ = sink;
+ new_sink->prot_data_ = data;
+ return ScopedComPtr<IInternetProtocolSink>(new_sink);
}
-void ProtocolSinkWrap::UnpatchProtocolHandlers() {
- vtable_patch::UnpatchInterfaceMethods(IInternetProtocol_PatchInfo);
- vtable_patch::UnpatchInterfaceMethods(IInternetProtocolEx_PatchInfo);
- vtable_patch::UnpatchInterfaceMethods(IInternetProtocolSecure_PatchInfo);
- vtable_patch::UnpatchInterfaceMethods(IInternetProtocolExSecure_PatchInfo);
+// IInternetProtocolSink methods
+STDMETHODIMP ProtocolSinkWrap::Switch(PROTOCOLDATA* protocol_data) {
+ HRESULT hr = E_FAIL;
+ if (delegate_)
+ hr = delegate_->Switch(protocol_data);
+ return hr;
}
-HRESULT ProtocolSinkWrap::CreateProtocolHandlerInstance(
- const CLSID& clsid, IInternetProtocol** protocol) {
- if (!protocol) {
- return E_INVALIDARG;
- }
+STDMETHODIMP ProtocolSinkWrap::ReportProgress(ULONG status_code,
+ LPCWSTR status_text) {
+ DLOG(INFO) << "ProtocolSinkWrap::ReportProgress: "
+ << BindStatus2Str(status_code)
+ << " Status: " << (status_text ? status_text : L"");
- HMODULE module = ::GetModuleHandle(kUrlMonDllName);
- if (!module) {
- NOTREACHED() << "urlmon is not yet loaded. Error: " << GetLastError();
- return E_FAIL;
- }
+ HRESULT hr = prot_data_->ReportProgress(delegate_, status_code, status_text);
+ return hr;
+}
- typedef HRESULT (WINAPI* DllGetClassObject_Fn)(REFCLSID, REFIID, LPVOID*);
- DllGetClassObject_Fn fn = reinterpret_cast<DllGetClassObject_Fn>(
- ::GetProcAddress(module, "DllGetClassObject"));
- if (!fn) {
- NOTREACHED() << "DllGetClassObject not found in urlmon.dll";
- return E_FAIL;
- }
+STDMETHODIMP ProtocolSinkWrap::ReportData(DWORD flags, ULONG progress,
+ ULONG max_progress) {
+ DCHECK(delegate_);
+ DLOG(INFO) << "ProtocolSinkWrap::ReportData: " << Bscf2Str(flags) <<
+ " progress: " << progress << " progress_max: " << max_progress;
- ScopedComPtr<IClassFactory> protocol_class_factory;
- HRESULT hr = fn(clsid, IID_IClassFactory,
- reinterpret_cast<LPVOID*>(protocol_class_factory.Receive()));
- if (FAILED(hr)) {
- NOTREACHED() << "DllGetclassObject failed. Error: " << hr;
- return hr;
- }
+ HRESULT hr = prot_data_->ReportData(delegate_, flags, progress, max_progress);
+ return hr;
+}
- ScopedComPtr<IInternetProtocol> handler_instance;
- hr = protocol_class_factory->CreateInstance(NULL, IID_IInternetProtocol,
- reinterpret_cast<void**>(handler_instance.Receive()));
- if (FAILED(hr)) {
- NOTREACHED() << "ClassFactory::CreateInstance failed for InternetProtocol."
- << " Error: " << hr;
- } else {
- *protocol = handler_instance.Detach();
- }
+STDMETHODIMP ProtocolSinkWrap::ReportResult(HRESULT result, DWORD error,
+ LPCWSTR result_text) {
+ DLOG(INFO) << "ProtocolSinkWrap::ReportResult: result: " << result <<
+ " error: " << error << " Text: " << (result_text ? result_text : L"");
+ DCHECK_NE(UNDETERMINED, prot_data_->renderer_type());
+ HRESULT hr = E_FAIL;
+ if (delegate_)
+ hr = delegate_->ReportResult(result, error, result_text);
+
return hr;
}
-HRESULT ProtocolSinkWrap::PatchProtocolMethods(
- const CLSID& clsid_protocol,
- vtable_patch::MethodPatchInfo* protocol_patch_info,
- vtable_patch::MethodPatchInfo* protocol_ex_patch_info) {
- if (!protocol_patch_info || !protocol_ex_patch_info) {
- return E_INVALIDARG;
- }
- ScopedComPtr<IInternetProtocol> http_protocol;
- HRESULT hr = CreateProtocolHandlerInstance(clsid_protocol,
- http_protocol.Receive());
- if (FAILED(hr)) {
- NOTREACHED() << "ClassFactory::CreateInstance failed for InternetProtocol."
- << " Error: " << hr;
- return false;
+// Helpers
+ScopedComPtr<IBindCtx> BindCtxFromIBindInfo(IInternetBindInfo* bind_info) {
+ LPOLESTR bind_ctx_string = NULL;
+ ULONG count;
+ ScopedComPtr<IBindCtx> bind_ctx;
+ bind_info->GetBindString(BINDSTRING_PTR_BIND_CONTEXT, &bind_ctx_string, 1,
+ &count);
+ if (bind_ctx_string) {
+ IBindCtx* pbc = reinterpret_cast<IBindCtx*>(StringToInt(bind_ctx_string));
+ bind_ctx.Attach(pbc);
+ CoTaskMemFree(bind_ctx_string);
}
- ScopedComPtr<IInternetProtocolEx> ipex;
- ipex.QueryFrom(http_protocol);
- if (ipex) {
- hr = vtable_patch::PatchInterfaceMethods(ipex, protocol_ex_patch_info);
- } else {
- hr = vtable_patch::PatchInterfaceMethods(http_protocol,
- protocol_patch_info);
- }
- return hr;
+ return bind_ctx;
}
-// IInternetProtocol/Ex method implementation.
-HRESULT ProtocolSinkWrap::OnStart(InternetProtocol_Start_Fn orig_start,
- IInternetProtocol* protocol, LPCWSTR url, IInternetProtocolSink* prot_sink,
- IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved) {
- DCHECK(orig_start);
- DLOG_IF(INFO, url != NULL) << "OnStart: " << url;
+bool ShouldWrapSink(IInternetProtocolSink* sink, const wchar_t* url) {
+ // TODO(stoyan): check the url scheme for http/https.
+ ScopedComPtr<IHttpNegotiate> http_negotiate;
+ HRESULT hr = DoQueryService(GUID_NULL, sink, http_negotiate.Receive());
+ if (http_negotiate && !IsSubFrameRequest(http_negotiate))
+ return true;
- ScopedComPtr<IInternetProtocolSink> sink_to_use(MaybeWrapSink(protocol,
- prot_sink, url));
- return orig_start(protocol, url, sink_to_use, bind_info, flags, reserved);
+ return false;
}
-HRESULT ProtocolSinkWrap::OnStartEx(InternetProtocol_StartEx_Fn orig_start_ex,
- IInternetProtocolEx* protocol, IUri* uri, IInternetProtocolSink* prot_sink,
- IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved) {
- DCHECK(orig_start_ex);
+// High level helpers
+bool IsCFRequest(IBindCtx* pbc) {
+ ScopedComPtr<BindContextInfo> info;
+ BindContextInfo::FromBindContext(pbc, info.Receive());
+ DCHECK(info);
+ if (info && info->chrome_request())
+ return true;
- ScopedBstr url;
- uri->GetPropertyBSTR(Uri_PROPERTY_ABSOLUTE_URI, url.Receive(), 0);
- DLOG_IF(INFO, url != NULL) << "OnStartEx: " << url;
+ return false;
+}
- ScopedComPtr<IInternetProtocolSink> sink_to_use(MaybeWrapSink(protocol,
- prot_sink, url));
- return orig_start_ex(protocol, uri, sink_to_use, bind_info, flags, reserved);
+void PutProtData(IBindCtx* pbc, ProtData* data) {
+ ScopedComPtr<BindContextInfo> info;
+ BindContextInfo::FromBindContext(pbc, info.Receive());
+ if (info)
+ info->set_prot_data(data);
}
-HRESULT ProtocolSinkWrap::OnRead(InternetProtocol_Read_Fn orig_read,
- IInternetProtocol* protocol, void* buffer, ULONG size, ULONG* size_read) {
- DCHECK(orig_read);
+bool IsTextHtml(const wchar_t* status_text) {
+ if (!status_text)
+ return false;
+ size_t status_text_length = lstrlenW(status_text);
+ const wchar_t* status_text_end = status_text +
+ std::min(status_text_length, arraysize(kTextHtmlMimeType) - 1);
+ bool is_text_html = LowerCaseEqualsASCII(status_text, status_text_end,
+ kTextHtmlMimeType);
+ return is_text_html;
+}
- scoped_refptr<ProtocolSinkWrap> instance =
- ProtocolSinkWrap::InstanceFromProtocol(protocol);
- HRESULT hr;
- if (instance) {
- DCHECK(instance->protocol_ == protocol);
- hr = instance->OnReadImpl(buffer, size, size_read, orig_read);
- } else {
- hr = orig_read(protocol, buffer, size, size_read);
+RendererType DetermineRendererType(void* buffer, DWORD size, bool last_chance) {
+ RendererType type = UNDETERMINED;
+ if (last_chance)
+ type = OTHER;
+
+ std::wstring html_contents;
+ // TODO(joshia): detect and handle different content encodings
+ UTF8ToWide(reinterpret_cast<char*>(buffer), size, &html_contents);
+
+ // Note that document_contents_ may have NULL characters in it. While
+ // browsers may handle this properly, we don't and will stop scanning
+ // for the XUACompat content value if we encounter one.
+ std::wstring xua_compat_content;
+ UtilGetXUACompatContentValue(html_contents, &xua_compat_content);
+ if (StrStrI(xua_compat_content.c_str(), kChromeContentPrefix)) {
+ type = CHROME;
}
- return hr;
+ return type;
}
-bool ProtocolSinkWrap::Initialize(IInternetProtocol* protocol,
- IInternetProtocolSink* original_sink, const wchar_t* url) {
- DCHECK(original_sink);
- delegate_ = original_sink;
- protocol_ = protocol;
- if (url)
- url_ = url;
+// ProtData
+ProtData::ProtData(IInternetProtocol* protocol,
+ InternetProtocol_Read_Fn read_fun, const wchar_t* url)
+ : has_suggested_mime_type_(false), has_server_mime_type_(false),
+ report_data_received_(false), buffer_size_(0), buffer_pos_(0),
+ renderer_type_(UNDETERMINED), protocol_(protocol), read_fun_(read_fun),
+ url_(url) {
+ memset(buffer_, 0, arraysize(buffer_));
+ DLOG(INFO) << __FUNCTION__ << " " << this;
- CComCritSecLock<CComAutoCriticalSection> lock(sink_map_lock_);
- DCHECK(sink_map_.end() == sink_map_.find(protocol));
- sink_map_[protocol] = this;
- DLOG(INFO) << "ProtocolSinkWrap: active sinks: " << sink_map_.size();
- return true;
+ // Add to map.
+ AutoLock lock(datamap_lock_);
+ DCHECK(datamap_.end() == datamap_.find(protocol_));
+ datamap_[protocol] = this;
}
-// IInternetProtocolSink methods
-STDMETHODIMP ProtocolSinkWrap::Switch(PROTOCOLDATA* protocol_data) {
- HRESULT hr = E_FAIL;
- if (delegate_)
- hr = delegate_->Switch(protocol_data);
- return hr;
+ProtData::~ProtData() {
+ DLOG(INFO) << __FUNCTION__ << " " << this;
+
+ // Remove from map.
+ AutoLock lock(datamap_lock_);
+ DCHECK(datamap_.end() != datamap_.find(protocol_));
+ datamap_.erase(protocol_);
}
-STDMETHODIMP ProtocolSinkWrap::ReportProgress(ULONG status_code,
- LPCWSTR status_text) {
- DLOG(INFO) << "ProtocolSinkWrap::ReportProgress: Code:" << status_code <<
- " Text: " << (status_text ? status_text : L"");
- if (!delegate_) {
- return E_FAIL;
+HRESULT ProtData::Read(void* buffer, ULONG size, ULONG* size_read) {
+ if (renderer_type_ == UNDETERMINED) {
+ return E_PENDING;
}
- if ((BINDSTATUS_MIMETYPEAVAILABLE == status_code) ||
- (BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE == status_code)) {
- // If we have a MIMETYPE and that MIMETYPE is not "text/html". we don't
- // want to do anything with this.
- if (status_text) {
- size_t status_text_length = lstrlenW(status_text);
- const wchar_t* status_text_end = status_text + std::min(
- status_text_length, arraysize(kTextHtmlMimeType) - 1);
- if (!LowerCaseEqualsASCII(status_text, status_text_end,
- kTextHtmlMimeType)) {
- renderer_type_ = OTHER;
- }
+
+ const ULONG bytes_available = buffer_size_ - buffer_pos_;
+ const ULONG bytes_to_copy = std::min(bytes_available, size);
+ if (bytes_to_copy) {
+ // Copy from the local buffer.
+ memcpy(buffer, buffer_ + buffer_pos_, bytes_to_copy);
+ *size_read = bytes_to_copy;
+ buffer_pos_ += bytes_to_copy;
+
+ HRESULT hr = S_OK;
+ ULONG new_data = 0;
+ if (size > bytes_available) {
+ // User buffer is greater than what we have.
+ buffer = reinterpret_cast<uint8*>(buffer) + bytes_to_copy;
+ size -= bytes_to_copy;
+ hr = read_fun_(protocol_, buffer, size, &new_data);
}
- }
- HRESULT hr = S_OK;
- if (delegate_ && renderer_type_ != CHROME) {
- hr = delegate_->ReportProgress(status_code, status_text);
+ if (size_read)
+ *size_read = bytes_to_copy + new_data;
+ return hr;
}
- return hr;
+
+ return read_fun_(protocol_, buffer, size, size_read);
}
-STDMETHODIMP ProtocolSinkWrap::ReportData(DWORD flags, ULONG progress,
- ULONG max_progress) {
- DCHECK(protocol_);
- DCHECK(delegate_);
- DLOG(INFO) << "ProtocolSinkWrap::ReportData: flags: " << flags <<
- " progress: " << progress << " progress_max: " << max_progress;
- scoped_refptr<ProtocolSinkWrap> self_ref(this);
+HRESULT ProtData::ReportProgress(IInternetProtocolSink* delegate,
+ ULONG status_code, LPCWSTR status_text) {
+ switch (status_code) {
+ case BINDSTATUS_DIRECTBIND:
+ renderer_type_ = OTHER;
+ break;
- // Maintain a stack depth to make a determination. ReportData is called
- // recursively in IE8. If the request can be served in a single Read, the
- // situation ends up like this:
- // orig_prot
- // |--> ProtocolSinkWrap::ReportData (BSCF_FIRSTDATANOTIFICATION)
- // |--> orig_prot->Read(...) - 1st read - S_OK and data
- // |--> ProtocolSinkWrap::ReportData (BSCF_LASTDATANOTIFICATION)
- // |--> orig_prot->Read(...) - 2nd read S_FALSE, 0 bytes
- //
- // Inner call returns S_FALSE and no data. We try to make a determination
- // of render type then and incorrectly set it to 'OTHER' as we don't have
- // any data yet. However, we can make a determination in the context of
- // outer ReportData since the first read will return S_OK with data. Then
- // the next Read in the loop will return S_FALSE and we will enter the
- // determination logic.
+ case BINDSTATUS_REDIRECTING:
+ url_.empty();
+ if (status_text)
+ url_ = status_text;
+ break;
- // NOTE: We use the report_data_recursiveness_ variable to detect situations
- // in which calls to ReportData are re-entrant (such as when the entire
- // contents of a page fit inside a single packet). In these cases, we
- // don't care about re-entrant calls beyond the second, and so we compare
- // report_data_recursiveness_ inside the while loop, making sure we skip
- // what would otherwise be spurious calls to ReportProgress().
- report_data_recursiveness_++;
+ case BINDSTATUS_SERVER_MIMETYPEAVAILABLE:
+ has_server_mime_type_ = true;
+ SaveSuggestedMimeType(status_text);
+ return S_OK;
- HRESULT hr = S_OK;
- if (is_undetermined()) {
- CheckAndReportChromeMimeTypeForRequest();
+ // TODO(stoyan): BINDSTATUS_RAWMIMETYPE
+ case BINDSTATUS_MIMETYPEAVAILABLE:
+ case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
+ SaveSuggestedMimeType(status_text);
+ return S_OK;
}
- // we call original only if the renderer type is other
- if (renderer_type() == OTHER) {
- hr = delegate_->ReportData(flags, progress, max_progress);
+ return delegate->ReportProgress(status_code, status_text);
+}
- if (is_saved_result_) {
- is_saved_result_ = false;
- delegate_->ReportResult(result_code_, result_error_,
- result_text_.c_str());
+HRESULT ProtData::ReportData(IInternetProtocolSink* delegate,
+ DWORD flags, ULONG progress, ULONG max_progress) {
+ if (renderer_type_ != UNDETERMINED) {
+ return delegate->ReportData(flags, progress, max_progress);
+ }
+
+ // Do these checks only once.
+ if (!report_data_received_) {
+ report_data_received_ = true;
+
+ DLOG_IF(INFO, (flags & BSCF_FIRSTDATANOTIFICATION) == 0) <<
+ "BUGBUG: BSCF_FIRSTDATANOTIFICATION is not set properly!";
+
+
+ // We check here, instead in ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE)
+ // to be safe when following multiple redirects.?
+ if (!IsTextHtml(suggested_mime_type_)) {
+ renderer_type_ = OTHER;
+ FireSugestedMimeType(delegate);
+ return delegate->ReportData(flags, progress, max_progress);
}
+
+ if (!url_.empty() && IsOptInUrl(url_.c_str())) {
+ // TODO(stoyan): We may attempt to remove ourselves from the bind context.
+ renderer_type_ = CHROME;
+ delegate->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, kChromeMimeType);
+ return delegate->ReportData(flags, progress, max_progress);
+ }
}
- report_data_recursiveness_--;
- return hr;
-}
+ HRESULT hr = FillBuffer();
-STDMETHODIMP ProtocolSinkWrap::ReportResult(HRESULT result, DWORD error,
- LPCWSTR result_text) {
- DLOG(INFO) << "ProtocolSinkWrap::ReportResult: result: " << result <<
- " error: " << error << " Text: " << (result_text ? result_text : L"");
+ bool last_chance = false;
+ if (hr == S_OK || hr == S_FALSE) {
+ last_chance = true;
+ }
- // If this request failed, we don't want to have anything to do with this.
- if (FAILED(result))
- renderer_type_ = OTHER;
+ renderer_type_ = DetermineRendererType(buffer_, buffer_size_, last_chance);
- // if we are still not sure about the renderer type, cache the result,
- // othewise urlmon will get confused about getting reported about a
- // success result for which it never received any data.
- if (is_undetermined()) {
- is_saved_result_ = true;
- result_code_ = result;
- result_error_ = error;
- if (result_text)
- result_text_ = result_text;
+ if (renderer_type_ == UNDETERMINED) {
+ // do not report anything, we need more data.
return S_OK;
}
- HRESULT hr = E_FAIL;
- if (delegate_)
- hr = delegate_->ReportResult(result, error, result_text);
+ if (renderer_type_ == CHROME) {
+ DLOG(INFO) << "Forwarding BINDSTATUS_MIMETYPEAVAILABLE "
+ << kChromeMimeType;
+ delegate->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, kChromeMimeType);
+ }
- return hr;
-}
+ if (renderer_type_ == OTHER) {
+ FireSugestedMimeType(delegate);
+ }
-// IInternetBindInfoEx
-STDMETHODIMP ProtocolSinkWrap::GetBindInfo(DWORD* flags,
- BINDINFO* bind_info_ret) {
- ScopedComPtr<IInternetBindInfo> bind_info;
- HRESULT hr = bind_info.QueryFrom(delegate_);
- if (bind_info)
- hr = bind_info->GetBindInfo(flags, bind_info_ret);
- return hr;
-}
+ // This is the first data notification we forward.
+ flags |= BSCF_FIRSTDATANOTIFICATION;
-STDMETHODIMP ProtocolSinkWrap::GetBindString(ULONG string_type,
- LPOLESTR* string_array, ULONG array_size, ULONG* size_returned) {
- ScopedComPtr<IInternetBindInfo> bind_info;
- HRESULT hr = bind_info.QueryFrom(delegate_);
- if (bind_info)
- hr = bind_info->GetBindString(string_type, string_array,
- array_size, size_returned);
- return hr;
-}
+ if (hr == S_FALSE) {
+ flags |= (BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE);
+ }
-STDMETHODIMP ProtocolSinkWrap::GetBindInfoEx(DWORD* flags, BINDINFO* bind_info,
- DWORD* bindf2, DWORD* reserved) {
- ScopedComPtr<IInternetBindInfoEx> bind_info_ex;
- HRESULT hr = bind_info_ex.QueryFrom(delegate_);
- if (bind_info_ex)
- hr = bind_info_ex->GetBindInfoEx(flags, bind_info, bindf2, reserved);
- return hr;
+ return delegate->ReportData(flags, progress, max_progress);
}
-// IServiceProvider
-STDMETHODIMP ProtocolSinkWrap::QueryService(REFGUID service_guid,
- REFIID riid, void** service) {
- ScopedComPtr<IServiceProvider> service_provider;
- HRESULT hr = service_provider.QueryFrom(delegate_);
- if (service_provider)
- hr = service_provider->QueryService(service_guid, riid, service);
- return hr;
+void ProtData::UpdateUrl(const wchar_t* url) {
+ url_ = url;
}
-// IAuthenticate
-STDMETHODIMP ProtocolSinkWrap::Authenticate(HWND* window,
- LPWSTR* user_name, LPWSTR* password) {
- ScopedComPtr<IAuthenticate> authenticate;
- HRESULT hr = authenticate.QueryFrom(delegate_);
- if (authenticate)
- hr = authenticate->Authenticate(window, user_name, password);
- return hr;
-}
+// S_FALSE - EOF
+// S_OK - buffer fully filled
+// E_PENDING - some data added to buffer, but buffer is not yet full
+// E_XXXX - some other error.
+HRESULT ProtData::FillBuffer() {
+ HRESULT hr_read = S_OK;
-// IInternetProtocolEx
-STDMETHODIMP ProtocolSinkWrap::Start(LPCWSTR url,
- IInternetProtocolSink *protocol_sink, IInternetBindInfo* bind_info,
- DWORD flags, HANDLE_PTR reserved) {
- ScopedComPtr<IInternetProtocolRoot> protocol;
- HRESULT hr = protocol.QueryFrom(delegate_);
- if (protocol)
- hr = protocol->Start(url, protocol_sink, bind_info, flags, reserved);
- return hr;
-}
+ while ((hr_read == S_OK) && (buffer_size_ < kMaxContentSniffLength)) {
+ ULONG size_read = 0;
+ hr_read = read_fun_(protocol_, buffer_ + buffer_size_,
+ kMaxContentSniffLength - buffer_size_, &size_read);
+ buffer_size_ += size_read;
+ }
-STDMETHODIMP ProtocolSinkWrap::Continue(PROTOCOLDATA* protocol_data) {
- ScopedComPtr<IInternetProtocolRoot> protocol;
- HRESULT hr = protocol.QueryFrom(delegate_);
- if (protocol)
- hr = protocol->Continue(protocol_data);
- return hr;
+ return hr_read;
}
-STDMETHODIMP ProtocolSinkWrap::Abort(HRESULT reason, DWORD options) {
- ScopedComPtr<IInternetProtocolRoot> protocol;
- HRESULT hr = protocol.QueryFrom(delegate_);
- if (protocol)
- hr = protocol->Abort(reason, options);
- return hr;
+void ProtData::SaveSuggestedMimeType(LPCWSTR status_text) {
+ has_suggested_mime_type_ = true;
+ suggested_mime_type_.Allocate(status_text);
}
-STDMETHODIMP ProtocolSinkWrap::Terminate(DWORD options) {
- ScopedComPtr<IInternetProtocolRoot> protocol;
- HRESULT hr = protocol.QueryFrom(delegate_);
- if (protocol)
- hr = protocol->Terminate(options);
- return hr;
-}
+void ProtData::FireSugestedMimeType(IInternetProtocolSink* delegate) {
+ if (has_server_mime_type_) {
+ DLOG(INFO) << "Forwarding BINDSTATUS_SERVER_MIMETYPEAVAILABLE "
+ << suggested_mime_type_;
+ delegate->ReportProgress(BINDSTATUS_SERVER_MIMETYPEAVAILABLE,
+ suggested_mime_type_);
+ return;
+ }
-STDMETHODIMP ProtocolSinkWrap::Suspend() {
- ScopedComPtr<IInternetProtocolRoot> protocol;
- HRESULT hr = protocol.QueryFrom(delegate_);
- if (protocol)
- hr = protocol->Suspend();
- return hr;
+ if (has_suggested_mime_type_) {
+ DLOG(INFO) << "Forwarding BINDSTATUS_MIMETYPEAVAILABLE "
+ << suggested_mime_type_;
+ delegate->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE,
+ suggested_mime_type_);
+ }
}
-STDMETHODIMP ProtocolSinkWrap::Resume() {
- ScopedComPtr<IInternetProtocolRoot> protocol;
- HRESULT hr = protocol.QueryFrom(delegate_);
- if (protocol)
- hr = protocol->Resume();
- return hr;
+scoped_refptr<ProtData> ProtData::DataFromProtocol(
+ IInternetProtocol* protocol) {
+ scoped_refptr<ProtData> instance;
+ AutoLock lock(datamap_lock_);
+ ProtocolDataMap::iterator it = datamap_.find(protocol);
+ if (datamap_.end() != it)
+ instance = it->second;
+ return instance;
}
-STDMETHODIMP ProtocolSinkWrap::Read(void *buffer, ULONG size,
- ULONG* size_read) {
- ScopedComPtr<IInternetProtocol> protocol;
- HRESULT hr = protocol.QueryFrom(delegate_);
- if (protocol)
- hr = protocol->Read(buffer, size, size_read);
- return hr;
-}
+// IInternetProtocol/Ex hooks.
+STDMETHODIMP Hook_Start(InternetProtocol_Start_Fn orig_start,
+ IInternetProtocol* protocol, LPCWSTR url, IInternetProtocolSink* prot_sink,
+ IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved) {
+ DCHECK(orig_start);
+ if (!url || !prot_sink || !bind_info)
+ return E_INVALIDARG;
+ DLOG_IF(INFO, url != NULL) << "OnStart: " << url << PiFlags2Str(flags);
-STDMETHODIMP ProtocolSinkWrap::Seek(LARGE_INTEGER move, DWORD origin,
- ULARGE_INTEGER* new_pos) {
- ScopedComPtr<IInternetProtocol> protocol;
- HRESULT hr = protocol.QueryFrom(delegate_);
- if (protocol)
- hr = protocol->Seek(move, origin, new_pos);
- return hr;
-}
+ ScopedComPtr<IBindCtx> bind_ctx = BindCtxFromIBindInfo(bind_info);
+ if (!bind_ctx) {
+ // MSHTML sometimes takes a short path, skips the creation of
+ // moniker and binding, by directly grabbing protocol from InternetSession
+ DLOG(INFO) << "DirectBind for " << url;
+ return orig_start(protocol, url, prot_sink, bind_info, flags, reserved);
+ }
-STDMETHODIMP ProtocolSinkWrap::LockRequest(DWORD options) {
- ScopedComPtr<IInternetProtocol> protocol;
- HRESULT hr = protocol.QueryFrom(delegate_);
- if (protocol)
- hr = protocol->LockRequest(options);
- return hr;
-}
+ if (IsCFRequest(bind_ctx)) {
+ return orig_start(protocol, url, prot_sink, bind_info, flags, reserved);
+ }
-STDMETHODIMP ProtocolSinkWrap::UnlockRequest() {
- ScopedComPtr<IInternetProtocol> protocol;
- HRESULT hr = protocol.QueryFrom(delegate_);
- if (protocol)
- hr = protocol->UnlockRequest();
- return hr;
-}
+ scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol);
+ if (prot_data) {
+ DLOG(INFO) << "Found existing ProtData!";
+ prot_data->UpdateUrl(url);
+ ScopedComPtr<IInternetProtocolSink> new_sink =
+ ProtocolSinkWrap::CreateNewSink(prot_sink, prot_data);
+ return orig_start(protocol, url, new_sink, bind_info, flags, reserved);
+ }
-STDMETHODIMP ProtocolSinkWrap::StartEx(IUri* uri,
- IInternetProtocolSink* protocol_sink, IInternetBindInfo* bind_info,
- DWORD flags, HANDLE_PTR reserved) {
- ScopedComPtr<IInternetProtocolEx> protocol;
- HRESULT hr = protocol.QueryFrom(delegate_);
- if (protocol)
- hr = protocol->StartEx(uri, protocol_sink, bind_info, flags, reserved);
- return hr;
-}
+ if (!ShouldWrapSink(prot_sink, url)) {
+ return orig_start(protocol, url, prot_sink, bind_info, flags, reserved);
+ }
-// IInternetPriority
-STDMETHODIMP ProtocolSinkWrap::SetPriority(LONG priority) {
- ScopedComPtr<IInternetPriority> internet_priority;
- HRESULT hr = internet_priority.QueryFrom(delegate_);
- if (internet_priority)
- hr = internet_priority->SetPriority(priority);
- return hr;
-}
+ // Fresh request.
+ InternetProtocol_Read_Fn read_fun = reinterpret_cast<InternetProtocol_Read_Fn>
+ (CTransaction_PatchInfo[1].stub_->argument());
+ prot_data = new ProtData(protocol, read_fun, url);
+ PutProtData(bind_ctx, prot_data);
-STDMETHODIMP ProtocolSinkWrap::GetPriority(LONG* priority) {
- ScopedComPtr<IInternetPriority> internet_priority;
- HRESULT hr = internet_priority.QueryFrom(delegate_);
- if (internet_priority)
- hr = internet_priority->GetPriority(priority);
- return hr;
+ ScopedComPtr<IInternetProtocolSink> new_sink =
+ ProtocolSinkWrap::CreateNewSink(prot_sink, prot_data);
+ return orig_start(protocol, url, new_sink, bind_info, flags, reserved);
}
-// IWrappedProtocol
-STDMETHODIMP ProtocolSinkWrap::GetWrapperCode(LONG *code, DWORD_PTR reserved) {
- ScopedComPtr<IWrappedProtocol> wrapped_protocol;
- HRESULT hr = wrapped_protocol.QueryFrom(delegate_);
- if (wrapped_protocol)
- hr = wrapped_protocol->GetWrapperCode(code, reserved);
- return hr;
+STDMETHODIMP Hook_StartEx(InternetProtocol_StartEx_Fn orig_start_ex,
+ IInternetProtocolEx* protocol, IUri* uri, IInternetProtocolSink* prot_sink,
+ IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved) {
+ DCHECK(orig_start_ex);
+ if (!uri || !prot_sink || !bind_info)
+ return E_INVALIDARG;
+
+ ScopedBstr url;
+ uri->GetPropertyBSTR(Uri_PROPERTY_ABSOLUTE_URI, url.Receive(), 0);
+ DLOG_IF(INFO, url != NULL) << "OnStartEx: " << url << PiFlags2Str(flags);
+
+ ScopedComPtr<IBindCtx> bind_ctx = BindCtxFromIBindInfo(bind_info);
+ if (!bind_ctx) {
+ // MSHTML sometimes takes a short path, skips the creation of
+ // moniker and binding, by directly grabbing protocol from InternetSession.
+ DLOG(INFO) << "DirectBind for " << url;
+ return orig_start_ex(protocol, uri, prot_sink, bind_info, flags, reserved);
+ }
+
+ if (IsCFRequest(bind_ctx)) {
+ return orig_start_ex(protocol, uri, prot_sink, bind_info, flags, reserved);
+ }
+
+ scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol);
+ if (prot_data) {
+ DLOG(INFO) << "Found existing ProtData!";
+ prot_data->UpdateUrl(url);
+ ScopedComPtr<IInternetProtocolSink> new_sink =
+ ProtocolSinkWrap::CreateNewSink(prot_sink, prot_data);
+ return orig_start_ex(protocol, uri, new_sink, bind_info, flags, reserved);
+ }
+
+ if (!ShouldWrapSink(prot_sink, url)) {
+ return orig_start_ex(protocol, uri, prot_sink, bind_info, flags, reserved);
+ }
+
+ // Fresh request.
+ InternetProtocol_Read_Fn read_fun = reinterpret_cast<InternetProtocol_Read_Fn>
+ (CTransaction_PatchInfo[1].stub_->argument());
+ prot_data = new ProtData(protocol, read_fun, url);
+ PutProtData(bind_ctx, prot_data);
+
+ ScopedComPtr<IInternetProtocolSink> new_sink =
+ ProtocolSinkWrap::CreateNewSink(prot_sink, prot_data);
+ return orig_start_ex(protocol, uri, new_sink, bind_info, flags, reserved);
}
+STDMETHODIMP Hook_Read(InternetProtocol_Read_Fn orig_read,
+ IInternetProtocol* protocol, void* buffer, ULONG size, ULONG* size_read) {
+ DCHECK(orig_read);
+ scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol);
+ if (!prot_data) {
+ return orig_read(protocol, buffer, size, size_read);
+ }
-// public IUriContainer
-STDMETHODIMP ProtocolSinkWrap::GetIUri(IUri** uri) {
- ScopedComPtr<IUriContainer> uri_container;
- HRESULT hr = uri_container.QueryFrom(delegate_);
- if (uri_container)
- hr = uri_container->GetIUri(uri);
+ HRESULT hr = prot_data->Read(buffer, size, size_read);
return hr;
}
-// Protected helpers
+// Patching / Hooking code.
+class FakeProtocol : public CComObjectRootEx<CComSingleThreadModel>,
+ public IInternetProtocol {
+ public:
+ BEGIN_COM_MAP(FakeProtocol)
+ COM_INTERFACE_ENTRY(IInternetProtocol)
+ COM_INTERFACE_ENTRY(IInternetProtocolRoot)
+ END_COM_MAP()
-void ProtocolSinkWrap::DetermineRendererType() {
- if (is_undetermined()) {
- if (IsOptInUrl(url_.c_str())) {
- renderer_type_ = CHROME;
- } else {
- std::wstring xua_compat_content;
- // Note that document_contents_ may have NULL characters in it. While
- // browsers may handle this properly, we don't and will stop scanning for
- // the XUACompat content value if we encounter one.
- DCHECK(buffer_size_ < arraysize(buffer_));
- buffer_[buffer_size_] = 0;
- std::wstring html_contents;
- // TODO(joshia): detect and handle different content encodings
- UTF8ToWide(buffer_, buffer_size_, &html_contents);
- UtilGetXUACompatContentValue(html_contents, &xua_compat_content);
- if (StrStrI(xua_compat_content.c_str(), kChromeContentPrefix)) {
- renderer_type_ = CHROME;
- } else {
- renderer_type_ = OTHER;
- }
- }
+ STDMETHOD(Start)(LPCWSTR url, IInternetProtocolSink *protocol_sink,
+ IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved) {
+ transaction_.QueryFrom(protocol_sink);
+ // Return some unusual error code.
+ return INET_E_INVALID_CERTIFICATE;
}
-}
-HRESULT ProtocolSinkWrap::CheckAndReportChromeMimeTypeForRequest() {
- if (!is_undetermined())
- return S_OK;
+ STDMETHOD(Continue)(PROTOCOLDATA* protocol_data) { return S_OK; }
+ STDMETHOD(Abort)(HRESULT reason, DWORD options) { return S_OK; }
+ STDMETHOD(Terminate)(DWORD options) { return S_OK; }
+ STDMETHOD(Suspend)() { return S_OK; }
+ STDMETHOD(Resume)() { return S_OK; }
+ STDMETHOD(Read)(void *buffer, ULONG size, ULONG* size_read) { return S_OK; }
+ STDMETHOD(Seek)(LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER* new_pos)
+ { return S_OK; }
+ STDMETHOD(LockRequest)(DWORD options) { return S_OK; }
+ STDMETHOD(UnlockRequest)() { return S_OK; }
- // This function could get invoked recursively in the context of
- // IInternetProtocol::Read. Check for the same and bail.
- if (determining_renderer_type_)
- return S_OK;
+ ScopedComPtr<IInternetProtocol> transaction_;
+};
- determining_renderer_type_ = true;
+struct FakeFactory : public IClassFactory,
+ public CComObjectRootEx<CComSingleThreadModel> {
+ BEGIN_COM_MAP(FakeFactory)
+ COM_INTERFACE_ENTRY(IClassFactory)
+ END_COM_MAP()
- HRESULT hr_read = S_OK;
- while (hr_read == S_OK) {
- ULONG size_read = 0;
- hr_read = protocol_->Read(buffer_ + buffer_size_,
- kMaxContentSniffLength - buffer_size_, &size_read);
- buffer_size_ += size_read;
+ STDMETHOD(CreateInstance)(IUnknown *pUnkOuter, REFIID riid, void **ppvObj) {
+ if (pUnkOuter)
+ return CLASS_E_NOAGGREGATION;
+ HRESULT hr = obj_->QueryInterface(riid, ppvObj);
+ return hr;
+ }
- // Attempt to determine the renderer type if we have received
- // sufficient data. Do not attempt this when we are called recursively.
- if (report_data_recursiveness_ < 2 && (S_FALSE == hr_read) ||
- (buffer_size_ >= kMaxContentSniffLength)) {
- DetermineRendererType();
- if (renderer_type() == CHROME) {
- // Workaround for IE 8 and "nosniff". See:
- // http://blogs.msdn.com/ie/archive/2008/09/02/ie8-security-part-vi-beta-2-update.aspx
- delegate_->ReportProgress(
- BINDSTATUS_SERVER_MIMETYPEAVAILABLE, kChromeMimeType);
- // For IE < 8.
- delegate_->ReportProgress(
- BINDSTATUS_MIMETYPEAVAILABLE, kChromeMimeType);
+ STDMETHOD(LockServer)(BOOL fLock) {
+ return S_OK;
+ }
- delegate_->ReportProgress(
- BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, kChromeMimeType);
+ IUnknown* obj_;
+};
- delegate_->ReportData(
- BSCF_FIRSTDATANOTIFICATION, 0, 0);
+static void HookTransactionVtable(IInternetProtocol* p) {
+ ScopedComPtr<IInternetProtocolEx> ex;
+ ex.QueryFrom(p);
- delegate_->ReportData(
- BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE, 0, 0);
- }
- break;
- }
+ HRESULT hr = vtable_patch::PatchInterfaceMethods(p, CTransaction_PatchInfo);
+ if (hr == S_OK && ex) {
+ vtable_patch::PatchInterfaceMethods(ex.get(), CTransaction2_PatchInfo);
}
-
- determining_renderer_type_ = false;
- return hr_read;
}
-HRESULT ProtocolSinkWrap::OnReadImpl(void* buffer, ULONG size, ULONG* size_read,
- InternetProtocol_Read_Fn orig_read) {
- // We want to switch the renderer to chrome, we cannot return any
- // data now.
- if (CHROME == renderer_type())
- return S_FALSE;
-
- // Serve data from our buffer first.
- if (OTHER == renderer_type()) {
- const ULONG bytes_to_copy = std::min(buffer_size_ - buffer_pos_, size);
- if (bytes_to_copy) {
- memcpy(buffer, buffer_ + buffer_pos_, bytes_to_copy);
- *size_read = bytes_to_copy;
- buffer_pos_ += bytes_to_copy;
- return S_OK;
- }
+void TransactionHooks::InstallHooks() {
+ if (IS_PATCHED(CTransaction)) {
+ DLOG(WARNING) << __FUNCTION__ << " called more than once.";
+ return;
}
- return orig_read(protocol_, buffer, size, size_read);
-}
+ CComObjectStackEx<FakeProtocol> prot;
+ CComObjectStackEx<FakeFactory> factory;
+ factory.obj_ = &prot;
+ ScopedComPtr<IInternetSession> session;
+ HRESULT hr = ::CoInternetGetSession(0, session.Receive(), 0);
+ hr = session->RegisterNameSpace(&factory, CLSID_NULL, L"611", 0, 0, 0);
+ DLOG_IF(FATAL, FAILED(hr)) << "Failed to register namespace";
+ if (hr != S_OK)
+ return;
-scoped_refptr<ProtocolSinkWrap> ProtocolSinkWrap::InstanceFromProtocol(
- IInternetProtocol* protocol) {
- CComCritSecLock<CComAutoCriticalSection> lock(sink_map_lock_);
- scoped_refptr<ProtocolSinkWrap> instance;
- ProtocolSinkMap::iterator it = sink_map_.find(protocol);
- if (sink_map_.end() != it)
- instance = it->second;
- return instance;
-}
+ do {
+ ScopedComPtr<IMoniker> mk;
+ ScopedComPtr<IBindCtx> bc;
+ ScopedComPtr<IStream> stream;
+ hr = ::CreateAsyncBindCtxEx(0, 0, 0, 0, bc.Receive(), 0);
+ DLOG_IF(FATAL, FAILED(hr)) << "CreateAsyncBindCtxEx failed " << hr;
+ if (hr != S_OK)
+ break;
-ScopedComPtr<IInternetProtocolSink> ProtocolSinkWrap::MaybeWrapSink(
- IInternetProtocol* protocol, IInternetProtocolSink* prot_sink,
- const wchar_t* url) {
- ScopedComPtr<IInternetProtocolSink> sink_to_use(prot_sink);
+ hr = ::CreateURLMoniker(NULL, L"611://512", mk.Receive());
+ DLOG_IF(FATAL, FAILED(hr)) << "CreateURLMoniker failed " << hr;
+ if (hr != S_OK)
+ break;
- // FYI: GUID_NULL doesn't work when the URL is being loaded from history.
- // asking for IID_IHttpNegotiate as the service id works, but
- // getting the IWebBrowser2 interface still doesn't work.
- ScopedComPtr<IHttpNegotiate> http_negotiate;
- HRESULT hr = DoQueryService(GUID_NULL, prot_sink, http_negotiate.Receive());
+ hr = mk->BindToStorage(bc, NULL, IID_IStream,
+ reinterpret_cast<void**>(stream.Receive()));
+ DLOG_IF(FATAL, hr != INET_E_INVALID_CERTIFICATE) <<
+ "BindToStorage failed " << hr;
+ } while (0);
- if (http_negotiate && !IsSubFrameRequest(http_negotiate)) {
- CComObject<ProtocolSinkWrap>* wrap = NULL;
- CComObject<ProtocolSinkWrap>::CreateInstance(&wrap);
- DCHECK(wrap);
- if (wrap) {
- wrap->AddRef();
- if (wrap->Initialize(protocol, prot_sink, url)) {
- sink_to_use = wrap;
- }
- wrap->Release();
- }
+ hr = session->UnregisterNameSpace(&factory, L"611");
+ if (prot.transaction_) {
+ HookTransactionVtable(prot.transaction_);
+ // Explicit release, otherwise ~CComObjectStackEx will complain about
+ // outstanding reference to us, because it runs before ~FakeProtocol
+ prot.transaction_.Release();
}
+}
- return sink_to_use;
+void TransactionHooks::RevertHooks() {
+ vtable_patch::UnpatchInterfaceMethods(CTransaction_PatchInfo);
+ vtable_patch::UnpatchInterfaceMethods(CTransaction2_PatchInfo);
}
« no previous file with comments | « chrome_frame/protocol_sink_wrap.h ('k') | chrome_frame/test/test_mock_with_web_server.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698