Bug 725943 - Refactor nsSearchService to generalize use of Lazy. r=MattN

This commit is contained in:
Raymond Lee 2013-10-29 15:48:33 +08:00
parent a4810a7316
commit 74653a35e0
3 changed files with 122 additions and 52 deletions

View File

@ -1190,8 +1190,8 @@ Engine.prototype = {
_updateURL: null,
// The url to check for a new icon
_iconUpdateURL: null,
// A reference to the timer used for lazily serializing the engine to file
_serializeTimer: null,
/* Deferred serialization task. */
_lazySerializeTask: null,
/**
* Retrieves the data from the engine's file. If the engine's dataType is
@ -2244,28 +2244,15 @@ Engine.prototype = {
return doc;
},
_lazySerializeToFile: function SRCH_ENG_serializeToFile() {
if (this._serializeTimer) {
// Reset the timer
this._serializeTimer.delay = LAZY_SERIALIZE_DELAY;
} else {
this._serializeTimer = Cc["@mozilla.org/timer;1"].
createInstance(Ci.nsITimer);
var timerCallback = {
self: this,
notify: function SRCH_ENG_notify(aTimer) {
try {
this.self._serializeToFile();
} catch (ex) {
LOG("Serialization from timer callback failed:\n" + ex);
}
this.self._serializeTimer = null;
}
};
this._serializeTimer.initWithCallback(timerCallback,
LAZY_SERIALIZE_DELAY,
Ci.nsITimer.TYPE_ONE_SHOT);
get lazySerializeTask() {
if (!this._lazySerializeTask) {
let task = function taskCallback() {
this._serializeToFile();
}.bind(this);
this._lazySerializeTask = new DeferredTask(task, LAZY_SERIALIZE_DELAY);
}
return this._lazySerializeTask;
},
/**
@ -2296,6 +2283,9 @@ Engine.prototype = {
}
closeSafeOutputStream(fos);
Services.obs.notifyObservers(null, SEARCH_SERVICE_TOPIC,
"write-engine-to-disk-complete");
},
/**
@ -2541,7 +2531,7 @@ Engine.prototype = {
url.addParam(aName, aValue);
// Serialize the changes to file lazily
this._lazySerializeToFile();
this.lazySerializeTask.start();
},
#ifdef ANDROID
@ -2895,25 +2885,17 @@ SearchService.prototype = {
return false;
},
_batchTimer: null,
_batchCacheInvalidation: function SRCH_SVC__batchCacheInvalidation() {
let callback = {
self: this,
notify: function SRCH_SVC_batchTimerNotify(aTimer) {
LOG("_batchCacheInvalidation: Invalidating engine cache");
this.self._buildCache();
this.self._batchTimer = null;
}
};
if (!this._batchTimer) {
this._batchTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
this._batchTimer.initWithCallback(callback, CACHE_INVALIDATION_DELAY,
Ci.nsITimer.TYPE_ONE_SHOT);
} else {
this._batchTimer.delay = CACHE_INVALIDATION_DELAY;
LOG("_batchCacheInvalidation: Batch timer reset");
_batchTask: null,
get batchTask() {
if (!this._batchTask) {
let task = function taskCallback() {
LOG("batchTask: Invalidating engine cache");
this._buildCache();
}.bind(this);
this._batchTask = new DeferredTask(task, CACHE_INVALIDATION_DELAY);
}
return this._batchTask;
},
_addEngineToStore: function SRCH_SVC_addEngineToStore(aEngine) {
@ -3403,7 +3385,7 @@ SearchService.prototype = {
engine._initFromMetadata(aName, aIconURL, aAlias, aDescription,
aMethod, aTemplate);
this._addEngineToStore(engine);
this._batchCacheInvalidation();
this.batchTask.start();
},
addEngine: function SRCH_SVC_addEngine(aEngineURL, aDataType, aIconURL,
@ -3466,10 +3448,10 @@ SearchService.prototype = {
engineToRemove.hidden = true;
engineToRemove.alias = null;
} else {
// Cancel the lazy serialization timer if it's running
if (engineToRemove._serializeTimer) {
engineToRemove._serializeTimer.cancel();
engineToRemove._serializeTimer = null;
// Cancel the serialized task if it's running
if (engineToRemove._lazySerializeTask) {
engineToRemove._lazySerializeTask.cancel();
engineToRemove._lazySerializeTask = null;
}
// Remove the engine file from disk (this might throw)
@ -3667,21 +3649,20 @@ SearchService.prototype = {
LOG("nsSearchService::observe: setting current");
this.currentEngine = aEngine;
}
this._batchCacheInvalidation();
this.batchTask.start();
break;
case SEARCH_ENGINE_CHANGED:
case SEARCH_ENGINE_REMOVED:
this._batchCacheInvalidation();
this.batchTask.start();
break;
}
break;
case QUIT_APPLICATION_TOPIC:
this._removeObservers();
if (this._batchTimer) {
if (this._batchTask) {
// Flush to disk immediately
this._batchTimer.cancel();
this._buildCache();
this._batchTask.flush();
}
engineMetadataService.flush();
break;

View File

@ -0,0 +1,88 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/*
* test_serialize_file: Add test engines
*
* Ensure that :
* - File is created.
* - File size is bigger than 0.
* - lazySerializeTask updates the file.
*/
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://testing-common/httpd.js");
Cu.import("resource://gre/modules/NetUtil.jsm");
add_test(function test_batchTask() {
let observer = function(aSubject, aTopic, aData) {
if (aTopic == "browser-search-engine-modified" && aData == "engine-loaded") {
let engine1 = Services.search.getEngineByName("Test search engine");
let engine2 = Services.search.getEngineByName("Sherlock test search engine");
if (engine1 && engine2) {
Services.obs.removeObserver(observer, aTopic);
// Test that files are written correctly.
let engineFile1 = engine1.wrappedJSObject._file;
let engineFile2 = engine2.wrappedJSObject._file;
do_check_true(engineFile1.exists());
do_check_true(engineFile2.exists());
do_check_neq(engineFile1.fileSize, 0);
do_check_neq(engineFile2.fileSize, 0);
run_next_test();
}
}
}
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
Services.search.addEngine("http://localhost:4444/data/engine.xml",
Ci.nsISearchEngine.DATA_XML, null, false);
Services.search.addEngine("http://localhost:4444/data/engine.src",
Ci.nsISearchEngine.DATA_TEXT,
"http://localhost:4444/data/ico-size-16x16-png.ico",
false);
});
add_test(function test_addParam() {
let engine = Services.search.getEngineByName("Test search engine");
engine.addParam("param-name", "param-value", null);
function readAsyncFile(aFile, aCallback) {
NetUtil.asyncFetch(aFile, function(inputStream, status) {
do_check_true(Components.isSuccessCode(status));
let data = NetUtil.readInputStreamToString(inputStream, inputStream.available());
aCallback(data);
});
}
let observer = function(aSubject, aTopic, aData) {
if (aTopic == "browser-search-service" &&
aData == "write-engine-to-disk-complete") {
Services.obs.removeObserver(observer, aTopic);
let engineFile = engine.wrappedJSObject._file;
readAsyncFile(engineFile, function(engineData) {
do_check_true(engineData.indexOf("param-name") > 0);
run_next_test();
});
}
}
Services.obs.addObserver(observer, "browser-search-service", false);
});
function run_test() {
updateAppInfo();
let httpServer = new HttpServer();
httpServer.start(4444);
httpServer.registerDirectory("/", do_get_cwd());
do_register_cleanup(function cleanup() {
httpServer.stop(function() {});
});
run_next_test();
}

View File

@ -28,3 +28,4 @@ support-files =
[test_prefSync.js]
[test_notifications.js]
[test_addEngine_callback.js]
[test_serialize_file.js]