refactor: BrowserView is owned by a BaseWindow (#35511)

This commit is contained in:
Jeremy Rose 2022-08-31 17:40:02 -07:00 committed by GitHub
parent 9cdc8bf6ca
commit f99122abfc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 71 additions and 73 deletions

View file

@ -753,63 +753,54 @@ void BaseWindow::SetParentWindow(v8::Local<v8::Value> value,
} }
} }
void BaseWindow::SetBrowserView(v8::Local<v8::Value> value) { void BaseWindow::SetBrowserView(
absl::optional<gin::Handle<BrowserView>> browser_view) {
ResetBrowserViews(); ResetBrowserViews();
AddBrowserView(value); if (browser_view)
AddBrowserView(*browser_view);
} }
void BaseWindow::AddBrowserView(v8::Local<v8::Value> value) { void BaseWindow::AddBrowserView(gin::Handle<BrowserView> browser_view) {
gin::Handle<BrowserView> browser_view; auto iter = browser_views_.find(browser_view->ID());
if (value->IsObject() && if (iter == browser_views_.end()) {
gin::ConvertFromV8(isolate(), value, &browser_view)) { // If we're reparenting a BrowserView, ensure that it's detached from
auto get_that_view = browser_views_.find(browser_view->ID()); // its previous owner window.
if (get_that_view == browser_views_.end()) { BaseWindow* owner_window = browser_view->owner_window();
// If we're reparenting a BrowserView, ensure that it's detached from if (owner_window) {
// its previous owner window. // iter == browser_views_.end() should imply owner_window != this.
auto* owner_window = browser_view->owner_window(); DCHECK_NE(owner_window, this);
if (owner_window && owner_window != window_.get()) { owner_window->RemoveBrowserView(browser_view);
owner_window->RemoveBrowserView(browser_view->view());
browser_view->SetOwnerWindow(nullptr);
}
window_->AddBrowserView(browser_view->view());
browser_view->SetOwnerWindow(window_.get());
browser_views_[browser_view->ID()].Reset(isolate(), value);
}
}
}
void BaseWindow::RemoveBrowserView(v8::Local<v8::Value> value) {
gin::Handle<BrowserView> browser_view;
if (value->IsObject() &&
gin::ConvertFromV8(isolate(), value, &browser_view)) {
auto get_that_view = browser_views_.find(browser_view->ID());
if (get_that_view != browser_views_.end()) {
window_->RemoveBrowserView(browser_view->view());
browser_view->SetOwnerWindow(nullptr); browser_view->SetOwnerWindow(nullptr);
(*get_that_view).second.Reset(isolate(), value);
browser_views_.erase(get_that_view);
} }
window_->AddBrowserView(browser_view->view());
browser_view->SetOwnerWindow(this);
browser_views_[browser_view->ID()].Reset(isolate(), browser_view.ToV8());
} }
} }
void BaseWindow::SetTopBrowserView(v8::Local<v8::Value> value, void BaseWindow::RemoveBrowserView(gin::Handle<BrowserView> browser_view) {
gin_helper::Arguments* args) { auto iter = browser_views_.find(browser_view->ID());
gin::Handle<BrowserView> browser_view; if (iter != browser_views_.end()) {
if (value->IsObject() && window_->RemoveBrowserView(browser_view->view());
gin::ConvertFromV8(isolate(), value, &browser_view)) { browser_view->SetOwnerWindow(nullptr);
auto* owner_window = browser_view->owner_window(); iter->second.Reset();
auto get_that_view = browser_views_.find(browser_view->ID()); browser_views_.erase(iter);
if (get_that_view == browser_views_.end() ||
(owner_window && owner_window != window_.get())) {
args->ThrowError("Given BrowserView is not attached to the window");
return;
}
window_->SetTopBrowserView(browser_view->view());
} }
} }
void BaseWindow::SetTopBrowserView(gin::Handle<BrowserView> browser_view,
gin_helper::Arguments* args) {
BaseWindow* owner_window = browser_view->owner_window();
auto iter = browser_views_.find(browser_view->ID());
if (iter == browser_views_.end() || (owner_window && owner_window != this)) {
args->ThrowError("Given BrowserView is not attached to the window");
return;
}
window_->SetTopBrowserView(browser_view->view());
}
std::string BaseWindow::GetMediaSourceId() const { std::string BaseWindow::GetMediaSourceId() const {
return window_->GetDesktopMediaID().ToString(); return window_->GetDesktopMediaID().ToString();
} }
@ -1127,11 +1118,11 @@ void BaseWindow::ResetBrowserViews() {
!browser_view.IsEmpty()) { !browser_view.IsEmpty()) {
// There's a chance that the BrowserView may have been reparented - only // There's a chance that the BrowserView may have been reparented - only
// reset if the owner window is *this* window. // reset if the owner window is *this* window.
auto* owner_window = browser_view->owner_window(); BaseWindow* owner_window = browser_view->owner_window();
if (owner_window && owner_window == window_.get()) { DCHECK_EQ(owner_window, this);
browser_view->SetOwnerWindow(nullptr); browser_view->SetOwnerWindow(nullptr);
owner_window->RemoveBrowserView(browser_view->view()); window_->RemoveBrowserView(browser_view->view());
} browser_view->SetOwnerWindow(nullptr);
} }
item.second.Reset(); item.second.Reset();

