import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,11 @@
# 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/.
include $(topsrcdir)/config/rules.mk
# need the executable for running the xpcshell unit tests
ifneq (,$(SIMPLE_PROGRAMS))
libs::
$(INSTALL) $(SIMPLE_PROGRAMS) $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit
endif

View file

@ -0,0 +1,24 @@
#include <stdio.h>
#include "prenv.h"
int main(int argc, char* argv[])
{
if (argc != 2)
return 1;
const char* value = PR_GetEnv("WRITE_ARGUMENT_FILE");
if (!value)
return 2;
FILE* outfile = fopen(value, "w");
if (!outfile)
return 3;
// We only need to write out the first argument (no newline).
fputs(argv[argc -1], outfile);
fclose(outfile);
return 0;
}

View file

@ -0,0 +1,8 @@
[DEFAULT]
head = head.js
support-files =
protocolHandler.html
[browser_download_always_ask_preferred_app.js]
[browser_remember_download_option.js]
[browser_web_protocol_handlers.js]

View file

@ -0,0 +1,19 @@
add_task(function*() {
// Create mocked objects for test
let launcher = createMockedObjects(false);
// Open helper app dialog with mocked launcher
let dlg = yield* openHelperAppDialog(launcher);
let doc = dlg.document;
let location = doc.getElementById("source");
let expectedValue = launcher.source.prePath;
if (location.value != expectedValue) {
info("Waiting for dialog to be populated.");
yield BrowserTestUtils.waitForAttribute("value", location, expectedValue);
}
is(doc.getElementById("mode").selectedItem.id, "open", "Should be opening the file.");
ok(!dlg.document.getElementById("openHandler").selectedItem.hidden,
"Should not have selected a hidden item.");
let helperAppDialogHiddenPromise = BrowserTestUtils.windowClosed(dlg);
doc.documentElement.cancelDialog();
yield helperAppDialogHiddenPromise;
});

View file

@ -0,0 +1,49 @@
add_task(function*() {
// create mocked objects
let launcher = createMockedObjects(true);
// open helper app dialog with mocked launcher
let dlg = yield* openHelperAppDialog(launcher);
let doc = dlg.document;
// Set remember choice
ok(!doc.getElementById("rememberChoice").checked,
"Remember choice checkbox should be not checked.");
doc.getElementById("rememberChoice").checked = true;
// Make sure the mock handler information is not in nsIHandlerService
ok(!gHandlerSvc.exists(launcher.MIMEInfo), "Should not be in nsIHandlerService.");
// close the dialog by pushing the ok button.
let dialogClosedPromise = BrowserTestUtils.windowClosed(dlg);
// Make sure the ok button is enabled, since the ok button might be disabled by
// EnableDelayHelper mechanism. Please refer the detailed
// https://dxr.mozilla.org/mozilla-central/source/toolkit/components/prompts/src/SharedPromptUtils.jsm#53
doc.documentElement.getButton("accept").disabled = false;
doc.documentElement.acceptDialog();
yield dialogClosedPromise;
// check the mocked handler information is saved in nsIHandlerService
ok(gHandlerSvc.exists(launcher.MIMEInfo), "Should be in nsIHandlerService.");
// check the extension.
var mimeType = gHandlerSvc.getTypeFromExtension("abc");
is(mimeType, launcher.MIMEInfo.type, "Got correct mime type.");
var handlerInfos = gHandlerSvc.enumerate();
while (handlerInfos.hasMoreElements()) {
let handlerInfo = handlerInfos.getNext().QueryInterface(Ci.nsIHandlerInfo);
if (handlerInfo.type == launcher.MIMEInfo.type) {
// check the alwaysAskBeforeHandling
ok(!handlerInfo.alwaysAskBeforeHandling,
"Should turn off the always ask.");
// check the preferredApplicationHandler
ok(handlerInfo.preferredApplicationHandler.equals(
launcher.MIMEInfo.preferredApplicationHandler),
"Should be equal to the mockedHandlerApp.");
// check the perferredAction
is(handlerInfo.preferredAction, launcher.MIMEInfo.preferredAction,
"Should be equal to Ci.nsIHandlerInfo.useHelperApp.");
break;
}
}
});

View file

@ -0,0 +1,76 @@
let testURL = "http://example.com/browser/" +
"uriloader/exthandler/tests/mochitest/protocolHandler.html";
add_task(function*() {
// Load a page registering a protocol handler.
let browser = gBrowser.selectedBrowser;
browser.loadURI(testURL);
yield BrowserTestUtils.browserLoaded(browser, testURL);
// Register the protocol handler by clicking the notificationbar button.
let notificationValue = "Protocol Registration: testprotocol";
let getNotification = () =>
gBrowser.getNotificationBox().getNotificationWithValue(notificationValue);
yield BrowserTestUtils.waitForCondition(getNotification);
let notification = getNotification();
let button =
notification.getElementsByClassName("notification-button-default")[0];
ok(button, "got registration button");
button.click();
// Set the new handler as default.
const protoSvc = Cc["@mozilla.org/uriloader/external-protocol-service;1"].
getService(Ci.nsIExternalProtocolService);
let protoInfo = protoSvc.getProtocolHandlerInfo("testprotocol");
is(protoInfo.preferredAction, protoInfo.useHelperApp,
"using a helper application is the preferred action");
ok(!protoInfo.preferredApplicationHandler, "no preferred handler is set");
let handlers = protoInfo.possibleApplicationHandlers;
is(1, handlers.length, "only one handler registered for testprotocol");
let handler = handlers.queryElementAt(0, Ci.nsIHandlerApp);
ok(handler instanceof Ci.nsIWebHandlerApp, "the handler is a web handler");
is(handler.uriTemplate, "https://example.com/foobar?uri=%s",
"correct url template")
protoInfo.preferredApplicationHandler = handler;
protoInfo.alwaysAskBeforeHandling = false;
const handlerSvc = Cc["@mozilla.org/uriloader/handler-service;1"].
getService(Ci.nsIHandlerService);
handlerSvc.store(protoInfo);
// Middle-click a testprotocol link and check the new tab is correct
let link = "#link";
const expectedURL = "https://example.com/foobar?uri=testprotocol%3Atest";
let promiseTabOpened =
BrowserTestUtils.waitForNewTab(gBrowser, expectedURL);
yield BrowserTestUtils.synthesizeMouseAtCenter(link, {button: 1}, browser);
let tab = yield promiseTabOpened;
gBrowser.selectedTab = tab;
is(gURLBar.value, expectedURL,
"the expected URL is displayed in the location bar");
yield BrowserTestUtils.removeTab(tab);
// Shift-click the testprotocol link and check the new window.
let newWindowPromise = BrowserTestUtils.waitForNewWindow();
yield BrowserTestUtils.synthesizeMouseAtCenter(link, {shiftKey: true},
browser);
let win = yield newWindowPromise;
yield BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
yield BrowserTestUtils.waitForCondition(() => win.gBrowser.currentURI.spec == expectedURL);
is(win.gURLBar.value, expectedURL,
"the expected URL is displayed in the location bar");
yield BrowserTestUtils.closeWindow(win);
// Click the testprotocol link and check the url in the current tab.
let loadPromise = BrowserTestUtils.browserLoaded(browser);
yield BrowserTestUtils.synthesizeMouseAtCenter(link, {}, browser);
yield loadPromise;
yield BrowserTestUtils.waitForCondition(() => gURLBar.value != testURL);
is(gURLBar.value, expectedURL,
"the expected URL is displayed in the location bar");
// Cleanup.
protoInfo.preferredApplicationHandler = null;
handlers.removeElementAt(0);
handlerSvc.store(protoInfo);
});

View file

@ -0,0 +1,30 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Pseudo Web Handler App</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload="onLoad()">
Pseudo Web Handler App
<script class="testbody" type="text/javascript">
<![CDATA[
function onLoad() {
// if we have a window.opener, this must be the windowContext
// instance of this test. check that we got the URI right and clean up.
if (window.opener) {
window.opener.is(location.search,
"?uri=" + encodeURIComponent(window.opener.testURI),
"uri passed to web-handler app");
window.opener.SimpleTest.finish();
}
window.close();
}
]]>
</script>
</body>
</html>

