Bug 1448057 - Asincify some Places tests and add a test for favicons on bookmark redirects. r=standard8

Async-ify some tests.
Moves some tests from browser-chrome to xpcshell.
Due to the move, I found out that we are fetching icons from network even when
we are not supposed to, so fix this bug (automatically tested by xpcshell through
disallowing remote network access).
Add a missing test for bookmark redirects, to cover the moved around code.

MozReview-Commit-ID: EB2Z0huovJh

--HG--
rename : toolkit/components/places/tests/browser/browser_favicon_setAndFetchFaviconForPage.js => toolkit/components/places/tests/favicons/test_setAndFetchFaviconForPage.js
rename : toolkit/components/places/tests/browser/browser_favicon_setAndFetchFaviconForPage_failures.js => toolkit/components/places/tests/favicons/test_setAndFetchFaviconForPage_failures.js
extra : rebase_source : 5289551f205bea9c5f2c6e68bbc70ce421b77311
This commit is contained in:
Marco Bonardo 2018-04-05 11:03:19 +02:00
Родитель f443774ffa
Коммит 8b76afe3e5
16 изменённых файлов: 413 добавлений и 716 удалений

Просмотреть файл

@ -4,8 +4,6 @@
// This test make sure that the favicon of the private browsing is isolated.
const CC = Components.Constructor;
const TEST_SITE = "http://mochi.test:8888";
const TEST_CACHE_SITE = "http://www.example.com";
const TEST_DIRECTORY = "/browser/browser/components/privatebrowsing/test/browser/";
@ -184,21 +182,17 @@ async function openTab(aBrowser, aURL) {
return {tab, browser};
}
// A clean up function to prevent affecting other tests.
registerCleanupFunction(() => {
// Clear all cookies.
registerCleanupFunction(async () => {
Services.cookies.removeAll();
// Clear all image caches and network caches.
clearAllImageCaches();
Services.cache2.clear();
await PlacesUtils.history.clear();
await PlacesUtils.bookmarks.eraseEverything();
});
add_task(async function test_favicon_privateBrowsing() {
// Clear all image caches before running the test.
clearAllImageCaches();
// Clear all favicons in Places.
await clearAllPlacesFavicons();
@ -221,10 +215,16 @@ add_task(async function test_favicon_privateBrowsing() {
// Add the observer earlier in case we don't capture events in time.
let promiseObserveFavicon = observeFavicon(true, cookies[0], pageURI);
// The page must be bookmarked for favicon requests to go through in PB mode.
await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
url: TEST_PAGE
});
// Open a tab for the private window.
let tabInfo = await openTab(privateWindow.gBrowser, TEST_PAGE);
// Waiting until favicon requests are all made.
info("Waiting until favicon requests are all made in private window.");
await promiseObserveFavicon;
// Close the tab.
@ -239,7 +239,7 @@ add_task(async function test_favicon_privateBrowsing() {
// Open a tab for the non-private window.
tabInfo = await openTab(gBrowser, TEST_PAGE);
// Waiting until favicon requests are all made.
info("Waiting until favicon requests are all made in non-private window.");
await promiseObserveFavicon;
// Close the tab.
@ -248,7 +248,7 @@ add_task(async function test_favicon_privateBrowsing() {
});
add_task(async function test_favicon_cache_privateBrowsing() {
// Clear all image cahces and network cache before running the test.
// Clear all image caches and network cache before running the test.
clearAllImageCaches();
Services.cache2.clear();
@ -274,6 +274,12 @@ add_task(async function test_favicon_cache_privateBrowsing() {
// Create a private browsing window.
let privateWindow = await BrowserTestUtils.openNewBrowserWindow({ private: true });
// The page must be bookmarked for favicon requests to go through in PB mode.
await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
url: TEST_CACHE_PAGE
});
// Open a tab for the private window.
let tabInfoPrivate = await openTab(privateWindow.gBrowser, TEST_CACHE_PAGE);

Просмотреть файл

@ -53,30 +53,36 @@ FetchPageInfo(const RefPtr<Database>& aDB,
MOZ_ASSERT(_page.spec.Length(), "Must have a non-empty spec!");
MOZ_ASSERT(!NS_IsMainThread());
// This query finds the bookmarked uri we want to set the icon for,
// walking up to two redirect levels.
// The subquery finds the bookmarked uri we want to set the icon for,
// walking up redirects.
nsCString query = nsPrintfCString(
"SELECT h.id, pi.id, h.guid, ( "
"SELECT h.url FROM moz_bookmarks b WHERE b.fk = h.id "
"UNION ALL " // Union not directly bookmarked pages.
"SELECT url FROM moz_places WHERE id = ( "
"SELECT COALESCE(grandparent.place_id, parent.place_id) as r_place_id "
"FROM moz_historyvisits dest "
"LEFT JOIN moz_historyvisits parent ON parent.id = dest.from_visit "
"AND dest.visit_type IN (%d, %d) "
"LEFT JOIN moz_historyvisits grandparent ON parent.from_visit = grandparent.id "
"AND parent.visit_type IN (%d, %d) "
"WHERE dest.place_id = h.id "
"AND EXISTS(SELECT 1 FROM moz_bookmarks b WHERE b.fk = r_place_id) "
"LIMIT 1 "
"WITH RECURSIVE "
"destinations(visit_type, from_visit, place_id, rev_host, bm) AS ( "
"SELECT v.visit_type, v.from_visit, p.id, p.rev_host, b.id "
"FROM moz_places p "
"LEFT JOIN moz_historyvisits v ON v.place_id = p.id "
"LEFT JOIN moz_bookmarks b ON b.fk = p.id "
"WHERE p.id = h.id "
"UNION "
"SELECT src.visit_type, src.from_visit, src.place_id, p.rev_host, b.id "
"FROM moz_places p "
"JOIN moz_historyvisits src ON src.place_id = p.id "
"JOIN destinations dest ON dest.from_visit = src.id AND dest.visit_type IN (%d, %d) "
"LEFT JOIN moz_bookmarks b ON b.fk = src.place_id "
"WHERE instr(p.rev_host, dest.rev_host) = 1 "
"OR instr(dest.rev_host, p.rev_host) = 1 "
") "
"SELECT url "
"FROM moz_places p "
"JOIN destinations r ON r.place_id = p.id "
"WHERE bm NOTNULL "
"LIMIT 1 "
"), fixup_url(get_unreversed_host(h.rev_host)) AS host "
"FROM moz_places h "
"LEFT JOIN moz_pages_w_icons pi ON page_url_hash = hash(:page_url) AND page_url = :page_url "
"WHERE h.url_hash = hash(:page_url) AND h.url = :page_url",
nsINavHistoryService::TRANSITION_REDIRECT_PERMANENT,
nsINavHistoryService::TRANSITION_REDIRECT_TEMPORARY,
nsINavHistoryService::TRANSITION_REDIRECT_PERMANENT,
nsINavHistoryService::TRANSITION_REDIRECT_TEMPORARY
);
@ -542,6 +548,19 @@ AsyncFetchAndSetIconForPage::Run()
bool fetchIconFromNetwork = mIcon.fetchMode == FETCH_ALWAYS ||
(mIcon.fetchMode == FETCH_IF_MISSING && isInvalidIcon);
// Check if we can associate the icon to this page.
rv = FetchPageInfo(DB, mPage);
if (NS_FAILED(rv)) {
if (rv == NS_ERROR_NOT_AVAILABLE) {
// We have never seen this page. If we can add the page to history,
// we will try to do it later, otherwise just bail out.
if (!mPage.canAddToHistory) {
return NS_OK;
}
}
return rv;
}
if (!fetchIconFromNetwork) {
// There is already a valid icon or we don't want to fetch a new one,
// directly proceed with association.
@ -827,20 +846,9 @@ NS_IMETHODIMP
AsyncAssociateIconToPage::Run()
{
MOZ_ASSERT(!NS_IsMainThread());
RefPtr<Database> DB = Database::GetDatabase();
NS_ENSURE_STATE(DB);
nsresult rv = FetchPageInfo(DB, mPage);
if (rv == NS_ERROR_NOT_AVAILABLE){
// We have never seen this page. If we can add the page to history,
// we will try to do it later, otherwise just bail out.
if (!mPage.canAddToHistory) {
return NS_OK;
}
}
else {
NS_ENSURE_SUCCESS(rv, rv);
}
MOZ_ASSERT(!mPage.guid.IsEmpty(), "Page info should have been fetched already");
MOZ_ASSERT(mPage.canAddToHistory || !mPage.bookmarkedSpec.IsEmpty(),
"The page should be addable to history or a bookmark");
bool shouldUpdateIcon = mIcon.status & ICON_STATUS_CHANGED;
if (!shouldUpdateIcon) {
@ -853,9 +861,11 @@ AsyncAssociateIconToPage::Run()
}
}
RefPtr<Database> DB = Database::GetDatabase();
NS_ENSURE_STATE(DB);
mozStorageTransaction transaction(DB->MainConn(), false,
mozIStorageConnection::TRANSACTION_IMMEDIATE);
nsresult rv;
if (shouldUpdateIcon) {
rv = SetIconInfo(DB, mIcon);
NS_ENSURE_SUCCESS(rv, rv);
@ -954,6 +964,23 @@ AsyncAssociateIconToPage::Run()
rv = NS_DispatchToMainThread(event);
NS_ENSURE_SUCCESS(rv, rv);
// If there is a bookmarked page that redirects to this one, try to update its
// icon as well.
if (!mPage.bookmarkedSpec.IsEmpty() &&
!mPage.bookmarkedSpec.Equals(mPage.spec)) {
// Create a new page struct to avoid polluting it with old data.
PageData bookmarkedPage;
bookmarkedPage.spec = mPage.bookmarkedSpec;
RefPtr<Database> DB = Database::GetDatabase();
if (DB && NS_SUCCEEDED(FetchPageInfo(DB, bookmarkedPage))) {
// This will be silent, so be sure to not pass in the current callback.
nsMainThreadPtrHandle<nsIFaviconDataCallback> nullCallback;
RefPtr<AsyncAssociateIconToPage> event =
new AsyncAssociateIconToPage(mIcon, bookmarkedPage, nullCallback);
Unused << event->Run();
}
}
return NS_OK;
}
@ -1128,7 +1155,15 @@ NotifyIconObservers::Run()
// Notify observers only if something changed.
if (mIcon.status & ICON_STATUS_SAVED ||
mIcon.status & ICON_STATUS_ASSOCIATED) {
SendGlobalNotifications(iconURI);
nsCOMPtr<nsIURI> pageURI;
MOZ_ALWAYS_SUCCEEDS(NS_NewURI(getter_AddRefs(pageURI), mPage.spec));
if (pageURI) {
nsFaviconService* favicons = nsFaviconService::GetFaviconService();
MOZ_ASSERT(favicons);
if (favicons) {
(void)favicons->SendFaviconNotifications(pageURI, iconURI, mPage.guid);
}
}
}
}
}
@ -1147,38 +1182,6 @@ NotifyIconObservers::Run()
EmptyCString(), 0);
}
void
NotifyIconObservers::SendGlobalNotifications(nsIURI* aIconURI)
{
nsCOMPtr<nsIURI> pageURI;
MOZ_ALWAYS_SUCCEEDS(NS_NewURI(getter_AddRefs(pageURI), mPage.spec));
if (pageURI) {
nsFaviconService* favicons = nsFaviconService::GetFaviconService();
MOZ_ASSERT(favicons);
if (favicons) {
(void)favicons->SendFaviconNotifications(pageURI, aIconURI, mPage.guid);
}
}
// If the page is bookmarked and the bookmarked url is different from the
// updated one, start a new task to update its icon as well.
if (!mPage.bookmarkedSpec.IsEmpty() &&
!mPage.bookmarkedSpec.Equals(mPage.spec)) {
// Create a new page struct to avoid polluting it with old data.
PageData bookmarkedPage;
bookmarkedPage.spec = mPage.bookmarkedSpec;
RefPtr<Database> DB = Database::GetDatabase();
if (!DB)
return;
// This will be silent, so be sure to not pass in the current callback.
nsMainThreadPtrHandle<nsIFaviconDataCallback> nullCallback;
RefPtr<AsyncAssociateIconToPage> event =
new AsyncAssociateIconToPage(mIcon, bookmarkedPage, nullCallback);
DB->DispatchToAsyncThread(event);
}
}
////////////////////////////////////////////////////////////////////////////////
//// FetchAndConvertUnsupportedPayloads

Просмотреть файл

@ -327,8 +327,6 @@ private:
nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback;
IconData mIcon;
PageData mPage;
void SendGlobalNotifications(nsIURI* aIconURI);
};
/**

Просмотреть файл

@ -13,8 +13,6 @@ support-files =
[browser_colorAnalyzer.js]
[browser_double_redirect.js]
[browser_favicon_privatebrowsing_perwindowpb.js]
[browser_favicon_setAndFetchFaviconForPage.js]
[browser_favicon_setAndFetchFaviconForPage_failures.js]
[browser_history_post.js]
[browser_notfound.js]
[browser_onvisit_title_null_for_navigation.js]

Просмотреть файл

@ -1,152 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This file tests the normal operation of setAndFetchFaviconForPage.
function test() {
// Initialization
waitForExplicitFinish();
let windowsToClose = [];
let favIconLocation =
"http://example.org/tests/toolkit/components/places/tests/browser/favicon-normal32.png";
let favIconURI = NetUtil.newURI(favIconLocation);
let favIconMimeType = "image/png";
let pageURI;
let favIconData;
function testOnWindow(aOptions, aCallback) {
whenNewWindowLoaded(aOptions, function(aWin) {
windowsToClose.push(aWin);
executeSoon(() => aCallback(aWin));
});
}
// This function is called after calling finish() on the test.
registerCleanupFunction(function() {
windowsToClose.forEach(function(aWin) {
aWin.close();
});
});
function getIconFile(aCallback) {
NetUtil.asyncFetch({
uri: favIconLocation,
loadUsingSystemPrincipal: true,
contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE_FAVICON
}, function(inputStream, status) {
if (!Components.isSuccessCode(status)) {
ok(false, "Could not get the icon file");
// Handle error.
return;
}
// Check the returned size versus the expected size.
let size = inputStream.available();
favIconData = NetUtil.readInputStreamToString(inputStream, size);
is(size, favIconData.length, "Check correct icon size");
// Check that the favicon loaded correctly before starting the actual tests.
is(favIconData.length, 344, "Check correct icon length (344)");
if (aCallback) {
aCallback();
} else {
finish();
}
});
}
function testNormal(aWindow, aCallback) {
pageURI = NetUtil.newURI("http://example.com/normal");
waitForFaviconChanged(pageURI, favIconURI, aWindow,
function testNormalCallback() {
checkFaviconDataForPage(pageURI, favIconMimeType, favIconData, aWindow,
aCallback);
}
);
addVisits({uri: pageURI, transition: TRANSITION_TYPED}, aWindow,
function() {
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI, favIconURI,
true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
Services.scriptSecurityManager.getSystemPrincipal());
}
);
}
function testAboutURIBookmarked(aWindow, aCallback) {
pageURI = NetUtil.newURI("about:testAboutURI_bookmarked");
waitForFaviconChanged(pageURI, favIconURI, aWindow,
function testAboutURIBookmarkedCallback() {
checkFaviconDataForPage(pageURI, favIconMimeType, favIconData, aWindow,
aCallback);
}
);
aWindow.PlacesUtils.bookmarks.insertBookmark(
aWindow.PlacesUtils.unfiledBookmarksFolderId, pageURI,
aWindow.PlacesUtils.bookmarks.DEFAULT_INDEX, pageURI.spec);
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI, favIconURI,
true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
Services.scriptSecurityManager.getSystemPrincipal());
}
function testPrivateBrowsingBookmarked(aWindow, aCallback) {
pageURI = NetUtil.newURI("http://example.com/privateBrowsing_bookmarked");
waitForFaviconChanged(pageURI, favIconURI, aWindow,
function testPrivateBrowsingBookmarkedCallback() {
checkFaviconDataForPage(pageURI, favIconMimeType, favIconData, aWindow,
aCallback);
}
);
aWindow.PlacesUtils.bookmarks.insertBookmark(
aWindow.PlacesUtils.unfiledBookmarksFolderId, pageURI,
aWindow.PlacesUtils.bookmarks.DEFAULT_INDEX, pageURI.spec);
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI, favIconURI,
true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_PRIVATE, null,
Services.scriptSecurityManager.getSystemPrincipal());
}
function testDisabledHistoryBookmarked(aWindow, aCallback) {
pageURI = NetUtil.newURI("http://example.com/disabledHistory_bookmarked");
waitForFaviconChanged(pageURI, favIconURI, aWindow,
function testDisabledHistoryBookmarkedCallback() {
checkFaviconDataForPage(pageURI, favIconMimeType, favIconData, aWindow,
aCallback);
}
);
// Disable history while changing the favicon.
aWindow.Services.prefs.setBoolPref("places.history.enabled", false);
aWindow.PlacesUtils.bookmarks.insertBookmark(
aWindow.PlacesUtils.unfiledBookmarksFolderId, pageURI,
aWindow.PlacesUtils.bookmarks.DEFAULT_INDEX, pageURI.spec);
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI, favIconURI,
true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
Services.scriptSecurityManager.getSystemPrincipal());
// The setAndFetchFaviconForPage function calls CanAddURI synchronously, thus
// we can set the preference back to true immediately. We don't clear the
// preference because not all products enable Places by default.
aWindow.Services.prefs.setBoolPref("places.history.enabled", true);
}
getIconFile(function() {
testOnWindow({}, function(aWin) {
testNormal(aWin, function() {
testOnWindow({}, function(aWin2) {
testAboutURIBookmarked(aWin2, function() {
testOnWindow({private: true}, function(aWin3) {
testPrivateBrowsingBookmarked(aWin3, function() {
testOnWindow({}, function(aWin4) {
testDisabledHistoryBookmarked(aWin4, finish);
});
});
});
});
});
});
});
});
}

Просмотреть файл

@ -1,263 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* eslint max-nested-callbacks: ["warn", 17] */
/**
* This file tests setAndFetchFaviconForPage when it is called with invalid
* arguments, and when no favicon is stored for the given arguments.
*/
function test() {
// Initialization
waitForExplicitFinish();
let windowsToClose = [];
let favIcon16Location =
"http://example.org/tests/toolkit/components/places/tests/browser/favicon-normal16.png";
let favIcon32Location =
"http://example.org/tests/toolkit/components/places/tests/browser/favicon-normal32.png";
let favIcon16URI = NetUtil.newURI(favIcon16Location);
let favIcon32URI = NetUtil.newURI(favIcon32Location);
let lastPageURI = NetUtil.newURI("http://example.com/verification");
// This error icon must stay in sync with FAVICON_ERRORPAGE_URL in
// nsIFaviconService.idl, aboutCertError.xhtml and netError.xhtml.
let favIconErrorPageURI =
NetUtil.newURI("chrome://global/skin/icons/warning-16.png");
let favIconsResultCount = 0;
function testOnWindow(aOptions, aCallback) {
whenNewWindowLoaded(aOptions, function(aWin) {
windowsToClose.push(aWin);
executeSoon(() => aCallback(aWin));
});
}
// This function is called after calling finish() on the test.
registerCleanupFunction(function() {
windowsToClose.forEach(function(aWin) {
aWin.close();
});
});
function checkFavIconsDBCount(aCallback) {
let stmt = DBConn().createAsyncStatement("SELECT icon_url FROM moz_icons");
stmt.executeAsync({
handleResult: function final_handleResult(aResultSet) {
while (aResultSet.getNextRow()) {
favIconsResultCount++;
}
},
handleError: function final_handleError(aError) {
throw ("Unexpected error (" + aError.result + "): " + aError.message);
},
handleCompletion: function final_handleCompletion(aReason) {
// begin testing
info("Previous records in moz_icons: " + favIconsResultCount);
if (aCallback) {
aCallback();
}
}
});
stmt.finalize();
}
function testNullPageURI(aWindow, aCallback) {
try {
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(null, favIcon16URI,
true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
Services.scriptSecurityManager.getSystemPrincipal());
throw ("Exception expected because aPageURI is null.");
} catch (ex) {
// We expected an exception.
ok(true, "Exception expected because aPageURI is null");
}
if (aCallback) {
aCallback();
}
}
function testNullFavIconURI(aWindow, aCallback) {
try {
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(
NetUtil.newURI("http://example.com/null_faviconURI"), null,
true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
null, Services.scriptSecurityManager.getSystemPrincipal());
throw ("Exception expected because aFaviconURI is null.");
} catch (ex) {
// We expected an exception.
ok(true, "Exception expected because aFaviconURI is null.");
}
if (aCallback) {
aCallback();
}
}
function testAboutURI(aWindow, aCallback) {
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(
NetUtil.newURI("about:testAboutURI"), favIcon16URI,
true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
null, Services.scriptSecurityManager.getSystemPrincipal());
if (aCallback) {
aCallback();
}
}
function testPrivateBrowsingNonBookmarkedURI(aWindow, aCallback) {
let pageURI = NetUtil.newURI("http://example.com/privateBrowsing");
addVisits({ uri: pageURI, transitionType: TRANSITION_TYPED }, aWindow,
function() {
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI,
favIcon16URI, true,
aWindow.PlacesUtils.favicons.FAVICON_LOAD_PRIVATE, null,
Services.scriptSecurityManager.getSystemPrincipal());
if (aCallback) {
aCallback();
}
});
}
function testDisabledHistory(aWindow, aCallback) {
let pageURI = NetUtil.newURI("http://example.com/disabledHistory");
addVisits({ uri: pageURI, transition: TRANSITION_TYPED }, aWindow,
function() {
aWindow.Services.prefs.setBoolPref("places.history.enabled", false);
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI,
favIcon16URI, true,
aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
Services.scriptSecurityManager.getSystemPrincipal());
// The setAndFetchFaviconForPage function calls CanAddURI synchronously, thus
// we can set the preference back to true immediately . We don't clear the
// preference because not all products enable Places by default.
aWindow.Services.prefs.setBoolPref("places.history.enabled", true);
if (aCallback) {
aCallback();
}
});
}
function testErrorIcon(aWindow, aCallback) {
let pageURI = NetUtil.newURI("http://example.com/errorIcon");
addVisits({ uri: pageURI, transition: TRANSITION_TYPED }, aWindow,
function() {
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI,
favIconErrorPageURI, true,
aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
Services.scriptSecurityManager.getSystemPrincipal());
if (aCallback) {
aCallback();
}
});
}
function testNonExistingPage(aWindow, aCallback) {
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(
NetUtil.newURI("http://example.com/nonexistingPage"), favIcon16URI,
true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
Services.scriptSecurityManager.getSystemPrincipal());
if (aCallback) {
aCallback();
}
}
function testFinalVerification(aWindow, aCallback) {
// Only the last test should raise the onPageChanged notification,
// executing the waitForFaviconChanged callback.
waitForFaviconChanged(lastPageURI, favIcon32URI, aWindow,
function final_callback() {
// Check that only one record corresponding to the last favicon is present.
let resultCount = 0;
let stmt = DBConn().createAsyncStatement("SELECT icon_url FROM moz_icons");
stmt.executeAsync({
handleResult: function final_handleResult(aResultSet) {
// If the moz_icons DB had been previously loaded (before our
// test began), we should focus only in the URI we are testing and
// skip the URIs not related to our test.
if (favIconsResultCount > 0) {
for (let row; (row = aResultSet.getNextRow()); ) {
if (favIcon32URI.spec === row.getResultByIndex(0)) {
is(favIcon32URI.spec, row.getResultByIndex(0),
"Check equal favicons");
resultCount++;
}
}
} else {
for (let row; (row = aResultSet.getNextRow()); ) {
is(favIcon32URI.spec, row.getResultByIndex(0),
"Check equal favicons");
resultCount++;
}
}
},
handleError: function final_handleError(aError) {
throw ("Unexpected error (" + aError.result + "): " + aError.message);
},
handleCompletion: function final_handleCompletion(aReason) {
is(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason,
"Check reasons are equal");
is(1, resultCount, "Check result count");
if (aCallback) {
aCallback();
}
}
});
stmt.finalize();
});
// This is the only test that should cause the waitForFaviconChanged
// callback to be invoked. In turn, the callback will invoke
// finish() causing the tests to finish.
addVisits({ uri: lastPageURI, transition: TRANSITION_TYPED }, aWindow,
function() {
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(lastPageURI,
favIcon32URI, true,
aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
Services.scriptSecurityManager.getSystemPrincipal());
});
}
checkFavIconsDBCount(function() {
testOnWindow({}, function(aWin) {
testNullPageURI(aWin, function() {
testOnWindow({}, function(aWin2) {
testNullFavIconURI(aWin2, function() {
testOnWindow({}, function(aWin3) {
testAboutURI(aWin3, function() {
testOnWindow({private: true}, function(aWin4) {
testPrivateBrowsingNonBookmarkedURI(aWin4, function() {
testOnWindow({}, function(aWin5) {
testDisabledHistory(aWin5, function() {
testOnWindow({}, function(aWin6) {
testErrorIcon(aWin6, function() {
testOnWindow({}, function(aWin7) {
testNonExistingPage(aWin7, function() {
testOnWindow({}, function(aWin8) {
testFinalVerification(aWin8, function() {
finish();
});
});
});
});
});
});
});
});
});
});
});
});
});
});
});
});
});
}

Просмотреть файл

@ -89,43 +89,6 @@ NavHistoryObserver.prototype = {
])
};
/**
* Waits for the first OnPageChanged notification for ATTRIBUTE_FAVICON, and
* verifies that it matches the expected page URI and associated favicon URI.
*
* This function also double-checks the GUID parameter of the notification.
*
* @param aExpectedPageURI
* nsIURI object of the page whose favicon should change.
* @param aExpectedFaviconURI
* nsIURI object of the newly associated favicon.
* @param aCallback
* This function is called after the check finished.
*/
function waitForFaviconChanged(aExpectedPageURI, aExpectedFaviconURI, aWindow,
aCallback) {
let historyObserver = {
__proto__: NavHistoryObserver.prototype,
onPageChanged: function WFFC_onPageChanged(aURI, aWhat, aValue, aGUID) {
if (aWhat != Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON) {
return;
}
aWindow.PlacesUtils.history.removeObserver(this);
ok(aURI.equals(aExpectedPageURI),
"Check URIs are equal for the page which favicon changed");
is(aValue, aExpectedFaviconURI.spec,
"Check changed favicon URI is the expected");
checkGuidForURI(aURI, aGUID);
if (aCallback) {
aCallback();
}
}
};
aWindow.PlacesUtils.history.addObserver(historyObserver);
}
/**
* Asynchronously adds visits to a page, invoking a callback function when done.
*
@ -183,139 +146,7 @@ function addVisits(aPlaceInfo, aWindow, aCallback, aStack) {
);
}
/**
* Checks that the favicon for the given page matches the provided data.
*
* @param aPageURI
* nsIURI object for the page to check.
* @param aExpectedMimeType
* Expected MIME type of the icon, for example "image/png".
* @param aExpectedData
* Expected icon data, expressed as an array of byte values.
* @param aCallback
* This function is called after the check finished.
*/
function checkFaviconDataForPage(aPageURI, aExpectedMimeType, aExpectedData,
aWindow, aCallback) {
aWindow.PlacesUtils.favicons.getFaviconDataForPage(aPageURI,
function(aURI, aDataLen, aData, aMimeType) {
is(aExpectedMimeType, aMimeType, "Check expected MimeType");
is(aExpectedData.length, aData.length,
"Check favicon data for the given page matches the provided data");
checkGuidForURI(aPageURI);
aCallback();
});
}
/**
* Tests that a guid was set in moz_places for a given uri.
*
* @param aURI
* The uri to check.
* @param [optional] aGUID
* The expected guid in the database.
*/
function checkGuidForURI(aURI, aGUID) {
let guid = doGetGuidForURI(aURI);
if (aGUID) {
doCheckValidPlacesGuid(aGUID);
is(guid, aGUID, "Check equal guid for URIs");
}
}
/**
* Retrieves the guid for a given uri.
*
* @param aURI
* The uri to check.
* @return the associated the guid.
*/
function doGetGuidForURI(aURI) {
let stmt = DBConn().createStatement(
`SELECT guid
FROM moz_places
WHERE url_hash = hash(:url) AND url = :url`
);
stmt.params.url = aURI.spec;
ok(stmt.executeStep(), "Check get guid for uri from moz_places");
let guid = stmt.row.guid;
stmt.finalize();
doCheckValidPlacesGuid(guid);
return guid;
}
/**
* Tests if a given guid is valid for use in Places or not.
*
* @param aGuid
* The guid to test.
*/
function doCheckValidPlacesGuid(aGuid) {
ok(/^[a-zA-Z0-9\-_]{12}$/.test(aGuid), "Check guid for valid places");
}
/**
* Gets the database connection. If the Places connection is invalid it will
* try to create a new connection.
*
* @param [optional] aForceNewConnection
* Forces creation of a new connection to the database. When a
* connection is asyncClosed it cannot anymore schedule async statements,
* though connectionReady will keep returning true (Bug 726990).
*
* @return The database connection or null if unable to get one.
*/
function DBConn(aForceNewConnection) {
let gDBConn;
if (!aForceNewConnection) {
let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.DBConnection;
if (db.connectionReady)
return db;
}
// If the Places database connection has been closed, create a new connection.
if (!gDBConn || aForceNewConnection) {
let file = Services.dirsvc.get("ProfD", Ci.nsIFile);
file.append("places.sqlite");
let dbConn = gDBConn = Services.storage.openDatabase(file);
// Be sure to cleanly close this connection.
Services.obs.addObserver(function DBCloseCallback(aSubject, aTopic, aData) {
Services.obs.removeObserver(DBCloseCallback, aTopic);
dbConn.asyncClose();
}, "profile-before-change");
}
return gDBConn.connectionReady ? gDBConn : null;
}
function whenNewWindowLoaded(aOptions, aCallback) {
BrowserTestUtils.waitForNewWindow().then(aCallback);
OpenBrowserWindow(aOptions);
}
function waitForCondition(condition, nextTest, errorMsg) {
let tries = 0;
let interval = setInterval(function() {
if (tries >= 30) {
ok(false, errorMsg);
moveOn();
}
let conditionPassed;
try {
conditionPassed = condition();
} catch (e) {
ok(false, e + "\n" + e.stack);
conditionPassed = false;
}
if (conditionPassed) {
moveOn();
}
tries++;
}, 200);
function moveOn() {
clearInterval(interval);
nextTest();
}
}

