chromium/chrome/test/data/banners/main.js

// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

const Action = {
  VERIFY_APPINSTALLED: 'verify_appinstalled',
  VERIFY_APPINSTALLED_STASH_EVENT: 'verify_appinstalled_stash_event',
  VERIFY_PROMPT_APPINSTALLED: 'verify_prompt_appinstalled',
  VERIFY_BEFOREINSTALLPROMPT: 'verify_beforeinstallprompt',
  CALL_PROMPT_DELAYED: 'call_prompt_delayed',
  CALL_PROMPT_IN_HANDLER: 'call_prompt_in_handler',
  CALL_PROMPT_NO_USERCHOICE: 'call_prompt_no_userchoice',
  CALL_STASHED_PROMPT_ON_CLICK: 'call_stashed_prompt_on_click',
  CALL_STASHED_PROMPT_ON_CLICK_VERIFY_APPINSTALLED:
      'call_stashed_prompt_on_click_verify_appinstalled',
  CANCEL_PROMPT_AND_NAVIGATE: 'cancel_prompt_and_navigate',
  CANCEL_PROMPT: 'cancel_prompt',
  STASH_EVENT: 'stash_event',
  STASH_EVENT_AND_PREVENT_DEFAULT: 'stash_event_and_prevent_default',
  FULLSCREEN_ON_CLICK: 'fullscreen_on_click',
};

const LISTENER = "listener";
const ATTR = "attr";

// These blanks will get filled in when each event comes through.
let gotEventsFrom = ['_'.repeat(LISTENER.length), '_'.repeat(ATTR.length)];

let stashedEvent = null;

function startWorker(worker) {
  navigator.serviceWorker.register(worker);
}

function verifyEvents(eventName) {
  function setTitle() {
    window.document.title = 'Got ' + eventName + ': ' +
      gotEventsFrom.join(', ');
  }

  window.addEventListener(eventName, () => {
    gotEventsFrom[0] = LISTENER;
    setTitle();
  });
  window['on' + eventName] = () => {
    gotEventsFrom[1] = ATTR;
    setTitle();
  };
}

function callPrompt(event) {
  event.prompt();
  event.userChoice.then(function(choiceResult) {
    window.document.title = 'Got userChoice: ' + choiceResult.outcome;
  });
}

function callStashedPrompt() {
  if (stashedEvent === null) {
      throw new Error('No event was previously stashed');
  }
  callPrompt(stashedEvent);
}

function isBodyFullscreen() {
  return document.fullscreenElement == document.body;
}

function toggleFullscreen() {
  if (isBodyFullscreen()) {
    document.exitFullscreen();
  } else {
    document.body.requestFullscreen();
  }
}

function addClickListener(action) {
  switch (action) {
    case Action.CALL_STASHED_PROMPT_ON_CLICK:
      window.addEventListener('click', callStashedPrompt);
      break;
    case Action.CALL_STASHED_PROMPT_ON_CLICK_VERIFY_APPINSTALLED:
      window.addEventListener('click', callStashedPrompt);
      verifyEvents("appinstalled");
      break;
    case Action.FULLSCREEN_ON_CLICK:
      window.addEventListener('click', toggleFullscreen);
      break;
  }
}

function addPromptListener(action) {
  window.addEventListener('beforeinstallprompt', function(e) {
    switch (action) {
      case Action.VERIFY_APPINSTALLED_STASH_EVENT:
        stashedEvent = e;
        verifyEvents('appinstalled');
        break;
      case Action.CALL_PROMPT_DELAYED:
        e.preventDefault();
        setTimeout(callPrompt, 0, e);
        break;
      case Action.CALL_PROMPT_IN_HANDLER:
        callPrompt(e);
        break;
      case Action.CALL_PROMPT_NO_USERCHOICE:
        e.preventDefault();
        setTimeout(() => e.prompt(), 0);
        break;
      case Action.CANCEL_PROMPT:
        e.preventDefault();
        break;
      case Action.CANCEL_PROMPT_AND_NAVIGATE:
        e.preventDefault();
        // Navigate the window to trigger cancellation in the renderer.
        setTimeout(function() { window.location.href = "/" }, 0);
        break;
      case Action.STASH_EVENT:
        stashedEvent = e;
        break;
      case Action.STASH_EVENT_AND_PREVENT_DEFAULT:
        stashedEvent = e;
        e.preventDefault();
        break;
    }
  });
}

