// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'chrome://resources/cr_elements/cr_button/cr_button.js';
import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
import 'chrome://resources/cr_elements/cr_input/cr_input.js';
import 'chrome://resources/cr_elements/cr_shared_style.css.js';
import 'chrome://resources/cr_elements/cr_shared_vars.css.js';
import './pack_dialog_alert.js';
import './strings.m.js';
import type {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
import type {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.js';
import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {getTemplate} from './pack_dialog.html.js';
export interface PackDialogDelegate {
/**
* Opens a file browser for the user to select the root directory.
* @return A promise that is resolved with the path the user selected.
*/
choosePackRootDirectory(): Promise<string>;
/**
* Opens a file browser for the user to select the private key file.
* @return A promise that is resolved with the path the user selected.
*/
choosePrivateKeyPath(): Promise<string>;
/** Packs the extension into a .crx. */
packExtension(rootPath: string, keyPath: string, flag?: number):
Promise<chrome.developerPrivate.PackDirectoryResponse>;
}
export interface ExtensionsPackDialogElement {
$: {
dialog: CrDialogElement,
keyFileBrowse: HTMLElement,
keyFile: CrInputElement,
rootDirBrowse: HTMLElement,
rootDir: CrInputElement,
};
}
export class ExtensionsPackDialogElement extends PolymerElement {
static get is() {
return 'extensions-pack-dialog';
}
static get template() {
return getTemplate();
}
static get properties() {
return {
delegate: Object,
packDirectory_: {
type: String,
value: '', // Initialized to trigger binding when attached.
},
keyFile_: String,
lastResponse_: Object,
};
}
delegate: PackDialogDelegate;
private packDirectory_: string;
private keyFile_: string;
private lastResponse_: chrome.developerPrivate.PackDirectoryResponse|null;
override connectedCallback() {
super.connectedCallback();
this.$.dialog.showModal();
}
private onRootBrowse_() {
this.delegate.choosePackRootDirectory().then(path => {
if (path) {
this.set('packDirectory_', path);
}
});
}
private onKeyBrowse_() {
this.delegate.choosePrivateKeyPath().then(path => {
if (path) {
this.set('keyFile_', path);
}
});
}
private onCancelClick_() {
this.$.dialog.cancel();
}
private onConfirmClick_() {
this.delegate.packExtension(this.packDirectory_, this.keyFile_, 0)
.then(response => this.onPackResponse_(response));
}
/**
* @param response The response from request to pack an extension.
*/
private onPackResponse_(response:
chrome.developerPrivate.PackDirectoryResponse) {
this.lastResponse_ = response;
}
/**
* In the case that the alert dialog was a success message, the entire
* pack-dialog should close. Otherwise, we detach the alert by setting
* lastResponse_ null. Additionally, if the user selected "proceed anyway"
* in the dialog, we pack the extension again with override flags.
*/
private onAlertClose_(e: Event) {
e.stopPropagation();
if (this.lastResponse_!.status ===
chrome.developerPrivate.PackStatus.SUCCESS) {
this.$.dialog.close();
return;
}
// This is only possible for a warning dialog.
if (this.shadowRoot!.querySelector(
'extensions-pack-dialog-alert')!.returnValue ===
'success') {
this.delegate
.packExtension(
this.lastResponse_!.item_path, this.lastResponse_!.pem_path,
this.lastResponse_!.override_flags)
.then(response => this.onPackResponse_(response));
}
this.lastResponse_ = null;
}
}
declare global {
interface HTMLElementTagNameMap {
'extensions-pack-dialog': ExtensionsPackDialogElement;
}
}
customElements.define(
ExtensionsPackDialogElement.is, ExtensionsPackDialogElement);