1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
|
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef EXTENSIONS_BROWSER_EXTENSION_WEB_CONTENTS_OBSERVER_H_
#define EXTENSIONS_BROWSER_EXTENSION_WEB_CONTENTS_OBSERVER_H_
#include <map>
#include <string>
#include "base/compiler_specific.h"
#include "base/memory/raw_ptr.h"
#include "base/types/pass_key.h"
#include "components/sessions/core/session_id.h"
#include "content/public/browser/web_contents_observer.h"
#include "extensions/browser/extension_function_dispatcher.h"
#include "extensions/common/mojom/frame.mojom.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
namespace content {
class BrowserContext;
class RenderFrameHost;
class WebContents;
}
namespace sessions {
class SessionTabHelper;
}
namespace extensions {
class Extension;
class ExtensionFrameHost;
// A web contents observer used for renderer and extension processes. Grants the
// renderer access to certain URL scheme patterns for extensions and notifies
// the renderer that the extension was loaded.
//
// Extension system embedders must create an instance for every extension
// WebContents. It must be a subclass so that creating an instance via
// content::WebContentsUserData::CreateForWebContents() provides an object of
// the correct type. For an example, see ChromeExtensionWebContentsObserver.
//
// This class is responsible for maintaining the registrations of extension
// frames with the ProcessManager. Only frames in an extension process are
// registered. If out-of-process frames are enabled, every frame hosts a
// chrome-extension: page. Otherwise non-extension frames may erroneously be
// registered, but only briefly until they are correctly classified. This is
// achieved using the following notifications:
// 1. RenderFrameCreated - registers all new frames in extension processes.
// 2. DidCommitProvisionalLoadForFrame - unregisters non-extension frames.
// 3. DidNavigateAnyFrame - registers extension frames if they had been
// unregistered.
//
// Without OOPIF, non-extension frames created by the Chrome extension are also
// registered at RenderFrameCreated. When the non-extension page is committed,
// we detect that the unexpected URL and unregister the frame.
// With OOPIF only the first notification is sufficient in most cases, except
// for sandboxed frames with a unique origin.
class ExtensionWebContentsObserver
: public content::WebContentsObserver,
public ExtensionFunctionDispatcher::Delegate {
public:
ExtensionWebContentsObserver(const ExtensionWebContentsObserver&) = delete;
ExtensionWebContentsObserver& operator=(const ExtensionWebContentsObserver&) =
delete;
// Returns the ExtensionWebContentsObserver for the given `web_contents`.
static ExtensionWebContentsObserver* GetForWebContents(
content::WebContents* web_contents);
// Binds the LocalFrameHost interface to the ExtensionFrameHost associated
// with the RenderFrameHost.
static void BindLocalFrameHost(
mojo::PendingAssociatedReceiver<mojom::LocalFrameHost> receiver,
content::RenderFrameHost* render_frame_host);
// This must be called by clients directly after the EWCO has been created.
void Initialize();
ExtensionFunctionDispatcher* dispatcher() { return &dispatcher_; }
// Returns the extension associated with the given `render_frame_host`, or
// null if there is none.
// If `verify_url` is false, only the SiteInstance is taken into account.
// If `verify_url` is true, the frame's last committed URL is also used to
// improve the classification of the frame.
const Extension* GetExtensionFromFrame(
content::RenderFrameHost* render_frame_host,
bool verify_url) const;
// Returns mojom::LocalFrame* corresponding `render_frame_host`. It emplaces
// AssociatedRemote<mojom::LocalFrame> to `local_frame_map_` if the map
// doesn't have it. Note that it could return nullptr if `render_frame_host`
// is not live or `render_frame_host` does not immediately belong to the
// associated `WebContents`.
mojom::LocalFrame* GetLocalFrame(content::RenderFrameHost* render_frame_host);
// Similar to `GetLocalFrame` but will not return nullptr, will crash.
mojom::LocalFrame& GetLocalFrameChecked(
content::RenderFrameHost* render_frame_host);
// Tells the receiver to start listening to window ID changes from the
// supplied SessionTabHelper. This method is public to allow the code that
// installs new SessionTabHelpers to call it; that in turn is required because
// SessionTabHelpers may be created after the corresponding
// ExtensionWebContentsObserver has already been initialized.
void ListenToWindowIdChangesFrom(sessions::SessionTabHelper* helper);
ExtensionFrameHost* extension_frame_host_for_testing() {
return extension_frame_host_.get();
}
protected:
explicit ExtensionWebContentsObserver(content::WebContents* web_contents);
~ExtensionWebContentsObserver() override;
bool initialized() const { return initialized_; }
content::BrowserContext* browser_context() { return browser_context_; }
// Initializes a new render frame. Subclasses should invoke this
// implementation if extending. Note: this should be called for both extension
// and non-extension frames.
virtual void InitializeRenderFrame(
content::RenderFrameHost* render_frame_host);
// Creates ExtensionFrameHost which implements mojom::LocalFrameHost.
virtual std::unique_ptr<ExtensionFrameHost> CreateExtensionFrameHost(
content::WebContents* web_contents);
// ExtensionFunctionDispatcher::Delegate overrides.
content::WebContents* GetAssociatedWebContents() const override;
// content::WebContentsObserver overrides.
void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override;
void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
void ReadyToCommitNavigation(
content::NavigationHandle* navigation_handle) override;
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override;
void MediaPictureInPictureChanged(bool is_picture_in_picture) override;
// Per the documentation in WebContentsObserver, these two methods are invoked
// when a Pepper plugin instance is attached/detached in the page DOM.
void PepperInstanceCreated() override;
void PepperInstanceDeleted() override;
// Temporarily needed to host common code between RenderFrameCreated and
// ReadyToCommitNavigation.
virtual void SetUpRenderFrameHost(
content::RenderFrameHost* render_frame_host);
private:
using PassKey = base::PassKey<ExtensionWebContentsObserver>;
void OnWindowIdChanged(SessionID id);
// The BrowserContext associated with the WebContents being observed.
raw_ptr<content::BrowserContext> browser_context_;
ExtensionFunctionDispatcher dispatcher_;
// Whether this object has been initialized.
bool initialized_;
std::unique_ptr<ExtensionFrameHost> extension_frame_host_;
base::CallbackListSubscription window_id_subscription_;
// A map of RenderFrameHost to mojo remotes.
std::map<content::RenderFrameHost*, mojo::AssociatedRemote<mojom::LocalFrame>>
local_frame_map_;
};
} // namespace extensions
#endif // EXTENSIONS_BROWSER_EXTENSION_WEB_CONTENTS_OBSERVER_H_
|