Commit 2644fc8d authored by Yann Dago's avatar Yann Dago Committed by Commit Bot

Use IPolicyStatus2 to get the updater's policies and state.

Use the new COM interface to show the updater's policies and conflicts.
Use the new interface to get the updater's version and the last time
policies were fetched. Maintain compatibility with IPolicyStatus so
that machine with older versions of the updater still show policies.

Bug: 1032756
Change-Id: Iadb2199bcdc704a426e80e00e2bb8aa5b21e0648
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2380582
Commit-Queue: Yann Dago <ydago@chromium.org>
Reviewed-by: default avatarS. Ganesh <ganesh@chromium.org>
Reviewed-by: default avatarPeter Kasting <pkasting@chromium.org>
Reviewed-by: default avatarGreg Thompson <grt@chromium.org>
Reviewed-by: default avatarOwen Min <zmin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#814536}
parent d90a982c
......@@ -4619,6 +4619,8 @@ static_library("browser") {
"component_updater/third_party_module_list_component_installer_win.h",
"google/google_update_policy_fetcher_win.cc",
"google/google_update_policy_fetcher_win.h",
"google/google_update_policy_fetcher_win_util.cc",
"google/google_update_policy_fetcher_win_util.h",
"google/google_update_win.cc",
"google/google_update_win.h",
"google/switches.cc",
......
......@@ -4,16 +4,25 @@
#include "chrome/browser/google/google_update_policy_fetcher_win.h"
#include <ATLComTime.h>
#include <wrl/client.h>
#include <utility>
#include "base/bind.h"
#include "base/macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util_win.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/com_init_util.h"
#include "base/win/scoped_bstr.h"
#include "chrome/browser/google/google_update_policy_fetcher_win_util.h"
#include "chrome/install_static/install_util.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_types.h"
#include "components/policy/core/common/schema.h"
#include "components/strings/grit/components_strings.h"
#include "components/update_client/updater_state.h"
#include "google_update/google_update_idl.h"
namespace {
......@@ -21,8 +30,12 @@ namespace {
constexpr char kAutoUpdateCheckPeriodMinutes[] = "AutoUpdateCheckPeriodMinutes";
constexpr char kDownloadPreference[] = "DownloadPreference";
constexpr char kInstallPolicy[] = "InstallPolicy";
constexpr char kProxyMode[] = "ProxyMode";
constexpr char kProxyPacUrl[] = "ProxyPacUrl";
constexpr char kProxyServer[] = "ProxyServer";
constexpr char kRollbackToTargetVersion[] = "RollbackToTargetVersion";
constexpr char kTargetVersionPrefix[] = "TargetVersionPrefix";
constexpr char kTargetChannel[] = "TargetChannel";
constexpr char kUpdatePolicy[] = "UpdatePolicy";
constexpr char kUpdatesSuppressedDurationMin[] = "UpdatesSuppressedDurationMin";
constexpr char kUpdatesSuppressedStartHour[] = "UpdatesSuppressedStartHour";
......@@ -32,61 +45,148 @@ constexpr char kUpdatesSuppressedStartMinute[] = "UpdatesSuppressedStartMinute";
// "Machine" scope and "Platform" source.
void AddPolicy(const char* policy_name,
base::Value value,
policy::PolicyMap* policies) {
DCHECK(policies);
policies->Set(policy_name, policy::POLICY_LEVEL_MANDATORY,
policy::PolicyMap& policies) {
policies.Set(policy_name, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_PLATFORM,
std::move(value), nullptr);
}
} // namespace
base::Value GetGoogleUpdatePolicyNames() {
base::Value names(base::Value::Type::LIST);
for (const auto& key_value : GetGoogleUpdatePolicySchemas())
names.Append(base::Value(key_value.first));
return names;
// Adds the policy |policy_name| extracted from |policy| into |policies|.
// |value_override_function| is an optional function that modifies and overrides
// the value of the policy that needs to be store in |policies|. This function
// may be used to convert the extracted value, that is always a string into
// other types or formats.
void AddPolicy(const char* policy_name,
IPolicyStatusValue* policy,
policy::PolicyMap& policies,
const PolicyValueOverrideFunction& value_override_function =
PolicyValueOverrideFunction()) {
auto policy_entry =
ConvertPolicyStatusValueToPolicyEntry(policy, value_override_function);
if (policy_entry)
policies.Set(policy_name, std::move(*policy_entry));
}
policy::PolicyConversions::PolicyToSchemaMap GetGoogleUpdatePolicySchemas() {
// TODO(ydago): Use actual schemas.
return policy::PolicyConversions::PolicyToSchemaMap{{
{kAutoUpdateCheckPeriodMinutes, policy::Schema()},
{kDownloadPreference, policy::Schema()},
{kInstallPolicy, policy::Schema()},
{kRollbackToTargetVersion, policy::Schema()},
{kTargetVersionPrefix, policy::Schema()},
{kUpdatePolicy, policy::Schema()},
{kUpdatesSuppressedDurationMin, policy::Schema()},
{kUpdatesSuppressedStartHour, policy::Schema()},
{kUpdatesSuppressedStartMinute, policy::Schema()},
}};
base::Time DateToTime(DATE date) {
::COleDateTime date_time(date);
base::Time time;
if (date_time.m_status == ::COleDateTime::valid) {
ignore_result(base::Time::FromLocalExploded(
{date_time.GetYear(), date_time.GetMonth(), date_time.GetDayOfWeek(),
date_time.GetDay(), date_time.GetHour(), date_time.GetMinute(),
date_time.GetSecond(), 0},
&time));
}
return time;
}
std::unique_ptr<policy::PolicyMap> GetGoogleUpdatePolicies() {
base::win::AssertComInitialized();
Microsoft::WRL::ComPtr<IPolicyStatus> policy_status;
HRESULT last_com_res =
::CoCreateInstance(CLSID_PolicyStatusMachineClass, nullptr, CLSCTX_ALL,
IID_PPV_ARGS(&policy_status));
// Returns the Google Update policies as of release 1.3.36.21.
std::unique_ptr<policy::PolicyMap> GetGoogleUpdatePolicies(
IPolicyStatus2* policy_status) {
DCHECK(policy_status);
policy_status->refreshPolicies();
auto policies = std::make_unique<policy::PolicyMap>();
base::win::ScopedBstr app_id(install_static::GetAppGuid());
// If PolicyStatusMachineClass cannot be instantiated or does not expose
// IPolicyStatus, assume the updater is not configured yet to return the
// policies.
if (FAILED(last_com_res))
return nullptr;
{
Microsoft::WRL::ComPtr<IPolicyStatusValue> policy;
if (SUCCEEDED(policy_status->get_lastCheckPeriodMinutes(&policy)))
AddPolicy(kAutoUpdateCheckPeriodMinutes, policy.Get(), *policies);
}
{
Microsoft::WRL::ComPtr<IPolicyStatusValue> policy;
if (SUCCEEDED(policy_status->get_downloadPreferenceGroupPolicy(&policy)))
AddPolicy(kDownloadPreference, policy.Get(), *policies);
}
{
Microsoft::WRL::ComPtr<IPolicyStatusValue> policy;
if (SUCCEEDED(policy_status->get_effectivePolicyForAppInstalls(app_id.Get(),
&policy))) {
AddPolicy(kInstallPolicy, policy.Get(), *policies);
}
}
{
Microsoft::WRL::ComPtr<IPolicyStatusValue> policy;
if (SUCCEEDED(policy_status->get_effectivePolicyForAppUpdates(app_id.Get(),
&policy))) {
AddPolicy(kUpdatePolicy, policy.Get(), *policies);
}
}
{
Microsoft::WRL::ComPtr<IPolicyStatusValue> policy;
VARIANT_BOOL are_updates_suppressed = VARIANT_FALSE;
if (SUCCEEDED(policy_status->get_updatesSuppressedTimes(
&policy, &are_updates_suppressed))) {
// A function that extracts the |index|-th value from a comma-separated
// |initial_value|.
const auto extract_value = [](int index, BSTR initial_value) {
auto split = base::SplitString(
initial_value, L",", base::WhitespaceHandling::TRIM_WHITESPACE,
base::SplitResult::SPLIT_WANT_NONEMPTY);
return base::Value(split.size() == 3 ? split[index] : L"");
};
AddPolicy(kUpdatesSuppressedStartHour, policy.Get(), *policies,
base::BindRepeating(extract_value, 0));
AddPolicy(kUpdatesSuppressedStartMinute, policy.Get(), *policies,
base::BindRepeating(extract_value, 1));
AddPolicy(kUpdatesSuppressedDurationMin, policy.Get(), *policies,
base::BindRepeating(extract_value, 2));
}
}
{
Microsoft::WRL::ComPtr<IPolicyStatusValue> policy;
if (SUCCEEDED(policy_status->get_isRollbackToTargetVersionAllowed(
app_id.Get(), &policy))) {
AddPolicy(kRollbackToTargetVersion, policy.Get(), *policies);
}
}
{
Microsoft::WRL::ComPtr<IPolicyStatusValue> policy;
if (SUCCEEDED(
policy_status->get_targetVersionPrefix(app_id.Get(), &policy))) {
AddPolicy(kTargetVersionPrefix, policy.Get(), *policies);
}
}
{
Microsoft::WRL::ComPtr<IPolicyStatusValue> policy;
if (SUCCEEDED(policy_status->get_targetChannel(app_id.Get(), &policy)))
AddPolicy(kTargetChannel, policy.Get(), *policies);
}
{
Microsoft::WRL::ComPtr<IPolicyStatusValue> policy;
if (SUCCEEDED(policy_status->get_proxyMode(&policy)))
AddPolicy(kProxyMode, policy.Get(), *policies);
}
{
Microsoft::WRL::ComPtr<IPolicyStatusValue> policy;
if (SUCCEEDED(policy_status->get_proxyPacUrl(&policy)))
AddPolicy(kProxyPacUrl, policy.Get(), *policies);
}
{
Microsoft::WRL::ComPtr<IPolicyStatusValue> policy;
if (SUCCEEDED(policy_status->get_proxyServer(&policy)))
AddPolicy(kProxyServer, policy.Get(), *policies);
}
return policies;
}
// Returns the Google Update policies as of release 1.3.35.331
std::unique_ptr<policy::PolicyMap> GetLegacyGoogleUpdatePolicies(
IPolicyStatus* policy_status) {
DCHECK(policy_status);
auto policies = std::make_unique<policy::PolicyMap>();
base::win::ScopedBstr app_id(install_static::GetAppGuid());
DWORD auto_update_check_period_minutes;
last_com_res = policy_status->get_lastCheckPeriodMinutes(
HRESULT last_com_res = policy_status->get_lastCheckPeriodMinutes(
&auto_update_check_period_minutes);
if (SUCCEEDED(last_com_res)) {
AddPolicy(kAutoUpdateCheckPeriodMinutes,
base::Value(
base::saturated_cast<int>(auto_update_check_period_minutes)),
policies.get());
*policies);
}
base::win::ScopedBstr download_preference_group_policy;
......@@ -95,8 +195,7 @@ std::unique_ptr<policy::PolicyMap> GetGoogleUpdatePolicies() {
if (SUCCEEDED(last_com_res) &&
download_preference_group_policy.Length() > 0) {
AddPolicy(kDownloadPreference,
base::Value(download_preference_group_policy.Get()),
policies.get());
base::Value(download_preference_group_policy.Get()), *policies);
}
DWORD effective_policy_for_app_installs;
......@@ -106,7 +205,7 @@ std::unique_ptr<policy::PolicyMap> GetGoogleUpdatePolicies() {
AddPolicy(kInstallPolicy,
base::Value(
base::saturated_cast<int>(effective_policy_for_app_installs)),
policies.get());
*policies);
}
DWORD effective_policy_for_app_updates;
......@@ -116,7 +215,7 @@ std::unique_ptr<policy::PolicyMap> GetGoogleUpdatePolicies() {
AddPolicy(kUpdatePolicy,
base::Value(
base::saturated_cast<int>(effective_policy_for_app_updates)),
policies.get());
*policies);
}
DWORD updates_suppressed_duration;
......@@ -130,15 +229,15 @@ std::unique_ptr<policy::PolicyMap> GetGoogleUpdatePolicies() {
AddPolicy(
kUpdatesSuppressedDurationMin,
base::Value(base::saturated_cast<int>(updates_suppressed_duration)),
policies.get());
*policies);
AddPolicy(
kUpdatesSuppressedStartHour,
base::Value(base::saturated_cast<int>(updates_suppressed_start_hour)),
policies.get());
*policies);
AddPolicy(
kUpdatesSuppressedStartMinute,
base::Value(base::saturated_cast<int>(updates_suppressed_start_minute)),
policies.get());
*policies);
}
VARIANT_BOOL is_rollback_to_target_version_allowed;
......@@ -148,7 +247,7 @@ std::unique_ptr<policy::PolicyMap> GetGoogleUpdatePolicies() {
AddPolicy(
kRollbackToTargetVersion,
base::Value(is_rollback_to_target_version_allowed == VARIANT_TRUE),
policies.get());
*policies);
}
base::win::ScopedBstr target_version_prefix;
......@@ -156,8 +255,102 @@ std::unique_ptr<policy::PolicyMap> GetGoogleUpdatePolicies() {
app_id.Get(), target_version_prefix.Receive());
if (SUCCEEDED(last_com_res) && target_version_prefix.Length() > 0) {
AddPolicy(kTargetVersionPrefix, base::Value(target_version_prefix.Get()),
policies.get());
*policies);
}
return policies;
}
// Returns the state for versions prior to release 1.3.36.21.
std::unique_ptr<GoogleUpdateState> GetLegacyGoogleUpdateState() {
auto state =
update_client::UpdaterState::GetState(install_static::IsSystemInstall());
auto result = std::make_unique<GoogleUpdateState>();
const auto version = state->find("version");
if (version != state->end())
result->version = base::AsString16(base::ASCIIToWide(version->second));
return result;
}
// Returns the state for release 1.3.36.21 and newer.
std::unique_ptr<GoogleUpdateState> GetGoogleUpdateState(
IPolicyStatus2* policy_status) {
DCHECK(policy_status);
auto state = std::make_unique<GoogleUpdateState>();
base::win::ScopedBstr updater_version;
HRESULT last_com_res =
policy_status->get_updaterVersion(updater_version.Receive());
if (SUCCEEDED(last_com_res)) {
DCHECK(updater_version.Length());
state->version.assign(updater_version.Get(), updater_version.Length());
}
DATE last_checked_time;
last_com_res = policy_status->get_lastCheckedTime(&last_checked_time);
if (SUCCEEDED(last_com_res))
state->last_checked_time = DateToTime(last_checked_time);
return state;
}
} // namespace
GoogleUpdatePoliciesAndState::GoogleUpdatePoliciesAndState() = default;
GoogleUpdatePoliciesAndState::~GoogleUpdatePoliciesAndState() = default;
base::Value GetGoogleUpdatePolicyNames() {
base::Value names(base::Value::Type::LIST);
for (const auto& key_value : GetGoogleUpdatePolicySchemas())
names.Append(base::Value(key_value.first));
return names;
}
policy::PolicyConversions::PolicyToSchemaMap GetGoogleUpdatePolicySchemas() {
// TODO(crbug/1133309): Use actual schemas.
return policy::PolicyConversions::PolicyToSchemaMap{{
{kAutoUpdateCheckPeriodMinutes, policy::Schema()},
{kDownloadPreference, policy::Schema()},
{kInstallPolicy, policy::Schema()},
{kProxyMode, policy::Schema()},
{kProxyPacUrl, policy::Schema()},
{kProxyServer, policy::Schema()},
{kRollbackToTargetVersion, policy::Schema()},
{kTargetVersionPrefix, policy::Schema()},
{kTargetChannel, policy::Schema()},
{kUpdatePolicy, policy::Schema()},
{kUpdatesSuppressedDurationMin, policy::Schema()},
{kUpdatesSuppressedStartHour, policy::Schema()},
{kUpdatesSuppressedStartMinute, policy::Schema()},
}};
}
std::unique_ptr<GoogleUpdatePoliciesAndState>
GetGoogleUpdatePoliciesAndState() {
base::win::AssertComInitialized();
Microsoft::WRL::ComPtr<IPolicyStatus2> policy_status2;
Microsoft::WRL::ComPtr<IPolicyStatus> policy_status;
auto policies_and_state = std::make_unique<GoogleUpdatePoliciesAndState>();
bool is_system_install = install_static::IsSystemInstall();
// The PolicyStatus{Machine,User}Class was introduced in Google
// Update 1.3.36.21. If the IPolicyStatus2 interface cannot be found on the
// relevant class, try to use the IPolicyStatus interface on
// PolicyStatusMachineClass (introduced in 1.3.35.331).
if (SUCCEEDED(::CoCreateInstance(
is_system_install ? CLSID_PolicyStatusMachineClass
: CLSID_PolicyStatusUserClass,
nullptr, CLSCTX_ALL, IID_PPV_ARGS(&policy_status2)))) {
policies_and_state->policies =
GetGoogleUpdatePolicies(policy_status2.Get());
policies_and_state->state = GetGoogleUpdateState(policy_status2.Get());
} else if (SUCCEEDED(::CoCreateInstance(CLSID_PolicyStatusMachineClass,
nullptr, CLSCTX_ALL,
IID_PPV_ARGS(&policy_status)))) {
policies_and_state->policies =
GetLegacyGoogleUpdatePolicies(policy_status.Get());
policies_and_state->state = GetLegacyGoogleUpdateState();
}
return policies_and_state;
}
......@@ -7,6 +7,8 @@
#include <memory>
#include "base/strings/string16.h"
#include "base/time/time.h"
#include "base/values.h"
#include "components/policy/core/browser/policy_conversions.h"
......@@ -14,6 +16,18 @@ namespace policy {
class PolicyMap;
}
struct GoogleUpdateState {
base::string16 version;
base::Time last_checked_time;
};
struct GoogleUpdatePoliciesAndState {
GoogleUpdatePoliciesAndState();
~GoogleUpdatePoliciesAndState();
std::unique_ptr<policy::PolicyMap> policies;
std::unique_ptr<GoogleUpdateState> state;
};
// Returns a list of all the Google Update policies available through the
// IPolicyStatus COM interface.
base::Value GetGoogleUpdatePolicyNames();
......@@ -22,11 +36,11 @@ base::Value GetGoogleUpdatePolicyNames();
// IPolicyStatus COM interface.
policy::PolicyConversions::PolicyToSchemaMap GetGoogleUpdatePolicySchemas();
// Fetches all the Google Update Policies available through the IPolicyStatus
// COM interface. Only the policies that have been set are returned by this
// function. This function returns null if the fetch fails because IPolicyStatus
// could not be instantiated. This function must run on a COM STA thread because
// it makes some COM calls.
std::unique_ptr<policy::PolicyMap> GetGoogleUpdatePolicies();
// Fetches all the Google Update Policies and state values available through the
// IPolicyStatus2 or IPolicyStatus COM interface. Only the policies that have
// been set are returned by this function. This function returns null if the
// fetch fails because IPolicyStatus interface could not be instantiated. This
// function must run on a COM STA thread because it makes some COM calls.
std::unique_ptr<GoogleUpdatePoliciesAndState> GetGoogleUpdatePoliciesAndState();
#endif // CHROME_BROWSER_GOOGLE_GOOGLE_UPDATE_POLICY_FETCHER_WIN_H_
// Copyright 2020 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/google/google_update_policy_fetcher_win_util.h"
#include <OleCtl.h>
#include "base/check.h"
#include "base/strings/string_piece.h"
#include "base/values.h"
#include "base/win/scoped_bstr.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_types.h"
namespace {
policy::PolicySource GetPolicySource(BSTR source_bstr) {
constexpr base::WStringPiece kCloudSource = L"Device Management";
constexpr base::WStringPiece kDefaultSource = L"Default";
const auto source =
base::WStringPiece(source_bstr, ::SysStringLen(source_bstr));
if (source == kCloudSource)
return policy::POLICY_SOURCE_CLOUD;
if (source == kDefaultSource)
return policy::POLICY_SOURCE_ENTERPRISE_DEFAULT;
DCHECK_EQ(source, base::WStringPiece(L"Group Policy"));
return policy::POLICY_SOURCE_PLATFORM;
}
} // namespace
std::unique_ptr<policy::PolicyMap::Entry> ConvertPolicyStatusValueToPolicyEntry(
IPolicyStatusValue* policy,
const PolicyValueOverrideFunction& value_override_function) {
DCHECK(policy);
base::win::ScopedBstr value;
if (FAILED(policy->get_value(value.Receive())) || value.Length() == 0) {
return nullptr;
}
base::win::ScopedBstr source;
if (FAILED(policy->get_source(source.Receive())))
return nullptr;
auto entry = std::make_unique<policy::PolicyMap::Entry>(
policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_MACHINE,
GetPolicySource(source.Get()),
value_override_function ? value_override_function.Run(value.Get())
: base::Value(value.Get()),
nullptr);
VARIANT_BOOL has_conflict = VARIANT_FALSE;
base::win::ScopedBstr conflict_value;
base::win::ScopedBstr conflict_source;
if (SUCCEEDED(policy->get_hasConflict(&has_conflict)) &&
has_conflict == VARIANT_TRUE &&
SUCCEEDED(policy->get_conflictValue(conflict_value.Receive())) &&
SUCCEEDED(policy->get_conflictSource(conflict_source.Receive()))) {
entry->AddConflictingPolicy(policy::PolicyMap::Entry(
policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_MACHINE,
GetPolicySource(conflict_source.Get()),
value_override_function
? value_override_function.Run(conflict_value.Get())
: base::Value(conflict_value.Get()),
nullptr));
}
if (entry->source == policy::POLICY_SOURCE_ENTERPRISE_DEFAULT)
entry->SetIsDefaultValue();
return entry;
}
// Copyright 2020 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_GOOGLE_GOOGLE_UPDATE_POLICY_FETCHER_WIN_UTIL_H_
#define CHROME_BROWSER_GOOGLE_GOOGLE_UPDATE_POLICY_FETCHER_WIN_UTIL_H_
#include <wtypes.h>
#include <memory>
#include "base/callback.h"
#include "base/values.h"
#include "components/policy/core/common/policy_map.h"
#include "google_update/google_update_idl.h"
using PolicyValueOverrideFunction = base::RepeatingCallback<base::Value(BSTR)>;
// Converts a |policy| into a PolicyMap::Entry. |value_override_function|
// is an optional callback that modifies the value of the resulting policy.
std::unique_ptr<policy::PolicyMap::Entry> ConvertPolicyStatusValueToPolicyEntry(
IPolicyStatusValue* policy,
const PolicyValueOverrideFunction& value_override_function);
#endif // CHROME_BROWSER_GOOGLE_GOOGLE_UPDATE_POLICY_FETCHER_WIN_UTIL_H_
// Copyright 2020 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/google/google_update_policy_fetcher_win_util.h"
#include <OleCtl.h>
#include <wtypes.h>
#include "base/test/bind_test_util.h"
#include "base/values.h"
#include "base/win/scoped_bstr.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_types.h"
#include "google_update/google_update_idl.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
struct MockPolicyStatusValue : public IPolicyStatusValue {
public:
MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_source, HRESULT(BSTR*));
MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_value, HRESULT(BSTR*));
MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
get_hasConflict,
HRESULT(VARIANT_BOOL*));
MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
get_conflictSource,
HRESULT(BSTR*));
MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
get_conflictValue,
HRESULT(BSTR*));
// IDispatch:
MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
GetTypeInfoCount,
HRESULT(UINT*));
MOCK_METHOD3_WITH_CALLTYPE(STDMETHODCALLTYPE,
GetTypeInfo,
HRESULT(UINT, LCID, ITypeInfo**));
MOCK_METHOD5_WITH_CALLTYPE(STDMETHODCALLTYPE,
GetIDsOfNames,
HRESULT(REFIID, LPOLESTR*, UINT, LCID, DISPID*));
MOCK_METHOD8_WITH_CALLTYPE(STDMETHODCALLTYPE,
Invoke,
HRESULT(DISPID,
REFIID,
LCID,
WORD,
DISPPARAMS*,
VARIANT*,
EXCEPINFO*,
UINT*));
// IUnknown:
MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
QueryInterface,
HRESULT(REFIID,
_COM_Outptr_ void __RPC_FAR* __RPC_FAR*));
MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, AddRef, ULONG(void));
MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, Release, ULONG(void));
};
} // namespace
TEST(ConvertPolicyStatusValueToPolicyEntry, DefaultSource) {
MockPolicyStatusValue policy_status_value;
base::win::ScopedBstr value(L"value");
base::win::ScopedBstr source(L"Default");
VARIANT_BOOL has_conflict = VARIANT_FALSE;
EXPECT_CALL(policy_status_value, get_value(testing::_))
.WillOnce(testing::DoAll(testing::SetArgPointee<0>(value.Get()),
testing::Return(S_OK)));
EXPECT_CALL(policy_status_value, get_source(testing::_))
.WillOnce(testing::DoAll(testing::SetArgPointee<0>(source.Get()),
testing::Return(S_OK)));
EXPECT_CALL(policy_status_value, get_hasConflict(testing::_))
.WillOnce(testing::DoAll(testing::SetArgPointee<0>(has_conflict),
testing::Return(S_OK)));
policy::PolicyMap::Entry expected(
policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_MACHINE,
policy::POLICY_SOURCE_ENTERPRISE_DEFAULT, base::Value("value"), nullptr);
expected.SetIsDefaultValue();
auto actual = ConvertPolicyStatusValueToPolicyEntry(
&policy_status_value, PolicyValueOverrideFunction());
EXPECT_TRUE(expected.Equals(*actual));
}
TEST(ConvertPolicyStatusValueToPolicyEntry, CloudSource) {
MockPolicyStatusValue policy_status_value;
base::win::ScopedBstr value(L"1");
base::win::ScopedBstr source(L"Device Management");
VARIANT_BOOL has_conflict = VARIANT_FALSE;
EXPECT_CALL(policy_status_value, get_value(testing::_))
.WillOnce(testing::DoAll(testing::SetArgPointee<0>(value.Get()),
testing::Return(S_OK)));
EXPECT_CALL(policy_status_value, get_source(testing::_))
.WillOnce(testing::DoAll(testing::SetArgPointee<0>(source.Get()),
testing::Return(S_OK)));
EXPECT_CALL(policy_status_value, get_hasConflict(testing::_))
.WillOnce(testing::DoAll(testing::SetArgPointee<0>(has_conflict),
testing::Return(S_OK)));
policy::PolicyMap::Entry expected(
policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_MACHINE,
policy::POLICY_SOURCE_CLOUD, base::Value("1"), nullptr);
auto actual = ConvertPolicyStatusValueToPolicyEntry(
&policy_status_value, PolicyValueOverrideFunction());
EXPECT_TRUE(expected.Equals(*actual));
}
TEST(ConvertPolicyStatusValueToPolicyEntry, Conflict) {
MockPolicyStatusValue policy_status_value;
base::win::ScopedBstr value(L"a");
base::win::ScopedBstr source(L"Group Policy");
VARIANT_BOOL has_conflict = VARIANT_TRUE;
base::win::ScopedBstr conflict_value(L"ab");
base::win::ScopedBstr conflict_source(L"Device Management");
EXPECT_CALL(policy_status_value, get_value(testing::_))
.WillOnce(testing::DoAll(testing::SetArgPointee<0>(value.Get()),
testing::Return(S_OK)));
EXPECT_CALL(policy_status_value, get_source(testing::_))
.WillOnce(testing::DoAll(testing::SetArgPointee<0>(source.Get()),
testing::Return(S_OK)));
EXPECT_CALL(policy_status_value, get_hasConflict(testing::_))
.WillOnce(testing::DoAll(testing::SetArgPointee<0>(has_conflict),
testing::Return(S_OK)));
EXPECT_CALL(policy_status_value, get_conflictValue(testing::_))
.WillOnce(testing::DoAll(testing::SetArgPointee<0>(conflict_value.Get()),
testing::Return(S_OK)));
EXPECT_CALL(policy_status_value, get_conflictSource(testing::_))
.WillOnce(testing::DoAll(testing::SetArgPointee<0>(conflict_source.Get()),
testing::Return(S_OK)));
policy::PolicyMap::Entry expected(
policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_MACHINE,
policy::POLICY_SOURCE_PLATFORM, base::Value(false), nullptr);
policy::PolicyMap::Entry conflict(
policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_MACHINE,
policy::POLICY_SOURCE_CLOUD, base::Value(true), nullptr);
expected.AddConflictingPolicy(std::move(conflict));
const auto override_value = [](BSTR initial_value) {
return base::Value(::SysStringLen(initial_value) > 1);
};
auto actual = ConvertPolicyStatusValueToPolicyEntry(
&policy_status_value, base::BindRepeating(override_value));
EXPECT_TRUE(expected.Equals(*actual));
}
TEST(ConvertPolicyStatusValueToPolicyEntry, ValueError) {
MockPolicyStatusValue policy_status_value;
base::win::ScopedBstr value(L"a");
base::win::ScopedBstr source(L"Group Policy");
VARIANT_BOOL has_conflict = VARIANT_TRUE;
base::win::ScopedBstr conflict_value(L"ab");
base::win::ScopedBstr conflict_source(L"Device Management");
policy::PolicyMap::Entry expected(
policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_MACHINE,
policy::POLICY_SOURCE_PLATFORM, base::Value("a"), nullptr);
// No policy created if we fail to get the value.
EXPECT_CALL(policy_status_value, get_value(testing::_))
.WillOnce(testing::Return(-1))
.WillRepeatedly(testing::DoAll(testing::SetArgPointee<0>(value.Get()),
testing::Return(S_OK)));
EXPECT_EQ(nullptr, ConvertPolicyStatusValueToPolicyEntry(
&policy_status_value, PolicyValueOverrideFunction())
.get());
// No policy created if we fail to get the source.
EXPECT_CALL(policy_status_value, get_source(testing::_))
.WillOnce(testing::Return(-1))
.WillRepeatedly(testing::DoAll(testing::SetArgPointee<0>(source.Get()),
testing::Return(S_OK)));
EXPECT_EQ(nullptr, ConvertPolicyStatusValueToPolicyEntry(
&policy_status_value, PolicyValueOverrideFunction())
.get());
// No conflict added if we fail to get any of the conflict info.
EXPECT_CALL(policy_status_value, get_hasConflict(testing::_))
.WillOnce(testing::Return(-1))
.WillRepeatedly(testing::DoAll(testing::SetArgPointee<0>(has_conflict),
testing::Return(S_OK)));
EXPECT_TRUE(expected.Equals(*ConvertPolicyStatusValueToPolicyEntry(
&policy_status_value, PolicyValueOverrideFunction())));
// No conflict added if we fail to get any of the conflict value.
EXPECT_CALL(policy_status_value, get_conflictValue(testing::_))
.WillOnce(testing::Return(-1))
.WillRepeatedly(
testing::DoAll(testing::SetArgPointee<0>(conflict_value.Get()),
testing::Return(S_OK)));
EXPECT_TRUE(expected.Equals(*ConvertPolicyStatusValueToPolicyEntry(
&policy_status_value, PolicyValueOverrideFunction())));
// No conflict added if we fail to get any of the conflict info.
EXPECT_CALL(policy_status_value, get_conflictSource(testing::_))
.WillOnce(testing::Return(-1));
EXPECT_TRUE(expected.Equals(*ConvertPolicyStatusValueToPolicyEntry(
&policy_status_value, PolicyValueOverrideFunction())));
}
......@@ -114,7 +114,6 @@
#include "chrome/browser/google/google_update_policy_fetcher_win.h"
#include "chrome/install_static/install_util.h"
#include "components/update_client/updater_state.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#endif // defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
......@@ -450,13 +449,14 @@ class UpdaterStatusProvider : public PolicyStatusProvider {
public:
UpdaterStatusProvider();
~UpdaterStatusProvider() override = default;
void SetUpdaterStatus(std::unique_ptr<GoogleUpdateState> status);
void GetStatus(base::DictionaryValue* dict) override;
private:
static std::string FetchActiveDirectoryDomain();
void OnDomainReceived(std::string domain);
std::string version_;
std::unique_ptr<GoogleUpdateState> updater_status_;
std::string domain_;
base::WeakPtrFactory<UpdaterStatusProvider> weak_factory_{this};
};
......@@ -739,12 +739,6 @@ void DeviceActiveDirectoryPolicyStatusProvider::GetStatus(
#if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
UpdaterStatusProvider::UpdaterStatusProvider() {
auto state =
update_client::UpdaterState::GetState(install_static::IsSystemInstall());
const auto& version = state->find("version");
if (version != state->end())
version_ = version->second;
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE,
{base::ThreadPool(), base::MayBlock(),
......@@ -754,11 +748,24 @@ UpdaterStatusProvider::UpdaterStatusProvider() {
weak_factory_.GetWeakPtr()));
}
void UpdaterStatusProvider::SetUpdaterStatus(
std::unique_ptr<GoogleUpdateState> status) {
updater_status_ = std::move(status);
NotifyStatusChange();
}
void UpdaterStatusProvider::GetStatus(base::DictionaryValue* dict) {
if (!version_.empty())
dict->SetString("version", version_);
if (!domain_.empty())
dict->SetString("domain", domain_);
dict->SetStringKey("domain", domain_);
if (!updater_status_)
return;
if (!updater_status_->version.empty())
dict->SetStringKey("version", updater_status_->version);
if (!updater_status_->last_checked_time.is_null()) {
dict->SetStringKey(
"timeSinceLastRefresh",
GetTimeSinceLastRefreshString(updater_status_->last_checked_time));
}
}
// static
......@@ -780,7 +787,8 @@ void UpdaterStatusProvider::OnDomainReceived(std::string domain) {
domain_ = std::move(domain);
NotifyStatusChange();
}
#endif
#endif // defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
PolicyUIHandler::PolicyUIHandler() {}
......@@ -826,6 +834,7 @@ void PolicyUIHandler::AddCommonLocalizedStringsToSource(
{"unknown", IDS_POLICY_UNKNOWN},
{"unset", IDS_POLICY_UNSET},
{"value", IDS_POLICY_LABEL_VALUE},
{"sourceDefault", IDS_POLICY_SOURCE_DEFAULT},
};
AddLocalizedStringsBulk(source, kStrings);
......@@ -895,7 +904,7 @@ void PolicyUIHandler::RegisterMessages() {
#endif // defined(OS_CHROMEOS)
#if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
ReloadUpdaterPolicies();
ReloadUpdaterPoliciesAndState();
#endif // defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
if (!user_status_provider_.get())
......@@ -1179,7 +1188,7 @@ void PolicyUIHandler::HandleReloadPolicies(const base::ListValue* args) {
#endif
#if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
ReloadUpdaterPolicies();
ReloadUpdaterPoliciesAndState();
#endif // defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
GetPolicyService()->RefreshPolicies(base::BindOnce(
......@@ -1286,14 +1295,16 @@ void PolicyUIHandler::SendPolicies() {
}
#if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
void PolicyUIHandler::SetUpdaterPolicies(
std::unique_ptr<policy::PolicyMap> updater_policies) {
updater_policies_ = std::move(updater_policies);
void PolicyUIHandler::SetUpdaterPoliciesAndState(
std::unique_ptr<GoogleUpdatePoliciesAndState> updater_policies_and_state) {
updater_policies_ = std::move(updater_policies_and_state->policies);
static_cast<UpdaterStatusProvider*>(updater_status_provider_.get())
->SetUpdaterStatus(std::move(updater_policies_and_state->state));
if (updater_policies_)
SendPolicies();
}
void PolicyUIHandler::ReloadUpdaterPolicies() {
void PolicyUIHandler::ReloadUpdaterPoliciesAndState() {
if (!updater_status_provider_)
updater_status_provider_ = std::make_unique<UpdaterStatusProvider>();
base::PostTaskAndReplyWithResult(
......@@ -1301,8 +1312,8 @@ void PolicyUIHandler::ReloadUpdaterPolicies() {
{base::TaskPriority::USER_BLOCKING,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN, base::MayBlock()})
.get(),
FROM_HERE, base::BindOnce(&GetGoogleUpdatePolicies),
base::BindOnce(&PolicyUIHandler::SetUpdaterPolicies,
FROM_HERE, base::BindOnce(&GetGoogleUpdatePoliciesAndState),
base::BindOnce(&PolicyUIHandler::SetUpdaterPoliciesAndState,
weak_factory_.GetWeakPtr()));
}
......
......@@ -32,6 +32,7 @@
#endif
class PolicyStatusProvider;
struct GoogleUpdatePoliciesAndState;
namespace policy {
class PolicyMap;
......@@ -97,11 +98,13 @@ class PolicyUIHandler : public content::WebUIMessageHandler,
void SendPolicies();
#if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
// Sets |updater_policies_| in this instance and refreshes the UI via
// Sets |updater_policies_| in this instance, updates
// |updater_status_provider_| with a new state and refreshes the UI via
// SendPolicies.
void SetUpdaterPolicies(std::unique_ptr<policy::PolicyMap> updater_policies);
void SetUpdaterPoliciesAndState(
std::unique_ptr<GoogleUpdatePoliciesAndState> updater_policies_and_state);
void ReloadUpdaterPolicies();
void ReloadUpdaterPoliciesAndState();
#endif // defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
// Send the status of cloud policy to the UI. For each scope that has cloud
......
......@@ -5828,7 +5828,10 @@ test("unit_tests") {
]
if (is_chrome_branded) {
sources += [ "../browser/google/google_update_win_unittest.cc" ]
sources += [
"../browser/google/google_update_policy_fetcher_win_util_unittest.cc",
"../browser/google/google_update_win_unittest.cc",
]
}
}
if (!is_android && !is_chromeos) {
......
......@@ -153,7 +153,9 @@ Value PolicyConversionsClient::GetPolicyValue(
value.SetKey("level", Value(Value((policy.level == POLICY_LEVEL_RECOMMENDED)
? "recommended"
: "mandatory")));
value.SetKey("source", Value(kPolicySources[policy.source].name));
value.SetKey("source", Value(policy.IsDefaultValue()
? "sourceDefault"
: kPolicySources[policy.source].name));
} else {
value.SetKey("scope", Value(policy.scope));
value.SetKey("level", Value(policy.level));
......
......@@ -67,6 +67,7 @@ PolicyMap::Entry PolicyMap::Entry::DeepCopy() const {
copy.error_strings_ = error_strings_;
copy.error_message_ids_ = error_message_ids_;
copy.warning_message_ids_ = warning_message_ids_;
copy.is_default_value_ = is_default_value_;
copy.conflicts.reserve(conflicts.size());
for (const auto& conflict : conflicts) {
copy.AddConflictingPolicy(conflict.DeepCopy());
......@@ -96,6 +97,7 @@ bool PolicyMap::Entry::Equals(const PolicyMap::Entry& other) const {
error_strings_ == other.error_strings_ &&
error_message_ids_ == other.error_message_ids_ &&
warning_message_ids_ == other.warning_message_ids_ &&
is_default_value_ == other.is_default_value_ &&
((!value_ && !other.value()) ||
(value_ && other.value() && *value_ == *other.value())) &&
ExternalDataFetcher::Equals(external_data_fetcher.get(),
......@@ -171,6 +173,14 @@ bool PolicyMap::Entry::IsIgnoredByAtomicGroup() const {
error_message_ids_.end();
}
void PolicyMap::Entry::SetIsDefaultValue() {
is_default_value_ = true;
}
bool PolicyMap::Entry::IsDefaultValue() const {
return is_default_value_;
}
PolicyMap::PolicyMap() = default;
PolicyMap::~PolicyMap() {
......
......@@ -102,6 +102,11 @@ class POLICY_EXPORT PolicyMap {
void SetIgnoredByPolicyAtomicGroup();
bool IsIgnoredByAtomicGroup() const;
// Sets that the policy's value is a default value set by the policy
// provider.
void SetIsDefaultValue();
bool IsDefaultValue() const;
// Callback used to look up a localized string given its l10n message ID. It
// should return a UTF-16 string.
typedef base::RepeatingCallback<base::string16(int message_id)>
......@@ -118,6 +123,7 @@ class POLICY_EXPORT PolicyMap {
private:
base::Optional<base::Value> value_;
bool ignored_ = false;
bool is_default_value_ = false;
std::string error_strings_;
std::set<int> error_message_ids_;
std::set<int> warning_message_ids_;
......
......@@ -171,10 +171,12 @@ cr.define('policy', function() {
status.isAffiliated ? 'isAffiliatedYes' : 'isAffiliatedNo'));
}
}
if (scope !== 'updater') {
if (status.timeSinceLastRefresh) {
this.setLabelAndShow_(
'.time-since-last-refresh', status.timeSinceLastRefresh);
}
if (scope !== 'updater') {
this.setLabelAndShow_('.refresh-interval', status.refreshInterval);
this.setLabelAndShow_('.status', status.status);
this.setLabelAndShow_(
......
......@@ -444,6 +444,9 @@ Additional details:
<message name="IDS_POLICY_SOURCE_ENTERPRISE_DEFAULT" desc="Indicates that a policy is set by default in an enterprise environment and can be overridden (for Chrome OS only).">
Enterprise default
</message>
<message name="IDS_POLICY_SOURCE_DEFAULT" desc="Indicates that a policy is set by default and can be overridden.">
Default
</message>
<message name="IDS_POLICY_SOURCE_COMMAND_LINE" desc="Indicates that a policy is set by command line switch for testing purpose.">
Command line
</message>
......
27e8e99e4c0e7bf60c11bd98395e7bebc3b9ad29
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment