Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(132)

Side by Side Diff: extensions/browser/renderer_startup_helper_unittest.cc

Issue 2766263003: Extensions: Only load incognito-enabled extensions in an incognito renderer. (Closed)
Patch Set: Address review Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « extensions/browser/renderer_startup_helper.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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/memory/ptr_util.h" 7 #include "base/memory/ptr_util.h"
8 #include "base/stl_util.h" 8 #include "base/stl_util.h"
9 #include "components/crx_file/id_util.h"
9 #include "content/public/browser/notification_service.h" 10 #include "content/public/browser/notification_service.h"
10 #include "content/public/browser/notification_types.h" 11 #include "content/public/browser/notification_types.h"
11 #include "content/public/test/mock_render_process_host.h" 12 #include "content/public/test/mock_render_process_host.h"
13 #include "extensions/browser/extension_prefs.h"
12 #include "extensions/browser/extension_registry.h" 14 #include "extensions/browser/extension_registry.h"
13 #include "extensions/browser/extension_registry_factory.h" 15 #include "extensions/browser/extension_registry_factory.h"
16 #include "extensions/browser/extension_util.h"
14 #include "extensions/browser/extensions_test.h" 17 #include "extensions/browser/extensions_test.h"
18 #include "extensions/browser/test_extensions_browser_client.h"
15 #include "extensions/common/extension_builder.h" 19 #include "extensions/common/extension_builder.h"
16 #include "extensions/common/extension_messages.h" 20 #include "extensions/common/extension_messages.h"
17 21
18 namespace extensions { 22 namespace extensions {
19 23
20 class RendererStartupHelperTest : public ExtensionsTest { 24 class RendererStartupHelperTest : public ExtensionsTest {
21 public: 25 public:
22 RendererStartupHelperTest() {} 26 RendererStartupHelperTest() {}
23 ~RendererStartupHelperTest() override {} 27 ~RendererStartupHelperTest() override {}
24 28
25 void SetUp() override { 29 void SetUp() override {
26 ExtensionsTest::SetUp(); 30 ExtensionsTest::SetUp();
27 helper_ = base::MakeUnique<RendererStartupHelper>(browser_context()); 31 helper_ = base::MakeUnique<RendererStartupHelper>(browser_context());
28 registry_ = 32 registry_ =
29 ExtensionRegistryFactory::GetForBrowserContext(browser_context()); 33 ExtensionRegistryFactory::GetForBrowserContext(browser_context());
30 render_process_host_ = 34 render_process_host_ =
31 base::MakeUnique<content::MockRenderProcessHost>(browser_context()); 35 base::MakeUnique<content::MockRenderProcessHost>(browser_context());
36 incognito_render_process_host_ =
37 base::MakeUnique<content::MockRenderProcessHost>(incognito_context());
32 extension_ = CreateExtension("ext_1"); 38 extension_ = CreateExtension("ext_1");
33 } 39 }
34 40
35 void TearDown() override { 41 void TearDown() override {
36 render_process_host_.reset(); 42 render_process_host_.reset();
43 incognito_render_process_host_.reset();
37 helper_.reset(); 44 helper_.reset();
38 ExtensionsTest::TearDown(); 45 ExtensionsTest::TearDown();
39 } 46 }
40 47
41 protected: 48 protected:
42 void SimulateRenderProcessCreated(content::RenderProcessHost* rph) { 49 void SimulateRenderProcessCreated(content::RenderProcessHost* rph) {
43 content::NotificationService::current()->Notify( 50 content::NotificationService::current()->Notify(
44 content::NOTIFICATION_RENDERER_PROCESS_CREATED, 51 content::NOTIFICATION_RENDERER_PROCESS_CREATED,
45 content::Source<content::RenderProcessHost>(rph), 52 content::Source<content::RenderProcessHost>(rph),
46 content::NotificationService::NoDetails()); 53 content::NotificationService::NoDetails());
47 } 54 }
48 55
49 void SimulateRenderProcessTerminated(content::RenderProcessHost* rph) { 56 void SimulateRenderProcessTerminated(content::RenderProcessHost* rph) {
50 content::NotificationService::current()->Notify( 57 content::NotificationService::current()->Notify(
51 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, 58 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
52 content::Source<content::RenderProcessHost>(rph), 59 content::Source<content::RenderProcessHost>(rph),
53 content::NotificationService::NoDetails()); 60 content::NotificationService::NoDetails());
54 } 61 }
55 62
56 scoped_refptr<Extension> CreateExtension(const std::string& extension_id) { 63 scoped_refptr<Extension> CreateExtension(const std::string& id_input) {
57 std::unique_ptr<base::DictionaryValue> manifest = 64 std::unique_ptr<base::DictionaryValue> manifest =
58 DictionaryBuilder() 65 DictionaryBuilder()
59 .Set("name", "extension") 66 .Set("name", "extension")
60 .Set("description", "an extension") 67 .Set("description", "an extension")
61 .Set("manifest_version", 2) 68 .Set("manifest_version", 2)
62 .Set("version", "0.1") 69 .Set("version", "0.1")
63 .Build(); 70 .Build();
64 return ExtensionBuilder() 71 return CreateExtension(id_input, std::move(manifest));
65 .SetManifest(std::move(manifest))
66 .SetID(extension_id)
67 .Build();
68 } 72 }
69 73
70 scoped_refptr<Extension> CreateTheme(const std::string& extension_id) { 74 scoped_refptr<Extension> CreateTheme(const std::string& id_input) {
71 std::unique_ptr<base::DictionaryValue> manifest = 75 std::unique_ptr<base::DictionaryValue> manifest =
72 DictionaryBuilder() 76 DictionaryBuilder()
73 .Set("name", "theme") 77 .Set("name", "theme")
74 .Set("description", "a theme") 78 .Set("description", "a theme")
75 .Set("theme", DictionaryBuilder().Build()) 79 .Set("theme", DictionaryBuilder().Build())
76 .Set("manifest_version", 2) 80 .Set("manifest_version", 2)
77 .Set("version", "0.1") 81 .Set("version", "0.1")
78 .Build(); 82 .Build();
79 return ExtensionBuilder() 83 return CreateExtension(id_input, std::move(manifest));
80 .SetManifest(std::move(manifest)) 84 }
81 .SetID(extension_id) 85
82 .Build(); 86 scoped_refptr<Extension> CreatePlatformApp(const std::string& id_input) {
87 std::unique_ptr<base::Value> background =
88 DictionaryBuilder()
89 .Set("scripts", ListBuilder().Append("background.js").Build())
90 .Build();
91 std::unique_ptr<base::DictionaryValue> manifest =
92 DictionaryBuilder()
93 .Set("name", "platform_app")
94 .Set("description", "a platform app")
95 .Set("app", DictionaryBuilder()
96 .Set("background", std::move(background))
97 .Build())
98 .Set("manifest_version", 2)
99 .Set("version", "0.1")
100 .Build();
101 return CreateExtension(id_input, std::move(manifest));
83 } 102 }
84 103
85 void AddExtensionToRegistry(scoped_refptr<Extension> extension) { 104 void AddExtensionToRegistry(scoped_refptr<Extension> extension) {
86 registry_->AddEnabled(extension); 105 registry_->AddEnabled(extension);
87 } 106 }
88 107
89 void RemoveExtensionFromRegistry(scoped_refptr<Extension> extension) { 108 void RemoveExtensionFromRegistry(scoped_refptr<Extension> extension) {
90 registry_->RemoveEnabled(extension->id()); 109 registry_->RemoveEnabled(extension->id());
91 } 110 }
92 111
(...skipping 15 matching lines...) Expand all
108 bool IsExtensionPendingActivationInProcess(const Extension& extension, 127 bool IsExtensionPendingActivationInProcess(const Extension& extension,
109 content::RenderProcessHost* rph) { 128 content::RenderProcessHost* rph) {
110 return base::ContainsKey(helper_->pending_active_extensions_, rph) && 129 return base::ContainsKey(helper_->pending_active_extensions_, rph) &&
111 base::ContainsKey(helper_->pending_active_extensions_[rph], 130 base::ContainsKey(helper_->pending_active_extensions_[rph],
112 extension.id()); 131 extension.id());
113 } 132 }
114 133
115 std::unique_ptr<RendererStartupHelper> helper_; 134 std::unique_ptr<RendererStartupHelper> helper_;
116 ExtensionRegistry* registry_; // Weak. 135 ExtensionRegistry* registry_; // Weak.
117 std::unique_ptr<content::MockRenderProcessHost> render_process_host_; 136 std::unique_ptr<content::MockRenderProcessHost> render_process_host_;
137 std::unique_ptr<content::MockRenderProcessHost>
138 incognito_render_process_host_;
118 scoped_refptr<Extension> extension_; 139 scoped_refptr<Extension> extension_;
119 140
120 private: 141 private:
142 scoped_refptr<Extension> CreateExtension(
143 const std::string& id_input,
144 std::unique_ptr<base::DictionaryValue> manifest) {
145 return ExtensionBuilder()
146 .SetManifest(std::move(manifest))
147 .SetID(crx_file::id_util::GenerateId(id_input))
148 .Build();
149 }
150
121 DISALLOW_COPY_AND_ASSIGN(RendererStartupHelperTest); 151 DISALLOW_COPY_AND_ASSIGN(RendererStartupHelperTest);
122 }; 152 };
123 153
124 // Tests extension loading, unloading and activation and render process creation 154 // Tests extension loading, unloading and activation and render process creation
125 // and termination. 155 // and termination.
126 TEST_F(RendererStartupHelperTest, NormalExtensionLifecycle) { 156 TEST_F(RendererStartupHelperTest, NormalExtensionLifecycle) {
127 // Initialize render process. 157 // Initialize render process.
128 EXPECT_FALSE(IsProcessInitialized(render_process_host_.get())); 158 EXPECT_FALSE(IsProcessInitialized(render_process_host_.get()));
129 SimulateRenderProcessCreated(render_process_host_.get()); 159 SimulateRenderProcessCreated(render_process_host_.get());
130 EXPECT_TRUE(IsProcessInitialized(render_process_host_.get())); 160 EXPECT_TRUE(IsProcessInitialized(render_process_host_.get()));
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 helper_->ActivateExtensionInProcess(*extension, render_process_host_.get()); 266 helper_->ActivateExtensionInProcess(*extension, render_process_host_.get());
237 EXPECT_EQ(0u, sink.message_count()); 267 EXPECT_EQ(0u, sink.message_count());
238 EXPECT_FALSE(IsExtensionPendingActivationInProcess( 268 EXPECT_FALSE(IsExtensionPendingActivationInProcess(
239 *extension, render_process_host_.get())); 269 *extension, render_process_host_.get()));
240 270
241 helper_->OnExtensionUnloaded(*extension); 271 helper_->OnExtensionUnloaded(*extension);
242 EXPECT_EQ(0u, sink.message_count()); 272 EXPECT_EQ(0u, sink.message_count());
243 EXPECT_FALSE(IsExtensionLoaded(*extension)); 273 EXPECT_FALSE(IsExtensionLoaded(*extension));
244 } 274 }
245 275
276 // Tests that only incognito-enabled extensions are loaded in an incognito
277 // context.
278 TEST_F(RendererStartupHelperTest, ExtensionInIncognitoRenderer) {
279 // Initialize the incognito renderer.
280 EXPECT_FALSE(IsProcessInitialized(incognito_render_process_host_.get()));
281 SimulateRenderProcessCreated(incognito_render_process_host_.get());
282 EXPECT_TRUE(IsProcessInitialized(incognito_render_process_host_.get()));
283
284 IPC::TestSink& sink = render_process_host_->sink();
285 IPC::TestSink& incognito_sink = incognito_render_process_host_->sink();
286
287 // Enable the extension. It should not be loaded in the initialized incognito
288 // renderer.
289 sink.ClearMessages();
290 incognito_sink.ClearMessages();
291 EXPECT_FALSE(util::IsIncognitoEnabled(extension_->id(), browser_context()));
292 EXPECT_FALSE(IsExtensionLoaded(*extension_));
293 AddExtensionToRegistry(extension_);
294 helper_->OnExtensionLoaded(*extension_);
295 EXPECT_EQ(0u, sink.message_count());
296 EXPECT_EQ(0u, incognito_sink.message_count());
297 EXPECT_TRUE(IsExtensionLoaded(*extension_));
298 EXPECT_FALSE(IsExtensionLoadedInProcess(
299 *extension_, incognito_render_process_host_.get()));
300 EXPECT_FALSE(
301 IsExtensionLoadedInProcess(*extension_, render_process_host_.get()));
302
303 // Initialize the normal renderer. The extension should get loaded in it.
304 sink.ClearMessages();
305 incognito_sink.ClearMessages();
306 EXPECT_FALSE(IsProcessInitialized(render_process_host_.get()));
307 SimulateRenderProcessCreated(render_process_host_.get());
308 EXPECT_TRUE(IsProcessInitialized(render_process_host_.get()));
309 EXPECT_TRUE(
310 IsExtensionLoadedInProcess(*extension_, render_process_host_.get()));
311 EXPECT_FALSE(IsExtensionLoadedInProcess(
312 *extension_, incognito_render_process_host_.get()));
313 // Multiple initialization messages including the extension load message
314 // should be dispatched to the non-incognito renderer.
315 EXPECT_LE(1u, sink.message_count());
316 EXPECT_EQ(0u, incognito_sink.message_count());
317
318 // Enable the extension in incognito mode. This will reload the extension.
319 sink.ClearMessages();
320 incognito_sink.ClearMessages();
321 ExtensionPrefs::Get(browser_context())
322 ->SetIsIncognitoEnabled(extension_->id(), true);
323 helper_->OnExtensionUnloaded(*extension_);
324 helper_->OnExtensionLoaded(*extension_);
325 EXPECT_TRUE(IsExtensionLoadedInProcess(*extension_,
326 incognito_render_process_host_.get()));
327 EXPECT_TRUE(
328 IsExtensionLoadedInProcess(*extension_, render_process_host_.get()));
329 // The extension would not have been unloaded from the incognito renderer
330 // since it wasn't loaded.
331 ASSERT_EQ(1u, incognito_sink.message_count());
332 EXPECT_EQ(ExtensionMsg_Loaded::ID, incognito_sink.GetMessageAt(0)->type());
333 // The extension would be first unloaded and then loaded from the normal
334 // renderer.
335 ASSERT_EQ(2u, sink.message_count());
336 EXPECT_EQ(ExtensionMsg_Unloaded::ID, sink.GetMessageAt(0)->type());
337 EXPECT_EQ(ExtensionMsg_Loaded::ID, sink.GetMessageAt(1)->type());
338 }
339
340 // Tests that platform apps are always loaded in an incognito renderer.
341 TEST_F(RendererStartupHelperTest, PlatformAppInIncognitoRenderer) {
342 // Initialize the incognito renderer.
343 EXPECT_FALSE(IsProcessInitialized(incognito_render_process_host_.get()));
344 SimulateRenderProcessCreated(incognito_render_process_host_.get());
345 EXPECT_TRUE(IsProcessInitialized(incognito_render_process_host_.get()));
346
347 IPC::TestSink& incognito_sink = incognito_render_process_host_->sink();
348
349 scoped_refptr<Extension> platform_app(CreatePlatformApp("platform_app"));
350 ASSERT_TRUE(platform_app->is_platform_app());
351 EXPECT_FALSE(util::IsIncognitoEnabled(platform_app->id(), browser_context()));
352 EXPECT_FALSE(util::CanBeIncognitoEnabled(platform_app.get()));
353
354 // Enable the app. It should get loaded in the incognito renderer even though
355 // IsIncognitoEnabled returns false for it, since it can't be enabled for
356 // incognito.
357 incognito_sink.ClearMessages();
358 AddExtensionToRegistry(platform_app);
359 helper_->OnExtensionLoaded(*platform_app);
360 EXPECT_TRUE(IsExtensionLoadedInProcess(*platform_app,
361 incognito_render_process_host_.get()));
362 ASSERT_EQ(1u, incognito_sink.message_count());
363 EXPECT_EQ(ExtensionMsg_Loaded::ID, incognito_sink.GetMessageAt(0)->type());
364 }
365
246 } // namespace extensions 366 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/browser/renderer_startup_helper.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698