View file

@ -0,0 +1,110 @@
/* 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/. */
// handlerApp.xhtml grabs this for verification purposes via window.opener
var testURI = "webcal://127.0.0.1/rheeeeet.html";
const Cc = SpecialPowers.Cc;
function test() {
// set up the web handler object
var webHandler = Cc["@mozilla.org/uriloader/web-handler-app;1"].
createInstance(SpecialPowers.Ci.nsIWebHandlerApp);
webHandler.name = "Test Web Handler App";
webHandler.uriTemplate =
"http://mochi.test:8888/tests/uriloader/exthandler/tests/mochitest/" +
"handlerApp.xhtml?uri=%s";
// set up the uri to test with
var ioService = Cc["@mozilla.org/network/io-service;1"].
getService(SpecialPowers.Ci.nsIIOService);
var uri = ioService.newURI(testURI, null, null);
// create a window, and launch the handler in it
var newWindow = window.open("", "handlerWindow", "height=300,width=300");
var windowContext =
SpecialPowers.wrap(newWindow).QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor).
getInterface(SpecialPowers.Ci.nsIWebNavigation).
QueryInterface(SpecialPowers.Ci.nsIDocShell);
webHandler.launchWithURI(uri, windowContext);
// if we get this far without an exception, we've at least partly passed
// (remaining check in handlerApp.xhtml)
ok(true, "webHandler launchWithURI (existing window/tab) started");
// make the web browser launch in its own window/tab
webHandler.launchWithURI(uri);
// if we get this far without an exception, we've passed
ok(true, "webHandler launchWithURI (new window/tab) test started");
// set up the local handler object
var localHandler = Cc["@mozilla.org/uriloader/local-handler-app;1"].
createInstance(SpecialPowers.Ci.nsILocalHandlerApp);
localHandler.name = "Test Local Handler App";
// get a local app that we know will be there and do something sane
var osString = Cc["@mozilla.org/xre/app-info;1"].
getService(SpecialPowers.Ci.nsIXULRuntime).OS;
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
getService(SpecialPowers.Ci.nsIDirectoryServiceProvider);
if (osString == "WINNT") {
var windowsDir = dirSvc.getFile("WinD", {});
var exe = windowsDir.clone().QueryInterface(SpecialPowers.Ci.nsILocalFile);
exe.appendRelativePath("SYSTEM32\\HOSTNAME.EXE");
} else if (osString == "Darwin") {
var localAppsDir = dirSvc.getFile("LocApp", {});
exe = localAppsDir.clone();
exe.append("iCal.app"); // lingers after the tests finish, but this seems
// seems better than explicitly killing it, since
// developers who run the tests locally may well
// information in their running copy of iCal
if (navigator.userAgent.match(/ SeaMonkey\//)) {
// SeaMonkey tinderboxes don't like to have iCal lingering (and focused)
// on next test suite run(s).
todo(false, "On SeaMonkey, testing OS X as generic Unix. (Bug 749872)");
// assume a generic UNIX variant
exe = Cc["@mozilla.org/file/local;1"].
createInstance(SpecialPowers.Ci.nsILocalFile);
exe.initWithPath("/bin/echo");
}
} else {
// assume a generic UNIX variant
exe = Cc["@mozilla.org/file/local;1"].
createInstance(SpecialPowers.Ci.nsILocalFile);
exe.initWithPath("/bin/echo");
}
localHandler.executable = exe;
localHandler.launchWithURI(ioService.newURI(testURI, null, null));
// if we get this far without an exception, we've passed
ok(true, "localHandler launchWithURI test");
// if we ever decide that killing iCal is the right thing to do, change
// the if statement below from "NOTDarwin" to "Darwin"
if (osString == "NOTDarwin") {
var killall = Cc["@mozilla.org/file/local;1"].
createInstance(SpecialPowers.Ci.nsILocalFile);
killall.initWithPath("/usr/bin/killall");
var process = Cc["@mozilla.org/process/util;1"].
createInstance(SpecialPowers.Ci.nsIProcess);
process.init(killall);
var args = ['iCal'];
process.run(false, args, args.length);
}
SimpleTest.waitForExplicitFinish();
}
test();

View file

@ -0,0 +1,105 @@
Components.utils.import("resource://gre/modules/FileUtils.jsm");
Components.utils.import("resource://gre/modules/Task.jsm");
var gMimeSvc = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
var gHandlerSvc = Cc["@mozilla.org/uriloader/handler-service;1"].getService(Ci.nsIHandlerService);
function createMockedHandlerApp() {
// Mock the executable
let mockedExecutable = FileUtils.getFile("TmpD", ["mockedExecutable"]);
if (!mockedExecutable.exists()) {
mockedExecutable.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o755);
}
// Mock the handler app
let mockedHandlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"]
.createInstance(Ci.nsILocalHandlerApp);
mockedHandlerApp.executable = mockedExecutable;
mockedHandlerApp.detailedDescription = "Mocked handler app";
registerCleanupFunction(function() {
// remove the mocked executable from disk.
if (mockedExecutable.exists()) {
mockedExecutable.remove(true);
}
});
return mockedHandlerApp;
}
function createMockedObjects(createHandlerApp) {
// Mock the mime info
let internalMockedMIME = gMimeSvc.getFromTypeAndExtension("text/x-test-handler", null);
internalMockedMIME.alwaysAskBeforeHandling = true;
internalMockedMIME.preferredAction = Ci.nsIHandlerInfo.useHelperApp;
internalMockedMIME.appendExtension("abc");
if (createHandlerApp) {
let mockedHandlerApp = createMockedHandlerApp();
internalMockedMIME.description = mockedHandlerApp.detailedDescription;
internalMockedMIME.possibleApplicationHandlers.appendElement(mockedHandlerApp, false);
internalMockedMIME.preferredApplicationHandler = mockedHandlerApp;
}
// Proxy for the mocked MIME info for faking the read-only attributes
let mockedMIME = new Proxy(internalMockedMIME, {
get: function (target, property) {
switch (property) {
case "hasDefaultHandler":
return true;
case "defaultDescription":
return "Default description";
default:
return target[property];
}
},
});
// Mock the launcher:
let mockedLauncher = {
MIMEInfo: mockedMIME,
source: Services.io.newURI("http://www.mozilla.org/", null, null),
suggestedFileName: "test_download_dialog.abc",
targetFileIsExecutable: false,
saveToDisk() {},
cancel() {},
launchWithApplication() {},
setWebProgressListener() {},
saveDestinationAvailable() {},
contentLength: 42,
targetFile: null, // never read
// PRTime is microseconds since epoch, Date.now() returns milliseconds:
timeDownloadStarted: Date.now() * 1000,
QueryInterface: XPCOMUtils.generateQI([Ci.nsICancelable, Ci.nsIHelperAppLauncher])
};
registerCleanupFunction(function() {
// remove the mocked mime info from database.
let mockHandlerInfo = gMimeSvc.getFromTypeAndExtension("text/x-test-handler", null);
if (gHandlerSvc.exists(mockHandlerInfo)) {
gHandlerSvc.remove(mockHandlerInfo);
}
});
return mockedLauncher;
}
function* openHelperAppDialog(launcher) {
let helperAppDialog = Cc["@mozilla.org/helperapplauncherdialog;1"].
createInstance(Ci.nsIHelperAppLauncherDialog);
let helperAppDialogShownPromise = BrowserTestUtils.domWindowOpened();
try {
helperAppDialog.show(launcher, window, "foopy");
} catch (ex) {
ok(false, "Trying to show unknownContentType.xul failed with exception: " + ex);
Cu.reportError(ex);
}
let dlg = yield helperAppDialogShownPromise;
yield BrowserTestUtils.waitForEvent(dlg, "load", false);
is(dlg.location.href, "chrome://mozapps/content/downloads/unknownContentType.xul",
"Got correct dialog");
return dlg;
}

View file

@ -0,0 +1,10 @@
[DEFAULT]
support-files =
handlerApp.xhtml
handlerApps.js
unsafeBidi_chromeScript.js
unsafeBidiFileName.sjs
[test_handlerApps.xhtml]
skip-if = (toolkit == 'android' || os == 'mac') || e10s # OS X: bug 786938
[test_unsafeBidiChars.xhtml]

