diff --git a/libcef/browser/browser_host_impl.cc b/libcef/browser/browser_host_impl.cc index 0d865c3b7..fdb5e5900 100644 --- a/libcef/browser/browser_host_impl.cc +++ b/libcef/browser/browser_host_impl.cc @@ -629,13 +629,13 @@ CefRefPtr CefBrowserHostImpl::GetBrowserForView( return GetBrowserForHost(render_view_host); } else { // Use the thread-safe approach. + bool is_guest_view = false; scoped_refptr info = CefContentBrowserClient::Get()->GetBrowserInfoForView( - render_process_id, - render_routing_id); - if (info.get()) { + render_process_id, render_routing_id, &is_guest_view); + if (info.get() && !is_guest_view) { CefRefPtr browser = info->browser(); - if (!browser.get() && !info->is_mime_handler_view()) { + if (!browser.get()) { LOG(WARNING) << "Found browser id " << info->browser_id() << " but no browser object matching view process id " << render_process_id << " and routing id " << @@ -662,13 +662,13 @@ CefRefPtr CefBrowserHostImpl::GetBrowserForFrame( return GetBrowserForHost(render_frame_host); } else { // Use the thread-safe approach. + bool is_guest_view = false; scoped_refptr info = CefContentBrowserClient::Get()->GetBrowserInfoForFrame( - render_process_id, - render_routing_id); - if (info.get()) { + render_process_id, render_routing_id, &is_guest_view); + if (info.get() && !is_guest_view) { CefRefPtr browser = info->browser(); - if (!browser.get() && !info->is_mime_handler_view()) { + if (!browser.get()) { LOG(WARNING) << "Found browser id " << info->browser_id() << " but no browser object matching frame process id " << render_process_id << " and routing id " << @@ -2220,6 +2220,8 @@ void CefBrowserHostImpl::DragSourceEndedAt( // content::WebContentsDelegate methods. // ----------------------------------------------------------------------------- +// |source| may be NULL if the navigation originates from a guest view via +// CefContentBrowserClient::CanCreateWindow. content::WebContents* CefBrowserHostImpl::OpenURLFromTab( content::WebContents* source, const content::OpenURLParams& params) { @@ -2484,12 +2486,17 @@ void CefBrowserHostImpl::WebContentsCreated( content::RenderFrameHost* main_frame_host = new_contents->GetMainFrame(); CefWindowHandle opener = kNullWindowHandle; + bool is_guest_view = false; scoped_refptr info = CefContentBrowserClient::Get()->GetOrCreateBrowserInfo( view_host->GetProcess()->GetID(), view_host->GetRoutingID(), main_frame_host->GetProcess()->GetID(), - main_frame_host->GetRoutingID()); + main_frame_host->GetRoutingID(), + &is_guest_view); + + // A CefBrowser should never be created for a guest view WebContents. + CHECK(!is_guest_view); if (source_contents) { DCHECK(info->is_popup()); @@ -2644,21 +2651,23 @@ bool CefBrowserHostImpl::CheckMediaAccessPermission( void CefBrowserHostImpl::RenderFrameCreated( content::RenderFrameHost* render_frame_host) { - browser_info_->add_render_frame_id(render_frame_host->GetProcess()->GetID(), - render_frame_host->GetRoutingID()); + browser_info_->render_id_manager()->add_render_frame_id( + render_frame_host->GetProcess()->GetID(), + render_frame_host->GetRoutingID()); } void CefBrowserHostImpl::RenderFrameDeleted( content::RenderFrameHost* render_frame_host) { - browser_info_->remove_render_frame_id( + browser_info_->render_id_manager()->remove_render_frame_id( render_frame_host->GetProcess()->GetID(), render_frame_host->GetRoutingID()); } void CefBrowserHostImpl::RenderViewCreated( content::RenderViewHost* render_view_host) { - browser_info_->add_render_view_id(render_view_host->GetProcess()->GetID(), - render_view_host->GetRoutingID()); + browser_info_->render_id_manager()->add_render_view_id( + render_view_host->GetProcess()->GetID(), + render_view_host->GetRoutingID()); // May be already registered if the renderer crashed previously. if (!registrar_->IsRegistered( @@ -2671,8 +2680,9 @@ void CefBrowserHostImpl::RenderViewCreated( void CefBrowserHostImpl::RenderViewDeleted( content::RenderViewHost* render_view_host) { - browser_info_->remove_render_view_id(render_view_host->GetProcess()->GetID(), - render_view_host->GetRoutingID()); + browser_info_->render_id_manager()->remove_render_view_id( + render_view_host->GetProcess()->GetID(), + render_view_host->GetRoutingID()); if (registrar_->IsRegistered( this, content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE, diff --git a/libcef/browser/browser_host_impl.h b/libcef/browser/browser_host_impl.h index fa7ad0877..d8b671f76 100644 --- a/libcef/browser/browser_host_impl.h +++ b/libcef/browser/browser_host_impl.h @@ -15,6 +15,7 @@ #include "include/cef_browser.h" #include "include/cef_client.h" #include "include/cef_frame.h" +#include "libcef/browser/browser_info.h" #include "libcef/browser/frame_host_impl.h" #include "libcef/browser/javascript_dialog_manager.h" #include "libcef/browser/menu_creator.h" @@ -303,6 +304,7 @@ class CefBrowserHostImpl : public CefBrowserHost, // Thread safe accessors. const CefBrowserSettings& settings() const { return settings_; } CefRefPtr client() const { return client_; } + scoped_refptr browser_info() const { return browser_info_; } int browser_id() const; #if defined(USE_AURA) diff --git a/libcef/browser/browser_info.cc b/libcef/browser/browser_info.cc index c3af71f23..83c7265fc 100644 --- a/libcef/browser/browser_info.cc +++ b/libcef/browser/browser_info.cc @@ -3,78 +3,59 @@ // be found in the LICENSE file. #include "libcef/browser/browser_info.h" + +#include "libcef/browser/browser_host_impl.h" + #include "ipc/ipc_message.h" -CefBrowserInfo::CefBrowserInfo(int browser_id, bool is_popup) - : browser_id_(browser_id), - is_popup_(is_popup), - is_windowless_(false), - is_mime_handler_view_(false) { - DCHECK_GT(browser_id, 0); +// CefBrowserInfo::RenderIDManager + +CefBrowserInfo::RenderIDManager::RenderIDManager(base::Lock* lock) + : lock_(lock) { + DCHECK(lock); } -CefBrowserInfo::~CefBrowserInfo() { -} - -void CefBrowserInfo::set_windowless(bool windowless) { - is_windowless_ = windowless; -} - -void CefBrowserInfo::set_mime_handler_view(bool mime_handler_view) { - is_mime_handler_view_ = mime_handler_view; -} - -void CefBrowserInfo::add_render_view_id( +void CefBrowserInfo::RenderIDManager::add_render_view_id( int render_process_id, int render_routing_id) { add_render_id(&render_view_id_set_, render_process_id, render_routing_id); } -void CefBrowserInfo::add_render_frame_id( +void CefBrowserInfo::RenderIDManager::add_render_frame_id( int render_process_id, int render_routing_id) { add_render_id(&render_frame_id_set_, render_process_id, render_routing_id); } -void CefBrowserInfo::remove_render_view_id( +void CefBrowserInfo::RenderIDManager::remove_render_view_id( int render_process_id, int render_routing_id) { remove_render_id(&render_view_id_set_, render_process_id, render_routing_id); } -void CefBrowserInfo::remove_render_frame_id( +void CefBrowserInfo::RenderIDManager::remove_render_frame_id( int render_process_id, int render_routing_id) { remove_render_id(&render_frame_id_set_, render_process_id, render_routing_id); } -bool CefBrowserInfo::is_render_view_id_match( +bool CefBrowserInfo::RenderIDManager::is_render_view_id_match( int render_process_id, int render_routing_id) { return is_render_id_match(&render_view_id_set_, render_process_id, render_routing_id); } -bool CefBrowserInfo::is_render_frame_id_match( +bool CefBrowserInfo::RenderIDManager::is_render_frame_id_match( int render_process_id, int render_routing_id) { return is_render_id_match(&render_frame_id_set_, render_process_id, render_routing_id); } -CefRefPtr CefBrowserInfo::browser() { - base::AutoLock lock_scope(lock_); - return browser_; -} - -void CefBrowserInfo::set_browser(CefRefPtr browser) { - base::AutoLock lock_scope(lock_); - browser_ = browser; -} - -void CefBrowserInfo::add_render_id(RenderIdSet* id_set, - int render_process_id, - int render_routing_id) { +void CefBrowserInfo::RenderIDManager::add_render_id(RenderIdSet* id_set, + int render_process_id, + int render_routing_id) { DCHECK_GT(render_process_id, 0); DCHECK_GT(render_routing_id, 0); - base::AutoLock lock_scope(lock_); + base::AutoLock lock_scope(*lock_); if (!id_set->empty()) { RenderIdSet::const_iterator it = @@ -86,13 +67,13 @@ void CefBrowserInfo::add_render_id(RenderIdSet* id_set, id_set->insert(std::make_pair(render_process_id, render_routing_id)); } -void CefBrowserInfo::remove_render_id(RenderIdSet* id_set, - int render_process_id, - int render_routing_id) { +void CefBrowserInfo::RenderIDManager::remove_render_id(RenderIdSet* id_set, + int render_process_id, + int render_routing_id) { DCHECK_GT(render_process_id, 0); DCHECK_GT(render_routing_id, 0); - base::AutoLock lock_scope(lock_); + base::AutoLock lock_scope(*lock_); DCHECK(!id_set->empty()); if (id_set->empty()) @@ -103,10 +84,11 @@ void CefBrowserInfo::remove_render_id(RenderIdSet* id_set, DCHECK(erased); } -bool CefBrowserInfo::is_render_id_match(const RenderIdSet* id_set, - int render_process_id, - int render_routing_id) { - base::AutoLock lock_scope(lock_); +bool CefBrowserInfo::RenderIDManager::is_render_id_match( + const RenderIdSet* id_set, + int render_process_id, + int render_routing_id) { + base::AutoLock lock_scope(*lock_); if (id_set->empty()) return false; @@ -115,3 +97,32 @@ bool CefBrowserInfo::is_render_id_match(const RenderIdSet* id_set, id_set->find(std::make_pair(render_process_id, render_routing_id)); return (it != id_set->end()); } + + +// CefBrowserInfo + +CefBrowserInfo::CefBrowserInfo(int browser_id, bool is_popup) + : browser_id_(browser_id), + is_popup_(is_popup), + is_windowless_(false), + render_id_manager_(&lock_), + guest_render_id_manager_(&lock_) { + DCHECK_GT(browser_id, 0); +} + +CefBrowserInfo::~CefBrowserInfo() { +} + +void CefBrowserInfo::set_windowless(bool windowless) { + is_windowless_ = windowless; +} + +CefRefPtr CefBrowserInfo::browser() { + base::AutoLock lock_scope(lock_); + return browser_; +} + +void CefBrowserInfo::set_browser(CefRefPtr browser) { + base::AutoLock lock_scope(lock_); + browser_ = browser; +} diff --git a/libcef/browser/browser_info.h b/libcef/browser/browser_info.h index 1d7d9f3eb..de3c8d413 100644 --- a/libcef/browser/browser_info.h +++ b/libcef/browser/browser_info.h @@ -8,8 +8,12 @@ #include -#include "libcef/browser/browser_host_impl.h" +#include "include/internal/cef_ptr.h" + #include "base/memory/ref_counted.h" +#include "base/synchronization/lock.h" + +class CefBrowserHostImpl; // CefBrowserInfo is used to associate a browser ID and render view/process // IDs with a particular CefBrowserHostImpl. Render view/process IDs may change @@ -19,27 +23,70 @@ // be created directly. class CefBrowserInfo : public base::RefCountedThreadSafe { public: + class RenderIDManager { + public: + explicit RenderIDManager(base::Lock* lock); + + // Adds an ID pair if it doesn't already exist. + void add_render_view_id(int render_process_id, int render_routing_id); + void add_render_frame_id(int render_process_id, int render_routing_id); + + // Remove an ID pair if it exists. + void remove_render_view_id(int render_process_id, int render_routing_id); + void remove_render_frame_id(int render_process_id, int render_routing_id); + + // Returns true if this browser matches the specified ID pair. + bool is_render_view_id_match(int render_process_id, int render_routing_id); + bool is_render_frame_id_match(int render_process_id, int render_routing_id); + + private: + typedef std::set > RenderIdSet; + + void add_render_id(RenderIdSet* id_set, + int render_process_id, + int render_routing_id); + void remove_render_id(RenderIdSet* id_set, + int render_process_id, + int render_routing_id); + bool is_render_id_match(const RenderIdSet* id_set, + int render_process_id, + int render_routing_id); + + base::Lock* lock_; + + // The below members must be protected by |lock_|. + + // Set of mapped (process_id, routing_id) pairs. Keeping this set is + // necessary for the following reasons: + // 1. When navigating cross-origin the new (pending) RenderViewHost will be + // created before the old (current) RenderViewHost is destroyed. + // 2. When canceling and asynchronously continuing navigation of the same + // URL a new RenderViewHost may be created for the first (canceled) + // navigation and then destroyed as a result of the second (allowed) + // navigation. + // 3. Out-of-process iframes have their own render IDs which must also be + // associated with the host browser. + RenderIdSet render_view_id_set_; + RenderIdSet render_frame_id_set_; + }; + CefBrowserInfo(int browser_id, bool is_popup); int browser_id() const { return browser_id_; }; bool is_popup() const { return is_popup_; } bool is_windowless() const { return is_windowless_; } - bool is_mime_handler_view() const { return is_mime_handler_view_; } void set_windowless(bool windowless); - void set_mime_handler_view(bool mime_handler_view); - // Adds an ID pair if it doesn't already exist. - void add_render_view_id(int render_process_id, int render_routing_id); - void add_render_frame_id(int render_process_id, int render_routing_id); + // Returns the render ID manager for this browser. + RenderIDManager* render_id_manager() { + return &render_id_manager_; + } - // Remove an ID pair if it exists. - void remove_render_view_id(int render_process_id, int render_routing_id); - void remove_render_frame_id(int render_process_id, int render_routing_id); - - // Returns true if this browser matches the specified ID pair. - bool is_render_view_id_match(int render_process_id, int render_routing_id); - bool is_render_frame_id_match(int render_process_id, int render_routing_id); + // Returns the render ID manager for guest views owned by this browser. + RenderIDManager* guest_render_id_manager() { + return &guest_render_id_manager_; + } CefRefPtr browser(); void set_browser(CefRefPtr browser); @@ -49,38 +96,16 @@ class CefBrowserInfo : public base::RefCountedThreadSafe { ~CefBrowserInfo(); - typedef std::set > RenderIdSet; - - void add_render_id(RenderIdSet* id_set, - int render_process_id, - int render_routing_id); - void remove_render_id(RenderIdSet* id_set, - int render_process_id, - int render_routing_id); - bool is_render_id_match(const RenderIdSet* id_set, - int render_process_id, - int render_routing_id); - int browser_id_; bool is_popup_; bool is_windowless_; - bool is_mime_handler_view_; base::Lock lock_; // The below members must be protected by |lock_|. - // Set of mapped (process_id, routing_id) pairs. Keeping this set is - // necessary for the following reasons: - // 1. When navigating cross-origin the new (pending) RenderViewHost will be - // created before the old (current) RenderViewHost is destroyed. - // 2. When canceling and asynchronously continuing navigation of the same URL - // a new RenderViewHost may be created for the first (canceled) navigation - // and then destroyed as a result of the second (allowed) navigation. - // 3. Out-of-process iframes have their own render IDs which must also be - // associated with the host browser. - RenderIdSet render_view_id_set_; - RenderIdSet render_frame_id_set_; + RenderIDManager render_id_manager_; + RenderIDManager guest_render_id_manager_; // May be NULL if the browser has not yet been created or if the browser has // been destroyed. diff --git a/libcef/browser/browser_message_filter.cc b/libcef/browser/browser_message_filter.cc index ca575d79f..5370891a6 100644 --- a/libcef/browser/browser_message_filter.cc +++ b/libcef/browser/browser_message_filter.cc @@ -97,11 +97,11 @@ void CefBrowserMessageFilter::OnGetNewBrowserInfo( host_->GetID(), render_view_routing_id, host_->GetID(), - render_frame_routing_id); + render_frame_routing_id, + ¶ms->is_guest_view); params->browser_id = info->browser_id(); params->is_popup = info->is_popup(); params->is_windowless = info->is_windowless(); - params->is_mime_handler_view = info->is_mime_handler_view(); } void CefBrowserMessageFilter::OnCreateWindow( diff --git a/libcef/browser/content_browser_client.cc b/libcef/browser/content_browser_client.cc index 162642ed8..968c82765 100644 --- a/libcef/browser/content_browser_client.cc +++ b/libcef/browser/content_browser_client.cc @@ -50,6 +50,7 @@ #include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/client_certificate_delegate.h" #include "content/public/browser/navigation_handle.h" +#include "content/public/browser/page_navigator.h" #include "content/public/browser/quota_permission_context.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" @@ -467,24 +468,37 @@ scoped_refptr int render_view_process_id, int render_view_routing_id, int render_frame_process_id, - int render_frame_routing_id) { + int render_frame_routing_id, + bool* is_guest_view) { base::AutoLock lock_scope(browser_info_lock_); + if (is_guest_view) + *is_guest_view = false; + BrowserInfoList::const_iterator it = browser_info_list_.begin(); for (; it != browser_info_list_.end(); ++it) { const scoped_refptr& browser_info = *it; - if (browser_info->is_render_view_id_match(render_view_process_id, - render_view_routing_id)) { + if (browser_info->render_id_manager()->is_render_view_id_match( + render_view_process_id, render_view_routing_id)) { // Make sure the frame id is also registered. - browser_info->add_render_frame_id(render_frame_process_id, - render_frame_routing_id); + browser_info->render_id_manager()->add_render_frame_id( + render_frame_process_id, render_frame_routing_id); return browser_info; - } else if (browser_info->is_render_frame_id_match( - render_frame_process_id, - render_frame_routing_id)) { + } + if (browser_info->render_id_manager()->is_render_frame_id_match( + render_frame_process_id, render_frame_routing_id)) { // Make sure the view id is also registered. - browser_info->add_render_view_id(render_view_process_id, - render_view_routing_id); + browser_info->render_id_manager()->add_render_view_id( + render_view_process_id, render_view_routing_id); + return browser_info; + } + if (extensions::ExtensionsEnabled() && + (browser_info->guest_render_id_manager()->is_render_view_id_match( + render_view_process_id, render_view_routing_id) || + browser_info->guest_render_id_manager()->is_render_frame_id_match( + render_frame_process_id, render_frame_routing_id))) { + if (is_guest_view) + *is_guest_view = true; return browser_info; } } @@ -492,10 +506,10 @@ scoped_refptr // Must be a popup if it hasn't already been created. scoped_refptr browser_info = new CefBrowserInfo(++next_browser_id_, true); - browser_info->add_render_view_id(render_view_process_id, - render_view_routing_id); - browser_info->add_render_frame_id(render_frame_process_id, - render_frame_routing_id); + browser_info->render_id_manager()->add_render_view_id( + render_view_process_id, render_view_routing_id); + browser_info->render_id_manager()->add_render_frame_id( + render_frame_process_id, render_frame_routing_id); browser_info_list_.push_back(browser_info); return browser_info; } @@ -550,16 +564,28 @@ void CefContentBrowserClient::DestroyAllBrowsers() { } scoped_refptr CefContentBrowserClient::GetBrowserInfoForView( - int render_process_id, int render_routing_id) { + int render_process_id, + int render_routing_id, + bool* is_guest_view) { base::AutoLock lock_scope(browser_info_lock_); + if (is_guest_view) + *is_guest_view = false; + BrowserInfoList::const_iterator it = browser_info_list_.begin(); for (; it != browser_info_list_.end(); ++it) { const scoped_refptr& browser_info = *it; - if (browser_info->is_render_view_id_match( + if (browser_info->render_id_manager()->is_render_view_id_match( render_process_id, render_routing_id)) { return browser_info; } + if (extensions::ExtensionsEnabled() && + browser_info->guest_render_id_manager()->is_render_view_id_match( + render_process_id, render_routing_id)) { + if (is_guest_view) + *is_guest_view = true; + return browser_info; + } } LOG(WARNING) << "No browser info matching view process id " << @@ -569,14 +595,26 @@ scoped_refptr CefContentBrowserClient::GetBrowserInfoForView( } scoped_refptr CefContentBrowserClient::GetBrowserInfoForFrame( - int render_process_id, int render_routing_id) { + int render_process_id, + int render_routing_id, + bool* is_guest_view) { base::AutoLock lock_scope(browser_info_lock_); + if (is_guest_view) + *is_guest_view = false; + BrowserInfoList::const_iterator it = browser_info_list_.begin(); for (; it != browser_info_list_.end(); ++it) { const scoped_refptr& browser_info = *it; - if (browser_info->is_render_frame_id_match( - render_process_id, render_routing_id)) { + if (browser_info->render_id_manager()->is_render_frame_id_match( + render_process_id, render_routing_id)) { + return browser_info; + } + if (extensions::ExtensionsEnabled() && + browser_info->guest_render_id_manager()->is_render_frame_id_match( + render_process_id, render_routing_id)) { + if (is_guest_view) + *is_guest_view = true; return browser_info; } } @@ -924,12 +962,36 @@ bool CefContentBrowserClient::CanCreateWindow( if (last_create_window_params_.opener_process_id == MSG_ROUTING_NONE) return false; + bool is_guest_view = false; CefRefPtr browser = - CefBrowserHostImpl::GetBrowserForView( + extensions::GetOwnerBrowserForView( last_create_window_params_.opener_process_id, - last_create_window_params_.opener_view_id); - if (!browser.get()) + last_create_window_params_.opener_view_id, + &is_guest_view); + DCHECK(browser.get()); + if (!browser.get()) { + // Cancel the popup. + last_create_window_params_.opener_process_id = MSG_ROUTING_NONE; return false; + } + + if (is_guest_view) { + content::OpenURLParams params(target_url, + referrer, + disposition, + ui::PAGE_TRANSITION_LINK, + true); + params.user_gesture = user_gesture; + + // Pass navigation to the owner browser. + CEF_POST_TASK(CEF_UIT, + base::Bind(base::IgnoreResult(&CefBrowserHostImpl::OpenURLFromTab), + browser.get(), nullptr, params)); + + // Cancel the popup. + last_create_window_params_.opener_process_id = MSG_ROUTING_NONE; + return false; + } CefRefPtr client = browser->GetClient(); bool allow = true; diff --git a/libcef/browser/content_browser_client.h b/libcef/browser/content_browser_client.h index 2720ca1c4..343659628 100644 --- a/libcef/browser/content_browser_client.h +++ b/libcef/browser/content_browser_client.h @@ -50,23 +50,30 @@ class CefContentBrowserClient : public content::ContentBrowserClient { // to CefBrowserHostImpl::ShouldCreateWebContents on the UI thread. To resolve // this race CefBrowserInfo may be created when requested for the first time // and before the associated CefBrowserHostImpl is created. + // |is_guest_view| will be set to true if the IDs match a guest view + // associated with the returned browser info instead of the browser itself. scoped_refptr CreateBrowserInfo(bool is_popup); scoped_refptr GetOrCreateBrowserInfo( int render_view_process_id, int render_view_routing_id, int render_frame_process_id, - int render_frame_routing_id); + int render_frame_routing_id, + bool* is_guest_view); void RemoveBrowserInfo(scoped_refptr browser_info); void DestroyAllBrowsers(); // Retrieves the CefBrowserInfo matching the specified IDs or an empty // pointer if no match is found. It is allowed to add new callers of this // method but consider using CefBrowserHostImpl::GetBrowserFor[View|Frame]() - // instead. + // or extensions::GetOwnerBrowserForView() instead. + // |is_guest_view| will be set to true if the IDs match a guest view + // associated with the returned browser info instead of the browser itself. scoped_refptr GetBrowserInfoForView(int render_process_id, - int render_routing_id); + int render_routing_id, + bool* is_guest_view); scoped_refptr GetBrowserInfoForFrame(int render_process_id, - int render_routing_id); + int render_routing_id, + bool* is_guest_view); // ContentBrowserClient implementation. content::BrowserMainParts* CreateBrowserMainParts( diff --git a/libcef/browser/extensions/browser_extensions_util.cc b/libcef/browser/extensions/browser_extensions_util.cc index ebd02cc79..bca211dd2 100644 --- a/libcef/browser/extensions/browser_extensions_util.cc +++ b/libcef/browser/extensions/browser_extensions_util.cc @@ -4,6 +4,8 @@ #include "libcef/browser/extensions/browser_extensions_util.h" +#include "libcef/browser/content_browser_client.h" +#include "libcef/browser/thread_util.h" #include "libcef/common/extensions/extensions_util.h" #include "content/browser/browser_plugin/browser_plugin_embedder.h" @@ -58,24 +60,51 @@ content::WebContents* GetOwnerForGuestContents(content::WebContents* guest) { } CefRefPtr GetOwnerBrowserForView(int render_process_id, - int render_routing_id) { - content::RenderViewHost* host = - content::RenderViewHost::FromID(render_process_id, render_routing_id); - if (host) - return GetOwnerBrowserForHost(host); - return NULL; + int render_routing_id, + bool* is_guest_view) { + if (CEF_CURRENTLY_ON_UIT()) { + // Use the non-thread-safe but potentially faster approach. + content::RenderViewHost* host = + content::RenderViewHost::FromID(render_process_id, render_routing_id); + if (host) + return GetOwnerBrowserForHost(host, is_guest_view); + return NULL; + } else { + // Use the thread-safe approach. + scoped_refptr info = + CefContentBrowserClient::Get()->GetBrowserInfoForView( + render_process_id, render_routing_id, is_guest_view); + if (info.get()) { + CefRefPtr browser = info->browser(); + if (!browser.get()) { + LOG(WARNING) << "Found browser id " << info->browser_id() << + " but no browser object matching view process id " << + render_process_id << " and routing id " << + render_routing_id; + } + return browser; + } + return NULL; + } } CefRefPtr GetOwnerBrowserForHost( - content::RenderViewHost* host) { + content::RenderViewHost* host, + bool* is_guest_view) { + if (is_guest_view) + *is_guest_view = false; + CefRefPtr browser = CefBrowserHostImpl::GetBrowserForHost(host); if (!browser.get() && ExtensionsEnabled()) { // Retrieve the owner browser, if any. content::WebContents* owner = GetOwnerForGuestContents( content::WebContents::FromRenderViewHost(host)); - if (owner) + if (owner) { browser = CefBrowserHostImpl::GetBrowserForContents(owner); + if (browser.get() && is_guest_view) + *is_guest_view = true; + } } return browser; } diff --git a/libcef/browser/extensions/browser_extensions_util.h b/libcef/browser/extensions/browser_extensions_util.h index a2d14d980..8668720ce 100644 --- a/libcef/browser/extensions/browser_extensions_util.h +++ b/libcef/browser/extensions/browser_extensions_util.h @@ -28,13 +28,19 @@ void GetAllGuestsForOwnerContents(content::WebContents* owner, content::WebContents* GetOwnerForGuestContents(content::WebContents* guest); // Returns the CefBrowserHostImpl that owns the host identified by the specified -// view routing IDs, if any. +// view routing IDs, if any. |is_guest_view| will be set to true if the IDs +// match a guest view associated with the returned browser instead of the +// browser itself. CefRefPtr GetOwnerBrowserForView(int render_process_id, - int render_routing_id); + int render_routing_id, + bool* is_guest_view); // Returns the CefBrowserHostImpl that owns the specified |host|, if any. +// |is_guest_view| will be set to true if the host matches a guest view +// associated with the returned browser instead of the browser itself. CefRefPtr GetOwnerBrowserForHost( - content::RenderViewHost* host); + content::RenderViewHost* host, + bool* is_guest_view); } // namespace extensions diff --git a/libcef/browser/extensions/mime_handler_view_guest_delegate.cc b/libcef/browser/extensions/mime_handler_view_guest_delegate.cc index 7e7e5c0c5..6b915ed90 100644 --- a/libcef/browser/extensions/mime_handler_view_guest_delegate.cc +++ b/libcef/browser/extensions/mime_handler_view_guest_delegate.cc @@ -55,18 +55,20 @@ bool CefMimeHandlerViewGuestDelegate::OnGuestAttached( content::WebContents* web_contents = guest_->web_contents(); DCHECK(web_contents); - // Associate state information with the new WebContents. content::RenderViewHost* view_host = web_contents->GetRenderViewHost(); content::RenderFrameHost* main_frame_host = web_contents->GetMainFrame(); - scoped_refptr info = - CefContentBrowserClient::Get()->GetOrCreateBrowserInfo( - view_host->GetProcess()->GetID(), - view_host->GetRoutingID(), - main_frame_host->GetProcess()->GetID(), - main_frame_host->GetRoutingID()); - info->set_mime_handler_view(true); CefRefPtr owner_browser = GetOwnerBrowser(guest_); + + // Associate guest state information with the owner browser. + scoped_refptr info = owner_browser->browser_info(); + info->guest_render_id_manager()->add_render_view_id( + view_host->GetProcess()->GetID(), + view_host->GetRoutingID()); + info->guest_render_id_manager()->add_render_frame_id( + main_frame_host->GetProcess()->GetID(), + main_frame_host->GetRoutingID()); + if (owner_browser->IsWindowless()) { // Use the OSR view instead of the default WebContentsViewGuest. content::WebContentsImpl* web_contents_impl = @@ -85,8 +87,25 @@ bool CefMimeHandlerViewGuestDelegate::OnGuestAttached( bool CefMimeHandlerViewGuestDelegate::OnGuestDetached( content::WebContentsView* guest_view, content::WebContentsView* parent_view) { + content::WebContents* web_contents = guest_->web_contents(); + DCHECK(web_contents); + + content::RenderViewHost* view_host = web_contents->GetRenderViewHost(); + content::RenderFrameHost* main_frame_host = web_contents->GetMainFrame(); + + CefRefPtr owner_browser = GetOwnerBrowser(guest_); + + // Disassociate guest state information with the owner browser. + scoped_refptr info = owner_browser->browser_info(); + info->guest_render_id_manager()->remove_render_view_id( + view_host->GetProcess()->GetID(), + view_host->GetRoutingID()); + info->guest_render_id_manager()->remove_render_frame_id( + main_frame_host->GetProcess()->GetID(), + main_frame_host->GetRoutingID()); + // Do nothing when the browser is windowless. - return GetOwnerBrowser(guest_)->IsWindowless(); + return owner_browser->IsWindowless(); } bool CefMimeHandlerViewGuestDelegate::CreateViewForWidget( diff --git a/libcef/browser/prefs/renderer_prefs.cc b/libcef/browser/prefs/renderer_prefs.cc index 9a10a8e0c..aa75b4885 100644 --- a/libcef/browser/prefs/renderer_prefs.cc +++ b/libcef/browser/prefs/renderer_prefs.cc @@ -366,7 +366,7 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { void PopulateWebPreferences(content::RenderViewHost* rvh, content::WebPreferences& web) { CefRefPtr browser = - extensions::GetOwnerBrowserForHost(rvh); + extensions::GetOwnerBrowserForHost(rvh, NULL); // Set defaults for preferences that are not handled by PrefService. SetDefaultPrefs(web); diff --git a/libcef/browser/printing/print_dialog_linux.cc b/libcef/browser/printing/print_dialog_linux.cc index e3b512239..2cd18a537 100644 --- a/libcef/browser/printing/print_dialog_linux.cc +++ b/libcef/browser/printing/print_dialog_linux.cc @@ -160,7 +160,9 @@ void CefPrintDialogLinux::OnPrintStart(int render_process_id, return; CefRefPtr browser = - extensions::GetOwnerBrowserForView(render_process_id, render_routing_id); + extensions::GetOwnerBrowserForView(render_process_id, + render_routing_id, + NULL); if (browser.get()) handler->OnPrintStart(browser.get()); } diff --git a/libcef/common/cef_messages.h b/libcef/common/cef_messages.h index e867c5d75..ca845a6d2 100644 --- a/libcef/common/cef_messages.h +++ b/libcef/common/cef_messages.h @@ -202,7 +202,7 @@ IPC_STRUCT_BEGIN(CefProcessHostMsg_GetNewBrowserInfo_Params) IPC_STRUCT_MEMBER(int, browser_id) IPC_STRUCT_MEMBER(bool, is_popup) IPC_STRUCT_MEMBER(bool, is_windowless) - IPC_STRUCT_MEMBER(bool, is_mime_handler_view) + IPC_STRUCT_MEMBER(bool, is_guest_view) IPC_STRUCT_END() // Retrieve information about a newly created browser. diff --git a/libcef/renderer/content_renderer_client.cc b/libcef/renderer/content_renderer_client.cc index 9b586820e..483cdc539 100644 --- a/libcef/renderer/content_renderer_client.cc +++ b/libcef/renderer/content_renderer_client.cc @@ -920,8 +920,8 @@ void CefContentRendererClient::BrowserCreated( ¶ms)); DCHECK_GT(params.browser_id, 0); - if (params.is_mime_handler_view) { - // Don't create a CefBrowser for mime handler views. + if (params.is_guest_view) { + // Don't create a CefBrowser for guest views. return; } diff --git a/tests/cefclient/browser/client_handler.cc b/tests/cefclient/browser/client_handler.cc index d3b3a6105..a37d45187 100644 --- a/tests/cefclient/browser/client_handler.cc +++ b/tests/cefclient/browser/client_handler.cc @@ -459,7 +459,8 @@ bool ClientHandler::OnOpenURLFromTab( const CefString& target_url, CefRequestHandler::WindowOpenDisposition target_disposition, bool user_gesture) { - if (user_gesture && target_disposition == WOD_NEW_BACKGROUND_TAB) { + if (target_disposition == WOD_NEW_BACKGROUND_TAB || + target_disposition == WOD_NEW_FOREGROUND_TAB) { // Handle middle-click and ctrl + left-click by opening the URL in a new // browser window. MainContext::Get()->GetRootWindowManager()->CreateRootWindow(