flutter_flutter/viewer/platform/platform_impl.cc
Eric Seidel 593c8f8de3 Wire up more of the DebuggerAgent
The debugger can now correctly break on exceptions
and show the corresponding line in the inspector.

It correctly understands which scripts are internal
to sky and does not pause during them.

There is still a ton to make work here
(including stacktraces which I have not tested),
but basic functionality seems to work.

The current implementation is not smart enough to
unpause the inspector when the frontend disconnects.

BUG=434510,434513
R=abarth@chromium.org

Review URL: https://codereview.chromium.org/727593004
2014-11-18 15:05:05 -08:00

266 lines
8.6 KiB
C++

// Copyright 2014 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 "sky/viewer/platform/platform_impl.h"
#include <cmath>
#include "base/debug/trace_event.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/path_service.h"
#include "base/rand_util.h"
#include "base/stl_util.h"
#include "base/synchronization/waitable_event.h"
#include "base/time/time.h"
#include "mojo/public/cpp/application/application_impl.h"
#include "net/base/data_url.h"
#include "net/base/mime_util.h"
#include "net/base/net_errors.h"
#include "sky/engine/public/platform/WebConvertableToTraceFormat.h"
#include "sky/viewer/platform/weburlloader_impl.h"
namespace sky {
namespace {
class ConvertableToTraceFormatWrapper
: public base::debug::ConvertableToTraceFormat {
public:
explicit ConvertableToTraceFormatWrapper(
const blink::WebConvertableToTraceFormat& convertable)
: convertable_(convertable) {}
virtual void AppendAsTraceFormat(std::string* out) const override {
*out += convertable_.asTraceFormat().utf8();
}
private:
virtual ~ConvertableToTraceFormatWrapper() {}
blink::WebConvertableToTraceFormat convertable_;
};
} // namespace
PlatformImpl::PlatformImpl(mojo::ApplicationImpl* app)
: main_loop_(base::MessageLoop::current()),
main_thread_task_runner_(base::MessageLoop::current()->task_runner()),
shared_timer_func_(NULL),
shared_timer_fire_time_(0.0),
shared_timer_fire_time_was_set_while_suspended_(false),
shared_timer_suspended_(0) {
app->ConnectToService("mojo:network_service", &network_service_);
mojo::CookieStorePtr cookie_store;
network_service_->GetCookieStore(GetProxy(&cookie_store));
}
PlatformImpl::~PlatformImpl() {
}
blink::WebMimeRegistry* PlatformImpl::mimeRegistry() {
return &mime_registry_;
}
blink::WebThemeEngine* PlatformImpl::themeEngine() {
return &theme_engine_;
}
blink::WebString PlatformImpl::defaultLocale() {
return blink::WebString::fromUTF8("en-US");
}
double PlatformImpl::currentTime() {
return base::Time::Now().ToDoubleT();
}
double PlatformImpl::monotonicallyIncreasingTime() {
return base::TimeTicks::Now().ToInternalValue() /
static_cast<double>(base::Time::kMicrosecondsPerSecond);
}
void PlatformImpl::setSharedTimerFiredFunction(void (*func)()) {
shared_timer_func_ = func;
}
void PlatformImpl::setSharedTimerFireInterval(
double interval_seconds) {
shared_timer_fire_time_ = interval_seconds + monotonicallyIncreasingTime();
if (shared_timer_suspended_) {
shared_timer_fire_time_was_set_while_suspended_ = true;
return;
}
// By converting between double and int64 representation, we run the risk
// of losing precision due to rounding errors. Performing computations in
// microseconds reduces this risk somewhat. But there still is the potential
// of us computing a fire time for the timer that is shorter than what we
// need.
// As the event loop will check event deadlines prior to actually firing
// them, there is a risk of needlessly rescheduling events and of
// needlessly looping if sleep times are too short even by small amounts.
// This results in measurable performance degradation unless we use ceil() to
// always round up the sleep times.
int64 interval = static_cast<int64>(
ceil(interval_seconds * base::Time::kMillisecondsPerSecond)
* base::Time::kMicrosecondsPerMillisecond);
if (interval < 0)
interval = 0;
shared_timer_.Stop();
shared_timer_.Start(FROM_HERE, base::TimeDelta::FromMicroseconds(interval),
this, &PlatformImpl::DoTimeout);
}
void PlatformImpl::stopSharedTimer() {
shared_timer_.Stop();
}
base::SingleThreadTaskRunner* PlatformImpl::mainThreadTaskRunner() {
return main_thread_task_runner_.get();
}
bool PlatformImpl::isThreadedCompositingEnabled() {
return true;
}
blink::WebCompositorSupport* PlatformImpl::compositorSupport() {
return &compositor_support_;
}
mojo::NetworkService* PlatformImpl::networkService() {
return network_service_.get();
}
blink::WebURLLoader* PlatformImpl::createURLLoader() {
return new WebURLLoaderImpl(network_service_.get());
}
blink::WebURLError PlatformImpl::cancelledError(const blink::WebURL& url)
const {
blink::WebURLError error;
error.domain = blink::WebString::fromUTF8(net::kErrorDomain);
error.reason = net::ERR_ABORTED;
error.unreachableURL = url;
error.staleCopyInCache = false;
error.isCancellation = true;
return error;
}
const unsigned char* PlatformImpl::getTraceCategoryEnabledFlag(
const char* category_group) {
return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group);
}
long* PlatformImpl::getTraceSamplingState(const unsigned thread_bucket) {
switch (thread_bucket) {
case 0:
return reinterpret_cast<long*>(&TRACE_EVENT_API_THREAD_BUCKET(0));
case 1:
return reinterpret_cast<long*>(&TRACE_EVENT_API_THREAD_BUCKET(1));
case 2:
return reinterpret_cast<long*>(&TRACE_EVENT_API_THREAD_BUCKET(2));
default:
NOTREACHED() << "Unknown thread bucket type.";
}
return NULL;
}
COMPILE_ASSERT(
sizeof(blink::Platform::TraceEventHandle) ==
sizeof(base::debug::TraceEventHandle),
TraceEventHandle_types_must_be_same_size);
blink::Platform::TraceEventHandle PlatformImpl::addTraceEvent(
char phase,
const unsigned char* category_group_enabled,
const char* name,
unsigned long long id,
int num_args,
const char** arg_names,
const unsigned char* arg_types,
const unsigned long long* arg_values,
unsigned char flags) {
base::debug::TraceEventHandle handle = TRACE_EVENT_API_ADD_TRACE_EVENT(
phase, category_group_enabled, name, id,
num_args, arg_names, arg_types, arg_values, NULL, flags);
blink::Platform::TraceEventHandle result;
memcpy(&result, &handle, sizeof(result));
return result;
}
blink::Platform::TraceEventHandle PlatformImpl::addTraceEvent(
char phase,
const unsigned char* category_group_enabled,
const char* name,
unsigned long long id,
int num_args,
const char** arg_names,
const unsigned char* arg_types,
const unsigned long long* arg_values,
const blink::WebConvertableToTraceFormat* convertable_values,
unsigned char flags) {
scoped_refptr<base::debug::ConvertableToTraceFormat> convertable_wrappers[2];
if (convertable_values) {
size_t size = std::min(static_cast<size_t>(num_args),
arraysize(convertable_wrappers));
for (size_t i = 0; i < size; ++i) {
if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) {
convertable_wrappers[i] =
new ConvertableToTraceFormatWrapper(convertable_values[i]);
}
}
}
base::debug::TraceEventHandle handle =
TRACE_EVENT_API_ADD_TRACE_EVENT(phase,
category_group_enabled,
name,
id,
num_args,
arg_names,
arg_types,
arg_values,
convertable_wrappers,
flags);
blink::Platform::TraceEventHandle result;
memcpy(&result, &handle, sizeof(result));
return result;
}
void PlatformImpl::updateTraceEventDuration(
const unsigned char* category_group_enabled,
const char* name,
TraceEventHandle handle) {
base::debug::TraceEventHandle traceEventHandle;
memcpy(&traceEventHandle, &handle, sizeof(handle));
TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(
category_group_enabled, name, traceEventHandle);
}
// FIXME(sky): This is a horrible hack and makes sky only work when run
// inside its source tree! crbug.com/434513
blink::WebData PlatformImpl::loadResource(const char* name)
{
base::FilePath root_dir;
PathService::Get(base::DIR_SOURCE_ROOT, &root_dir);
base::FilePath engine_dir = root_dir.AppendASCII("sky").AppendASCII("engine");
base::FilePath v8_dir = engine_dir.AppendASCII("bindings").AppendASCII("core").AppendASCII("v8");
base::FilePath inspector_dir = engine_dir.AppendASCII("core").AppendASCII("inspector");
base::FilePath path;
if (std::string("InjectedScriptSource.js") == name)
path = inspector_dir.AppendASCII(name);
else if (std::string("DebuggerScript.js") == name)
path = v8_dir.AppendASCII(name);
else
CHECK(false);
std::string buffer;
base::ReadFileToString(path, &buffer);
CHECK(!buffer.empty());
return blink::WebData(buffer.data(), buffer.size());
}
} // namespace sky