View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<title>Protocol handler</title>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
</head>
<body>
<script type="text/javascript">
navigator.registerProtocolHandler("testprotocol",
"https://example.com/foobar?uri=%s",
"Test Protocol");
</script>
<a id="link" href="testprotocol:test">testprotocol link</a>
</body>
</html>

View file

@ -0,0 +1,12 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test for Handler Apps </title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="handlerApps.js"/>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
</body>
</html>

View file

@ -0,0 +1,77 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test for Handling of unsafe bidi chars</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<iframe id="test"></iframe>
<script type="text/javascript">
<![CDATA[
var unsafeBidiChars = [
"\xe2\x80\xaa", // LRE
"\xe2\x80\xab", // RLE
"\xe2\x80\xac", // PDF
"\xe2\x80\xad", // LRO
"\xe2\x80\xae" // RLO
];
var tests = [
"{1}.test",
"{1}File.test",
"Fi{1}le.test",
"File{1}.test",
"File.{1}test",
"File.te{1}st",
"File.test{1}",
"File.{1}",
];
function replace(name, x) {
return name.replace(/\{1\}/, x);
}
function sanitize(name) {
return replace(name, '_');
}
add_task(function* () {
let url = SimpleTest.getTestFileURL("unsafeBidi_chromeScript.js");
let chromeScript = SpecialPowers.loadChromeScript(url);
for (let test of tests) {
for (let char of unsafeBidiChars) {
let promiseName = new Promise(function(resolve) {
chromeScript.addMessageListener("suggestedFileName",
function listener(data) {
chromeScript.removeMessageListener("suggestedFileName", listener);
resolve(data);
});
});
let name = replace(test, char);
let expected = sanitize(test);
document.getElementById("test").src =
"unsafeBidiFileName.sjs?name=" + encodeURIComponent(name);
is((yield promiseName), expected, "got the expected sanitized name");
}
}
let promise = new Promise(function(resolve) {
chromeScript.addMessageListener("unregistered", function listener() {
chromeScript.removeMessageListener("unregistered", listener);
resolve();
});
});
chromeScript.sendAsyncMessage("unregister");
yield promise;
chromeScript.destroy();
});
]]>
</script>
</body>
</html>

View file

@ -0,0 +1,14 @@
/* 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/. */
function handleRequest(request, response) {
response.setStatusLine(request.httpVersion, 200, "OK");
if (!request.queryString.match(/^name=/))
return;
var name = decodeURIComponent(request.queryString.substring(5));
response.setHeader("Content-Type", "application/octet-stream; name=\"" + name + "\"");
response.setHeader("Content-Disposition", "inline; filename=\"" + name + "\"");
}

View file

@ -0,0 +1,28 @@
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const HELPERAPP_DIALOG_CONTRACT = "@mozilla.org/helperapplauncherdialog;1";
const HELPERAPP_DIALOG_CID =
Components.ID(Cc[HELPERAPP_DIALOG_CONTRACT].number);
const FAKE_CID = Cc["@mozilla.org/uuid-generator;1"].
getService(Ci.nsIUUIDGenerator).generateUUID();
function HelperAppLauncherDialog() {}
HelperAppLauncherDialog.prototype = {
show: function(aLauncher, aWindowContext, aReason) {
sendAsyncMessage("suggestedFileName", aLauncher.suggestedFileName);
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIHelperAppLauncherDialog])
};
var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
registrar.registerFactory(FAKE_CID, "", HELPERAPP_DIALOG_CONTRACT,
XPCOMUtils._getFactory(HelperAppLauncherDialog));
addMessageListener("unregister", function() {
registrar.registerFactory(HELPERAPP_DIALOG_CID, "",
HELPERAPP_DIALOG_CONTRACT, null);
sendAsyncMessage("unregistered");
});

View file

@ -0,0 +1,24 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
MOCHITEST_MANIFESTS += ['mochitest/mochitest.ini']
XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']
BROWSER_CHROME_MANIFESTS += ['mochitest/browser.ini']
# The encoding test is already implemented in the Downloads API by a set of
# test cases with the string "content_encoding" in their names.
if not CONFIG['MOZ_JSDOWNLOADS']:
XPCSHELL_TESTS_MANIFESTS += ['unit_ipc/xpcshell.ini']
GeckoSimplePrograms([
'WriteArgument',
], linkage=None)
USE_LIBS += [
'nspr',
]

View file

@ -0,0 +1,163 @@
/* 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/. */
// Inspired by the Places infrastructure in head_bookmarks.js
var Cc = Components.classes;
var Ci = Components.interfaces;
var Cr = Components.results;
var Cu = Components.utils;
var HandlerServiceTest = {
//**************************************************************************//
// Convenience Getters
__dirSvc: null,
get _dirSvc() {
if (!this.__dirSvc)
this.__dirSvc = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties).
QueryInterface(Ci.nsIDirectoryService);
return this.__dirSvc;
},
__consoleSvc: null,
get _consoleSvc() {
if (!this.__consoleSvc)
this.__consoleSvc = Cc["@mozilla.org/consoleservice;1"].
getService(Ci.nsIConsoleService);
return this.__consoleSvc;
},
//**************************************************************************//
// nsISupports
interfaces: [Ci.nsIDirectoryServiceProvider, Ci.nsISupports],
QueryInterface: function HandlerServiceTest_QueryInterface(iid) {
if (!this.interfaces.some( function(v) { return iid.equals(v) } ))
throw Cr.NS_ERROR_NO_INTERFACE;
return this;
},
//**************************************************************************//
// Initialization & Destruction
init: function HandlerServiceTest_init() {
// Register ourselves as a directory provider for the datasource file
// if there isn't one registered already.
try {
this._dirSvc.get("UMimTyp", Ci.nsIFile);
} catch (ex) {
this._dirSvc.registerProvider(this);
this._providerRegistered = true;
}
// Delete the existing datasource file, if any, so we start from scratch.
// We also do this after finishing the tests, so there shouldn't be an old
// file lying around, but just in case we delete it here as well.
this._deleteDatasourceFile();
// Turn on logging so we can troubleshoot problems with the tests.
var prefBranch = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
prefBranch.setBoolPref("browser.contentHandling.log", true);
},
destroy: function HandlerServiceTest_destroy() {
// Delete the existing datasource file, if any, so we don't leave test files
// lying around and we start from scratch the next time.
this._deleteDatasourceFile();
// Unregister the directory service provider
if (this._providerRegistered)
this._dirSvc.unregisterProvider(this);
},
//**************************************************************************//
// nsIDirectoryServiceProvider
getFile: function HandlerServiceTest_getFile(property, persistent) {
this.log("getFile: requesting " + property);
persistent.value = true;
if (property == "UMimTyp") {
var datasourceFile = this._dirSvc.get("CurProcD", Ci.nsIFile);
datasourceFile.append("mimeTypes.rdf");
return datasourceFile;
}
// This causes extraneous errors to show up in the log when the directory
// service asks us first for CurProcD and MozBinD. I wish there was a way
// to suppress those errors.
this.log("the following NS_ERROR_FAILURE exception in " +
"nsIDirectoryServiceProvider::getFile is expected, " +
"as we don't provide the '" + property + "' file");
throw Cr.NS_ERROR_FAILURE;
},
//**************************************************************************//
// Utilities
/**
* Delete the datasource file.
*/
_deleteDatasourceFile: function HandlerServiceTest__deleteDatasourceFile() {
var file = this._dirSvc.get("UMimTyp", Ci.nsIFile);
if (file.exists())
file.remove(false);
},
/**
* Get the contents of the datasource as a serialized string. Useful for
* debugging problems with test failures, i.e.:
*
* HandlerServiceTest.log(HandlerServiceTest.getDatasourceContents());
*
* @returns {string} the serialized datasource
*/
getDatasourceContents: function HandlerServiceTest_getDatasourceContents() {
var rdf = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
var ioService = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
var fileHandler = ioService.getProtocolHandler("file").
QueryInterface(Ci.nsIFileProtocolHandler);
var fileURL = fileHandler.getURLSpecFromFile(this.getDatasourceFile());
var ds = rdf.GetDataSourceBlocking(fileURL);
var outputStream = {
data: "",
close: function() {},
flush: function() {},
write: function (buffer,count) {
this.data += buffer;
return count;
},
writeFrom: function (stream,count) {},
isNonBlocking: false
};
ds.QueryInterface(Components.interfaces.nsIRDFXMLSource);
ds.Serialize(outputStream);
return outputStream.data;
},
/**
* Log a message to the console and the test log.
*/
log: function HandlerServiceTest_log(message) {
message = "*** HandlerServiceTest: " + message;
this._consoleSvc.logStringMessage(message);
print(message);
}
};
HandlerServiceTest.init();