Просмотреть файл

@ -0,0 +1,97 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This file tests the normal operation of setAndFetchFaviconForPage.
let gTests = [
{
desc: "Normal test",
href: "http://example.com/normal",
loadType: PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
async setup() {
await PlacesTestUtils.addVisits({uri: this.href, transition: TRANSITION_TYPED});
}
},
{
desc: "Bookmarked about: uri",
href: "about:testAboutURI_bookmarked",
loadType: PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
async setup() {
await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
url: this.href
});
}
},
{
desc: "Bookmarked in private window",
href: "http://example.com/privateBrowsing_bookmarked",
loadType: PlacesUtils.favicons.FAVICON_LOAD_PRIVATE,
async setup() {
await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
url: this.href
});
}
},
{
desc: "Bookmarked with disabled history",
href: "http://example.com/disabledHistory_bookmarked",
loadType: PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
async setup() {
await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
url: this.href
});
Services.prefs.setBoolPref("places.history.enabled", false);
},
clean() {
Services.prefs.setBoolPref("places.history.enabled", true);
}
},
];
add_task(async function() {
let faviconURI = SMALLPNG_DATA_URI;
let faviconMimeType = "image/png";
registerCleanupFunction(async function() {
await PlacesUtils.bookmarks.eraseEverything();
await PlacesUtils.history.clear();
});
for (let test of gTests) {
info(test.desc);
let pageURI = Services.io.newURI(test.href);
await test.setup();
let pageGuid;
let promise = PlacesTestUtils.waitForNotification("onPageChanged", (uri, prop, value, guid) => {
pageGuid = guid;
return prop == Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON &&
uri.equals(pageURI) &&
value == faviconURI.spec;
}, "history");
PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI, faviconURI,
true, test.private, null,
Services.scriptSecurityManager.getSystemPrincipal());
await promise;
Assert.equal(pageGuid, await PlacesTestUtils.fieldInDB(pageURI, "guid"),
"Page guid is correct");
let {dataLen, data, mimeType} = await PlacesUtils.promiseFaviconData(pageURI.spec);
Assert.equal(faviconMimeType, mimeType, "Check expected MimeType");
Assert.equal(SMALLPNG_DATA_LEN, data.length,
"Check favicon data for the given page matches the provided data");
Assert.equal(dataLen, data.length,
"Check favicon dataLen for the given page matches the provided data");
if (test.clean) {
await test.clean();
}
}
});

