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