electron/atom/renderer/api/atom_api_web_frame.cc

353 lines
13 KiB
C++
Raw Normal View History

// Copyright (c) 2014 GitHub, Inc.
2014-10-24 10:24:12 +00:00
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/renderer/api/atom_api_web_frame.h"
#include "atom/common/api/api_messages.h"
#include "atom/common/api/event_emitter_caller.h"
2016-05-12 20:56:46 +00:00
#include "atom/common/native_mate_converters/blink_converter.h"
#include "atom/common/native_mate_converters/callback.h"
2015-05-29 05:47:09 +00:00
#include "atom/common/native_mate_converters/gfx_converter.h"
2014-10-24 10:24:12 +00:00
#include "atom/common/native_mate_converters/string16_converter.h"
2014-12-18 21:54:01 +00:00
#include "atom/renderer/api/atom_api_spell_check_client.h"
2016-05-12 21:36:49 +00:00
#include "base/memory/memory_pressure_listener.h"
2014-12-08 16:05:34 +00:00
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
2014-10-24 10:24:12 +00:00
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
2017-04-11 07:18:40 +00:00
#include "third_party/WebKit/public/platform/WebCache.h"
2014-10-24 10:24:12 +00:00
#include "third_party/WebKit/public/web/WebDocument.h"
2017-01-24 07:45:26 +00:00
#include "third_party/WebKit/public/web/WebFrameWidget.h"
#include "third_party/WebKit/public/web/WebInputMethodController.h"
2014-10-24 10:24:12 +00:00
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebScriptExecutionCallback.h"
2016-01-13 04:11:46 +00:00
#include "third_party/WebKit/public/web/WebScriptSource.h"
2014-10-24 10:24:12 +00:00
#include "third_party/WebKit/public/web/WebView.h"
#include "third_party/WebKit/Source/platform/weborigin/SchemeRegistry.h"
2014-10-24 10:24:12 +00:00
#include "atom/common/node_includes.h"
namespace mate {
template <>
struct Converter<blink::WebLocalFrame::ScriptExecutionType> {
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
blink::WebLocalFrame::ScriptExecutionType* out) {
std::string execution_type;
if (!ConvertFromV8(isolate, val, &execution_type))
return false;
if (execution_type == "asynchronous") {
*out = blink::WebLocalFrame::kAsynchronous;
} else if (execution_type ==
"asynchronousBlockingOnload") {
*out = blink::WebLocalFrame::kAsynchronousBlockingOnload;
} else if (execution_type == "synchronous") {
*out = blink::WebLocalFrame::kSynchronous;
} else {
return false;
}
return true;
}
};
} // namespace mate
2014-10-24 10:24:12 +00:00
namespace atom {
namespace api {
namespace {
class ScriptExecutionCallback : public blink::WebScriptExecutionCallback {
public:
using CompletionCallback =
base::Callback<void(
2016-02-22 14:00:21 +00:00
const v8::Local<v8::Value>& result)>;
explicit ScriptExecutionCallback(const CompletionCallback& callback)
: callback_(callback) {}
2016-07-10 11:21:42 +00:00
~ScriptExecutionCallback() override {}
2017-06-16 20:42:33 +00:00
void Completed(
const blink::WebVector<v8::Local<v8::Value>>& result) override {
2017-06-16 20:42:33 +00:00
if (!callback_.is_null() && !result.IsEmpty() && !result[0].IsEmpty())
2016-02-22 14:00:21 +00:00
// Right now only single results per frame is supported.
callback_.Run(result[0]);
delete this;
}
private:
CompletionCallback callback_;
DISALLOW_COPY_AND_ASSIGN(ScriptExecutionCallback);
};
} // namespace
2016-04-25 01:17:54 +00:00
WebFrame::WebFrame(v8::Isolate* isolate)
2017-06-16 20:42:33 +00:00
: web_frame_(blink::WebLocalFrame::FrameForCurrentContext()) {
2016-04-25 01:17:54 +00:00
Init(isolate);
2014-10-24 10:24:12 +00:00
}
WebFrame::~WebFrame() {
}
2014-10-24 10:44:15 +00:00
void WebFrame::SetName(const std::string& name) {
2017-06-16 20:42:33 +00:00
web_frame_->SetName(blink::WebString::FromUTF8(name));
2014-10-24 10:44:15 +00:00
}
2014-10-24 10:24:12 +00:00
double WebFrame::SetZoomLevel(double level) {
2017-01-31 09:25:48 +00:00
double result = 0.0;
content::RenderView* render_view =
2017-06-16 20:42:33 +00:00
content::RenderView::FromWebView(web_frame_->View());
render_view->Send(new AtomViewHostMsg_SetTemporaryZoomLevel(
render_view->GetRoutingID(), level, &result));
return result;
2014-10-24 10:24:12 +00:00
}
double WebFrame::GetZoomLevel() const {
2017-01-31 09:25:48 +00:00
double result = 0.0;
content::RenderView* render_view =
2017-06-16 20:42:33 +00:00
content::RenderView::FromWebView(web_frame_->View());
render_view->Send(
new AtomViewHostMsg_GetZoomLevel(render_view->GetRoutingID(), &result));
return result;
2014-10-24 10:24:12 +00:00
}
double WebFrame::SetZoomFactor(double factor) {
2017-06-16 20:42:33 +00:00
return blink::WebView::ZoomLevelToZoomFactor(SetZoomLevel(
blink::WebView::ZoomFactorToZoomLevel(factor)));
2014-10-24 10:24:12 +00:00
}
double WebFrame::GetZoomFactor() const {
2017-06-16 20:42:33 +00:00
return blink::WebView::ZoomLevelToZoomFactor(GetZoomLevel());
2014-10-24 10:24:12 +00:00
}
void WebFrame::SetVisualZoomLevelLimits(double min_level, double max_level) {
2017-06-16 20:42:33 +00:00
web_frame_->View()->SetDefaultPageScaleLimits(min_level, max_level);
2015-08-27 14:08:25 +00:00
}
void WebFrame::SetLayoutZoomLevelLimits(double min_level, double max_level) {
2017-06-16 20:42:33 +00:00
web_frame_->View()->ZoomLimitsChanged(min_level, max_level);
}
2015-05-22 11:11:22 +00:00
v8::Local<v8::Value> WebFrame::RegisterEmbedderCustomElement(
const base::string16& name, v8::Local<v8::Object> options) {
2014-10-24 10:24:12 +00:00
blink::WebExceptionCode c = 0;
2017-06-16 20:42:33 +00:00
return web_frame_->GetDocument().RegisterEmbedderCustomElement(
blink::WebString::FromUTF16(name), options, c);
2014-10-24 10:24:12 +00:00
}
2015-05-29 05:47:09 +00:00
void WebFrame::RegisterElementResizeCallback(
int element_instance_id,
const GuestViewContainer::ResizeCallback& callback) {
auto guest_view_container = GuestViewContainer::FromID(element_instance_id);
if (guest_view_container)
guest_view_container->RegisterElementResizeCallback(callback);
}
2014-12-08 16:05:34 +00:00
void WebFrame::AttachGuest(int id) {
content::RenderFrame::FromWebFrame(web_frame_)->AttachGuest(id);
}
void WebFrame::DetachGuest(int id) {
content::RenderFrame::FromWebFrame(web_frame_)->DetachGuest(id);
}
void WebFrame::SetSpellCheckProvider(mate::Arguments* args,
const std::string& language,
bool auto_spell_correct_turned_on,
2015-05-22 11:11:22 +00:00
v8::Local<v8::Object> provider) {
if (!provider->Has(mate::StringToV8(args->isolate(), "spellCheck"))) {
args->ThrowError("\"spellCheck\" has to be defined");
return;
}
spell_check_client_.reset(new SpellCheckClient(
language, auto_spell_correct_turned_on, args->isolate(), provider));
web_frame_->SetSpellCheckPanelHostClient(spell_check_client_.get());
web_frame_->SetTextCheckClient(spell_check_client_.get());
2014-12-18 21:54:01 +00:00
}
void WebFrame::RegisterURLSchemeAsSecure(const std::string& scheme) {
2016-11-14 18:33:30 +00:00
// TODO(pfrazee): Remove 2.0
2017-06-16 20:42:33 +00:00
blink::SchemeRegistry::RegisterURLSchemeAsSecure(
WTF::String::FromUTF8(scheme.data(), scheme.length()));
}
2015-11-13 08:03:40 +00:00
void WebFrame::RegisterURLSchemeAsBypassingCSP(const std::string& scheme) {
// Register scheme to bypass pages's Content Security Policy.
2017-06-16 20:42:33 +00:00
blink::SchemeRegistry::RegisterURLSchemeAsBypassingContentSecurityPolicy(
WTF::String::FromUTF8(scheme.data(), scheme.length()));
}
void WebFrame::RegisterURLSchemeAsPrivileged(const std::string& scheme,
mate::Arguments* args) {
// Read optional flags
bool secure = true;
bool bypassCSP = true;
bool allowServiceWorkers = true;
bool supportFetchAPI = true;
bool corsEnabled = true;
if (args->Length() == 2) {
mate::Dictionary options;
if (args->GetNext(&options)) {
options.Get("secure", &secure);
options.Get("bypassCSP", &bypassCSP);
options.Get("allowServiceWorkers", &allowServiceWorkers);
options.Get("supportFetchAPI", &supportFetchAPI);
options.Get("corsEnabled", &corsEnabled);
}
}
// Register scheme to privileged list (https, wss, data, chrome-extension)
WTF::String privileged_scheme(
2017-06-16 20:42:33 +00:00
WTF::String::FromUTF8(scheme.data(), scheme.length()));
if (secure) {
2016-11-14 18:33:30 +00:00
// TODO(pfrazee): Remove 2.0
2017-06-16 20:42:33 +00:00
blink::SchemeRegistry::RegisterURLSchemeAsSecure(privileged_scheme);
}
if (bypassCSP) {
2017-06-16 20:42:33 +00:00
blink::SchemeRegistry::RegisterURLSchemeAsBypassingContentSecurityPolicy(
privileged_scheme);
}
if (allowServiceWorkers) {
2017-06-16 20:42:33 +00:00
blink::SchemeRegistry::RegisterURLSchemeAsAllowingServiceWorkers(
privileged_scheme);
}
if (supportFetchAPI) {
2017-06-16 20:42:33 +00:00
blink::SchemeRegistry::RegisterURLSchemeAsSupportingFetchAPI(
privileged_scheme);
}
if (corsEnabled) {
2017-06-16 20:42:33 +00:00
blink::SchemeRegistry::RegisterURLSchemeAsCORSEnabled(privileged_scheme);
}
}
2016-01-13 03:21:16 +00:00
void WebFrame::InsertText(const std::string& text) {
2017-06-16 20:42:33 +00:00
web_frame_->FrameWidget()
->GetActiveWebInputMethodController()
->CommitText(blink::WebString::FromUTF8(text),
2017-04-11 07:18:40 +00:00
blink::WebVector<blink::WebCompositionUnderline>(),
blink::WebRange(),
0);
2016-01-13 03:21:16 +00:00
}
2016-12-19 23:50:47 +00:00
void WebFrame::InsertCSS(const std::string& css) {
2017-06-16 20:42:33 +00:00
web_frame_->GetDocument().InsertStyleSheet(blink::WebString::FromUTF8(css));
2016-12-19 23:50:47 +00:00
}
void WebFrame::ExecuteJavaScript(const base::string16& code,
mate::Arguments* args) {
bool has_user_gesture = false;
args->GetNext(&has_user_gesture);
ScriptExecutionCallback::CompletionCallback completion_callback;
args->GetNext(&completion_callback);
2016-05-23 01:59:39 +00:00
std::unique_ptr<blink::WebScriptExecutionCallback> callback(
new ScriptExecutionCallback(completion_callback));
2017-06-16 20:42:33 +00:00
web_frame_->RequestExecuteScriptAndReturnValue(
blink::WebScriptSource(blink::WebString::FromUTF16(code)),
has_user_gesture,
callback.release());
2016-01-13 04:11:46 +00:00
}
void WebFrame::ExecuteJavaScriptInIsolatedWorld(int world_id,
const base::string16& code,
mate::Arguments* args) {
std::vector<blink::WebScriptSource> sources;
sources.push_back(blink::WebScriptSource(blink::WebString::FromUTF16(code)));
bool has_user_gesture = false;
args->GetNext(&has_user_gesture);
blink::WebLocalFrame::ScriptExecutionType scriptExecutionType =
blink::WebLocalFrame::kSynchronous;
args->GetNext(&scriptExecutionType);
ScriptExecutionCallback::CompletionCallback completion_callback;
args->GetNext(&completion_callback);
std::unique_ptr<blink::WebScriptExecutionCallback> callback(
new ScriptExecutionCallback(completion_callback));
web_frame_->RequestExecuteScriptInIsolatedWorld(
world_id, &sources.front(), sources.size(), has_user_gesture,
scriptExecutionType, callback.release());
}
2016-04-25 01:17:54 +00:00
// static
mate::Handle<WebFrame> WebFrame::Create(v8::Isolate* isolate) {
2016-04-25 01:27:54 +00:00
return mate::CreateHandle(isolate, new WebFrame(isolate));
2016-04-25 01:17:54 +00:00
}
2016-05-14 13:40:18 +00:00
blink::WebCache::ResourceTypeStats WebFrame::GetResourceUsage(
v8::Isolate* isolate) {
2016-05-12 20:56:46 +00:00
blink::WebCache::ResourceTypeStats stats;
2017-06-16 20:42:33 +00:00
blink::WebCache::GetResourceTypeStats(&stats);
2016-05-13 17:43:08 +00:00
return stats;
2016-05-12 20:56:46 +00:00
}
void WebFrame::ClearCache(v8::Isolate* isolate) {
2016-05-12 21:36:49 +00:00
isolate->IdleNotificationDeadline(0.5);
2017-06-16 20:42:33 +00:00
blink::WebCache::Clear();
2016-05-12 21:36:49 +00:00
base::MemoryPressureListener::NotifyMemoryPressure(
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
}
2016-04-25 01:17:54 +00:00
// static
void WebFrame::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
2016-08-02 10:28:12 +00:00
prototype->SetClassName(mate::StringToV8(isolate, "WebFrame"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
2014-10-24 10:44:15 +00:00
.SetMethod("setName", &WebFrame::SetName)
2014-10-24 10:24:12 +00:00
.SetMethod("setZoomLevel", &WebFrame::SetZoomLevel)
.SetMethod("getZoomLevel", &WebFrame::GetZoomLevel)
.SetMethod("setZoomFactor", &WebFrame::SetZoomFactor)
.SetMethod("getZoomFactor", &WebFrame::GetZoomFactor)
.SetMethod("setVisualZoomLevelLimits",
&WebFrame::SetVisualZoomLevelLimits)
2016-11-21 20:13:34 +00:00
.SetMethod("setLayoutZoomLevelLimits",
&WebFrame::SetLayoutZoomLevelLimits)
2014-10-24 10:24:12 +00:00
.SetMethod("registerEmbedderCustomElement",
2014-12-08 16:05:34 +00:00
&WebFrame::RegisterEmbedderCustomElement)
2015-05-29 05:47:09 +00:00
.SetMethod("registerElementResizeCallback",
&WebFrame::RegisterElementResizeCallback)
2014-12-18 21:54:01 +00:00
.SetMethod("attachGuest", &WebFrame::AttachGuest)
.SetMethod("detachGuest", &WebFrame::DetachGuest)
.SetMethod("setSpellCheckProvider", &WebFrame::SetSpellCheckProvider)
2015-11-13 08:03:40 +00:00
.SetMethod("registerURLSchemeAsSecure",
&WebFrame::RegisterURLSchemeAsSecure)
2015-11-13 08:03:40 +00:00
.SetMethod("registerURLSchemeAsBypassingCSP",
&WebFrame::RegisterURLSchemeAsBypassingCSP)
.SetMethod("registerURLSchemeAsPrivileged",
2016-01-13 03:21:16 +00:00
&WebFrame::RegisterURLSchemeAsPrivileged)
2016-01-13 04:11:46 +00:00
.SetMethod("insertText", &WebFrame::InsertText)
2016-12-19 23:50:47 +00:00
.SetMethod("insertCSS", &WebFrame::InsertCSS)
2016-05-12 20:56:46 +00:00
.SetMethod("executeJavaScript", &WebFrame::ExecuteJavaScript)
.SetMethod("executeJavaScriptInIsolatedWorld",
&WebFrame::ExecuteJavaScriptInIsolatedWorld)
2016-05-12 21:36:49 +00:00
.SetMethod("getResourceUsage", &WebFrame::GetResourceUsage)
.SetMethod("clearCache", &WebFrame::ClearCache)
// TODO(kevinsawicki): Remove in 2.0, deprecate before then with warnings
.SetMethod("setZoomLevelLimits", &WebFrame::SetVisualZoomLevelLimits);
2014-10-24 10:24:12 +00:00
}
} // namespace api
} // namespace atom
namespace {
2016-08-02 12:02:28 +00:00
using atom::api::WebFrame;
2015-05-22 11:11:22 +00:00
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
2014-10-24 10:24:12 +00:00
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
2016-08-02 12:02:28 +00:00
dict.Set("webFrame", WebFrame::Create(isolate));
dict.Set("WebFrame", WebFrame::GetConstructor(isolate)->GetFunction());
2014-10-24 10:24:12 +00:00
}
} // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_renderer_web_frame, Initialize)