1 // Copyright 2015 The Chromium Embedded Framework Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can 3 // be found in the LICENSE file. 4 5 #ifndef CEF_LIBCEF_BROWSER_BROWSER_INFO_MANAGER_H_ 6 #define CEF_LIBCEF_BROWSER_BROWSER_INFO_MANAGER_H_ 7 #pragma once 8 9 #include "include/cef_client.h" 10 11 #include <list> 12 #include <map> 13 #include <memory> 14 #include <vector> 15 16 #include "libcef/browser/browser_info.h" 17 18 #include "base/synchronization/lock.h" 19 #include "base/task/sequenced_task_runner.h" 20 #include "cef/libcef/common/mojom/cef.mojom.h" 21 #include "content/public/browser/global_routing_id.h" 22 #include "content/public/browser/render_process_host_observer.h" 23 #include "third_party/blink/public/mojom/window_features/window_features.mojom.h" 24 #include "ui/base/window_open_disposition.h" 25 #include "url/gurl.h" 26 27 namespace blink { 28 struct WebWindowFeatures; 29 } 30 31 namespace content { 32 struct OpenURLParams; 33 struct Referrer; 34 class RenderFrameHost; 35 class RenderViewHostDelegateView; 36 class WebContents; 37 class WebContentsView; 38 } // namespace content 39 40 class CefBrowserHostBase; 41 class CefBrowserPlatformDelegate; 42 43 // Singleton object for managing BrowserInfo instances. 44 class CefBrowserInfoManager : public content::RenderProcessHostObserver { 45 public: 46 CefBrowserInfoManager(); 47 48 CefBrowserInfoManager(const CefBrowserInfoManager&) = delete; 49 CefBrowserInfoManager& operator=(const CefBrowserInfoManager&) = delete; 50 51 ~CefBrowserInfoManager() override; 52 53 // Returns this singleton instance of this class. 54 static CefBrowserInfoManager* GetInstance(); 55 56 // Called immediately before a new CefBrowserHost implementation is created 57 // directly. In this case |is_popup| will be true only for DevTools browsers. 58 scoped_refptr<CefBrowserInfo> CreateBrowserInfo( 59 bool is_popup, 60 bool is_windowless, 61 CefRefPtr<CefDictionaryValue> extra_info); 62 63 // Called from WebContentsDelegate::WebContentsCreated when a new browser is 64 // being created for a traditional popup (e.g. window.open() or targeted 65 // link). If any OnGetNewBrowserInfo requests are pending for the popup the 66 // response will be sent when this method is called. 67 scoped_refptr<CefBrowserInfo> CreatePopupBrowserInfo( 68 content::WebContents* new_contents, 69 bool is_windowless, 70 CefRefPtr<CefDictionaryValue> extra_info); 71 72 // Called from ContentBrowserClient::CanCreateWindow. See comments on 73 // PendingPopup for more information. 74 bool CanCreateWindow(content::RenderFrameHost* opener, 75 const GURL& target_url, 76 const content::Referrer& referrer, 77 const std::string& frame_name, 78 WindowOpenDisposition disposition, 79 const blink::mojom::WindowFeatures& features, 80 bool user_gesture, 81 bool opener_suppressed, 82 bool* no_javascript_access); 83 84 // Called from WebContentsDelegate::GetCustomWebContentsView (alloy runtime 85 // only). See comments on PendingPopup for more information. 86 void GetCustomWebContentsView( 87 const GURL& target_url, 88 const content::GlobalRenderFrameHostId& opener_global_id, 89 content::WebContentsView** view, 90 content::RenderViewHostDelegateView** delegate_view); 91 92 // Called from WebContentsDelegate::WebContentsCreated. See comments on 93 // PendingPopup for more information. 94 void WebContentsCreated( 95 const GURL& target_url, 96 const content::GlobalRenderFrameHostId& opener_global_id, 97 CefBrowserSettings& settings, 98 CefRefPtr<CefClient>& client, 99 std::unique_ptr<CefBrowserPlatformDelegate>& platform_delegate, 100 CefRefPtr<CefDictionaryValue>& extra_info); 101 102 // Called from CefBrowserManager::GetNewBrowserInfo for delivering 103 // browser info to the renderer process. If the browser info already exists 104 // the response will be sent immediately. Otherwise, the response will be sent 105 // when CreatePopupBrowserInfo creates the browser info. The info will already 106 // exist for explicitly created browsers and guest views. It may sometimes 107 // already exist for traditional popup browsers depending on timing. See 108 // comments on PendingPopup for more information. 109 void OnGetNewBrowserInfo( 110 const content::GlobalRenderFrameHostId& global_id, 111 cef::mojom::BrowserManager::GetNewBrowserInfoCallback callback); 112 113 // Called from CefBrowserHostBase::DestroyBrowser() when a browser is 114 // destroyed. 115 void RemoveBrowserInfo(scoped_refptr<CefBrowserInfo> browser_info); 116 117 // Called from CefContext::FinishShutdownOnUIThread() to destroy all browsers. 118 void DestroyAllBrowsers(); 119 120 // Returns the CefBrowserInfo matching the specified ID or nullptr if no 121 // match is found. It is allowed to add new callers of this method but 122 // consider using CefBrowserHostBase::GetBrowserForGlobalId() or 123 // extensions::GetOwnerBrowserForGlobalId() instead. If |is_guest_view| is 124 // non-nullptr it will be set to true if the ID matches a guest view 125 // associated with the returned browser info instead of the browser itself. 126 scoped_refptr<CefBrowserInfo> GetBrowserInfo( 127 const content::GlobalRenderFrameHostId& global_id, 128 bool* is_guest_view = nullptr); 129 130 // Returns all existing CefBrowserInfo objects. 131 using BrowserInfoList = std::list<scoped_refptr<CefBrowserInfo>>; 132 BrowserInfoList GetBrowserInfoList(); 133 134 // Returns true if the navigation should be allowed to proceed, or false if 135 // the navigation will instead be sent via OpenURLFromTab. If allowed, 136 // |browser| will be set to the target browser if any. 137 bool MaybeAllowNavigation(content::RenderFrameHost* opener, 138 const content::OpenURLParams& params, 139 CefRefPtr<CefBrowserHostBase>& browser) const; 140 141 private: 142 // RenderProcessHostObserver methods: 143 void RenderProcessHostDestroyed(content::RenderProcessHost* host) override; 144 145 // Store state information about pending popups. Call order is: 146 // - CanCreateWindow (UIT): 147 // Provides an opportunity to cancel the popup (calls OnBeforePopup) and 148 // creates the new platform delegate for the popup. If the popup owner is 149 // an extension guest view then the popup is canceled and 150 // WebContentsDelegate::OpenURLFromTab is called via the 151 // CefBrowserHostBase::MaybeAllowNavigation implementation. 152 // And then the following calls may occur at the same time: 153 // - GetCustomWebContentsView (UIT) (alloy runtime only): 154 // Creates the OSR views for windowless popups. 155 // - WebContentsCreated (UIT): 156 // Creates the CefBrowserHost representation for the popup. 157 // - CefBrowserManager::GetNewBrowserInfo (IOT) 158 // Passes information about the popup to the renderer process. 159 struct PendingPopup { 160 // Track the last method that modified this PendingPopup instance. There may 161 // be multiple pending popups with the same identifiers and this allows us 162 // to differentiate between them at different processing steps. 163 enum Step { 164 CAN_CREATE_WINDOW, 165 GET_CUSTOM_WEB_CONTENTS_VIEW, 166 } step; 167 168 // Initial state from ViewHostMsg_CreateWindow. 169 // |target_url| will be empty if a popup is created via window.open() and 170 // never navigated. For example: javascript:window.open(); 171 content::GlobalRenderFrameHostId opener_global_id; 172 GURL target_url; 173 std::string target_frame_name; 174 175 // Values specified by OnBeforePopup. 176 CefBrowserSettings settings; 177 CefRefPtr<CefClient> client; 178 CefRefPtr<CefDictionaryValue> extra_info; 179 180 // Platform delegate specific to the new popup. 181 std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate; 182 }; 183 184 // Manage pending popups. Only called on the UI thread. 185 void PushPendingPopup(std::unique_ptr<PendingPopup> popup); 186 std::unique_ptr<PendingPopup> PopPendingPopup( 187 PendingPopup::Step step, 188 const content::GlobalRenderFrameHostId& opener_global_id, 189 const GURL& target_url); 190 191 // Retrieves the BrowserInfo matching the specified ID. 192 scoped_refptr<CefBrowserInfo> GetBrowserInfoInternal( 193 const content::GlobalRenderFrameHostId& global_id, 194 bool* is_guest_view); 195 196 // Send the response for a pending OnGetNewBrowserInfo request. 197 static void SendNewBrowserInfoResponse( 198 scoped_refptr<CefBrowserInfo> browser_info, 199 bool is_guest_view, 200 cef::mojom::BrowserManager::GetNewBrowserInfoCallback callback, 201 scoped_refptr<base::SequencedTaskRunner> callback_runner); 202 203 // Pending request for OnGetNewBrowserInfo. 204 struct PendingNewBrowserInfo { 205 content::GlobalRenderFrameHostId global_id; 206 int timeout_id; 207 cef::mojom::BrowserManager::GetNewBrowserInfoCallback callback; 208 scoped_refptr<base::SequencedTaskRunner> callback_runner; 209 }; 210 211 // Cancel a response that is still pending. 212 static void CancelNewBrowserInfoResponse(PendingNewBrowserInfo* pending_info); 213 214 // Time out a response if it's still pending. 215 static void TimeoutNewBrowserInfoResponse( 216 const content::GlobalRenderFrameHostId& global_id, 217 int timeout_id); 218 219 mutable base::Lock browser_info_lock_; 220 221 // Access to the below members must be protected by |browser_info_lock_|. 222 223 BrowserInfoList browser_info_list_; 224 int next_browser_id_ = 0; 225 226 // Map of global ID to info. These IDs are guaranteed to uniquely 227 // identify a RFH for its complete lifespan. See documentation on 228 // RenderFrameHost::GetFrameTreeNodeId() for background. 229 using PendingNewBrowserInfoMap = 230 std::map<content::GlobalRenderFrameHostId, 231 std::unique_ptr<PendingNewBrowserInfo>>; 232 PendingNewBrowserInfoMap pending_new_browser_info_map_; 233 234 // Only accessed on the UI thread. 235 using PendingPopupList = std::vector<std::unique_ptr<PendingPopup>>; 236 PendingPopupList pending_popup_list_; 237 238 int next_timeout_id_ = 0; 239 }; 240 241 #endif // CEF_LIBCEF_BROWSER_BROWSER_INFO_H_ 242