Vectorize sad tab image.
[chromium-blink-merge.git] / chrome / browser / ui / webui / policy_ui.cc
blob7c646e0d19260c0b6334bdd109a985c91ffc81bf
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 <stddef.h>
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/callback.h"
12 #include "base/compiler_specific.h"
13 #include "base/json/json_writer.h"
14 #include "base/logging.h"
15 #include "base/macros.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/strings/string16.h"
18 #include "base/time/time.h"
19 #include "base/values.h"
20 #include "chrome/browser/browser_process.h"
21 #include "chrome/browser/policy/profile_policy_connector.h"
22 #include "chrome/browser/policy/profile_policy_connector_factory.h"
23 #include "chrome/browser/policy/schema_registry_service.h"
24 #include "chrome/browser/policy/schema_registry_service_factory.h"
25 #include "chrome/browser/profiles/profile.h"
26 #include "chrome/common/url_constants.h"
27 #include "components/policy/core/browser/browser_policy_connector.h"
28 #include "components/policy/core/browser/cloud/message_util.h"
29 #include "components/policy/core/browser/configuration_policy_handler_list.h"
30 #include "components/policy/core/browser/policy_error_map.h"
31 #include "components/policy/core/common/cloud/cloud_policy_client.h"
32 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
33 #include "components/policy/core/common/cloud/cloud_policy_core.h"
34 #include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h"
35 #include "components/policy/core/common/cloud/cloud_policy_store.h"
36 #include "components/policy/core/common/cloud/cloud_policy_validator.h"
37 #include "components/policy/core/common/policy_map.h"
38 #include "components/policy/core/common/policy_namespace.h"
39 #include "components/policy/core/common/policy_service.h"
40 #include "components/policy/core/common/policy_types.h"
41 #include "components/policy/core/common/remote_commands/remote_commands_service.h"
42 #include "components/policy/core/common/schema.h"
43 #include "components/policy/core/common/schema_map.h"
44 #include "components/policy/core/common/schema_registry.h"
45 #include "content/public/browser/web_contents.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"
57 #if defined(OS_CHROMEOS)
58 #include "chrome/browser/browser_process_platform_part.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 #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/browser/extension_registry_observer.h"
73 #include "extensions/common/extension.h"
74 #include "extensions/common/manifest.h"
75 #include "extensions/common/manifest_constants.h"
76 #endif
78 namespace em = enterprise_management;
80 namespace {
82 struct PolicySourceMap {
83 const char* key;
84 int string_id;
87 // Strings that map from PolicySource enum to i18n string keys and their IDs.
88 const PolicySourceMap kPolicySources[policy::POLICY_SOURCE_COUNT] = {
89 {"sourceEnterpriseDefault", IDS_POLICY_SOURCE_ENTERPRISE_DEFAULT},
90 {"sourceCloud", IDS_POLICY_SOURCE_CLOUD},
91 {"sourceEnterpriseOverride", IDS_POLICY_SOURCE_ENTERPRISE_OVERRIDE},
92 {"sourcePlatform", IDS_POLICY_SOURCE_PLATFORM}
95 void AddLocalizedPoilcySourceStrings(content::WebUIDataSource* source) {
96 DCHECK_EQ(static_cast<size_t>(policy::POLICY_SOURCE_COUNT),
97 arraysize(kPolicySources));
98 for (size_t i = 0; i < arraysize(kPolicySources); ++i) {
99 source->AddLocalizedString(kPolicySources[i].key,
100 kPolicySources[i].string_id);
104 content::WebUIDataSource* CreatePolicyUIHTMLSource() {
105 content::WebUIDataSource* source =
106 content::WebUIDataSource::Create(chrome::kChromeUIPolicyHost);
108 // Localized strings.
109 source->AddLocalizedString("title", IDS_POLICY_TITLE);
110 source->AddLocalizedString("filterPlaceholder",
111 IDS_POLICY_FILTER_PLACEHOLDER);
112 source->AddLocalizedString("reloadPolicies", IDS_POLICY_RELOAD_POLICIES);
113 source->AddLocalizedString("status", IDS_POLICY_STATUS);
114 source->AddLocalizedString("statusDevice", IDS_POLICY_STATUS_DEVICE);
115 source->AddLocalizedString("statusUser", IDS_POLICY_STATUS_USER);
116 source->AddLocalizedString("labelDomain", IDS_POLICY_LABEL_DOMAIN);
117 source->AddLocalizedString("labelUsername", IDS_POLICY_LABEL_USERNAME);
118 source->AddLocalizedString("labelClientId", IDS_POLICY_LABEL_CLIENT_ID);
119 source->AddLocalizedString("labelAssetId", IDS_POLICY_LABEL_ASSET_ID);
120 source->AddLocalizedString("labelLocation", IDS_POLICY_LABEL_LOCATION);
121 source->AddLocalizedString("labelDirectoryApiId",
122 IDS_POLICY_LABEL_DIRECTORY_API_ID);
123 source->AddLocalizedString("labelTimeSinceLastRefresh",
124 IDS_POLICY_LABEL_TIME_SINCE_LAST_REFRESH);
125 source->AddLocalizedString("labelRefreshInterval",
126 IDS_POLICY_LABEL_REFRESH_INTERVAL);
127 source->AddLocalizedString("labelStatus", IDS_POLICY_LABEL_STATUS);
128 source->AddLocalizedString("showUnset", IDS_POLICY_SHOW_UNSET);
129 source->AddLocalizedString("noPoliciesSet", IDS_POLICY_NO_POLICIES_SET);
130 source->AddLocalizedString("headerScope", IDS_POLICY_HEADER_SCOPE);
131 source->AddLocalizedString("headerLevel", IDS_POLICY_HEADER_LEVEL);
132 source->AddLocalizedString("headerName", IDS_POLICY_HEADER_NAME);
133 source->AddLocalizedString("headerValue", IDS_POLICY_HEADER_VALUE);
134 source->AddLocalizedString("headerStatus", IDS_POLICY_HEADER_STATUS);
135 source->AddLocalizedString("headerSource", IDS_POLICY_HEADER_SOURCE);
136 source->AddLocalizedString("showExpandedValue",
137 IDS_POLICY_SHOW_EXPANDED_VALUE);
138 source->AddLocalizedString("hideExpandedValue",
139 IDS_POLICY_HIDE_EXPANDED_VALUE);
140 source->AddLocalizedString("scopeUser", IDS_POLICY_SCOPE_USER);
141 source->AddLocalizedString("scopeDevice", IDS_POLICY_SCOPE_DEVICE);
142 source->AddLocalizedString("levelRecommended", IDS_POLICY_LEVEL_RECOMMENDED);
143 source->AddLocalizedString("levelMandatory", IDS_POLICY_LEVEL_MANDATORY);
144 source->AddLocalizedString("ok", IDS_POLICY_OK);
145 source->AddLocalizedString("unset", IDS_POLICY_UNSET);
146 source->AddLocalizedString("unknown", IDS_POLICY_UNKNOWN);
147 source->AddLocalizedString("notSpecified", IDS_POLICY_NOT_SPECIFIED);
148 AddLocalizedPoilcySourceStrings(source);
150 source->SetJsonPath("strings.js");
152 // Add required resources.
153 source->AddResourcePath("policy.css", IDR_POLICY_CSS);
154 source->AddResourcePath("policy.js", IDR_POLICY_JS);
155 source->AddResourcePath("uber_utils.js", IDR_UBER_UTILS_JS);
156 source->SetDefaultResource(IDR_POLICY_HTML);
158 return source;
161 // Formats the association state indicated by |data|. If |data| is NULL, the
162 // state is considered to be UNMANAGED.
163 base::string16 FormatAssociationState(const em::PolicyData* data) {
164 if (data) {
165 switch (data->state()) {
166 case em::PolicyData::ACTIVE:
167 return l10n_util::GetStringUTF16(IDS_POLICY_ASSOCIATION_STATE_ACTIVE);
168 case em::PolicyData::UNMANAGED:
169 return l10n_util::GetStringUTF16(
170 IDS_POLICY_ASSOCIATION_STATE_UNMANAGED);
171 case em::PolicyData::DEPROVISIONED:
172 return l10n_util::GetStringUTF16(
173 IDS_POLICY_ASSOCIATION_STATE_DEPROVISIONED);
175 NOTREACHED() << "Unknown state " << data->state();
178 // Default to UNMANAGED for the case of missing policy or bad state enum.
179 return l10n_util::GetStringUTF16(IDS_POLICY_ASSOCIATION_STATE_UNMANAGED);
182 void GetStatusFromCore(const policy::CloudPolicyCore* core,
183 base::DictionaryValue* dict) {
184 const policy::CloudPolicyStore* store = core->store();
185 const policy::CloudPolicyClient* client = core->client();
186 const policy::CloudPolicyRefreshScheduler* refresh_scheduler =
187 core->refresh_scheduler();
189 // CloudPolicyStore errors take precedence to show in the status message.
190 // Other errors (such as transient policy fetching problems) get displayed
191 // only if CloudPolicyStore is in STATUS_OK.
192 base::string16 status =
193 policy::FormatStoreStatus(store->status(), store->validation_status());
194 if (store->status() == policy::CloudPolicyStore::STATUS_OK) {
195 if (client && client->status() != policy::DM_STATUS_SUCCESS)
196 status = policy::FormatDeviceManagementStatus(client->status());
197 else if (!store->is_managed())
198 status = FormatAssociationState(store->policy());
201 const em::PolicyData* policy = store->policy();
202 std::string client_id = policy ? policy->device_id() : std::string();
203 std::string username = policy ? policy->username() : std::string();
205 if (policy && policy->has_annotated_asset_id())
206 dict->SetString("assetId", policy->annotated_asset_id());
207 if (policy && policy->has_annotated_location())
208 dict->SetString("location", policy->annotated_location());
209 if (policy && policy->has_directory_api_id())
210 dict->SetString("directoryApiId", policy->directory_api_id());
212 base::TimeDelta refresh_interval =
213 base::TimeDelta::FromMilliseconds(refresh_scheduler ?
214 refresh_scheduler->refresh_delay() :
215 policy::CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs);
216 base::Time last_refresh_time = refresh_scheduler ?
217 refresh_scheduler->last_refresh() : base::Time();
219 bool no_error = store->status() == policy::CloudPolicyStore::STATUS_OK &&
220 client && client->status() == policy::DM_STATUS_SUCCESS;
221 dict->SetBoolean("error", !no_error);
222 dict->SetString("status", status);
223 dict->SetString("clientId", client_id);
224 dict->SetString("username", username);
225 dict->SetString("refreshInterval",
226 ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_DURATION,
227 ui::TimeFormat::LENGTH_SHORT,
228 refresh_interval));
229 dict->SetString("timeSinceLastRefresh", last_refresh_time.is_null() ?
230 l10n_util::GetStringUTF16(IDS_POLICY_NEVER_FETCHED) :
231 ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_ELAPSED,
232 ui::TimeFormat::LENGTH_SHORT,
233 base::Time::NowFromSystemTime() -
234 last_refresh_time));
237 void ExtractDomainFromUsername(base::DictionaryValue* dict) {
238 std::string username;
239 dict->GetString("username", &username);
240 if (!username.empty())
241 dict->SetString("domain", gaia::ExtractDomainName(username));
244 // Utility function that returns a JSON serialization of the given |dict|.
245 scoped_ptr<base::StringValue> DictionaryToJSONString(
246 const base::DictionaryValue& dict) {
247 std::string json_string;
248 base::JSONWriter::WriteWithOptions(dict,
249 base::JSONWriter::OPTIONS_PRETTY_PRINT,
250 &json_string);
251 return make_scoped_ptr(new base::StringValue(json_string));
254 // Returns a copy of |value| with some values converted to a representation that
255 // i18n_template.js will display in a nicer way.
256 scoped_ptr<base::Value> CopyAndConvert(const base::Value* value) {
257 const base::DictionaryValue* dict = NULL;
258 if (value->GetAsDictionary(&dict))
259 return DictionaryToJSONString(*dict);
261 scoped_ptr<base::Value> copy(value->DeepCopy());
262 base::ListValue* list = NULL;
263 if (copy->GetAsList(&list)) {
264 for (size_t i = 0; i < list->GetSize(); ++i) {
265 if (list->GetDictionary(i, &dict))
266 list->Set(i, DictionaryToJSONString(*dict).release());
270 return copy.Pass();
273 } // namespace
275 // An interface for querying the status of cloud policy.
276 class CloudPolicyStatusProvider {
277 public:
278 CloudPolicyStatusProvider();
279 virtual ~CloudPolicyStatusProvider();
281 // Sets a callback to invoke upon status changes.
282 void SetStatusChangeCallback(const base::Closure& callback);
284 virtual void GetStatus(base::DictionaryValue* dict);
286 protected:
287 void NotifyStatusChange();
289 private:
290 base::Closure callback_;
292 DISALLOW_COPY_AND_ASSIGN(CloudPolicyStatusProvider);
295 // Status provider implementation that pulls cloud policy status from a
296 // CloudPolicyCore instance provided at construction time. Also listens for
297 // changes on that CloudPolicyCore and reports them through the status change
298 // callback.
299 class CloudPolicyCoreStatusProvider
300 : public CloudPolicyStatusProvider,
301 public policy::CloudPolicyStore::Observer {
302 public:
303 explicit CloudPolicyCoreStatusProvider(policy::CloudPolicyCore* core);
304 ~CloudPolicyCoreStatusProvider() override;
306 // policy::CloudPolicyStore::Observer implementation.
307 void OnStoreLoaded(policy::CloudPolicyStore* store) override;
308 void OnStoreError(policy::CloudPolicyStore* store) override;
310 protected:
311 // Policy status is read from the CloudPolicyClient, CloudPolicyStore and
312 // CloudPolicyRefreshScheduler hosted by this |core_|.
313 policy::CloudPolicyCore* core_;
315 private:
316 DISALLOW_COPY_AND_ASSIGN(CloudPolicyCoreStatusProvider);
319 // A cloud policy status provider for user policy.
320 class UserPolicyStatusProvider : public CloudPolicyCoreStatusProvider {
321 public:
322 explicit UserPolicyStatusProvider(policy::CloudPolicyCore* core);
323 ~UserPolicyStatusProvider() override;
325 // CloudPolicyCoreStatusProvider implementation.
326 void GetStatus(base::DictionaryValue* dict) override;
328 private:
329 DISALLOW_COPY_AND_ASSIGN(UserPolicyStatusProvider);
332 #if defined(OS_CHROMEOS)
333 // A cloud policy status provider for device policy.
334 class DevicePolicyStatusProvider : public CloudPolicyCoreStatusProvider {
335 public:
336 explicit DevicePolicyStatusProvider(
337 policy::BrowserPolicyConnectorChromeOS* connector);
338 ~DevicePolicyStatusProvider() override;
340 // CloudPolicyCoreStatusProvider implementation.
341 void GetStatus(base::DictionaryValue* dict) override;
343 private:
344 std::string domain_;
346 DISALLOW_COPY_AND_ASSIGN(DevicePolicyStatusProvider);
349 // A cloud policy status provider that reads policy status from the policy core
350 // associated with the device-local account specified by |user_id| at
351 // construction time. The indirection via user ID and
352 // DeviceLocalAccountPolicyService is necessary because the device-local account
353 // may go away any time behind the scenes, at which point the status message
354 // text will indicate CloudPolicyStore::STATUS_BAD_STATE.
355 class DeviceLocalAccountPolicyStatusProvider
356 : public CloudPolicyStatusProvider,
357 public policy::DeviceLocalAccountPolicyService::Observer {
358 public:
359 DeviceLocalAccountPolicyStatusProvider(
360 const std::string& user_id,
361 policy::DeviceLocalAccountPolicyService* service);
362 ~DeviceLocalAccountPolicyStatusProvider() override;
364 // CloudPolicyStatusProvider implementation.
365 void GetStatus(base::DictionaryValue* dict) override;
367 // policy::DeviceLocalAccountPolicyService::Observer implementation.
368 void OnPolicyUpdated(const std::string& user_id) override;
369 void OnDeviceLocalAccountsChanged() override;
371 private:
372 const std::string user_id_;
373 policy::DeviceLocalAccountPolicyService* service_;
375 DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountPolicyStatusProvider);
377 #endif
379 // The JavaScript message handler for the chrome://policy page.
380 class PolicyUIHandler : public content::WebUIMessageHandler,
381 #if defined(ENABLE_EXTENSIONS)
382 public extensions::ExtensionRegistryObserver,
383 #endif
384 public policy::PolicyService::Observer,
385 public policy::SchemaRegistry::Observer {
386 public:
387 PolicyUIHandler();
388 ~PolicyUIHandler() override;
390 // content::WebUIMessageHandler implementation.
391 void RegisterMessages() override;
393 #if defined(ENABLE_EXTENSIONS)
394 // extensions::ExtensionRegistryObserver implementation.
395 void OnExtensionLoaded(content::BrowserContext* browser_context,
396 const extensions::Extension* extension) override;
397 void OnExtensionUnloaded(
398 content::BrowserContext* browser_context,
399 const extensions::Extension* extension,
400 extensions::UnloadedExtensionInfo::Reason reason) override;
401 #endif
403 // policy::PolicyService::Observer implementation.
404 void OnPolicyUpdated(const policy::PolicyNamespace& ns,
405 const policy::PolicyMap& previous,
406 const policy::PolicyMap& current) override;
408 // policy::SchemaRegistry::Observer implementation.
409 void OnSchemaRegistryUpdated(bool has_new_schemas) override;
411 private:
412 // Send a dictionary containing the names of all known policies to the UI.
413 void SendPolicyNames() const;
415 // Send information about the current policy values to the UI. For each policy
416 // whose value has been set, a dictionary containing the value and additional
417 // metadata is sent.
418 void SendPolicyValues() const;
420 // Send the status of cloud policy to the UI. For each scope that has cloud
421 // policy enabled (device and/or user), a dictionary containing status
422 // information is sent.
423 void SendStatus() const;
425 // Inserts a description of each policy in |policy_map| into |values|, using
426 // the optional errors in |errors| to determine the status of each policy.
427 void GetPolicyValues(const policy::PolicyMap& policy_map,
428 policy::PolicyErrorMap* errors,
429 base::DictionaryValue* values) const;
431 void GetChromePolicyValues(base::DictionaryValue* values) const;
433 void HandleInitialized(const base::ListValue* args);
434 void HandleReloadPolicies(const base::ListValue* args);
436 void OnRefreshPoliciesDone() const;
438 policy::PolicyService* GetPolicyService() const;
440 std::string device_domain_;
442 // Providers that supply status dictionaries for user and device policy,
443 // respectively. These are created on initialization time as appropriate for
444 // the platform (Chrome OS / desktop) and type of policy that is in effect.
445 scoped_ptr<CloudPolicyStatusProvider> user_status_provider_;
446 scoped_ptr<CloudPolicyStatusProvider> device_status_provider_;
448 base::WeakPtrFactory<PolicyUIHandler> weak_factory_;
450 DISALLOW_COPY_AND_ASSIGN(PolicyUIHandler);
453 CloudPolicyStatusProvider::CloudPolicyStatusProvider() {
456 CloudPolicyStatusProvider::~CloudPolicyStatusProvider() {
459 void CloudPolicyStatusProvider::SetStatusChangeCallback(
460 const base::Closure& callback) {
461 callback_ = callback;
464 void CloudPolicyStatusProvider::GetStatus(base::DictionaryValue* dict) {
467 void CloudPolicyStatusProvider::NotifyStatusChange() {
468 if (!callback_.is_null())
469 callback_.Run();
472 CloudPolicyCoreStatusProvider::CloudPolicyCoreStatusProvider(
473 policy::CloudPolicyCore* core) : core_(core) {
474 core_->store()->AddObserver(this);
475 // TODO(bartfab): Add an observer that watches for client errors. Observing
476 // core_->client() directly is not safe as the client may be destroyed and
477 // (re-)created anytime if the user signs in or out on desktop platforms.
480 CloudPolicyCoreStatusProvider::~CloudPolicyCoreStatusProvider() {
481 core_->store()->RemoveObserver(this);
484 void CloudPolicyCoreStatusProvider::OnStoreLoaded(
485 policy::CloudPolicyStore* store) {
486 NotifyStatusChange();
489 void CloudPolicyCoreStatusProvider::OnStoreError(
490 policy::CloudPolicyStore* store) {
491 NotifyStatusChange();
494 UserPolicyStatusProvider::UserPolicyStatusProvider(
495 policy::CloudPolicyCore* core) : CloudPolicyCoreStatusProvider(core) {
498 UserPolicyStatusProvider::~UserPolicyStatusProvider() {
501 void UserPolicyStatusProvider::GetStatus(base::DictionaryValue* dict) {
502 if (!core_->store()->is_managed())
503 return;
504 GetStatusFromCore(core_, dict);
505 ExtractDomainFromUsername(dict);
508 #if defined(OS_CHROMEOS)
509 DevicePolicyStatusProvider::DevicePolicyStatusProvider(
510 policy::BrowserPolicyConnectorChromeOS* connector)
511 : CloudPolicyCoreStatusProvider(
512 connector->GetDeviceCloudPolicyManager()->core()) {
513 domain_ = connector->GetEnterpriseDomain();
516 DevicePolicyStatusProvider::~DevicePolicyStatusProvider() {
519 void DevicePolicyStatusProvider::GetStatus(base::DictionaryValue* dict) {
520 GetStatusFromCore(core_, dict);
521 dict->SetString("domain", domain_);
524 DeviceLocalAccountPolicyStatusProvider::DeviceLocalAccountPolicyStatusProvider(
525 const std::string& user_id,
526 policy::DeviceLocalAccountPolicyService* service)
527 : user_id_(user_id),
528 service_(service) {
529 service_->AddObserver(this);
532 DeviceLocalAccountPolicyStatusProvider::
533 ~DeviceLocalAccountPolicyStatusProvider() {
534 service_->RemoveObserver(this);
537 void DeviceLocalAccountPolicyStatusProvider::GetStatus(
538 base::DictionaryValue* dict) {
539 const policy::DeviceLocalAccountPolicyBroker* broker =
540 service_->GetBrokerForUser(user_id_);
541 if (broker) {
542 GetStatusFromCore(broker->core(), dict);
543 } else {
544 dict->SetBoolean("error", true);
545 dict->SetString("status",
546 policy::FormatStoreStatus(
547 policy::CloudPolicyStore::STATUS_BAD_STATE,
548 policy::CloudPolicyValidatorBase::VALIDATION_OK));
549 dict->SetString("username", std::string());
551 ExtractDomainFromUsername(dict);
552 dict->SetBoolean("publicAccount", true);
555 void DeviceLocalAccountPolicyStatusProvider::OnPolicyUpdated(
556 const std::string& user_id) {
557 if (user_id == user_id_)
558 NotifyStatusChange();
561 void DeviceLocalAccountPolicyStatusProvider::OnDeviceLocalAccountsChanged() {
562 NotifyStatusChange();
564 #endif
566 PolicyUIHandler::PolicyUIHandler()
567 : weak_factory_(this) {
570 PolicyUIHandler::~PolicyUIHandler() {
571 GetPolicyService()->RemoveObserver(policy::POLICY_DOMAIN_CHROME, this);
572 GetPolicyService()->RemoveObserver(policy::POLICY_DOMAIN_EXTENSIONS, this);
573 policy::SchemaRegistry* registry =
574 policy::SchemaRegistryServiceFactory::GetForContext(
575 Profile::FromWebUI(web_ui())->GetOriginalProfile())->registry();
576 registry->RemoveObserver(this);
578 #if defined(ENABLE_EXTENSIONS)
579 extensions::ExtensionRegistry::Get(Profile::FromWebUI(web_ui()))
580 ->RemoveObserver(this);
581 #endif
584 void PolicyUIHandler::RegisterMessages() {
585 #if defined(OS_CHROMEOS)
586 policy::BrowserPolicyConnectorChromeOS* connector =
587 g_browser_process->platform_part()->browser_policy_connector_chromeos();
588 if (connector->IsEnterpriseManaged())
589 device_status_provider_.reset(new DevicePolicyStatusProvider(connector));
591 const user_manager::UserManager* user_manager =
592 user_manager::UserManager::Get();
593 if (user_manager->IsLoggedInAsPublicAccount()) {
594 policy::DeviceLocalAccountPolicyService* local_account_service =
595 connector->GetDeviceLocalAccountPolicyService();
596 if (local_account_service) {
597 user_status_provider_.reset(
598 new DeviceLocalAccountPolicyStatusProvider(
599 user_manager->GetLoggedInUser()->email(), local_account_service));
601 } else {
602 policy::UserCloudPolicyManagerChromeOS* user_cloud_policy_manager =
603 policy::UserCloudPolicyManagerFactoryChromeOS::GetForProfile(
604 Profile::FromWebUI(web_ui()));
605 if (user_cloud_policy_manager) {
606 user_status_provider_.reset(
607 new UserPolicyStatusProvider(user_cloud_policy_manager->core()));
610 #else
611 policy::UserCloudPolicyManager* user_cloud_policy_manager =
612 policy::UserCloudPolicyManagerFactory::GetForBrowserContext(
613 web_ui()->GetWebContents()->GetBrowserContext());
614 if (user_cloud_policy_manager) {
615 user_status_provider_.reset(
616 new UserPolicyStatusProvider(user_cloud_policy_manager->core()));
618 #endif
620 if (!user_status_provider_.get())
621 user_status_provider_.reset(new CloudPolicyStatusProvider());
622 if (!device_status_provider_.get())
623 device_status_provider_.reset(new CloudPolicyStatusProvider());
625 base::Closure update_callback(base::Bind(&PolicyUIHandler::SendStatus,
626 base::Unretained(this)));
627 user_status_provider_->SetStatusChangeCallback(update_callback);
628 device_status_provider_->SetStatusChangeCallback(update_callback);
629 GetPolicyService()->AddObserver(policy::POLICY_DOMAIN_CHROME, this);
630 GetPolicyService()->AddObserver(policy::POLICY_DOMAIN_EXTENSIONS, this);
632 #if defined(ENABLE_EXTENSIONS)
633 extensions::ExtensionRegistry::Get(Profile::FromWebUI(web_ui()))
634 ->AddObserver(this);
635 #endif
636 policy::SchemaRegistry* registry =
637 policy::SchemaRegistryServiceFactory::GetForContext(
638 Profile::FromWebUI(web_ui())->GetOriginalProfile())->registry();
639 registry->AddObserver(this);
641 web_ui()->RegisterMessageCallback(
642 "initialized",
643 base::Bind(&PolicyUIHandler::HandleInitialized, base::Unretained(this)));
644 web_ui()->RegisterMessageCallback(
645 "reloadPolicies",
646 base::Bind(&PolicyUIHandler::HandleReloadPolicies,
647 base::Unretained(this)));
650 #if defined(ENABLE_EXTENSIONS)
651 void PolicyUIHandler::OnExtensionLoaded(
652 content::BrowserContext* browser_context,
653 const extensions::Extension* extension) {
654 SendPolicyNames();
655 SendPolicyValues();
658 void PolicyUIHandler::OnExtensionUnloaded(
659 content::BrowserContext* browser_context,
660 const extensions::Extension* extension,
661 extensions::UnloadedExtensionInfo::Reason reason) {
662 SendPolicyNames();
663 SendPolicyValues();
665 #endif
667 void PolicyUIHandler::OnSchemaRegistryUpdated(bool has_new_schemas) {
668 // Update UI when new schema is added.
669 if (has_new_schemas) {
670 SendPolicyNames();
671 SendPolicyValues();
675 void PolicyUIHandler::OnPolicyUpdated(const policy::PolicyNamespace& ns,
676 const policy::PolicyMap& previous,
677 const policy::PolicyMap& current) {
678 SendPolicyValues();
681 void PolicyUIHandler::SendPolicyNames() const {
682 base::DictionaryValue names;
684 Profile* profile = Profile::FromWebUI(web_ui());
685 policy::SchemaRegistry* registry =
686 policy::SchemaRegistryServiceFactory::GetForContext(
687 profile->GetOriginalProfile())->registry();
688 scoped_refptr<policy::SchemaMap> schema_map = registry->schema_map();
690 // Add Chrome policy names.
691 base::DictionaryValue* chrome_policy_names = new base::DictionaryValue;
692 policy::PolicyNamespace chrome_ns(policy::POLICY_DOMAIN_CHROME, "");
693 const policy::Schema* chrome_schema = schema_map->GetSchema(chrome_ns);
694 for (policy::Schema::Iterator it = chrome_schema->GetPropertiesIterator();
695 !it.IsAtEnd(); it.Advance()) {
696 chrome_policy_names->SetBoolean(it.key(), true);
698 names.Set("chromePolicyNames", chrome_policy_names);
700 #if defined(ENABLE_EXTENSIONS)
701 // Add extension policy names.
702 base::DictionaryValue* extension_policy_names = new base::DictionaryValue;
704 for (const scoped_refptr<const extensions::Extension>& extension :
705 extensions::ExtensionRegistry::Get(profile)->enabled_extensions()) {
706 // Skip this extension if it's not an enterprise extension.
707 if (!extension->manifest()->HasPath(
708 extensions::manifest_keys::kStorageManagedSchema))
709 continue;
710 base::DictionaryValue* extension_value = new base::DictionaryValue;
711 extension_value->SetString("name", extension->name());
712 const policy::Schema* schema =
713 schema_map->GetSchema(policy::PolicyNamespace(
714 policy::POLICY_DOMAIN_EXTENSIONS, extension->id()));
715 base::DictionaryValue* policy_names = new base::DictionaryValue;
716 if (schema && schema->valid()) {
717 // Get policy names from the extension's policy schema.
718 // Store in a map, not an array, for faster lookup on JS side.
719 for (policy::Schema::Iterator prop = schema->GetPropertiesIterator();
720 !prop.IsAtEnd(); prop.Advance()) {
721 policy_names->SetBoolean(prop.key(), true);
724 extension_value->Set("policyNames", policy_names);
725 extension_policy_names->Set(extension->id(), extension_value);
727 names.Set("extensionPolicyNames", extension_policy_names);
728 #endif // defined(ENABLE_EXTENSIONS)
730 web_ui()->CallJavascriptFunction("policy.Page.setPolicyNames", names);
733 void PolicyUIHandler::SendPolicyValues() const {
734 base::DictionaryValue all_policies;
736 // Add Chrome policy values.
737 base::DictionaryValue* chrome_policies = new base::DictionaryValue;
738 GetChromePolicyValues(chrome_policies);
739 all_policies.Set("chromePolicies", chrome_policies);
741 #if defined(ENABLE_EXTENSIONS)
742 // Add extension policy values.
743 extensions::ExtensionRegistry* registry =
744 extensions::ExtensionRegistry::Get(Profile::FromWebUI(web_ui()));
745 base::DictionaryValue* extension_values = new base::DictionaryValue;
747 for (const scoped_refptr<const extensions::Extension>& extension :
748 registry->enabled_extensions()) {
749 // Skip this extension if it's not an enterprise extension.
750 if (!extension->manifest()->HasPath(
751 extensions::manifest_keys::kStorageManagedSchema))
752 continue;
753 base::DictionaryValue* extension_policies = new base::DictionaryValue;
754 policy::PolicyNamespace policy_namespace = policy::PolicyNamespace(
755 policy::POLICY_DOMAIN_EXTENSIONS, extension->id());
756 policy::PolicyErrorMap empty_error_map;
757 GetPolicyValues(GetPolicyService()->GetPolicies(policy_namespace),
758 &empty_error_map, extension_policies);
759 extension_values->Set(extension->id(), extension_policies);
761 all_policies.Set("extensionPolicies", extension_values);
762 #endif
763 web_ui()->CallJavascriptFunction("policy.Page.setPolicyValues", all_policies);
766 void PolicyUIHandler::GetPolicyValues(const policy::PolicyMap& map,
767 policy::PolicyErrorMap* errors,
768 base::DictionaryValue* values) const {
769 for (policy::PolicyMap::const_iterator entry = map.begin();
770 entry != map.end(); ++entry) {
771 base::DictionaryValue* value = new base::DictionaryValue;
772 value->Set("value", CopyAndConvert(entry->second.value).release());
773 if (entry->second.scope == policy::POLICY_SCOPE_USER)
774 value->SetString("scope", "user");
775 else
776 value->SetString("scope", "machine");
777 if (entry->second.level == policy::POLICY_LEVEL_RECOMMENDED)
778 value->SetString("level", "recommended");
779 else
780 value->SetString("level", "mandatory");
781 value->SetString("source", kPolicySources[entry->second.source].key);
782 base::string16 error = errors->GetErrors(entry->first);
783 if (!error.empty())
784 value->SetString("error", error);
785 values->Set(entry->first, value);
789 void PolicyUIHandler::GetChromePolicyValues(
790 base::DictionaryValue* values) const {
791 policy::PolicyService* policy_service = GetPolicyService();
792 policy::PolicyMap map;
794 // Make a copy that can be modified, since some policy values are modified
795 // before being displayed.
796 map.CopyFrom(policy_service->GetPolicies(
797 policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string())));
799 // Get a list of all the errors in the policy values.
800 const policy::ConfigurationPolicyHandlerList* handler_list =
801 g_browser_process->browser_policy_connector()->GetHandlerList();
802 policy::PolicyErrorMap errors;
803 handler_list->ApplyPolicySettings(map, NULL, &errors);
805 // Convert dictionary values to strings for display.
806 handler_list->PrepareForDisplaying(&map);
808 GetPolicyValues(map, &errors, values);
811 void PolicyUIHandler::SendStatus() const {
812 scoped_ptr<base::DictionaryValue> device_status(new base::DictionaryValue);
813 device_status_provider_->GetStatus(device_status.get());
814 if (!device_domain_.empty())
815 device_status->SetString("domain", device_domain_);
816 scoped_ptr<base::DictionaryValue> user_status(new base::DictionaryValue);
817 user_status_provider_->GetStatus(user_status.get());
818 std::string username;
819 user_status->GetString("username", &username);
820 if (!username.empty())
821 user_status->SetString("domain", gaia::ExtractDomainName(username));
823 base::DictionaryValue status;
824 if (!device_status->empty())
825 status.Set("device", device_status.release());
826 if (!user_status->empty())
827 status.Set("user", user_status.release());
829 web_ui()->CallJavascriptFunction("policy.Page.setStatus", status);
832 void PolicyUIHandler::HandleInitialized(const base::ListValue* args) {
833 SendPolicyNames();
834 SendPolicyValues();
835 SendStatus();
838 void PolicyUIHandler::HandleReloadPolicies(const base::ListValue* args) {
839 #if defined(OS_CHROMEOS)
840 // Allow user to manually fetch remote commands, in case invalidation
841 // service is not working properly.
842 // TODO(binjin): evaluate and possibly remove this after invalidation
843 // service is landed and tested. http://crbug.com/480982
844 policy::BrowserPolicyConnectorChromeOS* connector =
845 g_browser_process->platform_part()->browser_policy_connector_chromeos();
846 policy::RemoteCommandsService* remote_commands_service =
847 connector->GetDeviceCloudPolicyManager()
848 ->core()
849 ->remote_commands_service();
850 if (remote_commands_service)
851 remote_commands_service->FetchRemoteCommands();
852 #endif
853 GetPolicyService()->RefreshPolicies(base::Bind(
854 &PolicyUIHandler::OnRefreshPoliciesDone, weak_factory_.GetWeakPtr()));
857 void PolicyUIHandler::OnRefreshPoliciesDone() const {
858 web_ui()->CallJavascriptFunction("policy.Page.reloadPoliciesDone");
861 policy::PolicyService* PolicyUIHandler::GetPolicyService() const {
862 return policy::ProfilePolicyConnectorFactory::GetForBrowserContext(
863 web_ui()->GetWebContents()->GetBrowserContext())->policy_service();
866 PolicyUI::PolicyUI(content::WebUI* web_ui) : WebUIController(web_ui) {
867 web_ui->AddMessageHandler(new PolicyUIHandler);
868 content::WebUIDataSource::Add(Profile::FromWebUI(web_ui),
869 CreatePolicyUIHTMLSource());
872 PolicyUI::~PolicyUI() {