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

Unified Diff: chrome/browser/extensions/extension_service_unittest.cc

Issue 13533007: Test extension reloading behavior. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 9 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/extension_service_unittest.cc
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index b1253ebc3b3b74a79ad79ccf9283a23627d150a4..8e18b60e756a5cffb290dd9d88f86ffebb947945 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -68,6 +68,7 @@
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_l10n_util.h"
#include "chrome/common/extensions/extension_manifest_constants.h"
+#include "chrome/common/extensions/extension_messages.h"
#include "chrome/common/extensions/manifest_handler.h"
#include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h"
#include "chrome/common/extensions/manifest_handlers/requirements_handler.h"
@@ -86,7 +87,10 @@
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/gpu_info.h"
+#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_content_client_initializer.h"
+#include "content/public/test/test_notification_tracker.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension_resource.h"
#include "extensions/common/url_pattern.h"
@@ -103,6 +107,7 @@
#include "sync/protocol/app_specifics.pb.h"
#include "sync/protocol/extension_specifics.pb.h"
#include "sync/protocol/sync.pb.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
#include "webkit/database/database_tracker.h"
@@ -508,9 +513,11 @@ void ExtensionServiceTestBase::InitializeEmptyExtensionService() {
}
void ExtensionServiceTestBase::InitializeExtensionProcessManager() {
- static_cast<extensions::TestExtensionSystem*>(
- ExtensionSystem::Get(profile_.get()))->
- CreateExtensionProcessManager();
+ extensions::TestExtensionSystem* system =
+ static_cast<extensions::TestExtensionSystem*>(
+ ExtensionSystem::Get(profile_.get()));
+ system->CreateExtensionProcessManager();
+ system->process_manager()->SetRenderProcessHostFactoryForTest(&rph_factory_);
}
void ExtensionServiceTestBase::InitializeExtensionServiceWithUpdater() {
@@ -3612,10 +3619,66 @@ TEST_F(ExtensionServiceTest, ReloadExtensions) {
EXPECT_EQ(0u, service_->disabled_extensions()->size());
}
+std::vector<uint32> MessageTypes(const IPC::TestSink& sink) {
+ std::vector<uint32> message_types;
+ for (size_t i = 0; i < sink.message_count(); ++i) {
+ message_types.push_back(sink.GetMessageAt(i)->type());
+ }
+ return message_types;
+}
+
+struct ProcessObserver
+ : public content::MockRenderProcessHostFactory::Observer {
+ explicit ProcessObserver(content::MockRenderProcessHostFactory* factory)
+ : Observer(factory) {}
+
+ ~ProcessObserver() {
+ for (size_t i = 0; i < hosts.size(); ++i) {
+ if (destroyed_processes.count(process_ids[i]) == 0)
+ hosts[i]->sink().RemoveFilter(process_messages[i]);
+ delete process_messages[i];
+ }
+ }
+
+ virtual void OnRenderProcessHostCreated(
+ content::MockRenderProcessHost* host) {
+ IPC::TestSink* sink = new IPC::TestSink;
+ hosts.push_back(host);
+ process_ids.push_back(host->GetID());
+ process_messages.push_back(sink);
+ host->sink().AddFilter(sink);
+ }
+ virtual void OnRenderProcessHostDestroyed(
+ content::MockRenderProcessHost* host) {
+ destroyed_processes.insert(host->GetID());
+ }
+
+ std::vector<content::MockRenderProcessHost*> hosts;
+ std::vector<int> process_ids;
+ std::vector<IPC::TestSink*> process_messages;
+ std::set<int> destroyed_processes;
+};
+
// Tests reloading an extension.
TEST_F(ExtensionServiceTest, ReloadExtension) {
+ ProcessObserver observer(&rph_factory_);
+
+ content::TestNotificationTracker notifications;
+ notifications.ListenForAll(chrome::NOTIFICATION_EXTENSIONS_READY);
Jeffrey Yasskin 2013/04/04 09:34:35 I think it makes a lot of sense to assert against
Matt Perry 2013/04/04 20:54:26 Yeah, I really like testing for notifications and
+ notifications.ListenForAll(chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED);
+ notifications.ListenForAll(chrome::NOTIFICATION_EXTENSION_LOADED);
+ notifications.ListenForAll(chrome::NOTIFICATION_EXTENSION_UNLOADED);
+ notifications.ListenForAll(content::NOTIFICATION_RENDERER_PROCESS_CLOSING);
+ notifications.ListenForAll(content::NOTIFICATION_RENDERER_PROCESS_CREATED);
+ notifications.ListenForAll(content::NOTIFICATION_RENDERER_PROCESS_TERMINATED);
+ notifications.ListenForAll(
+ content::NOTIFICATION_RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW);
+
InitializeEmptyExtensionService();
InitializeExtensionProcessManager();
+ service_->Init();
Matt Perry 2013/04/04 20:54:26 So this test used to work without ever calling Ini
Jeffrey Yasskin 2013/04/05 13:14:01 Yep. I it required the omission, or else it hit th
+ EXPECT_THAT(notifications.GetTypesAndReset(),
+ testing::ElementsAre(chrome::NOTIFICATION_EXTENSIONS_READY));
// Simple extension that should install without error.
const char* extension_id = "behllobkkfkfnphdnhnkndlbkcpglgmj";
@@ -3627,23 +3690,118 @@ TEST_F(ExtensionServiceTest, ReloadExtension) {
extensions::UnpackedInstaller::Create(service_)->Load(ext);
loop_.RunUntilIdle();
+ EXPECT_THAT(notifications.GetTypesAndReset(),
+ testing::ElementsAre(chrome::NOTIFICATION_EXTENSION_LOADED));
+ ASSERT_EQ(1u, observer.process_messages.size());
+ {
+ testing::Matcher<uint32> expected_types[] = {
Jeffrey Yasskin 2013/04/04 09:34:35 The long lists of notifications and message types
Matt Perry 2013/04/04 20:54:26 Some messages we probably don't care about. Might
Jeffrey Yasskin 2013/04/05 13:14:01 That's not quite right, since we want to assert th
+ ExtensionMsg_Loaded::ID,
+ ExtensionMsg_ActivateExtension::ID,
+ ExtensionMsg_Loaded::ID,
Jeffrey Yasskin 2013/04/04 09:34:35 Why do we send Loaded/ActivateExtension 3 times? P
Matt Perry 2013/04/04 20:54:26 Yikes! Good find.
+ ExtensionMsg_ActivateExtension::ID,
+ testing::_, // ViewMsg_New::ID,
Jeffrey Yasskin 2013/04/04 09:34:35 DEPS prevents me from #including content/common/vi
+ testing::_, // ViewMsg_AllowBindings::ID,
+ ExtensionMsg_Loaded::ID,
+ ExtensionMsg_ActivateExtension::ID,
+ ExtensionMsg_NotifyRenderViewType::ID,
+ testing::_, // ViewMsg_Close::ID,
+ testing::_, // ViewMsg_Navigate::ID
+ };
+ IPC::TestSink& sink = *observer.process_messages[0];
+ EXPECT_THAT(MessageTypes(sink), testing::ElementsAreArray(expected_types));
+ sink.ClearMessages();
+ }
+
EXPECT_EQ(1u, service_->extensions()->size());
EXPECT_EQ(0u, service_->disabled_extensions()->size());
service_->ReloadExtension(extension_id);
+ EXPECT_THAT(notifications.GetTypesAndReset(),
+ testing::ElementsAre(
+ chrome::NOTIFICATION_EXTENSION_UNLOADED,
+ content::NOTIFICATION_RENDERER_PROCESS_CLOSING,
+ chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
+ content::NOTIFICATION_RENDERER_PROCESS_TERMINATED));
+
+ ASSERT_EQ(1u, observer.process_messages.size());
+ EXPECT_THAT(MessageTypes(*observer.process_messages[0]),
+ testing::ElementsAre(testing::_ /*ViewMsg_Close::ID*/));
+ observer.process_messages[0]->ClearMessages();
+
// Extension should be disabled now, waiting to be reloaded.
EXPECT_EQ(0u, service_->extensions()->size());
EXPECT_EQ(1u, service_->disabled_extensions()->size());
EXPECT_EQ(Extension::DISABLE_RELOAD,
service_->extension_prefs()->GetDisableReasons(extension_id));
- // Reloading again should not crash.
+ // Reloading again before iterating the MessageLoop should not crash and
+ // shouldn't cause an extra reload.
Matt Perry 2013/04/04 20:54:26 I'm not sure I agree with the second half. It make
Jeffrey Yasskin 2013/04/05 13:14:01 I think that would be plausible behavior, but it w
service_->ReloadExtension(extension_id);
Jeffrey Yasskin 2013/04/04 09:34:35 Commenting this line out has no effect on the test
+ EXPECT_THAT(notifications.GetTypesAndReset(),
+ testing::ElementsAre());
+ ASSERT_EQ(1u, observer.process_messages.size());
+ EXPECT_THAT(MessageTypes(*observer.process_messages[0]),
+ testing::ElementsAre());
+ observer.process_messages[0]->ClearMessages();
// Finish reloading
loop_.RunUntilIdle();
+ EXPECT_THAT(notifications.GetTypesAndReset(),
+ testing::ElementsAre(
+ chrome::NOTIFICATION_EXTENSION_LOADED,
+ chrome::NOTIFICATION_EXTENSION_UNLOADED,
Jeffrey Yasskin 2013/04/04 09:34:35 Note the extra reload here.
+ content::NOTIFICATION_RENDERER_PROCESS_CLOSING,
+ chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
+ content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
+ chrome::NOTIFICATION_EXTENSION_LOADED));
+
+ ASSERT_EQ(3u, observer.process_messages.size());
Jeffrey Yasskin 2013/04/04 09:34:35 This should become "2" when I fix the extra-reload
+ EXPECT_THAT(observer.destroyed_processes,
+ testing::ElementsAre(observer.process_ids[0],
+ observer.process_ids[1]));
+ EXPECT_THAT(MessageTypes(*observer.process_messages[0]),
+ testing::ElementsAre());
+ observer.process_messages[0]->ClearMessages();
+ {
+ testing::Matcher<uint32> expected_types[] = {
+ ExtensionMsg_Loaded::ID,
+ ExtensionMsg_ActivateExtension::ID,
+ ExtensionMsg_Loaded::ID,
+ ExtensionMsg_ActivateExtension::ID,
+ testing::_, // ViewMsg_New::ID,
+ testing::_, // ViewMsg_AllowBindings::ID,
+ ExtensionMsg_Loaded::ID,
+ ExtensionMsg_ActivateExtension::ID,
+ ExtensionMsg_NotifyRenderViewType::ID,
+ testing::_, // ViewMsg_Close::ID,
+ testing::_, // ViewMsg_Navigate::ID,
+ testing::_, // ViewMsg_Close::ID
+ };
+ EXPECT_THAT(MessageTypes(*observer.process_messages[1]),
+ testing::ElementsAreArray(expected_types));
+ observer.process_messages[1]->ClearMessages();
+ }
+ {
+ testing::Matcher<uint32> expected_types[] = {
+ ExtensionMsg_Loaded::ID,
+ ExtensionMsg_ActivateExtension::ID,
+ ExtensionMsg_Loaded::ID,
+ ExtensionMsg_ActivateExtension::ID,
+ testing::_, // ViewMsg_New::ID
+ testing::_, // ViewMsg_AllowBindings::ID,
+ ExtensionMsg_Loaded::ID,
+ ExtensionMsg_ActivateExtension::ID,
+ ExtensionMsg_NotifyRenderViewType::ID,
+ testing::_, // ViewMsg_Close::ID,
+ testing::_, // ViewMsg_Navigate::ID
+ };
+ EXPECT_THAT(MessageTypes(*observer.process_messages[2]),
+ testing::ElementsAreArray(expected_types));
+ observer.process_messages[2]->ClearMessages();
+ }
+
// Extension should be enabled again.
EXPECT_EQ(1u, service_->extensions()->size());
EXPECT_EQ(0u, service_->disabled_extensions()->size());

Powered by Google App Engine
This is Rietveld 408576698