blob: 2c57bdcd0ed238071cb97245405f41ff67b9aa57 [file] [log] [blame]
Oksana Zhuravlova4dd171e82019-08-16 20:54:001// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_CHROME_BROWSER_INTERFACE_BINDERS_H_
6#define CHROME_BROWSER_CHROME_BROWSER_INTERFACE_BINDERS_H_
7
Christopher Lam2b09b822020-01-29 03:10:528#include "chrome/browser/bad_message.h"
9#include "content/public/browser/render_frame_host.h"
10#include "content/public/browser/web_contents.h"
Lei Zhang4b21e9c2020-02-28 00:32:0211#include "content/public/browser/web_ui.h"
Christopher Lam2b09b822020-01-29 03:10:5212#include "content/public/browser/web_ui_controller.h"
Robert Sesek5a5fbb82020-05-04 16:18:2813#include "mojo/public/cpp/bindings/binder_map.h"
Oksana Zhuravlova4dd171e82019-08-16 20:54:0014
15namespace content {
16
17class RenderFrameHost;
18} // namespace content
19
20namespace chrome {
21namespace internal {
22
Mario Sanchez Pradafe81d6c2019-12-16 11:25:0523// The mechanism implemented by the PopulateChrome*FrameBinders() functions
24// below will replace interface registries and binders used for handling
25// InterfaceProvider's GetInterface() calls (see crbug.com/718652).
26
Oksana Zhuravlova4dd171e82019-08-16 20:54:0027// PopulateChromeFrameBinders() registers BrowserInterfaceBroker's
28// GetInterface() handler callbacks for chrome-specific document-scoped
Mario Sanchez Pradafe81d6c2019-12-16 11:25:0529// interfaces.
Oksana Zhuravlova4dd171e82019-08-16 20:54:0030void PopulateChromeFrameBinders(
Wei-Yin Chen (陳威尹)5c2761d2021-03-06 09:15:5331 mojo::BinderMapWithContext<content::RenderFrameHost*>* map,
32 content::RenderFrameHost* render_frame_host);
Oksana Zhuravlova4dd171e82019-08-16 20:54:0033
Mario Sanchez Pradafe81d6c2019-12-16 11:25:0534// PopulateChromeWebUIFrameBinders() registers BrowserInterfaceBroker's
35// GetInterface() handler callbacks for chrome-specific document-scoped
36// interfaces used from WebUI pages (e.g. chrome://bluetooth-internals).
37void PopulateChromeWebUIFrameBinders(
Robert Sesek5a5fbb82020-05-04 16:18:2838 mojo::BinderMapWithContext<content::RenderFrameHost*>* map);
Mario Sanchez Pradafe81d6c2019-12-16 11:25:0539
Christopher Lam2b09b822020-01-29 03:10:5240template <typename Interface, int N, typename... Subclasses>
41struct BinderHelper;
42
43template <typename Interface, typename WebUIControllerSubclass>
44bool SafeDownCastAndBindInterface(content::WebUI* web_ui,
45 mojo::PendingReceiver<Interface>& receiver) {
46 // Performs a safe downcast to the concrete WebUIController subclass.
47 WebUIControllerSubclass* concrete_controller =
48 web_ui ? web_ui->GetController()->GetAs<WebUIControllerSubclass>()
49 : nullptr;
50
51 if (!concrete_controller)
52 return false;
53
54 // Fails to compile if |Subclass| does not implement the appropriate overload
55 // for |Interface|.
56 concrete_controller->BindInterface(std::move(receiver));
57 return true;
58}
59
60template <typename Interface, int N, typename Subclass, typename... Subclasses>
61struct BinderHelper<Interface, N, std::tuple<Subclass, Subclasses...>> {
62 static bool BindInterface(content::WebUI* web_ui,
63 mojo::PendingReceiver<Interface> receiver) {
64 // Try a different subclass if the current one is not the right
65 // WebUIController for the current WebUI page, and only fail if none of the
66 // passed subclasses match.
67 if (!SafeDownCastAndBindInterface<Interface, Subclass>(web_ui, receiver)) {
68 return BinderHelper<Interface, N - 1, std::tuple<Subclasses...>>::
69 BindInterface(web_ui, std::move(receiver));
70 }
71 return true;
72 }
73};
74
75template <typename Interface, typename Subclass, typename... Subclasses>
76struct BinderHelper<Interface, 0, std::tuple<Subclass, Subclasses...>> {
77 static bool BindInterface(content::WebUI* web_ui,
78 mojo::PendingReceiver<Interface> receiver) {
79 return SafeDownCastAndBindInterface<Interface, Subclass>(web_ui, receiver);
80 }
81};
82
83// Registers a binder in |map| that binds |Interface| iff the RenderFrameHost
84// has a WebUIController among type |WebUIControllerSubclasses|.
85template <typename Interface, typename... WebUIControllerSubclasses>
86void RegisterWebUIControllerInterfaceBinder(
Robert Sesek5a5fbb82020-05-04 16:18:2887 mojo::BinderMapWithContext<content::RenderFrameHost*>* map) {
Christopher Lam2b09b822020-01-29 03:10:5288 map->Add<Interface>(
89 base::BindRepeating([](content::RenderFrameHost* host,
90 mojo::PendingReceiver<Interface> receiver) {
91 // This is expected to be called only for main frames.
92 if (host->GetParent()) {
93 ReceivedBadMessage(
94 host->GetProcess(),
95 bad_message::BadMessageReason::RFH_INVALID_WEB_UI_CONTROLLER);
96 return;
97 }
98
99 const int size = sizeof...(WebUIControllerSubclasses);
Christopher Lam2b09b822020-01-29 03:10:52100 bool is_bound = BinderHelper<Interface, size - 1,
101 std::tuple<WebUIControllerSubclasses...>>::
Nasko Oskov310c66a2020-05-18 21:58:57102 BindInterface(host->GetWebUI(), std::move(receiver));
Christopher Lam2b09b822020-01-29 03:10:52103
104 // This is expected to be called only for the right WebUI pages matching
105 // the same WebUI associated to the RenderFrameHost.
106 if (!is_bound) {
107 ReceivedBadMessage(
108 host->GetProcess(),
109 bad_message::BadMessageReason::RFH_INVALID_WEB_UI_CONTROLLER);
110 return;
111 }
112 }));
113}
114
Oksana Zhuravlova4dd171e82019-08-16 20:54:00115} // namespace internal
116} // namespace chrome
117
118#endif // CHROME_BROWSER_CHROME_BROWSER_INTERFACE_BINDERS_H_