| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 } | 74 } |
| 75 | 75 |
| 76 STDMETHOD(OnDataAvailable)(DWORD flags, DWORD size, FORMATETC* formatetc, | 76 STDMETHOD(OnDataAvailable)(DWORD flags, DWORD size, FORMATETC* formatetc, |
| 77 STGMEDIUM* storage) { | 77 STGMEDIUM* storage) { |
| 78 return E_NOTIMPL; | 78 return E_NOTIMPL; |
| 79 } | 79 } |
| 80 STDMETHOD(OnObjectAvailable)(REFIID iid, IUnknown* object) { | 80 STDMETHOD(OnObjectAvailable)(REFIID iid, IUnknown* object) { |
| 81 return E_NOTIMPL; | 81 return E_NOTIMPL; |
| 82 } | 82 } |
| 83 }; | 83 }; |
| 84 } // end namespace | |
| 85 | 84 |
| 86 std::string AppendCFUserAgentString(LPCWSTR headers, | 85 // Returns the full user agent header from the HTTP header strings passed to |
| 86 // IHttpNegotiate::BeginningTransaction. Looks first in |additional_headers| |
| 87 // and if it can't be found there looks in |headers|. |
| 88 std::string GetUserAgentFromHeaders(LPCWSTR headers, |
| 87 LPCWSTR additional_headers) { | 89 LPCWSTR additional_headers) { |
| 88 using net::HttpUtil; | 90 using net::HttpUtil; |
| 89 | 91 |
| 90 std::string ascii_headers; | 92 std::string ascii_headers; |
| 91 if (additional_headers) { | 93 if (additional_headers) { |
| 92 ascii_headers = WideToASCII(additional_headers); | 94 ascii_headers = WideToASCII(additional_headers); |
| 93 } | 95 } |
| 94 | 96 |
| 95 // Extract "User-Agent" from |additional_headers| or |headers|. | 97 // Extract "User-Agent" from |additional_headers| or |headers|. |
| 96 HttpUtil::HeadersIterator headers_iterator(ascii_headers.begin(), | 98 HttpUtil::HeadersIterator headers_iterator(ascii_headers.begin(), |
| 97 ascii_headers.end(), "\r\n"); | 99 ascii_headers.end(), "\r\n"); |
| 98 std::string user_agent_value; | 100 std::string user_agent_value; |
| 99 if (headers_iterator.AdvanceTo(kLowerCaseUserAgent)) { | 101 if (headers_iterator.AdvanceTo(kLowerCaseUserAgent)) { |
| 100 user_agent_value = headers_iterator.values(); | 102 user_agent_value = headers_iterator.values(); |
| 101 } else if (headers != NULL) { | 103 } else if (headers != NULL) { |
| 102 // See if there's a user-agent header specified in the original headers. | 104 // See if there's a user-agent header specified in the original headers. |
| 103 std::string original_headers(WideToASCII(headers)); | 105 std::string original_headers(WideToASCII(headers)); |
| 104 HttpUtil::HeadersIterator original_it(original_headers.begin(), | 106 HttpUtil::HeadersIterator original_it(original_headers.begin(), |
| 105 original_headers.end(), "\r\n"); | 107 original_headers.end(), "\r\n"); |
| 106 if (original_it.AdvanceTo(kLowerCaseUserAgent)) | 108 if (original_it.AdvanceTo(kLowerCaseUserAgent)) |
| 107 user_agent_value = original_it.values(); | 109 user_agent_value = original_it.values(); |
| 108 } | 110 } |
| 109 | 111 |
| 112 return user_agent_value; |
| 113 } |
| 114 |
| 115 // Removes the named header |field| from a set of headers. |field| must be |
| 116 // lower-case. |
| 117 std::string ExcludeFieldFromHeaders(const std::string& old_headers, |
| 118 const char* field) { |
| 119 using net::HttpUtil; |
| 120 std::string new_headers; |
| 121 new_headers.reserve(old_headers.size()); |
| 122 HttpUtil::HeadersIterator headers_iterator(old_headers.begin(), |
| 123 old_headers.end(), "\r\n"); |
| 124 while (headers_iterator.GetNext()) { |
| 125 if (!LowerCaseEqualsASCII(headers_iterator.name_begin(), |
| 126 headers_iterator.name_end(), |
| 127 field)) { |
| 128 new_headers.append(headers_iterator.name_begin(), |
| 129 headers_iterator.name_end()); |
| 130 new_headers += ": "; |
| 131 new_headers.append(headers_iterator.values_begin(), |
| 132 headers_iterator.values_end()); |
| 133 new_headers += "\r\n"; |
| 134 } |
| 135 } |
| 136 |
| 137 return new_headers; |
| 138 } |
| 139 |
| 140 std::string MutateCFUserAgentString(LPCWSTR headers, |
| 141 LPCWSTR additional_headers, |
| 142 bool add_user_agent) { |
| 143 std::string user_agent_value(GetUserAgentFromHeaders(headers, |
| 144 additional_headers)); |
| 145 |
| 110 // Use the default "User-Agent" if none was provided. | 146 // Use the default "User-Agent" if none was provided. |
| 111 if (user_agent_value.empty()) | 147 if (user_agent_value.empty()) |
| 112 user_agent_value = http_utils::GetDefaultUserAgent(); | 148 user_agent_value = http_utils::GetDefaultUserAgent(); |
| 113 | 149 |
| 114 // Now add chromeframe to it. | 150 // Now add chromeframe to it. |
| 115 user_agent_value = http_utils::AddChromeFrameToUserAgentValue( | 151 user_agent_value = add_user_agent ? |
| 116 user_agent_value); | 152 http_utils::AddChromeFrameToUserAgentValue(user_agent_value) : |
| 153 http_utils::RemoveChromeFrameFromUserAgentValue(user_agent_value); |
| 117 | 154 |
| 118 // Build new headers, skip the existing user agent value from | 155 // Build a new set of additional headers, skipping the existing user agent |
| 119 // existing headers. | 156 // value if present. |
| 157 return ReplaceOrAddUserAgent(additional_headers, user_agent_value); |
| 158 } |
| 159 |
| 160 } // end namespace |
| 161 |
| 162 |
| 163 std::string AppendCFUserAgentString(LPCWSTR headers, |
| 164 LPCWSTR additional_headers) { |
| 165 return MutateCFUserAgentString(headers, additional_headers, true); |
| 166 } |
| 167 |
| 168 |
| 169 // Looks for a user agent header found in |headers| or |additional_headers| |
| 170 // then returns |additional_headers| with a modified user agent header that does |
| 171 // not include the chromeframe token. |
| 172 std::string RemoveCFUserAgentString(LPCWSTR headers, |
| 173 LPCWSTR additional_headers) { |
| 174 return MutateCFUserAgentString(headers, additional_headers, false); |
| 175 } |
| 176 |
| 177 |
| 178 // Unconditionally adds the specified |user_agent_value| to the given set of |
| 179 // |headers|, removing any that were already there. |
| 180 std::string ReplaceOrAddUserAgent(LPCWSTR headers, |
| 181 const std::string& user_agent_value) { |
| 120 std::string new_headers; | 182 std::string new_headers; |
| 121 headers_iterator.Reset(); | 183 if (headers) { |
| 122 while (headers_iterator.GetNext()) { | 184 std::string ascii_headers(WideToASCII(headers)); |
| 123 std::string name(headers_iterator.name()); | 185 // Build new headers, skip the existing user agent value from |
| 124 if (!LowerCaseEqualsASCII(name, kLowerCaseUserAgent)) { | 186 // existing headers. |
| 125 new_headers += name + ": " + headers_iterator.values() + "\r\n"; | 187 new_headers = ExcludeFieldFromHeaders(ascii_headers, kLowerCaseUserAgent); |
| 126 } | |
| 127 } | 188 } |
| 128 | 189 new_headers += "User-Agent: "; |
| 129 new_headers += "User-Agent: " + user_agent_value; | 190 new_headers += user_agent_value; |
| 130 new_headers += "\r\n"; | 191 new_headers += "\r\n"; |
| 131 return new_headers; | 192 return new_headers; |
| 132 } | 193 } |
| 133 | |
| 134 std::string ReplaceOrAddUserAgent(LPCWSTR headers, | |
| 135 const std::string& user_agent_value) { | |
| 136 using net::HttpUtil; | |
| 137 | |
| 138 std::string new_headers; | |
| 139 if (headers) { | |
| 140 std::string ascii_headers(WideToASCII(headers)); | |
| 141 | |
| 142 // Extract "User-Agent" from the headers. | |
| 143 HttpUtil::HeadersIterator headers_iterator(ascii_headers.begin(), | |
| 144 ascii_headers.end(), "\r\n"); | |
| 145 | |
| 146 // Build new headers, skip the existing user agent value from | |
| 147 // existing headers. | |
| 148 while (headers_iterator.GetNext()) { | |
| 149 std::string name(headers_iterator.name()); | |
| 150 if (!LowerCaseEqualsASCII(name, kLowerCaseUserAgent)) { | |
| 151 new_headers += name + ": " + headers_iterator.values() + "\r\n"; | |
| 152 } | |
| 153 } | |
| 154 } | |
| 155 new_headers += "User-Agent: " + user_agent_value; | |
| 156 new_headers += "\r\n"; | |
| 157 return new_headers; | |
| 158 } | |
| 159 | 194 |
| 160 HttpNegotiatePatch::HttpNegotiatePatch() { | 195 HttpNegotiatePatch::HttpNegotiatePatch() { |
| 161 } | 196 } |
| 162 | 197 |
| 163 HttpNegotiatePatch::~HttpNegotiatePatch() { | 198 HttpNegotiatePatch::~HttpNegotiatePatch() { |
| 164 } | 199 } |
| 165 | 200 |
| 166 // static | 201 // static |
| 167 bool HttpNegotiatePatch::Initialize() { | 202 bool HttpNegotiatePatch::Initialize() { |
| 168 if (IS_PATCHED(IHttpNegotiate)) { | 203 if (IS_PATCHED(IHttpNegotiate)) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 DVLOG(1) << __FUNCTION__ << " " << url << " headers:\n" << headers; | 259 DVLOG(1) << __FUNCTION__ << " " << url << " headers:\n" << headers; |
| 225 | 260 |
| 226 HRESULT hr = original(me, url, headers, reserved, additional_headers); | 261 HRESULT hr = original(me, url, headers, reserved, additional_headers); |
| 227 | 262 |
| 228 if (FAILED(hr)) { | 263 if (FAILED(hr)) { |
| 229 DLOG(WARNING) << __FUNCTION__ << " Delegate returned an error"; | 264 DLOG(WARNING) << __FUNCTION__ << " Delegate returned an error"; |
| 230 return hr; | 265 return hr; |
| 231 } | 266 } |
| 232 if (modify_user_agent_) { | 267 if (modify_user_agent_) { |
| 233 std::string updated_headers; | 268 std::string updated_headers; |
| 269 |
| 234 if (IsGcfDefaultRenderer() && | 270 if (IsGcfDefaultRenderer() && |
| 235 RendererTypeForUrl(url) == RENDERER_TYPE_CHROME_DEFAULT_RENDERER) { | 271 RendererTypeForUrl(url) == RENDERER_TYPE_CHROME_DEFAULT_RENDERER) { |
| 236 // Replace the user-agent header with Chrome's. | 272 // Replace the user-agent header with Chrome's. |
| 237 updated_headers = ReplaceOrAddUserAgent(*additional_headers, | 273 updated_headers = ReplaceOrAddUserAgent(*additional_headers, |
| 238 http_utils::GetChromeUserAgent()); | 274 http_utils::GetChromeUserAgent()); |
| 275 } else if (ShouldRemoveUAForUrl(url)) { |
| 276 updated_headers = RemoveCFUserAgentString(headers, *additional_headers); |
| 239 } else { | 277 } else { |
| 240 updated_headers = AppendCFUserAgentString(headers, *additional_headers); | 278 updated_headers = AppendCFUserAgentString(headers, *additional_headers); |
| 241 } | 279 } |
| 280 |
| 242 *additional_headers = reinterpret_cast<wchar_t*>(::CoTaskMemRealloc( | 281 *additional_headers = reinterpret_cast<wchar_t*>(::CoTaskMemRealloc( |
| 243 *additional_headers, | 282 *additional_headers, |
| 244 (updated_headers.length() + 1) * sizeof(wchar_t))); | 283 (updated_headers.length() + 1) * sizeof(wchar_t))); |
| 245 lstrcpyW(*additional_headers, ASCIIToWide(updated_headers).c_str()); | 284 lstrcpyW(*additional_headers, ASCIIToWide(updated_headers).c_str()); |
| 246 } else { | 285 } else { |
| 247 // TODO(erikwright): Remove the user agent if it is present (i.e., because | 286 // TODO(erikwright): Remove the user agent if it is present (i.e., because |
| 248 // of PostPlatform setting in the registry). | 287 // of PostPlatform setting in the registry). |
| 249 } | 288 } |
| 250 return S_OK; | 289 return S_OK; |
| 251 } | 290 } |
| OLD | NEW |