dom/inputmethod/Keyboard.jsm

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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 this.EXPORTED_SYMBOLS = ['Keyboard'];
     9 const Cu = Components.utils;
    10 const Cc = Components.classes;
    11 const Ci = Components.interfaces;
    13 Cu.import('resource://gre/modules/Services.jsm');
    14 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
    16 XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
    17   "@mozilla.org/parentprocessmessagemanager;1", "nsIMessageBroadcaster");
    19 XPCOMUtils.defineLazyModuleGetter(this, "SystemAppProxy",
    20                                   "resource://gre/modules/SystemAppProxy.jsm");
    22 this.Keyboard = {
    23   _formMM: null,     // The current web page message manager.
    24   _keyboardMM: null, // The keyboard app message manager.
    25   _systemMessageName: [
    26     'SetValue', 'RemoveFocus', 'SetSelectedOption', 'SetSelectedOptions'
    27   ],
    29   _messageNames: [
    30     'SetSelectionRange', 'ReplaceSurroundingText', 'ShowInputMethodPicker',
    31     'SwitchToNextInputMethod', 'HideInputMethod',
    32     'GetText', 'SendKey', 'GetContext',
    33     'SetComposition', 'EndComposition',
    34     'Register', 'Unregister'
    35   ],
    37   get formMM() {
    38     if (this._formMM && !Cu.isDeadWrapper(this._formMM))
    39       return this._formMM;
    41     return null;
    42   },
    44   set formMM(mm) {
    45     this._formMM = mm;
    46   },
    48   sendToForm: function(name, data) {
    49     try {
    50       this.formMM.sendAsyncMessage(name, data);
    51     } catch(e) { }
    52   },
    54   sendToKeyboard: function(name, data) {
    55     try {
    56       this._keyboardMM.sendAsyncMessage(name, data);
    57     } catch(e) { }
    58   },
    60   init: function keyboardInit() {
    61     Services.obs.addObserver(this, 'inprocess-browser-shown', false);
    62     Services.obs.addObserver(this, 'remote-browser-shown', false);
    63     Services.obs.addObserver(this, 'oop-frameloader-crashed', false);
    65     for (let name of this._messageNames) {
    66       ppmm.addMessageListener('Keyboard:' + name, this);
    67     }
    69     for (let name of this._systemMessageName) {
    70       ppmm.addMessageListener('System:' + name, this);
    71     }
    72   },
    74   observe: function keyboardObserve(subject, topic, data) {
    75     let frameLoader = subject.QueryInterface(Ci.nsIFrameLoader);
    76     let mm = frameLoader.messageManager;
    78     if (topic == 'oop-frameloader-crashed') {
    79       if (this.formMM == mm) {
    80         // The application has been closed unexpectingly. Let's tell the
    81         // keyboard app that the focus has been lost.
    82         this.sendToKeyboard('Keyboard:FocusChange', { 'type': 'blur' });
    83       }
    84     } else {
    85       // Ignore notifications that aren't from a BrowserOrApp
    86       if (!frameLoader.ownerIsBrowserOrAppFrame) {
    87         return;
    88       }
    89       this.initFormsFrameScript(mm);
    90     }
    91   },
    93   initFormsFrameScript: function(mm) {
    94     mm.addMessageListener('Forms:Input', this);
    95     mm.addMessageListener('Forms:SelectionChange', this);
    96     mm.addMessageListener('Forms:GetText:Result:OK', this);
    97     mm.addMessageListener('Forms:GetText:Result:Error', this);
    98     mm.addMessageListener('Forms:SetSelectionRange:Result:OK', this);
    99     mm.addMessageListener('Forms:SetSelectionRange:Result:Error', this);
   100     mm.addMessageListener('Forms:ReplaceSurroundingText:Result:OK', this);
   101     mm.addMessageListener('Forms:ReplaceSurroundingText:Result:Error', this);
   102     mm.addMessageListener('Forms:SendKey:Result:OK', this);
   103     mm.addMessageListener('Forms:SendKey:Result:Error', this);
   104     mm.addMessageListener('Forms:SequenceError', this);
   105     mm.addMessageListener('Forms:GetContext:Result:OK', this);
   106     mm.addMessageListener('Forms:SetComposition:Result:OK', this);
   107     mm.addMessageListener('Forms:EndComposition:Result:OK', this);
   108   },
   110   receiveMessage: function keyboardReceiveMessage(msg) {
   111     // If we get a 'Keyboard:XXX'/'System:XXX' message, check that the sender
   112     // has the required permission.
   113     let mm;
   114     let isKeyboardRegistration = msg.name == "Keyboard:Register" ||
   115                                  msg.name == "Keyboard:Unregister";
   116     if (msg.name.indexOf("Keyboard:") === 0 ||
   117         msg.name.indexOf("System:") === 0) {
   118       if (!this.formMM && !isKeyboardRegistration) {
   119         return;
   120       }
   122       try {
   123         mm = msg.target.QueryInterface(Ci.nsIFrameLoaderOwner)
   124                        .frameLoader.messageManager;
   125       } catch(e) {
   126         mm = msg.target;
   127       }
   129       // That should never happen.
   130       if (!mm) {
   131         dump("!! No message manager found for " + msg.name);
   132         return;
   133       }
   135       let testing = false;
   136       try {
   137         testing = Services.prefs.getBoolPref("dom.mozInputMethod.testing");
   138       } catch (e) {
   139       }
   141       let perm = (msg.name.indexOf("Keyboard:") === 0) ? "input"
   142                                                        : "input-manage";
   143       if (!isKeyboardRegistration && !testing &&
   144           !mm.assertPermission(perm)) {
   145         dump("Keyboard message " + msg.name +
   146         " from a content process with no '" + perm + "' privileges.");
   147         return;
   148       }
   149     }
   151     switch (msg.name) {
   152       case 'Forms:Input':
   153         this.handleFocusChange(msg);
   154         break;
   155       case 'Forms:SelectionChange':
   156       case 'Forms:GetText:Result:OK':
   157       case 'Forms:GetText:Result:Error':
   158       case 'Forms:SetSelectionRange:Result:OK':
   159       case 'Forms:ReplaceSurroundingText:Result:OK':
   160       case 'Forms:SendKey:Result:OK':
   161       case 'Forms:SendKey:Result:Error':
   162       case 'Forms:SequenceError':
   163       case 'Forms:GetContext:Result:OK':
   164       case 'Forms:SetComposition:Result:OK':
   165       case 'Forms:EndComposition:Result:OK':
   166       case 'Forms:SetSelectionRange:Result:Error':
   167       case 'Forms:ReplaceSurroundingText:Result:Error':
   168         let name = msg.name.replace(/^Forms/, 'Keyboard');
   169         this.forwardEvent(name, msg);
   170         break;
   172       case 'System:SetValue':
   173         this.setValue(msg);
   174         break;
   175       case 'Keyboard:RemoveFocus':
   176       case 'System:RemoveFocus':
   177         this.removeFocus();
   178         break;
   179       case 'System:SetSelectedOption':
   180         this.setSelectedOption(msg);
   181         break;
   182       case 'System:SetSelectedOptions':
   183         this.setSelectedOption(msg);
   184         break;
   185       case 'Keyboard:SetSelectionRange':
   186         this.setSelectionRange(msg);
   187         break;
   188       case 'Keyboard:ReplaceSurroundingText':
   189         this.replaceSurroundingText(msg);
   190         break;
   191       case 'Keyboard:SwitchToNextInputMethod':
   192         this.switchToNextInputMethod();
   193         break;
   194       case 'Keyboard:ShowInputMethodPicker':
   195         this.showInputMethodPicker();
   196         break;
   197       case 'Keyboard:GetText':
   198         this.getText(msg);
   199         break;
   200       case 'Keyboard:SendKey':
   201         this.sendKey(msg);
   202         break;
   203       case 'Keyboard:GetContext':
   204         this.getContext(msg);
   205         break;
   206       case 'Keyboard:SetComposition':
   207         this.setComposition(msg);
   208         break;
   209       case 'Keyboard:EndComposition':
   210         this.endComposition(msg);
   211         break;
   212       case 'Keyboard:Register':
   213         this._keyboardMM = mm;
   214         break;
   215       case 'Keyboard:Unregister':
   216         this._keyboardMM = null;
   217         break;
   218     }
   219   },
   221   forwardEvent: function keyboardForwardEvent(newEventName, msg) {
   222     this.formMM = msg.target.QueryInterface(Ci.nsIFrameLoaderOwner)
   223                             .frameLoader.messageManager;
   225     this.sendToKeyboard(newEventName, msg.data);
   226   },
   228   handleFocusChange: function keyboardHandleFocusChange(msg) {
   229     this.forwardEvent('Keyboard:FocusChange', msg);
   231     // Chrome event, used also to render value selectors; that's why we need
   232     // the info about choices / min / max here as well...
   233     SystemAppProxy.dispatchEvent({
   234       type: 'inputmethod-contextchange',
   235       inputType: msg.data.type,
   236       value: msg.data.value,
   237       choices: JSON.stringify(msg.data.choices),
   238       min: msg.data.min,
   239       max: msg.data.max
   240     });
   241   },
   243   setSelectedOption: function keyboardSetSelectedOption(msg) {
   244     this.sendToForm('Forms:Select:Choice', msg.data);
   245   },
   247   setSelectedOptions: function keyboardSetSelectedOptions(msg) {
   248     this.sendToForm('Forms:Select:Choice', msg.data);
   249   },
   251   setSelectionRange: function keyboardSetSelectionRange(msg) {
   252     this.sendToForm('Forms:SetSelectionRange', msg.data);
   253   },
   255   setValue: function keyboardSetValue(msg) {
   256     this.sendToForm('Forms:Input:Value', msg.data);
   257   },
   259   removeFocus: function keyboardRemoveFocus() {
   260     this.sendToForm('Forms:Select:Blur', {});
   261   },
   263   replaceSurroundingText: function keyboardReplaceSurroundingText(msg) {
   264     this.sendToForm('Forms:ReplaceSurroundingText', msg.data);
   265   },
   267   showInputMethodPicker: function keyboardShowInputMethodPicker() {
   268     SystemAppProxy.dispatchEvent({
   269       type: "inputmethod-showall"
   270     });
   271   },
   273   switchToNextInputMethod: function keyboardSwitchToNextInputMethod() {
   274     SystemAppProxy.dispatchEvent({
   275       type: "inputmethod-next"
   276     });
   277   },
   279   getText: function keyboardGetText(msg) {
   280     this.sendToForm('Forms:GetText', msg.data);
   281   },
   283   sendKey: function keyboardSendKey(msg) {
   284     this.sendToForm('Forms:Input:SendKey', msg.data);
   285   },
   287   getContext: function keyboardGetContext(msg) {
   288     if (this._layouts) {
   289       this.sendToKeyboard('Keyboard:LayoutsChange', this._layouts);
   290     }
   292     this.sendToForm('Forms:GetContext', msg.data);
   293   },
   295   setComposition: function keyboardSetComposition(msg) {
   296     this.sendToForm('Forms:SetComposition', msg.data);
   297   },
   299   endComposition: function keyboardEndComposition(msg) {
   300     this.sendToForm('Forms:EndComposition', msg.data);
   301   },
   303   /**
   304    * Get the number of keyboard layouts active from keyboard_manager
   305    */
   306   _layouts: null,
   307   setLayouts: function keyboardSetLayoutCount(layouts) {
   308     // The input method plugins may not have loaded yet,
   309     // cache the layouts so on init we can respond immediately instead
   310     // of going back and forth between keyboard_manager
   311     this._layouts = layouts;
   313     this.sendToKeyboard('Keyboard:LayoutsChange', layouts);
   314   }
   315 };
   317 this.Keyboard.init();

mercurial