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