Просмотреть файл

@ -0,0 +1,97 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* This file tests setAndFetchFaviconForPage when it is called with invalid
* arguments, and when no favicon is stored for the given arguments.
*/
let faviconURI = Services.io.newURI("http://example.org/tests/toolkit/components/places/tests/browser/favicon-normal16.png");
add_task(async function() {
registerCleanupFunction(async function() {
await PlacesUtils.bookmarks.eraseEverything();
await PlacesUtils.history.clear();
});
// We'll listen for favicon changes for the whole test, to ensure only the
// last one will send a notification. Due to thread serialization, at that
// point we can be sure previous calls didn't send a notification.
let lastPageURI = Services.io.newURI("http://example.com/verification");
let promiseIconChanged = PlacesTestUtils.waitForNotification("onPageChanged", (uri, prop, value) => {
return prop == Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON &&
uri.equals(lastPageURI) &&
value == SMALLPNG_DATA_URI.spec;
}, "history");
info("Test null page uri");
Assert.throws(() => {
PlacesUtils.favicons.setAndFetchFaviconForPage(null, faviconURI,
true, PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
Services.scriptSecurityManager.getSystemPrincipal());
}, /NS_ERROR_ILLEGAL_VALUE/, "Exception expected because aPageURI is null");
info("Test null favicon uri");
Assert.throws(() => {
PlacesUtils.favicons.setAndFetchFaviconForPage(
Services.io.newURI("http://example.com/null_faviconURI"), null,
true, PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
null, Services.scriptSecurityManager.getSystemPrincipal());
}, /NS_ERROR_ILLEGAL_VALUE/, "Exception expected because aFaviconURI is null.");
info("Test about uri");
PlacesUtils.favicons.setAndFetchFaviconForPage(
Services.io.newURI("about:testAboutURI"), faviconURI,
true, PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
null, Services.scriptSecurityManager.getSystemPrincipal());
info("Test private browsing non bookmarked uri");
let pageURI = Services.io.newURI("http://example.com/privateBrowsing");
await PlacesTestUtils.addVisits({ uri: pageURI, transitionType: TRANSITION_TYPED });
PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI, faviconURI, true,
PlacesUtils.favicons.FAVICON_LOAD_PRIVATE, null,
Services.scriptSecurityManager.getSystemPrincipal());
info("Test disabled history");
pageURI = Services.io.newURI("http://example.com/disabledHistory");
await PlacesTestUtils.addVisits({ uri: pageURI, transition: TRANSITION_TYPED });
Services.prefs.setBoolPref("places.history.enabled", false);
PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI,
faviconURI, true,
PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
Services.scriptSecurityManager.getSystemPrincipal());
// The setAndFetchFaviconForPage function calls CanAddURI synchronously, thus
// we can set the preference back to true immediately.
Services.prefs.setBoolPref("places.history.enabled", true);
info("Test error icon");
// This error icon must stay in sync with FAVICON_ERRORPAGE_URL in
// nsIFaviconService.idl, aboutCertError.xhtml and netError.xhtml.
let faviconErrorPageURI =
Services.io.newURI("chrome://global/skin/icons/warning-16.png");
pageURI = Services.io.newURI("http://example.com/errorIcon");
await PlacesTestUtils.addVisits({ uri: pageURI, transition: TRANSITION_TYPED });
PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI,
faviconErrorPageURI, true,
PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
Services.scriptSecurityManager.getSystemPrincipal());
info("Test nonexisting page");
PlacesUtils.favicons.setAndFetchFaviconForPage(
Services.io.newURI("http://example.com/nonexistingPage"), faviconURI,
true, PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
Services.scriptSecurityManager.getSystemPrincipal());
info("Final sanity check");
// This is the only test that should cause the waitForFaviconChanged
// callback to be invoked.
await PlacesTestUtils.addVisits({ uri: lastPageURI, transition: TRANSITION_TYPED });
PlacesUtils.favicons.setAndFetchFaviconForPage(lastPageURI,
SMALLPNG_DATA_URI, true, PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
Services.scriptSecurityManager.getSystemPrincipal());
await promiseIconChanged;
});

