diff options
author | fhorschig <fhorschig@chromium.org> | 2015-12-03 08:48:57 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-12-03 16:50:40 +0000 |
commit | 07c5e062f2ea6ef0e3b5844f1a11ecb4df4d41f6 (patch) | |
tree | f0711ba6d8d03dc5adf8c1f525e97537b77b74ee | |
parent | 78acd34a5a46c8398dbe1e1b1d3168551ba8b6ff (diff) | |
download | chromium_src-07c5e062f2ea6ef0e3b5844f1a11ecb4df4d41f6.zip chromium_src-07c5e062f2ea6ef0e3b5844f1a11ecb4df4d41f6.tar.gz chromium_src-07c5e062f2ea6ef0e3b5844f1a11ecb4df4d41f6.tar.bz2 |
Policy Ui sends correct translations for risk tags.
Send localized group names to frontend and reuse some strings from
the old WebUi.
(Prerequisite for CL 1371073003)
BUG=134849
Review URL: https://codereview.chromium.org/1395073002
Cr-Commit-Position: refs/heads/master@{#362997}
-rw-r--r-- | build/ios/grit_whitelist.txt | 7 | ||||
-rw-r--r-- | chrome/BUILD.gn | 3 | ||||
-rw-r--r-- | chrome/browser/browser_resources.grd | 1 | ||||
-rw-r--r-- | chrome/browser/resources/BUILD.gn | 11 | ||||
-rw-r--r-- | chrome/browser/resources/md_policy/policy_resources.grd | 21 | ||||
-rw-r--r-- | chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc | 1 | ||||
-rw-r--r-- | chrome/browser/ui/webui/policy_material_design_ui.cc | 97 | ||||
-rw-r--r-- | chrome/browser/ui/webui/policy_material_design_ui.h | 25 | ||||
-rw-r--r-- | chrome/browser/ui/webui/policy_ui.cc | 843 | ||||
-rw-r--r-- | chrome/browser/ui/webui/policy_ui.h | 10 | ||||
-rw-r--r-- | chrome/browser/ui/webui/policy_ui_handler.cc | 747 | ||||
-rw-r--r-- | chrome/browser/ui/webui/policy_ui_handler.h | 119 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 1 | ||||
-rw-r--r-- | chrome/chrome_browser_ui.gypi | 4 | ||||
-rw-r--r-- | chrome/chrome_repack_resources.gypi | 1 | ||||
-rw-r--r-- | chrome/chrome_resources.gyp | 8 | ||||
-rw-r--r-- | components/policy_strings.grdp | 21 | ||||
-rw-r--r-- | tools/gritsettings/resource_ids | 3 |
18 files changed, 1074 insertions, 849 deletions
diff --git a/build/ios/grit_whitelist.txt b/build/ios/grit_whitelist.txt index fc9e66e..0c0e624 100644 --- a/build/ios/grit_whitelist.txt +++ b/build/ios/grit_whitelist.txt @@ -464,6 +464,13 @@ IDS_PLATFORM_LABEL IDS_PLUGIN_CONFIRM_INSTALL_DIALOG_ACCEPT_BUTTON IDS_PLUGIN_CONFIRM_INSTALL_DIALOG_TITLE IDS_PLUGIN_NOT_SUPPORTED +IDS_POLICY_RISK_TAG_ADMIN_SHARING +IDS_POLICY_RISK_TAG_FILTERING +IDS_POLICY_RISK_TAG_FULL_ADMIN_ACCESS +IDS_POLICY_RISK_TAG_GOOGLE_SHARING +IDS_POLICY_RISK_TAG_LOCAL_DATA_ACCESS +IDS_POLICY_RISK_TAG_SYSTEM_SECURITY +IDS_POLICY_RISK_TAG_WEBSITE_SHARING IDS_PREFERENCES_CORRUPT_ERROR IDS_PREFERENCES_UNREADABLE_ERROR IDS_PRINT diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index b2ecaf4..efb7dc6 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn @@ -585,6 +585,7 @@ group("extra_resources") { "//chrome/browser/resources:memory_internals_resources", "//chrome/browser/resources:net_internals_resources", "//chrome/browser/resources:password_manager_internals_resources", + "//chrome/browser/resources:policy_resources", "//chrome/browser/resources:signin_internals_resources", "//chrome/browser/resources:translate_internals_resources", ] @@ -662,6 +663,7 @@ repack("packed_extra_resources") { "$root_gen_dir/chrome/memory_internals_resources.pak", "$root_gen_dir/chrome/net_internals_resources.pak", "$root_gen_dir/chrome/password_manager_internals_resources.pak", + "$root_gen_dir/chrome/policy_resources.pak", "$root_gen_dir/chrome/signin_internals_resources.pak", "$root_gen_dir/chrome/translate_internals_resources.pak", "$root_gen_dir/components/components_resources.pak", @@ -675,6 +677,7 @@ repack("packed_extra_resources") { "//chrome/browser/resources:memory_internals_resources", "//chrome/browser/resources:net_internals_resources", "//chrome/browser/resources:password_manager_internals_resources", + "//chrome/browser/resources:policy_resources", "//chrome/browser/resources:signin_internals_resources", "//chrome/browser/resources:translate_internals_resources", "//chrome/common:resources", diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 76cd0af..e41e967 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd @@ -274,7 +274,6 @@ <include name="IDR_POLICY_CSS" file="resources\policy.css" type="BINDATA"/> </if> <include name="IDR_POLICY_HTML" file="resources\policy.html" flattenhtml="true" allowexternalscript="true" type="BINDATA"/> - <include name="IDR_MD_POLICY_HTML" file="resources\md_policy\md_policy.html" flattenhtml="true" allowexternalscript="true" type="BINDATA"/> <include name="IDR_POLICY_JS" file="resources\policy.js" type="BINDATA"/> <if expr="enable_print_preview"> <include name="IDR_PRINT_PREVIEW_HTML" file="resources\print_preview\print_preview.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn index 14de709..d0af340 100644 --- a/chrome/browser/resources/BUILD.gn +++ b/chrome/browser/resources/BUILD.gn @@ -45,6 +45,17 @@ grit("password_manager_internals_resources") { output_dir = "$root_gen_dir/chrome" } +grit("policy_resources") { + source = "md_policy/policy_resources.grd" + outputs = [ + "grit/policy_resources.h", + "grit/policy_resources_map.cc", + "grit/policy_resources_map.h", + "policy_resources.pak", + ] + output_dir = "$root_gen_dir/chrome" +} + grit("signin_internals_resources") { source = "signin_internals_resources.grd" defines = chrome_grit_defines diff --git a/chrome/browser/resources/md_policy/policy_resources.grd b/chrome/browser/resources/md_policy/policy_resources.grd new file mode 100644 index 0000000..50c9bcc --- /dev/null +++ b/chrome/browser/resources/md_policy/policy_resources.grd @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<grit latest_public_release="0" current_release="1"> + <outputs> + <output filename="grit/policy_resources.h" type="rc_header"> + <emit emit_type='prepend'></emit> + </output> + <output filename="grit/policy_resources_map.cc" + type="resource_file_map_source" /> + <output filename="grit/policy_resources_map.h" + type="resource_map_header" /> + <output filename="policy_resources.pak" type="data_package" /> + </outputs> + <release seq="1"> + <structures> + <!-- TODO(fhorschig): Add upcoming polymer files here. --> + <structure name="IDR_MD_POLICY_HTML" + file="md_policy.html" + type="chrome_html"/> + </structures> + </release> +</grit> diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index a148b21..03d36a0 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc @@ -84,6 +84,7 @@ #endif #if defined(ENABLE_CONFIGURATION_POLICY) +#include "chrome/browser/ui/webui/policy_material_design_ui.h" #include "chrome/browser/ui/webui/policy_ui.h" #endif diff --git a/chrome/browser/ui/webui/policy_material_design_ui.cc b/chrome/browser/ui/webui/policy_material_design_ui.cc new file mode 100644 index 0000000..e81dafd --- /dev/null +++ b/chrome/browser/ui/webui/policy_material_design_ui.cc @@ -0,0 +1,97 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/policy_material_design_ui.h" + +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/policy_ui_handler.h" +#include "chrome/common/url_constants.h" +#include "components/policy/core/common/policy_types.h" +#include "grit/components_strings.h" +#include "grit/policy_resources.h" +#include "grit/policy_resources_map.h" +#include "policy/policy_constants.h" +#include "policy/risk_tag.h" + +namespace { + +// Strings that map from policy::RiskTag enum to i18n string keys and their IDs. +// Their order has to follow the order of the policy::RiskTag enum. +const PolicyStringMap kPolicyRiskTags[policy::RISK_TAG_COUNT] = { + {"fullAdminAccess", IDS_POLICY_RISK_TAG_FULL_ADMIN_ACCESS}, + {"systemSecurity", IDS_POLICY_RISK_TAG_SYSTEM_SECURITY}, + {"websiteSharing", IDS_POLICY_RISK_TAG_WEBSITE_SHARING}, + {"adminSharing", IDS_POLICY_RISK_TAG_ADMIN_SHARING}, + {"filtering", IDS_POLICY_RISK_TAG_FILTERING}, + {"localDataAccess", IDS_POLICY_RISK_TAG_LOCAL_DATA_ACCESS}, + {"googleSharing", IDS_POLICY_RISK_TAG_GOOGLE_SHARING}, +}; + +content::WebUIDataSource* CreatePolicyMaterialDesignUIHtmlSource() { + content::WebUIDataSource* source = + content::WebUIDataSource::Create(chrome::kChromeUIMdPolicyHost); + PolicyUIHandler::AddCommonLocalizedStringsToSource(source); + PolicyUIHandler::AddLocalizedPolicyStrings( + source, kPolicyRiskTags, static_cast<size_t>(policy::RISK_TAG_COUNT)); + for (size_t i = 0; i < kPolicyResourcesSize; ++i) { + source->AddResourcePath(kPolicyResources[i].name, + kPolicyResources[i].value); + } + source->SetDefaultResource(IDR_MD_POLICY_HTML); + return source; +} + +} // namespace + +// The JavaScript message handler for the chrome://md-policy page. +class PolicyMaterialDesignUIHandler : public PolicyUIHandler { + public: + PolicyMaterialDesignUIHandler(); + ~PolicyMaterialDesignUIHandler() override; + + protected: + // PolicyUIHandler: + void AddPolicyName(const std::string& name, + base::DictionaryValue* names) const override; + void SendPolicyNames() const override; + + private: + DISALLOW_COPY_AND_ASSIGN(PolicyMaterialDesignUIHandler); +}; + +PolicyMaterialDesignUIHandler::PolicyMaterialDesignUIHandler() { +} + +PolicyMaterialDesignUIHandler::~PolicyMaterialDesignUIHandler() { +} + +void PolicyMaterialDesignUIHandler::AddPolicyName( + const std::string& name, base::DictionaryValue* names) const { + scoped_ptr<base::ListValue> list(new base::ListValue()); + const policy::RiskTag* tags = policy::GetChromePolicyDetails(name)->risk_tags; + for (size_t i = 0; i < policy::kMaxRiskTagCount; ++i) { + if (tags[i] != policy::RISK_TAG_NONE) + list->AppendString(kPolicyRiskTags[tags[i]].key); + } + names->Set(name, list.Pass()); +} + +void PolicyMaterialDesignUIHandler::SendPolicyNames() const { + base::ListValue tags; + for (size_t tag = 0; tag < policy::RISK_TAG_COUNT; ++tag) + tags.AppendString(kPolicyRiskTags[tag].key); + + web_ui()->CallJavascriptFunction("policy.Page.setPolicyGroups", tags); + PolicyUIHandler::SendPolicyNames(); +} + +PolicyMaterialDesignUI::PolicyMaterialDesignUI(content::WebUI* web_ui) : + WebUIController(web_ui) { + web_ui->AddMessageHandler(new PolicyMaterialDesignUIHandler); + content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), + CreatePolicyMaterialDesignUIHtmlSource()); +} + +PolicyMaterialDesignUI::~PolicyMaterialDesignUI() { +} diff --git a/chrome/browser/ui/webui/policy_material_design_ui.h b/chrome/browser/ui/webui/policy_material_design_ui.h new file mode 100644 index 0000000..ecf7eb1 --- /dev/null +++ b/chrome/browser/ui/webui/policy_material_design_ui.h @@ -0,0 +1,25 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_POLICY_MATERIAL_DESIGN_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_POLICY_MATERIAL_DESIGN_UI_H_ + +#include "base/macros.h" +#include "content/public/browser/web_ui_controller.h" + +namespace content { +class WebUI; +} + +// The Web UI controller for the chrome://md-policy page. +class PolicyMaterialDesignUI : public content::WebUIController { + public: + explicit PolicyMaterialDesignUI(content::WebUI* web_ui); + ~PolicyMaterialDesignUI() override; + + private: + DISALLOW_COPY_AND_ASSIGN(PolicyMaterialDesignUI); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_POLICY_MATERIAL_DESIGN_UI_H_ diff --git a/chrome/browser/ui/webui/policy_ui.cc b/chrome/browser/ui/webui/policy_ui.cc index 3f768e0..f4ca756 100644 --- a/chrome/browser/ui/webui/policy_ui.cc +++ b/chrome/browser/ui/webui/policy_ui.cc @@ -4,105 +4,19 @@ #include "chrome/browser/ui/webui/policy_ui.h" -#include <stddef.h> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/json/json_writer.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "base/strings/string16.h" -#include "base/time/time.h" -#include "base/values.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/policy/profile_policy_connector.h" -#include "chrome/browser/policy/profile_policy_connector_factory.h" -#include "chrome/browser/policy/schema_registry_service.h" -#include "chrome/browser/policy/schema_registry_service_factory.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/policy_ui_handler.h" #include "chrome/common/url_constants.h" -#include "components/policy/core/browser/browser_policy_connector.h" -#include "components/policy/core/browser/cloud/message_util.h" -#include "components/policy/core/browser/configuration_policy_handler_list.h" -#include "components/policy/core/browser/policy_error_map.h" -#include "components/policy/core/common/cloud/cloud_policy_client.h" -#include "components/policy/core/common/cloud/cloud_policy_constants.h" -#include "components/policy/core/common/cloud/cloud_policy_core.h" -#include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h" -#include "components/policy/core/common/cloud/cloud_policy_store.h" -#include "components/policy/core/common/cloud/cloud_policy_validator.h" -#include "components/policy/core/common/policy_map.h" -#include "components/policy/core/common/policy_namespace.h" -#include "components/policy/core/common/policy_service.h" -#include "components/policy/core/common/policy_types.h" -#include "components/policy/core/common/remote_commands/remote_commands_service.h" -#include "components/policy/core/common/schema.h" -#include "components/policy/core/common/schema_map.h" -#include "components/policy/core/common/schema_registry.h" -#include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" -#include "content/public/browser/web_ui_data_source.h" -#include "content/public/browser/web_ui_message_handler.h" -#include "google_apis/gaia/gaia_auth_util.h" #include "grit/browser_resources.h" #include "grit/components_strings.h" -#include "policy/policy_constants.h" -#include "policy/proto/device_management_backend.pb.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/l10n/time_format.h" - -#if defined(OS_CHROMEOS) -#include "chrome/browser/browser_process_platform_part.h" -#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" -#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h" -#include "chrome/browser/chromeos/policy/device_local_account_policy_service.h" -#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h" -#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h" -#include "components/user_manager/user_manager.h" -#else -#include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h" -#include "components/policy/core/common/cloud/user_cloud_policy_manager.h" -#endif - -#if defined(ENABLE_EXTENSIONS) -#include "extensions/browser/extension_registry.h" -#include "extensions/browser/extension_registry_observer.h" -#include "extensions/common/extension.h" -#include "extensions/common/manifest.h" -#include "extensions/common/manifest_constants.h" -#endif - -namespace em = enterprise_management; namespace { -struct PolicySourceMap { - const char* key; - int string_id; -}; - -// Strings that map from PolicySource enum to i18n string keys and their IDs. -const PolicySourceMap kPolicySources[policy::POLICY_SOURCE_COUNT] = { - {"sourceEnterpriseDefault", IDS_POLICY_SOURCE_ENTERPRISE_DEFAULT}, - {"sourceCloud", IDS_POLICY_SOURCE_CLOUD}, - {"sourcePublicSessionOverride", IDS_POLICY_SOURCE_PUBLIC_SESSION_OVERRIDE}, - {"sourcePlatform", IDS_POLICY_SOURCE_PLATFORM} -}; - -void AddLocalizedPoilcySourceStrings(content::WebUIDataSource* source) { - DCHECK_EQ(static_cast<size_t>(policy::POLICY_SOURCE_COUNT), - arraysize(kPolicySources)); - for (size_t i = 0; i < arraysize(kPolicySources); ++i) { - source->AddLocalizedString(kPolicySources[i].key, - kPolicySources[i].string_id); - } -} - -void AddCommonLocalizedStringsToSource(content::WebUIDataSource* source) { - source->AddLocalizedString("title", IDS_POLICY_TITLE); +content::WebUIDataSource* CreatePolicyUIHtmlSource() { + content::WebUIDataSource* source = + content::WebUIDataSource::Create(chrome::kChromeUIPolicyHost); + PolicyUIHandler::AddCommonLocalizedStringsToSource(source); source->AddLocalizedString("filterPlaceholder", IDS_POLICY_FILTER_PLACEHOLDER); source->AddLocalizedString("reloadPolicies", IDS_POLICY_RELOAD_POLICIES); @@ -123,757 +37,20 @@ void AddCommonLocalizedStringsToSource(content::WebUIDataSource* source) { source->AddLocalizedString("labelStatus", IDS_POLICY_LABEL_STATUS); source->AddLocalizedString("showUnset", IDS_POLICY_SHOW_UNSET); source->AddLocalizedString("noPoliciesSet", IDS_POLICY_NO_POLICIES_SET); - source->AddLocalizedString("headerScope", IDS_POLICY_HEADER_SCOPE); - source->AddLocalizedString("headerLevel", IDS_POLICY_HEADER_LEVEL); - source->AddLocalizedString("headerName", IDS_POLICY_HEADER_NAME); - source->AddLocalizedString("headerValue", IDS_POLICY_HEADER_VALUE); - source->AddLocalizedString("headerStatus", IDS_POLICY_HEADER_STATUS); - source->AddLocalizedString("headerSource", IDS_POLICY_HEADER_SOURCE); source->AddLocalizedString("showExpandedValue", IDS_POLICY_SHOW_EXPANDED_VALUE); source->AddLocalizedString("hideExpandedValue", IDS_POLICY_HIDE_EXPANDED_VALUE); - source->AddLocalizedString("scopeUser", IDS_POLICY_SCOPE_USER); - source->AddLocalizedString("scopeDevice", IDS_POLICY_SCOPE_DEVICE); - source->AddLocalizedString("levelRecommended", IDS_POLICY_LEVEL_RECOMMENDED); - source->AddLocalizedString("levelMandatory", IDS_POLICY_LEVEL_MANDATORY); - source->AddLocalizedString("ok", IDS_POLICY_OK); - source->AddLocalizedString("unset", IDS_POLICY_UNSET); - source->AddLocalizedString("unknown", IDS_POLICY_UNKNOWN); - source->AddLocalizedString("notSpecified", IDS_POLICY_NOT_SPECIFIED); - AddLocalizedPoilcySourceStrings(source); - - source->SetJsonPath("strings.js"); -} - -content::WebUIDataSource* CreatePolicyMaterialDesignUIHtmlSource() { - content::WebUIDataSource* source = - content::WebUIDataSource::Create(chrome::kChromeUIMdPolicyHost); - AddCommonLocalizedStringsToSource(source); - source->SetDefaultResource(IDR_MD_POLICY_HTML); - - return source; -} - - -content::WebUIDataSource* CreatePolicyUIHtmlSource() { - content::WebUIDataSource* source = - content::WebUIDataSource::Create(chrome::kChromeUIPolicyHost); - AddCommonLocalizedStringsToSource(source); // Add required resources. source->AddResourcePath("policy.css", IDR_POLICY_CSS); source->AddResourcePath("policy.js", IDR_POLICY_JS); source->AddResourcePath("uber_utils.js", IDR_UBER_UTILS_JS); source->SetDefaultResource(IDR_POLICY_HTML); - return source; } -// Formats the association state indicated by |data|. If |data| is NULL, the -// state is considered to be UNMANAGED. -base::string16 FormatAssociationState(const em::PolicyData* data) { - if (data) { - switch (data->state()) { - case em::PolicyData::ACTIVE: - return l10n_util::GetStringUTF16(IDS_POLICY_ASSOCIATION_STATE_ACTIVE); - case em::PolicyData::UNMANAGED: - return l10n_util::GetStringUTF16( - IDS_POLICY_ASSOCIATION_STATE_UNMANAGED); - case em::PolicyData::DEPROVISIONED: - return l10n_util::GetStringUTF16( - IDS_POLICY_ASSOCIATION_STATE_DEPROVISIONED); - } - NOTREACHED() << "Unknown state " << data->state(); - } - - // Default to UNMANAGED for the case of missing policy or bad state enum. - return l10n_util::GetStringUTF16(IDS_POLICY_ASSOCIATION_STATE_UNMANAGED); -} - -void GetStatusFromCore(const policy::CloudPolicyCore* core, - base::DictionaryValue* dict) { - const policy::CloudPolicyStore* store = core->store(); - const policy::CloudPolicyClient* client = core->client(); - const policy::CloudPolicyRefreshScheduler* refresh_scheduler = - core->refresh_scheduler(); - - // CloudPolicyStore errors take precedence to show in the status message. - // Other errors (such as transient policy fetching problems) get displayed - // only if CloudPolicyStore is in STATUS_OK. - base::string16 status = - policy::FormatStoreStatus(store->status(), store->validation_status()); - if (store->status() == policy::CloudPolicyStore::STATUS_OK) { - if (client && client->status() != policy::DM_STATUS_SUCCESS) - status = policy::FormatDeviceManagementStatus(client->status()); - else if (!store->is_managed()) - status = FormatAssociationState(store->policy()); - } - - const em::PolicyData* policy = store->policy(); - std::string client_id = policy ? policy->device_id() : std::string(); - std::string username = policy ? policy->username() : std::string(); - - if (policy && policy->has_annotated_asset_id()) - dict->SetString("assetId", policy->annotated_asset_id()); - if (policy && policy->has_annotated_location()) - dict->SetString("location", policy->annotated_location()); - if (policy && policy->has_directory_api_id()) - dict->SetString("directoryApiId", policy->directory_api_id()); - - base::TimeDelta refresh_interval = - base::TimeDelta::FromMilliseconds(refresh_scheduler ? - refresh_scheduler->refresh_delay() : - policy::CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs); - base::Time last_refresh_time = refresh_scheduler ? - refresh_scheduler->last_refresh() : base::Time(); - - bool no_error = store->status() == policy::CloudPolicyStore::STATUS_OK && - client && client->status() == policy::DM_STATUS_SUCCESS; - dict->SetBoolean("error", !no_error); - dict->SetString("status", status); - dict->SetString("clientId", client_id); - dict->SetString("username", username); - dict->SetString("refreshInterval", - ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_DURATION, - ui::TimeFormat::LENGTH_SHORT, - refresh_interval)); - dict->SetString("timeSinceLastRefresh", last_refresh_time.is_null() ? - l10n_util::GetStringUTF16(IDS_POLICY_NEVER_FETCHED) : - ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_ELAPSED, - ui::TimeFormat::LENGTH_SHORT, - base::Time::NowFromSystemTime() - - last_refresh_time)); -} - -void ExtractDomainFromUsername(base::DictionaryValue* dict) { - std::string username; - dict->GetString("username", &username); - if (!username.empty()) - dict->SetString("domain", gaia::ExtractDomainName(username)); -} - -// Utility function that returns a JSON serialization of the given |dict|. -scoped_ptr<base::StringValue> DictionaryToJSONString( - const base::DictionaryValue& dict) { - std::string json_string; - base::JSONWriter::WriteWithOptions(dict, - base::JSONWriter::OPTIONS_PRETTY_PRINT, - &json_string); - return make_scoped_ptr(new base::StringValue(json_string)); -} - -// Returns a copy of |value| with some values converted to a representation that -// i18n_template.js will display in a nicer way. -scoped_ptr<base::Value> CopyAndConvert(const base::Value* value) { - const base::DictionaryValue* dict = NULL; - if (value->GetAsDictionary(&dict)) - return DictionaryToJSONString(*dict); - - scoped_ptr<base::Value> copy(value->DeepCopy()); - base::ListValue* list = NULL; - if (copy->GetAsList(&list)) { - for (size_t i = 0; i < list->GetSize(); ++i) { - if (list->GetDictionary(i, &dict)) - list->Set(i, DictionaryToJSONString(*dict).release()); - } - } - - return copy.Pass(); -} - } // namespace -// An interface for querying the status of cloud policy. -class CloudPolicyStatusProvider { - public: - CloudPolicyStatusProvider(); - virtual ~CloudPolicyStatusProvider(); - - // Sets a callback to invoke upon status changes. - void SetStatusChangeCallback(const base::Closure& callback); - - virtual void GetStatus(base::DictionaryValue* dict); - - protected: - void NotifyStatusChange(); - - private: - base::Closure callback_; - - DISALLOW_COPY_AND_ASSIGN(CloudPolicyStatusProvider); -}; - -// Status provider implementation that pulls cloud policy status from a -// CloudPolicyCore instance provided at construction time. Also listens for -// changes on that CloudPolicyCore and reports them through the status change -// callback. -class CloudPolicyCoreStatusProvider - : public CloudPolicyStatusProvider, - public policy::CloudPolicyStore::Observer { - public: - explicit CloudPolicyCoreStatusProvider(policy::CloudPolicyCore* core); - ~CloudPolicyCoreStatusProvider() override; - - // policy::CloudPolicyStore::Observer implementation. - void OnStoreLoaded(policy::CloudPolicyStore* store) override; - void OnStoreError(policy::CloudPolicyStore* store) override; - - protected: - // Policy status is read from the CloudPolicyClient, CloudPolicyStore and - // CloudPolicyRefreshScheduler hosted by this |core_|. - policy::CloudPolicyCore* core_; - - private: - DISALLOW_COPY_AND_ASSIGN(CloudPolicyCoreStatusProvider); -}; - -// A cloud policy status provider for user policy. -class UserPolicyStatusProvider : public CloudPolicyCoreStatusProvider { - public: - explicit UserPolicyStatusProvider(policy::CloudPolicyCore* core); - ~UserPolicyStatusProvider() override; - - // CloudPolicyCoreStatusProvider implementation. - void GetStatus(base::DictionaryValue* dict) override; - - private: - DISALLOW_COPY_AND_ASSIGN(UserPolicyStatusProvider); -}; - -#if defined(OS_CHROMEOS) -// A cloud policy status provider for device policy. -class DevicePolicyStatusProvider : public CloudPolicyCoreStatusProvider { - public: - explicit DevicePolicyStatusProvider( - policy::BrowserPolicyConnectorChromeOS* connector); - ~DevicePolicyStatusProvider() override; - - // CloudPolicyCoreStatusProvider implementation. - void GetStatus(base::DictionaryValue* dict) override; - - private: - std::string domain_; - - DISALLOW_COPY_AND_ASSIGN(DevicePolicyStatusProvider); -}; - -// A cloud policy status provider that reads policy status from the policy core -// associated with the device-local account specified by |user_id| at -// construction time. The indirection via user ID and -// DeviceLocalAccountPolicyService is necessary because the device-local account -// may go away any time behind the scenes, at which point the status message -// text will indicate CloudPolicyStore::STATUS_BAD_STATE. -class DeviceLocalAccountPolicyStatusProvider - : public CloudPolicyStatusProvider, - public policy::DeviceLocalAccountPolicyService::Observer { - public: - DeviceLocalAccountPolicyStatusProvider( - const std::string& user_id, - policy::DeviceLocalAccountPolicyService* service); - ~DeviceLocalAccountPolicyStatusProvider() override; - - // CloudPolicyStatusProvider implementation. - void GetStatus(base::DictionaryValue* dict) override; - - // policy::DeviceLocalAccountPolicyService::Observer implementation. - void OnPolicyUpdated(const std::string& user_id) override; - void OnDeviceLocalAccountsChanged() override; - - private: - const std::string user_id_; - policy::DeviceLocalAccountPolicyService* service_; - - DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountPolicyStatusProvider); -}; -#endif - -// The JavaScript message handler for the chrome://policy page. -class PolicyUIHandler : public content::WebUIMessageHandler, -#if defined(ENABLE_EXTENSIONS) - public extensions::ExtensionRegistryObserver, -#endif - public policy::PolicyService::Observer, - public policy::SchemaRegistry::Observer { - public: - PolicyUIHandler(); - ~PolicyUIHandler() override; - - // content::WebUIMessageHandler implementation. - void RegisterMessages() override; - -#if defined(ENABLE_EXTENSIONS) - // extensions::ExtensionRegistryObserver implementation. - void OnExtensionLoaded(content::BrowserContext* browser_context, - const extensions::Extension* extension) override; - void OnExtensionUnloaded( - content::BrowserContext* browser_context, - const extensions::Extension* extension, - extensions::UnloadedExtensionInfo::Reason reason) override; -#endif - - // policy::PolicyService::Observer implementation. - void OnPolicyUpdated(const policy::PolicyNamespace& ns, - const policy::PolicyMap& previous, - const policy::PolicyMap& current) override; - - // policy::SchemaRegistry::Observer implementation. - void OnSchemaRegistryUpdated(bool has_new_schemas) override; - - private: - // Send a dictionary containing the names of all known policies to the UI. - void SendPolicyNames() const; - - // Send information about the current policy values to the UI. For each policy - // whose value has been set, a dictionary containing the value and additional - // metadata is sent. - void SendPolicyValues() const; - - // Send the status of cloud policy to the UI. For each scope that has cloud - // policy enabled (device and/or user), a dictionary containing status - // information is sent. - void SendStatus() const; - - // Inserts a description of each policy in |policy_map| into |values|, using - // the optional errors in |errors| to determine the status of each policy. - void GetPolicyValues(const policy::PolicyMap& policy_map, - policy::PolicyErrorMap* errors, - base::DictionaryValue* values) const; - - void GetChromePolicyValues(base::DictionaryValue* values) const; - - void HandleInitialized(const base::ListValue* args); - void HandleReloadPolicies(const base::ListValue* args); - - void OnRefreshPoliciesDone() const; - - policy::PolicyService* GetPolicyService() const; - - std::string device_domain_; - - // Providers that supply status dictionaries for user and device policy, - // respectively. These are created on initialization time as appropriate for - // the platform (Chrome OS / desktop) and type of policy that is in effect. - scoped_ptr<CloudPolicyStatusProvider> user_status_provider_; - scoped_ptr<CloudPolicyStatusProvider> device_status_provider_; - - base::WeakPtrFactory<PolicyUIHandler> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(PolicyUIHandler); -}; - -CloudPolicyStatusProvider::CloudPolicyStatusProvider() { -} - -CloudPolicyStatusProvider::~CloudPolicyStatusProvider() { -} - -void CloudPolicyStatusProvider::SetStatusChangeCallback( - const base::Closure& callback) { - callback_ = callback; -} - -void CloudPolicyStatusProvider::GetStatus(base::DictionaryValue* dict) { -} - -void CloudPolicyStatusProvider::NotifyStatusChange() { - if (!callback_.is_null()) - callback_.Run(); -} - -CloudPolicyCoreStatusProvider::CloudPolicyCoreStatusProvider( - policy::CloudPolicyCore* core) : core_(core) { - core_->store()->AddObserver(this); - // TODO(bartfab): Add an observer that watches for client errors. Observing - // core_->client() directly is not safe as the client may be destroyed and - // (re-)created anytime if the user signs in or out on desktop platforms. -} - -CloudPolicyCoreStatusProvider::~CloudPolicyCoreStatusProvider() { - core_->store()->RemoveObserver(this); -} - -void CloudPolicyCoreStatusProvider::OnStoreLoaded( - policy::CloudPolicyStore* store) { - NotifyStatusChange(); -} - -void CloudPolicyCoreStatusProvider::OnStoreError( - policy::CloudPolicyStore* store) { - NotifyStatusChange(); -} - -UserPolicyStatusProvider::UserPolicyStatusProvider( - policy::CloudPolicyCore* core) : CloudPolicyCoreStatusProvider(core) { -} - -UserPolicyStatusProvider::~UserPolicyStatusProvider() { -} - -void UserPolicyStatusProvider::GetStatus(base::DictionaryValue* dict) { - if (!core_->store()->is_managed()) - return; - GetStatusFromCore(core_, dict); - ExtractDomainFromUsername(dict); -} - -#if defined(OS_CHROMEOS) -DevicePolicyStatusProvider::DevicePolicyStatusProvider( - policy::BrowserPolicyConnectorChromeOS* connector) - : CloudPolicyCoreStatusProvider( - connector->GetDeviceCloudPolicyManager()->core()) { - domain_ = connector->GetEnterpriseDomain(); -} - -DevicePolicyStatusProvider::~DevicePolicyStatusProvider() { -} - -void DevicePolicyStatusProvider::GetStatus(base::DictionaryValue* dict) { - GetStatusFromCore(core_, dict); - dict->SetString("domain", domain_); -} - -DeviceLocalAccountPolicyStatusProvider::DeviceLocalAccountPolicyStatusProvider( - const std::string& user_id, - policy::DeviceLocalAccountPolicyService* service) - : user_id_(user_id), - service_(service) { - service_->AddObserver(this); -} - -DeviceLocalAccountPolicyStatusProvider:: - ~DeviceLocalAccountPolicyStatusProvider() { - service_->RemoveObserver(this); -} - -void DeviceLocalAccountPolicyStatusProvider::GetStatus( - base::DictionaryValue* dict) { - const policy::DeviceLocalAccountPolicyBroker* broker = - service_->GetBrokerForUser(user_id_); - if (broker) { - GetStatusFromCore(broker->core(), dict); - } else { - dict->SetBoolean("error", true); - dict->SetString("status", - policy::FormatStoreStatus( - policy::CloudPolicyStore::STATUS_BAD_STATE, - policy::CloudPolicyValidatorBase::VALIDATION_OK)); - dict->SetString("username", std::string()); - } - ExtractDomainFromUsername(dict); - dict->SetBoolean("publicAccount", true); -} - -void DeviceLocalAccountPolicyStatusProvider::OnPolicyUpdated( - const std::string& user_id) { - if (user_id == user_id_) - NotifyStatusChange(); -} - -void DeviceLocalAccountPolicyStatusProvider::OnDeviceLocalAccountsChanged() { - NotifyStatusChange(); -} -#endif - -PolicyUIHandler::PolicyUIHandler() - : weak_factory_(this) { -} - -PolicyUIHandler::~PolicyUIHandler() { - GetPolicyService()->RemoveObserver(policy::POLICY_DOMAIN_CHROME, this); - GetPolicyService()->RemoveObserver(policy::POLICY_DOMAIN_EXTENSIONS, this); - policy::SchemaRegistry* registry = - policy::SchemaRegistryServiceFactory::GetForContext( - Profile::FromWebUI(web_ui())->GetOriginalProfile())->registry(); - registry->RemoveObserver(this); - -#if defined(ENABLE_EXTENSIONS) - extensions::ExtensionRegistry::Get(Profile::FromWebUI(web_ui())) - ->RemoveObserver(this); -#endif -} - -void PolicyUIHandler::RegisterMessages() { -#if defined(OS_CHROMEOS) - policy::BrowserPolicyConnectorChromeOS* connector = - g_browser_process->platform_part()->browser_policy_connector_chromeos(); - if (connector->IsEnterpriseManaged()) - device_status_provider_.reset(new DevicePolicyStatusProvider(connector)); - - const user_manager::UserManager* user_manager = - user_manager::UserManager::Get(); - if (user_manager->IsLoggedInAsPublicAccount()) { - policy::DeviceLocalAccountPolicyService* local_account_service = - connector->GetDeviceLocalAccountPolicyService(); - if (local_account_service) { - user_status_provider_.reset( - new DeviceLocalAccountPolicyStatusProvider( - user_manager->GetLoggedInUser()->email(), local_account_service)); - } - } else { - policy::UserCloudPolicyManagerChromeOS* user_cloud_policy_manager = - policy::UserCloudPolicyManagerFactoryChromeOS::GetForProfile( - Profile::FromWebUI(web_ui())); - if (user_cloud_policy_manager) { - user_status_provider_.reset( - new UserPolicyStatusProvider(user_cloud_policy_manager->core())); - } - } -#else - policy::UserCloudPolicyManager* user_cloud_policy_manager = - policy::UserCloudPolicyManagerFactory::GetForBrowserContext( - web_ui()->GetWebContents()->GetBrowserContext()); - if (user_cloud_policy_manager) { - user_status_provider_.reset( - new UserPolicyStatusProvider(user_cloud_policy_manager->core())); - } -#endif - - if (!user_status_provider_.get()) - user_status_provider_.reset(new CloudPolicyStatusProvider()); - if (!device_status_provider_.get()) - device_status_provider_.reset(new CloudPolicyStatusProvider()); - - base::Closure update_callback(base::Bind(&PolicyUIHandler::SendStatus, - base::Unretained(this))); - user_status_provider_->SetStatusChangeCallback(update_callback); - device_status_provider_->SetStatusChangeCallback(update_callback); - GetPolicyService()->AddObserver(policy::POLICY_DOMAIN_CHROME, this); - GetPolicyService()->AddObserver(policy::POLICY_DOMAIN_EXTENSIONS, this); - -#if defined(ENABLE_EXTENSIONS) - extensions::ExtensionRegistry::Get(Profile::FromWebUI(web_ui())) - ->AddObserver(this); -#endif - policy::SchemaRegistry* registry = - policy::SchemaRegistryServiceFactory::GetForContext( - Profile::FromWebUI(web_ui())->GetOriginalProfile())->registry(); - registry->AddObserver(this); - - web_ui()->RegisterMessageCallback( - "initialized", - base::Bind(&PolicyUIHandler::HandleInitialized, base::Unretained(this))); - web_ui()->RegisterMessageCallback( - "reloadPolicies", - base::Bind(&PolicyUIHandler::HandleReloadPolicies, - base::Unretained(this))); -} - -#if defined(ENABLE_EXTENSIONS) -void PolicyUIHandler::OnExtensionLoaded( - content::BrowserContext* browser_context, - const extensions::Extension* extension) { - SendPolicyNames(); - SendPolicyValues(); -} - -void PolicyUIHandler::OnExtensionUnloaded( - content::BrowserContext* browser_context, - const extensions::Extension* extension, - extensions::UnloadedExtensionInfo::Reason reason) { - SendPolicyNames(); - SendPolicyValues(); -} -#endif - -void PolicyUIHandler::OnSchemaRegistryUpdated(bool has_new_schemas) { - // Update UI when new schema is added. - if (has_new_schemas) { - SendPolicyNames(); - SendPolicyValues(); - } -} - -void PolicyUIHandler::OnPolicyUpdated(const policy::PolicyNamespace& ns, - const policy::PolicyMap& previous, - const policy::PolicyMap& current) { - SendPolicyValues(); -} - -void PolicyUIHandler::SendPolicyNames() const { - base::DictionaryValue names; - - Profile* profile = Profile::FromWebUI(web_ui()); - policy::SchemaRegistry* registry = - policy::SchemaRegistryServiceFactory::GetForContext( - profile->GetOriginalProfile())->registry(); - scoped_refptr<policy::SchemaMap> schema_map = registry->schema_map(); - - // Add Chrome policy names. - base::DictionaryValue* chrome_policy_names = new base::DictionaryValue; - policy::PolicyNamespace chrome_ns(policy::POLICY_DOMAIN_CHROME, ""); - const policy::Schema* chrome_schema = schema_map->GetSchema(chrome_ns); - for (policy::Schema::Iterator it = chrome_schema->GetPropertiesIterator(); - !it.IsAtEnd(); it.Advance()) { - chrome_policy_names->SetBoolean(it.key(), true); - } - names.Set("chromePolicyNames", chrome_policy_names); - -#if defined(ENABLE_EXTENSIONS) - // Add extension policy names. - base::DictionaryValue* extension_policy_names = new base::DictionaryValue; - - for (const scoped_refptr<const extensions::Extension>& extension : - extensions::ExtensionRegistry::Get(profile)->enabled_extensions()) { - // Skip this extension if it's not an enterprise extension. - if (!extension->manifest()->HasPath( - extensions::manifest_keys::kStorageManagedSchema)) - continue; - base::DictionaryValue* extension_value = new base::DictionaryValue; - extension_value->SetString("name", extension->name()); - const policy::Schema* schema = - schema_map->GetSchema(policy::PolicyNamespace( - policy::POLICY_DOMAIN_EXTENSIONS, extension->id())); - base::DictionaryValue* policy_names = new base::DictionaryValue; - if (schema && schema->valid()) { - // Get policy names from the extension's policy schema. - // Store in a map, not an array, for faster lookup on JS side. - for (policy::Schema::Iterator prop = schema->GetPropertiesIterator(); - !prop.IsAtEnd(); prop.Advance()) { - policy_names->SetBoolean(prop.key(), true); - } - } - extension_value->Set("policyNames", policy_names); - extension_policy_names->Set(extension->id(), extension_value); - } - names.Set("extensionPolicyNames", extension_policy_names); -#endif // defined(ENABLE_EXTENSIONS) - - web_ui()->CallJavascriptFunction("policy.Page.setPolicyNames", names); -} - -void PolicyUIHandler::SendPolicyValues() const { - base::DictionaryValue all_policies; - - // Add Chrome policy values. - base::DictionaryValue* chrome_policies = new base::DictionaryValue; - GetChromePolicyValues(chrome_policies); - all_policies.Set("chromePolicies", chrome_policies); - -#if defined(ENABLE_EXTENSIONS) - // Add extension policy values. - extensions::ExtensionRegistry* registry = - extensions::ExtensionRegistry::Get(Profile::FromWebUI(web_ui())); - base::DictionaryValue* extension_values = new base::DictionaryValue; - - for (const scoped_refptr<const extensions::Extension>& extension : - registry->enabled_extensions()) { - // Skip this extension if it's not an enterprise extension. - if (!extension->manifest()->HasPath( - extensions::manifest_keys::kStorageManagedSchema)) - continue; - base::DictionaryValue* extension_policies = new base::DictionaryValue; - policy::PolicyNamespace policy_namespace = policy::PolicyNamespace( - policy::POLICY_DOMAIN_EXTENSIONS, extension->id()); - policy::PolicyErrorMap empty_error_map; - GetPolicyValues(GetPolicyService()->GetPolicies(policy_namespace), - &empty_error_map, extension_policies); - extension_values->Set(extension->id(), extension_policies); - } - all_policies.Set("extensionPolicies", extension_values); -#endif - web_ui()->CallJavascriptFunction("policy.Page.setPolicyValues", all_policies); -} - -void PolicyUIHandler::GetPolicyValues(const policy::PolicyMap& map, - policy::PolicyErrorMap* errors, - base::DictionaryValue* values) const { - for (policy::PolicyMap::const_iterator entry = map.begin(); - entry != map.end(); ++entry) { - base::DictionaryValue* value = new base::DictionaryValue; - value->Set("value", CopyAndConvert(entry->second.value).release()); - if (entry->second.scope == policy::POLICY_SCOPE_USER) - value->SetString("scope", "user"); - else - value->SetString("scope", "machine"); - if (entry->second.level == policy::POLICY_LEVEL_RECOMMENDED) - value->SetString("level", "recommended"); - else - value->SetString("level", "mandatory"); - value->SetString("source", kPolicySources[entry->second.source].key); - base::string16 error = errors->GetErrors(entry->first); - if (!error.empty()) - value->SetString("error", error); - values->Set(entry->first, value); - } -} - -void PolicyUIHandler::GetChromePolicyValues( - base::DictionaryValue* values) const { - policy::PolicyService* policy_service = GetPolicyService(); - policy::PolicyMap map; - - // Make a copy that can be modified, since some policy values are modified - // before being displayed. - map.CopyFrom(policy_service->GetPolicies( - policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string()))); - - // Get a list of all the errors in the policy values. - const policy::ConfigurationPolicyHandlerList* handler_list = - g_browser_process->browser_policy_connector()->GetHandlerList(); - policy::PolicyErrorMap errors; - handler_list->ApplyPolicySettings(map, NULL, &errors); - - // Convert dictionary values to strings for display. - handler_list->PrepareForDisplaying(&map); - - GetPolicyValues(map, &errors, values); -} - -void PolicyUIHandler::SendStatus() const { - scoped_ptr<base::DictionaryValue> device_status(new base::DictionaryValue); - device_status_provider_->GetStatus(device_status.get()); - if (!device_domain_.empty()) - device_status->SetString("domain", device_domain_); - scoped_ptr<base::DictionaryValue> user_status(new base::DictionaryValue); - user_status_provider_->GetStatus(user_status.get()); - std::string username; - user_status->GetString("username", &username); - if (!username.empty()) - user_status->SetString("domain", gaia::ExtractDomainName(username)); - - base::DictionaryValue status; - if (!device_status->empty()) - status.Set("device", device_status.release()); - if (!user_status->empty()) - status.Set("user", user_status.release()); - - web_ui()->CallJavascriptFunction("policy.Page.setStatus", status); -} - -void PolicyUIHandler::HandleInitialized(const base::ListValue* args) { - SendPolicyNames(); - SendPolicyValues(); - SendStatus(); -} - -void PolicyUIHandler::HandleReloadPolicies(const base::ListValue* args) { -#if defined(OS_CHROMEOS) - // Allow user to manually fetch remote commands, in case invalidation - // service is not working properly. - // TODO(binjin): evaluate and possibly remove this after invalidation - // service is landed and tested. http://crbug.com/480982 - policy::BrowserPolicyConnectorChromeOS* connector = - g_browser_process->platform_part()->browser_policy_connector_chromeos(); - policy::RemoteCommandsService* remote_commands_service = - connector->GetDeviceCloudPolicyManager() - ->core() - ->remote_commands_service(); - if (remote_commands_service) - remote_commands_service->FetchRemoteCommands(); -#endif - GetPolicyService()->RefreshPolicies(base::Bind( - &PolicyUIHandler::OnRefreshPoliciesDone, weak_factory_.GetWeakPtr())); -} - -void PolicyUIHandler::OnRefreshPoliciesDone() const { - web_ui()->CallJavascriptFunction("policy.Page.reloadPoliciesDone"); -} - -policy::PolicyService* PolicyUIHandler::GetPolicyService() const { - return policy::ProfilePolicyConnectorFactory::GetForBrowserContext( - web_ui()->GetWebContents()->GetBrowserContext())->policy_service(); -} - PolicyUI::PolicyUI(content::WebUI* web_ui) : WebUIController(web_ui) { web_ui->AddMessageHandler(new PolicyUIHandler); content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), @@ -882,13 +59,3 @@ PolicyUI::PolicyUI(content::WebUI* web_ui) : WebUIController(web_ui) { PolicyUI::~PolicyUI() { } - -PolicyMaterialDesignUI::PolicyMaterialDesignUI(content::WebUI* web_ui) : - WebUIController(web_ui) { - web_ui->AddMessageHandler(new PolicyUIHandler); - content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), - CreatePolicyMaterialDesignUIHtmlSource()); -} - -PolicyMaterialDesignUI::~PolicyMaterialDesignUI() { -} diff --git a/chrome/browser/ui/webui/policy_ui.h b/chrome/browser/ui/webui/policy_ui.h index 4caf666..bbad641 100644 --- a/chrome/browser/ui/webui/policy_ui.h +++ b/chrome/browser/ui/webui/policy_ui.h @@ -24,14 +24,4 @@ class PolicyUI : public content::WebUIController { DISALLOW_COPY_AND_ASSIGN(PolicyUI); }; -// The Web UI controller for the chrome://md-policy page. -class PolicyMaterialDesignUI : public content::WebUIController { - public: - explicit PolicyMaterialDesignUI(content::WebUI* web_ui); - ~PolicyMaterialDesignUI() override; - - private: - DISALLOW_COPY_AND_ASSIGN(PolicyMaterialDesignUI); -}; - #endif // CHROME_BROWSER_UI_WEBUI_POLICY_UI_H_ diff --git a/chrome/browser/ui/webui/policy_ui_handler.cc b/chrome/browser/ui/webui/policy_ui_handler.cc new file mode 100644 index 0000000..d22cf51 --- /dev/null +++ b/chrome/browser/ui/webui/policy_ui_handler.cc @@ -0,0 +1,747 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/policy_ui_handler.h" + +#include <stddef.h> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/callback.h" +#include "base/compiler_specific.h" +#include "base/json/json_writer.h" +#include "base/logging.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/strings/string16.h" +#include "base/time/time.h" +#include "base/values.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/policy/profile_policy_connector.h" +#include "chrome/browser/policy/profile_policy_connector_factory.h" +#include "chrome/browser/policy/schema_registry_service.h" +#include "chrome/browser/policy/schema_registry_service_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "components/policy/core/browser/browser_policy_connector.h" +#include "components/policy/core/browser/cloud/message_util.h" +#include "components/policy/core/browser/configuration_policy_handler_list.h" +#include "components/policy/core/common/cloud/cloud_policy_client.h" +#include "components/policy/core/common/cloud/cloud_policy_constants.h" +#include "components/policy/core/common/cloud/cloud_policy_core.h" +#include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h" +#include "components/policy/core/common/cloud/cloud_policy_store.h" +#include "components/policy/core/common/cloud/cloud_policy_validator.h" +#include "components/policy/core/common/policy_details.h" +#include "components/policy/core/common/policy_types.h" +#include "components/policy/core/common/remote_commands/remote_commands_service.h" +#include "components/policy/core/common/schema.h" +#include "components/policy/core/common/schema_map.h" +#include "content/public/browser/web_contents.h" +#include "google_apis/gaia/gaia_auth_util.h" +#include "grit/components_strings.h" +#include "grit/policy_resources.h" +#include "grit/policy_resources_map.h" +#include "policy/policy_constants.h" +#include "policy/proto/device_management_backend.pb.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/l10n/time_format.h" + +#if defined(OS_CHROMEOS) +#include "chrome/browser/browser_process_platform_part.h" +#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" +#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h" +#include "chrome/browser/chromeos/policy/device_local_account_policy_service.h" +#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h" +#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h" +#include "components/user_manager/user_manager.h" +#else +#include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h" +#include "components/policy/core/common/cloud/user_cloud_policy_manager.h" +#endif + +#if defined(ENABLE_EXTENSIONS) +#include "extensions/browser/extension_registry.h" +#include "extensions/common/extension.h" +#include "extensions/common/manifest.h" +#include "extensions/common/manifest_constants.h" +#endif + +namespace em = enterprise_management; + +namespace { + +// Strings that map from PolicySource enum to i18n string keys and their IDs. +// Their order has to follow the order of the policy::PolicySource enum. +const PolicyStringMap kPolicySources[policy::POLICY_SOURCE_COUNT] = { + {"sourceEnterpriseDefault", IDS_POLICY_SOURCE_ENTERPRISE_DEFAULT}, + {"sourceCloud", IDS_POLICY_SOURCE_CLOUD}, + {"sourcePublicSessionOverride", IDS_POLICY_SOURCE_PUBLIC_SESSION_OVERRIDE}, + {"sourcePlatform", IDS_POLICY_SOURCE_PLATFORM}, +}; + +// Formats the association state indicated by |data|. If |data| is NULL, the +// state is considered to be UNMANAGED. +base::string16 FormatAssociationState(const em::PolicyData* data) { + if (data) { + switch (data->state()) { + case em::PolicyData::ACTIVE: + return l10n_util::GetStringUTF16(IDS_POLICY_ASSOCIATION_STATE_ACTIVE); + case em::PolicyData::UNMANAGED: + return l10n_util::GetStringUTF16( + IDS_POLICY_ASSOCIATION_STATE_UNMANAGED); + case em::PolicyData::DEPROVISIONED: + return l10n_util::GetStringUTF16( + IDS_POLICY_ASSOCIATION_STATE_DEPROVISIONED); + } + NOTREACHED() << "Unknown state " << data->state(); + } + + // Default to UNMANAGED for the case of missing policy or bad state enum. + return l10n_util::GetStringUTF16(IDS_POLICY_ASSOCIATION_STATE_UNMANAGED); +} + +void GetStatusFromCore(const policy::CloudPolicyCore* core, + base::DictionaryValue* dict) { + const policy::CloudPolicyStore* store = core->store(); + const policy::CloudPolicyClient* client = core->client(); + const policy::CloudPolicyRefreshScheduler* refresh_scheduler = + core->refresh_scheduler(); + + // CloudPolicyStore errors take precedence to show in the status message. + // Other errors (such as transient policy fetching problems) get displayed + // only if CloudPolicyStore is in STATUS_OK. + base::string16 status = + policy::FormatStoreStatus(store->status(), store->validation_status()); + if (store->status() == policy::CloudPolicyStore::STATUS_OK) { + if (client && client->status() != policy::DM_STATUS_SUCCESS) + status = policy::FormatDeviceManagementStatus(client->status()); + else if (!store->is_managed()) + status = FormatAssociationState(store->policy()); + } + + const em::PolicyData* policy = store->policy(); + std::string client_id = policy ? policy->device_id() : std::string(); + std::string username = policy ? policy->username() : std::string(); + + if (policy && policy->has_annotated_asset_id()) + dict->SetString("assetId", policy->annotated_asset_id()); + if (policy && policy->has_annotated_location()) + dict->SetString("location", policy->annotated_location()); + if (policy && policy->has_directory_api_id()) + dict->SetString("directoryApiId", policy->directory_api_id()); + + base::TimeDelta refresh_interval = + base::TimeDelta::FromMilliseconds(refresh_scheduler ? + refresh_scheduler->refresh_delay() : + policy::CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs); + base::Time last_refresh_time = refresh_scheduler ? + refresh_scheduler->last_refresh() : base::Time(); + + bool no_error = store->status() == policy::CloudPolicyStore::STATUS_OK && + client && client->status() == policy::DM_STATUS_SUCCESS; + dict->SetBoolean("error", !no_error); + dict->SetString("status", status); + dict->SetString("clientId", client_id); + dict->SetString("username", username); + dict->SetString("refreshInterval", + ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_DURATION, + ui::TimeFormat::LENGTH_SHORT, + refresh_interval)); + dict->SetString("timeSinceLastRefresh", last_refresh_time.is_null() ? + l10n_util::GetStringUTF16(IDS_POLICY_NEVER_FETCHED) : + ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_ELAPSED, + ui::TimeFormat::LENGTH_SHORT, + base::Time::NowFromSystemTime() - + last_refresh_time)); +} + +void ExtractDomainFromUsername(base::DictionaryValue* dict) { + std::string username; + dict->GetString("username", &username); + if (!username.empty()) + dict->SetString("domain", gaia::ExtractDomainName(username)); +} + +// Utility function that returns a JSON serialization of the given |dict|. +scoped_ptr<base::StringValue> DictionaryToJSONString( + const base::DictionaryValue& dict) { + std::string json_string; + base::JSONWriter::WriteWithOptions(dict, + base::JSONWriter::OPTIONS_PRETTY_PRINT, + &json_string); + return make_scoped_ptr(new base::StringValue(json_string)); +} + +// Returns a copy of |value| with some values converted to a representation that +// i18n_template.js will display in a nicer way. +scoped_ptr<base::Value> CopyAndConvert(const base::Value* value) { + const base::DictionaryValue* dict = NULL; + if (value->GetAsDictionary(&dict)) + return DictionaryToJSONString(*dict); + + scoped_ptr<base::Value> copy(value->DeepCopy()); + base::ListValue* list = NULL; + if (copy->GetAsList(&list)) { + for (size_t i = 0; i < list->GetSize(); ++i) { + if (list->GetDictionary(i, &dict)) + list->Set(i, DictionaryToJSONString(*dict).release()); + } + } + + return copy.Pass(); +} + +} // namespace + +// An interface for querying the status of cloud policy. +class CloudPolicyStatusProvider { + public: + CloudPolicyStatusProvider(); + virtual ~CloudPolicyStatusProvider(); + + // Sets a callback to invoke upon status changes. + void SetStatusChangeCallback(const base::Closure& callback); + + virtual void GetStatus(base::DictionaryValue* dict); + + protected: + void NotifyStatusChange(); + + private: + base::Closure callback_; + + DISALLOW_COPY_AND_ASSIGN(CloudPolicyStatusProvider); +}; + +// Status provider implementation that pulls cloud policy status from a +// CloudPolicyCore instance provided at construction time. Also listens for +// changes on that CloudPolicyCore and reports them through the status change +// callback. +class CloudPolicyCoreStatusProvider + : public CloudPolicyStatusProvider, + public policy::CloudPolicyStore::Observer { + public: + explicit CloudPolicyCoreStatusProvider(policy::CloudPolicyCore* core); + ~CloudPolicyCoreStatusProvider() override; + + // policy::CloudPolicyStore::Observer implementation. + void OnStoreLoaded(policy::CloudPolicyStore* store) override; + void OnStoreError(policy::CloudPolicyStore* store) override; + + protected: + // Policy status is read from the CloudPolicyClient, CloudPolicyStore and + // CloudPolicyRefreshScheduler hosted by this |core_|. + policy::CloudPolicyCore* core_; + + private: + DISALLOW_COPY_AND_ASSIGN(CloudPolicyCoreStatusProvider); +}; + +// A cloud policy status provider for user policy. +class UserPolicyStatusProvider : public CloudPolicyCoreStatusProvider { + public: + explicit UserPolicyStatusProvider(policy::CloudPolicyCore* core); + ~UserPolicyStatusProvider() override; + + // CloudPolicyCoreStatusProvider implementation. + void GetStatus(base::DictionaryValue* dict) override; + + private: + DISALLOW_COPY_AND_ASSIGN(UserPolicyStatusProvider); +}; + +#if defined(OS_CHROMEOS) +// A cloud policy status provider for device policy. +class DevicePolicyStatusProvider : public CloudPolicyCoreStatusProvider { + public: + explicit DevicePolicyStatusProvider( + policy::BrowserPolicyConnectorChromeOS* connector); + ~DevicePolicyStatusProvider() override; + + // CloudPolicyCoreStatusProvider implementation. + void GetStatus(base::DictionaryValue* dict) override; + + private: + std::string domain_; + + DISALLOW_COPY_AND_ASSIGN(DevicePolicyStatusProvider); +}; + +// A cloud policy status provider that reads policy status from the policy core +// associated with the device-local account specified by |user_id| at +// construction time. The indirection via user ID and +// DeviceLocalAccountPolicyService is necessary because the device-local account +// may go away any time behind the scenes, at which point the status message +// text will indicate CloudPolicyStore::STATUS_BAD_STATE. +class DeviceLocalAccountPolicyStatusProvider + : public CloudPolicyStatusProvider, + public policy::DeviceLocalAccountPolicyService::Observer { + public: + DeviceLocalAccountPolicyStatusProvider( + const std::string& user_id, + policy::DeviceLocalAccountPolicyService* service); + ~DeviceLocalAccountPolicyStatusProvider() override; + + // CloudPolicyStatusProvider implementation. + void GetStatus(base::DictionaryValue* dict) override; + + // policy::DeviceLocalAccountPolicyService::Observer implementation. + void OnPolicyUpdated(const std::string& user_id) override; + void OnDeviceLocalAccountsChanged() override; + + private: + const std::string user_id_; + policy::DeviceLocalAccountPolicyService* service_; + + DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountPolicyStatusProvider); +}; +#endif + +CloudPolicyStatusProvider::CloudPolicyStatusProvider() { +} + +CloudPolicyStatusProvider::~CloudPolicyStatusProvider() { +} + +void CloudPolicyStatusProvider::SetStatusChangeCallback( + const base::Closure& callback) { + callback_ = callback; +} + +void CloudPolicyStatusProvider::GetStatus(base::DictionaryValue* dict) { +} + +void CloudPolicyStatusProvider::NotifyStatusChange() { + if (!callback_.is_null()) + callback_.Run(); +} + +CloudPolicyCoreStatusProvider::CloudPolicyCoreStatusProvider( + policy::CloudPolicyCore* core) : core_(core) { + core_->store()->AddObserver(this); + // TODO(bartfab): Add an observer that watches for client errors. Observing + // core_->client() directly is not safe as the client may be destroyed and + // (re-)created anytime if the user signs in or out on desktop platforms. +} + +CloudPolicyCoreStatusProvider::~CloudPolicyCoreStatusProvider() { + core_->store()->RemoveObserver(this); +} + +void CloudPolicyCoreStatusProvider::OnStoreLoaded( + policy::CloudPolicyStore* store) { + NotifyStatusChange(); +} + +void CloudPolicyCoreStatusProvider::OnStoreError( + policy::CloudPolicyStore* store) { + NotifyStatusChange(); +} + +UserPolicyStatusProvider::UserPolicyStatusProvider( + policy::CloudPolicyCore* core) : CloudPolicyCoreStatusProvider(core) { +} + +UserPolicyStatusProvider::~UserPolicyStatusProvider() { +} + +void UserPolicyStatusProvider::GetStatus(base::DictionaryValue* dict) { + if (!core_->store()->is_managed()) + return; + GetStatusFromCore(core_, dict); + ExtractDomainFromUsername(dict); +} + +#if defined(OS_CHROMEOS) +DevicePolicyStatusProvider::DevicePolicyStatusProvider( + policy::BrowserPolicyConnectorChromeOS* connector) + : CloudPolicyCoreStatusProvider( + connector->GetDeviceCloudPolicyManager()->core()) { + domain_ = connector->GetEnterpriseDomain(); +} + +DevicePolicyStatusProvider::~DevicePolicyStatusProvider() { +} + +void DevicePolicyStatusProvider::GetStatus(base::DictionaryValue* dict) { + GetStatusFromCore(core_, dict); + dict->SetString("domain", domain_); +} + +DeviceLocalAccountPolicyStatusProvider::DeviceLocalAccountPolicyStatusProvider( + const std::string& user_id, + policy::DeviceLocalAccountPolicyService* service) + : user_id_(user_id), + service_(service) { + service_->AddObserver(this); +} + +DeviceLocalAccountPolicyStatusProvider:: + ~DeviceLocalAccountPolicyStatusProvider() { + service_->RemoveObserver(this); +} + +void DeviceLocalAccountPolicyStatusProvider::GetStatus( + base::DictionaryValue* dict) { + const policy::DeviceLocalAccountPolicyBroker* broker = + service_->GetBrokerForUser(user_id_); + if (broker) { + GetStatusFromCore(broker->core(), dict); + } else { + dict->SetBoolean("error", true); + dict->SetString("status", + policy::FormatStoreStatus( + policy::CloudPolicyStore::STATUS_BAD_STATE, + policy::CloudPolicyValidatorBase::VALIDATION_OK)); + dict->SetString("username", std::string()); + } + ExtractDomainFromUsername(dict); + dict->SetBoolean("publicAccount", true); +} + +void DeviceLocalAccountPolicyStatusProvider::OnPolicyUpdated( + const std::string& user_id) { + if (user_id == user_id_) + NotifyStatusChange(); +} + +void DeviceLocalAccountPolicyStatusProvider::OnDeviceLocalAccountsChanged() { + NotifyStatusChange(); +} +#endif + +PolicyUIHandler::PolicyUIHandler() + : weak_factory_(this) { +} + +PolicyUIHandler::~PolicyUIHandler() { + GetPolicyService()->RemoveObserver(policy::POLICY_DOMAIN_CHROME, this); + GetPolicyService()->RemoveObserver(policy::POLICY_DOMAIN_EXTENSIONS, this); + policy::SchemaRegistry* registry = + policy::SchemaRegistryServiceFactory::GetForContext( + Profile::FromWebUI(web_ui())->GetOriginalProfile())->registry(); + registry->RemoveObserver(this); + +#if defined(ENABLE_EXTENSIONS) + extensions::ExtensionRegistry::Get(Profile::FromWebUI(web_ui())) + ->RemoveObserver(this); +#endif +} + +void PolicyUIHandler::AddLocalizedPolicyStrings( + content::WebUIDataSource* source, + const PolicyStringMap* strings, + size_t count) { + for (size_t i = 0; i < count; ++i) + source->AddLocalizedString(strings[i].key, strings[i].string_id); +} + +void PolicyUIHandler::AddCommonLocalizedStringsToSource( + content::WebUIDataSource* source) { + AddLocalizedPolicyStrings(source, kPolicySources, + static_cast<size_t>(policy::POLICY_SOURCE_COUNT)); + source->AddLocalizedString("title", IDS_POLICY_TITLE); + source->AddLocalizedString("headerScope", IDS_POLICY_HEADER_SCOPE); + source->AddLocalizedString("headerLevel", IDS_POLICY_HEADER_LEVEL); + source->AddLocalizedString("headerName", IDS_POLICY_HEADER_NAME); + source->AddLocalizedString("headerValue", IDS_POLICY_HEADER_VALUE); + source->AddLocalizedString("headerStatus", IDS_POLICY_HEADER_STATUS); + source->AddLocalizedString("headerSource", IDS_POLICY_HEADER_SOURCE); + source->AddLocalizedString("scopeUser", IDS_POLICY_SCOPE_USER); + source->AddLocalizedString("scopeDevice", IDS_POLICY_SCOPE_DEVICE); + source->AddLocalizedString("levelRecommended", IDS_POLICY_LEVEL_RECOMMENDED); + source->AddLocalizedString("levelMandatory", IDS_POLICY_LEVEL_MANDATORY); + source->AddLocalizedString("ok", IDS_POLICY_OK); + source->AddLocalizedString("unset", IDS_POLICY_UNSET); + source->AddLocalizedString("unknown", IDS_POLICY_UNKNOWN); + source->AddLocalizedString("notSpecified", IDS_POLICY_NOT_SPECIFIED); + source->SetJsonPath("strings.js"); +} + +void PolicyUIHandler::RegisterMessages() { +#if defined(OS_CHROMEOS) + policy::BrowserPolicyConnectorChromeOS* connector = + g_browser_process->platform_part()->browser_policy_connector_chromeos(); + if (connector->IsEnterpriseManaged()) + device_status_provider_.reset(new DevicePolicyStatusProvider(connector)); + + const user_manager::UserManager* user_manager = + user_manager::UserManager::Get(); + if (user_manager->IsLoggedInAsPublicAccount()) { + policy::DeviceLocalAccountPolicyService* local_account_service = + connector->GetDeviceLocalAccountPolicyService(); + if (local_account_service) { + user_status_provider_.reset( + new DeviceLocalAccountPolicyStatusProvider( + user_manager->GetLoggedInUser()->email(), local_account_service)); + } + } else { + policy::UserCloudPolicyManagerChromeOS* user_cloud_policy_manager = + policy::UserCloudPolicyManagerFactoryChromeOS::GetForProfile( + Profile::FromWebUI(web_ui())); + if (user_cloud_policy_manager) { + user_status_provider_.reset( + new UserPolicyStatusProvider(user_cloud_policy_manager->core())); + } + } +#else + policy::UserCloudPolicyManager* user_cloud_policy_manager = + policy::UserCloudPolicyManagerFactory::GetForBrowserContext( + web_ui()->GetWebContents()->GetBrowserContext()); + if (user_cloud_policy_manager) { + user_status_provider_.reset( + new UserPolicyStatusProvider(user_cloud_policy_manager->core())); + } +#endif + + if (!user_status_provider_.get()) + user_status_provider_.reset(new CloudPolicyStatusProvider()); + if (!device_status_provider_.get()) + device_status_provider_.reset(new CloudPolicyStatusProvider()); + + base::Closure update_callback(base::Bind(&PolicyUIHandler::SendStatus, + base::Unretained(this))); + user_status_provider_->SetStatusChangeCallback(update_callback); + device_status_provider_->SetStatusChangeCallback(update_callback); + GetPolicyService()->AddObserver(policy::POLICY_DOMAIN_CHROME, this); + GetPolicyService()->AddObserver(policy::POLICY_DOMAIN_EXTENSIONS, this); + +#if defined(ENABLE_EXTENSIONS) + extensions::ExtensionRegistry::Get(Profile::FromWebUI(web_ui())) + ->AddObserver(this); +#endif + policy::SchemaRegistry* registry = + policy::SchemaRegistryServiceFactory::GetForContext( + Profile::FromWebUI(web_ui())->GetOriginalProfile())->registry(); + registry->AddObserver(this); + + web_ui()->RegisterMessageCallback( + "initialized", + base::Bind(&PolicyUIHandler::HandleInitialized, base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "reloadPolicies", + base::Bind(&PolicyUIHandler::HandleReloadPolicies, + base::Unretained(this))); +} + +#if defined(ENABLE_EXTENSIONS) +void PolicyUIHandler::OnExtensionLoaded( + content::BrowserContext* browser_context, + const extensions::Extension* extension) { + SendPolicyNames(); + SendPolicyValues(); +} + +void PolicyUIHandler::OnExtensionUnloaded( + content::BrowserContext* browser_context, + const extensions::Extension* extension, + extensions::UnloadedExtensionInfo::Reason reason) { + SendPolicyNames(); + SendPolicyValues(); +} +#endif + +void PolicyUIHandler::OnSchemaRegistryUpdated(bool has_new_schemas) { + // Update UI when new schema is added. + if (has_new_schemas) { + SendPolicyNames(); + SendPolicyValues(); + } +} + +void PolicyUIHandler::OnPolicyUpdated(const policy::PolicyNamespace& ns, + const policy::PolicyMap& previous, + const policy::PolicyMap& current) { + SendPolicyValues(); +} + +void PolicyUIHandler::AddPolicyName(const std::string& name, + base::DictionaryValue* names) const { + names->SetBoolean(name, true); +} + +void PolicyUIHandler::SendPolicyNames() const { + base::DictionaryValue names; + + Profile* profile = Profile::FromWebUI(web_ui()); + policy::SchemaRegistry* registry = + policy::SchemaRegistryServiceFactory::GetForContext( + profile->GetOriginalProfile())->registry(); + scoped_refptr<policy::SchemaMap> schema_map = registry->schema_map(); + + // Add Chrome policy names. + base::DictionaryValue* chrome_policy_names = new base::DictionaryValue; + policy::PolicyNamespace chrome_ns(policy::POLICY_DOMAIN_CHROME, ""); + const policy::Schema* chrome_schema = schema_map->GetSchema(chrome_ns); + for (policy::Schema::Iterator it = chrome_schema->GetPropertiesIterator(); + !it.IsAtEnd(); it.Advance()) { + AddPolicyName(it.key(), chrome_policy_names); + } + names.Set("chromePolicyNames", chrome_policy_names); + +#if defined(ENABLE_EXTENSIONS) + // Add extension policy names. + base::DictionaryValue* extension_policy_names = new base::DictionaryValue; + + for (const scoped_refptr<const extensions::Extension>& extension : + extensions::ExtensionRegistry::Get(profile)->enabled_extensions()) { + // Skip this extension if it's not an enterprise extension. + if (!extension->manifest()->HasPath( + extensions::manifest_keys::kStorageManagedSchema)) + continue; + base::DictionaryValue* extension_value = new base::DictionaryValue; + extension_value->SetString("name", extension->name()); + const policy::Schema* schema = + schema_map->GetSchema(policy::PolicyNamespace( + policy::POLICY_DOMAIN_EXTENSIONS, extension->id())); + base::DictionaryValue* policy_names = new base::DictionaryValue; + if (schema && schema->valid()) { + // Get policy names from the extension's policy schema. + // Store in a map, not an array, for faster lookup on JS side. + for (policy::Schema::Iterator prop = schema->GetPropertiesIterator(); + !prop.IsAtEnd(); prop.Advance()) { + policy_names->SetBoolean(prop.key(), true); + } + } + extension_value->Set("policyNames", policy_names); + extension_policy_names->Set(extension->id(), extension_value); + } + names.Set("extensionPolicyNames", extension_policy_names); +#endif // defined(ENABLE_EXTENSIONS) + + web_ui()->CallJavascriptFunction("policy.Page.setPolicyNames", names); +} + +void PolicyUIHandler::SendPolicyValues() const { + base::DictionaryValue all_policies; + + // Add Chrome policy values. + base::DictionaryValue* chrome_policies = new base::DictionaryValue; + GetChromePolicyValues(chrome_policies); + all_policies.Set("chromePolicies", chrome_policies); + +#if defined(ENABLE_EXTENSIONS) + // Add extension policy values. + extensions::ExtensionRegistry* registry = + extensions::ExtensionRegistry::Get(Profile::FromWebUI(web_ui())); + base::DictionaryValue* extension_values = new base::DictionaryValue; + + for (const scoped_refptr<const extensions::Extension>& extension : + registry->enabled_extensions()) { + // Skip this extension if it's not an enterprise extension. + if (!extension->manifest()->HasPath( + extensions::manifest_keys::kStorageManagedSchema)) + continue; + base::DictionaryValue* extension_policies = new base::DictionaryValue; + policy::PolicyNamespace policy_namespace = policy::PolicyNamespace( + policy::POLICY_DOMAIN_EXTENSIONS, extension->id()); + policy::PolicyErrorMap empty_error_map; + GetPolicyValues(GetPolicyService()->GetPolicies(policy_namespace), + &empty_error_map, extension_policies); + extension_values->Set(extension->id(), extension_policies); + } + all_policies.Set("extensionPolicies", extension_values); +#endif + web_ui()->CallJavascriptFunction("policy.Page.setPolicyValues", all_policies); +} + +void PolicyUIHandler::GetPolicyValues(const policy::PolicyMap& map, + policy::PolicyErrorMap* errors, + base::DictionaryValue* values) const { + for (policy::PolicyMap::const_iterator entry = map.begin(); + entry != map.end(); ++entry) { + base::DictionaryValue* value = new base::DictionaryValue; + value->Set("value", CopyAndConvert(entry->second.value).release()); + if (entry->second.scope == policy::POLICY_SCOPE_USER) + value->SetString("scope", "user"); + else + value->SetString("scope", "machine"); + if (entry->second.level == policy::POLICY_LEVEL_RECOMMENDED) + value->SetString("level", "recommended"); + else + value->SetString("level", "mandatory"); + value->SetString("source", kPolicySources[entry->second.source].key); + base::string16 error = errors->GetErrors(entry->first); + if (!error.empty()) + value->SetString("error", error); + values->Set(entry->first, value); + } +} + +void PolicyUIHandler::GetChromePolicyValues( + base::DictionaryValue* values) const { + policy::PolicyService* policy_service = GetPolicyService(); + policy::PolicyMap map; + + // Make a copy that can be modified, since some policy values are modified + // before being displayed. + map.CopyFrom(policy_service->GetPolicies( + policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string()))); + + // Get a list of all the errors in the policy values. + const policy::ConfigurationPolicyHandlerList* handler_list = + g_browser_process->browser_policy_connector()->GetHandlerList(); + policy::PolicyErrorMap errors; + handler_list->ApplyPolicySettings(map, NULL, &errors); + + // Convert dictionary values to strings for display. + handler_list->PrepareForDisplaying(&map); + + GetPolicyValues(map, &errors, values); +} + +void PolicyUIHandler::SendStatus() const { + scoped_ptr<base::DictionaryValue> device_status(new base::DictionaryValue); + device_status_provider_->GetStatus(device_status.get()); + if (!device_domain_.empty()) + device_status->SetString("domain", device_domain_); + scoped_ptr<base::DictionaryValue> user_status(new base::DictionaryValue); + user_status_provider_->GetStatus(user_status.get()); + std::string username; + user_status->GetString("username", &username); + if (!username.empty()) + user_status->SetString("domain", gaia::ExtractDomainName(username)); + + base::DictionaryValue status; + if (!device_status->empty()) + status.Set("device", device_status.release()); + if (!user_status->empty()) + status.Set("user", user_status.release()); + + web_ui()->CallJavascriptFunction("policy.Page.setStatus", status); +} + +void PolicyUIHandler::HandleInitialized(const base::ListValue* args) { + SendPolicyNames(); + SendPolicyValues(); + SendStatus(); +} + +void PolicyUIHandler::HandleReloadPolicies(const base::ListValue* args) { +#if defined(OS_CHROMEOS) + // Allow user to manually fetch remote commands, in case invalidation + // service is not working properly. + // TODO(binjin): evaluate and possibly remove this after invalidation + // service is landed and tested. http://crbug.com/480982 + policy::BrowserPolicyConnectorChromeOS* connector = + g_browser_process->platform_part()->browser_policy_connector_chromeos(); + policy::RemoteCommandsService* remote_commands_service = + connector->GetDeviceCloudPolicyManager() + ->core() + ->remote_commands_service(); + if (remote_commands_service) + remote_commands_service->FetchRemoteCommands(); +#endif + GetPolicyService()->RefreshPolicies(base::Bind( + &PolicyUIHandler::OnRefreshPoliciesDone, weak_factory_.GetWeakPtr())); +} + +void PolicyUIHandler::OnRefreshPoliciesDone() const { + web_ui()->CallJavascriptFunction("policy.Page.reloadPoliciesDone"); +} + +policy::PolicyService* PolicyUIHandler::GetPolicyService() const { + return policy::ProfilePolicyConnectorFactory::GetForBrowserContext( + web_ui()->GetWebContents()->GetBrowserContext())->policy_service(); +} diff --git a/chrome/browser/ui/webui/policy_ui_handler.h b/chrome/browser/ui/webui/policy_ui_handler.h new file mode 100644 index 0000000..f2b0446 --- /dev/null +++ b/chrome/browser/ui/webui/policy_ui_handler.h @@ -0,0 +1,119 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_POLICY_UI_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_POLICY_UI_HANDLER_H_ + +#include <string.h> + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "components/policy/core/browser/policy_error_map.h" +#include "components/policy/core/common/policy_map.h" +#include "components/policy/core/common/policy_namespace.h" +#include "components/policy/core/common/policy_service.h" +#include "components/policy/core/common/schema_registry.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_data_source.h" +#include "content/public/browser/web_ui_message_handler.h" + +#if defined(ENABLE_EXTENSIONS) +#include "extensions/browser/extension_registry_observer.h" +#endif + +struct PolicyStringMap { + const char* key; + int string_id; +}; + +class CloudPolicyStatusProvider; + +// The JavaScript message handler for the chrome://policy page. +class PolicyUIHandler : public content::WebUIMessageHandler, +#if defined(ENABLE_EXTENSIONS) + public extensions::ExtensionRegistryObserver, +#endif + public policy::PolicyService::Observer, + public policy::SchemaRegistry::Observer { + public: + PolicyUIHandler(); + ~PolicyUIHandler() override; + + + static void AddLocalizedPolicyStrings(content::WebUIDataSource* source, + const PolicyStringMap* strings, + size_t count); + + static void AddCommonLocalizedStringsToSource( + content::WebUIDataSource* source); + + // content::WebUIMessageHandler implementation. + void RegisterMessages() override; + +#if defined(ENABLE_EXTENSIONS) + // extensions::ExtensionRegistryObserver implementation. + void OnExtensionLoaded(content::BrowserContext* browser_context, + const extensions::Extension* extension) override; + void OnExtensionUnloaded( + content::BrowserContext* browser_context, + const extensions::Extension* extension, + extensions::UnloadedExtensionInfo::Reason reason) override; +#endif + + // policy::PolicyService::Observer implementation. + void OnPolicyUpdated(const policy::PolicyNamespace& ns, + const policy::PolicyMap& previous, + const policy::PolicyMap& current) override; + + // policy::SchemaRegistry::Observer implementation. + void OnSchemaRegistryUpdated(bool has_new_schemas) override; + + protected: + virtual void AddPolicyName(const std::string& name, + base::DictionaryValue* names) const; + + // Send a dictionary containing the names of all known policies to the UI. + virtual void SendPolicyNames() const; + + private: + // Send information about the current policy values to the UI. For each policy + // whose value has been set, a dictionary containing the value and additional + // metadata is sent. + void SendPolicyValues() const; + + // Send the status of cloud policy to the UI. For each scope that has cloud + // policy enabled (device and/or user), a dictionary containing status + // information is sent. + void SendStatus() const; + + // Inserts a description of each policy in |policy_map| into |values|, using + // the optional errors in |errors| to determine the status of each policy. + void GetPolicyValues(const policy::PolicyMap& policy_map, + policy::PolicyErrorMap* errors, + base::DictionaryValue* values) const; + + void GetChromePolicyValues(base::DictionaryValue* values) const; + + void HandleInitialized(const base::ListValue* args); + void HandleReloadPolicies(const base::ListValue* args); + + void OnRefreshPoliciesDone() const; + + policy::PolicyService* GetPolicyService() const; + + std::string device_domain_; + + // Providers that supply status dictionaries for user and device policy, + // respectively. These are created on initialization time as appropriate for + // the platform (Chrome OS / desktop) and type of policy that is in effect. + scoped_ptr<CloudPolicyStatusProvider> user_status_provider_; + scoped_ptr<CloudPolicyStatusProvider> device_status_provider_; + + base::WeakPtrFactory<PolicyUIHandler> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(PolicyUIHandler); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_POLICY_UI_HANDLER_H_ diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index b7a5fad..e76071b 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -3318,6 +3318,7 @@ '<(SHARED_INTERMEDIATE_DIR)/components/grit/components_scaled_resources_map.cc', '<(SHARED_INTERMEDIATE_DIR)/ui/resources/grit/ui_resources_map.cc', '<(grit_out_dir)/grit/component_extension_resources_map.cc', + '<(grit_out_dir)/grit/policy_resources_map.cc', '<(grit_out_dir)/grit/settings_resources_map.cc', '<(grit_out_dir)/grit/theme_resources_map.cc', ], diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index 112ad6d..816ddb3 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi @@ -2741,8 +2741,12 @@ 'browser/ui/webui/plugins_ui.h', ], 'chrome_browser_ui_policy_sources': [ + 'browser/ui/webui/policy_material_design_ui.cc', + 'browser/ui/webui/policy_material_design_ui.h', 'browser/ui/webui/policy_ui.cc', 'browser/ui/webui/policy_ui.h', + 'browser/ui/webui/policy_ui_handler.cc', + 'browser/ui/webui/policy_ui_handler.h', ], 'chrome_browser_ui_print_preview_sources': [ 'browser/ui/webui/print_preview/extension_printer_handler.cc', diff --git a/chrome/chrome_repack_resources.gypi b/chrome/chrome_repack_resources.gypi index 8b5b3df..4668372 100644 --- a/chrome/chrome_repack_resources.gypi +++ b/chrome/chrome_repack_resources.gypi @@ -15,6 +15,7 @@ '<(grit_out_dir)/memory_internals_resources.pak', '<(grit_out_dir)/net_internals_resources.pak', '<(grit_out_dir)/password_manager_internals_resources.pak', + '<(grit_out_dir)/policy_resources.pak', '<(grit_out_dir)/settings_strings.pak', '<(grit_out_dir)/signin_internals_resources.pak', '<(grit_out_dir)/translate_internals_resources.pak', diff --git a/chrome/chrome_resources.gyp b/chrome/chrome_resources.gyp index 85116d4..6d15442 100644 --- a/chrome/chrome_resources.gyp +++ b/chrome/chrome_resources.gyp @@ -54,6 +54,14 @@ 'includes': [ '../build/grit_action.gypi' ], }, { + # GN version: //chrome/browser/resources:policy_resources + 'action_name': 'generate_policy_resources', + 'variables': { + 'grit_grd_file': 'browser/resources/md_policy/policy_resources.grd', + }, + 'includes': [ '../build/grit_action.gypi' ], + }, + { # GN version: //chrome/browser/resources:signin_internals_resources 'action_name': 'generate_signin_internals_resources', 'variables': { diff --git a/components/policy_strings.grdp b/components/policy_strings.grdp index e39f1d1..1876a68 100644 --- a/components/policy_strings.grdp +++ b/components/policy_strings.grdp @@ -334,4 +334,25 @@ <message name="IDS_POLICY_SOURCE_PUBLIC_SESSION_OVERRIDE" desc="Indicates that the policy is set programmatically because of an active public session (for Chrome OS only). It could have overridden other sources that set this policy."> Public session override </message> + <message name="IDS_POLICY_RISK_TAG_FULL_ADMIN_ACCESS" desc="Title of a group/tag whose policies potentially allow the administrator to access all of a user's data."> + Full Admin Access + </message> + <message name="IDS_POLICY_RISK_TAG_SYSTEM_SECURITY" desc="Title of a group/tag whose policies might influence the system's security."> + System Security + </message> + <message name="IDS_POLICY_RISK_TAG_WEBSITE_SHARING" desc="Title of a group/tag whose policies might lead to information sharing with other websites."> + Sharing with Websites + </message> + <message name="IDS_POLICY_RISK_TAG_ADMIN_SHARING" desc="Title of a group/tag whose policies potentially allow sending information about the user (like activity times) to an administrator."> + Sharing with Administrator + </message> + <message name="IDS_POLICY_RISK_TAG_FILTERING" desc="Title of a group/tag whose policies might restrict web contents which would be visible otherwise (e.g. forced SafeSearch)."> + Filtering + </message> + <message name="IDS_POLICY_RISK_TAG_LOCAL_DATA_ACCESS" desc="Title of a group/tag whose policies might allow storage of user data to local drives where others might access them."> + Local Data Access + </message> + <message name="IDS_POLICY_RISK_TAG_GOOGLE_SHARING" desc="Title of a group/tag whose policies enable functionality that might share user data with trusted Google services."> + Sharing with Google + </message> </grit-part> diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids index d5d0271..6f53f31 100644 --- a/tools/gritsettings/resource_ids +++ b/tools/gritsettings/resource_ids @@ -298,6 +298,9 @@ "chrome/browser/devtools/device/webrtc/resources.grd": { "includes": [30820], }, + "chrome/browser/resources/md_policy/policy_resources.grd": { + "structures": [30900], + }, "chrome/browser/resources/settings/settings_resources.grd": { "structures": [30920], }, |