[inspector] added inspector test runner [part 2]

- added the channel implementation,
- added inspector implementation,
- added v8::Extension for communication between backend and frontend.

BUG=chromium:635948
R=dgozman@chromium.org,alph@chromium.org

Committed: https://crrev.com/cceaa1225c6a96a28d2c7410d1db520423fb8c31
Review-Url: https://codereview.chromium.org/2368393003
Cr-Original-Commit-Position: refs/heads/master@{#39888}
Cr-Commit-Position: refs/heads/master@{#39928}
This commit is contained in:
kozyatinskiy 2016-10-02 09:45:33 -07:00 committed by Commit bot
parent fad5dd827d
commit 751814a128
4 changed files with 232 additions and 0 deletions

View File

@ -8,6 +8,8 @@ v8_executable("inspector-test") {
testonly = true
sources = [
"inspector-impl.cc",
"inspector-impl.h",
"task-runner.cc",
"task-runner.h",
]

View File

@ -0,0 +1,152 @@
// Copyright 2016 the V8 project 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 "test/inspector/inspector-impl.h"
#include "include/v8.h"
#include "src/inspector/string-16.h"
namespace {
const int kInspectorClientIndex = v8::Context::kDebugIdIndex + 1;
class ChannelImpl final : public v8_inspector::V8Inspector::Channel {
public:
explicit ChannelImpl(InspectorClientImpl::FrontendChannel* frontend_channel)
: frontend_channel_(frontend_channel) {}
virtual ~ChannelImpl() = default;
private:
void sendProtocolResponse(int callId,
const v8_inspector::StringView& message) override {
frontend_channel_->SendMessageToFrontend(message);
}
void sendProtocolNotification(
const v8_inspector::StringView& message) override {
frontend_channel_->SendMessageToFrontend(message);
}
void flushProtocolNotifications() override {}
InspectorClientImpl::FrontendChannel* frontend_channel_;
DISALLOW_COPY_AND_ASSIGN(ChannelImpl);
};
} // namespace
class ConnectTask : public TaskRunner::Task {
public:
ConnectTask(InspectorClientImpl* client, v8::base::Semaphore* ready_semaphore)
: client_(client), ready_semaphore_(ready_semaphore) {}
virtual ~ConnectTask() = default;
bool is_inspector_task() final { return true; }
void Run(v8::Isolate* isolate,
const v8::Global<v8::Context>& global_context) {
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = global_context.Get(isolate);
client_->connect(context);
if (ready_semaphore_) ready_semaphore_->Signal();
}
private:
InspectorClientImpl* client_;
v8::base::Semaphore* ready_semaphore_;
};
InspectorClientImpl::InspectorClientImpl(TaskRunner* task_runner,
FrontendChannel* frontend_channel,
v8::base::Semaphore* ready_semaphore)
: isolate_(nullptr),
task_runner_(task_runner),
frontend_channel_(frontend_channel) {
task_runner_->Append(new ConnectTask(this, ready_semaphore));
}
InspectorClientImpl::~InspectorClientImpl() {}
void InspectorClientImpl::connect(v8::Local<v8::Context> context) {
isolate_ = context->GetIsolate();
channel_.reset(new ChannelImpl(frontend_channel_));
inspector_ = v8_inspector::V8Inspector::create(isolate_, this);
session_ = inspector_->connect(1, channel_.get(), v8_inspector::StringView());
context->SetAlignedPointerInEmbedderData(kInspectorClientIndex, this);
inspector_->contextCreated(
v8_inspector::V8ContextInfo(context, 1, v8_inspector::StringView()));
context_.Reset(isolate_, context);
}
v8::Local<v8::Context> InspectorClientImpl::ensureDefaultContextInGroup(int) {
CHECK(isolate_);
return context_.Get(isolate_);
}
double InspectorClientImpl::currentTimeMS() {
return v8::base::OS::TimeCurrentMillis();
}
void InspectorClientImpl::runMessageLoopOnPause(int) {
task_runner_->RunMessageLoop(true);
}
void InspectorClientImpl::quitMessageLoopOnPause() {
task_runner_->QuitMessageLoop();
}
v8_inspector::V8InspectorSession* InspectorClientImpl::SessionFromContext(
v8::Local<v8::Context> context) {
InspectorClientImpl* inspector_client = static_cast<InspectorClientImpl*>(
context->GetAlignedPointerFromEmbedderData(kInspectorClientIndex));
CHECK(inspector_client);
return inspector_client->session_.get();
}
class SendMessageToBackendTask : public TaskRunner::Task {
public:
explicit SendMessageToBackendTask(const v8_inspector::String16& message)
: message_(message) {}
bool is_inspector_task() final { return true; }
void Run(v8::Isolate* isolate,
const v8::Global<v8::Context>& global_context) override {
v8_inspector::V8InspectorSession* session = nullptr;
{
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = global_context.Get(isolate);
session = InspectorClientImpl::SessionFromContext(context);
CHECK(session);
}
v8_inspector::StringView message_view(
reinterpret_cast<const uint16_t*>(message_.characters16()),
message_.length());
session->dispatchProtocolMessage(message_view);
}
private:
v8_inspector::String16 message_;
};
TaskRunner* SendMessageToBackendExtension::backend_task_runner_ = nullptr;
v8::Local<v8::FunctionTemplate>
SendMessageToBackendExtension::GetNativeFunctionTemplate(
v8::Isolate* isolate, v8::Local<v8::String> name) {
return v8::FunctionTemplate::New(
isolate, SendMessageToBackendExtension::SendMessageToBackend);
}
void SendMessageToBackendExtension::SendMessageToBackend(
const v8::FunctionCallbackInfo<v8::Value>& args) {
CHECK(backend_task_runner_);
CHECK(args.Length() == 1 && args[0]->IsString());
v8::Local<v8::String> message = args[0].As<v8::String>();
std::unique_ptr<uint16_t[]> buffer(new uint16_t[message->Length()]);
message.As<v8::String>()->Write(reinterpret_cast<uint16_t*>(buffer.get()), 0,
message->Length());
v8_inspector::String16 message_string(buffer.get(), message->Length());
backend_task_runner_->Append(new SendMessageToBackendTask(message_string));
}

View File

@ -0,0 +1,76 @@
// Copyright 2016 the V8 project 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 V8_TEST_INSPECTOR_PROTOCOL_INSPECTOR_IMPL_H_
#define V8_TEST_INSPECTOR_PROTOCOL_INSPECTOR_IMPL_H_
#include "include/v8-inspector.h"
#include "include/v8.h"
#include "src/base/macros.h"
#include "src/base/platform/platform.h"
#include "test/inspector/task-runner.h"
class InspectorClientImpl : public v8_inspector::V8InspectorClient {
public:
class FrontendChannel {
public:
virtual ~FrontendChannel() = default;
virtual void SendMessageToFrontend(
const v8_inspector::StringView& message) = 0;
};
InspectorClientImpl(TaskRunner* task_runner,
FrontendChannel* frontend_channel,
v8::base::Semaphore* ready_semaphore);
virtual ~InspectorClientImpl();
private:
// V8InspectorClient implementation.
v8::Local<v8::Context> ensureDefaultContextInGroup(
int context_group_id) override;
double currentTimeMS() override;
void runMessageLoopOnPause(int context_group_id) override;
void quitMessageLoopOnPause() override;
static v8_inspector::V8InspectorSession* SessionFromContext(
v8::Local<v8::Context> context);
friend class SendMessageToBackendTask;
friend class ConnectTask;
void connect(v8::Local<v8::Context> context);
std::unique_ptr<v8_inspector::V8Inspector> inspector_;
std::unique_ptr<v8_inspector::V8InspectorSession> session_;
std::unique_ptr<v8_inspector::V8Inspector::Channel> channel_;
v8::Isolate* isolate_;
v8::Global<v8::Context> context_;
TaskRunner* task_runner_;
FrontendChannel* frontend_channel_;
DISALLOW_COPY_AND_ASSIGN(InspectorClientImpl);
};
class SendMessageToBackendExtension : public v8::Extension {
public:
SendMessageToBackendExtension()
: v8::Extension("v8_inspector/frontend",
"native function sendMessageToBackend();") {}
virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
v8::Isolate* isolate, v8::Local<v8::String> name);
static void set_backend_task_runner(TaskRunner* task_runner) {
backend_task_runner_ = task_runner;
}
private:
static void SendMessageToBackend(
const v8::FunctionCallbackInfo<v8::Value>& args);
static TaskRunner* backend_task_runner_;
};
#endif // V8_TEST_INSPECTOR_PROTOCOL_INSPECTOR_IMPL_H_

View File

@ -6,6 +6,8 @@
'variables': {
'v8_code': 1,
'inspector_protocol_sources': [
'inspector-impl.cc',
'inspector-impl.h',
'task-runner.cc',
'task-runner.h',
],