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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/webui/policy_ui.h" 6 7 #include "base/bind.h" 8 #include "base/bind_helpers.h" 9 #include "base/callback.h" 10 #include "base/compiler_specific.h" 11 #include "base/logging.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/weak_ptr.h" 14 #include "base/strings/string16.h" 15 #include "base/time/time.h" 16 #include "base/values.h" 17 #include "chrome/browser/browser_process.h" 18 #include "chrome/browser/chrome_notification_types.h" 19 #include "chrome/browser/policy/browser_policy_connector.h" 20 #include "chrome/browser/policy/cloud/cloud_policy_client.h" 21 #include "chrome/browser/policy/cloud/cloud_policy_constants.h" 22 #include "chrome/browser/policy/cloud/cloud_policy_core.h" 23 #include "chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.h" 24 #include "chrome/browser/policy/cloud/cloud_policy_store.h" 25 #include "chrome/browser/policy/cloud/cloud_policy_validator.h" 26 #include "chrome/browser/policy/cloud/message_util.h" 27 #include "chrome/browser/policy/configuration_policy_handler_list.h" 28 #include "chrome/browser/policy/policy_error_map.h" 29 #include "chrome/browser/policy/policy_map.h" 30 #include "chrome/browser/policy/policy_service.h" 31 #include "chrome/browser/policy/policy_types.h" 32 #include "chrome/browser/policy/profile_policy_connector.h" 33 #include "chrome/browser/policy/profile_policy_connector_factory.h" 34 #include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h" 35 #include "chrome/browser/profiles/profile.h" 36 #include "chrome/common/url_constants.h" 37 #include "content/public/browser/notification_observer.h" 38 #include "content/public/browser/notification_registrar.h" 39 #include "content/public/browser/notification_service.h" 40 #include "content/public/browser/web_ui.h" 41 #include "content/public/browser/web_ui_data_source.h" 42 #include "content/public/browser/web_ui_message_handler.h" 43 #include "google_apis/gaia/gaia_auth_util.h" 44 #include "grit/browser_resources.h" 45 #include "grit/generated_resources.h" 46 #include "policy/policy_constants.h" 47 #include "ui/base/l10n/l10n_util.h" 48 #include "ui/base/l10n/time_format.h" 49 50 #if defined(OS_CHROMEOS) 51 #include "chrome/browser/chromeos/login/user_manager.h" 52 #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h" 53 #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h" 54 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h" 55 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h" 56 #else 57 #include "chrome/browser/policy/cloud/user_cloud_policy_manager.h" 58 #include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h" 59 #endif 60 61 #if !defined(OS_ANDROID) && !defined(OS_IOS) 62 #include "chrome/browser/extensions/extension_service.h" 63 #include "chrome/browser/extensions/extension_system.h" 64 #include "chrome/browser/policy/policy_domain_descriptor.h" 65 #include "chrome/common/extensions/extension.h" 66 #include "chrome/common/extensions/extension_manifest_constants.h" 67 #include "chrome/common/extensions/extension_set.h" 68 #include "chrome/common/extensions/manifest.h" 69 #include "chrome/common/policy/policy_schema.h" 70 #endif 71 72 namespace em = enterprise_management; 73 74 namespace { 75 76 content::WebUIDataSource* CreatePolicyUIHTMLSource() { 77 content::WebUIDataSource* source = 78 content::WebUIDataSource::Create(chrome::kChromeUIPolicyHost); 79 80 // Localized strings. 81 source->AddLocalizedString("title", IDS_POLICY_TITLE); 82 source->AddLocalizedString("filterPlaceholder", 83 IDS_POLICY_FILTER_PLACEHOLDER); 84 source->AddLocalizedString("reloadPolicies", IDS_POLICY_RELOAD_POLICIES); 85 source->AddLocalizedString("status", IDS_POLICY_STATUS); 86 source->AddLocalizedString("statusDevice", IDS_POLICY_STATUS_DEVICE); 87 source->AddLocalizedString("statusUser", IDS_POLICY_STATUS_USER); 88 source->AddLocalizedString("labelDomain", IDS_POLICY_LABEL_DOMAIN); 89 source->AddLocalizedString("labelUsername", IDS_POLICY_LABEL_USERNAME); 90 source->AddLocalizedString("labelClientId", IDS_POLICY_LABEL_CLIENT_ID); 91 source->AddLocalizedString("labelTimeSinceLastRefresh", 92 IDS_POLICY_LABEL_TIME_SINCE_LAST_REFRESH); 93 source->AddLocalizedString("labelRefreshInterval", 94 IDS_POLICY_LABEL_REFRESH_INTERVAL); 95 source->AddLocalizedString("labelStatus", IDS_POLICY_LABEL_STATUS); 96 source->AddLocalizedString("showUnset", IDS_POLICY_SHOW_UNSET); 97 source->AddLocalizedString("noPoliciesSet", IDS_POLICY_NO_POLICIES_SET); 98 source->AddLocalizedString("headerScope", IDS_POLICY_HEADER_SCOPE); 99 source->AddLocalizedString("headerLevel", IDS_POLICY_HEADER_LEVEL); 100 source->AddLocalizedString("headerName", IDS_POLICY_HEADER_NAME); 101 source->AddLocalizedString("headerValue", IDS_POLICY_HEADER_VALUE); 102 source->AddLocalizedString("headerStatus", IDS_POLICY_HEADER_STATUS); 103 source->AddLocalizedString("showExpandedValue", 104 IDS_POLICY_SHOW_EXPANDED_VALUE); 105 source->AddLocalizedString("hideExpandedValue", 106 IDS_POLICY_HIDE_EXPANDED_VALUE); 107 source->AddLocalizedString("scopeUser", IDS_POLICY_SCOPE_USER); 108 source->AddLocalizedString("scopeDevice", IDS_POLICY_SCOPE_DEVICE); 109 source->AddLocalizedString("levelRecommended", IDS_POLICY_LEVEL_RECOMMENDED); 110 source->AddLocalizedString("levelMandatory", IDS_POLICY_LEVEL_MANDATORY); 111 source->AddLocalizedString("ok", IDS_POLICY_OK); 112 source->AddLocalizedString("unset", IDS_POLICY_UNSET); 113 source->AddLocalizedString("unknown", IDS_POLICY_UNKNOWN); 114 115 source->SetUseJsonJSFormatV2(); 116 source->SetJsonPath("strings.js"); 117 118 // Add required resources. 119 source->AddResourcePath("policy.css", IDR_POLICY_CSS); 120 source->AddResourcePath("policy.js", IDR_POLICY_JS); 121 source->AddResourcePath("uber_utils.js", IDR_UBER_UTILS_JS); 122 source->SetDefaultResource(IDR_POLICY_HTML); 123 124 return source; 125 } 126 127 void GetStatusFromCore(const policy::CloudPolicyCore* core, 128 base::DictionaryValue* dict) { 129 const policy::CloudPolicyStore* store = core->store(); 130 const policy::CloudPolicyClient* client = core->client(); 131 const policy::CloudPolicyRefreshScheduler* refresh_scheduler = 132 core->refresh_scheduler(); 133 134 bool no_error = store->status() == policy::CloudPolicyStore::STATUS_OK && 135 client && client->status() == policy::DM_STATUS_SUCCESS; 136 string16 status = store->status() == policy::CloudPolicyStore::STATUS_OK && 137 client && client->status() != policy::DM_STATUS_SUCCESS ? 138 policy::FormatDeviceManagementStatus(client->status()) : 139 policy::FormatStoreStatus(store->status(), 140 store->validation_status()); 141 const em::PolicyData* policy = store->policy(); 142 std::string client_id = policy ? policy->device_id() : std::string(); 143 std::string username = policy ? policy->username() : std::string(); 144 base::TimeDelta refresh_interval = 145 base::TimeDelta::FromMilliseconds(refresh_scheduler ? 146 refresh_scheduler->refresh_delay() : 147 policy::CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs); 148 base::Time last_refresh_time = refresh_scheduler ? 149 refresh_scheduler->last_refresh() : base::Time(); 150 151 dict->SetBoolean("error", !no_error); 152 dict->SetString("status", status); 153 dict->SetString("clientId", client_id); 154 dict->SetString("username", username); 155 dict->SetString("refreshInterval", 156 ui::TimeFormat::TimeRemainingShort(refresh_interval)); 157 dict->SetString("timeSinceLastRefresh", last_refresh_time.is_null() ? 158 l10n_util::GetStringUTF16(IDS_POLICY_NEVER_FETCHED) : 159 ui::TimeFormat::TimeElapsed(base::Time::NowFromSystemTime() - 160 last_refresh_time)); 161 } 162 163 void ExtractDomainFromUsername(base::DictionaryValue* dict) { 164 std::string username; 165 dict->GetString("username", &username); 166 if (!username.empty()) 167 dict->SetString("domain", gaia::ExtractDomainName(username)); 168 } 169 170 } // namespace 171 172 // An interface for querying the status of cloud policy. 173 class CloudPolicyStatusProvider { 174 public: 175 CloudPolicyStatusProvider(); 176 virtual ~CloudPolicyStatusProvider(); 177 178 // Sets a callback to invoke upon status changes. 179 void SetStatusChangeCallback(const base::Closure& callback); 180 181 virtual void GetStatus(base::DictionaryValue* dict); 182 183 protected: 184 void NotifyStatusChange(); 185 186 private: 187 base::Closure callback_; 188 189 DISALLOW_COPY_AND_ASSIGN(CloudPolicyStatusProvider); 190 }; 191 192 // Status provider implementation that pulls cloud policy status from a 193 // CloudPolicyCore instance provided at construction time. Also listens for 194 // changes on that CloudPolicyCore and reports them through the status change 195 // callback. 196 class CloudPolicyCoreStatusProvider 197 : public CloudPolicyStatusProvider, 198 public policy::CloudPolicyStore::Observer { 199 public: 200 explicit CloudPolicyCoreStatusProvider(policy::CloudPolicyCore* core); 201 virtual ~CloudPolicyCoreStatusProvider(); 202 203 // policy::CloudPolicyStore::Observer implementation. 204 virtual void OnStoreLoaded(policy::CloudPolicyStore* store) OVERRIDE; 205 virtual void OnStoreError(policy::CloudPolicyStore* store) OVERRIDE; 206 207 protected: 208 // Policy status is read from the CloudPolicyClient, CloudPolicyStore and 209 // CloudPolicyRefreshScheduler hosted by this |core_|. 210 policy::CloudPolicyCore* core_; 211 212 DISALLOW_COPY_AND_ASSIGN(CloudPolicyCoreStatusProvider); 213 }; 214 215 // A cloud policy status provider for user policy. 216 class UserPolicyStatusProvider : public CloudPolicyCoreStatusProvider { 217 public: 218 explicit UserPolicyStatusProvider(policy::CloudPolicyCore* core); 219 virtual ~UserPolicyStatusProvider(); 220 221 // CloudPolicyCoreStatusProvider implementation. 222 virtual void GetStatus(base::DictionaryValue* dict) OVERRIDE; 223 224 private: 225 DISALLOW_COPY_AND_ASSIGN(UserPolicyStatusProvider); 226 }; 227 228 #if defined(OS_CHROMEOS) 229 // A cloud policy status provider for device policy. 230 class DevicePolicyStatusProvider : public CloudPolicyCoreStatusProvider { 231 public: 232 explicit DevicePolicyStatusProvider( 233 policy::BrowserPolicyConnector* connector); 234 virtual ~DevicePolicyStatusProvider(); 235 236 // CloudPolicyCoreStatusProvider implementation. 237 virtual void GetStatus(base::DictionaryValue* dict) OVERRIDE; 238 239 private: 240 std::string domain_; 241 242 DISALLOW_COPY_AND_ASSIGN(DevicePolicyStatusProvider); 243 }; 244 245 // A cloud policy status provider that reads policy status from the policy core 246 // associated with the device-local account specified by |user_id| at 247 // construction time. The indirection via user ID and 248 // DeviceLocalAccountPolicyService is necessary because the device-local account 249 // may go away any time behind the scenes, at which point the status message 250 // text will indicate CloudPolicyStore::STATUS_BAD_STATE. 251 class DeviceLocalAccountPolicyStatusProvider 252 : public CloudPolicyStatusProvider, 253 public policy::DeviceLocalAccountPolicyService::Observer { 254 public: 255 DeviceLocalAccountPolicyStatusProvider( 256 const std::string& user_id, 257 policy::DeviceLocalAccountPolicyService* service); 258 virtual ~DeviceLocalAccountPolicyStatusProvider(); 259 260 // CloudPolicyStatusProvider implementation. 261 virtual void GetStatus(base::DictionaryValue* dict) OVERRIDE; 262 263 // policy::DeviceLocalAccountPolicyService::Observer implementation. 264 virtual void OnPolicyUpdated(const std::string& user_id) OVERRIDE; 265 virtual void OnDeviceLocalAccountsChanged() OVERRIDE; 266 267 private: 268 const std::string user_id_; 269 policy::DeviceLocalAccountPolicyService* service_; 270 271 DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountPolicyStatusProvider); 272 }; 273 #endif 274 275 // The JavaScript message handler for the chrome://policy page. 276 class PolicyUIHandler : public content::NotificationObserver, 277 public content::WebUIMessageHandler, 278 public policy::PolicyService::Observer { 279 public: 280 PolicyUIHandler(); 281 virtual ~PolicyUIHandler(); 282 283 // content::NotificationObserver implementation. 284 virtual void Observe(int type, 285 const content::NotificationSource& source, 286 const content::NotificationDetails& details) OVERRIDE; 287 288 // content::WebUIMessageHandler implementation. 289 virtual void RegisterMessages() OVERRIDE; 290 291 // policy::PolicyService::Observer implementation. 292 virtual void OnPolicyUpdated(const policy::PolicyNamespace& ns, 293 const policy::PolicyMap& previous, 294 const policy::PolicyMap& current) OVERRIDE; 295 296 private: 297 // Send a dictionary containing the names of all known policies to the UI. 298 void SendPolicyNames() const; 299 300 // Send information about the current policy values to the UI. For each policy 301 // whose value has been set, a dictionary containing the value and additional 302 // metadata is sent. 303 void SendPolicyValues() const; 304 305 // Send the status of cloud policy to the UI. For each scope that has cloud 306 // policy enabled (device and/or user), a dictionary containing status 307 // information is sent. 308 void SendStatus() const; 309 310 // Inserts a description of each policy in |policy_map| into |values|, using 311 // the optional errors in |errors| to determine the status of each policy. 312 void GetPolicyValues(const policy::PolicyMap& policy_map, 313 policy::PolicyErrorMap* errors, 314 base::DictionaryValue* values) const; 315 316 void GetChromePolicyValues(base::DictionaryValue* values) const; 317 318 void HandleInitialized(const base::ListValue* args); 319 void HandleReloadPolicies(const base::ListValue* args); 320 321 void OnRefreshPoliciesDone() const; 322 323 policy::PolicyService* GetPolicyService() const; 324 325 bool initialized_; 326 std::string device_domain_; 327 base::WeakPtrFactory<PolicyUIHandler> weak_factory_; 328 329 // Providers that supply status dictionaries for user and device policy, 330 // respectively. These are created on initialization time as appropriate for 331 // the platform (Chrome OS / desktop) and type of policy that is in effect. 332 scoped_ptr<CloudPolicyStatusProvider> user_status_provider_; 333 scoped_ptr<CloudPolicyStatusProvider> device_status_provider_; 334 335 content::NotificationRegistrar registrar_; 336 337 DISALLOW_COPY_AND_ASSIGN(PolicyUIHandler); 338 }; 339 340 CloudPolicyStatusProvider::CloudPolicyStatusProvider() { 341 } 342 343 CloudPolicyStatusProvider::~CloudPolicyStatusProvider() { 344 } 345 346 void CloudPolicyStatusProvider::SetStatusChangeCallback( 347 const base::Closure& callback) { 348 callback_ = callback; 349 } 350 351 void CloudPolicyStatusProvider::GetStatus(base::DictionaryValue* dict) { 352 } 353 354 void CloudPolicyStatusProvider::NotifyStatusChange() { 355 if (!callback_.is_null()) 356 callback_.Run(); 357 } 358 359 CloudPolicyCoreStatusProvider::CloudPolicyCoreStatusProvider( 360 policy::CloudPolicyCore* core) : core_(core) { 361 core_->store()->AddObserver(this); 362 // TODO(bartfab): Add an observer that watches for client errors. Observing 363 // core_->client() directly is not safe as the client may be destroyed and 364 // (re-)created anytime if the user signs in or out on desktop platforms. 365 } 366 367 CloudPolicyCoreStatusProvider::~CloudPolicyCoreStatusProvider() { 368 core_->store()->RemoveObserver(this); 369 } 370 371 void CloudPolicyCoreStatusProvider::OnStoreLoaded( 372 policy::CloudPolicyStore* store) { 373 NotifyStatusChange(); 374 } 375 376 void CloudPolicyCoreStatusProvider::OnStoreError( 377 policy::CloudPolicyStore* store) { 378 NotifyStatusChange(); 379 } 380 381 UserPolicyStatusProvider::UserPolicyStatusProvider( 382 policy::CloudPolicyCore* core) : CloudPolicyCoreStatusProvider(core) { 383 } 384 385 UserPolicyStatusProvider::~UserPolicyStatusProvider() { 386 } 387 388 void UserPolicyStatusProvider::GetStatus(base::DictionaryValue* dict) { 389 if (!core_->store()->is_managed()) 390 return; 391 GetStatusFromCore(core_, dict); 392 ExtractDomainFromUsername(dict); 393 } 394 395 #if defined(OS_CHROMEOS) 396 DevicePolicyStatusProvider::DevicePolicyStatusProvider( 397 policy::BrowserPolicyConnector* connector) 398 : CloudPolicyCoreStatusProvider( 399 connector->GetDeviceCloudPolicyManager()->core()) { 400 domain_ = connector->GetEnterpriseDomain(); 401 } 402 403 DevicePolicyStatusProvider::~DevicePolicyStatusProvider() { 404 } 405 406 void DevicePolicyStatusProvider::GetStatus(base::DictionaryValue* dict) { 407 GetStatusFromCore(core_, dict); 408 dict->SetString("domain", domain_); 409 } 410 411 DeviceLocalAccountPolicyStatusProvider::DeviceLocalAccountPolicyStatusProvider( 412 const std::string& user_id, 413 policy::DeviceLocalAccountPolicyService* service) 414 : user_id_(user_id), 415 service_(service) { 416 service_->AddObserver(this); 417 } 418 419 DeviceLocalAccountPolicyStatusProvider:: 420 ~DeviceLocalAccountPolicyStatusProvider() { 421 service_->RemoveObserver(this); 422 } 423 424 void DeviceLocalAccountPolicyStatusProvider::GetStatus( 425 base::DictionaryValue* dict) { 426 const policy::DeviceLocalAccountPolicyBroker* broker = 427 service_->GetBrokerForUser(user_id_); 428 if (broker) { 429 GetStatusFromCore(broker->core(), dict); 430 } else { 431 dict->SetBoolean("error", true); 432 dict->SetString("status", 433 policy::FormatStoreStatus( 434 policy::CloudPolicyStore::STATUS_BAD_STATE, 435 policy::CloudPolicyValidatorBase::VALIDATION_OK)); 436 dict->SetString("username", std::string()); 437 } 438 ExtractDomainFromUsername(dict); 439 dict->SetBoolean("publicAccount", true); 440 } 441 442 void DeviceLocalAccountPolicyStatusProvider::OnPolicyUpdated( 443 const std::string& user_id) { 444 if (user_id == user_id_) 445 NotifyStatusChange(); 446 } 447 448 void DeviceLocalAccountPolicyStatusProvider::OnDeviceLocalAccountsChanged() { 449 NotifyStatusChange(); 450 } 451 #endif 452 453 PolicyUIHandler::PolicyUIHandler() 454 : weak_factory_(this) { 455 } 456 457 PolicyUIHandler::~PolicyUIHandler() { 458 GetPolicyService()->RemoveObserver(policy::POLICY_DOMAIN_CHROME, this); 459 GetPolicyService()->RemoveObserver(policy::POLICY_DOMAIN_EXTENSIONS, this); 460 } 461 462 void PolicyUIHandler::RegisterMessages() { 463 #if defined(OS_CHROMEOS) 464 policy::BrowserPolicyConnector* connector = 465 g_browser_process->browser_policy_connector(); 466 if (connector->IsEnterpriseManaged()) 467 device_status_provider_.reset(new DevicePolicyStatusProvider(connector)); 468 469 const chromeos::UserManager* user_manager = chromeos::UserManager::Get(); 470 if (user_manager->IsLoggedInAsPublicAccount()) { 471 policy::DeviceLocalAccountPolicyService* local_account_service = 472 connector->GetDeviceLocalAccountPolicyService(); 473 if (local_account_service) { 474 user_status_provider_.reset( 475 new DeviceLocalAccountPolicyStatusProvider( 476 user_manager->GetLoggedInUser()->email(), local_account_service)); 477 } 478 } else { 479 policy::UserCloudPolicyManagerChromeOS* user_cloud_policy_manager = 480 policy::UserCloudPolicyManagerFactoryChromeOS::GetForProfile( 481 Profile::FromWebUI(web_ui())); 482 if (user_cloud_policy_manager) { 483 user_status_provider_.reset( 484 new UserPolicyStatusProvider(user_cloud_policy_manager->core())); 485 } 486 } 487 #else 488 policy::UserCloudPolicyManager* user_cloud_policy_manager = 489 policy::UserCloudPolicyManagerFactory::GetForProfile( 490 Profile::FromWebUI(web_ui())); 491 if (user_cloud_policy_manager) { 492 user_status_provider_.reset( 493 new UserPolicyStatusProvider(user_cloud_policy_manager->core())); 494 } 495 #endif 496 497 if (!user_status_provider_.get()) 498 user_status_provider_.reset(new CloudPolicyStatusProvider()); 499 if (!device_status_provider_.get()) 500 device_status_provider_.reset(new CloudPolicyStatusProvider()); 501 502 base::Closure update_callback(base::Bind(&PolicyUIHandler::SendStatus, 503 base::Unretained(this))); 504 user_status_provider_->SetStatusChangeCallback(update_callback); 505 device_status_provider_->SetStatusChangeCallback(update_callback); 506 GetPolicyService()->AddObserver(policy::POLICY_DOMAIN_CHROME, this); 507 GetPolicyService()->AddObserver(policy::POLICY_DOMAIN_EXTENSIONS, this); 508 509 registrar_.Add(this, 510 chrome::NOTIFICATION_EXTENSION_LOADED, 511 content::NotificationService::AllSources()); 512 registrar_.Add(this, 513 chrome::NOTIFICATION_EXTENSION_UNLOADED, 514 content::NotificationService::AllSources()); 515 516 web_ui()->RegisterMessageCallback( 517 "initialized", 518 base::Bind(&PolicyUIHandler::HandleInitialized, base::Unretained(this))); 519 web_ui()->RegisterMessageCallback( 520 "reloadPolicies", 521 base::Bind(&PolicyUIHandler::HandleReloadPolicies, 522 base::Unretained(this))); 523 } 524 525 void PolicyUIHandler::Observe(int type, 526 const content::NotificationSource& source, 527 const content::NotificationDetails& details) { 528 DCHECK(type == chrome::NOTIFICATION_EXTENSION_LOADED || 529 type == chrome::NOTIFICATION_EXTENSION_UNLOADED); 530 SendPolicyNames(); 531 SendPolicyValues(); 532 } 533 534 void PolicyUIHandler::OnPolicyUpdated(const policy::PolicyNamespace& ns, 535 const policy::PolicyMap& previous, 536 const policy::PolicyMap& current) { 537 SendPolicyValues(); 538 } 539 540 void PolicyUIHandler::SendPolicyNames() const { 541 base::DictionaryValue names; 542 543 // Add Chrome policy names. 544 base::DictionaryValue* chrome_policy_names = new base::DictionaryValue; 545 const policy::PolicyDefinitionList* list = 546 policy::GetChromePolicyDefinitionList(); 547 for (const policy::PolicyDefinitionList::Entry* entry = list->begin; 548 entry != list->end; ++entry) { 549 chrome_policy_names->SetBoolean(entry->name, true); 550 } 551 names.Set("chromePolicyNames", chrome_policy_names); 552 553 #if !defined(OS_ANDROID) && !defined(OS_IOS) 554 // Add extension policy names. 555 base::DictionaryValue* extension_policy_names = new base::DictionaryValue; 556 extensions::ExtensionSystem* extension_system = 557 extensions::ExtensionSystem::Get(Profile::FromWebUI(web_ui())); 558 const ExtensionSet* extensions = 559 extension_system->extension_service()->extensions(); 560 scoped_refptr<const policy::PolicyDomainDescriptor> policy_domain_descriptor; 561 policy_domain_descriptor = GetPolicyService()-> 562 GetPolicyDomainDescriptor(policy::POLICY_DOMAIN_EXTENSIONS); 563 const policy::PolicyDomainDescriptor::SchemaMap& schema_map = 564 policy_domain_descriptor->components(); 565 566 for (ExtensionSet::const_iterator it = extensions->begin(); 567 it != extensions->end(); ++it) { 568 const extensions::Extension* extension = it->get(); 569 // Skip this extension if it's not an enterprise extension. 570 if (!extension->manifest()->HasPath( 571 extension_manifest_keys::kStorageManagedSchema)) 572 continue; 573 base::DictionaryValue* extension_value = new base::DictionaryValue; 574 extension_value->SetString("name", extension->name()); 575 policy::PolicyDomainDescriptor::SchemaMap::const_iterator schema = 576 schema_map.find(extension->id()); 577 base::DictionaryValue* policy_names = new base::DictionaryValue; 578 if (schema != schema_map.end()) { 579 // Get policy names from the extension's policy schema. 580 // Store in a map, not an array, for faster lookup on JS side. 581 const policy::PolicySchemaMap* policies = schema->second->GetProperties(); 582 policy::PolicySchemaMap::const_iterator it_policies; 583 for (it_policies = policies->begin(); it_policies != policies->end(); 584 it_policies++) { 585 policy_names->SetBoolean(it_policies->first, true); 586 } 587 } 588 extension_value->Set("policyNames", policy_names); 589 extension_policy_names->Set(extension->id(), extension_value); 590 } 591 names.Set("extensionPolicyNames", extension_policy_names); 592 #endif 593 594 web_ui()->CallJavascriptFunction("policy.Page.setPolicyNames", names); 595 } 596 597 void PolicyUIHandler::SendPolicyValues() const { 598 base::DictionaryValue all_policies; 599 600 // Add Chrome policy values. 601 base::DictionaryValue* chrome_policies = new base::DictionaryValue; 602 GetChromePolicyValues(chrome_policies); 603 all_policies.Set("chromePolicies", chrome_policies); 604 605 #if !defined(OS_ANDROID) && !defined(OS_IOS) 606 // Add extension policy values. 607 extensions::ExtensionSystem* extension_system = 608 extensions::ExtensionSystem::Get(Profile::FromWebUI(web_ui())); 609 const ExtensionSet* extensions = 610 extension_system->extension_service()->extensions(); 611 base::DictionaryValue* extension_values = new base::DictionaryValue; 612 613 for (ExtensionSet::const_iterator it = extensions->begin(); 614 it != extensions->end(); ++it) { 615 const extensions::Extension* extension = it->get(); 616 // Skip this extension if it's not an enterprise extension. 617 if (!extension->manifest()->HasPath( 618 extension_manifest_keys::kStorageManagedSchema)) 619 continue; 620 base::DictionaryValue* extension_policies = new base::DictionaryValue; 621 policy::PolicyNamespace policy_namespace = policy::PolicyNamespace( 622 policy::POLICY_DOMAIN_EXTENSIONS, extension->id()); 623 policy::PolicyErrorMap empty_error_map; 624 GetPolicyValues(GetPolicyService()->GetPolicies(policy_namespace), 625 &empty_error_map, extension_policies); 626 extension_values->Set(extension->id(), extension_policies); 627 } 628 all_policies.Set("extensionPolicies", extension_values); 629 #endif 630 web_ui()->CallJavascriptFunction("policy.Page.setPolicyValues", all_policies); 631 } 632 633 void PolicyUIHandler::GetPolicyValues(const policy::PolicyMap& map, 634 policy::PolicyErrorMap* errors, 635 base::DictionaryValue* values) const { 636 for (policy::PolicyMap::const_iterator entry = map.begin(); 637 entry != map.end(); ++entry) { 638 base::DictionaryValue* value = new base::DictionaryValue; 639 value->Set("value", entry->second.value->DeepCopy()); 640 if (entry->second.scope == policy::POLICY_SCOPE_USER) 641 value->SetString("scope", "user"); 642 else 643 value->SetString("scope", "machine"); 644 if (entry->second.level == policy::POLICY_LEVEL_RECOMMENDED) 645 value->SetString("level", "recommended"); 646 else 647 value->SetString("level", "mandatory"); 648 string16 error = errors->GetErrors(entry->first); 649 if (!error.empty()) 650 value->SetString("error", error); 651 values->Set(entry->first, value); 652 } 653 } 654 655 void PolicyUIHandler::GetChromePolicyValues( 656 base::DictionaryValue* values) const { 657 policy::PolicyService* policy_service = GetPolicyService(); 658 policy::PolicyMap map; 659 660 // Make a copy that can be modified, since some policy values are modified 661 // before being displayed. 662 map.CopyFrom(policy_service->GetPolicies( 663 policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string()))); 664 665 // Get a list of all the errors in the policy values. 666 const policy::ConfigurationPolicyHandlerList* handler_list = 667 g_browser_process->browser_policy_connector()->GetHandlerList(); 668 policy::PolicyErrorMap errors; 669 handler_list->ApplyPolicySettings(map, NULL, &errors); 670 671 // Convert dictionary values to strings for display. 672 handler_list->PrepareForDisplaying(&map); 673 674 GetPolicyValues(map, &errors, values); 675 } 676 677 void PolicyUIHandler::SendStatus() const { 678 scoped_ptr<base::DictionaryValue> device_status(new base::DictionaryValue); 679 device_status_provider_->GetStatus(device_status.get()); 680 if (!device_domain_.empty()) 681 device_status->SetString("domain", device_domain_); 682 scoped_ptr<base::DictionaryValue> user_status(new base::DictionaryValue); 683 user_status_provider_->GetStatus(user_status.get()); 684 std::string username; 685 user_status->GetString("username", &username); 686 if (!username.empty()) 687 user_status->SetString("domain", gaia::ExtractDomainName(username)); 688 689 base::DictionaryValue status; 690 if (!device_status->empty()) 691 status.Set("device", device_status.release()); 692 if (!user_status->empty()) 693 status.Set("user", user_status.release()); 694 695 web_ui()->CallJavascriptFunction("policy.Page.setStatus", status); 696 } 697 698 void PolicyUIHandler::HandleInitialized(const base::ListValue* args) { 699 SendPolicyNames(); 700 SendPolicyValues(); 701 SendStatus(); 702 } 703 704 void PolicyUIHandler::HandleReloadPolicies(const base::ListValue* args) { 705 GetPolicyService()->RefreshPolicies( 706 base::Bind(&PolicyUIHandler::OnRefreshPoliciesDone, 707 weak_factory_.GetWeakPtr())); 708 } 709 710 void PolicyUIHandler::OnRefreshPoliciesDone() const { 711 web_ui()->CallJavascriptFunction("policy.Page.reloadPoliciesDone"); 712 } 713 714 policy::PolicyService* PolicyUIHandler::GetPolicyService() const { 715 return policy::ProfilePolicyConnectorFactory::GetForProfile( 716 Profile::FromWebUI(web_ui()))->policy_service(); 717 } 718 719 PolicyUI::PolicyUI(content::WebUI* web_ui) : WebUIController(web_ui) { 720 web_ui->AddMessageHandler(new PolicyUIHandler); 721 content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), 722 CreatePolicyUIHTMLSource()); 723 } 724 725 PolicyUI::~PolicyUI() { 726 } 727