function addManifestLinkTag(optionalCustomUrl) {
  const url = new URL(window.location.href);
  let manifestUrl = url.searchParams.get('manifest');
  if (!manifestUrl) {
    manifestUrl = optionalCustomUrl || 'manifest.json';
  }

  var linkTag = document.createElement("link");
  linkTag.id = "manifest";
  linkTag.rel = "manifest";
  linkTag.href = manifestUrl;
  document.head.append(linkTag);
}

function addFavicon(favicon_url) {
  var linkTag = document.createElement("link");
  linkTag.id = "new-icon";
  linkTag.rel = "icon";
  linkTag.type = "image/x-icon";
  linkTag.href = favicon_url;
  document.head.append(linkTag);
}

function removeAllManifestTags() {
  for (let i = 0; i < document.head.children.length; ++i) {
    let child = document.head.children[i];
    if (child.rel == "manifest")
      child.parentElement.removeChild(child);
  }
}

function initialize() {
  const url = new URL(window.location.href);
  initializeActions(url.searchParams.get('action'));
  addOtherTags(url);
}

function initializeActions(action) {
  if (!action) {
    return;
  }

  switch (action) {
    case Action.VERIFY_APPINSTALLED:
      verifyEvents('appinstalled');
      break;
    case Action.VERIFY_PROMPT_APPINSTALLED:
      addPromptListener(Action.CALL_PROMPT_NO_USERCHOICE);
      verifyEvents('appinstalled');
      break;
    case Action.VERIFY_BEFOREINSTALLPROMPT:
      verifyEvents('beforeinstallprompt');
      break;
    case Action.CALL_STASHED_PROMPT_ON_CLICK:
    case Action.CALL_STASHED_PROMPT_ON_CLICK_VERIFY_APPINSTALLED:
      addPromptListener(Action.STASH_EVENT);
      addClickListener(action);
      break;
    case Action.STASH_EVENT_AND_PREVENT_DEFAULT:
      addPromptListener(action);
      addClickListener(Action.CALL_STASHED_PROMPT_ON_CLICK);
      break;
    case Action.VERIFY_APPINSTALLED_STASH_EVENT:
    case Action.CALL_PROMPT_DELAYED:
    case Action.CALL_PROMPT_IN_HANDLER:
    case Action.CALL_PROMPT_NO_USERCHOICE:
    case Action.CANCEL_PROMPT_AND_NAVIGATE:
    case Action.CANCEL_PROMPT:
    case Action.STASH_EVENT:
      addPromptListener(action);
      break;
    case Action.FULLSCREEN_ON_CLICK:
      addClickListener(action);
      break;
    default:
      throw new Error("Unrecognised action: " + action);
  }
}

function initializeWithWorker(worker) {
  startWorker(worker);
  initialize();
}

function changeManifestUrl(newManifestUrl) {
  var linkTag = document.getElementById("manifest");
  linkTag.href = newManifestUrl;
}

function addOtherTags(url) {
  for (const [key, value] of url.searchParams) {
    if (key === "manifest" || key === "action" || !value) {
      continue;
    }
    if (key === 'icon') {
      var linkTag = document.createElement("link");
      linkTag.id = key
      linkTag.rel = key;
      linkTag.href = value;
      document.head.append(linkTag);
    }
    else {
      var meta = document.createElement('meta');
      meta.name = key
      meta.content = value
      document.head.append(meta);
    }
  }
}