From 88b887fe47812a3013a2d584e64bd9adca8dad07 Mon Sep 17 00:00:00 2001 From: bughit Date: Tue, 9 Jan 2018 14:41:40 -0500 Subject: [PATCH] frame navigation API --- atom/renderer/api/atom_api_web_frame.cc | 93 ++++++++++++++++++++++++- atom/renderer/api/atom_api_web_frame.h | 10 +++ docs/api/web-frame.md | 52 +++++++++++++- 3 files changed, 152 insertions(+), 3 deletions(-) diff --git a/atom/renderer/api/atom_api_web_frame.cc b/atom/renderer/api/atom_api_web_frame.cc index d0164f44a0..1f4798f74b 100644 --- a/atom/renderer/api/atom_api_web_frame.cc +++ b/atom/renderer/api/atom_api_web_frame.cc @@ -19,6 +19,7 @@ #include "native_mate/object_template_builder.h" #include "third_party/WebKit/public/platform/WebCache.h" #include "third_party/WebKit/public/web/WebDocument.h" +#include "third_party/WebKit/public/web/WebElement.h" #include "third_party/WebKit/public/web/WebFrameWidget.h" #include "third_party/WebKit/public/web/WebInputMethodController.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" @@ -112,7 +113,12 @@ class FrameSpellChecker : public content::RenderFrameVisitor { } // namespace WebFrame::WebFrame(v8::Isolate* isolate) - : web_frame_(blink::WebLocalFrame::FrameForCurrentContext()) { + : web_frame_(blink::WebLocalFrame::FrameForCurrentContext()) { + Init(isolate); +} + +WebFrame::WebFrame(v8::Isolate* isolate, blink::WebLocalFrame* blink_frame) + : web_frame_(blink_frame) { Init(isolate); } @@ -368,6 +374,82 @@ void WebFrame::ClearCache(v8::Isolate* isolate) { base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL); } +v8::Local WebFrame::Opener() const { + blink::WebFrame* frame = web_frame_->Opener(); + if (frame && frame->IsWebLocalFrame()) + return mate::CreateHandle(isolate(), + new WebFrame(isolate(), + frame->ToWebLocalFrame())).ToV8(); + else + return v8::Null(isolate()); +} + +v8::Local WebFrame::Parent() const { + blink::WebFrame* frame = web_frame_->Parent(); + if (frame && frame->IsWebLocalFrame()) + return mate::CreateHandle(isolate(), + new WebFrame(isolate(), + frame->ToWebLocalFrame())).ToV8(); + else + return v8::Null(isolate()); +} + +v8::Local WebFrame::Top() const { + blink::WebFrame* frame = web_frame_->Top(); + if (frame && frame->IsWebLocalFrame()) + return mate::CreateHandle(isolate(), + new WebFrame(isolate(), + frame->ToWebLocalFrame())).ToV8(); + else + return v8::Null(isolate()); +} + +v8::Local WebFrame::FirstChild() const { + blink::WebFrame* frame = web_frame_->FirstChild(); + if (frame && frame->IsWebLocalFrame()) + return mate::CreateHandle(isolate(), + new WebFrame(isolate(), + frame->ToWebLocalFrame())).ToV8(); + else + return v8::Null(isolate()); +} + +v8::Local WebFrame::NextSibling() const { + blink::WebFrame* frame = web_frame_->NextSibling(); + if (frame && frame->IsWebLocalFrame()) + return mate::CreateHandle(isolate(), + new WebFrame(isolate(), + frame->ToWebLocalFrame())).ToV8(); + else + return v8::Null(isolate()); +} + +v8::Local WebFrame::GetFrameForSelector(const std::string& selector) +const { + blink::WebElement element = + web_frame_->GetDocument() + .QuerySelector(blink::WebString::FromUTF8(selector)); + blink::WebLocalFrame* element_frame = + blink::WebLocalFrame::FromFrameOwnerElement(element); + if (element_frame) + return mate::CreateHandle(isolate(), + new WebFrame(isolate(), element_frame)).ToV8(); + else + return v8::Null(isolate()); +} + +v8::Local WebFrame::FindFrameByName(const std::string& name) const { + blink::WebLocalFrame* local_frame = + WebFrame::web_frame_ + ->FindFrameByName(blink::WebString::FromUTF8(name)) + ->ToWebLocalFrame(); + if (local_frame) + return mate::CreateHandle(isolate(), + new WebFrame(isolate(), local_frame)).ToV8(); + else + return v8::Null(isolate()); +} + // static void WebFrame::BuildPrototype( v8::Isolate* isolate, v8::Local prototype) { @@ -407,7 +489,14 @@ void WebFrame::BuildPrototype( .SetMethod("setIsolatedWorldHumanReadableName", &WebFrame::SetIsolatedWorldHumanReadableName) .SetMethod("getResourceUsage", &WebFrame::GetResourceUsage) - .SetMethod("clearCache", &WebFrame::ClearCache); + .SetMethod("clearCache", &WebFrame::ClearCache) + .SetProperty("opener", &WebFrame::Opener) + .SetProperty("parent", &WebFrame::Parent) + .SetProperty("top", &WebFrame::Top) + .SetProperty("firstChild", &WebFrame::FirstChild) + .SetProperty("nextSibling", &WebFrame::NextSibling) + .SetMethod("getFrameForSelector", &WebFrame::GetFrameForSelector) + .SetMethod("findFrameByName", &WebFrame::FindFrameByName); } } // namespace api diff --git a/atom/renderer/api/atom_api_web_frame.h b/atom/renderer/api/atom_api_web_frame.h index 7abf870e7a..fd6a2c3e58 100644 --- a/atom/renderer/api/atom_api_web_frame.h +++ b/atom/renderer/api/atom_api_web_frame.h @@ -38,6 +38,7 @@ class WebFrame : public mate::Wrappable { private: explicit WebFrame(v8::Isolate* isolate); + explicit WebFrame(v8::Isolate* isolate, blink::WebLocalFrame* blink_frame); ~WebFrame() override; void SetName(const std::string& name); @@ -93,6 +94,15 @@ class WebFrame : public mate::Wrappable { blink::WebCache::ResourceTypeStats GetResourceUsage(v8::Isolate* isolate); void ClearCache(v8::Isolate* isolate); + // Frame navigation + v8::Local Opener() const; + v8::Local Parent() const; + v8::Local Top() const; + v8::Local FirstChild() const; + v8::Local NextSibling() const; + v8::Local GetFrameForSelector(const std::string& selector) const; + v8::Local FindFrameByName(const std::string& name) const; + std::unique_ptr spell_check_client_; blink::WebLocalFrame* web_frame_; diff --git a/docs/api/web-frame.md b/docs/api/web-frame.md index 441e2b4d05..d2704d53d4 100644 --- a/docs/api/web-frame.md +++ b/docs/api/web-frame.md @@ -4,6 +4,10 @@ Process: [Renderer](../glossary.md#renderer-process) +`webFrame` export of the electron module is an instance of the `WebFrame` +class representing the top frame of the current `BrowserWindow`. Sub-frames can +be retrieved by certain properties and methods (e.g. `webFrame.firstChild`) + An example of zooming current page to 200%. ```javascript @@ -14,7 +18,7 @@ webFrame.setZoomFactor(2) ## Methods -The `webFrame` module has the following methods: +The `WebFrame` class has the following instance methods: ### `webFrame.setZoomFactor(factor)` @@ -214,3 +218,49 @@ memory (i.e. you have navigated from a super heavy page to a mostly empty one, and intend to stay there). [spellchecker]: https://github.com/atom/node-spellchecker + +### `webFrame.getFrameForSelector(selector)` + +* Returns `WebFrame` for the frame element in `webFrame's` document selected by + `selector` +* Returns `null` if `selector` does not select a frame or if the frame is not in + the current renderer process. +* `selector` String - CSS selector for a frame element + + +### `webFrame.findFrameByName(name)` + +* Returns `WebFrame` - a child of `webFrame` with the supplied `name` +* Returns `null` if there's no such frame or if the frame is not in the current + renderer process. + +## Properties + +### `webFrame.top` + +* Returns `WebFrame` - top frame in frame hierarchy to which `webFrame` belongs +* Returns `null` if top frame is not in the current renderer process. + +### `webFrame.opener` + +* Returns `WebFrame` - frame which opened `webFrame` +* Returns `null` if there's no opener or opener is not in the current renderer + process. + +### `webFrame.parent` + +* Returns `WebFrame` - parent frame of `webFrame` +* Returns `null` if `webFrame` is top or parent is not in the current renderer + process. + +### `webFrame.firstChild` + +* Returns `WebFrame` - first child frame of `webFrame` +* Returns `null` if `webFrame` has no children or if first child is not in the + current renderer process. + +### `webFrame.nextSibling` + +* Returns `WebFrame` - next sibling frame +* Returns `null` if `webFrame` is the last frame its parent or if the next + sibling is not in the current renderer process.