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

Side by Side Diff: chrome_frame/protocol_sink_wrap.cc

Issue 2987001: Implement HTTP headers sniffing in the ProtocolSinkWrap, instead of relying o... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 5 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome_frame/protocol_sink_wrap.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
176 if (!status_text) 176 if (!status_text)
177 return false; 177 return false;
178 size_t status_text_length = lstrlenW(status_text); 178 size_t status_text_length = lstrlenW(status_text);
179 const wchar_t* status_text_end = status_text + 179 const wchar_t* status_text_end = status_text +
180 std::min(status_text_length, arraysize(kTextHtmlMimeType) - 1); 180 std::min(status_text_length, arraysize(kTextHtmlMimeType) - 1);
181 bool is_text_html = LowerCaseEqualsASCII(status_text, status_text_end, 181 bool is_text_html = LowerCaseEqualsASCII(status_text, status_text_end,
182 kTextHtmlMimeType); 182 kTextHtmlMimeType);
183 return is_text_html; 183 return is_text_html;
184 } 184 }
185 185
186 // Returns:
187 // CHROME: if suggested mime type is "text/html" and at least one of the
188 // following is true: 1) X-UA-Compatible tag is in HTTP headers.
189 // 2) Url is listed in OptInURLs registry key.
190 // OTHER: if suggested mime type is not text/html.
191 // UNDETERMINED: if suggested mime type is text/html.
192 RendererType DetermineRendererTypeFromMetaData(
193 const wchar_t* suggested_mime_type,
194 const std::wstring& url,
195 IWinInetHttpInfo* info) {
196 if (!IsTextHtml(suggested_mime_type)) {
197 return OTHER;
198 }
199
200 if (!url.empty() && IsOptInUrl(url.c_str())) {
201 return CHROME;
202 }
203
204 if (info) {
205 char buffer[32] = "x-ua-compatible";
206 DWORD len = sizeof(buffer);
207 DWORD flags = 0;
208 HRESULT hr = info->QueryInfo(HTTP_QUERY_CUSTOM, buffer, &len, &flags, NULL);
209 if (hr == S_OK && len > 0) {
210 if (StrStrIA(buffer, "chrome=1")) {
211 return CHROME;
212 }
213 }
214 }
215 return UNDETERMINED;
216 }
217
186 RendererType DetermineRendererType(void* buffer, DWORD size, bool last_chance) { 218 RendererType DetermineRendererType(void* buffer, DWORD size, bool last_chance) {
187 RendererType type = UNDETERMINED; 219 RendererType type = UNDETERMINED;
188 if (last_chance) 220 if (last_chance)
189 type = OTHER; 221 type = OTHER;
190 222
191 std::wstring html_contents; 223 std::wstring html_contents;
192 // TODO(joshia): detect and handle different content encodings 224 // TODO(joshia): detect and handle different content encodings
193 UTF8ToWide(reinterpret_cast<char*>(buffer), size, &html_contents); 225 UTF8ToWide(reinterpret_cast<char*>(buffer), size, &html_contents);
194 226
195 // Note that document_contents_ may have NULL characters in it. While 227 // Note that document_contents_ may have NULL characters in it. While
196 // browsers may handle this properly, we don't and will stop scanning 228 // browsers may handle this properly, we don't and will stop scanning
197 // for the XUACompat content value if we encounter one. 229 // for the XUACompat content value if we encounter one.
198 std::wstring xua_compat_content; 230 std::wstring xua_compat_content;
199 UtilGetXUACompatContentValue(html_contents, &xua_compat_content); 231 UtilGetXUACompatContentValue(html_contents, &xua_compat_content);
200 if (StrStrI(xua_compat_content.c_str(), kChromeContentPrefix)) { 232 if (StrStrI(xua_compat_content.c_str(), kChromeContentPrefix)) {
201 type = CHROME; 233 type = CHROME;
202 } 234 }
203 235
204 return type; 236 return type;
205 } 237 }
206 238
207 // ProtData 239 // ProtData
208 ProtData::ProtData(IInternetProtocol* protocol, 240 ProtData::ProtData(IInternetProtocol* protocol,
209 InternetProtocol_Read_Fn read_fun, const wchar_t* url) 241 InternetProtocol_Read_Fn read_fun, const wchar_t* url)
210 : has_suggested_mime_type_(false), has_server_mime_type_(false), 242 : has_suggested_mime_type_(false), has_server_mime_type_(false),
211 report_data_received_(false), buffer_size_(0), buffer_pos_(0), 243 buffer_size_(0), buffer_pos_(0),
212 renderer_type_(UNDETERMINED), protocol_(protocol), read_fun_(read_fun), 244 renderer_type_(UNDETERMINED), protocol_(protocol), read_fun_(read_fun),
213 url_(url) { 245 url_(url) {
214 memset(buffer_, 0, arraysize(buffer_)); 246 memset(buffer_, 0, arraysize(buffer_));
215 DLOG(INFO) << __FUNCTION__ << " " << this; 247 DLOG(INFO) << __FUNCTION__ << " " << this;
216 248
217 // Add to map. 249 // Add to map.
218 AutoLock lock(datamap_lock_); 250 AutoLock lock(datamap_lock_);
219 DCHECK(datamap_.end() == datamap_.find(protocol_)); 251 DCHECK(datamap_.end() == datamap_.find(protocol_));
220 datamap_[protocol] = this; 252 datamap_[protocol] = this;
221 } 253 }
(...skipping 30 matching lines...) Expand all
252 } 284 }
253 285
254 if (size_read) 286 if (size_read)
255 *size_read = bytes_to_copy + new_data; 287 *size_read = bytes_to_copy + new_data;
256 return hr; 288 return hr;
257 } 289 }
258 290
259 return read_fun_(protocol_, buffer, size, size_read); 291 return read_fun_(protocol_, buffer, size, size_read);
260 } 292 }
261 293
262
263 HRESULT ProtData::ReportProgress(IInternetProtocolSink* delegate, 294 HRESULT ProtData::ReportProgress(IInternetProtocolSink* delegate,
264 ULONG status_code, LPCWSTR status_text) { 295 ULONG status_code, LPCWSTR status_text) {
265 switch (status_code) { 296 switch (status_code) {
266 case BINDSTATUS_DIRECTBIND: 297 case BINDSTATUS_DIRECTBIND:
267 renderer_type_ = OTHER; 298 renderer_type_ = OTHER;
268 break; 299 break;
269 300
270 case BINDSTATUS_REDIRECTING: 301 case BINDSTATUS_REDIRECTING:
271 url_.empty(); 302 url_.empty();
272 if (status_text) 303 if (status_text)
273 url_ = status_text; 304 url_ = status_text;
274 break; 305 break;
275 306
276 case BINDSTATUS_SERVER_MIMETYPEAVAILABLE: 307 case BINDSTATUS_SERVER_MIMETYPEAVAILABLE:
277 has_server_mime_type_ = true; 308 has_server_mime_type_ = true;
278 SaveSuggestedMimeType(status_text); 309 SaveSuggestedMimeType(status_text);
279 return S_OK; 310 return S_OK;
280 311
281 // TODO(stoyan): BINDSTATUS_RAWMIMETYPE 312 // TODO(stoyan): BINDSTATUS_RAWMIMETYPE
282 case BINDSTATUS_MIMETYPEAVAILABLE: 313 case BINDSTATUS_MIMETYPEAVAILABLE:
283 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE: 314 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
284 SaveSuggestedMimeType(status_text); 315 SaveSuggestedMimeType(status_text);
316
317 ScopedComPtr<IWinInetHttpInfo> info;
318 info.QueryFrom(delegate);
319 renderer_type_ = DetermineRendererTypeFromMetaData(suggested_mime_type_,
320 url_, info);
321
322 if (renderer_type_ == CHROME) {
323 // Suggested mime type is "text/html" and we either have OptInUrl
324 // or X-UA-Compatible HTTP headers.
325 DLOG(INFO) << "Forwarding BINDSTATUS_MIMETYPEAVAILABLE "
326 << kChromeMimeType;
327 delegate->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, kChromeMimeType);
328 } else if (renderer_type_ == OTHER) {
329 // Suggested mime type is not "text/html" - we are not interested in
330 // this request anymore.
331 FireSugestedMimeType(delegate);
332 } else {
333 // Suggested mime type is "text/html"; We will try to sniff the
334 // HTML content in ReportData.
335 DCHECK_EQ(UNDETERMINED, renderer_type_);
336 }
285 return S_OK; 337 return S_OK;
286 } 338 }
287 339
288 return delegate->ReportProgress(status_code, status_text); 340 return delegate->ReportProgress(status_code, status_text);
289 } 341 }
290 342
291 HRESULT ProtData::ReportData(IInternetProtocolSink* delegate, 343 HRESULT ProtData::ReportData(IInternetProtocolSink* delegate,
292 DWORD flags, ULONG progress, ULONG max_progress) { 344 DWORD flags, ULONG progress, ULONG max_progress) {
293 if (renderer_type_ != UNDETERMINED) { 345 if (renderer_type_ != UNDETERMINED) {
294 return delegate->ReportData(flags, progress, max_progress); 346 return delegate->ReportData(flags, progress, max_progress);
295 } 347 }
296 348
297 // Do these checks only once.
298 if (!report_data_received_) {
299 report_data_received_ = true;
300
301 DLOG_IF(INFO, (flags & BSCF_FIRSTDATANOTIFICATION) == 0) <<
302 "BUGBUG: BSCF_FIRSTDATANOTIFICATION is not set properly!";
303
304
305 // We check here, instead in ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE)
306 // to be safe when following multiple redirects.?
307 if (!IsTextHtml(suggested_mime_type_)) {
308 renderer_type_ = OTHER;
309 FireSugestedMimeType(delegate);
310 return delegate->ReportData(flags, progress, max_progress);
311 }
312
313 if (!url_.empty() && IsOptInUrl(url_.c_str())) {
314 // TODO(stoyan): We may attempt to remove ourselves from the bind context.
315 renderer_type_ = CHROME;
316 delegate->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, kChromeMimeType);
317 return delegate->ReportData(flags, progress, max_progress);
318 }
319 }
320
321 HRESULT hr = FillBuffer(); 349 HRESULT hr = FillBuffer();
322 350
323 bool last_chance = false; 351 bool last_chance = false;
324 if (hr == S_OK || hr == S_FALSE) { 352 if (hr == S_OK || hr == S_FALSE) {
325 last_chance = true; 353 last_chance = true;
326 } 354 }
327 355
328 renderer_type_ = DetermineRendererType(buffer_, buffer_size_, last_chance); 356 renderer_type_ = DetermineRendererType(buffer_, buffer_size_, last_chance);
329 357
330 if (renderer_type_ == UNDETERMINED) { 358 if (renderer_type_ == UNDETERMINED) {
331 // do not report anything, we need more data. 359 // do not report anything, we need more data.
332 return S_OK; 360 return S_OK;
333 } 361 }
334 362
335 if (renderer_type_ == CHROME) { 363 if (renderer_type_ == CHROME) {
336 DLOG(INFO) << "Forwarding BINDSTATUS_MIMETYPEAVAILABLE " 364 DLOG(INFO) << "Forwarding BINDSTATUS_MIMETYPEAVAILABLE "
337 << kChromeMimeType; 365 << kChromeMimeType;
338 delegate->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, kChromeMimeType); 366 delegate->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, kChromeMimeType);
339 } 367 }
340 368
341 if (renderer_type_ == OTHER) { 369 if (renderer_type_ == OTHER) {
342 FireSugestedMimeType(delegate); 370 FireSugestedMimeType(delegate);
343 } 371 }
344 372
345 // This is the first data notification we forward. 373 // This is the first data notification we forward, since up to now we hold
374 // the content received.
346 flags |= BSCF_FIRSTDATANOTIFICATION; 375 flags |= BSCF_FIRSTDATANOTIFICATION;
347 376
348 if (hr == S_FALSE) { 377 if (hr == S_FALSE) {
349 flags |= (BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE); 378 flags |= (BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE);
350 } 379 }
351 380
352 return delegate->ReportData(flags, progress, max_progress); 381 return delegate->ReportData(flags, progress, max_progress);
353 } 382 }
354 383
355 HRESULT ProtData::ReportResult(IInternetProtocolSink* delegate, HRESULT result, 384 HRESULT ProtData::ReportResult(IInternetProtocolSink* delegate, HRESULT result,
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
627 // Explicit release, otherwise ~CComObjectStackEx will complain about 656 // Explicit release, otherwise ~CComObjectStackEx will complain about
628 // outstanding reference to us, because it runs before ~FakeProtocol 657 // outstanding reference to us, because it runs before ~FakeProtocol
629 prot.transaction_.Release(); 658 prot.transaction_.Release();
630 } 659 }
631 } 660 }
632 661
633 void TransactionHooks::RevertHooks() { 662 void TransactionHooks::RevertHooks() {
634 vtable_patch::UnpatchInterfaceMethods(CTransaction_PatchInfo); 663 vtable_patch::UnpatchInterfaceMethods(CTransaction_PatchInfo);
635 vtable_patch::UnpatchInterfaceMethods(CTransaction2_PatchInfo); 664 vtable_patch::UnpatchInterfaceMethods(CTransaction2_PatchInfo);
636 } 665 }
OLDNEW
« no previous file with comments | « chrome_frame/protocol_sink_wrap.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698