Closed Bug 1126182 Opened 6 years ago Closed 6 years ago

Extract related tiles data from links json and store for later selection

Categories

(Firefox :: New Tab Page, defect)

defect
Not set
normal
Points:
5

Tracking

()

RESOLVED FIXED
Firefox 39
Iteration:
39.2 - 23 Mar
Tracking Status
firefox38 --- fixed
firefox39 --- fixed

People

(Reporter: Mardak, Assigned: emtwo)

References

Details

(Whiteboard: .002)

Attachments

(1 file, 1 obsolete file)

The json payload from the server will have tiles with "type": "related" as well as "related": ["array.com", "of.org", "sites.net"]

We'll want to extract them in a way that they don't show up as directory tiles and persist the data so we can do decisioning on which related tile to show.
Blocks: 1126184
Depends on: 1126191
If we want to store the related tiles in a way that we can access them separately, why not have the server send directoryLinks.json with a format like:

{
"related": "en-US": [...],
"directory": "en-US": [...]
}

instead of having to iterate through directoryTiles.json, look for related tiles, then store them separately? Would this be a big change? Also, by persisting the data, do you mean as a separate json file also in the profile directory? (e.g. relatedTiles.json?)
Flags: needinfo?(edilee)
Assignee: nobody → msamuel
Iteration: --- → 38.2 - 9 Feb
Points: --- → 5
(In reply to Marina Samuel [:emtwo] from comment #1)
> If we want to store the related tiles in a way that we can access them
> separately, why not have the server send directoryLinks.json with a format
> like:
> 
> {
> "related": "en-US": [...],
> "directory": "en-US": [...]
> }
That's a fair point and would affect what we need to do for bug 1126191 as well.

I believe I was trying to keep the v2/links/fetch endpoint usable in a backwards compatible way. Where current v2 responds with { "en-US": [tiles] }. But I'm not sure if backwards compatibility is completely desirable anyway. What would older clients do with related tiles it didn't know about? Probably show them as if they were directory tiles?

So assuming we do want a v3, do we need to keep the extra locale information around in the response? I believe it was originally there so that the server could theoretically provide multiple locales of tiles, but any given Firefox installation will have a single locale anyway?

So just a response of:
{
  "related": [tiles..],
  "directory": [tiles..]
}

?

> persisting the data, do you mean as a separate json file also in the profile
> directory? (e.g. relatedTiles.json?)
Nah, we have the response from the server on disk already, and reparsing the json should be okay for now. I meant keep it in memory so that we can pick out a related tile to show. Although technically, if we don't change which related tile we show right now, we only really need to pick one and save that one for when its information is needed in rendering.
Flags: needinfo?(edilee)
Attachment #8559369 - Flags: review?(adw)
Do you have an idea of how you'll implement bug 1126184 to select the related tile? I ask because currently, DirectoryLinksProvider_getLinks() is the place to let NewTabUtils know about the selected related tile.

Stashing the _relatedTiles with link data probably will help us make better decisions and be able to show appropriate information in the UI.
Yes, I was thinking since we're reading the file in getLinks() already, it's a good time to store _relatedTiles here.

We will also need to provide notifications to DirectoryLinksProvider when the frecency of a history tile (or many history tiles) changes so that we can adjust the related tile accordingly. Both on these notifications and in DirectoryLinksProvider.getLinks() we will do decisioning for which related tile to show, then notify NewTabUtils that a link has changed.

As you suggested earlier, Ed, we can initially choose a related tile at random. We can create a list of all potential related tiles given a user's frecent tiles then choose one at random from it.
(In reply to Marina Samuel [:emtwo] from comment #5)
> We will also need to provide notifications to DirectoryLinksProvider when
> the frecency of a history tile (or many history tiles) changes
Hmm.. That does make sense, although it seems like we would need to call PlacesUtils.history.addObserver just like what PlacesProvider does except for DirectoryLinksProvider. I'm not sure if there's a better way though.

> Both on these notifications and in DirectoryLinksProvider.getLinks() 
> we will do decisioning for which related tile to show
Seems like we'll probably want a helper function that returns a link for getLinks to prepend or for the notification to trigger potentially 2 onLinkChanged (one to add and one to remove). In either case, with the helper function, we'll indeed want to stash away related links info as you've done.
(In reply to Ed Lee :Mardak from comment #6)
> Hmm.. That does make sense, although it seems like we would need to call
> PlacesUtils.history.addObserver just like what PlacesProvider does except
> for DirectoryLinksProvider. I'm not sure if there's a better way though.

Mentioned in IRC but adding the comment here: Perhaps we can use Services.obs to send the notification instead of listening directly to frecency changes and also delay decisioning to after siteMap is updated.
Comment on attachment 8559369 [details] [diff] [review]
v1: Cache related tiles for easy lookup by site

Review of attachment 8559369 [details] [diff] [review]:
-----------------------------------------------------------------

Looks fine to me.

::: browser/modules/DirectoryLinksProvider.jsm
@@ +86,5 @@
>  
> +  /**
> +   * A mapping from site to a list of related link objects
> +   */
> +  _relatedTiles: new Map(),

_relatedLinks

@@ +191,5 @@
>        Services.prefs.removeObserver(prefName, this);
>      }
>    },
>  
> +  _cacheRelatedTiles: function(link) {

Links

@@ +193,5 @@
>    },
>  
> +  _cacheRelatedTiles: function(link) {
> +    for (let relatedSite of link.related) {
> +      let relatedArray = this._relatedTiles.get(relatedSite) || [];

Are you sure that this doesn't want to be a Set instead of an Array?

@@ +421,2 @@
>  
> +        // Related tiles will have a higher frecency.

I don't understand what this comment means.  The link's frecency isn't set at all in this case.  Is it in the JSON?  Where's it set?  And why skip adding the link to the list?  Please make the comment clearer.
Attachment #8559369 - Flags: review?(adw) → review+
(In reply to Drew Willcoxon :adw from comment #8)
> > +      let relatedArray = this._relatedTiles.get(relatedSite) || [];
> Are you sure that this doesn't want to be a Set instead of an Array?
Good question that got me thinking of a related question. Do we expect the array of related sites (from the server) to have meaningful ordering? E.g., [irs.gov, taxact.com] vs [taxact.com, irs.gov]? The patch + review right now just splits up the array as keys for the _relatedLinks map to keep track of which link could be shown if the user's top sites matches (optimizing for looking up by user's sites).

To adw's question, does the access pattern matter affect it being a Set vs array? E.g., if for now we want to pick a random Link that matches a user's top site, it being a Set would require us to convert it to an Iterator/array to pick something, no? The main benefit of the Set would be if we wanted to check if a Link was in the set, and I'm not sure if we would do that..?
If I could offer my opinion, I think of it in kind of a different way, not how am I going to use it, but what is the data?  If the data is ordered or can contain duplicates, then it's a list/array.  Otherwise, it's a set -- even if I use a JS array to store it.  If it were me I wouldn't really care about whether I need to convert a set to an array just so I could, for example, easily pick out a random item from it.  (Although Sets are iterable, so I don't think that particular example is a good reason to use an array anyway.)
Fair enough. :) The "using it" aspect is more of an optimization, but that's probably premature and probably nowhere close to being a bottleneck.
Flags: firefox-backlog+
Whiteboard: .? → .007
Flags: qe-verify?
I just wanted to confirm this change makes sense to both of you since there was some back and forth on it.

I changed from an array to a Map. I believe a related tile in our list should be unique, although I think that ensuring directoryLinks.json has unique related links would already be done by the server. Also, I used a map because I think URL is sufficient enough to uniquely identify a link (otherwise it looks like we'd need a toString() function for links so Set can identify uniques)
Attachment #8559369 - Attachment is obsolete: true
Attachment #8560541 - Flags: review?(adw)
Attachment #8560541 - Flags: feedback?(edilee)
Comment on attachment 8560541 [details] [diff] [review]
v2: Cache related tiles for easy lookup by site

Review of attachment 8560541 [details] [diff] [review]:
-----------------------------------------------------------------

Good point!  I didn't think that through, sorry.  Please don't let me stop you from using an array then.  No reason to jump through hoops and use a Map if you don't really need it. :-)  r+ either way.
Attachment #8560541 - Flags: review?(adw) → review+
Iteration: 38.2 - 9 Feb → 38.3 - 23 Feb
Whiteboard: .007 → .002
Status: NEW → ASSIGNED
Depends on: 1134550
Iteration: 38.3 - 23 Feb → 39.1 - 9 Mar
Iteration: 39.1 - 9 Mar → ---
https://hg.mozilla.org/mozilla-central/rev/22dde7d7f911
Status: ASSIGNED → RESOLVED
Closed: 6 years ago
Resolution: --- → FIXED
Target Milestone: --- → Firefox 39
Iteration: --- → 39.2 - 23 Mar
Attachment #8560541 - Flags: feedback?(edilee)
This does not seem to be a high impact fix, and seems to be covered in browser/modules/test/xpcshell/test_DirectoryLinksProvider.js.

Marking as qe-verify-.
Flags: qe-verify? → qe-verify-
Blocks: 1148859
Blocks: 1155443
No longer blocks: 1155443
You need to log in before you can comment on or make changes to this bug.