Add ICU message format support
[chromium-blink-merge.git] / chrome / browser / ui / webui / policy_ui.cc
blob03d43485804641fe4dced0da2ec12c88bcb51905
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.
5 #include "chrome/browser/ui/webui/policy_ui.h"
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/policy/profile_policy_connector.h"
20 #include "chrome/browser/policy/profile_policy_connector_factory.h"
21 #include "chrome/browser/policy/schema_registry_service.h"
22 #include "chrome/browser/policy/schema_registry_service_factory.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/common/url_constants.h"
25 #include "components/policy/core/browser/browser_policy_connector.h"
26 #include "components/policy/core/browser/cloud/message_util.h"
27 #include "components/policy/core/browser/configuration_policy_handler_list.h"
28 #include "components/policy/core/browser/policy_error_map.h"
29 #include "components/policy/core/common/cloud/cloud_policy_client.h"
30 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
31 #include "components/policy/core/common/cloud/cloud_policy_core.h"
32 #include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h"
33 #include "components/policy/core/common/cloud/cloud_policy_store.h"
34 #include "components/policy/core/common/cloud/cloud_policy_validator.h"
35 #include "components/policy/core/common/policy_map.h"
36 #include "components/policy/core/common/policy_namespace.h"
37 #include "components/policy/core/common/policy_service.h"
38 #include "components/policy/core/common/policy_types.h"
39 #include "components/policy/core/common/remote_commands/remote_commands_service.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/web_contents.h"
44 #include "content/public/browser/web_ui.h"
45 #include "content/public/browser/web_ui_data_source.h"
46 #include "content/public/browser/web_ui_message_handler.h"
47 #include "google_apis/gaia/gaia_auth_util.h"
48 #include "grit/browser_resources.h"
49 #include "grit/components_strings.h"
50 #include "policy/policy_constants.h"
51 #include "policy/proto/device_management_backend.pb.h"
52 #include "ui/base/l10n/l10n_util.h"
53 #include "ui/base/l10n/time_format.h"
55 #if defined(OS_CHROMEOS)
56 #include "chrome/browser/browser_process_platform_part.h"
57 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
58 #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
59 #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
60 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h"
61 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h"
62 #include "components/user_manager/user_manager.h"
63 #else
64 #include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
65 #include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
66 #endif
68 #if defined(ENABLE_EXTENSIONS)
69 #include "extensions/browser/extension_registry.h"
70 #include "extensions/browser/extension_registry_observer.h"
71 #include "extensions/common/extension.h"
72 #include "extensions/common/manifest.h"
73 #include "extensions/common/manifest_constants.h"
74 #endif
76 namespace em = enterprise_management;
78 namespace {
80 content::WebUIDataSource* CreatePolicyUIHTMLSource() {
81 content::WebUIDataSource* source =
82 content::WebUIDataSource::Create(chrome::kChromeUIPolicyHost);
84 // Localized strings.
85 source->AddLocalizedString("title", IDS_POLICY_TITLE);
86 source->AddLocalizedString("filterPlaceholder",
87 IDS_POLICY_FILTER_PLACEHOLDER);
88 source->AddLocalizedString("reloadPolicies", IDS_POLICY_RELOAD_POLICIES);
89 source->AddLocalizedString("status", IDS_POLICY_STATUS);
90 source->AddLocalizedString("statusDevice", IDS_POLICY_STATUS_DEVICE);
91 source->AddLocalizedString("statusUser", IDS_POLICY_STATUS_USER);
92 source->AddLocalizedString("labelDomain", IDS_POLICY_LABEL_DOMAIN);
93 source->AddLocalizedString("labelUsername", IDS_POLICY_LABEL_USERNAME);
94 source->AddLocalizedString("labelClientId", IDS_POLICY_LABEL_CLIENT_ID);
95 source->AddLocalizedString("labelAssetId", IDS_POLICY_LABEL_ASSET_ID);
96 source->AddLocalizedString("labelLocation", IDS_POLICY_LABEL_LOCATION);
97 source->AddLocalizedString("labelDirectoryApiId",
98 IDS_POLICY_LABEL_DIRECTORY_API_ID);
99 source->AddLocalizedString("labelTimeSinceLastRefresh",
100 IDS_POLICY_LABEL_TIME_SINCE_LAST_REFRESH);
101 source->AddLocalizedString("labelRefreshInterval",
102 IDS_POLICY_LABEL_REFRESH_INTERVAL);
103 source->AddLocalizedString("labelStatus", IDS_POLICY_LABEL_STATUS);
104 source->AddLocalizedString("showUnset", IDS_POLICY_SHOW_UNSET);
105 source->AddLocalizedString("noPoliciesSet", IDS_POLICY_NO_POLICIES_SET);
106 source->AddLocalizedString("headerScope", IDS_POLICY_HEADER_SCOPE);
107 source->AddLocalizedString("headerLevel", IDS_POLICY_HEADER_LEVEL);
108 source->AddLocalizedString("headerName", IDS_POLICY_HEADER_NAME);
109 source->AddLocalizedString("headerValue", IDS_POLICY_HEADER_VALUE);
110 source->AddLocalizedString("headerStatus", IDS_POLICY_HEADER_STATUS);
111 source->AddLocalizedString("showExpandedValue",
112 IDS_POLICY_SHOW_EXPANDED_VALUE);
113 source->AddLocalizedString("hideExpandedValue",
114 IDS_POLICY_HIDE_EXPANDED_VALUE);
115 source->AddLocalizedString("scopeUser", IDS_POLICY_SCOPE_USER);
116 source->AddLocalizedString("scopeDevice", IDS_POLICY_SCOPE_DEVICE);
117 source->AddLocalizedString("levelRecommended", IDS_POLICY_LEVEL_RECOMMENDED);
118 source->AddLocalizedString("levelMandatory", IDS_POLICY_LEVEL_MANDATORY);
119 source->AddLocalizedString("ok", IDS_POLICY_OK);
120 source->AddLocalizedString("unset", IDS_POLICY_UNSET);
121 source->AddLocalizedString("unknown", IDS_POLICY_UNKNOWN);
122 source->AddLocalizedString("notSpecified", IDS_POLICY_NOT_SPECIFIED);
124 source->SetJsonPath("strings.js");
126 // Add required resources.
127 source->AddResourcePath("policy.css", IDR_POLICY_CSS);
128 source->AddResourcePath("policy.js", IDR_POLICY_JS);
129 source->AddResourcePath("uber_utils.js", IDR_UBER_UTILS_JS);
130 source->SetDefaultResource(IDR_POLICY_HTML);
132 return source;
135 // Formats the association state indicated by |data|. If |data| is NULL, the
136 // state is considered to be UNMANAGED.
137 base::string16 FormatAssociationState(const em::PolicyData* data) {
138 if (data) {
139 switch (data->state()) {
140 case em::PolicyData::ACTIVE:
141 return l10n_util::GetStringUTF16(IDS_POLICY_ASSOCIATION_STATE_ACTIVE);
142 case em::PolicyData::UNMANAGED:
143 return l10n_util::GetStringUTF16(
144 IDS_POLICY_ASSOCIATION_STATE_UNMANAGED);
145 case em::PolicyData::DEPROVISIONED:
146 return l10n_util::GetStringUTF16(
147 IDS_POLICY_ASSOCIATION_STATE_DEPROVISIONED);
149 NOTREACHED() << "Unknown state " << data->state();
152 // Default to UNMANAGED for the case of missing policy or bad state enum.
153 return l10n_util::GetStringUTF16(IDS_POLICY_ASSOCIATION_STATE_UNMANAGED);
156 void GetStatusFromCore(const policy::CloudPolicyCore* core,
157 base::DictionaryValue* dict) {
158 const policy::CloudPolicyStore* store = core->store();
159 const policy::CloudPolicyClient* client = core->client();
160 const policy::CloudPolicyRefreshScheduler* refresh_scheduler =
161 core->refresh_scheduler();
163 // CloudPolicyStore errors take precedence to show in the status message.
164 // Other errors (such as transient policy fetching problems) get displayed
165 // only if CloudPolicyStore is in STATUS_OK.
166 base::string16 status =
167 policy::FormatStoreStatus(store->status(), store->validation_status());
168 if (store->status() == policy::CloudPolicyStore::STATUS_OK) {
169 if (client && client->status() != policy::DM_STATUS_SUCCESS)
170 status = policy::FormatDeviceManagementStatus(client->status());
171 else if (!store->is_managed())
172 status = FormatAssociationState(store->policy());
175 const em::PolicyData* policy = store->policy();
176 std::string client_id = policy ? policy->device_id() : std::string();
177 std::string username = policy ? policy->username() : std::string();
179 if (policy && policy->has_annotated_asset_id())
180 dict->SetString("assetId", policy->annotated_asset_id());
181 if (policy && policy->has_annotated_location())
182 dict->SetString("location", policy->annotated_location());
183 if (policy && policy->has_directory_api_id())
184 dict->SetString("directoryApiId", policy->directory_api_id());
186 base::TimeDelta refresh_interval =
187 base::TimeDelta::FromMilliseconds(refresh_scheduler ?
188 refresh_scheduler->refresh_delay() :
189 policy::CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs);
190 base::Time last_refresh_time = refresh_scheduler ?
191 refresh_scheduler->last_refresh() : base::Time();
193 bool no_error = store->status() == policy::CloudPolicyStore::STATUS_OK &&
194 client && client->status() == policy::DM_STATUS_SUCCESS;
195 dict->SetBoolean("error", !no_error);
196 dict->SetString("status", status);
197 dict->SetString("clientId", client_id);
198 dict->SetString("username", username);
199 dict->SetString("refreshInterval",
200 ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_DURATION,
201 ui::TimeFormat::LENGTH_SHORT,
202 refresh_interval));
203 dict->SetString("timeSinceLastRefresh", last_refresh_time.is_null() ?
204 l10n_util::GetStringUTF16(IDS_POLICY_NEVER_FETCHED) :
205 ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_ELAPSED,
206 ui::TimeFormat::LENGTH_SHORT,
207 base::Time::NowFromSystemTime() -
208 last_refresh_time));
211 void ExtractDomainFromUsername(base::DictionaryValue* dict) {
212 std::string username;
213 dict->GetString("username", &username);
214 if (!username.empty())
215 dict->SetString("domain", gaia::ExtractDomainName(username));
218 // Utility function that returns a JSON serialization of the given |dict|.
219 scoped_ptr<base::StringValue> DictionaryToJSONString(
220 const base::DictionaryValue& dict) {
221 std::string json_string;
222 base::JSONWriter::WriteWithOptions(dict,
223 base::JSONWriter::OPTIONS_PRETTY_PRINT,
224 &json_string);
225 return make_scoped_ptr(new base::StringValue(json_string));
228 // Returns a copy of |value| with some values converted to a representation that
229 // i18n_template.js will display in a nicer way.
230 scoped_ptr<base::Value> CopyAndConvert(const base::Value* value) {
231 const base::DictionaryValue* dict = NULL;
232 if (value->GetAsDictionary(&dict))
233 return DictionaryToJSONString(*dict);
235 scoped_ptr<base::Value> copy(value->DeepCopy());
236 base::ListValue* list = NULL;
237 if (copy->GetAsList(&list)) {
238 for (size_t i = 0; i < list->GetSize(); ++i) {
239 if (list->GetDictionary(i, &dict))
240 list->Set(i, DictionaryToJSONString(*dict).release());
244 return copy.Pass();
247 } // namespace
249 // An interface for querying the status of cloud policy.
250 class CloudPolicyStatusProvider {
251 public:
252 CloudPolicyStatusProvider();
253 virtual ~CloudPolicyStatusProvider();
255 // Sets a callback to invoke upon status changes.
256 void SetStatusChangeCallback(const base::Closure& callback);
258 virtual void GetStatus(base::DictionaryValue* dict);
260 protected:
261 void NotifyStatusChange();
263 private:
264 base::Closure callback_;
266 DISALLOW_COPY_AND_ASSIGN(CloudPolicyStatusProvider);
269 // Status provider implementation that pulls cloud policy status from a
270 // CloudPolicyCore instance provided at construction time. Also listens for
271 // changes on that CloudPolicyCore and reports them through the status change
272 // callback.
273 class CloudPolicyCoreStatusProvider
274 : public CloudPolicyStatusProvider,
275 public policy::CloudPolicyStore::Observer {
276 public:
277 explicit CloudPolicyCoreStatusProvider(policy::CloudPolicyCore* core);
278 ~CloudPolicyCoreStatusProvider() override;
280 // policy::CloudPolicyStore::Observer implementation.
281 void OnStoreLoaded(policy::CloudPolicyStore* store) override;
282 void OnStoreError(policy::CloudPolicyStore* store) override;
284 protected:
285 // Policy status is read from the CloudPolicyClient, CloudPolicyStore and
286 // CloudPolicyRefreshScheduler hosted by this |core_|.
287 policy::CloudPolicyCore* core_;
289 private:
290 DISALLOW_COPY_AND_ASSIGN(CloudPolicyCoreStatusProvider);
293 // A cloud policy status provider for user policy.
294 class UserPolicyStatusProvider : public CloudPolicyCoreStatusProvider {
295 public:
296 explicit UserPolicyStatusProvider(policy::CloudPolicyCore* core);
297 ~UserPolicyStatusProvider() override;
299 // CloudPolicyCoreStatusProvider implementation.
300 void GetStatus(base::DictionaryValue* dict) override;
302 private:
303 DISALLOW_COPY_AND_ASSIGN(UserPolicyStatusProvider);
306 #if defined(OS_CHROMEOS)
307 // A cloud policy status provider for device policy.
308 class DevicePolicyStatusProvider : public CloudPolicyCoreStatusProvider {
309 public:
310 explicit DevicePolicyStatusProvider(
311 policy::BrowserPolicyConnectorChromeOS* connector);
312 ~DevicePolicyStatusProvider() override;
314 // CloudPolicyCoreStatusProvider implementation.
315 void GetStatus(base::DictionaryValue* dict) override;
317 private:
318 std::string domain_;
320 DISALLOW_COPY_AND_ASSIGN(DevicePolicyStatusProvider);
323 // A cloud policy status provider that reads policy status from the policy core
324 // associated with the device-local account specified by |user_id| at
325 // construction time. The indirection via user ID and
326 // DeviceLocalAccountPolicyService is necessary because the device-local account
327 // may go away any time behind the scenes, at which point the status message
328 // text will indicate CloudPolicyStore::STATUS_BAD_STATE.
329 class DeviceLocalAccountPolicyStatusProvider
330 : public CloudPolicyStatusProvider,
331 public policy::DeviceLocalAccountPolicyService::Observer {
332 public:
333 DeviceLocalAccountPolicyStatusProvider(
334 const std::string& user_id,
335 policy::DeviceLocalAccountPolicyService* service);
336 ~DeviceLocalAccountPolicyStatusProvider() override;
338 // CloudPolicyStatusProvider implementation.
339 void GetStatus(base::DictionaryValue* dict) override;
341 // policy::DeviceLocalAccountPolicyService::Observer implementation.
342 void OnPolicyUpdated(const std::string& user_id) override;
343 void OnDeviceLocalAccountsChanged() override;
345 private:
346 const std::string user_id_;
347 policy::DeviceLocalAccountPolicyService* service_;
349 DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountPolicyStatusProvider);
351 #endif
353 // The JavaScript message handler for the chrome://policy page.
354 class PolicyUIHandler : public content::WebUIMessageHandler,
355 #if defined(ENABLE_EXTENSIONS)
356 public extensions::ExtensionRegistryObserver,
357 #endif
358 public policy::PolicyService::Observer,
359 public policy::SchemaRegistry::Observer {
360 public:
361 PolicyUIHandler();
362 ~PolicyUIHandler() override;
364 // content::WebUIMessageHandler implementation.
365 void RegisterMessages() override;
367 #if defined(ENABLE_EXTENSIONS)
368 // extensions::ExtensionRegistryObserver implementation.
369 void OnExtensionLoaded(content::BrowserContext* browser_context,
370 const extensions::Extension* extension) override;
371 void OnExtensionUnloaded(
372 content::BrowserContext* browser_context,
373 const extensions::Extension* extension,
374 extensions::UnloadedExtensionInfo::Reason reason) override;
375 #endif
377 // policy::PolicyService::Observer implementation.
378 void OnPolicyUpdated(const policy::PolicyNamespace& ns,
379 const policy::PolicyMap& previous,
380 const policy::PolicyMap& current) override;
382 // policy::SchemaRegistry::Observer implementation.
383 void OnSchemaRegistryUpdated(bool has_new_schemas) override;
385 private:
386 // Send a dictionary containing the names of all known policies to the UI.
387 void SendPolicyNames() const;
389 // Send information about the current policy values to the UI. For each policy
390 // whose value has been set, a dictionary containing the value and additional
391 // metadata is sent.
392 void SendPolicyValues() const;
394 // Send the status of cloud policy to the UI. For each scope that has cloud
395 // policy enabled (device and/or user), a dictionary containing status
396 // information is sent.
397 void SendStatus() const;
399 // Inserts a description of each policy in |policy_map| into |values|, using
400 // the optional errors in |errors| to determine the status of each policy.
401 void GetPolicyValues(const policy::PolicyMap& policy_map,
402 policy::PolicyErrorMap* errors,
403 base::DictionaryValue* values) const;
405 void GetChromePolicyValues(base::DictionaryValue* values) const;
407 void HandleInitialized(const base::ListValue* args);
408 void HandleReloadPolicies(const base::ListValue* args);
410 void OnRefreshPoliciesDone() const;
412 policy::PolicyService* GetPolicyService() const;
414 std::string device_domain_;
416 // Providers that supply status dictionaries for user and device policy,
417 // respectively. These are created on initialization time as appropriate for
418 // the platform (Chrome OS / desktop) and type of policy that is in effect.
419 scoped_ptr<CloudPolicyStatusProvider> user_status_provider_;
420 scoped_ptr<CloudPolicyStatusProvider> device_status_provider_;
422 base::WeakPtrFactory<PolicyUIHandler> weak_factory_;
424 DISALLOW_COPY_AND_ASSIGN(PolicyUIHandler);
427 CloudPolicyStatusProvider::CloudPolicyStatusProvider() {
430 CloudPolicyStatusProvider::~CloudPolicyStatusProvider() {
433 void CloudPolicyStatusProvider::SetStatusChangeCallback(
434 const base::Closure& callback) {
435 callback_ = callback;
438 void CloudPolicyStatusProvider::GetStatus(base::DictionaryValue* dict) {
441 void CloudPolicyStatusProvider::NotifyStatusChange() {
442 if (!callback_.is_null())
443 callback_.Run();
446 CloudPolicyCoreStatusProvider::CloudPolicyCoreStatusProvider(
447 policy::CloudPolicyCore* core) : core_(core) {
448 core_->store()->AddObserver(this);
449 // TODO(bartfab): Add an observer that watches for client errors. Observing
450 // core_->client() directly is not safe as the client may be destroyed and
451 // (re-)created anytime if the user signs in or out on desktop platforms.
454 CloudPolicyCoreStatusProvider::~CloudPolicyCoreStatusProvider() {
455 core_->store()->RemoveObserver(this);
458 void CloudPolicyCoreStatusProvider::OnStoreLoaded(
459 policy::CloudPolicyStore* store) {
460 NotifyStatusChange();
463 void CloudPolicyCoreStatusProvider::OnStoreError(
464 policy::CloudPolicyStore* store) {
465 NotifyStatusChange();
468 UserPolicyStatusProvider::UserPolicyStatusProvider(
469 policy::CloudPolicyCore* core) : CloudPolicyCoreStatusProvider(core) {
472 UserPolicyStatusProvider::~UserPolicyStatusProvider() {
475 void UserPolicyStatusProvider::GetStatus(base::DictionaryValue* dict) {
476 if (!core_->store()->is_managed())
477 return;
478 GetStatusFromCore(core_, dict);
479 ExtractDomainFromUsername(dict);
482 #if defined(OS_CHROMEOS)
483 DevicePolicyStatusProvider::DevicePolicyStatusProvider(
484 policy::BrowserPolicyConnectorChromeOS* connector)
485 : CloudPolicyCoreStatusProvider(
486 connector->GetDeviceCloudPolicyManager()->core()) {
487 domain_ = connector->GetEnterpriseDomain();
490 DevicePolicyStatusProvider::~DevicePolicyStatusProvider() {
493 void DevicePolicyStatusProvider::GetStatus(base::DictionaryValue* dict) {
494 GetStatusFromCore(core_, dict);
495 dict->SetString("domain", domain_);
498 DeviceLocalAccountPolicyStatusProvider::DeviceLocalAccountPolicyStatusProvider(
499 const std::string& user_id,
500 policy::DeviceLocalAccountPolicyService* service)
501 : user_id_(user_id),
502 service_(service) {
503 service_->AddObserver(this);
506 DeviceLocalAccountPolicyStatusProvider::
507 ~DeviceLocalAccountPolicyStatusProvider() {
508 service_->RemoveObserver(this);
511 void DeviceLocalAccountPolicyStatusProvider::GetStatus(
512 base::DictionaryValue* dict) {
513 const policy::DeviceLocalAccountPolicyBroker* broker =
514 service_->GetBrokerForUser(user_id_);
515 if (broker) {
516 GetStatusFromCore(broker->core(), dict);
517 } else {
518 dict->SetBoolean("error", true);
519 dict->SetString("status",
520 policy::FormatStoreStatus(
521 policy::CloudPolicyStore::STATUS_BAD_STATE,
522 policy::CloudPolicyValidatorBase::VALIDATION_OK));
523 dict->SetString("username", std::string());
525 ExtractDomainFromUsername(dict);
526 dict->SetBoolean("publicAccount", true);
529 void DeviceLocalAccountPolicyStatusProvider::OnPolicyUpdated(
530 const std::string& user_id) {
531 if (user_id == user_id_)
532 NotifyStatusChange();
535 void DeviceLocalAccountPolicyStatusProvider::OnDeviceLocalAccountsChanged() {
536 NotifyStatusChange();
538 #endif
540 PolicyUIHandler::PolicyUIHandler()
541 : weak_factory_(this) {
544 PolicyUIHandler::~PolicyUIHandler() {
545 GetPolicyService()->RemoveObserver(policy::POLICY_DOMAIN_CHROME, this);
546 GetPolicyService()->RemoveObserver(policy::POLICY_DOMAIN_EXTENSIONS, this);
547 policy::SchemaRegistry* registry =
548 policy::SchemaRegistryServiceFactory::GetForContext(
549 Profile::FromWebUI(web_ui())->GetOriginalProfile())->registry();
550 registry->RemoveObserver(this);
552 #if defined(ENABLE_EXTENSIONS)
553 extensions::ExtensionRegistry::Get(Profile::FromWebUI(web_ui()))
554 ->RemoveObserver(this);
555 #endif
558 void PolicyUIHandler::RegisterMessages() {
559 #if defined(OS_CHROMEOS)
560 policy::BrowserPolicyConnectorChromeOS* connector =
561 g_browser_process->platform_part()->browser_policy_connector_chromeos();
562 if (connector->IsEnterpriseManaged())
563 device_status_provider_.reset(new DevicePolicyStatusProvider(connector));
565 const user_manager::UserManager* user_manager =
566 user_manager::UserManager::Get();
567 if (user_manager->IsLoggedInAsPublicAccount()) {
568 policy::DeviceLocalAccountPolicyService* local_account_service =
569 connector->GetDeviceLocalAccountPolicyService();
570 if (local_account_service) {
571 user_status_provider_.reset(
572 new DeviceLocalAccountPolicyStatusProvider(
573 user_manager->GetLoggedInUser()->email(), local_account_service));
575 } else {
576 policy::UserCloudPolicyManagerChromeOS* user_cloud_policy_manager =
577 policy::UserCloudPolicyManagerFactoryChromeOS::GetForProfile(
578 Profile::FromWebUI(web_ui()));
579 if (user_cloud_policy_manager) {
580 user_status_provider_.reset(
581 new UserPolicyStatusProvider(user_cloud_policy_manager->core()));
584 #else
585 policy::UserCloudPolicyManager* user_cloud_policy_manager =
586 policy::UserCloudPolicyManagerFactory::GetForBrowserContext(
587 web_ui()->GetWebContents()->GetBrowserContext());
588 if (user_cloud_policy_manager) {
589 user_status_provider_.reset(
590 new UserPolicyStatusProvider(user_cloud_policy_manager->core()));
592 #endif
594 if (!user_status_provider_.get())
595 user_status_provider_.reset(new CloudPolicyStatusProvider());
596 if (!device_status_provider_.get())
597 device_status_provider_.reset(new CloudPolicyStatusProvider());
599 base::Closure update_callback(base::Bind(&PolicyUIHandler::SendStatus,
600 base::Unretained(this)));
601 user_status_provider_->SetStatusChangeCallback(update_callback);
602 device_status_provider_->SetStatusChangeCallback(update_callback);
603 GetPolicyService()->AddObserver(policy::POLICY_DOMAIN_CHROME, this);
604 GetPolicyService()->AddObserver(policy::POLICY_DOMAIN_EXTENSIONS, this);
606 #if defined(ENABLE_EXTENSIONS)
607 extensions::ExtensionRegistry::Get(Profile::FromWebUI(web_ui()))
608 ->AddObserver(this);
609 #endif
610 policy::SchemaRegistry* registry =
611 policy::SchemaRegistryServiceFactory::GetForContext(
612 Profile::FromWebUI(web_ui())->GetOriginalProfile())->registry();
613 registry->AddObserver(this);
615 web_ui()->RegisterMessageCallback(
616 "initialized",
617 base::Bind(&PolicyUIHandler::HandleInitialized, base::Unretained(this)));
618 web_ui()->RegisterMessageCallback(
619 "reloadPolicies",
620 base::Bind(&PolicyUIHandler::HandleReloadPolicies,
621 base::Unretained(this)));
624 #if defined(ENABLE_EXTENSIONS)
625 void PolicyUIHandler::OnExtensionLoaded(
626 content::BrowserContext* browser_context,
627 const extensions::Extension* extension) {
628 SendPolicyNames();
629 SendPolicyValues();
632 void PolicyUIHandler::OnExtensionUnloaded(
633 content::BrowserContext* browser_context,
634 const extensions::Extension* extension,
635 extensions::UnloadedExtensionInfo::Reason reason) {
636 SendPolicyNames();
637 SendPolicyValues();
639 #endif
641 void PolicyUIHandler::OnSchemaRegistryUpdated(bool has_new_schemas) {
642 // Update UI when new schema is added.
643 if (has_new_schemas) {
644 SendPolicyNames();
645 SendPolicyValues();
649 void PolicyUIHandler::OnPolicyUpdated(const policy::PolicyNamespace& ns,
650 const policy::PolicyMap& previous,
651 const policy::PolicyMap& current) {
652 SendPolicyValues();
655 void PolicyUIHandler::SendPolicyNames() const {
656 base::DictionaryValue names;
658 Profile* profile = Profile::FromWebUI(web_ui());
659 policy::SchemaRegistry* registry =
660 policy::SchemaRegistryServiceFactory::GetForContext(
661 profile->GetOriginalProfile())->registry();
662 scoped_refptr<policy::SchemaMap> schema_map = registry->schema_map();
664 // Add Chrome policy names.
665 base::DictionaryValue* chrome_policy_names = new base::DictionaryValue;
666 policy::PolicyNamespace chrome_ns(policy::POLICY_DOMAIN_CHROME, "");
667 const policy::Schema* chrome_schema = schema_map->GetSchema(chrome_ns);
668 for (policy::Schema::Iterator it = chrome_schema->GetPropertiesIterator();
669 !it.IsAtEnd(); it.Advance()) {
670 chrome_policy_names->SetBoolean(it.key(), true);
672 names.Set("chromePolicyNames", chrome_policy_names);
674 #if defined(ENABLE_EXTENSIONS)
675 // Add extension policy names.
676 base::DictionaryValue* extension_policy_names = new base::DictionaryValue;
678 for (const scoped_refptr<const extensions::Extension>& extension :
679 extensions::ExtensionRegistry::Get(profile)->enabled_extensions()) {
680 // Skip this extension if it's not an enterprise extension.
681 if (!extension->manifest()->HasPath(
682 extensions::manifest_keys::kStorageManagedSchema))
683 continue;
684 base::DictionaryValue* extension_value = new base::DictionaryValue;
685 extension_value->SetString("name", extension->name());
686 const policy::Schema* schema =
687 schema_map->GetSchema(policy::PolicyNamespace(
688 policy::POLICY_DOMAIN_EXTENSIONS, extension->id()));
689 base::DictionaryValue* policy_names = new base::DictionaryValue;
690 if (schema && schema->valid()) {
691 // Get policy names from the extension's policy schema.
692 // Store in a map, not an array, for faster lookup on JS side.
693 for (policy::Schema::Iterator prop = schema->GetPropertiesIterator();
694 !prop.IsAtEnd(); prop.Advance()) {
695 policy_names->SetBoolean(prop.key(), true);
698 extension_value->Set("policyNames", policy_names);
699 extension_policy_names->Set(extension->id(), extension_value);
701 names.Set("extensionPolicyNames", extension_policy_names);
702 #endif // defined(ENABLE_EXTENSIONS)
704 web_ui()->CallJavascriptFunction("policy.Page.setPolicyNames", names);
707 void PolicyUIHandler::SendPolicyValues() const {
708 base::DictionaryValue all_policies;
710 // Add Chrome policy values.
711 base::DictionaryValue* chrome_policies = new base::DictionaryValue;
712 GetChromePolicyValues(chrome_policies);
713 all_policies.Set("chromePolicies", chrome_policies);
715 #if defined(ENABLE_EXTENSIONS)
716 // Add extension policy values.
717 extensions::ExtensionRegistry* registry =
718 extensions::ExtensionRegistry::Get(Profile::FromWebUI(web_ui()));
719 base::DictionaryValue* extension_values = new base::DictionaryValue;
721 for (const scoped_refptr<const extensions::Extension>& extension :
722 registry->enabled_extensions()) {
723 // Skip this extension if it's not an enterprise extension.
724 if (!extension->manifest()->HasPath(
725 extensions::manifest_keys::kStorageManagedSchema))
726 continue;
727 base::DictionaryValue* extension_policies = new base::DictionaryValue;
728 policy::PolicyNamespace policy_namespace = policy::PolicyNamespace(
729 policy::POLICY_DOMAIN_EXTENSIONS, extension->id());
730 policy::PolicyErrorMap empty_error_map;
731 GetPolicyValues(GetPolicyService()->GetPolicies(policy_namespace),
732 &empty_error_map, extension_policies);
733 extension_values->Set(extension->id(), extension_policies);
735 all_policies.Set("extensionPolicies", extension_values);
736 #endif
737 web_ui()->CallJavascriptFunction("policy.Page.setPolicyValues", all_policies);
740 void PolicyUIHandler::GetPolicyValues(const policy::PolicyMap& map,
741 policy::PolicyErrorMap* errors,
742 base::DictionaryValue* values) const {
743 for (policy::PolicyMap::const_iterator entry = map.begin();
744 entry != map.end(); ++entry) {
745 base::DictionaryValue* value = new base::DictionaryValue;
746 value->Set("value", CopyAndConvert(entry->second.value).release());
747 if (entry->second.scope == policy::POLICY_SCOPE_USER)
748 value->SetString("scope", "user");
749 else
750 value->SetString("scope", "machine");
751 if (entry->second.level == policy::POLICY_LEVEL_RECOMMENDED)
752 value->SetString("level", "recommended");
753 else
754 value->SetString("level", "mandatory");
755 base::string16 error = errors->GetErrors(entry->first);
756 if (!error.empty())
757 value->SetString("error", error);
758 values->Set(entry->first, value);
762 void PolicyUIHandler::GetChromePolicyValues(
763 base::DictionaryValue* values) const {
764 policy::PolicyService* policy_service = GetPolicyService();
765 policy::PolicyMap map;
767 // Make a copy that can be modified, since some policy values are modified
768 // before being displayed.
769 map.CopyFrom(policy_service->GetPolicies(
770 policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string())));
772 // Get a list of all the errors in the policy values.
773 const policy::ConfigurationPolicyHandlerList* handler_list =
774 g_browser_process->browser_policy_connector()->GetHandlerList();
775 policy::PolicyErrorMap errors;
776 handler_list->ApplyPolicySettings(map, NULL, &errors);
778 // Convert dictionary values to strings for display.
779 handler_list->PrepareForDisplaying(&map);
781 GetPolicyValues(map, &errors, values);
784 void PolicyUIHandler::SendStatus() const {
785 scoped_ptr<base::DictionaryValue> device_status(new base::DictionaryValue);
786 device_status_provider_->GetStatus(device_status.get());
787 if (!device_domain_.empty())
788 device_status->SetString("domain", device_domain_);
789 scoped_ptr<base::DictionaryValue> user_status(new base::DictionaryValue);
790 user_status_provider_->GetStatus(user_status.get());
791 std::string username;
792 user_status->GetString("username", &username);
793 if (!username.empty())
794 user_status->SetString("domain", gaia::ExtractDomainName(username));
796 base::DictionaryValue status;
797 if (!device_status->empty())
798 status.Set("device", device_status.release());
799 if (!user_status->empty())
800 status.Set("user", user_status.release());
802 web_ui()->CallJavascriptFunction("policy.Page.setStatus", status);
805 void PolicyUIHandler::HandleInitialized(const base::ListValue* args) {
806 SendPolicyNames();
807 SendPolicyValues();
808 SendStatus();
811 void PolicyUIHandler::HandleReloadPolicies(const base::ListValue* args) {
812 #if defined(OS_CHROMEOS)
813 // Allow user to manually fetch remote commands, in case invalidation
814 // service is not working properly.
815 // TODO(binjin): evaluate and possibly remove this after invalidation
816 // service is landed and tested. http://crbug.com/480982
817 policy::BrowserPolicyConnectorChromeOS* connector =
818 g_browser_process->platform_part()->browser_policy_connector_chromeos();
819 policy::RemoteCommandsService* remote_commands_service =
820 connector->GetDeviceCloudPolicyManager()
821 ->core()
822 ->remote_commands_service();
823 if (remote_commands_service)
824 remote_commands_service->FetchRemoteCommands();
825 #endif
826 GetPolicyService()->RefreshPolicies(base::Bind(
827 &PolicyUIHandler::OnRefreshPoliciesDone, weak_factory_.GetWeakPtr()));
830 void PolicyUIHandler::OnRefreshPoliciesDone() const {
831 web_ui()->CallJavascriptFunction("policy.Page.reloadPoliciesDone");
834 policy::PolicyService* PolicyUIHandler::GetPolicyService() const {
835 return policy::ProfilePolicyConnectorFactory::GetForBrowserContext(
836 web_ui()->GetWebContents()->GetBrowserContext())->policy_service();
839 PolicyUI::PolicyUI(content::WebUI* web_ui) : WebUIController(web_ui) {
840 web_ui->AddMessageHandler(new PolicyUIHandler);
841 content::WebUIDataSource::Add(Profile::FromWebUI(web_ui),
842 CreatePolicyUIHTMLSource());
845 PolicyUI::~PolicyUI() {