Merge from mozilla-central

This commit is contained in:
Ed Morley 2012-04-24 11:46:16 +01:00
commit 352ceec39d
28 changed files with 823 additions and 359 deletions

View File

@ -8038,6 +8038,10 @@ var gIdentityHandler = {
delete this._identityIconCountryLabel;
return this._identityIconCountryLabel = document.getElementById("identity-icon-country-label");
},
get _identityIcon () {
delete this._identityIcon;
return this._identityIcon = document.getElementById("page-proxy-favicon");
},
/**
* Rebuild cache of the elements that may or may not exist depending
@ -8047,9 +8051,11 @@ var gIdentityHandler = {
delete this._identityBox;
delete this._identityIconLabel;
delete this._identityIconCountryLabel;
delete this._identityIcon;
this._identityBox = document.getElementById("identity-box");
this._identityIconLabel = document.getElementById("identity-icon-label");
this._identityIconCountryLabel = document.getElementById("identity-icon-country-label");
this._identityIcon = document.getElementById("page-proxy-favicon");
},
/**
@ -8354,7 +8360,7 @@ var gIdentityHandler = {
}, false);
// Now open the popup, anchored off the primary chrome element
this._identityPopup.openPopup(this._identityBox, "bottomcenter topleft");
this._identityPopup.openPopup(this._identityIcon, "bottomcenter topleft");
},
onPopupShown : function(event) {

View File

@ -18,7 +18,6 @@ var MigrationWizard = {
_wiz: null,
_migrator: null,
_autoMigrate: null,
_bookmarks: false,
init: function ()
{
@ -64,34 +63,15 @@ var MigrationWizard = {
// 1 - Import Source
onImportSourcePageShow: function ()
{
// Reference to the "From File" radio button
var fromfile = null;
// init is not called when openDialog opens the wizard, so check for bookmarks here.
if ("arguments" in window && window.arguments[0] == "bookmarks") {
this._bookmarks = true;
fromfile = document.getElementById("fromfile");
fromfile.hidden = false;
var importBookmarks = document.getElementById("importBookmarks");
importBookmarks.hidden = false;
var importAll = document.getElementById("importAll");
importAll.hidden = true;
}
this._wiz.canRewind = false;
// The migrator to select. If the "fromfile" migrator is available, use it
// as the default in case we have no other migrators.
var selectedMigrator = fromfile;
var selectedMigrator = null;
// Figure out what source apps are are available to import from:
var group = document.getElementById("importSourceGroup");
for (var i = 0; i < group.childNodes.length; ++i) {
var migratorKey = group.childNodes[i].id;
if (migratorKey != "nothing" && migratorKey != "fromfile") {
if (migratorKey != "nothing") {
var migrator = MigrationUtils.getMigrator(migratorKey);
if (migrator) {
// Save this as the first selectable item, if we don't already have
@ -128,9 +108,7 @@ var MigrationWizard = {
{
var newSource = document.getElementById("importSourceGroup").selectedItem.id;
if (newSource == "nothing" || newSource == "fromfile") {
if(newSource == "fromfile")
window.opener.fromFile = true;
if (newSource == "nothing") {
document.documentElement.cancel();
return false;
}
@ -152,8 +130,6 @@ var MigrationWizard = {
else {
if (this._autoMigrate)
this._wiz.currentPage.next = "homePageImport";
else if (this._bookmarks)
this._wiz.currentPage.next = "migrating"
else
this._wiz.currentPage.next = "importItems";
@ -205,8 +181,6 @@ var MigrationWizard = {
// If we're automigrating or just doing bookmarks don't show the item selection page
if (this._autoMigrate)
this._wiz.currentPage.next = "homePageImport";
else if (this._bookmarks)
this._wiz.currentPage.next = "migrating"
},
// 3 - ImportItems
@ -352,10 +326,6 @@ var MigrationWizard = {
if (this._autoMigrate)
this._itemsFlags = this._migrator.getMigrateData(this._selectedProfile, this._autoMigrate);
// When importing bookmarks, show only bookmarks
if (this._bookmarks)
this._itemsFlags = 32;
this._listItems("migratingItems");
setTimeout(this.onMigratingMigrate, 0, this);
},

View File

@ -71,7 +71,6 @@
<radio id="ie" label="&importFromIE.label;" accesskey="&importFromIE.accesskey;"/>
<radio id="chrome" label="&importFromChrome.label;" accesskey="&importFromChrome.accesskey;"/>
<radio id="firefox" label="&importFromFirefox.label;" accesskey="&importFromFirefox.accesskey;"/>
<radio id="fromfile" label="&importFromHTMLFile.label;" accesskey="&importFromHTMLFile.accesskey;" hidden="true"/>
<radio id="nothing" label="&importFromNothing.label;" accesskey="&importFromNothing.accesskey;" hidden="true"/>
</radiogroup>
<label id="noSources" hidden="true">&noMigrationSources.label;</label>

View File

@ -15,8 +15,6 @@
<!ENTITY importFromChrome.accesskey "C">
<!ENTITY importFromFirefox.label "Firefox">
<!ENTITY importFromFirefox.accesskey "X">
<!ENTITY importFromHTMLFile.label "From an HTML File">
<!ENTITY importFromHTMLFile.accesskey "F">
<!ENTITY noMigrationSources.label "No programs that contain bookmarks, history or password data could be found.">

View File

@ -1,179 +1,255 @@
<!DOCTYPE HTML>
<html>
<!--
-->
<head>
<title>Basic websocket test</title>
<title>Basic WebSocket test</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="testWebSocket()">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=472529">Mozilla Bug </a>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=472529">Mozilla Bug 472529</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
const kUrl = "ws://mochi.test:8888/tests/content/base/test/file_websocket_basic";
var gTestElement;
var ws;
var params = ["protocol", "resource", "origin", "end"];
var results = ["test", "/tests/content/base/test/file_websocket_basic", "http://mochi.test:8888", "end"];
function forcegc(){
function forcegc() {
SpecialPowers.forceGC();
SpecialPowers.gc();
}
function finishWSTest() {
SimpleTest.finish();
function testWebSocket() {
gTestElement = document.getElementById("test");
SimpleTest.executeSoon(testWebSocket1);
}
function testWebSocket () {
var url = "ws://mochi.test:8888/tests/content/base/test/file_websocket_basic";
ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_basic", "test");
is(ws.url, url, "Wrong Websocket.url!");
/**
* Sends message keywords, then receives their values.
*/
function testWebSocket1() {
gTestElement.textContent = "Running testWebSocket1()";
var results = ["test",
"/tests/content/base/test/file_websocket_basic",
"http://mochi.test:8888",
"end"];
ws = new WebSocket(kUrl, "test");
is(ws.url, kUrl, "[1] WebSocket.url");
ws.onopen = function(e) {
const params = ["protocol", "resource", "origin", "end"];
gTestElement.textContent += "\nSending :";
for (var i = 0; i < params.length; ++i) {
document.getElementById('log').textContent += "sending " + params[i] + "\n";
gTestElement.textContent += " " + params[i];
ws.send(params[i]);
}
}
// Set this before onmessage() is called, so it is displayed once only.
gTestElement.textContent += "\nReceived:";
};
ws.onclose = function(e) {
is(results.length, 0, "All the messages should have been processed!");
ok(e.wasClean, "Connection closed cleanly");
testWebSocket2();
}
is(results.length, 0, "[1] Number of unreceived messages");
ok(e.wasClean, "[1] Connection closed cleanly");
SimpleTest.executeSoon(testWebSocket2);
};
ws.onerror = function(e) {
ok(false, "onerror called!");
finishWSTest();
}
ok(false, "[1] onerror() should not have been called!");
gTestElement.textContent += "\nonerror() should not have been called!";
SimpleTest.executeSoon(SimpleTest.finish);
};
ws.onmessage = function(e) {
document.getElementById('log').textContent += "\n" + e.data;
is(e.data, results[0], "Unexpected message");
is(e.data, results[0], "[1] Received message");
gTestElement.textContent += " " + e.data;
results.shift();
}
};
}
/**
* Sends 1000+1 test messages, then receives them.
*/
function testWebSocket2() {
ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_basic", "test");
var testCount = 1000; // Send lots of messages
gTestElement.textContent = "Running testWebSocket2()";
const displayInterval = 100;
const testCount = 1000;
const testMessage = "test message 2.";
var messageCount = 0;
var testMessage = "test message";
ws = new WebSocket(kUrl, "test");
ws.onopen = function(e) {
for (var i = 0; i < testCount; ++i) {
ws.send(testMessage + (i + 1));
gTestElement.textContent += "\nSending :";
for (var i = 1; i <= testCount; ++i) {
if (i % displayInterval == 1) {
gTestElement.textContent += " " + i;
}
ws.send(testMessage + i);
}
gTestElement.textContent += " end";
ws.send("end");
}
// Set this before onmessage() is called, so it is displayed once only.
gTestElement.textContent += "\nReceived:";
};
ws.onclose = function(e) {
is(messageCount, testCount, "Didn't receive all the messages!");
ok(e.wasClean, "Connection closed cleanly");
testWebSocket3();
}
is(messageCount, testCount + 1, "[2] Number of received messages");
ok(e.wasClean, "[2] Connection closed cleanly");
SimpleTest.executeSoon(testWebSocket3);
};
ws.onerror = function(e) {
ok(false, "onerror called!");
finishWSTest();
}
ok(false, "[2] onerror() should not have been called!");
gTestElement.textContent += "\nonerror() should not have been called!";
SimpleTest.executeSoon(SimpleTest.finish);
};
ws.onmessage = function(e) {
++messageCount;
is(e.data, testMessage + messageCount, "Wrong message");
document.getElementById('log').textContent = messageCount;
if (messageCount == testCount) {
this.onmessage = null;
if (messageCount > testCount)
is(e.data, "end", "[2] Received message");
else
is(e.data, testMessage + messageCount, "[2] Received message");
if (messageCount % displayInterval == 1) {
gTestElement.textContent += " " + messageCount;
}
}
};
}
/**
* Sends 100+1 test messages, then receives them, calling forcegc() at each step.
*/
function testWebSocket3() {
ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_basic", "test");
var testCount = 100; // Send lots of messages
gTestElement.textContent = "Running testWebSocket3() [can take a little while]";
const displayInterval = 10;
const testCount = 100;
const testMessage = "test message 3.";
var messageCount = 0;
var testMessage = "test message";
ws = new WebSocket(kUrl, "test");
// Set this before onopen() is called,
// otherwise its display would be delayed by forcegc() calls...
gTestElement.textContent += "\nSending :";
ws.onopen = function(e) {
for (var i = 0; i < testCount; ++i) {
forcegc(); // Do something evil, call cycle collector a lot.
ws.send(testMessage + (i + 1));
for (var i = 1; i <= testCount; ++i) {
forcegc();
if (i % displayInterval == 1) {
// Actual display is delayed by forcegc() calls...
gTestElement.textContent += " " + i;
}
ws.send(testMessage + i);
}
forcegc();
gTestElement.textContent += " end";
ws.send("end");
}
// Set this before onmessage() is called, so it is displayed once only.
gTestElement.textContent += "\nReceived:";
};
ws.onclose = function(e) {
is(messageCount, testCount, "Didn't receive all the messages!");
ok(e.wasClean, "Connection closed cleanly");
testWebSocket4();
}
is(messageCount, testCount + 1, "[3] Number of received messages");
ok(e.wasClean, "[3] Connection closed cleanly");
SimpleTest.executeSoon(testWebSocket4);
};
ws.onerror = function(e) {
ok(false, "onerror called!");
finishWSTest();
}
ok(false, "[3] onerror() should not have been called!");
gTestElement.textContent += "\nonerror() should not have been called!";
SimpleTest.executeSoon(SimpleTest.finish);
};
ws.onmessage = function(e) {
forcegc(); // Do something evil, call cycle collector a lot.
forcegc();
++messageCount;
is(e.data, testMessage + messageCount, "Wrong message");
document.getElementById('log').textContent = messageCount;
if (messageCount == testCount) {
this.onmessage = null;
if (messageCount > testCount)
is(e.data, "end", "[3] Received message");
else
is(e.data, testMessage + messageCount, "[3] Received message");
if (messageCount % displayInterval == 1) {
// Actual display is delayed by forcegc() call(s)...
gTestElement.textContent += " " + messageCount;
}
}
};
}
/**
* Sends a huge test message, then receives it, then closes the WebSocket from client-side.
*/
function testWebSocket4() {
ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_basic", "test");
// String length = (10,000 - 1) * 23 = 229,977 = almost 225 KiB.
var longString = new Array(10000).join("-huge websocket message");
gTestElement.textContent = "Running testWebSocket4()";
// String length = 13 + ((10,000 - 1) * 26) + 11 = 259,998 = almost 254 KiB.
const longString = "messageStart " + new Array(10000).join(" -huge WebSocket message- ") + " messageEnd";
ws = new WebSocket(kUrl, "test");
ws.onopen = function(e) {
is(this, ws, "'this' should point to the WebSocket. (1)");
is(this, ws, "[4, onopen()] 'this' should point to the WebSocket.");
gTestElement.textContent += "\nSending the huge message";
ws.send(longString);
}
};
ws.onclose = function(e) {
is(this, ws, "'this' should point to the WebSocket. (2)");
ok(e.wasClean, "Connection closed cleanly");
testWebSocket5();
}
is(this, ws, "[4, onclose()] 'this' should point to the WebSocket.");
ok(e.wasClean, "[4] Connection closed cleanly");
SimpleTest.executeSoon(testWebSocket5);
};
ws.onerror = function(e) {
ok(false, "onerror called!");
finishWSTest();
}
is(this, ws, "[4, onerror()] 'this' should point to the WebSocket.");
ok(false, "[4, onerror()] should not have been called!");
gTestElement.textContent += "\nonerror() should not have been called!";
SimpleTest.executeSoon(SimpleTest.finish);
};
ws.onmessage = function(e) {
is(this, ws, "'this' should point to the WebSocket. (3)");
is(this, ws, "[4, onmessage()] 'this' should point to the WebSocket.");
// Do not use |is(e.data, longString, "...");| that results in a _very_ long line.
is(e.data.length, longString.length, "Length of received message");
ok(e.data == longString, "Content of received message");
document.getElementById('log').textContent += "\nReceived the huge message";
is(e.data.length, longString.length, "[4] Length of received message");
ok(e.data == longString, "[4] Content of received message");
gTestElement.textContent += "\nReceived the huge message";
this.close();
}
};
}
/**
* Closes the WebSocket from client-side, then sends a test message that should be buffered.
*/
function testWebSocket5() {
ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_basic", "test");
gTestElement.textContent = "Running testWebSocket5()";
ws = new WebSocket(kUrl, "test");
ws.onopen = function(e) {
is(this.bufferedAmount, 0, "[5] Length of empty buffer before closing");
this.close();
}
};
ws.onclose = function(e) {
ok(e.wasClean, "Connection closed cleanly");
is(this.bufferedAmount, 0, "Shouldn't have anything buffered");
var msg = "some data";
ok(e.wasClean, "[5] Connection closed cleanly");
is(this.bufferedAmount, 0, "[5] Length of empty buffer after closing");
var msg = "test message to be buffered";
this.send(msg);
is(this.bufferedAmount, msg.length, "Should have some data buffered");
finishWSTest();
}
is(this.bufferedAmount, msg.length, "[5] Length of buffered message sent after closing");
gTestElement.textContent += "\ntestWebSocket5() completed";
SimpleTest.executeSoon(SimpleTest.finish);
};
ws.onerror = function(e) {
ok(false, "onerror called!");
finishWSTest();
}
ok(false, "[5] onerror() should not have been called!");
gTestElement.textContent += "\nonerror() should not have been called!";
SimpleTest.executeSoon(SimpleTest.finish);
};
}
SimpleTest.waitForExplicitFinish();
</script>
<pre id="log">
</pre>
</pre>
<div>
</div>
</body>
</html>