View file

@ -22,6 +22,7 @@
namespace electron::api { namespace electron::api {
class View; class View;
class BrowserView;
class BaseWindow : public gin_helper::TrackableObject<BaseWindow>, class BaseWindow : public gin_helper::TrackableObject<BaseWindow>,
public NativeWindowObserver { public NativeWindowObserver {
@ -173,10 +174,11 @@ class BaseWindow : public gin_helper::TrackableObject<BaseWindow>,
void SetMenu(v8::Isolate* isolate, v8::Local<v8::Value> menu); void SetMenu(v8::Isolate* isolate, v8::Local<v8::Value> menu);
void RemoveMenu(); void RemoveMenu();
void SetParentWindow(v8::Local<v8::Value> value, gin_helper::Arguments* args); void SetParentWindow(v8::Local<v8::Value> value, gin_helper::Arguments* args);
virtual void SetBrowserView(v8::Local<v8::Value> value); virtual void SetBrowserView(
virtual void AddBrowserView(v8::Local<v8::Value> value); absl::optional<gin::Handle<BrowserView>> browser_view);
virtual void RemoveBrowserView(v8::Local<v8::Value> value); virtual void AddBrowserView(gin::Handle<BrowserView> browser_view);
virtual void SetTopBrowserView(v8::Local<v8::Value> value, virtual void RemoveBrowserView(gin::Handle<BrowserView> browser_view);
virtual void SetTopBrowserView(gin::Handle<BrowserView> browser_view,
gin_helper::Arguments* args); gin_helper::Arguments* args);
virtual std::vector<v8::Local<v8::Value>> GetBrowserViews() const; virtual std::vector<v8::Local<v8::Value>> GetBrowserViews() const;
virtual void ResetBrowserViews(); virtual void ResetBrowserViews();

View file

@ -8,6 +8,7 @@
#include "content/browser/renderer_host/render_widget_host_view_base.h" // nogncheck #include "content/browser/renderer_host/render_widget_host_view_base.h" // nogncheck
#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/render_widget_host_view.h"
#include "shell/browser/api/electron_api_base_window.h"
#include "shell/browser/api/electron_api_web_contents.h" #include "shell/browser/api/electron_api_web_contents.h"
#include "shell/browser/browser.h" #include "shell/browser/browser.h"
#include "shell/browser/native_browser_view.h" #include "shell/browser/native_browser_view.h"
@ -99,10 +100,10 @@ BrowserView::BrowserView(gin::Arguments* args,
NativeBrowserView::Create(api_web_contents_->inspectable_web_contents())); NativeBrowserView::Create(api_web_contents_->inspectable_web_contents()));
} }
void BrowserView::SetOwnerWindow(NativeWindow* window) { void BrowserView::SetOwnerWindow(BaseWindow* window) {
// Ensure WebContents and BrowserView owner windows are in sync. // Ensure WebContents and BrowserView owner windows are in sync.
if (web_contents()) if (web_contents())
web_contents()->SetOwnerWindow(window); web_contents()->SetOwnerWindow(window ? window->window() : nullptr);
owner_window_ = window ? window->GetWeakPtr() : nullptr; owner_window_ = window ? window->GetWeakPtr() : nullptr;
} }

View file

@ -31,6 +31,7 @@ class Dictionary;
namespace electron::api { namespace electron::api {
class WebContents; class WebContents;
class BaseWindow;
class BrowserView : public gin::Wrappable<BrowserView>, class BrowserView : public gin::Wrappable<BrowserView>,
public gin_helper::Constructible<BrowserView>, public gin_helper::Constructible<BrowserView>,
@ -51,9 +52,9 @@ class BrowserView : public gin::Wrappable<BrowserView>,
WebContents* web_contents() const { return api_web_contents_; } WebContents* web_contents() const { return api_web_contents_; }
NativeBrowserView* view() const { return view_.get(); } NativeBrowserView* view() const { return view_.get(); }
NativeWindow* owner_window() const { return owner_window_.get(); } BaseWindow* owner_window() const { return owner_window_.get(); }
void SetOwnerWindow(NativeWindow* window); void SetOwnerWindow(BaseWindow* window);
int32_t ID() const { return id_; } int32_t ID() const { return id_; }
@ -83,7 +84,7 @@ class BrowserView : public gin::Wrappable<BrowserView>,
class WebContents* api_web_contents_ = nullptr; class WebContents* api_web_contents_ = nullptr;
std::unique_ptr<NativeBrowserView> view_; std::unique_ptr<NativeBrowserView> view_;
base::WeakPtr<NativeWindow> owner_window_; base::WeakPtr<BaseWindow> owner_window_;
int32_t id_; int32_t id_;
}; };

View file

@ -395,31 +395,33 @@ void BrowserWindow::SetBackgroundColor(const std::string& color_name) {
} }
} }
void BrowserWindow::SetBrowserView(v8::Local<v8::Value> value) { void BrowserWindow::SetBrowserView(
absl::optional<gin::Handle<BrowserView>> browser_view) {
BaseWindow::ResetBrowserViews(); BaseWindow::ResetBrowserViews();
BaseWindow::AddBrowserView(value); if (browser_view)
BaseWindow::AddBrowserView(*browser_view);
#if BUILDFLAG(IS_MAC) #if BUILDFLAG(IS_MAC)
UpdateDraggableRegions(draggable_regions_); UpdateDraggableRegions(draggable_regions_);
#endif #endif
} }
void BrowserWindow::AddBrowserView(v8::Local<v8::Value> value) { void BrowserWindow::AddBrowserView(gin::Handle<BrowserView> browser_view) {
BaseWindow::AddBrowserView(value); BaseWindow::AddBrowserView(browser_view);
#if BUILDFLAG(IS_MAC) #if BUILDFLAG(IS_MAC)
UpdateDraggableRegions(draggable_regions_); UpdateDraggableRegions(draggable_regions_);
#endif #endif
} }
void BrowserWindow::RemoveBrowserView(v8::Local<v8::Value> value) { void BrowserWindow::RemoveBrowserView(gin::Handle<BrowserView> browser_view) {
BaseWindow::RemoveBrowserView(value); BaseWindow::RemoveBrowserView(browser_view);
#if BUILDFLAG(IS_MAC) #if BUILDFLAG(IS_MAC)
UpdateDraggableRegions(draggable_regions_); UpdateDraggableRegions(draggable_regions_);
#endif #endif
} }
void BrowserWindow::SetTopBrowserView(v8::Local<v8::Value> value, void BrowserWindow::SetTopBrowserView(gin::Handle<BrowserView> browser_view,
gin_helper::Arguments* args) { gin_helper::Arguments* args) {
BaseWindow::SetTopBrowserView(value, args); BaseWindow::SetTopBrowserView(browser_view, args);
#if BUILDFLAG(IS_MAC) #if BUILDFLAG(IS_MAC)
UpdateDraggableRegions(draggable_regions_); UpdateDraggableRegions(draggable_regions_);
#endif #endif

View file

@ -82,10 +82,11 @@ class BrowserWindow : public BaseWindow,
void Focus() override; void Focus() override;
void Blur() override; void Blur() override;
void SetBackgroundColor(const std::string& color_name) override; void SetBackgroundColor(const std::string& color_name) override;
void SetBrowserView(v8::Local<v8::Value> value) override; void SetBrowserView(
void AddBrowserView(v8::Local<v8::Value> value) override; absl::optional<gin::Handle<BrowserView>> browser_view) override;
void RemoveBrowserView(v8::Local<v8::Value> value) override; void AddBrowserView(gin::Handle<BrowserView> browser_view) override;
void SetTopBrowserView(v8::Local<v8::Value> value, void RemoveBrowserView(gin::Handle<BrowserView> browser_view) override;
void SetTopBrowserView(gin::Handle<BrowserView> browser_view,
gin_helper::Arguments* args) override; gin_helper::Arguments* args) override;
void ResetBrowserViews() override; void ResetBrowserViews() override;
void SetVibrancy(v8::Isolate* isolate, v8::Local<v8::Value> value) override; void SetVibrancy(v8::Isolate* isolate, v8::Local<v8::Value> value) override;

View file

@ -30,7 +30,7 @@ describe('BrowserView module', () => {
w = null as any; w = null as any;
await p; await p;
if (view) { if (view && view.webContents) {
const p = emittedOnce(view.webContents, 'destroyed'); const p = emittedOnce(view.webContents, 'destroyed');
(view.webContents as any).destroy(); (view.webContents as any).destroy();
view = null as any; view = null as any;