Commit bebcb3a6 authored by Esmael El-Moslimany's avatar Esmael El-Moslimany Committed by Commit Bot

Settings WebUI: password export dialog, remove other dialogs when opening new dialog

Bug: 899602
Change-Id: I58371b62f9e810b25fa05e431db8e17b82ff0d10
Reviewed-on: https://chromium-review.googlesource.com/c/1308908Reviewed-by: default avatarDemetrios Papadopoulos <dpapad@chromium.org>
Reviewed-by: default avatarScott Chen <scottchen@chromium.org>
Commit-Queue: Esmael El-Moslimany <aee@chromium.org>
Cr-Commit-Position: refs/heads/master@{#606238}
parent e0c9eec9
......@@ -114,6 +114,8 @@ class PasswordManagerProxy {
* listener
*/
removePasswordsFileExportProgressListener(listener) {}
cancelExportPasswords() {}
}
/** @typedef {chrome.passwordsPrivate.PasswordUiEntry} */
......@@ -231,6 +233,11 @@ class PasswordManagerImpl {
chrome.passwordsPrivate.onPasswordsFileExportProgress.removeListener(
listener);
}
/** @override */
cancelExportPasswords() {
chrome.passwordsPrivate.cancelExportPasswords();
}
}
cr.addSingletonGetter(PasswordManagerImpl);
......@@ -17,59 +17,65 @@
margin-inline-start: 8px;
}
</style>
<cr-dialog id="dialog_start" close-text="$i18n{close}">
<div slot="title">$i18n{exportPasswordsTitle}</div>
<div slot="body">
<div class="layout horizontal center">
<div>$i18n{exportPasswordsDescription}</div>
<template is="dom-if" if="[[showStartDialog_]]" restamp>
<cr-dialog id="dialog_start" close-text="$i18n{close}" show-on-attach>
<div slot="title">$i18n{exportPasswordsTitle}</div>
<div slot="body">
<div class="layout horizontal center">
<div>$i18n{exportPasswordsDescription}</div>
</div>
</div>
</div>
<div slot="button-container">
<paper-button class="secondary-button header-aligned-button"
on-click="onCancelButtonTap_" id="cancelButton">
$i18n{cancel}
</paper-button>
<paper-button class="action-button header-aligned-button"
on-click="onExportTap_" id="exportPasswordsButton">
$i18n{exportPasswords}
</paper-button>
</div>
</cr-dialog>
<div slot="button-container">
<paper-button class="secondary-button header-aligned-button"
on-click="onCancelButtonTap_" id="cancelButton">
$i18n{cancel}
</paper-button>
<paper-button class="action-button header-aligned-button"
on-click="onExportTap_" id="exportPasswordsButton">
$i18n{exportPasswords}
</paper-button>
</div>
</cr-dialog>
</template>
<cr-dialog id="dialog_progress" no-cancel="true">
<div slot="title">$i18n{exportingPasswordsTitle}</div>
<div slot="body">
<paper-progress indeterminate class="blue"></paper-progress>
</div>
<div slot="button-container">
<paper-button id="cancel_progress_button"
class="secondary-button header-aligned-button"
on-click="onCancelProgressButtonTap_">
$i18n{cancel}
</paper-button>
</div>
</cr-dialog>
<template is="dom-if" if="[[showProgressDialog_]]" restamp>
<cr-dialog id="dialog_progress" no-cancel="true" show-on-attach>
<div slot="title">$i18n{exportingPasswordsTitle}</div>
<div slot="body">
<paper-progress indeterminate class="blue"></paper-progress>
</div>
<div slot="button-container">
<paper-button id="cancel_progress_button"
class="secondary-button header-aligned-button"
on-click="onCancelProgressButtonTap_">
$i18n{cancel}
</paper-button>
</div>
</cr-dialog>
</template>
<cr-dialog id="dialog_error" close-text="$i18n{close}">
<div slot="title">[[exportErrorMessage]]</div>
<div slot="body">
$i18n{exportPasswordsFailTips}
<ul>
<li>$i18n{exportPasswordsFailTipsEnoughSpace}</li>
<li>$i18n{exportPasswordsFailTipsAnotherFolder}</li>
</ul>
</div>
<div slot="button-container">
<paper-button class="secondary-button header-aligned-button"
on-click="onCancelButtonTap_" id="cancelErrorButton">
$i18n{cancel}
</paper-button>
<paper-button class="action-button header-aligned-button"
on-click="onExportTap_" id="tryAgainButton">
$i18n{exportPasswordsTryAgain}
</paper-button>
</div>
</cr-dialog>
<template is="dom-if" if="[[showErrorDialog_]]" restamp>
<cr-dialog id="dialog_error" close-text="$i18n{close}" show-on-attach>
<div slot="title">[[exportErrorMessage]]</div>
<div slot="body">
$i18n{exportPasswordsFailTips}
<ul>
<li>$i18n{exportPasswordsFailTipsEnoughSpace}</li>
<li>$i18n{exportPasswordsFailTipsAnotherFolder}</li>
</ul>
</div>
<div slot="button-container">
<paper-button class="secondary-button header-aligned-button"
on-click="onCancelButtonTap_" id="cancelErrorButton">
$i18n{cancel}
</paper-button>
<paper-button class="action-button header-aligned-button"
on-click="onExportTap_" id="tryAgainButton">
$i18n{exportPasswordsTryAgain}
</paper-button>
</div>
</cr-dialog>
</template>
</template>
<script src="passwords_export_dialog.js"></script>
......
......@@ -43,6 +43,15 @@ Polymer({
properties: {
/** The error that occurred while exporting. */
exportErrorMessage: String,
/** @private */
showStartDialog_: Boolean,
/** @private */
showProgressDialog_: Boolean,
/** @private */
showErrorDialog_: Boolean,
},
listeners: {'cancel': 'close'},
......@@ -157,12 +166,9 @@ Polymer({
this.delayedCompletionToken_ = null;
this.passwordManager_.removePasswordsFileExportProgressListener(
this.onPasswordsFileExportProgressListener_);
if (this.$.dialog_start.open)
this.$.dialog_start.close();
if (this.$.dialog_progress.open)
this.$.dialog_progress.close();
if (this.$.dialog_error.open)
this.$.dialog_error.close();
this.showStartDialog_ = false;
this.showProgressDialog_ = false;
this.showErrorDialog_ = false;
},
/**
......@@ -210,16 +216,9 @@ Polymer({
* @private
*/
switchToDialog_(state) {
this.$.dialog_start.open = false;
this.$.dialog_error.open = false;
this.$.dialog_progress.open = false;
if (state == States.START)
this.$.dialog_start.showModal();
if (state == States.ERROR)
this.$.dialog_error.showModal();
if (state == States.IN_PROGRESS)
this.$.dialog_progress.showModal();
this.showStartDialog_ = state == States.START;
this.showProgressDialog_ = state == States.IN_PROGRESS;
this.showErrorDialog_ = state == States.ERROR;
},
/**
......
......@@ -471,4 +471,13 @@ suite('cr-dialog', function() {
document.removeEventListener('keydown', assertKeydownCount);
});
});
test('show on attach', () => {
document.body.innerHTML = `
<cr-dialog show-on-attach>
<div slot="title">title</div>
</cr-dialog>`;
const dialog = document.body.querySelector('cr-dialog');
assertTrue(dialog.open);
});
});
......@@ -736,7 +736,7 @@ TEST_F('SettingsPasswordSectionBrowserTest', 'uiTests', function() {
done();
};
exportDialog.$.exportPasswordsButton.click();
exportDialog.$$('#exportPasswordsButton').click();
});
// Test the export flow. If exporting is fast, we should skip the
......@@ -749,18 +749,19 @@ TEST_F('SettingsPasswordSectionBrowserTest', 'uiTests', function() {
let mockTimer = new MockTimer();
mockTimer.install();
assertTrue(exportDialog.$.dialog_start.open);
exportDialog.$.exportPasswordsButton.click();
assertTrue(exportDialog.$.dialog_start.open);
assertTrue(exportDialog.$$('#dialog_start').open);
exportDialog.$$('#exportPasswordsButton').click();
assertTrue(exportDialog.$$('#dialog_start').open);
progressCallback(
{status: chrome.passwordsPrivate.ExportProgressStatus.IN_PROGRESS});
progressCallback(
{status: chrome.passwordsPrivate.ExportProgressStatus.SUCCEEDED});
Polymer.dom.flush();
// When we are done, the export dialog closes completely.
assertFalse(exportDialog.$.dialog_start.open);
assertFalse(exportDialog.$.dialog_error.open);
assertFalse(exportDialog.$.dialog_progress.open);
assertFalse(!!exportDialog.$$('#dialog_start'));
assertFalse(!!exportDialog.$$('#dialog_error'));
assertFalse(!!exportDialog.$$('#dialog_progress'));
done();
mockTimer.uninstall();
......@@ -775,9 +776,9 @@ TEST_F('SettingsPasswordSectionBrowserTest', 'uiTests', function() {
let mockTimer = new MockTimer();
mockTimer.install();
assertTrue(exportDialog.$.dialog_start.open);
exportDialog.$.exportPasswordsButton.click();
assertTrue(exportDialog.$.dialog_start.open);
assertTrue(exportDialog.$$('#dialog_start').open);
exportDialog.$$('#exportPasswordsButton').click();
assertTrue(exportDialog.$$('#dialog_start').open);
progressCallback(
{status: chrome.passwordsPrivate.ExportProgressStatus.IN_PROGRESS});
progressCallback({
......@@ -786,11 +787,13 @@ TEST_F('SettingsPasswordSectionBrowserTest', 'uiTests', function() {
folderName: 'tmp',
});
Polymer.dom.flush();
// Test that the error dialog is shown.
assertTrue(exportDialog.$.dialog_error.open);
assertTrue(exportDialog.$$('#dialog_error').open);
// Test that the error dialog can be dismissed.
exportDialog.$.cancelErrorButton.click();
assertFalse(exportDialog.$.dialog_error.open);
exportDialog.$$('#cancelErrorButton').click();
Polymer.dom.flush();
assertFalse(!!exportDialog.$$('#dialog_error'));
done();
mockTimer.uninstall();
......@@ -805,7 +808,7 @@ TEST_F('SettingsPasswordSectionBrowserTest', 'uiTests', function() {
let mockTimer = new MockTimer();
mockTimer.install();
exportDialog.$.exportPasswordsButton.click();
exportDialog.$$('#exportPasswordsButton').click();
progressCallback(
{status: chrome.passwordsPrivate.ExportProgressStatus.IN_PROGRESS});
progressCallback({
......@@ -814,14 +817,15 @@ TEST_F('SettingsPasswordSectionBrowserTest', 'uiTests', function() {
folderName: 'tmp',
});
Polymer.dom.flush();
// Test that the error dialog is shown.
assertTrue(exportDialog.$.dialog_error.open);
assertTrue(exportDialog.$$('#dialog_error').open);
// Test that clicking retry will start a new export.
passwordManager.exportPasswords = (callback) => {
callback();
done();
};
exportDialog.$.tryAgainButton.click();
exportDialog.$$('#tryAgainButton').click();
mockTimer.uninstall();
});
......@@ -837,32 +841,34 @@ TEST_F('SettingsPasswordSectionBrowserTest', 'uiTests', function() {
// The initial dialog remains open for 100ms after export enters the
// in-progress state.
assertTrue(exportDialog.$.dialog_start.open);
exportDialog.$.exportPasswordsButton.click();
assertTrue(exportDialog.$.dialog_start.open);
assertTrue(exportDialog.$$('#dialog_start').open);
exportDialog.$$('#exportPasswordsButton').click();
assertTrue(exportDialog.$$('#dialog_start').open);
progressCallback(
{status: chrome.passwordsPrivate.ExportProgressStatus.IN_PROGRESS});
assertTrue(exportDialog.$.dialog_start.open);
assertTrue(exportDialog.$$('#dialog_start').open);
// After 100ms of not having completed, the dialog switches to the
// progress bar. Chrome will continue to show the progress bar for 1000ms,
// despite a completion event.
mockTimer.tick(99);
assertTrue(exportDialog.$.dialog_start.open);
assertTrue(exportDialog.$$('#dialog_start').open);
mockTimer.tick(1);
assertTrue(exportDialog.$.dialog_progress.open);
Polymer.dom.flush();
assertTrue(exportDialog.$$('#dialog_progress').open);
progressCallback(
{status: chrome.passwordsPrivate.ExportProgressStatus.SUCCEEDED});
assertTrue(exportDialog.$.dialog_progress.open);
assertTrue(exportDialog.$$('#dialog_progress').open);
// After 1000ms, Chrome will display the completion event.
mockTimer.tick(999);
assertTrue(exportDialog.$.dialog_progress.open);
assertTrue(exportDialog.$$('#dialog_progress').open);
mockTimer.tick(1);
Polymer.dom.flush();
// On SUCCEEDED the dialog closes completely.
assertFalse(exportDialog.$.dialog_progress.open);
assertFalse(exportDialog.$.dialog_start.open);
assertFalse(exportDialog.$.dialog_error.open);
assertFalse(!!exportDialog.$$('#dialog_progress'));
assertFalse(!!exportDialog.$$('#dialog_start'));
assertFalse(!!exportDialog.$$('#dialog_error'));
done();
mockTimer.uninstall();
......@@ -883,18 +889,20 @@ TEST_F('SettingsPasswordSectionBrowserTest', 'uiTests', function() {
// The initial dialog remains open for 100ms after export enters the
// in-progress state.
exportDialog.$.exportPasswordsButton.click();
exportDialog.$$('#exportPasswordsButton').click();
progressCallback(
{status: chrome.passwordsPrivate.ExportProgressStatus.IN_PROGRESS});
// The progress bar only appears after 100ms.
mockTimer.tick(100);
assertTrue(exportDialog.$.dialog_progress.open);
exportDialog.$.cancel_progress_button.click();
Polymer.dom.flush();
assertTrue(exportDialog.$$('#dialog_progress').open);
exportDialog.$$('#cancel_progress_button').click();
Polymer.dom.flush();
// The dialog should be dismissed entirely.
assertFalse(exportDialog.$.dialog_progress.open);
assertFalse(exportDialog.$.dialog_start.open);
assertFalse(exportDialog.$.dialog_error.open);
assertFalse(!!exportDialog.$$('#dialog_progress'));
assertFalse(!!exportDialog.$$('#dialog_start'));
assertFalse(!!exportDialog.$$('#dialog_error'));
mockTimer.uninstall();
});
......@@ -903,9 +911,10 @@ TEST_F('SettingsPasswordSectionBrowserTest', 'uiTests', function() {
test('exportDismissable', function(done) {
const exportDialog = createExportPasswordsDialog(passwordManager);
assertTrue(exportDialog.$.dialog_start.open);
exportDialog.$.cancelButton.click();
assertFalse(exportDialog.$.dialog_start.open);
assertTrue(exportDialog.$$('#dialog_start').open);
exportDialog.$$('#cancelButton').click();
Polymer.dom.flush();
assertFalse(!!exportDialog.$$('#dialog_start'));
done();
});
......
......@@ -74,6 +74,11 @@ Polymer({
type: Boolean,
value: false,
},
showOnAttach: {
type: Boolean,
value: false,
},
},
listeners: {
......@@ -123,6 +128,8 @@ Polymer({
// In some cases dialog already has the 'open' attribute by this point.
mutationObserverCallback();
if (this.showOnAttach)
this.showModal();
},
/** @override */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment