Fix assertion when loading the PDF extension with begin-frame-scheduling and OSR (issue #1686)

This commit is contained in:
Marshall Greenblatt 2015-08-17 15:48:57 -04:00
parent a63d646e3b
commit 4b491c3a77
6 changed files with 119 additions and 59 deletions

View File

@ -371,6 +371,9 @@ class UploadFolderHelper :
DISALLOW_COPY_AND_ASSIGN(UploadFolderHelper); DISALLOW_COPY_AND_ASSIGN(UploadFolderHelper);
}; };
// Returns the primary OSR host view for the specified |web_contents|. If a
// full-screen host view currently exists then it will be returned. Otherwise,
// the main host view will be returned.
CefRenderWidgetHostViewOSR* GetOSRHostView(content::WebContents* web_contents) { CefRenderWidgetHostViewOSR* GetOSRHostView(content::WebContents* web_contents) {
CefRenderWidgetHostViewOSR* fs_view = CefRenderWidgetHostViewOSR* fs_view =
static_cast<CefRenderWidgetHostViewOSR*>( static_cast<CefRenderWidgetHostViewOSR*>(
@ -2375,7 +2378,7 @@ bool CefBrowserHostImpl::HandleContextMenu(
content::WebContents* CefBrowserHostImpl::GetActionableWebContents() { content::WebContents* CefBrowserHostImpl::GetActionableWebContents() {
if (web_contents() && extensions::ExtensionsEnabled()) { if (web_contents() && extensions::ExtensionsEnabled()) {
content::WebContents* guest_contents = content::WebContents* guest_contents =
extensions::GetGuestForOwnerContents(web_contents()); extensions::GetFullPageGuestForOwnerContents(web_contents());
if (guest_contents) if (guest_contents)
return guest_contents; return guest_contents;
} }

View File

@ -7,28 +7,51 @@
#include "content/browser/browser_plugin/browser_plugin_embedder.h" #include "content/browser/browser_plugin/browser_plugin_embedder.h"
#include "content/browser/browser_plugin/browser_plugin_guest.h" #include "content/browser/browser_plugin/browser_plugin_guest.h"
#include "content/browser/web_contents/web_contents_impl.h" #include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_plugin_guest_manager.h"
namespace extensions { namespace extensions {
content::WebContents* GetGuestForOwnerContents(content::WebContents* guest) { namespace {
content::WebContentsImpl* guest_impl =
static_cast<content::WebContentsImpl*>(guest); bool InsertWebContents(std::vector<content::WebContents*>* vector,
content::BrowserPluginEmbedder* embedder = content::WebContents* web_contents) {
guest_impl->GetBrowserPluginEmbedder(); vector->push_back(web_contents);
if (embedder) { return false; // Continue iterating.
content::BrowserPluginGuest* guest = embedder->GetFullPageGuest(); }
if (guest)
return guest->web_contents(); } // namespace
content::WebContents* GetFullPageGuestForOwnerContents(
content::WebContents* owner) {
content::WebContentsImpl* owner_impl =
static_cast<content::WebContentsImpl*>(owner);
content::BrowserPluginEmbedder* plugin_embedder =
owner_impl->GetBrowserPluginEmbedder();
if (plugin_embedder) {
content::BrowserPluginGuest* plugin_guest =
plugin_embedder->GetFullPageGuest();
if (plugin_guest)
return plugin_guest->web_contents();
} }
return NULL; return NULL;
} }
content::WebContents* GetOwnerForGuestContents(content::WebContents* owner) { void GetAllGuestsForOwnerContents(content::WebContents* owner,
content::WebContentsImpl* owner_impl = std::vector<content::WebContents*>* guests) {
static_cast<content::WebContentsImpl*>(owner); content::BrowserPluginGuestManager* plugin_guest_manager =
content::BrowserPluginGuest* guest = owner_impl->GetBrowserPluginGuest(); owner->GetBrowserContext()->GetGuestManager();
if (guest) plugin_guest_manager->ForEachGuest(owner,
return guest->embedder_web_contents(); base::Bind(InsertWebContents, guests));
}
content::WebContents* GetOwnerForGuestContents(content::WebContents* guest) {
content::WebContentsImpl* guest_impl =
static_cast<content::WebContentsImpl*>(guest);
content::BrowserPluginGuest* plugin_guest =
guest_impl->GetBrowserPluginGuest();
if (plugin_guest)
return plugin_guest->embedder_web_contents();
return NULL; return NULL;
} }

View File

@ -5,17 +5,24 @@
#ifndef CEF_LIBCEF_BROWSER_EXTENSIONS_BROWSER_EXTENSIONS_UTIL_H_ #ifndef CEF_LIBCEF_BROWSER_EXTENSIONS_BROWSER_EXTENSIONS_UTIL_H_
#define CEF_LIBCEF_BROWSER_EXTENSIONS_BROWSER_EXTENSIONS_UTIL_H_ #define CEF_LIBCEF_BROWSER_EXTENSIONS_BROWSER_EXTENSIONS_UTIL_H_
#include <vector>
namespace content { namespace content {
class WebContents; class WebContents;
} }
namespace extensions { namespace extensions {
// Returns the WebContents that owns the specified |guest|, if any. // Returns the full-page guest WebContents for the specified |owner|, if any.
content::WebContents* GetGuestForOwnerContents(content::WebContents* guest); content::WebContents* GetFullPageGuestForOwnerContents(
content::WebContents* owner);
// Returns the guest WebContents for the specified |owner|, if any. // Populates |guests| with all guest WebContents with the specified |owner|.
content::WebContents* GetOwnerForGuestContents(content::WebContents* owner); void GetAllGuestsForOwnerContents(content::WebContents* owner,
std::vector<content::WebContents*>* guests);
// Returns the WebContents that owns the specified |guest|, if any.
content::WebContents* GetOwnerForGuestContents(content::WebContents* guest);
} // namespace extensions } // namespace extensions

View File

@ -498,6 +498,11 @@ CefRenderWidgetHostViewOSR::~CefRenderWidgetHostViewOSR() {
delegated_frame_host_.reset(NULL); delegated_frame_host_.reset(NULL);
compositor_.reset(NULL); compositor_.reset(NULL);
root_layer_.reset(NULL); root_layer_.reset(NULL);
DCHECK(parent_host_view_ == NULL);
DCHECK(popup_host_view_ == NULL);
DCHECK(child_host_view_ == NULL);
DCHECK(guest_host_views_.empty());
} }
// Called for full-screen widgets. // Called for full-screen widgets.
@ -508,7 +513,7 @@ void CefRenderWidgetHostViewOSR::InitAsChild(gfx::NativeView parent_view) {
if (parent_host_view_->child_host_view_) { if (parent_host_view_->child_host_view_) {
// Cancel the previous popup widget. // Cancel the previous popup widget.
parent_host_view_->child_host_view_->CancelChildWidget(); parent_host_view_->child_host_view_->CancelWidget();
} }
parent_host_view_->set_child_host_view(this); parent_host_view_->set_child_host_view(this);
@ -690,7 +695,7 @@ void CefRenderWidgetHostViewOSR::InitAsPopup(
if (parent_host_view_->popup_host_view_) { if (parent_host_view_->popup_host_view_) {
// Cancel the previous popup widget. // Cancel the previous popup widget.
parent_host_view_->popup_host_view_->CancelPopupWidget(); parent_host_view_->popup_host_view_->CancelWidget();
} }
parent_host_view_->set_popup_host_view(this); parent_host_view_->set_popup_host_view(this);
@ -792,6 +797,7 @@ void CefRenderWidgetHostViewOSR::RenderProcessGone(
parent_host_view_ = NULL; parent_host_view_ = NULL;
popup_host_view_ = NULL; popup_host_view_ = NULL;
child_host_view_ = NULL; child_host_view_ = NULL;
guest_host_views_.clear();
} }
void CefRenderWidgetHostViewOSR::Destroy() { void CefRenderWidgetHostViewOSR::Destroy() {
@ -799,15 +805,14 @@ void CefRenderWidgetHostViewOSR::Destroy() {
is_destroyed_ = true; is_destroyed_ = true;
if (has_parent_) { if (has_parent_) {
if (IsPopupWidget()) CancelWidget();
CancelPopupWidget();
else
CancelChildWidget();
} else { } else {
if (popup_host_view_) if (popup_host_view_)
popup_host_view_->CancelPopupWidget(); popup_host_view_->CancelWidget();
if (child_host_view_) if (child_host_view_)
child_host_view_->CancelChildWidget(); child_host_view_->CancelWidget();
for (auto guest_host_view : guest_host_views_)
guest_host_view->CancelWidget();
Hide(); Hide();
} }
} }
@ -978,6 +983,8 @@ bool CefRenderWidgetHostViewOSR::OnMessageReceived(const IPC::Message& msg) {
} }
void CefRenderWidgetHostViewOSR::OnSetNeedsBeginFrames(bool enabled) { void CefRenderWidgetHostViewOSR::OnSetNeedsBeginFrames(bool enabled) {
SetFrameRate();
// Start/stop the timer that sends BeginFrame requests. // Start/stop the timer that sends BeginFrame requests.
begin_frame_timer_->SetActive(enabled); begin_frame_timer_->SetActive(enabled);
if (software_output_device_) { if (software_output_device_) {
@ -1094,6 +1101,10 @@ void CefRenderWidgetHostViewOSR::OnScreenInfoChanged() {
// We might want to change the cursor scale factor here as well - see the // We might want to change the cursor scale factor here as well - see the
// cache for the current_cursor_, as passed by UpdateCursor from the renderer // cache for the current_cursor_, as passed by UpdateCursor from the renderer
// in the rwhv_aura (current_cursor_.SetScaleFactor) // in the rwhv_aura (current_cursor_.SetScaleFactor)
// Notify the guest hosts if any.
for (auto guest_host_view : guest_host_views_)
guest_host_view->OnScreenInfoChanged();
} }
void CefRenderWidgetHostViewOSR::Invalidate( void CefRenderWidgetHostViewOSR::Invalidate(
@ -1174,7 +1185,7 @@ void CefRenderWidgetHostViewOSR::SendMouseWheelEvent(
// Execute asynchronously to avoid deleting the widget from inside some // Execute asynchronously to avoid deleting the widget from inside some
// other callback. // other callback.
CEF_POST_TASK(CEF_UIT, CEF_POST_TASK(CEF_UIT,
base::Bind(&CefRenderWidgetHostViewOSR::CancelPopupWidget, base::Bind(&CefRenderWidgetHostViewOSR::CancelWidget,
popup_host_view_->weak_ptr_factory_.GetWeakPtr())); popup_host_view_->weak_ptr_factory_.GetWeakPtr()));
} }
} }
@ -1205,6 +1216,10 @@ void CefRenderWidgetHostViewOSR::SendFocusEvent(bool focus) {
void CefRenderWidgetHostViewOSR::UpdateFrameRate() { void CefRenderWidgetHostViewOSR::UpdateFrameRate() {
frame_rate_threshold_ms_ = 0; frame_rate_threshold_ms_ = 0;
SetFrameRate(); SetFrameRate();
// Notify the guest hosts if any.
for (auto guest_host_view : guest_host_views_)
guest_host_view->UpdateFrameRate();
} }
void CefRenderWidgetHostViewOSR::HoldResize() { void CefRenderWidgetHostViewOSR::HoldResize() {
@ -1258,6 +1273,16 @@ void CefRenderWidgetHostViewOSR::OnPaint(
ReleaseResize(); ReleaseResize();
} }
void CefRenderWidgetHostViewOSR::AddGuestHostView(
CefRenderWidgetHostViewOSR* guest_host) {
guest_host_views_.insert(guest_host);
}
void CefRenderWidgetHostViewOSR::RemoveGuestHostView(
CefRenderWidgetHostViewOSR* guest_host) {
guest_host_views_.erase(guest_host);
}
// static // static
int CefRenderWidgetHostViewOSR::ClampFrameRate(int frame_rate) { int CefRenderWidgetHostViewOSR::ClampFrameRate(int frame_rate) {
if (frame_rate < 1) if (frame_rate < 1)
@ -1268,16 +1293,21 @@ int CefRenderWidgetHostViewOSR::ClampFrameRate(int frame_rate) {
} }
void CefRenderWidgetHostViewOSR::SetFrameRate() { void CefRenderWidgetHostViewOSR::SetFrameRate() {
DCHECK(browser_impl_.get()); CefRefPtr<CefBrowserHostImpl> browser;
if (!browser_impl_.get()) if (parent_host_view_) {
return; // Use the same frame rate as the embedding browser.
browser = parent_host_view_->browser_impl_;
} else {
browser = browser_impl_;
}
CHECK(browser);
// Only set the frame rate one time. // Only set the frame rate one time.
if (frame_rate_threshold_ms_ != 0) if (frame_rate_threshold_ms_ != 0)
return; return;
const int frame_rate = const int frame_rate =
ClampFrameRate(browser_impl_->settings().windowless_frame_rate); ClampFrameRate(browser->settings().windowless_frame_rate);
frame_rate_threshold_ms_ = 1000 / frame_rate; frame_rate_threshold_ms_ = 1000 / frame_rate;
// Configure the VSync interval for the browser process. // Configure the VSync interval for the browser process.
@ -1377,15 +1407,13 @@ void CefRenderWidgetHostViewOSR::SendBeginFrame(base::TimeTicks frame_time,
vsync_period, cc::BeginFrameArgs::NORMAL))); vsync_period, cc::BeginFrameArgs::NORMAL)));
} }
void CefRenderWidgetHostViewOSR::CancelPopupWidget() { void CefRenderWidgetHostViewOSR::CancelWidget() {
DCHECK(IsPopupWidget());
if (render_widget_host_) if (render_widget_host_)
render_widget_host_->LostCapture(); render_widget_host_->LostCapture();
Hide(); Hide();
if (browser_impl_.get()) { if (IsPopupWidget() && browser_impl_.get()) {
CefRefPtr<CefRenderHandler> handler = CefRefPtr<CefRenderHandler> handler =
browser_impl_->client()->GetRenderHandler(); browser_impl_->client()->GetRenderHandler();
if (handler.get()) if (handler.get())
@ -1394,25 +1422,12 @@ void CefRenderWidgetHostViewOSR::CancelPopupWidget() {
} }
if (parent_host_view_) { if (parent_host_view_) {
parent_host_view_->set_popup_host_view(NULL); if (parent_host_view_->popup_host_view_ == this)
parent_host_view_ = NULL; parent_host_view_->set_popup_host_view(NULL);
} else if (parent_host_view_->child_host_view_ == this)
parent_host_view_->set_child_host_view(NULL);
if (render_widget_host_ && !is_destroyed_) { else
is_destroyed_ = true; parent_host_view_->RemoveGuestHostView(this);
// Results in a call to Destroy().
render_widget_host_->Shutdown();
}
}
void CefRenderWidgetHostViewOSR::CancelChildWidget() {
if (render_widget_host_)
render_widget_host_->LostCapture();
Hide();
if (parent_host_view_) {
parent_host_view_->set_child_host_view(NULL);
parent_host_view_ = NULL; parent_host_view_ = NULL;
} }

View File

@ -7,6 +7,7 @@
#define CEF_LIBCEF_BROWSER_RENDER_WIDGET_HOST_VIEW_OSR_H_ #define CEF_LIBCEF_BROWSER_RENDER_WIDGET_HOST_VIEW_OSR_H_
#pragma once #pragma once
#include <set>
#include <vector> #include <vector>
#include "include/cef_base.h" #include "include/cef_base.h"
@ -255,6 +256,9 @@ class CefRenderWidgetHostViewOSR
gfx::Range* actual_range) const; gfx::Range* actual_range) const;
#endif // defined(OS_MACOSX) #endif // defined(OS_MACOSX)
void AddGuestHostView(CefRenderWidgetHostViewOSR* guest_host);
void RemoveGuestHostView(CefRenderWidgetHostViewOSR* guest_host);
CefRefPtr<CefBrowserHostImpl> browser_impl() const { return browser_impl_; } CefRefPtr<CefBrowserHostImpl> browser_impl() const { return browser_impl_; }
void set_browser_impl(CefRefPtr<CefBrowserHostImpl> browser) { void set_browser_impl(CefRefPtr<CefBrowserHostImpl> browser) {
browser_impl_ = browser; browser_impl_ = browser;
@ -286,8 +290,7 @@ class CefRenderWidgetHostViewOSR
void SendBeginFrame(base::TimeTicks frame_time, void SendBeginFrame(base::TimeTicks frame_time,
base::TimeDelta vsync_period); base::TimeDelta vsync_period);
void CancelPopupWidget(); void CancelWidget();
void CancelChildWidget();
void OnScrollOffsetChanged(); void OnScrollOffsetChanged();
@ -357,6 +360,7 @@ class CefRenderWidgetHostViewOSR
CefRenderWidgetHostViewOSR* parent_host_view_; CefRenderWidgetHostViewOSR* parent_host_view_;
CefRenderWidgetHostViewOSR* popup_host_view_; CefRenderWidgetHostViewOSR* popup_host_view_;
CefRenderWidgetHostViewOSR* child_host_view_; CefRenderWidgetHostViewOSR* child_host_view_;
std::set<CefRenderWidgetHostViewOSR*> guest_host_views_;
CefRefPtr<CefBrowserHostImpl> browser_impl_; CefRefPtr<CefBrowserHostImpl> browser_impl_;

View File

@ -119,8 +119,16 @@ content::RenderWidgetHostViewBase* CefWebContentsViewOSR::CreateViewForWidget(
if (guest_) { if (guest_) {
// Based on WebContentsViewGuest::CreateViewForWidget. // Based on WebContentsViewGuest::CreateViewForWidget.
content::WebContents* embedder_web_contents =
guest_->embedder_web_contents();
CefRenderWidgetHostViewOSR* embedder_host_view =
static_cast<CefRenderWidgetHostViewOSR*>(
embedder_web_contents->GetRenderViewHost()->GetView());
CefRenderWidgetHostViewOSR* platform_widget = CefRenderWidgetHostViewOSR* platform_widget =
new CefRenderWidgetHostViewOSR(render_widget_host, NULL); new CefRenderWidgetHostViewOSR(render_widget_host, embedder_host_view);
embedder_host_view->AddGuestHostView(platform_widget);
return new content::RenderWidgetHostViewGuest( return new content::RenderWidgetHostViewGuest(
render_widget_host, render_widget_host,
guest_, guest_,