Merge pull request #3855 from deepak1556/find_api_patch

webContents: adding findInPage api
This commit is contained in:
Cheng Zhao 2015-12-22 19:01:39 +08:00
commit 8ca42e9d9f
13 changed files with 260 additions and 6 deletions

View file

@ -224,7 +224,8 @@ WebContents::WebContents(content::WebContents* web_contents)
}
WebContents::WebContents(v8::Isolate* isolate,
const mate::Dictionary& options) {
const mate::Dictionary& options)
: request_id_(0) {
// Whether it is a guest WebContents.
bool is_guest = false;
options.Get("isGuest", &is_guest);
@ -426,6 +427,29 @@ bool WebContents::OnGoToEntryOffset(int offset) {
return false;
}
void WebContents::FindReply(content::WebContents* web_contents,
int request_id,
int number_of_matches,
const gfx::Rect& selection_rect,
int active_match_ordinal,
bool final_update) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
mate::Dictionary result = mate::Dictionary::CreateEmpty(isolate());
if (number_of_matches == -1) {
result.Set("requestId", request_id);
result.Set("selectionArea", selection_rect);
result.Set("finalUpdate", final_update);
Emit("found-in-page", result);
} else if (final_update) {
result.Set("requestId", request_id);
result.Set("matches", number_of_matches);
result.Set("finalUpdate", final_update);
Emit("found-in-page", result);
}
}
void WebContents::BeforeUnloadFired(const base::TimeTicks& proceed_time) {
// Do nothing, we override this method just to avoid compilation error since
// there are two virtual functions named BeforeUnloadFired.
@ -902,6 +926,25 @@ void WebContents::ReplaceMisspelling(const base::string16& word) {
web_contents()->ReplaceMisspelling(word);
}
uint32 WebContents::FindInPage(mate::Arguments* args) {
uint32 request_id = GetNextRequestId();
base::string16 search_text;
blink::WebFindOptions options;
if (!args->GetNext(&search_text) || search_text.empty()) {
args->ThrowError("Must provide a non-empty search content");
return 0;
}
args->GetNext(&options);
web_contents()->Find(request_id, search_text, options);
return request_id;
}
void WebContents::StopFindInPage(content::StopFindAction action) {
web_contents()->StopFinding(action);
}
void WebContents::Focus() {
web_contents()->Focus();
}
@ -1048,6 +1091,8 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
.SetMethod("unselect", &WebContents::Unselect)
.SetMethod("replace", &WebContents::Replace)
.SetMethod("replaceMisspelling", &WebContents::ReplaceMisspelling)
.SetMethod("findInPage", &WebContents::FindInPage)
.SetMethod("stopFindInPage", &WebContents::StopFindInPage)
.SetMethod("focus", &WebContents::Focus)
.SetMethod("tabTraverse", &WebContents::TabTraverse)
.SetMethod("_send", &WebContents::SendIPCMessage)

View file

@ -110,6 +110,8 @@ class WebContents : public mate::TrackableObject<WebContents>,
void Unselect();
void Replace(const base::string16& word);
void ReplaceMisspelling(const base::string16& word);
uint32 FindInPage(mate::Arguments* args);
void StopFindInPage(content::StopFindAction action);
// Focus.
void Focus();
@ -187,6 +189,12 @@ class WebContents : public mate::TrackableObject<WebContents>,
void RendererResponsive(content::WebContents* source) override;
bool HandleContextMenu(const content::ContextMenuParams& params) override;
bool OnGoToEntryOffset(int offset) override;
void FindReply(content::WebContents* web_contents,
int request_id,
int number_of_matches,
const gfx::Rect& selection_rect,
int active_match_ordinal,
bool final_update) override;
// content::WebContentsObserver:
void BeforeUnloadFired(const base::TimeTicks& proceed_time) override;
@ -242,6 +250,10 @@ class WebContents : public mate::TrackableObject<WebContents>,
AtomBrowserContext* GetBrowserContext() const;
uint32 GetNextRequestId() {
return ++request_id_;
}
// Called when received a message from renderer.
void OnRendererMessage(const base::string16& channel,
const base::ListValue& args);
@ -263,6 +275,9 @@ class WebContents : public mate::TrackableObject<WebContents>,
// The type of current WebContents.
Type type_;
// Request id used for findInPage request.
uint32 request_id_;
DISALLOW_COPY_AND_ASSIGN(WebContents);
};

View file

@ -22,9 +22,10 @@ supportedWebViewEvents = [
'page-title-updated'
'page-favicon-updated'
'enter-html-full-screen'
'leave-html-full-screen',
'media-started-playing',
'media-paused',
'leave-html-full-screen'
'media-started-playing'
'media-paused'
'found-in-page'
]
nextInstanceId = 0

