blob: 3335d977e9ead940021f50098467cd9470265d55 [file] [log] [blame]
// Copyright 2016 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.
/**
* Returns the Play Store footer element that can be detected by id or class
* name.
*/
function getPlayFooterElement() {
var elements = document.getElementsByClassName('play-footer');
if (!elements || elements.length == 0) {
console.error('Failed to find play-footer element in ToS.');
return null;
}
if (elements.length != 1) {
console.error('Found more than one play-footer element in ToS.');
}
return elements[0];
}
/**
* Returns the select element that controls zone/language selection.
*/
function getLangZoneSelect() {
var footer = getPlayFooterElement();
if (!footer) {
return null;
}
var elements = footer.getElementsByTagName('select');
if (!elements || elements.length == 0) {
console.error('Cannot find zone/language select select element');
return null;
}
if (elements.length != 1) {
console.error('Found more than one zone/language select element in ToS.');
}
return elements[0];
}
/**
* Analyzes current document and tries to find the link to the Play Store ToS
* that matches requested |language| and |countryCode|. Once found, navigate
* to this link and returns True. If no match was found then returns False.
*/
function navigateToLanguageAndCountryCode(language, countryCode) {
var selectLangZoneTerms = getLangZoneSelect();
if (!selectLangZoneTerms) {
// Layout is not recognized, cannot check document structure.
return false;
}
var applyTermsForLangAndZone = function(termsLang) {
// Check special case for en_us which may be mapped to en.
var matchDefaultUs = null;
if (window.location.href.startsWith(
'https://play.google.com/intl/en_us/about/play-terms') &&
termsLang == 'en' && countryCode == 'us' &&
selectLangZoneTerms.value.startsWith('/intl/en/about/play-terms')) {
return true;
}
var matchByLangZone =
'/intl/' + termsLang + '_' + countryCode + '/about/play-terms';
if (selectLangZoneTerms.value.startsWith(matchByLangZone)) {
// Already selected what is needed.
return true;
}
for (var i = selectLangZoneTerms.options.length - 1; i >= 0; --i) {
var option = selectLangZoneTerms.options[i];
if (option.value.startsWith(matchByLangZone)) {
window.location.href = option.value;
return true;
}
}
return false;
};
// Try two versions of the language, full and short (if it exists, for
// example en-GB -> en). Note, terms may contain entries for both types, for
// example: en_ie, es-419_ar, es_as, pt-PT_pt.
if (applyTermsForLangAndZone(language)) {
return true;
}
var langSegments = language.split('-');
if (langSegments.length == 2 && applyTermsForLangAndZone(langSegments[0])) {
return true;
}
return false;
}
/**
* Processes select tag that contains list of available terms for different
* languages and zones. In case of initial load, tries to find terms that match
* exactly current language and country code and automatically redirects the
* view in case such terms are found. Leaves terms in select tag that only match
* current language or country code or default English variant or currently
* selected.
*
* @return {boolean} True.
*/
function processLangZoneTerms(initialLoad, language, countryCode) {
var langSegments = language.split('-');
if (initialLoad && navigateToLanguageAndCountryCode(language, countryCode)) {
document.body.hidden = false;
return true;
}
var footer = getPlayFooterElement();
if (!footer) {
// Layout is not recognized, show content and stop processing.
document.body.hidden = false;
return true;
}
var matchByLang = '/intl/' + language + '_';
var matchByLangShort = null;
if (langSegments.length == 2) {
matchByLangShort = '/intl/' + langSegments[0] + '_';
}
var matchByZone = '_' + countryCode + '/about/play-terms';
var matchByDefault = '/intl/en/about/play-terms';
// We are allowed to display terms by default only in language that matches
// current UI language. In other cases we have to switch to default version.
var langMatch = false;
var defaultExist = false;
var selectLangZoneTerms = getLangZoneSelect();
if (!selectLangZoneTerms) {
document.body.hidden = false;
return;
}
for (var i = selectLangZoneTerms.options.length - 1; i >= 0; --i) {
var option = selectLangZoneTerms.options[i];
if (selectLangZoneTerms.selectedIndex == i) {
langMatch = option.value.startsWith(matchByLang) ||
(matchByLangShort && option.value.startsWith(matchByLangShort));
continue;
}
if (option.value.startsWith(matchByDefault)) {
defaultExist = true;
continue;
}
option.hidden = !option.value.startsWith(matchByLang) &&
!option.value.includes(matchByZone) &&
!(matchByLangShort && option.value.startsWith(matchByLangShort)) &&
option.text != 'English';
}
if (initialLoad && !langMatch && defaultExist) {
window.location.href = matchByDefault;
} else {
// Show content once we reached target url.
document.body.hidden = false;
}
return true;
}
/**
* Returns the raw body HTML of the ToS contents.
* @return {string} HTML of document body.
*/
function getToSContent() {
return document.body.innerHTML;
}
/**
* Formats current document in order to display it correctly.
*/
function formatDocument() {
if (document.viewMode) {
document.body.classList.add(document.viewMode);
}
// playstore.css is injected into the document and it is applied first.
// Need to remove existing links that contain references to external
// stylesheets which override playstore.css.
var links = document.head.getElementsByTagName('link');
for (var i = links.length - 1; i >= 0; --i) {
document.head.removeChild(links[i]);
}
// Create base element that forces internal links to be opened in new window.
var base = document.createElement('base');
base.target = '_blank';
document.head.appendChild(base);
// Hide content at this point. We might want to redirect our view to terms
// that exactly match current language and country code.
document.body.hidden = true;
}
/**
* Searches in footer for a privacy policy link.
* @return {string} Link to Google Privacy Policy detected from the current
* document or link to the default policy if it is not found.
*/
function getPrivacyPolicyLink() {
var footer = getPlayFooterElement();
if (footer) {
var links = footer.getElementsByTagName('a');
for (var i = 0; i < links.length; ++i) {
var targetURL = links[i].href;
if (targetURL.endsWith('/policies/privacy/')) {
return targetURL;
}
}
}
return 'https://www.google.com/policies/privacy/';
}
/**
* Processes the current document by applying required formatting and selected
* right PlayStore ToS.
* Note that document.countryCode must be set before calling this function.
*/
function processDocument() {
if (document.wasProcessed) {
return;
}
formatDocument();
var initialLoad = window.location.href.startsWith(
'https://play.google.com/about/play-terms');
var language = document.language;
if (!language) {
language = navigator.language;
}
processLangZoneTerms(initialLoad, language, document.countryCode);
document.wasProcessed = true;
}
processDocument();