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.

(cherry picked from commit 2644fc8db25fa9aa5e26f298208636112c434a47)

Bug: 1032756
Change-Id: Iadb2199bcdc704a426e80e00e2bb8aa5b21e0648
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2380582
Commit-Queue: Yann Dago <[email protected]>
Reviewed-by: S. Ganesh <[email protected]>
Reviewed-by: Peter Kasting <[email protected]>
Reviewed-by: Greg Thompson <[email protected]>
Reviewed-by: Owen Min <[email protected]>
Cr-Original-Commit-Position: refs/heads/master@{#814536}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2463442
Reviewed-by: Yann Dago <[email protected]>
Cr-Commit-Position: refs/branch-heads/4280@{#188}
Cr-Branched-From: ea420fb963f9658c9969b6513c56b8f47efa1a2a-refs/heads/master@{#812852}
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 7bab0f8..c2fa470 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -4605,6 +4605,8 @@
         "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",
diff --git a/chrome/browser/google/google_update_policy_fetcher_win.cc b/chrome/browser/google/google_update_policy_fetcher_win.cc
index 6f4ee998..b1833d5 100644
--- a/chrome/browser/google/google_update_policy_fetcher_win.cc
+++ b/chrome/browser/google/google_update_policy_fetcher_win.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 @@
 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 @@
 // "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::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_PLATFORM,
-                std::move(value), nullptr);
+               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);
 
-  // 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;
+  policy_status->refreshPolicies();
+  auto policies = std::make_unique<policy::PolicyMap>();
+  base::win::ScopedBstr app_id(install_static::GetAppGuid());
 
+  {
+    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 @@
   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 @@
     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 @@
     AddPolicy(kUpdatePolicy,
               base::Value(
                   base::saturated_cast<int>(effective_policy_for_app_updates)),
-              policies.get());
+              *policies);
   }
 
   DWORD updates_suppressed_duration;
@@ -130,15 +229,15 @@
     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 @@
     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 @@
       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;
+}
diff --git a/chrome/browser/google/google_update_policy_fetcher_win.h b/chrome/browser/google/google_update_policy_fetcher_win.h
index 199497fc..926064c 100644
--- a/chrome/browser/google/google_update_policy_fetcher_win.h
+++ b/chrome/browser/google/google_update_policy_fetcher_win.h
@@ -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 @@
 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 @@
 // 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_
diff --git a/chrome/browser/google/google_update_policy_fetcher_win_util.cc b/chrome/browser/google/google_update_policy_fetcher_win_util.cc
new file mode 100644
index 0000000..5bf78e6d
--- /dev/null
+++ b/chrome/browser/google/google_update_policy_fetcher_win_util.cc
@@ -0,0 +1,71 @@
+// 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;
+}
diff --git a/chrome/browser/google/google_update_policy_fetcher_win_util.h b/chrome/browser/google/google_update_policy_fetcher_win_util.h
new file mode 100644
index 0000000..01bd998c
--- /dev/null
+++ b/chrome/browser/google/google_update_policy_fetcher_win_util.h
@@ -0,0 +1,24 @@
+// 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_
diff --git a/chrome/browser/google/google_update_policy_fetcher_win_util_unittest.cc b/chrome/browser/google/google_update_policy_fetcher_win_util_unittest.cc
new file mode 100644
index 0000000..f051bb1
--- /dev/null
+++ b/chrome/browser/google/google_update_policy_fetcher_win_util_unittest.cc
@@ -0,0 +1,207 @@
+// 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())));
+}
diff --git a/chrome/browser/ui/webui/policy_ui_handler.cc b/chrome/browser/ui/webui/policy_ui_handler.cc
index cb9a791a..bb401e07 100644
--- a/chrome/browser/ui/webui/policy_ui_handler.cc
+++ b/chrome/browser/ui/webui/policy_ui_handler.cc
@@ -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 @@
  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 @@
 
 #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 @@
                      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 @@
   domain_ = std::move(domain);
   NotifyStatusChange();
 }
-#endif
+
+#endif  // defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
 
 PolicyUIHandler::PolicyUIHandler() {}
 
@@ -826,6 +834,7 @@
       {"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 @@
 #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 @@
 #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 @@
 }
 
 #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 @@
           {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()));
 }
 
diff --git a/chrome/browser/ui/webui/policy_ui_handler.h b/chrome/browser/ui/webui/policy_ui_handler.h
index 4967821b5..2b26a9a 100644
--- a/chrome/browser/ui/webui/policy_ui_handler.h
+++ b/chrome/browser/ui/webui/policy_ui_handler.h
@@ -32,6 +32,7 @@
 #endif
 
 class PolicyStatusProvider;
+struct GoogleUpdatePoliciesAndState;
 
 namespace policy {
 class PolicyMap;
@@ -97,11 +98,13 @@
   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
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index ecfa05b..5a980cb 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -5704,7 +5704,10 @@
     ]
 
     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) {
diff --git a/components/policy/core/browser/policy_conversions_client.cc b/components/policy/core/browser/policy_conversions_client.cc
index 7ec3468..1285d8e 100644
--- a/components/policy/core/browser/policy_conversions_client.cc
+++ b/components/policy/core/browser/policy_conversions_client.cc
@@ -153,7 +153,9 @@
     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));
diff --git a/components/policy/core/common/policy_map.cc b/components/policy/core/common/policy_map.cc
index 8c8cb7d..9361093 100644
--- a/components/policy/core/common/policy_map.cc
+++ b/components/policy/core/common/policy_map.cc
@@ -67,6 +67,7 @@
   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 @@
       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 @@
          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() {
diff --git a/components/policy/core/common/policy_map.h b/components/policy/core/common/policy_map.h
index 9b07543..cb7effd 100644
--- a/components/policy/core/common/policy_map.h
+++ b/components/policy/core/common/policy_map.h
@@ -102,6 +102,11 @@
     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 @@
    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_;
diff --git a/components/policy/resources/webui/policy_base.js b/components/policy/resources/webui/policy_base.js
index 0dfd2768..39607fa 100644
--- a/components/policy/resources/webui/policy_base.js
+++ b/components/policy/resources/webui/policy_base.js
@@ -171,10 +171,12 @@
                   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_(
diff --git a/components/policy_strings.grdp b/components/policy_strings.grdp
index c93f5ecf..80f52152 100644
--- a/components/policy_strings.grdp
+++ b/components/policy_strings.grdp
@@ -444,6 +444,9 @@
   <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>
diff --git a/components/policy_strings_grdp/IDS_POLICY_SOURCE_DEFAULT.png.sha1 b/components/policy_strings_grdp/IDS_POLICY_SOURCE_DEFAULT.png.sha1
new file mode 100644
index 0000000..314243b
--- /dev/null
+++ b/components/policy_strings_grdp/IDS_POLICY_SOURCE_DEFAULT.png.sha1
@@ -0,0 +1 @@
+27e8e99e4c0e7bf60c11bd98395e7bebc3b9ad29
\ No newline at end of file