Bug 793310 - Support sms:, tel: and mailto: URI schemes, r=philipp

This commit is contained in:
Andrea Marchesini 2012-10-01 11:28:01 -07:00
parent 46daae9502
commit 418f096481
11 changed files with 382 additions and 9 deletions

View File

@ -190,6 +190,9 @@ var shell = {
this.isHomeLoaded = false;
ppmm.addMessageListener("content-handler", this);
ppmm.addMessageListener("dial-handler", this);
ppmm.addMessageListener("sms-handler", this);
ppmm.addMessageListener("mail-handler", this);
},
stop: function shell_stop() {
@ -394,17 +397,18 @@ var shell = {
},
receiveMessage: function shell_receiveMessage(message) {
if (message.name != 'content-handler') {
var names = { 'content-handler': 'view',
'dial-handler' : 'dial',
'mail-handler' : 'new',
'sms-handler' : 'new' }
if (!(message.name in names))
return;
}
let handler = message.json;
let data = message.data;
new MozActivity({
name: 'view',
data: {
type: handler.type,
url: handler.url,
extras: handler.extras
}
name: names[message.name],
data: data
});
}
};

View File

@ -42,6 +42,18 @@ contract @mozilla.org/uriloader/content-handler;1?type=application/pdf {d18d0216
component {8b83eabc-7929-47f4-8b48-4dea8d887e4b} PaymentGlue.js
contract @mozilla.org/payment/ui-glue;1 {8b83eabc-7929-47f4-8b48-4dea8d887e4b}
# TelProtocolHandler.js
component {782775dd-7351-45ea-aff1-0ffa872cfdd2} TelProtocolHandler.js
contract @mozilla.org/network/protocol;1?name=tel {782775dd-7351-45ea-aff1-0ffa872cfdd2}
# SmsProtocolHandler.js
component {81ca20cb-0dad-4e32-8566-979c8998bd73} SmsProtocolHandler.js
contract @mozilla.org/network/protocol;1?name=sms {81ca20cb-0dad-4e32-8566-979c8998bd73}
# MailtoProtocolHandler.js
component {50777e53-0331-4366-a191-900999be386c} MailtoProtocolHandler.js
contract @mozilla.org/network/protocol;1?name=mailto {50777e53-0331-4366-a191-900999be386c}
# YoutubeProtocolHandler.js
component {c3f1b945-7e71-49c8-95c7-5ae9cc9e2bad} YoutubeProtocolHandler.js
contract @mozilla.org/network/protocol;1?name=vnd.youtube {c3f1b945-7e71-49c8-95c7-5ae9cc9e2bad}

View File

@ -0,0 +1,46 @@
/* 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/. */
"use strict";
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
"@mozilla.org/childprocessmessagemanager;1",
"nsIMessageSender");
function MailtoProtocolHandler() {
}
MailtoProtocolHandler.prototype = {
scheme: "mailto",
defaultPort: -1,
protocolFlags: Ci.nsIProtocolHandler.URI_NORELATIVE |
Ci.nsIProtocolHandler.URI_NOAUTH |
Ci.nsIProtocolHandler.URI_LOADABLE_BY_ANYONE |
Ci.nsIProtocolHandler.URI_DOES_NOT_RETURN_DATA,
allowPort: function() false,
newURI: function Proto_newURI(aSpec, aOriginCharset) {
let uri = Cc["@mozilla.org/network/simple-uri;1"].createInstance(Ci.nsIURI);
uri.spec = aSpec;
return uri;
},
newChannel: function Proto_newChannel(aURI) {
cpmm.sendAsyncMessage("mail-handler", {
URI: aURI.spec,
type: "mail" });
throw Components.results.NS_ERROR_ILLEGAL_VALUE;
},
classID: Components.ID("{50777e53-0331-4366-a191-900999be386c}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIProtocolHandler])
};
let NSGetFactory = XPCOMUtils.generateNSGetFactory([MailtoProtocolHandler]);

View File

@ -23,13 +23,24 @@ EXTRA_PP_COMPONENTS = \
ContentHandler.js \
ContentPermissionPrompt.js \
DirectoryProvider.js \
MailtoProtocolHandler.js \
MozKeyboard.js \
ProcessGlobal.js \
PaymentGlue.js \
SmsProtocolHandler.js \
TelProtocolHandler.js \
YoutubeProtocolHandler.js \
RecoveryService.js \
$(NULL)
EXTRA_JS_MODULES = \
TelURIParser.jsm \
$(NULL)
TEST_DIRS = \
test \
$(NULL)
ifdef MOZ_UPDATER
EXTRA_PP_COMPONENTS += UpdatePrompt.js
endif

View File

@ -0,0 +1,59 @@
/* 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/. */
/**
* SmsProtocolHandle.js
*
* This file implements the URLs for SMS
* https://www.rfc-editor.org/rfc/rfc5724.txt
*/
"use strict";
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import("resource:///modules/TelURIParser.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
"@mozilla.org/childprocessmessagemanager;1",
"nsIMessageSender");
function SmsProtocolHandler() {
}
SmsProtocolHandler.prototype = {
scheme: "sms",
defaultPort: -1,
protocolFlags: Ci.nsIProtocolHandler.URI_NORELATIVE |
Ci.nsIProtocolHandler.URI_NOAUTH |
Ci.nsIProtocolHandler.URI_LOADABLE_BY_ANYONE |
Ci.nsIProtocolHandler.URI_DOES_NOT_RETURN_DATA,
allowPort: function() false,
newURI: function Proto_newURI(aSpec, aOriginCharset) {
let uri = Cc["@mozilla.org/network/simple-uri;1"].createInstance(Ci.nsIURI);
uri.spec = aSpec;
return uri;
},
newChannel: function Proto_newChannel(aURI) {
let number = TelURIParser.parseURI('sms', aURI.spec);
if (number) {
cpmm.sendAsyncMessage("sms-handler", {
number: number,
type: "websms/sms" });
}
throw Components.results.NS_ERROR_ILLEGAL_VALUE;
},
classID: Components.ID("{81ca20cb-0dad-4e32-8566-979c8998bd73}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIProtocolHandler])
};
let NSGetFactory = XPCOMUtils.generateNSGetFactory([SmsProtocolHandler]);

View File

@ -0,0 +1,58 @@
/* 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/. */
/**
* TelProtocolHandle.js
*
* This file implements the URLs for Telephone Calls
* https://www.ietf.org/rfc/rfc2806.txt
*/
"use strict";
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import("resource:///modules/TelURIParser.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
"@mozilla.org/childprocessmessagemanager;1",
"nsIMessageSender");
function TelProtocolHandler() {
}
TelProtocolHandler.prototype = {
scheme: "tel",
defaultPort: -1,
protocolFlags: Ci.nsIProtocolHandler.URI_NORELATIVE |
Ci.nsIProtocolHandler.URI_NOAUTH |
Ci.nsIProtocolHandler.URI_LOADABLE_BY_ANYONE |
Ci.nsIProtocolHandler.URI_DOES_NOT_RETURN_DATA,
allowPort: function() false,
newURI: function Proto_newURI(aSpec, aOriginCharset) {
let uri = Cc["@mozilla.org/network/simple-uri;1"].createInstance(Ci.nsIURI);
uri.spec = aSpec;
return uri;
},
newChannel: function Proto_newChannel(aURI) {
let number = TelURIParser.parseURI('tel', aURI.spec);
if (number) {
cpmm.sendAsyncMessage("dial-handler", {
number: number,
type: "webtelephony/number" });
}
throw Components.results.NS_ERROR_ILLEGAL_VALUE;
},
classID: Components.ID("{782775dd-7351-45ea-aff1-0ffa872cfdd2}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIProtocolHandler])
};
let NSGetFactory = XPCOMUtils.generateNSGetFactory([TelProtocolHandler]);

View File

@ -0,0 +1,120 @@
/* 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/. */
"use strict";
let EXPORTED_SYMBOLS = ["TelURIParser"];
/**
* Singleton providing functionality for parsing tel: and sms: URIs
*/
let TelURIParser = {
parseURI: function(scheme, uri) {
// Ignore MWI and USSD codes. See 794034.
if (uri.indexOf('*') != -1 || uri.indexOf('#') != -1) {
return null;
}
// https://www.ietf.org/rfc/rfc2806.txt
let subscriber = uri.slice((scheme + ':').length);
if (!subscriber.length) {
return null;
}
let number = '';
let pos = 0;
let len = subscriber.length;
// visual-separator
let visualSeparator = [ '-', '.', '(', ')' ];
let digits = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ];
let dtmfDigits = [ '*', '#', 'A', 'B', 'C', 'D' ];
let pauseCharacter = [ 'p', 'w' ];
// global-phone-number
if (subscriber[pos] == '+') {
number += '+';
for (++pos; pos < len; ++pos) {
if (visualSeparator.indexOf(subscriber[pos]) != -1) {
number += subscriber[pos];
} else if (digits.indexOf(subscriber[pos]) != -1) {
number += subscriber[pos];
} else {
break;
}
}
}
// local-phone-number
else {
for (; pos < len; ++pos) {
if (visualSeparator.indexOf(subscriber[pos]) != -1) {
number += subscriber[pos];
} else if (digits.indexOf(subscriber[pos]) != -1) {
number += subscriber[pos];
} else if (dtmfDigits.indexOf(subscriber[pos]) != -1) {
number += subscriber[pos];
} else if (pauseCharacter.indexOf(subscriber[pos]) != -1) {
number += subscriber[pos];
} else {
break;
}
}
// this means error
if (!number.length) {
return null;
}
// isdn-subaddress
if (subscriber.substring(pos, pos + 6) == ';isub=') {
let subaddress = '';
for (pos += 6; pos < len; ++pos) {
if (visualSeparator.indexOf(subscriber[pos]) != -1) {
subaddress += subscriber[pos];
} else if (digits.indexOf(subscriber[pos]) != -1) {
subaddress += subscriber[pos];
} else {
break;
}
}
// FIXME: ignore subaddress - Bug 795242
}
// post-dial
if (subscriber.substring(pos, pos + 7) == ';postd=') {
let subaddress = '';
for (pos += 7; pos < len; ++pos) {
if (visualSeparator.indexOf(subscriber[pos]) != -1) {
subaddress += subscriber[pos];
} else if (digits.indexOf(subscriber[pos]) != -1) {
subaddress += subscriber[pos];
} else if (dtmfDigits.indexOf(subscriber[pos]) != -1) {
subaddress += subscriber[pos];
} else if (pauseCharacter.indexOf(subscriber[pos]) != -1) {
subaddress += subscriber[pos];
} else {
break;
}
}
// FIXME: ignore subaddress - Bug 795242
}
// area-specific
if (subscriber.substring(pos, pos + 15) == ';phone-context=') {
pos += 15;
// global-network-prefix | local-network-prefix | private-prefi
number = subscriber.substring(pos, subscriber.length) + number;
}
}
return number || null;
}
};

View File

@ -0,0 +1,20 @@
# vim: noexpandtab ts=8 sw=8
#
# 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/.
DEPTH = @DEPTH@
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = @relativesrcdir@
FAIL_ON_WARNINGS := 1
include $(DEPTH)/config/autoconf.mk
MODULE = B2GComponents
XPCSHELL_TESTS = unit
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,36 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function run_test() {
Components.utils.import("resource:///modules/TelURIParser.jsm")
// global-phone-number
do_check_eq(TelURIParser.parseURI('tel', 'tel:+1234'), '+1234');
// global-phone-number => ignored chars
do_check_eq(TelURIParser.parseURI('tel', 'tel:+1234_123'), '+1234');
// global-phone-number => visualSeparator + digits
do_check_eq(TelURIParser.parseURI('tel', 'tel:+-.()1234567890'), '+-.()1234567890');
// local-phone-number
do_check_eq(TelURIParser.parseURI('tel', 'tel:1234'), '1234');
// local-phone-number => visualSeparator + digits + dtmfDigits + pauseCharacter
do_check_eq(TelURIParser.parseURI('tel', 'tel:-.()1234567890ABCDpw'), '-.()1234567890ABCDpw');
// local-phone-number => visualSeparator + digits + dtmfDigits + pauseCharacter + ignored chars
do_check_eq(TelURIParser.parseURI('tel', 'tel:-.()1234567890ABCDpw_'), '-.()1234567890ABCDpw');
// local-phone-number => isdn-subaddress
do_check_eq(TelURIParser.parseURI('tel', 'tel:123;isub=123'), '123');
// local-phone-number => post-dial
do_check_eq(TelURIParser.parseURI('tel', 'tel:123;postd=123'), '123');
// local-phone-number => prefix
do_check_eq(TelURIParser.parseURI('tel', 'tel:123;phone-context=+0321'), '+0321123');
// local-phone-number => isdn-subaddress + post-dial + prefix
do_check_eq(TelURIParser.parseURI('tel', 'tel:123;isub=123;postd=123;phone-context=+0321'), '+0321123');
}

View File

@ -0,0 +1,5 @@
[DEFAULT]
head =
tail =
[test_bug793310.js]

View File

@ -130,4 +130,6 @@ skip-if = os == "win" || os == "mac" || os == "os2"
[include:modules/libmar/tests/unit/xpcshell.ini]
skip-if = os == "android"
[include:b2g/components/test/unit/xpcshell.ini]
[include:tools/profiler/tests/xpcshell.ini]