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

Side by Side Diff: chrome/browser/policy/browser_policy_connector.cc

Issue 10449071: Enable user policy handling through the new cloud policy stack. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase. Created 8 years, 6 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "chrome/browser/policy/browser_policy_connector.h" 5 #include "chrome/browser/policy/browser_policy_connector.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/file_path.h" 10 #include "base/file_path.h"
11 #include "base/path_service.h" 11 #include "base/path_service.h"
12 #include "chrome/browser/browser_process.h" 12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/policy/cloud_policy_provider.h" 13 #include "chrome/browser/policy/cloud_policy_provider.h"
14 #include "chrome/browser/policy/cloud_policy_subsystem.h" 14 #include "chrome/browser/policy/cloud_policy_subsystem.h"
15 #include "chrome/browser/policy/configuration_policy_provider.h" 15 #include "chrome/browser/policy/configuration_policy_provider.h"
16 #include "chrome/browser/policy/device_management_service.h"
16 #include "chrome/browser/policy/policy_service_impl.h" 17 #include "chrome/browser/policy/policy_service_impl.h"
18 #include "chrome/browser/policy/user_cloud_policy_manager.h"
17 #include "chrome/browser/policy/user_policy_cache.h" 19 #include "chrome/browser/policy/user_policy_cache.h"
18 #include "chrome/browser/policy/user_policy_token_cache.h" 20 #include "chrome/browser/policy/user_policy_token_cache.h"
19 #include "chrome/browser/signin/token_service.h" 21 #include "chrome/browser/signin/token_service.h"
20 #include "chrome/common/chrome_notification_types.h" 22 #include "chrome/common/chrome_notification_types.h"
21 #include "chrome/common/chrome_paths.h" 23 #include "chrome/common/chrome_paths.h"
22 #include "chrome/common/chrome_switches.h" 24 #include "chrome/common/chrome_switches.h"
23 #include "chrome/common/net/gaia/gaia_constants.h" 25 #include "chrome/common/net/gaia/gaia_constants.h"
24 #include "chrome/common/pref_names.h" 26 #include "chrome/common/pref_names.h"
25 #include "content/public/browser/notification_details.h" 27 #include "content/public/browser/notification_details.h"
26 #include "content/public/browser/notification_source.h" 28 #include "content/public/browser/notification_source.h"
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 device_data_store_.reset(); 101 device_data_store_.reset();
100 #endif 102 #endif
101 103
102 // Shutdown user cloud policy. 104 // Shutdown user cloud policy.
103 if (user_cloud_policy_subsystem_.get()) 105 if (user_cloud_policy_subsystem_.get())
104 user_cloud_policy_subsystem_->Shutdown(); 106 user_cloud_policy_subsystem_->Shutdown();
105 user_cloud_policy_subsystem_.reset(); 107 user_cloud_policy_subsystem_.reset();
106 user_policy_token_cache_.reset(); 108 user_policy_token_cache_.reset();
107 user_data_store_.reset(); 109 user_data_store_.reset();
108 110
111 if (user_cloud_policy_manager_.get())
112 user_cloud_policy_manager_->Shutdown();
113 user_cloud_policy_manager_.reset();
114
115 device_management_service_.reset();
116
109 // Delete the providers while the |handler_list_| is still valid, since 117 // Delete the providers while the |handler_list_| is still valid, since
110 // OnProviderGoingAway() can trigger refreshes at the 118 // OnProviderGoingAway() can trigger refreshes at the
111 // ConfigurationPolicyPrefStore. 119 // ConfigurationPolicyPrefStore.
112 recommended_cloud_provider_.reset(); 120 recommended_cloud_provider_.reset();
113 managed_cloud_provider_.reset(); 121 managed_cloud_provider_.reset();
114 recommended_platform_provider_.reset(); 122 recommended_platform_provider_.reset();
115 managed_platform_provider_.reset(); 123 managed_platform_provider_.reset();
116 } 124 }
117 125
118 void BrowserPolicyConnector::Init() { 126 void BrowserPolicyConnector::Init() {
119 managed_platform_provider_.reset(CreateManagedPlatformProvider()); 127 managed_platform_provider_.reset(CreateManagedPlatformProvider());
120 recommended_platform_provider_.reset(CreateRecommendedPlatformProvider()); 128 recommended_platform_provider_.reset(CreateRecommendedPlatformProvider());
121 129
122 #if defined(OS_CHROMEOS) 130 #if defined(OS_CHROMEOS)
123 // The CloudPolicyProvider blocks asynchronous Profile creation until a login 131 // The CloudPolicyProvider blocks asynchronous Profile creation until a login
124 // is performed. This is used to ensure that the Profile's PrefService sees 132 // is performed. This is used to ensure that the Profile's PrefService sees
125 // managed preferences on managed Chrome OS devices. However, this also 133 // managed preferences on managed Chrome OS devices. However, this also
126 // prevents creation of new Profiles in Desktop Chrome. The implementation of 134 // prevents creation of new Profiles in Desktop Chrome. The implementation of
127 // cloud policy on the Desktop requires a refactoring of the cloud provider, 135 // cloud policy on the Desktop requires a refactoring of the cloud provider,
128 // but for now it just isn't created. 136 // but for now it just isn't created.
129 CommandLine* command_line = CommandLine::ForCurrentProcess(); 137 CommandLine* command_line = CommandLine::ForCurrentProcess();
130 if (command_line->HasSwitch(switches::kDeviceManagementUrl)) { 138 if (command_line->HasSwitch(switches::kDeviceManagementUrl)) {
131 managed_cloud_provider_.reset(new CloudPolicyProvider( 139 device_management_service_.reset(
132 this, 140 new DeviceManagementService(
133 GetChromePolicyDefinitionList(), 141 command_line->GetSwitchValueASCII(switches::kDeviceManagementUrl)));
134 POLICY_LEVEL_MANDATORY)); 142 if (!command_line->HasSwitch(switches::kEnableCloudPolicyService)) {
135 recommended_cloud_provider_.reset(new CloudPolicyProvider( 143 managed_cloud_provider_.reset(new CloudPolicyProvider(
136 this, 144 this,
137 GetChromePolicyDefinitionList(), 145 GetChromePolicyDefinitionList(),
138 POLICY_LEVEL_RECOMMENDED)); 146 POLICY_LEVEL_MANDATORY));
147 recommended_cloud_provider_.reset(new CloudPolicyProvider(
148 this,
149 GetChromePolicyDefinitionList(),
150 POLICY_LEVEL_RECOMMENDED));
151 }
139 } 152 }
140 153
141 InitializeDevicePolicy(); 154 InitializeDevicePolicy();
142 155
143 // Create the AppPackUpdater to start updating the cache. It requires the 156 // Create the AppPackUpdater to start updating the cache. It requires the
144 // system request context, which isn't available yet; therefore it is 157 // system request context, which isn't available yet; therefore it is
145 // created only once the loops are running. 158 // created only once the loops are running.
146 MessageLoop::current()->PostTask( 159 MessageLoop::current()->PostTask(
147 FROM_HERE, 160 FROM_HERE,
148 base::Bind(base::IgnoreResult(&BrowserPolicyConnector::GetAppPackUpdater), 161 base::Bind(base::IgnoreResult(&BrowserPolicyConnector::GetAppPackUpdater),
149 weak_ptr_factory_.GetWeakPtr())); 162 weak_ptr_factory_.GetWeakPtr()));
150 #endif 163 #endif
151 } 164 }
152 165
153 PolicyService* BrowserPolicyConnector::CreatePolicyService( 166 PolicyService* BrowserPolicyConnector::CreatePolicyService(
154 Profile* profile) const { 167 Profile* profile) const {
155 // |providers| in decreasing order of priority. 168 // |providers| in decreasing order of priority.
156 PolicyServiceImpl::Providers providers; 169 PolicyServiceImpl::Providers providers;
157 if (managed_platform_provider_.get()) 170 if (managed_platform_provider_.get())
158 providers.push_back(managed_platform_provider_.get()); 171 providers.push_back(managed_platform_provider_.get());
159 if (managed_cloud_provider_.get()) 172 if (managed_cloud_provider_.get())
160 providers.push_back(managed_cloud_provider_.get()); 173 providers.push_back(managed_cloud_provider_.get());
161 if (recommended_platform_provider_.get()) 174 if (recommended_platform_provider_.get())
162 providers.push_back(recommended_platform_provider_.get()); 175 providers.push_back(recommended_platform_provider_.get());
163 if (recommended_cloud_provider_.get()) 176 if (recommended_cloud_provider_.get())
164 providers.push_back(recommended_cloud_provider_.get()); 177 providers.push_back(recommended_cloud_provider_.get());
178 if (user_cloud_policy_manager_.get())
179 providers.push_back(user_cloud_policy_manager_.get());
165 return new PolicyServiceImpl(providers); 180 return new PolicyServiceImpl(providers);
166 } 181 }
167 182
168 void BrowserPolicyConnector::RegisterForDevicePolicy( 183 void BrowserPolicyConnector::RegisterForDevicePolicy(
169 const std::string& owner_email, 184 const std::string& owner_email,
170 const std::string& token, 185 const std::string& token,
171 bool known_machine_id) { 186 bool known_machine_id) {
172 #if defined(OS_CHROMEOS) 187 #if defined(OS_CHROMEOS)
173 if (device_data_store_.get()) { 188 if (device_data_store_.get()) {
174 if (!device_data_store_->device_token().empty()) { 189 if (!device_data_store_->device_token().empty()) {
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 #if defined(OS_CHROMEOS) 268 #if defined(OS_CHROMEOS)
254 if (device_cloud_policy_subsystem_.get()) 269 if (device_cloud_policy_subsystem_.get())
255 device_cloud_policy_subsystem_->RefreshPolicies(false); 270 device_cloud_policy_subsystem_->RefreshPolicies(false);
256 if (user_cloud_policy_subsystem_.get()) 271 if (user_cloud_policy_subsystem_.get())
257 user_cloud_policy_subsystem_->RefreshPolicies(true); // wait_for_auth_token 272 user_cloud_policy_subsystem_->RefreshPolicies(true); // wait_for_auth_token
258 #endif 273 #endif
259 } 274 }
260 275
261 void BrowserPolicyConnector::ScheduleServiceInitialization( 276 void BrowserPolicyConnector::ScheduleServiceInitialization(
262 int64 delay_milliseconds) { 277 int64 delay_milliseconds) {
278 if (device_management_service_.get())
279 device_management_service_->ScheduleInitialization(delay_milliseconds);
263 if (user_cloud_policy_subsystem_.get()) { 280 if (user_cloud_policy_subsystem_.get()) {
264 user_cloud_policy_subsystem_-> 281 user_cloud_policy_subsystem_->
265 ScheduleServiceInitialization(delay_milliseconds); 282 ScheduleServiceInitialization(delay_milliseconds);
266 } 283 }
267 #if defined(OS_CHROMEOS) 284 #if defined(OS_CHROMEOS)
268 if (device_cloud_policy_subsystem_.get()) { 285 if (device_cloud_policy_subsystem_.get()) {
269 device_cloud_policy_subsystem_-> 286 device_cloud_policy_subsystem_->
270 ScheduleServiceInitialization(delay_milliseconds); 287 ScheduleServiceInitialization(delay_milliseconds);
271 } 288 }
272 #endif 289 #endif
273 } 290 }
274 void BrowserPolicyConnector::InitializeUserPolicy( 291 void BrowserPolicyConnector::InitializeUserPolicy(
275 const std::string& user_name, 292 const std::string& user_name,
276 bool wait_for_policy_fetch) { 293 bool wait_for_policy_fetch) {
277 // Throw away the old backend. 294 // Throw away the old backend.
295 user_cloud_policy_manager_.reset();
296
278 user_cloud_policy_subsystem_.reset(); 297 user_cloud_policy_subsystem_.reset();
279 user_policy_token_cache_.reset(); 298 user_policy_token_cache_.reset();
280 user_data_store_.reset(); 299 user_data_store_.reset();
281 token_service_ = NULL; 300 token_service_ = NULL;
282 registrar_.RemoveAll(); 301 registrar_.RemoveAll();
283 302
284 CommandLine* command_line = CommandLine::ForCurrentProcess(); 303 CommandLine* command_line = CommandLine::ForCurrentProcess();
285 304
286 if (command_line->HasSwitch(switches::kDeviceManagementUrl)) { 305 if (command_line->HasSwitch(switches::kDeviceManagementUrl)) {
287 user_data_store_.reset(CloudPolicyDataStore::CreateForUserPolicies()); 306 int64 startup_delay =
307 wait_for_policy_fetch ? 0 : kServiceInitializationStartupDelay;
288 308
289 FilePath profile_dir; 309 if (command_line->HasSwitch(switches::kEnableCloudPolicyService)) {
290 PathService::Get(chrome::DIR_USER_DATA, &profile_dir);
291 #if defined(OS_CHROMEOS) 310 #if defined(OS_CHROMEOS)
292 profile_dir = profile_dir.Append( 311 user_cloud_policy_manager_ =
293 command_line->GetSwitchValuePath(switches::kLoginProfile)); 312 UserCloudPolicyManager::Create(wait_for_policy_fetch);
313 user_cloud_policy_manager_->Initialize(g_browser_process->local_state(),
314 device_management_service_.get(),
315 GetUserAffiliation(user_name));
316
317 device_management_service_->ScheduleInitialization(startup_delay);
294 #endif 318 #endif
295 const FilePath policy_dir = profile_dir.Append(kPolicyDir); 319 } else {
296 const FilePath policy_cache_file = policy_dir.Append(kPolicyCacheFile); 320 FilePath profile_dir;
297 const FilePath token_cache_file = policy_dir.Append(kTokenCacheFile); 321 PathService::Get(chrome::DIR_USER_DATA, &profile_dir);
298 CloudPolicyCacheBase* user_policy_cache = NULL; 322 #if defined(OS_CHROMEOS)
323 profile_dir = profile_dir.Append(
324 command_line->GetSwitchValuePath(switches::kLoginProfile));
325 #endif
326 const FilePath policy_dir = profile_dir.Append(kPolicyDir);
327 const FilePath policy_cache_file = policy_dir.Append(kPolicyCacheFile);
328 const FilePath token_cache_file = policy_dir.Append(kTokenCacheFile);
329 CloudPolicyCacheBase* user_policy_cache = NULL;
299 330
331 user_data_store_.reset(CloudPolicyDataStore::CreateForUserPolicies());
300 #if defined(OS_CHROMEOS) 332 #if defined(OS_CHROMEOS)
301 user_policy_cache = 333 user_policy_cache =
302 new CrosUserPolicyCache( 334 new CrosUserPolicyCache(
303 chromeos::DBusThreadManager::Get()->GetSessionManagerClient(), 335 chromeos::DBusThreadManager::Get()->GetSessionManagerClient(),
304 user_data_store_.get(), 336 user_data_store_.get(),
305 wait_for_policy_fetch, 337 wait_for_policy_fetch,
306 token_cache_file, 338 token_cache_file,
307 policy_cache_file); 339 policy_cache_file);
308 #else 340 #else
309 user_policy_cache = new UserPolicyCache(policy_cache_file, 341 user_policy_cache = new UserPolicyCache(policy_cache_file,
310 wait_for_policy_fetch); 342 wait_for_policy_fetch);
311 user_policy_token_cache_.reset( 343 user_policy_token_cache_.reset(
312 new UserPolicyTokenCache(user_data_store_.get(), token_cache_file)); 344 new UserPolicyTokenCache(user_data_store_.get(), token_cache_file));
313 345
314 // Initiate the DM-Token load. 346 // Initiate the DM-Token load.
315 user_policy_token_cache_->Load(); 347 user_policy_token_cache_->Load();
316 #endif 348 #endif
317 349
318 managed_cloud_provider_->SetUserPolicyCache(user_policy_cache); 350 user_cloud_policy_subsystem_.reset(new CloudPolicySubsystem(
319 recommended_cloud_provider_->SetUserPolicyCache(user_policy_cache); 351 user_data_store_.get(),
320 user_cloud_policy_subsystem_.reset(new CloudPolicySubsystem( 352 user_policy_cache));
321 user_data_store_.get(),
322 user_policy_cache));
323 353
324 user_data_store_->set_user_name(user_name); 354 user_data_store_->set_user_name(user_name);
325 user_data_store_->set_user_affiliation(GetUserAffiliation(user_name)); 355 user_data_store_->set_user_affiliation(GetUserAffiliation(user_name));
326 356
327 int64 delay = 357 user_cloud_policy_subsystem_->CompleteInitialization(
328 wait_for_policy_fetch ? 0 : kServiceInitializationStartupDelay; 358 prefs::kUserPolicyRefreshRate,
329 user_cloud_policy_subsystem_->CompleteInitialization( 359 startup_delay);
330 prefs::kUserPolicyRefreshRate, 360
331 delay); 361 managed_cloud_provider_->SetUserPolicyCache(user_policy_cache);
362 recommended_cloud_provider_->SetUserPolicyCache(user_policy_cache);
363 }
332 } 364 }
333 } 365 }
334 366
335 void BrowserPolicyConnector::SetUserPolicyTokenService( 367 void BrowserPolicyConnector::SetUserPolicyTokenService(
336 TokenService* token_service) { 368 TokenService* token_service) {
337 token_service_ = token_service; 369 token_service_ = token_service;
338 registrar_.Add(this, 370 registrar_.Add(this,
339 chrome::NOTIFICATION_TOKEN_AVAILABLE, 371 chrome::NOTIFICATION_TOKEN_AVAILABLE,
340 content::Source<TokenService>(token_service_)); 372 content::Source<TokenService>(token_service_));
341 373
(...skipping 11 matching lines...) Expand all
353 // the user policy cache of this, so that a potential blocked login 385 // the user policy cache of this, so that a potential blocked login
354 // proceeds without waiting for user policy. 386 // proceeds without waiting for user policy.
355 if (user_cloud_policy_subsystem_.get()) { 387 if (user_cloud_policy_subsystem_.get()) {
356 user_cloud_policy_subsystem_->GetCloudPolicyCacheBase()-> 388 user_cloud_policy_subsystem_->GetCloudPolicyCacheBase()->
357 SetFetchingDone(); 389 SetFetchingDone();
358 } 390 }
359 } else { 391 } else {
360 if (user_data_store_.get()) 392 if (user_data_store_.get())
361 user_data_store_->SetOAuthToken(oauth_token); 393 user_data_store_->SetOAuthToken(oauth_token);
362 } 394 }
395 if (user_cloud_policy_manager_.get()) {
396 CloudPolicyService* service =
397 user_cloud_policy_manager_->cloud_policy_service();
398 if (service->client() &&
399 !service->client()->is_registered() &&
400 !oauth_token.empty()) {
401 service->client()->Register(oauth_token);
402 } else {
403 user_cloud_policy_manager_->CancelWaitForPolicyFetch();
404 }
405 }
363 } 406 }
364 407
365 CloudPolicyDataStore* BrowserPolicyConnector::GetDeviceCloudPolicyDataStore() { 408 CloudPolicyDataStore* BrowserPolicyConnector::GetDeviceCloudPolicyDataStore() {
366 #if defined(OS_CHROMEOS) 409 #if defined(OS_CHROMEOS)
367 return device_data_store_.get(); 410 return device_data_store_.get();
368 #else 411 #else
369 return NULL; 412 return NULL;
370 #endif 413 #endif
371 } 414 }
372 415
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 } 475 }
433 476
434 void BrowserPolicyConnector::InitializeDevicePolicy() { 477 void BrowserPolicyConnector::InitializeDevicePolicy() {
435 #if defined(OS_CHROMEOS) 478 #if defined(OS_CHROMEOS)
436 // Throw away the old backend. 479 // Throw away the old backend.
437 device_cloud_policy_subsystem_.reset(); 480 device_cloud_policy_subsystem_.reset();
438 device_data_store_.reset(); 481 device_data_store_.reset();
439 482
440 CommandLine* command_line = CommandLine::ForCurrentProcess(); 483 CommandLine* command_line = CommandLine::ForCurrentProcess();
441 if (command_line->HasSwitch(switches::kEnableDevicePolicy)) { 484 if (command_line->HasSwitch(switches::kEnableDevicePolicy)) {
442 device_data_store_.reset(CloudPolicyDataStore::CreateForDevicePolicies()); 485 if (command_line->HasSwitch(switches::kEnableCloudPolicyService)) {
443 chromeos::CryptohomeLibrary* cryptohome = 486 // TODO(mnissler): Initialize new-style device policy here once it's
444 chromeos::CrosLibrary::Get()->GetCryptohomeLibrary(); 487 // implemented.
445 install_attributes_.reset(new EnterpriseInstallAttributes(cryptohome)); 488 } else {
446 DevicePolicyCache* device_policy_cache = 489 device_data_store_.reset(CloudPolicyDataStore::CreateForDevicePolicies());
447 new DevicePolicyCache(device_data_store_.get(), 490 chromeos::CryptohomeLibrary* cryptohome =
448 install_attributes_.get()); 491 chromeos::CrosLibrary::Get()->GetCryptohomeLibrary();
492 install_attributes_.reset(new EnterpriseInstallAttributes(cryptohome));
493 DevicePolicyCache* device_policy_cache =
494 new DevicePolicyCache(device_data_store_.get(),
495 install_attributes_.get());
449 496
450 managed_cloud_provider_->SetDevicePolicyCache(device_policy_cache); 497 managed_cloud_provider_->SetDevicePolicyCache(device_policy_cache);
451 recommended_cloud_provider_->SetDevicePolicyCache(device_policy_cache); 498 recommended_cloud_provider_->SetDevicePolicyCache(device_policy_cache);
452 499
453 device_cloud_policy_subsystem_.reset(new CloudPolicySubsystem( 500 device_cloud_policy_subsystem_.reset(new CloudPolicySubsystem(
454 device_data_store_.get(), 501 device_data_store_.get(),
455 device_policy_cache)); 502 device_policy_cache));
456 503
457 // Initialize the subsystem once the message loops are spinning. 504 // Initialize the subsystem once the message loops are spinning.
458 MessageLoop::current()->PostTask( 505 MessageLoop::current()->PostTask(
459 FROM_HERE, 506 FROM_HERE,
460 base::Bind(&BrowserPolicyConnector::CompleteInitialization, 507 base::Bind(&BrowserPolicyConnector::CompleteInitialization,
461 weak_ptr_factory_.GetWeakPtr())); 508 weak_ptr_factory_.GetWeakPtr()));
509 }
462 } 510 }
463 #endif 511 #endif
464 } 512 }
465 513
466 void BrowserPolicyConnector::CompleteInitialization() { 514 void BrowserPolicyConnector::CompleteInitialization() {
467 #if defined(OS_CHROMEOS) 515 #if defined(OS_CHROMEOS)
468 if (device_cloud_policy_subsystem_.get()) { 516 if (device_cloud_policy_subsystem_.get()) {
469 // Read serial number and machine model. This must be done before we call 517 // Read serial number and machine model. This must be done before we call
470 // CompleteInitialization() below such that the serial number is available 518 // CompleteInitialization() below such that the serial number is available
471 // for re-submission in case we're doing serial number recovery. 519 // for re-submission in case we're doing serial number recovery.
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
545 config_dir_path.Append(FILE_PATH_LITERAL("recommended"))); 593 config_dir_path.Append(FILE_PATH_LITERAL("recommended")));
546 } else { 594 } else {
547 return NULL; 595 return NULL;
548 } 596 }
549 #else 597 #else
550 return NULL; 598 return NULL;
551 #endif 599 #endif
552 } 600 }
553 601
554 } // namespace policy 602 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698