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
content / browser / webui / web_ui_impl.h [blame]
// 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_