View file

@ -0,0 +1,2 @@
text/plain; cat '%s'; needsterminal
text/plain; sed '%s'

View file

@ -0,0 +1,5 @@
/* 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/. */
HandlerServiceTest.destroy();

View file

@ -0,0 +1,26 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
* 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/. */
function run_test() {
// "text/plain" has an 0xFF character appended to it. This means it's an
// invalid string, which is tricky to enter using a text editor (I used
// emacs' hexl-mode). It also means an ordinary text editor might drop it
// or convert it to something that *is* valid (in UTF8). So we measure
// its length to make sure this hasn't happened.
var badMimeType = "text/plainÿ";
do_check_eq(badMimeType.length, 11);
try {
var type = Cc["@mozilla.org/mime;1"].
getService(Ci.nsIMIMEService).
getFromTypeAndExtension(badMimeType, "txt");
} catch (e if (e instanceof Ci.nsIException &&
e.result == Cr.NS_ERROR_NOT_AVAILABLE)) {
// This is an expected exception, thrown if the type can't be determined
} finally {
}
// Not crashing is good enough
do_check_eq(true, true);
}

View file

@ -0,0 +1,53 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
* 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/. */
/**
* Test for bug 508030 <https://bugzilla.mozilla.org/show_bug.cgi?id=508030>:
* nsIMIMEService.getTypeFromExtension fails to find a match in the
* "ext-to-type-mapping" category if the provided extension is not lowercase.
*/
function run_test() {
// --- Common services ---
const mimeService = Cc["@mozilla.org/mime;1"].
getService(Ci.nsIMIMEService);
const categoryManager = Cc["@mozilla.org/categorymanager;1"].
getService(Ci.nsICategoryManager);
// --- Test procedure ---
const kTestExtension = "testextension";
const kTestExtensionMixedCase = "testExtensIon";
const kTestMimeType = "application/x-testextension";
// Ensure that the test extension is not initially recognized by the operating
// system or the "ext-to-type-mapping" category.
try {
// Try and get the MIME type associated with the extension.
mimeService.getTypeFromExtension(kTestExtension);
// The line above should have thrown an exception.
do_throw("nsIMIMEService.getTypeFromExtension succeeded unexpectedly");
} catch (e if (e instanceof Ci.nsIException &&
e.result == Cr.NS_ERROR_NOT_AVAILABLE)) {
// This is an expected exception, thrown if the type can't be determined.
// Any other exception would cause the test to fail.
}
// Add a temporary category entry mapping the extension to the MIME type.
categoryManager.addCategoryEntry("ext-to-type-mapping", kTestExtension,
kTestMimeType, false, true);
// Check that the mapping is recognized in the simple case.
var type = mimeService.getTypeFromExtension(kTestExtension);
do_check_eq(type, kTestMimeType);
// Check that the mapping is recognized even if the extension has mixed case.
type = mimeService.getTypeFromExtension(kTestExtensionMixedCase);
do_check_eq(type, kTestMimeType);
// Clean up after ourselves.
categoryManager.deleteCategoryEntry("ext-to-type-mapping", kTestExtension, false);
}

View file

@ -0,0 +1,186 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
* 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/. */
/**
* Test for bug 484579 <https://bugzilla.mozilla.org/show_bug.cgi?id=484579>:
* nsIMIMEService.getTypeFromExtension may fail unexpectedly on Windows when
* "Content Type" is empty in the registry.
*/
function run_test() {
// --- Preliminary platform check ---
// If this test is not running on the Windows platform, stop now, before
// calling XPCOMUtils.generateQI during the MockWindowsRegKey declaration.
if (mozinfo.os != "win")
return;
// --- Modified nsIWindowsRegKey implementation ---
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
/**
* Constructs a new mock registry key by wrapping the provided object.
*
* This mock implementation is tailored for this test, and forces consumers
* of the readStringValue method to believe that the "Content Type" value of
* the ".txt" key under HKEY_CLASSES_ROOT is an empty string.
*
* The same value read from "HKEY_LOCAL_MACHINE\SOFTWARE\Classes" is not
* affected.
*
* @param aWrappedObject An actual nsIWindowsRegKey implementation.
*/
function MockWindowsRegKey(aWrappedObject) {
this._wrappedObject = aWrappedObject;
// This function creates a forwarding function for wrappedObject
function makeForwardingFunction(functionName) {
return function() {
return aWrappedObject[functionName].apply(aWrappedObject, arguments);
}
}
// Forward all the functions that are not explicitly overridden
for (var propertyName in aWrappedObject) {
if (!(propertyName in this)) {
if (typeof aWrappedObject[propertyName] == "function") {
this[propertyName] = makeForwardingFunction(propertyName);
} else {
this[propertyName] = aWrappedObject[propertyName];
}
}
}
}
MockWindowsRegKey.prototype = {
// --- Overridden nsISupports interface functions ---
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWindowsRegKey]),
// --- Overridden nsIWindowsRegKey interface functions ---
open: function(aRootKey, aRelPath, aMode) {
// Remember the provided root key and path
this._rootKey = aRootKey;
this._relPath = aRelPath;
// Create the actual registry key
return this._wrappedObject.open(aRootKey, aRelPath, aMode);
},
openChild: function(aRelPath, aMode) {
// Open the child key and wrap it
var innerKey = this._wrappedObject.openChild(aRelPath, aMode);
var key = new MockWindowsRegKey(innerKey);
// Set the properties of the child key and return it
key._rootKey = this._rootKey;
key._relPath = this._relPath + aRelPath;
return key;
},
createChild: function(aRelPath, aMode) {
// Create the child key and wrap it
var innerKey = this._wrappedObject.createChild(aRelPath, aMode);
var key = new MockWindowsRegKey(innerKey);
// Set the properties of the child key and return it
key._rootKey = this._rootKey;
key._relPath = this._relPath + aRelPath;
return key;
},
get childCount() {
return this._wrappedObject.childCount;
},
get valueCount() {
return this._wrappedObject.valueCount;
},
readStringValue: function(aName) {
// If this is the key under test, return a fake value
if (this._rootKey == Ci.nsIWindowsRegKey.ROOT_KEY_CLASSES_ROOT &&
this._relPath.toLowerCase() == ".txt" &&
aName.toLowerCase() == "content type") {
return "";
}
// Return the real value in the registry
return this._wrappedObject.readStringValue(aName);
}
};
// --- Mock nsIWindowsRegKey factory ---
var componentRegistrar = Components.manager.
QueryInterface(Ci.nsIComponentRegistrar);
var originalWindowsRegKeyCID;
var mockWindowsRegKeyFactory;
const kMockCID = Components.ID("{9b23dfe9-296b-4740-ba1c-d39c9a16e55e}");
const kWindowsRegKeyContractID = "@mozilla.org/windows-registry-key;1";
const kWindowsRegKeyClassName = "nsWindowsRegKey";
function registerMockWindowsRegKeyFactory() {
mockWindowsRegKeyFactory = {
createInstance: function(aOuter, aIid) {
if (aOuter != null)
throw Cr.NS_ERROR_NO_AGGREGATION;
var innerKey = originalWindowsRegKeyFactory.createInstance(null, aIid);
var key = new MockWindowsRegKey(innerKey);
return key.QueryInterface(aIid);
}
};
// Preserve the original factory
originalWindowsRegKeyCID = Cc[kWindowsRegKeyContractID].number;
// Register the mock factory
componentRegistrar.registerFactory(
kMockCID,
"Mock Windows Registry Key Implementation",
kWindowsRegKeyContractID,
mockWindowsRegKeyFactory
);
}
function unregisterMockWindowsRegKeyFactory() {
// Free references to the mock factory
componentRegistrar.unregisterFactory(
kMockCID,
mockWindowsRegKeyFactory
);
// Restore the original factory
componentRegistrar.registerFactory(
Components.ID(originalWindowsRegKeyCID),
"",
kWindowsRegKeyContractID,
null
);
}
// --- Test procedure ---
// Activate the override of the ".txt" file association data in the registry
registerMockWindowsRegKeyFactory();
try {
// Try and get the MIME type associated with the extension. If this
// operation does not throw an unexpected exception, the test succeeds.
var type = Cc["@mozilla.org/mime;1"].
getService(Ci.nsIMIMEService).
getTypeFromExtension(".txt");
} catch (e if (e instanceof Ci.nsIException &&
e.result == Cr.NS_ERROR_NOT_AVAILABLE)) {
// This is an expected exception, thrown if the type can't be determined
} finally {
// Ensure we restore the original factory when the test is finished
unregisterMockWindowsRegKeyFactory();
}
}

