// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights // reserved. Use of this source code is governed by a BSD-style license that can // be found in the LICENSE file. #ifndef CEF_LIBCEF_BROWSER_BROWSER_INFO_H_ #define CEF_LIBCEF_BROWSER_BROWSER_INFO_H_ #pragma once #include #include #include #include "include/internal/cef_ptr.h" #include "libcef/common/values_impl.h" #include "base/containers/unique_ptr_adapters.h" #include "base/functional/callback.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" #include "base/values.h" #include "content/public/browser/global_routing_id.h" #include "content/public/browser/render_frame_host.h" class CefBrowserHostBase; class CefFrameHandler; class CefFrameHostImpl; // CefBrowserInfo is used to associate a browser ID and render view/process // IDs with a particular CefBrowserHostBase. Render view/process IDs may change // during the lifetime of a single CefBrowserHostBase. // // CefBrowserInfo objects are managed by CefBrowserInfoManager and should not be // created directly. class CefBrowserInfo : public base::RefCountedThreadSafe { public: CefBrowserInfo(int browser_id, bool is_popup, bool is_windowless, CefRefPtr extra_info); CefBrowserInfo(const CefBrowserInfo&) = delete; CefBrowserInfo& operator=(const CefBrowserInfo&) = delete; int browser_id() const { return browser_id_; } bool is_popup() const { return is_popup_; } bool is_windowless() const { return is_windowless_; } CefRefPtr extra_info() const { return extra_info_; } // May return NULL if the browser has not yet been created or if the browser // has been destroyed. CefRefPtr browser() const; // Set or clear the browser. Called from CefBrowserHostBase InitializeBrowser // (to set) and DestroyBrowser (to clear). void SetBrowser(CefRefPtr browser); // Called after OnBeforeClose and before SetBrowser(nullptr). This will cause // browser() and GetMainFrame() to return nullptr as expected by // CefFrameHandler callbacks. Note that this differs from calling // SetBrowser(nullptr) because the WebContents has not yet been destroyed and // further frame-related callbacks are expected. void SetClosing(); // Ensure that a frame record exists for |host|. Called for the main frame // when the RenderView is created, or for a sub-frame when the associated // RenderFrame is created in the renderer process. // Called from CefBrowserContentsDelegate::RenderFrameCreated (is_guest_view = // false) or CefMimeHandlerViewGuestDelegate::OnGuestAttached (is_guest_view = // true). void MaybeCreateFrame(content::RenderFrameHost* host, bool is_guest_view); // Used to track state changes such as entering/exiting the BackForwardCache. // Called from CefBrowserContentsDelegate::RenderFrameHostStateChanged. void FrameHostStateChanged( content::RenderFrameHost* host, content::RenderFrameHost::LifecycleState old_state, content::RenderFrameHost::LifecycleState new_state); // Remove the frame record for |host|. Called for the main frame when the // RenderView is destroyed, or for a sub-frame when the associated RenderFrame // is destroyed in the renderer process. // Called from CefBrowserContentsDelegate::RenderFrameDeleted or // CefMimeHandlerViewGuestDelegate::OnGuestDetached. void RemoveFrame(content::RenderFrameHost* host); // Returns the main frame object. This object will remain valid until the // browser is destroyed even though the indentifier may change with cross- // origin navigations. Furthermore, calling LoadURL on this object will always // behave as expected because the call is routed through the browser's // NavigationController. CefRefPtr GetMainFrame(); // Creates a temporary sub-frame object for situations during navigation or // resource loading where a RFH does not yet exist. If |parent_frame_id| // is invalid the current main frame will be specified as the parent. // Temporary frame objects are not tracked but will be implicitly detached // on browser destruction. CefRefPtr CreateTempSubFrame( const content::GlobalRenderFrameHostId& parent_global_id); // Returns the frame object matching the specified host or nullptr if no match // is found. Nullptr will also be returned if a guest view match is found // because we don't create frame objects for guest views. If |is_guest_view| // is non-nullptr it will be set to true in this case. Must be called on the // UI thread. CefRefPtr GetFrameForHost( const content::RenderFrameHost* host, bool* is_guest_view = nullptr, bool prefer_speculative = false) const; // Returns the frame object matching the specified ID or nullptr if no match // is found. Nullptr will also be returned if a guest view match is found // because we don't create frame objects for guest views. If |is_guest_view| // is non-nullptr it will be set to true in this case. Safe to call from any // thread. CefRefPtr GetFrameForGlobalId( const content::GlobalRenderFrameHostId& global_id, bool* is_guest_view = nullptr, bool prefer_speculative = false) const; // Returns all non-speculative frame objects that currently exist. Guest views // will be excluded because they don't have a frame object. Safe to call from // any thread. using FrameHostList = std::set>; FrameHostList GetAllFrames() const; class NavigationLock final : public base::RefCounted { private: friend class CefBrowserInfo; friend class base::RefCounted; NavigationLock(); ~NavigationLock(); base::OnceClosure pending_action_; base::WeakPtrFactory weak_ptr_factory_; }; // Block navigation actions on NavigationLock life span. Must be called on the // UI thread. scoped_refptr CreateNavigationLock(); // Returns true if navigation actions are currently blocked. If this method // returns true the most recent |pending_action| will be executed on the UI // thread once the navigation lock is released. Must be called on the UI // thread. bool IsNavigationLocked(base::OnceClosure pending_action); using FrameNotifyOnceAction = base::OnceCallback)>; // Specifies a CefFrameHandler notification action whose execution may need // to be blocked on release of a potentially held NotificationStateLock. If no // CefFrameHandler exists then the action will be discarded without executing. // If the NotificationStateLock is not currently held then the action will be // executed immediately. void MaybeExecuteFrameNotification(FrameNotifyOnceAction pending_action); void MaybeNotifyDraggableRegionsChanged( CefRefPtr browser, CefRefPtr frame, std::vector draggable_regions); private: friend class base::RefCountedThreadSafe; virtual ~CefBrowserInfo(); struct FrameInfo { ~FrameInfo(); inline bool IsCurrentMainFrame() const { return frame_ && is_main_frame_ && !is_speculative_ && !is_in_bfcache_; } content::RenderFrameHost* host_; content::GlobalRenderFrameHostId global_id_; bool is_guest_view_; bool is_main_frame_; bool is_speculative_; bool is_in_bfcache_ = false; CefRefPtr frame_; }; void SetMainFrame(CefRefPtr browser, CefRefPtr frame); void MaybeNotifyFrameCreated(CefRefPtr frame); void MaybeNotifyFrameDetached(CefRefPtr browser, CefRefPtr frame); void MaybeNotifyMainFrameChanged(CefRefPtr browser, CefRefPtr old_frame, CefRefPtr new_frame); void RemoveAllFrames(CefRefPtr old_browser); int browser_id_; bool is_popup_; bool is_windowless_; CefRefPtr extra_info_; // Navigation will be blocked while |navigation_lock_| exists. // Only accessed on the UI thread. base::WeakPtr navigation_lock_; // Used instead of |base::AutoLock(lock_)| in situations that might generate // CefFrameHandler notifications. Any notifications passed to // MaybeExecuteFrameNotification() will be queued until the lock is released, // and then executed in order. Only accessed on the UI thread. class NotificationStateLock final { public: explicit NotificationStateLock(CefBrowserInfo* browser_info); ~NotificationStateLock(); protected: friend class CefBrowserInfo; CefBrowserInfo* const browser_info_; CefRefPtr frame_handler_; std::unique_ptr browser_info_lock_scope_; std::queue queue_; }; mutable base::Lock notification_lock_; // These members must be protected by |notification_lock_|. NotificationStateLock* notification_state_lock_ = nullptr; CefRefPtr frame_handler_; mutable base::Lock lock_; // The below members must be protected by |lock_|. CefRefPtr browser_; // Owner of FrameInfo structs. using FrameInfoSet = std::set, base::UniquePtrComparator>; FrameInfoSet frame_info_set_; // Map a global ID to one frame. These IDs are guaranteed to uniquely // identify a RFH for its complete lifespan. See documentation on // RenderFrameHost::GetFrameTreeNodeId() for background. using FrameIDMap = std::unordered_map; FrameIDMap frame_id_map_; // The current main frame. CefRefPtr main_frame_; // True if the browser is currently closing. bool is_closing_ = false; // Only accessed on the UI thread. std::vector draggable_regions_; }; #endif // CEF_LIBCEF_BROWSER_BROWSER_INFO_H_