зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1164159 - Send information about the default search engines through Telemetry, r=markh,gfritzsche.
This commit is contained in:
Родитель
1341bf71a3
Коммит
a9ec9ab1eb
|
@ -2818,6 +2818,75 @@ Engine.prototype = {
|
|||
return this.__id = this._file.path;
|
||||
},
|
||||
|
||||
// This indicates where we found the .xml file to load the engine,
|
||||
// and attempts to hide user-identifiable data (such as username).
|
||||
get _anonymizedLoadPath() {
|
||||
/* Examples of expected output:
|
||||
* jar:[app]/omni.ja!browser/engine.xml
|
||||
* 'browser' here is the name of the chrome package, not a folder.
|
||||
* [profile]/searchplugins/engine.xml
|
||||
* [distribution]/searchplugins/common/engine.xml
|
||||
* [other]/engine.xml
|
||||
*/
|
||||
|
||||
let leafName = this._getLeafName();
|
||||
if (!leafName)
|
||||
return "null";
|
||||
|
||||
let prefix = "", suffix = "";
|
||||
let file = this._file;
|
||||
if (!file) {
|
||||
let uri = this._uri;
|
||||
if (uri.schemeIs("chrome")) {
|
||||
let packageName = uri.hostPort;
|
||||
uri = gChromeReg.convertChromeURL(uri);
|
||||
if (uri instanceof Ci.nsINestedURI) {
|
||||
prefix = "jar:";
|
||||
suffix = "!" + packageName + "/" + leafName;
|
||||
uri = uri.innermostURI;
|
||||
}
|
||||
uri.QueryInterface(Ci.nsIFileURL)
|
||||
file = uri.file;
|
||||
} else {
|
||||
return "[" + uri.scheme + "]/" + leafName;
|
||||
}
|
||||
}
|
||||
|
||||
let id;
|
||||
let enginePath = file.path;
|
||||
|
||||
const NS_XPCOM_CURRENT_PROCESS_DIR = "XCurProcD";
|
||||
const NS_APP_USER_PROFILE_50_DIR = "ProfD";
|
||||
const XRE_APP_DISTRIBUTION_DIR = "XREAppDist";
|
||||
|
||||
const knownDirs = {
|
||||
app: NS_XPCOM_CURRENT_PROCESS_DIR,
|
||||
profile: NS_APP_USER_PROFILE_50_DIR,
|
||||
distribution: XRE_APP_DISTRIBUTION_DIR
|
||||
};
|
||||
|
||||
for (let key in knownDirs) {
|
||||
let path;
|
||||
try {
|
||||
path = getDir(knownDirs[key]).path;
|
||||
} catch(e) {
|
||||
// Getting XRE_APP_DISTRIBUTION_DIR throws during unit tests.
|
||||
continue;
|
||||
}
|
||||
if (enginePath.startsWith(path)) {
|
||||
id = "[" + key + "]" + enginePath.slice(path.length).replace(/\\/g, "/");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If the folder doesn't have a known ancestor, don't record its path to
|
||||
// avoid leaking user identifiable data.
|
||||
if (!id)
|
||||
id = "[other]/" + file.leafName;
|
||||
|
||||
return prefix + id + suffix;
|
||||
},
|
||||
|
||||
get _installLocation() {
|
||||
if (this.__installLocation === null) {
|
||||
if (!this._file) {
|
||||
|
@ -3200,6 +3269,10 @@ function SearchService() {
|
|||
SearchService.prototype = {
|
||||
classID: Components.ID("{7319788a-fe93-4db3-9f39-818cf08f4256}"),
|
||||
|
||||
get wrappedJSObject() {
|
||||
return this;
|
||||
},
|
||||
|
||||
// The current status of initialization. Note that it does not determine if
|
||||
// initialization is complete, only if an error has been encountered so far.
|
||||
_initRV: Cr.NS_OK,
|
||||
|
@ -4597,6 +4670,71 @@ SearchService.prototype = {
|
|||
notifyAction(this._currentEngine, SEARCH_ENGINE_CURRENT);
|
||||
},
|
||||
|
||||
getDefaultEngineInfo() {
|
||||
let result = {};
|
||||
|
||||
let engine;
|
||||
try {
|
||||
engine = this.defaultEngine;
|
||||
} catch(e) {
|
||||
// The defaultEngine getter will throw if there's no engine at all,
|
||||
// which shouldn't happen unless an add-on or a test deleted all of them.
|
||||
// Our preferences UI doesn't let users do that.
|
||||
Cu.reportError("getDefaultEngineInfo: No default engine");
|
||||
}
|
||||
|
||||
if (!engine) {
|
||||
result.name = "NONE";
|
||||
} else {
|
||||
if (engine.name)
|
||||
result.name = engine.name;
|
||||
|
||||
result.loadPath = engine._anonymizedLoadPath;
|
||||
|
||||
// For privacy, we only collect the submission URL for engines
|
||||
// from the application or distribution folder...
|
||||
let sendSubmissionURL =
|
||||
/^(?:jar:|\[app\]|\[distribution\])/.test(result.loadPath);
|
||||
|
||||
// ... or engines sorted by default near the top of the list.
|
||||
if (!sendSubmissionURL) {
|
||||
let extras =
|
||||
Services.prefs.getChildList(BROWSER_SEARCH_PREF + "order.extra.");
|
||||
|
||||
for (let prefName of extras) {
|
||||
try {
|
||||
if (result.name == Services.prefs.getCharPref(prefName)) {
|
||||
sendSubmissionURL = true;
|
||||
break;
|
||||
}
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
let prefNameBase = getGeoSpecificPrefName(BROWSER_SEARCH_PREF + "order");
|
||||
let i = 0;
|
||||
while (!sendSubmissionURL) {
|
||||
let prefName = prefNameBase + "." + (++i);
|
||||
let engineName = getLocalizedPref(prefName);
|
||||
if (!engineName)
|
||||
break;
|
||||
if (result.name == engineName) {
|
||||
sendSubmissionURL = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sendSubmissionURL) {
|
||||
let uri = engine._getURLOfType("text/html")
|
||||
.getSubmission("", engine, "searchbar").uri;
|
||||
uri.userPass = ""; // Avoid reporting a username or password.
|
||||
result.submissionURL = uri.spec;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* This map is built lazily after the available search engines change. It
|
||||
* allows quick parsing of an URL representing a search submission into the
|
||||
|
|
|
@ -880,6 +880,8 @@ EnvironmentCache.prototype = {
|
|||
this._currentEnvironment.settings = this._currentEnvironment.settings || {};
|
||||
// Update the search engine entry in the current environment.
|
||||
this._currentEnvironment.settings.defaultSearchEngine = this._getDefaultSearchEngine();
|
||||
this._currentEnvironment.settings.defaultSearchEngineData =
|
||||
Services.search.wrappedJSObject.getDefaultEngineInfo();
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -35,6 +35,11 @@ Structure::
|
|||
blocklistEnabled: <bool>, // true on failure
|
||||
isDefaultBrowser: <bool>, // null on failure, not available on Android
|
||||
defaultSearchEngine: <string>, // e.g. "yahoo"
|
||||
defaultSearchEngineData: {, // data about the current default engine
|
||||
name: <string>, // engine name, e.g. "Yahoo"; or "NONE" if no default
|
||||
loadPath: <string>, // where the engine line is located; missing if no default
|
||||
submissionURL: <string> // missing if no default or for user-installed engines
|
||||
},
|
||||
e10sEnabled: <bool>, // false on failure
|
||||
telemetryEnabled: <bool>, // false on failure
|
||||
locale: <string>, // e.g. "it", null on failure
|
||||
|
@ -197,6 +202,8 @@ Settings
|
|||
|
||||
defaultSearchEngine
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
Note: Deprecated, use defaultSearchEngineData instead.
|
||||
|
||||
Contains the string identifier or name of the default search engine provider. This will not be present in environment data collected before the Search Service initialization.
|
||||
|
||||
The special value ``NONE`` could occur if there is no default search engine.
|
||||
|
@ -204,3 +211,24 @@ The special value ``NONE`` could occur if there is no default search engine.
|
|||
The special value ``UNDEFINED`` could occur if a default search engine exists but its identifier could not be determined.
|
||||
|
||||
This field's contents are ``Services.search.defaultEngine.identifier`` (if defined) or ``"other-"`` + ``Services.search.defaultEngine.name`` if not. In other words, search engines without an ``.identifier`` are prefixed with ``other-``.
|
||||
|
||||
defaultSearchEngineData
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Contains data identifying the engine currently set as the default.
|
||||
|
||||
The object contains:
|
||||
|
||||
- a ``name`` property with the name of the engine, or ``NONE`` if no
|
||||
engine is currently set as the default.
|
||||
|
||||
- a ``loadPath`` property: an anonymized path of the engine xml file, e.g.
|
||||
jar:[app]/omni.ja!browser/engine.xml
|
||||
(where 'browser' is the name of the chrome package, not a folder)
|
||||
[profile]/searchplugins/engine.xml
|
||||
[distribution]/searchplugins/common/engine.xml
|
||||
[other]/engine.xml
|
||||
|
||||
- a ``submissionURL`` property with the HTTP url we would use to search.
|
||||
For privacy, we don't record this for user-installed engines.
|
||||
|
||||
``loadPath`` and ``submissionURL`` are not present if ``name`` is ``NONE``.
|
||||
|
|
|
@ -284,6 +284,7 @@ function checkSettingsSection(data) {
|
|||
// Check "defaultSearchEngine" separately, as it can either be undefined or string.
|
||||
if ("defaultSearchEngine" in data.settings) {
|
||||
checkString(data.settings.defaultSearchEngine);
|
||||
Assert.equal(typeof data.settings.defaultSearchEngineData, "object");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -994,6 +995,7 @@ add_task(function* test_defaultSearchEngine() {
|
|||
let data = TelemetryEnvironment.currentEnvironment;
|
||||
checkEnvironmentData(data);
|
||||
Assert.ok(!("defaultSearchEngine" in data.settings));
|
||||
Assert.ok(!("defaultSearchEngineData" in data.settings));
|
||||
|
||||
// Load the engines definitions from a custom JAR file: that's needed so that
|
||||
// the search provider reports an engine identifier.
|
||||
|
@ -1011,6 +1013,12 @@ add_task(function* test_defaultSearchEngine() {
|
|||
data = TelemetryEnvironment.currentEnvironment;
|
||||
checkEnvironmentData(data);
|
||||
Assert.equal(data.settings.defaultSearchEngine, "telemetrySearchIdentifier");
|
||||
let expectedSearchEngineData = {
|
||||
name: "telemetrySearchIdentifier",
|
||||
loadPath: "jar:[other]/searchTest.jar!testsearchplugin/telemetrySearchIdentifier.xml",
|
||||
submissionURL: "http://ar.wikipedia.org/wiki/%D8%AE%D8%A7%D8%B5:%D8%A8%D8%AD%D8%AB?search=&sourceid=Mozilla-search"
|
||||
};
|
||||
Assert.deepEqual(data.settings.defaultSearchEngineData, expectedSearchEngineData);
|
||||
|
||||
// Remove all the search engines.
|
||||
for (let engine of Services.search.getEngines()) {
|
||||
|
@ -1025,6 +1033,7 @@ add_task(function* test_defaultSearchEngine() {
|
|||
data = TelemetryEnvironment.currentEnvironment;
|
||||
checkEnvironmentData(data);
|
||||
Assert.equal(data.settings.defaultSearchEngine, "NONE");
|
||||
Assert.deepEqual(data.settings.defaultSearchEngineData, {name:"NONE"});
|
||||
|
||||
// Add a new search engine (this will have no engine identifier).
|
||||
const SEARCH_ENGINE_ID = "telemetry_default";
|
||||
|
@ -1044,6 +1053,12 @@ add_task(function* test_defaultSearchEngine() {
|
|||
|
||||
const EXPECTED_SEARCH_ENGINE = "other-" + SEARCH_ENGINE_ID;
|
||||
Assert.equal(data.settings.defaultSearchEngine, EXPECTED_SEARCH_ENGINE);
|
||||
|
||||
const EXPECTED_SEARCH_ENGINE_DATA = {
|
||||
name: "telemetry_default",
|
||||
loadPath: "[profile]/searchplugins/telemetrydefault.xml"
|
||||
};
|
||||
Assert.deepEqual(data.settings.defaultSearchEngineData, EXPECTED_SEARCH_ENGINE_DATA);
|
||||
TelemetryEnvironment.unregisterChangeListener("testWatch_SearchDefault");
|
||||
|
||||
// Define and reset the test preference.
|
||||
|
|
Загрузка…
Ссылка в новой задаче