1 // 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 COMPONENTS_JS_INJECTION_BROWSER_JS_COMMUNICATION_HOST_H_
6 #define COMPONENTS_JS_INJECTION_BROWSER_JS_COMMUNICATION_HOST_H_
7 
8 #include <memory>
9 #include <vector>
10 
11 #include "base/optional.h"
12 #include "base/strings/string16.h"
13 #include "components/js_injection/common/interfaces.mojom.h"
14 #include "content/public/browser/web_contents_observer.h"
15 
16 namespace content {
17 class RenderFrameHost;
18 }  // namespace content
19 
20 namespace js_injection {
21 
22 class OriginMatcher;
23 struct DocumentStartJavaScript;
24 struct JsObject;
25 class JsToBrowserMessaging;
26 class WebMessageHostFactory;
27 
28 // This class is 1:1 with WebContents, when AddWebMessageListener() is called,
29 // it stores the information in this class and send them to renderer side
30 // JsCommunication if there is any. When RenderFrameCreated() gets called, it
31 // needs to configure that new RenderFrame with the information stores in this
32 // class.
33 class JsCommunicationHost : public content::WebContentsObserver {
34  public:
35   explicit JsCommunicationHost(content::WebContents* web_contents);
36   ~JsCommunicationHost() override;
37 
38   // Captures the result of adding script. There are two possibilities when
39   // adding script: there was an error, in which case |error_message| is set,
40   // otherwise the add was successful and |script_id| is set.
41   struct AddScriptResult {
42     AddScriptResult();
43     AddScriptResult(const AddScriptResult&);
44     AddScriptResult& operator=(const AddScriptResult&);
45     ~AddScriptResult();
46 
47     base::Optional<std::string> error_message;
48     base::Optional<int> script_id;
49   };
50 
51   // Native side AddDocumentStartJavaScript, returns an error message if the
52   // parameters didn't pass necessary checks.
53   AddScriptResult AddDocumentStartJavaScript(
54       const base::string16& script,
55       const std::vector<std::string>& allowed_origin_rules);
56 
57   bool RemoveDocumentStartJavaScript(int script_id);
58 
59   // Adds a new WebMessageHostFactory. For any urls that match
60   // |allowed_origin_rules|, |js_object_name| is registered as a JS object that
61   // can be used by script on the page to send and receive messages. Returns
62   // an empty string on success. On failure, the return string gives the error
63   // message.
64   base::string16 AddWebMessageHostFactory(
65       std::unique_ptr<WebMessageHostFactory> factory,
66       const base::string16& js_object_name,
67       const std::vector<std::string>& allowed_origin_rules);
68 
69   // Returns the factory previously registered under the specified name.
70   void RemoveWebMessageHostFactory(const base::string16& js_object_name);
71 
72   struct RegisteredFactory {
73     base::string16 js_name;
74     OriginMatcher allowed_origin_rules;
75     WebMessageHostFactory* factory = nullptr;
76   };
77 
78   // Returns the registered factories.
79   std::vector<RegisteredFactory> GetWebMessageHostFactories();
80 
81   // content::WebContentsObserver implementations
82   void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override;
83   void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
84 
85  private:
86   void NotifyFrameForWebMessageListener(
87       content::RenderFrameHost* render_frame_host);
88   void NotifyFrameForAllDocumentStartJavaScripts(
89       content::RenderFrameHost* render_frame_host);
90   void NotifyFrameForAddDocumentStartJavaScript(
91       const DocumentStartJavaScript* script,
92       content::RenderFrameHost* render_frame_host);
93 
94   void NotifyFrameForRemoveDocumentStartJavaScript(
95       int32_t script_id,
96       content::RenderFrameHost* render_frame_host);
97 
98   int32_t next_script_id_ = 0;
99   std::vector<DocumentStartJavaScript> scripts_;
100   std::vector<std::unique_ptr<JsObject>> js_objects_;
101   std::map<content::RenderFrameHost*,
102            std::vector<std::unique_ptr<JsToBrowserMessaging>>>
103       js_to_browser_messagings_;
104 
105   DISALLOW_COPY_AND_ASSIGN(JsCommunicationHost);
106 };
107 
108 }  // namespace js_injection
109 
110 #endif  // COMPONENTS_JS_INJECTION_BROWSER_JS_COMMUNICATION_HOST_H_
111