native_bindings_helper.cc 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. // Copyright 2019 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 "chromecast/renderer/native_bindings_helper.h"
  5. #include "base/logging.h"
  6. #include "content/public/renderer/render_frame.h"
  7. #include "gin/converter.h"
  8. #include "third_party/blink/public/web/blink.h"
  9. #include "third_party/blink/public/web/web_local_frame.h"
  10. namespace chromecast {
  11. namespace {
  12. const char kCastObjectName[] = "cast";
  13. const char kCastPlatformObjectKey[] = "__platform__";
  14. } // namespace
  15. v8::Local<v8::Object> GetOrCreateCastPlatformObject(
  16. v8::Isolate* isolate,
  17. v8::Local<v8::Object> global) {
  18. v8::Local<v8::Object> cast =
  19. EnsureObjectExists(isolate, global, kCastObjectName);
  20. return EnsureObjectExists(isolate, cast, kCastPlatformObjectKey);
  21. }
  22. v8::Local<v8::Object> EnsureObjectExists(v8::Isolate* isolate,
  23. v8::Local<v8::Object> parent,
  24. const std::string& key) {
  25. v8::Local<v8::Context> context = isolate->GetCurrentContext();
  26. v8::MaybeLocal<v8::Value> child =
  27. parent->Get(context, gin::StringToV8(isolate, key));
  28. v8::Local<v8::Value> child_local;
  29. v8::Local<v8::Object> child_object;
  30. if (child.ToLocal(&child_local) && child_local->IsObject() &&
  31. child_local->ToObject(context).ToLocal(&child_object))
  32. return child_object;
  33. if (!child_local.IsEmpty() && !child_local->IsUndefined())
  34. LOG(WARNING) << "Overwriting non-empty non-object with key " << key;
  35. v8::Local<v8::Object> new_child_object = v8::Object::New(isolate);
  36. v8::Maybe<bool> result =
  37. parent->Set(context, gin::StringToSymbol(isolate, key), new_child_object);
  38. if (result.IsNothing() || !result.FromJust())
  39. LOG(ERROR) << "Failed to set new object with key " << key;
  40. return new_child_object;
  41. }
  42. CastBinding::CastBinding(content::RenderFrame* render_frame)
  43. : content::RenderFrameObserver(render_frame) {}
  44. CastBinding::~CastBinding() {}
  45. void CastBinding::DidClearWindowObject() {
  46. TryInstall();
  47. }
  48. void CastBinding::OnDestruct() {
  49. delete this;
  50. }
  51. void CastBinding::TryInstall() {
  52. blink::WebLocalFrame* web_frame = render_frame()->GetWebFrame();
  53. if (!web_frame)
  54. return;
  55. v8::Isolate* isolate = blink::MainThreadIsolate();
  56. if (!isolate)
  57. return;
  58. v8::MicrotasksScope microtasks(isolate,
  59. v8::MicrotasksScope::kDoNotRunMicrotasks);
  60. v8::HandleScope handle_scope(isolate);
  61. v8::Local<v8::Context> context = web_frame->MainWorldScriptContext();
  62. if (context.IsEmpty())
  63. return;
  64. v8::Context::Scope context_scope(context);
  65. v8::Local<v8::Object> global = context->Global();
  66. v8::Local<v8::Object> cast_platform =
  67. GetOrCreateCastPlatformObject(isolate, global);
  68. Install(cast_platform, isolate);
  69. }
  70. } // namespace chromecast