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 |