OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "extensions/browser/renderer_startup_helper.h" | 5 #include "extensions/browser/renderer_startup_helper.h" |
6 | 6 |
7 #include "base/debug/dump_without_crashing.h" | 7 #include "base/debug/dump_without_crashing.h" |
8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
10 #include "base/values.h" | 10 #include "base/values.h" |
11 #include "components/keyed_service/content/browser_context_dependency_manager.h" | 11 #include "components/keyed_service/content/browser_context_dependency_manager.h" |
| 12 #include "content/public/browser/browser_context.h" |
12 #include "content/public/browser/notification_service.h" | 13 #include "content/public/browser/notification_service.h" |
13 #include "content/public/browser/notification_types.h" | 14 #include "content/public/browser/notification_types.h" |
14 #include "content/public/browser/render_process_host.h" | 15 #include "content/public/browser/render_process_host.h" |
15 #include "extensions/browser/extension_function_dispatcher.h" | 16 #include "extensions/browser/extension_function_dispatcher.h" |
16 #include "extensions/browser/extension_registry.h" | 17 #include "extensions/browser/extension_registry.h" |
| 18 #include "extensions/browser/extension_util.h" |
17 #include "extensions/browser/extensions_browser_client.h" | 19 #include "extensions/browser/extensions_browser_client.h" |
18 #include "extensions/browser/guest_view/web_view/web_view_guest.h" | 20 #include "extensions/browser/guest_view/web_view/web_view_guest.h" |
19 #include "extensions/common/extension_messages.h" | 21 #include "extensions/common/extension_messages.h" |
20 #include "extensions/common/extension_set.h" | 22 #include "extensions/common/extension_set.h" |
21 #include "extensions/common/extensions_client.h" | 23 #include "extensions/common/extensions_client.h" |
22 #include "extensions/common/features/feature_channel.h" | 24 #include "extensions/common/features/feature_channel.h" |
23 #include "extensions/common/features/feature_session_type.h" | 25 #include "extensions/common/features/feature_session_type.h" |
24 #include "ui/base/webui/web_ui_util.h" | 26 #include "ui/base/webui/web_ui_util.h" |
25 | 27 |
26 using content::BrowserContext; | 28 using content::BrowserContext; |
27 | 29 |
28 namespace extensions { | 30 namespace extensions { |
29 | 31 |
| 32 namespace { |
| 33 |
| 34 // Returns whether the |extension| should be loaded in the given |
| 35 // |browser_context|. |
| 36 bool IsExtensionVisibleToContext(const Extension& extension, |
| 37 content::BrowserContext* browser_context) { |
| 38 // Renderers don't need to know about themes. |
| 39 if (extension.is_theme()) |
| 40 return false; |
| 41 |
| 42 // Only extensions enabled in incognito mode should be loaded in an incognito |
| 43 // renderer. However extensions which can't be enabled in the incognito mode |
| 44 // (e.g. platform apps) should also be loaded in an incognito renderer to |
| 45 // ensure connections from incognito tabs to such extensions work. |
| 46 return !browser_context->IsOffTheRecord() || |
| 47 !util::CanBeIncognitoEnabled(&extension) || |
| 48 util::IsIncognitoEnabled(extension.id(), browser_context); |
| 49 } |
| 50 |
| 51 } // namespace |
| 52 |
30 RendererStartupHelper::RendererStartupHelper(BrowserContext* browser_context) | 53 RendererStartupHelper::RendererStartupHelper(BrowserContext* browser_context) |
31 : browser_context_(browser_context) { | 54 : browser_context_(browser_context) { |
32 DCHECK(browser_context); | 55 DCHECK(browser_context); |
33 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED, | 56 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED, |
34 content::NotificationService::AllBrowserContextsAndSources()); | 57 content::NotificationService::AllBrowserContextsAndSources()); |
35 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 58 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
36 content::NotificationService::AllBrowserContextsAndSources()); | 59 content::NotificationService::AllBrowserContextsAndSources()); |
37 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | 60 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, |
38 content::NotificationService::AllBrowserContextsAndSources()); | 61 content::NotificationService::AllBrowserContextsAndSources()); |
39 } | 62 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 // If the new render process is a WebView guest process, propagate the WebView | 118 // If the new render process is a WebView guest process, propagate the WebView |
96 // partition ID to it. | 119 // partition ID to it. |
97 std::string webview_partition_id = WebViewGuest::GetPartitionID(process); | 120 std::string webview_partition_id = WebViewGuest::GetPartitionID(process); |
98 if (!webview_partition_id.empty()) { | 121 if (!webview_partition_id.empty()) { |
99 process->Send(new ExtensionMsg_SetWebViewPartitionID( | 122 process->Send(new ExtensionMsg_SetWebViewPartitionID( |
100 WebViewGuest::GetPartitionID(process))); | 123 WebViewGuest::GetPartitionID(process))); |
101 } | 124 } |
102 | 125 |
103 // Loaded extensions. | 126 // Loaded extensions. |
104 std::vector<ExtensionMsg_Loaded_Params> loaded_extensions; | 127 std::vector<ExtensionMsg_Loaded_Params> loaded_extensions; |
| 128 BrowserContext* renderer_context = process->GetBrowserContext(); |
105 const ExtensionSet& extensions = | 129 const ExtensionSet& extensions = |
106 ExtensionRegistry::Get(browser_context_)->enabled_extensions(); | 130 ExtensionRegistry::Get(browser_context_)->enabled_extensions(); |
107 for (const auto& ext : extensions) { | 131 for (const auto& ext : extensions) { |
108 // OnLoadedExtension should have already been called for the extension. | 132 // OnLoadedExtension should have already been called for the extension. |
109 DCHECK(base::ContainsKey(extension_process_map_, ext->id())); | 133 DCHECK(base::ContainsKey(extension_process_map_, ext->id())); |
110 DCHECK(!base::ContainsKey(extension_process_map_[ext->id()], process)); | 134 DCHECK(!base::ContainsKey(extension_process_map_[ext->id()], process)); |
111 | 135 |
112 // Renderers don't need to know about themes. | 136 if (!IsExtensionVisibleToContext(*ext, renderer_context)) |
113 if (!ext->is_theme()) { | 137 continue; |
114 // TODO(kalman): Only include tab specific permissions for extension | 138 |
115 // processes, no other process needs it, so it's mildly wasteful. | 139 // TODO(kalman): Only include tab specific permissions for extension |
116 // I am not sure this is possible to know this here, at such a low | 140 // processes, no other process needs it, so it's mildly wasteful. |
117 // level of the stack. Perhaps site isolation can help. | 141 // I am not sure this is possible to know this here, at such a low |
118 bool include_tab_permissions = true; | 142 // level of the stack. Perhaps site isolation can help. |
119 loaded_extensions.push_back( | 143 bool include_tab_permissions = true; |
120 ExtensionMsg_Loaded_Params(ext.get(), include_tab_permissions)); | 144 loaded_extensions.push_back( |
121 extension_process_map_[ext->id()].insert(process); | 145 ExtensionMsg_Loaded_Params(ext.get(), include_tab_permissions)); |
122 } | 146 extension_process_map_[ext->id()].insert(process); |
123 } | 147 } |
| 148 |
| 149 // Activate pending extensions. |
124 process->Send(new ExtensionMsg_Loaded(loaded_extensions)); | 150 process->Send(new ExtensionMsg_Loaded(loaded_extensions)); |
125 auto iter = pending_active_extensions_.find(process); | 151 auto iter = pending_active_extensions_.find(process); |
126 if (iter != pending_active_extensions_.end()) { | 152 if (iter != pending_active_extensions_.end()) { |
127 for (const ExtensionId& id : iter->second) { | 153 for (const ExtensionId& id : iter->second) { |
128 // The extension should be loaded in the process. | 154 // The extension should be loaded in the process. |
129 DCHECK(extensions.Contains(id)); | 155 DCHECK(extensions.Contains(id)); |
130 DCHECK(base::ContainsKey(extension_process_map_, id)); | 156 DCHECK(base::ContainsKey(extension_process_map_, id)); |
131 DCHECK(base::ContainsKey(extension_process_map_[id], process)); | 157 DCHECK(base::ContainsKey(extension_process_map_[id], process)); |
132 process->Send(new ExtensionMsg_ActivateExtension(id)); | 158 process->Send(new ExtensionMsg_ActivateExtension(id)); |
133 } | 159 } |
(...skipping 24 matching lines...) Expand all Loading... |
158 if (!base::ContainsKey(extension_process_map_, extension.id())) { | 184 if (!base::ContainsKey(extension_process_map_, extension.id())) { |
159 #if DCHECK_IS_ON() | 185 #if DCHECK_IS_ON() |
160 NOTREACHED() << "Extension " << extension.id() | 186 NOTREACHED() << "Extension " << extension.id() |
161 << "activated before loading"; | 187 << "activated before loading"; |
162 #else | 188 #else |
163 base::debug::DumpWithoutCrashing(); | 189 base::debug::DumpWithoutCrashing(); |
164 return; | 190 return; |
165 #endif | 191 #endif |
166 } | 192 } |
167 | 193 |
168 // Renderers don't need to know about themes. We also don't normally | 194 if (!IsExtensionVisibleToContext(extension, process->GetBrowserContext())) |
169 // "activate" themes, but this could happen if someone tries to open a tab | |
170 // to the e.g. theme's manifest. | |
171 if (extension.is_theme()) | |
172 return; | 195 return; |
173 | 196 |
174 if (base::ContainsKey(initialized_processes_, process)) { | 197 if (base::ContainsKey(initialized_processes_, process)) { |
175 DCHECK(base::ContainsKey(extension_process_map_[extension.id()], process)); | 198 DCHECK(base::ContainsKey(extension_process_map_[extension.id()], process)); |
176 process->Send(new ExtensionMsg_ActivateExtension(extension.id())); | 199 process->Send(new ExtensionMsg_ActivateExtension(extension.id())); |
177 } else { | 200 } else { |
178 pending_active_extensions_[process].insert(extension.id()); | 201 pending_active_extensions_[process].insert(extension.id()); |
179 } | 202 } |
180 } | 203 } |
181 | 204 |
182 void RendererStartupHelper::OnExtensionLoaded(const Extension& extension) { | 205 void RendererStartupHelper::OnExtensionLoaded(const Extension& extension) { |
183 // Extension was already loaded. | 206 // Extension was already loaded. |
184 // TODO(crbug.com/708230): Ensure that clients don't call this for an | 207 // TODO(crbug.com/708230): Ensure that clients don't call this for an |
185 // already loaded extension and change this to a DCHECK. | 208 // already loaded extension and change this to a DCHECK. |
186 if (base::ContainsKey(extension_process_map_, extension.id())) | 209 if (base::ContainsKey(extension_process_map_, extension.id())) |
187 return; | 210 return; |
188 | 211 |
189 // Mark the extension as loaded. | 212 // Mark the extension as loaded. |
190 std::set<content::RenderProcessHost*>& loaded_process_set = | 213 std::set<content::RenderProcessHost*>& loaded_process_set = |
191 extension_process_map_[extension.id()]; | 214 extension_process_map_[extension.id()]; |
192 | 215 |
193 // Renderers don't need to know about themes. | 216 // IsExtensionVisibleToContext() would filter out themes, but we choose to |
| 217 // return early for performance reasons. |
194 if (extension.is_theme()) | 218 if (extension.is_theme()) |
195 return; | 219 return; |
196 | 220 |
197 // We don't need to include tab permisisons here, since the extension | 221 // We don't need to include tab permisisons here, since the extension |
198 // was just loaded. | 222 // was just loaded. |
199 // Uninitialized renderers will be informed of the extension load during the | 223 // Uninitialized renderers will be informed of the extension load during the |
200 // first batch of messages. | 224 // first batch of messages. |
201 std::vector<ExtensionMsg_Loaded_Params> params( | 225 std::vector<ExtensionMsg_Loaded_Params> params( |
202 1, | 226 1, |
203 ExtensionMsg_Loaded_Params(&extension, false /* no tab permissions */)); | 227 ExtensionMsg_Loaded_Params(&extension, false /* no tab permissions */)); |
204 for (content::RenderProcessHost* process : initialized_processes_) { | 228 for (content::RenderProcessHost* process : initialized_processes_) { |
| 229 if (!IsExtensionVisibleToContext(extension, process->GetBrowserContext())) |
| 230 continue; |
205 process->Send(new ExtensionMsg_Loaded(params)); | 231 process->Send(new ExtensionMsg_Loaded(params)); |
206 loaded_process_set.insert(process); | 232 loaded_process_set.insert(process); |
207 } | 233 } |
208 } | 234 } |
209 | 235 |
210 void RendererStartupHelper::OnExtensionUnloaded(const Extension& extension) { | 236 void RendererStartupHelper::OnExtensionUnloaded(const Extension& extension) { |
211 // Extension is not loaded. | 237 // Extension is not loaded. |
212 // TODO(crbug.com/708230): Ensure that clients call this for a loaded | 238 // TODO(crbug.com/708230): Ensure that clients call this for a loaded |
213 // extension only and change this to a DCHECK. | 239 // extension only and change this to a DCHECK. |
214 if (!base::ContainsKey(extension_process_map_, extension.id())) | 240 if (!base::ContainsKey(extension_process_map_, extension.id())) |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 BrowserContext* context) const { | 286 BrowserContext* context) const { |
261 // Redirected in incognito. | 287 // Redirected in incognito. |
262 return ExtensionsBrowserClient::Get()->GetOriginalContext(context); | 288 return ExtensionsBrowserClient::Get()->GetOriginalContext(context); |
263 } | 289 } |
264 | 290 |
265 bool RendererStartupHelperFactory::ServiceIsCreatedWithBrowserContext() const { | 291 bool RendererStartupHelperFactory::ServiceIsCreatedWithBrowserContext() const { |
266 return true; | 292 return true; |
267 } | 293 } |
268 | 294 |
269 } // namespace extensions | 295 } // namespace extensions |
OLD | NEW |