Commit 296a6c85 authored by Friedrich Horschig's avatar Friedrich Horschig Committed by Commit Bot

[Passwords] Listen to native leak status update events

This CL updates the status according to native events instead and
queries the status initially.
This enables continuous updates (e.g. during or after a password check).

Bug: 1047726
Change-Id: I075a56b4713782cc1df782b93d3569946e8d9ad4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2089769
Commit-Queue: Friedrich [CET] <fhorschig@chromium.org>
Reviewed-by: default avatarJan Wilken Dörrie <jdoerrie@chromium.org>
Cr-Commit-Position: refs/heads/master@{#748264}
parent be1ab205
......@@ -2,6 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(function() {
'use strict';
const CheckState = chrome.passwordsPrivate.PasswordCheckState;
Polymer({
is: 'settings-password-check',
......@@ -28,8 +33,26 @@ Polymer({
// load.
value: () => [],
},
/**
* The status indicates progress and affects banner, title and icon.
* @type {!PasswordManagerProxy.PasswordCheckStatus}
* @private
*/
status_: {
type: PasswordManagerProxy.PasswordCheckStatus,
value: () => {
return {state: CheckState.IDLE};
},
}
},
/**
* @type {?function(!PasswordManagerProxy.PasswordCheckStatus):void}
* @private
*/
statusChangedListener_: null,
/**
* @type {?function(!PasswordManagerProxy.CompromisedCredentialsInfo):void}
* @private
......@@ -53,25 +76,34 @@ Polymer({
// Set the manager. These can be overridden by tests.
this.passwordManager_ = PasswordManagerImpl.getInstance();
const statusChangeListener = status => this.status_ = status;
const setLeakedCredentialsListener = info => {
this.leakedPasswords = info.compromisedCredentials;
this.passwordLeakCount_ = info.compromisedCredentials.length;
this.lastCompletedCheck_ = info.elapsedTimeSinceLastCheck;
};
this.statusChangedListener_ = statusChangeListener;
this.leakedCredentialsListener_ = setLeakedCredentialsListener;
// Request initial data.
this.passwordManager_.getPasswordCheckStatus().then(
this.statusChangedListener_);
this.passwordManager_.getCompromisedCredentialsInfo().then(
this.leakedCredentialsListener_);
// Listen for changes.
this.passwordManager_.addPasswordCheckStatusListener(
this.statusChangedListener_);
this.passwordManager_.addCompromisedCredentialsListener(
this.leakedCredentialsListener_);
},
/** @override */
detached() {
this.passwordManager_.removePasswordCheckStatusListener(
assert(this.statusChangedListener_));
this.statusChangedListener_ = null;
this.passwordManager_.removeCompromisedCredentialsListener(
assert(this.leakedCredentialsListener_));
this.leakedCredentialsListener_ = null;
......@@ -136,3 +168,4 @@ Polymer({
// TODO(crbug.com/1047726) Implement dialog.
},
});
})();
......@@ -160,6 +160,12 @@ class PasswordManagerProxy {
*/
getCompromisedCredentialsInfo() {}
/**
* Returns the current status of the check via |callback|.
* @return {!Promise<(PasswordManagerProxy.PasswordCheckStatus)>}
*/
getPasswordCheckStatus() {}
/**
* Add an observer to the compromised passwords change.
* @param {function(!PasswordManagerProxy.CompromisedCredentialsInfo):void}
......@@ -173,6 +179,18 @@ class PasswordManagerProxy {
* listener
*/
removeCompromisedCredentialsListener(listener) {}
/**
* Remove an observer to the compromised passwords change.
* @param {function(!PasswordManagerProxy.PasswordCheckStatus):void} listener
*/
addPasswordCheckStatusListener(listener) {}
/**
* Remove an observer to the compromised passwords change.
* @param {function(!PasswordManagerProxy.PasswordCheckStatus):void} listener
*/
removePasswordCheckStatusListener(listener) {}
}
/** @typedef {chrome.passwordsPrivate.PasswordUiEntry} */
......@@ -198,6 +216,9 @@ PasswordManagerProxy.CompromisedCredential;
/** @typedef {chrome.passwordsPrivate.CompromisedCredentialsInfo} */
PasswordManagerProxy.CompromisedCredentialsInfo;
/** @typedef {chrome.passwordsPrivate.PasswordCheckStatus} */
PasswordManagerProxy.PasswordCheckStatus;
/**
* Implementation that accesses the private API.
* @implements {PasswordManagerProxy}
......@@ -321,6 +342,13 @@ class PasswordManagerImpl {
});
}
/** @override */
getPasswordCheckStatus() {
return new Promise(resolve => {
chrome.passwordsPrivate.getPasswordCheckStatus(resolve);
});
}
/** @override */
startBulkPasswordCheck() {
chrome.passwordsPrivate.startPasswordCheck();
......@@ -344,6 +372,17 @@ class PasswordManagerImpl {
chrome.passwordsPrivate.onCompromisedCredentialsInfoChanged.removeListener(
listener);
}
/** @override */
addPasswordCheckStatusListener(listener) {
chrome.passwordsPrivate.onPasswordCheckStatusChanged.addListener(listener);
}
/** @override */
removePasswordCheckStatusListener(listener) {
chrome.passwordsPrivate.onPasswordCheckStatusChanged.removeListener(
listener);
}
}
cr.addSingletonGetter(PasswordManagerImpl);
......@@ -5,6 +5,8 @@
/** @fileoverview Runs the Polymer Check Password tests. */
cr.define('settings_passwords_check', function() {
const PasswordCheckState = chrome.passwordsPrivate.PasswordCheckState;
function createCheckPasswordSection() {
// Create a passwords-section to use for testing.
const passwordsSection =
......@@ -147,5 +149,47 @@ cr.define('settings_passwords_check', function() {
assertTrue(menu.open);
});
});
// A changing status is immediately reflected in title, icon and banner.
test('testUpdatesNumberOfCheckedPasswordsWhileRunning', function() {
passwordManager.data.checkStatus =
autofill_test_util.makePasswordCheckStatus(
/*state=*/ PasswordCheckState.RUNNING,
/*checked=*/ 1,
/*remaining=*/ 1);
passwordManager.data.leakedCredentials =
autofill_test_util.makeCompromisedCredentialsInfo([], 'just now');
const section = createCheckPasswordSection();
return passwordManager.whenCalled('getPasswordCheckStatus').then(() => {
Polymer.dom.flush();
expectEquals(section.status_.state, PasswordCheckState.RUNNING);
// Change status from running to IDLE.
assert(!!passwordManager.lastCallback.addPasswordCheckStatusListener);
passwordManager.lastCallback.addPasswordCheckStatusListener(
autofill_test_util.makePasswordCheckStatus(
/*state=*/ PasswordCheckState.IDLE,
/*checked=*/ 2,
/*remaining=*/ 0));
Polymer.dom.flush();
expectEquals(section.status_.state, PasswordCheckState.IDLE);
});
});
// Tests that the status is queried right when the page loads.
test('testQueriesCheckedStatusImmediately', function() {
const data = passwordManager.data;
assertEquals(PasswordCheckState.IDLE, data.checkStatus.state);
assertEquals(0, data.leakedCredentials.compromisedCredentials.length);
const checkPasswordSection = createCheckPasswordSection();
return passwordManager.whenCalled('getPasswordCheckStatus').then(() => {
Polymer.dom.flush();
expectEquals(
checkPasswordSection.status_.state, PasswordCheckState.IDLE);
}, () => assert(false));
});
});
});
......@@ -145,6 +145,21 @@ cr.define('autofill_test_util', function() {
};
}
/**
* Creates a new password check status.
* @param {!chrome.passwordsPrivate.PasswordCheckState} state
* @param {number} checked
* @param {number} remaining
* @return {!chrome.passwordsPrivate.PasswordCheckStatus}
*/
function makePasswordCheckStatus(state, checked, remaining) {
return {
state: state || chrome.passwordsPrivate.PasswordCheckState.IDLE,
alreadyProcessed: checked || 0,
remainingInQueue: remaining || 0
};
}
/**
* Creates a new random GUID for testing.
* @return {string}
......@@ -411,6 +426,7 @@ cr.define('autofill_test_util', function() {
createCreditCardEntry: createCreditCardEntry,
makeCompromisedCredentials: makeCompromisedCredentials,
makeCompromisedCredentialsInfo: makeCompromisedCredentialsInfo,
makePasswordCheckStatus: makePasswordCheckStatus,
TestPaymentsManager: TestPaymentsManager,
PaymentsManagerExpectations: PaymentsManagerExpectations,
TestAutofillManager: TestAutofillManager,
......
......@@ -15,6 +15,7 @@ class TestPasswordManagerProxy extends TestBrowserProxy {
'requestPlaintextPassword',
'startBulkPasswordCheck',
'getCompromisedCredentialsInfo',
'getPasswordCheckStatus',
]);
this.actual_ = new autofill_test_util.PasswordManagerExpectations();
......@@ -25,10 +26,12 @@ class TestPasswordManagerProxy extends TestBrowserProxy {
exceptions: [],
leakedCredentials:
autofill_test_util.makeCompromisedCredentialsInfo([], ''),
checkStatus: autofill_test_util.makePasswordCheckStatus(),
};
// Holds the last callbacks so they can be called when needed/
this.lastCallback = {
addPasswordCheckStatusListener: null,
addSavedPasswordListChangedListener: null,
addExceptionListChangedListener: null,
requestPlaintextPassword: null,
......@@ -156,9 +159,23 @@ class TestPasswordManagerProxy extends TestBrowserProxy {
return Promise.resolve(this.data.leakedCredentials);
}
/** @override */
getPasswordCheckStatus() {
this.methodCalled('getPasswordCheckStatus');
return Promise.resolve(this.data.checkStatus);
}
/** @override */
addCompromisedCredentialsListener(listener) {}
/** @override */
removeCompromisedCredentialsListener(listener) {}
/** @override */
addPasswordCheckStatusListener(listener) {
this.lastCallback.addPasswordCheckStatusListener = listener;
}
/** @override */
removePasswordCheckStatusListener(listener) {}
}
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