View file

@ -0,0 +1,470 @@
/* 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/. */
function run_test() {
//**************************************************************************//
// Constants
const handlerSvc = Cc["@mozilla.org/uriloader/handler-service;1"].
getService(Ci.nsIHandlerService);
const mimeSvc = Cc["@mozilla.org/mime;1"].
getService(Ci.nsIMIMEService);
const protoSvc = Cc["@mozilla.org/uriloader/external-protocol-service;1"].
getService(Ci.nsIExternalProtocolService);
const prefSvc = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefService);
const ioService = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
const env = Cc["@mozilla.org/process/environment;1"].
getService(Components.interfaces.nsIEnvironment);
const rootPrefBranch = prefSvc.getBranch("");
let noMailto = false;
if (mozinfo.os == "win") {
// Check mailto handler from registry.
// If registry entry is nothing, no mailto handler
let regSvc = Cc["@mozilla.org/windows-registry-key;1"].
createInstance(Ci.nsIWindowsRegKey);
try {
regSvc.open(regSvc.ROOT_KEY_CLASSES_ROOT,
"mailto",
regSvc.ACCESS_READ);
noMailto = false;
} catch (ex) {
noMailto = true;
}
regSvc.close();
}
if (mozinfo.os == "linux") {
// Check mailto handler from GIO
// If there isn't one, then we have no mailto handler
let gIOSvc = Cc["@mozilla.org/gio-service;1"].
createInstance(Ci.nsIGIOService);
try {
gIOSvc.getAppForURIScheme("mailto");
noMailto = false;
} catch (ex) {
noMailto = true;
}
}
//**************************************************************************//
// Sample Data
// It doesn't matter whether or not this nsIFile is actually executable,
// only that it has a path and exists. Since we don't know any executable
// that exists on all platforms (except possibly the application being
// tested, but there doesn't seem to be a way to get a reference to that
// from the directory service), we use the temporary directory itself.
var executable = HandlerServiceTest._dirSvc.get("TmpD", Ci.nsIFile);
// XXX We could, of course, create an actual executable in the directory:
//executable.append("localhandler");
//if (!executable.exists())
// executable.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o755);
var localHandler = {
name: "Local Handler",
executable: executable,
interfaces: [Ci.nsIHandlerApp, Ci.nsILocalHandlerApp, Ci.nsISupports],
QueryInterface: function(iid) {
if (!this.interfaces.some( function(v) { return iid.equals(v) } ))
throw Cr.NS_ERROR_NO_INTERFACE;
return this;
}
};
var webHandler = Cc["@mozilla.org/uriloader/web-handler-app;1"].
createInstance(Ci.nsIWebHandlerApp);
webHandler.name = "Web Handler";
webHandler.uriTemplate = "http://www.example.com/?%s";
// FIXME: these tests create and manipulate enough variables that it would
// make sense to move each test into its own scope so we don't run the risk
// of one test stomping on another's data.
//**************************************************************************//
// Test Default Properties
// Get a handler info for a MIME type that neither the application nor
// the OS knows about and make sure its properties are set to the proper
// default values.
var handlerInfo = mimeSvc.getFromTypeAndExtension("nonexistent/type", null);
// Make sure it's also an nsIHandlerInfo.
do_check_true(handlerInfo instanceof Ci.nsIHandlerInfo);
do_check_eq(handlerInfo.type, "nonexistent/type");
// Deprecated property, but we should still make sure it's set correctly.
do_check_eq(handlerInfo.MIMEType, "nonexistent/type");
// These properties are the ones the handler service knows how to store.
do_check_eq(handlerInfo.preferredAction, Ci.nsIHandlerInfo.saveToDisk);
do_check_eq(handlerInfo.preferredApplicationHandler, null);
do_check_eq(handlerInfo.possibleApplicationHandlers.length, 0);
do_check_true(handlerInfo.alwaysAskBeforeHandling);
// These properties are initialized to default values by the service,
// so we might as well make sure they're initialized to the right defaults.
do_check_eq(handlerInfo.description, "");
do_check_eq(handlerInfo.hasDefaultHandler, false);
do_check_eq(handlerInfo.defaultDescription, "");
// test some default protocol info properties
var haveDefaultHandlersVersion = false;
try {
// If we have a defaultHandlersVersion pref, then assume that we're in the
// firefox tree and that we'll also have default handlers.
// Bug 395131 has been filed to make this test work more generically
// by providing our own prefs for this test rather than this icky
// special casing.
rootPrefBranch.getCharPref("gecko.handlerService.defaultHandlersVersion");
haveDefaultHandlersVersion = true;
} catch (ex) {}
const kExternalWarningDefault =
"network.protocol-handler.warn-external-default";
prefSvc.setBoolPref(kExternalWarningDefault, true);
// XXX add more thorough protocol info property checking
// no OS default handler exists
var protoInfo = protoSvc.getProtocolHandlerInfo("x-moz-rheet");
do_check_eq(protoInfo.preferredAction, protoInfo.alwaysAsk);
do_check_true(protoInfo.alwaysAskBeforeHandling);
// OS default exists, injected default does not exist,
// explicit warning pref: false
const kExternalWarningPrefPrefix = "network.protocol-handler.warn-external.";
prefSvc.setBoolPref(kExternalWarningPrefPrefix + "http", false);
protoInfo = protoSvc.getProtocolHandlerInfo("http");
do_check_eq(0, protoInfo.possibleApplicationHandlers.length);
do_check_false(protoInfo.alwaysAskBeforeHandling);
// OS default exists, injected default does not exist,
// explicit warning pref: true
prefSvc.setBoolPref(kExternalWarningPrefPrefix + "http", true);
protoInfo = protoSvc.getProtocolHandlerInfo("http");
// OS handler isn't included in possibleApplicationHandlers, so length is 0
// Once they become instances of nsILocalHandlerApp, this number will need
// to change.
do_check_eq(0, protoInfo.possibleApplicationHandlers.length);
do_check_true(protoInfo.alwaysAskBeforeHandling);
// OS default exists, injected default exists, explicit warning pref: false
prefSvc.setBoolPref(kExternalWarningPrefPrefix + "mailto", false);
protoInfo = protoSvc.getProtocolHandlerInfo("mailto");
if (haveDefaultHandlersVersion)
do_check_eq(2, protoInfo.possibleApplicationHandlers.length);
else
do_check_eq(0, protoInfo.possibleApplicationHandlers.length);
// Win7+ or Linux's GIO might not have a default mailto: handler
if (noMailto)
do_check_true(protoInfo.alwaysAskBeforeHandling);
else
do_check_false(protoInfo.alwaysAskBeforeHandling);
// OS default exists, injected default exists, explicit warning pref: true
prefSvc.setBoolPref(kExternalWarningPrefPrefix + "mailto", true);
protoInfo = protoSvc.getProtocolHandlerInfo("mailto");
if (haveDefaultHandlersVersion) {
do_check_eq(2, protoInfo.possibleApplicationHandlers.length);
// Win7+ or Linux's GIO may have no default mailto: handler. Otherwise
// alwaysAskBeforeHandling is expected to be false here, because although
// the pref is true, the value in RDF is false. The injected mailto handler
// carried over the default pref value, and so when we set the pref above
// to true it's ignored.
if (noMailto)
do_check_true(protoInfo.alwaysAskBeforeHandling);
else
do_check_false(protoInfo.alwaysAskBeforeHandling);
} else {
do_check_eq(0, protoInfo.possibleApplicationHandlers.length);
do_check_true(protoInfo.alwaysAskBeforeHandling);
}
if (haveDefaultHandlersVersion) {
// Now set the value stored in RDF to true, and the pref to false, to make
// sure we still get the right value. (Basically, same thing as above but
// with the values reversed.)
prefSvc.setBoolPref(kExternalWarningPrefPrefix + "mailto", false);
protoInfo.alwaysAskBeforeHandling = true;
handlerSvc.store(protoInfo);
protoInfo = protoSvc.getProtocolHandlerInfo("mailto");
do_check_eq(2, protoInfo.possibleApplicationHandlers.length);
do_check_true(protoInfo.alwaysAskBeforeHandling);
}
//**************************************************************************//
// Test Round-Trip Data Integrity
// Test round-trip data integrity by setting the properties of the handler
// info object to different values, telling the handler service to store the
// object, and then retrieving a new info object for the same type and making
// sure its properties are identical.
handlerInfo.preferredAction = Ci.nsIHandlerInfo.useHelperApp;
handlerInfo.preferredApplicationHandler = localHandler;
handlerInfo.alwaysAskBeforeHandling = false;
handlerSvc.store(handlerInfo);
handlerInfo = mimeSvc.getFromTypeAndExtension("nonexistent/type", null);
do_check_eq(handlerInfo.preferredAction, Ci.nsIHandlerInfo.useHelperApp);
do_check_neq(handlerInfo.preferredApplicationHandler, null);
var preferredHandler = handlerInfo.preferredApplicationHandler;
do_check_eq(typeof preferredHandler, "object");
do_check_eq(preferredHandler.name, "Local Handler");
do_check_true(preferredHandler instanceof Ci.nsILocalHandlerApp);
preferredHandler.QueryInterface(Ci.nsILocalHandlerApp);
do_check_eq(preferredHandler.executable.path, localHandler.executable.path);
do_check_false(handlerInfo.alwaysAskBeforeHandling);
// Make sure the handler service's enumerate method lists all known handlers.
var handlerInfo2 = mimeSvc.getFromTypeAndExtension("nonexistent/type2", null);
handlerSvc.store(handlerInfo2);
var handlerTypes = ["nonexistent/type", "nonexistent/type2"];
if (haveDefaultHandlersVersion) {
handlerTypes.push("webcal");
handlerTypes.push("mailto");
handlerTypes.push("irc");
handlerTypes.push("ircs");
}
var handlers = handlerSvc.enumerate();
while (handlers.hasMoreElements()) {
var handler = handlers.getNext().QueryInterface(Ci.nsIHandlerInfo);
do_check_neq(handlerTypes.indexOf(handler.type), -1);
handlerTypes.splice(handlerTypes.indexOf(handler.type), 1);
}
do_check_eq(handlerTypes.length, 0);
// Make sure the handler service's remove method removes a handler record.
handlerSvc.remove(handlerInfo2);
handlers = handlerSvc.enumerate();
while (handlers.hasMoreElements())
do_check_neq(handlers.getNext().QueryInterface(Ci.nsIHandlerInfo).type,
handlerInfo2.type);
// Make sure we can store and retrieve a handler info object with no preferred
// handler.
var noPreferredHandlerInfo =
mimeSvc.getFromTypeAndExtension("nonexistent/no-preferred-handler", null);
handlerSvc.store(noPreferredHandlerInfo);
noPreferredHandlerInfo =
mimeSvc.getFromTypeAndExtension("nonexistent/no-preferred-handler", null);
do_check_eq(noPreferredHandlerInfo.preferredApplicationHandler, null);
// Make sure that the handler service removes an existing handler record
// if we store a handler info object with no preferred handler.
var removePreferredHandlerInfo =
mimeSvc.getFromTypeAndExtension("nonexistent/rem-preferred-handler", null);
removePreferredHandlerInfo.preferredApplicationHandler = localHandler;
handlerSvc.store(removePreferredHandlerInfo);
removePreferredHandlerInfo =
mimeSvc.getFromTypeAndExtension("nonexistent/rem-preferred-handler", null);
removePreferredHandlerInfo.preferredApplicationHandler = null;
handlerSvc.store(removePreferredHandlerInfo);
removePreferredHandlerInfo =
mimeSvc.getFromTypeAndExtension("nonexistent/rem-preferred-handler", null);
do_check_eq(removePreferredHandlerInfo.preferredApplicationHandler, null);
// Make sure we can store and retrieve a handler info object with possible
// handlers. We test both adding and removing handlers.
// Get a handler info and make sure it has no possible handlers.
var possibleHandlersInfo =
mimeSvc.getFromTypeAndExtension("nonexistent/possible-handlers", null);
do_check_eq(possibleHandlersInfo.possibleApplicationHandlers.length, 0);
// Store and re-retrieve the handler and make sure it still has no possible
// handlers.
handlerSvc.store(possibleHandlersInfo);
possibleHandlersInfo =
mimeSvc.getFromTypeAndExtension("nonexistent/possible-handlers", null);
do_check_eq(possibleHandlersInfo.possibleApplicationHandlers.length, 0);
// Add two handlers, store the object, re-retrieve it, and make sure it has
// two handlers.
possibleHandlersInfo.possibleApplicationHandlers.appendElement(localHandler,
false);
possibleHandlersInfo.possibleApplicationHandlers.appendElement(webHandler,
false);
handlerSvc.store(possibleHandlersInfo);
possibleHandlersInfo =
mimeSvc.getFromTypeAndExtension("nonexistent/possible-handlers", null);
do_check_eq(possibleHandlersInfo.possibleApplicationHandlers.length, 2);
// Figure out which is the local and which is the web handler and the index
// in the array of the local handler, which is the one we're going to remove
// to test removal of a handler.
var handler1 = possibleHandlersInfo.possibleApplicationHandlers.
queryElementAt(0, Ci.nsIHandlerApp);
var handler2 = possibleHandlersInfo.possibleApplicationHandlers.
queryElementAt(1, Ci.nsIHandlerApp);
var localPossibleHandler, webPossibleHandler, localIndex;
if (handler1 instanceof Ci.nsILocalHandlerApp)
[localPossibleHandler, webPossibleHandler, localIndex] = [handler1,
handler2,
0];
else
[localPossibleHandler, webPossibleHandler, localIndex] = [handler2,
handler1,
1];
localPossibleHandler.QueryInterface(Ci.nsILocalHandlerApp);
webPossibleHandler.QueryInterface(Ci.nsIWebHandlerApp);
// Make sure the two handlers are the ones we stored.
do_check_eq(localPossibleHandler.name, localHandler.name);
do_check_true(localPossibleHandler.equals(localHandler));
do_check_eq(webPossibleHandler.name, webHandler.name);
do_check_true(webPossibleHandler.equals(webHandler));
// Remove a handler, store the object, re-retrieve it, and make sure
// it only has one handler.
possibleHandlersInfo.possibleApplicationHandlers.removeElementAt(localIndex);
handlerSvc.store(possibleHandlersInfo);
possibleHandlersInfo =
mimeSvc.getFromTypeAndExtension("nonexistent/possible-handlers", null);
do_check_eq(possibleHandlersInfo.possibleApplicationHandlers.length, 1);
// Make sure the handler is the one we didn't remove.
webPossibleHandler = possibleHandlersInfo.possibleApplicationHandlers.
queryElementAt(0, Ci.nsIWebHandlerApp);
do_check_eq(webPossibleHandler.name, webHandler.name);
do_check_true(webPossibleHandler.equals(webHandler));
//////////////////////////////////////////////////////
// handler info command line parameters and equality
var localApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
createInstance(Ci.nsILocalHandlerApp);
var handlerApp = localApp.QueryInterface(Ci.nsIHandlerApp);
do_check_true(handlerApp.equals(localApp));
localApp.executable = executable;
do_check_eq(0, localApp.parameterCount);
localApp.appendParameter("-test1");
do_check_eq(1, localApp.parameterCount);
localApp.appendParameter("-test2");
do_check_eq(2, localApp.parameterCount);
do_check_true(localApp.parameterExists("-test1"));
do_check_true(localApp.parameterExists("-test2"));
do_check_false(localApp.parameterExists("-false"));
localApp.clearParameters();
do_check_eq(0, localApp.parameterCount);
var localApp2 = Cc["@mozilla.org/uriloader/local-handler-app;1"].
createInstance(Ci.nsILocalHandlerApp);
localApp2.executable = executable;
localApp.clearParameters();
do_check_true(localApp.equals(localApp2));
// equal:
// cut -d 1 -f 2
// cut -d 1 -f 2
localApp.appendParameter("-test1");
localApp.appendParameter("-test2");
localApp.appendParameter("-test3");
localApp2.appendParameter("-test1");
localApp2.appendParameter("-test2");
localApp2.appendParameter("-test3");
do_check_true(localApp.equals(localApp2));
// not equal:
// cut -d 1 -f 2
// cut -f 1 -d 2
localApp.clearParameters();
localApp2.clearParameters();
localApp.appendParameter("-test1");
localApp.appendParameter("-test2");
localApp.appendParameter("-test3");
localApp2.appendParameter("-test2");
localApp2.appendParameter("-test1");
localApp2.appendParameter("-test3");
do_check_false(localApp2.equals(localApp));
var str;
str = localApp.getParameter(0)
do_check_eq(str, "-test1");
str = localApp.getParameter(1)
do_check_eq(str, "-test2");
str = localApp.getParameter(2)
do_check_eq(str, "-test3");
// FIXME: test round trip integrity for a protocol.
// FIXME: test round trip integrity for a handler info with a web handler.
//**************************************************************************//
// getTypeFromExtension tests
// test nonexistent extension
var lolType = handlerSvc.getTypeFromExtension("lolcat");
do_check_eq(lolType, "");
// add a handler for the extension
var lolHandler = mimeSvc.getFromTypeAndExtension("application/lolcat", null);
do_check_false(lolHandler.extensionExists("lolcat"));
lolHandler.preferredAction = Ci.nsIHandlerInfo.useHelperApp;
lolHandler.preferredApplicationHandler = localHandler;
lolHandler.alwaysAskBeforeHandling = false;
// store the handler
do_check_false(handlerSvc.exists(lolHandler));
handlerSvc.store(lolHandler);
do_check_true(handlerSvc.exists(lolHandler));
// Get a file:// string pointing to mimeTypes.rdf
var rdfFile = HandlerServiceTest._dirSvc.get("UMimTyp", Ci.nsIFile);
var fileHandler = ioService.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler);
var rdfFileURI = fileHandler.getURLSpecFromFile(rdfFile);
// Assign a file extenstion to the handler. handlerSvc.store() doesn't
// actually store any file extensions added with setFileExtensions(), you
// have to wade into RDF muck to do so.
// Based on toolkit/mozapps/downloads/content/helperApps.js :: addExtension()
var gRDF = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
var mimeSource = gRDF.GetUnicodeResource("urn:mimetype:application/lolcat");
var valueProperty = gRDF.GetUnicodeResource("http://home.netscape.com/NC-rdf#fileExtensions");
var mimeLiteral = gRDF.GetLiteral("lolcat");
var DS = gRDF.GetDataSourceBlocking(rdfFileURI);
DS.Assert(mimeSource, valueProperty, mimeLiteral, true);
// test now-existent extension
lolType = handlerSvc.getTypeFromExtension("lolcat");
do_check_eq(lolType, "application/lolcat");
// test mailcap entries with needsterminal are ignored on non-Windows non-Mac.
if (mozinfo.os != "win" && mozinfo.os != "mac") {
env.set('PERSONAL_MAILCAP', do_get_file('mailcap').path);
handlerInfo = mimeSvc.getFromTypeAndExtension("text/plain", null);
do_check_eq(handlerInfo.preferredAction, Ci.nsIHandlerInfo.useSystemDefault);
do_check_eq(handlerInfo.defaultDescription, "sed");
}
}