Просмотреть файл

@ -0,0 +1,71 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This file tests setAndFetchFaviconForPage on bookmarked redirects.
add_task(async function same_host_redirect() {
// Add a bookmarked page that redirects to another page, set a favicon on the
// latter and check the former gets it too, if they are in the same host.
let srcUrl = "http://bookmarked.com/";
let destUrl = "https://other.bookmarked.com/";
await PlacesTestUtils.addVisits([
{ uri: srcUrl, transition: TRANSITION_LINK },
{ uri: destUrl, transition: TRANSITION_REDIRECT_TEMPORARY, referrer: srcUrl }
]);
await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
url: srcUrl
});
registerCleanupFunction(async function() {
await PlacesUtils.bookmarks.eraseEverything();
await PlacesUtils.history.clear();
});
let promise = PlacesTestUtils.waitForNotification("onPageChanged", (uri, prop, value, guid) => {
return prop == Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON &&
uri.spec == srcUrl &&
value == SMALLPNG_DATA_URI.spec;
}, "history");
PlacesUtils.favicons.setAndFetchFaviconForPage(Services.io.newURI(destUrl),
SMALLPNG_DATA_URI, true, PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
Services.scriptSecurityManager.getSystemPrincipal());
await promise;
// The favicon should be set also on the bookmarked url that redirected.
let {dataLen} = await PlacesUtils.promiseFaviconData(srcUrl);
Assert.equal(dataLen, SMALLPNG_DATA_LEN, "Check favicon dataLen");
});
add_task(async function other_host_redirect() {
// Add a bookmarked page that redirects to another page, set a favicon on the
// latter and check the former gets it too, if they are in the same host.
let srcUrl = "http://first.com/";
let destUrl = "https://notfirst.com/";
await PlacesTestUtils.addVisits([
{ uri: srcUrl, transition: TRANSITION_LINK },
{ uri: destUrl, transition: TRANSITION_REDIRECT_TEMPORARY, referrer: srcUrl }
]);
await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
url: srcUrl
});
let promise = Promise.race([
PlacesTestUtils.waitForNotification("onPageChanged", (uri, prop, value, guid) => {
return prop == Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON &&
uri.spec == srcUrl &&
value == SMALLPNG_DATA_URI.spec;
}, "history"),
new Promise((resolve, reject) => do_timeout(300, () => reject(new Error("timeout"))))
]);
PlacesUtils.favicons.setAndFetchFaviconForPage(Services.io.newURI(destUrl),
SMALLPNG_DATA_URI, true, PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
Services.scriptSecurityManager.getSystemPrincipal());
await Assert.rejects(promise, /timeout/);
});

