Browse Source

webContents: adding findInPage api

Robo 9 years ago
parent
commit
39e615ed87

+ 51 - 0
atom/browser/api/atom_api_web_contents.cc

@@ -49,6 +49,7 @@
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/context_menu_params.h"
+#include "native_mate/converter.h"
 #include "native_mate/dictionary.h"
 #include "native_mate/object_template_builder.h"
 #include "net/http/http_response_headers.h"
@@ -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("find-in-page-response", result);
+  } else if (final_update) {
+    result.Set("requestId", request_id);
+    result.Set("matches", number_of_matches);
+    result.Set("finalUpdate", final_update);
+    Emit("find-in-page-response", 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,31 @@ void WebContents::ReplaceMisspelling(const base::string16& word) {
   web_contents()->ReplaceMisspelling(word);
 }
 
+void WebContents::FindInPage(mate::Arguments* args) {
+  int request_id;
+  base::string16 search_text;
+  blink::WebFindOptions options;
+  if (!args->GetNext(&request_id)) {
+    args->ThrowError("Must provide a request id");
+    return;
+  }
+
+  if (!args->GetNext(&search_text)) {
+    args->ThrowError("Must provide a non-empty search content");
+    return;
+  }
+
+  args->GetNext(&options);
+
+  web_contents()->Find(request_id, search_text, options);
+  web_contents()->GetMainFrame()
+                ->ActivateFindInPageResultForAccessibility(request_id);
+}
+
+void WebContents::StopFindInPage(content::StopFindAction action) {
+  web_contents()->StopFinding(action);
+}
+
 void WebContents::Focus() {
   web_contents()->Focus();
 }
@@ -1048,6 +1097,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)

+ 8 - 0
atom/browser/api/atom_api_web_contents.h

@@ -110,6 +110,8 @@ class WebContents : public mate::TrackableObject<WebContents>,
   void Unselect();
   void Replace(const base::string16& word);
   void ReplaceMisspelling(const base::string16& word);
+  void 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;

+ 16 - 0
atom/common/native_mate_converters/blink_converter.cc

@@ -282,4 +282,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

+ 7 - 0
atom/common/native_mate_converters/blink_converter.h

@@ -6,6 +6,7 @@
 #define ATOM_COMMON_NATIVE_MATE_CONVERTERS_BLINK_CONVERTER_H_
 
 #include "native_mate/converter.h"
+#include "third_party/WebKit/public/web/WebFindOptions.h"
 
 namespace blink {
 class WebInputEvent;
@@ -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_

+ 20 - 0
atom/common/native_mate_converters/content_converter.cc

@@ -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,23 @@ 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
+    *out = content::STOP_FIND_ACTION_ACTIVATE_SELECTION;
+
+  return true;
+}
+
 }  // namespace mate

+ 7 - 0
atom/common/native_mate_converters/content_converter.h

@@ -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_

+ 48 - 1
docs/api/web-contents.md

@@ -229,6 +229,20 @@ Emitted when media starts playing.
 
 Emitted when media is paused or done playing.
 
+### Event: 'find-in-page-response'
+
+Returns:
+
+* `event` Event
+* `result` Object
+  * `requestId` Integer
+  * `matches` Integer __Optional__ - Number of Matches.
+  * `selectionArea` Object __Optional__ - Coordinates of first match region.
+  * `finalUpdate` Boolean - Indicates if more responses are to follow.
+
+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,39 @@ Executes the editing command `replace` in web page.
 
 Executes the editing command `replaceMisspelling` in web page.
 
+### `webContents.findInPage(id, text[, options])`
+
+* `id` Integer
+* `text` String - Content to be searched, must not be empty.
+* `options` Object __Optional__
+  * `forward` Boolean - Whether to search forward or backward.
+  * `findNext` Boolean - Whether the operation is first request or a follow up.
+  * `matchCase` Boolean - Whether search should be case-sensitive.
+  * `wordStart` Boolean - Whether to look only at the start of words.
+  * ` 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
+
+Finds all matches for the `text` in the web page.
+
+### `webContents.stopFindInPage(action)`
+
+* `action` String - Should be called with either `clearSelection` or `keepSelection`.
+                    By default it keeps the last selection.
+
+Stops any `findInPage` request for the `webContents`
+with the provided `action`.
+
+```javascript
+webContents.on('find-in-page-response', function(event, result) {
+  if (result.finalUpdate)
+    webContents.stopFindInPage("clearSelection");
+});
+
+webContents.findInPage(1, "api");
+```.
+
 ### `webContents.hasServiceWorker(callback)`
 
 * `callback` Function
@@ -462,7 +509,7 @@ size.
   * 1 - none
   * 2 - minimum
 * `pageSize` String - Specify page size of the generated PDF.
-  * `A5` 
+  * `A5`
   * `A4`
   * `A3`
   * `Legal`