| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/browser/extensions/extension_webrequest_api_helpers.h" | 5 #include "chrome/browser/extensions/extension_webrequest_api_helpers.h" |
| 6 | 6 |
| 7 #include "base/string_util.h" |
| 7 #include "base/values.h" | 8 #include "base/values.h" |
| 8 #include "chrome/browser/extensions/extension_webrequest_api.h" | 9 #include "chrome/browser/extensions/extension_webrequest_api.h" |
| 9 #include "net/http/http_util.h" | 10 #include "net/http/http_util.h" |
| 10 | 11 |
| 11 namespace extension_webrequest_api_helpers { | 12 namespace extension_webrequest_api_helpers { |
| 12 | 13 |
| 13 | 14 |
| 14 EventResponseDelta::EventResponseDelta( | 15 EventResponseDelta::EventResponseDelta( |
| 15 const std::string& extension_id, const base::Time& extension_install_time) | 16 const std::string& extension_id, const base::Time& extension_install_time) |
| 16 : extension_id(extension_id), | 17 : extension_id(extension_id), |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 } | 159 } |
| 159 } | 160 } |
| 160 } | 161 } |
| 161 return result; | 162 return result; |
| 162 } | 163 } |
| 163 | 164 |
| 164 EventResponseDelta* CalculateOnHeadersReceivedDelta( | 165 EventResponseDelta* CalculateOnHeadersReceivedDelta( |
| 165 const std::string& extension_id, | 166 const std::string& extension_id, |
| 166 const base::Time& extension_install_time, | 167 const base::Time& extension_install_time, |
| 167 bool cancel, | 168 bool cancel, |
| 168 const std::string& status_line, | 169 net::HttpResponseHeaders* old_response_headers, |
| 169 const std::string& response_headers_string) { | 170 ResponseHeaders* new_response_headers) { |
| 170 EventResponseDelta* result = | 171 EventResponseDelta* result = |
| 171 new EventResponseDelta(extension_id, extension_install_time); | 172 new EventResponseDelta(extension_id, extension_install_time); |
| 172 result->cancel = cancel; | 173 result->cancel = cancel; |
| 173 | 174 |
| 174 if (!response_headers_string.empty()) { | 175 // Find deleted headers. |
| 175 std::string new_headers_string = | 176 { |
| 176 status_line + "\n" + response_headers_string; | 177 void* iter = NULL; |
| 178 std::string name; |
| 179 std::string value; |
| 180 while (old_response_headers->EnumerateHeaderLines(&iter, &name, &value)) { |
| 181 ResponseHeader current_header(name, value); |
| 182 if (std::find(new_response_headers->begin(), |
| 183 new_response_headers->end(), |
| 184 current_header) == new_response_headers->end()) { |
| 185 result->deleted_response_headers.push_back(current_header); |
| 186 } |
| 187 } |
| 188 } |
| 177 | 189 |
| 178 result->new_response_headers = | 190 // Find added headers. |
| 179 new net::HttpResponseHeaders( | 191 { |
| 180 net::HttpUtil::AssembleRawHeaders(new_headers_string.c_str(), | 192 for (ResponseHeaders::const_iterator i = new_response_headers->begin(); |
| 181 new_headers_string.length())); | 193 i != new_response_headers->end(); ++i) { |
| 194 bool header_found = false; |
| 195 void* iter = NULL; |
| 196 std::string name; |
| 197 std::string value; |
| 198 // We don't use HttpResponseHeaders::HasHeaderValue because it is |
| 199 // case insensitive |
| 200 while (old_response_headers->EnumerateHeaderLines(&iter, &name, &value) && |
| 201 !header_found) { |
| 202 header_found = (name == i->first) && (value == i->second); |
| 203 } |
| 204 if (!header_found) |
| 205 result->added_response_headers.push_back(*i); |
| 206 } |
| 182 } | 207 } |
| 208 |
| 183 return result; | 209 return result; |
| 184 } | 210 } |
| 185 | 211 |
| 186 EventResponseDelta* CalculateOnAuthRequiredDelta( | 212 EventResponseDelta* CalculateOnAuthRequiredDelta( |
| 187 const std::string& extension_id, | 213 const std::string& extension_id, |
| 188 const base::Time& extension_install_time, | 214 const base::Time& extension_install_time, |
| 189 bool cancel, | 215 bool cancel, |
| 190 scoped_ptr<net::AuthCredentials>* auth_credentials) { | 216 scoped_ptr<net::AuthCredentials>* auth_credentials) { |
| 191 EventResponseDelta* result = | 217 EventResponseDelta* result = |
| 192 new EventResponseDelta(extension_id, extension_install_time); | 218 new EventResponseDelta(extension_id, extension_install_time); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 216 void MergeOnBeforeRequestResponses( | 242 void MergeOnBeforeRequestResponses( |
| 217 const EventResponseDeltas& deltas, | 243 const EventResponseDeltas& deltas, |
| 218 GURL* new_url, | 244 GURL* new_url, |
| 219 std::set<std::string>* conflicting_extensions, | 245 std::set<std::string>* conflicting_extensions, |
| 220 EventLogEntries* event_log_entries) { | 246 EventLogEntries* event_log_entries) { |
| 221 EventResponseDeltas::const_iterator delta; | 247 EventResponseDeltas::const_iterator delta; |
| 222 | 248 |
| 223 bool redirected = false; | 249 bool redirected = false; |
| 224 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { | 250 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { |
| 225 if (!(*delta)->new_url.is_empty()) { | 251 if (!(*delta)->new_url.is_empty()) { |
| 226 if (!redirected) { | 252 if (!redirected || *new_url == (*delta)->new_url) { |
| 227 *new_url = (*delta)->new_url; | 253 *new_url = (*delta)->new_url; |
| 228 redirected = true; | 254 redirected = true; |
| 229 EventLogEntry log_entry( | 255 EventLogEntry log_entry( |
| 230 net::NetLog::TYPE_CHROME_EXTENSION_REDIRECTED_REQUEST, | 256 net::NetLog::TYPE_CHROME_EXTENSION_REDIRECTED_REQUEST, |
| 231 make_scoped_refptr( | 257 make_scoped_refptr( |
| 232 new NetLogExtensionIdParameter((*delta)->extension_id))); | 258 new NetLogExtensionIdParameter((*delta)->extension_id))); |
| 233 event_log_entries->push_back(log_entry); | 259 event_log_entries->push_back(log_entry); |
| 234 } else { | 260 } else { |
| 235 conflicting_extensions->insert((*delta)->extension_id); | 261 conflicting_extensions->insert((*delta)->extension_id); |
| 236 EventLogEntry log_entry( | 262 EventLogEntry log_entry( |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 conflicting_extensions->insert((*delta)->extension_id); | 365 conflicting_extensions->insert((*delta)->extension_id); |
| 340 EventLogEntry log_entry( | 366 EventLogEntry log_entry( |
| 341 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, | 367 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, |
| 342 make_scoped_refptr( | 368 make_scoped_refptr( |
| 343 new NetLogExtensionIdParameter((*delta)->extension_id))); | 369 new NetLogExtensionIdParameter((*delta)->extension_id))); |
| 344 event_log_entries->push_back(log_entry); | 370 event_log_entries->push_back(log_entry); |
| 345 } | 371 } |
| 346 } | 372 } |
| 347 } | 373 } |
| 348 | 374 |
| 375 // Converts the key of the (key, value) pair to lower case. |
| 376 ResponseHeader toLowerCase(const ResponseHeader& header) { |
| 377 std::string lower_key(header.first); |
| 378 std::transform(lower_key.begin(), lower_key.end(), |
| 379 lower_key.begin(), ::tolower); |
| 380 return ResponseHeader(lower_key, header.second); |
| 381 } |
| 382 |
| 349 void MergeOnHeadersReceivedResponses( | 383 void MergeOnHeadersReceivedResponses( |
| 350 const EventResponseDeltas& deltas, | 384 const EventResponseDeltas& deltas, |
| 351 scoped_refptr<net::HttpResponseHeaders>* override_response_headers, | 385 scoped_refptr<net::HttpResponseHeaders>* override_response_headers, |
| 352 std::set<std::string>* conflicting_extensions, | 386 std::set<std::string>* conflicting_extensions, |
| 353 EventLogEntries* event_log_entries) { | 387 EventLogEntries* event_log_entries) { |
| 354 EventResponseDeltas::const_iterator delta; | 388 EventResponseDeltas::const_iterator delta; |
| 355 | 389 |
| 356 // Whether any extension has overridden the response headers, yet. | 390 // Here we collect which headers we have removed or added so far due to |
| 357 bool headers_overridden = false; | 391 // extensions of higher precedence. Header keys are always stored as |
| 392 // lower case. |
| 393 std::set<ResponseHeader> removed_headers; |
| 394 std::set<ResponseHeader> added_headers; |
| 358 | 395 |
| 359 // We assume here that the deltas are sorted in decreasing extension | 396 // We assume here that the deltas are sorted in decreasing extension |
| 360 // precedence (i.e. decreasing extension installation time). | 397 // precedence (i.e. decreasing extension installation time). |
| 361 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { | 398 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { |
| 362 if (!(*delta)->new_response_headers.get()) | 399 if ((*delta)->added_response_headers.empty() && |
| 400 (*delta)->deleted_response_headers.empty()) { |
| 363 continue; | 401 continue; |
| 402 } |
| 364 | 403 |
| 365 scoped_refptr<NetLogModificationParameter> log( | 404 // We consider modifications as pairs of (delete, add) operations. |
| 366 new NetLogModificationParameter((*delta)->extension_id)); | 405 // If a header is deleted twice by different extensions we assume that the |
| 406 // intention was to modify it to different values and consider this a |
| 407 // conflict. As deltas is sorted by decreasing extension installation order, |
| 408 // this takes care of precedence. |
| 409 bool extension_conflicts = false; |
| 410 ResponseHeaders::const_iterator i; |
| 411 for (i = (*delta)->deleted_response_headers.begin(); |
| 412 i != (*delta)->deleted_response_headers.end(); ++i) { |
| 413 if (removed_headers.find(toLowerCase(*i)) != removed_headers.end()) { |
| 414 extension_conflicts = true; |
| 415 break; |
| 416 } |
| 417 } |
| 367 | 418 |
| 368 // Conflict if a second extension returned new response headers; | 419 // Now execute the modifications if there were no conflicts. |
| 369 bool extension_conflicts = headers_overridden; | 420 if (!extension_conflicts) { |
| 421 // Delete headers |
| 422 { |
| 423 for (i = (*delta)->deleted_response_headers.begin(); |
| 424 i != (*delta)->deleted_response_headers.end(); ++i) { |
| 425 (*override_response_headers)->RemoveHeader(i->first, i->second); |
| 426 removed_headers.insert(toLowerCase(*i)); |
| 427 } |
| 428 } |
| 370 | 429 |
| 371 if (!extension_conflicts) { | 430 // Add headers. |
| 372 headers_overridden = true; | 431 { |
| 373 *override_response_headers = (*delta)->new_response_headers; | 432 for (i = (*delta)->added_response_headers.begin(); |
| 433 i != (*delta)->added_response_headers.end(); ++i) { |
| 434 ResponseHeader lowercase_header(toLowerCase(*i)); |
| 435 if (added_headers.find(lowercase_header) != added_headers.end()) |
| 436 continue; |
| 437 added_headers.insert(lowercase_header); |
| 438 (*override_response_headers)->AddHeader(i->first + ": " + i->second); |
| 439 } |
| 440 } |
| 374 EventLogEntry log_entry( | 441 EventLogEntry log_entry( |
| 375 net::NetLog::TYPE_CHROME_EXTENSION_MODIFIED_HEADERS, log); | 442 net::NetLog::TYPE_CHROME_EXTENSION_MODIFIED_HEADERS, |
| 443 make_scoped_refptr( |
| 444 new NetLogModificationParameter((*delta)->extension_id))); |
| 376 event_log_entries->push_back(log_entry); | 445 event_log_entries->push_back(log_entry); |
| 377 } else { | 446 } else { |
| 378 conflicting_extensions->insert((*delta)->extension_id); | 447 conflicting_extensions->insert((*delta)->extension_id); |
| 379 EventLogEntry log_entry( | 448 EventLogEntry log_entry( |
| 380 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, | 449 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, |
| 381 make_scoped_refptr( | 450 make_scoped_refptr( |
| 382 new NetLogExtensionIdParameter((*delta)->extension_id))); | 451 new NetLogExtensionIdParameter((*delta)->extension_id))); |
| 383 event_log_entries->push_back(log_entry); | 452 event_log_entries->push_back(log_entry); |
| 384 } | 453 } |
| 385 } | 454 } |
| 386 } | 455 } |
| 387 | 456 |
| 388 bool MergeOnAuthRequiredResponses( | 457 bool MergeOnAuthRequiredResponses( |
| 389 const EventResponseDeltas& deltas, | 458 const EventResponseDeltas& deltas, |
| 390 net::AuthCredentials* auth_credentials, | 459 net::AuthCredentials* auth_credentials, |
| 391 std::set<std::string>* conflicting_extensions, | 460 std::set<std::string>* conflicting_extensions, |
| 392 EventLogEntries* event_log_entries) { | 461 EventLogEntries* event_log_entries) { |
| 393 CHECK(auth_credentials); | 462 CHECK(auth_credentials); |
| 394 bool credentials_set = false; | 463 bool credentials_set = false; |
| 395 | 464 |
| 396 for (EventResponseDeltas::const_iterator delta = deltas.begin(); | 465 for (EventResponseDeltas::const_iterator delta = deltas.begin(); |
| 397 delta != deltas.end(); | 466 delta != deltas.end(); |
| 398 ++delta) { | 467 ++delta) { |
| 399 if (!(*delta)->auth_credentials.get()) | 468 if (!(*delta)->auth_credentials.get()) |
| 400 continue; | 469 continue; |
| 401 if (credentials_set) { | 470 bool different = |
| 471 auth_credentials->username() != |
| 472 (*delta)->auth_credentials->username() || |
| 473 auth_credentials->password() != (*delta)->auth_credentials->password(); |
| 474 if (credentials_set && different) { |
| 402 conflicting_extensions->insert((*delta)->extension_id); | 475 conflicting_extensions->insert((*delta)->extension_id); |
| 403 EventLogEntry log_entry( | 476 EventLogEntry log_entry( |
| 404 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, | 477 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, |
| 405 make_scoped_refptr( | 478 make_scoped_refptr( |
| 406 new NetLogExtensionIdParameter((*delta)->extension_id))); | 479 new NetLogExtensionIdParameter((*delta)->extension_id))); |
| 407 event_log_entries->push_back(log_entry); | 480 event_log_entries->push_back(log_entry); |
| 408 } else { | 481 } else { |
| 409 EventLogEntry log_entry( | 482 EventLogEntry log_entry( |
| 410 net::NetLog::TYPE_CHROME_EXTENSION_PROVIDE_AUTH_CREDENTIALS, | 483 net::NetLog::TYPE_CHROME_EXTENSION_PROVIDE_AUTH_CREDENTIALS, |
| 411 make_scoped_refptr( | 484 make_scoped_refptr( |
| 412 new NetLogExtensionIdParameter((*delta)->extension_id))); | 485 new NetLogExtensionIdParameter((*delta)->extension_id))); |
| 413 event_log_entries->push_back(log_entry); | 486 event_log_entries->push_back(log_entry); |
| 414 *auth_credentials = *(*delta)->auth_credentials; | 487 *auth_credentials = *(*delta)->auth_credentials; |
| 415 credentials_set = true; | 488 credentials_set = true; |
| 416 } | 489 } |
| 417 } | 490 } |
| 418 return credentials_set; | 491 return credentials_set; |
| 419 } | 492 } |
| 420 | 493 |
| 421 } // namespace extension_webrequest_api_helpers | 494 } // namespace extension_webrequest_api_helpers |
| OLD | NEW |