diff options
author | stoyan@chromium.org <stoyan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-14 17:31:25 +0000 |
---|---|---|
committer | stoyan@chromium.org <stoyan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-14 17:31:25 +0000 |
commit | 3f3130a68035f8317100d98e3e3b3ab49cf6ebb3 (patch) | |
tree | 7ac5bc311d687654ffb315d171502a53ffd6cbc4 | |
parent | 90242e9e03d4eeff67d9fbc97e555597206c69d1 (diff) | |
download | chromium_src-3f3130a68035f8317100d98e3e3b3ab49cf6ebb3.zip chromium_src-3f3130a68035f8317100d98e3e3b3ab49cf6ebb3.tar.gz chromium_src-3f3130a68035f8317100d98e3e3b3ab49cf6ebb3.tar.bz2 |
Implement HTTP headers sniffing in the ProtocolSinkWrap, instead of relying on IHttpNegotiate patch.
Moved some code based on over-conservative assumptions to execute earlier in pipeline.
Will prevent BUG=38480 to manifest itself.
BUG=47879
Review URL: http://codereview.chromium.org/2987001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@52337 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome_frame/http_negotiate.cc | 26 | ||||
-rw-r--r-- | chrome_frame/protocol_sink_wrap.cc | 83 | ||||
-rw-r--r-- | chrome_frame/protocol_sink_wrap.h | 2 |
3 files changed, 71 insertions, 40 deletions
diff --git a/chrome_frame/http_negotiate.cc b/chrome_frame/http_negotiate.cc index 87dc65c5..30d7961 100644 --- a/chrome_frame/http_negotiate.cc +++ b/chrome_frame/http_negotiate.cc @@ -173,17 +173,21 @@ HRESULT HttpNegotiatePatch::PatchHttpNegotiate(IUnknown* to_patch) { << StringPrintf("IHttpNegotiate not supported 0x%08X", hr); } - ScopedComPtr<IBindStatusCallback> bscb; - hr = bscb.QueryFrom(to_patch); - - if (bscb) { - hr = vtable_patch::PatchInterfaceMethods(bscb, - IBindStatusCallback_PatchInfo); - DLOG_IF(ERROR, FAILED(hr)) - << StringPrintf("BindStatusCallback patch failed 0x%08X", hr); - } else { - DLOG(WARNING) << StringPrintf("IBindStatusCallback not supported 0x%08X", - hr); + // CTransaction patch supports sniffing HTTP headers, so no need of + // sniffing inside HttpNegotiatePatch::ReportProgress. + if (GetPatchMethod() != PATCH_METHOD_INET_PROTOCOL) { + ScopedComPtr<IBindStatusCallback> bscb; + hr = bscb.QueryFrom(to_patch); + + if (bscb) { + hr = vtable_patch::PatchInterfaceMethods(bscb, + IBindStatusCallback_PatchInfo); + DLOG_IF(ERROR, FAILED(hr)) + << StringPrintf("BindStatusCallback patch failed 0x%08X", hr); + } else { + DLOG(WARNING) << StringPrintf("IBindStatusCallback not supported 0x%08X", + hr); + } } return hr; } diff --git a/chrome_frame/protocol_sink_wrap.cc b/chrome_frame/protocol_sink_wrap.cc index 5a9b68d..1d20e9b 100644 --- a/chrome_frame/protocol_sink_wrap.cc +++ b/chrome_frame/protocol_sink_wrap.cc @@ -183,6 +183,38 @@ bool IsTextHtml(const wchar_t* status_text) { return is_text_html; } +// Returns: +// CHROME: if suggested mime type is "text/html" and at least one of the +// following is true: 1) X-UA-Compatible tag is in HTTP headers. +// 2) Url is listed in OptInURLs registry key. +// OTHER: if suggested mime type is not text/html. +// UNDETERMINED: if suggested mime type is text/html. +RendererType DetermineRendererTypeFromMetaData( + const wchar_t* suggested_mime_type, + const std::wstring& url, + IWinInetHttpInfo* info) { + if (!IsTextHtml(suggested_mime_type)) { + return OTHER; + } + + if (!url.empty() && IsOptInUrl(url.c_str())) { + return CHROME; + } + + if (info) { + char buffer[32] = "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 (StrStrIA(buffer, "chrome=1")) { + return CHROME; + } + } + } + return UNDETERMINED; +} + RendererType DetermineRendererType(void* buffer, DWORD size, bool last_chance) { RendererType type = UNDETERMINED; if (last_chance) @@ -208,7 +240,7 @@ RendererType DetermineRendererType(void* buffer, DWORD size, bool last_chance) { 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), + buffer_size_(0), buffer_pos_(0), renderer_type_(UNDETERMINED), protocol_(protocol), read_fun_(read_fun), url_(url) { memset(buffer_, 0, arraysize(buffer_)); @@ -259,7 +291,6 @@ HRESULT ProtData::Read(void* buffer, ULONG size, ULONG* size_read) { return read_fun_(protocol_, buffer, size, size_read); } - HRESULT ProtData::ReportProgress(IInternetProtocolSink* delegate, ULONG status_code, LPCWSTR status_text) { switch (status_code) { @@ -282,6 +313,27 @@ HRESULT ProtData::ReportProgress(IInternetProtocolSink* delegate, case BINDSTATUS_MIMETYPEAVAILABLE: case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE: SaveSuggestedMimeType(status_text); + + ScopedComPtr<IWinInetHttpInfo> info; + info.QueryFrom(delegate); + renderer_type_ = DetermineRendererTypeFromMetaData(suggested_mime_type_, + url_, info); + + if (renderer_type_ == CHROME) { + // Suggested mime type is "text/html" and we either have OptInUrl + // or X-UA-Compatible HTTP headers. + DLOG(INFO) << "Forwarding BINDSTATUS_MIMETYPEAVAILABLE " + << kChromeMimeType; + delegate->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, kChromeMimeType); + } else if (renderer_type_ == OTHER) { + // Suggested mime type is not "text/html" - we are not interested in + // this request anymore. + FireSugestedMimeType(delegate); + } else { + // Suggested mime type is "text/html"; We will try to sniff the + // HTML content in ReportData. + DCHECK_EQ(UNDETERMINED, renderer_type_); + } return S_OK; } @@ -294,30 +346,6 @@ HRESULT ProtData::ReportData(IInternetProtocolSink* delegate, 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); - } - } - HRESULT hr = FillBuffer(); bool last_chance = false; @@ -342,7 +370,8 @@ HRESULT ProtData::ReportData(IInternetProtocolSink* delegate, FireSugestedMimeType(delegate); } - // This is the first data notification we forward. + // This is the first data notification we forward, since up to now we hold + // the content received. flags |= BSCF_FIRSTDATANOTIFICATION; if (hr == S_FALSE) { diff --git a/chrome_frame/protocol_sink_wrap.h b/chrome_frame/protocol_sink_wrap.h index 2b8a08d0..a6b88b6 100644 --- a/chrome_frame/protocol_sink_wrap.h +++ b/chrome_frame/protocol_sink_wrap.h @@ -134,8 +134,6 @@ class ProtData : public base::RefCounted<ProtData> { // BINDSTATUS_SERVER_MIMETYPEAVAILABLE received, so we shall fire one. bool has_server_mime_type_; - // Did we received ReportData() - bool report_data_received_; RendererType renderer_type_; // Buffer for accumulated data including 1 extra for NULL-terminator |