View File

@ -0,0 +1,22 @@
<html>
<head>
<title></title>
<script type="text/javascript">
function go() {
var canvas = document.createElement("canvas");
var ctx = canvas.getContext('2d');
ctx.globalAlpha = 4
ctx.lineCap = "foo"
ctx.strokeRect(256,1024,8,4)
ctx.shadowColor = "black"
ctx.shadowOffsetY = 64
ctx.stroke()
ctx.moveTo(32,1024)
ctx.closePath()
}
</script>
</head>
<body onload="go()">
<canvas id="canvas"></canvas>
</body>
</html>

View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<script>
function boom()
{
var a = document.getElementById("a");
var b = document.getElementById("b");
a.getContext('2d').createPattern(b, 'no-repeat');
}
</script>
</head>
<body onload="boom();">
<canvas id="a" width="61" height="26"></canvas>
<canvas id="b" width="611" height="439807"></canvas>
</body>
</html>

View File

@ -6,3 +6,6 @@ load 0px-size-font-667225.html
load texImage2D.html
load 729116.html
load 745699-1.html
# this test crashes in a bunch places still
#load 745818-large-source.html
load 743499-negative-size.html

View File

@ -1973,7 +1973,7 @@ nsCanvasRenderingContext2DAzure::CreatePattern(nsIDOMHTMLElement *image,
}
// Ignore nsnull cairo surfaces! See bug 666312.
if (!res.mSurface->CairoSurface()) {
if (!res.mSurface->CairoSurface() || res.mSurface->CairoStatus()) {
return NS_OK;
}

View File

@ -58,7 +58,6 @@ enum FormControlsTypes {
NS_FORM_SELECT,
NS_FORM_TEXTAREA,
NS_FORM_OBJECT,
NS_FORM_PROGRESS,
eFormControlsWithoutSubTypesMax,
// After this, all types will have sub-types which introduce new enum lists.
// eFormControlsWithoutSubTypesMax let us know if the previous types values
@ -284,7 +283,6 @@ nsIFormControl::IsLabelableControl() const
// type == NS_FORM_KEYGEN ||
// type == NS_FORM_METER ||
type == NS_FORM_OUTPUT ||
type == NS_FORM_PROGRESS ||
type == NS_FORM_SELECT ||
type == NS_FORM_TEXTAREA;
}

View File

@ -2929,8 +2929,7 @@ nsGenericHTMLFormElement::CanBeDisabled() const
return
type != NS_FORM_LABEL &&
type != NS_FORM_OBJECT &&
type != NS_FORM_OUTPUT &&
type != NS_FORM_PROGRESS;
type != NS_FORM_OUTPUT;
}
bool

