| 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 |