| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |