summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorstoyan@chromium.org <stoyan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-14 17:31:25 +0000
committerstoyan@chromium.org <stoyan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-14 17:31:25 +0000
commit3f3130a68035f8317100d98e3e3b3ab49cf6ebb3 (patch)
tree7ac5bc311d687654ffb315d171502a53ffd6cbc4
parent90242e9e03d4eeff67d9fbc97e555597206c69d1 (diff)
downloadchromium_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.cc26
-rw-r--r--chrome_frame/protocol_sink_wrap.cc83
-rw-r--r--chrome_frame/protocol_sink_wrap.h2
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