text: // 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();
  