mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	This change moves the SendProcessMessage method from CefBrowser to CefFrame and adds CefBrowser parameters to OnProcessMessageReceived and OnDraggableRegionsChanged. The internal implementation has changed as follows: - Frame IDs are now a 64-bit combination of the 32-bit render_process_id and render_routing_id values that uniquely identify a RenderFrameHost (RFH). - CefFrameHostImpl objects are now managed by CefBrowserInfo with life span tied to RFH expectations. Specifically, a CefFrameHostImpl object representing a sub-frame will be created when a RenderFrame is created in the renderer process and detached when the associated RenderFrame is deleted or the renderer process in which it runs has died. - The CefFrameHostImpl object representing the main frame will always be valid but the underlying RFH (and associated frame ID) may change over time as a result of cross-origin navigations. Despite these changes calling LoadURL on the main frame object in the browser process will always navigate as expected. - Speculative RFHs, which may be created as a result of a cross-origin navigation and discarded if that navigation is not committed, are now handled correctly (e.g. ignored in most cases until they're committed). - It is less likely, but still possible, to receive a CefFrame object with an invalid frame ID (ID < 0). This can happen in cases where a RFH has not yet been created for a sub-frame. For example, when OnBeforeBrowse is called before initiating navigation in a previously nonexisting sub-frame. To test: All tests pass with NetworkService enabled and disabled.
		
			
				
	
	
		
			517 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			517 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// Copyright 2015 The Chromium Embedded Framework Authors. All rights reserved.
 | 
						|
// Use of this source code is governed by a BSD-style license that can
 | 
						|
// be found in the LICENSE file.
 | 
						|
 | 
						|
#include "libcef/browser/browser_info_manager.h"
 | 
						|
 | 
						|
#include <utility>
 | 
						|
 | 
						|
#include "libcef/browser/browser_host_impl.h"
 | 
						|
#include "libcef/browser/browser_platform_delegate.h"
 | 
						|
#include "libcef/browser/extensions/browser_extensions_util.h"
 | 
						|
#include "libcef/browser/thread_util.h"
 | 
						|
#include "libcef/common/cef_messages.h"
 | 
						|
#include "libcef/common/extensions/extensions_util.h"
 | 
						|
#include "libcef/common/values_impl.h"
 | 
						|
 | 
						|
#include "base/logging.h"
 | 
						|
#include "content/common/view_messages.h"
 | 
						|
#include "content/public/browser/render_frame_host.h"
 | 
						|
#include "content/public/browser/render_process_host.h"
 | 
						|
#include "content/public/browser/web_contents.h"
 | 
						|
#include "content/public/common/child_process_host.h"
 | 
						|
 | 
						|
namespace {
 | 
						|
 | 
						|
void TranslatePopupFeatures(const blink::mojom::WindowFeatures& webKitFeatures,
 | 
						|
                            CefPopupFeatures& features) {
 | 
						|
  features.x = static_cast<int>(webKitFeatures.x);
 | 
						|
  features.xSet = webKitFeatures.has_x;
 | 
						|
  features.y = static_cast<int>(webKitFeatures.y);
 | 
						|
  features.ySet = webKitFeatures.has_y;
 | 
						|
  features.width = static_cast<int>(webKitFeatures.width);
 | 
						|
  features.widthSet = webKitFeatures.has_width;
 | 
						|
  features.height = static_cast<int>(webKitFeatures.height);
 | 
						|
  features.heightSet = webKitFeatures.has_height;
 | 
						|
 | 
						|
  features.menuBarVisible = webKitFeatures.menu_bar_visible;
 | 
						|
  features.statusBarVisible = webKitFeatures.status_bar_visible;
 | 
						|
  features.toolBarVisible = webKitFeatures.tool_bar_visible;
 | 
						|
  features.scrollbarsVisible = webKitFeatures.scrollbars_visible;
 | 
						|
}
 | 
						|
 | 
						|
CefBrowserInfoManager* g_info_manager = nullptr;
 | 
						|
 | 
						|
}  // namespace
 | 
						|
 | 
						|
CefBrowserInfoManager::CefBrowserInfoManager() : next_browser_id_(0) {
 | 
						|
  DCHECK(!g_info_manager);
 | 
						|
  g_info_manager = this;
 | 
						|
}
 | 
						|
 | 
						|
CefBrowserInfoManager::~CefBrowserInfoManager() {
 | 
						|
  DCHECK(browser_info_list_.empty());
 | 
						|
  g_info_manager = nullptr;
 | 
						|
}
 | 
						|
 | 
						|
// static
 | 
						|
CefBrowserInfoManager* CefBrowserInfoManager::GetInstance() {
 | 
						|
  return g_info_manager;
 | 
						|
}
 | 
						|
 | 
						|
scoped_refptr<CefBrowserInfo> CefBrowserInfoManager::CreateBrowserInfo(
 | 
						|
    bool is_popup,
 | 
						|
    bool is_windowless,
 | 
						|
    CefRefPtr<CefDictionaryValue> extra_info) {
 | 
						|
  base::AutoLock lock_scope(browser_info_lock_);
 | 
						|
 | 
						|
  scoped_refptr<CefBrowserInfo> browser_info = new CefBrowserInfo(
 | 
						|
      ++next_browser_id_, is_popup, is_windowless, extra_info);
 | 
						|
  browser_info_list_.push_back(browser_info);
 | 
						|
 | 
						|
  return browser_info;
 | 
						|
}
 | 
						|
 | 
						|
scoped_refptr<CefBrowserInfo> CefBrowserInfoManager::CreatePopupBrowserInfo(
 | 
						|
    content::WebContents* new_contents,
 | 
						|
    bool is_windowless,
 | 
						|
    CefRefPtr<CefDictionaryValue> extra_info) {
 | 
						|
  base::AutoLock lock_scope(browser_info_lock_);
 | 
						|
 | 
						|
  auto frame_host = new_contents->GetMainFrame();
 | 
						|
  const int render_process_id = frame_host->GetProcess()->GetID();
 | 
						|
  const auto frame_id = CefFrameHostImpl::MakeFrameId(frame_host);
 | 
						|
 | 
						|
  scoped_refptr<CefBrowserInfo> browser_info =
 | 
						|
      new CefBrowserInfo(++next_browser_id_, true, is_windowless, extra_info);
 | 
						|
  browser_info_list_.push_back(browser_info);
 | 
						|
 | 
						|
  // Continue any pending NewBrowserInfo requests.
 | 
						|
  auto it = pending_new_browser_info_map_.find(frame_id);
 | 
						|
  if (it != pending_new_browser_info_map_.end()) {
 | 
						|
    SendNewBrowserInfoResponse(render_process_id, browser_info, false,
 | 
						|
                               it->second->reply_msg);
 | 
						|
    pending_new_browser_info_map_.erase(it);
 | 
						|
  }
 | 
						|
 | 
						|
  return browser_info;
 | 
						|
}
 | 
						|
 | 
						|
bool CefBrowserInfoManager::CanCreateWindow(
 | 
						|
    content::RenderFrameHost* opener,
 | 
						|
    const GURL& target_url,
 | 
						|
    const content::Referrer& referrer,
 | 
						|
    const std::string& frame_name,
 | 
						|
    WindowOpenDisposition disposition,
 | 
						|
    const blink::mojom::WindowFeatures& features,
 | 
						|
    bool user_gesture,
 | 
						|
    bool opener_suppressed,
 | 
						|
    bool* no_javascript_access) {
 | 
						|
  CEF_REQUIRE_UIT();
 | 
						|
 | 
						|
  bool is_guest_view = false;
 | 
						|
  CefRefPtr<CefBrowserHostImpl> browser =
 | 
						|
      extensions::GetOwnerBrowserForHost(opener, &is_guest_view);
 | 
						|
  DCHECK(browser.get());
 | 
						|
  if (!browser.get()) {
 | 
						|
    // Cancel the popup.
 | 
						|
    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.
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  CefRefPtr<CefClient> client = browser->GetClient();
 | 
						|
  bool allow = true;
 | 
						|
 | 
						|
  std::unique_ptr<CefWindowInfo> window_info(new CefWindowInfo);
 | 
						|
 | 
						|
#if defined(OS_WIN)
 | 
						|
  window_info->SetAsPopup(NULL, CefString());
 | 
						|
#endif
 | 
						|
 | 
						|
  auto pending_popup = std::make_unique<CefBrowserInfoManager::PendingPopup>();
 | 
						|
  pending_popup->step = CefBrowserInfoManager::PendingPopup::CAN_CREATE_WINDOW;
 | 
						|
  pending_popup->opener_render_process_id = opener->GetProcess()->GetID();
 | 
						|
  pending_popup->opener_render_routing_id = opener->GetRoutingID();
 | 
						|
  pending_popup->target_url = target_url;
 | 
						|
  pending_popup->target_frame_name = frame_name;
 | 
						|
 | 
						|
  // Start with the current browser's settings.
 | 
						|
  pending_popup->client = client;
 | 
						|
  pending_popup->settings = browser->settings();
 | 
						|
 | 
						|
  if (client.get()) {
 | 
						|
    CefRefPtr<CefLifeSpanHandler> handler = client->GetLifeSpanHandler();
 | 
						|
    if (handler.get()) {
 | 
						|
      CefRefPtr<CefFrame> opener_frame = browser->GetFrameForHost(opener);
 | 
						|
      DCHECK(opener_frame);
 | 
						|
 | 
						|
      CefPopupFeatures cef_features;
 | 
						|
      TranslatePopupFeatures(features, cef_features);
 | 
						|
 | 
						|
#if (defined(OS_WIN) || defined(OS_MACOSX))
 | 
						|
      // Default to the size from the popup features.
 | 
						|
      if (cef_features.xSet)
 | 
						|
        window_info->x = cef_features.x;
 | 
						|
      if (cef_features.ySet)
 | 
						|
        window_info->y = cef_features.y;
 | 
						|
      if (cef_features.widthSet)
 | 
						|
        window_info->width = cef_features.width;
 | 
						|
      if (cef_features.heightSet)
 | 
						|
        window_info->height = cef_features.height;
 | 
						|
#endif
 | 
						|
 | 
						|
      allow = !handler->OnBeforePopup(
 | 
						|
          browser.get(), opener_frame, pending_popup->target_url.spec(),
 | 
						|
          pending_popup->target_frame_name,
 | 
						|
          static_cast<cef_window_open_disposition_t>(disposition), user_gesture,
 | 
						|
          cef_features, *window_info, pending_popup->client,
 | 
						|
          pending_popup->settings, pending_popup->extra_info,
 | 
						|
          no_javascript_access);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (allow) {
 | 
						|
    CefBrowserHostImpl::CreateParams create_params;
 | 
						|
 | 
						|
    if (!browser->IsViewsHosted())
 | 
						|
      create_params.window_info = std::move(window_info);
 | 
						|
 | 
						|
    create_params.settings = pending_popup->settings;
 | 
						|
    create_params.client = pending_popup->client;
 | 
						|
    create_params.extra_info = pending_popup->extra_info;
 | 
						|
 | 
						|
    pending_popup->platform_delegate =
 | 
						|
        CefBrowserPlatformDelegate::Create(create_params);
 | 
						|
    CHECK(pending_popup->platform_delegate.get());
 | 
						|
 | 
						|
    // Between the calls to CanCreateWindow and GetCustomWebContentsView
 | 
						|
    // RenderViewHostImpl::CreateNewWindow() will call
 | 
						|
    // RenderProcessHostImpl::FilterURL() which, in the case of "javascript:"
 | 
						|
    // URIs, rewrites the URL to "about:blank". We need to apply the same filter
 | 
						|
    // otherwise GetCustomWebContentsView will fail to retrieve the PopupInfo.
 | 
						|
    opener->GetProcess()->FilterURL(false, &pending_popup->target_url);
 | 
						|
 | 
						|
    PushPendingPopup(std::move(pending_popup));
 | 
						|
  }
 | 
						|
 | 
						|
  return allow;
 | 
						|
}
 | 
						|
 | 
						|
void CefBrowserInfoManager::GetCustomWebContentsView(
 | 
						|
    const GURL& target_url,
 | 
						|
    int opener_render_process_id,
 | 
						|
    int opener_render_routing_id,
 | 
						|
    content::WebContentsView** view,
 | 
						|
    content::RenderViewHostDelegateView** delegate_view) {
 | 
						|
  CEF_REQUIRE_UIT();
 | 
						|
 | 
						|
  std::unique_ptr<CefBrowserInfoManager::PendingPopup> pending_popup =
 | 
						|
      PopPendingPopup(CefBrowserInfoManager::PendingPopup::CAN_CREATE_WINDOW,
 | 
						|
                      opener_render_process_id, opener_render_routing_id,
 | 
						|
                      target_url);
 | 
						|
  DCHECK(pending_popup.get());
 | 
						|
  DCHECK(pending_popup->platform_delegate.get());
 | 
						|
 | 
						|
  if (pending_popup->platform_delegate->IsWindowless()) {
 | 
						|
    pending_popup->platform_delegate->CreateViewForWebContents(view,
 | 
						|
                                                               delegate_view);
 | 
						|
  }
 | 
						|
 | 
						|
  pending_popup->step =
 | 
						|
      CefBrowserInfoManager::PendingPopup::GET_CUSTOM_WEB_CONTENTS_VIEW;
 | 
						|
  PushPendingPopup(std::move(pending_popup));
 | 
						|
}
 | 
						|
 | 
						|
void CefBrowserInfoManager::WebContentsCreated(
 | 
						|
    const GURL& target_url,
 | 
						|
    int opener_render_process_id,
 | 
						|
    int opener_render_routing_id,
 | 
						|
    CefBrowserSettings& settings,
 | 
						|
    CefRefPtr<CefClient>& client,
 | 
						|
    std::unique_ptr<CefBrowserPlatformDelegate>& platform_delegate,
 | 
						|
    CefRefPtr<CefDictionaryValue>& extra_info) {
 | 
						|
  CEF_REQUIRE_UIT();
 | 
						|
 | 
						|
  std::unique_ptr<CefBrowserInfoManager::PendingPopup> pending_popup =
 | 
						|
      PopPendingPopup(
 | 
						|
          CefBrowserInfoManager::PendingPopup::GET_CUSTOM_WEB_CONTENTS_VIEW,
 | 
						|
          opener_render_process_id, opener_render_routing_id, target_url);
 | 
						|
  DCHECK(pending_popup.get());
 | 
						|
  DCHECK(pending_popup->platform_delegate.get());
 | 
						|
 | 
						|
  settings = pending_popup->settings;
 | 
						|
  client = pending_popup->client;
 | 
						|
  platform_delegate = std::move(pending_popup->platform_delegate);
 | 
						|
  extra_info = pending_popup->extra_info;
 | 
						|
}
 | 
						|
 | 
						|
void CefBrowserInfoManager::OnGetNewBrowserInfo(int render_process_id,
 | 
						|
                                                int render_routing_id,
 | 
						|
                                                IPC::Message* reply_msg) {
 | 
						|
  DCHECK_NE(render_process_id, content::ChildProcessHost::kInvalidUniqueID);
 | 
						|
  DCHECK_GT(render_routing_id, 0);
 | 
						|
  DCHECK(reply_msg);
 | 
						|
 | 
						|
  base::AutoLock lock_scope(browser_info_lock_);
 | 
						|
 | 
						|
  bool is_guest_view = false;
 | 
						|
 | 
						|
  scoped_refptr<CefBrowserInfo> browser_info =
 | 
						|
      GetBrowserInfo(render_process_id, render_routing_id, &is_guest_view);
 | 
						|
 | 
						|
  if (browser_info.get()) {
 | 
						|
    // Send the response immediately.
 | 
						|
    SendNewBrowserInfoResponse(render_process_id, browser_info, is_guest_view,
 | 
						|
                               reply_msg);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  const auto frame_id =
 | 
						|
      CefFrameHostImpl::MakeFrameId(render_process_id, render_routing_id);
 | 
						|
 | 
						|
  // Verify that no request for the same route is currently queued.
 | 
						|
  DCHECK(pending_new_browser_info_map_.find(frame_id) ==
 | 
						|
         pending_new_browser_info_map_.end());
 | 
						|
 | 
						|
  // Queue the request.
 | 
						|
  std::unique_ptr<PendingNewBrowserInfo> pending(new PendingNewBrowserInfo());
 | 
						|
  pending->render_process_id = render_process_id;
 | 
						|
  pending->render_routing_id = render_routing_id;
 | 
						|
  pending->reply_msg = reply_msg;
 | 
						|
  pending_new_browser_info_map_.insert(
 | 
						|
      std::make_pair(frame_id, std::move(pending)));
 | 
						|
}
 | 
						|
 | 
						|
void CefBrowserInfoManager::RemoveBrowserInfo(
 | 
						|
    scoped_refptr<CefBrowserInfo> browser_info) {
 | 
						|
  base::AutoLock lock_scope(browser_info_lock_);
 | 
						|
 | 
						|
  BrowserInfoList::iterator it = browser_info_list_.begin();
 | 
						|
  for (; it != browser_info_list_.end(); ++it) {
 | 
						|
    if (*it == browser_info) {
 | 
						|
      browser_info_list_.erase(it);
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  NOTREACHED();
 | 
						|
}
 | 
						|
 | 
						|
void CefBrowserInfoManager::DestroyAllBrowsers() {
 | 
						|
  BrowserInfoList list;
 | 
						|
 | 
						|
  {
 | 
						|
    base::AutoLock lock_scope(browser_info_lock_);
 | 
						|
    list = browser_info_list_;
 | 
						|
  }
 | 
						|
 | 
						|
  // Destroy any remaining browser windows.
 | 
						|
  if (!list.empty()) {
 | 
						|
    BrowserInfoList::iterator it = list.begin();
 | 
						|
    for (; it != list.end(); ++it) {
 | 
						|
      CefRefPtr<CefBrowserHostImpl> browser = (*it)->browser();
 | 
						|
      DCHECK(browser.get());
 | 
						|
      if (browser.get()) {
 | 
						|
        // DestroyBrowser will call RemoveBrowserInfo.
 | 
						|
        browser->DestroyBrowser();
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
#if DCHECK_IS_ON()
 | 
						|
  {
 | 
						|
    // Verify that all browser windows have been destroyed.
 | 
						|
    base::AutoLock lock_scope(browser_info_lock_);
 | 
						|
    DCHECK(browser_info_list_.empty());
 | 
						|
  }
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
scoped_refptr<CefBrowserInfo>
 | 
						|
CefBrowserInfoManager::GetBrowserInfoForFrameRoute(int render_process_id,
 | 
						|
                                                   int render_routing_id,
 | 
						|
                                                   bool* is_guest_view) {
 | 
						|
  base::AutoLock lock_scope(browser_info_lock_);
 | 
						|
  return GetBrowserInfo(render_process_id, render_routing_id, is_guest_view);
 | 
						|
}
 | 
						|
 | 
						|
scoped_refptr<CefBrowserInfo>
 | 
						|
CefBrowserInfoManager::GetBrowserInfoForFrameTreeNode(int frame_tree_node_id,
 | 
						|
                                                      bool* is_guest_view) {
 | 
						|
  if (is_guest_view)
 | 
						|
    *is_guest_view = false;
 | 
						|
 | 
						|
  if (frame_tree_node_id < 0)
 | 
						|
    return nullptr;
 | 
						|
 | 
						|
  base::AutoLock lock_scope(browser_info_lock_);
 | 
						|
 | 
						|
  for (const auto& browser_info : browser_info_list_) {
 | 
						|
    bool is_guest_view_tmp;
 | 
						|
    auto frame = browser_info->GetFrameForFrameTreeNode(frame_tree_node_id,
 | 
						|
                                                        &is_guest_view_tmp);
 | 
						|
    if (frame || is_guest_view_tmp) {
 | 
						|
      if (is_guest_view)
 | 
						|
        *is_guest_view = is_guest_view_tmp;
 | 
						|
      return browser_info;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return nullptr;
 | 
						|
}
 | 
						|
 | 
						|
CefBrowserInfoManager::BrowserInfoList
 | 
						|
CefBrowserInfoManager::GetBrowserInfoList() {
 | 
						|
  base::AutoLock lock_scope(browser_info_lock_);
 | 
						|
  BrowserInfoList copy;
 | 
						|
  copy.assign(browser_info_list_.begin(), browser_info_list_.end());
 | 
						|
  return copy;
 | 
						|
}
 | 
						|
 | 
						|
void CefBrowserInfoManager::RenderProcessHostDestroyed(
 | 
						|
    content::RenderProcessHost* host) {
 | 
						|
  CEF_REQUIRE_UIT();
 | 
						|
 | 
						|
  const int render_process_id = host->GetID();
 | 
						|
  DCHECK_GT(render_process_id, 0);
 | 
						|
 | 
						|
  // Remove all pending requests that reference the destroyed host.
 | 
						|
  {
 | 
						|
    base::AutoLock lock_scope(browser_info_lock_);
 | 
						|
 | 
						|
    PendingNewBrowserInfoMap::iterator it =
 | 
						|
        pending_new_browser_info_map_.begin();
 | 
						|
    while (it != pending_new_browser_info_map_.end()) {
 | 
						|
      auto info = it->second.get();
 | 
						|
      if (info->render_process_id == render_process_id)
 | 
						|
        it = pending_new_browser_info_map_.erase(it);
 | 
						|
      else
 | 
						|
        ++it;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Remove all pending popups that reference the destroyed host as the opener.
 | 
						|
  {
 | 
						|
    PendingPopupList::iterator it = pending_popup_list_.begin();
 | 
						|
    while (it != pending_popup_list_.end()) {
 | 
						|
      PendingPopup* popup = it->get();
 | 
						|
      if (popup->opener_render_process_id == render_process_id) {
 | 
						|
        it = pending_popup_list_.erase(it);
 | 
						|
      } else {
 | 
						|
        ++it;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void CefBrowserInfoManager::PushPendingPopup(
 | 
						|
    std::unique_ptr<PendingPopup> popup) {
 | 
						|
  CEF_REQUIRE_UIT();
 | 
						|
  pending_popup_list_.push_back(std::move(popup));
 | 
						|
}
 | 
						|
 | 
						|
std::unique_ptr<CefBrowserInfoManager::PendingPopup>
 | 
						|
CefBrowserInfoManager::PopPendingPopup(PendingPopup::Step step,
 | 
						|
                                       int opener_render_process_id,
 | 
						|
                                       int opener_render_routing_id,
 | 
						|
                                       const GURL& target_url) {
 | 
						|
  CEF_REQUIRE_UIT();
 | 
						|
  DCHECK_GT(opener_render_process_id, 0);
 | 
						|
  DCHECK_GT(opener_render_routing_id, 0);
 | 
						|
 | 
						|
  PendingPopupList::iterator it = pending_popup_list_.begin();
 | 
						|
  for (; it != pending_popup_list_.end(); ++it) {
 | 
						|
    PendingPopup* popup = it->get();
 | 
						|
    if (popup->step == step &&
 | 
						|
        popup->opener_render_process_id == opener_render_process_id &&
 | 
						|
        popup->opener_render_routing_id == opener_render_routing_id &&
 | 
						|
        popup->target_url == target_url) {
 | 
						|
      // Transfer ownership of the pointer.
 | 
						|
      it->release();
 | 
						|
      pending_popup_list_.erase(it);
 | 
						|
      return base::WrapUnique(popup);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return nullptr;
 | 
						|
}
 | 
						|
 | 
						|
scoped_refptr<CefBrowserInfo> CefBrowserInfoManager::GetBrowserInfo(
 | 
						|
    int render_process_id,
 | 
						|
    int render_routing_id,
 | 
						|
    bool* is_guest_view) {
 | 
						|
  browser_info_lock_.AssertAcquired();
 | 
						|
 | 
						|
  if (is_guest_view)
 | 
						|
    *is_guest_view = false;
 | 
						|
 | 
						|
  if (render_process_id < 0 || render_routing_id < 0)
 | 
						|
    return nullptr;
 | 
						|
 | 
						|
  for (const auto& browser_info : browser_info_list_) {
 | 
						|
    bool is_guest_view_tmp;
 | 
						|
    auto frame = browser_info->GetFrameForRoute(
 | 
						|
        render_process_id, render_routing_id, &is_guest_view_tmp);
 | 
						|
    if (frame || is_guest_view_tmp) {
 | 
						|
      if (is_guest_view)
 | 
						|
        *is_guest_view = is_guest_view_tmp;
 | 
						|
      return browser_info;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return nullptr;
 | 
						|
}
 | 
						|
 | 
						|
// static
 | 
						|
void CefBrowserInfoManager::SendNewBrowserInfoResponse(
 | 
						|
    int render_process_id,
 | 
						|
    scoped_refptr<CefBrowserInfo> browser_info,
 | 
						|
    bool is_guest_view,
 | 
						|
    IPC::Message* reply_msg) {
 | 
						|
  if (!CEF_CURRENTLY_ON_UIT()) {
 | 
						|
    CEF_POST_TASK(
 | 
						|
        CEF_UIT,
 | 
						|
        base::Bind(&CefBrowserInfoManager::SendNewBrowserInfoResponse,
 | 
						|
                   render_process_id, browser_info, is_guest_view, reply_msg));
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  content::RenderProcessHost* host =
 | 
						|
      content::RenderProcessHost::FromID(render_process_id);
 | 
						|
  if (!host) {
 | 
						|
    delete reply_msg;
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  CefProcessHostMsg_GetNewBrowserInfo_Params params;
 | 
						|
  params.browser_id = browser_info->browser_id();
 | 
						|
  params.is_windowless = browser_info->is_windowless();
 | 
						|
  params.is_popup = browser_info->is_popup();
 | 
						|
  params.is_guest_view = is_guest_view;
 | 
						|
 | 
						|
  auto extra_info = browser_info->extra_info();
 | 
						|
  if (extra_info) {
 | 
						|
    auto extra_info_impl =
 | 
						|
        static_cast<CefDictionaryValueImpl*>(extra_info.get());
 | 
						|
    auto extra_info_value = extra_info_impl->CopyValue();
 | 
						|
    extra_info_value->Swap(¶ms.extra_info);
 | 
						|
  }
 | 
						|
 | 
						|
  CefProcessHostMsg_GetNewBrowserInfo::WriteReplyParams(reply_msg, params);
 | 
						|
  host->Send(reply_msg);
 | 
						|
}
 |