View File

@ -160,8 +160,7 @@ nsHTMLFieldSetElement::MatchListedElements(nsIContent* aContent, PRInt32 aNamesp
nsIAtom* aAtom, void* aData)
{
nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(aContent);
return formControl && formControl->GetType() != NS_FORM_LABEL &&
formControl->GetType() != NS_FORM_PROGRESS;
return formControl && formControl->GetType() != NS_FORM_LABEL;
}
NS_IMETHODIMP

View File

@ -223,7 +223,6 @@ ShouldBeInElements(nsIFormControl* aFormControl)
//
// NS_FORM_INPUT_IMAGE
// NS_FORM_LABEL
// NS_FORM_PROGRESS
return false;
}

View File

@ -41,7 +41,7 @@
#include "nsEventStateManager.h"
class nsHTMLProgressElement : public nsGenericHTMLFormElement,
class nsHTMLProgressElement : public nsGenericHTMLElement,
public nsIDOMHTMLProgressElement
{
public:
@ -52,22 +52,17 @@ public:
NS_DECL_ISUPPORTS_INHERITED
// nsIDOMNode
NS_FORWARD_NSIDOMNODE(nsGenericHTMLFormElement::)
NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
// nsIDOMElement
NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLFormElement::)
NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
// nsIDOMHTMLElement
NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLFormElement::)
NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
// nsIDOMHTMLProgressElement
NS_DECL_NSIDOMHTMLPROGRESSELEMENT
// nsIFormControl
NS_IMETHOD_(PRUint32) GetType() const { return NS_FORM_PROGRESS; }
NS_IMETHOD Reset();
NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission);
nsEventStates IntrinsicState() const;
nsresult Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const;
@ -100,7 +95,7 @@ NS_IMPL_NS_NEW_HTML_ELEMENT(Progress)
nsHTMLProgressElement::nsHTMLProgressElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLFormElement(aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
{
// We start out indeterminate
AddStatesSilently(NS_EVENT_STATE_INDETERMINATE);
@ -119,30 +114,16 @@ NS_INTERFACE_TABLE_HEAD(nsHTMLProgressElement)
NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLProgressElement,
nsIDOMHTMLProgressElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLProgressElement,
nsGenericHTMLFormElement)
nsGenericHTMLElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLProgressElement)
NS_IMPL_ELEMENT_CLONE(nsHTMLProgressElement)
NS_IMETHODIMP
nsHTMLProgressElement::Reset()
{
// The progress element is not resettable.
return NS_OK;
}
NS_IMETHODIMP
nsHTMLProgressElement::SubmitNamesValues(nsFormSubmission* aFormSubmission)
{
// The progress element is not submittable.
return NS_OK;
}
nsEventStates
nsHTMLProgressElement::IntrinsicState() const
{
nsEventStates state = nsGenericHTMLFormElement::IntrinsicState();
nsEventStates state = nsGenericHTMLElement::IntrinsicState();
if (IsIndeterminate()) {
state |= NS_EVENT_STATE_INDETERMINATE;
@ -161,14 +142,8 @@ nsHTMLProgressElement::ParseAttribute(PRInt32 aNamespaceID, nsIAtom* aAttribute,
}
}
return nsGenericHTMLFormElement::ParseAttribute(aNamespaceID, aAttribute,
aValue, aResult);
}
NS_IMETHODIMP
nsHTMLProgressElement::GetForm(nsIDOMHTMLFormElement** aForm)
{
return nsGenericHTMLFormElement::GetForm(aForm);
return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute,
aValue, aResult);
}
NS_IMETHODIMP

View File

