зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1738957 - Get page image from snapshot data. r=mossop
Add a way to get an image that best represents a snapshot. The current priority is: 1) meta data image 2) thumbnail of page Differential Revision: https://phabricator.services.mozilla.com/D130204
This commit is contained in:
Родитель
1aeac93d23
Коммит
d870cdcfe5
|
@ -13,10 +13,13 @@ const { XPCOMUtils } = ChromeUtils.import(
|
|||
const VERSION_PREF = "browser.places.snapshots.version";
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
BackgroundPageThumbs: "resource://gre/modules/BackgroundPageThumbs.jsm",
|
||||
CommonNames: "resource:///modules/CommonNames.jsm",
|
||||
Interactions: "resource:///modules/Interactions.jsm",
|
||||
PageDataCollector: "resource:///modules/pagedata/PageDataCollector.jsm",
|
||||
PageDataService: "resource:///modules/pagedata/PageDataService.jsm",
|
||||
PageThumbs: "resource://gre/modules/PageThumbs.jsm",
|
||||
PageThumbsStorage: "resource://gre/modules/PageThumbs.jsm",
|
||||
PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
|
||||
Services: "resource://gre/modules/Services.jsm",
|
||||
});
|
||||
|
@ -117,6 +120,8 @@ const Snapshots = new (class Snapshots {
|
|||
// want to accumulate changes and update on idle, plus store a cache of the
|
||||
// last notified pages to avoid hitting the same page continuously.
|
||||
// PageDataService.on("page-data", this.#onPageData);
|
||||
|
||||
PageThumbs.addExpirationFilter(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -137,6 +142,20 @@ const Snapshots = new (class Snapshots {
|
|||
Services.obs.notifyObservers(null, topic, JSON.stringify(urls));
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called by PageThumbs to see what thumbnails should be kept alive.
|
||||
* Currently, the last 100 snapshots are kept alive.
|
||||
* @param {function} callback
|
||||
*/
|
||||
async filterForThumbnailExpiration(callback) {
|
||||
let snapshots = await this.query();
|
||||
let urls = [];
|
||||
for (let snapshot of snapshots) {
|
||||
urls.push(snapshot.url);
|
||||
}
|
||||
callback(urls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches page data for the given urls and stores it with snapshots.
|
||||
* @param {Array<Objects>} urls Array of {placeId, url} tuples.
|
||||
|
@ -147,6 +166,7 @@ const Snapshots = new (class Snapshots {
|
|||
let bindings = {};
|
||||
for (let { placeId, url } of urls) {
|
||||
let pageData = PageDataService.getCached(url);
|
||||
let imageURL = null;
|
||||
if (pageData?.data.length) {
|
||||
for (let data of pageData.data) {
|
||||
if (Object.values(PageDataCollector.DATA_TYPE).includes(data.type)) {
|
||||
|
@ -158,6 +178,14 @@ const Snapshots = new (class Snapshots {
|
|||
bindings[`data${index}`] = JSON.stringify(data);
|
||||
values.push(`(:id${index}, :type${index}, :data${index})`);
|
||||
index++;
|
||||
if (data.type === PageDataCollector.DATA_TYPE.GENERAL) {
|
||||
let websiteData = data.data.find(
|
||||
element => element.type === "website"
|
||||
);
|
||||
if (websiteData?.image) {
|
||||
imageURL = websiteData.image;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -165,6 +193,7 @@ const Snapshots = new (class Snapshots {
|
|||
// was found, but we're not yet handling that, see the constructor.
|
||||
PageDataService.queueFetch(url).catch(console.error);
|
||||
}
|
||||
this.#downloadPageImage(url, imageURL);
|
||||
}
|
||||
|
||||
logConsole.debug(
|
||||
|
@ -190,6 +219,24 @@ const Snapshots = new (class Snapshots {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Store the downloaded and rescaled page image. For now this
|
||||
* only kicks off the page thumbnail if there isn't a meta data image.
|
||||
*
|
||||
* @param {string} url The URL of the page. This is only used if there isn't
|
||||
* a `metaDataImageURL`.
|
||||
* @param {string} metaDataImageURL The URL of the meta data page image. If
|
||||
* this exists, it is prioritized over the page thumbnail.
|
||||
*/
|
||||
#downloadPageImage(url, metaDataImageURL = null) {
|
||||
if (!metaDataImageURL) {
|
||||
// No metadata image was found, start the process to capture a thumbnail
|
||||
// so it will be ready when needed. Ignore any errors since we can
|
||||
// fallback to a favicon.
|
||||
BackgroundPageThumbs.captureIfMissing(url).catch(console.error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a given URL can be added to snapshots.
|
||||
* The rules are defined in this.urlRequirements.
|
||||
|
@ -486,6 +533,32 @@ const Snapshots = new (class Snapshots {
|
|||
return snapshot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the image that should represent the snapshot. The image URL
|
||||
* returned comes from the following priority:
|
||||
* 1) meta data page image
|
||||
* 2) thumbnail of the page
|
||||
* @param {Snapshot} snapshot
|
||||
*
|
||||
* @returns {string?}
|
||||
*/
|
||||
async getSnapshotImageURL(snapshot) {
|
||||
const generalPageData = snapshot.pageData
|
||||
.get(PageDataCollector.DATA_TYPE.GENERAL)
|
||||
?.find(element => element.type === "website");
|
||||
if (generalPageData) {
|
||||
return generalPageData.image;
|
||||
}
|
||||
const url = snapshot.url;
|
||||
await BackgroundPageThumbs.captureIfMissing(url).catch(console.error);
|
||||
const exists = await PageThumbsStorage.fileExistsForURL(url);
|
||||
if (exists) {
|
||||
return PageThumbs.getThumbnailURL(url);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates a date value from the database.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that adding a snapshot also adds related page data.
|
||||
*/
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
PageDataCollector: "resource:///modules/pagedata/PageDataCollector.jsm",
|
||||
PageDataService: "resource:///modules/pagedata/PageDataService.jsm",
|
||||
});
|
||||
|
||||
const TEST_URL1 = "https://example.com/";
|
||||
const TEST_URL2 = "https://example.com/12345";
|
||||
|
||||
const TEST_IMAGE_URL = "https://example.com/dummy.png";
|
||||
|
||||
add_task(async function pageImage() {
|
||||
// Register some page data.
|
||||
PageDataService.pageDataDiscovered(TEST_URL1, [
|
||||
{
|
||||
type: PageDataCollector.DATA_TYPE.GENERAL,
|
||||
data: [
|
||||
{
|
||||
type: "website",
|
||||
image: TEST_IMAGE_URL,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
let now = Date.now();
|
||||
|
||||
// Make snapshots for any page with a typing time greater than 30 seconds
|
||||
// in any one visit.
|
||||
Services.prefs.setCharPref(
|
||||
"browser.places.interactions.snapshotCriteria",
|
||||
JSON.stringify([
|
||||
{
|
||||
property: "total_view_time",
|
||||
aggregator: "max",
|
||||
cutoff: 30000,
|
||||
},
|
||||
])
|
||||
);
|
||||
|
||||
// Page thumbnails are broken in xpcshell tests.
|
||||
Services.prefs.setBoolPref("browser.pagethumbnails.capturing_disabled", true);
|
||||
|
||||
await addInteractions([
|
||||
{
|
||||
url: TEST_URL1,
|
||||
totalViewTime: 40000,
|
||||
created_at: now - 1000,
|
||||
},
|
||||
{
|
||||
url: TEST_URL2,
|
||||
totalViewTime: 20000,
|
||||
created_at: now - 2000,
|
||||
},
|
||||
]);
|
||||
|
||||
await assertSnapshots([
|
||||
{
|
||||
url: TEST_URL1,
|
||||
userPersisted: false,
|
||||
documentType: Interactions.DOCUMENT_TYPE.GENERIC,
|
||||
},
|
||||
]);
|
||||
|
||||
let snap = await Snapshots.get(TEST_URL1);
|
||||
let imageUrl = await Snapshots.getSnapshotImageURL(snap);
|
||||
Assert.equal(snap.pageData.size, 1, "Should have some page data.");
|
||||
Assert.equal(imageUrl, TEST_IMAGE_URL, "Should have a page image.");
|
||||
|
||||
// In the browser a snapshot would usually have a thumbnail generated, but the
|
||||
// thumbnail service does not work in xpcshell tests.
|
||||
await Snapshots.add({ url: TEST_URL2 });
|
||||
snap = await Snapshots.get(TEST_URL2);
|
||||
imageUrl = await Snapshots.getSnapshotImageURL(snap);
|
||||
Assert.equal(imageUrl, null, "Should not have a page image.");
|
||||
|
||||
await reset();
|
||||
});
|
|
@ -14,6 +14,7 @@ skip-if = toolkit == 'android' # bug 1730213
|
|||
[test_snapshots_create_allow_protocols.js]
|
||||
[test_snapshots_create_criteria.js]
|
||||
[test_snapshots_pagedata.js]
|
||||
[test_snapshots_page_image.js]
|
||||
[test_snapshots_queries.js]
|
||||
[test_snapshotselection_adult.js]
|
||||
[test_snapshotselection_recent.js]
|
||||
|
|
Загрузка…
Ссылка в новой задаче