extension_js_runner.cc 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "extensions/renderer/extension_js_runner.h"
  5. #include "base/bind.h"
  6. #include "content/public/renderer/worker_thread.h"
  7. #include "extensions/renderer/script_context.h"
  8. #include "third_party/blink/public/web/web_local_frame.h"
  9. #include "third_party/blink/public/web/web_script_execution_callback.h"
  10. #include "v8/include/v8-function.h"
  11. #include "v8/include/v8-isolate.h"
  12. #include "v8/include/v8-microtask-queue.h"
  13. namespace extensions {
  14. ExtensionJSRunner::ExtensionJSRunner(ScriptContext* script_context)
  15. : script_context_(script_context) {}
  16. ExtensionJSRunner::~ExtensionJSRunner() {}
  17. void ExtensionJSRunner::RunJSFunction(v8::Local<v8::Function> function,
  18. v8::Local<v8::Context> context,
  19. int argc,
  20. v8::Local<v8::Value> argv[],
  21. ResultCallback callback) {
  22. blink::WebScriptExecutionCallback wrapper_callback;
  23. if (callback) {
  24. wrapper_callback =
  25. base::BindOnce(&ExtensionJSRunner::OnFunctionComplete,
  26. weak_factory_.GetWeakPtr(), std::move(callback));
  27. }
  28. // TODO(devlin): Move ScriptContext::SafeCallFunction() into here?
  29. script_context_->SafeCallFunction(function, argc, argv,
  30. std::move(wrapper_callback));
  31. }
  32. v8::MaybeLocal<v8::Value> ExtensionJSRunner::RunJSFunctionSync(
  33. v8::Local<v8::Function> function,
  34. v8::Local<v8::Context> context,
  35. int argc,
  36. v8::Local<v8::Value> argv[]) {
  37. DCHECK(script_context_->v8_context() == context);
  38. v8::Isolate* isolate = context->GetIsolate();
  39. DCHECK(context == isolate->GetCurrentContext());
  40. v8::MicrotasksScope microtasks(isolate,
  41. v8::MicrotasksScope::kDoNotRunMicrotasks);
  42. v8::Local<v8::Object> global = context->Global();
  43. blink::WebLocalFrame* web_frame = script_context_->web_frame();
  44. v8::MaybeLocal<v8::Value> result;
  45. // NOTE(devlin): We use relatively unsafe execution variants here
  46. // (WebLocalFrame::CallFunctionEvenIfScriptDisabled() and
  47. // v8::Function::Call()); these ignore things like script suspension. We need
  48. // to use these because RunJSFunctionSync() is used when in direct response
  49. // to JS running, and JS that's running sometimes needs a synchronous
  50. // response (such as when returning the value to a synchronous API or a
  51. // newly-constructed object). It's a shame that we have to use them here, but
  52. // at the end of the day, the right solution is to instead ensure that if
  53. // script is suspended, JS is not running at all, and thus none of these
  54. // entry points would be reached during suspension. It would be nice to reduce
  55. // or eliminate the need for this method.
  56. if (web_frame) {
  57. result = web_frame->CallFunctionEvenIfScriptDisabled(function, global, argc,
  58. argv);
  59. } else {
  60. result = function->Call(context, global, argc, argv);
  61. }
  62. return result;
  63. }
  64. void ExtensionJSRunner::OnFunctionComplete(
  65. ResultCallback callback,
  66. const blink::WebVector<v8::Local<v8::Value>>& results,
  67. base::TimeTicks start_time) {
  68. DCHECK(script_context_->is_valid());
  69. v8::MaybeLocal<v8::Value> result;
  70. if (!results.empty() && !results[0].IsEmpty())
  71. result = results[0];
  72. std::move(callback).Run(script_context_->v8_context(), result);
  73. }
  74. } // namespace extensions