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"
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"
64 #include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
65 #include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
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"
76 namespace em
= enterprise_management
;
80 content::WebUIDataSource
* CreatePolicyUIHTMLSource() {
81 content::WebUIDataSource
* source
=
82 content::WebUIDataSource::Create(chrome::kChromeUIPolicyHost
);
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
);
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
) {
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
,
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() -
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
,
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());
249 // An interface for querying the status of cloud policy.
250 class CloudPolicyStatusProvider
{
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
);
261 void NotifyStatusChange();
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
273 class CloudPolicyCoreStatusProvider
274 : public CloudPolicyStatusProvider
,
275 public policy::CloudPolicyStore::Observer
{
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
;
285 // Policy status is read from the CloudPolicyClient, CloudPolicyStore and
286 // CloudPolicyRefreshScheduler hosted by this |core_|.
287 policy::CloudPolicyCore
* core_
;
290 DISALLOW_COPY_AND_ASSIGN(CloudPolicyCoreStatusProvider
);
293 // A cloud policy status provider for user policy.
294 class UserPolicyStatusProvider
: public CloudPolicyCoreStatusProvider
{
296 explicit UserPolicyStatusProvider(policy::CloudPolicyCore
* core
);
297 ~UserPolicyStatusProvider() override
;
299 // CloudPolicyCoreStatusProvider implementation.
300 void GetStatus(base::DictionaryValue
* dict
) override
;
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
{
310 explicit DevicePolicyStatusProvider(
311 policy::BrowserPolicyConnectorChromeOS
* connector
);
312 ~DevicePolicyStatusProvider() override
;
314 // CloudPolicyCoreStatusProvider implementation.
315 void GetStatus(base::DictionaryValue
* dict
) override
;
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
{
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
;
346 const std::string user_id_
;
347 policy::DeviceLocalAccountPolicyService
* service_
;
349 DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountPolicyStatusProvider
);
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
,
358 public policy::PolicyService::Observer
,
359 public policy::SchemaRegistry::Observer
{
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
;
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
;
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
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())
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())
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
)
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_
);
516 GetStatusFromCore(broker
->core(), dict
);
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();
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);
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
));
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()));
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()));
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()))
610 policy::SchemaRegistry
* registry
=
611 policy::SchemaRegistryServiceFactory::GetForContext(
612 Profile::FromWebUI(web_ui())->GetOriginalProfile())->registry();
613 registry
->AddObserver(this);
615 web_ui()->RegisterMessageCallback(
617 base::Bind(&PolicyUIHandler::HandleInitialized
, base::Unretained(this)));
618 web_ui()->RegisterMessageCallback(
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
) {
632 void PolicyUIHandler::OnExtensionUnloaded(
633 content::BrowserContext
* browser_context
,
634 const extensions::Extension
* extension
,
635 extensions::UnloadedExtensionInfo::Reason reason
) {
641 void PolicyUIHandler::OnSchemaRegistryUpdated(bool has_new_schemas
) {
642 // Update UI when new schema is added.
643 if (has_new_schemas
) {
649 void PolicyUIHandler::OnPolicyUpdated(const policy::PolicyNamespace
& ns
,
650 const policy::PolicyMap
& previous
,
651 const policy::PolicyMap
& current
) {
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
))
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
))
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
);
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");
750 value
->SetString("scope", "machine");
751 if (entry
->second
.level
== policy::POLICY_LEVEL_RECOMMENDED
)
752 value
->SetString("level", "recommended");
754 value
->SetString("level", "mandatory");
755 base::string16 error
= errors
->GetErrors(entry
->first
);
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
) {
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()
822 ->remote_commands_service();
823 if (remote_commands_service
)
824 remote_commands_service
->FetchRemoteCommands();
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() {