summaryrefslogtreecommitdiffstats
path: root/chromium/chrome/browser/resources/webapks/about_webapks.js
blob: b21be02901e24731860cc95638a60e50f885530d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// Copyright 2017 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.

/**
 * @typedef {{
 *   name: string,
 *   shortName: string,
 *   packageName: string,
 *   id: string,
 *   shellApkVersion: number,
 *   versionCode: number,
 *   uri: string,
 *   scope: string,
 *   manifestUrl: string,
 *   manifestStartUrl: string,
 *   displayMode: string,
 *   orientation: string,
 *   themeColor: string,
 *   backgroundColor: string,
 *   lastUpdateCheckTimeMs: number,
 *   lastUpdateCompletionTimeMs: number,
 *   relaxUpdates: boolean,
 *   backingBrowser: string,
 *   isBackingBrowser: boolean,
 *   updateStatus: string,
 * }}
 */
let WebApkInfo;

/**
 * @typedef {{
 *   id: string,
 *   status: string,
 * }}
 */
let UpdateStatus;

const UPDATE_TIMEOUT = 60 * 1000;  // milliseconds.

/**
 * Creates and returns an element (with |text| as content) assigning it the
 * |className| class.
 *
 * @param {string} text Text to be shown in the span.
 * @param {string} type Type of element to be added such as 'div'.
 * @param {string} className Class to be assigned to the new element.
 * @return {Element} The created element.
 */
function createElementWithTextAndClass(text, type, className) {
  const element = createElementWithClassName(type, className);
  element.textContent = text;
  return element;
}

/**
 * Callback from the backend with the information of a WebAPK to display.
 * This will be called once per WebAPK.
 *
 * @param {!WebApkInfo} webApkInfo Object with information about an
 * installed WebAPK.
 */
function returnWebApkInfo(webApkInfo) {
  addWebApk(webApkInfo);
}

/**
 * @param {HTMLElement} webApkList List of elements which contain WebAPK
 * attributes.
 * @param {string} label Text that identifies the new element.
 * @param {string} value Text to set in the new element.
 */
function addWebApkField(webApkList, label, value) {
  const divElement =
      createElementWithTextAndClass(label, 'div', 'app-property-label');
  divElement.appendChild(
      createElementWithTextAndClass(value, 'span', 'app-property-value'));
  webApkList.appendChild(divElement);
}

/**
 * @param {HTMLElement} webApkList List of elements which contain WebAPK
 * attributes.
 * @param {string} text For the button.
 * @param {function()} callback Invoked on click.
 * @return {Element} The button that was created.
 */
function addWebApkButton(webApkList, text, callback) {
  const divElement =
      createElementWithTextAndClass(text, 'button', 'update-button');
  divElement.onclick = callback;
  webApkList.appendChild(divElement);
  return divElement;
}

/**
 * Adds a new entry to the page with the information of a WebAPK.
 *
 * @param {WebApkInfo} webApkInfo Information about an installed WebAPK.
 */
function addWebApk(webApkInfo) {
  /** @type {HTMLElement} */ const webApkList = $('webapk-list');

  webApkList.appendChild(
      createElementWithTextAndClass(webApkInfo.name, 'span', 'app-name'));

  webApkList.appendChild(createElementWithTextAndClass(
      'Short name: ', 'span', 'app-property-label'));
  webApkList.appendChild(document.createTextNode(webApkInfo.shortName));

  addWebApkField(webApkList, 'Package name: ', webApkInfo.packageName);
  addWebApkField(
      webApkList, 'Shell APK version: ', '' + webApkInfo.shellApkVersion);
  addWebApkField(webApkList, 'Version code: ', '' + webApkInfo.versionCode);
  addWebApkField(webApkList, 'URI: ', webApkInfo.uri);
  addWebApkField(webApkList, 'Scope: ', webApkInfo.scope);
  addWebApkField(webApkList, 'Manifest URL: ', webApkInfo.manifestUrl);
  addWebApkField(
      webApkList, 'Manifest Start URL: ', webApkInfo.manifestStartUrl);
  addWebApkField(webApkList, 'Display Mode: ', webApkInfo.displayMode);
  addWebApkField(webApkList, 'Orientation: ', webApkInfo.orientation);
  addWebApkField(webApkList, 'Theme color: ', webApkInfo.themeColor);
  addWebApkField(webApkList, 'Background color: ', webApkInfo.backgroundColor);
  addWebApkField(
      webApkList, 'Last Update Check Time: ',
      new Date(webApkInfo.lastUpdateCheckTimeMs).toString());
  addWebApkField(
      webApkList, 'Last Update Completion Time: ',
      new Date(webApkInfo.lastUpdateCompletionTimeMs).toString());
  addWebApkField(
      webApkList, 'Check for Updates Less Frequently: ',
      webApkInfo.relaxUpdates.toString());
  addWebApkField(webApkList, 'Owning Browser: ', webApkInfo.backingBrowser);
  addWebApkField(webApkList, 'Update Status: ', webApkInfo.updateStatus);

  // TODO(ckitagawa): Convert to an enum using mojom handlers.
  if (webApkInfo.updateStatus == 'Not updatable' ||
      !webApkInfo.isBackingBrowser) {
    return;
  }

  const buttonElement =
      addWebApkButton(webApkList, 'Update ' + webApkInfo.name, () => {
        alert(
            'The WebAPK will check for an update the next time it launches. ' +
            'If an update is available, the "Update Status" on this page ' +
            'will switch to "Scheduled". The update will be installed once ' +
            'the WebAPK is closed (this may take a few minutes).');
        chrome.send('requestWebApkUpdate', [webApkInfo.id]);
      });

  // Prevent updates in the WebAPK server caching window as they will fail.
  const msSinceLastUpdate = Date.now() - webApkInfo.lastUpdateCompletionTimeMs;
  if (msSinceLastUpdate < UPDATE_TIMEOUT) {
    buttonElement.disabled = true;
    window.setTimeout(() => {
      buttonElement.disabled = false;
    }, UPDATE_TIMEOUT - msSinceLastUpdate);
  }
}

document.addEventListener('DOMContentLoaded', function() {
  chrome.send('requestWebApksInfo');
});