mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Add CefV8ContextHandler::OnUncaughtException callback (issue #736).
git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@890 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
@@ -17,6 +17,7 @@ MSVC_POP_WARNING();
|
||||
#include "libcef/common/content_client.h"
|
||||
#include "libcef/renderer/browser_impl.h"
|
||||
#include "libcef/renderer/chrome_bindings.h"
|
||||
#include "libcef/renderer/render_message_filter.h"
|
||||
#include "libcef/renderer/render_process_observer.h"
|
||||
#include "libcef/renderer/thread_util.h"
|
||||
#include "libcef/renderer/v8_impl.h"
|
||||
@@ -71,7 +72,9 @@ struct CefContentRendererClient::SchemeInfo {
|
||||
bool is_display_isolated;
|
||||
};
|
||||
|
||||
CefContentRendererClient::CefContentRendererClient() {
|
||||
CefContentRendererClient::CefContentRendererClient()
|
||||
: devtools_agent_count_(0),
|
||||
uncaught_exception_stack_size_(0) {
|
||||
}
|
||||
|
||||
CefContentRendererClient::~CefContentRendererClient() {
|
||||
@@ -148,12 +151,33 @@ void CefContentRendererClient::RegisterCustomSchemes() {
|
||||
}
|
||||
}
|
||||
|
||||
void CefContentRendererClient::DevToolsAgentAttached() {
|
||||
CEF_REQUIRE_RT();
|
||||
++devtools_agent_count_;
|
||||
}
|
||||
|
||||
void CefContentRendererClient::DevToolsAgentDetached() {
|
||||
CEF_REQUIRE_RT();
|
||||
--devtools_agent_count_;
|
||||
if (devtools_agent_count_ == 0 && uncaught_exception_stack_size_ > 0) {
|
||||
// When the last DevToolsAgent is detached the stack size is set to 0.
|
||||
// Restore the user-specified stack size here.
|
||||
v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
|
||||
uncaught_exception_stack_size_, v8::StackTrace::kDetailed);
|
||||
}
|
||||
}
|
||||
|
||||
void CefContentRendererClient::SetUncaughtExceptionStackSize(int stackSize) {
|
||||
uncaught_exception_stack_size_ = stackSize;
|
||||
}
|
||||
|
||||
void CefContentRendererClient::RenderThreadStarted() {
|
||||
render_loop_ = base::MessageLoopProxy::current();
|
||||
observer_.reset(new CefRenderProcessObserver());
|
||||
|
||||
content::RenderThread* thread = content::RenderThread::Get();
|
||||
thread->AddObserver(observer_.get());
|
||||
thread->GetChannel()->AddFilter(new CefRenderMessageFilter);
|
||||
|
||||
WebKit::WebPrerenderingSupport::initialize(new CefPrerenderingSupport());
|
||||
|
||||
|
@@ -48,6 +48,10 @@ class CefContentRendererClient : public content::ContentRendererClient {
|
||||
// Render thread message loop proxy.
|
||||
base::MessageLoopProxy* render_loop() const { return render_loop_.get(); }
|
||||
|
||||
void DevToolsAgentAttached();
|
||||
void DevToolsAgentDetached();
|
||||
void SetUncaughtExceptionStackSize(int stackSize);
|
||||
|
||||
private:
|
||||
// ContentRendererClient implementation.
|
||||
virtual void RenderThreadStarted() OVERRIDE;
|
||||
@@ -71,6 +75,9 @@ class CefContentRendererClient : public content::ContentRendererClient {
|
||||
struct SchemeInfo;
|
||||
typedef std::list<SchemeInfo> SchemeInfoList;
|
||||
SchemeInfoList scheme_info_list_;
|
||||
|
||||
int devtools_agent_count_;
|
||||
int uncaught_exception_stack_size_;
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_RENDERER_CONTENT_RENDERER_CLIENT_H_
|
||||
|
82
libcef/renderer/render_message_filter.cc
Normal file
82
libcef/renderer/render_message_filter.cc
Normal file
@@ -0,0 +1,82 @@
|
||||
/// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
||||
// Portions (c) 2011 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "libcef/renderer/render_message_filter.h"
|
||||
#include "libcef/renderer/thread_util.h"
|
||||
#include "libcef/common/cef_messages.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/message_loop.h"
|
||||
#include "content/common/devtools_messages.h"
|
||||
#include "googleurl/src/gurl.h"
|
||||
#include "googleurl/src/url_util.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityPolicy.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
|
||||
|
||||
CefRenderMessageFilter::CefRenderMessageFilter()
|
||||
: channel_(NULL) {
|
||||
}
|
||||
|
||||
CefRenderMessageFilter::~CefRenderMessageFilter() {
|
||||
}
|
||||
|
||||
void CefRenderMessageFilter::OnFilterAdded(IPC::Channel* channel) {
|
||||
channel_ = channel;
|
||||
}
|
||||
|
||||
void CefRenderMessageFilter::OnFilterRemoved() {
|
||||
}
|
||||
|
||||
bool CefRenderMessageFilter::OnMessageReceived(const IPC::Message& message) {
|
||||
bool handled = true;
|
||||
if (message.type() == DevToolsAgentMsg_Attach::ID ||
|
||||
message.type() == DevToolsAgentMsg_Reattach::ID ||
|
||||
message.type() == DevToolsAgentMsg_Detach::ID) {
|
||||
// Observe the DevTools messages but don't handle them.
|
||||
handled = false;
|
||||
}
|
||||
|
||||
IPC_BEGIN_MESSAGE_MAP(CefRenderMessageFilter, message)
|
||||
IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Attach, OnDevToolsAgentAttach)
|
||||
IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Reattach, OnDevToolsAgentReattach)
|
||||
IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Detach, OnDevToolsAgentDetach)
|
||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||
IPC_END_MESSAGE_MAP()
|
||||
return handled;
|
||||
}
|
||||
|
||||
void CefRenderMessageFilter::OnDevToolsAgentAttach() {
|
||||
CEF_POST_TASK_RT(
|
||||
base::Bind(&CefRenderMessageFilter::OnDevToolsAgentAttach_RT, this));
|
||||
}
|
||||
|
||||
void CefRenderMessageFilter::OnDevToolsAgentReattach(
|
||||
const std::string& agent_state) {
|
||||
// Treat reattach the same as attach.
|
||||
OnDevToolsAgentAttach();
|
||||
}
|
||||
|
||||
void CefRenderMessageFilter::OnDevToolsAgentDetach() {
|
||||
// CefContentRendererClient::DevToolsAgentDetached() needs to be called after
|
||||
// the IPC message has been handled by DevToolsAgent. A workaround for this is
|
||||
// to first post to the IO thread and then post to the renderer thread.
|
||||
MessageLoop::current()->PostTask(FROM_HERE,
|
||||
base::Bind(&CefRenderMessageFilter::OnDevToolsAgentDetach_IOT, this));
|
||||
}
|
||||
|
||||
void CefRenderMessageFilter::OnDevToolsAgentAttach_RT() {
|
||||
CEF_REQUIRE_RT();
|
||||
CefContentRendererClient::Get()->DevToolsAgentAttached();
|
||||
}
|
||||
|
||||
void CefRenderMessageFilter::OnDevToolsAgentDetach_IOT() {
|
||||
CEF_POST_TASK_RT(
|
||||
base::Bind(&CefRenderMessageFilter::OnDevToolsAgentDetach_RT, this));
|
||||
}
|
||||
|
||||
void CefRenderMessageFilter::OnDevToolsAgentDetach_RT() {
|
||||
CEF_REQUIRE_RT();
|
||||
CefContentRendererClient::Get()->DevToolsAgentDetached();
|
||||
}
|
39
libcef/renderer/render_message_filter.h
Normal file
39
libcef/renderer/render_message_filter.h
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
||||
// Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef CEF_LIBCEF_RENDERER_RENDER_MESSAGE_FILTER_H_
|
||||
#define CEF_LIBCEF_RENDERER_RENDER_MESSAGE_FILTER_H_
|
||||
|
||||
#include <string>
|
||||
#include "ipc/ipc_channel_proxy.h"
|
||||
|
||||
// This class sends and receives control messages on the renderer process.
|
||||
class CefRenderMessageFilter : public IPC::ChannelProxy::MessageFilter {
|
||||
public:
|
||||
CefRenderMessageFilter();
|
||||
virtual ~CefRenderMessageFilter();
|
||||
|
||||
// IPC::ChannelProxy::MessageFilter implementation.
|
||||
virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE;
|
||||
virtual void OnFilterRemoved() OVERRIDE;
|
||||
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
|
||||
|
||||
private:
|
||||
// Message handlers called on the IO thread.
|
||||
void OnDevToolsAgentAttach();
|
||||
void OnDevToolsAgentReattach(const std::string& agent_state);
|
||||
void OnDevToolsAgentDetach();
|
||||
|
||||
void OnDevToolsAgentAttach_RT();
|
||||
void OnDevToolsAgentDetach_IOT();
|
||||
void OnDevToolsAgentDetach_RT();
|
||||
|
||||
IPC::Channel* channel_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CefRenderMessageFilter);
|
||||
};
|
||||
|
||||
|
||||
#endif // CEF_LIBCEF_RENDERER_RENDER_MESSAGE_FILTER_H_
|
@@ -5,11 +5,15 @@
|
||||
|
||||
#include "libcef/renderer/render_process_observer.h"
|
||||
#include "libcef/common/cef_messages.h"
|
||||
#include "libcef/common/cef_switches.h"
|
||||
#include "libcef/common/command_line_impl.h"
|
||||
#include "libcef/common/content_client.h"
|
||||
#include "libcef/renderer/content_renderer_client.h"
|
||||
#include "libcef/renderer/v8_impl.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/path_service.h"
|
||||
#include "base/string_number_conversions.h"
|
||||
#include "googleurl/src/gurl.h"
|
||||
#include "googleurl/src/url_util.h"
|
||||
#include "media/base/media.h"
|
||||
@@ -53,6 +57,23 @@ void CefRenderProcessObserver::WebKitInitialized() {
|
||||
// Register any custom schemes with WebKit.
|
||||
CefContentRendererClient::Get()->RegisterCustomSchemes();
|
||||
|
||||
// The number of stack trace frames to capture for uncaught exceptions.
|
||||
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
|
||||
if (command_line.HasSwitch(switches::kUncaughtExceptionStackSize)) {
|
||||
int uncaught_exception_stack_size = 0;
|
||||
base::StringToInt(
|
||||
command_line.GetSwitchValueASCII(switches::kUncaughtExceptionStackSize),
|
||||
&uncaught_exception_stack_size);
|
||||
|
||||
if (uncaught_exception_stack_size > 0) {
|
||||
CefContentRendererClient::Get()->SetUncaughtExceptionStackSize(
|
||||
uncaught_exception_stack_size);
|
||||
v8::V8::AddMessageListener(&CefV8MessageHandler);
|
||||
v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
|
||||
uncaught_exception_stack_size, v8::StackTrace::kDetailed);
|
||||
}
|
||||
}
|
||||
|
||||
// Notify the render process handler.
|
||||
CefRefPtr<CefApp> application = CefContentClient::Get()->application();
|
||||
if (application.get()) {
|
||||
|
@@ -21,6 +21,7 @@ MSVC_POP_WARNING();
|
||||
#include "libcef/renderer/v8_impl.h"
|
||||
|
||||
#include "libcef/common/cef_switches.h"
|
||||
#include "libcef/common/content_client.h"
|
||||
#include "libcef/common/tracker.h"
|
||||
#include "libcef/renderer/browser_impl.h"
|
||||
#include "libcef/renderer/thread_util.h"
|
||||
@@ -1665,3 +1666,28 @@ bool CefV8StackFrameImpl::IsConstructor() {
|
||||
v8::HandleScope handle_scope;
|
||||
return GetHandle()->IsConstructor();
|
||||
}
|
||||
|
||||
void CefV8MessageHandler(v8::Handle<v8::Message> message,
|
||||
v8::Handle<v8::Value> data) {
|
||||
CEF_REQUIRE_RT_RETURN(void());
|
||||
|
||||
CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
|
||||
CefRefPtr<CefBrowser> browser = context->GetBrowser();
|
||||
CefRefPtr<CefFrame> frame = context->GetFrame();
|
||||
|
||||
v8::Handle<v8::StackTrace> v8Stack = message->GetStackTrace();
|
||||
DCHECK(!v8Stack.IsEmpty());
|
||||
CefRefPtr<CefV8StackTrace> stackTrace = new CefV8StackTraceImpl(v8Stack);
|
||||
|
||||
CefRefPtr<CefApp> application = CefContentClient::Get()->application();
|
||||
if (!application.get())
|
||||
return;
|
||||
|
||||
CefRefPtr<CefRenderProcessHandler> handler =
|
||||
application->GetRenderProcessHandler();
|
||||
if (!handler.get())
|
||||
return;
|
||||
|
||||
CefRefPtr<CefV8Exception> exception = new CefV8ExceptionImpl(message);
|
||||
handler->OnUncaughtException(browser, frame, context, exception, stackTrace);
|
||||
}
|
||||
|
@@ -293,4 +293,7 @@ class CefV8StackFrameImpl : public CefV8StackFrame {
|
||||
DISALLOW_COPY_AND_ASSIGN(CefV8StackFrameImpl);
|
||||
};
|
||||
|
||||
void CefV8MessageHandler(v8::Handle<v8::Message> message,
|
||||
v8::Handle<v8::Value> data);
|
||||
|
||||
#endif // CEF_LIBCEF_RENDERER_V8_IMPL_H_
|
||||
|
Reference in New Issue
Block a user