Bug 672681 - Make nsIDownloadHistory::addDownload asynchronous. r=mak

This commit is contained in:
Paolo Amadini 2012-01-20 13:48:20 +01:00
Родитель cb9bb9c2f3
Коммит 70fdd3f42f
8 изменённых файлов: 308 добавлений и 188 удалений

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

@ -45,6 +45,7 @@
#include "History.h"
#include "nsNavHistory.h"
#include "nsNavBookmarks.h"
#include "nsAnnotationService.h"
#include "Helpers.h"
#include "PlaceInfo.h"
#include "VisitInfo.h"
@ -79,6 +80,11 @@ namespace places {
// Observer event fired after a visit has been registered in the DB.
#define URI_VISIT_SAVED "uri-visit-saved"
#define DESTINATIONFILEURI_ANNO \
NS_LITERAL_CSTRING("downloads/destinationFileURI")
#define DESTINATIONFILENAME_ANNO \
NS_LITERAL_CSTRING("downloads/destinationFileName")
////////////////////////////////////////////////////////////////////////////////
//// VisitData
@ -1255,6 +1261,109 @@ private:
nsRefPtr<History> mHistory;
};
/**
* Adds download-specific annotations to a download page.
*/
class SetDownloadAnnotations : public mozIVisitInfoCallback
{
public:
NS_DECL_ISUPPORTS
SetDownloadAnnotations(nsIURI* aDestination)
: mDestination(aDestination)
, mHistory(History::GetService())
{
MOZ_ASSERT(mDestination);
MOZ_ASSERT(NS_IsMainThread());
}
NS_IMETHOD HandleError(nsresult aResultCode, mozIPlaceInfo *aPlaceInfo)
{
// Just don't add the annotations in case the visit isn't added.
return NS_OK;
}
NS_IMETHOD HandleResult(mozIPlaceInfo *aPlaceInfo)
{
// Exit silently if the download destination is not a local file.
nsCOMPtr<nsIFileURL> destinationFileURL = do_QueryInterface(mDestination);
if (!destinationFileURL) {
return NS_OK;
}
nsCOMPtr<nsIURI> source;
nsresult rv = aPlaceInfo->GetUri(getter_AddRefs(source));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFile> destinationFile;
rv = destinationFileURL->GetFile(getter_AddRefs(destinationFile));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString destinationFileName;
rv = destinationFile->GetLeafName(destinationFileName);
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString destinationURISpec;
rv = destinationFileURL->GetSpec(destinationURISpec);
NS_ENSURE_SUCCESS(rv, rv);
// Use annotations for storing the additional download metadata.
nsAnnotationService* annosvc = nsAnnotationService::GetAnnotationService();
NS_ENSURE_TRUE(annosvc, NS_ERROR_OUT_OF_MEMORY);
rv = annosvc->SetPageAnnotationString(
source,
DESTINATIONFILEURI_ANNO,
NS_ConvertUTF8toUTF16(destinationURISpec),
0,
nsIAnnotationService::EXPIRE_WITH_HISTORY
);
NS_ENSURE_SUCCESS(rv, rv);
rv = annosvc->SetPageAnnotationString(
source,
DESTINATIONFILENAME_ANNO,
destinationFileName,
0,
nsIAnnotationService::EXPIRE_WITH_HISTORY
);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString title;
rv = aPlaceInfo->GetTitle(title);
NS_ENSURE_SUCCESS(rv, rv);
// In case we are downloading a file that does not correspond to a web
// page for which the title is present, we populate the otherwise empty
// history title with the name of the destination file, to allow it to be
// visible and searchable in history results.
if (title.IsEmpty()) {
rv = mHistory->SetURITitle(source, destinationFileName);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
NS_IMETHOD HandleCompletion()
{
return NS_OK;
}
private:
nsCOMPtr<nsIURI> mDestination;
/**
* Strong reference to the History object because we do not want it to
* disappear out from under us.
*/
nsRefPtr<History> mHistory;
};
NS_IMPL_ISUPPORTS1(
SetDownloadAnnotations,
mozIVisitInfoCallback
)
/**
* Stores an embed visit, and notifies observers.
*
@ -1905,6 +2014,65 @@ History::SetURITitle(nsIURI* aURI, const nsAString& aTitle)
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
//// nsIDownloadHistory
NS_IMETHODIMP
History::AddDownload(nsIURI* aSource, nsIURI* aReferrer,
PRTime aStartTime, nsIURI* aDestination)
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG(aSource);
if (mShuttingDown) {
return NS_OK;
}
if (XRE_GetProcessType() == GeckoProcessType_Content) {
NS_ERROR("Cannot add downloads to history from content process!");
return NS_ERROR_NOT_AVAILABLE;
}
nsNavHistory* navHistory = nsNavHistory::GetHistoryService();
NS_ENSURE_TRUE(navHistory, NS_ERROR_OUT_OF_MEMORY);
// Silently return if URI is something we shouldn't add to DB.
bool canAdd;
nsresult rv = navHistory->CanAddURI(aSource, &canAdd);
NS_ENSURE_SUCCESS(rv, rv);
if (!canAdd) {
return NS_OK;
}
nsTArray<VisitData> placeArray(1);
NS_ENSURE_TRUE(placeArray.AppendElement(VisitData(aSource, aReferrer)),
NS_ERROR_OUT_OF_MEMORY);
VisitData& place = placeArray.ElementAt(0);
NS_ENSURE_FALSE(place.spec.IsEmpty(), NS_ERROR_INVALID_ARG);
place.visitTime = aStartTime;
place.SetTransitionType(nsINavHistoryService::TRANSITION_DOWNLOAD);
mozIStorageConnection* dbConn = GetDBConn();
NS_ENSURE_STATE(dbConn);
nsCOMPtr<mozIVisitInfoCallback> callback = aDestination
? new SetDownloadAnnotations(aDestination)
: nsnull;
rv = InsertVisitedURIs::Start(dbConn, placeArray, callback);
NS_ENSURE_SUCCESS(rv, rv);
// Finally, notify that we've been visited.
nsCOMPtr<nsIObserverService> obsService =
mozilla::services::GetObserverService();
if (obsService) {
obsService->NotifyObservers(aSource, NS_LINK_VISITED_EVENT_TOPIC, nsnull);
}
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
//// mozIAsyncHistory
@ -2101,9 +2269,10 @@ History::Observe(nsISupports* aSubject, const char* aTopic,
////////////////////////////////////////////////////////////////////////////////
//// nsISupports
NS_IMPL_THREADSAFE_ISUPPORTS3(
NS_IMPL_THREADSAFE_ISUPPORTS4(
History
, IHistory
, nsIDownloadHistory
, mozIAsyncHistory
, nsIObserver
)

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

@ -42,6 +42,7 @@
#include "mozilla/IHistory.h"
#include "mozIAsyncHistory.h"
#include "nsIDownloadHistory.h"
#include "Database.h"
#include "mozilla/dom/Link.h"
@ -62,12 +63,14 @@ struct VisitData;
{0x0937a705, 0x91a6, 0x417a, {0x82, 0x92, 0xb2, 0x2e, 0xb1, 0x0d, 0xa8, 0x6c}}
class History : public IHistory
, public nsIDownloadHistory
, public mozIAsyncHistory
, public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IHISTORY
NS_DECL_NSIDOWNLOADHISTORY
NS_DECL_MOZIASYNCHISTORY
NS_DECL_NSIOBSERVER

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

@ -151,14 +151,6 @@ static const PRInt64 USECS_PER_DAY = LL_INIT(20, 500654080);
// character-set annotation
#define CHARSET_ANNO NS_LITERAL_CSTRING("URIProperties/characterSet")
// Download destination file URI annotation
#define DESTINATIONFILEURI_ANNO \
NS_LITERAL_CSTRING("downloads/destinationFileURI")
// Download destination file name annotation
#define DESTINATIONFILENAME_ANNO \
NS_LITERAL_CSTRING("downloads/destinationFileName")
// These macros are used when splitting history by date.
// These are the day containers and catch-all final container.
#define HISTORY_ADDITIONAL_DATE_CONT_NUM 3
@ -219,7 +211,6 @@ NS_IMPL_CLASSINFO(nsNavHistory, NULL, nsIClassInfo::SINGLETON,
NS_INTERFACE_MAP_BEGIN(nsNavHistory)
NS_INTERFACE_MAP_ENTRY(nsINavHistoryService)
NS_INTERFACE_MAP_ENTRY(nsIGlobalHistory2)
NS_INTERFACE_MAP_ENTRY(nsIDownloadHistory)
NS_INTERFACE_MAP_ENTRY(nsIBrowserHistory)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
@ -231,11 +222,10 @@ NS_INTERFACE_MAP_BEGIN(nsNavHistory)
NS_INTERFACE_MAP_END
// We don't care about flattening everything
NS_IMPL_CI_INTERFACE_GETTER4(
NS_IMPL_CI_INTERFACE_GETTER3(
nsNavHistory
, nsINavHistoryService
, nsIGlobalHistory2
, nsIDownloadHistory
, nsIBrowserHistory
)
@ -3783,80 +3773,6 @@ nsNavHistory::OnEndVacuum(bool aSucceeded)
}
////////////////////////////////////////////////////////////////////////////////
//// nsIDownloadHistory
NS_IMETHODIMP
nsNavHistory::AddDownload(nsIURI* aSource, nsIURI* aReferrer,
PRTime aStartTime, nsIURI* aDestination)
{
NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread");
NS_ENSURE_ARG(aSource);
// don't add when history is disabled and silently fail
if (IsHistoryDisabled())
return NS_OK;
PRInt64 visitID;
nsresult rv = AddVisit(aSource, aStartTime, aReferrer, TRANSITION_DOWNLOAD,
false, 0, &visitID);
NS_ENSURE_SUCCESS(rv, rv);
if (!aDestination) {
return NS_OK;
}
// Exit silently if the download destination is not a local file.
nsCOMPtr<nsIFileURL> destinationFileURL = do_QueryInterface(aDestination);
if (!destinationFileURL) {
return NS_OK;
}
nsCOMPtr<nsIFile> destinationFile;
rv = destinationFileURL->GetFile(getter_AddRefs(destinationFile));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString destinationFileName;
rv = destinationFile->GetLeafName(destinationFileName);
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString destinationURISpec;
rv = destinationFileURL->GetSpec(destinationURISpec);
NS_ENSURE_SUCCESS(rv, rv);
// Use annotations for storing the additional download metadata.
nsAnnotationService* annosvc = nsAnnotationService::GetAnnotationService();
NS_ENSURE_TRUE(annosvc, NS_ERROR_OUT_OF_MEMORY);
(void)annosvc->SetPageAnnotationString(
aSource,
DESTINATIONFILEURI_ANNO,
NS_ConvertUTF8toUTF16(destinationURISpec),
0,
nsIAnnotationService::EXPIRE_WITH_HISTORY
);
(void)annosvc->SetPageAnnotationString(
aSource,
DESTINATIONFILENAME_ANNO,
destinationFileName,
0,
nsIAnnotationService::EXPIRE_WITH_HISTORY
);
// In case we are downloading a file that does not correspond to a web
// page for which the title is present, we populate the otherwise empty
// history title with the name of the destination file, to allow it to be
// visible and searchable in history results.
nsAutoString title;
if (NS_SUCCEEDED(GetPageTitle(aSource, title)) && title.IsEmpty()) {
(void)SetPageTitle(aSource, destinationFileName);
}
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
//// nsPIPlacesDatabase

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

@ -47,7 +47,6 @@
#include "nsPIPlacesHistoryListenersNotifier.h"
#include "nsIBrowserHistory.h"
#include "nsIGlobalHistory.h"
#include "nsIDownloadHistory.h"
#include "nsINavBookmarksService.h"
#include "nsIPrivateBrowsingService.h"
#include "nsIFaviconService.h"
@ -109,7 +108,6 @@ class nsNavHistory : public nsSupportsWeakReference
, public nsINavHistoryService
, public nsIObserver
, public nsIBrowserHistory
, public nsIDownloadHistory
, public nsPIPlacesDatabase
, public nsPIPlacesHistoryListenersNotifier
, public mozIStorageVacuumParticipant
@ -122,7 +120,6 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSINAVHISTORYSERVICE
NS_DECL_NSIGLOBALHISTORY2
NS_DECL_NSIDOWNLOADHISTORY
NS_DECL_NSIBROWSERHISTORY
NS_DECL_NSIOBSERVER
NS_DECL_NSPIPLACESDATABASE

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

@ -64,7 +64,6 @@ const mozilla::Module::CIDEntry kPlacesCIDs[] = {
const mozilla::Module::ContractIDEntry kPlacesContracts[] = {
{ NS_NAVHISTORYSERVICE_CONTRACTID, &kNS_NAVHISTORYSERVICE_CID },
{ NS_GLOBALHISTORY2_CONTRACTID, &kNS_NAVHISTORYSERVICE_CID },
{ NS_DOWNLOADHISTORY_CONTRACTID, &kNS_NAVHISTORYSERVICE_CID },
{ NS_ANNOTATIONSERVICE_CONTRACTID, &kNS_ANNOTATIONSERVICE_CID },
{ NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "moz-anno", &kNS_ANNOPROTOCOLHANDLER_CID },
{ NS_NAVBOOKMARKSSERVICE_CONTRACTID, &kNS_NAVBOOKMARKSSERVICE_CID },
@ -74,6 +73,7 @@ const mozilla::Module::ContractIDEntry kPlacesContracts[] = {
{ NS_IHISTORY_CONTRACTID, &kNS_ANDROIDHISTORY_CID },
#else
{ NS_IHISTORY_CONTRACTID, &kNS_HISTORYSERVICE_CID },
{ NS_DOWNLOADHISTORY_CONTRACTID, &kNS_HISTORYSERVICE_CID },
#endif
{ NS_PLACESIMPORTEXPORTSERVICE_CONTRACTID, &kNS_PLACESIMPORTEXPORTSERVICE_CID },
{ NULL }

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

@ -736,3 +736,24 @@ function do_compare_arrays(a1, a2, sorted)
a2.filter(function (e) a1.indexOf(e) == -1).length == 0;
}
}
/**
* Generic nsINavHistoryObserver that doesn't implement anything, but provides
* dummy methods to prevent errors about an object not having a certain method.
*/
function NavHistoryObserver() {}
NavHistoryObserver.prototype = {
onBeginUpdateBatch: function () {},
onEndUpdateBatch: function () {},
onVisit: function () {},
onTitleChanged: function () {},
onBeforeDeleteURI: function () {},
onDeleteURI: function () {},
onClearHistory: function () {},
onPageChanged: function () {},
onDeleteVisits: function () {},
QueryInterface: XPCOMUtils.generateQI([
Ci.nsINavHistoryObserver,
])
};

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

@ -40,29 +40,6 @@ function VisitInfo(aTransitionType,
this.visitDate = aVisitTime || Date.now() * 1000;
}
/**
* Generic nsINavHistoryObserver that doesn't implement anything, but provides
* dummy methods to prevent errors about an object not having a certain method.
*/
function NavHistoryObserver()
{
}
NavHistoryObserver.prototype =
{
onBeginUpdateBatch: function() { },
onEndUpdateBatch: function() { },
onVisit: function() { },
onTitleChanged: function() { },
onBeforeDeleteURI: function() { },
onDeleteURI: function() { },
onClearHistory: function() { },
onPageChanged: function() { },
onDeleteVisits: function() { },
QueryInterface: XPCOMUtils.generateQI([
Ci.nsINavHistoryObserver,
]),
};
/**
* Listens for a title change notification, and calls aCallback when it gets it.
*

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

@ -8,30 +8,34 @@
////////////////////////////////////////////////////////////////////////////////
/// Globals
const downloadHistory = Cc["@mozilla.org/browser/download-history;1"]
.getService(Ci.nsIDownloadHistory);
XPCOMUtils.defineLazyServiceGetter(this, "gDownloadHistory",
"@mozilla.org/browser/download-history;1",
"nsIDownloadHistory");
const TEST_URI = NetUtil.newURI("http://google.com/");
const REFERRER_URI = NetUtil.newURI("http://yahoo.com");
XPCOMUtils.defineLazyServiceGetter(this, "gHistory",
"@mozilla.org/browser/history;1",
"mozIAsyncHistory");
const NS_LINK_VISITED_EVENT_TOPIC = "link-visited";
const ENABLE_HISTORY_PREF = "places.history.enabled";
const PB_KEEP_SESSION_PREF = "browser.privatebrowsing.keep_current_session";
const DOWNLOAD_URI = NetUtil.newURI("http://www.example.com/");
const REFERRER_URI = NetUtil.newURI("http://www.example.org/");
const PRIVATE_URI = NetUtil.newURI("http://www.example.net/");
/**
* Sets a flag when the link visited notification is received.
* Waits for the first visit notification to be received.
*
* @param aCallback
* This function is called with the same arguments of onVisit.
*/
const visitedObserver = {
topicReceived: false,
observe: function VO_observe(aSubject, aTopic, aData)
{
this.topicReceived = true;
}
};
Services.obs.addObserver(visitedObserver, NS_LINK_VISITED_EVENT_TOPIC, false);
do_register_cleanup(function() {
Services.obs.removeObserver(visitedObserver, NS_LINK_VISITED_EVENT_TOPIC);
});
function waitForOnVisit(aCallback) {
let historyObserver = {
__proto__: NavHistoryObserver.prototype,
onVisit: function HO_onVisit() {
PlacesUtils.history.removeObserver(this);
aCallback.apply(null, arguments);
}
};
PlacesUtils.history.addObserver(historyObserver, false);
}
/**
* Checks to see that a URI is in the database.
@ -59,15 +63,6 @@ function uri_in_db(aURI, aExpected)
root.containerOpen = false;
}
/**
* Cleanup function called by each individual test if necessary.
*/
function cleanup_and_run_next_test()
{
visitedObserver.topicReceived = false;
waitForClearHistory(run_next_test);
}
////////////////////////////////////////////////////////////////////////////////
/// Tests
@ -79,72 +74,113 @@ function run_test()
add_test(function test_dh_is_from_places()
{
// Test that this nsIDownloadHistory is the one places implements.
do_check_true(downloadHistory instanceof Ci.nsINavHistoryService);
do_check_true(gDownloadHistory instanceof Ci.mozIAsyncHistory);
run_next_test();
waitForClearHistory(run_next_test);
});
add_test(function test_dh_addDownload()
{
// Sanity checks.
uri_in_db(TEST_URI, false);
uri_in_db(REFERRER_URI, false);
waitForOnVisit(function DHAD_onVisit(aURI) {
do_check_true(aURI.equals(DOWNLOAD_URI));
downloadHistory.addDownload(TEST_URI, REFERRER_URI, Date.now() * 1000);
// Verify that the URI is already available in results at this time.
uri_in_db(DOWNLOAD_URI, true);
do_check_true(visitedObserver.topicReceived);
uri_in_db(TEST_URI, true);
uri_in_db(REFERRER_URI, true);
waitForClearHistory(run_next_test);
});
cleanup_and_run_next_test();
gDownloadHistory.addDownload(DOWNLOAD_URI, null, Date.now() * 1000);
});
add_test(function test_dh_privateBrowsing()
add_test(function test_dh_addDownload_referrer()
{
// Sanity checks.
uri_in_db(TEST_URI, false);
uri_in_db(REFERRER_URI, false);
waitForOnVisit(function DHAD_prepareReferrer(aURI, aVisitID) {
do_check_true(aURI.equals(REFERRER_URI));
let referrerVisitId = aVisitID;
var pb = null;
try {
// PrivateBrowsing component is not always available to Places implementers.
pb = Cc["@mozilla.org/privatebrowsing;1"].
getService(Ci.nsIPrivateBrowsingService);
} catch (ex) {
// Skip this test.
waitForOnVisit(function DHAD_onVisit(aURI, aVisitID, aTime, aSessionID,
aReferringID) {
do_check_true(aURI.equals(DOWNLOAD_URI));
do_check_eq(aReferringID, referrerVisitId);
// Verify that the URI is already available in results at this time.
uri_in_db(DOWNLOAD_URI, true);
waitForClearHistory(run_next_test);
});
gDownloadHistory.addDownload(DOWNLOAD_URI, REFERRER_URI, Date.now() * 1000);
});
// Note that we don't pass the optional callback argument here because we must
// ensure that we receive the onVisit notification before we call addDownload.
gHistory.updatePlaces({
uri: REFERRER_URI,
visits: [{
transitionType: Ci.nsINavHistoryService.TRANSITION_TYPED,
visitDate: Date.now() * 1000
}]
});
});
add_test(function test_dh_addDownload_privateBrowsing()
{
if (!("@mozilla.org/privatebrowsing;1" in Cc)) {
todo(false, "PB service is not available, bail out");
run_next_test();
return;
}
Services.prefs.setBoolPref(PB_KEEP_SESSION_PREF, true);
waitForOnVisit(function DHAD_onVisit(aURI) {
// We should only receive the notification for the non-private URI. This
// test is based on the assumption that visit notifications are received in
// the same order of the addDownload calls, which is currently true because
// database access is serialized on the same worker thread.
do_check_true(aURI.equals(DOWNLOAD_URI));
uri_in_db(DOWNLOAD_URI, true);
uri_in_db(PRIVATE_URI, false);
waitForClearHistory(run_next_test);
});
let pb = Cc["@mozilla.org/privatebrowsing;1"]
.getService(Ci.nsIPrivateBrowsingService);
Services.prefs.setBoolPref("browser.privatebrowsing.keep_current_session",
true);
pb.privateBrowsingEnabled = true;
gDownloadHistory.addDownload(PRIVATE_URI, REFERRER_URI, Date.now() * 1000);
downloadHistory.addDownload(TEST_URI, REFERRER_URI, Date.now() * 1000);
do_check_false(visitedObserver.topicReceived);
uri_in_db(TEST_URI, false);
uri_in_db(REFERRER_URI, false);
// The addDownload functions calls CanAddURI synchronously, thus we can exit
// Private Browsing Mode immediately.
pb.privateBrowsingEnabled = false;
cleanup_and_run_next_test();
Services.prefs.clearUserPref("browser.privatebrowsing.keep_current_session");
gDownloadHistory.addDownload(DOWNLOAD_URI, REFERRER_URI, Date.now() * 1000);
});
add_test(function test_dh_disabledHistory()
add_test(function test_dh_addDownload_disabledHistory()
{
// Sanity checks.
uri_in_db(TEST_URI, false);
uri_in_db(REFERRER_URI, false);
waitForOnVisit(function DHAD_onVisit(aURI) {
// We should only receive the notification for the non-private URI. This
// test is based on the assumption that visit notifications are received in
// the same order of the addDownload calls, which is currently true because
// database access is serialized on the same worker thread.
do_check_true(aURI.equals(DOWNLOAD_URI));
// Disable history.
Services.prefs.setBoolPref(ENABLE_HISTORY_PREF, false);
uri_in_db(DOWNLOAD_URI, true);
uri_in_db(PRIVATE_URI, false);
downloadHistory.addDownload(TEST_URI, REFERRER_URI, Date.now() * 1000);
waitForClearHistory(run_next_test);
});
do_check_false(visitedObserver.topicReceived);
uri_in_db(TEST_URI, false);
uri_in_db(REFERRER_URI, false);
Services.prefs.setBoolPref("places.history.enabled", false);
gDownloadHistory.addDownload(PRIVATE_URI, REFERRER_URI, Date.now() * 1000);
Services.prefs.setBoolPref(ENABLE_HISTORY_PREF, true);
cleanup_and_run_next_test();
// The addDownload functions calls CanAddURI synchronously, thus we can reset
// the preference immediately.
Services.prefs.clearUserPref("places.history.enabled");
gDownloadHistory.addDownload(DOWNLOAD_URI, REFERRER_URI, Date.now() * 1000);
});
/**
@ -170,7 +206,7 @@ add_test(function test_dh_details()
PlacesUtils.annotations.removeObserver(annoObserver);
PlacesUtils.history.removeObserver(historyObserver);
cleanup_and_run_next_test();
waitForClearHistory(run_next_test);
}
};
@ -214,17 +250,18 @@ add_test(function test_dh_details()
onDeleteURI: function() {},
onClearHistory: function() {},
onPageChanged: function() {},
onDeleteVisits: function() {}
onDeleteVisits: function() {}
};
PlacesUtils.annotations.addObserver(annoObserver, false);
PlacesUtils.history.addObserver(historyObserver, false);
// Both null values and remote URIs should not cause errors.
downloadHistory.addDownload(SOURCE_URI, null, Date.now() * 1000);
downloadHistory.addDownload(SOURCE_URI, null, Date.now() * 1000, null);
downloadHistory.addDownload(SOURCE_URI, null, Date.now() * 1000, REMOTE_URI);
gDownloadHistory.addDownload(SOURCE_URI, null, Date.now() * 1000);
gDownloadHistory.addDownload(SOURCE_URI, null, Date.now() * 1000, null);
gDownloadHistory.addDownload(SOURCE_URI, null, Date.now() * 1000, REMOTE_URI);
// Valid local file URIs should cause the download details to be saved.
downloadHistory.addDownload(SOURCE_URI, null, Date.now() * 1000, destFileUri);
gDownloadHistory.addDownload(SOURCE_URI, null, Date.now() * 1000,
destFileUri);
});