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

Side by Side Diff: chrome_frame/protocol_sink_wrap.cc

Issue 244002: This fixes a crash in IE8 with ChromeFrame when a new tab was created. ... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 3 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/vtable_patch_manager.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
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 6
7 #include "chrome_frame/protocol_sink_wrap.h" 7 #include "chrome_frame/protocol_sink_wrap.h"
8 8
9 #include "base/scoped_bstr_win.h" 9 #include "base/scoped_bstr_win.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/registry.h" 11 #include "base/registry.h"
12 #include "base/scoped_bstr_win.h" 12 #include "base/scoped_bstr_win.h"
13 #include "base/singleton.h" 13 #include "base/singleton.h"
14 #include "base/string_util.h" 14 #include "base/string_util.h"
15 15
16 #include "chrome_frame/utils.h" 16 #include "chrome_frame/utils.h"
17 #include "chrome_frame/vtable_patch_manager.h"
18 17
19 // BINDSTATUS_SERVER_MIMETYPEAVAILABLE == 54. Introduced in IE 8, so 18 // BINDSTATUS_SERVER_MIMETYPEAVAILABLE == 54. Introduced in IE 8, so
20 // not in everyone's headers yet. See: 19 // not in everyone's headers yet. See:
21 // http://msdn.microsoft.com/en-us/library/ms775133(VS.85,loband).aspx 20 // http://msdn.microsoft.com/en-us/library/ms775133(VS.85,loband).aspx
22 #ifndef BINDSTATUS_SERVER_MIMETYPEAVAILABLE 21 #ifndef BINDSTATUS_SERVER_MIMETYPEAVAILABLE
23 #define BINDSTATUS_SERVER_MIMETYPEAVAILABLE 54 22 #define BINDSTATUS_SERVER_MIMETYPEAVAILABLE 54
24 #endif 23 #endif
25 24
26 static const wchar_t* kChromeMimeType = L"application/chromepage"; 25 static const wchar_t* kChromeMimeType = L"application/chromepage";
27 static const char kTextHtmlMimeType[] = "text/html"; 26 static const char kTextHtmlMimeType[] = "text/html";
27 const wchar_t kUrlMonDllName[] = L"urlmon.dll";
28 28
29 static const int kInternetProtocolStartIndex = 3; 29 static const int kInternetProtocolStartIndex = 3;
30 static const int kInternetProtocolReadIndex = 9; 30 static const int kInternetProtocolReadIndex = 9;
31 static const int kInternetProtocolStartExIndex = 13; 31 static const int kInternetProtocolStartExIndex = 13;
32 32
33 // TODO(ananta)
34 // We should avoid duplicate VTable declarations.
33 BEGIN_VTABLE_PATCHES(IInternetProtocol) 35 BEGIN_VTABLE_PATCHES(IInternetProtocol)
34 VTABLE_PATCH_ENTRY(kInternetProtocolStartIndex, ProtocolSinkWrap::OnStart) 36 VTABLE_PATCH_ENTRY(kInternetProtocolStartIndex, ProtocolSinkWrap::OnStart)
35 VTABLE_PATCH_ENTRY(kInternetProtocolReadIndex, ProtocolSinkWrap::OnRead) 37 VTABLE_PATCH_ENTRY(kInternetProtocolReadIndex, ProtocolSinkWrap::OnRead)
36 END_VTABLE_PATCHES() 38 END_VTABLE_PATCHES()
37 39
40 BEGIN_VTABLE_PATCHES(IInternetProtocolSecure)
41 VTABLE_PATCH_ENTRY(kInternetProtocolStartIndex, ProtocolSinkWrap::OnStart)
42 VTABLE_PATCH_ENTRY(kInternetProtocolReadIndex, ProtocolSinkWrap::OnRead)
43 END_VTABLE_PATCHES()
44
38 BEGIN_VTABLE_PATCHES(IInternetProtocolEx) 45 BEGIN_VTABLE_PATCHES(IInternetProtocolEx)
39 VTABLE_PATCH_ENTRY(kInternetProtocolStartIndex, ProtocolSinkWrap::OnStart) 46 VTABLE_PATCH_ENTRY(kInternetProtocolStartIndex, ProtocolSinkWrap::OnStart)
40 VTABLE_PATCH_ENTRY(kInternetProtocolReadIndex, ProtocolSinkWrap::OnRead) 47 VTABLE_PATCH_ENTRY(kInternetProtocolReadIndex, ProtocolSinkWrap::OnRead)
41 VTABLE_PATCH_ENTRY(kInternetProtocolStartExIndex, ProtocolSinkWrap::OnStartEx) 48 VTABLE_PATCH_ENTRY(kInternetProtocolStartExIndex, ProtocolSinkWrap::OnStartEx)
42 END_VTABLE_PATCHES() 49 END_VTABLE_PATCHES()
43 50
51 BEGIN_VTABLE_PATCHES(IInternetProtocolExSecure)
52 VTABLE_PATCH_ENTRY(kInternetProtocolStartIndex, ProtocolSinkWrap::OnStart)
53 VTABLE_PATCH_ENTRY(kInternetProtocolReadIndex, ProtocolSinkWrap::OnRead)
54 VTABLE_PATCH_ENTRY(kInternetProtocolStartExIndex, ProtocolSinkWrap::OnStartEx)
55 END_VTABLE_PATCHES()
56
44 // 57 //
45 // ProtocolSinkWrap implementation 58 // ProtocolSinkWrap implementation
46 // 59 //
47 60
48 // Static map initialization 61 // Static map initialization
49 ProtocolSinkWrap::ProtocolSinkMap ProtocolSinkWrap::sink_map_; 62 ProtocolSinkWrap::ProtocolSinkMap ProtocolSinkWrap::sink_map_;
50 CComAutoCriticalSection ProtocolSinkWrap::sink_map_lock_; 63 CComAutoCriticalSection ProtocolSinkWrap::sink_map_lock_;
51 64
52 ProtocolSinkWrap::ProtocolSinkWrap() 65 ProtocolSinkWrap::ProtocolSinkWrap()
53 : protocol_(NULL), renderer_type_(UNDETERMINED), 66 : protocol_(NULL), renderer_type_(UNDETERMINED),
54 buffer_size_(0), buffer_pos_(0), is_saved_result_(false), 67 buffer_size_(0), buffer_pos_(0), is_saved_result_(false),
55 result_code_(0), result_error_(0), report_data_recursiveness_(0) { 68 result_code_(0), result_error_(0), report_data_recursiveness_(0) {
56 memset(buffer_, 0, arraysize(buffer_)); 69 memset(buffer_, 0, arraysize(buffer_));
57 } 70 }
58 71
59 ProtocolSinkWrap::~ProtocolSinkWrap() { 72 ProtocolSinkWrap::~ProtocolSinkWrap() {
60 CComCritSecLock<CComAutoCriticalSection> lock(sink_map_lock_); 73 CComCritSecLock<CComAutoCriticalSection> lock(sink_map_lock_);
61 DCHECK(sink_map_.end() != sink_map_.find(protocol_)); 74 DCHECK(sink_map_.end() != sink_map_.find(protocol_));
62 sink_map_.erase(protocol_); 75 sink_map_.erase(protocol_);
63 protocol_ = NULL; 76 protocol_ = NULL;
64 DLOG(INFO) << "ProtocolSinkWrap: active sinks: " << sink_map_.size(); 77 DLOG(INFO) << "ProtocolSinkWrap: active sinks: " << sink_map_.size();
65 } 78 }
66 79
67 bool ProtocolSinkWrap::PatchProtocolHandler(const wchar_t* dll, 80 bool ProtocolSinkWrap::PatchProtocolHandlers() {
68 const CLSID& handler_clsid) { 81 HRESULT hr = PatchProtocolMethods(CLSID_HttpProtocol,
69 HMODULE module = ::GetModuleHandle(dll); 82 IInternetProtocol_PatchInfo,
70 if (!module) { 83 IInternetProtocolEx_PatchInfo);
71 NOTREACHED() << "urlmon is not yet loaded. Error: " << GetLastError(); 84 if (FAILED(hr)) {
85 NOTREACHED() << "Failed to patch IInternetProtocol interface."
86 << " Error: " << hr;
72 return false; 87 return false;
73 } 88 }
74 89
90 hr = PatchProtocolMethods(CLSID_HttpSProtocol,
91 IInternetProtocolSecure_PatchInfo,
92 IInternetProtocolExSecure_PatchInfo);
93 if (FAILED(hr)) {
94 NOTREACHED() << "Failed to patch IInternetProtocol secure interface."
95 << " Error: " << hr;
96 return false;
97 }
98
99 return true;
100 }
101
102 void ProtocolSinkWrap::UnpatchProtocolHandlers() {
103 vtable_patch::UnpatchInterfaceMethods(IInternetProtocol_PatchInfo);
104 vtable_patch::UnpatchInterfaceMethods(IInternetProtocolEx_PatchInfo);
105 vtable_patch::UnpatchInterfaceMethods(IInternetProtocolSecure_PatchInfo);
106 vtable_patch::UnpatchInterfaceMethods(IInternetProtocolExSecure_PatchInfo);
107 }
108
109 HRESULT ProtocolSinkWrap::CreateProtocolHandlerInstance(
110 const CLSID& clsid, IInternetProtocol** protocol) {
111 if (!protocol) {
112 return E_INVALIDARG;
113 }
114
115 HMODULE module = ::GetModuleHandle(kUrlMonDllName);
116 if (!module) {
117 NOTREACHED() << "urlmon is not yet loaded. Error: " << GetLastError();
118 return E_FAIL;
119 }
120
75 typedef HRESULT (WINAPI* DllGetClassObject_Fn)(REFCLSID, REFIID, LPVOID*); 121 typedef HRESULT (WINAPI* DllGetClassObject_Fn)(REFCLSID, REFIID, LPVOID*);
76 DllGetClassObject_Fn fn = reinterpret_cast<DllGetClassObject_Fn>( 122 DllGetClassObject_Fn fn = reinterpret_cast<DllGetClassObject_Fn>(
77 ::GetProcAddress(module, "DllGetClassObject")); 123 ::GetProcAddress(module, "DllGetClassObject"));
78 if (!fn) { 124 if (!fn) {
79 NOTREACHED() << "DllGetClassObject not found in urlmon.dll"; 125 NOTREACHED() << "DllGetClassObject not found in urlmon.dll";
80 return false; 126 return E_FAIL;
81 } 127 }
82 128
83 ScopedComPtr<IClassFactory> protocol_class_factory; 129 ScopedComPtr<IClassFactory> protocol_class_factory;
84 HRESULT hr = fn(handler_clsid, IID_IClassFactory, 130 HRESULT hr = fn(clsid, IID_IClassFactory,
85 reinterpret_cast<LPVOID*>(protocol_class_factory.Receive())); 131 reinterpret_cast<LPVOID*>(protocol_class_factory.Receive()));
86 if (FAILED(hr)) { 132 if (FAILED(hr)) {
87 NOTREACHED() << "DllGetclassObject failed. Error: " << hr; 133 NOTREACHED() << "DllGetclassObject failed. Error: " << hr;
88 return false; 134 return hr;
89 } 135 }
90 136
91 ScopedComPtr<IInternetProtocol> handler_instance; 137 ScopedComPtr<IInternetProtocol> handler_instance;
92 hr = protocol_class_factory->CreateInstance(NULL, IID_IInternetProtocol, 138 hr = protocol_class_factory->CreateInstance(NULL, IID_IInternetProtocol,
93 reinterpret_cast<void**>(handler_instance.Receive())); 139 reinterpret_cast<void**>(handler_instance.Receive()));
94 if (FAILED(hr)) { 140 if (FAILED(hr)) {
95 NOTREACHED() << "ClassFactory::CreateInstance failed for InternetProtocol." 141 NOTREACHED() << "ClassFactory::CreateInstance failed for InternetProtocol."
96 << " Error: " << hr; 142 << " Error: " << hr;
143 } else {
144 *protocol = handler_instance.Detach();
145 }
146
147 return hr;
148 }
149
150 HRESULT ProtocolSinkWrap::PatchProtocolMethods(
151 const CLSID& clsid_protocol,
152 vtable_patch::MethodPatchInfo* protocol_patch_info,
153 vtable_patch::MethodPatchInfo* protocol_ex_patch_info) {
154 if (!protocol_patch_info || !protocol_ex_patch_info) {
155 return E_INVALIDARG;
156 }
157
158 ScopedComPtr<IInternetProtocol> http_protocol;
159 HRESULT hr = CreateProtocolHandlerInstance(clsid_protocol,
160 http_protocol.Receive());
161 if (FAILED(hr)) {
162 NOTREACHED() << "ClassFactory::CreateInstance failed for InternetProtocol."
163 << " Error: " << hr;
97 return false; 164 return false;
98 } 165 }
99 166
100 ScopedComPtr<IInternetProtocolEx> ipex; 167 ScopedComPtr<IInternetProtocolEx> ipex;
101 ipex.QueryFrom(handler_instance); 168 ipex.QueryFrom(http_protocol);
102 if (ipex) { 169 if (ipex) {
103 vtable_patch::PatchInterfaceMethods(ipex, IInternetProtocolEx_PatchInfo); 170 hr = vtable_patch::PatchInterfaceMethods(ipex, protocol_ex_patch_info);
104 } else { 171 } else {
105 vtable_patch::PatchInterfaceMethods(handler_instance, 172 hr = vtable_patch::PatchInterfaceMethods(http_protocol,
106 IInternetProtocol_PatchInfo); 173 protocol_patch_info);
107 } 174 }
108 175 return hr;
109 return true;
110 } 176 }
111 177
112 // IInternetProtocol/Ex method implementation. 178 // IInternetProtocol/Ex method implementation.
113 HRESULT ProtocolSinkWrap::OnStart(InternetProtocol_Start_Fn orig_start, 179 HRESULT ProtocolSinkWrap::OnStart(InternetProtocol_Start_Fn orig_start,
114 IInternetProtocol* protocol, LPCWSTR url, IInternetProtocolSink* prot_sink, 180 IInternetProtocol* protocol, LPCWSTR url, IInternetProtocolSink* prot_sink,
115 IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved) { 181 IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved) {
116 DCHECK(orig_start); 182 DCHECK(orig_start);
117 DLOG_IF(INFO, url != NULL) << "OnStart: " << url; 183 DLOG_IF(INFO, url != NULL) << "OnStart: " << url;
118 184
119 ScopedComPtr<IInternetProtocolSink> sink_to_use(MaybeWrapSink(protocol, 185 ScopedComPtr<IInternetProtocolSink> sink_to_use(MaybeWrapSink(protocol,
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 // |--> orig_prot->Read(...) - 2nd read S_FALSE, 0 bytes 323 // |--> orig_prot->Read(...) - 2nd read S_FALSE, 0 bytes
258 // 324 //
259 // Inner call returns S_FALSE and no data. We try to make a determination 325 // 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 326 // 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 327 // 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 328 // 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 329 // the next Read in the loop will return S_FALSE and we will enter the
264 // determination logic. 330 // determination logic.
265 331
266 // NOTE: We use the report_data_recursiveness_ variable to detect situations 332 // 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 333 // 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 334 // 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 335 // 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 336 // report_data_recursiveness_ inside the while loop, making sure we skip
271 // what would otherwise be spurious calls to ReportProgress(). 337 // what would otherwise be spurious calls to ReportProgress().
272 report_data_recursiveness_++; 338 report_data_recursiveness_++;
273 339
274 HRESULT hr = S_OK; 340 HRESULT hr = S_OK;
275 if (is_undetermined()) { 341 if (is_undetermined()) {
276 HRESULT hr_read = S_OK; 342 HRESULT hr_read = S_OK;
277 while (hr_read == S_OK) { 343 while (hr_read == S_OK) {
278 ULONG size_read = 0; 344 ULONG size_read = 0;
279 hr_read = protocol_->Read(buffer_ + buffer_size_, 345 hr_read = protocol_->Read(buffer_ + buffer_size_,
280 kMaxContentSniffLength - buffer_size_, &size_read); 346 kMaxContentSniffLength - buffer_size_, &size_read);
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
606 CComObject<ProtocolSinkWrap>* wrap = NULL; 672 CComObject<ProtocolSinkWrap>* wrap = NULL;
607 CComObject<ProtocolSinkWrap>::CreateInstance(&wrap); 673 CComObject<ProtocolSinkWrap>::CreateInstance(&wrap);
608 DCHECK(wrap); 674 DCHECK(wrap);
609 if (wrap->Initialize(protocol, prot_sink, url)) { 675 if (wrap->Initialize(protocol, prot_sink, url)) {
610 sink_to_use = wrap; 676 sink_to_use = wrap;
611 } 677 }
612 } 678 }
613 679
614 return sink_to_use; 680 return sink_to_use;
615 } 681 }
OLDNEW
« no previous file with comments | « chrome_frame/protocol_sink_wrap.h ('k') | chrome_frame/vtable_patch_manager.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698