• 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 <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