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

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

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