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.
5 #include "extensions/renderer/user_script_set_manager.h"
7 #include "components/crx_file/id_util.h"
8 #include "content/public/renderer/render_thread.h"
9 #include "extensions/common/extension_messages.h"
10 #include "extensions/renderer/dispatcher.h"
11 #include "extensions/renderer/script_injection.h"
12 #include "extensions/renderer/user_script_set.h"
13 #include "ipc/ipc_message.h"
14 #include "ipc/ipc_message_macros.h"
15 #include "third_party/WebKit/public/web/WebFrame.h"
17 namespace extensions
{
19 UserScriptSetManager::UserScriptSetManager(const ExtensionSet
* extensions
)
20 : static_scripts_(extensions
), extensions_(extensions
) {
21 content::RenderThread::Get()->AddObserver(this);
24 UserScriptSetManager::~UserScriptSetManager() {
27 void UserScriptSetManager::AddObserver(Observer
* observer
) {
28 observers_
.AddObserver(observer
);
31 void UserScriptSetManager::RemoveObserver(Observer
* observer
) {
32 observers_
.RemoveObserver(observer
);
35 scoped_ptr
<ScriptInjection
>
36 UserScriptSetManager::GetInjectionForDeclarativeScript(
38 blink::WebFrame
* web_frame
,
41 const std::string
& extension_id
) {
42 UserScriptSet
* user_script_set
=
43 GetProgrammaticScriptsByExtension(extension_id
);
45 return scoped_ptr
<ScriptInjection
>();
47 return user_script_set
->GetDeclarativeScriptInjection(
51 UserScript::BROWSER_DRIVEN
,
55 bool UserScriptSetManager::OnControlMessageReceived(
56 const IPC::Message
& message
) {
58 IPC_BEGIN_MESSAGE_MAP(UserScriptSetManager
, message
)
59 IPC_MESSAGE_HANDLER(ExtensionMsg_UpdateUserScripts
, OnUpdateUserScripts
)
60 IPC_MESSAGE_UNHANDLED(handled
= false)
65 void UserScriptSetManager::GetAllInjections(
66 ScopedVector
<ScriptInjection
>* injections
,
67 blink::WebFrame
* web_frame
,
69 UserScript::RunLocation run_location
) {
70 static_scripts_
.GetInjections(injections
, web_frame
, tab_id
, run_location
);
71 for (UserScriptSetMap::iterator it
= programmatic_scripts_
.begin();
72 it
!= programmatic_scripts_
.end();
74 it
->second
->GetInjections(injections
, web_frame
, tab_id
, run_location
);
78 void UserScriptSetManager::GetAllActiveExtensionIds(
79 std::set
<std::string
>* ids
) const {
81 static_scripts_
.GetActiveExtensionIds(ids
);
82 for (UserScriptSetMap::const_iterator it
= programmatic_scripts_
.begin();
83 it
!= programmatic_scripts_
.end();
85 it
->second
->GetActiveExtensionIds(ids
);
89 UserScriptSet
* UserScriptSetManager::GetProgrammaticScriptsByExtension(
90 const ExtensionId
& extension_id
) {
91 UserScriptSetMap::const_iterator it
=
92 programmatic_scripts_
.find(extension_id
);
93 return it
!= programmatic_scripts_
.end() ? it
->second
.get() : NULL
;
96 void UserScriptSetManager::OnUpdateUserScripts(
97 base::SharedMemoryHandle shared_memory
,
98 const ExtensionId
& extension_id
,
99 const std::set
<std::string
>& changed_extensions
) {
100 if (!base::SharedMemory::IsHandleValid(shared_memory
)) {
101 NOTREACHED() << "Bad scripts handle";
105 for (std::set
<std::string
>::const_iterator iter
= changed_extensions
.begin();
106 iter
!= changed_extensions
.end();
108 if (!crx_file::id_util::IdIsValid(*iter
)) {
109 NOTREACHED() << "Invalid extension id: " << *iter
;
114 UserScriptSet
* scripts
= NULL
;
115 if (!extension_id
.empty()) {
116 // The expectation when there is an extension that "owns" this shared
117 // memory region is that the |changed_extensions| is either the empty list
118 // or just the owner.
119 CHECK(changed_extensions
.size() <= 1);
120 if (programmatic_scripts_
.find(extension_id
) ==
121 programmatic_scripts_
.end()) {
122 scripts
= new UserScriptSet(extensions_
);
123 programmatic_scripts_
[extension_id
] = make_linked_ptr(scripts
);
125 scripts
= programmatic_scripts_
[extension_id
].get();
128 scripts
= &static_scripts_
;
132 // If no extensions are included in the set, that indicates that all
133 // extensions were updated. Add them all to the set so that observers and
134 // individual UserScriptSets don't need to know this detail.
135 const std::set
<std::string
>* effective_extensions
= &changed_extensions
;
136 std::set
<std::string
> all_extensions
;
137 if (changed_extensions
.empty()) {
138 // The meaning of "all extensions" varies, depending on whether some
139 // extension "owns" this shared memory region.
140 // No owner => all known extensions.
141 // Owner => just the owner extension.
142 if (extension_id
.empty())
143 all_extensions
= extensions_
->GetIDs();
145 all_extensions
.insert(extension_id
);
146 effective_extensions
= &all_extensions
;
149 if (scripts
->UpdateUserScripts(shared_memory
, *effective_extensions
)) {
153 OnUserScriptsUpdated(*effective_extensions
, scripts
->scripts()));
157 } // namespace extensions