Commit 5a5b7a65 authored by Aga Wronska's avatar Aga Wronska Committed by Commit Bot

Load Play Store privacy policy from the disk during offline Demo Mode setup.

      Run about_ui_unittest.
      Manually perform offline demo mode setup.

Bug: 857275
Test: Run wizard controller and demo setup browser tests.
Change-Id: Ife8f6daa3d8fb87f2adf31350845efa67463b939
Reviewed-on: https://chromium-review.googlesource.com/1244476
Commit-Queue: Aga Wronska <agawronska@chromium.org>
Reviewed-by: default avatarMichael Giuffrida <michaelpg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#594545}
parent 17a64949
......@@ -191,7 +191,8 @@ login.createScreen('EulaScreen', 'eula', function() {
var TERMS_URL = 'chrome://terms';
var loadBundledEula = function() {
WebViewHelper.loadUrlToWebview(webview, TERMS_URL);
WebViewHelper.loadUrlContentToWebView(
webview, TERMS_URL, WebViewHelper.ContentType.HTML);
};
webview.addContentScripts([{
......
......@@ -390,7 +390,14 @@ login.createScreen('ArcTermsOfServiceScreen', 'arc-tos', function() {
* @param {string} targetUrl URL to open.
*/
showUrlOverlay: function(targetUrl) {
$('arc-tos-overlay-webview').src = targetUrl;
var webView = $('arc-tos-overlay-webview');
if (this.usingOfflineTerms_) {
const TERMS_URL = 'chrome://terms/arc/privacy_policy';
WebViewHelper.loadUrlContentToWebView(
webView, TERMS_URL, WebViewHelper.ContentType.PDF);
} else {
webView.src = targetUrl;
}
$('arc-tos-overlay-webview-container').classList.add('overlay-loading');
this.showOverlay('arc-overlay-url');
},
......@@ -555,9 +562,10 @@ login.createScreen('ArcTermsOfServiceScreen', 'arc-tos', function() {
// If in demo mode fallback to offline Terms of Service copy.
if (this.isDemoModeSetup_()) {
this.usingOfflineTerms_ = true;
const TERMS_URL = 'chrome://terms/arc';
const TERMS_URL = 'chrome://terms/arc/terms';
var webView = this.getElement_('arc-tos-view');
WebViewHelper.loadUrlToWebview(webView, TERMS_URL);
WebViewHelper.loadUrlContentToWebView(
webView, TERMS_URL, WebViewHelper.ContentType.HTML);
return;
}
this.showError_();
......
......@@ -9,28 +9,43 @@
/** Web view helper shared between OOBE screens. */
class WebViewHelper {
/**
* Loads text/html contents from the given url into the given webview. The
* content is loaded via XHR and is sent to webview via data url so that it
* is properly sandboxed.
* Loads content of the given url into the given web view.
* The content is loaded via XHR and is sent to web view via data url so that
* it is properly sandboxed.
*
* @param {!WebView} webView web view element to host the text/html content.
* @param {string} url URL to load text/html from.
* @param {!WebView} webView web view element to host the content.
* @param {string} url URL to load the content from.
* @param {!ContentType} contentType type of the content to load.
*/
static loadUrlToWebview(webView, url) {
static loadUrlContentToWebView(webView, url, contentType) {
assert(webView.tagName === 'WEBVIEW');
const onError = function() {
webView.src = 'about:blank';
};
const setContents = function(contents) {
webView.src =
'data:text/html;charset=utf-8,' + encodeURIComponent(contents);
/**
* Sets contents to web view.
* Prefixes data with appropriate scheme, MIME type and token.
* @param {string} data data string to set.
*/
const setContents = function(data) {
switch (contentType) {
case WebViewHelper.ContentType.HTML:
webView.src =
'data:text/html;charset=utf-8,' + encodeURIComponent(data);
break;
case WebViewHelper.ContentType.PDF:
webView.src = 'data:application/pdf;base64,' + data;
break;
default:
assertNotReached('Unknown content type to load.');
}
};
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.setRequestHeader('Accept', 'text/html');
xhr.setRequestHeader('Accept', contentType);
xhr.onreadystatechange = function() {
if (xhr.readyState != XMLHttpRequest.DONE)
return;
......@@ -39,12 +54,11 @@ class WebViewHelper {
return;
}
var contentType = xhr.getResponseHeader('Content-Type');
if (contentType && !contentType.includes('text/html')) {
var responseContentType = xhr.getResponseHeader('Content-Type');
if (responseContentType && !responseContentType.includes(contentType)) {
onError();
return;
}
setContents(xhr.response);
};
......@@ -54,4 +68,15 @@ class WebViewHelper {
onError();
}
}
}
\ No newline at end of file
}
/**
* Type of content to load into web view.
* @enum {string}
*/
WebViewHelper.ContentType = {
/** UTF-8 encoded text/html content type. */
HTML: 'text/html',
/** Base64 encoded application/pdf content type. */
PDF: 'application/pdf',
};
\ No newline at end of file
......@@ -78,6 +78,7 @@
#if defined(OS_CHROMEOS)
#include <map>
#include "base/base64.h"
#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "chrome/browser/browser_process_platform_part_chromeos.h"
......@@ -203,6 +204,13 @@ class ChromeOSTermsHandler
FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&ChromeOSTermsHandler::LoadArcTermsFileAsync, this),
base::BindOnce(&ChromeOSTermsHandler::ResponseOnUIThread, this));
} else if (path_ == chrome::kArcPrivacyPolicyURLPath) {
// Load ARC++ privacy policy from the file.
base::PostTaskWithTraitsAndReply(
FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&ChromeOSTermsHandler::LoadArcPrivacyPolicyFileAsync,
this),
base::BindOnce(&ChromeOSTermsHandler::ResponseOnUIThread, this));
} else {
// Load local ChromeOS terms from the file.
base::PostTaskWithTraitsAndReply(
......@@ -247,49 +255,76 @@ class ChromeOSTermsHandler
}
}
void LoadArcTermsFileAsync() {
void LoadArcPrivacyPolicyFileAsync() {
base::ScopedBlockingCall scoped_blocking_call(
base::BlockingType::MAY_BLOCK);
const CountryRegionMap kCountryRegionMap = CreateCountryRegionMap();
const std::string kDeviceRegion = ReadDeviceRegionFromVpd();
// To determine version of Play Store ToS:
// * try to match language and device region combination
// * if not found check the mapping to default region (APAC, EMEA, EU)
// * if no default region mapping default to en-US
// Note: AMERICAS region defaults to en-US and to simplify it is not
// included in the country region map.
const std::string locale_region = base::StrCat(
{base::ToLowerASCII(language::ExtractBaseLanguage(locale_)), "-",
kDeviceRegion});
if (base::ReadFileToString(CreateArcTermsPath(locale_region), &contents_))
return;
const auto region = kCountryRegionMap.find(kDeviceRegion);
if (region != kCountryRegionMap.end()) {
LOG(WARNING) << "Could not find offline Play Store ToS for: "
<< locale_region << ". Trying by region: " << region->second;
if (base::ReadFileToString(CreateArcTermsPath(region->second.c_str()),
&contents_)) {
for (const auto& locale : CreateArcLocaleLookupArray()) {
auto path = CreateArcPrivacyPolicyPath(locale.c_str());
std::string contents;
if (base::ReadFileToString(path, &contents)) {
base::Base64Encode(contents, &contents_);
VLOG(1) << "Read offline Play Store privacy policy for: " << locale;
return;
}
LOG(WARNING) << "Could not find offline Play Store privacy policy for: "
<< locale;
}
LOG(ERROR) << "Failed to load offline Play Store privacy policy";
contents_.clear();
}
LOG(WARNING) << "Could not find offline Play Store ToS by locale nor "
"region for: "
<< locale_region << ". Loading: en-US";
if (base::ReadFileToString(CreateArcTermsPath("en-us"), &contents_))
return;
void LoadArcTermsFileAsync() {
base::ScopedBlockingCall scoped_blocking_call(
base::BlockingType::MAY_BLOCK);
for (const auto& locale : CreateArcLocaleLookupArray()) {
auto path = CreateArcTermsPath(locale.c_str());
std::string contents;
if (base::ReadFileToString(CreateArcTermsPath(locale), &contents_)) {
VLOG(1) << "Read offline Play Store terms for: " << locale;
return;
}
LOG(WARNING) << "Could not find offline Play Store terms for: " << locale;
}
LOG(ERROR) << "Failed to load offline Play Store ToS";
contents_.clear();
}
std::vector<std::string> CreateArcLocaleLookupArray() {
// To get Play Store asset we look for the first locale match in the
// following order:
// * language and device region combination
// * default region (APAC, EMEA, EU)
// * en-US
// Note: AMERICAS region defaults to en-US and to simplify it is not
// included in the country region map.
std::vector<std::string> locale_lookup_array;
const std::string device_region = ReadDeviceRegionFromVpd();
locale_lookup_array.push_back(base::StrCat(
{base::ToLowerASCII(language::ExtractBaseLanguage(locale_)), "-",
device_region}));
const CountryRegionMap country_region_map = CreateCountryRegionMap();
const auto region = country_region_map.find(device_region);
if (region != country_region_map.end()) {
locale_lookup_array.push_back(region->second.c_str());
}
locale_lookup_array.push_back("en-us");
return locale_lookup_array;
}
base::FilePath CreateArcTermsPath(const std::string& locale) const {
return chromeos_assets_path_.Append(
base::StringPrintf(chrome::kArcTermsPathFormat, locale.c_str()));
}
base::FilePath CreateArcPrivacyPolicyPath(const std::string& locale) const {
return chromeos_assets_path_.Append(base::StringPrintf(
chrome::kArcPrivacyPolicyPathFormat, locale.c_str()));
}
void ResponseOnUIThread() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// If we fail to load Chrome OS EULA from disk, load it from resources.
......
......@@ -271,6 +271,8 @@ const char kEULAPathFormat[] = "/usr/share/chromeos-assets/eula/%s/eula.html";
const char kArcTermsPathFormat[] = "arc_tos/%s/terms.html";
const char kArcPrivacyPolicyPathFormat[] = "arc_tos/%s/privacy_policy.pdf";
const char kEolNotificationURL[] = "https://www.google.com/chromebook/older/";
const char kGoogleNameserversLearnMoreURL[] =
......@@ -302,7 +304,9 @@ const char kNaturalScrollHelpURL[] =
const char kOemEulaURLPath[] = "oem";
const char kArcTermsURLPath[] = "arc";
const char kArcTermsURLPath[] = "arc/terms";
const char kArcPrivacyPolicyURLPath[] = "arc/privacy_policy";
const char kOnlineEulaURLPath[] =
"https://www.google.com/intl/%s/chrome/eula_text.html";
......
......@@ -223,6 +223,10 @@ extern const char kEULAPathFormat[];
// Relative to |kChromeOSAssetPath|.
extern const char kArcTermsPathFormat[];
// The path format to the localized offline ARC++ Privacy Policy.
// Relative to |kChromeOSAssetPath|.
extern const char kArcPrivacyPolicyPathFormat[];
// The URL for EOL notification
extern const char kEolNotificationURL[];
......@@ -256,9 +260,12 @@ extern const char kNaturalScrollHelpURL[];
// The URL path to offline OEM EULA.
extern const char kOemEulaURLPath[];
// THE URL path to offline ARC++ Terms of Service.
// The URL path to offline ARC++ Terms of Service.
extern const char kArcTermsURLPath[];
// The URL path to offline ARC++ Privacy Policy.
extern const char kArcPrivacyPolicyURLPath[];
extern const char kOnlineEulaURLPath[];
// The URL for the "learn more" link for TPM firmware update.
......
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