• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
2 // reserved. 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_H_
6 #define CEF_LIBCEF_BROWSER_BROWSER_INFO_H_
7 #pragma once
8 
9 #include <queue>
10 #include <set>
11 #include <unordered_map>
12 
13 #include "include/internal/cef_ptr.h"
14 #include "libcef/common/values_impl.h"
15 
16 #include "base/callback.h"
17 #include "base/containers/unique_ptr_adapters.h"
18 #include "base/memory/ref_counted.h"
19 #include "base/memory/weak_ptr.h"
20 #include "base/synchronization/lock.h"
21 #include "base/values.h"
22 #include "content/public/browser/global_routing_id.h"
23 #include "content/public/browser/render_frame_host.h"
24 
25 class CefBrowserHostBase;
26 class CefFrameHandler;
27 class CefFrameHostImpl;
28 
29 // CefBrowserInfo is used to associate a browser ID and render view/process
30 // IDs with a particular CefBrowserHostBase. Render view/process IDs may change
31 // during the lifetime of a single CefBrowserHostBase.
32 //
33 // CefBrowserInfo objects are managed by CefBrowserInfoManager and should not be
34 // created directly.
35 class CefBrowserInfo : public base::RefCountedThreadSafe<CefBrowserInfo> {
36  public:
37   CefBrowserInfo(int browser_id,
38                  bool is_popup,
39                  bool is_windowless,
40                  CefRefPtr<CefDictionaryValue> extra_info);
41 
42   CefBrowserInfo(const CefBrowserInfo&) = delete;
43   CefBrowserInfo& operator=(const CefBrowserInfo&) = delete;
44 
browser_id()45   int browser_id() const { return browser_id_; }
is_popup()46   bool is_popup() const { return is_popup_; }
is_windowless()47   bool is_windowless() const { return is_windowless_; }
extra_info()48   CefRefPtr<CefDictionaryValue> extra_info() const { return extra_info_; }
49 
50   // May return NULL if the browser has not yet been created or if the browser
51   // has been destroyed.
52   CefRefPtr<CefBrowserHostBase> browser() const;
53 
54   // Set or clear the browser. Called from CefBrowserHostBase InitializeBrowser
55   // (to set) and DestroyBrowser (to clear).
56   void SetBrowser(CefRefPtr<CefBrowserHostBase> browser);
57 
58   // Called after OnBeforeClose and before SetBrowser(nullptr). This will cause
59   // browser() and GetMainFrame() to return nullptr as expected by
60   // CefFrameHandler callbacks. Note that this differs from calling
61   // SetBrowser(nullptr) because the WebContents has not yet been destroyed and
62   // further frame-related callbacks are expected.
63   void SetClosing();
64 
65   // Ensure that a frame record exists for |host|. Called for the main frame
66   // when the RenderView is created, or for a sub-frame when the associated
67   // RenderFrame is created in the renderer process.
68   // Called from CefBrowserContentsDelegate::RenderFrameCreated (is_guest_view =
69   // false) or CefMimeHandlerViewGuestDelegate::OnGuestAttached (is_guest_view =
70   // true).
71   void MaybeCreateFrame(content::RenderFrameHost* host, bool is_guest_view);
72 
73   // Used to track state changes such as entering/exiting the BackForwardCache.
74   // Called from CefBrowserContentsDelegate::RenderFrameHostStateChanged.
75   void FrameHostStateChanged(
76       content::RenderFrameHost* host,
77       content::RenderFrameHost::LifecycleState old_state,
78       content::RenderFrameHost::LifecycleState new_state);
79 
80   // Remove the frame record for |host|. Called for the main frame when the
81   // RenderView is destroyed, or for a sub-frame when the associated RenderFrame
82   // is destroyed in the renderer process.
83   // Called from CefBrowserContentsDelegate::RenderFrameDeleted or
84   // CefMimeHandlerViewGuestDelegate::OnGuestDetached.
85   void RemoveFrame(content::RenderFrameHost* host);
86 
87   // Returns the main frame object. This object will remain valid until the
88   // browser is destroyed even though the indentifier may change with cross-
89   // origin navigations. Furthermore, calling LoadURL on this object will always
90   // behave as expected because the call is routed through the browser's
91   // NavigationController.
92   CefRefPtr<CefFrameHostImpl> GetMainFrame();
93 
94   // Creates a temporary sub-frame object for situations during navigation or
95   // resource loading where a RFH does not yet exist. If |parent_frame_id|
96   // is invalid the current main frame will be specified as the parent.
97   // Temporary frame objects are not tracked but will be implicitly detached
98   // on browser destruction.
99   CefRefPtr<CefFrameHostImpl> CreateTempSubFrame(
100       const content::GlobalRenderFrameHostId& parent_global_id);
101 
102   // Returns the frame object matching the specified host or nullptr if no match
103   // is found. Nullptr will also be returned if a guest view match is found
104   // because we don't create frame objects for guest views. If |is_guest_view|
105   // is non-nullptr it will be set to true in this case. Must be called on the
106   // UI thread.
107   CefRefPtr<CefFrameHostImpl> GetFrameForHost(
108       const content::RenderFrameHost* host,
109       bool* is_guest_view = nullptr,
110       bool prefer_speculative = false) const;
111 
112   // Returns the frame object matching the specified ID or nullptr if no match
113   // is found. Nullptr will also be returned if a guest view match is found
114   // because we don't create frame objects for guest views. If |is_guest_view|
115   // is non-nullptr it will be set to true in this case. Safe to call from any
116   // thread.
117   CefRefPtr<CefFrameHostImpl> GetFrameForGlobalId(
118       const content::GlobalRenderFrameHostId& global_id,
119       bool* is_guest_view = nullptr,
120       bool prefer_speculative = false) const;
121 
122   // Returns all non-speculative frame objects that currently exist. Guest views
123   // will be excluded because they don't have a frame object. Safe to call from
124   // any thread.
125   using FrameHostList = std::set<CefRefPtr<CefFrameHostImpl>>;
126   FrameHostList GetAllFrames() const;
127 
128   class NavigationLock final : public base::RefCounted<NavigationLock> {
129    private:
130     friend class CefBrowserInfo;
131     friend class base::RefCounted<NavigationLock>;
132 
133     NavigationLock();
134     ~NavigationLock();
135 
136     base::OnceClosure pending_action_;
137     base::WeakPtrFactory<NavigationLock> weak_ptr_factory_;
138   };
139 
140   // Block navigation actions on NavigationLock life span. Must be called on the
141   // UI thread.
142   scoped_refptr<NavigationLock> CreateNavigationLock();
143 
144   // Returns true if navigation actions are currently blocked. If this method
145   // returns true the most recent |pending_action| will be executed on the UI
146   // thread once the navigation lock is released. Must be called on the UI
147   // thread.
148   bool IsNavigationLocked(base::OnceClosure pending_action);
149 
150   using FrameNotifyOnceAction =
151       base::OnceCallback<void(CefRefPtr<CefFrameHandler>)>;
152 
153   // Specifies a CefFrameHandler notification action whose execution may need
154   // to be blocked on release of a potentially held NotificationStateLock. If no
155   // CefFrameHandler exists then the action will be discarded without executing.
156   // If the NotificationStateLock is not currently held then the action will be
157   // executed immediately.
158   void MaybeExecuteFrameNotification(FrameNotifyOnceAction pending_action);
159 
160   void MaybeNotifyDraggableRegionsChanged(
161       CefRefPtr<CefBrowserHostBase> browser,
162       CefRefPtr<CefFrameHostImpl> frame,
163       std::vector<CefDraggableRegion> draggable_regions);
164 
165  private:
166   friend class base::RefCountedThreadSafe<CefBrowserInfo>;
167 
168   virtual ~CefBrowserInfo();
169 
170   struct FrameInfo {
171     ~FrameInfo();
172 
IsCurrentMainFrameFrameInfo173     inline bool IsCurrentMainFrame() const {
174       return frame_ && is_main_frame_ && !is_speculative_ && !is_in_bfcache_;
175     }
176 
177     content::RenderFrameHost* host_;
178     content::GlobalRenderFrameHostId global_id_;
179     bool is_guest_view_;
180     bool is_main_frame_;
181     bool is_speculative_;
182     bool is_in_bfcache_ = false;
183     CefRefPtr<CefFrameHostImpl> frame_;
184   };
185 
186   void SetMainFrame(CefRefPtr<CefBrowserHostBase> browser,
187                     CefRefPtr<CefFrameHostImpl> frame);
188 
189   void MaybeNotifyFrameCreated(CefRefPtr<CefFrameHostImpl> frame);
190   void MaybeNotifyFrameDetached(CefRefPtr<CefBrowserHostBase> browser,
191                                 CefRefPtr<CefFrameHostImpl> frame);
192   void MaybeNotifyMainFrameChanged(CefRefPtr<CefBrowserHostBase> browser,
193                                    CefRefPtr<CefFrameHostImpl> old_frame,
194                                    CefRefPtr<CefFrameHostImpl> new_frame);
195 
196   void RemoveAllFrames(CefRefPtr<CefBrowserHostBase> old_browser);
197 
198   int browser_id_;
199   bool is_popup_;
200   bool is_windowless_;
201   CefRefPtr<CefDictionaryValue> extra_info_;
202 
203   // Navigation will be blocked while |navigation_lock_| exists.
204   // Only accessed on the UI thread.
205   base::WeakPtr<NavigationLock> navigation_lock_;
206 
207   // Used instead of |base::AutoLock(lock_)| in situations that might generate
208   // CefFrameHandler notifications. Any notifications passed to
209   // MaybeExecuteFrameNotification() will be queued until the lock is released,
210   // and then executed in order. Only accessed on the UI thread.
211   class NotificationStateLock final {
212    public:
213     explicit NotificationStateLock(CefBrowserInfo* browser_info);
214     ~NotificationStateLock();
215 
216    protected:
217     friend class CefBrowserInfo;
218     CefBrowserInfo* const browser_info_;
219     CefRefPtr<CefFrameHandler> frame_handler_;
220     std::unique_ptr<base::AutoLock> browser_info_lock_scope_;
221     std::queue<FrameNotifyOnceAction> queue_;
222   };
223 
224   mutable base::Lock notification_lock_;
225 
226   // These members must be protected by |notification_lock_|.
227   NotificationStateLock* notification_state_lock_ = nullptr;
228   CefRefPtr<CefFrameHandler> frame_handler_;
229 
230   mutable base::Lock lock_;
231 
232   // The below members must be protected by |lock_|.
233 
234   CefRefPtr<CefBrowserHostBase> browser_;
235 
236   // Owner of FrameInfo structs.
237   using FrameInfoSet =
238       std::set<std::unique_ptr<FrameInfo>, base::UniquePtrComparator>;
239   FrameInfoSet frame_info_set_;
240 
241   // Map a global ID to one frame. These IDs are guaranteed to uniquely
242   // identify a RFH for its complete lifespan. See documentation on
243   // RenderFrameHost::GetFrameTreeNodeId() for background.
244   using FrameIDMap = std::unordered_map<content::GlobalRenderFrameHostId,
245                                         FrameInfo*,
246                                         content::GlobalRenderFrameHostIdHasher>;
247   FrameIDMap frame_id_map_;
248 
249   // The current main frame.
250   CefRefPtr<CefFrameHostImpl> main_frame_;
251 
252   // True if the browser is currently closing.
253   bool is_closing_ = false;
254 
255   // Only accessed on the UI thread.
256   std::vector<CefDraggableRegion> draggable_regions_;
257 };
258 
259 #endif  // CEF_LIBCEF_BROWSER_BROWSER_INFO_H_
260