Back out a5a5d2c176f7 (bug 882865) because of Android test failures on a CLOSED TREE
[gecko.git] / b2g / components / MozKeyboard.js
blob0bd21e098980f0be336ccc0cc02f9a028119c38c
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 "use strict";
7 const Ci = Components.interfaces;
8 const Cu = Components.utils;
10 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
11 Cu.import("resource://gre/modules/Services.jsm");
12 Cu.import("resource://gre/modules/ObjectWrapper.jsm");
14 XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
15   "@mozilla.org/childprocessmessagemanager;1", "nsIMessageSender");
17 XPCOMUtils.defineLazyServiceGetter(this, "tm",
18   "@mozilla.org/thread-manager;1", "nsIThreadManager");
20 // -----------------------------------------------------------------------
21 // MozKeyboard
22 // -----------------------------------------------------------------------
24 function MozKeyboard() { }
26 MozKeyboard.prototype = {
27   classID: Components.ID("{397a7fdf-2254-47be-b74e-76625a1a66d5}"),
29   QueryInterface: XPCOMUtils.generateQI([
30     Ci.nsIB2GKeyboard, Ci.nsIDOMGlobalPropertyInitializer, Ci.nsIObserver
31   ]),
33   classInfo: XPCOMUtils.generateCI({
34     "classID": Components.ID("{397a7fdf-2254-47be-b74e-76625a1a66d5}"),
35     "contractID": "@mozilla.org/b2g-keyboard;1",
36     "interfaces": [Ci.nsIB2GKeyboard],
37     "flags": Ci.nsIClassInfo.DOM_OBJECT,
38     "classDescription": "B2G Virtual Keyboard"
39   }),
41   init: function mozKeyboardInit(win) {
42     let principal = win.document.nodePrincipal;
43     let perm = Services.perms
44                .testExactPermissionFromPrincipal(principal, "keyboard");
45     if (perm != Ci.nsIPermissionManager.ALLOW_ACTION) {
46       dump("No permission to use the keyboard API for " +
47            principal.origin + "\n");
48       return null;
49     }
51     Services.obs.addObserver(this, "inner-window-destroyed", false);
52     cpmm.addMessageListener('Keyboard:FocusChange', this);
53     cpmm.addMessageListener('Keyboard:SelectionChange', this);
55     this._window = win;
56     this._utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
57                      .getInterface(Ci.nsIDOMWindowUtils);
58     this.innerWindowID = this._utils.currentInnerWindowID;
59     this._focusHandler = null;
60     this._selectionHandler = null;
61     this._selectionStart = -1;
62     this._selectionEnd = -1;
63   },
65   uninit: function mozKeyboardUninit() {
66     Services.obs.removeObserver(this, "inner-window-destroyed");
67     cpmm.removeMessageListener('Keyboard:FocusChange', this);
68     cpmm.removeMessageListener('Keyboard:SelectionChange', this);
70     this._window = null;
71     this._utils = null;
72     this._focusHandler = null;
73     this._selectionHandler = null;
74   },
76   sendKey: function mozKeyboardSendKey(keyCode, charCode) {
77     charCode = (charCode == undefined) ? keyCode : charCode;
79     let mainThread = tm.mainThread;
80     let utils = this._utils;
82     function send(type) {
83       mainThread.dispatch(function() {
84         utils.sendKeyEvent(type, keyCode, charCode, null);
85       }, mainThread.DISPATCH_NORMAL);
86     }
88     send("keydown");
89     send("keypress");
90     send("keyup");
91   },
93   setSelectedOption: function mozKeyboardSetSelectedOption(index) {
94     cpmm.sendAsyncMessage('Keyboard:SetSelectedOption', {
95       'index': index
96     });
97   },
99   setValue: function mozKeyboardSetValue(value) {
100     cpmm.sendAsyncMessage('Keyboard:SetValue', {
101       'value': value
102     });
103   },
105   setSelectedOptions: function mozKeyboardSetSelectedOptions(indexes) {
106     cpmm.sendAsyncMessage('Keyboard:SetSelectedOptions', {
107       'indexes': indexes
108     });
109   },
111   set onselectionchange(val) {
112     this._selectionHandler = val;
113   },
115   get onselectionchange() {
116     return this._selectionHandler;
117   },
119   get selectionStart() {
120     return this._selectionStart;
121   },
123   get selectionEnd() {
124     return this._selectionEnd;
125   },
127   setSelectionRange: function mozKeyboardSetSelectionRange(start, end) {
128     cpmm.sendAsyncMessage('Keyboard:SetSelectionRange', {
129       'selectionStart': start,
130       'selectionEnd': end
131     });
132   },
134   removeFocus: function mozKeyboardRemoveFocus() {
135     cpmm.sendAsyncMessage('Keyboard:RemoveFocus', {});
136   },
138   set onfocuschange(val) {
139     this._focusHandler = val;
140   },
142   get onfocuschange() {
143     return this._focusHandler;
144   },
146   replaceSurroundingText: function mozKeyboardReplaceSurroundingText(
147     text, beforeLength, afterLength) {
148     cpmm.sendAsyncMessage('Keyboard:ReplaceSurroundingText', {
149       'text': text || '',
150       'beforeLength': (typeof beforeLength === 'number' ? beforeLength : 0),
151       'afterLength': (typeof afterLength === 'number' ? afterLength: 0)
152     });
153   },
155   receiveMessage: function mozKeyboardReceiveMessage(msg) {
156     if (msg.name == "Keyboard:FocusChange") {
157        let msgJson = msg.json;
158        if (msgJson.type != "blur") {
159          this._selectionStart = msgJson.selectionStart;
160          this._selectionEnd = msgJson.selectionEnd;
161        } else {
162          this._selectionStart = 0;
163          this._selectionEnd = 0;
164        }
166       let handler = this._focusHandler;
167       if (!handler || !(handler instanceof Ci.nsIDOMEventListener))
168         return;
170       let detail = {
171         "detail": msgJson
172       };
174       let evt = new this._window.CustomEvent("focuschanged",
175           ObjectWrapper.wrap(detail, this._window));
176       handler.handleEvent(evt);
177     } else if (msg.name == "Keyboard:SelectionChange") {
178       let msgJson = msg.json;
180       this._selectionStart = msgJson.selectionStart;
181       this._selectionEnd = msgJson.selectionEnd;
183       let handler = this._selectionHandler;
184       if (!handler || !(handler instanceof Ci.nsIDOMEventListener))
185         return;
187       let evt = new this._window.CustomEvent("selectionchange",
188           ObjectWrapper.wrap({}, this._window));
189       handler.handleEvent(evt);
190     }
191   },
193   observe: function mozKeyboardObserve(subject, topic, data) {
194     let wId = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
195     if (wId == this.innerWindowID)
196       this.uninit();
197   }
200 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MozKeyboard]);