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 "chrome_frame/http_negotiate.h" | 5 #include "chrome_frame/http_negotiate.h" |
6 | 6 |
7 #include <atlbase.h> | 7 #include <atlbase.h> |
8 #include <atlcom.h> | 8 #include <atlcom.h> |
9 #include <htiframe.h> | 9 #include <htiframe.h> |
10 | 10 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 } | 86 } |
87 | 87 |
88 STDMETHOD(OnDataAvailable)(DWORD flags, DWORD size, FORMATETC* formatetc, | 88 STDMETHOD(OnDataAvailable)(DWORD flags, DWORD size, FORMATETC* formatetc, |
89 STGMEDIUM* storage) { | 89 STGMEDIUM* storage) { |
90 return E_NOTIMPL; | 90 return E_NOTIMPL; |
91 } | 91 } |
92 STDMETHOD(OnObjectAvailable)(REFIID iid, IUnknown* object) { | 92 STDMETHOD(OnObjectAvailable)(REFIID iid, IUnknown* object) { |
93 return E_NOTIMPL; | 93 return E_NOTIMPL; |
94 } | 94 } |
95 }; | 95 }; |
| 96 } // end namespace |
96 | 97 |
97 } // end namespace | 98 std::string AppendCFUserAgentString(LPCWSTR headers, |
| 99 LPCWSTR additional_headers) { |
| 100 static const char kLowerCaseUserAgent[] = "user-agent"; |
| 101 using net::HttpUtil; |
| 102 |
| 103 std::string ascii_headers; |
| 104 if (additional_headers) { |
| 105 ascii_headers = WideToASCII(additional_headers); |
| 106 } |
| 107 |
| 108 // Extract "User-Agent" from |additiona_headers| or |headers|. |
| 109 HttpUtil::HeadersIterator headers_iterator(ascii_headers.begin(), |
| 110 ascii_headers.end(), "\r\n"); |
| 111 std::string user_agent_value; |
| 112 if (headers_iterator.AdvanceTo(kLowerCaseUserAgent)) { |
| 113 user_agent_value = headers_iterator.values(); |
| 114 } else if (headers != NULL) { |
| 115 // See if there's a user-agent header specified in the original headers. |
| 116 std::string original_headers(WideToASCII(headers)); |
| 117 HttpUtil::HeadersIterator original_it(original_headers.begin(), |
| 118 original_headers.end(), "\r\n"); |
| 119 if (original_it.AdvanceTo(kLowerCaseUserAgent)) |
| 120 user_agent_value = original_it.values(); |
| 121 } |
| 122 |
| 123 // Use the default "User-Agent" if none was provided. |
| 124 if (user_agent_value.empty()) |
| 125 user_agent_value = http_utils::GetDefaultUserAgent(); |
| 126 |
| 127 // Now add chromeframe to it. |
| 128 user_agent_value = http_utils::AddChromeFrameToUserAgentValue( |
| 129 user_agent_value); |
| 130 |
| 131 // Build new headers, skip the existing user agent value from |
| 132 // existing headers. |
| 133 std::string new_headers; |
| 134 headers_iterator.Reset(); |
| 135 while (headers_iterator.GetNext()) { |
| 136 std::string name(headers_iterator.name()); |
| 137 if (!LowerCaseEqualsASCII(name, kLowerCaseUserAgent)) { |
| 138 new_headers += name + ": " + headers_iterator.values() + "\r\n"; |
| 139 } |
| 140 } |
| 141 |
| 142 new_headers += "User-Agent: " + user_agent_value; |
| 143 new_headers += "\r\n"; |
| 144 return new_headers; |
| 145 } |
98 | 146 |
99 HRESULT GetBrowserServiceFromProtocolSink(IInternetProtocolSink* sink, | 147 HRESULT GetBrowserServiceFromProtocolSink(IInternetProtocolSink* sink, |
100 IBrowserService** browser_service) { | 148 IBrowserService** browser_service) { |
101 DCHECK(browser_service); | 149 DCHECK(browser_service); |
102 // When fetching a page for the first time (not cached), we can query the | 150 // When fetching a page for the first time (not cached), we can query the |
103 // sink directly for IID_IShellBrowser to get the browser service. | 151 // sink directly for IID_IShellBrowser to get the browser service. |
104 HRESULT hr = DoQueryService(IID_IShellBrowser, sink, browser_service); | 152 HRESULT hr = DoQueryService(IID_IShellBrowser, sink, browser_service); |
105 if (FAILED(hr)) { | 153 if (FAILED(hr)) { |
106 // When the request is being served up from the cache, we have to take | 154 // When the request is being served up from the cache, we have to take |
107 // a different route via IID_ITargetFrame2. | 155 // a different route via IID_ITargetFrame2. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
166 | 214 |
167 if (http) { | 215 if (http) { |
168 hr = vtable_patch::PatchInterfaceMethods(http, IHttpNegotiate_PatchInfo); | 216 hr = vtable_patch::PatchInterfaceMethods(http, IHttpNegotiate_PatchInfo); |
169 DLOG_IF(ERROR, FAILED(hr)) | 217 DLOG_IF(ERROR, FAILED(hr)) |
170 << StringPrintf("HttpNegotiate patch failed 0x%08X", hr); | 218 << StringPrintf("HttpNegotiate patch failed 0x%08X", hr); |
171 } else { | 219 } else { |
172 DLOG(WARNING) | 220 DLOG(WARNING) |
173 << StringPrintf("IHttpNegotiate not supported 0x%08X", hr); | 221 << StringPrintf("IHttpNegotiate not supported 0x%08X", hr); |
174 } | 222 } |
175 | 223 |
176 // CTransaction patch supports sniffing HTTP headers, so no need of | 224 ScopedComPtr<IBindStatusCallback> bscb; |
177 // sniffing inside HttpNegotiatePatch::ReportProgress. | 225 hr = bscb.QueryFrom(to_patch); |
178 if (GetPatchMethod() != PATCH_METHOD_INET_PROTOCOL) { | |
179 ScopedComPtr<IBindStatusCallback> bscb; | |
180 hr = bscb.QueryFrom(to_patch); | |
181 | 226 |
182 if (bscb) { | 227 if (bscb) { |
183 hr = vtable_patch::PatchInterfaceMethods(bscb, | 228 hr = vtable_patch::PatchInterfaceMethods(bscb, |
184 IBindStatusCallback_PatchInfo); | 229 IBindStatusCallback_PatchInfo); |
185 DLOG_IF(ERROR, FAILED(hr)) | 230 DLOG_IF(ERROR, FAILED(hr)) |
186 << StringPrintf("BindStatusCallback patch failed 0x%08X", hr); | 231 << StringPrintf("BindStatusCallback patch failed 0x%08X", hr); |
187 } else { | 232 } else { |
188 DLOG(WARNING) << StringPrintf("IBindStatusCallback not supported 0x%08X", | 233 DLOG(WARNING) << StringPrintf("IBindStatusCallback not supported 0x%08X", |
189 hr); | 234 hr); |
190 } | |
191 } | 235 } |
192 return hr; | 236 return hr; |
193 } | 237 } |
194 | 238 |
195 // static | 239 // static |
196 HRESULT HttpNegotiatePatch::BeginningTransaction( | 240 HRESULT HttpNegotiatePatch::BeginningTransaction( |
197 IHttpNegotiate_BeginningTransaction_Fn original, IHttpNegotiate* me, | 241 IHttpNegotiate_BeginningTransaction_Fn original, IHttpNegotiate* me, |
198 LPCWSTR url, LPCWSTR headers, DWORD reserved, LPWSTR* additional_headers) { | 242 LPCWSTR url, LPCWSTR headers, DWORD reserved, LPWSTR* additional_headers) { |
199 DLOG(INFO) << __FUNCTION__ << " " << url << " headers:\n" << headers; | 243 DLOG(INFO) << __FUNCTION__ << " " << url << " headers:\n" << headers; |
200 | 244 |
(...skipping 25 matching lines...) Expand all Loading... |
226 mgr->set_referrer(referrer); | 270 mgr->set_referrer(referrer); |
227 } | 271 } |
228 } | 272 } |
229 } else { | 273 } else { |
230 DLOG(INFO) << "No IWebBrowser2"; | 274 DLOG(INFO) << "No IWebBrowser2"; |
231 } | 275 } |
232 } else { | 276 } else { |
233 DLOG(INFO) << "No NavigationManager"; | 277 DLOG(INFO) << "No NavigationManager"; |
234 } | 278 } |
235 | 279 |
236 static const char kLowerCaseUserAgent[] = "user-agent"; | 280 std::string updated = AppendCFUserAgentString(headers, *additional_headers); |
237 | 281 *additional_headers = reinterpret_cast<wchar_t*>(::CoTaskMemRealloc( |
238 using net::HttpUtil; | 282 *additional_headers, (updated.length() + 1) * sizeof(wchar_t))); |
239 | 283 lstrcpyW(*additional_headers, ASCIIToWide(updated).c_str()); |
240 std::string ascii_headers; | 284 return S_OK; |
241 if (*additional_headers) { | |
242 ascii_headers = WideToASCII(*additional_headers); | |
243 DLOG(INFO) << __FUNCTION__ << " additional headers: " << ascii_headers; | |
244 } | |
245 | |
246 HttpUtil::HeadersIterator headers_iterator(ascii_headers.begin(), | |
247 ascii_headers.end(), "\r\n"); | |
248 std::string user_agent_value; | |
249 if (headers_iterator.AdvanceTo(kLowerCaseUserAgent)) { | |
250 user_agent_value = headers_iterator.values(); | |
251 } else if (headers != NULL) { | |
252 // See if there's a user-agent header specified in the original headers. | |
253 std::string original_headers(WideToASCII(headers)); | |
254 HttpUtil::HeadersIterator original_it(original_headers.begin(), | |
255 original_headers.end(), "\r\n"); | |
256 if (original_it.AdvanceTo(kLowerCaseUserAgent)) | |
257 user_agent_value = original_it.values(); | |
258 } | |
259 | |
260 // Use the default one if none was provided. | |
261 if (user_agent_value.empty()) | |
262 user_agent_value = http_utils::GetDefaultUserAgent(); | |
263 | |
264 // Now add chromeframe to it. | |
265 user_agent_value = http_utils::AddChromeFrameToUserAgentValue( | |
266 user_agent_value); | |
267 | |
268 // Build new headers, skip the existing user agent value from | |
269 // existing headers. | |
270 std::string new_headers; | |
271 headers_iterator.Reset(); | |
272 while (headers_iterator.GetNext()) { | |
273 std::string name(headers_iterator.name()); | |
274 if (!LowerCaseEqualsASCII(name, kLowerCaseUserAgent)) { | |
275 new_headers += name + ": " + headers_iterator.values() + "\r\n"; | |
276 } | |
277 } | |
278 | |
279 new_headers += "User-Agent: " + user_agent_value; | |
280 new_headers += "\r\n\r\n"; | |
281 | |
282 if (*additional_headers) | |
283 ::CoTaskMemFree(*additional_headers); | |
284 *additional_headers = reinterpret_cast<wchar_t*>(::CoTaskMemAlloc( | |
285 (new_headers.length() + 1) * sizeof(wchar_t))); | |
286 lstrcpyW(*additional_headers, ASCIIToWide(new_headers).c_str()); | |
287 | |
288 return hr; | |
289 } | 285 } |
290 | 286 |
291 // static | 287 // static |
292 HRESULT HttpNegotiatePatch::StartBinding( | 288 HRESULT HttpNegotiatePatch::StartBinding( |
293 IBindStatusCallback_StartBinding_Fn original, | 289 IBindStatusCallback_StartBinding_Fn original, |
294 IBindStatusCallback* me, DWORD reserved, IBinding* binding) { | 290 IBindStatusCallback* me, DWORD reserved, IBinding* binding) { |
295 ScopedComPtr<IBinding> local_binding(binding); | 291 ScopedComPtr<IBinding> local_binding(binding); |
296 ScopedComPtr<IInternetProtocolSink> protocol_sink; | 292 ScopedComPtr<IInternetProtocolSink> protocol_sink; |
297 | 293 |
298 HRESULT hr = protocol_sink.QueryFrom(local_binding); | 294 HRESULT hr = protocol_sink.QueryFrom(local_binding); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 // Note that this avoids having the VEH report a crash if an SEH earlier in | 397 // Note that this avoids having the VEH report a crash if an SEH earlier in |
402 // the chain handles the exception. | 398 // the chain handles the exception. |
403 ExceptionBarrier barrier; | 399 ExceptionBarrier barrier; |
404 return original(me, status_code, status_text); | 400 return original(me, status_code, status_text); |
405 } else { | 401 } else { |
406 // Only report exceptions caused within ChromeFrame in this context. | 402 // Only report exceptions caused within ChromeFrame in this context. |
407 ExceptionBarrierReportOnlyModule barrier; | 403 ExceptionBarrierReportOnlyModule barrier; |
408 return original(me, status_code, status_text); | 404 return original(me, status_code, status_text); |
409 } | 405 } |
410 } | 406 } |
| 407 |
| 408 STDMETHODIMP UserAgentAddOn::BeginningTransaction(LPCWSTR url, LPCWSTR headers, |
| 409 DWORD reserved, |
| 410 LPWSTR* additional_headers) { |
| 411 HRESULT hr = S_OK; |
| 412 if (delegate_) { |
| 413 hr = delegate_->BeginningTransaction(url, headers, reserved, |
| 414 additional_headers); |
| 415 } |
| 416 |
| 417 if (hr == S_OK) { |
| 418 // Add "chromeframe" user-agent string. |
| 419 std::string updated_headers = AppendCFUserAgentString(headers, |
| 420 *additional_headers); |
| 421 *additional_headers = reinterpret_cast<wchar_t*>(::CoTaskMemRealloc( |
| 422 *additional_headers, (updated_headers.length() + 1) * sizeof(wchar_t))); |
| 423 lstrcpyW(*additional_headers, ASCIIToWide(updated_headers).c_str()); |
| 424 } |
| 425 return hr; |
| 426 } |
| 427 |
| 428 STDMETHODIMP UserAgentAddOn::OnResponse(DWORD response_code, |
| 429 LPCWSTR response_headers, LPCWSTR request_headers, |
| 430 LPWSTR* additional_headers) { |
| 431 HRESULT hr = S_OK; |
| 432 if (delegate_) { |
| 433 hr = delegate_->OnResponse(response_code, response_headers, request_headers, |
| 434 additional_headers); |
| 435 } |
| 436 return hr; |
| 437 } |
OLD | NEW |