| 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 |