editor/AsyncSpellCheckTestHelper.jsm

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 this.EXPORTED_SYMBOLS = [
     6   "onSpellCheck",
     7 ];
     9 const SPELL_CHECK_ENDED_TOPIC = "inlineSpellChecker-spellCheck-ended";
    10 const SPELL_CHECK_STARTED_TOPIC = "inlineSpellChecker-spellCheck-started";
    12 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
    14 /**
    15  * Waits until spell checking has stopped on the given element.
    16  *
    17  * When a spell check is pending, this waits indefinitely until the spell check
    18  * ends.  When a spell check is not pending, it waits a small number of turns of
    19  * the event loop: if a spell check begins, it resumes waiting indefinitely for
    20  * the end, and otherwise it stops waiting and calls the callback.
    21  *
    22  * This this can therefore trap spell checks that have not started at the time
    23  * of calling, spell checks that have already started, multiple consecutive
    24  * spell checks, and the absence of spell checks altogether.
    25  *
    26  * @param editableElement  The element being spell checked.
    27  * @param callback         Called when spell check has completed or enough turns
    28  *                         of the event loop have passed to determine it has not
    29  *                         started.
    30  */
    31 function onSpellCheck(editableElement, callback) {
    32   let editor = editableElement.editor;
    33   if (!editor) {
    34     let win = editableElement.ownerDocument.defaultView;
    35     editor = win.QueryInterface(Ci.nsIInterfaceRequestor).
    36                  getInterface(Ci.nsIWebNavigation).
    37                  QueryInterface(Ci.nsIInterfaceRequestor).
    38                  getInterface(Ci.nsIEditingSession).
    39                  getEditorForWindow(win);
    40   }
    41   if (!editor)
    42     throw new Error("Unable to find editor for element " + editableElement);
    44   try {
    45     // False is important here.  Pass false so that the inline spell checker
    46     // isn't created if it doesn't already exist.
    47     var isc = editor.getInlineSpellChecker(false);
    48   }
    49   catch (err) {
    50     // getInlineSpellChecker throws if spell checking is not enabled instead of
    51     // just returning null, which seems kind of lame.  (Spell checking is not
    52     // enabled on Android.)  The point here is only to determine whether spell
    53     // check is pending, and if getInlineSpellChecker throws, then it's not
    54     // pending.
    55   }
    56   let waitingForEnded = isc && isc.spellCheckPending;
    57   let count = 0;
    59   function observe(subj, topic, data) {
    60     if (subj != editor)
    61       return;
    62     count = 0;
    63     let expectedTopic = waitingForEnded ? SPELL_CHECK_ENDED_TOPIC :
    64                         SPELL_CHECK_STARTED_TOPIC;
    65     if (topic != expectedTopic)
    66       Cu.reportError("Expected " + expectedTopic + " but got " + topic + "!");
    67     waitingForEnded = !waitingForEnded;
    68   }
    70   let os = Cc["@mozilla.org/observer-service;1"].
    71            getService(Ci.nsIObserverService);
    72   os.addObserver(observe, SPELL_CHECK_STARTED_TOPIC, false);
    73   os.addObserver(observe, SPELL_CHECK_ENDED_TOPIC, false);
    75   let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
    76   timer.init(function tick() {
    77     // Wait an arbitrarily large number -- 50 -- turns of the event loop before
    78     // declaring that no spell checks will start.
    79     if (waitingForEnded || ++count < 50)
    80       return;
    81     timer.cancel();
    82     os.removeObserver(observe, SPELL_CHECK_STARTED_TOPIC);
    83     os.removeObserver(observe, SPELL_CHECK_ENDED_TOPIC);
    84     callback();
    85   }, 0, Ci.nsITimer.TYPE_REPEATING_SLACK);
    86 };

mercurial