tenfourfox/mobile/android/chrome/content/FindHelper.js
Cameron Kaiser c9b2922b70 hello FPR
2017-04-19 00:56:45 -07:00

159 lines
4.4 KiB
JavaScript

/* 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/. */
"use strict";
var FindHelper = {
_finder: null,
_targetTab: null,
_initialViewport: null,
_viewportChanged: false,
_result: null,
_limit: 0,
observe: function(aMessage, aTopic, aData) {
switch(aTopic) {
case "FindInPage:Opened": {
this._findOpened();
break;
}
case "Tab:Selected": {
// Allow for page switching.
this._uninit();
break;
}
case "FindInPage:Closed":
this._uninit();
this._findClosed();
break;
}
},
_findOpened: function() {
try {
this._limit = Services.prefs.getIntPref("accessibility.typeaheadfind.matchesCountLimit");
} catch (e) {
// Pref not available, assume 0, no match counting.
this._limit = 0;
}
Messaging.addListener((data) => {
this.doFind(data.searchString, data.matchCase);
return this._getMatchesCountResult(data.searchString);
}, "FindInPage:Find");
Messaging.addListener((data) => {
this.findAgain(data.searchString, false, data.matchCase);
return this._getMatchesCountResult(data.searchString);
}, "FindInPage:Next");
Messaging.addListener((data) => {
this.findAgain(data.searchString, true, data.matchCase);
return this._getMatchesCountResult(data.searchString);
}, "FindInPage:Prev");
},
_init: function() {
// If there's no find in progress, start one.
if (this._finder) {
return;
}
this._targetTab = BrowserApp.selectedTab;
try {
this._finder = this._targetTab.browser.finder;
} catch (e) {
throw new Error("FindHelper: " + e + "\n" +
"JS stack: \n" + (e.stack || Components.stack.formattedStack));
}
this._finder.addResultListener(this);
this._initialViewport = JSON.stringify(this._targetTab.getViewport());
this._viewportChanged = false;
},
_uninit: function() {
// If there's no find in progress, there's nothing to clean up.
if (!this._finder) {
return;
}
this._finder.removeSelection();
this._finder.removeResultListener(this);
this._finder = null;
this._targetTab = null;
this._initialViewport = null;
this._viewportChanged = false;
},
_findClosed: function() {
Messaging.removeListener("FindInPage:Find");
Messaging.removeListener("FindInPage:Next");
Messaging.removeListener("FindInPage:Prev");
},
/**
* Request, wait for, and return the current matchesCount results for a string.
*/
_getMatchesCountResult: function(findString) {
// Count matches up to any provided limit.
if (this._limit <= 0) {
return { total: 0, current: 0, limit: 0 };
}
// Sync call to Finder, results available immediately.
this._finder.requestMatchesCount(findString, this._limit);
return this._result;
},
/**
* Pass along the count results to FindInPageBar for display.
*/
onMatchesCountResult: function(result) {
this._result = result;
this._result.limit = this._limit;
},
doFind: function(searchString, matchCase) {
if (!this._finder) {
this._init();
}
this._finder.caseSensitive = matchCase;
this._finder.fastFind(searchString, false);
},
findAgain: function(searchString, findBackwards, matchCase) {
// This always happens if the user taps next/previous after re-opening the
// search bar, and not only forces _init() but also an initial fastFind(STRING)
// before any findAgain(DIRECTION).
if (!this._finder) {
this.doFind(searchString, matchCase);
return;
}
this._finder.caseSensitive = matchCase;
this._finder.findAgain(findBackwards, false, false);
},
onFindResult: function(aData) {
if (aData.result == Ci.nsITypeAheadFind.FIND_NOTFOUND) {
if (this._viewportChanged) {
if (this._targetTab != BrowserApp.selectedTab) {
// this should never happen
Cu.reportError("Warning: selected tab changed during find!");
// fall through and restore viewport on the initial tab anyway
}
this._targetTab.setViewport(JSON.parse(this._initialViewport));
this._targetTab.sendViewportUpdate();
}
} else {
// Disabled until bug 1014113 is fixed
// ZoomHelper.zoomToRect(aData.rect);
this._viewportChanged = true;
}
}
};