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

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: Fix Pawel's and Matt's comments Created 7 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 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 a6068b5d2c4d97bb3c4a13771d4c17b7024ee903..0d50e6c8955d57516239bd7c1a88adad390db0f6 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -58,6 +58,7 @@
#include "chrome/browser/prefs/pref_service_mock_builder.h"
#include "chrome/browser/prefs/pref_service_syncable.h"
#include "chrome/browser/prefs/scoped_user_pref_update.h"
+#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_paths.h"
@@ -68,12 +69,14 @@
#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_handlers/content_scripts_handler.h"
#include "chrome/common/extensions/manifest_handlers/requirements_handler.h"
#include "chrome/common/extensions/manifest_url_handler.h"
#include "chrome/common/extensions/permissions/permission_set.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
+#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "components/user_prefs/pref_registry_syncable.h"
#include "content/public/browser/dom_storage_context.h"
@@ -82,10 +85,12 @@
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/plugin_service.h"
+#include "content/public/browser/site_instance.h"
#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/test_browser_thread.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"
@@ -102,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"
@@ -438,6 +444,8 @@ ExtensionServiceTestBase::~ExtensionServiceTestBase() {
MessageLoop::current()->RunUntilIdle();
profile_.reset(NULL);
MessageLoop::current()->RunUntilIdle();
+
+ TestingBrowserProcess::GetGlobal()->SetProfileManager(NULL);
}
void ExtensionServiceTestBase::InitializeExtensionService(
@@ -507,9 +515,16 @@ void ExtensionServiceTestBase::InitializeEmptyExtensionService() {
}
void ExtensionServiceTestBase::InitializeExtensionProcessManager() {
- static_cast<extensions::TestExtensionSystem*>(
- ExtensionSystem::Get(profile_.get()))->
- CreateExtensionProcessManager();
+ // Needed in order to look up RenderProcessHosts.
+ TestingBrowserProcess::GetGlobal()->SetProfileManager(
+ new ProfileManagerWithoutInit(temp_dir_.path()));
+
+ extensions::TestExtensionSystem* system =
+ static_cast<extensions::TestExtensionSystem*>(
+ ExtensionSystem::Get(profile_.get()));
+ system->CreateExtensionProcessManager();
+ system->process_manager()->GetSiteInstanceForTest()->
+ SetRenderProcessHostFactory(&rph_factory_);
}
void ExtensionServiceTestBase::InitializeExtensionServiceWithUpdater() {
@@ -3607,10 +3622,68 @@ TEST_F(ExtensionServiceTest, ReloadExtensions) {
EXPECT_EQ(0u, service_->disabled_extensions()->size());
}
+namespace {
+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;
+};
+} // namespace
+
// Tests reloading an extension.
TEST_F(ExtensionServiceTest, ReloadExtension) {
+ ProcessObserver observer(&rph_factory_);
+
+ content::TestNotificationTracker notifications;
+ notifications.ListenForAll(chrome::NOTIFICATION_EXTENSIONS_READY);
+ 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();
+ EXPECT_THAT(notifications.GetTypesAndReset(),
+ testing::ElementsAre(chrome::NOTIFICATION_EXTENSIONS_READY));
// Simple extension that should install without error.
const char* extension_id = "behllobkkfkfnphdnhnkndlbkcpglgmj";
@@ -3622,23 +3695,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[] = {
+ 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
+ };
+ 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.
service_->ReloadExtension(extension_id);
+ 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,
+ 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());
+ 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