View file

@ -13,6 +13,7 @@
#include "content/public/browser/native_web_keyboard_event.h"
#include "native_mate/dictionary.h"
#include "third_party/WebKit/public/web/WebDeviceEmulationParams.h"
#include "third_party/WebKit/public/web/WebFindOptions.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
namespace {
@ -282,4 +283,20 @@ bool Converter<blink::WebDeviceEmulationParams>::FromV8(
return true;
}
bool Converter<blink::WebFindOptions>::FromV8(
v8::Isolate* isolate,
v8::Local<v8::Value> val,
blink::WebFindOptions* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
dict.Get("forward", &out->forward);
dict.Get("matchCase", &out->matchCase);
dict.Get("findNext", &out->findNext);
dict.Get("wordStart", &out->wordStart);
dict.Get("medialCapitalAsWordStart", &out->medialCapitalAsWordStart);
return true;
}
} // namespace mate

View file

@ -13,10 +13,11 @@ class WebMouseEvent;
class WebMouseWheelEvent;
class WebKeyboardEvent;
struct WebDeviceEmulationParams;
struct WebFindOptions;
struct WebFloatPoint;
struct WebPoint;
struct WebSize;
}
} // namespace blink
namespace content {
struct NativeWebKeyboardEvent;
@ -80,6 +81,12 @@ struct Converter<blink::WebDeviceEmulationParams> {
blink::WebDeviceEmulationParams* out);
};
template<>
struct Converter<blink::WebFindOptions> {
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
blink::WebFindOptions* out);
};
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_BLINK_CONVERTER_H_

View file

@ -4,6 +4,7 @@
#include "atom/common/native_mate_converters/content_converter.h"
#include <string>
#include <vector>
#include "atom/common/native_mate_converters/callback.h"
@ -97,4 +98,25 @@ v8::Local<v8::Value> Converter<ContextMenuParamsWithWebContents>::ToV8(
return mate::ConvertToV8(isolate, dict);
}
// static
bool Converter<content::StopFindAction>::FromV8(
v8::Isolate* isolate,
v8::Local<v8::Value> val,
content::StopFindAction* out) {
std::string action;
if (!ConvertFromV8(isolate, val, &action))
return false;
if (action == "clearSelection")
*out = content::STOP_FIND_ACTION_CLEAR_SELECTION;
else if (action == "keepSelection")
*out = content::STOP_FIND_ACTION_KEEP_SELECTION;
else if (action == "activateSelection")
*out = content::STOP_FIND_ACTION_ACTIVATE_SELECTION;
else
return false;
return true;
}
} // namespace mate

View file

@ -8,6 +8,7 @@
#include <utility>
#include "content/public/common/menu_item.h"
#include "content/public/common/stop_find_action.h"
#include "native_mate/converter.h"
namespace content {
@ -32,6 +33,12 @@ struct Converter<ContextMenuParamsWithWebContents> {
const ContextMenuParamsWithWebContents& val);
};
template<>
struct Converter<content::StopFindAction> {
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
content::StopFindAction* out);
};
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_CONTENT_CONVERTER_H_

View file

@ -27,6 +27,7 @@ WEB_VIEW_EVENTS =
'page-favicon-updated': ['favicons']
'enter-html-full-screen': []
'leave-html-full-screen': []
'found-in-page': ['result']
DEPRECATED_EVENTS =
'page-title-updated': 'page-title-set'

View file

@ -287,6 +287,8 @@ registerWebViewElement = ->
'unselect'
'replace'
'replaceMisspelling'
'findInPage'
'stopFindInPage'
'getId'
'downloadURL'
'inspectServiceWorker'

View file