Просмотреть файл

@ -41,4 +41,7 @@ support-files =
[test_replaceFaviconData.js]
[test_replaceFaviconDataFromDataURL.js]
[test_root_icons.js]
[test_setAndFetchFaviconForPage.js]
[test_setAndFetchFaviconForPage_failures.js]
[test_setAndFetchFaviconForPage_redirects.js]
[test_svg_favicon.js]

Просмотреть файл

@ -47,6 +47,8 @@ XPCOMUtils.defineLazyGetter(this, "SMALLPNG_DATA_URI", function() {
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAA" +
"AAAA6fptVAAAACklEQVQI12NgAAAAAgAB4iG8MwAAAABJRU5ErkJggg==");
});
const SMALLPNG_DATA_LEN = 67;
XPCOMUtils.defineLazyGetter(this, "SMALLSVG_DATA_URI", function() {
return NetUtil.newURI(
"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy5" +

Просмотреть файл

@ -31,11 +31,11 @@ add_task(async function test_remove_single() {
let removeArg = await filter(uri);
if (options.addBookmark) {
PlacesUtils.bookmarks.insertBookmark(
PlacesUtils.unfiledBookmarksFolderId,
uri,
PlacesUtils.bookmarks.DEFAULT_INDEX,
"test bookmark");
await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
url: uri,
title: "test bookmark"
});
}
let shouldRemove = !options.addBookmark;

Просмотреть файл

@ -44,11 +44,11 @@ add_task(async function test_remove_many() {
await PlacesTestUtils.addVisits(page);
page.guid = do_get_guid_for_uri(uri);
if (hasBookmark) {
PlacesUtils.bookmarks.insertBookmark(
PlacesUtils.unfiledBookmarksFolderId,
uri,
PlacesUtils.bookmarks.DEFAULT_INDEX,
"test bookmark " + i);
await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
url: uri,
title: "test bookmark " + i
});
}
Assert.ok(page_in_database(uri), "Page added");
}

Просмотреть файл

@ -1,3 +1,6 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const JS_NOW = Date.now();
const DB_NOW = JS_NOW * 1000;
const TEST_URI = uri("http://example.com/");
@ -64,11 +67,11 @@ add_task(async function remove_visits_outside_bookmarked_uri() {
}
await PlacesTestUtils.addVisits(visits);
info("Bookmark the URI.");
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
TEST_URI,
PlacesUtils.bookmarks.DEFAULT_INDEX,
"bookmark title");
await PlacesTestUtils.promiseAsyncUpdates();
await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
url: TEST_URI,
title: "bookmark title"
});
info("Remove visits using timerange outside the URI's visits.");
let filter = {
@ -160,11 +163,11 @@ add_task(async function remove_visits_bookmarked_uri() {
}
await PlacesTestUtils.addVisits(visits);
info("Bookmark the URI.");
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
TEST_URI,
PlacesUtils.bookmarks.DEFAULT_INDEX,
"bookmark title");
await PlacesTestUtils.promiseAsyncUpdates();
await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
url: TEST_URI,
title: "bookmark title"
});
info("Remove the 5 most recent visits.");
let filter = {
@ -248,10 +251,11 @@ add_task(async function remove_all_visits_bookmarked_uri() {
}
await PlacesTestUtils.addVisits(visits);
info("Bookmark the URI.");
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
TEST_URI,
PlacesUtils.bookmarks.DEFAULT_INDEX,
"bookmark title");
await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
url: TEST_URI,
title: "bookmark title"
});
await PlacesTestUtils.promiseAsyncUpdates();
let initialFrecency = frecencyForUrl(TEST_URI);

