Skip to content

Commit

Permalink
fix: handle BrowserView reparenting (#27220)
Browse files Browse the repository at this point in the history
  • Loading branch information
codebytere committed Jan 11, 2021
1 parent f3a4b44 commit 08da5ee
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 2 deletions.
17 changes: 15 additions & 2 deletions shell/browser/api/electron_api_top_level_window.cc
Expand Up @@ -752,6 +752,14 @@ void TopLevelWindow::AddBrowserView(v8::Local<v8::Value> value) {
auto get_that_view = browser_views_.find(browser_view->weak_map_id());
if (get_that_view == browser_views_.end()) {
if (browser_view->web_contents()) {
// If we're reparenting a BrowserView, ensure that it's detached from
// its previous owner window.
auto* owner_window = browser_view->web_contents()->owner_window();
if (owner_window && owner_window != window_.get()) {
owner_window->RemoveBrowserView(browser_view->view());
browser_view->web_contents()->SetOwnerWindow(nullptr);
}

window_->AddBrowserView(browser_view->view());
browser_view->web_contents()->SetOwnerWindow(window_.get());
}
Expand Down Expand Up @@ -1067,9 +1075,14 @@ void TopLevelWindow::ResetBrowserViews() {
v8::Local<v8::Value>::New(isolate(), item.second),
&browser_view) &&
!browser_view.IsEmpty()) {
// There's a chance that the BrowserView may have been reparented - only
// reset if the owner window is *this* window.
if (browser_view->web_contents()) {
window_->RemoveBrowserView(browser_view->view());
browser_view->web_contents()->SetOwnerWindow(nullptr);
auto* owner_window = browser_view->web_contents()->owner_window();
if (owner_window == window_.get()) {
browser_view->web_contents()->SetOwnerWindow(nullptr);
owner_window->RemoveBrowserView(browser_view->view());
}
}
}

Expand Down
22 changes: 22 additions & 0 deletions spec-main/api-browser-view-spec.ts
Expand Up @@ -149,12 +149,34 @@ describe('BrowserView module', () => {
view1.destroy();
view2.destroy();
});

it('does not throw if called multiple times with same view', () => {
view = new BrowserView();
w.addBrowserView(view);
w.addBrowserView(view);
w.addBrowserView(view);
});

it('can handle BrowserView reparenting', async () => {
view = new BrowserView();

w.addBrowserView(view);
view.webContents.loadURL('about:blank');
await emittedOnce(view.webContents, 'did-finish-load');

const w2 = new BrowserWindow({ show: false });
w2.addBrowserView(view);

w.close();

view.webContents.loadURL(`file://${fixtures}/pages/blank.html`);
await emittedOnce(view.webContents, 'did-finish-load');

// Clean up - the afterEach hook assumes the webContents on w is still alive.
w = new BrowserWindow({ show: false });
w2.close();
w2.destroy();
});
});

describe('BrowserWindow.removeBrowserView()', () => {
Expand Down

0 comments on commit 08da5ee

Please sign in to comment.