Merge branch 'master' into roller/chromium/master

This commit is contained in:
John Kleinschmidt 2021-03-15 18:43:25 -04:00
parent 8f4e362d8f
commit 57a8781c01
137 changed files with 876 additions and 4289 deletions

View file

@ -910,51 +910,49 @@ void WebContents::InitWithWebContents(content::WebContents* web_contents,
}
WebContents::~WebContents() {
MarkDestroyed();
// The destroy() is called.
if (inspectable_web_contents_) {
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
if (type_ == Type::kBackgroundPage) {
// Background pages are owned by extensions::ExtensionHost
inspectable_web_contents_->ReleaseWebContents();
}
#endif
inspectable_web_contents_->GetView()->SetDelegate(nullptr);
if (web_contents()) {
RenderViewDeleted(web_contents()->GetRenderViewHost());
}
if (type_ == Type::kBrowserWindow && owner_window()) {
// For BrowserWindow we should close the window and clean up everything
// before WebContents is destroyed.
for (ExtendedWebContentsObserver& observer : observers_)
observer.OnCloseContents();
// BrowserWindow destroys WebContents asynchronously, manually emit the
// destroyed event here.
WebContentsDestroyed();
} else if (Browser::Get()->is_shutting_down()) {
// Destroy WebContents directly when app is shutting down.
DestroyWebContents(false /* async */);
} else {
// Destroy WebContents asynchronously unless app is shutting down,
// because destroy() might be called inside WebContents's event handler.
bool is_browser_view = type_ == Type::kBrowserView;
DestroyWebContents(!(IsGuest() || is_browser_view) /* async */);
// The WebContentsDestroyed will not be called automatically because we
// destroy the webContents in the next tick. So we have to manually
// call it here to make sure "destroyed" event is emitted.
WebContentsDestroyed();
}
if (!inspectable_web_contents_) {
WebContentsDestroyed();
return;
}
}
void WebContents::DestroyWebContents(bool async) {
if (guest_delegate_)
guest_delegate_->WillDestroy();
// This event is only for internal use, which is emitted when WebContents is
// being destroyed.
Emit("will-destroy");
ResetManagedWebContents(async);
// For guest view based on OOPIF, the WebContents is released by the embedder
// frame, and we need to clear the reference to the memory.
bool not_owned_by_this = IsGuest() && attached_;
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
// And background pages are owned by extensions::ExtensionHost.
if (type_ == Type::kBackgroundPage)
not_owned_by_this = true;
#endif
if (not_owned_by_this) {
inspectable_web_contents_->ReleaseWebContents();
WebContentsDestroyed();
}
// InspectableWebContents will be automatically destroyed.
}
void WebContents::Destroy() {
// The content::WebContents should be destroyed asyncronously when possible
// as user may choose to destroy WebContents during an event of it.
if (Browser::Get()->is_shutting_down() || IsGuest() ||
type_ == Type::kBrowserView) {
delete this;
} else {
base::PostTask(FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(
[](base::WeakPtr<WebContents> contents) {
if (contents)
delete contents.get();
},
GetWeakPtr()));
}
}
bool WebContents::DidAddMessageToConsole(
@ -1060,11 +1058,21 @@ void WebContents::AddNewContents(
v8::HandleScope handle_scope(isolate);
auto api_web_contents =
CreateAndTake(isolate, std::move(new_contents), Type::kBrowserWindow);
// We call RenderFrameCreated here as at this point the empty "about:blank"
// render frame has already been created. If the window never navigates again
// RenderFrameCreated won't be called and certain prefs like
// "kBackgroundColor" will not be applied.
auto* frame = api_web_contents->MainFrame();
if (frame) {
api_web_contents->HandleNewRenderFrame(frame);
}
if (Emit("-add-new-contents", api_web_contents, disposition, user_gesture,
initial_rect.x(), initial_rect.y(), initial_rect.width(),
initial_rect.height(), tracker->url, tracker->frame_name,
tracker->referrer, tracker->raw_features, tracker->body)) {
api_web_contents->DestroyWebContents(false /* async */);
api_web_contents->Destroy();
}
}
@ -1134,8 +1142,6 @@ void WebContents::CloseContents(content::WebContents* source) {
autofill_driver_factory->CloseAllPopups();
}
if (inspectable_web_contents_)
inspectable_web_contents_->GetView()->SetDelegate(nullptr);
for (ExtendedWebContentsObserver& observer : observers_)
observer.OnCloseContents();
}
@ -1351,7 +1357,7 @@ void WebContents::BeforeUnloadFired(bool proceed,
// there are two virtual functions named BeforeUnloadFired.
}
void WebContents::RenderFrameCreated(
void WebContents::HandleNewRenderFrame(
content::RenderFrameHost* render_frame_host) {
auto* rwhv = render_frame_host->GetView();
if (!rwhv)
@ -1380,6 +1386,11 @@ void WebContents::RenderFrameCreated(
WebFrameMain::RenderFrameCreated(render_frame_host);
}
void WebContents::RenderFrameCreated(
content::RenderFrameHost* render_frame_host) {
HandleNewRenderFrame(render_frame_host);
}
void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) {
// This event is necessary for tracking any states with respect to
// intermediate render view hosts aka speculative render view hosts. Currently
@ -1812,21 +1823,6 @@ void WebContents::SetOwnerWindow(content::WebContents* web_contents,
#endif
}
void WebContents::ResetManagedWebContents(bool async) {
if (async) {
// Browser context should be destroyed only after the WebContents,
// this is guaranteed in the sync mode by the order of declaration,
// in the async version we maintain a reference until the WebContents
// is destroyed.
// //electron/patches/chromium/content_browser_main_loop.patch
// is required to get the right quit closure for the main message loop.
base::ThreadTaskRunnerHandle::Get()->DeleteSoon(
FROM_HERE, inspectable_web_contents_.release());
} else {
inspectable_web_contents_.reset();
}
}
content::WebContents* WebContents::GetWebContents() const {
if (!inspectable_web_contents_)
return nullptr;
@ -1839,7 +1835,8 @@ content::WebContents* WebContents::GetDevToolsWebContents() const {
return inspectable_web_contents_->GetDevToolsWebContents();
}
void WebContents::MarkDestroyed() {
void WebContents::WebContentsDestroyed() {
// Clear the pointer stored in wrapper.
if (GetAllWebContents().Lookup(id_))
GetAllWebContents().Remove(id_);
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
@ -1848,52 +1845,9 @@ void WebContents::MarkDestroyed() {
if (!GetWrapper(isolate).ToLocal(&wrapper))
return;
wrapper->SetAlignedPointerInInternalField(0, nullptr);
}
// There are three ways of destroying a webContents:
// 1. call webContents.destroy();
// 2. garbage collection;
// 3. user closes the window of webContents;
// 4. the embedder detaches the frame.
// For webview only #4 will happen, for BrowserWindow both #1 and #3 may
// happen. The #2 should never happen for webContents, because webview is
// managed by GuestViewManager, and BrowserWindow's webContents is managed
// by api::BrowserWindow.
// For #1, the destructor will do the cleanup work and we only need to make
// sure "destroyed" event is emitted. For #3, the content::WebContents will
// be destroyed on close, and WebContentsDestroyed would be called for it, so
// we need to make sure the api::WebContents is also deleted.
// For #4, the WebContents will be destroyed by embedder.
void WebContents::WebContentsDestroyed() {
// Give chance for guest delegate to cleanup its observers
// since the native class is only destroyed in the next tick.
if (guest_delegate_)
guest_delegate_->WillDestroy();
// Cleanup relationships with other parts.
// We can not call Destroy here because we need to call Emit first, but we
// also do not want any method to be used, so just mark as destroyed here.
MarkDestroyed();
Observe(nullptr); // this->web_contents() will return nullptr
Observe(nullptr);
Emit("destroyed");
// For guest view based on OOPIF, the WebContents is released by the embedder
// frame, and we need to clear the reference to the memory.
if (IsGuest() && inspectable_web_contents_) {
inspectable_web_contents_->ReleaseWebContents();
ResetManagedWebContents(false);
}
// Destroy the native class in next tick.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(
[](base::WeakPtr<WebContents> wc) {
if (wc)
delete wc.get();
},
GetWeakPtr()));
}
void WebContents::NavigationEntryCommitted(
@ -2820,6 +2774,18 @@ v8::Local<v8::Promise> WebContents::CapturePage(gin::Arguments* args) {
return handle;
}
#if !defined(OS_MAC)
// If the view's renderer is suspended this may fail on Windows/Linux -
// bail if so. See CopyFromSurface in
// content/public/browser/render_widget_host_view.h.
auto* rfh = web_contents()->GetMainFrame();
if (rfh &&
rfh->GetVisibilityState() == blink::mojom::PageVisibilityState::kHidden) {
promise.Resolve(gfx::Image());
return handle;
}
#endif // defined(OS_MAC)
// Capture full page if user doesn't specify a |rect|.
const gfx::Size view_size =
rect.IsEmpty() ? view->GetViewBounds().size() : rect.size();
@ -2886,6 +2852,7 @@ bool WebContents::IsGuest() const {
void WebContents::AttachToIframe(content::WebContents* embedder_web_contents,
int embedder_frame_id) {
attached_ = true;
if (guest_delegate_)
guest_delegate_->AttachToIframe(embedder_web_contents, embedder_frame_id);
}
@ -3538,17 +3505,11 @@ v8::Local<v8::ObjectTemplate> WebContents::FillObjectTemplate(
gin::CreateFunctionTemplate(
isolate, base::BindRepeating(&gin_helper::Destroyable::IsDestroyed),
options));
templ->Set(
gin::StringToSymbol(isolate, "destroy"),
gin::CreateFunctionTemplate(
isolate, base::BindRepeating([](gin::Handle<WebContents> handle) {
delete handle.get();
}),
options));
// We use gin_helper::ObjectTemplateBuilder instead of
// gin::ObjectTemplateBuilder here to handle the fact that WebContents is
// destroyable.
return gin_helper::ObjectTemplateBuilder(isolate, templ)
.SetMethod("destroy", &WebContents::Destroy)
.SetMethod("getBackgroundThrottling",
&WebContents::GetBackgroundThrottling)
.SetMethod("setBackgroundThrottling",