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