From 65fcbf7c7603d6168c71afaf3e7584e9ef57f7f5 Mon Sep 17 00:00:00 2001 From: Zachary Anderson Date: Mon, 13 Mar 2017 14:46:14 -0700 Subject: [PATCH] Add listViews service extension for the content handler (#3468) --- content_handler/BUILD.gn | 2 + content_handler/app.cc | 46 ++++++++++ content_handler/app.h | 15 +++ .../application_controller_impl.cc | 13 +++ content_handler/application_controller_impl.h | 5 + content_handler/runtime_holder.cc | 13 +++ content_handler/runtime_holder.h | 3 + content_handler/service_protocol_hooks.cc | 92 +++++++++++++++++++ content_handler/service_protocol_hooks.h | 29 ++++++ travis/licenses_golden/licenses_flutter | 2 + 10 files changed, 220 insertions(+) create mode 100644 content_handler/service_protocol_hooks.cc create mode 100644 content_handler/service_protocol_hooks.h diff --git a/content_handler/BUILD.gn b/content_handler/BUILD.gn index 6dfa62441..cb799cfd9 100644 --- a/content_handler/BUILD.gn +++ b/content_handler/BUILD.gn @@ -27,6 +27,8 @@ executable("content_handler") { "rasterizer.h", "runtime_holder.cc", "runtime_holder.h", + "service_protocol_hooks.cc", + "service_protocol_hooks.h", "software_rasterizer.cc", "software_rasterizer.h", ] diff --git a/content_handler/app.cc b/content_handler/app.cc index fdb089f29..df44589e9 100644 --- a/content_handler/app.cc +++ b/content_handler/app.cc @@ -11,6 +11,8 @@ #include "apps/tracing/lib/trace/provider.h" #include "flutter/common/settings.h" #include "flutter/common/threads.h" +#include "flutter/content_handler/service_protocol_hooks.h" +#include "flutter/runtime/dart_init.h" #include "flutter/runtime/runtime_init.h" #include "flutter/sky/engine/platform/fonts/fuchsia/FontCacheFuchsia.h" #include "lib/ftl/macros.h" @@ -20,6 +22,8 @@ namespace flutter_runner { namespace { +static App* g_app = nullptr; + void QuitMessageLoop() { mtl::MessageLoop::GetCurrent()->QuitNow(); } @@ -27,6 +31,7 @@ void QuitMessageLoop() { } // namespace App::App() { + g_app = this; context_ = app::ApplicationContext::CreateFromStartupInfo(); tracing::InitializeTracer(context_.get(), {}); @@ -57,6 +62,9 @@ App::App() { blink::Settings::Set(settings); blink::InitRuntime(); + blink::SetRegisterNativeServiceProtocolExtensionHook( + ServiceProtocolHooks::RegisterHooks); + blink::SetFontProvider( context_->ConnectToEnvironmentService()); @@ -70,6 +78,44 @@ App::~App() { icu_data::Release(); blink::Threads::Gpu()->PostTask(QuitMessageLoop); blink::Threads::IO()->PostTask(QuitMessageLoop); + g_app = nullptr; +} + +App& App::Shared() { + FTL_DCHECK(g_app); + return *g_app; +} + +void App::WaitForPlatformViewIds( + std::vector* platform_view_ids) { + ftl::AutoResetWaitableEvent latch; + + blink::Threads::UI()->PostTask([this, platform_view_ids, &latch]() { + WaitForPlatformViewsIdsUIThread(platform_view_ids, &latch); + }); + + latch.Wait(); +} + +void App::WaitForPlatformViewsIdsUIThread( + std::vector* platform_view_ids, + ftl::AutoResetWaitableEvent* latch) { + for (auto it = controllers_.begin(); it != controllers_.end(); it++) { + ApplicationControllerImpl* controller = it->first; + + if (!controller) { + continue; + } + + PlatformViewInfo info; + // TODO(zra): We should create real IDs for these instead of relying on the + // address of the controller. Maybe just use the UI Isolate main port? + info.view_id = reinterpret_cast(controller); + info.isolate_id = controller->GetUIIsolateMainPort(); + info.isolate_name = controller->GetUIIsolateName(); + platform_view_ids->push_back(info); + } + latch->Signal(); } void App::StartApplication( diff --git a/content_handler/app.h b/content_handler/app.h index 9b72c1644..0783ebdb1 100644 --- a/content_handler/app.h +++ b/content_handler/app.h @@ -13,6 +13,7 @@ #include "flutter/content_handler/application_controller_impl.h" #include "flutter/content_handler/content_handler_thread.h" #include "lib/ftl/macros.h" +#include "lib/ftl/synchronization/waitable_event.h" namespace flutter_runner { @@ -21,6 +22,8 @@ class App : public app::ApplicationRunner { App(); ~App(); + static App& Shared(); + // |app::ApplicationRunner| implementation: void StartApplication(app::ApplicationPackagePtr application, @@ -30,7 +33,19 @@ class App : public app::ApplicationRunner { void Destroy(ApplicationControllerImpl* controller); + struct PlatformViewInfo { + uintptr_t view_id; + int64_t isolate_id; + std::string isolate_name; + }; + + void WaitForPlatformViewIds(std::vector* platform_view_ids); + private: + void WaitForPlatformViewsIdsUIThread( + std::vector* platform_view_ids, + ftl::AutoResetWaitableEvent* latch); + std::unique_ptr context_; std::unique_ptr gpu_thread_; std::unique_ptr io_thread_; diff --git a/content_handler/application_controller_impl.cc b/content_handler/application_controller_impl.cc index 10a87ab14..4eb7d1d65 100644 --- a/content_handler/application_controller_impl.cc +++ b/content_handler/application_controller_impl.cc @@ -79,4 +79,17 @@ void ApplicationControllerImpl::CreateView( std::move(services)); } +Dart_Port ApplicationControllerImpl::GetUIIsolateMainPort() { + if (!runtime_holder_) + return ILLEGAL_PORT; + return runtime_holder_->GetUIIsolateMainPort(); +} + +std::string ApplicationControllerImpl::GetUIIsolateName() { + if (!runtime_holder_) { + return ""; + } + return runtime_holder_->GetUIIsolateName(); +} + } // namespace flutter_runner diff --git a/content_handler/application_controller_impl.h b/content_handler/application_controller_impl.h index b4efae41f..ddcc3634a 100644 --- a/content_handler/application_controller_impl.h +++ b/content_handler/application_controller_impl.h @@ -11,9 +11,11 @@ #include "application/services/application_runner.fidl.h" #include "application/services/service_provider.fidl.h" #include "apps/mozart/services/views/view_provider.fidl.h" +#include "dart/runtime/include/dart_api.h" #include "lib/fidl/cpp/bindings/binding.h" #include "lib/fidl/cpp/bindings/binding_set.h" #include "lib/ftl/macros.h" +#include "lib/ftl/synchronization/waitable_event.h" namespace flutter_runner { class App; @@ -47,6 +49,9 @@ class ApplicationControllerImpl : public app::ApplicationController, fidl::InterfaceRequest view_owner_request, fidl::InterfaceRequest services) override; + Dart_Port GetUIIsolateMainPort(); + std::string GetUIIsolateName(); + private: void StartRuntimeIfReady(); diff --git a/content_handler/runtime_holder.cc b/content_handler/runtime_holder.cc index 0acdf9ecb..ae8987595 100644 --- a/content_handler/runtime_holder.cc +++ b/content_handler/runtime_holder.cc @@ -169,6 +169,19 @@ void RuntimeHolder::CreateView( } } +Dart_Port RuntimeHolder::GetUIIsolateMainPort() { + if (!runtime_) + return ILLEGAL_PORT; + return runtime_->GetMainPort(); +} + +std::string RuntimeHolder::GetUIIsolateName() { + if (!runtime_) { + return ""; + } + return runtime_->GetIsolateName(); +} + void RuntimeHolder::ScheduleFrame() { if (pending_invalidation_ || deferred_invalidation_callback_) return; diff --git a/content_handler/runtime_holder.h b/content_handler/runtime_holder.h index a681d7f9f..ffb58ae24 100644 --- a/content_handler/runtime_holder.h +++ b/content_handler/runtime_holder.h @@ -45,6 +45,9 @@ class RuntimeHolder : public blink::RuntimeDelegate, fidl::InterfaceRequest view_owner_request, fidl::InterfaceRequest services); + Dart_Port GetUIIsolateMainPort(); + std::string GetUIIsolateName(); + private: // |blink::RuntimeDelegate| implementation: void ScheduleFrame() override; diff --git a/content_handler/service_protocol_hooks.cc b/content_handler/service_protocol_hooks.cc new file mode 100644 index 000000000..3d1bde3a2 --- /dev/null +++ b/content_handler/service_protocol_hooks.cc @@ -0,0 +1,92 @@ +// Copyright 2017 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 "flutter/content_handler/service_protocol_hooks.h" + +#include + +#include +#include + +#include "flutter/common/threads.h" +#include "flutter/content_handler/app.h" +#include "lib/ftl/memory/weak_ptr.h" + +namespace flutter_runner { +namespace { + +constexpr char kViewIdPrefx[] = "_flutterView/"; + +static void AppendIsolateRef(std::stringstream* stream, + int64_t main_port, + const std::string name) { + *stream << "{\"type\":\"@Isolate\",\"fixedId\":true,\"id\":\"isolates/"; + *stream << main_port << "\",\"name\":\"" << name << "\","; + *stream << "\"number\":\"" << main_port << "\"}"; +} + +static void AppendFlutterView(std::stringstream* stream, + uintptr_t view_id, + int64_t isolate_id, + const std::string isolate_name) { + *stream << "{\"type\":\"FlutterView\", \"id\": \"" << kViewIdPrefx << "0x" + << std::hex << view_id << std::dec << "\""; + if (isolate_id != ILLEGAL_PORT) { + // Append the isolate (if it exists). + *stream << "," + << "\"isolate\":"; + AppendIsolateRef(stream, isolate_id, isolate_name); + } + *stream << "}"; +} + +} // namespace + +void ServiceProtocolHooks::RegisterHooks(bool running_precompiled_code) { + // Listing of FlutterViews. + Dart_RegisterRootServiceRequestCallback(kListViewsExtensionName, &ListViews, + nullptr); +} + + +const char* ServiceProtocolHooks::kListViewsExtensionName = + "_flutter.listViews"; + +bool ServiceProtocolHooks::ListViews(const char* method, + const char** param_keys, + const char** param_values, + intptr_t num_params, + void* user_data, + const char** json_object) { + // Ask the App for the list of platform views. This will run a task on + // the UI thread before returning. + App& app = App::Shared(); + std::vector platform_views; + app.WaitForPlatformViewIds(&platform_views); + + std::stringstream response; + + response << "{\"type\":\"FlutterViewList\",\"views\":["; + bool prefix_comma = false; + for (auto it = platform_views.begin(); it != platform_views.end(); it++) { + uintptr_t view_id = it->view_id; + int64_t isolate_id = it->isolate_id; + const std::string& isolate_name = it->isolate_name; + if (!view_id) { + continue; + } + if (prefix_comma) { + response << ','; + } else { + prefix_comma = true; + } + AppendFlutterView(&response, view_id, isolate_id, isolate_name); + } + response << "]}"; + // Copy the response. + *json_object = strdup(response.str().c_str()); + return true; +} + +} // namespace flutter_runner diff --git a/content_handler/service_protocol_hooks.h b/content_handler/service_protocol_hooks.h new file mode 100644 index 000000000..c669b0690 --- /dev/null +++ b/content_handler/service_protocol_hooks.h @@ -0,0 +1,29 @@ +// Copyright 2017 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 FLUTTER_CONTENT_HANDLER_SERVICE_PROTOCOL_HOOKS_H_ +#define FLUTTER_CONTENT_HANDLER_SERVICE_PROTOCOL_HOOKS_H_ + +#include "dart/runtime/include/dart_tools_api.h" +#include "lib/ftl/synchronization/waitable_event.h" + +namespace flutter_runner { + +class ServiceProtocolHooks { + public: + static void RegisterHooks(bool running_precompiled_code); + + private: + static const char* kListViewsExtensionName; + static bool ListViews(const char* method, + const char** param_keys, + const char** param_values, + intptr_t num_params, + void* user_data, + const char** json_object); +}; + +} // namespace flutter_runner + +#endif // FLUTTER_CONTENT_HANDLER_SERVICE_PROTOCOL_HOOKS_H_ diff --git a/travis/licenses_golden/licenses_flutter b/travis/licenses_golden/licenses_flutter index 6f05b2a46..c90fd256e 100644 --- a/travis/licenses_golden/licenses_flutter +++ b/travis/licenses_golden/licenses_flutter @@ -1904,6 +1904,8 @@ FILE: ../../../flutter/content_handler/content_handler_thread.cc FILE: ../../../flutter/content_handler/content_handler_thread.h FILE: ../../../flutter/content_handler/direct_input.cc FILE: ../../../flutter/content_handler/direct_input.h +FILE: ../../../flutter/content_handler/service_protocol_hooks.cc +FILE: ../../../flutter/content_handler/service_protocol_hooks.h FILE: ../../../flutter/content_handler/software_rasterizer.cc FILE: ../../../flutter/content_handler/software_rasterizer.h FILE: ../../../flutter/content_handler/vulkan_rasterizer.cc -- GitLab