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
|
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_WEBUI_WEB_UI_IMPL_H_
#define CONTENT_BROWSER_WEBUI_WEB_UI_IMPL_H_
#include <map>
#include <memory>
#include <string>
#include <string_view>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/webui/url_data_manager_backend.h"
#include "content/common/content_export.h"
#include "content/common/web_ui.mojom.h"
#include "content/public/browser/web_ui.h"
#include "content/public/common/bindings_policy.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "third_party/blink/public/mojom/loader/local_resource_loader_config.mojom.h"
namespace content {
class NavigationRequest;
class RenderFrameHost;
class RenderFrameHostImpl;
class WebUIMainFrameObserver;
class CONTENT_EXPORT WebUIImpl : public WebUI, public mojom::WebUIHost {
public:
explicit WebUIImpl(WebContents* web_contents);
explicit WebUIImpl(NavigationRequest* request);
WebUIImpl(const WebUIImpl&) = delete;
WebUIImpl& operator=(const WebUIImpl&) = delete;
~WebUIImpl() override;
// A WebUIImpl object is created and owned by the WebUI navigation's
// NavigationRequest, until a RenderFrameHost has been picked for the
// navigation, at which point the ownership of the WebUIImpl object is moved
// to the RenderFrameHost. This function is called when that happens.
void SetRenderFrameHost(RenderFrameHost* render_frame_host);
// Called when a RenderFrame is created for a WebUI (reload after a renderer
// crash) or when a WebUI is created for a RenderFrame (i.e. navigating from
// chrome://downloads to chrome://bookmarks) or when both are new (i.e.
// opening a new tab).
void WebUIRenderFrameCreated(RenderFrameHost* render_frame_host);
// Called when the owning RenderFrameHost has started unloading.
void RenderFrameHostUnloading();
// Called when the renderer-side frame is destroyed, along with any mojo
// connections to it. The browser can not attempt to communicate with the
// renderer afterward.
void RenderFrameDeleted();
// Called right after AllowBindings is notified to a RenderFrame.
void SetUpMojoConnection();
// Called when a RenderFrame is deleted for a WebUI (i.e. a renderer crash).
void TearDownMojoConnection();
// Add a property to the WebUI binding object.
void SetProperty(const std::string& name, const std::string& value);
// WebUI implementation:
WebContents* GetWebContents() override;
WebUIController* GetController() override;
RenderFrameHost* GetRenderFrameHost() override;
void SetController(std::unique_ptr<WebUIController> controller) override;
float GetDeviceScaleFactor() override;
const std::u16string& GetOverriddenTitle() override;
void OverrideTitle(const std::u16string& title) override;
BindingsPolicySet GetBindings() override;
void SetBindings(BindingsPolicySet bindings) override;
const std::vector<std::string>& GetRequestableSchemes() override;
void AddRequestableScheme(const char* scheme) override;
void AddMessageHandler(std::unique_ptr<WebUIMessageHandler> handler) override;
void RegisterMessageCallback(std::string_view message,
MessageCallback callback) override;
void ProcessWebUIMessage(const GURL& source_url,
const std::string& message,
base::Value::List args) override;
bool CanCallJavascript() override;
void CallJavascriptFunctionUnsafe(
std::string_view function_name,
base::span<const base::ValueView> args) override;
std::vector<std::unique_ptr<WebUIMessageHandler>>* GetHandlersForTesting()
override;
const mojo::AssociatedRemote<mojom::WebUI>& GetRemoteForTest() const {
return remote_;
}
WebUIMainFrameObserver* GetWebUIMainFrameObserverForTest() const {
return web_contents_observer_.get();
}
bool HasRenderFrameHost() const;
static blink::mojom::LocalResourceLoaderConfigPtr
GetLocalResourceLoaderConfigForTesting(URLDataManagerBackend* data_backend);
private:
friend class WebUIMainFrameObserver;
// mojom::WebUIHost
void Send(const std::string& message, base::Value::List args) override;
// Execute a string of raw JavaScript on the page.
void ExecuteJavascript(const std::u16string& javascript);
// Called internally and by the owned WebUIMainFrameObserver.
void DisallowJavascriptOnAllHandlers();
blink::mojom::LocalResourceLoaderConfigPtr GetLocalResourceLoaderConfig();
// A map of message name -> message handling callback.
std::map<std::string, MessageCallback> message_callbacks_;
// Options that may be overridden by individual Web UI implementations. The
// bool options default to false. See the public getters for more information.
std::u16string overridden_title_; // Defaults to empty string.
// The bindings that should be enabled for this page.
BindingsPolicySet bindings_ =
BindingsPolicySet({BindingsPolicyValue::kWebUi});
// The URL schemes that can be requested by this document.
std::vector<std::string> requestable_schemes_;
// Non-owning pointer to the WebContents and RenderFrameHostImpl this WebUI is
// associated with. It is generally safe, because |web_content_| indirectly
// owns |frame_host_|, which owns |this|.
//
// Note: During the destructor, releasing |controller_| calls content/
// embedder code. This might delete both synchronously.
// This lead to one UAF. See https://crbug.com/1308391
// See regression test:
// `WebUIImplBrowserTest::SynchronousWebContentDeletionInUnload`
const raw_ptr<WebContents, DisableDanglingPtrDetection> web_contents_;
// During WebUI construction, `frame_host_` might stay unset for a while,
// as the WebUIImpl object is created early in a navigation, and a
// RenderFrameHost for the navigation might not be created until the final
// response for the navigation is received in some cases
// (after `NavigationRequest::OnResponseStarted()`).
// During WebUI destruction, `frame_host_` is always valid except
// if the WebContents is destroyed by the WebUIController subclass.
// See regression test:
// `WebUIImplBrowserTest::SynchronousWebContentDeletionInUnload`
base::WeakPtr<RenderFrameHostImpl> frame_host_;
// The WebUIMessageHandlers we own.
std::vector<std::unique_ptr<WebUIMessageHandler>> handlers_;
// Notifies this WebUI about notifications in the main frame.
const std::unique_ptr<WebUIMainFrameObserver> web_contents_observer_;
std::unique_ptr<WebUIController> controller_;
mojo::AssociatedRemote<mojom::WebUI> remote_;
mojo::AssociatedReceiver<mojom::WebUIHost> receiver_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_WEBUI_WEB_UI_IMPL_H_
|