diff --git a/atom/browser/api/atom_api_view.cc b/atom/browser/api/atom_api_view.cc index fdb63dc89fd..f986835ac30 100644 --- a/atom/browser/api/atom_api_view.cc +++ b/atom/browser/api/atom_api_view.cc @@ -12,11 +12,16 @@ namespace atom { namespace api { +View::View(views::View* view) : view_(view) {} + View::View() : view_(new views::View()) { view_->set_owned_by_client(); } -View::~View() {} +View::~View() { + if (delete_view_) + delete view_; +} // static mate::WrappableBase* View::New(mate::Arguments* args) { diff --git a/atom/browser/api/atom_api_view.h b/atom/browser/api/atom_api_view.h index e60aa0329a1..6be2423afc1 100644 --- a/atom/browser/api/atom_api_view.h +++ b/atom/browser/api/atom_api_view.h @@ -21,12 +21,19 @@ class View : public mate::EventEmitter { static void BuildPrototype(v8::Isolate* isolate, v8::Local prototype); + views::View* view() const { return view_; } + protected: + explicit View(views::View* view); View(); ~View() override; + // Should delete the |view_| in destructor. + void set_delete_view(bool should) { delete_view_ = should; } + private: - std::unique_ptr view_; + bool delete_view_ = true; + views::View* view_ = nullptr; DISALLOW_COPY_AND_ASSIGN(View); }; diff --git a/atom/browser/api/atom_api_web_contents_view.cc b/atom/browser/api/atom_api_web_contents_view.cc new file mode 100644 index 00000000000..ef6d951e9e6 --- /dev/null +++ b/atom/browser/api/atom_api_web_contents_view.cc @@ -0,0 +1,85 @@ +// Copyright (c) 2018 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/api/atom_api_web_contents_view.h" + +#include "atom/browser/api/atom_api_web_contents.h" +#include "brightray/browser/inspectable_web_contents_view.h" +#include "native_mate/dictionary.h" +#include "ui/views/controls/native/native_view_host.h" + +#include "atom/common/node_includes.h" + +namespace atom { + +namespace api { + +WebContentsView::WebContentsView( + v8::Isolate* isolate, + v8::Local web_contents_wrapper, + brightray::InspectableWebContents* web_contents) +#if defined(OS_MACOSX) + : View(new views::NativeViewHost()), +#else + : View(web_contents->GetView()->GetView()), +#endif + web_contents_wrapper_(isolate, web_contents_wrapper) { +#if defined(OS_MACOSX) + // On macOS a View is created to wrap the NSView, and its lifetime is managed + // by us. + auto* host = static_cast(view()); + host->set_owned_by_client(); + host->Attach(web_contents->GetView()->GetNativeView()); +#else + // On other platforms the View is managed by InspectableWebContents. + set_delete_view(false); +#endif +} + +WebContentsView::~WebContentsView() {} + +// static +mate::WrappableBase* WebContentsView::New( + v8::Isolate* isolate, + mate::Handle web_contents) { + if (!web_contents->managed_web_contents()) { + const char* error = "The WebContents must be created by user"; + isolate->ThrowException( + v8::Exception::Error(mate::StringToV8(isolate, error))); + return nullptr; + } + return new WebContentsView(isolate, web_contents->GetWrapper(), + web_contents->managed_web_contents()); +} + +// static +void WebContentsView::BuildPrototype( + v8::Isolate* isolate, + v8::Local prototype) {} + +} // namespace api + +} // namespace atom + +namespace { + +using atom::api::WebContentsView; + +void Initialize(v8::Local exports, + v8::Local unused, + v8::Local context, + void* priv) { + v8::Isolate* isolate = context->GetIsolate(); + WebContentsView::SetConstructor(isolate, base::Bind(&WebContentsView::New)); + + mate::Dictionary constructor( + isolate, WebContentsView::GetConstructor(isolate)->GetFunction()); + + mate::Dictionary dict(isolate, exports); + dict.Set("WebContentsView", constructor); +} + +} // namespace + +NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_web_contents_view, Initialize) diff --git a/atom/browser/api/atom_api_web_contents_view.h b/atom/browser/api/atom_api_web_contents_view.h new file mode 100644 index 00000000000..0dae03db0b9 --- /dev/null +++ b/atom/browser/api/atom_api_web_contents_view.h @@ -0,0 +1,46 @@ +// Copyright (c) 2018 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_API_ATOM_API_WEB_CONTENTS_VIEW_H_ +#define ATOM_BROWSER_API_ATOM_API_WEB_CONTENTS_VIEW_H_ + +#include "atom/browser/api/atom_api_view.h" +#include "native_mate/handle.h" + +namespace brightray { +class InspectableWebContents; +} + +namespace atom { + +namespace api { + +class WebContents; + +class WebContentsView : public View { + public: + static mate::WrappableBase* New(v8::Isolate* isolate, + mate::Handle web_contents); + + static void BuildPrototype(v8::Isolate* isolate, + v8::Local prototype); + + protected: + WebContentsView(v8::Isolate* isolate, + v8::Local web_contents_wrapper, + brightray::InspectableWebContents* web_contents); + ~WebContentsView() override; + + private: + // Keep a reference to v8 wrapper. + v8::Global web_contents_wrapper_; + + DISALLOW_COPY_AND_ASSIGN(WebContentsView); +}; + +} // namespace api + +} // namespace atom + +#endif // ATOM_BROWSER_API_ATOM_API_WEB_CONTENTS_VIEW_H_ diff --git a/atom/common/node_bindings.cc b/atom/common/node_bindings.cc index 48359d91380..bdcf5f34e37 100644 --- a/atom/common/node_bindings.cc +++ b/atom/common/node_bindings.cc @@ -49,6 +49,7 @@ V(atom_browser_top_level_window) \ V(atom_browser_tray) \ V(atom_browser_web_contents) \ + V(atom_browser_web_contents_view) \ V(atom_browser_view) \ V(atom_browser_web_view_manager) \ V(atom_browser_window) \ diff --git a/filenames.gypi b/filenames.gypi index 205da5ebf7e..bfb2967c3bc 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -40,6 +40,7 @@ 'lib/browser/api/tray.js', 'lib/browser/api/view.js', 'lib/browser/api/web-contents.js', + 'lib/browser/api/web-contents-view.js', 'lib/browser/chrome-extension.js', 'lib/browser/desktop-capturer.js', 'lib/browser/guest-view-manager.js', @@ -168,6 +169,8 @@ 'atom/browser/api/atom_api_web_contents.cc', 'atom/browser/api/atom_api_web_contents.h', 'atom/browser/api/atom_api_web_contents_mac.mm', + 'atom/browser/api/atom_api_web_contents_view.cc', + 'atom/browser/api/atom_api_web_contents_view.h', 'atom/browser/api/atom_api_web_request.cc', 'atom/browser/api/atom_api_web_request.h', 'atom/browser/api/atom_api_web_view_manager.cc', diff --git a/lib/browser/api/module-list.js b/lib/browser/api/module-list.js index 4d534d30184..5b218838acf 100644 --- a/lib/browser/api/module-list.js +++ b/lib/browser/api/module-list.js @@ -24,6 +24,7 @@ module.exports = [ {name: 'Tray', file: 'tray'}, {name: 'View', file: 'view'}, {name: 'webContents', file: 'web-contents'}, + {name: 'WebContentsView', file: 'web-contents-view'}, // The internal modules, invisible unless you know their names. {name: 'NavigationController', file: 'navigation-controller', private: true} ] diff --git a/lib/browser/api/web-contents-view.js b/lib/browser/api/web-contents-view.js new file mode 100644 index 00000000000..d7428db7a05 --- /dev/null +++ b/lib/browser/api/web-contents-view.js @@ -0,0 +1,15 @@ +'use strict' + +const electron = require('electron') + +const {View} = electron +const {WebContentsView} = process.atomBinding('web_contents_view') + +Object.setPrototypeOf(WebContentsView.prototype, View.prototype) + +WebContentsView.prototype._init = function () { + // Call parent class's _init. + View.prototype._init.call(this) +} + +module.exports = WebContentsView