Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(608)

Side by Side Diff: extensions/browser/extension_function.cc

Issue 2656013005: Better crash stacktraces for ExtensionFunction bad messages. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « extensions/browser/extension_function.h ('k') | extensions/browser/extension_function_dispatcher.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698