Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / ui / webui / policy_ui.cc
blob4077d2d327e0a9376131dc251dcfc3c920bc1bd7
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/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_contents.h"
47 #include "content/public/browser/web_ui.h"
48 #include "content/public/browser/web_ui_data_source.h"
49 #include "content/public/browser/web_ui_message_handler.h"
50 #include "google_apis/gaia/gaia_auth_util.h"
51 #include "grit/browser_resources.h"
52 #include "grit/components_strings.h"
53 #include "policy/policy_constants.h"
54 #include "policy/proto/device_management_backend.pb.h"
55 #include "ui/base/l10n/l10n_util.h"
56 #include "ui/base/l10n/time_format.h"
58 #if defined(OS_CHROMEOS)
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 #include "components/user_manager/user_manager.h"
65 #else
66 #include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
67 #include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
68 #endif
70 #if defined(ENABLE_EXTENSIONS)
71 #include "extensions/browser/extension_registry.h"
72 #include "extensions/common/extension.h"
73 #include "extensions/common/extension_set.h"
74 #include "extensions/common/manifest.h"
75 #include "extensions/common/manifest_constants.h"
76 #endif
78 namespace em = enterprise_management;
80 namespace {
82 content::WebUIDataSource* CreatePolicyUIHTMLSource() {
83 content::WebUIDataSource* source =
84 content::WebUIDataSource::Create(chrome::kChromeUIPolicyHost);
86 // Localized strings.
87 source->AddLocalizedString("title", IDS_POLICY_TITLE);
88 source->AddLocalizedString("filterPlaceholder",
89 IDS_POLICY_FILTER_PLACEHOLDER);
90 source->AddLocalizedString("reloadPolicies", IDS_POLICY_RELOAD_POLICIES);
91 source->AddLocalizedString("status", IDS_POLICY_STATUS);
92 source->AddLocalizedString("statusDevice", IDS_POLICY_STATUS_DEVICE);
93 source->AddLocalizedString("statusUser", IDS_POLICY_STATUS_USER);
94 source->AddLocalizedString("labelDomain", IDS_POLICY_LABEL_DOMAIN);
95 source->AddLocalizedString("labelUsername", IDS_POLICY_LABEL_USERNAME);
96 source->AddLocalizedString("labelClientId", IDS_POLICY_LABEL_CLIENT_ID);
97 source->AddLocalizedString("labelTimeSinceLastRefresh",
98 IDS_POLICY_LABEL_TIME_SINCE_LAST_REFRESH);
99 source->AddLocalizedString("labelRefreshInterval",
100 IDS_POLICY_LABEL_REFRESH_INTERVAL);
101 source->AddLocalizedString("labelStatus", IDS_POLICY_LABEL_STATUS);
102 source->AddLocalizedString("showUnset", IDS_POLICY_SHOW_UNSET);
103 source->AddLocalizedString("noPoliciesSet", IDS_POLICY_NO_POLICIES_SET);
104 source->AddLocalizedString("headerScope", IDS_POLICY_HEADER_SCOPE);
105 source->AddLocalizedString("headerLevel", IDS_POLICY_HEADER_LEVEL);
106 source->AddLocalizedString("headerName", IDS_POLICY_HEADER_NAME);
107 source->AddLocalizedString("headerValue", IDS_POLICY_HEADER_VALUE);
108 source->AddLocalizedString("headerStatus", IDS_POLICY_HEADER_STATUS);
109 source->AddLocalizedString("showExpandedValue",
110 IDS_POLICY_SHOW_EXPANDED_VALUE);
111 source->AddLocalizedString("hideExpandedValue",
112 IDS_POLICY_HIDE_EXPANDED_VALUE);
113 source->AddLocalizedString("scopeUser", IDS_POLICY_SCOPE_USER);
114 source->AddLocalizedString("scopeDevice", IDS_POLICY_SCOPE_DEVICE);
115 source->AddLocalizedString("levelRecommended", IDS_POLICY_LEVEL_RECOMMENDED);
116 source->AddLocalizedString("levelMandatory", IDS_POLICY_LEVEL_MANDATORY);
117 source->AddLocalizedString("ok", IDS_POLICY_OK);
118 source->AddLocalizedString("unset", IDS_POLICY_UNSET);
119 source->AddLocalizedString("unknown", IDS_POLICY_UNKNOWN);
121 source->SetJsonPath("strings.js");
123 // Add required resources.
124 source->AddResourcePath("policy.css", IDR_POLICY_CSS);
125 source->AddResourcePath("policy.js", IDR_POLICY_JS);
126 source->AddResourcePath("uber_utils.js", IDR_UBER_UTILS_JS);
127 source->SetDefaultResource(IDR_POLICY_HTML);
129 return source;
132 // Formats the association state indicated by |data|. If |data| is NULL, the
133 // state is considered to be UNMANAGED.
134 base::string16 FormatAssociationState(const em::PolicyData* data) {
135 if (data) {
136 switch (data->state()) {
137 case em::PolicyData::ACTIVE:
138 return l10n_util::GetStringUTF16(IDS_POLICY_ASSOCIATION_STATE_ACTIVE);
139 case em::PolicyData::UNMANAGED:
140 return l10n_util::GetStringUTF16(
141 IDS_POLICY_ASSOCIATION_STATE_UNMANAGED);
142 case em::PolicyData::DEPROVISIONED:
143 return l10n_util::GetStringUTF16(
144 IDS_POLICY_ASSOCIATION_STATE_DEPROVISIONED);
146 NOTREACHED() << "Unknown state " << data->state();
149 // Default to UNMANAGED for the case of missing policy or bad state enum.
150 return l10n_util::GetStringUTF16(IDS_POLICY_ASSOCIATION_STATE_UNMANAGED);
153 void GetStatusFromCore(const policy::CloudPolicyCore* core,
154 base::DictionaryValue* dict) {
155 const policy::CloudPolicyStore* store = core->store();
156 const policy::CloudPolicyClient* client = core->client();
157 const policy::CloudPolicyRefreshScheduler* refresh_scheduler =
158 core->refresh_scheduler();
160 // CloudPolicyStore errors take precedence to show in the status message.
161 // Other errors (such as transient policy fetching problems) get displayed
162 // only if CloudPolicyStore is in STATUS_OK.
163 base::string16 status =
164 policy::FormatStoreStatus(store->status(), store->validation_status());
165 if (store->status() == policy::CloudPolicyStore::STATUS_OK) {
166 if (client && client->status() != policy::DM_STATUS_SUCCESS)
167 status = policy::FormatDeviceManagementStatus(client->status());
168 else if (!store->is_managed())
169 status = FormatAssociationState(store->policy());
172 const em::PolicyData* policy = store->policy();
173 std::string client_id = policy ? policy->device_id() : std::string();
174 std::string username = policy ? policy->username() : std::string();
175 base::TimeDelta refresh_interval =
176 base::TimeDelta::FromMilliseconds(refresh_scheduler ?
177 refresh_scheduler->refresh_delay() :
178 policy::CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs);
179 base::Time last_refresh_time = refresh_scheduler ?
180 refresh_scheduler->last_refresh() : base::Time();
182 bool no_error = store->status() == policy::CloudPolicyStore::STATUS_OK &&
183 client && client->status() == policy::DM_STATUS_SUCCESS;
184 dict->SetBoolean("error", !no_error);
185 dict->SetString("status", status);
186 dict->SetString("clientId", client_id);
187 dict->SetString("username", username);
188 dict->SetString("refreshInterval",
189 ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_DURATION,
190 ui::TimeFormat::LENGTH_SHORT,
191 refresh_interval));
192 dict->SetString("timeSinceLastRefresh", last_refresh_time.is_null() ?
193 l10n_util::GetStringUTF16(IDS_POLICY_NEVER_FETCHED) :
194 ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_ELAPSED,
195 ui::TimeFormat::LENGTH_SHORT,
196 base::Time::NowFromSystemTime() -
197 last_refresh_time));
200 void ExtractDomainFromUsername(base::DictionaryValue* dict) {
201 std::string username;
202 dict->GetString("username", &username);
203 if (!username.empty())
204 dict->SetString("domain", gaia::ExtractDomainName(username));
207 // Utility function that returns a JSON serialization of the given |dict|.
208 scoped_ptr<base::StringValue> DictionaryToJSONString(
209 const base::DictionaryValue* dict) {
210 std::string json_string;
211 base::JSONWriter::WriteWithOptions(dict,
212 base::JSONWriter::OPTIONS_PRETTY_PRINT,
213 &json_string);
214 return make_scoped_ptr(new base::StringValue(json_string));
217 // Returns a copy of |value| with some values converted to a representation that
218 // i18n_template.js will display in a nicer way.
219 scoped_ptr<base::Value> CopyAndConvert(const base::Value* value) {
220 const base::DictionaryValue* dict = NULL;
221 if (value->GetAsDictionary(&dict))
222 return DictionaryToJSONString(dict);
224 scoped_ptr<base::Value> copy(value->DeepCopy());
225 base::ListValue* list = NULL;
226 if (copy->GetAsList(&list)) {
227 for (size_t i = 0; i < list->GetSize(); ++i) {
228 if (list->GetDictionary(i, &dict))
229 list->Set(i, DictionaryToJSONString(dict).release());
233 return copy.Pass();
236 } // namespace
238 // An interface for querying the status of cloud policy.
239 class CloudPolicyStatusProvider {
240 public:
241 CloudPolicyStatusProvider();
242 virtual ~CloudPolicyStatusProvider();
244 // Sets a callback to invoke upon status changes.
245 void SetStatusChangeCallback(const base::Closure& callback);
247 virtual void GetStatus(base::DictionaryValue* dict);
249 protected:
250 void NotifyStatusChange();
252 private:
253 base::Closure callback_;
255 DISALLOW_COPY_AND_ASSIGN(CloudPolicyStatusProvider);
258 // Status provider implementation that pulls cloud policy status from a
259 // CloudPolicyCore instance provided at construction time. Also listens for
260 // changes on that CloudPolicyCore and reports them through the status change
261 // callback.
262 class CloudPolicyCoreStatusProvider
263 : public CloudPolicyStatusProvider,
264 public policy::CloudPolicyStore::Observer {
265 public:
266 explicit CloudPolicyCoreStatusProvider(policy::CloudPolicyCore* core);
267 ~CloudPolicyCoreStatusProvider() override;
269 // policy::CloudPolicyStore::Observer implementation.
270 void OnStoreLoaded(policy::CloudPolicyStore* store) override;
271 void OnStoreError(policy::CloudPolicyStore* store) override;
273 protected:
274 // Policy status is read from the CloudPolicyClient, CloudPolicyStore and
275 // CloudPolicyRefreshScheduler hosted by this |core_|.
276 policy::CloudPolicyCore* core_;
278 private:
279 DISALLOW_COPY_AND_ASSIGN(CloudPolicyCoreStatusProvider);
282 // A cloud policy status provider for user policy.
283 class UserPolicyStatusProvider : public CloudPolicyCoreStatusProvider {
284 public:
285 explicit UserPolicyStatusProvider(policy::CloudPolicyCore* core);
286 ~UserPolicyStatusProvider() override;
288 // CloudPolicyCoreStatusProvider implementation.
289 void GetStatus(base::DictionaryValue* dict) override;
291 private:
292 DISALLOW_COPY_AND_ASSIGN(UserPolicyStatusProvider);
295 #if defined(OS_CHROMEOS)
296 // A cloud policy status provider for device policy.
297 class DevicePolicyStatusProvider : public CloudPolicyCoreStatusProvider {
298 public:
299 explicit DevicePolicyStatusProvider(
300 policy::BrowserPolicyConnectorChromeOS* connector);
301 ~DevicePolicyStatusProvider() override;
303 // CloudPolicyCoreStatusProvider implementation.
304 void GetStatus(base::DictionaryValue* dict) override;
306 private:
307 std::string domain_;
309 DISALLOW_COPY_AND_ASSIGN(DevicePolicyStatusProvider);
312 // A cloud policy status provider that reads policy status from the policy core
313 // associated with the device-local account specified by |user_id| at
314 // construction time. The indirection via user ID and
315 // DeviceLocalAccountPolicyService is necessary because the device-local account
316 // may go away any time behind the scenes, at which point the status message
317 // text will indicate CloudPolicyStore::STATUS_BAD_STATE.
318 class DeviceLocalAccountPolicyStatusProvider
319 : public CloudPolicyStatusProvider,
320 public policy::DeviceLocalAccountPolicyService::Observer {
321 public:
322 DeviceLocalAccountPolicyStatusProvider(
323 const std::string& user_id,
324 policy::DeviceLocalAccountPolicyService* service);
325 ~DeviceLocalAccountPolicyStatusProvider() override;
327 // CloudPolicyStatusProvider implementation.
328 void GetStatus(base::DictionaryValue* dict) override;
330 // policy::DeviceLocalAccountPolicyService::Observer implementation.
331 void OnPolicyUpdated(const std::string& user_id) override;
332 void OnDeviceLocalAccountsChanged() override;
334 private:
335 const std::string user_id_;
336 policy::DeviceLocalAccountPolicyService* service_;
338 DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountPolicyStatusProvider);
340 #endif
342 // The JavaScript message handler for the chrome://policy page.
343 class PolicyUIHandler : public content::NotificationObserver,
344 public content::WebUIMessageHandler,
345 public policy::PolicyService::Observer,
346 public policy::SchemaRegistry::Observer {
347 public:
348 PolicyUIHandler();
349 ~PolicyUIHandler() override;
351 // content::NotificationObserver implementation.
352 void Observe(int type,
353 const content::NotificationSource& source,
354 const content::NotificationDetails& details) override;
356 // content::WebUIMessageHandler implementation.
357 void RegisterMessages() override;
359 // policy::PolicyService::Observer implementation.
360 void OnPolicyUpdated(const policy::PolicyNamespace& ns,
361 const policy::PolicyMap& previous,
362 const policy::PolicyMap& current) override;
364 // policy::SchemaRegistry::Observer implementation.
365 void OnSchemaRegistryReady() override;
366 void OnSchemaRegistryUpdated(bool has_new_schemas) override;
368 private:
369 // Send a dictionary containing the names of all known policies to the UI.
370 void SendPolicyNames() const;
372 // Send information about the current policy values to the UI. For each policy
373 // whose value has been set, a dictionary containing the value and additional
374 // metadata is sent.
375 void SendPolicyValues() const;
377 // Send the status of cloud policy to the UI. For each scope that has cloud
378 // policy enabled (device and/or user), a dictionary containing status
379 // information is sent.
380 void SendStatus() const;
382 // Inserts a description of each policy in |policy_map| into |values|, using
383 // the optional errors in |errors| to determine the status of each policy.
384 void GetPolicyValues(const policy::PolicyMap& policy_map,
385 policy::PolicyErrorMap* errors,
386 base::DictionaryValue* values) const;
388 void GetChromePolicyValues(base::DictionaryValue* values) const;
390 void HandleInitialized(const base::ListValue* args);
391 void HandleReloadPolicies(const base::ListValue* args);
393 void OnRefreshPoliciesDone() const;
395 policy::PolicyService* GetPolicyService() const;
397 bool initialized_;
398 std::string device_domain_;
400 // Providers that supply status dictionaries for user and device policy,
401 // respectively. These are created on initialization time as appropriate for
402 // the platform (Chrome OS / desktop) and type of policy that is in effect.
403 scoped_ptr<CloudPolicyStatusProvider> user_status_provider_;
404 scoped_ptr<CloudPolicyStatusProvider> device_status_provider_;
406 #if defined(ENABLE_EXTENSIONS)
407 content::NotificationRegistrar registrar_;
408 #endif
410 base::WeakPtrFactory<PolicyUIHandler> weak_factory_;
412 DISALLOW_COPY_AND_ASSIGN(PolicyUIHandler);
415 CloudPolicyStatusProvider::CloudPolicyStatusProvider() {
418 CloudPolicyStatusProvider::~CloudPolicyStatusProvider() {
421 void CloudPolicyStatusProvider::SetStatusChangeCallback(
422 const base::Closure& callback) {
423 callback_ = callback;
426 void CloudPolicyStatusProvider::GetStatus(base::DictionaryValue* dict) {
429 void CloudPolicyStatusProvider::NotifyStatusChange() {
430 if (!callback_.is_null())
431 callback_.Run();
434 CloudPolicyCoreStatusProvider::CloudPolicyCoreStatusProvider(
435 policy::CloudPolicyCore* core) : core_(core) {
436 core_->store()->AddObserver(this);
437 // TODO(bartfab): Add an observer that watches for client errors. Observing
438 // core_->client() directly is not safe as the client may be destroyed and
439 // (re-)created anytime if the user signs in or out on desktop platforms.
442 CloudPolicyCoreStatusProvider::~CloudPolicyCoreStatusProvider() {
443 core_->store()->RemoveObserver(this);
446 void CloudPolicyCoreStatusProvider::OnStoreLoaded(
447 policy::CloudPolicyStore* store) {
448 NotifyStatusChange();
451 void CloudPolicyCoreStatusProvider::OnStoreError(
452 policy::CloudPolicyStore* store) {
453 NotifyStatusChange();
456 UserPolicyStatusProvider::UserPolicyStatusProvider(
457 policy::CloudPolicyCore* core) : CloudPolicyCoreStatusProvider(core) {
460 UserPolicyStatusProvider::~UserPolicyStatusProvider() {
463 void UserPolicyStatusProvider::GetStatus(base::DictionaryValue* dict) {
464 if (!core_->store()->is_managed())
465 return;
466 GetStatusFromCore(core_, dict);
467 ExtractDomainFromUsername(dict);
470 #if defined(OS_CHROMEOS)
471 DevicePolicyStatusProvider::DevicePolicyStatusProvider(
472 policy::BrowserPolicyConnectorChromeOS* connector)
473 : CloudPolicyCoreStatusProvider(
474 connector->GetDeviceCloudPolicyManager()->core()) {
475 domain_ = connector->GetEnterpriseDomain();
478 DevicePolicyStatusProvider::~DevicePolicyStatusProvider() {
481 void DevicePolicyStatusProvider::GetStatus(base::DictionaryValue* dict) {
482 GetStatusFromCore(core_, dict);
483 dict->SetString("domain", domain_);
486 DeviceLocalAccountPolicyStatusProvider::DeviceLocalAccountPolicyStatusProvider(
487 const std::string& user_id,
488 policy::DeviceLocalAccountPolicyService* service)
489 : user_id_(user_id),
490 service_(service) {
491 service_->AddObserver(this);
494 DeviceLocalAccountPolicyStatusProvider::
495 ~DeviceLocalAccountPolicyStatusProvider() {
496 service_->RemoveObserver(this);
499 void DeviceLocalAccountPolicyStatusProvider::GetStatus(
500 base::DictionaryValue* dict) {
501 const policy::DeviceLocalAccountPolicyBroker* broker =
502 service_->GetBrokerForUser(user_id_);
503 if (broker) {
504 GetStatusFromCore(broker->core(), dict);
505 } else {
506 dict->SetBoolean("error", true);
507 dict->SetString("status",
508 policy::FormatStoreStatus(
509 policy::CloudPolicyStore::STATUS_BAD_STATE,
510 policy::CloudPolicyValidatorBase::VALIDATION_OK));
511 dict->SetString("username", std::string());
513 ExtractDomainFromUsername(dict);
514 dict->SetBoolean("publicAccount", true);
517 void DeviceLocalAccountPolicyStatusProvider::OnPolicyUpdated(
518 const std::string& user_id) {
519 if (user_id == user_id_)
520 NotifyStatusChange();
523 void DeviceLocalAccountPolicyStatusProvider::OnDeviceLocalAccountsChanged() {
524 NotifyStatusChange();
526 #endif
528 PolicyUIHandler::PolicyUIHandler()
529 : initialized_(false),
530 weak_factory_(this) {
533 PolicyUIHandler::~PolicyUIHandler() {
534 GetPolicyService()->RemoveObserver(policy::POLICY_DOMAIN_CHROME, this);
535 GetPolicyService()->RemoveObserver(policy::POLICY_DOMAIN_EXTENSIONS, this);
536 policy::SchemaRegistry* registry =
537 policy::SchemaRegistryServiceFactory::GetForContext(
538 Profile::FromWebUI(web_ui())->GetOriginalProfile())->registry();
539 registry->RemoveObserver(this);
542 void PolicyUIHandler::RegisterMessages() {
543 #if defined(OS_CHROMEOS)
544 policy::BrowserPolicyConnectorChromeOS* connector =
545 g_browser_process->platform_part()->browser_policy_connector_chromeos();
546 if (connector->IsEnterpriseManaged())
547 device_status_provider_.reset(new DevicePolicyStatusProvider(connector));
549 const user_manager::UserManager* user_manager =
550 user_manager::UserManager::Get();
551 if (user_manager->IsLoggedInAsPublicAccount()) {
552 policy::DeviceLocalAccountPolicyService* local_account_service =
553 connector->GetDeviceLocalAccountPolicyService();
554 if (local_account_service) {
555 user_status_provider_.reset(
556 new DeviceLocalAccountPolicyStatusProvider(
557 user_manager->GetLoggedInUser()->email(), local_account_service));
559 } else {
560 policy::UserCloudPolicyManagerChromeOS* user_cloud_policy_manager =
561 policy::UserCloudPolicyManagerFactoryChromeOS::GetForProfile(
562 Profile::FromWebUI(web_ui()));
563 if (user_cloud_policy_manager) {
564 user_status_provider_.reset(
565 new UserPolicyStatusProvider(user_cloud_policy_manager->core()));
568 #else
569 policy::UserCloudPolicyManager* user_cloud_policy_manager =
570 policy::UserCloudPolicyManagerFactory::GetForBrowserContext(
571 web_ui()->GetWebContents()->GetBrowserContext());
572 if (user_cloud_policy_manager) {
573 user_status_provider_.reset(
574 new UserPolicyStatusProvider(user_cloud_policy_manager->core()));
576 #endif
578 if (!user_status_provider_.get())
579 user_status_provider_.reset(new CloudPolicyStatusProvider());
580 if (!device_status_provider_.get())
581 device_status_provider_.reset(new CloudPolicyStatusProvider());
583 base::Closure update_callback(base::Bind(&PolicyUIHandler::SendStatus,
584 base::Unretained(this)));
585 user_status_provider_->SetStatusChangeCallback(update_callback);
586 device_status_provider_->SetStatusChangeCallback(update_callback);
587 GetPolicyService()->AddObserver(policy::POLICY_DOMAIN_CHROME, this);
588 GetPolicyService()->AddObserver(policy::POLICY_DOMAIN_EXTENSIONS, this);
590 #if defined(ENABLE_EXTENSIONS)
591 registrar_.Add(this,
592 extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
593 content::NotificationService::AllSources());
594 registrar_.Add(this,
595 extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
596 content::NotificationService::AllSources());
597 #endif
598 policy::SchemaRegistry* registry =
599 policy::SchemaRegistryServiceFactory::GetForContext(
600 Profile::FromWebUI(web_ui())->GetOriginalProfile())->registry();
601 registry->AddObserver(this);
603 web_ui()->RegisterMessageCallback(
604 "initialized",
605 base::Bind(&PolicyUIHandler::HandleInitialized, base::Unretained(this)));
606 web_ui()->RegisterMessageCallback(
607 "reloadPolicies",
608 base::Bind(&PolicyUIHandler::HandleReloadPolicies,
609 base::Unretained(this)));
612 void PolicyUIHandler::Observe(int type,
613 const content::NotificationSource& source,
614 const content::NotificationDetails& details) {
615 #if defined(ENABLE_EXTENSIONS)
616 DCHECK(type == extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED ||
617 type == extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED);
618 SendPolicyNames();
619 SendPolicyValues();
620 #endif
623 // TODO(limasdf): Add default implementation and remove this override.
624 void PolicyUIHandler::OnSchemaRegistryReady() {
627 void PolicyUIHandler::OnSchemaRegistryUpdated(bool has_new_schemas) {
628 // Update UI when new schema is added.
629 if (has_new_schemas) {
630 SendPolicyNames();
631 SendPolicyValues();
635 void PolicyUIHandler::OnPolicyUpdated(const policy::PolicyNamespace& ns,
636 const policy::PolicyMap& previous,
637 const policy::PolicyMap& current) {
638 SendPolicyValues();
641 void PolicyUIHandler::SendPolicyNames() const {
642 base::DictionaryValue names;
644 Profile* profile = Profile::FromWebUI(web_ui());
645 policy::SchemaRegistry* registry =
646 policy::SchemaRegistryServiceFactory::GetForContext(
647 profile->GetOriginalProfile())->registry();
648 scoped_refptr<policy::SchemaMap> schema_map = registry->schema_map();
650 // Add Chrome policy names.
651 base::DictionaryValue* chrome_policy_names = new base::DictionaryValue;
652 policy::PolicyNamespace chrome_ns(policy::POLICY_DOMAIN_CHROME, "");
653 const policy::Schema* chrome_schema = schema_map->GetSchema(chrome_ns);
654 for (policy::Schema::Iterator it = chrome_schema->GetPropertiesIterator();
655 !it.IsAtEnd(); it.Advance()) {
656 chrome_policy_names->SetBoolean(it.key(), true);
658 names.Set("chromePolicyNames", chrome_policy_names);
660 #if defined(ENABLE_EXTENSIONS)
661 // Add extension policy names.
662 base::DictionaryValue* extension_policy_names = new base::DictionaryValue;
664 for (const scoped_refptr<const extensions::Extension>& extension :
665 extensions::ExtensionRegistry::Get(profile)->enabled_extensions()) {
666 // Skip this extension if it's not an enterprise extension.
667 if (!extension->manifest()->HasPath(
668 extensions::manifest_keys::kStorageManagedSchema))
669 continue;
670 base::DictionaryValue* extension_value = new base::DictionaryValue;
671 extension_value->SetString("name", extension->name());
672 const policy::Schema* schema =
673 schema_map->GetSchema(policy::PolicyNamespace(
674 policy::POLICY_DOMAIN_EXTENSIONS, extension->id()));
675 base::DictionaryValue* policy_names = new base::DictionaryValue;
676 if (schema && schema->valid()) {
677 // Get policy names from the extension's policy schema.
678 // Store in a map, not an array, for faster lookup on JS side.
679 for (policy::Schema::Iterator prop = schema->GetPropertiesIterator();
680 !prop.IsAtEnd(); prop.Advance()) {
681 policy_names->SetBoolean(prop.key(), true);
684 extension_value->Set("policyNames", policy_names);
685 extension_policy_names->Set(extension->id(), extension_value);
687 names.Set("extensionPolicyNames", extension_policy_names);
688 #endif // defined(ENABLE_EXTENSIONS)
690 web_ui()->CallJavascriptFunction("policy.Page.setPolicyNames", names);
693 void PolicyUIHandler::SendPolicyValues() const {
694 base::DictionaryValue all_policies;
696 // Add Chrome policy values.
697 base::DictionaryValue* chrome_policies = new base::DictionaryValue;
698 GetChromePolicyValues(chrome_policies);
699 all_policies.Set("chromePolicies", chrome_policies);
701 #if defined(ENABLE_EXTENSIONS)
702 // Add extension policy values.
703 extensions::ExtensionRegistry* registry =
704 extensions::ExtensionRegistry::Get(Profile::FromWebUI(web_ui()));
705 base::DictionaryValue* extension_values = new base::DictionaryValue;
707 for (const scoped_refptr<const extensions::Extension>& extension :
708 registry->enabled_extensions()) {
709 // Skip this extension if it's not an enterprise extension.
710 if (!extension->manifest()->HasPath(
711 extensions::manifest_keys::kStorageManagedSchema))
712 continue;
713 base::DictionaryValue* extension_policies = new base::DictionaryValue;
714 policy::PolicyNamespace policy_namespace = policy::PolicyNamespace(
715 policy::POLICY_DOMAIN_EXTENSIONS, extension->id());
716 policy::PolicyErrorMap empty_error_map;
717 GetPolicyValues(GetPolicyService()->GetPolicies(policy_namespace),
718 &empty_error_map, extension_policies);
719 extension_values->Set(extension->id(), extension_policies);
721 all_policies.Set("extensionPolicies", extension_values);
722 #endif
723 web_ui()->CallJavascriptFunction("policy.Page.setPolicyValues", all_policies);
726 void PolicyUIHandler::GetPolicyValues(const policy::PolicyMap& map,
727 policy::PolicyErrorMap* errors,
728 base::DictionaryValue* values) const {
729 for (policy::PolicyMap::const_iterator entry = map.begin();
730 entry != map.end(); ++entry) {
731 base::DictionaryValue* value = new base::DictionaryValue;
732 value->Set("value", CopyAndConvert(entry->second.value).release());
733 if (entry->second.scope == policy::POLICY_SCOPE_USER)
734 value->SetString("scope", "user");
735 else
736 value->SetString("scope", "machine");
737 if (entry->second.level == policy::POLICY_LEVEL_RECOMMENDED)
738 value->SetString("level", "recommended");
739 else
740 value->SetString("level", "mandatory");
741 base::string16 error = errors->GetErrors(entry->first);
742 if (!error.empty())
743 value->SetString("error", error);
744 values->Set(entry->first, value);
748 void PolicyUIHandler::GetChromePolicyValues(
749 base::DictionaryValue* values) const {
750 policy::PolicyService* policy_service = GetPolicyService();
751 policy::PolicyMap map;
753 // Make a copy that can be modified, since some policy values are modified
754 // before being displayed.
755 map.CopyFrom(policy_service->GetPolicies(
756 policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string())));
758 // Get a list of all the errors in the policy values.
759 const policy::ConfigurationPolicyHandlerList* handler_list =
760 g_browser_process->browser_policy_connector()->GetHandlerList();
761 policy::PolicyErrorMap errors;
762 handler_list->ApplyPolicySettings(map, NULL, &errors);
764 // Convert dictionary values to strings for display.
765 handler_list->PrepareForDisplaying(&map);
767 GetPolicyValues(map, &errors, values);
770 void PolicyUIHandler::SendStatus() const {
771 scoped_ptr<base::DictionaryValue> device_status(new base::DictionaryValue);
772 device_status_provider_->GetStatus(device_status.get());
773 if (!device_domain_.empty())
774 device_status->SetString("domain", device_domain_);
775 scoped_ptr<base::DictionaryValue> user_status(new base::DictionaryValue);
776 user_status_provider_->GetStatus(user_status.get());
777 std::string username;
778 user_status->GetString("username", &username);
779 if (!username.empty())
780 user_status->SetString("domain", gaia::ExtractDomainName(username));
782 base::DictionaryValue status;
783 if (!device_status->empty())
784 status.Set("device", device_status.release());
785 if (!user_status->empty())
786 status.Set("user", user_status.release());
788 web_ui()->CallJavascriptFunction("policy.Page.setStatus", status);
791 void PolicyUIHandler::HandleInitialized(const base::ListValue* args) {
792 SendPolicyNames();
793 SendPolicyValues();
794 SendStatus();
797 void PolicyUIHandler::HandleReloadPolicies(const base::ListValue* args) {
798 GetPolicyService()->RefreshPolicies(
799 base::Bind(&PolicyUIHandler::OnRefreshPoliciesDone,
800 weak_factory_.GetWeakPtr()));
803 void PolicyUIHandler::OnRefreshPoliciesDone() const {
804 web_ui()->CallJavascriptFunction("policy.Page.reloadPoliciesDone");
807 policy::PolicyService* PolicyUIHandler::GetPolicyService() const {
808 return policy::ProfilePolicyConnectorFactory::GetForBrowserContext(
809 web_ui()->GetWebContents()->GetBrowserContext())->policy_service();
812 PolicyUI::PolicyUI(content::WebUI* web_ui) : WebUIController(web_ui) {
813 web_ui->AddMessageHandler(new PolicyUIHandler);
814 content::WebUIDataSource::Add(Profile::FromWebUI(web_ui),
815 CreatePolicyUIHTMLSource());
818 PolicyUI::~PolicyUI() {