Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "extensions/browser/extension_function.h" | 5 #include "extensions/browser/extension_function.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/macros.h" | 10 #include "base/macros.h" |
| 11 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
| 12 #include "base/memory/singleton.h" | 12 #include "base/memory/singleton.h" |
| 13 #include "base/metrics/histogram_macros.h" | 13 #include "base/metrics/histogram_macros.h" |
| 14 #include "base/metrics/sparse_histogram.h" | 14 #include "base/metrics/sparse_histogram.h" |
| 15 #include "base/synchronization/lock.h" | 15 #include "base/synchronization/lock.h" |
| 16 #include "content/public/browser/notification_source.h" | 16 #include "content/public/browser/notification_source.h" |
| 17 #include "content/public/browser/notification_types.h" | 17 #include "content/public/browser/notification_types.h" |
| 18 #include "content/public/browser/render_frame_host.h" | 18 #include "content/public/browser/render_frame_host.h" |
| 19 #include "content/public/browser/user_metrics.h" | |
| 19 #include "content/public/browser/web_contents.h" | 20 #include "content/public/browser/web_contents.h" |
| 20 #include "content/public/browser/web_contents_observer.h" | 21 #include "content/public/browser/web_contents_observer.h" |
| 22 #include "extensions/browser/bad_message.h" | |
| 21 #include "extensions/browser/extension_function_dispatcher.h" | 23 #include "extensions/browser/extension_function_dispatcher.h" |
| 22 #include "extensions/browser/extension_message_filter.h" | 24 #include "extensions/browser/extension_message_filter.h" |
| 23 #include "extensions/browser/extensions_browser_client.h" | 25 #include "extensions/browser/extensions_browser_client.h" |
| 24 #include "extensions/common/error_utils.h" | 26 #include "extensions/common/error_utils.h" |
| 25 #include "extensions/common/extension_api.h" | 27 #include "extensions/common/extension_api.h" |
| 26 #include "extensions/common/extension_messages.h" | 28 #include "extensions/common/extension_messages.h" |
| 27 | 29 |
| 28 using content::BrowserThread; | 30 using content::BrowserThread; |
| 29 using content::RenderViewHost; | 31 using content::RenderViewHost; |
| 30 using content::WebContents; | 32 using content::WebContents; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 69 histogram_value); | 71 histogram_value); |
| 70 } else { | 72 } else { |
| 71 UMA_HISTOGRAM_SPARSE_SLOWLY("Extensions.Functions.FailedTime.Over10ms", | 73 UMA_HISTOGRAM_SPARSE_SLOWLY("Extensions.Functions.FailedTime.Over10ms", |
| 72 histogram_value); | 74 histogram_value); |
| 73 } | 75 } |
| 74 UMA_HISTOGRAM_TIMES("Extensions.Functions.FailedTotalExecutionTime", | 76 UMA_HISTOGRAM_TIMES("Extensions.Functions.FailedTotalExecutionTime", |
| 75 elapsed_time); | 77 elapsed_time); |
| 76 } | 78 } |
| 77 } | 79 } |
| 78 | 80 |
| 81 void LogBadMessage(extensions::functions::HistogramValue histogram_value) { | |
| 82 content::RecordAction(base::UserMetricsAction("BadMessageTerminate_EFD")); | |
| 83 // Track the specific function's |histogram_value|, as this may indicate a | |
| 84 // bug in that API's implementation. | |
| 85 UMA_HISTOGRAM_ENUMERATION("Extensions.BadMessageFunctionName", | |
| 86 histogram_value, | |
| 87 extensions::functions::ENUM_BOUNDARY); | |
| 88 } | |
| 89 | |
| 90 template <class T> | |
| 91 void ReceivedBadMessage(T* bad_message_sender, | |
| 92 extensions::bad_message::BadMessageReason reason, | |
| 93 extensions::functions::HistogramValue histogram_value) { | |
| 94 LogBadMessage(histogram_value); | |
| 95 // The renderer has done validation before sending extension api requests. | |
| 96 // Therefore, we should never receive a request that is invalid in a way | |
| 97 // that JSON validation in the renderer should have caught. It could be an | |
| 98 // attacker trying to exploit the browser, so we crash the renderer instead. | |
| 99 extensions::bad_message::ReceivedBadMessage(bad_message_sender, reason); | |
| 100 } | |
| 101 | |
| 79 class ArgumentListResponseValue | 102 class ArgumentListResponseValue |
| 80 : public ExtensionFunction::ResponseValueObject { | 103 : public ExtensionFunction::ResponseValueObject { |
| 81 public: | 104 public: |
| 82 ArgumentListResponseValue(ExtensionFunction* function, | 105 ArgumentListResponseValue(ExtensionFunction* function, |
| 83 std::unique_ptr<base::ListValue> result) { | 106 std::unique_ptr<base::ListValue> result) { |
| 84 SetFunctionResults(function, std::move(result)); | 107 SetFunctionResults(function, std::move(result)); |
| 85 // It would be nice to DCHECK(error.empty()) but some legacy extension | 108 // It would be nice to DCHECK(error.empty()) but some legacy extension |
| 86 // function implementations... I'm looking at chrome.input.ime... do this | 109 // function implementations... I'm looking at chrome.input.ime... do this |
| 87 // for some reason. | 110 // for some reason. |
| 88 } | 111 } |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 115 } | 138 } |
| 116 | 139 |
| 117 ~ErrorResponseValue() override {} | 140 ~ErrorResponseValue() override {} |
| 118 | 141 |
| 119 bool Apply() override { return false; } | 142 bool Apply() override { return false; } |
| 120 }; | 143 }; |
| 121 | 144 |
| 122 class BadMessageResponseValue : public ExtensionFunction::ResponseValueObject { | 145 class BadMessageResponseValue : public ExtensionFunction::ResponseValueObject { |
| 123 public: | 146 public: |
| 124 explicit BadMessageResponseValue(ExtensionFunction* function) { | 147 explicit BadMessageResponseValue(ExtensionFunction* function) { |
| 125 function->set_bad_message(true); | 148 function->SetBadMessage(); |
| 126 NOTREACHED() << function->name() << ": bad message"; | 149 NOTREACHED() << function->name() << ": bad message"; |
| 127 } | 150 } |
| 128 | 151 |
| 129 ~BadMessageResponseValue() override {} | 152 ~BadMessageResponseValue() override {} |
| 130 | 153 |
| 131 bool Apply() override { return false; } | 154 bool Apply() override { return false; } |
| 132 }; | 155 }; |
| 133 | 156 |
| 134 class RespondNowAction : public ExtensionFunction::ResponseActionObject { | 157 class RespondNowAction : public ExtensionFunction::ResponseActionObject { |
| 135 public: | 158 public: |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 312 } | 335 } |
| 313 | 336 |
| 314 const base::ListValue* ExtensionFunction::GetResultList() const { | 337 const base::ListValue* ExtensionFunction::GetResultList() const { |
| 315 return results_.get(); | 338 return results_.get(); |
| 316 } | 339 } |
| 317 | 340 |
| 318 const std::string& ExtensionFunction::GetError() const { | 341 const std::string& ExtensionFunction::GetError() const { |
| 319 return error_; | 342 return error_; |
| 320 } | 343 } |
| 321 | 344 |
| 345 void ExtensionFunction::SetBadMessage() { | |
|
Devlin
2017/01/27 17:38:58
Does this compile? ExtensionFunction::SetBadMessa
lazyboy
2017/01/27 18:17:24
Ah, I've put a mental note to fix it after noticin
| |
| 346 bad_message_ = true; | |
| 347 } | |
| 348 | |
| 322 bool ExtensionFunction::user_gesture() const { | 349 bool ExtensionFunction::user_gesture() const { |
| 323 return user_gesture_ || UserGestureForTests::GetInstance()->HaveGesture(); | 350 return user_gesture_ || UserGestureForTests::GetInstance()->HaveGesture(); |
| 324 } | 351 } |
| 325 | 352 |
| 326 ExtensionFunction::ResponseValue ExtensionFunction::NoArguments() { | 353 ExtensionFunction::ResponseValue ExtensionFunction::NoArguments() { |
| 327 return ResponseValue( | 354 return ResponseValue( |
| 328 new ArgumentListResponseValue(this, base::MakeUnique<base::ListValue>())); | 355 new ArgumentListResponseValue(this, base::MakeUnique<base::ListValue>())); |
| 329 } | 356 } |
| 330 | 357 |
| 331 ExtensionFunction::ResponseValue ExtensionFunction::OneArgument( | 358 ExtensionFunction::ResponseValue ExtensionFunction::OneArgument( |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 501 // here and use weakptrs for the tasks, then have it owned by something that | 528 // here and use weakptrs for the tasks, then have it owned by something that |
| 502 // will be destroyed naturally in the course of shut down. | 529 // will be destroyed naturally in the course of shut down. |
| 503 if (extensions::ExtensionsBrowserClient::Get()->IsShuttingDown()) { | 530 if (extensions::ExtensionsBrowserClient::Get()->IsShuttingDown()) { |
| 504 *error = "The browser is shutting down."; | 531 *error = "The browser is shutting down."; |
| 505 return false; | 532 return false; |
| 506 } | 533 } |
| 507 | 534 |
| 508 return true; | 535 return true; |
| 509 } | 536 } |
| 510 | 537 |
| 538 void UIThreadExtensionFunction::SetBadMessage() { | |
| 539 ExtensionFunction::SetBadMessage(); | |
| 540 | |
| 541 if (render_frame_host()) { | |
| 542 ReceivedBadMessage(render_frame_host()->GetProcess(), | |
| 543 is_from_service_worker() | |
| 544 ? extensions::bad_message::EFD_BAD_MESSAGE_WORKER | |
| 545 : extensions::bad_message::EFD_BAD_MESSAGE, | |
| 546 histogram_value()); | |
| 547 } | |
| 548 } | |
| 549 | |
| 511 bool UIThreadExtensionFunction::OnMessageReceived(const IPC::Message& message) { | 550 bool UIThreadExtensionFunction::OnMessageReceived(const IPC::Message& message) { |
| 512 return false; | 551 return false; |
| 513 } | 552 } |
| 514 | 553 |
| 515 void UIThreadExtensionFunction::Destruct() const { | 554 void UIThreadExtensionFunction::Destruct() const { |
| 516 BrowserThread::DeleteOnUIThread::Destruct(this); | 555 BrowserThread::DeleteOnUIThread::Destruct(this); |
| 517 } | 556 } |
| 518 | 557 |
| 519 void UIThreadExtensionFunction::SetRenderFrameHost( | 558 void UIThreadExtensionFunction::SetRenderFrameHost( |
| 520 content::RenderFrameHost* render_frame_host) { | 559 content::RenderFrameHost* render_frame_host) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 570 } | 609 } |
| 571 | 610 |
| 572 IOThreadExtensionFunction::~IOThreadExtensionFunction() { | 611 IOThreadExtensionFunction::~IOThreadExtensionFunction() { |
| 573 } | 612 } |
| 574 | 613 |
| 575 IOThreadExtensionFunction* | 614 IOThreadExtensionFunction* |
| 576 IOThreadExtensionFunction::AsIOThreadExtensionFunction() { | 615 IOThreadExtensionFunction::AsIOThreadExtensionFunction() { |
| 577 return this; | 616 return this; |
| 578 } | 617 } |
| 579 | 618 |
| 619 void IOThreadExtensionFunction::SetBadMessage() { | |
| 620 ExtensionFunction::SetBadMessage(); | |
| 621 if (ipc_sender_) { | |
| 622 ReceivedBadMessage((content::BrowserMessageFilter*)ipc_sender_.get(), | |
|
Devlin
2017/01/27 17:38:58
nit: prefer static_cast<> over c-style casts
lazyboy
2017/01/27 18:17:24
Done.
| |
| 623 extensions::bad_message::EFD_BAD_MESSAGE, | |
| 624 histogram_value()); | |
| 625 } | |
| 626 } | |
| 627 | |
| 580 void IOThreadExtensionFunction::Destruct() const { | 628 void IOThreadExtensionFunction::Destruct() const { |
| 581 BrowserThread::DeleteOnIOThread::Destruct(this); | 629 BrowserThread::DeleteOnIOThread::Destruct(this); |
| 582 } | 630 } |
| 583 | 631 |
| 584 AsyncExtensionFunction::AsyncExtensionFunction() { | 632 AsyncExtensionFunction::AsyncExtensionFunction() { |
| 585 } | 633 } |
| 586 | 634 |
| 587 void AsyncExtensionFunction::SetError(const std::string& error) { | 635 void AsyncExtensionFunction::SetError(const std::string& error) { |
| 588 error_ = error; | 636 error_ = error; |
| 589 } | 637 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 629 void AsyncExtensionFunction::SendResponse(bool success) { | 677 void AsyncExtensionFunction::SendResponse(bool success) { |
| 630 ResponseValue response; | 678 ResponseValue response; |
| 631 if (success) { | 679 if (success) { |
| 632 response = ArgumentList(std::move(results_)); | 680 response = ArgumentList(std::move(results_)); |
| 633 } else { | 681 } else { |
| 634 response = results_ ? ErrorWithArguments(std::move(results_), error_) | 682 response = results_ ? ErrorWithArguments(std::move(results_), error_) |
| 635 : Error(error_); | 683 : Error(error_); |
| 636 } | 684 } |
| 637 Respond(std::move(response)); | 685 Respond(std::move(response)); |
| 638 } | 686 } |
| OLD | NEW |