зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1163961 - Browser API: Page search. r=kchen, r=ehsan
This commit is contained in:
Родитель
fce6dd199a
Коммит
53184296fe
|
@ -229,7 +229,10 @@ BrowserElementChild.prototype = {
|
|||
"activate-next-paint-listener": this._activateNextPaintListener.bind(this),
|
||||
"set-input-method-active": this._recvSetInputMethodActive.bind(this),
|
||||
"deactivate-next-paint-listener": this._deactivateNextPaintListener.bind(this),
|
||||
"do-command": this._recvDoCommand
|
||||
"do-command": this._recvDoCommand,
|
||||
"find-all": this._recvFindAll.bind(this),
|
||||
"find-next": this._recvFindNext.bind(this),
|
||||
"clear-match": this._recvClearMatch.bind(this),
|
||||
}
|
||||
|
||||
addMessageListener("browser-element-api:call", function(aMessage) {
|
||||
|
@ -1240,6 +1243,57 @@ BrowserElementChild.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
_initFinder: function() {
|
||||
if (!this._finder) {
|
||||
try {
|
||||
this._findLimit = Services.prefs.getIntPref("accessibility.typeaheadfind.matchesCountLimit");
|
||||
} catch (e) {
|
||||
// Pref not available, assume 0, no match counting.
|
||||
this._findLimit = 0;
|
||||
}
|
||||
|
||||
let {Finder} = Components.utils.import("resource://gre/modules/Finder.jsm", {});
|
||||
this._finder = new Finder(docShell);
|
||||
this._finder.addResultListener({
|
||||
onMatchesCountResult: (data) => {
|
||||
sendAsyncMsg('findchange', {
|
||||
active: true,
|
||||
searchString: this._finder.searchString,
|
||||
searchLimit: this._findLimit,
|
||||
activeMatchOrdinal: data.current,
|
||||
numberOfMatches: data.total
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_recvFindAll: function(data) {
|
||||
this._initFinder();
|
||||
let searchString = data.json.searchString;
|
||||
this._finder.caseSensitive = data.json.caseSensitive;
|
||||
this._finder.fastFind(searchString, false, false);
|
||||
this._finder.requestMatchesCount(searchString, this._findLimit, false);
|
||||
},
|
||||
|
||||
_recvFindNext: function(data) {
|
||||
if (!this._finder) {
|
||||
debug("findNext() called before findAll()");
|
||||
return;
|
||||
}
|
||||
this._finder.findAgain(data.json.backward, false, false);
|
||||
this._finder.requestMatchesCount(this._finder.searchString, this._findLimit, false);
|
||||
},
|
||||
|
||||
_recvClearMatch: function(data) {
|
||||
if (!this._finder) {
|
||||
debug("clearMach() called before findAll()");
|
||||
return;
|
||||
}
|
||||
this._finder.removeSelection();
|
||||
sendAsyncMsg('findchange', {active: false});
|
||||
},
|
||||
|
||||
_recvSetInputMethodActive: function(data) {
|
||||
let msgData = { id: data.json.id };
|
||||
if (!this._isContentWindowCreated) {
|
||||
|
|
|
@ -206,6 +206,7 @@ BrowserElementParent.prototype = {
|
|||
"selectionstatechanged": this._handleSelectionStateChanged,
|
||||
"scrollviewchange": this._handleScrollViewChange,
|
||||
"caretstatechanged": this._handleCaretStateChanged,
|
||||
"findchange": this._handleFindChange
|
||||
};
|
||||
|
||||
let mmSecuritySensitiveCalls = {
|
||||
|
@ -475,6 +476,12 @@ BrowserElementParent.prototype = {
|
|||
this._frameElement.dispatchEvent(evt);
|
||||
},
|
||||
|
||||
_handleFindChange: function(data) {
|
||||
let evt = this._createEvent("findchange", data.json,
|
||||
/* cancelable = */ false);
|
||||
this._frameElement.dispatchEvent(evt);
|
||||
},
|
||||
|
||||
_createEvent: function(evtName, detail, cancelable) {
|
||||
// This will have to change if we ever want to send a CustomEvent with null
|
||||
// detail. For now, it's OK.
|
||||
|
@ -646,6 +653,23 @@ BrowserElementParent.prototype = {
|
|||
getCanGoForward: defineDOMRequestMethod('get-can-go-forward'),
|
||||
getContentDimensions: defineDOMRequestMethod('get-contentdimensions'),
|
||||
|
||||
findAll: defineNoReturnMethod(function(searchString, caseSensitivity) {
|
||||
return this._sendAsyncMsg('find-all', {
|
||||
searchString,
|
||||
caseSensitive: caseSensitivity == Ci.nsIBrowserElementAPI.FIND_CASE_SENSITIVE
|
||||
});
|
||||
}),
|
||||
|
||||
findNext: defineNoReturnMethod(function(direction) {
|
||||
return this._sendAsyncMsg('find-next', {
|
||||
backward: direction == Ci.nsIBrowserElementAPI.FIND_BACKWARD
|
||||
});
|
||||
}),
|
||||
|
||||
clearMatch: defineNoReturnMethod(function() {
|
||||
return this._sendAsyncMsg('clear-match');
|
||||
}),
|
||||
|
||||
goBack: defineNoReturnMethod(function() {
|
||||
this._sendAsyncMsg('go-back');
|
||||
}),
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
/* Any copyright is dedicated to the public domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Bug 1163961 - Test search API
|
||||
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
browserElementTestHelpers.setEnabledPref(true);
|
||||
browserElementTestHelpers.addPermission();
|
||||
|
||||
function runTest() {
|
||||
|
||||
let iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('mozbrowser', 'true');
|
||||
iframe.src = 'data:text/html,foo bar foo XXX Foo BAR foobar foobar';
|
||||
|
||||
const once = (eventName) => {
|
||||
return new Promise((resolve) => {
|
||||
iframe.addEventListener(eventName, function onEvent(...args) {
|
||||
iframe.removeEventListener(eventName, onEvent);
|
||||
resolve(...args);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Test if all key=>value pairs in o1 are present in o2.
|
||||
const c = (o1, o2) => Object.keys(o1).every(k => o1[k] == o2[k]);
|
||||
|
||||
let testCount = 0;
|
||||
|
||||
once('mozbrowserloadend').then(() => {
|
||||
iframe.findAll('foo', 'case-insensitive');
|
||||
return once('mozbrowserfindchange');
|
||||
}).then(({detail}) => {
|
||||
ok(c(detail, {
|
||||
msg_name: "findchange",
|
||||
active: true,
|
||||
searchString: 'foo',
|
||||
searchLimit: 100,
|
||||
activeMatchOrdinal: 1,
|
||||
numberOfMatches: 5,
|
||||
}), `test ${testCount++}`);
|
||||
iframe.findNext('forward');
|
||||
return once('mozbrowserfindchange');
|
||||
}).then(({detail}) => {
|
||||
ok(c(detail, {
|
||||
msg_name: "findchange",
|
||||
active: true,
|
||||
searchString: 'foo',
|
||||
searchLimit: 100,
|
||||
activeMatchOrdinal: 2,
|
||||
numberOfMatches: 5,
|
||||
}), `test ${testCount++}`);
|
||||
iframe.findNext('backward');
|
||||
return once('mozbrowserfindchange');
|
||||
}).then(({detail}) => {
|
||||
ok(c(detail, {
|
||||
msg_name: "findchange",
|
||||
active: true,
|
||||
searchString: 'foo',
|
||||
searchLimit: 100,
|
||||
activeMatchOrdinal: 1,
|
||||
numberOfMatches: 5,
|
||||
}), `test ${testCount++}`);
|
||||
iframe.findAll('xxx', 'case-sensitive');
|
||||
return once('mozbrowserfindchange');
|
||||
}).then(({detail}) => {
|
||||
ok(c(detail, {
|
||||
msg_name: "findchange",
|
||||
active: true,
|
||||
searchString: 'xxx',
|
||||
searchLimit: 100,
|
||||
activeMatchOrdinal: 0,
|
||||
numberOfMatches: 0,
|
||||
}), `test ${testCount++}`);
|
||||
iframe.findAll('bar', 'case-insensitive');
|
||||
return once('mozbrowserfindchange');
|
||||
}).then(({detail}) => {
|
||||
ok(c(detail, {
|
||||
msg_name: "findchange",
|
||||
active: true,
|
||||
searchString: 'bar',
|
||||
searchLimit: 100,
|
||||
activeMatchOrdinal: 1,
|
||||
numberOfMatches: 4,
|
||||
}), `test ${testCount++}`);
|
||||
iframe.findNext('forward');
|
||||
return once('mozbrowserfindchange');
|
||||
}).then(({detail}) => {
|
||||
ok(c(detail, {
|
||||
msg_name: "findchange",
|
||||
active: true,
|
||||
searchString: 'bar',
|
||||
searchLimit: 100,
|
||||
activeMatchOrdinal: 2,
|
||||
numberOfMatches: 4,
|
||||
}), `test ${testCount++}`);
|
||||
iframe.findNext('forward');
|
||||
return once('mozbrowserfindchange');
|
||||
}).then(({detail}) => {
|
||||
ok(c(detail, {
|
||||
msg_name: "findchange",
|
||||
active: true,
|
||||
searchString: 'bar',
|
||||
searchLimit: 100,
|
||||
activeMatchOrdinal: 3,
|
||||
numberOfMatches: 4,
|
||||
}), `test ${testCount++}`);
|
||||
iframe.findNext('forward');
|
||||
return once('mozbrowserfindchange');
|
||||
}).then(({detail}) => {
|
||||
ok(c(detail, {
|
||||
msg_name: "findchange",
|
||||
active: true,
|
||||
searchString: 'bar',
|
||||
searchLimit: 100,
|
||||
activeMatchOrdinal: 4,
|
||||
numberOfMatches: 4,
|
||||
}), `test ${testCount++}`);
|
||||
iframe.findNext('forward');
|
||||
return once('mozbrowserfindchange');
|
||||
}).then(({detail}) => {
|
||||
ok(c(detail, {
|
||||
msg_name: "findchange",
|
||||
active: true,
|
||||
searchString: 'bar',
|
||||
searchLimit: 100,
|
||||
activeMatchOrdinal: 1,
|
||||
numberOfMatches: 4,
|
||||
}), `test ${testCount++}`);
|
||||
iframe.clearMatch();
|
||||
return once('mozbrowserfindchange');
|
||||
}).then(({detail}) => {
|
||||
ok(c(detail, {
|
||||
msg_name: "findchange",
|
||||
active: false
|
||||
}), `test ${testCount++}`);
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
}
|
||||
|
||||
addEventListener('testready', runTest);
|
|
@ -7,6 +7,7 @@ skip-if = os == "android" || (toolkit == "cocoa" && debug) || buildapp == 'mulet
|
|||
support-files =
|
||||
browserElement_OpenMixedProcess.js
|
||||
file_browserElement_OpenMixedProcess.html
|
||||
browserElement_Find.js
|
||||
browserElement_OpenTab.js
|
||||
|
||||
[test_browserElement_oop_Viewmode.html]
|
||||
|
@ -41,6 +42,7 @@ skip-if = (toolkit == 'gonk' && !debug)
|
|||
disabled = bug 1022281
|
||||
[test_browserElement_oop_ErrorSecurity.html]
|
||||
skip-if = (toolkit == 'gonk' && !debug)
|
||||
[test_browserElement_oop_Find.html]
|
||||
[test_browserElement_oop_FirstPaint.html]
|
||||
[test_browserElement_oop_ForwardName.html]
|
||||
[test_browserElement_oop_FrameWrongURI.html]
|
||||
|
|
|
@ -29,6 +29,7 @@ support-files =
|
|||
browserElement_Download.js
|
||||
browserElement_ErrorSecurity.js
|
||||
browserElement_ExposableURI.js
|
||||
browserElement_Find.js
|
||||
browserElement_FirstPaint.js
|
||||
browserElement_ForwardName.js
|
||||
browserElement_FrameWrongURI.js
|
||||
|
@ -159,6 +160,7 @@ skip-if = os == "android" || toolkit == 'gonk' # embed-apps doesn't work in the
|
|||
[test_browserElement_inproc_Download.html]
|
||||
disabled = bug 1022281
|
||||
[test_browserElement_inproc_ExposableURI.html]
|
||||
[test_browserElement_inproc_Find.html]
|
||||
[test_browserElement_inproc_FirstPaint.html]
|
||||
[test_browserElement_inproc_ForwardName.html]
|
||||
[test_browserElement_inproc_FrameWrongURI.html]
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1163961
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1163961</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1163961">Mozilla Bug 1163961</a>
|
||||
|
||||
<script type="application/javascript;version=1.7" src="browserElement_Find.js">
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1163961
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1163961</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1163961">Mozilla Bug 1163961</a>
|
||||
|
||||
<script type="application/javascript;version=1.7" src="browserElement_Find.js">
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -26,9 +26,15 @@ interface nsIBrowserElementNextPaintListener : nsISupports
|
|||
* Interface to the BrowserElementParent implementation. All methods
|
||||
* but setFrameLoader throw when the remote process is dead.
|
||||
*/
|
||||
[scriptable, uuid(3811446f-90bb-42c1-b2b6-aae3603b61e1)]
|
||||
[scriptable, uuid(8ecb598c-f886-11e4-9915-778f934fbf93)]
|
||||
interface nsIBrowserElementAPI : nsISupports
|
||||
{
|
||||
const long FIND_CASE_SENSITIVE = 0;
|
||||
const long FIND_CASE_INSENSITIVE = 1;
|
||||
|
||||
const long FIND_FORWARD = 0;
|
||||
const long FIND_BACKWARD = 1;
|
||||
|
||||
void setFrameLoader(in nsIFrameLoader frameLoader);
|
||||
|
||||
void setVisible(in boolean visible);
|
||||
|
@ -67,6 +73,10 @@ interface nsIBrowserElementAPI : nsISupports
|
|||
nsIDOMDOMRequest getCanGoForward();
|
||||
nsIDOMDOMRequest getContentDimensions();
|
||||
|
||||
void findAll(in DOMString searchString, in long caseSensitivity);
|
||||
void findNext(in long direction);
|
||||
void clearMatch();
|
||||
|
||||
void addNextPaintListener(in nsIBrowserElementNextPaintListener listener);
|
||||
void removeNextPaintListener(in nsIBrowserElementNextPaintListener listener);
|
||||
|
||||
|
|
|
@ -376,6 +376,62 @@ nsBrowserElement::GetContentDimensions(ErrorResult& aRv)
|
|||
return req.forget().downcast<DOMRequest>();
|
||||
}
|
||||
|
||||
void
|
||||
nsBrowserElement::FindAll(const nsAString& aSearchString,
|
||||
BrowserFindCaseSensitivity aCaseSensitivity,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
|
||||
NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv));
|
||||
|
||||
uint32_t caseSensitivity;
|
||||
if (aCaseSensitivity == BrowserFindCaseSensitivity::Case_insensitive) {
|
||||
caseSensitivity = nsIBrowserElementAPI::FIND_CASE_INSENSITIVE;
|
||||
} else {
|
||||
caseSensitivity = nsIBrowserElementAPI::FIND_CASE_SENSITIVE;
|
||||
}
|
||||
|
||||
nsresult rv = mBrowserElementAPI->FindAll(aSearchString, caseSensitivity);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsBrowserElement::FindNext(BrowserFindDirection aDirection,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
|
||||
NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv));
|
||||
|
||||
uint32_t direction;
|
||||
if (aDirection == BrowserFindDirection::Backward) {
|
||||
direction = nsIBrowserElementAPI::FIND_BACKWARD;
|
||||
} else {
|
||||
direction = nsIBrowserElementAPI::FIND_FORWARD;
|
||||
}
|
||||
|
||||
nsresult rv = mBrowserElementAPI->FindNext(direction);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsBrowserElement::ClearMatch(ErrorResult& aRv)
|
||||
{
|
||||
NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
|
||||
NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv));
|
||||
|
||||
nsresult rv = mBrowserElementAPI->ClearMatch();
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsBrowserElement::AddNextPaintListener(BrowserElementNextPaintEventCallback& aListener,
|
||||
ErrorResult& aRv)
|
||||
|
|
|
@ -20,6 +20,8 @@ namespace dom {
|
|||
struct BrowserElementDownloadOptions;
|
||||
class BrowserElementNextPaintEventCallback;
|
||||
class DOMRequest;
|
||||
enum class BrowserFindCaseSensitivity: uint32_t;
|
||||
enum class BrowserFindDirection: uint32_t;
|
||||
} // namespace dom
|
||||
|
||||
class ErrorResult;
|
||||
|
@ -80,6 +82,11 @@ public:
|
|||
already_AddRefed<dom::DOMRequest> GetCanGoForward(ErrorResult& aRv);
|
||||
already_AddRefed<dom::DOMRequest> GetContentDimensions(ErrorResult& aRv);
|
||||
|
||||
void FindAll(const nsAString& aSearchString, dom::BrowserFindCaseSensitivity aCaseSensitivity,
|
||||
ErrorResult& aRv);
|
||||
void FindNext(dom::BrowserFindDirection aDirection, ErrorResult& aRv);
|
||||
void ClearMatch(ErrorResult& aRv);
|
||||
|
||||
void AddNextPaintListener(dom::BrowserElementNextPaintEventCallback& listener,
|
||||
ErrorResult& aRv);
|
||||
void RemoveNextPaintListener(dom::BrowserElementNextPaintEventCallback& listener,
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
|
||||
callback BrowserElementNextPaintEventCallback = void ();
|
||||
|
||||
enum BrowserFindCaseSensitivity { "case-sensitive", "case-insensitive" };
|
||||
enum BrowserFindDirection { "forward", "backward" };
|
||||
|
||||
dictionary BrowserElementDownloadOptions {
|
||||
DOMString? filename;
|
||||
DOMString? referrer;
|
||||
|
@ -146,4 +149,20 @@ interface BrowserElementPrivileged {
|
|||
Pref="dom.mozBrowserFramesEnabled",
|
||||
CheckPermissions="browser"]
|
||||
void setNFCFocus(boolean isFocus);
|
||||
|
||||
[Throws,
|
||||
Pref="dom.mozBrowserFramesEnabled",
|
||||
CheckPermissions="browser"]
|
||||
void findAll(DOMString searchString, BrowserFindCaseSensitivity caseSensitivity);
|
||||
|
||||
[Throws,
|
||||
Pref="dom.mozBrowserFramesEnabled",
|
||||
CheckPermissions="browser"]
|
||||
void findNext(BrowserFindDirection direction);
|
||||
|
||||
[Throws,
|
||||
Pref="dom.mozBrowserFramesEnabled",
|
||||
CheckPermissions="browser"]
|
||||
void clearMatch();
|
||||
|
||||
};
|
||||
|
|
|
@ -1048,3 +1048,6 @@ function GetClipboardSearchString(aLoadContext) {
|
|||
|
||||
return searchString;
|
||||
}
|
||||
|
||||
this.Finder = Finder;
|
||||
this.GetClipboardSearchString = GetClipboardSearchString;
|
||||
|
|
Загрузка…
Ссылка в новой задаче