1 // Copyright 2014 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 EXTENSIONS_RENDERER_USER_SCRIPT_SET_MANAGER_H_
6 #define EXTENSIONS_RENDERER_USER_SCRIPT_SET_MANAGER_H_
7 
8 #include <map>
9 #include <set>
10 #include <string>
11 #include <vector>
12 
13 #include "base/macros.h"
14 #include "base/memory/read_only_shared_memory_region.h"
15 #include "base/observer_list.h"
16 #include "content/public/renderer/render_thread_observer.h"
17 #include "extensions/common/extension.h"
18 #include "extensions/common/user_script.h"
19 #include "extensions/renderer/user_script_set.h"
20 
21 namespace content {
22 class RenderFrame;
23 }
24 
25 namespace IPC {
26 class Message;
27 }
28 
29 namespace extensions {
30 
31 class ScriptInjection;
32 
33 // Manager for separate UserScriptSets, one for each shared memory region.
34 // Regions are organized as follows:
35 // static_scripts -- contains all extensions' scripts that are statically
36 //                   declared in the extension manifest.
37 // programmatic_scripts -- one region per host (extension or WebUI) containing
38 //                         only programmatically-declared scripts, instantiated
39 //                         when an extension first creates a declarative rule
40 //                         that would, if triggered, request a script injection.
41 class UserScriptSetManager : public content::RenderThreadObserver {
42  public:
43   // Like a UserScriptSet::Observer, but automatically subscribes to all sets
44   // associated with the manager.
45   class Observer {
46    public:
47     virtual void OnUserScriptsUpdated(
48         const std::set<HostID>& changed_hosts) = 0;
49   };
50 
51   UserScriptSetManager();
52 
53   ~UserScriptSetManager() override;
54 
55   void AddObserver(Observer* observer);
56   void RemoveObserver(Observer* observer);
57 
58   // Looks up the script injection associated with |script_id| and
59   // |extension_id| in the context of the given |web_frame|, |tab_id|,
60   // and |url|.
61   std::unique_ptr<ScriptInjection> GetInjectionForDeclarativeScript(
62       int script_id,
63       content::RenderFrame* render_frame,
64       int tab_id,
65       const GURL& url,
66       const std::string& extension_id);
67 
68   // Append all injections from |static_scripts| and each of
69   // |programmatic_scripts_| to |injections|.
70   void GetAllInjections(
71       std::vector<std::unique_ptr<ScriptInjection>>* injections,
72       content::RenderFrame* render_frame,
73       int tab_id,
74       UserScript::RunLocation run_location);
75 
76   // Get active extension IDs from |static_scripts| and each of
77   // |programmatic_scripts_|.
78   void GetAllActiveExtensionIds(std::set<std::string>* ids) const;
79 
static_scripts()80   const UserScriptSet* static_scripts() const { return &static_scripts_; }
81 
set_activity_logging_enabled(bool enabled)82   void set_activity_logging_enabled(bool enabled) {
83     activity_logging_enabled_ = enabled;
84   }
85 
86  private:
87   // Map for per-extension sets that may be defined programmatically.
88   using UserScriptSetMap = std::map<HostID, std::unique_ptr<UserScriptSet>>;
89 
90   // content::RenderThreadObserver implementation.
91   bool OnControlMessageReceived(const IPC::Message& message) override;
92 
93   UserScriptSet* GetProgrammaticScriptsByHostID(const HostID& host_id);
94 
95   // Handle the UpdateUserScripts extension message.
96   void OnUpdateUserScripts(base::ReadOnlySharedMemoryRegion shared_memory,
97                            const HostID& host_id,
98                            const std::set<HostID>& changed_hosts,
99                            bool whitelisted_only);
100 
101   // Scripts statically defined in extension manifests.
102   UserScriptSet static_scripts_;
103 
104   // Scripts programmatically-defined through API calls (initialized and stored
105   // per-extension).
106   UserScriptSetMap programmatic_scripts_;
107 
108   // Whether or not dom activity should be logged for injected scripts.
109   bool activity_logging_enabled_;
110 
111   // The associated observers.
112   base::ObserverList<Observer>::Unchecked observers_;
113 
114   DISALLOW_COPY_AND_ASSIGN(UserScriptSetManager);
115 };
116 
117 }  // namespace extensions
118 
119 #endif  // EXTENSIONS_RENDERER_USER_SCRIPT_SET_MANAGER_H_
120