From 61a2d129cfc8c52cf1ff59b03bccf67d9b07af63 Mon Sep 17 00:00:00 2001 From: Ben Konyi Date: Tue, 12 Jun 2018 15:50:48 -0700 Subject: [PATCH] Added IsolateNameServer functionality (#5410) * Added IsolateNameServer functionality, which allows for the association of string names with isolate SendPort ids that can be used to establish inter-isolate communications. --- lib/ui/BUILD.gn | 4 + lib/ui/dart_ui.cc | 2 + lib/ui/dart_ui.gni | 1 + lib/ui/isolate_name_server.dart | 44 ++++++ .../isolate_name_server.cc | 44 ++++++ .../isolate_name_server/isolate_name_server.h | 50 +++++++ .../isolate_name_server_natives.cc | 64 +++++++++ .../isolate_name_server_natives.h | 27 ++++ lib/ui/ui.dart | 2 + lib/ui/ui_dart_state.cc | 10 +- lib/ui/ui_dart_state.h | 7 +- runtime/dart_isolate.cc | 11 +- runtime/dart_isolate.h | 8 +- runtime/dart_vm.cc | 4 + runtime/dart_vm.h | 4 + runtime/dart_vm_unittests.cc | 14 ++ runtime/runtime_controller.cc | 4 +- runtime/runtime_controller.h | 6 +- shell/common/engine.cc | 2 +- shell/common/engine.h | 2 +- shell/common/shell.cc | 2 +- shell/common/shell.h | 2 +- testing/dart/isolate_name_server_test.dart | 128 ++++++++++++++++++ testing/run_tests.sh | 1 - travis/licenses_golden/licenses_flutter | 5 + 25 files changed, 426 insertions(+), 22 deletions(-) create mode 100644 lib/ui/isolate_name_server.dart create mode 100644 lib/ui/isolate_name_server/isolate_name_server.cc create mode 100644 lib/ui/isolate_name_server/isolate_name_server.h create mode 100644 lib/ui/isolate_name_server/isolate_name_server_natives.cc create mode 100644 lib/ui/isolate_name_server/isolate_name_server_natives.h create mode 100644 testing/dart/isolate_name_server_test.dart diff --git a/lib/ui/BUILD.gn b/lib/ui/BUILD.gn index 592f985b8b7d8..027159fb897a9 100644 --- a/lib/ui/BUILD.gn +++ b/lib/ui/BUILD.gn @@ -14,6 +14,10 @@ source_set("ui") { "dart_runtime_hooks.h", "dart_ui.cc", "dart_ui.h", + "isolate_name_server/isolate_name_server.cc", + "isolate_name_server/isolate_name_server.h", + "isolate_name_server/isolate_name_server_natives.cc", + "isolate_name_server/isolate_name_server_natives.h", "painting/canvas.cc", "painting/canvas.h", "painting/codec.cc", diff --git a/lib/ui/dart_ui.cc b/lib/ui/dart_ui.cc index 824152e28e8d0..306743c82f39f 100644 --- a/lib/ui/dart_ui.cc +++ b/lib/ui/dart_ui.cc @@ -7,6 +7,7 @@ #include "flutter/lib/ui/compositing/scene.h" #include "flutter/lib/ui/compositing/scene_builder.h" #include "flutter/lib/ui/dart_runtime_hooks.h" +#include "flutter/lib/ui/isolate_name_server/isolate_name_server_natives.h" #include "flutter/lib/ui/painting/canvas.h" #include "flutter/lib/ui/painting/codec.h" #include "flutter/lib/ui/painting/frame_info.h" @@ -60,6 +61,7 @@ void DartUI::InitForGlobal() { FrameInfo::RegisterNatives(g_natives); ImageFilter::RegisterNatives(g_natives); ImageShader::RegisterNatives(g_natives); + IsolateNameServerNatives::RegisterNatives(g_natives); Paragraph::RegisterNatives(g_natives); ParagraphBuilder::RegisterNatives(g_natives); Picture::RegisterNatives(g_natives); diff --git a/lib/ui/dart_ui.gni b/lib/ui/dart_ui.gni index 418b6531004a0..e1885d1d09ace 100644 --- a/lib/ui/dart_ui.gni +++ b/lib/ui/dart_ui.gni @@ -7,6 +7,7 @@ dart_ui_files = [ "$flutter_root/lib/ui/geometry.dart", "$flutter_root/lib/ui/hash_codes.dart", "$flutter_root/lib/ui/hooks.dart", + "$flutter_root/lib/ui/isolate_name_server.dart", "$flutter_root/lib/ui/lerp.dart", "$flutter_root/lib/ui/natives.dart", "$flutter_root/lib/ui/painting.dart", diff --git a/lib/ui/isolate_name_server.dart b/lib/ui/isolate_name_server.dart new file mode 100644 index 0000000000000..8dcbf79977ef7 --- /dev/null +++ b/lib/ui/isolate_name_server.dart @@ -0,0 +1,44 @@ +// Copyright 2018 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. + +part of dart.ui; + +abstract class IsolateNameServer { + // Looks up the [SendPort] associated with a given name. Returns null + // if the name does not exist. + static SendPort lookupPortByName(String name) { + if (name == null) { + throw new ArgumentError("'name' cannot be null."); + } + return _lookupPortByName(name); + } + + // Registers a SendPort with a given name. Returns true if registration is + // successful, false if the name entry already exists. + static bool registerPortWithName(SendPort port, String name) { + if (name == null) { + throw new ArgumentError("'name' cannot be null."); + } + if (port == null) { + throw new ArgumentError("'port' cannot be null."); + } + return _registerPortWithName(port, name); + } + + // Removes a name to SendPort mapping given a name. Returns true if the + // mapping was successfully removed, false if the mapping does not exist. + static bool removePortNameMapping(String name) { + if (name == null) { + throw new ArgumentError("'name' cannot be null."); + } + return _removePortNameMapping(name); + } + + static SendPort _lookupPortByName(String name) + native 'IsolateNameServerNatives_LookupPortByName'; + static bool _registerPortWithName(SendPort port, String name) + native 'IsolateNameServerNatives_RegisterPortWithName'; + static bool _removePortNameMapping(String name) + native 'IsolateNameServerNatives_RemovePortNameMapping'; +} diff --git a/lib/ui/isolate_name_server/isolate_name_server.cc b/lib/ui/isolate_name_server/isolate_name_server.cc new file mode 100644 index 0000000000000..7a6a1fe5889e4 --- /dev/null +++ b/lib/ui/isolate_name_server/isolate_name_server.cc @@ -0,0 +1,44 @@ +// Copyright 2018 The Flutter 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/lib/ui/isolate_name_server/isolate_name_server.h" + +namespace blink { + +Dart_Port IsolateNameServer::LookupIsolatePortByName(const std::string& name) { + std::unique_lock lock(mutex_); + return LookupIsolatePortByNameUnprotected(name); +} + +Dart_Port IsolateNameServer::LookupIsolatePortByNameUnprotected( + const std::string& name) { + auto port_iterator = port_mapping_.find(name); + if (port_iterator != port_mapping_.end()) { + return port_iterator->second; + } + return ILLEGAL_PORT; +} + +bool IsolateNameServer::RegisterIsolatePortWithName(Dart_Port port, + const std::string& name) { + std::unique_lock lock(mutex_); + if (LookupIsolatePortByNameUnprotected(name) != ILLEGAL_PORT) { + // Name is already registered. + return false; + } + port_mapping_[name] = port; + return true; +} + +bool IsolateNameServer::RemoveIsolateNameMapping(const std::string& name) { + std::unique_lock lock(mutex_); + auto port_iterator = port_mapping_.find(name); + if (port_iterator == port_mapping_.end()) { + return false; + } + port_mapping_.erase(port_iterator); + return true; +} + +} // namespace blink diff --git a/lib/ui/isolate_name_server/isolate_name_server.h b/lib/ui/isolate_name_server/isolate_name_server.h new file mode 100644 index 0000000000000..fe1ee7910e57c --- /dev/null +++ b/lib/ui/isolate_name_server/isolate_name_server.h @@ -0,0 +1,50 @@ +// Copyright 2018 The Flutter 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_LIB_UI_ISOLATE_NAME_SERVER_H_ +#define FLUTTER_LIB_UI_ISOLATE_NAME_SERVER_H_ + +#include +#include +#include + +#include "flutter/fml/synchronization/thread_annotations.h" +#include "lib/fxl/macros.h" +#include "third_party/dart/runtime/include/dart_api.h" + +#define LOCK_UNLOCK(m) FML_ACQUIRE(m) FML_RELEASE(m) + +namespace blink { + +class IsolateNameServer { + public: + IsolateNameServer() {} + + // Looks up the Dart_Port associated with a given name. Returns ILLEGAL_PORT + // if the name does not exist. + Dart_Port LookupIsolatePortByName(const std::string& name) + LOCK_UNLOCK(mutex_); + + // Registers a Dart_Port with a given name. Returns true if registration is + // successful, false if the name entry already exists. + bool RegisterIsolatePortWithName(Dart_Port port, const std::string& name) + LOCK_UNLOCK(mutex_); + + // Removes a name to Dart_Port mapping given a name. Returns true if the + // mapping was successfully removed, false if the mapping does not exist. + bool RemoveIsolateNameMapping(const std::string& name) LOCK_UNLOCK(mutex_); + + private: + Dart_Port LookupIsolatePortByNameUnprotected(const std::string& name) + FML_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + mutable std::mutex mutex_; + std::map port_mapping_ FML_GUARDED_BY(mutex_); + + FXL_DISALLOW_COPY_AND_ASSIGN(IsolateNameServer); +}; + +} // namespace blink + +#endif // FLUTTER_LIB_UI_ISOLATE_NAME_SERVER_H_ diff --git a/lib/ui/isolate_name_server/isolate_name_server_natives.cc b/lib/ui/isolate_name_server/isolate_name_server_natives.cc new file mode 100644 index 0000000000000..3919f9f4898c1 --- /dev/null +++ b/lib/ui/isolate_name_server/isolate_name_server_natives.cc @@ -0,0 +1,64 @@ +// Copyright 2018 The Flutter 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 + +#include "flutter/lib/ui/isolate_name_server/isolate_name_server.h" +#include "flutter/lib/ui/isolate_name_server/isolate_name_server_natives.h" +#include "flutter/lib/ui/ui_dart_state.h" +#include "lib/tonic/dart_binding_macros.h" +#include "lib/tonic/dart_library_natives.h" + +namespace blink { + +Dart_Handle IsolateNameServerNatives::LookupPortByName( + const std::string& name) { + IsolateNameServer* name_server = + UIDartState::Current()->GetIsolateNameServer(); + Dart_Port port = name_server->LookupIsolatePortByName(name); + if (port == ILLEGAL_PORT) { + return Dart_Null(); + } + return Dart_NewSendPort(port); +} + +Dart_Handle IsolateNameServerNatives::RegisterPortWithName( + Dart_Handle port_handle, + const std::string& name) { + IsolateNameServer* name_server = + UIDartState::Current()->GetIsolateNameServer(); + Dart_Port port = ILLEGAL_PORT; + Dart_SendPortGetId(port_handle, &port); + if (!name_server->RegisterIsolatePortWithName(port, name)) { + return Dart_False(); + } + return Dart_True(); +} + +Dart_Handle IsolateNameServerNatives::RemovePortNameMapping( + const std::string& name) { + IsolateNameServer* name_server = + UIDartState::Current()->GetIsolateNameServer(); + if (!name_server->RemoveIsolateNameMapping(name)) { + return Dart_False(); + } + return Dart_True(); +} + +#define FOR_EACH_BINDING(V) \ + V(IsolateNameServerNatives, LookupPortByName) \ + V(IsolateNameServerNatives, RegisterPortWithName) \ + V(IsolateNameServerNatives, RemovePortNameMapping) + +FOR_EACH_BINDING(DART_NATIVE_CALLBACK_STATIC) + +#define DART_REGISTER_NATIVE_STATIC_(CLASS, METHOD) \ + DART_REGISTER_NATIVE_STATIC(CLASS, METHOD), + +void IsolateNameServerNatives::RegisterNatives( + tonic::DartLibraryNatives* natives) { + natives->Register({FOR_EACH_BINDING(DART_REGISTER_NATIVE_STATIC_)}); +} + +} // namespace blink diff --git a/lib/ui/isolate_name_server/isolate_name_server_natives.h b/lib/ui/isolate_name_server/isolate_name_server_natives.h new file mode 100644 index 0000000000000..2ebbe6e445010 --- /dev/null +++ b/lib/ui/isolate_name_server/isolate_name_server_natives.h @@ -0,0 +1,27 @@ +// Copyright 2018 The Flutter 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_LIB_UI_ISOLATE_NAME_SERVER_NATIVES_H_ +#define FLUTTER_LIB_UI_ISOLATE_NAME_SERVER_NATIVES_H_ + +#include "third_party/dart/runtime/include/dart_api.h" + +namespace tonic { +class DartLibraryNatives; +} // namespace tonic + +namespace blink { + +class IsolateNameServerNatives { + public: + static Dart_Handle LookupPortByName(const std::string& name); + static Dart_Handle RegisterPortWithName(Dart_Handle port_handle, + const std::string& name); + static Dart_Handle RemovePortNameMapping(const std::string& name); + static void RegisterNatives(tonic::DartLibraryNatives* natives); +}; + +} // namespace blink + +#endif // FLUTTER_LIB_UI_ISOLATE_NAME_SERVER_NATIVES_H_ diff --git a/lib/ui/ui.dart b/lib/ui/ui.dart index b6d22ca2939e9..1d9782311f310 100644 --- a/lib/ui/ui.dart +++ b/lib/ui/ui.dart @@ -17,6 +17,7 @@ import 'dart:collection' as collection; import 'dart:convert'; import 'dart:developer' as developer; import 'dart:io'; +import 'dart:isolate' show SendPort; import 'dart:math' as math; import 'dart:nativewrappers'; import 'dart:typed_data'; @@ -25,6 +26,7 @@ part 'compositing.dart'; part 'geometry.dart'; part 'hash_codes.dart'; part 'hooks.dart'; +part 'isolate_name_server.dart'; part 'lerp.dart'; part 'natives.dart'; part 'painting.dart'; diff --git a/lib/ui/ui_dart_state.cc b/lib/ui/ui_dart_state.cc index 77830affdd561..f7d3d4c81cca6 100644 --- a/lib/ui/ui_dart_state.cc +++ b/lib/ui/ui_dart_state.cc @@ -19,7 +19,8 @@ UIDartState::UIDartState(TaskRunners task_runners, fxl::RefPtr skia_unref_queue, std::string advisory_script_uri, std::string advisory_script_entrypoint, - std::string logger_prefix) + std::string logger_prefix, + IsolateNameServer* isolate_name_server) : task_runners_(std::move(task_runners)), add_callback_(std::move(add_callback)), remove_callback_(std::move(remove_callback)), @@ -27,7 +28,8 @@ UIDartState::UIDartState(TaskRunners task_runners, advisory_script_uri_(std::move(advisory_script_uri)), advisory_script_entrypoint_(std::move(advisory_script_entrypoint)), logger_prefix_(std::move(logger_prefix)), - skia_unref_queue_(std::move(skia_unref_queue)) { + skia_unref_queue_(std::move(skia_unref_queue)), + isolate_name_server_(isolate_name_server) { AddOrRemoveTaskObserver(true /* add */); } @@ -100,4 +102,8 @@ fml::WeakPtr UIDartState::GetResourceContext() const { return resource_context_; } +IsolateNameServer* UIDartState::GetIsolateNameServer() { + return isolate_name_server_; +} + } // namespace blink diff --git a/lib/ui/ui_dart_state.h b/lib/ui/ui_dart_state.h index ef1832594d3c0..5cfdf9a44f11c 100644 --- a/lib/ui/ui_dart_state.h +++ b/lib/ui/ui_dart_state.h @@ -13,6 +13,7 @@ #include "flutter/common/task_runners.h" #include "flutter/flow/skia_gpu_object.h" #include "flutter/fml/memory/weak_ptr.h" +#include "flutter/lib/ui/isolate_name_server/isolate_name_server.h" #include "lib/fxl/build_config.h" #include "lib/tonic/dart_microtask_queue.h" #include "lib/tonic/dart_persistent_value.h" @@ -46,6 +47,8 @@ class UIDartState : public tonic::DartState { fml::WeakPtr GetResourceContext() const; + IsolateNameServer* GetIsolateNameServer(); + template static flow::SkiaGPUObject CreateGPUObject(sk_sp object) { if (!object) { @@ -65,7 +68,8 @@ class UIDartState : public tonic::DartState { fxl::RefPtr skia_unref_queue, std::string advisory_script_uri, std::string advisory_script_entrypoint, - std::string logger_prefix); + std::string logger_prefix, + IsolateNameServer* isolate_name_server); ~UIDartState() override; @@ -90,6 +94,7 @@ class UIDartState : public tonic::DartState { std::unique_ptr window_; fxl::RefPtr skia_unref_queue_; tonic::DartMicrotaskQueue microtask_queue_; + IsolateNameServer* isolate_name_server_; void AddOrRemoveTaskObserver(bool add); }; diff --git a/runtime/dart_isolate.cc b/runtime/dart_isolate.cc index ded3ff8f6da2a..66af59a5872c7 100644 --- a/runtime/dart_isolate.cc +++ b/runtime/dart_isolate.cc @@ -33,7 +33,7 @@ namespace blink { fml::WeakPtr DartIsolate::CreateRootIsolate( - const DartVM* vm, + DartVM* vm, fxl::RefPtr isolate_snapshot, fxl::RefPtr shared_snapshot, TaskRunners task_runners, @@ -94,7 +94,7 @@ fml::WeakPtr DartIsolate::CreateRootIsolate( return embedder_isolate; } -DartIsolate::DartIsolate(const DartVM* vm, +DartIsolate::DartIsolate(DartVM* vm, fxl::RefPtr isolate_snapshot, fxl::RefPtr shared_snapshot, TaskRunners task_runners, @@ -110,7 +110,8 @@ DartIsolate::DartIsolate(const DartVM* vm, std::move(unref_queue), advisory_script_uri, advisory_script_entrypoint, - vm->GetSettings().log_tag), + vm->GetSettings().log_tag, + vm->GetIsolateNameServer()), vm_(vm), isolate_snapshot_(std::move(isolate_snapshot)), shared_snapshot_(std::move(shared_snapshot)), @@ -131,7 +132,7 @@ DartIsolate::Phase DartIsolate::GetPhase() const { return phase_; } -const DartVM* DartIsolate::GetDartVM() const { +DartVM* DartIsolate::GetDartVM() const { return vm_; } @@ -651,7 +652,7 @@ DartIsolate::CreateDartVMAndEmbedderObjectPair( return {nullptr, {}}; } - const DartVM* vm = embedder_isolate->GetDartVM(); + DartVM* const vm = embedder_isolate->GetDartVM(); if (!is_root_isolate) { auto raw_embedder_isolate = embedder_isolate.release(); diff --git a/runtime/dart_isolate.h b/runtime/dart_isolate.h index e8219469034f7..ceed7a0fd7a2a 100644 --- a/runtime/dart_isolate.h +++ b/runtime/dart_isolate.h @@ -39,7 +39,7 @@ class DartIsolate : public UIDartState { // bindings. From the VM's perspective, this isolate is not special in any // way. static fml::WeakPtr CreateRootIsolate( - const DartVM* vm, + DartVM* vm, fxl::RefPtr isolate_snapshot, fxl::RefPtr shared_snapshot, TaskRunners task_runners, @@ -50,7 +50,7 @@ class DartIsolate : public UIDartState { std::string advisory_script_entrypoint, Dart_IsolateFlags* flags = nullptr); - DartIsolate(const DartVM* vm, + DartIsolate(DartVM* vm, fxl::RefPtr isolate_snapshot, fxl::RefPtr shared_snapshot, TaskRunners task_runners, @@ -84,7 +84,7 @@ class DartIsolate : public UIDartState { void AddIsolateShutdownCallback(fxl::Closure closure); - const DartVM* GetDartVM() const; + DartVM* GetDartVM() const; fxl::RefPtr GetIsolateSnapshot() const; fxl::RefPtr GetSharedSnapshot() const; @@ -107,7 +107,7 @@ class DartIsolate : public UIDartState { }; friend class DartVM; - const DartVM* vm_ = nullptr; + DartVM* const vm_ = nullptr; Phase phase_ = Phase::Unknown; const fxl::RefPtr isolate_snapshot_; const fxl::RefPtr shared_snapshot_; diff --git a/runtime/dart_vm.cc b/runtime/dart_vm.cc index 776fbab983e10..4f24b5bad23b9 100644 --- a/runtime/dart_vm.cc +++ b/runtime/dart_vm.cc @@ -471,6 +471,10 @@ const DartSnapshot& DartVM::GetVMSnapshot() const { return *vm_snapshot_.get(); } +IsolateNameServer* DartVM::GetIsolateNameServer() { + return &isolate_name_server_; +} + fxl::RefPtr DartVM::GetIsolateSnapshot() const { return isolate_snapshot_; } diff --git a/runtime/dart_vm.h b/runtime/dart_vm.h index 8202aad1204c4..8c2c6f3fe5019 100644 --- a/runtime/dart_vm.h +++ b/runtime/dart_vm.h @@ -10,6 +10,7 @@ #include #include "flutter/common/settings.h" +#include "flutter/lib/ui/isolate_name_server/isolate_name_server.h" #include "flutter/runtime/dart_isolate.h" #include "flutter/runtime/dart_snapshot.h" #include "flutter/runtime/service_protocol.h" @@ -43,6 +44,8 @@ class DartVM : public fxl::RefCountedThreadSafe { const DartSnapshot& GetVMSnapshot() const; + IsolateNameServer* GetIsolateNameServer(); + fxl::RefPtr GetIsolateSnapshot() const; fxl::RefPtr GetSharedSnapshot() const; @@ -53,6 +56,7 @@ class DartVM : public fxl::RefCountedThreadSafe { private: const Settings settings_; const fxl::RefPtr vm_snapshot_; + IsolateNameServer isolate_name_server_; const fxl::RefPtr isolate_snapshot_; const fxl::RefPtr shared_snapshot_; std::unique_ptr platform_kernel_mapping_; diff --git a/runtime/dart_vm_unittests.cc b/runtime/dart_vm_unittests.cc index d0664d111181b..280375dd19feb 100644 --- a/runtime/dart_vm_unittests.cc +++ b/runtime/dart_vm_unittests.cc @@ -18,4 +18,18 @@ TEST(DartVM, SimpleInitialization) { ASSERT_EQ(vm->GetPlatformKernel().GetSize(), 0u); } +TEST(DartVM, SimpleIsolateNameServer) { + Settings settings = {}; + settings.task_observer_add = [](intptr_t, fxl::Closure) {}; + settings.task_observer_remove = [](intptr_t) {}; + auto vm = DartVM::ForProcess(settings); + auto ns = vm->GetIsolateNameServer(); + ASSERT_EQ(ns->LookupIsolatePortByName("foobar"), ILLEGAL_PORT); + ASSERT_FALSE(ns->RemoveIsolateNameMapping("foobar")); + ASSERT_TRUE(ns->RegisterIsolatePortWithName(123, "foobar")); + ASSERT_FALSE(ns->RegisterIsolatePortWithName(123, "foobar")); + ASSERT_EQ(ns->LookupIsolatePortByName("foobar"), 123); + ASSERT_TRUE(ns->RemoveIsolateNameMapping("foobar")); +} + } // namespace blink diff --git a/runtime/runtime_controller.cc b/runtime/runtime_controller.cc index 4b4c2cdf30aad..18eaaebad68bc 100644 --- a/runtime/runtime_controller.cc +++ b/runtime/runtime_controller.cc @@ -20,7 +20,7 @@ namespace blink { RuntimeController::RuntimeController( RuntimeDelegate& p_client, - const DartVM* p_vm, + DartVM* p_vm, fxl::RefPtr p_isolate_snapshot, fxl::RefPtr p_shared_snapshot, TaskRunners p_task_runners, @@ -41,7 +41,7 @@ RuntimeController::RuntimeController( RuntimeController::RuntimeController( RuntimeDelegate& p_client, - const DartVM* p_vm, + DartVM* p_vm, fxl::RefPtr p_isolate_snapshot, fxl::RefPtr p_shared_snapshot, TaskRunners p_task_runners, diff --git a/runtime/runtime_controller.h b/runtime/runtime_controller.h index 746845a7c0fba..599d9c73b274c 100644 --- a/runtime/runtime_controller.h +++ b/runtime/runtime_controller.h @@ -24,7 +24,7 @@ class Window; class RuntimeController final : public WindowClient { public: RuntimeController(RuntimeDelegate& client, - const DartVM* vm, + DartVM* vm, fxl::RefPtr isolate_snapshot, fxl::RefPtr shared_snapshot, TaskRunners task_runners, @@ -82,7 +82,7 @@ class RuntimeController final : public WindowClient { }; RuntimeDelegate& client_; - const DartVM* vm_; + DartVM* const vm_; fxl::RefPtr isolate_snapshot_; fxl::RefPtr shared_snapshot_; TaskRunners task_runners_; @@ -95,7 +95,7 @@ class RuntimeController final : public WindowClient { std::pair root_isolate_return_code_ = {false, 0}; RuntimeController(RuntimeDelegate& client, - const DartVM* vm, + DartVM* vm, fxl::RefPtr isolate_snapshot, fxl::RefPtr shared_snapshot, TaskRunners task_runners, diff --git a/shell/common/engine.cc b/shell/common/engine.cc index 0eea25f8de8e0..d2f6e57807200 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -36,7 +36,7 @@ static constexpr char kLocalizationChannel[] = "flutter/localization"; static constexpr char kSettingsChannel[] = "flutter/settings"; Engine::Engine(Delegate& delegate, - const blink::DartVM& vm, + blink::DartVM& vm, fxl::RefPtr isolate_snapshot, fxl::RefPtr shared_snapshot, blink::TaskRunners task_runners, diff --git a/shell/common/engine.h b/shell/common/engine.h index e1fed0d683d61..46602cdea9fd6 100644 --- a/shell/common/engine.h +++ b/shell/common/engine.h @@ -39,7 +39,7 @@ class Engine final : public blink::RuntimeDelegate { }; Engine(Delegate& delegate, - const blink::DartVM& vm, + blink::DartVM& vm, fxl::RefPtr isolate_snapshot, fxl::RefPtr shared_snapshot, blink::TaskRunners task_runners, diff --git a/shell/common/shell.cc b/shell/common/shell.cc index 97385fab65f72..0da5126e53e3d 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -400,7 +400,7 @@ fml::WeakPtr Shell::GetPlatformView() { return platform_view_->GetWeakPtr(); } -const blink::DartVM& Shell::GetDartVM() const { +blink::DartVM& Shell::GetDartVM() const { return *vm_; } diff --git a/shell/common/shell.h b/shell/common/shell.h index 2a8caeb476583..75ab39052ce21 100644 --- a/shell/common/shell.h +++ b/shell/common/shell.h @@ -72,7 +72,7 @@ class Shell final : public PlatformView::Delegate, fml::WeakPtr GetPlatformView(); - const blink::DartVM& GetDartVM() const; + blink::DartVM& GetDartVM() const; bool IsSetup() const; diff --git a/testing/dart/isolate_name_server_test.dart b/testing/dart/isolate_name_server_test.dart new file mode 100644 index 0000000000000..98dbf612ce123 --- /dev/null +++ b/testing/dart/isolate_name_server_test.dart @@ -0,0 +1,128 @@ +// Copyright 2018 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. + +import 'dart:async'; +import 'dart:isolate'; +import 'dart:ui'; + +import 'package:test/test.dart'; + +const kPortName = 'foobar'; +const kErrorCode = -1; +const kStartCode = 0; +const kCloseCode = 1; +const kDeletedCode = 2; + +void isolateSpawnEntrypoint(SendPort port) { + sendHelper(int code, [String message = '']) { + port.send([code, message]); + } + + SendPort shared = IsolateNameServer.lookupPortByName(kPortName); + if (shared == null) { + sendHelper(kErrorCode, 'Could not find port: $kPortName'); + return; + } + + // ack that the SendPort lookup was successful. + sendHelper(kStartCode); + + //shared.send(kPortName); + sendHelper(kCloseCode); + + // We'll fail if the ReceivePort's callback is called more than once. Try to + // send another message to ensure we don't crash. + shared.send('garbage'); + + bool result = IsolateNameServer.removePortNameMapping(kPortName); + if (result) { + sendHelper(kDeletedCode); + } else { + sendHelper(kErrorCode, 'Was unable to remove mapping for $kPortName'); + } +} + +void main() { + tearDown(() { + IsolateNameServer.removePortNameMapping(kPortName); + }); + + test('simple isolate name server', () { + // Mapping for 'foobar' isn't set. Check these cases to ensure correct + // negative response. + expect(IsolateNameServer.lookupPortByName(kPortName), isNull); + expect(IsolateNameServer.removePortNameMapping(kPortName), isFalse); + + // Register a SendPort. + final receivePort = new ReceivePort(); + final sendPort = receivePort.sendPort; + expect(IsolateNameServer.registerPortWithName(sendPort, kPortName), isTrue); + expect(IsolateNameServer.lookupPortByName(kPortName), sendPort); + + // Check we can't register the same name twice. + final receivePort2 = new ReceivePort(); + final sendPort2 = receivePort2.sendPort; + expect( + IsolateNameServer.registerPortWithName(sendPort2, kPortName), isFalse); + expect(IsolateNameServer.lookupPortByName(kPortName), sendPort); + + // Remove the mapping. + expect(IsolateNameServer.removePortNameMapping(kPortName), isTrue); + expect(IsolateNameServer.lookupPortByName(kPortName), isNull); + + // Ensure registering a new port with the old name returns the new port. + expect( + IsolateNameServer.registerPortWithName(sendPort2, kPortName), isTrue); + expect(IsolateNameServer.lookupPortByName(kPortName), sendPort2); + }); + + test('isolate name server null args', () { + // None of our IsolateNameServer methods should accept null. + expect(() => IsolateNameServer.lookupPortByName(null), throwsArgumentError); + expect(() => IsolateNameServer.registerPortWithName(null, 'abc'), + throwsArgumentError); + final receivePort = new ReceivePort(); + final sendPort = receivePort.sendPort; + expect(() => IsolateNameServer.registerPortWithName(sendPort, null), + throwsArgumentError); + expect(() => IsolateNameServer.removePortNameMapping(null), + throwsArgumentError); + }); + + test('isolate name server multi-isolate', () async { + // Register our send port with the name server. + final receivePort = new ReceivePort(); + final sendPort = receivePort.sendPort; + expect(IsolateNameServer.registerPortWithName(sendPort, kPortName), isTrue); + + // Test driver. + final testReceivePort = new ReceivePort(); + testReceivePort.listen(expectAsync1((List response) { + final int code = response[0]; + final String message = response[1]; + switch (code) { + case kStartCode: + break; + case kCloseCode: + receivePort.close(); + break; + case kDeletedCode: + expect(IsolateNameServer.lookupPortByName(kPortName), isNull); + break; + case kErrorCode: + throw message; + default: + throw 'UNREACHABLE'; + } + }, count: 3)); + + receivePort.listen(expectAsync1((message) { + // If we don't get this message, we timeout and fail. + expect(message, kPortName); + })); + + // Run the test. + await Isolate.spawn(isolateSpawnEntrypoint, testReceivePort.sendPort); + }); +} diff --git a/testing/run_tests.sh b/testing/run_tests.sh index 73579c97160c3..26e9401d43d91 100755 --- a/testing/run_tests.sh +++ b/testing/run_tests.sh @@ -4,7 +4,6 @@ set -ex out/host_debug_unopt/fxl_unittests out/host_debug_unopt/synchronization_unittests -out/host_debug_unopt/wtf_unittests flutter/travis/analyze.sh diff --git a/travis/licenses_golden/licenses_flutter b/travis/licenses_golden/licenses_flutter index a66035fa469c5..222cc2f4523e4 100644 --- a/travis/licenses_golden/licenses_flutter +++ b/travis/licenses_golden/licenses_flutter @@ -490,6 +490,7 @@ LIBRARY: engine ORIGIN: ../../../flutter/flutter_kernel_transformers/lib/track_widget_constructor_locations.dart + ../../../LICENSE TYPE: LicenseType.bsd FILE: ../../../flutter/flutter_kernel_transformers/lib/track_widget_constructor_locations.dart +FILE: ../../../flutter/lib/ui/isolate_name_server.dart FILE: ../../../flutter/lib/ui/painting/image_encoding.cc FILE: ../../../flutter/lib/ui/painting/image_encoding.h FILE: ../../../flutter/shell/platform/android/apk_asset_provider.h @@ -580,6 +581,10 @@ FILE: ../../../flutter/fml/platform/win/wstring_conversion.h FILE: ../../../flutter/fml/unique_fd.cc FILE: ../../../flutter/fml/unique_fd.h FILE: ../../../flutter/fml/unique_object.h +FILE: ../../../flutter/lib/ui/isolate_name_server/isolate_name_server.cc +FILE: ../../../flutter/lib/ui/isolate_name_server/isolate_name_server.h +FILE: ../../../flutter/lib/ui/isolate_name_server/isolate_name_server_natives.cc +FILE: ../../../flutter/lib/ui/isolate_name_server/isolate_name_server_natives.h FILE: ../../../flutter/shell/common/isolate_configuration.cc FILE: ../../../flutter/shell/common/isolate_configuration.h FILE: ../../../flutter/shell/platform/android/android_shell_holder.cc