@ -229,6 +229,20 @@ Emitted when media starts playing.
Emitted when media is paused or done playing.
### Event: 'found-in-page'
Returns:
* `event` Event
* `result` Object
* `requestId` Integer
* `finalUpdate` Boolean - Indicates if more responses are to follow.
* `matches` Integer (Optional) - Number of Matches.
* `selectionArea` Object (Optional) - Coordinates of first match region.
Emitted when a result is available for
[`webContents.findInPage`](web-contents.md#webcontentsfindinpage) request.
## Instance Methods
The `webContents` object has the following instance methods:
@ -420,6 +434,45 @@ Executes the editing command `replace` in web page.
Executes the editing command `replaceMisspelling` in web page.
### `webContents.findInPage(text[, options])`
* `text` String - Content to be searched, must not be empty.
* `options` Object (Optional)
* `forward` Boolean - Whether to search forward or backward, defaults to `true`.
* `findNext` Boolean - Whether the operation is first request or a follow up,
defaults to `false`.
* `matchCase` Boolean - Whether search should be case-sensitive,
defaults to `false`.
* `wordStart` Boolean - Whether to look only at the start of words.
defaults to `false`.
* `medialCapitalAsWordStart` Boolean - When combined with `wordStart`,
accepts a match in the middle of a word if the match begins with an
uppercase letter followed by a lowercase or non-letter.
Accepts several other intra-word matches, defaults to `false`.
Starts a request to find all matches for the `text` in the web page and returns an `Integer`
representing the request id used for the request. The result of the request can be
obtained by subscribing to [`found-in-page`](web-contents.md#event-found-in-page) event.
### `webContents.stopFindInPage(action)`
* `action` String - Specifies the action to take place when ending
[`webContents.findInPage`](web-contents.md#webcontentfindinpage) request.
* `clearSelection` - Translate the selection into a normal selection.
* `keepSelection` - Clear the selection.
* `activateSelection` - Focus and click the selection node.
Stops any `findInPage` request for the `webContents` with the provided `action`.
```javascript
webContents.on('found-in-page', function(event, result) {
if (result.finalUpdate)
webContents.stopFindInPage("clearSelection");
});
const requestId = webContents.findInPage("api");
```
### `webContents.hasServiceWorker(callback)`
* `callback` Function

View file

@ -348,6 +348,36 @@ Executes editing command `replace` in page.
Executes editing command `replaceMisspelling` in page.
### `<webview>.findInPage(text[, options])`
* `text` String - Content to be searched, must not be empty.
* `options` Object (Optional)
* `forward` Boolean - Whether to search forward or backward, defaults to `true`.
* `findNext` Boolean - Whether the operation is first request or a follow up,
defaults to `false`.
* `matchCase` Boolean - Whether search should be case-sensitive,
defaults to `false`.
* `wordStart` Boolean - Whether to look only at the start of words.
defaults to `false`.
* `medialCapitalAsWordStart` Boolean - When combined with `wordStart`,
accepts a match in the middle of a word if the match begins with an
uppercase letter followed by a lowercase or non-letter.
Accepts several other intra-word matches, defaults to `false`.
Starts a request to find all matches for the `text` in the web page and returns an `Integer`
representing the request id used for the request. The result of the request can be
obtained by subscribing to [`found-in-page`](web-view-tag.md#event-found-in-page) event.
### `<webview>.stopFindInPage(action)`
* `action` String - Specifies the action to take place when ending
[`<webview>.findInPage`](web-view-tag.md#webviewtagfindinpage) request.
* `clearSelection` - Translate the selection into a normal selection.
* `keepSelection` - Clear the selection.
* `activateSelection` - Focus and click the selection node.
Stops any `findInPage` request for the `webview` with the provided `action`.
### `<webview>.print([options])`
Prints `webview`'s web page. Same with `webContents.print([options])`.
@ -499,6 +529,28 @@ webview.addEventListener('console-message', function(e) {
});
```
### Event: 'found-in-page'
Returns:
* `result` Object
* `requestId` Integer
* `finalUpdate` Boolean - Indicates if more responses are to follow.
* `matches` Integer (Optional) - Number of Matches.
* `selectionArea` Object (Optional) - Coordinates of first match region.
Fired when a result is available for
[`webview.findInPage`](web-view-tag.md#webviewtagfindinpage) request.
```javascript
webview.addEventListener('found-in-page', function(e) {
if (e.result.finalUpdate)
webview.stopFindInPage("keepSelection");
});
const rquestId = webview.findInPage("test");
```
### Event: 'new-window'
Returns:

16
spec/fixtures/pages/content.html vendored Normal file
View file

@ -0,0 +1,16 @@
<p>
Virtual member functions are key to the object-oriented paradigm,
such as making it easy for old code to call new code.
A virtual function allows derived classes to replace the implementation
provided by the base class. The compiler makes sure the replacement is
always called whenever the object in question is actually of the derived class,
even if the object is accessed by a base pointer rather than a derived pointer.
This allows algorithms in the base class to be replaced in the derived class,
even if users dont know about the derived class.
<code>
class A {
public:
virtual void foo() {}
}
</code>
</p>

View file

@ -390,3 +390,19 @@ describe '<webview> tag', ->
done()
webview.src = "file://#{fixtures}/pages/audio.html"
document.body.appendChild webview
describe 'found-in-page event', ->
it 'emits when a request is made', (done) ->
requestId = null
listener = (e) ->
assert.equal e.result.requestId, requestId
if e.result.finalUpdate
assert.equal e.result.matches, 3
webview.stopFindInPage "clearSelection"
done()
listener2 = (e) ->
requestId = webview.findInPage "virtual"
webview.addEventListener 'found-in-page', listener
webview.addEventListener 'did-finish-load', listener2
webview.src = "file://#{fixtures}/pages/content.html"
document.body.appendChild webview