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/login/users/user_manager.h" 59 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" 60 #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h" 61 #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h" 62 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h" 63 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.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 chromeos::UserManager* user_manager = chromeos::UserManager::Get(); 540 if (user_manager->IsLoggedInAsPublicAccount()) { 541 policy::DeviceLocalAccountPolicyService* local_account_service = 542 connector->GetDeviceLocalAccountPolicyService(); 543 if (local_account_service) { 544 user_status_provider_.reset( 545 new DeviceLocalAccountPolicyStatusProvider( 546 user_manager->GetLoggedInUser()->email(), local_account_service)); 547 } 548 } else { 549 policy::UserCloudPolicyManagerChromeOS* user_cloud_policy_manager = 550 policy::UserCloudPolicyManagerFactoryChromeOS::GetForProfile( 551 Profile::FromWebUI(web_ui())); 552 if (user_cloud_policy_manager) { 553 user_status_provider_.reset( 554 new UserPolicyStatusProvider(user_cloud_policy_manager->core())); 555 } 556 } 557 #else 558 policy::UserCloudPolicyManager* user_cloud_policy_manager = 559 policy::UserCloudPolicyManagerFactory::GetForBrowserContext( 560 web_ui()->GetWebContents()->GetBrowserContext()); 561 if (user_cloud_policy_manager) { 562 user_status_provider_.reset( 563 new UserPolicyStatusProvider(user_cloud_policy_manager->core())); 564 } 565 #endif 566 567 if (!user_status_provider_.get()) 568 user_status_provider_.reset(new CloudPolicyStatusProvider()); 569 if (!device_status_provider_.get()) 570 device_status_provider_.reset(new CloudPolicyStatusProvider()); 571 572 base::Closure update_callback(base::Bind(&PolicyUIHandler::SendStatus, 573 base::Unretained(this))); 574 user_status_provider_->SetStatusChangeCallback(update_callback); 575 device_status_provider_->SetStatusChangeCallback(update_callback); 576 GetPolicyService()->AddObserver(policy::POLICY_DOMAIN_CHROME, this); 577 GetPolicyService()->AddObserver(policy::POLICY_DOMAIN_EXTENSIONS, this); 578 579 registrar_.Add(this, 580 chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED, 581 content::NotificationService::AllSources()); 582 registrar_.Add(this, 583 chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED, 584 content::NotificationService::AllSources()); 585 586 web_ui()->RegisterMessageCallback( 587 "initialized", 588 base::Bind(&PolicyUIHandler::HandleInitialized, base::Unretained(this))); 589 web_ui()->RegisterMessageCallback( 590 "reloadPolicies", 591 base::Bind(&PolicyUIHandler::HandleReloadPolicies, 592 base::Unretained(this))); 593 } 594 595 void PolicyUIHandler::Observe(int type, 596 const content::NotificationSource& source, 597 const content::NotificationDetails& details) { 598 DCHECK(type == chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED || 599 type == chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED); 600 SendPolicyNames(); 601 SendPolicyValues(); 602 } 603 604 void PolicyUIHandler::OnPolicyUpdated(const policy::PolicyNamespace& ns, 605 const policy::PolicyMap& previous, 606 const policy::PolicyMap& current) { 607 SendPolicyValues(); 608 } 609 610 void PolicyUIHandler::SendPolicyNames() const { 611 base::DictionaryValue names; 612 613 Profile* profile = Profile::FromWebUI(web_ui()); 614 policy::SchemaRegistry* registry = 615 policy::SchemaRegistryServiceFactory::GetForContext( 616 profile->GetOriginalProfile())->registry(); 617 scoped_refptr<policy::SchemaMap> schema_map = registry->schema_map(); 618 619 // Add Chrome policy names. 620 base::DictionaryValue* chrome_policy_names = new base::DictionaryValue; 621 policy::PolicyNamespace chrome_ns(policy::POLICY_DOMAIN_CHROME, ""); 622 const policy::Schema* chrome_schema = schema_map->GetSchema(chrome_ns); 623 for (policy::Schema::Iterator it = chrome_schema->GetPropertiesIterator(); 624 !it.IsAtEnd(); it.Advance()) { 625 chrome_policy_names->SetBoolean(it.key(), true); 626 } 627 names.Set("chromePolicyNames", chrome_policy_names); 628 629 #if !defined(OS_ANDROID) && !defined(OS_IOS) 630 // Add extension policy names. 631 base::DictionaryValue* extension_policy_names = new base::DictionaryValue; 632 633 extensions::ExtensionSystem* extension_system = 634 extensions::ExtensionSystem::Get(profile); 635 const extensions::ExtensionSet* extensions = 636 extension_system->extension_service()->extensions(); 637 638 for (extensions::ExtensionSet::const_iterator it = extensions->begin(); 639 it != extensions->end(); ++it) { 640 const extensions::Extension* extension = it->get(); 641 // Skip this extension if it's not an enterprise extension. 642 if (!extension->manifest()->HasPath( 643 extensions::manifest_keys::kStorageManagedSchema)) 644 continue; 645 base::DictionaryValue* extension_value = new base::DictionaryValue; 646 extension_value->SetString("name", extension->name()); 647 const policy::Schema* schema = 648 schema_map->GetSchema(policy::PolicyNamespace( 649 policy::POLICY_DOMAIN_EXTENSIONS, extension->id())); 650 base::DictionaryValue* policy_names = new base::DictionaryValue; 651 if (schema && schema->valid()) { 652 // Get policy names from the extension's policy schema. 653 // Store in a map, not an array, for faster lookup on JS side. 654 for (policy::Schema::Iterator prop = schema->GetPropertiesIterator(); 655 !prop.IsAtEnd(); prop.Advance()) { 656 policy_names->SetBoolean(prop.key(), true); 657 } 658 } 659 extension_value->Set("policyNames", policy_names); 660 extension_policy_names->Set(extension->id(), extension_value); 661 } 662 names.Set("extensionPolicyNames", extension_policy_names); 663 #endif 664 665 web_ui()->CallJavascriptFunction("policy.Page.setPolicyNames", names); 666 } 667 668 void PolicyUIHandler::SendPolicyValues() const { 669 base::DictionaryValue all_policies; 670 671 // Add Chrome policy values. 672 base::DictionaryValue* chrome_policies = new base::DictionaryValue; 673 GetChromePolicyValues(chrome_policies); 674 all_policies.Set("chromePolicies", chrome_policies); 675 676 #if !defined(OS_ANDROID) && !defined(OS_IOS) 677 // Add extension policy values. 678 extensions::ExtensionSystem* extension_system = 679 extensions::ExtensionSystem::Get(Profile::FromWebUI(web_ui())); 680 const extensions::ExtensionSet* extensions = 681 extension_system->extension_service()->extensions(); 682 base::DictionaryValue* extension_values = new base::DictionaryValue; 683 684 for (extensions::ExtensionSet::const_iterator it = extensions->begin(); 685 it != extensions->end(); ++it) { 686 const extensions::Extension* extension = it->get(); 687 // Skip this extension if it's not an enterprise extension. 688 if (!extension->manifest()->HasPath( 689 extensions::manifest_keys::kStorageManagedSchema)) 690 continue; 691 base::DictionaryValue* extension_policies = new base::DictionaryValue; 692 policy::PolicyNamespace policy_namespace = policy::PolicyNamespace( 693 policy::POLICY_DOMAIN_EXTENSIONS, extension->id()); 694 policy::PolicyErrorMap empty_error_map; 695 GetPolicyValues(GetPolicyService()->GetPolicies(policy_namespace), 696 &empty_error_map, extension_policies); 697 extension_values->Set(extension->id(), extension_policies); 698 } 699 all_policies.Set("extensionPolicies", extension_values); 700 #endif 701 web_ui()->CallJavascriptFunction("policy.Page.setPolicyValues", all_policies); 702 } 703 704 void PolicyUIHandler::GetPolicyValues(const policy::PolicyMap& map, 705 policy::PolicyErrorMap* errors, 706 base::DictionaryValue* values) const { 707 for (policy::PolicyMap::const_iterator entry = map.begin(); 708 entry != map.end(); ++entry) { 709 base::DictionaryValue* value = new base::DictionaryValue; 710 value->Set("value", CopyAndConvert(entry->second.value).release()); 711 if (entry->second.scope == policy::POLICY_SCOPE_USER) 712 value->SetString("scope", "user"); 713 else 714 value->SetString("scope", "machine"); 715 if (entry->second.level == policy::POLICY_LEVEL_RECOMMENDED) 716 value->SetString("level", "recommended"); 717 else 718 value->SetString("level", "mandatory"); 719 base::string16 error = errors->GetErrors(entry->first); 720 if (!error.empty()) 721 value->SetString("error", error); 722 values->Set(entry->first, value); 723 } 724 } 725 726 void PolicyUIHandler::GetChromePolicyValues( 727 base::DictionaryValue* values) const { 728 policy::PolicyService* policy_service = GetPolicyService(); 729 policy::PolicyMap map; 730 731 // Make a copy that can be modified, since some policy values are modified 732 // before being displayed. 733 map.CopyFrom(policy_service->GetPolicies( 734 policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string()))); 735 736 // Get a list of all the errors in the policy values. 737 const policy::ConfigurationPolicyHandlerList* handler_list = 738 g_browser_process->browser_policy_connector()->GetHandlerList(); 739 policy::PolicyErrorMap errors; 740 handler_list->ApplyPolicySettings(map, NULL, &errors); 741 742 // Convert dictionary values to strings for display. 743 handler_list->PrepareForDisplaying(&map); 744 745 GetPolicyValues(map, &errors, values); 746 } 747 748 void PolicyUIHandler::SendStatus() const { 749 scoped_ptr<base::DictionaryValue> device_status(new base::DictionaryValue); 750 device_status_provider_->GetStatus(device_status.get()); 751 if (!device_domain_.empty()) 752 device_status->SetString("domain", device_domain_); 753 scoped_ptr<base::DictionaryValue> user_status(new base::DictionaryValue); 754 user_status_provider_->GetStatus(user_status.get()); 755 std::string username; 756 user_status->GetString("username", &username); 757 if (!username.empty()) 758 user_status->SetString("domain", gaia::ExtractDomainName(username)); 759 760 base::DictionaryValue status; 761 if (!device_status->empty()) 762 status.Set("device", device_status.release()); 763 if (!user_status->empty()) 764 status.Set("user", user_status.release()); 765 766 web_ui()->CallJavascriptFunction("policy.Page.setStatus", status); 767 } 768 769 void PolicyUIHandler::HandleInitialized(const base::ListValue* args) { 770 SendPolicyNames(); 771 SendPolicyValues(); 772 SendStatus(); 773 } 774 775 void PolicyUIHandler::HandleReloadPolicies(const base::ListValue* args) { 776 GetPolicyService()->RefreshPolicies( 777 base::Bind(&PolicyUIHandler::OnRefreshPoliciesDone, 778 weak_factory_.GetWeakPtr())); 779 } 780 781 void PolicyUIHandler::OnRefreshPoliciesDone() const { 782 web_ui()->CallJavascriptFunction("policy.Page.reloadPoliciesDone"); 783 } 784 785 policy::PolicyService* PolicyUIHandler::GetPolicyService() const { 786 return policy::ProfilePolicyConnectorFactory::GetForProfile( 787 Profile::FromWebUI(web_ui()))->policy_service(); 788 } 789 790 PolicyUI::PolicyUI(content::WebUI* web_ui) : WebUIController(web_ui) { 791 web_ui->AddMessageHandler(new PolicyUIHandler); 792 content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), 793 CreatePolicyUIHTMLSource()); 794 } 795 796 PolicyUI::~PolicyUI() { 797 } 798