Merge pull request #234 from atom/api-web-contents
Separate out WebContents API to a new class
This commit is contained in:
commit
3584d48dbe
30 changed files with 603 additions and 835 deletions
8
atom.gyp
8
atom.gyp
|
@ -24,6 +24,7 @@
|
|||
'atom/browser/api/lib/menu-item.coffee',
|
||||
'atom/browser/api/lib/power-monitor.coffee',
|
||||
'atom/browser/api/lib/protocol.coffee',
|
||||
'atom/browser/api/lib/web-contents.coffee',
|
||||
'atom/browser/lib/init.coffee',
|
||||
'atom/browser/lib/objects-registry.coffee',
|
||||
'atom/browser/lib/rpc-server.coffee',
|
||||
|
@ -48,7 +49,6 @@
|
|||
'atom/browser/api/atom_api_app.h',
|
||||
'atom/browser/api/atom_api_auto_updater.cc',
|
||||
'atom/browser/api/atom_api_auto_updater.h',
|
||||
'atom/browser/api/atom_api_browser_ipc.cc',
|
||||
'atom/browser/api/atom_api_dialog.cc',
|
||||
'atom/browser/api/atom_api_menu.cc',
|
||||
'atom/browser/api/atom_api_menu.h',
|
||||
|
@ -62,10 +62,10 @@
|
|||
'atom/browser/api/atom_api_power_monitor.h',
|
||||
'atom/browser/api/atom_api_protocol.cc',
|
||||
'atom/browser/api/atom_api_protocol.h',
|
||||
'atom/browser/api/atom_api_web_contents.cc',
|
||||
'atom/browser/api/atom_api_web_contents.h',
|
||||
'atom/browser/api/atom_api_window.cc',
|
||||
'atom/browser/api/atom_api_window.h',
|
||||
'atom/browser/api/atom_browser_bindings.cc',
|
||||
'atom/browser/api/atom_browser_bindings.h',
|
||||
'atom/browser/api/event.cc',
|
||||
'atom/browser/api/event.h',
|
||||
'atom/browser/api/event_emitter.cc',
|
||||
|
@ -93,8 +93,6 @@
|
|||
'atom/browser/browser_observer.h',
|
||||
'atom/browser/devtools_delegate.cc',
|
||||
'atom/browser/devtools_delegate.h',
|
||||
'atom/browser/devtools_web_contents_observer.cc',
|
||||
'atom/browser/devtools_web_contents_observer.h',
|
||||
'atom/browser/mac/atom_application.h',
|
||||
'atom/browser/mac/atom_application.mm',
|
||||
'atom/browser/mac/atom_application_delegate.h',
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
using content::RenderViewHost;
|
||||
|
||||
namespace {
|
||||
|
||||
bool Send(const string16& channel, int process_id, int routing_id,
|
||||
const base::ListValue& arguments) {
|
||||
RenderViewHost* render_view_host(RenderViewHost::FromID(
|
||||
process_id, routing_id));
|
||||
if (!render_view_host) {
|
||||
node::ThrowError("Invalid render view host");
|
||||
return false;
|
||||
}
|
||||
|
||||
return render_view_host->Send(new AtomViewMsg_Message(routing_id, channel,
|
||||
arguments));
|
||||
}
|
||||
|
||||
void Initialize(v8::Handle<v8::Object> exports) {
|
||||
mate::Dictionary dict(v8::Isolate::GetCurrent(), exports);
|
||||
dict.SetMethod("send", &Send);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE(atom_browser_ipc, Initialize)
|
206
atom/browser/api/atom_api_web_contents.cc
Normal file
206
atom/browser/api/atom_api_web_contents.cc
Normal file
|
@ -0,0 +1,206 @@
|
|||
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
WebContents::WebContents(content::WebContents* web_contents)
|
||||
: content::WebContentsObserver(web_contents),
|
||||
web_contents_(web_contents) {
|
||||
}
|
||||
|
||||
void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) {
|
||||
base::ListValue args;
|
||||
args.AppendInteger(render_view_host->GetProcess()->GetID());
|
||||
args.AppendInteger(render_view_host->GetRoutingID());
|
||||
Emit("render-view-deleted", args);
|
||||
}
|
||||
|
||||
void WebContents::RenderProcessGone(base::TerminationStatus status) {
|
||||
Emit("crashed");
|
||||
}
|
||||
|
||||
void WebContents::DidFinishLoad(int64 frame_id,
|
||||
const GURL& validated_url,
|
||||
bool is_main_frame,
|
||||
content::RenderViewHost* render_view_host) {
|
||||
Emit("did-finish-load");
|
||||
}
|
||||
|
||||
void WebContents::DidStartLoading(content::RenderViewHost* render_view_host) {
|
||||
Emit("did-start-loading");
|
||||
}
|
||||
|
||||
void WebContents::DidStopLoading(content::RenderViewHost* render_view_host) {
|
||||
Emit("did-stop-loading");
|
||||
}
|
||||
|
||||
bool WebContents::OnMessageReceived(const IPC::Message& message) {
|
||||
bool handled = true;
|
||||
IPC_BEGIN_MESSAGE_MAP(WebContents, message)
|
||||
IPC_MESSAGE_HANDLER(AtomViewHostMsg_Message, OnRendererMessage)
|
||||
IPC_MESSAGE_HANDLER_DELAY_REPLY(AtomViewHostMsg_Message_Sync,
|
||||
OnRendererMessageSync)
|
||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||
IPC_END_MESSAGE_MAP()
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
void WebContents::WebContentsDestroyed(content::WebContents*) {
|
||||
// The RenderViewDeleted was not called when the WebContents is destroyed.
|
||||
RenderViewDeleted(web_contents_->GetRenderViewHost());
|
||||
Emit("destroyed");
|
||||
}
|
||||
|
||||
bool WebContents::IsAlive() const {
|
||||
return web_contents() != NULL;
|
||||
}
|
||||
|
||||
void WebContents::LoadURL(const GURL& url) {
|
||||
content::NavigationController::LoadURLParams params(url);
|
||||
params.transition_type = content::PAGE_TRANSITION_TYPED;
|
||||
params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE;
|
||||
web_contents()->GetController().LoadURLWithParams(params);
|
||||
}
|
||||
|
||||
GURL WebContents::GetURL() const {
|
||||
return web_contents()->GetURL();
|
||||
}
|
||||
|
||||
string16 WebContents::GetTitle() const {
|
||||
return web_contents()->GetTitle();
|
||||
}
|
||||
|
||||
bool WebContents::IsLoading() const {
|
||||
return web_contents()->IsLoading();
|
||||
}
|
||||
|
||||
bool WebContents::IsWaitingForResponse() const {
|
||||
return web_contents()->IsWaitingForResponse();
|
||||
}
|
||||
|
||||
void WebContents::Stop() {
|
||||
web_contents()->Stop();
|
||||
}
|
||||
|
||||
void WebContents::Reload() {
|
||||
web_contents()->GetController().Reload(false);
|
||||
}
|
||||
|
||||
void WebContents::ReloadIgnoringCache() {
|
||||
web_contents()->GetController().ReloadIgnoringCache(false);
|
||||
}
|
||||
|
||||
bool WebContents::CanGoBack() const {
|
||||
return web_contents()->GetController().CanGoBack();
|
||||
}
|
||||
|
||||
bool WebContents::CanGoForward() const {
|
||||
return web_contents()->GetController().CanGoForward();
|
||||
}
|
||||
|
||||
bool WebContents::CanGoToOffset(int offset) const {
|
||||
return web_contents()->GetController().CanGoToOffset(offset);
|
||||
}
|
||||
|
||||
void WebContents::GoBack() {
|
||||
web_contents()->GetController().GoBack();
|
||||
}
|
||||
|
||||
void WebContents::GoForward() {
|
||||
web_contents()->GetController().GoForward();
|
||||
}
|
||||
|
||||
void WebContents::GoToIndex(int index) {
|
||||
web_contents()->GetController().GoToIndex(index);
|
||||
}
|
||||
|
||||
void WebContents::GoToOffset(int offset) {
|
||||
web_contents()->GetController().GoToOffset(offset);
|
||||
}
|
||||
|
||||
int WebContents::GetRoutingID() const {
|
||||
return web_contents()->GetRoutingID();
|
||||
}
|
||||
|
||||
int WebContents::GetProcessID() const {
|
||||
return web_contents()->GetRenderProcessHost()->GetID();
|
||||
}
|
||||
|
||||
bool WebContents::IsCrashed() const {
|
||||
return web_contents()->IsCrashed();
|
||||
}
|
||||
|
||||
void WebContents::ExecuteJavaScript(const string16& code) {
|
||||
web_contents()->GetRenderViewHost()->ExecuteJavascriptInWebFrame(
|
||||
string16(), code);
|
||||
}
|
||||
|
||||
bool WebContents::SendIPCMessage(const string16& channel,
|
||||
const base::ListValue& args) {
|
||||
return Send(new AtomViewMsg_Message(routing_id(), channel, args));
|
||||
}
|
||||
|
||||
mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
return mate::ObjectTemplateBuilder(isolate)
|
||||
.SetMethod("isAlive", &WebContents::IsAlive)
|
||||
.SetMethod("loadUrl", &WebContents::LoadURL)
|
||||
.SetMethod("getUrl", &WebContents::GetURL)
|
||||
.SetMethod("getTitle", &WebContents::GetTitle)
|
||||
.SetMethod("isLoading", &WebContents::IsLoading)
|
||||
.SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse)
|
||||
.SetMethod("stop", &WebContents::Stop)
|
||||
.SetMethod("reload", &WebContents::Reload)
|
||||
.SetMethod("reloadIgnoringCache", &WebContents::ReloadIgnoringCache)
|
||||
.SetMethod("canGoBack", &WebContents::CanGoBack)
|
||||
.SetMethod("canGoForward", &WebContents::CanGoForward)
|
||||
.SetMethod("canGoToOffset", &WebContents::CanGoToOffset)
|
||||
.SetMethod("goBack", &WebContents::GoBack)
|
||||
.SetMethod("goForward", &WebContents::GoForward)
|
||||
.SetMethod("goToIndex", &WebContents::GoToIndex)
|
||||
.SetMethod("goToOffset", &WebContents::GoToOffset)
|
||||
.SetMethod("getRoutingId", &WebContents::GetRoutingID)
|
||||
.SetMethod("getProcessId", &WebContents::GetProcessID)
|
||||
.SetMethod("isCrashed", &WebContents::IsCrashed)
|
||||
.SetMethod("executeJavaScript", &WebContents::ExecuteJavaScript)
|
||||
.SetMethod("_send", &WebContents::SendIPCMessage);
|
||||
}
|
||||
|
||||
void WebContents::OnRendererMessage(const string16& channel,
|
||||
const base::ListValue& args) {
|
||||
// webContents.emit(channel, new Event(), args...);
|
||||
Emit(UTF16ToUTF8(channel), args, web_contents(), NULL);
|
||||
}
|
||||
|
||||
void WebContents::OnRendererMessageSync(const string16& channel,
|
||||
const base::ListValue& args,
|
||||
IPC::Message* message) {
|
||||
// webContents.emit(channel, new Event(sender, message), args...);
|
||||
Emit(UTF16ToUTF8(channel), args, web_contents(), message);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<WebContents> WebContents::Create(
|
||||
v8::Isolate* isolate, content::WebContents* web_contents) {
|
||||
return CreateHandle(isolate, new WebContents(web_contents));
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
84
atom/browser/api/atom_api_web_contents.h
Normal file
84
atom/browser/api/atom_api_web_contents.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_WEB_CONTENTS_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_WEB_CONTENTS_H_
|
||||
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class WebContents : public mate::EventEmitter,
|
||||
public content::WebContentsObserver {
|
||||
public:
|
||||
static mate::Handle<WebContents> Create(v8::Isolate* isolate,
|
||||
content::WebContents* web_contents);
|
||||
|
||||
bool IsAlive() const;
|
||||
void LoadURL(const GURL& url);
|
||||
GURL GetURL() const;
|
||||
string16 GetTitle() const;
|
||||
bool IsLoading() const;
|
||||
bool IsWaitingForResponse() const;
|
||||
void Stop();
|
||||
void Reload();
|
||||
void ReloadIgnoringCache();
|
||||
bool CanGoBack() const;
|
||||
bool CanGoForward() const;
|
||||
bool CanGoToOffset(int offset) const;
|
||||
void GoBack();
|
||||
void GoForward();
|
||||
void GoToIndex(int index);
|
||||
void GoToOffset(int offset);
|
||||
int GetRoutingID() const;
|
||||
int GetProcessID() const;
|
||||
bool IsCrashed() const;
|
||||
void ExecuteJavaScript(const string16& code);
|
||||
bool SendIPCMessage(const string16& channel, const base::ListValue& args);
|
||||
|
||||
protected:
|
||||
explicit WebContents(content::WebContents* web_contents);
|
||||
|
||||
// mate::Wrappable implementations:
|
||||
virtual mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) OVERRIDE;
|
||||
|
||||
// content::WebContentsObserver implementations:
|
||||
virtual void RenderViewDeleted(content::RenderViewHost*) OVERRIDE;
|
||||
virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
|
||||
virtual void DidFinishLoad(
|
||||
int64 frame_id,
|
||||
const GURL& validated_url,
|
||||
bool is_main_frame,
|
||||
content::RenderViewHost* render_view_host) OVERRIDE;
|
||||
virtual void DidStartLoading(
|
||||
content::RenderViewHost* render_view_host) OVERRIDE;
|
||||
virtual void DidStopLoading(
|
||||
content::RenderViewHost* render_view_host) OVERRIDE;
|
||||
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
|
||||
virtual void WebContentsDestroyed(content::WebContents*) OVERRIDE;
|
||||
|
||||
private:
|
||||
// Called when received a message from renderer.
|
||||
void OnRendererMessage(const string16& channel, const base::ListValue& args);
|
||||
|
||||
// Called when received a synchronous message from renderer.
|
||||
void OnRendererMessageSync(const string16& channel,
|
||||
const base::ListValue& args,
|
||||
IPC::Message* message);
|
||||
|
||||
content::WebContents* web_contents_; // Weak.
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(WebContents);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_WEB_CONTENTS_H_
|
|
@ -4,15 +4,12 @@
|
|||
|
||||
#include "atom/browser/api/atom_api_window.h"
|
||||
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/common/native_mate_converters/function_converter.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/callback.h"
|
||||
#include "content/public/browser/navigation_entry.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "native_mate/constructor.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
@ -22,8 +19,6 @@
|
|||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
using content::NavigationController;
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
|
@ -86,12 +81,6 @@ void Window::OnPageTitleUpdated(bool* prevent_default,
|
|||
*prevent_default = Emit("page-title-updated", args);
|
||||
}
|
||||
|
||||
void Window::OnLoadingStateChanged(bool is_loading) {
|
||||
base::ListValue args;
|
||||
args.AppendBoolean(is_loading);
|
||||
Emit("loading-state-changed", args);
|
||||
}
|
||||
|
||||
void Window::WillCloseWindow(bool* prevent_default) {
|
||||
*prevent_default = Emit("close");
|
||||
}
|
||||
|
@ -114,17 +103,6 @@ void Window::OnRendererResponsive() {
|
|||
Emit("responsive");
|
||||
}
|
||||
|
||||
void Window::OnRenderViewDeleted(int process_id, int routing_id) {
|
||||
base::ListValue args;
|
||||
args.AppendInteger(process_id);
|
||||
args.AppendInteger(routing_id);
|
||||
Emit("render-view-deleted", args);
|
||||
}
|
||||
|
||||
void Window::OnRendererCrashed() {
|
||||
Emit("crashed");
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Wrappable* Window::New(mate::Arguments* args,
|
||||
const base::DictionaryValue& options) {
|
||||
|
@ -326,96 +304,13 @@ void Window::CapturePage(mate::Arguments* args) {
|
|||
window_->CapturePage(rect, base::Bind(&OnCapturePageDone, callback));
|
||||
}
|
||||
|
||||
string16 Window::GetPageTitle() {
|
||||
return window_->GetWebContents()->GetTitle();
|
||||
mate::Handle<WebContents> Window::GetWebContents(v8::Isolate* isolate) const {
|
||||
return WebContents::Create(isolate, window_->GetWebContents());
|
||||
}
|
||||
|
||||
bool Window::IsLoading() {
|
||||
return window_->GetWebContents()->IsLoading();
|
||||
}
|
||||
|
||||
bool Window::IsWaitingForResponse() {
|
||||
return window_->GetWebContents()->IsWaitingForResponse();
|
||||
}
|
||||
|
||||
void Window::Stop() {
|
||||
window_->GetWebContents()->Stop();
|
||||
}
|
||||
|
||||
int Window::GetRoutingID() {
|
||||
return window_->GetWebContents()->GetRoutingID();
|
||||
}
|
||||
|
||||
int Window::GetProcessID() {
|
||||
return window_->GetWebContents()->GetRenderProcessHost()->GetID();
|
||||
}
|
||||
|
||||
bool Window::IsCrashed() {
|
||||
return window_->GetWebContents()->IsCrashed();
|
||||
}
|
||||
|
||||
mate::Dictionary Window::GetDevTools(v8::Isolate* isolate) {
|
||||
mate::Dictionary dict(mate::Dictionary::CreateEmpty(isolate));
|
||||
content::WebContents* web_contents = window_->GetDevToolsWebContents();
|
||||
dict.Set("processId", web_contents->GetRenderProcessHost()->GetID());
|
||||
dict.Set("routingId", web_contents->GetRoutingID());
|
||||
return dict;
|
||||
}
|
||||
|
||||
void Window::ExecuteJavaScriptInDevTools(const std::string& code) {
|
||||
window_->ExecuteJavaScriptInDevTools(code);
|
||||
}
|
||||
|
||||
void Window::LoadURL(const GURL& url) {
|
||||
NavigationController& controller = window_->GetWebContents()->GetController();
|
||||
|
||||
content::NavigationController::LoadURLParams params(url);
|
||||
params.transition_type = content::PAGE_TRANSITION_TYPED;
|
||||
params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE;
|
||||
controller.LoadURLWithParams(params);
|
||||
}
|
||||
|
||||
GURL Window::GetURL() {
|
||||
NavigationController& controller = window_->GetWebContents()->GetController();
|
||||
if (!controller.GetActiveEntry())
|
||||
return GURL();
|
||||
return controller.GetActiveEntry()->GetVirtualURL();
|
||||
}
|
||||
|
||||
bool Window::CanGoBack() {
|
||||
return window_->GetWebContents()->GetController().CanGoBack();
|
||||
}
|
||||
|
||||
bool Window::CanGoForward() {
|
||||
return window_->GetWebContents()->GetController().CanGoForward();
|
||||
}
|
||||
|
||||
bool Window::CanGoToOffset(int offset) {
|
||||
return window_->GetWebContents()->GetController().CanGoToOffset(offset);
|
||||
}
|
||||
|
||||
void Window::GoBack() {
|
||||
window_->GetWebContents()->GetController().GoBack();
|
||||
}
|
||||
|
||||
void Window::GoForward() {
|
||||
window_->GetWebContents()->GetController().GoForward();
|
||||
}
|
||||
|
||||
void Window::GoToIndex(int index) {
|
||||
window_->GetWebContents()->GetController().GoToIndex(index);
|
||||
}
|
||||
|
||||
void Window::GoToOffset(int offset) {
|
||||
window_->GetWebContents()->GetController().GoToOffset(offset);
|
||||
}
|
||||
|
||||
void Window::Reload() {
|
||||
window_->GetWebContents()->GetController().Reload(false);
|
||||
}
|
||||
|
||||
void Window::ReloadIgnoringCache() {
|
||||
window_->GetWebContents()->GetController().ReloadIgnoringCache(false);
|
||||
mate::Handle<WebContents> Window::GetDevToolsWebContents(
|
||||
v8::Isolate* isolate) const {
|
||||
return WebContents::Create(isolate, window_->GetDevToolsWebContents());
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -462,27 +357,8 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
|||
.SetMethod("blurWebView", &Window::BlurWebView)
|
||||
.SetMethod("isWebViewFocused", &Window::IsWebViewFocused)
|
||||
.SetMethod("capturePage", &Window::CapturePage)
|
||||
.SetMethod("getPageTitle", &Window::GetPageTitle)
|
||||
.SetMethod("isLoading", &Window::IsLoading)
|
||||
.SetMethod("isWaitingForResponse", &Window::IsWaitingForResponse)
|
||||
.SetMethod("stop", &Window::Stop)
|
||||
.SetMethod("getRoutingId", &Window::GetRoutingID)
|
||||
.SetMethod("getProcessId", &Window::GetProcessID)
|
||||
.SetMethod("isCrashed", &Window::IsCrashed)
|
||||
.SetMethod("getDevTools", &Window::GetDevTools)
|
||||
.SetMethod("executeJavaScriptInDevTools",
|
||||
&Window::ExecuteJavaScriptInDevTools)
|
||||
.SetMethod("loadUrl", &Window::LoadURL)
|
||||
.SetMethod("getUrl", &Window::GetURL)
|
||||
.SetMethod("canGoBack", &Window::CanGoBack)
|
||||
.SetMethod("canGoForward", &Window::CanGoForward)
|
||||
.SetMethod("canGoToOffset", &Window::CanGoToOffset)
|
||||
.SetMethod("goBack", &Window::GoBack)
|
||||
.SetMethod("goForward", &Window::GoForward)
|
||||
.SetMethod("goToIndex", &Window::GoToIndex)
|
||||
.SetMethod("goToOffset", &Window::GoToOffset)
|
||||
.SetMethod("reload", &Window::Reload)
|
||||
.SetMethod("reloadIgnoringCache", &Window::ReloadIgnoringCache);
|
||||
.SetMethod("_getWebContents", &Window::GetWebContents)
|
||||
.SetMethod("_getDevToolsWebContents", &Window::GetDevToolsWebContents);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "base/memory/scoped_ptr.h"
|
||||
#include "atom/browser/native_window_observer.h"
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
class GURL;
|
||||
|
||||
|
@ -29,6 +30,8 @@ class NativeWindow;
|
|||
|
||||
namespace api {
|
||||
|
||||
class WebContents;
|
||||
|
||||
class Window : public mate::EventEmitter,
|
||||
public NativeWindowObserver {
|
||||
public:
|
||||
|
@ -47,14 +50,11 @@ class Window : public mate::EventEmitter,
|
|||
// Implementations of NativeWindowObserver:
|
||||
virtual void OnPageTitleUpdated(bool* prevent_default,
|
||||
const std::string& title) OVERRIDE;
|
||||
virtual void OnLoadingStateChanged(bool is_loading) OVERRIDE;
|
||||
virtual void WillCloseWindow(bool* prevent_default) OVERRIDE;
|
||||
virtual void OnWindowClosed() OVERRIDE;
|
||||
virtual void OnWindowBlur() OVERRIDE;
|
||||
virtual void OnRendererUnresponsive() OVERRIDE;
|
||||
virtual void OnRendererResponsive() OVERRIDE;
|
||||
virtual void OnRenderViewDeleted(int process_id, int routing_id) OVERRIDE;
|
||||
virtual void OnRendererCrashed() OVERRIDE;
|
||||
|
||||
private:
|
||||
// APIs for NativeWindow.
|
||||
|
@ -100,30 +100,8 @@ class Window : public mate::EventEmitter,
|
|||
void CapturePage(mate::Arguments* args);
|
||||
|
||||
// APIs for WebContents.
|
||||
string16 GetPageTitle();
|
||||
bool IsLoading();
|
||||
bool IsWaitingForResponse();
|
||||
void Stop();
|
||||
int GetRoutingID();
|
||||
int GetProcessID();
|
||||
bool IsCrashed();
|
||||
|
||||
// APIs for devtools.
|
||||
mate::Dictionary GetDevTools(v8::Isolate* isolate);
|
||||
void ExecuteJavaScriptInDevTools(const std::string& code);
|
||||
|
||||
// APIs for NavigationController.
|
||||
void LoadURL(const GURL& url);
|
||||
GURL GetURL();
|
||||
bool CanGoBack();
|
||||
bool CanGoForward();
|
||||
bool CanGoToOffset(int offset);
|
||||
void GoBack();
|
||||
void GoForward();
|
||||
void GoToIndex(int index);
|
||||
void GoToOffset(int offset);
|
||||
void Reload();
|
||||
void ReloadIgnoringCache();
|
||||
mate::Handle<WebContents> GetWebContents(v8::Isolate* isolate) const;
|
||||
mate::Handle<WebContents> GetDevToolsWebContents(v8::Isolate* isolate) const;
|
||||
|
||||
scoped_ptr<NativeWindow> window_;
|
||||
|
||||
|
|
|
@ -1,93 +0,0 @@
|
|||
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_browser_bindings.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/event.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "atom/common/native_mate_converters/v8_value_converter.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/values.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
AtomBrowserBindings::AtomBrowserBindings() {
|
||||
}
|
||||
|
||||
void AtomBrowserBindings::OnRendererMessage(int process_id,
|
||||
int routing_id,
|
||||
const string16& channel,
|
||||
const base::ListValue& args) {
|
||||
v8::Locker locker(node_isolate);
|
||||
v8::HandleScope handle_scope(node_isolate);
|
||||
|
||||
scoped_ptr<V8ValueConverter> converter(new V8ValueConverter);
|
||||
|
||||
// process.emit(channel, 'message', process_id, routing_id);
|
||||
std::vector<v8::Handle<v8::Value>> arguments;
|
||||
arguments.reserve(3 + args.GetSize());
|
||||
arguments.push_back(mate::ConvertToV8(node_isolate, channel));
|
||||
const base::Value* value;
|
||||
if (args.Get(0, &value))
|
||||
arguments.push_back(converter->ToV8Value(value, global_env->context()));
|
||||
arguments.push_back(v8::Integer::New(process_id));
|
||||
arguments.push_back(v8::Integer::New(routing_id));
|
||||
|
||||
for (size_t i = 1; i < args.GetSize(); i++) {
|
||||
const base::Value* value;
|
||||
if (args.Get(i, &value))
|
||||
arguments.push_back(converter->ToV8Value(value, global_env->context()));
|
||||
}
|
||||
|
||||
node::MakeCallback(global_env->process_object(),
|
||||
"emit",
|
||||
arguments.size(),
|
||||
&arguments[0]);
|
||||
}
|
||||
|
||||
void AtomBrowserBindings::OnRendererMessageSync(
|
||||
int process_id,
|
||||
int routing_id,
|
||||
const string16& channel,
|
||||
const base::ListValue& args,
|
||||
content::WebContents* sender,
|
||||
IPC::Message* message) {
|
||||
v8::Locker locker(node_isolate);
|
||||
v8::HandleScope handle_scope(node_isolate);
|
||||
|
||||
scoped_ptr<V8ValueConverter> converter(new V8ValueConverter);
|
||||
|
||||
// Create the event object.
|
||||
mate::Handle<mate::Event> event = mate::Event::Create(node_isolate);
|
||||
event->SetSenderAndMessage(sender, message);
|
||||
|
||||
// process.emit(channel, 'sync-message', event, process_id, routing_id);
|
||||
std::vector<v8::Handle<v8::Value>> arguments;
|
||||
arguments.reserve(3 + args.GetSize());
|
||||
arguments.push_back(mate::ConvertToV8(node_isolate, channel));
|
||||
const base::Value* value;
|
||||
if (args.Get(0, &value))
|
||||
arguments.push_back(converter->ToV8Value(value, global_env->context()));
|
||||
arguments.push_back(event.ToV8());
|
||||
arguments.push_back(v8::Integer::New(process_id));
|
||||
arguments.push_back(v8::Integer::New(routing_id));
|
||||
|
||||
for (size_t i = 1; i < args.GetSize(); i++) {
|
||||
const base::Value* value;
|
||||
if (args.Get(i, &value))
|
||||
arguments.push_back(converter->ToV8Value(value, global_env->context()));
|
||||
}
|
||||
|
||||
node::MakeCallback(global_env->process_object(),
|
||||
"emit",
|
||||
arguments.size(),
|
||||
&arguments[0]);
|
||||
}
|
||||
|
||||
} // namespace atom
|
|
@ -1,49 +0,0 @@
|
|||
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_BROWSER_BINDINGS_H_
|
||||
#define ATOM_BROWSER_API_ATOM_BROWSER_BINDINGS_H_
|
||||
|
||||
#include "atom/common/api/atom_bindings.h"
|
||||
#include "base/strings/string16.h"
|
||||
|
||||
namespace base {
|
||||
class ListValue;
|
||||
}
|
||||
|
||||
namespace content {
|
||||
class WebContents;
|
||||
}
|
||||
|
||||
namespace IPC {
|
||||
class Message;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomBrowserBindings : public AtomBindings {
|
||||
public:
|
||||
AtomBrowserBindings();
|
||||
|
||||
// Called when received a message from renderer.
|
||||
void OnRendererMessage(int process_id,
|
||||
int routing_id,
|
||||
const string16& channel,
|
||||
const base::ListValue& args);
|
||||
|
||||
// Called when received a synchronous message from renderer.
|
||||
void OnRendererMessageSync(int process_id,
|
||||
int routing_id,
|
||||
const string16& channel,
|
||||
const base::ListValue& args,
|
||||
content::WebContents* sender,
|
||||
IPC::Message* message);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomBrowserBindings);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_BROWSER_BINDINGS_H_
|
|
@ -24,6 +24,13 @@ bool EventEmitter::Emit(const base::StringPiece& name) {
|
|||
|
||||
bool EventEmitter::Emit(const base::StringPiece& name,
|
||||
const base::ListValue& args) {
|
||||
return Emit(name, args, NULL, NULL);
|
||||
}
|
||||
|
||||
bool EventEmitter::Emit(const base::StringPiece& name,
|
||||
const base::ListValue& args,
|
||||
content::WebContents* sender,
|
||||
IPC::Message* message) {
|
||||
v8::Locker locker(node_isolate);
|
||||
v8::HandleScope handle_scope(node_isolate);
|
||||
|
||||
|
@ -31,6 +38,8 @@ bool EventEmitter::Emit(const base::StringPiece& name,
|
|||
scoped_ptr<atom::V8ValueConverter> converter(new atom::V8ValueConverter);
|
||||
|
||||
mate::Handle<mate::Event> event = mate::Event::Create(node_isolate);
|
||||
if (sender && message)
|
||||
event->SetSenderAndMessage(sender, message);
|
||||
|
||||
// v8_args = [name, event, args...];
|
||||
std::vector<v8::Handle<v8::Value>> v8_args;
|
||||
|
|
|
@ -11,6 +11,14 @@ namespace base {
|
|||
class ListValue;
|
||||
}
|
||||
|
||||
namespace content {
|
||||
class WebContents;
|
||||
}
|
||||
|
||||
namespace IPC {
|
||||
class Message;
|
||||
}
|
||||
|
||||
namespace mate {
|
||||
|
||||
// Provide helperers to emit event in JavaScript.
|
||||
|
@ -18,12 +26,16 @@ class EventEmitter : public Wrappable {
|
|||
protected:
|
||||
EventEmitter();
|
||||
|
||||
// this.emit(name);
|
||||
// this.emit(name, new Event());
|
||||
bool Emit(const base::StringPiece& name);
|
||||
|
||||
// this.emit(name, args...);
|
||||
// this.emit(name, new Event(), args...);
|
||||
bool Emit(const base::StringPiece& name, const base::ListValue& args);
|
||||
|
||||
// this.emit(name, new Event(sender, message), args...);
|
||||
bool Emit(const base::StringPiece& name, const base::ListValue& args,
|
||||
content::WebContents* sender, IPC::Message* message);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(EventEmitter);
|
||||
};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
EventEmitter = require('events').EventEmitter
|
||||
IDWeakMap = require 'id-weak-map'
|
||||
app = require 'app'
|
||||
wrapWebContents = require('web-contents').wrap
|
||||
|
||||
BrowserWindow = process.atomBinding('window').BrowserWindow
|
||||
BrowserWindow::__proto__ = EventEmitter.prototype
|
||||
|
@ -14,6 +15,20 @@ BrowserWindow::_init = ->
|
|||
menu = app.getApplicationMenu()
|
||||
@setMenu menu if menu?
|
||||
|
||||
@webContents = @getWebContents()
|
||||
@webContents.once 'destroyed', => @webContents = null
|
||||
|
||||
# Define getter for devToolsWebContents.
|
||||
devToolsWebContents = null
|
||||
@__defineGetter__ 'devToolsWebContents', ->
|
||||
if @isDevToolsOpened()
|
||||
# Get a new devToolsWebContents if previous one has been destroyed, it
|
||||
# could happen when the devtools has been closed and then reopened.
|
||||
devToolsWebContents = null unless devToolsWebContents?.isAlive()
|
||||
devToolsWebContents ?= @getDevToolsWebContents()
|
||||
else
|
||||
devToolsWebContents = null
|
||||
|
||||
# Remember the window.
|
||||
id = BrowserWindow.windows.add this
|
||||
|
||||
|
@ -24,12 +39,18 @@ BrowserWindow::_init = ->
|
|||
|
||||
# Tell the rpc server that a render view has been deleted and we need to
|
||||
# release all objects owned by it.
|
||||
@on 'render-view-deleted', (event, processId, routingId) ->
|
||||
process.emit 'ATOM_BROWSER_RELEASE_RENDER_VIEW', processId, routingId
|
||||
@webContents.on 'render-view-deleted', (event, processId, routingId) ->
|
||||
process.emit 'ATOM_BROWSER_RELEASE_RENDER_VIEW', "#{processId}-#{routingId}"
|
||||
|
||||
BrowserWindow::toggleDevTools = ->
|
||||
if @isDevToolsOpened() then @closeDevTools() else @openDevTools()
|
||||
|
||||
BrowserWindow::getWebContents = ->
|
||||
wrapWebContents @_getWebContents()
|
||||
|
||||
BrowserWindow::getDevToolsWebContents = ->
|
||||
wrapWebContents @_getDevToolsWebContents()
|
||||
|
||||
BrowserWindow::restart = ->
|
||||
@loadUrl(@getUrl())
|
||||
|
||||
|
@ -50,16 +71,30 @@ BrowserWindow.getFocusedWindow = ->
|
|||
windows = BrowserWindow.getAllWindows()
|
||||
return window for window in windows when window.isFocused()
|
||||
|
||||
BrowserWindow.fromProcessIdAndRoutingId = (processId, routingId) ->
|
||||
BrowserWindow.fromWebContents = (webContents) ->
|
||||
windows = BrowserWindow.getAllWindows()
|
||||
return window for window in windows when window.getProcessId() == processId and
|
||||
window.getRoutingId() == routingId
|
||||
return window for window in windows when webContents.equal window.webContents
|
||||
|
||||
BrowserWindow.fromDevTools = (processId, routingId) ->
|
||||
BrowserWindow.fromDevToolsWebContents = (webContents) ->
|
||||
windows = BrowserWindow.getAllWindows()
|
||||
for window in windows when window.isDevToolsOpened()
|
||||
devtools = window.getDevTools()
|
||||
return window if devtools.processId == processId and
|
||||
devtools.routingId == routingId
|
||||
return window for window in windows when webContents.equal window.devToolsWebContents
|
||||
|
||||
# Helpers.
|
||||
BrowserWindow::loadUrl = -> @webContents.loadUrl.apply @webContents, arguments
|
||||
BrowserWindow::send = -> @webContents.send.apply @webContents, arguments
|
||||
|
||||
# Be compatible with old API.
|
||||
BrowserWindow::getUrl = -> @webContents.getUrl()
|
||||
BrowserWindow::reload = -> @webContents.reload()
|
||||
BrowserWindow::reloadIgnoringCache = -> @webContents.reloadIgnoringCache()
|
||||
BrowserWindow::getPageTitle = -> @webContents.getTitle()
|
||||
BrowserWindow::isLoading = -> @webContents.isLoading()
|
||||
BrowserWindow::isWaitingForResponse = -> @webContents.isWaitingForResponse()
|
||||
BrowserWindow::stop = -> @webContents.stop()
|
||||
BrowserWindow::getRoutingId = -> @webContents.getRoutingId()
|
||||
BrowserWindow::getProcessId = -> @webContents.getProcessId()
|
||||
BrowserWindow::isCrashed = -> @webContents.isCrashed()
|
||||
BrowserWindow::executeJavaScriptInDevTools = (code) ->
|
||||
@devToolsWebContents.executeJavaScript code
|
||||
|
||||
module.exports = BrowserWindow
|
||||
|
|
|
@ -1,32 +1,3 @@
|
|||
EventEmitter = require('events').EventEmitter
|
||||
send = process.atomBinding('ipc').send
|
||||
|
||||
sendWrap = (channel, processId, routingId, args...) ->
|
||||
BrowserWindow = require 'browser-window'
|
||||
if processId?.constructor is BrowserWindow
|
||||
window = processId
|
||||
args = [routingId, args...]
|
||||
processId = window.getProcessId()
|
||||
routingId = window.getRoutingId()
|
||||
|
||||
send channel, processId, routingId, [args...]
|
||||
|
||||
class Ipc extends EventEmitter
|
||||
constructor: ->
|
||||
process.on 'ATOM_INTERNAL_MESSAGE', (args...) =>
|
||||
@emit(args...)
|
||||
process.on 'ATOM_INTERNAL_MESSAGE_SYNC', (channel, event, args...) =>
|
||||
set = (value) -> event.sendReply JSON.stringify(value)
|
||||
|
||||
Object.defineProperty event, 'returnValue', {set}
|
||||
Object.defineProperty event, 'result', {set}
|
||||
|
||||
@emit(channel, event, args...)
|
||||
|
||||
send: (processId, routingId, args...) ->
|
||||
@sendChannel(processId, routingId, 'message', args...)
|
||||
|
||||
sendChannel: (args...) ->
|
||||
sendWrap('ATOM_INTERNAL_MESSAGE', args...)
|
||||
|
||||
module.exports = new Ipc
|
||||
module.exports = new EventEmitter
|
||||
|
|
27
atom/browser/api/lib/web-contents.coffee
Normal file
27
atom/browser/api/lib/web-contents.coffee
Normal file
|
@ -0,0 +1,27 @@
|
|||
EventEmitter = require('events').EventEmitter
|
||||
ipc = require 'ipc'
|
||||
|
||||
module.exports.wrap = (webContents) ->
|
||||
return null unless webContents.isAlive()
|
||||
|
||||
# webContents is an EventEmitter.
|
||||
webContents.__proto__ = EventEmitter.prototype
|
||||
|
||||
# WebContents::send(channel, args..)
|
||||
webContents.send = (args...) ->
|
||||
@_send 'ATOM_INTERNAL_MESSAGE', [args...]
|
||||
|
||||
# The processId and routingId and identify a webContents.
|
||||
webContents.getId = -> "#{@getProcessId()}-#{@getRoutingId()}"
|
||||
webContents.equal = (other) -> @getId() is other.getId()
|
||||
|
||||
# Dispatch IPC messages to the ipc module.
|
||||
webContents.on 'ipc-message', (event, channel, args...) =>
|
||||
Object.defineProperty event, 'sender', value: webContents
|
||||
ipc.emit channel, event, args...
|
||||
webContents.on 'ipc-message-sync', (event, channel, args...) =>
|
||||
Object.defineProperty event, 'returnValue', set: (value) -> event.sendReply JSON.stringify(value)
|
||||
Object.defineProperty event, 'sender', value: webContents
|
||||
ipc.emit channel, event, args...
|
||||
|
||||
webContents
|
|
@ -4,10 +4,10 @@
|
|||
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
|
||||
#include "atom/browser/api/atom_browser_bindings.h"
|
||||
#include "atom/browser/atom_browser_client.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/common/api/atom_bindings.h"
|
||||
#include "atom/common/node_bindings.h"
|
||||
#include "net/proxy/proxy_resolver_v8.h"
|
||||
|
||||
|
@ -23,7 +23,7 @@ namespace atom {
|
|||
AtomBrowserMainParts* AtomBrowserMainParts::self_ = NULL;
|
||||
|
||||
AtomBrowserMainParts::AtomBrowserMainParts()
|
||||
: atom_bindings_(new AtomBrowserBindings),
|
||||
: atom_bindings_(new AtomBindings),
|
||||
browser_(new Browser),
|
||||
node_bindings_(NodeBindings::Create(true)) {
|
||||
DCHECK(!self_) << "Cannot have two AtomBrowserMainParts";
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
namespace atom {
|
||||
|
||||
class AtomBrowserBindings;
|
||||
class AtomBindings;
|
||||
class Browser;
|
||||
class NodeBindings;
|
||||
|
||||
|
@ -20,7 +20,6 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
|
|||
|
||||
static AtomBrowserMainParts* Get();
|
||||
|
||||
AtomBrowserBindings* atom_bindings() { return atom_bindings_.get(); }
|
||||
Browser* browser() { return browser_.get(); }
|
||||
|
||||
protected:
|
||||
|
@ -37,7 +36,7 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
|
|||
#endif
|
||||
|
||||
private:
|
||||
scoped_ptr<AtomBrowserBindings> atom_bindings_;
|
||||
scoped_ptr<AtomBindings> atom_bindings_;
|
||||
scoped_ptr<Browser> browser_;
|
||||
scoped_ptr<NodeBindings> node_bindings_;
|
||||
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/devtools_web_contents_observer.h"
|
||||
|
||||
#include "atom/browser/api/atom_browser_bindings.h"
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "base/logging.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "ipc/ipc_message_macros.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
DevToolsWebContentsObserver::DevToolsWebContentsObserver(
|
||||
NativeWindow* native_window,
|
||||
content::WebContents* web_contents)
|
||||
: content::WebContentsObserver(web_contents),
|
||||
inspected_window_(native_window) {
|
||||
DCHECK(native_window);
|
||||
}
|
||||
|
||||
DevToolsWebContentsObserver::~DevToolsWebContentsObserver() {
|
||||
}
|
||||
|
||||
bool DevToolsWebContentsObserver::OnMessageReceived(
|
||||
const IPC::Message& message) {
|
||||
bool handled = true;
|
||||
IPC_BEGIN_MESSAGE_MAP(DevToolsWebContentsObserver, message)
|
||||
IPC_MESSAGE_HANDLER(AtomViewHostMsg_Message, OnRendererMessage)
|
||||
IPC_MESSAGE_HANDLER_DELAY_REPLY(AtomViewHostMsg_Message_Sync,
|
||||
OnRendererMessageSync)
|
||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||
IPC_END_MESSAGE_MAP()
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
void DevToolsWebContentsObserver::OnRendererMessage(
|
||||
const string16& channel,
|
||||
const base::ListValue& args) {
|
||||
AtomBrowserMainParts::Get()->atom_bindings()->OnRendererMessage(
|
||||
web_contents()->GetRenderProcessHost()->GetID(),
|
||||
web_contents()->GetRoutingID(),
|
||||
channel,
|
||||
args);
|
||||
}
|
||||
|
||||
void DevToolsWebContentsObserver::OnRendererMessageSync(
|
||||
const string16& channel,
|
||||
const base::ListValue& args,
|
||||
IPC::Message* reply_msg) {
|
||||
AtomBrowserMainParts::Get()->atom_bindings()->OnRendererMessageSync(
|
||||
web_contents()->GetRenderProcessHost()->GetID(),
|
||||
web_contents()->GetRoutingID(),
|
||||
channel,
|
||||
args,
|
||||
web_contents(),
|
||||
reply_msg);
|
||||
}
|
||||
|
||||
} // namespace atom
|
|
@ -1,41 +0,0 @@
|
|||
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_DEVTOOLS_WEB_CONTENTS_OBSERVER_H_
|
||||
#define ATOM_BROWSER_DEVTOOLS_WEB_CONTENTS_OBSERVER_H_
|
||||
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
|
||||
namespace base {
|
||||
class ListValue;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class NativeWindow;
|
||||
|
||||
class DevToolsWebContentsObserver : public content::WebContentsObserver {
|
||||
public:
|
||||
DevToolsWebContentsObserver(NativeWindow* native_window,
|
||||
content::WebContents* web_contents);
|
||||
virtual ~DevToolsWebContentsObserver();
|
||||
|
||||
protected:
|
||||
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
|
||||
|
||||
void OnRendererMessage(const string16& channel,
|
||||
const base::ListValue& args);
|
||||
void OnRendererMessageSync(const string16& channel,
|
||||
const base::ListValue& args,
|
||||
IPC::Message* reply_msg);
|
||||
|
||||
private:
|
||||
NativeWindow* inspected_window_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DevToolsWebContentsObserver);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_DEVTOOLS_WEB_CONTENTS_OBSERVER_H_
|
|
@ -29,13 +29,11 @@ class ObjectsStore
|
|||
throw new Error("Invalid key #{id} for ObjectsStore") unless @has id
|
||||
@objects[id]
|
||||
|
||||
@forRenderView: (processId, routingId) ->
|
||||
key = "#{processId}_#{routingId}"
|
||||
@forRenderView: (key) ->
|
||||
@stores[key] = new ObjectsStore unless @stores[key]?
|
||||
@stores[key]
|
||||
|
||||
@releaseForRenderView: (processId, routingId) ->
|
||||
key = "#{processId}_#{routingId}"
|
||||
@releaseForRenderView: (key) ->
|
||||
delete @stores[key]
|
||||
|
||||
class ObjectsRegistry extends EventEmitter
|
||||
|
@ -52,7 +50,7 @@ class ObjectsRegistry extends EventEmitter
|
|||
|
||||
# Register a new object, the object would be kept referenced until you release
|
||||
# it explicitly.
|
||||
add: (processId, routingId, obj) ->
|
||||
add: (key, obj) ->
|
||||
# Some native objects may already been added to objectsWeakMap, be care not
|
||||
# to add it twice.
|
||||
@objectsWeakMap.add obj unless v8Util.getHiddenValue obj, 'atomId'
|
||||
|
@ -63,7 +61,7 @@ class ObjectsRegistry extends EventEmitter
|
|||
# with the storeId.
|
||||
# We use a difference key because the same object can be referenced for
|
||||
# multiple times by the same renderer view.
|
||||
store = ObjectsStore.forRenderView processId, routingId
|
||||
store = ObjectsStore.forRenderView key
|
||||
storeId = store.add obj
|
||||
|
||||
[id, storeId]
|
||||
|
@ -73,12 +71,12 @@ class ObjectsRegistry extends EventEmitter
|
|||
@objectsWeakMap.get id
|
||||
|
||||
# Remove an object according to its storeId.
|
||||
remove: (processId, routingId, storeId) ->
|
||||
ObjectsStore.forRenderView(processId, routingId).remove storeId
|
||||
remove: (key, storeId) ->
|
||||
ObjectsStore.forRenderView(key).remove storeId
|
||||
|
||||
# Clear all references to objects from renderer view.
|
||||
clear: (processId, routingId) ->
|
||||
@emit "release-renderer-view-#{processId}-#{routingId}"
|
||||
ObjectsStore.releaseForRenderView processId, routingId
|
||||
clear: (key) ->
|
||||
@emit "clear-#{key}"
|
||||
ObjectsStore.releaseForRenderView key
|
||||
|
||||
module.exports = new ObjectsRegistry
|
||||
|
|
|
@ -4,7 +4,7 @@ objectsRegistry = require './objects-registry.js'
|
|||
v8Util = process.atomBinding 'v8_util'
|
||||
|
||||
# Convert a real value into meta data.
|
||||
valueToMeta = (processId, routingId, value) ->
|
||||
valueToMeta = (sender, value) ->
|
||||
meta = type: typeof value
|
||||
|
||||
meta.type = 'value' if value is null
|
||||
|
@ -15,14 +15,14 @@ valueToMeta = (processId, routingId, value) ->
|
|||
|
||||
if meta.type is 'array'
|
||||
meta.members = []
|
||||
meta.members.push valueToMeta(processId, routingId, el) for el in value
|
||||
meta.members.push valueToMeta(sender, el) for el in value
|
||||
else if meta.type is 'object' or meta.type is 'function'
|
||||
meta.name = value.constructor.name
|
||||
|
||||
# Reference the original value if it's an object, because when it's
|
||||
# passed to renderer we would assume the renderer keeps a reference of
|
||||
# it.
|
||||
[meta.id, meta.storeId] = objectsRegistry.add processId, routingId, value
|
||||
[meta.id, meta.storeId] = objectsRegistry.add sender.getId(), value
|
||||
|
||||
meta.members = []
|
||||
meta.members.push {name: prop, type: typeof field} for prop, field of value
|
||||
|
@ -37,12 +37,12 @@ errorToMeta = (error) ->
|
|||
type: 'error', message: error.message, stack: (error.stack || error)
|
||||
|
||||
# Convert array of meta data from renderer into array of real values.
|
||||
unwrapArgs = (processId, routingId, args) ->
|
||||
unwrapArgs = (sender, args) ->
|
||||
metaToValue = (meta) ->
|
||||
switch meta.type
|
||||
when 'value' then meta.value
|
||||
when 'remote-object' then objectsRegistry.get meta.id
|
||||
when 'array' then unwrapArgs processId, routingId, meta.value
|
||||
when 'array' then unwrapArgs sender, meta.value
|
||||
when 'object'
|
||||
ret = v8Util.createObjectWithName meta.name
|
||||
for member in meta.members
|
||||
|
@ -53,15 +53,15 @@ unwrapArgs = (processId, routingId, args) ->
|
|||
-> returnValue
|
||||
when 'function'
|
||||
rendererReleased = false
|
||||
objectsRegistry.once "release-renderer-view-#{processId}-#{routingId}", ->
|
||||
objectsRegistry.once "clear-#{sender.getId()}", ->
|
||||
rendererReleased = true
|
||||
|
||||
ret = ->
|
||||
throw new Error('Calling a callback of released renderer view') if rendererReleased
|
||||
ipc.sendChannel processId, routingId, 'ATOM_RENDERER_CALLBACK', meta.id, valueToMeta(processId, routingId, arguments)
|
||||
sender.send 'ATOM_RENDERER_CALLBACK', meta.id, valueToMeta(sender, arguments)
|
||||
v8Util.setDestructor ret, ->
|
||||
return if rendererReleased
|
||||
ipc.sendChannel processId, routingId, 'ATOM_RENDERER_RELEASE_CALLBACK', meta.id
|
||||
sender.send 'ATOM_RENDERER_RELEASE_CALLBACK', meta.id
|
||||
ret
|
||||
else throw new TypeError("Unknown type: #{meta.type}")
|
||||
|
||||
|
@ -69,78 +69,78 @@ unwrapArgs = (processId, routingId, args) ->
|
|||
|
||||
# Call a function and send reply asynchronously if it's a an asynchronous
|
||||
# style function and the caller didn't pass a callback.
|
||||
callFunction = (event, processId, routingId, func, caller, args) ->
|
||||
callFunction = (event, func, caller, args) ->
|
||||
if v8Util.getHiddenValue(func, 'asynchronous') and typeof args[args.length - 1] isnt 'function'
|
||||
args.push (ret) ->
|
||||
event.returnValue = valueToMeta processId, routingId, ret
|
||||
event.returnValue = valueToMeta event.sender, ret
|
||||
func.apply caller, args
|
||||
else
|
||||
ret = func.apply caller, args
|
||||
event.returnValue = valueToMeta processId, routingId, ret
|
||||
event.returnValue = valueToMeta event.sender, ret
|
||||
|
||||
# Send by BrowserWindow when its render view is deleted.
|
||||
process.on 'ATOM_BROWSER_RELEASE_RENDER_VIEW', (processId, routingId) ->
|
||||
objectsRegistry.clear processId, routingId
|
||||
process.on 'ATOM_BROWSER_RELEASE_RENDER_VIEW', (id) ->
|
||||
objectsRegistry.clear id
|
||||
|
||||
ipc.on 'ATOM_BROWSER_REQUIRE', (event, processId, routingId, module) ->
|
||||
ipc.on 'ATOM_BROWSER_REQUIRE', (event, module) ->
|
||||
try
|
||||
event.returnValue = valueToMeta processId, routingId, require(module)
|
||||
event.returnValue = valueToMeta event.sender, require(module)
|
||||
catch e
|
||||
event.returnValue = errorToMeta e
|
||||
|
||||
ipc.on 'ATOM_BROWSER_GLOBAL', (event, processId, routingId, name) ->
|
||||
ipc.on 'ATOM_BROWSER_GLOBAL', (event, name) ->
|
||||
try
|
||||
event.returnValue = valueToMeta processId, routingId, global[name]
|
||||
event.returnValue = valueToMeta event.sender, global[name]
|
||||
catch e
|
||||
event.returnValue = errorToMeta e
|
||||
|
||||
ipc.on 'ATOM_BROWSER_CURRENT_WINDOW', (event, processId, routingId) ->
|
||||
ipc.on 'ATOM_BROWSER_CURRENT_WINDOW', (event) ->
|
||||
try
|
||||
BrowserWindow = require 'browser-window'
|
||||
window = BrowserWindow.fromProcessIdAndRoutingId processId, routingId
|
||||
window = BrowserWindow.fromDevTools processId, routingId unless window?
|
||||
event.returnValue = valueToMeta processId, routingId, window
|
||||
window = BrowserWindow.fromWebContents event.sender
|
||||
window = BrowserWindow.fromDevToolsWebContents event.sender unless window?
|
||||
event.returnValue = valueToMeta event.sender, window
|
||||
catch e
|
||||
event.returnValue = errorToMeta e
|
||||
|
||||
ipc.on 'ATOM_BROWSER_CONSTRUCTOR', (event, processId, routingId, id, args) ->
|
||||
ipc.on 'ATOM_BROWSER_CONSTRUCTOR', (event, id, args) ->
|
||||
try
|
||||
args = unwrapArgs processId, routingId, args
|
||||
args = unwrapArgs event.sender, args
|
||||
constructor = objectsRegistry.get id
|
||||
# Call new with array of arguments.
|
||||
# http://stackoverflow.com/questions/1606797/use-of-apply-with-new-operator-is-this-possible
|
||||
obj = new (Function::bind.apply(constructor, [null].concat(args)))
|
||||
event.returnValue = valueToMeta processId, routingId, obj
|
||||
event.returnValue = valueToMeta event.sender, obj
|
||||
catch e
|
||||
event.returnValue = errorToMeta e
|
||||
|
||||
ipc.on 'ATOM_BROWSER_FUNCTION_CALL', (event, processId, routingId, id, args) ->
|
||||
ipc.on 'ATOM_BROWSER_FUNCTION_CALL', (event, id, args) ->
|
||||
try
|
||||
args = unwrapArgs processId, routingId, args
|
||||
args = unwrapArgs event.sender, args
|
||||
func = objectsRegistry.get id
|
||||
callFunction event, processId, routingId, func, global, args
|
||||
callFunction event, func, global, args
|
||||
catch e
|
||||
event.returnValue = errorToMeta e
|
||||
|
||||
ipc.on 'ATOM_BROWSER_MEMBER_CONSTRUCTOR', (event, processId, routingId, id, method, args) ->
|
||||
ipc.on 'ATOM_BROWSER_MEMBER_CONSTRUCTOR', (event, id, method, args) ->
|
||||
try
|
||||
args = unwrapArgs processId, routingId, args
|
||||
args = unwrapArgs event.sender, args
|
||||
constructor = objectsRegistry.get(id)[method]
|
||||
# Call new with array of arguments.
|
||||
obj = new (Function::bind.apply(constructor, [null].concat(args)))
|
||||
event.returnValue = valueToMeta processId, routingId, obj
|
||||
event.returnValue = valueToMeta event.sender, obj
|
||||
catch e
|
||||
event.returnValue = errorToMeta e
|
||||
|
||||
ipc.on 'ATOM_BROWSER_MEMBER_CALL', (event, processId, routingId, id, method, args) ->
|
||||
ipc.on 'ATOM_BROWSER_MEMBER_CALL', (event, id, method, args) ->
|
||||
try
|
||||
args = unwrapArgs processId, routingId, args
|
||||
args = unwrapArgs event.sender, args
|
||||
obj = objectsRegistry.get id
|
||||
callFunction event, processId, routingId, obj[method], obj, args
|
||||
callFunction event, obj[method], obj, args
|
||||
catch e
|
||||
event.returnValue = errorToMeta e
|
||||
|
||||
ipc.on 'ATOM_BROWSER_MEMBER_SET', (event, processId, routingId, id, name, value) ->
|
||||
ipc.on 'ATOM_BROWSER_MEMBER_SET', (event, id, name, value) ->
|
||||
try
|
||||
obj = objectsRegistry.get id
|
||||
obj[name] = value
|
||||
|
@ -148,12 +148,12 @@ ipc.on 'ATOM_BROWSER_MEMBER_SET', (event, processId, routingId, id, name, value)
|
|||
catch e
|
||||
event.returnValue = errorToMeta e
|
||||
|
||||
ipc.on 'ATOM_BROWSER_MEMBER_GET', (event, processId, routingId, id, name) ->
|
||||
ipc.on 'ATOM_BROWSER_MEMBER_GET', (event, id, name) ->
|
||||
try
|
||||
obj = objectsRegistry.get id
|
||||
event.returnValue = valueToMeta processId, routingId, obj[name]
|
||||
event.returnValue = valueToMeta event.sender, obj[name]
|
||||
catch e
|
||||
event.returnValue = errorToMeta e
|
||||
|
||||
ipc.on 'ATOM_BROWSER_DEREFERENCE', (processId, routingId, storeId) ->
|
||||
objectsRegistry.remove processId, routingId, storeId
|
||||
ipc.on 'ATOM_BROWSER_DEREFERENCE', (event, storeId) ->
|
||||
objectsRegistry.remove event.sender.getId(), storeId
|
||||
|
|
|
@ -8,13 +8,10 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/atom_browser_bindings.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "atom/browser/atom_javascript_dialog_manager.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/devtools_delegate.h"
|
||||
#include "atom/browser/devtools_web_contents_observer.h"
|
||||
#include "atom/browser/ui/file_dialog.h"
|
||||
#include "atom/browser/window_list.h"
|
||||
#include "atom/common/api/api_messages.h"
|
||||
|
@ -195,12 +192,8 @@ bool NativeWindow::HasModalDialog() {
|
|||
void NativeWindow::OpenDevTools() {
|
||||
if (devtools_window_) {
|
||||
devtools_window_->Focus(true);
|
||||
devtools_web_contents_observer_.reset(new DevToolsWebContentsObserver(
|
||||
this, devtools_window_->GetWebContents()));
|
||||
} else {
|
||||
inspectable_web_contents()->ShowDevTools();
|
||||
devtools_web_contents_observer_.reset(new DevToolsWebContentsObserver(
|
||||
this, GetDevToolsWebContents()));
|
||||
#if defined(OS_MACOSX)
|
||||
// Temporary fix for flashing devtools, try removing this after upgraded to
|
||||
// Chrome 32.
|
||||
|
@ -229,11 +222,6 @@ void NativeWindow::InspectElement(int x, int y) {
|
|||
agent->InspectElement(x, y);
|
||||
}
|
||||
|
||||
void NativeWindow::ExecuteJavaScriptInDevTools(const std::string& script) {
|
||||
GetDevToolsWebContents()->GetRenderViewHost()->ExecuteJavascriptInWebFrame(
|
||||
string16(), base::UTF8ToUTF16(script));
|
||||
}
|
||||
|
||||
void NativeWindow::FocusOnWebView() {
|
||||
GetWebContents()->GetRenderViewHost()->Focus();
|
||||
}
|
||||
|
@ -305,14 +293,6 @@ void NativeWindow::DestroyWebContents() {
|
|||
if (!inspectable_web_contents_)
|
||||
return;
|
||||
|
||||
// The OnRenderViewDeleted is not called when the WebContents is destroyed
|
||||
// directly (e.g. when closing the window), so we make sure it's always
|
||||
// emitted to users by sending it before window is closed..
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_,
|
||||
OnRenderViewDeleted(
|
||||
GetWebContents()->GetRenderProcessHost()->GetID(),
|
||||
GetWebContents()->GetRoutingID()));
|
||||
|
||||
inspectable_web_contents_.reset();
|
||||
}
|
||||
|
||||
|
@ -437,13 +417,6 @@ void NativeWindow::DeactivateContents(content::WebContents* contents) {
|
|||
BlurWebView();
|
||||
}
|
||||
|
||||
void NativeWindow::LoadingStateChanged(content::WebContents* source) {
|
||||
bool is_loading = source->IsLoading();
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver,
|
||||
observers_,
|
||||
OnLoadingStateChanged(is_loading));
|
||||
}
|
||||
|
||||
void NativeWindow::MoveContents(content::WebContents* source,
|
||||
const gfx::Rect& pos) {
|
||||
SetPosition(pos.origin());
|
||||
|
@ -482,16 +455,6 @@ void NativeWindow::RendererResponsive(content::WebContents* source) {
|
|||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnRendererResponsive());
|
||||
}
|
||||
|
||||
void NativeWindow::RenderViewDeleted(content::RenderViewHost* rvh) {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_,
|
||||
OnRenderViewDeleted(rvh->GetProcess()->GetID(),
|
||||
rvh->GetRoutingID()));
|
||||
}
|
||||
|
||||
void NativeWindow::RenderProcessGone(base::TerminationStatus status) {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnRendererCrashed());
|
||||
}
|
||||
|
||||
void NativeWindow::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.
|
||||
|
@ -500,9 +463,6 @@ void NativeWindow::BeforeUnloadFired(const base::TimeTicks& proceed_time) {
|
|||
bool NativeWindow::OnMessageReceived(const IPC::Message& message) {
|
||||
bool handled = true;
|
||||
IPC_BEGIN_MESSAGE_MAP(NativeWindow, message)
|
||||
IPC_MESSAGE_HANDLER(AtomViewHostMsg_Message, OnRendererMessage)
|
||||
IPC_MESSAGE_HANDLER_DELAY_REPLY(AtomViewHostMsg_Message_Sync,
|
||||
OnRendererMessageSync)
|
||||
IPC_MESSAGE_HANDLER(AtomViewHostMsg_UpdateDraggableRegions,
|
||||
UpdateDraggableRegions)
|
||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||
|
@ -628,28 +588,8 @@ void NativeWindow::CallDevToolsFunction(const std::string& function_name,
|
|||
}
|
||||
}
|
||||
}
|
||||
ExecuteJavaScriptInDevTools(function_name + "(" + params + ");");
|
||||
}
|
||||
|
||||
void NativeWindow::OnRendererMessage(const string16& channel,
|
||||
const base::ListValue& args) {
|
||||
AtomBrowserMainParts::Get()->atom_bindings()->OnRendererMessage(
|
||||
GetWebContents()->GetRenderProcessHost()->GetID(),
|
||||
GetWebContents()->GetRoutingID(),
|
||||
channel,
|
||||
args);
|
||||
}
|
||||
|
||||
void NativeWindow::OnRendererMessageSync(const string16& channel,
|
||||
const base::ListValue& args,
|
||||
IPC::Message* reply_msg) {
|
||||
AtomBrowserMainParts::Get()->atom_bindings()->OnRendererMessageSync(
|
||||
GetWebContents()->GetRenderProcessHost()->GetID(),
|
||||
GetWebContents()->GetRoutingID(),
|
||||
channel,
|
||||
args,
|
||||
GetWebContents(),
|
||||
reply_msg);
|
||||
GetDevToolsWebContents()->GetRenderViewHost()->ExecuteJavascriptInWebFrame(
|
||||
string16(), base::UTF8ToUTF16(function_name + "(" + params + ");"));
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
|
|
@ -46,7 +46,6 @@ namespace atom {
|
|||
|
||||
class AtomJavaScriptDialogManager;
|
||||
class DevToolsDelegate;
|
||||
class DevToolsWebContentsObserver;
|
||||
struct DraggableRegion;
|
||||
|
||||
class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
||||
|
@ -136,7 +135,6 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
|||
virtual void CloseDevTools();
|
||||
virtual bool IsDevToolsOpened();
|
||||
virtual void InspectElement(int x, int y);
|
||||
virtual void ExecuteJavaScriptInDevTools(const std::string& script);
|
||||
|
||||
virtual void FocusOnWebView();
|
||||
virtual void BlurWebView();
|
||||
|
@ -220,7 +218,6 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
|||
virtual bool CanOverscrollContent() const OVERRIDE;
|
||||
virtual void ActivateContents(content::WebContents* contents) OVERRIDE;
|
||||
virtual void DeactivateContents(content::WebContents* contents) OVERRIDE;
|
||||
virtual void LoadingStateChanged(content::WebContents* source) OVERRIDE;
|
||||
virtual void MoveContents(content::WebContents* source,
|
||||
const gfx::Rect& pos) OVERRIDE;
|
||||
virtual void CloseContents(content::WebContents* source) OVERRIDE;
|
||||
|
@ -230,8 +227,6 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
|||
virtual void RendererResponsive(content::WebContents* source) OVERRIDE;
|
||||
|
||||
// Implementations of content::WebContentsObserver.
|
||||
virtual void RenderViewDeleted(content::RenderViewHost*) OVERRIDE;
|
||||
virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
|
||||
virtual void BeforeUnloadFired(const base::TimeTicks& proceed_time) OVERRIDE;
|
||||
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
|
||||
|
||||
|
@ -274,13 +269,6 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
|||
bool succeed,
|
||||
const SkBitmap& bitmap);
|
||||
|
||||
void OnRendererMessage(const string16& channel,
|
||||
const base::ListValue& args);
|
||||
|
||||
void OnRendererMessageSync(const string16& channel,
|
||||
const base::ListValue& args,
|
||||
IPC::Message* reply_msg);
|
||||
|
||||
// Notification manager.
|
||||
content::NotificationRegistrar registrar_;
|
||||
|
||||
|
@ -305,9 +293,6 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
|||
base::WeakPtr<NativeWindow> devtools_window_;
|
||||
scoped_ptr<DevToolsDelegate> devtools_delegate_;
|
||||
|
||||
// WebContentsObserver for the WebContents of devtools.
|
||||
scoped_ptr<DevToolsWebContentsObserver> devtools_web_contents_observer_;
|
||||
|
||||
scoped_ptr<AtomJavaScriptDialogManager> dialog_manager_;
|
||||
|
||||
// Notice that inspectable_web_contents_ must be placed after dialog_manager_,
|
||||
|
|
|
@ -17,9 +17,6 @@ class NativeWindowObserver {
|
|||
virtual void OnPageTitleUpdated(bool* prevent_default,
|
||||
const std::string& title) {}
|
||||
|
||||
// Called when the window is starting or is done loading a page.
|
||||
virtual void OnLoadingStateChanged(bool is_loading) {}
|
||||
|
||||
// Called when the window is gonna closed.
|
||||
virtual void WillCloseWindow(bool* prevent_default) {}
|
||||
|
||||
|
@ -34,12 +31,6 @@ class NativeWindowObserver {
|
|||
|
||||
// Called when renderer recovers.
|
||||
virtual void OnRendererResponsive() {}
|
||||
|
||||
// Called when a render view has been deleted.
|
||||
virtual void OnRenderViewDeleted(int process_id, int routing_id) {}
|
||||
|
||||
// Called when renderer has crashed.
|
||||
virtual void OnRendererCrashed() {}
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
|
|
@ -12,7 +12,6 @@ NODE_EXT_LIST_START
|
|||
NODE_EXT_LIST_ITEM(atom_browser_app)
|
||||
NODE_EXT_LIST_ITEM(atom_browser_auto_updater)
|
||||
NODE_EXT_LIST_ITEM(atom_browser_dialog)
|
||||
NODE_EXT_LIST_ITEM(atom_browser_ipc)
|
||||
NODE_EXT_LIST_ITEM(atom_browser_menu)
|
||||
NODE_EXT_LIST_ITEM(atom_browser_power_monitor)
|
||||
NODE_EXT_LIST_ITEM(atom_browser_protocol)
|
||||
|
|
|
@ -10,15 +10,13 @@ class Ipc extends EventEmitter
|
|||
process.removeAllListeners 'ATOM_INTERNAL_MESSAGE'
|
||||
|
||||
send: (args...) ->
|
||||
@sendChannel 'message', args...
|
||||
|
||||
sendChannel: (args...) ->
|
||||
ipc.send 'ATOM_INTERNAL_MESSAGE', [args...]
|
||||
ipc.send 'ipc-message', [args...]
|
||||
|
||||
sendSync: (args...) ->
|
||||
@sendSync 'sync-message', args...
|
||||
JSON.parse ipc.sendSync('ipc-message-sync', [args...])
|
||||
|
||||
sendChannelSync: (args...) ->
|
||||
JSON.parse ipc.sendSync('ATOM_INTERNAL_MESSAGE_SYNC', [args...])
|
||||
# Discarded
|
||||
sendChannel: -> @send.apply this, arguments
|
||||
sendChannelSync: -> @sendSync.apply this, arguments
|
||||
|
||||
module.exports = new Ipc
|
||||
|
|
|
@ -7,7 +7,7 @@ example is:
|
|||
var BrowserWindow = require('browser-window');
|
||||
|
||||
var win = new BrowserWindow({ width: 800, height: 600, show: false });
|
||||
win.on('destroyed', function() {
|
||||
win.on('closed', function() {
|
||||
win = null;
|
||||
});
|
||||
|
||||
|
@ -86,13 +86,6 @@ you should explictly set `sandbox` to `none`:
|
|||
Emitted when the document changed its title, calling `event.preventDefault()`
|
||||
would prevent the native window's title to change.
|
||||
|
||||
### Event: 'loading-state-changed'
|
||||
|
||||
* `event` Event
|
||||
* `isLoading` Boolean
|
||||
|
||||
Emitted when the window is starting or is done loading a page.
|
||||
|
||||
### Event: 'close'
|
||||
|
||||
* `event` Event
|
||||
|
@ -137,10 +130,6 @@ Emiited when the web page becomes unresponsive.
|
|||
|
||||
Emitted when the unresponsive web page becomes responsive again.
|
||||
|
||||
### Event: 'crashed'
|
||||
|
||||
Emitted when the renderer process is crashed.
|
||||
|
||||
### Event: 'blur'
|
||||
|
||||
Emiited when window loses focus.
|
||||
|
@ -153,12 +142,20 @@ Returns an array of all opened browser windows.
|
|||
|
||||
Returns the window that is focused in this application.
|
||||
|
||||
### Class Method: BrowserWindow.fromProcessIdAndRoutingId(processId, routingId)
|
||||
### Class Method: BrowserWindow.fromWebContents(webContents)
|
||||
|
||||
* `processId` Integer
|
||||
* `routingId` Integer
|
||||
* `webContents` WebContents
|
||||
|
||||
Find a window according to its `processId` and `routingId`.
|
||||
Find a window according to the `webContents` it owns
|
||||
|
||||
### BrowserWindow.webContents
|
||||
|
||||
The `WebContents` object this window owns, all web page related events and
|
||||
operations would be done via it.
|
||||
|
||||
### BrowserWindow.devToolsWebContents
|
||||
|
||||
Get the `WebContents` of devtools of this window.
|
||||
|
||||
### BrowserWindow.destroy()
|
||||
|
||||
|
@ -334,13 +331,6 @@ Closes the developer tools.
|
|||
|
||||
Starts inspecting element at position (`x`, `y`).
|
||||
|
||||
### BrowserWindow.executeJavaScriptInDevTools(code)
|
||||
|
||||
* `code` String
|
||||
|
||||
Evaluate `code` in devtools to use
|
||||
[InspectorFrontendAPI](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/devtools/front_end/InspectorFrontendAPI.js&q=InspectorFrontendAPI&sq=package:chromium&type=cs)
|
||||
|
||||
### BrowserWindow.focusOnWebView()
|
||||
|
||||
### BrowserWindow.blurWebView()
|
||||
|
@ -366,82 +356,113 @@ encode it and use data URL to embed the image in HTML.
|
|||
[remote](../renderer/remote.md) if you are going to use this API in renderer
|
||||
process.
|
||||
|
||||
### BrowserWindow.getPageTitle()
|
||||
|
||||
Returns the title of web page.
|
||||
|
||||
### BrowserWindow.isLoading()
|
||||
|
||||
Returns whether web page is still loading resources.
|
||||
|
||||
### BrowserWindow.isWaitingForResponse()
|
||||
|
||||
Returns whether web page is waiting for a first-response for the main resource
|
||||
of the page.
|
||||
|
||||
### BrowserWindow.stop()
|
||||
|
||||
Stops any pending navigation.
|
||||
|
||||
### BrowserWindow.getProcessId()
|
||||
|
||||
Returns window's process ID. The process ID and routing ID can be used
|
||||
together to locate a window.
|
||||
|
||||
### BrowserWindow.getRoutingId()
|
||||
|
||||
Returns window's routing ID. The process ID and routing ID can be used
|
||||
together to locate a window.
|
||||
|
||||
### BrowserWindow.loadUrl(url)
|
||||
|
||||
Same with `webContents.loadUrl(url)`.
|
||||
|
||||
## Class: WebContents
|
||||
|
||||
A `WebContents` is responsible for rendering and controlling a web page.
|
||||
|
||||
`WebContents` is an
|
||||
[EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter).
|
||||
|
||||
### Event: 'crashed'
|
||||
|
||||
Emitted when the renderer process is crashed.
|
||||
|
||||
### Event: 'did-finish-load'
|
||||
|
||||
Emitted when the navigation is done, i.e. the spinner of the tab will stop
|
||||
spinning, and the onload event was dispatched.
|
||||
|
||||
### Event: 'did-start-loading'
|
||||
|
||||
### Event: 'did-stop-loading'
|
||||
|
||||
### WebContents.loadUrl(url)
|
||||
|
||||
* `url` URL
|
||||
|
||||
Loads the `url` in the window, the `url` must contains the protocol prefix,
|
||||
e.g. the `http://` or `file://`.
|
||||
|
||||
### BrowserWindow.getUrl()
|
||||
### WebContents.getUrl()
|
||||
|
||||
Returns URL of current web page.
|
||||
|
||||
### BrowserWindow.canGoBack()
|
||||
### WebContents.getTitle()
|
||||
|
||||
Returns the title of web page.
|
||||
|
||||
### WebContents.isLoading()
|
||||
|
||||
Returns whether web page is still loading resources.
|
||||
|
||||
### WebContents.isWaitingForResponse()
|
||||
|
||||
Returns whether web page is waiting for a first-response for the main resource
|
||||
of the page.
|
||||
|
||||
### WebContents.stop()
|
||||
|
||||
Stops any pending navigation.
|
||||
|
||||
### WebContents.reload()
|
||||
|
||||
Reloads current page.
|
||||
|
||||
### WebContents.reloadIgnoringCache()
|
||||
|
||||
Reloads current page and ignores cache.
|
||||
|
||||
### WebContents.canGoBack()
|
||||
|
||||
Returns whether the web page can go back.
|
||||
|
||||
### BrowserWindow.canGoForward()
|
||||
### WebContents.canGoForward()
|
||||
|
||||
Returns whether the web page can go forward.
|
||||
|
||||
### BrowserWindow.canGoToOffset(offset)
|
||||
### WebContents.canGoToOffset(offset)
|
||||
|
||||
* `offset` Integer
|
||||
|
||||
Returns whether the web page can go to `offset`.
|
||||
|
||||
### BrowserWindow.goBack()
|
||||
### WebContents.goBack()
|
||||
|
||||
Makes the web page go back.
|
||||
|
||||
### BrowserWindow.goForward()
|
||||
### WebContents.goForward()
|
||||
|
||||
Makes the web page go forward.
|
||||
|
||||
### BrowserWindow.goToIndex(index)
|
||||
### WebContents.goToIndex(index)
|
||||
|
||||
* `index` Integer
|
||||
|
||||
Navigates to the specified absolute index.
|
||||
|
||||
### BrowserWindow.goToOffset(offset)
|
||||
### WebContents.goToOffset(offset)
|
||||
|
||||
* `offset` Integer
|
||||
|
||||
Navigates to the specified offset from the "current entry".
|
||||
|
||||
### BrowserWindow.reload()
|
||||
### WebContents.IsCrashed()
|
||||
|
||||
Reloads current window.
|
||||
Whether the renderer process has crashed.
|
||||
|
||||
### BrowserWindow.reloadIgnoringCache()
|
||||
### WebContents.executeJavaScript(code)
|
||||
|
||||
Reloads current window and ignores cache.
|
||||
* `code` String
|
||||
|
||||
Evaluate `code` in page.
|
||||
|
||||
### WebContents.send(channel[, args...])
|
||||
|
||||
* `channel` String
|
||||
|
||||
Send `args..` to the web page via `channel` in asynchronous message, the web
|
||||
page can handle it by listening to the `channel` event of `ipc` module.
|
||||
|
|
|
@ -1,52 +1,45 @@
|
|||
# ipc (browser)
|
||||
|
||||
The `ipc` module allows developers to send asynchronous messages to renderers.
|
||||
To avoid possible dead-locks, it's not allowed to send synchronous messages in
|
||||
browser.
|
||||
Handles asynchronous and synchronous message sent from web page.
|
||||
|
||||
## Event: 'message'
|
||||
The messages sent from web page would be emitted to this module, the event name
|
||||
is the `channel` when sending message. To reply a synchronous message, you need
|
||||
to set `event.returnValue`, to send an asynchronous back to the sender, you can
|
||||
use `event.sender.send(...)`.
|
||||
|
||||
* `processId` Integer
|
||||
* `routingId` Integer
|
||||
|
||||
Emitted when renderer sent a message to the browser.
|
||||
|
||||
## Event: 'sync-message'
|
||||
|
||||
* `event` Object
|
||||
* `processId` Integer
|
||||
* `routingId` Integer
|
||||
|
||||
Emitted when renderer sent a synchronous message to the browser. The receiver
|
||||
should store the result in `event.returnValue`.
|
||||
|
||||
**Note:** Due to the limitation of `EventEmitter`, returning value in the
|
||||
event handler has no effect, so we have to store the result by using the
|
||||
`event` parameter.
|
||||
|
||||
## ipc.send(processId, routingId, [args...])
|
||||
|
||||
* `processId` Integer
|
||||
* `routingId` Integer
|
||||
|
||||
Send `args...` to the renderer specified by `processId` and `routingId` and
|
||||
return immediately, the renderer should handle the message by listening to the
|
||||
`message` event.
|
||||
|
||||
## ipc.sendChannel(processId, routingId, channel, [args...])
|
||||
|
||||
* `processId` Integer
|
||||
* `routingId` Integer
|
||||
* `channel` String
|
||||
|
||||
This is the same with ipc.send, except that the renderer should listen to the
|
||||
`channel` event. The ipc.send(processId, routingId, args...) can be seen as
|
||||
ipc.sendChannel(processId, routingId, 'message', args...).
|
||||
|
||||
**Note:** If the the first argument (e.g. `processId`) is a `BrowserWindow`,
|
||||
`ipc.sendChannel` would automatically get the `processId` and `routingId`
|
||||
from it, so you can send a message to window like this:
|
||||
An example of sending and handling messages:
|
||||
|
||||
```javascript
|
||||
ipc.sendChannel(browserWindow, 'message', ...);
|
||||
// In browser.
|
||||
var ipc = require('ipc');
|
||||
ipc.on('asynchronous-message', function(event, arg) {
|
||||
console.log(arg); // prints "ping"
|
||||
event.sender.send('asynchronous-reply', 'pong');
|
||||
});
|
||||
|
||||
ipc.on('synchronous-message', function(event, arg) {
|
||||
console.log(arg); // prints "ping"
|
||||
event.returnValue = 'pong'.
|
||||
});
|
||||
```
|
||||
|
||||
```javascript
|
||||
// In web page.
|
||||
var ipc = require('ipc');
|
||||
console.log(ipc.sendSync('synchronous-message', 'ping')); // prints "pong"
|
||||
|
||||
ipc.on('asynchronous-reply', function(arg) {
|
||||
console.log(arg); // prints "pong"
|
||||
});
|
||||
ipc.send('asynchronous-message', 'ping');
|
||||
```
|
||||
|
||||
### Class: Event
|
||||
|
||||
## Event.returnValue
|
||||
|
||||
Assign to this to return an value to synchronous messages.
|
||||
|
||||
## Event.sender
|
||||
|
||||
The `WebContents` of the web page that has sent the message.
|
||||
|
|
|
@ -5,75 +5,18 @@ asynchronous messages to the browser, and also receive messages sent from
|
|||
browser. If you want to make use of modules of browser from renderer, you
|
||||
might consider using the [remote](remote.md) module.
|
||||
|
||||
An example of echoing messages between browser and renderer:
|
||||
See [ipc (browser)](../browser/ipc-browser.md) for examples.
|
||||
|
||||
```javascript
|
||||
// In browser:
|
||||
var ipc = require('ipc');
|
||||
ipc.on('message', function(processId, routingId, m) {
|
||||
ipc.send(processId, routingId, m);
|
||||
});
|
||||
```
|
||||
## ipc.send(channel[, args...])
|
||||
|
||||
```javascript
|
||||
// In renderer:
|
||||
var ipc = require('ipc');
|
||||
ipc.on('message', function(m) {
|
||||
console.log('Received message', m);
|
||||
});
|
||||
ipc.send('Hello world');
|
||||
```
|
||||
Send `args..` to the web page via `channel` in asynchronous message, the browser
|
||||
process can handle it by listening to the `channel` event of `ipc` module.
|
||||
|
||||
An example of sending synchronous message from renderer to browser:
|
||||
## ipc.sendSync(channel[, args...])
|
||||
|
||||
```javascript
|
||||
// In browser:
|
||||
var ipc = require('ipc');
|
||||
ipc.on('browser-data-request', function(event, processId, routingId, message) {
|
||||
event.returnValue = 'THIS SOME DATA FROM THE BROWSER';
|
||||
});
|
||||
```
|
||||
|
||||
```javascript
|
||||
// In renderer:
|
||||
var ipc = require('ipc');
|
||||
console.log(ipc.sendChannelSync('browser-data-request', 'THIS IS FROM THE RENDERER'));
|
||||
```
|
||||
|
||||
## Event: 'message'
|
||||
|
||||
Emitted when browser sent a message to this window.
|
||||
|
||||
## ipc.send([args...])
|
||||
|
||||
Send all arguments to the browser and return immediately, the browser should
|
||||
handle the message by listening to the `message` event.
|
||||
|
||||
## ipc.sendSync([args...])
|
||||
|
||||
Send all arguments to the browser synchronously, and returns the result sent
|
||||
from browser. The browser should handle the message by listening to the
|
||||
`sync-message` event.
|
||||
Send `args..` to the web page via `channel` in synchronous message, and returns
|
||||
the result sent from browser. The browser process can handle it by listening to
|
||||
the `channel` event of `ipc` module, and returns by setting `event.returnValue`.
|
||||
|
||||
**Note:** Usually developers should never use this API, since sending
|
||||
synchronous message would block the browser.
|
||||
|
||||
## ipc.sendChannel(channel, [args...])
|
||||
|
||||
* `channel` String
|
||||
|
||||
This is the same with `ipc.send`, except that the browser should listen to the
|
||||
`channel` event. The `ipc.send(args...)` can be seen as
|
||||
`ipc.sendChannel('message', args...)`.
|
||||
|
||||
|
||||
## ipc.sendChannelSync(channel, [args...])
|
||||
|
||||
* `channel` String
|
||||
|
||||
This is the same with `ipc.sendSync`, except that the browser should listen to
|
||||
the `channel` event. The `ipc.sendSync(args...)` can be seen as
|
||||
`ipc.sendChannelSync('sync-message', args...)`.
|
||||
|
||||
**Note:** Usually developers should never use this API, since sending
|
||||
synchronous message would block the browser.
|
||||
synchronous message would block the whole web page.
|
||||
|
|
|
@ -18,9 +18,8 @@ describe 'browser-window module', ->
|
|||
|
||||
describe 'BrowserWindow.close()', ->
|
||||
it 'should emit unload handler', (done) ->
|
||||
w.on 'loading-state-changed', (event, isLoading) ->
|
||||
if (!isLoading)
|
||||
w.close()
|
||||
w.webContents.on 'did-finish-load', ->
|
||||
w.close()
|
||||
w.on 'closed', ->
|
||||
test = path.join(fixtures, 'api', 'unload')
|
||||
content = fs.readFileSync(test)
|
||||
|
@ -32,9 +31,8 @@ describe 'browser-window module', ->
|
|||
it 'should emit beforeunload handler', (done) ->
|
||||
w.on 'onbeforeunload', ->
|
||||
done()
|
||||
w.on 'loading-state-changed', (event, isLoading) ->
|
||||
if (!isLoading)
|
||||
w.close()
|
||||
w.webContents.on 'did-finish-load', ->
|
||||
w.close()
|
||||
w.loadUrl 'file://' + path.join(fixtures, 'api', 'beforeunload-false.html')
|
||||
|
||||
describe 'window.close()', ->
|
||||
|
@ -53,18 +51,9 @@ describe 'browser-window module', ->
|
|||
w.loadUrl 'file://' + path.join(fixtures, 'api', 'close-beforeunload-false.html')
|
||||
|
||||
describe 'BrowserWindow.loadUrl(url)', ->
|
||||
it 'should emit loading-state-changed event', (done) ->
|
||||
count = 0
|
||||
w.on 'loading-state-changed', (event, isLoading) ->
|
||||
if count == 0
|
||||
assert.equal isLoading, true
|
||||
else if count == 1
|
||||
assert.equal isLoading, false
|
||||
done()
|
||||
else
|
||||
assert false
|
||||
|
||||
++count
|
||||
it 'should emit did-start-loading event', (done) ->
|
||||
w.webContents.on 'did-start-loading', ->
|
||||
done()
|
||||
w.loadUrl 'about:blank'
|
||||
|
||||
describe 'BrowserWindow.focus()', ->
|
||||
|
|
|
@ -48,13 +48,13 @@ describe 'ipc module', ->
|
|||
print_name = remote.require path.join(fixtures, 'module', 'print_name.js')
|
||||
assert.equal print_name.print(buf), 'Buffer'
|
||||
|
||||
describe 'ipc.send', ->
|
||||
describe 'ipc.sender.send', ->
|
||||
it 'should work when sending an object containing id property', (done) ->
|
||||
obj = id: 1, name: 'ly'
|
||||
ipc.once 'message', (message) ->
|
||||
assert.deepEqual message, obj
|
||||
done()
|
||||
ipc.send obj
|
||||
ipc.send 'message', obj
|
||||
|
||||
describe 'ipc.sendSync', ->
|
||||
it 'can be replied by setting event.returnValue', ->
|
||||
|
|
|
@ -8,8 +8,8 @@ var window = null;
|
|||
|
||||
app.commandLine.appendSwitch('js-flags', '--expose_gc');
|
||||
|
||||
ipc.on('message', function() {
|
||||
ipc.send.apply(this, arguments);
|
||||
ipc.on('message', function(event, arg) {
|
||||
event.sender.send('message', arg);
|
||||
});
|
||||
|
||||
ipc.on('console.log', function(pid, rid, args) {
|
||||
|
@ -24,11 +24,11 @@ ipc.on('process.exit', function(pid, rid, code) {
|
|||
process.exit(code);
|
||||
});
|
||||
|
||||
ipc.on('eval', function(ev, pid, rid, script) {
|
||||
ipc.on('eval', function(ev, script) {
|
||||
ev.returnValue = eval(script);
|
||||
});
|
||||
|
||||
ipc.on('echo', function(ev, pid, rid, msg) {
|
||||
ipc.on('echo', function(ev, msg) {
|
||||
ev.returnValue = msg;
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue