Skip to content
This repository has been archived by the owner on Jan 11, 2023. It is now read-only.

Initial minimal logins API connection to datastore #62

Merged
merged 2 commits into from Jan 18, 2019

Conversation

lmorchard
Copy link
Contributor

Connected to #21

This doesn't actually fix #21, but it's kind of a start as it connects up the add-on to the real logins info data.

Testing and Review Notes

  • The add-on should now display real login entries
  • Editing the login entries from the add-on should affect changes in the in-product login manager.
  • Editing entries in the in-product login manager should affect changes in the add-on.

@lmorchard lmorchard requested a review from a team as a code owner January 16, 2019 18:25
@ghost ghost assigned lmorchard Jan 16, 2019
@ghost ghost added the in progress label Jan 16, 2019
@lmorchard lmorchard changed the title Initial minimal logins API connection to datastore WIP: Initial minimal logins API connection to datastore Jan 16, 2019
@lmorchard
Copy link
Contributor Author

Oof, actually: Adding a WIP to the title, as I appear to have broken something just before submitting 😞

@@ -37,7 +37,13 @@ export function cacheReducer(state = {items: [], currentItem: null}, action) {
case actions.ADD_ITEM_COMPLETED:
return {
...state,
items: [...state.items, makeItemSummary(action.item)],
items: [
// HACK: add dispatched via Logins API events may be a duplicate
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small hacky wrinkle here: Since I'm broadcasting datastore changes based on Logins API events without any source, the UI source that made the changes will get its own change dispatched back to it. This will look like a duplicate. So, I papered over that by making the "add" action idempotent here.

@lmorchard lmorchard changed the title WIP: Initial minimal logins API connection to datastore Initial minimal logins API connection to datastore Jan 16, 2019
@lmorchard
Copy link
Contributor Author

Okay, I think I worked out the issues. At least, insofar as I'm going to take off the "WIP" title and go get some lunch.

@lmorchard
Copy link
Contributor Author

lmorchard commented Jan 16, 2019

Oh, but one other thing I may need to investigate for this PR or in a follow-up: Nothing here calls touch() on the Logins API to register that a login has been used. Wanted to do a little more digging to make sure I don't make fetches for display end up counting as a use. (i.e. don't stick a touch() call in datastore, make it an explicit message to send on copying username / password?)

Copy link
Contributor

@jaredhirsch jaredhirsch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! Seems to be working for me. Called out a couple smallish things.

timeCreated: Date.now(),
timePasswordChanged: Date.now(),
};
await browser.experiments.logins.add(added);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and other logins-modifying API methods do throw if something goes wrong, so I'd wrap them in try/catch blocks and just log the errors for now. I think we can handle the errors in the relevant issues (looks like #18, #30, #34 might all be relevant).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I can just silently log them, though datastore.js does throw errors for other validation problems and such. Kind of figured it was useful to let these throw too, though it doesn't look like we do anything useful with them yet. (e.g. report an error over a message port, etc)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

datastore.js does throw errors for other validation problems and such

Ah, ok. Probably fine as is, then.

src/background/datastore.js Outdated Show resolved Hide resolved
src/background/datastore.js Outdated Show resolved Hide resolved
src/background/datastore.js Outdated Show resolved Hide resolved
test/unit/background/datastore-test.js Show resolved Hide resolved
@linuxwolf
Copy link
Contributor

Nothing here calls touch() on the Logins API to register that a login has been used

That was on the list of things to get to from before; I'll make sure it's accounted for in our issues.

@@ -44,19 +44,16 @@ export default function initializeMessagePorts() {
case "add_item":
return openDataStore().then(async (ds) => {
const item = await ds.add(message.item);
broadcast({type: "added_item", item}, sender);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Realized that since I've got the datastore now broadcasting these on the Logins API event handlers, all these messages got doubled up.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes a lot more sense.

I hope it's clear the code was in an "evolutionary transitional" phase when you picked it up (-:

@@ -80,7 +83,6 @@ describe("background > message ports", () => {
itemId = result.item.id;

expect(result.item).to.deep.include(item);
expect(selfListener).to.have.callCount(0);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the datastore broadcasts messages to relay events from the Logins API, there's no sender or self available at that time to refrain from sending the event back to "self"

logins: {
async getAll() { return []; },
async add(login) {
browser.experiments.logins.onAdded.getListener()({ login });
Copy link
Contributor Author

@lmorchard lmorchard Jan 17, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was hoping I could be less verbose here by just using this rather than browser.experiments.logins, but that apparently ends up being the wrong reference

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔

@lmorchard
Copy link
Contributor Author

Addressed comments except for wrapping things in try/catch to log errors. We might want to let those throw, so we can catch those higher up along with datastore validation errors.

@jaredhirsch
Copy link
Contributor

Nice work 👍 Took this branch for a test drive, and all the logins add / update / delete happy paths are seamlessly mirrored across the logins management UI in Firefox, and the Lockbox management UI.

I dunno if @linuxwolf wants to take a pass before merging, but LGTM

Copy link
Contributor

@linuxwolf linuxwolf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r+

:shipit:

logins.onRemoved.addListener(({ login }) => dataStore.removeInfo(login));
}

export default openDataStore;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this pattern better

@@ -44,19 +44,16 @@ export default function initializeMessagePorts() {
case "add_item":
return openDataStore().then(async (ds) => {
const item = await ds.add(message.item);
broadcast({type: "added_item", item}, sender);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes a lot more sense.

I hope it's clear the code was in an "evolutionary transitional" phase when you picked it up (-:

const LOGINS_METHODS = ["getAll", "add", "update", "remove"];
const LOGINS_EVENTS = ["Added", "Updated", "Removed"].map(name => `on${name}`);

describe("background > datastore", () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😍

logins: {
async getAll() { return []; },
async add(login) {
browser.experiments.logins.onAdded.getListener()({ login });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔

@lmorchard lmorchard merged commit f4cd29b into mozilla-lockwise:master Jan 18, 2019
@ghost ghost removed the in progress label Jan 18, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Use nsILoginInfo as the Data Model
3 participants