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

Side by Side Diff: chrome_frame/protocol_sink_wrap.cc

Issue 218019: Initial import of the Chrome Frame codebase. Integration in chrome.gyp coming... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 11 years, 2 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') | chrome_frame/rename_me_to_supplement.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include <htiframe.h>
6
7 #include "chrome_frame/protocol_sink_wrap.h"
8
9 #include "base/scoped_bstr_win.h"
10 #include "base/logging.h"
11 #include "base/registry.h"
12 #include "base/scoped_bstr_win.h"
13 #include "base/singleton.h"
14 #include "base/string_util.h"
15
16 #include "chrome_frame/utils.h"
17 #include "chrome_frame/vtable_patch_manager.h"
18
19 // BINDSTATUS_SERVER_MIMETYPEAVAILABLE == 54. Introduced in IE 8, so
20 // not in everyone's headers yet. See:
21 // http://msdn.microsoft.com/en-us/library/ms775133(VS.85,loband).aspx
22 #ifndef BINDSTATUS_SERVER_MIMETYPEAVAILABLE
23 #define BINDSTATUS_SERVER_MIMETYPEAVAILABLE 54
24 #endif
25
26 static const wchar_t* kChromeMimeType = L"application/chromepage";
27 static const char kTextHtmlMimeType[] = "text/html";
28
29 static const int kInternetProtocolStartIndex = 3;
30 static const int kInternetProtocolReadIndex = 9;
31 static const int kInternetProtocolStartExIndex = 13;
32
33 BEGIN_VTABLE_PATCHES(IInternetProtocol)
34 VTABLE_PATCH_ENTRY(kInternetProtocolStartIndex, ProtocolSinkWrap::OnStart)
35 VTABLE_PATCH_ENTRY(kInternetProtocolReadIndex, ProtocolSinkWrap::OnRead)
36 END_VTABLE_PATCHES()
37
38 BEGIN_VTABLE_PATCHES(IInternetProtocolEx)
39 VTABLE_PATCH_ENTRY(kInternetProtocolStartIndex, ProtocolSinkWrap::OnStart)
40 VTABLE_PATCH_ENTRY(kInternetProtocolReadIndex, ProtocolSinkWrap::OnRead)
41 VTABLE_PATCH_ENTRY(kInternetProtocolStartExIndex, ProtocolSinkWrap::OnStartEx)
42 END_VTABLE_PATCHES()
43
44 //
45 // ProtocolSinkWrap implementation
46 //
47
48 // Static map initialization
49 ProtocolSinkWrap::ProtocolSinkMap ProtocolSinkWrap::sink_map_;
50 CComAutoCriticalSection ProtocolSinkWrap::sink_map_lock_;
51
52 ProtocolSinkWrap::ProtocolSinkWrap()
53 : protocol_(NULL), renderer_type_(UNDETERMINED),
54 buffer_size_(0), buffer_pos_(0), is_saved_result_(false),
55 result_code_(0), result_error_(0), report_data_recursiveness_(0) {
56 memset(buffer_, 0, arraysize(buffer_));
57 }
58
59 ProtocolSinkWrap::~ProtocolSinkWrap() {
60 CComCritSecLock<CComAutoCriticalSection> lock(sink_map_lock_);
61 DCHECK(sink_map_.end() != sink_map_.find(protocol_));
62 sink_map_.erase(protocol_);
63 protocol_ = NULL;
64 DLOG(INFO) << "ProtocolSinkWrap: active sinks: " << sink_map_.size();
65 }
66
67 bool ProtocolSinkWrap::PatchProtocolHandler(const wchar_t* dll,
68 const CLSID& handler_clsid) {
69 HMODULE module = ::GetModuleHandle(dll);
70 if (!module) {
71 NOTREACHED() << "urlmon is not yet loaded. Error: " << GetLastError();
72 return false;
73 }
74
75 typedef HRESULT (WINAPI* DllGetClassObject_Fn)(REFCLSID, REFIID, LPVOID*);
76 DllGetClassObject_Fn fn = reinterpret_cast<DllGetClassObject_Fn>(
77 ::GetProcAddress(module, "DllGetClassObject"));
78 if (!fn) {
79 NOTREACHED() << "DllGetClassObject not found in urlmon.dll";
80 return false;
81 }
82
83 ScopedComPtr<IClassFactory> protocol_class_factory;
84 HRESULT hr = fn(handler_clsid, IID_IClassFactory,
85 reinterpret_cast<LPVOID*>(protocol_class_factory.Receive()));
86 if (FAILED(hr)) {
87 NOTREACHED() << "DllGetclassObject failed. Error: " << hr;
88 return false;
89 }
90
91 ScopedComPtr<IInternetProtocol> handler_instance;
92 hr = protocol_class_factory->CreateInstance(NULL, IID_IInternetProtocol,
93 reinterpret_cast<void**>(handler_instance.Receive()));
94 if (FAILED(hr)) {
95 NOTREACHED() << "ClassFactory::CreateInstance failed for InternetProtocol."
96 << " Error: " << hr;
97 return false;
98 }
99
100 ScopedComPtr<IInternetProtocolEx> ipex;
101 ipex.QueryFrom(handler_instance);
102 if (ipex) {
103 vtable_patch::PatchInterfaceMethods(ipex, IInternetProtocolEx_PatchInfo);
104 } else {
105 vtable_patch::PatchInterfaceMethods(handler_instance,
106 IInternetProtocol_PatchInfo);
107 }
108
109 return true;
110 }
111
112 // IInternetProtocol/Ex method implementation.
113 HRESULT ProtocolSinkWrap::OnStart(InternetProtocol_Start_Fn orig_start,
114 IInternetProtocol* protocol, LPCWSTR url, IInternetProtocolSink* prot_sink,
115 IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved) {
116 DCHECK(orig_start);
117 DLOG_IF(INFO, url != NULL) << "OnStart: " << url;
118
119 ScopedComPtr<IInternetProtocolSink> sink_to_use(MaybeWrapSink(protocol,
120 prot_sink, url));
121 return orig_start(protocol, url, sink_to_use, bind_info, flags, reserved);
122 }
123
124 HRESULT ProtocolSinkWrap::OnStartEx(InternetProtocol_StartEx_Fn orig_start_ex,
125 IInternetProtocolEx* protocol, IUri* uri, IInternetProtocolSink* prot_sink,
126 IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved) {
127 DCHECK(orig_start_ex);
128
129 ScopedBstr url;
130 uri->GetPropertyBSTR(Uri_PROPERTY_ABSOLUTE_URI, url.Receive(), 0);
131 DLOG_IF(INFO, url != NULL) << "OnStartEx: " << url;
132
133 ScopedComPtr<IInternetProtocolSink> sink_to_use(MaybeWrapSink(protocol,
134 prot_sink, url));
135 return orig_start_ex(protocol, uri, sink_to_use, bind_info, flags, reserved);
136 }
137
138 HRESULT ProtocolSinkWrap::OnRead(InternetProtocol_Read_Fn orig_read,
139 IInternetProtocol* protocol, void* buffer, ULONG size, ULONG* size_read) {
140 DCHECK(orig_read);
141
142 scoped_refptr<ProtocolSinkWrap> instance =
143 ProtocolSinkWrap::InstanceFromProtocol(protocol);
144 HRESULT hr;
145 if (instance) {
146 DCHECK(instance->protocol_ == protocol);
147 hr = instance->OnReadImpl(buffer, size, size_read, orig_read);
148 } else {
149 hr = orig_read(protocol, buffer, size, size_read);
150 }
151
152 return hr;
153 }
154
155 bool ProtocolSinkWrap::Initialize(IInternetProtocol* protocol,
156 IInternetProtocolSink* original_sink, const wchar_t* url) {
157 DCHECK(original_sink);
158 delegate_ = original_sink;
159 protocol_ = protocol;
160 if (url)
161 url_ = url;
162
163 CComCritSecLock<CComAutoCriticalSection> lock(sink_map_lock_);
164 DCHECK(sink_map_.end() == sink_map_.find(protocol));
165 sink_map_[protocol] = this;
166 DLOG(INFO) << "ProtocolSinkWrap: active sinks: " << sink_map_.size();
167 return true;
168 }
169
170 HRESULT WINAPI ProtocolSinkWrap::CheckOutgoingInterface(void* obj,
171 REFIID iid, LPVOID* ret, DWORD cookie) {
172 ProtocolSinkWrap* instance = reinterpret_cast<ProtocolSinkWrap*>(obj);
173 HRESULT hr = E_NOINTERFACE;
174 if (instance && instance->delegate_)
175 hr = instance->delegate_->QueryInterface(iid, ret);
176
177 #ifndef NDEBUG
178 if (SUCCEEDED(hr)) {
179 wchar_t iid_string[64] = {0};
180 StringFromGUID2(iid, iid_string, arraysize(iid_string));
181 DLOG(INFO) << "Giving out wrapped interface: " << iid_string;
182 }
183 #endif
184
185 return hr;
186 }
187
188 HRESULT WINAPI ProtocolSinkWrap::IfDelegateSupports(void* obj,
189 REFIID iid, LPVOID* ret, DWORD cookie) {
190 HRESULT hr = E_NOINTERFACE;
191 ProtocolSinkWrap* instance = reinterpret_cast<ProtocolSinkWrap*>(obj);
192 if (instance && instance->delegate_) {
193 ScopedComPtr<IUnknown> original;
194 hr = instance->delegate_->QueryInterface(iid,
195 reinterpret_cast<void**>(original.Receive()));
196 if (original) {
197 IUnknown* supported_interface = reinterpret_cast<IUnknown*>(
198 reinterpret_cast<DWORD_PTR>(obj) + cookie);
199 supported_interface->AddRef();
200 *ret = supported_interface;
201 hr = S_OK;
202 }
203 }
204
205 return hr;
206 }
207
208 // IInternetProtocolSink methods
209 STDMETHODIMP ProtocolSinkWrap::Switch(PROTOCOLDATA* protocol_data) {
210 HRESULT hr = E_FAIL;
211 if (delegate_)
212 hr = delegate_->Switch(protocol_data);
213 return hr;
214 }
215
216 STDMETHODIMP ProtocolSinkWrap::ReportProgress(ULONG status_code,
217 LPCWSTR status_text) {
218 DLOG(INFO) << "ProtocolSinkWrap::ReportProgress: Code:" << status_code <<
219 " Text: " << (status_text ? status_text : L"");
220 if ((BINDSTATUS_MIMETYPEAVAILABLE == status_code) ||
221 (BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE == status_code)) {
222 // If we have a MIMETYPE and that MIMETYPE is not "text/html". we don't
223 // want to do anything with this.
224 if (status_text) {
225 size_t status_text_length = lstrlenW(status_text);
226 const wchar_t* status_text_end = status_text + std::min(
227 status_text_length, arraysize(kTextHtmlMimeType) - 1);
228 if (!LowerCaseEqualsASCII(status_text, status_text_end,
229 kTextHtmlMimeType)) {
230 renderer_type_ = OTHER;
231 }
232 }
233 }
234
235 HRESULT hr = E_FAIL;
236 if (delegate_)
237 hr = delegate_->ReportProgress(status_code, status_text);
238 return hr;
239 }
240
241 STDMETHODIMP ProtocolSinkWrap::ReportData(DWORD flags, ULONG progress,
242 ULONG max_progress) {
243 DCHECK(protocol_);
244 DCHECK(delegate_);
245 DLOG(INFO) << "ProtocolSinkWrap::ReportData: flags: " << flags <<
246 " progress: " << progress << " progress_max: " << max_progress;
247
248 scoped_refptr<ProtocolSinkWrap> self_ref(this);
249
250 // Maintain a stack depth to make a determination. ReportData is called
251 // recursively in IE8. If the request can be served in a single Read, the
252 // situation ends up like this:
253 // orig_prot
254 // |--> ProtocolSinkWrap::ReportData (BSCF_FIRSTDATANOTIFICATION)
255 // |--> orig_prot->Read(...) - 1st read - S_OK and data
256 // |--> ProtocolSinkWrap::ReportData (BSCF_LASTDATANOTIFICATION)
257 // |--> orig_prot->Read(...) - 2nd read S_FALSE, 0 bytes
258 //
259 // Inner call returns S_FALSE and no data. We try to make a determination
260 // of render type then and incorrectly set it to 'OTHER' as we don't have
261 // any data yet. However, we can make a determination in the context of
262 // outer ReportData since the first read will return S_OK with data. Then
263 // the next Read in the loop will return S_FALSE and we will enter the
264 // determination logic.
265
266 // NOTE: We use the report_data_recursiveness_ variable to detect situations
267 // in which calls to ReportData are re-entrant (such as when the entire
268 // contents of a page fit inside a single packet). In these cases, we
269 // don't care about re-entrant calls beyond the second, and so we compare
270 // report_data_recursiveness_ inside the while loop, making sure we skip
271 // what would otherwise be spurious calls to ReportProgress().
272 report_data_recursiveness_++;
273
274 HRESULT hr = S_OK;
275 if (is_undetermined()) {
276 HRESULT hr_read = S_OK;
277 while (hr_read == S_OK) {
278 ULONG size_read = 0;
279 hr_read = protocol_->Read(buffer_ + buffer_size_,
280 kMaxContentSniffLength - buffer_size_, &size_read);
281 buffer_size_ += size_read;
282
283 // Attempt to determine the renderer type if we have received
284 // sufficient data. Do not attempt this when we are called recursively.
285 if (report_data_recursiveness_ < 2 && (S_FALSE == hr_read) ||
286 (buffer_size_ >= kMaxContentSniffLength)) {
287 DetermineRendererType();
288 if (renderer_type() == CHROME) {
289 // Workaround for IE 8 and "nosniff". See:
290 // http://blogs.msdn.com/ie/archive/2008/09/02/ie8-security-part-vi-be ta-2-update.aspx
291 delegate_->ReportProgress(
292 BINDSTATUS_SERVER_MIMETYPEAVAILABLE, kChromeMimeType);
293 // For IE < 8.
294 delegate_->ReportProgress(
295 BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, kChromeMimeType);
296
297 delegate_->ReportData(
298 BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE, 0, 0);
299 }
300 break;
301 }
302 }
303 }
304
305 // we call original only if the renderer type is other
306 if (renderer_type() == OTHER) {
307 hr = delegate_->ReportData(flags, progress, max_progress);
308
309 if (is_saved_result_) {
310 is_saved_result_ = false;
311 delegate_->ReportResult(result_code_, result_error_,
312 result_text_.c_str());
313 }
314 }
315
316 report_data_recursiveness_--;
317 return hr;
318 }
319
320 STDMETHODIMP ProtocolSinkWrap::ReportResult(HRESULT result, DWORD error,
321 LPCWSTR result_text) {
322 DLOG(INFO) << "ProtocolSinkWrap::ReportResult: result: " << result <<
323 " error: " << error << " Text: " << (result_text ? result_text : L"");
324
325 // If this request failed, we don't want to have anything to do with this.
326 if (FAILED(result))
327 renderer_type_ = OTHER;
328
329 // if we are still not sure about the renderer type, cache the result,
330 // othewise urlmon will get confused about getting reported about a
331 // success result for which it never received any data.
332 if (is_undetermined()) {
333 is_saved_result_ = true;
334 result_code_ = result;
335 result_error_ = error;
336 if (result_text)
337 result_text_ = result_text;
338 return S_OK;
339 }
340
341 HRESULT hr = E_FAIL;
342 if (delegate_)
343 hr = delegate_->ReportResult(result, error, result_text);
344
345 return hr;
346 }
347
348 // IInternetBindInfoEx
349 STDMETHODIMP ProtocolSinkWrap::GetBindInfo(
350 DWORD* flags, BINDINFO* bind_info_ret) {
351 ScopedComPtr<IInternetBindInfo> bind_info;
352 HRESULT hr = bind_info.QueryFrom(delegate_);
353 if (bind_info)
354 hr = bind_info->GetBindInfo(flags, bind_info_ret);
355 return hr;
356 }
357
358 STDMETHODIMP ProtocolSinkWrap::GetBindString(ULONG string_type,
359 LPOLESTR* string_array, ULONG array_size, ULONG* size_returned) {
360 ScopedComPtr<IInternetBindInfo> bind_info;
361 HRESULT hr = bind_info.QueryFrom(delegate_);
362 if (bind_info)
363 hr = bind_info->GetBindString(string_type, string_array,
364 array_size, size_returned);
365 return hr;
366 }
367
368 STDMETHODIMP ProtocolSinkWrap::GetBindInfoEx(DWORD *flags, BINDINFO* bind_info,
369 DWORD* bindf2, DWORD *reserved) {
370 ScopedComPtr<IInternetBindInfoEx> bind_info_ex;
371 HRESULT hr = bind_info_ex.QueryFrom(delegate_);
372 if (bind_info_ex)
373 hr = bind_info_ex->GetBindInfoEx(flags, bind_info, bindf2, reserved);
374 return hr;
375 }
376
377 // IServiceProvider
378 STDMETHODIMP ProtocolSinkWrap::QueryService(REFGUID service_guid,
379 REFIID riid, void** service) {
380 ScopedComPtr<IServiceProvider> service_provider;
381 HRESULT hr = service_provider.QueryFrom(delegate_);
382 if (service_provider)
383 hr = service_provider->QueryService(service_guid, riid, service);
384 return hr;
385 }
386
387 // IAuthenticate
388 STDMETHODIMP ProtocolSinkWrap::Authenticate(HWND* window,
389 LPWSTR* user_name, LPWSTR* password) {
390 ScopedComPtr<IAuthenticate> authenticate;
391 HRESULT hr = authenticate.QueryFrom(delegate_);
392 if (authenticate)
393 hr = authenticate->Authenticate(window, user_name, password);
394 return hr;
395 }
396
397 // IInternetProtocolEx
398 STDMETHODIMP ProtocolSinkWrap::Start(LPCWSTR url,
399 IInternetProtocolSink *protocol_sink, IInternetBindInfo* bind_info,
400 DWORD flags, HANDLE_PTR reserved) {
401 ScopedComPtr<IInternetProtocolRoot> protocol;
402 HRESULT hr = protocol.QueryFrom(delegate_);
403 if (protocol)
404 hr = protocol->Start(url, protocol_sink, bind_info, flags, reserved);
405 return hr;
406 }
407
408 STDMETHODIMP ProtocolSinkWrap::Continue(PROTOCOLDATA* protocol_data) {
409 ScopedComPtr<IInternetProtocolRoot> protocol;
410 HRESULT hr = protocol.QueryFrom(delegate_);
411 if (protocol)
412 hr = protocol->Continue(protocol_data);
413 return hr;
414 }
415
416 STDMETHODIMP ProtocolSinkWrap::Abort(HRESULT reason, DWORD options) {
417 ScopedComPtr<IInternetProtocolRoot> protocol;
418 HRESULT hr = protocol.QueryFrom(delegate_);
419 if (protocol)
420 hr = protocol->Abort(reason, options);
421 return hr;
422 }
423
424 STDMETHODIMP ProtocolSinkWrap::Terminate(DWORD options) {
425 ScopedComPtr<IInternetProtocolRoot> protocol;
426 HRESULT hr = protocol.QueryFrom(delegate_);
427 if (protocol)
428 hr = protocol->Terminate(options);
429 return hr;
430 }
431
432 STDMETHODIMP ProtocolSinkWrap::Suspend() {
433 ScopedComPtr<IInternetProtocolRoot> protocol;
434 HRESULT hr = protocol.QueryFrom(delegate_);
435 if (protocol)
436 hr = protocol->Suspend();
437 return hr;
438 }
439
440 STDMETHODIMP ProtocolSinkWrap::Resume() {
441 ScopedComPtr<IInternetProtocolRoot> protocol;
442 HRESULT hr = protocol.QueryFrom(delegate_);
443 if (protocol)
444 hr = protocol->Resume();
445 return hr;
446 }
447
448 STDMETHODIMP ProtocolSinkWrap::Read(void *buffer, ULONG size,
449 ULONG* size_read) {
450 ScopedComPtr<IInternetProtocol> protocol;
451 HRESULT hr = protocol.QueryFrom(delegate_);
452 if (protocol)
453 hr = protocol->Read(buffer, size, size_read);
454 return hr;
455 }
456
457 STDMETHODIMP ProtocolSinkWrap::Seek(LARGE_INTEGER move, DWORD origin,
458 ULARGE_INTEGER* new_pos) {
459 ScopedComPtr<IInternetProtocol> protocol;
460 HRESULT hr = protocol.QueryFrom(delegate_);
461 if (protocol)
462 hr = protocol->Seek(move, origin, new_pos);
463 return hr;
464 }
465
466 STDMETHODIMP ProtocolSinkWrap::LockRequest(DWORD options) {
467 ScopedComPtr<IInternetProtocol> protocol;
468 HRESULT hr = protocol.QueryFrom(delegate_);
469 if (protocol)
470 hr = protocol->LockRequest(options);
471 return hr;
472 }
473
474 STDMETHODIMP ProtocolSinkWrap::UnlockRequest() {
475 ScopedComPtr<IInternetProtocol> protocol;
476 HRESULT hr = protocol.QueryFrom(delegate_);
477 if (protocol)
478 hr = protocol->UnlockRequest();
479 return hr;
480 }
481
482 STDMETHODIMP ProtocolSinkWrap::StartEx(IUri* uri,
483 IInternetProtocolSink* protocol_sink, IInternetBindInfo* bind_info,
484 DWORD flags, HANDLE_PTR reserved) {
485 ScopedComPtr<IInternetProtocolEx> protocol;
486 HRESULT hr = protocol.QueryFrom(delegate_);
487 if (protocol)
488 hr = protocol->StartEx(uri, protocol_sink, bind_info, flags, reserved);
489 return hr;
490 }
491
492 // IInternetPriority
493 STDMETHODIMP ProtocolSinkWrap::SetPriority(LONG priority) {
494 ScopedComPtr<IInternetPriority> internet_priority;
495 HRESULT hr = internet_priority.QueryFrom(delegate_);
496 if (internet_priority)
497 hr = internet_priority->SetPriority(priority);
498 return hr;
499 }
500
501 STDMETHODIMP ProtocolSinkWrap::GetPriority(LONG* priority) {
502 ScopedComPtr<IInternetPriority> internet_priority;
503 HRESULT hr = internet_priority.QueryFrom(delegate_);
504 if (internet_priority)
505 hr = internet_priority->GetPriority(priority);
506 return hr;
507 }
508
509 // IWrappedProtocol
510 STDMETHODIMP ProtocolSinkWrap::GetWrapperCode(LONG *code, DWORD_PTR reserved) {
511 ScopedComPtr<IWrappedProtocol> wrapped_protocol;
512 HRESULT hr = wrapped_protocol.QueryFrom(delegate_);
513 if (wrapped_protocol)
514 hr = wrapped_protocol->GetWrapperCode(code, reserved);
515 return hr;
516 }
517
518
519 // public IUriContainer
520 STDMETHODIMP ProtocolSinkWrap::GetIUri(IUri** uri) {
521 ScopedComPtr<IUriContainer> uri_container;
522 HRESULT hr = uri_container.QueryFrom(delegate_);
523 if (uri_container)
524 hr = uri_container->GetIUri(uri);
525 return hr;
526 }
527
528 // Protected helpers
529
530 void ProtocolSinkWrap::DetermineRendererType() {
531 if (is_undetermined()) {
532 if (IsOptInUrl(url_.c_str())) {
533 renderer_type_ = CHROME;
534 } else {
535 std::wstring xua_compat_content;
536 // Note that document_contents_ may have NULL characters in it. While
537 // browsers may handle this properly, we don't and will stop scanning for
538 // the XUACompat content value if we encounter one.
539 DCHECK(buffer_size_ < arraysize(buffer_));
540 buffer_[buffer_size_] = 0;
541 std::wstring html_contents;
542 // TODO(joshia): detect and handle different content encodings
543 UTF8ToWide(buffer_, buffer_size_, &html_contents);
544 UtilGetXUACompatContentValue(html_contents, &xua_compat_content);
545 if (StrStrI(xua_compat_content.c_str(), kChromeContentPrefix)) {
546 renderer_type_ = CHROME;
547 } else {
548 renderer_type_ = OTHER;
549 }
550 }
551 }
552 }
553
554 HRESULT ProtocolSinkWrap::OnReadImpl(void* buffer, ULONG size, ULONG* size_read,
555 InternetProtocol_Read_Fn orig_read) {
556 // We want to switch the renderer to chrome, we cannot return any
557 // data now.
558 if (CHROME == renderer_type())
559 return S_FALSE;
560
561 // Serve data from our buffer first.
562 if (OTHER == renderer_type()) {
563 const ULONG bytes_to_copy = std::min(buffer_size_ - buffer_pos_, size);
564 if (bytes_to_copy) {
565 memcpy(buffer, buffer_ + buffer_pos_, bytes_to_copy);
566 *size_read = bytes_to_copy;
567 buffer_pos_ += bytes_to_copy;
568 return S_OK;
569 }
570 }
571
572 return orig_read(protocol_, buffer, size, size_read);
573 }
574
575 scoped_refptr<ProtocolSinkWrap> ProtocolSinkWrap::InstanceFromProtocol(
576 IInternetProtocol* protocol) {
577 CComCritSecLock<CComAutoCriticalSection> lock(sink_map_lock_);
578 scoped_refptr<ProtocolSinkWrap> instance;
579 ProtocolSinkMap::iterator it = sink_map_.find(protocol);
580 if (sink_map_.end() != it)
581 instance = it->second;
582 return instance;
583 }
584
585 HRESULT ProtocolSinkWrap::WebBrowserFromProtocolSink(
586 IInternetProtocolSink* sink, IWebBrowser2** web_browser) {
587 // TODO(tommi): GUID_NULL doesn't work when loading from history.
588 // asking for IID_IHttpNegotiate as the service id works, but
589 // getting the IWebBrowser2 interface still doesn't work.
590 ScopedComPtr<IHttpNegotiate> http_negotiate;
591 HRESULT hr = DoQueryService(GUID_NULL, sink, http_negotiate.Receive());
592 if (http_negotiate)
593 hr = DoQueryService(IID_ITargetFrame2, http_negotiate, web_browser);
594
595 return hr;
596 }
597
598 ScopedComPtr<IInternetProtocolSink> ProtocolSinkWrap::MaybeWrapSink(
599 IInternetProtocol* protocol, IInternetProtocolSink* prot_sink,
600 const wchar_t* url) {
601 ScopedComPtr<IInternetProtocolSink> sink_to_use;
602 sink_to_use.QueryFrom(prot_sink);
603 ScopedComPtr<IWebBrowser2> web_browser;
604 WebBrowserFromProtocolSink(prot_sink, web_browser.Receive());
605 if (web_browser) {
606 CComObject<ProtocolSinkWrap>* wrap = NULL;
607 CComObject<ProtocolSinkWrap>::CreateInstance(&wrap);
608 DCHECK(wrap);
609 if (wrap->Initialize(protocol, prot_sink, url)) {
610 sink_to_use = wrap;
611 }
612 }
613
614 return sink_to_use;
615 }
OLDNEW
« no previous file with comments | « chrome_frame/protocol_sink_wrap.h ('k') | chrome_frame/rename_me_to_supplement.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698