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

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

Issue 2360073002: [Extensions] Isolate ExtensionFunction results_ and error_ (Closed)
Patch Set: errorwithargs Created 4 years, 2 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"
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 histogram_value); 72 histogram_value);
73 } 73 }
74 UMA_HISTOGRAM_TIMES("Extensions.Functions.FailedTotalExecutionTime", 74 UMA_HISTOGRAM_TIMES("Extensions.Functions.FailedTotalExecutionTime",
75 elapsed_time); 75 elapsed_time);
76 } 76 }
77 } 77 }
78 78
79 class ArgumentListResponseValue 79 class ArgumentListResponseValue
80 : public ExtensionFunction::ResponseValueObject { 80 : public ExtensionFunction::ResponseValueObject {
81 public: 81 public:
82 ArgumentListResponseValue(const std::string& function_name, 82 ArgumentListResponseValue(ExtensionFunction* function,
83 const char* title, 83 std::unique_ptr<base::ListValue> result) {
84 ExtensionFunction* function, 84 SetFunctionResults(function, std::move(result));
85 std::unique_ptr<base::ListValue> result)
86 : function_name_(function_name), title_(title) {
87 if (function->GetResultList()) {
88 DCHECK_EQ(function->GetResultList(), result.get())
89 << "The result set on this function (" << function_name_ << ") "
90 << "either by calling SetResult() or directly modifying |result_| is "
91 << "different to the one passed to " << title_ << "(). "
92 << "The best way to fix this problem is to exclusively use " << title_
93 << "(). SetResult() and |result_| are deprecated.";
94 } else {
95 function->SetResultList(std::move(result));
96 }
97 // It would be nice to DCHECK(error.empty()) but some legacy extension 85 // It would be nice to DCHECK(error.empty()) but some legacy extension
98 // function implementations... I'm looking at chrome.input.ime... do this 86 // function implementations... I'm looking at chrome.input.ime... do this
99 // for some reason. 87 // for some reason.
100 } 88 }
101 89
102 ~ArgumentListResponseValue() override {} 90 ~ArgumentListResponseValue() override {}
103 91
104 bool Apply() override { return true; } 92 bool Apply() override { return true; }
105
106 private:
107 std::string function_name_;
108 const char* title_;
109 }; 93 };
110 94
111 class ErrorWithArgumentsResponseValue : public ArgumentListResponseValue { 95 class ErrorWithArgumentsResponseValue : public ArgumentListResponseValue {
112 public: 96 public:
113 ErrorWithArgumentsResponseValue(const std::string& function_name, 97 ErrorWithArgumentsResponseValue(ExtensionFunction* function,
114 const char* title,
115 ExtensionFunction* function,
116 std::unique_ptr<base::ListValue> result, 98 std::unique_ptr<base::ListValue> result,
117 const std::string& error) 99 const std::string& error)
118 : ArgumentListResponseValue(function_name, 100 : ArgumentListResponseValue(function, std::move(result)) {
119 title, 101 SetFunctionError(function, error);
120 function,
121 std::move(result)) {
122 function->SetError(error);
123 } 102 }
124 103
125 ~ErrorWithArgumentsResponseValue() override {} 104 ~ErrorWithArgumentsResponseValue() override {}
126 105
127 bool Apply() override { return false; } 106 bool Apply() override { return false; }
128 }; 107 };
129 108
130 class ErrorResponseValue : public ExtensionFunction::ResponseValueObject { 109 class ErrorResponseValue : public ExtensionFunction::ResponseValueObject {
131 public: 110 public:
132 ErrorResponseValue(ExtensionFunction* function, const std::string& error) { 111 ErrorResponseValue(ExtensionFunction* function, const std::string& error) {
133 // It would be nice to DCHECK(!error.empty()) but too many legacy extension 112 // It would be nice to DCHECK(!error.empty()) but too many legacy extension
134 // function implementations don't set error but signal failure. 113 // function implementations don't set error but signal failure.
135 function->SetError(error); 114 SetFunctionError(function, error);
136 } 115 }
137 116
138 ~ErrorResponseValue() override {} 117 ~ErrorResponseValue() override {}
139 118
140 bool Apply() override { return false; } 119 bool Apply() override { return false; }
141 }; 120 };
142 121
143 class BadMessageResponseValue : public ExtensionFunction::ResponseValueObject { 122 class BadMessageResponseValue : public ExtensionFunction::ResponseValueObject {
144 public: 123 public:
145 explicit BadMessageResponseValue(ExtensionFunction* function) { 124 explicit BadMessageResponseValue(ExtensionFunction* function) {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 } 193 }
215 194
216 void UserGestureForTests::DecrementCount() { 195 void UserGestureForTests::DecrementCount() {
217 base::AutoLock autolock(lock_); 196 base::AutoLock autolock(lock_);
218 --count_; 197 --count_;
219 } 198 }
220 199
221 200
222 } // namespace 201 } // namespace
223 202
203 void ExtensionFunction::ResponseValueObject::SetFunctionResults(
204 ExtensionFunction* function,
205 std::unique_ptr<base::ListValue> results) {
206 DCHECK(!function->results_) << "Function " << function->name_
207 << "already has results set.";
208 function->results_ = std::move(results);
209 }
210
211 void ExtensionFunction::ResponseValueObject::SetFunctionError(
212 ExtensionFunction* function,
213 const std::string& error) {
214 DCHECK(function->error_.empty()) << "Function " << function->name_
215 << "already has an error.";
216 function->error_ = error;
217 }
218
224 // static 219 // static
225 bool ExtensionFunction::ignore_all_did_respond_for_testing_do_not_use = false; 220 bool ExtensionFunction::ignore_all_did_respond_for_testing_do_not_use = false;
226 221
227 // static 222 // static
228 const char* ExtensionFunction::kUnknownErrorDoNotUse = "Unknown error."; 223 const char* ExtensionFunction::kUnknownErrorDoNotUse = "Unknown error.";
229 224
230 // static 225 // static
231 void ExtensionFunctionDeleteTraits::Destruct(const ExtensionFunction* x) { 226 void ExtensionFunctionDeleteTraits::Destruct(const ExtensionFunction* x) {
232 x->Destruct(); 227 x->Destruct();
233 } 228 }
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 void ExtensionFunction::OnQuotaExceeded(const std::string& violation_error) { 297 void ExtensionFunction::OnQuotaExceeded(const std::string& violation_error) {
303 error_ = violation_error; 298 error_ = violation_error;
304 SendResponseImpl(false); 299 SendResponseImpl(false);
305 } 300 }
306 301
307 void ExtensionFunction::SetArgs(const base::ListValue* args) { 302 void ExtensionFunction::SetArgs(const base::ListValue* args) {
308 DCHECK(!args_.get()); // Should only be called once. 303 DCHECK(!args_.get()); // Should only be called once.
309 args_ = args->CreateDeepCopy(); 304 args_ = args->CreateDeepCopy();
310 } 305 }
311 306
312 void ExtensionFunction::SetResult(std::unique_ptr<base::Value> result) {
313 results_.reset(new base::ListValue());
314 results_->Append(std::move(result));
315 }
316
317 void ExtensionFunction::SetResultList(
318 std::unique_ptr<base::ListValue> results) {
319 results_ = std::move(results);
320 }
321
322 const base::ListValue* ExtensionFunction::GetResultList() const { 307 const base::ListValue* ExtensionFunction::GetResultList() const {
323 return results_.get(); 308 return results_.get();
324 } 309 }
325 310
326 std::string ExtensionFunction::GetError() const { 311 const std::string& ExtensionFunction::GetError() const {
327 return error_; 312 return error_;
328 } 313 }
329 314
330 void ExtensionFunction::SetError(const std::string& error) { 315 void ExtensionFunction::SetError(const std::string& error) {
331 error_ = error; 316 error_ = error;
332 } 317 }
333 318
334 bool ExtensionFunction::user_gesture() const { 319 bool ExtensionFunction::user_gesture() const {
335 return user_gesture_ || UserGestureForTests::GetInstance()->HaveGesture(); 320 return user_gesture_ || UserGestureForTests::GetInstance()->HaveGesture();
336 } 321 }
337 322
338 ExtensionFunction::ResponseValue ExtensionFunction::NoArguments() { 323 ExtensionFunction::ResponseValue ExtensionFunction::NoArguments() {
339 return ResponseValue(new ArgumentListResponseValue( 324 return ResponseValue(
340 name(), "NoArguments", this, base::MakeUnique<base::ListValue>())); 325 new ArgumentListResponseValue(this, base::MakeUnique<base::ListValue>()));
341 } 326 }
342 327
343 ExtensionFunction::ResponseValue ExtensionFunction::OneArgument( 328 ExtensionFunction::ResponseValue ExtensionFunction::OneArgument(
344 std::unique_ptr<base::Value> arg) { 329 std::unique_ptr<base::Value> arg) {
345 std::unique_ptr<base::ListValue> args(new base::ListValue()); 330 std::unique_ptr<base::ListValue> args(new base::ListValue());
346 args->Append(std::move(arg)); 331 args->Append(std::move(arg));
347 return ResponseValue(new ArgumentListResponseValue(name(), "OneArgument", 332 return ResponseValue(new ArgumentListResponseValue(this, std::move(args)));
348 this, std::move(args)));
349 } 333 }
350 334
351 ExtensionFunction::ResponseValue ExtensionFunction::TwoArguments( 335 ExtensionFunction::ResponseValue ExtensionFunction::TwoArguments(
352 std::unique_ptr<base::Value> arg1, 336 std::unique_ptr<base::Value> arg1,
353 std::unique_ptr<base::Value> arg2) { 337 std::unique_ptr<base::Value> arg2) {
354 std::unique_ptr<base::ListValue> args(new base::ListValue()); 338 std::unique_ptr<base::ListValue> args(new base::ListValue());
355 args->Append(std::move(arg1)); 339 args->Append(std::move(arg1));
356 args->Append(std::move(arg2)); 340 args->Append(std::move(arg2));
357 return ResponseValue(new ArgumentListResponseValue(name(), "TwoArguments", 341 return ResponseValue(new ArgumentListResponseValue(this, std::move(args)));
358 this, std::move(args)));
359 } 342 }
360 343
361 ExtensionFunction::ResponseValue ExtensionFunction::ArgumentList( 344 ExtensionFunction::ResponseValue ExtensionFunction::ArgumentList(
362 std::unique_ptr<base::ListValue> args) { 345 std::unique_ptr<base::ListValue> args) {
363 return ResponseValue(new ArgumentListResponseValue(name(), "ArgumentList", 346 return ResponseValue(new ArgumentListResponseValue(this, std::move(args)));
364 this, std::move(args)));
365 } 347 }
366 348
367 ExtensionFunction::ResponseValue ExtensionFunction::Error( 349 ExtensionFunction::ResponseValue ExtensionFunction::Error(
368 const std::string& error) { 350 const std::string& error) {
369 return ResponseValue(new ErrorResponseValue(this, error)); 351 return ResponseValue(new ErrorResponseValue(this, error));
370 } 352 }
371 353
372 ExtensionFunction::ResponseValue ExtensionFunction::Error( 354 ExtensionFunction::ResponseValue ExtensionFunction::Error(
373 const std::string& format, 355 const std::string& format,
374 const std::string& s1) { 356 const std::string& s1) {
(...skipping 14 matching lines...) Expand all
389 const std::string& s1, 371 const std::string& s1,
390 const std::string& s2, 372 const std::string& s2,
391 const std::string& s3) { 373 const std::string& s3) {
392 return ResponseValue(new ErrorResponseValue( 374 return ResponseValue(new ErrorResponseValue(
393 this, ErrorUtils::FormatErrorMessage(format, s1, s2, s3))); 375 this, ErrorUtils::FormatErrorMessage(format, s1, s2, s3)));
394 } 376 }
395 377
396 ExtensionFunction::ResponseValue ExtensionFunction::ErrorWithArguments( 378 ExtensionFunction::ResponseValue ExtensionFunction::ErrorWithArguments(
397 std::unique_ptr<base::ListValue> args, 379 std::unique_ptr<base::ListValue> args,
398 const std::string& error) { 380 const std::string& error) {
399 return ResponseValue(new ErrorWithArgumentsResponseValue( 381 return ResponseValue(
400 name(), "ErrorWithArguments", this, std::move(args), error)); 382 new ErrorWithArgumentsResponseValue(this, std::move(args), error));
401 } 383 }
402 384
403 ExtensionFunction::ResponseValue ExtensionFunction::BadMessage() { 385 ExtensionFunction::ResponseValue ExtensionFunction::BadMessage() {
404 return ResponseValue(new BadMessageResponseValue(this)); 386 return ResponseValue(new BadMessageResponseValue(this));
405 } 387 }
406 388
407 ExtensionFunction::ResponseAction ExtensionFunction::RespondNow( 389 ExtensionFunction::ResponseAction ExtensionFunction::RespondNow(
408 ResponseValue result) { 390 ResponseValue result) {
409 return ResponseAction(new RespondNowAction( 391 return ResponseAction(new RespondNowAction(
410 std::move(result), 392 std::move(result),
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 UIThreadExtensionFunction::~UIThreadExtensionFunction() { 459 UIThreadExtensionFunction::~UIThreadExtensionFunction() {
478 if (dispatcher() && render_frame_host()) 460 if (dispatcher() && render_frame_host())
479 dispatcher()->OnExtensionFunctionCompleted(extension()); 461 dispatcher()->OnExtensionFunctionCompleted(extension());
480 // The extension function should always respond to avoid leaks in the 462 // The extension function should always respond to avoid leaks in the
481 // renderer, dangling callbacks, etc. The exception is if the system is 463 // renderer, dangling callbacks, etc. The exception is if the system is
482 // shutting down. 464 // shutting down.
483 // TODO(devlin): Duplicate this check in IOThreadExtensionFunction. It's 465 // TODO(devlin): Duplicate this check in IOThreadExtensionFunction. It's
484 // tricky because checking IsShuttingDown has to be called from the UI thread. 466 // tricky because checking IsShuttingDown has to be called from the UI thread.
485 extensions::ExtensionsBrowserClient* browser_client = 467 extensions::ExtensionsBrowserClient* browser_client =
486 extensions::ExtensionsBrowserClient::Get(); 468 extensions::ExtensionsBrowserClient::Get();
487 DCHECK(!browser_client || browser_client->IsShuttingDown() || did_respond_ || 469 DCHECK(!browser_client || browser_client->IsShuttingDown() || did_respond() ||
488 ignore_all_did_respond_for_testing_do_not_use) 470 ignore_all_did_respond_for_testing_do_not_use)
489 << name_; 471 << name();
490 } 472 }
491 473
492 UIThreadExtensionFunction* 474 UIThreadExtensionFunction*
493 UIThreadExtensionFunction::AsUIThreadExtensionFunction() { 475 UIThreadExtensionFunction::AsUIThreadExtensionFunction() {
494 return this; 476 return this;
495 } 477 }
496 478
497 bool UIThreadExtensionFunction::PreRunValidation(std::string* error) { 479 bool UIThreadExtensionFunction::PreRunValidation(std::string* error) {
498 if (!ExtensionFunction::PreRunValidation(error)) 480 if (!ExtensionFunction::PreRunValidation(error))
499 return false; 481 return false;
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 return this; 565 return this;
584 } 566 }
585 567
586 void IOThreadExtensionFunction::Destruct() const { 568 void IOThreadExtensionFunction::Destruct() const {
587 BrowserThread::DeleteOnIOThread::Destruct(this); 569 BrowserThread::DeleteOnIOThread::Destruct(this);
588 } 570 }
589 571
590 AsyncExtensionFunction::AsyncExtensionFunction() { 572 AsyncExtensionFunction::AsyncExtensionFunction() {
591 } 573 }
592 574
575 void AsyncExtensionFunction::SetError(const std::string& error) {
576 error_ = error;
577 }
578
579 const std::string& AsyncExtensionFunction::GetError() const {
580 return error_.empty() ? UIThreadExtensionFunction::GetError() : error_;
581 }
582
593 AsyncExtensionFunction::~AsyncExtensionFunction() { 583 AsyncExtensionFunction::~AsyncExtensionFunction() {
594 } 584 }
595 585
586 void AsyncExtensionFunction::SetResult(std::unique_ptr<base::Value> result) {
587 results_.reset(new base::ListValue());
588 results_->Append(std::move(result));
589 }
590
591 void AsyncExtensionFunction::SetResultList(
592 std::unique_ptr<base::ListValue> results) {
593 results_ = std::move(results);
594 }
595
596 ExtensionFunction::ScopedUserGestureForTests::ScopedUserGestureForTests() { 596 ExtensionFunction::ScopedUserGestureForTests::ScopedUserGestureForTests() {
597 UserGestureForTests::GetInstance()->IncrementCount(); 597 UserGestureForTests::GetInstance()->IncrementCount();
598 } 598 }
599 599
600 ExtensionFunction::ScopedUserGestureForTests::~ScopedUserGestureForTests() { 600 ExtensionFunction::ScopedUserGestureForTests::~ScopedUserGestureForTests() {
601 UserGestureForTests::GetInstance()->DecrementCount(); 601 UserGestureForTests::GetInstance()->DecrementCount();
602 } 602 }
603 603
604 ExtensionFunction::ResponseAction AsyncExtensionFunction::Run() { 604 ExtensionFunction::ResponseAction AsyncExtensionFunction::Run() {
605 return RunAsync() ? RespondLater() : RespondNow(Error(error_)); 605 if (RunAsync())
606 return RespondLater();
607 DCHECK(!results_);
608 return RespondNow(Error(error_));
606 } 609 }
607 610
608 // static 611 // static
609 bool AsyncExtensionFunction::ValidationFailure( 612 bool AsyncExtensionFunction::ValidationFailure(
610 AsyncExtensionFunction* function) { 613 AsyncExtensionFunction* function) {
611 return false; 614 return false;
612 } 615 }
613 616
614 void AsyncExtensionFunction::SendResponse(bool success) { 617 void AsyncExtensionFunction::SendResponse(bool success) {
615 Respond(success ? ArgumentList(std::move(results_)) : Error(error_)); 618 ResponseValue response;
619 if (success) {
620 response = ArgumentList(std::move(results_));
621 } else {
622 response = results_ ? ErrorWithArguments(std::move(results_), error_)
623 : Error(error_);
624 }
625 Respond(std::move(response));
616 } 626 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698