Просмотреть файл

@ -145,41 +145,43 @@ add_task(function visits_searchterm_query() {
});
});
add_task(function pages_searchterm_is_tag_query() {
add_task(async function pages_searchterm_is_tag_query() {
let [query, options] = newQueryWithOptions();
query.searchTerms = "test-tag";
testQueryContents(query, options, function(root) {
compareArrayToResult([], root);
gTestData.forEach(function(data) {
let uri = NetUtil.newURI(data.uri);
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
uri,
PlacesUtils.bookmarks.DEFAULT_INDEX,
data.title);
PlacesUtils.tagging.tagURI(uri, ["test-tag"]);
compareArrayToResult([data], root);
PlacesUtils.tagging.untagURI(uri, ["test-tag"]);
compareArrayToResult([], root);
let root;
testQueryContents(query, options, rv => root = rv);
compareArrayToResult([], root);
for (let data of gTestData) {
let uri = NetUtil.newURI(data.uri);
await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
url: uri,
title: data.title
});
});
PlacesUtils.tagging.tagURI(uri, ["test-tag"]);
compareArrayToResult([data], root);
PlacesUtils.tagging.untagURI(uri, ["test-tag"]);
compareArrayToResult([], root);
}
});
add_task(function visits_searchterm_is_tag_query() {
add_task(async function visits_searchterm_is_tag_query() {
let [query, options] = newQueryWithOptions();
query.searchTerms = "test-tag";
options.resultType = Ci.nsINavHistoryQueryOptions.RESULTS_AS_VISIT;
testQueryContents(query, options, function(root) {
compareArrayToResult([], root);
gTestData.forEach(function(data) {
let uri = NetUtil.newURI(data.uri);
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
uri,
PlacesUtils.bookmarks.DEFAULT_INDEX,
data.title);
PlacesUtils.tagging.tagURI(uri, ["test-tag"]);
compareArrayToResult([data], root);
PlacesUtils.tagging.untagURI(uri, ["test-tag"]);
compareArrayToResult([], root);
let root;
testQueryContents(query, options, rv => root = rv);
compareArrayToResult([], root);
for (let data of gTestData) {
let uri = NetUtil.newURI(data.uri);
await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
url: uri,
title: data.title
});
});
PlacesUtils.tagging.tagURI(uri, ["test-tag"]);
compareArrayToResult([data], root);
PlacesUtils.tagging.untagURI(uri, ["test-tag"]);
compareArrayToResult([], root);
}
});