mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-16 20:20:51 +01: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:
parent
202cdc4eb4
commit
e599cc1fab
2
cef.gyp
2
cef.gyp
@ -917,6 +917,8 @@
|
||||
'libcef/renderer/dom_node_impl.h',
|
||||
'libcef/renderer/frame_impl.cc',
|
||||
'libcef/renderer/frame_impl.h',
|
||||
'libcef/renderer/render_message_filter.cc',
|
||||
'libcef/renderer/render_message_filter.h',
|
||||
'libcef/renderer/render_process_observer.cc',
|
||||
'libcef/renderer/render_process_observer.h',
|
||||
'libcef/renderer/render_urlrequest_impl.cc',
|
||||
|
@ -100,6 +100,17 @@ typedef struct _cef_render_process_handler_t {
|
||||
struct _cef_browser_t* browser, struct _cef_frame_t* frame,
|
||||
struct _cef_v8context_t* context);
|
||||
|
||||
///
|
||||
// Called for global uncaught exceptions. Execution of this callback is
|
||||
// disabled by default. To enable set
|
||||
// CefSettings.uncaught_exception_stack_size > 0.
|
||||
///
|
||||
void (CEF_CALLBACK *on_uncaught_exception)(
|
||||
struct _cef_render_process_handler_t* self,
|
||||
struct _cef_browser_t* browser, struct _cef_frame_t* frame,
|
||||
struct _cef_v8context_t* context, struct _cef_v8exception_t* exception,
|
||||
struct _cef_v8stack_trace_t* stackTrace);
|
||||
|
||||
///
|
||||
// Called when a new node in the the browser gets focus. The |node| value may
|
||||
// be NULL if no specific node has gained focus. The node object passed to
|
||||
|
@ -95,6 +95,18 @@ class CefRenderProcessHandler : public virtual CefBase {
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context) {}
|
||||
|
||||
///
|
||||
// Called for global uncaught exceptions. Execution of this callback is
|
||||
// disabled by default. To enable set
|
||||
// CefSettings.uncaught_exception_stack_size > 0.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual void OnUncaughtException(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context,
|
||||
CefRefPtr<CefV8Exception> exception,
|
||||
CefRefPtr<CefV8StackTrace> stackTrace) {}
|
||||
|
||||
///
|
||||
// Called when a new node in the the browser gets focus. The |node| value may
|
||||
// be empty if no specific node has gained focus. The node object passed to
|
||||
|
@ -253,6 +253,14 @@ typedef struct _cef_settings_t {
|
||||
///
|
||||
int remote_debugging_port;
|
||||
|
||||
///
|
||||
// The number of stack trace frames to capture for uncaught exceptions.
|
||||
// Specify a positive value to enable the CefV8ContextHandler::
|
||||
// OnUncaughtException() callback. Specify 0 (default value) and
|
||||
// OnUncaughtException() will not be called.
|
||||
///
|
||||
int uncaught_exception_stack_size;
|
||||
|
||||
///
|
||||
// By default CEF V8 references will be invalidated (the IsValid() method will
|
||||
// return false) after the owning context has been released. This reduces the
|
||||
@ -757,28 +765,28 @@ enum cef_urlrequest_flags_t {
|
||||
// Default behavior.
|
||||
///
|
||||
UR_FLAG_NONE = 0,
|
||||
|
||||
|
||||
///
|
||||
// If set the cache will be skipped when handling the request.
|
||||
///
|
||||
UR_FLAG_SKIP_CACHE = 1 << 0,
|
||||
|
||||
|
||||
///
|
||||
// If set user name, password, and cookies may be sent with the request.
|
||||
///
|
||||
UR_FLAG_ALLOW_CACHED_CREDENTIALS = 1 << 1,
|
||||
|
||||
|
||||
///
|
||||
// If set cookies may be sent with the request and saved from the response.
|
||||
// UR_FLAG_ALLOW_CACHED_CREDENTIALS must also be set.
|
||||
///
|
||||
UR_FLAG_ALLOW_COOKIES = 1 << 2,
|
||||
|
||||
|
||||
///
|
||||
// If set upload progress events will be generated when a request has a body.
|
||||
///
|
||||
UR_FLAG_REPORT_UPLOAD_PROGRESS = 1 << 3,
|
||||
|
||||
|
||||
///
|
||||
// If set load timing info will be collected for the request.
|
||||
///
|
||||
@ -810,23 +818,23 @@ enum cef_urlrequest_status_t {
|
||||
// Unknown status.
|
||||
///
|
||||
UR_UNKNOWN = 0,
|
||||
|
||||
|
||||
///
|
||||
// Request succeeded.
|
||||
///
|
||||
UR_SUCCESS,
|
||||
|
||||
|
||||
///
|
||||
// An IO request is pending, and the caller will be informed when it is
|
||||
// completed.
|
||||
///
|
||||
UR_IO_PENDING,
|
||||
|
||||
|
||||
///
|
||||
// Request was canceled programatically.
|
||||
///
|
||||
UR_CANCELED,
|
||||
|
||||
|
||||
///
|
||||
// Request failed for some reason.
|
||||
///
|
||||
@ -1121,7 +1129,7 @@ typedef struct _cef_key_event_t {
|
||||
// The type of keyboard event.
|
||||
///
|
||||
cef_key_event_type_t type;
|
||||
|
||||
|
||||
///
|
||||
// Bit flags describing any pressed modifier keys. See
|
||||
// cef_key_event_modifiers_t for values.
|
||||
|
@ -300,6 +300,7 @@ struct CefSettingsTraits {
|
||||
&target->locales_dir_path, copy);
|
||||
target->pack_loading_disabled = src->pack_loading_disabled;
|
||||
target->remote_debugging_port = src->remote_debugging_port;
|
||||
target->uncaught_exception_stack_size = src->uncaught_exception_stack_size;
|
||||
target->context_safety_implementation = src->context_safety_implementation;
|
||||
}
|
||||
};
|
||||
|
@ -279,6 +279,7 @@ void CefContentBrowserClient::AppendExtraCommandLineSwitches(
|
||||
static const char* const kSwitchNames[] = {
|
||||
switches::kContextSafetyImplementation,
|
||||
switches::kProductVersion,
|
||||
switches::kUncaughtExceptionStackSize,
|
||||
};
|
||||
command_line->CopySwitchesFrom(browser_cmd, kSwitchNames,
|
||||
arraysize(kSwitchNames));
|
||||
|
@ -30,6 +30,9 @@ const char kLocalesDirPath[] = "locales-dir-path";
|
||||
// Path to locales directory.
|
||||
const char kPackLoadingDisabled[] = "pack-loading-disabled";
|
||||
|
||||
// Stack size for uncaught exceptions.
|
||||
const char kUncaughtExceptionStackSize[] = "uncaught-exception-stack-size";
|
||||
|
||||
// Context safety implementation type.
|
||||
const char kContextSafetyImplementation[] = "context-safety-implementation";
|
||||
|
||||
|
@ -22,6 +22,7 @@ extern const char kLogSeverity_Disable[];
|
||||
extern const char kResourcesDirPath[];
|
||||
extern const char kLocalesDirPath[];
|
||||
extern const char kPackLoadingDisabled[];
|
||||
extern const char kUncaughtExceptionStackSize[];
|
||||
extern const char kContextSafetyImplementation[];
|
||||
|
||||
} // namespace switches
|
||||
|
@ -252,6 +252,11 @@ bool CefMainDelegate::BasicStartupComplete(int* exit_code) {
|
||||
base::IntToString(settings.remote_debugging_port));
|
||||
}
|
||||
|
||||
if (settings.uncaught_exception_stack_size > 0) {
|
||||
command_line->AppendSwitchASCII(switches::kUncaughtExceptionStackSize,
|
||||
base::IntToString(settings.uncaught_exception_stack_size));
|
||||
}
|
||||
|
||||
if (settings.context_safety_implementation != 0) {
|
||||
command_line->AppendSwitchASCII(switches::kContextSafetyImplementation,
|
||||
base::IntToString(settings.context_safety_implementation));
|
||||
|
@ -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_
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include "libcef_dll/ctocpp/frame_ctocpp.h"
|
||||
#include "libcef_dll/ctocpp/process_message_ctocpp.h"
|
||||
#include "libcef_dll/ctocpp/v8context_ctocpp.h"
|
||||
#include "libcef_dll/ctocpp/v8exception_ctocpp.h"
|
||||
#include "libcef_dll/ctocpp/v8stack_trace_ctocpp.h"
|
||||
|
||||
|
||||
// MEMBER FUNCTIONS - Body may be edited by hand.
|
||||
@ -134,6 +136,46 @@ void CEF_CALLBACK render_process_handler_on_context_released(
|
||||
CefV8ContextCToCpp::Wrap(context));
|
||||
}
|
||||
|
||||
void CEF_CALLBACK render_process_handler_on_uncaught_exception(
|
||||
struct _cef_render_process_handler_t* self, cef_browser_t* browser,
|
||||
cef_frame_t* frame, struct _cef_v8context_t* context,
|
||||
struct _cef_v8exception_t* exception,
|
||||
struct _cef_v8stack_trace_t* stackTrace) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return;
|
||||
// Verify param: browser; type: refptr_diff
|
||||
DCHECK(browser);
|
||||
if (!browser)
|
||||
return;
|
||||
// Verify param: frame; type: refptr_diff
|
||||
DCHECK(frame);
|
||||
if (!frame)
|
||||
return;
|
||||
// Verify param: context; type: refptr_diff
|
||||
DCHECK(context);
|
||||
if (!context)
|
||||
return;
|
||||
// Verify param: exception; type: refptr_diff
|
||||
DCHECK(exception);
|
||||
if (!exception)
|
||||
return;
|
||||
// Verify param: stackTrace; type: refptr_diff
|
||||
DCHECK(stackTrace);
|
||||
if (!stackTrace)
|
||||
return;
|
||||
|
||||
// Execute
|
||||
CefRenderProcessHandlerCppToC::Get(self)->OnUncaughtException(
|
||||
CefBrowserCToCpp::Wrap(browser),
|
||||
CefFrameCToCpp::Wrap(frame),
|
||||
CefV8ContextCToCpp::Wrap(context),
|
||||
CefV8ExceptionCToCpp::Wrap(exception),
|
||||
CefV8StackTraceCToCpp::Wrap(stackTrace));
|
||||
}
|
||||
|
||||
void CEF_CALLBACK render_process_handler_on_focused_node_changed(
|
||||
struct _cef_render_process_handler_t* self, cef_browser_t* browser,
|
||||
cef_frame_t* frame, cef_domnode_t* node) {
|
||||
@ -202,6 +244,8 @@ CefRenderProcessHandlerCppToC::CefRenderProcessHandlerCppToC(
|
||||
render_process_handler_on_context_created;
|
||||
struct_.struct_.on_context_released =
|
||||
render_process_handler_on_context_released;
|
||||
struct_.struct_.on_uncaught_exception =
|
||||
render_process_handler_on_uncaught_exception;
|
||||
struct_.struct_.on_focused_node_changed =
|
||||
render_process_handler_on_focused_node_changed;
|
||||
struct_.struct_.on_process_message_received =
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "libcef_dll/cpptoc/frame_cpptoc.h"
|
||||
#include "libcef_dll/cpptoc/process_message_cpptoc.h"
|
||||
#include "libcef_dll/cpptoc/v8context_cpptoc.h"
|
||||
#include "libcef_dll/cpptoc/v8exception_cpptoc.h"
|
||||
#include "libcef_dll/cpptoc/v8stack_trace_cpptoc.h"
|
||||
#include "libcef_dll/ctocpp/render_process_handler_ctocpp.h"
|
||||
|
||||
|
||||
@ -130,6 +132,45 @@ void CefRenderProcessHandlerCToCpp::OnContextReleased(
|
||||
CefV8ContextCppToC::Wrap(context));
|
||||
}
|
||||
|
||||
void CefRenderProcessHandlerCToCpp::OnUncaughtException(
|
||||
CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context, CefRefPtr<CefV8Exception> exception,
|
||||
CefRefPtr<CefV8StackTrace> stackTrace) {
|
||||
if (CEF_MEMBER_MISSING(struct_, on_uncaught_exception))
|
||||
return;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Verify param: browser; type: refptr_diff
|
||||
DCHECK(browser.get());
|
||||
if (!browser.get())
|
||||
return;
|
||||
// Verify param: frame; type: refptr_diff
|
||||
DCHECK(frame.get());
|
||||
if (!frame.get())
|
||||
return;
|
||||
// Verify param: context; type: refptr_diff
|
||||
DCHECK(context.get());
|
||||
if (!context.get())
|
||||
return;
|
||||
// Verify param: exception; type: refptr_diff
|
||||
DCHECK(exception.get());
|
||||
if (!exception.get())
|
||||
return;
|
||||
// Verify param: stackTrace; type: refptr_diff
|
||||
DCHECK(stackTrace.get());
|
||||
if (!stackTrace.get())
|
||||
return;
|
||||
|
||||
// Execute
|
||||
struct_->on_uncaught_exception(struct_,
|
||||
CefBrowserCppToC::Wrap(browser),
|
||||
CefFrameCppToC::Wrap(frame),
|
||||
CefV8ContextCppToC::Wrap(context),
|
||||
CefV8ExceptionCppToC::Wrap(exception),
|
||||
CefV8StackTraceCppToC::Wrap(stackTrace));
|
||||
}
|
||||
|
||||
void CefRenderProcessHandlerCToCpp::OnFocusedNodeChanged(
|
||||
CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefDOMNode> node) {
|
||||
|
@ -42,6 +42,10 @@ class CefRenderProcessHandlerCToCpp
|
||||
CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context) OVERRIDE;
|
||||
virtual void OnContextReleased(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context) OVERRIDE;
|
||||
virtual void OnUncaughtException(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context,
|
||||
CefRefPtr<CefV8Exception> exception,
|
||||
CefRefPtr<CefV8StackTrace> stackTrace) OVERRIDE;
|
||||
virtual void OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame, CefRefPtr<CefDOMNode> node) OVERRIDE;
|
||||
virtual bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
|
||||
|
@ -272,6 +272,13 @@ void ClientApp::OnWebKitInitialized() {
|
||||
(*it)->OnWebKitInitialized(this);
|
||||
}
|
||||
|
||||
void ClientApp::OnBrowserDestroyed(CefRefPtr<CefBrowser> browser) {
|
||||
// Execute delegate callbacks.
|
||||
RenderDelegateSet::iterator it = render_delegates_.begin();
|
||||
for (; it != render_delegates_.end(); ++it)
|
||||
(*it)->OnBrowserDestroyed(this, browser);
|
||||
}
|
||||
|
||||
void ClientApp::OnContextCreated(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context) {
|
||||
@ -302,6 +309,19 @@ void ClientApp::OnContextReleased(CefRefPtr<CefBrowser> browser,
|
||||
}
|
||||
}
|
||||
|
||||
void ClientApp::OnUncaughtException(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context,
|
||||
CefRefPtr<CefV8Exception> exception,
|
||||
CefRefPtr<CefV8StackTrace> stackTrace) {
|
||||
// Execute delegate callbacks.
|
||||
RenderDelegateSet::iterator it = render_delegates_.begin();
|
||||
for (; it != render_delegates_.end(); ++it) {
|
||||
(*it)->OnUncaughtException(this, browser, frame, context, exception,
|
||||
stackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientApp::OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefDOMNode> node) {
|
||||
|
@ -28,8 +28,9 @@ class ClientApp : public CefApp,
|
||||
virtual void OnContextInitialized(CefRefPtr<ClientApp> app) {
|
||||
}
|
||||
|
||||
// Called on the browser process IO thread before a child process is launched.
|
||||
// Provides an opportunity to modify the child process command line.
|
||||
// Called on the browser process IO thread before a child process is
|
||||
// launched Provides an opportunity to modify the child process command
|
||||
// line.
|
||||
virtual void OnBeforeChildProcessLaunch(
|
||||
CefRefPtr<ClientApp> app,
|
||||
CefRefPtr<CefCommandLine> command_line) {
|
||||
@ -51,6 +52,11 @@ class ClientApp : public CefApp,
|
||||
virtual void OnWebKitInitialized(CefRefPtr<ClientApp> app) {
|
||||
}
|
||||
|
||||
// Called before a browser is destroyed.
|
||||
virtual void OnBrowserDestroyed(CefRefPtr<ClientApp> app,
|
||||
CefRefPtr<CefBrowser> browser) {
|
||||
}
|
||||
|
||||
// Called when a V8 context is created. Used to create V8 window bindings
|
||||
// and set message callbacks. RenderDelegates should check for unique URLs
|
||||
// to avoid interfering with each other.
|
||||
@ -69,6 +75,16 @@ class ClientApp : public CefApp,
|
||||
CefRefPtr<CefV8Context> context) {
|
||||
}
|
||||
|
||||
// Global V8 exception handler, disabled by default, to enable set
|
||||
// CefSettings.uncaught_exception_stack_size > 0.
|
||||
virtual void OnUncaughtException(CefRefPtr<ClientApp> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context,
|
||||
CefRefPtr<CefV8Exception> exception,
|
||||
CefRefPtr<CefV8StackTrace> stackTrace) {
|
||||
}
|
||||
|
||||
// Called when the focused node in a frame has changed.
|
||||
virtual void OnFocusedNodeChanged(CefRefPtr<ClientApp> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
@ -152,12 +168,19 @@ class ClientApp : public CefApp,
|
||||
// CefRenderProcessHandler methods.
|
||||
virtual void OnRenderThreadCreated() OVERRIDE;
|
||||
virtual void OnWebKitInitialized() OVERRIDE;
|
||||
virtual void OnBrowserDestroyed(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
virtual void OnContextCreated(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context) OVERRIDE;
|
||||
virtual void OnContextReleased(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context) OVERRIDE;
|
||||
virtual void OnUncaughtException(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context,
|
||||
CefRefPtr<CefV8Exception> exception,
|
||||
CefRefPtr<CefV8StackTrace> stackTrace)
|
||||
OVERRIDE;
|
||||
virtual void OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefDOMNode> node) OVERRIDE;
|
||||
|
@ -58,6 +58,10 @@ void CefTestSuite::GetSettings(CefSettings& settings) {
|
||||
if (!other_javascript_flags.empty())
|
||||
javascript_flags += " " + other_javascript_flags;
|
||||
CefString(&settings.javascript_flags) = javascript_flags;
|
||||
|
||||
// Necessary for V8Test.OnUncaughtException tests.
|
||||
settings.uncaught_exception_stack_size = 10;
|
||||
settings.remote_debugging_port = 12345;
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -25,8 +25,12 @@ const char kV8BindingTestUrl[] = "http://tests/V8Test.BindingTest";
|
||||
const char kV8ContextParentTestUrl[] = "http://tests/V8Test.ContextParentTest";
|
||||
const char kV8ContextChildTestUrl[] = "http://tests/V8Test.ContextChildTest";
|
||||
const char kV8NavTestUrl[] = "http://tests/V8Test.NavTest";
|
||||
const char kV8OnUncaughtExceptionTestUrl[] =
|
||||
"http://tests/V8Test.OnUncaughtException";
|
||||
const char kV8TestMsg[] = "V8Test.Test";
|
||||
const char kV8TestCmdArg[] = "v8-test";
|
||||
const char kV8DevToolsURLMsg[] = "V8Test.DevToolsURL";
|
||||
const char kV8DevToolsLoadHookMsg[] = "V8Test.DevToolsLoadHook";
|
||||
|
||||
enum V8TestMode {
|
||||
V8TEST_NONE = 0,
|
||||
@ -65,6 +69,8 @@ enum V8TestMode {
|
||||
V8TEST_BINDING,
|
||||
V8TEST_STACK_TRACE,
|
||||
V8TEST_EXTENSION,
|
||||
V8TEST_ON_UNCAUGHT_EXCEPTION,
|
||||
V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS,
|
||||
};
|
||||
|
||||
// Set to the current test being run in the browser process. Will always be
|
||||
@ -97,7 +103,8 @@ class V8BrowserTest : public ClientApp::BrowserDelegate {
|
||||
class V8RendererTest : public ClientApp::RenderDelegate {
|
||||
public:
|
||||
V8RendererTest()
|
||||
: test_mode_(V8TEST_NONE) {
|
||||
: test_mode_(V8TEST_NONE),
|
||||
devtools_url_("") {
|
||||
}
|
||||
|
||||
// Run a test when the process message is received from the browser.
|
||||
@ -206,6 +213,12 @@ class V8RendererTest : public ClientApp::RenderDelegate {
|
||||
case V8TEST_STACK_TRACE:
|
||||
RunStackTraceTest();
|
||||
break;
|
||||
case V8TEST_ON_UNCAUGHT_EXCEPTION:
|
||||
RunOnUncaughtExceptionTest();
|
||||
break;
|
||||
case V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS:
|
||||
RunOnUncaughtExceptionDevToolsTest();
|
||||
break;
|
||||
default:
|
||||
// Was a startup test.
|
||||
EXPECT_TRUE(startup_test_success_);
|
||||
@ -1558,6 +1571,49 @@ class V8RendererTest : public ClientApp::RenderDelegate {
|
||||
DestroyTest();
|
||||
}
|
||||
|
||||
void RunOnUncaughtExceptionTest() {
|
||||
test_context_ =
|
||||
browser_->GetMainFrame()->GetV8Context();
|
||||
browser_->GetMainFrame()->ExecuteJavaScript(
|
||||
"window.setTimeout(test, 0)", "about:blank", 0);
|
||||
}
|
||||
|
||||
void RunOnUncaughtExceptionDevToolsTest() {
|
||||
EXPECT_FALSE(browser_->IsPopup());
|
||||
test_context_ =
|
||||
browser_->GetMainFrame()->GetV8Context();
|
||||
// Show DevTools.
|
||||
EXPECT_FALSE(devtools_url_.empty());
|
||||
browser_->GetMainFrame()->ExecuteJavaScript(
|
||||
"window.open('" + devtools_url_ + "');", "about:blank", 0);
|
||||
}
|
||||
|
||||
void OnUncaughtException(CefRefPtr<ClientApp> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context,
|
||||
CefRefPtr<CefV8Exception> exception,
|
||||
CefRefPtr<CefV8StackTrace> stackTrace) OVERRIDE {
|
||||
if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION ||
|
||||
test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
|
||||
EXPECT_TRUE(test_context_->IsSame(context));
|
||||
EXPECT_STREQ("Uncaught ReferenceError: asd is not defined",
|
||||
exception->GetMessage().ToString().c_str());
|
||||
std::ostringstream stackFormatted;
|
||||
for (int i = 0; i < stackTrace->GetFrameCount(); ++i) {
|
||||
stackFormatted << "at "
|
||||
<< stackTrace->GetFrame(i)->GetFunctionName().ToString()
|
||||
<< "() in " << stackTrace->GetFrame(i)->GetScriptName().ToString()
|
||||
<< " on line " << stackTrace->GetFrame(i)->GetLineNumber() << "\n";
|
||||
}
|
||||
const char* stackFormattedShouldBe =
|
||||
"at test2() in http://tests/V8Test.OnUncaughtException on line 3\n"
|
||||
"at test() in http://tests/V8Test.OnUncaughtException on line 2\n";
|
||||
EXPECT_STREQ(stackFormattedShouldBe, stackFormatted.str().c_str());
|
||||
DestroyTest();
|
||||
}
|
||||
}
|
||||
|
||||
// Test execution of a native function when the extension is loaded.
|
||||
void RunExtensionTest() {
|
||||
std::string code = "native function v8_extension_test();"
|
||||
@ -1606,6 +1662,16 @@ class V8RendererTest : public ClientApp::RenderDelegate {
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context) OVERRIDE {
|
||||
if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
|
||||
if (browser_.get() == NULL) {
|
||||
app_ = app;
|
||||
browser_ = browser;
|
||||
}
|
||||
// The test is run from OnProcessMessageReceived(), after the message
|
||||
// and the devtools url has been received from OnLoadEnd().
|
||||
return;
|
||||
}
|
||||
|
||||
app_ = app;
|
||||
browser_ = browser;
|
||||
|
||||
@ -1686,6 +1752,119 @@ class V8RendererTest : public ClientApp::RenderDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnBrowserDestroyed(CefRefPtr<ClientApp> app,
|
||||
CefRefPtr<CefBrowser> browser) OVERRIDE {
|
||||
if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
|
||||
if (browser->IsPopup()) {
|
||||
// After window destruction there is still a call to
|
||||
// ScriptController::setCaptureCallStackForUncaughtExceptions(0),
|
||||
// for which we have to wait.
|
||||
CefPostDelayedTask(TID_RENDERER, NewCefRunnableMethod(
|
||||
this, &V8RendererTest::DevToolsClosed), 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool OnProcessMessageReceived(CefRefPtr<ClientApp> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefProcessId source_process,
|
||||
CefRefPtr<CefProcessMessage> message)
|
||||
OVERRIDE {
|
||||
if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
|
||||
EXPECT_TRUE(browser.get());
|
||||
EXPECT_EQ(PID_BROWSER, source_process);
|
||||
EXPECT_TRUE(message.get());
|
||||
EXPECT_TRUE(message->IsReadOnly());
|
||||
|
||||
if (message->GetName() == kV8DevToolsURLMsg) {
|
||||
EXPECT_FALSE(browser->IsPopup());
|
||||
devtools_url_ = message->GetArgumentList()->GetString(0);
|
||||
EXPECT_FALSE(devtools_url_.empty());
|
||||
if (!TestFailed()) {
|
||||
CefPostTask(TID_RENDERER,
|
||||
NewCefRunnableMethod(this, &V8RendererTest::RunTest));
|
||||
}
|
||||
} else if (message->GetName() == kV8DevToolsLoadHookMsg) {
|
||||
EXPECT_TRUE(browser->IsPopup());
|
||||
DevToolsLoadHook(browser);
|
||||
} else {
|
||||
EXPECT_TRUE(false) << "not reached";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DevToolsLoadHook(CefRefPtr<CefBrowser> browser) {
|
||||
EXPECT_TRUE(browser->IsPopup());
|
||||
CefRefPtr<CefV8Context> context = browser->GetMainFrame()->GetV8Context();
|
||||
static const char* kFuncName = "DevToolsLoaded";
|
||||
|
||||
class Handler : public CefV8Handler {
|
||||
public:
|
||||
Handler() {}
|
||||
virtual bool Execute(const CefString& name,
|
||||
CefRefPtr<CefV8Value> object,
|
||||
const CefV8ValueList& arguments,
|
||||
CefRefPtr<CefV8Value>& retval,
|
||||
CefString& exception) OVERRIDE {
|
||||
EXPECT_STREQ(kFuncName, name.ToString().c_str());
|
||||
if (name == kFuncName) {
|
||||
EXPECT_TRUE(exception.empty());
|
||||
retval = CefV8Value::CreateNull();
|
||||
EXPECT_TRUE(retval.get());
|
||||
renderer_test_->DevToolsLoaded(browser_);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
CefRefPtr<V8RendererTest> renderer_test_;
|
||||
CefRefPtr<CefBrowser> browser_;
|
||||
IMPLEMENT_REFCOUNTING(Handler);
|
||||
};
|
||||
|
||||
EXPECT_TRUE(context->Enter());
|
||||
Handler* handler = new Handler;
|
||||
handler->renderer_test_ = this;
|
||||
handler->browser_ = browser;
|
||||
CefRefPtr<CefV8Handler> handlerPtr(handler);
|
||||
CefRefPtr<CefV8Value> func =
|
||||
CefV8Value::CreateFunction(kFuncName, handler);
|
||||
EXPECT_TRUE(func.get());
|
||||
EXPECT_TRUE(context->GetGlobal()->SetValue(
|
||||
kFuncName, func, V8_PROPERTY_ATTRIBUTE_NONE));
|
||||
EXPECT_TRUE(context->Exit());
|
||||
|
||||
// Call DevToolsLoaded() when DevTools window completed loading.
|
||||
std::string jsCode = "(function(){"
|
||||
" var oldLoadCompleted = InspectorFrontendAPI.loadCompleted;"
|
||||
" InspectorFrontendAPI.loadCompleted = function(){"
|
||||
" oldLoadCompleted.call(InspectorFrontendAPI);"
|
||||
" console.log('InspectorFrontendAPI.loadCompleted event fired');"
|
||||
" window.DevToolsLoaded();"
|
||||
" };"
|
||||
"})();";
|
||||
|
||||
CefRefPtr<CefV8Value> retval;
|
||||
CefRefPtr<CefV8Exception> exception;
|
||||
EXPECT_TRUE(context->Eval(CefString(jsCode), retval, exception));
|
||||
}
|
||||
|
||||
void DevToolsLoaded(CefRefPtr<CefBrowser> browser) {
|
||||
EXPECT_TRUE(browser->IsPopup());
|
||||
EXPECT_NE(browser->GetIdentifier(), browser_->GetIdentifier());
|
||||
CefRefPtr<CefV8Value> retval;
|
||||
CefRefPtr<CefV8Exception> exception;
|
||||
EXPECT_TRUE(browser->GetMainFrame()->GetV8Context()->Eval(
|
||||
"window.close()", retval, exception));
|
||||
}
|
||||
|
||||
void DevToolsClosed() {
|
||||
browser_->GetMainFrame()->ExecuteJavaScript(
|
||||
"window.setTimeout(test, 0);", "about:blank", 0);
|
||||
}
|
||||
|
||||
protected:
|
||||
// Return from the test.
|
||||
void DestroyTest() {
|
||||
@ -1707,6 +1886,9 @@ class V8RendererTest : public ClientApp::RenderDelegate {
|
||||
|
||||
app_ = NULL;
|
||||
browser_ = NULL;
|
||||
test_context_ = NULL;
|
||||
test_object_ = NULL;
|
||||
devtools_url_ = "";
|
||||
}
|
||||
|
||||
// Return the V8 context.
|
||||
@ -1719,6 +1901,7 @@ class V8RendererTest : public ClientApp::RenderDelegate {
|
||||
CefRefPtr<ClientApp> app_;
|
||||
CefRefPtr<CefBrowser> browser_;
|
||||
V8TestMode test_mode_;
|
||||
std::string devtools_url_;
|
||||
|
||||
CefRefPtr<CefV8Context> test_context_;
|
||||
CefRefPtr<CefV8Value> test_object_;
|
||||
@ -1748,6 +1931,17 @@ class V8TestHandler : public TestHandler {
|
||||
"<script>var i = 0;</script>CHILD</body></html>",
|
||||
"text/html");
|
||||
CreateBrowser(kV8ContextParentTestUrl);
|
||||
} else if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION ||
|
||||
test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
|
||||
AddResource(kV8OnUncaughtExceptionTestUrl, "<html><body>"
|
||||
"<h1>OnUncaughtException</h1>"
|
||||
"<script>\n"
|
||||
"function test(){ test2(); }\n"
|
||||
"function test2(){ asd(); }\n"
|
||||
"</script>\n"
|
||||
"</body></html>\n",
|
||||
"text/html");
|
||||
CreateBrowser(kV8OnUncaughtExceptionTestUrl);
|
||||
} else {
|
||||
EXPECT_TRUE(test_url_ != NULL);
|
||||
AddResource(test_url_, "<html><body>"
|
||||
@ -1756,6 +1950,27 @@ class V8TestHandler : public TestHandler {
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int httpStatusCode) OVERRIDE {
|
||||
if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
|
||||
if (browser->IsPopup()) {
|
||||
EXPECT_STREQ(GetBrowser()->GetHost()->GetDevToolsURL(true).c_str(),
|
||||
frame->GetURL().c_str());
|
||||
CefRefPtr<CefProcessMessage> return_msg =
|
||||
CefProcessMessage::Create(kV8DevToolsLoadHookMsg);
|
||||
EXPECT_TRUE(browser->SendProcessMessage(PID_RENDERER, return_msg));
|
||||
} else {
|
||||
// Send the DevTools url message only for the main browser.
|
||||
CefRefPtr<CefProcessMessage> return_msg =
|
||||
CefProcessMessage::Create(kV8DevToolsURLMsg);
|
||||
EXPECT_TRUE(return_msg->GetArgumentList()->SetString(0,
|
||||
browser->GetHost()->GetDevToolsURL(true)));
|
||||
EXPECT_TRUE(browser->SendProcessMessage(PID_RENDERER, return_msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool OnProcessMessageReceived(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefProcessId source_process,
|
||||
@ -1849,4 +2064,6 @@ V8_TEST_EX(ContextEntered, V8TEST_CONTEXT_ENTERED, NULL);
|
||||
V8_TEST(ContextInvalid, V8TEST_CONTEXT_INVALID);
|
||||
V8_TEST_EX(Binding, V8TEST_BINDING, kV8BindingTestUrl);
|
||||
V8_TEST(StackTrace, V8TEST_STACK_TRACE);
|
||||
V8_TEST(OnUncaughtException, V8TEST_ON_UNCAUGHT_EXCEPTION);
|
||||
V8_TEST(OnUncaughtExceptionDevTools, V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS);
|
||||
V8_TEST(Extension, V8TEST_EXTENSION);
|
||||
|
Loading…
x
Reference in New Issue
Block a user