View file

@ -0,0 +1,126 @@
/* 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/. */
// Encoded test URI to work on all platforms/independent of file encoding
const kTestURI = "http://\u65e5\u672c\u8a93.jp/";
const kExpectedURI = "http://xn--wgv71a309e.jp/";
const kOutputFile = "result.txt";
// Try several times in case the box we're running on is slow.
const kMaxCheckExistAttempts = 30; // seconds
var gCheckExistsAttempts = 0;
const tempDir = do_get_tempdir();
function checkFile() {
// This is where we expect the output
var tempFile = tempDir.clone();
tempFile.append(kOutputFile);
if (!tempFile.exists()) {
if (gCheckExistsAttempts >= kMaxCheckExistAttempts) {
do_throw("Expected File " + tempFile.path + " does not exist after " +
kMaxCheckExistAttempts + " seconds");
}
else {
++gCheckExistsAttempts;
// Wait a bit longer then try again
do_timeout(1000, checkFile);
return;
}
}
// Now read it
var fstream =
Components.classes["@mozilla.org/network/file-input-stream;1"]
.createInstance(Components.interfaces.nsIFileInputStream);
var sstream =
Components.classes["@mozilla.org/scriptableinputstream;1"]
.createInstance(Components.interfaces.nsIScriptableInputStream);
fstream.init(tempFile, -1, 0, 0);
sstream.init(fstream);
// Read the first line only as that's the one we expect WriteArguments
// to be writing the argument to.
var data = sstream.read(4096);
sstream.close();
fstream.close();
// Now remove the old file
tempFile.remove(false);
// This currently fails on Mac with an argument like -psn_0_nnnnnn
// This seems to be to do with how the executable is called, but I couldn't
// find a way around it.
// Additionally the lack of OS detection in xpcshell tests sucks, so we'll
// have to check for the argument mac gives us.
if (data.substring(0, 7) != "-psn_0_")
do_check_eq(data, kExpectedURI);
do_test_finished();
}
function run_test() {
if (mozinfo.os == "mac") {
dump("INFO | test_punycodeURIs.js | Skipping test on mac, bug 599475")
return;
}
// set up the uri to test with
var ioService =
Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
// set up the local handler object
var localHandler =
Components.classes["@mozilla.org/uriloader/local-handler-app;1"]
.createInstance(Components.interfaces.nsILocalHandlerApp);
localHandler.name = "Test Local Handler App";
// WriteArgument will just dump its arguments to a file for us.
var processDir = do_get_cwd();
var exe = processDir.clone();
exe.append("WriteArgument");
if (!exe.exists()) {
// Maybe we are on windows
exe.leafName = "WriteArgument.exe";
if (!exe.exists())
do_throw("Could not locate the WriteArgument tests executable\n");
}
var outFile = tempDir.clone();
outFile.append(kOutputFile);
// Set an environment variable for WriteArgument to pick up
var envSvc =
Components.classes["@mozilla.org/process/environment;1"]
.getService(Components.interfaces.nsIEnvironment);
// The Write Argument file needs to know where its libraries are, so
// just force the path variable
// For mac
var greDir = HandlerServiceTest._dirSvc.get("GreD", Components.interfaces.nsIFile);
envSvc.set("DYLD_LIBRARY_PATH", greDir.path);
// For Linux
envSvc.set("LD_LIBRARY_PATH", greDir.path);
//XXX: handle windows
// Now tell it where we want the file.
envSvc.set("WRITE_ARGUMENT_FILE", outFile.path);
var uri = ioService.newURI(kTestURI, null, null);
// Just check we've got these matching, if we haven't there's a problem
// with ascii spec or our test case.
do_check_eq(uri.asciiSpec, kExpectedURI);
localHandler.executable = exe;
localHandler.launchWithURI(uri);
do_test_pending();
do_timeout(1000, checkFile);
}

