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