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

Unified Diff: chrome_frame/protocol_sink_wrap.cc

Issue 126143005: Remove Chrome Frame code and resources. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: sync to r244038 Created 6 years, 11 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
Index: chrome_frame/protocol_sink_wrap.cc
diff --git a/chrome_frame/protocol_sink_wrap.cc b/chrome_frame/protocol_sink_wrap.cc
deleted file mode 100644
index 9bd069ed86d4aea293956b72ee5a43cb56e3f12c..0000000000000000000000000000000000000000
--- a/chrome_frame/protocol_sink_wrap.cc
+++ /dev/null
@@ -1,1010 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <htiframe.h>
-#include <mshtml.h>
-#include <algorithm>
-
-#include "chrome_frame/protocol_sink_wrap.h"
-
-#include "base/logging.h"
-#include "base/memory/singleton.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/win/scoped_bstr.h"
-#include "chrome_frame/bho.h"
-#include "chrome_frame/bind_context_info.h"
-#include "chrome_frame/exception_barrier.h"
-#include "chrome_frame/function_stub.h"
-#include "chrome_frame/policy_settings.h"
-#include "chrome_frame/utils.h"
-
-using std::min;
-
-// BINDSTATUS_SERVER_MIMETYPEAVAILABLE == 54. Introduced in IE 8, so
-// not in everyone's headers yet. See:
-// http://msdn.microsoft.com/en-us/library/ms775133(VS.85,loband).aspx
-#ifndef BINDSTATUS_SERVER_MIMETYPEAVAILABLE
-#define BINDSTATUS_SERVER_MIMETYPEAVAILABLE 54
-#endif
-
-bool ProtocolSinkWrap::ignore_xua_ = false;
-
-static const char kTextHtmlMimeType[] = "text/html";
-const wchar_t kUrlMonDllName[] = L"urlmon.dll";
-
-static const int kInternetProtocolStartIndex = 3;
-static const int kInternetProtocolReadIndex = 9;
-static const int kInternetProtocolStartExIndex = 13;
-static const int kInternetProtocolLockRequestIndex = 11;
-static const int kInternetProtocolUnlockRequestIndex = 12;
-static const int kInternetProtocolAbortIndex = 5;
-static const int kInternetProtocolTerminateIndex = 6;
-
-
-// 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);
-
-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);
-
-STDMETHODIMP Hook_LockRequest(InternetProtocol_LockRequest_Fn orig_req,
- IInternetProtocol* protocol,
- DWORD options);
-
-STDMETHODIMP Hook_UnlockRequest(InternetProtocol_UnlockRequest_Fn orig_req,
- IInternetProtocol* protocol);
-
-STDMETHODIMP Hook_Abort(InternetProtocol_Abort_Fn orig_req,
- IInternetProtocol* protocol,
- HRESULT hr,
- DWORD options);
-
-STDMETHODIMP Hook_Terminate(InternetProtocol_Terminate_Fn orig_req,
- IInternetProtocol* protocol,
- DWORD options);
-
-/////////////////////////////////////////////////////////////////////////////
-BEGIN_VTABLE_PATCHES(CTransaction)
- VTABLE_PATCH_ENTRY(kInternetProtocolStartIndex, Hook_Start)
- VTABLE_PATCH_ENTRY(kInternetProtocolReadIndex, Hook_Read)
- VTABLE_PATCH_ENTRY(kInternetProtocolLockRequestIndex, Hook_LockRequest)
- VTABLE_PATCH_ENTRY(kInternetProtocolUnlockRequestIndex, Hook_UnlockRequest)
- VTABLE_PATCH_ENTRY(kInternetProtocolAbortIndex, Hook_Abort)
- VTABLE_PATCH_ENTRY(kInternetProtocolTerminateIndex, Hook_Terminate)
-END_VTABLE_PATCHES()
-
-BEGIN_VTABLE_PATCHES(CTransaction2)
- VTABLE_PATCH_ENTRY(kInternetProtocolStartExIndex, Hook_StartEx)
-END_VTABLE_PATCHES()
-
-//
-// ProtocolSinkWrap implementation
-
-// Static map initialization
-ProtData::ProtocolDataMap ProtData::datamap_;
-base::Lock ProtData::datamap_lock_;
-
-ProtocolSinkWrap::ProtocolSinkWrap() {
- DVLOG(1) << __FUNCTION__ << base::StringPrintf(" 0x%08X", this);
-}
-
-ProtocolSinkWrap::~ProtocolSinkWrap() {
- DVLOG(1) << __FUNCTION__ << base::StringPrintf(" 0x%08X", this);
-}
-
-base::win::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 base::win::ScopedComPtr<IInternetProtocolSink>(new_sink);
-}
-
-// IInternetProtocolSink methods
-STDMETHODIMP ProtocolSinkWrap::Switch(PROTOCOLDATA* protocol_data) {
- HRESULT hr = E_FAIL;
- if (delegate_)
- hr = delegate_->Switch(protocol_data);
- return hr;
-}
-
-STDMETHODIMP ProtocolSinkWrap::ReportProgress(ULONG status_code,
- LPCWSTR status_text) {
- DVLOG(1) << "ProtocolSinkWrap::ReportProgress: "
- << BindStatus2Str(status_code)
- << " Status: " << (status_text ? status_text : L"");
-
- HRESULT hr = prot_data_->ReportProgress(delegate_, status_code, status_text);
- return hr;
-}
-
-STDMETHODIMP ProtocolSinkWrap::ReportData(DWORD flags, ULONG progress,
- ULONG max_progress) {
- DCHECK(delegate_);
- DVLOG(1) << "ProtocolSinkWrap::ReportData: " << Bscf2Str(flags)
- << " progress: " << progress << " progress_max: " << max_progress;
-
- HRESULT hr = prot_data_->ReportData(delegate_, flags, progress, max_progress);
- return hr;
-}
-
-STDMETHODIMP ProtocolSinkWrap::ReportResult(HRESULT result, DWORD error,
- LPCWSTR result_text) {
- DVLOG(1) << "ProtocolSinkWrap::ReportResult: result: " << result
- << " error: " << error
- << " Text: " << (result_text ? result_text : L"");
- ExceptionBarrier barrier;
- HRESULT hr = prot_data_->ReportResult(delegate_, result, error, result_text);
- return hr;
-}
-
-
-// Helpers
-base::win::ScopedComPtr<IBindCtx> BindCtxFromIBindInfo(
- IInternetBindInfo* bind_info) {
- LPOLESTR bind_ctx_string = NULL;
- ULONG count;
- base::win::ScopedComPtr<IBindCtx> bind_ctx;
- bind_info->GetBindString(BINDSTRING_PTR_BIND_CONTEXT, &bind_ctx_string, 1,
- &count);
- if (bind_ctx_string) {
- int bind_ctx_int;
- base::StringToInt(bind_ctx_string, &bind_ctx_int);
- IBindCtx* pbc = reinterpret_cast<IBindCtx*>(bind_ctx_int);
- bind_ctx.Attach(pbc);
- CoTaskMemFree(bind_ctx_string);
- }
-
- return bind_ctx;
-}
-
-bool ShouldWrapSink(IInternetProtocolSink* sink, const wchar_t* url) {
- // Ignore everything that does not start with http:// or https://.
- // |url| is already normalized (i.e. no leading spaces, capital letters in
- // protocol etc) and non-null (we check in Hook_Start).
- DCHECK(url != NULL);
-
- if (ProtocolSinkWrap::ignore_xua())
- return false; // No need to intercept, we're ignoring X-UA-Compatible tags
-
- if ((url != StrStrW(url, L"http://")) && (url != StrStrW(url, L"https://")))
- return false;
-
- base::win::ScopedComPtr<IHttpNegotiate> http_negotiate;
- HRESULT hr = DoQueryService(GUID_NULL, sink, http_negotiate.Receive());
- if (http_negotiate && !IsSubFrameRequest(http_negotiate))
- return true;
-
- return false;
-}
-
-// High level helpers
-bool IsCFRequest(IBindCtx* pbc) {
- base::win::ScopedComPtr<BindContextInfo> info;
- BindContextInfo::FromBindContext(pbc, info.Receive());
- if (info && info->chrome_request())
- return true;
-
- return false;
-}
-
-bool HasProtData(IBindCtx* pbc) {
- base::win::ScopedComPtr<BindContextInfo> info;
- BindContextInfo::FromBindContext(pbc, info.Receive());
- bool result = false;
- if (info)
- result = info->has_prot_data();
- return result;
-}
-
-void PutProtData(IBindCtx* pbc, ProtData* data) {
- // AddRef and Release to avoid a potential leak of a ProtData instance if
- // FromBindContext fails.
- data->AddRef();
- base::win::ScopedComPtr<BindContextInfo> info;
- BindContextInfo::FromBindContext(pbc, info.Receive());
- if (info)
- info->set_prot_data(data);
- data->Release();
-}
-
-bool IsTextHtml(const wchar_t* status_text) {
- const std::wstring str = status_text;
- bool is_text_html = LowerCaseEqualsASCII(str, kTextHtmlMimeType);
- return is_text_html;
-}
-
-bool IsAdditionallySupportedContentType(const wchar_t* status_text) {
- static const char* kHeaderContentTypes[] = {
- "application/xhtml+xml",
- "application/xml",
- "image/svg",
- "image/svg+xml",
- "text/xml",
- "video/ogg",
- "video/webm",
- "video/mp4"
- };
-
- const std::wstring str = status_text;
- for (int i = 0; i < arraysize(kHeaderContentTypes); ++i) {
- if (LowerCaseEqualsASCII(str, kHeaderContentTypes[i]))
- return true;
- }
-
- if (PolicySettings::GetInstance()->GetRendererForContentType(
- status_text) == PolicySettings::RENDER_IN_CHROME_FRAME) {
- return true;
- }
-
- return false;
-}
-
-// Returns:
-// RENDERER_TYPE_OTHER: if suggested mime type is not text/html.
-// RENDERER_TYPE_UNDETERMINED: if suggested mime type is text/html.
-// RENDERER_TYPE_CHROME_RESPONSE_HEADER: X-UA-Compatible tag is in HTTP headers.
-// RENDERER_TYPE_CHROME_DEFAULT_RENDERER: GCF is the default renderer and the
-// Url is not listed in the
-// RenderInHostUrls registry key.
-// RENDERER_TYPE_CHROME_OPT_IN_URL: GCF is not the default renderer and the Url
-// is listed in the RenderInGcfUrls registry
-// key.
-RendererType DetermineRendererTypeFromMetaData(
- const wchar_t* suggested_mime_type,
- const std::wstring& url,
- IWinInetHttpInfo* info) {
- bool is_text_html = IsTextHtml(suggested_mime_type);
- bool is_supported_content_type = is_text_html ||
- IsAdditionallySupportedContentType(suggested_mime_type);
-
- if (!is_supported_content_type)
- return RENDERER_TYPE_OTHER;
-
- if (!url.empty()) {
- RendererType renderer_type = RendererTypeForUrl(url);
- if (IsChrome(renderer_type)) {
- return renderer_type;
- }
- }
-
- if (info) {
- char buffer[512] = "x-ua-compatible";
- DWORD len = sizeof(buffer);
- DWORD flags = 0;
- HRESULT hr = info->QueryInfo(HTTP_QUERY_CUSTOM, buffer, &len, &flags, NULL);
-
- if (hr == S_OK && len > 0) {
- if (CheckXUaCompatibleDirective(buffer, GetIEMajorVersion())) {
- return RENDERER_TYPE_CHROME_RESPONSE_HEADER;
- }
- }
- }
-
- // We can (and want) to sniff the content.
- if (is_text_html) {
- return RENDERER_TYPE_UNDETERMINED;
- }
-
- // We cannot sniff the content.
- return RENDERER_TYPE_OTHER;
-}
-
-RendererType DetermineRendererType(void* buffer, DWORD size, bool last_chance) {
- RendererType renderer_type = RENDERER_TYPE_UNDETERMINED;
- if (last_chance)
- renderer_type = RENDERER_TYPE_OTHER;
-
- std::wstring html_contents;
- // TODO(joshia): detect and handle different content encodings
- base::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;
- if (SUCCEEDED(UtilGetXUACompatContentValue(html_contents,
- &xua_compat_content))) {
- if (CheckXUaCompatibleDirective(WideToASCII(xua_compat_content),
- GetIEMajorVersion())) {
- renderer_type = RENDERER_TYPE_CHROME_HTTP_EQUIV;
- }
- }
-
- return renderer_type;
-}
-
-// ProtData
-ProtData::ProtData(IInternetProtocol* protocol,
- InternetProtocol_Read_Fn read_fun, const wchar_t* url)
- : has_suggested_mime_type_(false), has_server_mime_type_(false),
- buffer_size_(0), buffer_pos_(0),
- renderer_type_(RENDERER_TYPE_UNDETERMINED), protocol_(protocol),
- read_fun_(read_fun), url_(url) {
- memset(buffer_, 0, arraysize(buffer_));
- DVLOG(1) << __FUNCTION__ << " " << this;
-
- // Add to map.
- base::AutoLock lock(datamap_lock_);
- DCHECK(datamap_.end() == datamap_.find(protocol_));
- datamap_[protocol] = this;
-}
-
-ProtData::~ProtData() {
- DVLOG(1) << __FUNCTION__ << " " << this;
- Invalidate();
-}
-
-HRESULT ProtData::Read(void* buffer, ULONG size, ULONG* size_read) {
- if (renderer_type_ == RENDERER_TYPE_UNDETERMINED) {
- return E_PENDING;
- }
-
- 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);
- }
-
- if (size_read)
- *size_read = bytes_to_copy + new_data;
- return hr;
- }
-
- return read_fun_(protocol_, buffer, size, size_read);
-}
-
-// Attempt to detect ChromeFrame from HTTP headers when
-// BINDSTATUS_MIMETYPEAVAILABLE is received.
-// There are three possible outcomes: CHROME_*/OTHER/UNDETERMINED.
-// If RENDERER_TYPE_UNDETERMINED we are going to sniff the content later in
-// ReportData().
-//
-// With not-so-well-written software (mime filters/protocols/protocol patchers)
-// BINDSTATUS_MIMETYPEAVAILABLE might be fired multiple times with different
-// values for the same client.
-// If the renderer_type_ member is:
-// RENDERER_TYPE_CHROME_* - 2nd (and any subsequent)
-// BINDSTATUS_MIMETYPEAVAILABLE is ignored.
-// RENDERER_TYPE_OTHER - 2nd (and any subsequent) BINDSTATUS_MIMETYPEAVAILABLE
-// is passed through.
-// RENDERER_TYPE_UNDETERMINED - Try to detect ChromeFrame from HTTP headers
-// (acts as if this is the first time
-// BINDSTATUS_MIMETYPEAVAILABLE is received).
-HRESULT ProtData::ReportProgress(IInternetProtocolSink* delegate,
- ULONG status_code, LPCWSTR status_text) {
- switch (status_code) {
- case BINDSTATUS_DIRECTBIND:
- renderer_type_ = RENDERER_TYPE_OTHER;
- break;
-
- case BINDSTATUS_REDIRECTING:
- url_.clear();
- if (status_text)
- url_ = status_text;
- break;
-
- case BINDSTATUS_SERVER_MIMETYPEAVAILABLE:
- has_server_mime_type_ = true;
- SaveSuggestedMimeType(status_text);
- return S_OK;
-
- // TODO(stoyan): BINDSTATUS_RAWMIMETYPE
- case BINDSTATUS_MIMETYPEAVAILABLE:
- case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
- SaveSuggestedMimeType(status_text);
- // When Transaction is attached i.e. when existing BTS it terminated
- // and "converted" to BTO, events will be re-fired for the new sink,
- // but we may skip the renderer_type_ determination since it's already
- // done.
- if (renderer_type_ == RENDERER_TYPE_UNDETERMINED) {
- // This may seem awkward. CBinding's implementation of IWinInetHttpInfo
- // will forward to CTransaction that will forward to the real protocol.
- // We may ask CTransaction (our protocol_ member) for IWinInetHttpInfo.
- base::win::ScopedComPtr<IWinInetHttpInfo> info;
- info.QueryFrom(delegate);
- renderer_type_ = DetermineRendererTypeFromMetaData(suggested_mime_type_,
- url_, info);
- }
-
- if (IsChrome(renderer_type_)) {
- // Suggested mime type is "text/html" and we have DEFAULT_RENDERER,
- // OPT_IN_URL, or RESPONSE_HEADER.
- DVLOG(1) << "Forwarding BINDSTATUS_MIMETYPEAVAILABLE "
- << kChromeMimeType;
- SaveReferrer(delegate);
- delegate->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, kChromeMimeType);
- } else if (renderer_type_ == RENDERER_TYPE_OTHER) {
- // Suggested mime type is not "text/html" - we are not interested in
- // this request anymore.
- FireSuggestedMimeType(delegate);
- } else {
- // Suggested mime type is "text/html"; We will try to sniff the
- // HTML content in ReportData.
- DCHECK_EQ(RENDERER_TYPE_UNDETERMINED, renderer_type_);
- }
- return S_OK;
- }
-
- // We are just pass through at this point, avoid false positive crash reports.
- ExceptionBarrierReportOnlyModule barrier;
- return delegate->ReportProgress(status_code, status_text);
-}
-
-HRESULT ProtData::ReportData(IInternetProtocolSink* delegate,
- DWORD flags, ULONG progress, ULONG max_progress) {
- if (renderer_type_ != RENDERER_TYPE_UNDETERMINED) {
- // We are just pass through now, avoid false positive crash reports.
- ExceptionBarrierReportOnlyModule barrier;
- return delegate->ReportData(flags, progress, max_progress);
- }
-
- HRESULT hr = FillBuffer();
-
- bool last_chance = false;
- if (hr == S_OK || hr == S_FALSE) {
- last_chance = true;
- }
-
- renderer_type_ = SkipMetadataCheck() ? RENDERER_TYPE_OTHER
- : DetermineRendererType(buffer_, buffer_size_, last_chance);
-
- if (renderer_type_ == RENDERER_TYPE_UNDETERMINED) {
- // do not report anything, we need more data.
- return S_OK;
- }
-
- if (IsChrome(renderer_type_)) {
- DVLOG(1) << "Forwarding BINDSTATUS_MIMETYPEAVAILABLE " << kChromeMimeType;
- SaveReferrer(delegate);
- delegate->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, kChromeMimeType);
- }
-
- if (renderer_type_ == RENDERER_TYPE_OTHER) {
- FireSuggestedMimeType(delegate);
- }
-
- // This is the first data notification we forward, since up to now we hold
- // the content received.
- flags |= BSCF_FIRSTDATANOTIFICATION;
-
- if (hr == S_FALSE) {
- flags |= (BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE);
- }
-
- return delegate->ReportData(flags, progress, max_progress);
-}
-
-HRESULT ProtData::ReportResult(IInternetProtocolSink* delegate, HRESULT result,
- DWORD error, LPCWSTR result_text) {
- // We may receive ReportResult without ReportData, if the connection fails
- // for example.
- if (renderer_type_ == RENDERER_TYPE_UNDETERMINED) {
- DVLOG(1) << "ReportResult received but renderer type is yet unknown.";
- renderer_type_ = RENDERER_TYPE_OTHER;
- FireSuggestedMimeType(delegate);
- }
-
- HRESULT hr = S_OK;
- if (delegate)
- hr = delegate->ReportResult(result, error, result_text);
- return hr;
-}
-
-
-void ProtData::UpdateUrl(const wchar_t* url) {
- url_ = url;
-}
-
-// 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;
-
- 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;
- }
-
- return hr_read;
-}
-
-void ProtData::SaveSuggestedMimeType(LPCWSTR status_text) {
- has_suggested_mime_type_ = true;
- suggested_mime_type_.Allocate(status_text);
-}
-
-void ProtData::FireSuggestedMimeType(IInternetProtocolSink* delegate) {
- if (has_server_mime_type_) {
- DVLOG(1) << "Forwarding BINDSTATUS_SERVER_MIMETYPEAVAILABLE "
- << suggested_mime_type_;
- delegate->ReportProgress(BINDSTATUS_SERVER_MIMETYPEAVAILABLE,
- suggested_mime_type_);
- }
-
- if (has_suggested_mime_type_) {
- DVLOG(1) << "Forwarding BINDSTATUS_MIMETYPEAVAILABLE "
- << suggested_mime_type_;
- delegate->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE,
- suggested_mime_type_);
- }
-}
-
-void ProtData::SaveReferrer(IInternetProtocolSink* delegate) {
- DCHECK(IsChrome(renderer_type_));
- base::win::ScopedComPtr<IWinInetHttpInfo> info;
- info.QueryFrom(delegate);
- if (info) {
- char buffer[4096] = {0};
- DWORD len = sizeof(buffer);
- DWORD flags = 0;
- HRESULT hr = info->QueryInfo(
- HTTP_QUERY_REFERER | HTTP_QUERY_FLAG_REQUEST_HEADERS,
- buffer, &len, &flags, 0);
- if (hr == S_OK && len > 0)
- referrer_.assign(buffer);
- } else {
- DLOG(WARNING) << "Failed to QI for IWinInetHttpInfo";
- }
-}
-
-scoped_refptr<ProtData> ProtData::DataFromProtocol(
- IInternetProtocol* protocol) {
- scoped_refptr<ProtData> instance;
- base::AutoLock lock(datamap_lock_);
- ProtocolDataMap::iterator it = datamap_.find(protocol);
- if (datamap_.end() != it)
- instance = it->second;
- return instance;
-}
-
-void ProtData::Invalidate() {
- if (protocol_) {
- // Remove from map.
- base::AutoLock lock(datamap_lock_);
- DCHECK(datamap_.end() != datamap_.find(protocol_));
- datamap_.erase(protocol_);
- protocol_ = NULL;
- }
-}
-
-// This function looks for the url pattern indicating that this request needs
-// to be forced into chrome frame.
-// This hack is required because window.open requests from Chrome don't have
-// the URL up front. The URL comes in much later when the renderer initiates a
-// top level navigation for the url passed into window.open.
-// The new page must be rendered in ChromeFrame to preserve the opener
-// relationship with its parent even if the new page does not have the chrome
-// meta tag.
-bool HandleAttachToExistingExternalTab(LPCWSTR url,
- IInternetProtocol* protocol,
- IInternetProtocolSink* prot_sink,
- IBindCtx* bind_ctx) {
- ChromeFrameUrl cf_url;
- if (cf_url.Parse(url) && cf_url.attach_to_external_tab()) {
- scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol);
- if (!prot_data) {
- // Pass NULL as the read function which indicates that always return EOF
- // without calling the underlying protocol.
- prot_data = new ProtData(protocol, NULL, url);
- PutProtData(bind_ctx, prot_data);
- }
-
- prot_sink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, kChromeMimeType);
-
- int data_flags = BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION;
- prot_sink->ReportData(data_flags, 0, 0);
-
- prot_sink->ReportResult(S_OK, 0, NULL);
- return true;
- }
- return false;
-}
-
-HRESULT ForwardHookStart(InternetProtocol_Start_Fn orig_start,
- IInternetProtocol* protocol, LPCWSTR url, IInternetProtocolSink* prot_sink,
- IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved) {
- ExceptionBarrierReportOnlyModule barrier;
- return orig_start(protocol, url, prot_sink, bind_info, flags, reserved);
-}
-
-HRESULT ForwardWrappedHookStart(InternetProtocol_Start_Fn orig_start,
- IInternetProtocol* protocol, LPCWSTR url, IInternetProtocolSink* prot_sink,
- IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved) {
- ExceptionBarrier barrier;
- return orig_start(protocol, url, prot_sink, bind_info, flags, reserved);
-}
-
-// 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;
- DVLOG_IF(1, url != NULL) << "OnStart: " << url << PiFlags2Str(flags);
-
- base::win::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
- DVLOG(1) << "DirectBind for " << url;
- return ForwardHookStart(orig_start, protocol, url, prot_sink, bind_info,
- flags, reserved);
- }
-
- scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol);
- if (prot_data && !HasProtData(bind_ctx)) {
- prot_data->Invalidate();
- prot_data = NULL;
- }
-
- if (HandleAttachToExistingExternalTab(url, protocol, prot_sink, bind_ctx)) {
- return S_OK;
- }
-
- if (IsCFRequest(bind_ctx)) {
- base::win::ScopedComPtr<BindContextInfo> info;
- BindContextInfo::FromBindContext(bind_ctx, info.Receive());
- DCHECK(info);
- if (info) {
- info->set_protocol(protocol);
- }
- return ForwardHookStart(orig_start, protocol, url, prot_sink, bind_info,
- flags, reserved);
- }
-
- if (prot_data) {
- DVLOG(1) << "Found existing ProtData!";
- prot_data->UpdateUrl(url);
- base::win::ScopedComPtr<IInternetProtocolSink> new_sink =
- ProtocolSinkWrap::CreateNewSink(prot_sink, prot_data);
- return ForwardWrappedHookStart(orig_start, protocol, url, new_sink,
- bind_info, flags, reserved);
- }
-
- if (!ShouldWrapSink(prot_sink, url)) {
- return ForwardHookStart(orig_start, protocol, url, 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);
-
- base::win::ScopedComPtr<IInternetProtocolSink> new_sink =
- ProtocolSinkWrap::CreateNewSink(prot_sink, prot_data);
- return ForwardWrappedHookStart(orig_start, protocol, url, new_sink, bind_info,
- flags, reserved);
-}
-
-HRESULT ForwardHookStartEx(InternetProtocol_StartEx_Fn orig_start_ex,
- IInternetProtocolEx* protocol, IUri* uri, IInternetProtocolSink* prot_sink,
- IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved) {
- ExceptionBarrierReportOnlyModule barrier;
- return orig_start_ex(protocol, uri, prot_sink, bind_info, flags, reserved);
-}
-
-HRESULT ForwardWrappedHookStartEx(InternetProtocol_StartEx_Fn orig_start_ex,
- IInternetProtocolEx* protocol, IUri* uri, IInternetProtocolSink* prot_sink,
- IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved) {
- ExceptionBarrier barrier;
- return orig_start_ex(protocol, uri, prot_sink, bind_info, flags, reserved);
-}
-
-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;
-
- base::win::ScopedBstr url;
- uri->GetPropertyBSTR(Uri_PROPERTY_ABSOLUTE_URI, url.Receive(), 0);
- DVLOG_IF(1, url != NULL) << "OnStartEx: " << url << PiFlags2Str(flags);
-
- base::win::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.
- DVLOG(1) << "DirectBind for " << url;
- return ForwardHookStartEx(orig_start_ex, protocol, uri, prot_sink,
- bind_info, flags, reserved);
- }
-
- scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol);
- if (prot_data && !HasProtData(bind_ctx)) {
- prot_data->Invalidate();
- prot_data = NULL;
- }
-
- if (HandleAttachToExistingExternalTab(url, protocol, prot_sink, bind_ctx)) {
- return S_OK;
- }
-
- if (IsCFRequest(bind_ctx)) {
- base::win::ScopedComPtr<BindContextInfo> info;
- BindContextInfo::FromBindContext(bind_ctx, info.Receive());
- DCHECK(info);
- if (info) {
- info->set_protocol(protocol);
- }
- return ForwardHookStartEx(orig_start_ex, protocol, uri, prot_sink,
- bind_info, flags, reserved);
- }
-
- if (prot_data) {
- DVLOG(1) << "Found existing ProtData!";
- prot_data->UpdateUrl(url);
- base::win::ScopedComPtr<IInternetProtocolSink> new_sink =
- ProtocolSinkWrap::CreateNewSink(prot_sink, prot_data);
- return ForwardWrappedHookStartEx(orig_start_ex, protocol, uri, new_sink,
- bind_info, flags, reserved);
- }
-
- if (!ShouldWrapSink(prot_sink, url)) {
- return ForwardHookStartEx(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);
-
- base::win::ScopedComPtr<IInternetProtocolSink> new_sink =
- ProtocolSinkWrap::CreateNewSink(prot_sink, prot_data);
- return ForwardWrappedHookStartEx(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);
- HRESULT hr = E_FAIL;
-
- scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol);
- if (!prot_data) {
- // We are not wrapping this request, avoid false positive crash reports.
- ExceptionBarrierReportOnlyModule barrier;
- hr = orig_read(protocol, buffer, size, size_read);
- return hr;
- }
-
- if (prot_data->is_attach_external_tab_request()) {
- // return EOF always.
- if (size_read)
- *size_read = 0;
- return S_FALSE;
- }
-
- hr = prot_data->Read(buffer, size, size_read);
- return hr;
-}
-
-STDMETHODIMP Hook_LockRequest(InternetProtocol_LockRequest_Fn orig_req,
- IInternetProtocol* protocol,
- DWORD options) {
- DCHECK(orig_req);
-
- scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol);
- if (prot_data && prot_data->is_attach_external_tab_request()) {
- prot_data->AddRef();
- return S_OK;
- }
-
- // We are just pass through at this point, avoid false positive crash
- // reports.
- ExceptionBarrierReportOnlyModule barrier;
- return orig_req(protocol, options);
-}
-
-STDMETHODIMP Hook_UnlockRequest(InternetProtocol_UnlockRequest_Fn orig_req,
- IInternetProtocol* protocol) {
- DCHECK(orig_req);
-
- scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol);
- if (prot_data && prot_data->is_attach_external_tab_request()) {
- prot_data->Release();
- return S_OK;
- }
-
- // We are just pass through at this point, avoid false positive crash
- // reports.
- ExceptionBarrierReportOnlyModule barrier;
- return orig_req(protocol);
-}
-
-STDMETHODIMP Hook_Abort(InternetProtocol_Abort_Fn orig_req,
- IInternetProtocol* protocol,
- HRESULT hr,
- DWORD options) {
- scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol);
- if (prot_data)
- prot_data->Invalidate();
-
- // We are just pass through at this point, avoid false positive crash
- // reports.
- ExceptionBarrierReportOnlyModule barrier;
- return orig_req(protocol, hr, options);
-}
-
-STDMETHODIMP Hook_Terminate(InternetProtocol_Terminate_Fn orig_req,
- IInternetProtocol* protocol,
- DWORD options) {
- scoped_refptr<ProtData> prot_data = ProtData::DataFromProtocol(protocol);
- // We should not be invalidating the cached protocol data in the following
- // cases:-
- // 1. Pages which are switching into ChromeFrame.
- // When IE switches into ChromeFrame, we report the Chrome mime type as
- // the handler for the page. This results in urlmon terminating the
- // protocol. When Chrome attempts to read the data we need to report the
- // cached data back to Chrome.
- // 2. For the attach external tab requests which are temporary navigations
- // to ensure that a top level URL is opened in IE from ChromeFrame.
- // We rely on the mapping to identify these requests as attach tab
- // requests. This mapping is referred to in the
- // IInternetProtocol::LockRequest/IInternetProtocol::UnlockRequest
- // intercepts. Invalidating the mapping after LockRequest is called and
- // before UnlockRequest causes IE to crash.
- if (prot_data && !IsChrome(prot_data->renderer_type()) &&
- !prot_data->is_attach_external_tab_request())
- prot_data->Invalidate();
-
- // We are just pass through at this point, avoid false positive crash
- // reports.
- ExceptionBarrierReportOnlyModule barrier;
- return orig_req(protocol, options);
-}
-
-// 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()
-
- 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;
- }
-
- 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; }
-
- base::win::ScopedComPtr<IInternetProtocol> transaction_;
-};
-
-struct FakeFactory : public IClassFactory,
- public CComObjectRootEx<CComSingleThreadModel> {
- BEGIN_COM_MAP(FakeFactory)
- COM_INTERFACE_ENTRY(IClassFactory)
- END_COM_MAP()
-
- STDMETHOD(CreateInstance)(IUnknown *pUnkOuter, REFIID riid, void **ppvObj) {
- if (pUnkOuter)
- return CLASS_E_NOAGGREGATION;
- HRESULT hr = obj_->QueryInterface(riid, ppvObj);
- return hr;
- }
-
- STDMETHOD(LockServer)(BOOL fLock) {
- return S_OK;
- }
-
- IUnknown* obj_;
-};
-
-static void HookTransactionVtable(IInternetProtocol* p) {
- base::win::ScopedComPtr<IInternetProtocolEx> ex;
- ex.QueryFrom(p);
-
- HRESULT hr = vtable_patch::PatchInterfaceMethods(p, CTransaction_PatchInfo);
- if (hr == S_OK && ex) {
- vtable_patch::PatchInterfaceMethods(ex.get(), CTransaction2_PatchInfo);
- }
-}
-
-void TransactionHooks::InstallHooks() {
- if (IS_PATCHED(CTransaction)) {
- DLOG(WARNING) << __FUNCTION__ << " called more than once.";
- return;
- }
-
- CComObjectStackEx<FakeProtocol> prot;
- CComObjectStackEx<FakeFactory> factory;
- factory.obj_ = &prot;
- base::win::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;
-
- do {
- base::win::ScopedComPtr<IMoniker> mk;
- base::win::ScopedComPtr<IBindCtx> bc;
- base::win::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;
-
- hr = ::CreateURLMoniker(NULL, L"611://512", mk.Receive());
- DLOG_IF(FATAL, FAILED(hr)) << "CreateURLMoniker failed " << hr;
- if (hr != S_OK)
- break;
-
- 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);
-
- 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();
- }
-}
-
-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/ready_mode/internal/ready_mode_web_browser_adapter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698