• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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