Decoupled the SchemaRegistryService from SchemaRegistry.

The service is not a SchemaRegistry anymore but owns one instead. This
enables the service to own subclasses of SchemaRegistry.

Also added a ForwardingSchemaRegisy, which wraps another
SchemaRegistry. This will be used in a future CL.

R=bartfab@chromium.org
TBR=kalman@chromium.org
BUG=224596

Review URL: https://codereview.chromium.org/349643002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@278735 0039d316-1c4b-4281-b951-d872f2087c98
parent 68a31b1b
......@@ -209,7 +209,8 @@ scoped_ptr<UserCloudPolicyManagerChromeOS>
manager->EnableWildcardLoginCheck(username);
}
manager->Init(SchemaRegistryServiceFactory::GetForContext(profile));
manager->Init(
SchemaRegistryServiceFactory::GetForContext(profile)->registry());
manager->Connect(g_browser_process->local_state(),
device_management_service,
g_browser_process->system_request_context(),
......
......@@ -107,8 +107,8 @@ class ManagedValueStoreCache::ExtensionTracker
ManagedValueStoreCache::ExtensionTracker::ExtensionTracker(Profile* profile)
: profile_(profile),
extension_registry_observer_(this),
schema_registry_(
policy::SchemaRegistryServiceFactory::GetForContext(profile)),
schema_registry_(policy::SchemaRegistryServiceFactory::GetForContext(
profile)->registry()),
weak_factory_(this) {
extension_registry_observer_.Add(ExtensionRegistry::Get(profile_));
// Load schemas when the extension system is ready. It might be ready now.
......@@ -291,7 +291,7 @@ void ManagedValueStoreCache::OnPolicyServiceInitialized(
// The PolicyService now has all the initial policies ready. Send policy
// for all the managed extensions to their backing stores now.
policy::SchemaRegistry* registry =
policy::SchemaRegistryServiceFactory::GetForContext(profile_);
policy::SchemaRegistryServiceFactory::GetForContext(profile_)->registry();
const policy::ComponentMap* map = registry->schema_map()->GetComponents(
policy::POLICY_DOMAIN_EXTENSIONS);
if (!map)
......
......@@ -432,7 +432,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest, ExtensionsSchemas) {
message_.clear();
policy::SchemaRegistry* registry =
policy::SchemaRegistryServiceFactory::GetForContext(profile);
policy::SchemaRegistryServiceFactory::GetForContext(profile)->registry();
ASSERT_TRUE(registry);
EXPECT_FALSE(registry->schema_map()->GetSchema(policy::PolicyNamespace(
policy::POLICY_DOMAIN_EXTENSIONS, kManagedStorageExtensionId)));
......
......@@ -160,7 +160,8 @@ UserCloudPolicyManagerFactory::CreateManagerForOriginalBrowserContext(
base::MessageLoopProxy::current(),
file_task_runner,
io_task_runner));
manager->Init(SchemaRegistryServiceFactory::GetForContext(context));
manager->Init(
SchemaRegistryServiceFactory::GetForContext(context)->registry());
manager_wrappers_[context] = new ManagerWrapper(manager.get());
return manager.Pass();
}
......
......@@ -91,7 +91,8 @@ ProfilePolicyConnectorFactory::CreateForProfileInternal(
CloudPolicyManager* user_cloud_policy_manager = NULL;
#if defined(ENABLE_CONFIGURATION_POLICY)
schema_registry = SchemaRegistryServiceFactory::GetForContext(profile);
schema_registry =
SchemaRegistryServiceFactory::GetForContext(profile)->registry();
#if defined(OS_CHROMEOS)
chromeos::User* user = NULL;
......
......@@ -4,31 +4,26 @@
#include "chrome/browser/policy/schema_registry_service.h"
#include "base/logging.h"
#include "components/policy/core/common/policy_namespace.h"
#include "components/policy/core/common/schema.h"
#include "components/policy/core/common/schema_registry.h"
namespace policy {
SchemaRegistryService::SchemaRegistryService(
scoped_ptr<SchemaRegistry> registry,
const Schema& chrome_schema,
CombinedSchemaRegistry* global_registry)
: global_registry_(global_registry) {
if (chrome_schema.valid())
RegisterComponent(PolicyNamespace(POLICY_DOMAIN_CHROME, ""), chrome_schema);
SetReady(POLICY_DOMAIN_CHROME);
if (global_registry_)
global_registry->Track(this);
: registry_(registry.Pass()) {
if (chrome_schema.valid()) {
registry_->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_CHROME, ""),
chrome_schema);
}
registry_->SetReady(POLICY_DOMAIN_CHROME);
if (global_registry)
global_registry->Track(registry_.get());
}
SchemaRegistryService::~SchemaRegistryService() {}
void SchemaRegistryService::Shutdown() {
if (global_registry_) {
global_registry_->Untrack(this);
global_registry_ = NULL;
}
DCHECK(!HasObservers());
}
} // namespace policy
......@@ -6,30 +6,30 @@
#define CHROME_BROWSER_POLICY_SCHEMA_REGISTRY_SERVICE_H_
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/policy/core/common/schema_registry.h"
namespace policy {
class CombinedSchemaRegistry;
class Schema;
class SchemaRegistry;
// A SchemaRegistry that is also a KeyedService, and is associated
// with a Profile.
class SchemaRegistryService : public SchemaRegistry, public KeyedService {
// A KeyedService associated with a Profile that contains a SchemaRegistry.
class SchemaRegistryService : public KeyedService {
public:
// This SchemaRegistry will initially contain only the |chrome_schema|, if
// This |registry| will initially contain only the |chrome_schema|, if
// it's valid. The optional |global_registry| must outlive this, and will
// track this registry.
SchemaRegistryService(const Schema& chrome_schema,
// track |registry|.
SchemaRegistryService(scoped_ptr<SchemaRegistry> registry,
const Schema& chrome_schema,
CombinedSchemaRegistry* global_registry);
virtual ~SchemaRegistryService();
// KeyedService:
virtual void Shutdown() OVERRIDE;
SchemaRegistry* registry() const { return registry_.get(); }
private:
CombinedSchemaRegistry* global_registry_;
scoped_ptr<SchemaRegistry> registry_;
DISALLOW_COPY_AND_ASSIGN(SchemaRegistryService);
};
......
......@@ -60,10 +60,11 @@ SchemaRegistryServiceFactory::CreateForContextInternal(
CombinedSchemaRegistry* global_registry) {
DCHECK(!context->IsOffTheRecord());
DCHECK(registries_.find(context) == registries_.end());
SchemaRegistryService* registry =
new SchemaRegistryService(chrome_schema, global_registry);
registries_[context] = registry;
return make_scoped_ptr(registry);
scoped_ptr<SchemaRegistry> registry(new SchemaRegistry);
scoped_ptr<SchemaRegistryService> service(new SchemaRegistryService(
registry.Pass(), chrome_schema, global_registry));
registries_[context] = service.get();
return service.Pass();
}
void SchemaRegistryServiceFactory::BrowserContextShutdown(
......
......@@ -613,7 +613,7 @@ void PolicyUIHandler::SendPolicyNames() const {
Profile* profile = Profile::FromWebUI(web_ui());
policy::SchemaRegistry* registry =
policy::SchemaRegistryServiceFactory::GetForContext(
profile->GetOriginalProfile());
profile->GetOriginalProfile())->registry();
scoped_refptr<policy::SchemaMap> schema_map = registry->schema_map();
// Add Chrome policy names.
......
......@@ -10,6 +10,8 @@ namespace policy {
SchemaRegistry::Observer::~Observer() {}
SchemaRegistry::InternalObserver::~InternalObserver() {}
SchemaRegistry::SchemaRegistry() : schema_map_(new SchemaMap) {
for (int i = 0; i < POLICY_DOMAIN_SIZE; ++i)
domains_ready_[i] = false;
......@@ -18,7 +20,11 @@ SchemaRegistry::SchemaRegistry() : schema_map_(new SchemaMap) {
#endif
}
SchemaRegistry::~SchemaRegistry() {}
SchemaRegistry::~SchemaRegistry() {
FOR_EACH_OBSERVER(InternalObserver,
internal_observers_,
OnSchemaRegistryShuttingDown(this));
}
void SchemaRegistry::RegisterComponent(const PolicyNamespace& ns,
const Schema& schema) {
......@@ -77,15 +83,19 @@ void SchemaRegistry::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
void SchemaRegistry::AddInternalObserver(InternalObserver* observer) {
internal_observers_.AddObserver(observer);
}
void SchemaRegistry::RemoveInternalObserver(InternalObserver* observer) {
internal_observers_.RemoveObserver(observer);
}
void SchemaRegistry::Notify(bool has_new_schemas) {
FOR_EACH_OBSERVER(
Observer, observers_, OnSchemaRegistryUpdated(has_new_schemas));
}
bool SchemaRegistry::HasObservers() const {
return observers_.might_have_observers();
}
CombinedSchemaRegistry::CombinedSchemaRegistry()
: own_schema_map_(new SchemaMap) {
// The combined registry is always ready, since it can always start tracking
......@@ -100,22 +110,13 @@ CombinedSchemaRegistry::~CombinedSchemaRegistry() {}
void CombinedSchemaRegistry::Track(SchemaRegistry* registry) {
registries_.insert(registry);
registry->AddObserver(this);
registry->AddInternalObserver(this);
// Recombine the maps only if the |registry| has any components other than
// POLICY_DOMAIN_CHROME.
if (registry->schema_map()->HasComponents())
Combine(true);
}
void CombinedSchemaRegistry::Untrack(SchemaRegistry* registry) {
registry->RemoveObserver(this);
if (registries_.erase(registry) != 0) {
if (registry->schema_map()->HasComponents())
Combine(false);
} else {
NOTREACHED();
}
}
void CombinedSchemaRegistry::RegisterComponents(
PolicyDomain domain,
const ComponentMap& components) {
......@@ -146,6 +147,18 @@ void CombinedSchemaRegistry::OnSchemaRegistryReady() {
// Ignore.
}
void CombinedSchemaRegistry::OnSchemaRegistryShuttingDown(
SchemaRegistry* registry) {
registry->RemoveObserver(this);
registry->RemoveInternalObserver(this);
if (registries_.erase(registry) != 0) {
if (registry->schema_map()->HasComponents())
Combine(false);
} else {
NOTREACHED();
}
}
void CombinedSchemaRegistry::Combine(bool has_new_schemas) {
// If two registries publish a Schema for the same component then it's
// undefined which version gets in the combined registry.
......@@ -175,4 +188,53 @@ void CombinedSchemaRegistry::Combine(bool has_new_schemas) {
Notify(has_new_schemas);
}
ForwardingSchemaRegistry::ForwardingSchemaRegistry(SchemaRegistry* wrapped)
: wrapped_(wrapped) {
schema_map_ = wrapped_->schema_map();
wrapped_->AddObserver(this);
wrapped_->AddInternalObserver(this);
// This registry is always ready.
for (int i = 0; i < POLICY_DOMAIN_SIZE; ++i)
SetReady(static_cast<PolicyDomain>(i));
}
ForwardingSchemaRegistry::~ForwardingSchemaRegistry() {
if (wrapped_) {
wrapped_->RemoveObserver(this);
wrapped_->RemoveInternalObserver(this);
}
}
void ForwardingSchemaRegistry::RegisterComponents(
PolicyDomain domain,
const ComponentMap& components) {
if (wrapped_)
wrapped_->RegisterComponents(domain, components);
// Ignore otherwise.
}
void ForwardingSchemaRegistry::UnregisterComponent(const PolicyNamespace& ns) {
if (wrapped_)
wrapped_->UnregisterComponent(ns);
// Ignore otherwise.
}
void ForwardingSchemaRegistry::OnSchemaRegistryUpdated(bool has_new_schemas) {
schema_map_ = wrapped_->schema_map();
Notify(has_new_schemas);
}
void ForwardingSchemaRegistry::OnSchemaRegistryReady() {
// Ignore.
}
void ForwardingSchemaRegistry::OnSchemaRegistryShuttingDown(
SchemaRegistry* registry) {
DCHECK_EQ(wrapped_, registry);
wrapped_->RemoveObserver(this);
wrapped_->RemoveInternalObserver(this);
wrapped_ = NULL;
// Keep serving the same |schema_map_|.
}
} // namespace policy
......@@ -43,6 +43,16 @@ class POLICY_EXPORT SchemaRegistry : public base::NonThreadSafe {
virtual ~Observer();
};
// This observer is only meant to be used by subclasses.
class POLICY_EXPORT InternalObserver {
public:
// Invoked when |registry| is about to be destroyed.
virtual void OnSchemaRegistryShuttingDown(SchemaRegistry* registry) = 0;
protected:
virtual ~InternalObserver();
};
SchemaRegistry();
virtual ~SchemaRegistry();
......@@ -69,7 +79,8 @@ class POLICY_EXPORT SchemaRegistry : public base::NonThreadSafe {
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
bool HasObservers() const;
void AddInternalObserver(InternalObserver* observer);
void RemoveInternalObserver(InternalObserver* observer);
protected:
void Notify(bool has_new_schemas);
......@@ -78,30 +89,35 @@ class POLICY_EXPORT SchemaRegistry : public base::NonThreadSafe {
private:
ObserverList<Observer, true> observers_;
ObserverList<InternalObserver, true> internal_observers_;
bool domains_ready_[POLICY_DOMAIN_SIZE];
DISALLOW_COPY_AND_ASSIGN(SchemaRegistry);
};
// A registry that combines the maps of other registries.
class POLICY_EXPORT CombinedSchemaRegistry : public SchemaRegistry,
public SchemaRegistry::Observer {
class POLICY_EXPORT CombinedSchemaRegistry
: public SchemaRegistry,
public SchemaRegistry::Observer,
public SchemaRegistry::InternalObserver {
public:
CombinedSchemaRegistry();
virtual ~CombinedSchemaRegistry();
void Track(SchemaRegistry* registry);
void Untrack(SchemaRegistry* registry);
// SchemaRegistry:
virtual void RegisterComponents(PolicyDomain domain,
const ComponentMap& components) OVERRIDE;
virtual void UnregisterComponent(const PolicyNamespace& ns) OVERRIDE;
// SchemaRegistry::Observer:
virtual void OnSchemaRegistryUpdated(bool has_new_schemas) OVERRIDE;
virtual void OnSchemaRegistryReady() OVERRIDE;
// SchemaRegistry::InternalObserver:
virtual void OnSchemaRegistryShuttingDown(SchemaRegistry* registry) OVERRIDE;
private:
void Combine(bool has_new_schemas);
......@@ -111,6 +127,35 @@ class POLICY_EXPORT CombinedSchemaRegistry : public SchemaRegistry,
DISALLOW_COPY_AND_ASSIGN(CombinedSchemaRegistry);
};
// A registry that wraps another schema registry.
class POLICY_EXPORT ForwardingSchemaRegistry
: public SchemaRegistry,
public SchemaRegistry::Observer,
public SchemaRegistry::InternalObserver {
public:
// This registry will stop updating its SchemaMap when |wrapped| is
// destroyed.
explicit ForwardingSchemaRegistry(SchemaRegistry* wrapped);
virtual ~ForwardingSchemaRegistry();
// SchemaRegistry:
virtual void RegisterComponents(PolicyDomain domain,
const ComponentMap& components) OVERRIDE;
virtual void UnregisterComponent(const PolicyNamespace& ns) OVERRIDE;
// SchemaRegistry::Observer:
virtual void OnSchemaRegistryUpdated(bool has_new_schemas) OVERRIDE;
virtual void OnSchemaRegistryReady() OVERRIDE;
// SchemaRegistry::InternalObserver:
virtual void OnSchemaRegistryShuttingDown(SchemaRegistry* registry) OVERRIDE;
private:
SchemaRegistry* wrapped_;
DISALLOW_COPY_AND_ASSIGN(ForwardingSchemaRegistry);
};
} // namespace policy
#endif // COMPONENTS_POLICY_CORE_COMMON_SCHEMA_REGISTRY_H_
......@@ -4,6 +4,7 @@
#include "components/policy/core/common/schema_registry.h"
#include "base/memory/scoped_ptr.h"
#include "components/policy/core/common/policy_namespace.h"
#include "components/policy/core/common/schema.h"
#include "testing/gmock/include/gmock/gmock.h"
......@@ -48,6 +49,14 @@ class MockSchemaRegistryObserver : public SchemaRegistry::Observer {
MOCK_METHOD0(OnSchemaRegistryReady, void());
};
bool SchemaMapEquals(const scoped_refptr<SchemaMap>& schema_map1,
const scoped_refptr<SchemaMap>& schema_map2) {
PolicyNamespaceList added;
PolicyNamespaceList removed;
schema_map1->GetChanges(schema_map2, &removed, &added);
return added.empty() && removed.empty();
}
} // namespace
TEST(SchemaRegistryTest, Notifications) {
......@@ -57,9 +66,7 @@ TEST(SchemaRegistryTest, Notifications) {
MockSchemaRegistryObserver observer;
SchemaRegistry registry;
EXPECT_FALSE(registry.HasObservers());
registry.AddObserver(&observer);
EXPECT_TRUE(registry.HasObservers());
ASSERT_TRUE(registry.schema_map());
EXPECT_FALSE(registry.schema_map()->GetSchema(
......@@ -98,7 +105,6 @@ TEST(SchemaRegistryTest, Notifications) {
Mock::VerifyAndClearExpectations(&observer);
registry.RemoveObserver(&observer);
EXPECT_FALSE(registry.HasObservers());
}
TEST(SchemaRegistryTest, IsReady) {
......@@ -134,25 +140,25 @@ TEST(SchemaRegistryTest, Combined) {
ASSERT_TRUE(schema.valid()) << error;
MockSchemaRegistryObserver observer;
SchemaRegistry registry1;
SchemaRegistry registry2;
scoped_ptr<SchemaRegistry> registry1(new SchemaRegistry);
scoped_ptr<SchemaRegistry> registry2(new SchemaRegistry);
CombinedSchemaRegistry combined;
combined.AddObserver(&observer);
EXPECT_CALL(observer, OnSchemaRegistryUpdated(_)).Times(0);
registry1.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"),
schema);
registry1->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"),
schema);
Mock::VerifyAndClearExpectations(&observer);
// Starting to track a registry issues notifications when it comes with new
// schemas.
EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
combined.Track(&registry1);
combined.Track(registry1.get());
Mock::VerifyAndClearExpectations(&observer);
// Adding a new empty registry does not trigger notifications.
EXPECT_CALL(observer, OnSchemaRegistryUpdated(_)).Times(0);
combined.Track(&registry2);
combined.Track(registry2.get());
Mock::VerifyAndClearExpectations(&observer);
// Adding the same component to the combined registry itself triggers
......@@ -164,15 +170,15 @@ TEST(SchemaRegistryTest, Combined) {
// Adding components to the sub-registries triggers notifications.
EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
registry2.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def"),
schema);
registry2->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def"),
schema);
Mock::VerifyAndClearExpectations(&observer);
// If the same component is published in 2 sub-registries then the combined
// registry publishes one of them.
EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
registry1.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def"),
schema);
registry1->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def"),
schema);
Mock::VerifyAndClearExpectations(&observer);
ASSERT_EQ(1u, combined.schema_map()->GetDomains().size());
......@@ -188,7 +194,7 @@ TEST(SchemaRegistryTest, Combined) {
PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "xyz")));
EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
registry1.UnregisterComponent(
registry1->UnregisterComponent(
PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"));
Mock::VerifyAndClearExpectations(&observer);
// Still registered at the combined registry.
......@@ -204,7 +210,7 @@ TEST(SchemaRegistryTest, Combined) {
PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc")));
EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
registry1.UnregisterComponent(
registry1->UnregisterComponent(
PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def"));
Mock::VerifyAndClearExpectations(&observer);
// Still registered at registry2.
......@@ -212,7 +218,7 @@ TEST(SchemaRegistryTest, Combined) {
PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def")));
EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
registry2.UnregisterComponent(
registry2->UnregisterComponent(
PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def"));
Mock::VerifyAndClearExpectations(&observer);
// Now it's gone.
......@@ -220,23 +226,66 @@ TEST(SchemaRegistryTest, Combined) {
PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def")));
EXPECT_CALL(observer, OnSchemaRegistryUpdated(true)).Times(2);
registry1.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_CHROME, ""),
schema);
registry2.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "hij"),
schema);
registry1->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_CHROME, ""),
schema);
registry2->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "hij"),
schema);
Mock::VerifyAndClearExpectations(&observer);
// Untracking |registry1| doesn't trigger an update notification, because it
// doesn't contain any components.
EXPECT_CALL(observer, OnSchemaRegistryUpdated(_)).Times(0);
combined.Untrack(&registry1);
registry1.reset();
Mock::VerifyAndClearExpectations(&observer);
EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
combined.Untrack(&registry2);
registry2.reset();
Mock::VerifyAndClearExpectations(&observer);
combined.RemoveObserver(&observer);
}
TEST(SchemaRegistryTest, ForwardingSchemaRegistry) {
scoped_ptr<SchemaRegistry> registry(new SchemaRegistry);
ForwardingSchemaRegistry forwarding(registry.get());
MockSchemaRegistryObserver observer;
forwarding.AddObserver(&observer);
EXPECT_FALSE(registry->IsReady());
// The ForwardingSchemaRegistry is always ready, even if the wrapped registry
// isn't.
EXPECT_TRUE(forwarding.IsReady());
// But they alreday have the same SchemaMap.
EXPECT_TRUE(SchemaMapEquals(registry->schema_map(), forwarding.schema_map()));
EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
registry->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"),
Schema());
Mock::VerifyAndClearExpectations(&observer);
EXPECT_TRUE(SchemaMapEquals(registry->schema_map(), forwarding.schema_map()));
EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
registry->UnregisterComponent(
PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"));
Mock::VerifyAndClearExpectations(&observer);
EXPECT_TRUE(SchemaMapEquals(registry->schema_map(), forwarding.schema_map()));
// No notifications expected for this call.
EXPECT_FALSE(registry->IsReady());
registry->SetReady(POLICY_DOMAIN_CHROME);
registry->SetReady(POLICY_DOMAIN_EXTENSIONS);
EXPECT_TRUE(registry->IsReady());
EXPECT_TRUE(SchemaMapEquals(registry->schema_map(), forwarding.schema_map()));
Mock::VerifyAndClearExpectations(&observer);
// Keep the same SchemaMap when the original registry is gone.
// No notifications are expected in this case either.
scoped_refptr<SchemaMap> schema_map = registry->schema_map();
registry.reset();
EXPECT_TRUE(SchemaMapEquals(schema_map, forwarding.schema_map()));
Mock::VerifyAndClearExpectations(&observer);
forwarding.RemoveObserver(&observer);
}
} // namespace policy
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment