Commit 149f5cd5 authored by Yann Dago's avatar Yann Dago Committed by Commit Bot

Management WebUI: Refactor to remove non static data from loadTimeData

Visual: http://screen/f95xLi88ybU

Bug: 951066
Change-Id: I31ddebbd8b41a291b668b24c47cc4a1e9db33c44
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1558686Reviewed-by: default avatarHector Carmona <hcarmona@chromium.org>
Reviewed-by: default avatarThiemo Nagel <tnagel@chromium.org>
Commit-Queue: Yann Dago <ydago@chromium.org>
Cr-Commit-Position: refs/heads/master@{#650405}
parent 9a8df283
......@@ -28,6 +28,27 @@ management.ReportingType = {
*/
management.BrowserReportingResponse;
/**
* @typedef {{
* overview: string,
* setup: string,
* data: string,
* }}
*/
management.ManagedInfo;
/**
* @typedef {{
* accountManagedInfo: ?management.ManagedInfo,
* browserManagementNotice: string,
* deviceManagedInfo: ?management.ManagedInfo,
* extensionReportingTitle: string,
* pageSubtitle: string,
* overview: string,
* }}
*/
management.ManagedDataResponse;
// <if expr="chromeos">
/**
* @enum {string} Look at ToJSDeviceReportingType usage in
......@@ -52,33 +73,12 @@ management.DeviceReportingType = {
management.DeviceReportingResponse;
// </if>
/**
* @typedef {{
* overview: string,
* setup: string,
* data: string,
* }}
*/
management.ManagedInfo;
/**
* @typedef {{
* overview: string,
* deviceManagedInfo: ?management.ManagedInfo,
* accountManagedInfo: ?management.ManagedInfo,
* }}
*/
management.ManagementStatus;
cr.define('management', function() {
/** @interface */
class ManagementBrowserProxy {
/** @return {!Promise<!Array<!management.Extension>>} */
getExtensions() {}
/** @return {!Promise<!management.ManagementStatus>} */
getManagementStatus() {}
// <if expr="chromeos">
/**
* @return {!Promise<boolean>} Boolean describing trust root configured
......@@ -93,10 +93,8 @@ cr.define('management', function() {
getDeviceReportingInfo() {}
// </if>
// <if expr="not chromeos">
/** @return {string} */
getManagementNotice() {}
// </if>
/** @return {!Promise<!management.ManagedDataResponse>} */
getContextualManagedData() {}
/**
* @return {!Promise<!Array<!management.BrowserReportingResponse>>} The list
......@@ -112,11 +110,6 @@ cr.define('management', function() {
return cr.sendWithPromise('getExtensions');
}
/** @override */
getManagementStatus() {
return cr.sendWithPromise('getManagementStatus');
}
// <if expr="chromeos">
/** @override */
getLocalTrustRootsInfo() {
......@@ -129,12 +122,10 @@ cr.define('management', function() {
}
// </if>
// <if expr="not chromeos">
/** @override */
getManagementNotice() {
return loadTimeData.getString('managementNotice');
getContextualManagedData() {
return cr.sendWithPromise('getContextualManagedData');
}
// </if>
/** @override */
initBrowserReportingInfo() {
......
......@@ -96,10 +96,14 @@
margin-top: 1em;
}
.overview-messages div + div {
.overview-messages {
margin-top: 0;
}
.overview-messages li {
margin-top: 8px;
}
<if expr="chromeos">
.device-reporting div {
align-items: center;
......@@ -173,36 +177,27 @@
[[subtitle_]]
</section>
<section class="single-column overview-section">
<if expr="not chromeos">
<if expr="not chromeos">
<p inner-h-t-m-l="[[managementNoticeHtml_]]"></p>
</if>
</if>
<if expr="chromeos">
<div>[[managementOverview_]]</div>
<div class="overview-messages"
<div>[[deviceManagedInfo_.overview]]</div>
<ul class="overview-messages"
hidden="[[!deviceManagedInfo_]]">
[[deviceManagedInfo_.overview]]
<div class="content-indented">
<li>
[[deviceManagedInfo_.setup]]
<a href="$i18nRaw{managementDeviceLearnMoreUrl}"
target="_blank">$i18n{learnMore}</a>
</div>
<div class="content-indented">[[deviceManagedInfo_.data]]</div>
</div>
</if>
<div class="overview-messages" hidden="[[!accountManagedInfo_]]">
[[accountManagedInfo_.overview]]
<div class="content-indented">
<if expr="chromeos">
[[accountManagedInfo_.setup]]
<a href="$i18nRaw{managementAccountLearnMoreUrl}"
target="_blank">$i18n{learnMore}</a>
</if>
<if expr="not chromeos">
[[accountManagedInfo_.setup]]
</li>
<li>[[deviceManagedInfo_.data]]</li>
</ul>
</if>
</div>
<div class="content-indented">[[accountManagedInfo_.data]]</div>
</div>
<div>[[accountManagedInfo_.overview]]</div>
<ul class="overview-messages" hidden="[[!accountManagedInfo_]]">
<li>[[accountManagedInfo_.setup]]</li>
<li>[[accountManagedInfo_.data]]</li>
</ul>
</section>
<if expr="chromeos">
<div hidden="[[!localTrustRoots_]]">
......
......@@ -81,8 +81,7 @@ Polymer({
'browser-reporting-info-updated',
reportingInfo => this.onBrowserReportingInfoReceived_(reportingInfo));
this.addWebUIListener('update-load-time-data', data => {
loadTimeData.overrideValues(data);
this.addWebUIListener('managed_state_changed', () => {
this.updateManagedFields_();
});
......@@ -91,7 +90,6 @@ Polymer({
this.getDeviceReportingInfo_();
this.getLocalTrustRootsInfo_();
// </if>
this.getManagementStatus_();
},
/** @private */
......@@ -128,17 +126,6 @@ Polymer({
.map(reportingType => reportingInfoMap[reportingType]);
},
/** @private */
getManagementStatus_() {
this.browserProxy_.getManagementStatus().then(status => {
// <if expr="chromeos">
this.managementOverview_ = status.overview;
this.deviceManagedInfo_ = status.deviceManagedInfo;
// </if>
this.accountManagedInfo_ = status.accountManagedInfo;
});
},
/** @private */
getExtensions_() {
this.browserProxy_.getExtensions().then(extensions => {
......@@ -250,11 +237,17 @@ Polymer({
/** @private */
updateManagedFields_() {
this.subtitle_ = loadTimeData.getString('subtitle');
this.browserProxy_.getContextualManagedData().then(data => {
this.extensionReportingSubtitle_ = data.extensionReportingTitle;
this.subtitle_ = data.pageSubtitle;
this.accountManagedInfo_ = data.accountManagedInfo;
// <if expr="chromeos">
this.managementOverview_ = data.overview;
this.deviceManagedInfo_ = data.deviceManagedInfo;
// </if>
// <if expr="not chromeos">
this.managementNoticeHtml_ = this.browserProxy_.getManagementNotice();
this.managementNoticeHtml_ = data.browserManagementNotice;
// </if>
this.extensionReportingSubtitle_ =
loadTimeData.getString('extensionReportingTitle');
});
},
});
......@@ -123,8 +123,6 @@ content::WebUIDataSource* CreateManagementUIHtmlSource() {
source->AddString("managementDeviceLearnMoreUrl",
chrome::kLearnMoreEnterpriseURL);
#endif // defined(OS_CHROMEOS)
source->AddString("managementAccountLearnMoreUrl",
chrome::kManagedUiLearnMoreUrl);
source->SetJsonPath("strings.js");
// Add required resources.
......
......@@ -33,21 +33,14 @@ class ManagementUITest : public InProcessBrowserTest {
void VerifyTexts(base::Value* actual_values,
std::map<std::string, base::string16>& expected_values) {
base::ListValue* values_as_list = NULL;
actual_values->GetAsList(&values_as_list);
for (size_t i = 0; i < values_as_list->GetSize(); ++i) {
base::Value* result = NULL;
EXPECT_TRUE(values_as_list->Get(i, &result));
auto* name = result->FindStringKey("name");
auto* value = result->FindKey("value");
DCHECK(name);
auto expected_value = base::Value(expected_values[*name]);
DCHECK(value);
ASSERT_TRUE(value->Equals(&expected_value));
base::DictionaryValue* values_as_dict = NULL;
actual_values->GetAsDictionary(&values_as_dict);
for (const auto& val : expected_values) {
base::string16 actual_value;
values_as_dict->GetString(val.first, &actual_value);
ASSERT_EQ(actual_value, val.second);
}
}
policy::MockConfigurationPolicyProvider* provider() { return &provider_; }
policy::ProfilePolicyConnector* profile_policy_connector() {
......@@ -68,21 +61,10 @@ IN_PROC_BROWSER_TEST_F(ManagementUITest, ManagementStateChange) {
// The browser is not managed.
const std::string javascript =
"const unmanaged_result = [];"
"unmanaged_result.push({"
" name: 'browserManagementNotice',"
" value: management.ManagementBrowserProxyImpl"
" .getInstance().getManagementNotice()"
"});"
"unmanaged_result.push({"
" name: 'extensionReportingTitle',"
" value: loadTimeData.getString('extensionReportingTitle')"
"});"
"unmanaged_result.push({"
" name: 'pageSubtitle',"
" value: loadTimeData.getString('subtitle')"
"});"
"domAutomationController.send(JSON.stringify(unmanaged_result));";
"management.ManagementBrowserProxyImpl.getInstance()"
" .getContextualManagedData()"
" .then(managed_result => "
" domAutomationController.send(JSON.stringify(managed_result)));";
content::WebContents* contents =
browser()->tab_strip_model()->GetActiveWebContents();
......@@ -101,6 +83,9 @@ IN_PROC_BROWSER_TEST_F(ManagementUITest, ManagementStateChange) {
l10n_util::GetStringUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED)},
{"pageSubtitle",
l10n_util::GetStringUTF16(IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE)},
{"accountManagedInfo.overview", base::string16()},
{"accountManagedInfo.data", base::string16()},
{"accountManagedInfo.setup", base::string16()},
};
VerifyTexts(unmanaged_value_ptr.get(), expected_unmanaged_values);
......@@ -117,24 +102,8 @@ IN_PROC_BROWSER_TEST_F(ManagementUITest, ManagementStateChange) {
contents = browser()->tab_strip_model()->GetActiveWebContents();
std::string managed_json;
const std::string javascript_2 =
"const managed_result = [];"
"managed_result.push({"
" name: 'browserManagementNotice',"
" value: management.ManagementBrowserProxyImpl"
" .getInstance().getManagementNotice()"
"});"
"managed_result.push({"
" name: 'extensionReportingTitle',"
" value: loadTimeData.getString('extensionReportingTitle')"
"});"
"managed_result.push({"
" name: 'pageSubtitle',"
" value: loadTimeData.getString('subtitle')"
"});"
"domAutomationController.send(JSON.stringify(managed_result));";
ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents, javascript_2,
ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents, javascript,
&managed_json));
std::unique_ptr<base::Value> managed_value_ptr =
......@@ -147,6 +116,13 @@ IN_PROC_BROWSER_TEST_F(ManagementUITest, ManagementStateChange) {
{"extensionReportingTitle",
l10n_util::GetStringUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED)},
{"pageSubtitle", l10n_util::GetStringUTF16(IDS_MANAGEMENT_SUBTITLE)},
{"accountManagedInfo.overview",
l10n_util::GetStringUTF16(
IDS_MANAGEMENT_ACCOUNT_MANAGED_CLARIFICATION_UNKNOWN_DOMAIN)},
{"accountManagedInfo.data",
l10n_util::GetStringUTF16(IDS_MANAGEMENT_ACCOUNT_MANAGED_DATA)},
{"accountManagedInfo.setup",
l10n_util::GetStringUTF16(IDS_MANAGEMENT_ACCOUNT_MANAGED_SETUP)},
};
VerifyTexts(managed_value_ptr.get(), expected_managed_values);
......
......@@ -116,10 +116,10 @@ const char kManagementReportNetworkInterfaces[] =
"managementReportNetworkInterfaces";
const char kManagementReportUsers[] = "managementReportUsers";
const char kManagementPrinting[] = "managementPrinting";
const char kDeviceManagedInfo[] = "deviceManagedInfo";
#endif // defined(OS_CHROMEOS)
const char kOverview[] = "overview";
const char kDeviceManagedInfo[] = "deviceManagedInfo";
const char kAccountManagedInfo[] = "accountManagedInfo";
const char kSetup[] = "setup";
const char kData[] = "data";
......@@ -155,53 +155,6 @@ std::string GetAccountDomain(Profile* profile) {
return consumer_domain_pos == std::string::npos ? domain : std::string();
}
#if !defined(OS_CHROMEOS)
void GetDataManagementBrowserContextualSourceUpdate(
base::DictionaryValue* update,
Profile* profile,
bool managed) {
auto management_domain = GetAccountDomain(profile);
if (management_domain.empty()) {
update->SetString(
"extensionReportingTitle",
l10n_util::GetStringUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED));
update->SetString("managementNotice",
l10n_util::GetStringFUTF16(
managed ? IDS_MANAGEMENT_BROWSER_NOTICE
: IDS_MANAGEMENT_NOT_MANAGED_NOTICE,
base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl)));
update->SetString("subtitle",
l10n_util::GetStringUTF16(
managed ? IDS_MANAGEMENT_SUBTITLE
: IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE));
} else {
update->SetString(
"extensionReportingTitle",
l10n_util::GetStringFUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED_BY,
base::UTF8ToUTF16(management_domain)));
update->SetString(
"managementNotice",
managed ? l10n_util::GetStringFUTF16(
IDS_MANAGEMENT_MANAGEMENT_BY_NOTICE,
base::UTF8ToUTF16(management_domain),
base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl))
: l10n_util::GetStringFUTF16(
IDS_MANAGEMENT_NOT_MANAGED_NOTICE,
base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl)));
update->SetString(
"subtitle",
managed
? l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED_BY,
base::UTF8ToUTF16(management_domain))
: l10n_util::GetStringUTF16(IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE));
}
}
#endif // !defined(OS_CHROMEOS)
#if defined(OS_CHROMEOS)
enum class DeviceReportingType {
......@@ -385,17 +338,13 @@ void ManagementUIHandler::InitializeInternal(content::WebUI* web_ui,
handler->managed_ = IsProfileManaged(profile) || IsBrowserManaged();
#endif // defined(OS_CHROMEOS)
source->AddLocalizedStrings(
*handler->GetDataManagementContextualSourceUpdate(profile));
handler->web_ui_data_source_name_ = source->GetSource();
web_ui->AddMessageHandler(std::move(handler));
}
void ManagementUIHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback(
"getManagementStatus",
base::BindRepeating(&ManagementUIHandler::HandleGetManagementStatus,
"getContextualManagedData",
base::BindRepeating(&ManagementUIHandler::HandleGetContextualManagedData,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"getExtensions",
......@@ -523,6 +472,57 @@ void ManagementUIHandler::AddExtensionReportingInfo(
}
}
base::DictionaryValue ManagementUIHandler::GetContextualManagedData(
Profile* profile) const {
base::DictionaryValue response;
auto management_domain = GetAccountDomain(profile);
if (management_domain.empty()) {
response.SetString(
"extensionReportingTitle",
l10n_util::GetStringUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED));
#if !defined(OS_CHROMEOS)
response.SetString("browserManagementNotice",
l10n_util::GetStringFUTF16(
managed_ ? IDS_MANAGEMENT_BROWSER_NOTICE
: IDS_MANAGEMENT_NOT_MANAGED_NOTICE,
base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl)));
response.SetString("pageSubtitle",
l10n_util::GetStringUTF16(
managed_ ? IDS_MANAGEMENT_SUBTITLE
: IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE));
#endif // !defined(OS_CHROMEOS)
} else {
response.SetString(
"extensionReportingTitle",
l10n_util::GetStringFUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED_BY,
base::UTF8ToUTF16(management_domain)));
#if !defined(OS_CHROMEOS)
response.SetString(
"browserManagementNotice",
managed_ ? l10n_util::GetStringFUTF16(
IDS_MANAGEMENT_MANAGEMENT_BY_NOTICE,
base::UTF8ToUTF16(management_domain),
base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl))
: l10n_util::GetStringFUTF16(
IDS_MANAGEMENT_NOT_MANAGED_NOTICE,
base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl)));
#endif // !defined(OS_CHROMEOS)
response.SetString(
"pageSubtitle",
managed_
? l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED_BY,
base::UTF8ToUTF16(management_domain))
: l10n_util::GetStringUTF16(IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE));
}
GetManagementStatus(profile, &response);
return response;
}
policy::PolicyService* ManagementUIHandler::GetPolicyService() const {
return policy::ProfilePolicyConnectorFactory::GetForBrowserContext(
Profile::FromWebUI(web_ui()))
......@@ -537,18 +537,6 @@ const extensions::Extension* ManagementUIHandler::GetEnabledExtension(
}
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
std::unique_ptr<base::DictionaryValue>
ManagementUIHandler::GetDataManagementContextualSourceUpdate(
Profile* profile) const {
auto update = std::make_unique<base::DictionaryValue>();
#if !defined(OS_CHROMEOS)
GetDataManagementBrowserContextualSourceUpdate(update.get(), profile,
managed_);
#endif // !defined(OS_CHROMEOS)
return update;
}
#if defined(OS_CHROMEOS)
void AddStatusDeviceManagedInfo(base::Value* status,
const std::string& device_domain) {
......@@ -582,9 +570,16 @@ void AddStatusDeviceAndAccountManagedInfo(
void AddStatusAccountManagedInfo(base::Value* status,
const std::string& account_domain) {
base::Value info(base::Value::Type::DICTIONARY);
if (account_domain.empty()) {
info.SetKey(
kOverview,
base::Value(l10n_util::GetStringUTF16(
IDS_MANAGEMENT_ACCOUNT_MANAGED_CLARIFICATION_UNKNOWN_DOMAIN)));
} else {
info.SetKey(kOverview, base::Value(l10n_util::GetStringFUTF16(
IDS_MANAGEMENT_ACCOUNT_MANAGED_CLARIFICATION,
base::UTF8ToUTF16(account_domain))));
}
info.SetKey(kSetup, base::Value(l10n_util::GetStringUTF16(
IDS_MANAGEMENT_ACCOUNT_MANAGED_SETUP)));
info.SetKey(kData, base::Value(l10n_util::GetStringUTF16(
......@@ -633,8 +628,8 @@ void AddStatusOverviewManagedAccount(base::Value* status,
status->SetKey(kOverview, base::Value(l10n_util::GetStringFUTF16(
IDS_MANAGEMENT_ACCOUNT_MANAGED_BY,
base::UTF8ToUTF16(account_domain))));
#endif // defined(OS_CHROMEOS)
status->SetKey(kDeviceManagedInfo, base::Value());
#endif // defined(OS_CHROMEOS)
AddStatusAccountManagedInfo(status, account_domain);
}
......@@ -647,8 +642,8 @@ void AddStatusOverviewNotManaged(base::Value* status) {
}
#endif // defined(OS_CHROMEOS)
void ManagementUIHandler::GetManagementStatus(base::Value* status) {
auto* profile = Profile::FromWebUI(web_ui());
void ManagementUIHandler::GetManagementStatus(Profile* profile,
base::Value* status) const {
const std::string account_domain = GetAccountDomain(profile);
#if defined(OS_CHROMEOS)
const bool account_managed = IsProfileManaged(profile);
......@@ -709,15 +704,6 @@ void ManagementUIHandler::GetManagementStatus(base::Value* status) {
#endif // defined(OS_CHROMEOS)
}
void ManagementUIHandler::HandleGetManagementStatus(
const base::ListValue* args) {
base::RecordAction(base::UserMetricsAction("ManagementPageViewed"));
AllowJavascript();
base::Value status(base::Value::Type::DICTIONARY);
GetManagementStatus(&status);
ResolveJavascriptCallback(args->GetList()[0] /* callback_id */, status);
}
void ManagementUIHandler::HandleGetExtensions(const base::ListValue* args) {
AllowJavascript();
#if BUILDFLAG(ENABLE_EXTENSIONS)
......@@ -765,6 +751,13 @@ void ManagementUIHandler::HandleGetDeviceReportingInfo(
}
#endif // defined(OS_CHROMEOS)
void ManagementUIHandler::HandleGetContextualManagedData(
const base::ListValue* args) {
AllowJavascript();
auto result = GetContextualManagedData(Profile::FromWebUI(web_ui()));
ResolveJavascriptCallback(args->GetList()[0] /* callback_id */,
std::move(result));
}
void ManagementUIHandler::HandleInitBrowserReportingInfo(
const base::ListValue* args) {
......@@ -816,11 +809,7 @@ void ManagementUIHandler::OnManagedStateChanged() {
managed_ = managed;
auto data_source_update = GetDataManagementContextualSourceUpdate(profile);
FireWebUIListener("update-load-time-data", data_source_update->Clone());
content::WebUIDataSource::Update(profile, web_ui_data_source_name_,
std::move(data_source_update));
FireWebUIListener("managed_state_changed");
}
void ManagementUIHandler::OnPolicyUpdated(
......
......@@ -106,22 +106,19 @@ class ManagementUIHandler : public content::WebUIMessageHandler {
protected:
// Protected for testing.
std::unique_ptr<base::DictionaryValue>
GetDataManagementContextualSourceUpdate(Profile* profile) const;
static void InitializeInternal(content::WebUI* web_ui,
content::WebUIDataSource* source,
Profile* profile);
void AddExtensionReportingInfo(base::Value* report_sources);
base::DictionaryValue GetContextualManagedData(Profile* profile) const;
virtual policy::PolicyService* GetPolicyService() const;
virtual const extensions::Extension* GetEnabledExtension(
const std::string& extensionId) const;
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
private:
void GetManagementStatus(base::Value* status);
void HandleGetManagementStatus(const base::ListValue* args);
void GetManagementStatus(Profile* profile, base::Value* status) const;
#if defined(OS_CHROMEOS)
void HandleGetDeviceReportingInfo(const base::ListValue* args);
......@@ -133,6 +130,7 @@ class ManagementUIHandler : public content::WebUIMessageHandler {
void HandleGetLocalTrustRootsInfo(const base::ListValue* args);
#endif // defined(OS_CHROMEOS)
void HandleGetContextualManagedData(const base::ListValue* args);
void HandleInitBrowserReportingInfo(const base::ListValue* args);
#if BUILDFLAG(ENABLE_EXTENSIONS)
......
......@@ -95,7 +95,10 @@
</message>
</if>
<!-- Account managed clarification -->
<message name="IDS_MANAGEMENT_ACCOUNT_MANAGED_CLARIFICATION" desc="First part of the sentence of the managed account clarification.">
<message name="IDS_MANAGEMENT_ACCOUNT_MANAGED_CLARIFICATION_UNKNOWN_DOMAIN" desc="First part of the sentence for managed account clarification. This is a header over a bullet point list.">
The company, school, or organization that manages this account:
</message>
<message name="IDS_MANAGEMENT_ACCOUNT_MANAGED_CLARIFICATION" desc="First part of the sentence for managed account clarification. This is a header over a bullet point list.">
As the manager of your account, <ph name="ACCOUNT_DOMAIN">$1<ex>example.com</ex></ph>:
</message>
<message name="IDS_MANAGEMENT_ACCOUNT_MANAGED_SETUP" desc="Continuation of the managed account clarification sentence explaining account setup management.">
......
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