mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 674741 - Part 4: NFC Chrome Worker. r=yoshi
--HG-- extra : rebase_source : 4aee7bf49a45f778d70ce7354c94fd454384cb93
This commit is contained in:
parent
278e45cab9
commit
51016c01ae
486
dom/system/gonk/Nfc.js
Normal file
486
dom/system/gonk/Nfc.js
Normal file
@ -0,0 +1,486 @@
|
||||
/* Copyright 2012 Mozilla Foundation and Mozilla contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Copyright © 2013, Deutsche Telekom, Inc. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
let NFC = {};
|
||||
Cu.import("resource://gre/modules/nfc_consts.js", NFC);
|
||||
|
||||
// set to true in nfc_consts.js to see debug messages
|
||||
let DEBUG = NFC.DEBUG_NFC;
|
||||
|
||||
let debug;
|
||||
if (DEBUG) {
|
||||
debug = function (s) {
|
||||
dump("-*- Nfc: " + s + "\n");
|
||||
};
|
||||
} else {
|
||||
debug = function (s) {};
|
||||
}
|
||||
|
||||
const NFC_CONTRACTID = "@mozilla.org/nfc;1";
|
||||
const NFC_CID =
|
||||
Components.ID("{2ff24790-5e74-11e1-b86c-0800200c9a66}");
|
||||
|
||||
const NFC_IPC_MSG_NAMES = [
|
||||
"NFC:SetSessionToken",
|
||||
"NFC:ReadNDEF",
|
||||
"NFC:WriteNDEF",
|
||||
"NFC:GetDetailsNDEF",
|
||||
"NFC:MakeReadOnlyNDEF",
|
||||
"NFC:Connect",
|
||||
"NFC:Close"
|
||||
];
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
|
||||
"@mozilla.org/parentprocessmessagemanager;1",
|
||||
"nsIMessageBroadcaster");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gSystemMessenger",
|
||||
"@mozilla.org/system-message-internal;1",
|
||||
"nsISystemMessagesInternal");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gSystemWorkerManager",
|
||||
"@mozilla.org/telephony/system-worker-manager;1",
|
||||
"nsISystemWorkerManager");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
|
||||
"@mozilla.org/settingsService;1",
|
||||
"nsISettingsService");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "UUIDGenerator",
|
||||
"@mozilla.org/uuid-generator;1",
|
||||
"nsIUUIDGenerator");
|
||||
XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
|
||||
return {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIMessageListener,
|
||||
Ci.nsIObserver]),
|
||||
|
||||
nfc: null,
|
||||
|
||||
// Manage message targets in terms of sessionToken. Only the authorized and
|
||||
// registered contents can receive related messages.
|
||||
targetsBySessionTokens: {},
|
||||
sessionTokens: [],
|
||||
|
||||
init: function init(nfc) {
|
||||
this.nfc = nfc;
|
||||
|
||||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||
this._registerMessageListeners();
|
||||
},
|
||||
|
||||
_shutdown: function _shutdown() {
|
||||
this.nfc = null;
|
||||
|
||||
Services.obs.removeObserver(this, "xpcom-shutdown");
|
||||
this._unregisterMessageListeners();
|
||||
},
|
||||
|
||||
_registerMessageListeners: function _registerMessageListeners() {
|
||||
ppmm.addMessageListener("child-process-shutdown", this);
|
||||
for (let msgname of NFC_IPC_MSG_NAMES) {
|
||||
ppmm.addMessageListener(msgname, this);
|
||||
}
|
||||
},
|
||||
|
||||
_unregisterMessageListeners: function _unregisterMessageListeners() {
|
||||
ppmm.removeMessageListener("child-process-shutdown", this);
|
||||
for (let msgname of NFC_IPC_MSG_NAMES) {
|
||||
ppmm.removeMessageListener(msgname, this);
|
||||
}
|
||||
ppmm = null;
|
||||
},
|
||||
|
||||
_registerMessageTarget: function _registerMessageTarget(sessionToken, target) {
|
||||
let targets = this.targetsBySessionTokens[sessionToken];
|
||||
if (!targets) {
|
||||
targets = this.targetsBySessionTokens[sessionToken] = [];
|
||||
let list = this.sessionTokens;
|
||||
if (list.indexOf(sessionToken) == -1) {
|
||||
list.push(sessionToken);
|
||||
}
|
||||
}
|
||||
|
||||
if (targets.indexOf(target) != -1) {
|
||||
debug("Already registered this target!");
|
||||
return;
|
||||
}
|
||||
|
||||
targets.push(target);
|
||||
debug("Registered :" + sessionToken + " target: " + target);
|
||||
},
|
||||
|
||||
_unregisterMessageTarget: function _unregisterMessageTarget(sessionToken, target) {
|
||||
if (sessionToken == null) {
|
||||
// Unregister the target for every sessionToken when no sessionToken is specified.
|
||||
for (let session of this.sessionTokens) {
|
||||
this._unregisterMessageTarget(session, target);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Unregister the target for a specified sessionToken.
|
||||
let targets = this.targetsBySessionTokens[sessionToken];
|
||||
if (!targets) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (target == null) {
|
||||
debug("Unregistered all targets for the " + sessionToken + " targets: " + targets);
|
||||
targets = [];
|
||||
let list = this.sessionTokens;
|
||||
if (sessionToken !== null) {
|
||||
let index = list.indexOf(sessionToken);
|
||||
if (index > -1) {
|
||||
list.splice(index, 1);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let index = targets.indexOf(target);
|
||||
if (index != -1) {
|
||||
targets.splice(index, 1);
|
||||
}
|
||||
},
|
||||
|
||||
_sendTargetMessage: function _sendTargetMessage(sessionToken, message, options) {
|
||||
let targets = this.targetsBySessionTokens[sessionToken];
|
||||
if (!targets) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let target of targets) {
|
||||
target.sendAsyncMessage(message, options);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIMessageListener interface methods.
|
||||
*/
|
||||
|
||||
receiveMessage: function receiveMessage(msg) {
|
||||
debug("Received '" + msg.name + "' message from content process");
|
||||
if (msg.name == "child-process-shutdown") {
|
||||
// By the time we receive child-process-shutdown, the child process has
|
||||
// already forgotten its permissions so we need to unregister the target
|
||||
// for every permission.
|
||||
this._unregisterMessageTarget(null, msg.target);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (NFC_IPC_MSG_NAMES.indexOf(msg.name) != -1) {
|
||||
if (!msg.target.assertPermission("nfc-read")) {
|
||||
debug("Nfc message " + msg.name +
|
||||
" from a content process with no 'nfc-read' privileges.");
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
debug("Ignoring unknown message type: " + msg.name);
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (msg.name) {
|
||||
case "NFC:SetSessionToken":
|
||||
this._registerMessageTarget(this.nfc.sessionTokenMap[this.nfc._currentSessionId], msg.target);
|
||||
debug("Registering target for this SessionToken : " +
|
||||
this.nfc.sessionTokenMap[this.nfc._currentSessionId]);
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIObserver interface methods.
|
||||
*/
|
||||
|
||||
observe: function observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "xpcom-shutdown":
|
||||
this._shutdown();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
sendNfcResponseMessage: function sendNfcResponseMessage(message, data) {
|
||||
this._sendTargetMessage(this.nfc.sessionTokenMap[this.nfc._currentSessionId], message, data);
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
function Nfc() {
|
||||
debug("Starting Worker");
|
||||
this.worker = new ChromeWorker("resource://gre/modules/nfc_worker.js");
|
||||
this.worker.onerror = this.onerror.bind(this);
|
||||
this.worker.onmessage = this.onmessage.bind(this);
|
||||
|
||||
for each (let msgname in NFC_IPC_MSG_NAMES) {
|
||||
ppmm.addMessageListener(msgname, this);
|
||||
}
|
||||
|
||||
Services.obs.addObserver(this, NFC.TOPIC_MOZSETTINGS_CHANGED, false);
|
||||
Services.obs.addObserver(this, NFC.TOPIC_XPCOM_SHUTDOWN, false);
|
||||
|
||||
gMessageManager.init(this);
|
||||
let lock = gSettingsService.createLock();
|
||||
lock.get(NFC.SETTING_NFC_POWER_LEVEL, this);
|
||||
lock.get(NFC.SETTING_NFC_ENABLED, this);
|
||||
// Maps sessionId (that are generated from nfcd) with a unique guid : 'SessionToken'
|
||||
this.sessionTokenMap = {};
|
||||
|
||||
gSystemWorkerManager.registerNfcWorker(this.worker);
|
||||
}
|
||||
|
||||
Nfc.prototype = {
|
||||
|
||||
classID: NFC_CID,
|
||||
classInfo: XPCOMUtils.generateCI({classID: NFC_CID,
|
||||
classDescription: "Nfc",
|
||||
interfaces: [Ci.nsIWorkerHolder]}),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWorkerHolder,
|
||||
Ci.nsIObserver,
|
||||
Ci.nsISettingsServiceCallback]),
|
||||
|
||||
_currentSessionId: null,
|
||||
_enabled: false,
|
||||
|
||||
onerror: function onerror(event) {
|
||||
debug("Got an error: " + event.filename + ":" +
|
||||
event.lineno + ": " + event.message + "\n");
|
||||
event.preventDefault();
|
||||
},
|
||||
|
||||
/**
|
||||
* Send arbitrary message to worker.
|
||||
*
|
||||
* @param nfcMessageType
|
||||
* A text message type.
|
||||
* @param message [optional]
|
||||
* An optional message object to send.
|
||||
*/
|
||||
sendToWorker: function sendToWorker(nfcMessageType, message) {
|
||||
message = message || {};
|
||||
message.type = nfcMessageType;
|
||||
this.worker.postMessage(message);
|
||||
},
|
||||
|
||||
/**
|
||||
* Send Error response to content.
|
||||
*
|
||||
* @param message
|
||||
* An nsIMessageListener's message parameter.
|
||||
*/
|
||||
sendNfcErrorResponse: function sendNfcErrorResponse(message) {
|
||||
if (!message.target) {
|
||||
return;
|
||||
}
|
||||
|
||||
let nfcMsgType = message.name + "Response";
|
||||
message.target.sendAsyncMessage(nfcMsgType, {
|
||||
sessionId: message.json.sessionToken,
|
||||
requestId: message.json.requestId,
|
||||
status: NFC.GECKO_NFC_ERROR_GENERIC_FAILURE
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Process the incoming message from the NFC worker
|
||||
*/
|
||||
onmessage: function onmessage(event) {
|
||||
let message = event.data;
|
||||
debug("Received message from NFC worker: " + JSON.stringify(message));
|
||||
|
||||
switch (message.type) {
|
||||
case "techDiscovered":
|
||||
this._currentSessionId = message.sessionId;
|
||||
// Check if the session token already exists. If exists, continue to use the same one.
|
||||
// If not, generate a new token.
|
||||
if (!this.sessionTokenMap[this._currentSessionId]) {
|
||||
this.sessionTokenMap[this._currentSessionId] = UUIDGenerator.generateUUID().toString();
|
||||
}
|
||||
// Update the upper layers with a session token (alias)
|
||||
message.sessionToken = this.sessionTokenMap[this._currentSessionId];
|
||||
// Do not expose the actual session to the content
|
||||
delete message.sessionId;
|
||||
gSystemMessenger.broadcastMessage("nfc-manager-tech-discovered", message);
|
||||
break;
|
||||
case "techLost":
|
||||
gMessageManager._unregisterMessageTarget(this.sessionTokenMap[this._currentSessionId], null);
|
||||
// Update the upper layers with a session token (alias)
|
||||
message.sessionToken = this.sessionTokenMap[this._currentSessionId];
|
||||
// Do not expose the actual session to the content
|
||||
delete message.sessionId;
|
||||
gSystemMessenger.broadcastMessage("nfc-manager-tech-lost", message);
|
||||
delete this.sessionTokenMap[this._currentSessionId];
|
||||
this._currentSessionId = null;
|
||||
break;
|
||||
case "ConfigResponse":
|
||||
gSystemMessenger.broadcastMessage("nfc-powerlevel-change", message);
|
||||
break;
|
||||
case "ConnectResponse": // Fall through.
|
||||
case "CloseResponse":
|
||||
case "GetDetailsNDEFResponse":
|
||||
case "ReadNDEFResponse":
|
||||
case "MakeReadOnlyNDEFResponse":
|
||||
case "WriteNDEFResponse":
|
||||
message.sessionToken = this.sessionTokenMap[this._currentSessionId];
|
||||
// Do not expose the actual session to the content
|
||||
delete message.sessionId;
|
||||
gMessageManager.sendNfcResponseMessage("NFC:" + message.type, message);
|
||||
break;
|
||||
default:
|
||||
throw new Error("Don't know about this message type: " + message.type);
|
||||
}
|
||||
},
|
||||
|
||||
// nsINfcWorker
|
||||
worker: null,
|
||||
|
||||
powerLevel: NFC.NFC_POWER_LEVEL_DISABLED,
|
||||
|
||||
sessionTokenMap: null,
|
||||
|
||||
/**
|
||||
* Process a message from the content process.
|
||||
*/
|
||||
receiveMessage: function receiveMessage(message) {
|
||||
debug("Received '" + JSON.stringify(message) + "' message from content process");
|
||||
|
||||
if (!this._enabled) {
|
||||
debug("NFC is not enabled.");
|
||||
this.sendNfcErrorResponse(message);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Enforce bare minimums for NFC permissions
|
||||
switch (message.name) {
|
||||
case "NFC:Connect": // Fall through
|
||||
case "NFC:Close":
|
||||
case "NFC:GetDetailsNDEF":
|
||||
case "NFC:ReadNDEF":
|
||||
if (!message.target.assertPermission("nfc-read")) {
|
||||
debug("NFC message " + message.name +
|
||||
" from a content process with no 'nfc-read' privileges.");
|
||||
this.sendNfcErrorResponse(message);
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
case "NFC:WriteNDEF": // Fall through
|
||||
case "NFC:MakeReadOnlyNDEF":
|
||||
if (!message.target.assertPermission("nfc-write")) {
|
||||
debug("NFC message " + message.name +
|
||||
" from a content process with no 'nfc-write' privileges.");
|
||||
this.sendNfcErrorResponse(message);
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
case "NFC:SetSessionToken":
|
||||
//Do nothing here. No need to process this message further
|
||||
return null;
|
||||
}
|
||||
|
||||
// Sanity check on sessionId
|
||||
if (message.json.sessionToken !== this.sessionTokenMap[this._currentSessionId]) {
|
||||
debug("Invalid Session Token: " + message.json.sessionToken +
|
||||
" Expected Session Token: " + this.sessionTokenMap[this._currentSessionId]);
|
||||
this.sendNfcErrorResponse(message);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Update the current sessionId before sending to the worker
|
||||
message.sessionId = this._currentSessionId;
|
||||
|
||||
switch (message.name) {
|
||||
case "NFC:GetDetailsNDEF":
|
||||
this.sendToWorker("getDetailsNDEF", message.json);
|
||||
break;
|
||||
case "NFC:ReadNDEF":
|
||||
this.sendToWorker("readNDEF", message.json);
|
||||
break;
|
||||
case "NFC:WriteNDEF":
|
||||
this.sendToWorker("writeNDEF", message.json);
|
||||
break;
|
||||
case "NFC:MakeReadOnlyNDEF":
|
||||
this.sendToWorker("makeReadOnlyNDEF", message.json);
|
||||
break;
|
||||
case "NFC:Connect":
|
||||
this.sendToWorker("connect", message.json);
|
||||
break;
|
||||
case "NFC:Close":
|
||||
this.sendToWorker("close", message.json);
|
||||
break;
|
||||
default:
|
||||
debug("UnSupported : Message Name " + message.name);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* nsISettingsServiceCallback
|
||||
*/
|
||||
|
||||
handle: function handle(aName, aResult) {
|
||||
switch(aName) {
|
||||
case NFC.SETTING_NFC_ENABLED:
|
||||
debug("'nfc.enabled' is now " + aResult);
|
||||
this._enabled = aResult;
|
||||
// General power setting
|
||||
let powerLevel = this._enabled ? NFC.NFC_POWER_LEVEL_ENABLED :
|
||||
NFC.NFC_POWER_LEVEL_DISABLED;
|
||||
// Only if the value changes, set the power config and persist
|
||||
if (powerLevel !== this.powerLevel) {
|
||||
debug("New Power Level " + powerLevel);
|
||||
this.setConfig({powerLevel: powerLevel});
|
||||
this.powerLevel = powerLevel;
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIObserver
|
||||
*/
|
||||
|
||||
observe: function observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case NFC.TOPIC_XPCOM_SHUTDOWN:
|
||||
for each (let msgname in NFC_IPC_MSG_NAMES) {
|
||||
ppmm.removeMessageListener(msgname, this);
|
||||
}
|
||||
ppmm = null;
|
||||
Services.obs.removeObserver(this, NFC.TOPIC_XPCOM_SHUTDOWN);
|
||||
break;
|
||||
case NFC.TOPIC_MOZSETTINGS_CHANGED:
|
||||
let setting = JSON.parse(data);
|
||||
if (setting) {
|
||||
let setting = JSON.parse(data);
|
||||
this.handle(setting.key, setting.value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
setConfig: function setConfig(prop) {
|
||||
this.sendToWorker("config", prop);
|
||||
}
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([Nfc]);
|
314
dom/system/gonk/NfcContentHelper.js
Normal file
314
dom/system/gonk/NfcContentHelper.js
Normal file
@ -0,0 +1,314 @@
|
||||
/* Copyright 2012 Mozilla Foundation and Mozilla contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Copyright © 2013, Deutsche Telekom, Inc. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
|
||||
|
||||
let NFC = {};
|
||||
Cu.import("resource://gre/modules/nfc_consts.js", NFC);
|
||||
|
||||
// set to true to in nfc_consts.js to see debug messages
|
||||
let DEBUG = NFC.DEBUG_CONTENT_HELPER;
|
||||
|
||||
let debug;
|
||||
if (DEBUG) {
|
||||
debug = function (s) {
|
||||
dump("-*- NfcContentHelper: " + s + "\n");
|
||||
};
|
||||
} else {
|
||||
debug = function (s) {};
|
||||
}
|
||||
|
||||
const NFCCONTENTHELPER_CID =
|
||||
Components.ID("{4d72c120-da5f-11e1-9b23-0800200c9a66}");
|
||||
|
||||
const NFC_IPC_MSG_NAMES = [
|
||||
"NFC:ReadNDEFResponse",
|
||||
"NFC:WriteNDEFResponse",
|
||||
"NFC:GetDetailsNDEFResponse",
|
||||
"NFC:MakeReadOnlyNDEFResponse",
|
||||
"NFC:ConnectResponse",
|
||||
"NFC:CloseResponse"
|
||||
];
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
||||
"@mozilla.org/childprocessmessagemanager;1",
|
||||
"nsISyncMessageSender");
|
||||
|
||||
function NfcContentHelper() {
|
||||
this.initDOMRequestHelper(/* aWindow */ null, NFC_IPC_MSG_NAMES);
|
||||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||
|
||||
this._requestMap = [];
|
||||
}
|
||||
|
||||
NfcContentHelper.prototype = {
|
||||
__proto__: DOMRequestIpcHelper.prototype,
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsINfcContentHelper,
|
||||
Ci.nsISupportsWeakReference,
|
||||
Ci.nsIObserver]),
|
||||
classID: NFCCONTENTHELPER_CID,
|
||||
classInfo: XPCOMUtils.generateCI({
|
||||
classID: NFCCONTENTHELPER_CID,
|
||||
classDescription: "NfcContentHelper",
|
||||
interfaces: [Ci.nsINfcContentHelper]
|
||||
}),
|
||||
|
||||
_requestMap: null,
|
||||
|
||||
/* TODO: Bug 815526: This is a limitation when a DOMString is used in sequences of Moz DOM Objects.
|
||||
* Strings such as 'type', 'id' 'payload' will not be acccessible to NfcWorker.
|
||||
* Therefore this function exists till the bug is addressed.
|
||||
*/
|
||||
encodeNdefRecords: function encodeNdefRecords(records) {
|
||||
let encodedRecords = [];
|
||||
for (let i = 0; i < records.length; i++) {
|
||||
let record = records[i];
|
||||
encodedRecords.push({
|
||||
tnf: record.tnf,
|
||||
type: record.type,
|
||||
id: record.id,
|
||||
payload: record.payload,
|
||||
});
|
||||
}
|
||||
return encodedRecords;
|
||||
},
|
||||
|
||||
// NFC interface:
|
||||
setSessionToken: function setSessionToken(sessionToken) {
|
||||
if (sessionToken == null) {
|
||||
throw Components.Exception("No session token!",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
// Report session to Nfc.js only.
|
||||
cpmm.sendAsyncMessage("NFC:SetSessionToken", {
|
||||
sessionToken: sessionToken,
|
||||
});
|
||||
},
|
||||
|
||||
// NFCTag interface
|
||||
getDetailsNDEF: function getDetailsNDEF(window, sessionToken) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
let request = Services.DOMRequest.createRequest(window);
|
||||
let requestId = btoa(this.getRequestId(request));
|
||||
this._requestMap[requestId] = window;
|
||||
|
||||
cpmm.sendAsyncMessage("NFC:GetDetailsNDEF", {
|
||||
requestId: requestId,
|
||||
sessionToken: sessionToken
|
||||
});
|
||||
return request;
|
||||
},
|
||||
|
||||
readNDEF: function readNDEF(window, sessionToken) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
let request = Services.DOMRequest.createRequest(window);
|
||||
let requestId = btoa(this.getRequestId(request));
|
||||
this._requestMap[requestId] = window;
|
||||
|
||||
cpmm.sendAsyncMessage("NFC:ReadNDEF", {
|
||||
requestId: requestId,
|
||||
sessionToken: sessionToken
|
||||
});
|
||||
return request;
|
||||
},
|
||||
|
||||
writeNDEF: function writeNDEF(window, records, sessionToken) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
|
||||
let request = Services.DOMRequest.createRequest(window);
|
||||
let requestId = btoa(this.getRequestId(request));
|
||||
this._requestMap[requestId] = window;
|
||||
|
||||
let encodedRecords = this.encodeNdefRecords(records);
|
||||
|
||||
cpmm.sendAsyncMessage("NFC:WriteNDEF", {
|
||||
requestId: requestId,
|
||||
sessionToken: sessionToken,
|
||||
records: encodedRecords
|
||||
});
|
||||
return request;
|
||||
},
|
||||
|
||||
makeReadOnlyNDEF: function makeReadOnlyNDEF(window, sessionToken) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
|
||||
let request = Services.DOMRequest.createRequest(window);
|
||||
let requestId = btoa(this.getRequestId(request));
|
||||
this._requestMap[requestId] = window;
|
||||
|
||||
cpmm.sendAsyncMessage("NFC:MakeReadOnlyNDEF", {
|
||||
requestId: requestId,
|
||||
sessionToken: sessionToken
|
||||
});
|
||||
return request;
|
||||
},
|
||||
|
||||
connect: function connect(window, techType, sessionToken) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
let request = Services.DOMRequest.createRequest(window);
|
||||
let requestId = btoa(this.getRequestId(request));
|
||||
this._requestMap[requestId] = window;
|
||||
|
||||
cpmm.sendAsyncMessage("NFC:Connect", {
|
||||
requestId: requestId,
|
||||
sessionToken: sessionToken,
|
||||
techType: techType
|
||||
});
|
||||
return request;
|
||||
},
|
||||
|
||||
close: function close(window, sessionToken) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
let request = Services.DOMRequest.createRequest(window);
|
||||
let requestId = btoa(this.getRequestId(request));
|
||||
this._requestMap[requestId] = window;
|
||||
|
||||
cpmm.sendAsyncMessage("NFC:Close", {
|
||||
requestId: requestId,
|
||||
sessionToken: sessionToken
|
||||
});
|
||||
return request;
|
||||
},
|
||||
|
||||
// nsIObserver
|
||||
|
||||
observe: function observe(subject, topic, data) {
|
||||
if (topic == "xpcom-shutdown") {
|
||||
this.removeMessageListener();
|
||||
Services.obs.removeObserver(this, "xpcom-shutdown");
|
||||
cpmm = null;
|
||||
}
|
||||
},
|
||||
|
||||
// nsIMessageListener
|
||||
|
||||
fireRequestSuccess: function fireRequestSuccess(requestId, result) {
|
||||
let request = this.takeRequest(requestId);
|
||||
if (!request) {
|
||||
debug("not firing success for id: " + requestId +
|
||||
", result: " + JSON.stringify(result));
|
||||
return;
|
||||
}
|
||||
|
||||
debug("fire request success, id: " + requestId +
|
||||
", result: " + JSON.stringify(result));
|
||||
Services.DOMRequest.fireSuccess(request, result);
|
||||
},
|
||||
|
||||
fireRequestError: function fireRequestError(requestId, error) {
|
||||
let request = this.takeRequest(requestId);
|
||||
if (!request) {
|
||||
debug("not firing error for id: " + requestId +
|
||||
", error: " + JSON.stringify(error));
|
||||
return;
|
||||
}
|
||||
|
||||
debug("fire request error, id: " + requestId +
|
||||
", result: " + JSON.stringify(error));
|
||||
Services.DOMRequest.fireError(request, error);
|
||||
},
|
||||
|
||||
receiveMessage: function receiveMessage(message) {
|
||||
debug("Message received: " + JSON.stringify(message));
|
||||
switch (message.name) {
|
||||
case "NFC:ReadNDEFResponse":
|
||||
this.handleReadNDEFResponse(message.json);
|
||||
break;
|
||||
case "NFC:ConnectResponse": // Fall through.
|
||||
case "NFC:CloseResponse":
|
||||
case "NFC:WriteNDEFResponse":
|
||||
case "NFC:MakeReadOnlyNDEFResponse":
|
||||
case "NFC:GetDetailsNDEFResponse":
|
||||
this.handleResponse(message.json);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
handleReadNDEFResponse: function handleReadNDEFResponse(message) {
|
||||
debug("ReadNDEFResponse(" + JSON.stringify(message) + ")");
|
||||
let requester = this._requestMap[message.requestId];
|
||||
if (!requester) {
|
||||
debug("ReadNDEFResponse Invalid requester=" + requester +
|
||||
" message.sessionToken=" + message.sessionToken);
|
||||
return; // Nothing to do in this instance.
|
||||
}
|
||||
delete this._requestMap[message.requestId];
|
||||
let records = message.records;
|
||||
let requestId = atob(message.requestId);
|
||||
|
||||
if (message.status !== NFC.GECKO_NFC_ERROR_SUCCESS) {
|
||||
this.fireRequestError(requestId, message.status);
|
||||
} else {
|
||||
let ndefMsg = [];
|
||||
for (let i = 0; i < records.length; i++) {
|
||||
let record = records[i];
|
||||
ndefMsg.push(new requester.MozNdefRecord(record.tnf,
|
||||
record.type,
|
||||
record.id,
|
||||
record.payload));
|
||||
}
|
||||
this.fireRequestSuccess(requestId, ndefMsg);
|
||||
}
|
||||
},
|
||||
|
||||
handleResponse: function handleResponse(message) {
|
||||
debug("Response(" + JSON.stringify(message) + ")");
|
||||
let requester = this._requestMap[message.requestId];
|
||||
if (!requester) {
|
||||
debug("Response Invalid requester=" + requester +
|
||||
" message.sessionToken=" + message.sessionToken);
|
||||
return; // Nothing to do in this instance.
|
||||
}
|
||||
delete this._requestMap[message.requestId];
|
||||
let result = message;
|
||||
let requestId = atob(message.requestId);
|
||||
|
||||
if (message.status !== NFC.GECKO_NFC_ERROR_SUCCESS) {
|
||||
this.fireRequestError(requestId, result.status);
|
||||
} else {
|
||||
this.fireRequestSuccess(requestId, result);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NfcContentHelper]);
|
71
dom/system/gonk/nfc_consts.js
Normal file
71
dom/system/gonk/nfc_consts.js
Normal file
@ -0,0 +1,71 @@
|
||||
/* Copyright 2012 Mozilla Foundation and Mozilla contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Copyright © 2013, Deutsche Telekom, Inc. */
|
||||
|
||||
// Set to true to debug all NFC layers
|
||||
this.DEBUG_ALL = false;
|
||||
|
||||
// Set individually to debug specific layers
|
||||
this.DEBUG_WORKER = false || DEBUG_ALL;
|
||||
this.DEBUG_CONTENT_HELPER = false || DEBUG_ALL;
|
||||
this.DEBUG_NFC = false || DEBUG_ALL;
|
||||
|
||||
// Current version
|
||||
this.NFC_MAJOR_VERSION = 1;
|
||||
this.NFC_MINOR_VERSION = 7;
|
||||
|
||||
this.NFC_REQUEST_CONFIG = 0;
|
||||
this.NFC_REQUEST_CONNECT = 1;
|
||||
this.NFC_REQUEST_CLOSE = 2;
|
||||
this.NFC_REQUEST_GET_DETAILS = 3;
|
||||
this.NFC_REQUEST_READ_NDEF = 4;
|
||||
this.NFC_REQUEST_WRITE_NDEF = 5;
|
||||
this.NFC_REQUEST_MAKE_NDEF_READ_ONLY = 6;
|
||||
|
||||
this.NFC_RESPONSE_GENERAL = 1000;
|
||||
this.NFC_RESPONSE_CONFIG = 1001;
|
||||
this.NFC_RESPONSE_READ_NDEF_DETAILS = 1002;
|
||||
this.NFC_RESPONSE_READ_NDEF = 1003;
|
||||
|
||||
this.NFC_NOTIFICATION_INITIALIZED = 2000;
|
||||
this.NFC_NOTIFICATION_TECH_DISCOVERED = 2001;
|
||||
this.NFC_NOTIFICATION_TECH_LOST = 2002;
|
||||
|
||||
this.NFC_TECHS = {
|
||||
0:'NDEF',
|
||||
1:'NDEF_WRITEABLE',
|
||||
2:'NDEF_FORMATABLE',
|
||||
3:'P2P',
|
||||
4:'NFC_A'
|
||||
};
|
||||
|
||||
// TODO: Bug 933595. Fill-in all error codes for Gonk/nfcd protocol
|
||||
this.GECKO_NFC_ERROR_SUCCESS = 0;
|
||||
this.GECKO_NFC_ERROR_GENERIC_FAILURE = 1;
|
||||
|
||||
// NFC powerlevels must match config PDUs.
|
||||
this.NFC_POWER_LEVEL_UNKNOWN = -1;
|
||||
this.NFC_POWER_LEVEL_DISABLED = 0;
|
||||
this.NFC_POWER_LEVEL_LOW = 1;
|
||||
this.NFC_POWER_LEVEL_ENABLED = 2;
|
||||
|
||||
this.TOPIC_MOZSETTINGS_CHANGED = "mozsettings-changed";
|
||||
this.TOPIC_XPCOM_SHUTDOWN = "xpcom-shutdown";
|
||||
this.SETTING_NFC_ENABLED = "nfc.enabled";
|
||||
this.SETTING_NFC_POWER_LEVEL = "nfc.powerlevel";
|
||||
|
||||
// Allow this file to be imported via Components.utils.import().
|
||||
this.EXPORTED_SYMBOLS = Object.keys(this);
|
440
dom/system/gonk/nfc_worker.js
Normal file
440
dom/system/gonk/nfc_worker.js
Normal file
@ -0,0 +1,440 @@
|
||||
/* Copyright 2012 Mozilla Foundation and Mozilla contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Copyright © 2013, Deutsche Telekom, Inc. */
|
||||
|
||||
"use strict";
|
||||
|
||||
importScripts("systemlibs.js", "nfc_consts.js");
|
||||
importScripts("resource://gre/modules/workers/require.js");
|
||||
|
||||
// set to true in nfc_consts.js to see debug messages
|
||||
let DEBUG = DEBUG_WORKER;
|
||||
|
||||
function getPaddingLen(len) {
|
||||
return (len % 4) ? (4 - len % 4) : 0;
|
||||
}
|
||||
|
||||
let Buf = {
|
||||
__proto__: (function(){
|
||||
return require("resource://gre/modules/workers/worker_buf.js").Buf;
|
||||
})(),
|
||||
|
||||
init: function init() {
|
||||
this._init();
|
||||
},
|
||||
|
||||
/**
|
||||
* Process one parcel.
|
||||
*/
|
||||
processParcel: function processParcel() {
|
||||
let pduType = this.readInt32();
|
||||
if (DEBUG) debug("Number of bytes available in Parcel : " + this.readAvailable);
|
||||
NfcWorker.handleParcel(pduType, this.mCallback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Start a new outgoing parcel.
|
||||
*
|
||||
* @param type
|
||||
* Integer specifying the request type.
|
||||
* @param callback
|
||||
*/
|
||||
newParcel: function newParcel(type, callback) {
|
||||
if (DEBUG) debug("New outgoing parcel of type " + type);
|
||||
this.mCallback = callback;
|
||||
// We're going to leave room for the parcel size at the beginning.
|
||||
this.outgoingIndex = this.PARCEL_SIZE_SIZE;
|
||||
this.writeInt32(type);
|
||||
},
|
||||
|
||||
simpleRequest: function simpleRequest(type) {
|
||||
this.newParcel(type);
|
||||
this.sendParcel();
|
||||
},
|
||||
|
||||
onSendParcel: function onSendParcel(parcel) {
|
||||
postNfcMessage(parcel);
|
||||
},
|
||||
|
||||
/**
|
||||
* TODO: Bug 933593. Callback map of NFC_RESPONSE_XXX and RequestID
|
||||
* needs to be maintained
|
||||
*/
|
||||
mCallback: null,
|
||||
};
|
||||
|
||||
/**
|
||||
* Provide a high-level API representing NFC capabilities.
|
||||
* Rensponsible for converting NFC requests from Content process to binary data
|
||||
* and NFC Responses from binary data to dictionary objects.
|
||||
*/
|
||||
let NfcWorker = {
|
||||
/**
|
||||
* Handle incoming messages from the main UI thread.
|
||||
*
|
||||
* @param message
|
||||
* Object containing the message. Messages are supposed
|
||||
*/
|
||||
handleDOMMessage: function handleMessage(message) {
|
||||
if (DEBUG) debug("Received DOM message " + JSON.stringify(message));
|
||||
let method = this[message.type];
|
||||
if (typeof method != "function") {
|
||||
if (DEBUG) {
|
||||
debug("Don't know what to do with message " + JSON.stringify(message));
|
||||
}
|
||||
return;
|
||||
}
|
||||
method.call(this, message);
|
||||
},
|
||||
|
||||
/**
|
||||
* Unmarshals a NDEF message
|
||||
*/
|
||||
unMarshallNdefMessage: function unMarshallNdefMessage() {
|
||||
let numOfRecords = Buf.readInt32();
|
||||
debug("numOfRecords = " + numOfRecords);
|
||||
if (numOfRecords <= 0) {
|
||||
return null;
|
||||
}
|
||||
let records = [];
|
||||
|
||||
for (let i = 0; i < numOfRecords; i++) {
|
||||
let tnf = Buf.readInt32();
|
||||
let typeLength = Buf.readInt32();
|
||||
let type = [];
|
||||
for (let i = 0; i < typeLength; i++) {
|
||||
type.push(Buf.readUint8());
|
||||
}
|
||||
let padding = getPaddingLen(typeLength);
|
||||
for (let i = 0; i < padding; i++) {
|
||||
Buf.readUint8();
|
||||
}
|
||||
|
||||
let idLength = Buf.readInt32();
|
||||
let id = [];
|
||||
for (let i = 0; i < idLength; i++) {
|
||||
id.push(Buf.readUint8());
|
||||
}
|
||||
padding = getPaddingLen(idLength);
|
||||
for (let i = 0; i < padding; i++) {
|
||||
Buf.readUint8();
|
||||
}
|
||||
|
||||
let payloadLength = Buf.readInt32();
|
||||
let payload = [];
|
||||
for (let i = 0; i < payloadLength; i++) {
|
||||
payload.push(Buf.readUint8());
|
||||
}
|
||||
padding = getPaddingLen(payloadLength);
|
||||
for (let i = 0; i < padding; i++) {
|
||||
Buf.readUint8();
|
||||
}
|
||||
records.push({tnf: tnf,
|
||||
type: type,
|
||||
id: id,
|
||||
payload: payload});
|
||||
}
|
||||
return records;
|
||||
},
|
||||
|
||||
/**
|
||||
* Read and return NDEF data, if present.
|
||||
*/
|
||||
readNDEF: function readNDEF(message) {
|
||||
let cb = function callback() {
|
||||
let error = Buf.readInt32();
|
||||
let sessionId = Buf.readInt32();
|
||||
let records = this.unMarshallNdefMessage();
|
||||
|
||||
message.type = "ReadNDEFResponse";
|
||||
message.sessionId = sessionId;
|
||||
message.records = records;
|
||||
message.status = (error === 0) ? GECKO_NFC_ERROR_SUCCESS :
|
||||
GECKO_NFC_ERROR_GENERIC_FAILURE;
|
||||
this.sendDOMMessage(message);
|
||||
}
|
||||
|
||||
Buf.newParcel(NFC_REQUEST_READ_NDEF, cb);
|
||||
Buf.writeInt32(message.sessionId);
|
||||
Buf.sendParcel();
|
||||
},
|
||||
|
||||
/**
|
||||
* Write to a target that accepts NDEF formattable data
|
||||
*/
|
||||
writeNDEF: function writeNDEF(message) {
|
||||
let cb = function callback() {
|
||||
let error = Buf.readInt32();
|
||||
let sessionId = Buf.readInt32();
|
||||
|
||||
message.type = "WriteNDEFResponse";
|
||||
message.sessionId = sessionId;
|
||||
message.status = (error === 0) ? GECKO_NFC_ERROR_SUCCESS :
|
||||
GECKO_NFC_ERROR_GENERIC_FAILURE;
|
||||
this.sendDOMMessage(message);
|
||||
};
|
||||
|
||||
Buf.newParcel(NFC_REQUEST_WRITE_NDEF, cb);
|
||||
Buf.writeInt32(message.sessionId);
|
||||
let records = message.records;
|
||||
let numRecords = records.length;
|
||||
Buf.writeInt32(numRecords);
|
||||
for (let i = 0; i < numRecords; i++) {
|
||||
let record = records[i];
|
||||
Buf.writeInt32(record.tnf);
|
||||
|
||||
let typeLength = record.type.length;
|
||||
Buf.writeInt32(typeLength);
|
||||
for (let j = 0; j < typeLength; j++) {
|
||||
Buf.writeUint8(record.type.charCodeAt(j));
|
||||
}
|
||||
let padding = getPaddingLen(typeLength);
|
||||
for (let i = 0; i < padding; i++) {
|
||||
Buf.writeUint8(0x00);
|
||||
}
|
||||
|
||||
let idLength = record.id.length;
|
||||
Buf.writeInt32(idLength);
|
||||
for (let j = 0; j < idLength; j++) {
|
||||
Buf.writeUint8(record.id.charCodeAt(j));
|
||||
}
|
||||
padding = getPaddingLen(idLength);
|
||||
for (let i = 0; i < padding; i++) {
|
||||
Buf.writeUint8(0x00);
|
||||
}
|
||||
|
||||
let payloadLength = record.payload && record.payload.length;
|
||||
Buf.writeInt32(payloadLength);
|
||||
for (let j = 0; j < payloadLength; j++) {
|
||||
Buf.writeUint8(record.payload.charCodeAt(j));
|
||||
}
|
||||
padding = getPaddingLen(payloadLength);
|
||||
for (let i = 0; i < padding; i++) {
|
||||
Buf.writeUint8(0x00);
|
||||
}
|
||||
}
|
||||
|
||||
Buf.sendParcel();
|
||||
},
|
||||
|
||||
/**
|
||||
* Make the NFC NDEF tag permanently read only
|
||||
*/
|
||||
makeReadOnlyNDEF: function makeReadOnlyNDEF(message) {
|
||||
let cb = function callback() {
|
||||
let error = Buf.readInt32();
|
||||
let sessionId = Buf.readInt32();
|
||||
|
||||
message.type = "MakeReadOnlyNDEFResponse";
|
||||
message.sessionId = sessionId;
|
||||
message.status = (error === 0) ? GECKO_NFC_ERROR_SUCCESS :
|
||||
GECKO_NFC_ERROR_GENERIC_FAILURE;
|
||||
this.sendDOMMessage(message);
|
||||
};
|
||||
|
||||
Buf.newParcel(NFC_REQUEST_MAKE_NDEF_READ_ONLY, cb);
|
||||
Buf.writeInt32(message.sessionId);
|
||||
Buf.sendParcel();
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve metadata describing the NDEF formatted data, if present.
|
||||
*/
|
||||
getDetailsNDEF: function getDetailsNDEF(message) {
|
||||
let cb = function callback() {
|
||||
let error = Buf.readInt32();
|
||||
let sessionId = Buf.readInt32();
|
||||
let isReadOnly = Buf.readUint8();
|
||||
let canBeMadeReadOnly = Buf.readUint8();
|
||||
// Ensure that padding is taken care here after reading two successive uint8's
|
||||
Buf.readUint8();
|
||||
Buf.readUint8();
|
||||
let maxSupportedLength = Buf.readInt32();
|
||||
|
||||
message.type = "GetDetailsNDEFResponse";
|
||||
message.sessionId = sessionId;
|
||||
message.isReadOnly = isReadOnly;
|
||||
message.canBeMadeReadOnly = canBeMadeReadOnly;
|
||||
message.maxSupportedLength = maxSupportedLength;
|
||||
message.status = (error === 0) ? GECKO_NFC_ERROR_SUCCESS :
|
||||
GECKO_NFC_ERROR_GENERIC_FAILURE;
|
||||
this.sendDOMMessage(message);
|
||||
};
|
||||
Buf.newParcel(NFC_REQUEST_GET_DETAILS, cb);
|
||||
Buf.writeInt32(message.sessionId);
|
||||
Buf.sendParcel();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Open a connection to the NFC target.
|
||||
*/
|
||||
connect: function connect(message) {
|
||||
let cb = function callback() {
|
||||
let error = Buf.readInt32();
|
||||
let sessionId = Buf.readInt32();
|
||||
|
||||
message.type = "ConnectResponse";
|
||||
message.sessionId = sessionId;
|
||||
message.status = (error === 0) ? GECKO_NFC_ERROR_SUCCESS :
|
||||
GECKO_NFC_ERROR_GENERIC_FAILURE;
|
||||
this.sendDOMMessage(message);
|
||||
};
|
||||
|
||||
Buf.newParcel(NFC_REQUEST_CONNECT, cb);
|
||||
Buf.writeInt32(message.sessionId);
|
||||
Buf.writeInt32(message.techType);
|
||||
Buf.sendParcel();
|
||||
},
|
||||
|
||||
/**
|
||||
* NFC Configuration
|
||||
*/
|
||||
config: function config(message) {
|
||||
let cb = function callback() {
|
||||
let error = Buf.readInt32();
|
||||
|
||||
message.type = "ConfigResponse";
|
||||
message.status = (error === 0) ? GECKO_NFC_ERROR_SUCCESS :
|
||||
GECKO_NFC_ERROR_GENERIC_FAILURE;
|
||||
this.sendDOMMessage(message);
|
||||
};
|
||||
|
||||
Buf.newParcel(NFC_REQUEST_CONFIG , cb);
|
||||
Buf.writeInt32(message.powerLevel);
|
||||
Buf.sendParcel();
|
||||
},
|
||||
|
||||
/**
|
||||
* Close connection to the NFC target.
|
||||
*/
|
||||
close: function close(message) {
|
||||
let cb = function callback() {
|
||||
let error = Buf.readInt32();
|
||||
let sessionId = Buf.readInt32();
|
||||
|
||||
message.type = "CloseResponse";
|
||||
message.sessionId = sessionId;
|
||||
message.status = (error === 0) ? GECKO_NFC_ERROR_SUCCESS :
|
||||
GECKO_NFC_ERROR_GENERIC_FAILURE;
|
||||
this.sendDOMMessage(message);
|
||||
};
|
||||
|
||||
Buf.newParcel(NFC_REQUEST_CLOSE , cb);
|
||||
Buf.writeInt32(message.sessionId);
|
||||
Buf.sendParcel();
|
||||
},
|
||||
|
||||
handleParcel: function handleParcel(request_type, callback) {
|
||||
let method = this[request_type];
|
||||
if (typeof method == "function") {
|
||||
if (DEBUG) debug("Handling parcel as " + method.name);
|
||||
method.call(this);
|
||||
} else if (typeof callback == "function") {
|
||||
callback.call(this, request_type);
|
||||
this.mCallback = null;
|
||||
} else {
|
||||
debug("Unable to handle ReqType:"+request_type);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Send messages to the main UI thread.
|
||||
*/
|
||||
sendDOMMessage: function sendDOMMessage(message) {
|
||||
postMessage(message);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Notification Handlers
|
||||
*/
|
||||
NfcWorker[NFC_NOTIFICATION_INITIALIZED] = function NFC_NOTIFICATION_INITIALIZED () {
|
||||
let status = Buf.readInt32();
|
||||
let majorVersion = Buf.readInt32();
|
||||
let minorVersion = Buf.readInt32();
|
||||
debug("NFC_NOTIFICATION_INITIALIZED status:" + status);
|
||||
if ((majorVersion != NFC_MAJOR_VERSION) || (minorVersion != NFC_MINOR_VERSION)) {
|
||||
debug("Version Mismatch! Current Supported Version : " +
|
||||
NFC_MAJOR_VERSION + "." + NFC_MINOR_VERSION +
|
||||
" Received Version : " + majorVersion + "." + minorVersion);
|
||||
}
|
||||
};
|
||||
|
||||
NfcWorker[NFC_NOTIFICATION_TECH_DISCOVERED] = function NFC_NOTIFICATION_TECH_DISCOVERED() {
|
||||
debug("NFC_NOTIFICATION_TECH_DISCOVERED");
|
||||
let techs = [];
|
||||
let ndefMsgs = [];
|
||||
|
||||
let sessionId = Buf.readInt32();
|
||||
let techCount = Buf.readInt32();
|
||||
for (let count = 0; count < techCount; count++) {
|
||||
techs.push(NFC_TECHS[Buf.readUint8()]);
|
||||
}
|
||||
|
||||
let padding = getPaddingLen(techCount);
|
||||
for (let i = 0; i < padding; i++) {
|
||||
Buf.readUint8();
|
||||
}
|
||||
|
||||
let ndefMsgCount = Buf.readInt32();
|
||||
for (let count = 0; count < ndefMsgCount; count++) {
|
||||
ndefMsgs.push(this.unMarshallNdefMessage());
|
||||
}
|
||||
this.sendDOMMessage({type: "techDiscovered",
|
||||
sessionId: sessionId,
|
||||
tech: techs,
|
||||
ndef: ndefMsgs
|
||||
});
|
||||
};
|
||||
|
||||
NfcWorker[NFC_NOTIFICATION_TECH_LOST] = function NFC_NOTIFICATION_TECH_LOST() {
|
||||
debug("NFC_NOTIFICATION_TECH_LOST");
|
||||
let sessionId = Buf.readInt32();
|
||||
debug("sessionId = " + sessionId);
|
||||
this.sendDOMMessage({type: "techLost",
|
||||
sessionId: sessionId,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Global stuff.
|
||||
*/
|
||||
|
||||
if (!this.debug) {
|
||||
// Debugging stub that goes nowhere.
|
||||
this.debug = function debug(message) {
|
||||
dump("Nfc Worker: " + message + "\n");
|
||||
};
|
||||
}
|
||||
|
||||
// Initialize buffers. This is a separate function so that unit tests can
|
||||
// re-initialize the buffers at will.
|
||||
Buf.init();
|
||||
|
||||
function onNfcMessage(data) {
|
||||
Buf.processIncoming(data);
|
||||
};
|
||||
|
||||
onmessage = function onmessage(event) {
|
||||
NfcWorker.handleDOMMessage(event.data);
|
||||
};
|
||||
|
||||
onerror = function onerror(event) {
|
||||
debug("OnError: event: " + JSON.stringify(event));
|
||||
debug("NFC Worker error " + event.message + " " + event.filename + ":" +
|
||||
event.lineno + ":\n");
|
||||
};
|
22
dom/system/gonk/nsINfcContentHelper.idl
Normal file
22
dom/system/gonk/nsINfcContentHelper.idl
Normal file
@ -0,0 +1,22 @@
|
||||
/* 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 "nsISupports.idl"
|
||||
#include "nsIDOMDOMRequest.idl"
|
||||
|
||||
interface nsIVariant;
|
||||
|
||||
[scriptable, uuid(28c8f240-da8c-11e1-9b23-0800200c9a66)]
|
||||
interface nsINfcContentHelper : nsISupports
|
||||
{
|
||||
void setSessionToken(in DOMString sessionToken);
|
||||
|
||||
nsIDOMDOMRequest getDetailsNDEF(in nsIDOMWindow window, in DOMString sessionToken);
|
||||
nsIDOMDOMRequest readNDEF(in nsIDOMWindow window, in DOMString sessionToken);
|
||||
nsIDOMDOMRequest writeNDEF(in nsIDOMWindow window, in nsIVariant records, in DOMString sessionToken);
|
||||
nsIDOMDOMRequest makeReadOnlyNDEF(in nsIDOMWindow window, in DOMString sessionToken);
|
||||
|
||||
nsIDOMDOMRequest connect(in nsIDOMWindow window, in unsigned long techType, in DOMString sessionToken);
|
||||
nsIDOMDOMRequest close(in nsIDOMWindow window, in DOMString sessionToken);
|
||||
};
|
Loading…
Reference in New Issue
Block a user