View file

@ -0,0 +1,15 @@
[DEFAULT]
head = head_handlerService.js
tail = tail_handlerService.js
run-sequentially = Bug 912235 - Intermittent failures
[test_getTypeFromExtension_ext_to_type_mapping.js]
[test_getTypeFromExtension_with_empty_Content_Type.js]
[test_badMIMEType.js]
[test_handlerService.js]
support-files = mailcap
# Bug 676997: test consistently fails on Android
fail-if = os == "android"
[test_punycodeURIs.js]
# Bug 676997: test consistently fails on Android
fail-if = os == "android"

View file

@ -0,0 +1,231 @@
var Cc = Components.classes;
var Ci = Components.interfaces;
var Cu = Components.utils;
var Cr = Components.results;
Cu.import("resource://testing-common/httpd.js");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource://testing-common/MockRegistrar.js");
do_get_profile();
var DownloadListener = {
init: function () {
let obs = Services.obs;
obs.addObserver(this, "dl-done", true);
},
observe: function (subject, topic, data) {
this.onFinished(subject, topic, data);
},
QueryInterface: function (iid) {
if (iid.equals(Ci.nsIObserver) ||
iid.equals(Ci.nsISupportsWeakReference) ||
iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
}
}
DownloadListener.init();
function HelperAppDlg() { }
HelperAppDlg.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIHelperAppLauncherDialog]),
show: function (launcher, ctx, reason, usePrivateUI) {
launcher.MIMEInfo.preferredAction = Ci.nsIMIMEInfo.saveToFile;
launcher.launchWithApplication(null, false);
}
}
// Override the download-manager-ui to prevent anyone from trying to open
// a window.
function DownloadMgrUI() { }
DownloadMgrUI.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDownloadManagerUI]),
show: function (ir, aID, reason) { },
visible: false,
getAttention: function () { }
}
function AlertsSVC() { }
AlertsSVC.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAlertsService]),
showAlertNotification: function (url, title, text, clickable, cookie, listener, name) { },
}
MockRegistrar.register("@mozilla.org/helperapplauncherdialog;1",
HelperAppDlg);
MockRegistrar.register("@mozilla.org/download-manager-ui;1",
DownloadMgrUI);
MockRegistrar.register("@mozilla.org/alerts-service;1",
AlertsSVC);
function initChildTestEnv()
{
sendCommand(' \
const Cc = Components.classes; \
const Ci = Components.interfaces; \
const Cr = Components.results; \
const Cu = Components.utils; \
Cu.import("resource://gre/modules/Services.jsm"); \
function WindowContext() { } \
\
WindowContext.prototype = { \
getInterface: function (iid) { \
if (iid.equals(Ci.nsIInterfaceRequestor) || \
iid.equals(Ci.nsIURIContentListener) || \
iid.equals(Ci.nsILoadGroup) || \
iid.equals(Ci.nsIDocumentLoader) || \
iid.equals(Ci.nsIDOMWindow)) \
return this; \
\
throw Cr.NS_ERROR_NO_INTERFACE; \
}, \
\
/* nsIURIContentListener */ \
onStartURIOpen: function (uri) { }, \
isPreferred: function (type, desiredtype) { return false; }, \
\
/* nsILoadGroup */ \
addRequest: function (request, context) { }, \
removeRequest: function (request, context, status) { } \
}; \
\
var ioservice = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);\
var uriloader = Cc["@mozilla.org/uriloader;1"].getService(Ci.nsIURILoader);\
');
}
function testFinisher(endFunc) {
let ef = endFunc;
return function (file) {
ef(file);
runNextTest();
}
}
function runChildTestSet(set)
{
DownloadListener.onFinished = testFinisher(set[2]);
sendCommand('\
let uri = ioservice.newURI("http://localhost:4444' + set[0] + '", null, null); \
let channel = NetUtil.newChannel({uri: uri, loadUsingSystemPrincipal: true}); \
uriloader.openURI(channel, Ci.nsIURILoader.IS_CONTENT_PREFERRED, new WindowContext()); \
');
}
var httpserver = null;
var currentTest = 0;
function runNextTest()
{
if (currentTest == tests.length) {
httpserver.stop(do_test_finished);
return;
}
let set = tests[currentTest++];
runChildTestSet(set);
}
const responseBody = [0x1f, 0x8b, 0x08, 0x00, 0x16, 0x5a, 0x8a, 0x48, 0x02,
0x03, 0x2b, 0x49, 0x2d, 0x2e, 0xe1, 0x02, 0x00, 0xc6,
0x35, 0xb9, 0x3b, 0x05, 0x00, 0x00, 0x00];
/*
* First test: a file with Content-Type application/x-gzip and Content-Encoding gzip
* should not be decoded in a round-trip
*/
function testResponse1(metadata, response) {
response.setHeader("Content-Type", "application/x-gzip", false);
response.setHeader("Content-Encoding", "gzip", false);
response.setHeader("Content-Disposition", "attachment", false);
var bos = Cc["@mozilla.org/binaryoutputstream;1"].createInstance(Ci.nsIBinaryOutputStream);
bos.setOutputStream(response.bodyOutputStream);
bos.writeByteArray(responseBody, responseBody.length);
}
function finishTest1(subject, topic, data) {
let file = subject.QueryInterface(Ci.nsIDownload).targetFile;
do_check_true(file.path.search("test1.gz") != 0);
let fis = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
fis.init(file, -1, -1, 0);
let bis = Cc["@mozilla.org/binaryinputstream;1"].createInstance(Ci.nsIBinaryInputStream);
bis.setInputStream(fis);
let str = bis.readByteArray(bis.available());
do_check_matches(str, responseBody);
}
/*
* Second test: a file with Content-Type text/html and Content-Encoding gzip
* should not be decoded in a round-trip, if its filename ends in ".gz".
* We specify a Content-disposition header to force it to be saved as a file.
*/
function testResponse2(metadata, response) {
response.setHeader("Content-Type", "text/html", false);
response.setHeader("Content-Encoding", "gzip", false);
response.setHeader("Content-Disposition", "attachment", false);
var bos = Cc["@mozilla.org/binaryoutputstream;1"].createInstance(Ci.nsIBinaryOutputStream);
bos.setOutputStream(response.bodyOutputStream);
bos.writeByteArray(responseBody, responseBody.length);
}
function finishTest2(subject, topic, data) {
let file = subject.QueryInterface(Ci.nsIDownload).targetFile;
do_check_true(file.path.search("test2.gz") != 0);
let fis = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
fis.init(file, -1, -1, 0);
let bis = Cc["@mozilla.org/binaryinputstream;1"].createInstance(Ci.nsIBinaryInputStream);
bis.setInputStream(fis);
let str = bis.readByteArray(bis.available());
do_check_matches(str, responseBody);
}
function testResponse3(metadata, response) {
response.setHeader("Content-Type", "text/html", false);
response.setHeader("Content-Encoding", "gzip", false);
response.setHeader("Content-Disposition", "attachment", false);
var bos = Cc["@mozilla.org/binaryoutputstream;1"].createInstance(Ci.nsIBinaryOutputStream);
bos.setOutputStream(response.bodyOutputStream);
bos.writeByteArray(responseBody, responseBody.length);
}
function finishTest3(subject, topic, data) {
let file = subject.QueryInterface(Ci.nsIDownload).targetFile;
do_check_true(file.path.search("test3.txt") != 0);
let fis = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
fis.init(file, -1, -1, 0);
let bis = Cc["@mozilla.org/binaryinputstream;1"].createInstance(Ci.nsIBinaryInputStream);
bis.setInputStream(fis);
let str = bis.readByteArray(bis.available());
let decodedBody = [ 116, 101, 115, 116, 10 ]; // 't','e','s','t','\n'
do_check_matches(str, decodedBody);
}
var tests = [
[ "/test1.gz", testResponse1, finishTest1 ],
[ "/test2.gz", testResponse2, finishTest2 ],
[ "/test3.txt", testResponse3, finishTest3 ],
];
function run_test() {
// do_load_child_test_harness();
httpserver = new HttpServer();
httpserver.start(4444);
do_test_pending();
initChildTestEnv();
for (let set of tests)
httpserver.registerPathHandler(set[0], set[1]);
runNextTest();
}

View file

@ -0,0 +1,8 @@
[DEFAULT]
head =
tail =
[test_encoding.js]
# Bug 676995: test hangs consistently on Android
# Bug 907732: thunderbird still uses legacy downloads manager.
skip-if = (os == "android" || buildapp == '../mail')