@ -29,7 +29,6 @@ function checkFormIDLAttribute(aElement)
{
var form = document.forms[0];
var content = document.getElementById('content');
is(aElement.form, form, "The form IDL attribute should be the parent form");
content.removeChild(form);
content.appendChild(aElement);
@ -226,20 +225,6 @@ function checkFormListedElement(aElement)
is(document.forms[0].elements.length, 0, "the form should have no element");
}
function checkLabelable(aElement)
{
var content = document.getElementById('content');
var label = document.createElement('label');
content.appendChild(label);
label.appendChild(aElement);
is(label.control, aElement, "progress should be labelable");
// Cleaning-up.
content.removeChild(label);
content.appendChild(aElement);
}
function checkNotResetableAndFormSubmission(aElement)
{
// Creating an input element to check the submission worked.
@ -312,8 +297,6 @@ checkIndeterminatePseudoClass();
checkFormListedElement(p);
checkLabelable(p);
checkNotResetableAndFormSubmission(p);
</script>

View File

@ -400,7 +400,7 @@ var forms = [
var elementNames = [
'button', 'fieldset', 'input', 'label', 'object', 'output', 'select',
'textarea', 'progress',
'textarea',
];
var todoElements = [

View File

@ -47,13 +47,12 @@
* @status UNDER_DEVELOPMENT
*/
[scriptable, uuid(842AEE33-8381-4DA4-A347-9E70C797BC3E)]
[scriptable, uuid(275851c9-c3e2-4427-a770-3d2aaad6c546)]
interface nsIDOMHTMLProgressElement : nsIDOMHTMLElement
{
attribute double value;
attribute double max;
readonly attribute double position;
readonly attribute nsIDOMHTMLFormElement form;
/**
* The labels attribute will be done with bug 567740.
*/

View File

@ -150,7 +150,7 @@ function RadioInterfaceLayer() {
this.radioState = {
radioState: RIL.GECKO_RADIOSTATE_UNAVAILABLE,
cardState: RIL.GECKO_CARDSTATE_UNAVAILABLE,
msisdn: null,
icc: null,
// These objects implement the nsIDOMMozMobileConnectionInfo interface,
// although the actual implementation lives in the content process.
@ -173,6 +173,7 @@ function RadioInterfaceLayer() {
Services.obs.addObserver(this, "xpcom-shutdown", false);
this._sentSmsEnvelopes = {};
this.portAddressedSmsApps = {};
}
RadioInterfaceLayer.prototype = {
@ -276,8 +277,8 @@ RadioInterfaceLayer.prototype = {
" dst=" + message.dstFlag +
" timestamp=" + message.localTimeStampInMS);
break;
case "siminfo":
this.radioState.msisdn = message.msisdn;
case "iccinfochange":
this.radioState.icc = message;
break;
default:
throw new Error("Don't know about this message type: " + message.type);
@ -460,8 +461,26 @@ RadioInterfaceLayer.prototype = {
}
},
portAddressedSmsApps: null,
handleSmsReceived: function handleSmsReceived(message) {
debug("handleSmsReceived: " + JSON.stringify(message));
// Dispatch to registered handler if application port addressing is
// available. Note that the destination port can possibly be zero when
// representing a UDP/TCP port.
if (message.header.destinationPort != null) {
let handler = this.portAddressedSmsApps[message.header.destinationPort];
if (handler) {
handler(message);
}
return;
}
if (message.encoding == RIL.PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
// Don't know how to handle binary data yet.
return;
}
let id = gSmsDatabaseService.saveReceivedMessage(message.sender || null,
message.fullBody || null,
message.timestamp);

View File

@ -373,34 +373,35 @@ const CALL_PRESENTATION_UNKNOWN = 2;
const CALL_PRESENTATION_PAYPHONE = 3;
// ICC commands, see TS 27.007 +CRSM commands
const ICC_COMMAND_READ_BINARY = 0xb0;
const ICC_COMMAND_UPDATE_BINARY = 0xd6;
const ICC_COMMAND_READ_RECORD = 0xb2;
const ICC_COMMAND_UPDATE_RECORD = 0xdc;
const ICC_COMMAND_SEEK = 0xa2;
const ICC_COMMAND_READ_BINARY = 0xb0;
const ICC_COMMAND_READ_RECORD = 0xb2;
const ICC_COMMAND_GET_RESPONSE = 0xc0;
const ICC_COMMAND_UPDATE_BINARY = 0xd6;
const ICC_COMMAND_UPDATE_RECORD = 0xdc;
// ICC constants, GSM SIM file ids from TS 51.011
const ICC_EF_ADN = 0x6F3A;
const ICC_EF_FDN = 0x6F3B;
const ICC_EF_SDN = 0x6F49;
const ICC_EF_EXT1 = 0x6F4A;
const ICC_EF_EXT2 = 0x6F4B;
const ICC_EF_EXT3 = 0x6F4C;
const ICC_EF_EXT6 = 0x6fc8; // Ext record for EF[MBDN]
const ICC_EF_MWIS = 0x6FCA;
const ICC_EF_MBDN = 0x6fc7;
const ICC_EF_PNN = 0x6fc5;
const ICC_EF_SPN = 0x6F46;
const ICC_EF_SMS = 0x6F3C;
const ICC_EF_ICCID = 0x2fe2;
const ICC_EF_AD = 0x6FAD;
const ICC_EF_MBI = 0x6fc9;
const ICC_EF_ICCID = 0x2fe2;
const ICC_EF_IMG = 0x4f20;
const ICC_EF_SST = 0x6f38;
const ICC_EF_UST = 0x6f38; // For USIM
const ICC_EF_ADN = 0x6f3a;
const ICC_EF_FDN = 0x6f3b;
const ICC_EF_SMS = 0x6f3c;
const ICC_EF_MSISDN = 0x6f40;
const ICC_EF_SPDI = 0x6fcd;
const ICC_EF_SST = 0x6f38;
const ICC_EF_CFIS = 0x6FCB;
const ICC_EF_IMG = 0x4f20;
const ICC_EF_SPN = 0x6f46;
const ICC_EF_SDN = 0x6f49;
const ICC_EF_EXT1 = 0x6f4a;
const ICC_EF_EXT2 = 0x6f4b;
const ICC_EF_EXT3 = 0x6f4c;
const ICC_EF_AD = 0x6fad;
const ICC_EF_PNN = 0x6fc5;
const ICC_EF_MBDN = 0x6fc7;
const ICC_EF_EXT6 = 0x6fc8; // Ext record for EF[MBDN]
const ICC_EF_MBI = 0x6fc9;
const ICC_EF_MWIS = 0x6fca;
const ICC_EF_CFIS = 0x6fcb;
const ICC_EF_SPDI = 0x6fcd;
// Types of files TS 11.11 9.3
const TYPE_RFU = 0;
@ -408,6 +409,7 @@ const TYPE_MF = 1;
const TYPE_DF = 2;
const TYPE_EF = 4;
const RESPONSE_DATA_FILE_SIZE = 2;
const RESPONSE_DATA_FILE_ID_1 = 4;
const RESPONSE_DATA_FILE_ID_2 = 5;
const RESPONSE_DATA_FILE_TYPE = 6;
@ -425,9 +427,9 @@ const EF_TYPE_TRANSPARENT = 0;
const EF_TYPE_LINEAR_FIXED = 1;
const EF_TYPE_CYCLIC = 3;
// For retriveing MSISDN
const FOOTER_SIZE_BYTES = 14;
const MAX_NUMBER_SIZE_BYTES = 11;
// For retrieving MSISDN, TS 151.011 clause 10.5.5
const MSISDN_FOOTER_SIZE_BYTES = 14;
const MSISDN_MAX_NUMBER_SIZE_BYTES = 10;
// READ_RECORD mode, TS 102.221
const READ_RECORD_ABSOLUTE_MODE = 4;
@ -439,6 +441,7 @@ const GET_RESPONSE_EF_SIZE_BYTES = 15;
// EF path
const EF_PATH_MF_SIM = "3f00";
const EF_PATH_DF_TELECOM = "7f10";
const EF_PATH_DF_GSM = "7f20";
// Status code of sw1 for ICC I/O,
// see GSM11.11 and TS 51.011 clause 9.4, and ISO 7816-4
@ -655,6 +658,10 @@ const PDU_IEI_ENHANCED_VOICE_MAIL_INFORMATION = 0x23;
const PDU_IEI_NATIONAL_LANGUAGE_SINGLE_SHIFT = 0x24;
const PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT = 0x25;
// Application Port Addressing, see 3GPP TS 23.040 9.2.3.24.3
const PDU_APA_RESERVED_8BIT_PORTS = 240;
const PDU_APA_VALID_16BIT_PORTS = 49152;
// 7bit alphabet escape character. The encoded value of this code point is left
// undefined in official spec. Its code value is internally assigned to \uffff,
// <noncharacter-FFFF> in Unicode basic multilingual plane.

View File

@ -75,6 +75,8 @@ const UINT16_SIZE = 2;
const UINT32_SIZE = 4;
const PARCEL_SIZE_SIZE = UINT32_SIZE;
const PDU_HEX_OCTET_SIZE = 4;
let RILQUIRKS_CALLSTATE_EXTRA_UINT32 = false;
let RILQUIRKS_DATACALLSTATE_DOWN_IS_UP = false;
// This flag defaults to true since on RIL v6 and later, we get the
@ -202,6 +204,51 @@ let Buf = {
* These are all little endian, apart from readParcelSize();
*/
/**
* Ensure position specified is readable.
*
* @param index
* Data position in incoming parcel, valid from 0 to
* this.currentParcelSize.
*/
ensureIncomingAvailable: function ensureIncomingAvailable(index) {
if (index >= this.currentParcelSize) {
throw new Error("Trying to read data beyond the parcel end!");
} else if (index < 0) {
throw new Error("Trying to read data before the parcel begin!");
}
},
/**
* Seek in current incoming parcel.
*
* @param offset
* Seek offset in relative to current position.
*/
seekIncoming: function seekIncoming(offset) {
// Translate to 0..currentParcelSize
let cur = this.currentParcelSize - this.readAvailable;
let newIndex = cur + offset;
this.ensureIncomingAvailable(newIndex);
// ... incomingReadIndex -->|
// 0 new cur currentParcelSize
// |================|=======|===================|
// |<-- cur -->|<- readAvailable ->|
// |<-- newIndex -->|<-- new readAvailable -->|
this.readAvailable = this.currentParcelSize - newIndex;
// Translate back:
if (this.incomingReadIndex < cur) {
// The incomingReadIndex is wrapped.
newIndex += this.INCOMING_BUFFER_LENGTH;
}
newIndex += (this.incomingReadIndex - cur);
newIndex %= this.INCOMING_BUFFER_LENGTH;
this.incomingReadIndex = newIndex;
},
readUint8Unchecked: function readUint8Unchecked() {
let value = this.incomingBytes[this.incomingReadIndex];
this.incomingReadIndex = (this.incomingReadIndex + 1) %
@ -210,9 +257,9 @@ let Buf = {
},
readUint8: function readUint8() {
if (!this.readAvailable) {
throw new Error("Trying to read data beyond the parcel end!");
}
// Translate to 0..currentParcelSize
let cur = this.currentParcelSize - this.readAvailable;
this.ensureIncomingAvailable(cur);
this.readAvailable--;
return this.readUint8Unchecked();
@ -567,9 +614,12 @@ let RIL = {
*/
IMEI: null,
IMEISV: null,
IMSI: null,
SMSC: null,
MSISDN: null,
/**
* ICC information, such as MSISDN, IMSI, ...etc.
*/
iccInfo: {},
voiceRegistrationState: {},
dataRegistrationState: {},
@ -766,10 +816,10 @@ let RIL = {
*
* @param command
* The I/O command, one of the ICC_COMMAND_* constants.
* @param fileid
* @param fileId
* The file to operate on, one of the ICC_EF_* constants.
* @param pathid
* String type, check pathid from TS 27.007 +CRSM
* @param pathId
* String type, check the 'pathid' parameter from TS 27.007 +CRSM.
* @param p1, p2, p3
* Arbitrary integer parameters for the command.
* @param data
@ -780,8 +830,8 @@ let RIL = {
iccIO: function iccIO(options) {
let token = Buf.newParcel(REQUEST_SIM_IO, options);
Buf.writeUint32(options.command);
Buf.writeUint32(options.fileid);
Buf.writeString(options.pathid);
Buf.writeUint32(options.fileId);
Buf.writeString(options.pathId);
Buf.writeUint32(options.p1);
Buf.writeUint32(options.p2);
Buf.writeUint32(options.p3);
@ -792,19 +842,183 @@ let RIL = {
Buf.sendParcel();
},
/**
* Fetch ICC records.
*/
fetchICCRecords: function fetchICCRecords() {
this.getIMSI();
this.getMSISDN();
this.getAD();
this.getUST();
},
/**
* Update the ICC information to RadioInterfaceLayer.
*/
_handleICCInfoChange: function _handleICCInfoChange() {
this.iccInfo.type = "iccinfochange";
this.sendDOMMessage(this.iccInfo);
},
getIMSI: function getIMSI() {
Buf.simpleRequest(REQUEST_GET_IMSI);
},
/**
* Read the MSISDN from the ICC.
*/
getMSISDN: function getMSISDN() {
function callback() {
let length = Buf.readUint32();
// Each octet is encoded into two chars.
let recordLength = length / 2;
// Skip prefixed alpha identifier
Buf.seekIncoming((recordLength - MSISDN_FOOTER_SIZE_BYTES) *
PDU_HEX_OCTET_SIZE);
// Dialling Number/SSC String
let len = GsmPDUHelper.readHexOctet();
if (len > MSISDN_MAX_NUMBER_SIZE_BYTES) {
debug("ICC_EF_MSISDN: invalid length of BCD number/SSC contents - " + len);
return;
}
this.iccInfo.MSISDN = GsmPDUHelper.readAddress(len);
let delimiter = Buf.readUint16();
if (!(length & 1)) {
delimiter |= Buf.readUint16();
}
if (DEBUG) {
if (delimiter != 0) {
debug("Something's wrong, found string delimiter: " + delimiter);
}
}
if (DEBUG) debug("MSISDN: " + this.iccInfo.MSISDN);
if (this.iccInfo.MSISDN) {
this._handleICCInfoChange();
}
}
this.iccIO({
command: ICC_COMMAND_GET_RESPONSE,
fileid: ICC_EF_MSISDN,
pathid: EF_PATH_MF_SIM + EF_PATH_DF_TELECOM,
p1: 0, // For GET_RESPONSE, p1 = 0
p2: 0, // For GET_RESPONSE, p2 = 0
p3: GET_RESPONSE_EF_SIZE_BYTES,
data: null,
pin2: null,
command: ICC_COMMAND_GET_RESPONSE,
fileId: ICC_EF_MSISDN,
pathId: EF_PATH_MF_SIM + EF_PATH_DF_TELECOM,
p1: 0, // For GET_RESPONSE, p1 = 0
p2: 0, // For GET_RESPONSE, p2 = 0
p3: GET_RESPONSE_EF_SIZE_BYTES,
data: null,
pin2: null,
type: EF_TYPE_LINEAR_FIXED,
callback: callback,
});
},
/**
* Read the AD from the ICC.
*/
getAD: function getAD() {
function callback() {
let length = Buf.readUint32();
// Each octet is encoded into two chars.
let len = length / 2;
this.iccInfo.AD = GsmPDUHelper.readHexOctetArray(len);
let delimiter = Buf.readUint16();
if (!(length & 1)) {
delimiter |= Buf.readUint16();
}
if (DEBUG) {
if (delimiter != 0) {
debug("Something's wrong, found string delimiter: " + delimiter);
}
}
if (DEBUG) {
let str = "";
for (let i = 0; i < this.iccInfo.AD.length; i++) {
str += this.iccInfo.AD[i] + ", ";
}
debug("AD: " + str);
}
if (this.iccInfo.IMSI) {
// MCC is the first 3 digits of IMSI
this.iccInfo.MCC = this.iccInfo.IMSI.substr(0,3);
// The 4th byte of the response is the length of MNC
this.iccInfo.MNC = this.iccInfo.IMSI.substr(3, this.iccInfo.AD[3]);
if (DEBUG) debug("MCC: " + this.iccInfo.MCC + " MNC: " + this.iccInfo.MNC);
this._handleICCInfoChange();
}
}
this.iccIO({
command: ICC_COMMAND_GET_RESPONSE,
fileId: ICC_EF_AD,
pathId: EF_PATH_MF_SIM + EF_PATH_DF_GSM,
p1: 0, // For GET_RESPONSE, p1 = 0
p2: 0, // For GET_RESPONSE, p2 = 0
p3: GET_RESPONSE_EF_SIZE_BYTES,
data: null,
pin2: null,
type: EF_TYPE_TRANSPARENT,
callback: callback,
});
},
/**
* Get whether specificed USIM service is available.
*
* @param service
* Service id, valid in 1..N. See 3GPP TS 31.102 4.2.8.
* @return
* true if the service is enabled,
* false otherwise.
*/
isUSTServiceAvailable: function isUSTServiceAvailable(service) {
service -= 1;
let index = service / 8;
let bitmask = 1 << (service % 8);
return this.UST && (index < this.UST.length) && (this.UST[index] & bitmask);
},
/**
* Read the UST from the ICC.
*/
getUST: function getUST() {
function callback() {
let length = Buf.readUint32();
// Each octet is encoded into two chars.
let len = length / 2;
this.iccInfo.UST = GsmPDUHelper.readHexOctetArray(len);
let delimiter = Buf.readUint16();
if (!(length & 1)) {
delimiter |= Buf.readUint16();
}
if (DEBUG) {
if (delimiter != 0) {
debug("Something's wrong, found string delimiter: " + delimiter);
}
}
if (DEBUG) {
let str = "";
for (let i = 0; i < this.iccInfo.UST.length; i++) {
str += this.iccInfo.UST[i] + ", ";
}
debug("UST: " + str);
}
}
this.iccIO({
command: ICC_COMMAND_GET_RESPONSE,
fileId: ICC_EF_UST,
pathId: EF_PATH_MF_SIM + EF_PATH_DF_GSM,
p1: 0, // For GET_RESPONSE, p1 = 0
p2: 0, // For GET_RESPONSE, p2 = 0
p3: GET_RESPONSE_EF_SIZE_BYTES,
data: null,
pin2: null,
type: EF_TYPE_TRANSPARENT,
callback: callback,
});
},
@ -1263,7 +1477,7 @@ let RIL = {
case CARD_APPSTATE_READY:
this.requestNetworkInfo();
this.getSignalStrength();
this.getMSISDN();
this.fetchICCRecords();
newCardState = GECKO_CARDSTATE_READY;
break;
case CARD_APPSTATE_UNKNOWN:
@ -1281,33 +1495,119 @@ let RIL = {
},
/**
* Process the MSISDN ICC I/O response.
* Process a ICC_COMMAND_GET_RESPONSE type command for REQUEST_SIM_IO.
*/
_processMSISDNResponse: function _processMSISDNResponse(options) {
_processICCIOGetResponse: function _processICCIOGetResponse(options) {
let length = Buf.readUint32();
// The format is from TS 51.011, clause 9.2.1
// Skip RFU, data[0] data[1]
Buf.seekIncoming(2 * PDU_HEX_OCTET_SIZE);
// File size, data[2], data[3]
let fileSize = (GsmPDUHelper.readHexOctet() << 8) |
GsmPDUHelper.readHexOctet();
// 2 bytes File id. data[4], data[5]
let fileId = (GsmPDUHelper.readHexOctet() << 8) |
GsmPDUHelper.readHexOctet();
if (fileId != options.fileId) {
if (DEBUG) {
debug("Expected file ID " + options.fileId + " but read " + fileId);
}
return;
}
// Type of file, data[6]
let fileType = GsmPDUHelper.readHexOctet();
if (fileType != TYPE_EF) {
if (DEBUG) {
debug("Unexpected file type " + fileType);
}
return;
}
// Skip 1 byte RFU, data[7],
// 3 bytes Access conditions, data[8] data[9] data[10],
// 1 byte File status, data[11],
// 1 byte Length of the following data, data[12].
Buf.seekIncoming(((RESPONSE_DATA_STRUCTURE - RESPONSE_DATA_FILE_TYPE - 1) *
PDU_HEX_OCTET_SIZE));
// Read Structure of EF, data[13]
let efType = GsmPDUHelper.readHexOctet();
if (efType != options.type) {
if (DEBUG) {
debug("Expected EF type " + options.type + " but read " + efType);
}
return;
}
// Length of a record, data[14]
let recordSize = GsmPDUHelper.readHexOctet();
let delimiter = Buf.readUint16();
if (!(length & 1)) {
delimiter |= Buf.readUint16();
}
if (DEBUG) {
if (delimiter != 0) {
debug("Something's wrong, found string delimiter: " + delimiter);
}
}
switch (options.type) {
case EF_TYPE_LINEAR_FIXED:
// Reuse the options object and update some properties.
options.command = ICC_COMMAND_READ_RECORD;
options.p1 = 1; // Record number, always use the 1st record
options.p2 = READ_RECORD_ABSOLUTE_MODE;
options.p3 = recordSize;
this.iccIO(options);
break;
case EF_TYPE_TRANSPARENT:
// Reuse the options object and update some properties.
options.command = ICC_COMMAND_READ_BINARY;
options.p3 = fileSize;
this.iccIO(options);
break;
}
},
/**
* Process a ICC_COMMAND_READ_RECORD type command for REQUEST_SIM_IO.
*/
_processICCIOReadRecord: function _processICCIOReadRecord(options) {
if (options.callback) {
options.callback.call(this);
}
},
/**
* Process a ICC_COMMAND_READ_BINARY type command for REQUEST_SIM_IO.
*/
_processICCIOReadBinary: function _processICCIOReadBinary(options) {
if (options.callback) {
options.callback.call(this);
}
},
/**
* Process ICC I/O response.
*/
_processICCIO: function _processICCIO(options) {
switch (options.command) {
case ICC_COMMAND_GET_RESPONSE:
let response = Buf.readString();
let recordSize = parseInt(
response.substr(RESPONSE_DATA_RECORD_LENGTH * 2, 2), 16) & 0xff;
let options = {
command: ICC_COMMAND_READ_RECORD,
fileid: ICC_EF_MSISDN,
pathid: EF_PATH_MF_SIM + EF_PATH_DF_TELECOM,
p1: 1, // Record number, MSISDN is always in the 1st record
p2: READ_RECORD_ABSOLUTE_MODE,
p3: recordSize,
data: null,
pin2: null,
};
this.iccIO(options);
this._processICCIOGetResponse(options);
break;
case ICC_COMMAND_READ_RECORD:
// Ignore 2 bytes prefix, which is 4 chars
let number = GsmPDUHelper.readStringAsBCD().toString().substr(4);
if (DEBUG) debug("MSISDN: " + number);
this.MSISDN = number || null;
this.sendDOMMessage({type: "siminfo", msisdn: this.MSISDN});
this._processICCIOReadRecord(options);
break;
case ICC_COMMAND_READ_BINARY:
this._processICCIOReadBinary(options);
break;
}
},
@ -1550,7 +1850,13 @@ let RIL = {
if (message.header && (message.header.segmentMaxSeq > 1)) {
message = this._processReceivedSmsSegment(message);
} else {
message.fullBody = message.body;
if (message.encoding == PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
message.fullData = message.data;
delete message.data;
} else {
message.fullBody = message.body;
delete message.body;
}
}
if (message) {
@ -1629,7 +1935,7 @@ let RIL = {
* Helper for processing received multipart SMS.
*
* @return null for handled segments, and an object containing full message
* body once all segments are received.
* body/data once all segments are received.
*/
_processReceivedSmsSegment: function _processReceivedSmsSegment(original) {
let hash = original.sender + ":" + original.header.segmentRef;
@ -1652,7 +1958,13 @@ let RIL = {
return null;
}
options.segments[seq] = original.body;
if (options.encoding == PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
options.segments[seq] = original.data;
delete original.data;
} else {
options.segments[seq] = original.body;
delete original.body;
}
options.receivedSegments++;
if (options.receivedSegments < options.segmentMaxSeq) {
if (DEBUG) {
@ -1666,9 +1978,23 @@ let RIL = {
delete this._receivedSmsSegmentsMap[hash];
// Rebuild full body
options.fullBody = "";
for (let i = 1; i <= options.segmentMaxSeq; i++) {
options.fullBody += options.segments[i];
if (options.encoding == PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
// Uint8Array doesn't have `concat`, so we have to merge all segements
// by hand.
let fullDataLen = 0;
for (let i = 1; i <= options.segmentMaxSeq; i++) {
fullDataLen += options.segments[i].length;
}
options.fullData = new Uint8Array(fullDataLen);
for (let d= 0, i = 1; i <= options.segmentMaxSeq; i++) {
let data = options.segments[i];
for (let j = 0; j < data.length; j++) {
options.fullData[d++] = data[j];
}
}
} else {
options.fullBody = options.segments.join("");
}
if (DEBUG) {
@ -1869,7 +2195,7 @@ RIL[REQUEST_GET_IMSI] = function REQUEST_GET_IMSI(length, options) {
return;
}
this.IMSI = Buf.readString();
this.iccInfo.IMSI = Buf.readString();
};
RIL[REQUEST_HANGUP] = function REQUEST_HANGUP(length, options) {
if (options.rilRequestError) {
@ -2106,18 +2432,13 @@ RIL[REQUEST_SIM_IO] = function REQUEST_SIM_IO(length, options) {
// See GSM11.11, TS 51.011 clause 9.4, and ISO 7816-4 for the error
// description.
if (DEBUG) {
debug("ICC I/O Error EF id = " + options.fileid.toString(16) +
debug("ICC I/O Error EF id = " + options.fileId.toString(16) +
" command = " + options.command.toString(16) +
"(" + sw1.toString(16) + "/" + sw2.toString(16) + ")");
}
return;
}
switch (options.fileid) {
case ICC_EF_MSISDN:
this._processMSISDNResponse(options);
break;
}
this._processICCIO(options);
};
RIL[REQUEST_SEND_USSD] = null;
RIL[REQUEST_CANCEL_USSD] = null;
@ -2559,6 +2880,17 @@ let GsmPDUHelper = {
this.writeHexNibble(octet);
},
/**
* Read an array of hex-encoded octets.
*/
readHexOctetArray: function readHexOctetArray(length) {
let array = new Uint8Array(length);
for (let i = 0; i < length; i++) {
array[i] = this.readHexOctet();
}
return array;
},
/**
* Convert an octet (number) to a BCD number.
*
@ -2863,6 +3195,35 @@ let GsmPDUHelper = {
}
break;
}
case PDU_IEI_APPLICATION_PORT_ADDREESING_SCHEME_8BIT: {
let dstp = this.readHexOctet();
let orip = this.readHexOctet();
dataAvailable -= 2;
if ((dstp < PDU_APA_RESERVED_8BIT_PORTS)
|| (orip < PDU_APA_RESERVED_8BIT_PORTS)) {
// 3GPP TS 23.040 clause 9.2.3.24.3: "A receiving entity shall
// ignore any information element where the value of the
// Information-Element-Data is Reserved or not supported"
break;
}
header.destinationPort = dstp;
header.originatorPort = orip;
break;
}
case PDU_IEI_APPLICATION_PORT_ADDREESING_SCHEME_16BIT: {
let dstp = (this.readHexOctet() << 8) | this.readHexOctet();
let orip = (this.readHexOctet() << 8) | this.readHexOctet();
dataAvailable -= 4;
// 3GPP TS 23.040 clause 9.2.3.24.4: "A receiving entity shall
// ignore any information element where the value of the
// Information-Element-Data is Reserved or not supported"
if ((dstp < PDU_APA_VALID_16BIT_PORTS)
&& (orip < PDU_APA_VALID_16BIT_PORTS)) {
header.destinationPort = dstp;
header.originatorPort = orip;
}
break;
}
case PDU_IEI_CONCATENATED_SHORT_MESSAGES_16BIT: {
let ref = (this.readHexOctet() << 8) | this.readHexOctet();
let max = this.readHexOctet();
@ -3014,6 +3375,55 @@ let GsmPDUHelper = {
msg.epid = PDU_PID_DEFAULT;
},
/**
* Read TP-Data-Coding-Scheme(TP-DCS)
*
* @param msg
* message object for output.
*
* @see 3GPP TS 23.040 9.2.3.10, 3GPP TS 23.038 4.
*/
readDataCodingScheme: function readDataCodingScheme(msg) {
let dcs = this.readHexOctet();
// 7 bit is the default fallback encoding.
let encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
switch (dcs & 0xC0) {
case 0x0:
// bits 7..4 = 00xx
switch (dcs & 0x0C) {
case 0x4:
encoding = PDU_DCS_MSG_CODING_8BITS_ALPHABET;
break;
case 0x8:
encoding = PDU_DCS_MSG_CODING_16BITS_ALPHABET;
break;
}
break;
case 0xC0:
// bits 7..4 = 11xx
switch (dcs & 0x30) {
case 0x20:
encoding = PDU_DCS_MSG_CODING_16BITS_ALPHABET;
break;
case 0x30:
if (!dcs & 0x04) {
encoding = PDU_DCS_MSG_CODING_8BITS_ALPHABET;
}
break;
}
break;
default:
// Falling back to default encoding.
break;
}
msg.dcs = dcs;
msg.encoding = encoding;
if (DEBUG) debug("PDU: message encoding is " + encoding + " bit.");
},
/**
* Read GSM TP-Service-Centre-Time-Stamp(TP-SCTS).
*
@ -3051,50 +3461,15 @@ let GsmPDUHelper = {
* length of user data to read in octets.
*/
readUserData: function readUserData(msg, length) {
let dcs = msg.dcs;
if (DEBUG) {
debug("Reading " + length + " bytes of user data.");
debug("Coding scheme: " + dcs);
}
// 7 bit is the default fallback encoding.
let encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
switch (dcs & 0xC0) {
case 0x0:
// bits 7..4 = 00xx
switch (dcs & 0x0C) {
case 0x4:
encoding = PDU_DCS_MSG_CODING_8BITS_ALPHABET;
break;
case 0x8:
encoding = PDU_DCS_MSG_CODING_16BITS_ALPHABET;
break;
}
break;
case 0xC0:
// bits 7..4 = 11xx
switch (dcs & 0x30) {
case 0x20:
encoding = PDU_DCS_MSG_CODING_16BITS_ALPHABET;
break;
case 0x30:
if (!dcs & 0x04) {
encoding = PDU_DCS_MSG_CODING_8BITS_ALPHABET;
}
break;
}
break;
default:
// Falling back to default encoding.
break;
}
if (DEBUG) debug("PDU: message encoding is " + encoding + " bit.");
let paddingBits = 0;
if (msg.udhi) {
msg.header = this.readUserDataHeader();
if (encoding == PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
if (msg.encoding == PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
let headerBits = (msg.header.length + 1) * 8;
let headerSeptets = Math.ceil(headerBits / 7);
@ -3106,7 +3481,8 @@ let GsmPDUHelper = {
}
msg.body = null;
switch (encoding) {
msg.data = null;
switch (msg.encoding) {
case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
// 7 bit encoding allows 140 octets, which means 160 characters
// ((140x8) / 7 = 160 chars)
@ -3121,7 +3497,7 @@ let GsmPDUHelper = {
langShiftIndex);
break;
case PDU_DCS_MSG_CODING_8BITS_ALPHABET:
// Unsupported.
msg.data = this.readHexOctetArray(length);
break;
case PDU_DCS_MSG_CODING_16BITS_ALPHABET:
msg.body = this.readUCS2String(length);
@ -3157,6 +3533,7 @@ let GsmPDUHelper = {
// the receiving entity shall for TP-DCS assume a value of 0x00, i.e. the
// 7bit default alphabet.` ~ 3GPP 23.040 9.2.3.27
msg.dcs = 0;
msg.encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
// TP-Protocol-Identifier
if (pi & PDU_PI_PROTOCOL_IDENTIFIER) {
@ -3164,7 +3541,7 @@ let GsmPDUHelper = {
}
// TP-Data-Coding-Scheme
if (pi & PDU_PI_DATA_CODING_SCHEME) {
msg.dcs = this.readHexOctet();
this.readDataCodingScheme(msg);
}
// TP-User-Data-Length
if (pi & PDU_PI_USER_DATA_LENGTH) {
@ -3194,7 +3571,9 @@ let GsmPDUHelper = {
pid: null, // M O M O O M
epid: null, // M O M O O M
dcs: null, // M O M O O X
encoding: null, // M O M O O X
body: null, // M O M O O O
data: null, // M O M O O O
timestamp: null, // M X X X X X
status: null, // X X X X M X
scts: null, // X X X M M X
@ -3246,7 +3625,7 @@ let GsmPDUHelper = {
// - TP-Protocolo-Identifier -
this.readProtocolIndicator(msg);
// - TP-Data-Coding-Scheme -
msg.dcs = this.readHexOctet();
this.readDataCodingScheme(msg);
// - TP-Service-Center-Time-Stamp -
msg.timestamp = this.readTimestamp();
// - TP-User-Data-Length -

View File

@ -873,7 +873,7 @@ DrawTargetCG::Init(const IntSize &aSize, SurfaceFormat &)
{
// XXX: we should come up with some consistent semantics for dealing
// with zero area drawtargets
if (aSize.width == 0 || aSize.height == 0 ||
if (aSize.width <= 0 || aSize.height <= 0 ||
// 32767 is the maximum size supported by cairo
// we clamp to that to make it easier to interoperate
aSize.width > 32767 || aSize.height > 32767) {

View File

@ -10,7 +10,7 @@
#endif
>
<uses-sdk android:minSdkVersion="8"
android:targetSdkVersion="14"/>
android:targetSdkVersion="11"/>
#include ../sync/manifests/SyncAndroidManifest_permissions.xml.in

View File

@ -630,7 +630,8 @@ abstract public class GeckoApp
}
void handleLocationChange(final int tabId, final String uri,
final String documentURI, final String contentType) {
final String documentURI, final String contentType,
final boolean sameDocument) {
final Tab tab = Tabs.getInstance().getTab(tabId);
if (tab == null)
return;
@ -642,19 +643,10 @@ abstract public class GeckoApp
hideAboutHome();
}
String oldBaseURI = tab.getURL();
tab.updateURL(uri);
tab.setDocumentURI(documentURI);
tab.setContentType(contentType);
String baseURI = uri;
if (baseURI.indexOf('#') != -1)
baseURI = uri.substring(0, uri.indexOf('#'));
if (oldBaseURI != null && oldBaseURI.indexOf('#') != -1)
oldBaseURI = oldBaseURI.substring(0, oldBaseURI.indexOf('#'));
if (baseURI.equals(oldBaseURI)) {
if (sameDocument) {
mMainHandler.post(new Runnable() {
public void run() {
if (Tabs.getInstance().isSelectedTab(tab)) {
@ -665,6 +657,7 @@ abstract public class GeckoApp
return;
}
tab.setContentType(contentType);
tab.updateFavicon(null);
tab.updateFaviconURL(null);
tab.updateSecurityMode("unknown");
@ -868,8 +861,9 @@ abstract public class GeckoApp
final String uri = message.getString("uri");
final String documentURI = message.getString("documentURI");
final String contentType = message.getString("contentType");
final boolean sameDocument = message.getBoolean("sameDocument");
Log.i(LOGTAG, "URI - " + uri);
handleLocationChange(tabId, uri, documentURI, contentType);
handleLocationChange(tabId, uri, documentURI, contentType, sameDocument);
} else if (event.equals("Content:SecurityChange")) {
final int tabId = message.getInt("tabID");
final String mode = message.getString("mode");
@ -877,6 +871,7 @@ abstract public class GeckoApp
handleSecurityChange(tabId, mode);
} else if (event.equals("Content:StateChange")) {
final int tabId = message.getInt("tabID");
final String uri = message.getString("uri");
final boolean success = message.getBoolean("success");
int state = message.getInt("state");
Log.i(LOGTAG, "State - " + state);
@ -884,7 +879,7 @@ abstract public class GeckoApp
if ((state & GeckoAppShell.WPL_STATE_START) != 0) {
Log.i(LOGTAG, "Got a document start");
final boolean showProgress = message.getBoolean("showProgress");
handleDocumentStart(tabId, showProgress);
handleDocumentStart(tabId, showProgress, uri);
} else if ((state & GeckoAppShell.WPL_STATE_STOP) != 0) {
Log.i(LOGTAG, "Got a document stop");
handleDocumentStop(tabId, success);
@ -1190,11 +1185,12 @@ abstract public class GeckoApp
});
}
void handleDocumentStart(int tabId, final boolean showProgress) {
void handleDocumentStart(int tabId, final boolean showProgress, String uri) {
final Tab tab = Tabs.getInstance().getTab(tabId);
if (tab == null)
return;
tab.updateURL(uri);
tab.setState(Tab.STATE_LOADING);
tab.updateSecurityMode("unknown");
@ -1202,7 +1198,7 @@ abstract public class GeckoApp
public void run() {
if (Tabs.getInstance().isSelectedTab(tab)) {
mBrowserToolbar.setSecurityMode(tab.getSecurityMode());
if (showProgress)
if (showProgress && tab.getState() == Tab.STATE_LOADING)
mBrowserToolbar.setProgressVisibility(true);
}
Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.START);
@ -2163,7 +2159,8 @@ abstract public class GeckoApp
Log.i(LOGTAG, "application paused");
GeckoAppShell.sendEventToGecko(GeckoEvent.createPauseEvent(true));
mConnectivityReceiver.unregisterFor(mAppContext);
if (mConnectivityReceiver != null)
mConnectivityReceiver.unregisterFor(mAppContext);
GeckoNetworkManager.getInstance().stop();
GeckoScreenOrientationListener.getInstance().stop();
}
@ -2174,7 +2171,8 @@ abstract public class GeckoApp
if (checkLaunchState(LaunchState.GeckoRunning))
GeckoAppShell.sendEventToGecko(GeckoEvent.createResumeEvent(true));
mConnectivityReceiver.registerFor(mAppContext);
if (mConnectivityReceiver != null)
mConnectivityReceiver.registerFor(mAppContext);
GeckoNetworkManager.getInstance().start();
GeckoScreenOrientationListener.getInstance().start();
}

View File

@ -2084,6 +2084,7 @@ Tab.prototype = {
let uri = browser.currentURI.spec;
let documentURI = "";
let contentType = "";
let sameDocument = (aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) != 0;
if (browser.contentDocument) {
documentURI = browser.contentDocument.documentURIObject.spec;
contentType = browser.contentDocument.contentType;
@ -2099,13 +2100,14 @@ Tab.prototype = {
tabID: this.id,
uri: uri,
documentURI: documentURI,
contentType: contentType
contentType: contentType,
sameDocument: sameDocument
}
};
sendMessageToJava(message);
if ((aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) == 0) {
if (!sameDocument) {
// XXX This code assumes that this is the earliest hook we have at which
// browser.contentDocument is changed to the new document we're loading
this.contentDocumentIsDisplayed = false;

View File

@ -23,6 +23,7 @@ do_load_httpd_js();
function run_test()
{
do_print("Preparing test");
removeMetadata();
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "2");
do_load_manifest("data/chrome.manifest");
@ -33,17 +34,22 @@ function run_test()
let search = Services.search;
do_print("Setting up observer");
function observer(aSubject, aTopic, aData) {
do_print("Observing topic " + aTopic);
if ("engine-added" == aData) {
let engine1 = search.getEngineByName("Test search engine");
let engine2 = search.getEngineByName("Sherlock test search engine");
dumpn("Got engine 2: "+engine2);
do_print("Currently, engine1 is " + engine1);
do_print("Currently, engine2 is " + engine2);
if(engine1 && engine2)
{
search.moveEngine(engine1, 0);
search.moveEngine(engine2, 1);
do_print("Next step is forcing flush");
do_timeout(0,
function() {
do_print("Forcing flush");
// Force flush
// Note: the timeout is needed, to avoid some reentrency
// issues in nsSearchService.
@ -53,19 +59,22 @@ function run_test()
afterCommit(
function()
{
do_print("Commit complete");
// Check that search-metadata.json has been created
let metadata = gProfD.clone();
metadata.append("search-metadata.json");
do_check_true(metadata.exists());
// Check that the entries are placed as specified correctly
let stream = NetUtil.newChannel(metadata).open();
let stream = NetUtil.newChannel(metadata).open();
let json = parseJsonFromStream(stream);
do_check_eq(json["[app]/test-search-engine.xml"].order, 1);
do_check_eq(json["[profile]/sherlock-test-search-engine.xml"].order, 2);
httpServer.stop(function() {});
stream.close(); // Stream must be closed under Windows
removeMetadata();
do_print("Cleaning up");
httpServer.stop(function() {});
stream.close(); // Stream must be closed under Windows
removeMetadata();
do_test_finished();
}
);
@ -84,4 +93,8 @@ function run_test()
Ci.nsISearchEngine.DATA_TEXT,
"http://localhost:4444/data/ico-size-16x16-png.ico",
false);
do_timeout(120000, function() {
do_throw("Timeout");
});
}

View File

@ -287,6 +287,7 @@ namespace {
NS_ENSURE_SUCCESS(rv, rv);
SetAllocatedString(webShellAppData->profile, profile);
SetAllocatedString(webShellAppData->name, profile);
nsCOMPtr<nsILocalFile> directory;
rv = XRE_GetFileFromPath(rtPath, getter_AddRefs(directory));

View File

@ -521,6 +521,7 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj)
case SCREENSHOT: {
mMetaState = jenv->GetIntField(jobj, jMetaStateField);
ReadPointArray(mPoints, jenv, jPoints, 2);
break;
}
case SCREENORIENTATION_CHANGED: {
@ -702,8 +703,8 @@ AndroidGeckoLayerClient::SyncViewportInfo(const nsIntRect& aDisplayPort, float a
NS_ABORT_IF_FALSE(viewTransformJObj, "No view transform object!");
viewTransform.Init(viewTransformJObj);
aScrollOffset = nsIntPoint(viewTransform.GetX(), viewTransform.GetY());
aScaleX = aScaleY = viewTransform.GetScale();
aScrollOffset = nsIntPoint(viewTransform.GetX(env), viewTransform.GetY(env));
aScaleX = aScaleY = viewTransform.GetScale(env);
}
jobject
@ -829,27 +830,24 @@ AndroidLayerRendererFrame::EndDrawing()
}
float
AndroidViewTransform::GetX()
AndroidViewTransform::GetX(JNIEnv *env)
{
JNIEnv *env = GetJNIForThread();
if (!env)
return 0.0f;
return env->GetFloatField(wrapped_obj, jXField);
}
float
AndroidViewTransform::GetY()
AndroidViewTransform::GetY(JNIEnv *env)
{
JNIEnv *env = GetJNIForThread();
if (!env)
return 0.0f;
return env->GetFloatField(wrapped_obj, jYField);
}
float
AndroidViewTransform::GetScale()
AndroidViewTransform::GetScale(JNIEnv *env)
{
JNIEnv *env = GetJNIForThread();
if (!env)
return 0.0f;
return env->GetFloatField(wrapped_obj, jScaleField);

View File

@ -162,9 +162,9 @@ public:
AndroidViewTransform() {}
AndroidViewTransform(jobject jobj) { Init(jobj); }
float GetX();
float GetY();
float GetScale();
float GetX(JNIEnv *env);
float GetY(JNIEnv *env);
float GetScale(JNIEnv *env);
private:
static jclass jViewTransformClass;