diff options
429 files changed, 1421 insertions, 44410 deletions
@@ -178,25 +178,18 @@ group("both_gn_and_gyp") { "//media/midi:midi_unittests", "//mojo", "//mojo/common:mojo_common_unittests", + "//mojo/edk/system:mojo_system_unittests", + "//mojo/edk/test:mojo_public_bindings_unittests", + "//mojo/edk/test:mojo_public_environment_unittests", + "//mojo/edk/test:mojo_public_system_unittests", + "//mojo/edk/test:mojo_public_utility_unittests", "//mojo/shell/public/cpp", "//net:net_perftests", - - # TODO(use-new-edk): - #"//mojo/edk/system:mojo_system_unittests", - #"//mojo/edk/test:mojo_public_bindings_unittests", - #"//mojo/edk/test:mojo_public_environment_unittests", - #"//mojo/edk/test:mojo_public_system_unittests", - #"//mojo/edk/test:mojo_public_utility_unittests", "//third_party/WebKit/Source/platform:blink_heap_unittests", "//third_party/WebKit/Source/platform:blink_platform_unittests", "//third_party/WebKit/Source/web:webkit_unit_tests", "//third_party/WebKit/Source/wtf:wtf_unittests", "//third_party/catapult/telemetry:bitmaptools($host_toolchain)", - "//third_party/mojo/src/mojo/edk/system:mojo_system_unittests", - "//third_party/mojo/src/mojo/edk/test:mojo_public_bindings_unittests", - "//third_party/mojo/src/mojo/edk/test:mojo_public_environment_unittests", - "//third_party/mojo/src/mojo/edk/test:mojo_public_system_unittests", - "//third_party/mojo/src/mojo/edk/test:mojo_public_utility_unittests", "//third_party/smhasher:pmurhash", "//tools/imagediff($host_toolchain)", "//ui/display:display_unittests", @@ -499,13 +492,10 @@ group("both_gn_and_gyp") { # TODO(GYP): Remove this when the gles2 tests work "//gpu/command_buffer/client:gles2_implementation_no_check", "//gpu/khronos_glcts_support:khronos_glcts_test", # TODO(GYP) crbug.com/471903 to make this complete. + "//mojo/edk/test:mojo_public_system_perftests", "//mojo/shell/public/cpp", "//testing/gmock:gmock_main", - - # TODO(use-new-edk): - #"//mojo/edk/test:mojo_public_system_perftests", "//third_party/codesighs:nm2tsv", - "//third_party/mojo/src/mojo/edk/test:mojo_public_system_perftests", ] if (!is_android) { @@ -764,9 +754,6 @@ group("gn_mojo_targets") { "//media/mojo:tests", "//media/mojo/services:cdm_service", "//mojo:tests", - - # TODO(use-new-edk): - #"//mojo/edk/js/tests:js_to_cpp_bindings_python", ] } } diff --git a/build/all.gyp b/build/all.gyp index cff1ff8..c62c52d 100644 --- a/build/all.gyp +++ b/build/all.gyp @@ -55,17 +55,17 @@ '../mojo/mojo_base.gyp:mojo_common_lib', '../mojo/mojo_base.gyp:mojo_common_unittests', '../mojo/mojo_base.gyp:mojo_environment_chromium', + '../mojo/mojo_edk.gyp:mojo_system_impl', + '../mojo/mojo_edk_tests.gyp:mojo_public_bindings_unittests', + '../mojo/mojo_edk_tests.gyp:mojo_public_environment_unittests', + '../mojo/mojo_edk_tests.gyp:mojo_public_system_unittests', + '../mojo/mojo_edk_tests.gyp:mojo_public_utility_unittests', + '../mojo/mojo_edk_tests.gyp:mojo_system_unittests', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', + '../mojo/mojo_public.gyp:mojo_public_test_utils', + '../mojo/mojo_public.gyp:mojo_system', '../google_apis/google_apis.gyp:google_apis_unittests', '../skia/skia_tests.gyp:skia_unittests', - '../third_party/mojo/mojo_edk.gyp:mojo_system_impl', - '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_bindings_unittests', - '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_environment_unittests', - '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_system_unittests', - '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_utility_unittests', - '../third_party/mojo/mojo_edk_tests.gyp:mojo_system_unittests', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', - '../third_party/mojo/mojo_public.gyp:mojo_public_test_utils', - '../third_party/mojo/mojo_public.gyp:mojo_system', '../ui/base/ui_base_tests.gyp:ui_base_unittests', '../ui/gfx/gfx_tests.gyp:gfx_unittests', ], diff --git a/build/gn_migration.gypi b/build/gn_migration.gypi index 7464d78..db63977 100644 --- a/build/gn_migration.gypi +++ b/build/gn_migration.gypi @@ -281,6 +281,12 @@ '../google_apis/google_apis.gyp:google_apis_unittests', '../jingle/jingle.gyp:jingle_unittests', '../mojo/mojo.gyp:mojo', + '../mojo/mojo_edk_tests.gyp:mojo_system_unittests', + '../mojo/mojo_edk_tests.gyp:mojo_public_bindings_unittests', + '../mojo/mojo_edk_tests.gyp:mojo_public_environment_unittests', + '../mojo/mojo_edk_tests.gyp:mojo_public_system_perftests', + '../mojo/mojo_edk_tests.gyp:mojo_public_system_unittests', + '../mojo/mojo_edk_tests.gyp:mojo_public_utility_unittests', '../net/net.gyp:crash_cache', '../net/net.gyp:crl_set_dump', '../net/net.gyp:dns_fuzz_stub', @@ -332,12 +338,6 @@ '../sync/sync.gyp:run_sync_testserver', '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests', '../third_party/libphonenumber/libphonenumber.gyp:libphonenumber_unittests', - '../third_party/mojo/mojo_edk_tests.gyp:mojo_system_unittests', - '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_bindings_unittests', - '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_environment_unittests', - '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_system_perftests', - '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_system_unittests', - '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_utility_unittests', '../tools/imagediff/image_diff.gyp:image_diff', '../ui/app_list/app_list.gyp:app_list_unittests', '../ui/compositor/compositor.gyp:compositor_unittests', @@ -567,6 +567,10 @@ '../media/cast/cast.gyp:cast_unittests_run', '../media/media.gyp:media_unittests_run', '../media/midi/midi.gyp:midi_unittests_run', + '../mojo/mojo_edk_tests.gyp:mojo_public_bindings_unittests_run', + '../mojo/mojo_edk_tests.gyp:mojo_public_environment_unittests_run', + '../mojo/mojo_edk_tests.gyp:mojo_public_system_unittests_run', + '../mojo/mojo_edk_tests.gyp:mojo_public_utility_unittests_run', '../net/net.gyp:net_unittests_run', '../printing/printing.gyp:printing_unittests_run', '../remoting/remoting.gyp:remoting_unittests_run', @@ -578,10 +582,6 @@ '../third_party/WebKit/Source/web/web_tests.gyp:webkit_unit_tests_run', '../third_party/WebKit/Source/wtf/wtf_tests.gyp:wtf_unittests_run', '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests_run', - '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_bindings_unittests_run', - '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_environment_unittests_run', - '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_system_unittests_run', - '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_utility_unittests_run', '../tools/battor_agent/battor_agent.gyp:battor_agent_unittests_run', '../tools/gn/gn.gyp:gn_unittests_run', '../ui/accessibility/accessibility.gyp:accessibility_unittests_run', diff --git a/build/rmdir_and_stamp.py b/build/rmdir_and_stamp.py index 6aa11f8..8f046ea 100755 --- a/build/rmdir_and_stamp.py +++ b/build/rmdir_and_stamp.py @@ -21,7 +21,7 @@ The general pattern of use is: The net result is that you will force |out_path| to be wiped and all |gen_sources| to be regenerated any time any file in |inputs| changes. -See //third_party/mojo/mojom_bindings_generator.gypi for an example use case. +See //mojo/mojom_bindings_generator.gypi for an example use case. """ diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 807bd48..7cfd4d9 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn @@ -364,6 +364,7 @@ source_set("browser") { "//media", "//media/midi", "//mojo/common", + "//mojo/edk/system", "//mojo/environment:chromium", "//mojo/public/cpp/bindings", "//mojo/public/js", @@ -378,7 +379,6 @@ source_set("browser") { "//third_party/leveldatabase", "//third_party/libaddressinput", "//third_party/libyuv", - "//third_party/mojo/src/mojo/edk/system", "//third_party/re2", "//third_party/smhasher:cityhash", "//third_party/webrtc/modules/desktop_capture", diff --git a/chrome/browser/media/router/media_router.gyp b/chrome/browser/media/router/media_router.gyp index 69136ce..78c49b4 100644 --- a/chrome/browser/media/router/media_router.gyp +++ b/chrome/browser/media/router/media_router.gyp @@ -47,7 +47,7 @@ 'media_router.mojom', ], 'includes': [ - '../../../../third_party/mojo/mojom_bindings_generator.gypi', + '../../../../mojo/mojom_bindings_generator.gypi', ], }, { diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 7b6003b..97023a7e 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn @@ -123,6 +123,7 @@ source_set("ui") { "//components/url_formatter", "//device/nfc", "//media", + "//mojo/edk/system", "//net:net_with_v8", "//net:stale_while_revalidate_experiment_domains", "//storage/browser", @@ -131,7 +132,6 @@ source_set("ui") { "//third_party/adobe/flash:flapper_version_h", "//third_party/leveldatabase", "//third_party/libjingle", - "//third_party/mojo/src/mojo/edk/system", "//third_party/re2", "//ui/base/ime", "//ui/compositor", diff --git a/chrome/browser/ui/libgtk2ui/BUILD.gn b/chrome/browser/ui/libgtk2ui/BUILD.gn index 9b1c927..df0649d 100644 --- a/chrome/browser/ui/libgtk2ui/BUILD.gn +++ b/chrome/browser/ui/libgtk2ui/BUILD.gn @@ -100,10 +100,10 @@ component("libgtk2ui") { "//chrome/app/theme:theme_resources", "//components/resources", "//content/public/browser", + "//mojo/edk/system", "//mojo/environment:chromium", "//printing", "//skia", - "//third_party/mojo/src/mojo/edk/system", "//ui/aura", "//ui/base", "//ui/base/ime", diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 5f32c6c..cd5d21a 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -3332,6 +3332,9 @@ '../mojo/mojo_base.gyp:mojo_environment_chromium', '../mojo/mojo_base.gyp:mojo_message_pump_lib', '../mojo/mojo_base.gyp:mojo_url_type_converters', + '../mojo/mojo_edk.gyp:mojo_system_impl', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', + '../mojo/mojo_public.gyp:mojo_js_bindings', '../net/net.gyp:net_extras', '../net/net.gyp:net_with_v8', '../storage/storage_browser.gyp:storage', @@ -3339,9 +3342,6 @@ '../third_party/leveldatabase/leveldatabase.gyp:leveldatabase', '../third_party/libaddressinput/libaddressinput.gyp:libaddressinput', '../third_party/libyuv/libyuv.gyp:libyuv', - '../third_party/mojo/mojo_edk.gyp:mojo_system_impl', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', - '../third_party/mojo/mojo_public.gyp:mojo_js_bindings', '../third_party/smhasher/smhasher.gyp:cityhash', '../third_party/webrtc/modules/modules.gyp:desktop_capture', '../ui/base/ime/ui_base_ime.gyp:ui_base_ime', diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index 9afbb25..8947387 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi @@ -2930,12 +2930,12 @@ '../components/components_resources.gyp:components_resources', '../content/app/resources/content_resources.gyp:content_resources', '../media/media.gyp:media', + '../mojo/mojo_edk.gyp:mojo_system_impl', '../net/net.gyp:net_with_v8', '../net/net.gyp:stale_while_revalidate_experiment_domains', '../storage/storage_browser.gyp:storage', '../storage/storage_common.gyp:storage_common', '../third_party/leveldatabase/leveldatabase.gyp:leveldatabase', - '../third_party/mojo/mojo_edk.gyp:mojo_system_impl', '../third_party/re2/re2.gyp:re2', '../ui/base/ime/ui_base_ime.gyp:ui_base_ime', '../ui/compositor/compositor.gyp:compositor', diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi index 51e06d4b..dc732b1 100644 --- a/chrome/chrome_common.gypi +++ b/chrome/chrome_common.gypi @@ -635,14 +635,14 @@ 'target_name': 'common_mojo_bindings', 'type': 'static_library', 'includes': [ - '../third_party/mojo/mojom_bindings_generator.gypi' + '../mojo/mojom_bindings_generator.gypi' ], 'sources': [ 'common/resource_usage_reporter.mojom', ], 'dependencies': [ '../mojo/mojo_base.gyp:mojo_environment_chromium', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', ], }, ], diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 04181b5..3e0032f 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi @@ -2172,11 +2172,11 @@ 'test_support_common', '../base/base.gyp:base', '../mojo/mojo_base.gyp:mojo_environment_chromium', + '../mojo/mojo_edk.gyp:mojo_system_impl', '../skia/skia.gyp:skia', '../sync/sync.gyp:sync', '../testing/gmock.gyp:gmock', '../testing/gtest.gyp:gtest', - '../third_party/mojo/mojo_edk.gyp:mojo_system_impl', ], 'include_dirs': [ '..', diff --git a/chrome/chrome_web_ui_mojo_bindings.gyp b/chrome/chrome_web_ui_mojo_bindings.gyp index 7e2842a..b56eb28 100644 --- a/chrome/chrome_web_ui_mojo_bindings.gyp +++ b/chrome/chrome_web_ui_mojo_bindings.gyp @@ -17,7 +17,7 @@ # GN version: //chrome/browser/ui/webui/plugins:mojo_bindings 'browser/ui/webui/plugins/plugins.mojom', ], - 'includes': [ '../third_party/mojo/mojom_bindings_generator.gypi' ], + 'includes': [ '../mojo/mojom_bindings_generator.gypi' ], }, ], } diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index ae1e09d..bc6d227 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn @@ -2191,8 +2191,8 @@ source_set("test_support_unit") { "//chrome:strings", "//chrome/browser", "//chrome/common", + "//mojo/edk/system", "//mojo/environment:chromium", - "//third_party/mojo/src/mojo/edk/system", ] if (!is_android && use_ash) { diff --git a/chrome/test/DEPS b/chrome/test/DEPS index 2167a41..ed43ea1 100644 --- a/chrome/test/DEPS +++ b/chrome/test/DEPS @@ -19,8 +19,8 @@ include_rules = [ "+gin/public", "+grit", # For generated headers. TODO(thestig): Remove. "+media/base", + "+mojo/edk/embedder", "+sandbox/win/tests", - "+third_party/mojo/src/mojo/edk/embedder", "+third_party/ocmock", "+win8/test", ] diff --git a/chrome/test/base/run_all_unittests.cc b/chrome/test/base/run_all_unittests.cc index 1e43697..60f2d3a 100644 --- a/chrome/test/base/run_all_unittests.cc +++ b/chrome/test/base/run_all_unittests.cc @@ -7,16 +7,12 @@ #include "base/test/launcher/unit_test_launcher.h" #include "chrome/test/base/chrome_unit_test_suite.h" #include "content/public/test/unittest_test_suite.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/embedder.h" int main(int argc, char **argv) { content::UnitTestTestSuite test_suite(new ChromeUnitTestSuite(argc, argv)); - // TODO(use_chrome_edk): This flag will go away and be default behavior soon, - // but we explicitly add it here for test coverage. - base::CommandLine::ForCurrentProcess()->AppendSwitch("use-new-edk"); - - mojo::embedder::Init(); + mojo::edk::Init(); return base::LaunchUnitTests( argc, argv, base::Bind(&content::UnitTestTestSuite::Run, base::Unretained(&test_suite))); diff --git a/chromecast/chromecast_tests.gypi b/chromecast/chromecast_tests.gypi index 4bd94b8..dfb1a23 100644 --- a/chromecast/chromecast_tests.gypi +++ b/chromecast/chromecast_tests.gypi @@ -323,8 +323,8 @@ 'cast_shell_core', '../content/content_shell_and_tests.gyp:content_browser_test_base', '../content/content_shell_and_tests.gyp:content_browser_test_support', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', '../testing/gtest.gyp:gtest', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', ], 'export_dependent_settings': [ '../content/content_shell_and_tests.gyp:content_browser_test_base', diff --git a/components/BUILD.gn b/components/BUILD.gn index 1ae5399..0125273 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn @@ -69,9 +69,9 @@ test("components_unittests") { "//components/variations:unit_tests", "//components/variations/service:unit_tests", "//components/web_resource:unit_tests", + "//mojo/edk/embedder:headers", "//net", "//testing/gtest", - "//third_party/mojo/src/mojo/edk/embedder:headers", "//ui/base", "//ui/resources:ui_test_pak", ] diff --git a/components/arc.gypi b/components/arc.gypi index 4926f87..dc465ba 100644 --- a/components/arc.gypi +++ b/components/arc.gypi @@ -79,7 +79,7 @@ 'target_name': 'arc_mojo_bindings', 'type': 'static_library', 'includes': [ - '../third_party/mojo/mojom_bindings_generator.gypi', + '../mojo/mojom_bindings_generator.gypi', ], 'sources': [ 'arc/common/app.mojom', diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn index c856bcb..f11c2bf 100644 --- a/components/arc/BUILD.gn +++ b/components/arc/BUILD.gn @@ -43,7 +43,7 @@ static_library("arc") { "//google_apis", "//ipc:ipc", "//ipc/mojo:mojo", - "//third_party/mojo/src/mojo/edk/system", + "//mojo/edk/system", "//ui/arc", "//ui/aura", "//ui/base:base", diff --git a/components/arc/DEPS b/components/arc/DEPS index 2f5f4b8..bcfc65a 100644 --- a/components/arc/DEPS +++ b/components/arc/DEPS @@ -6,6 +6,5 @@ include_rules = [ "+components/signin/core/account_id", "+ipc", "+mojo", - "+third_party/mojo", "+ui/arc", ] diff --git a/components/arc/input/arc_input_bridge.cc b/components/arc/input/arc_input_bridge.cc index d4e8e8f..4a797e8 100644 --- a/components/arc/input/arc_input_bridge.cc +++ b/components/arc/input/arc_input_bridge.cc @@ -15,7 +15,7 @@ #include "base/thread_task_runner_handle.h" #include "base/time/time.h" #include "components/arc/arc_bridge_service.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/embedder.h" #include "ui/aura/env.h" #include "ui/aura/env_observer.h" #include "ui/aura/window.h" @@ -346,9 +346,9 @@ base::ScopedFD ArcInputBridge::CreateBridgeInputDevice( return base::ScopedFD(); } MojoHandle wrapped_handle; - MojoResult wrap_result = mojo::embedder::CreatePlatformHandleWrapper( - mojo::embedder::ScopedPlatformHandle( - mojo::embedder::PlatformHandle(read_fd.release())), + MojoResult wrap_result = mojo::edk::CreatePlatformHandleWrapper( + mojo::edk::ScopedPlatformHandle( + mojo::edk::PlatformHandle(read_fd.release())), &wrapped_handle); if (wrap_result != MOJO_RESULT_OK) { LOG(WARNING) << "Pipe failed to wrap handles. Closing: " << wrap_result; diff --git a/components/arc/net/arc_net_host_impl.cc b/components/arc/net/arc_net_host_impl.cc index bca78b1..0b8c226 100644 --- a/components/arc/net/arc_net_host_impl.cc +++ b/components/arc/net/arc_net_host_impl.cc @@ -16,7 +16,6 @@ #include "chromeos/network/network_util.h" #include "chromeos/network/onc/onc_utils.h" #include "components/arc/arc_bridge_service.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" namespace { diff --git a/components/contextual_search.gypi b/components/contextual_search.gypi index d9f323e..32a1e00 100644 --- a/components/contextual_search.gypi +++ b/components/contextual_search.gypi @@ -50,7 +50,7 @@ 'contextual_search/common/overlay_page_notifier_service.mojom', ], 'includes': [ - '../third_party/mojo/mojom_bindings_generator.gypi', + '../mojo/mojom_bindings_generator.gypi', ], }, ], diff --git a/components/dom_distiller.gypi b/components/dom_distiller.gypi index 59dc03e..b6d25e3 100644 --- a/components/dom_distiller.gypi +++ b/components/dom_distiller.gypi @@ -144,7 +144,7 @@ 'dom_distiller/content/common/distiller_page_notifier_service.mojom', ], 'includes': [ - '../third_party/mojo/mojom_bindings_generator.gypi', + '../mojo/mojom_bindings_generator.gypi', ], }, ], @@ -163,10 +163,10 @@ '../base/base.gyp:base', '../content/content.gyp:content_browser', '../mojo/mojo_base.gyp:mojo_environment_chromium', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', '../net/net.gyp:net', '../skia/skia.gyp:skia', '../sync/sync.gyp:sync', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', '../ui/gfx/gfx.gyp:gfx', '../url/url.gyp:url_lib', 'components_resources.gyp:components_resources', @@ -215,7 +215,7 @@ '../content/content.gyp:content_browser', '../gin/gin.gyp:gin', '../mojo/mojo_base.gyp:mojo_environment_chromium', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', ], 'include_dirs': [ '..', diff --git a/components/message_port.gypi b/components/message_port.gypi index 7891058..232782c 100644 --- a/components/message_port.gypi +++ b/components/message_port.gypi @@ -10,8 +10,8 @@ 'dependencies': [ '../base/base.gyp:base', '../mojo/mojo_base.gyp:mojo_message_pump_lib', + '../mojo/mojo_public.gyp:mojo_system_cpp_headers', '../third_party/WebKit/public/blink.gyp:blink', - '../third_party/mojo/mojo_public.gyp:mojo_system_cpp_headers', ], 'include_dirs': [ '..', diff --git a/components/mus/public/cpp/tests/BUILD.gn b/components/mus/public/cpp/tests/BUILD.gn index f7c2b25..dde0ebf 100644 --- a/components/mus/public/cpp/tests/BUILD.gn +++ b/components/mus/public/cpp/tests/BUILD.gn @@ -54,12 +54,12 @@ test("mojo_view_manager_lib_unittests") { "//mojo/common:common_base", "//mojo/converters/geometry", "//mojo/converters/input_events", + "//mojo/edk/system", "//mojo/gles2", "//mojo/platform_handle:platform_handle_impl", "//mojo/public/cpp/system", "//mojo/shell/public/cpp", "//testing/gtest", - "//third_party/mojo/src/mojo/edk/system", "//ui/events", "//ui/gfx:test_support", "//ui/gfx/geometry", diff --git a/components/mus/ws/BUILD.gn b/components/mus/ws/BUILD.gn index 2c7a358..1e443a9 100644 --- a/components/mus/ws/BUILD.gn +++ b/components/mus/ws/BUILD.gn @@ -151,13 +151,13 @@ test("window_manager_unittests") { "//mojo/converters/geometry", "//mojo/converters/input_events", "//mojo/converters/transform", + "//mojo/edk/test:run_all_unittests", "//mojo/environment:chromium", "//mojo/gles2", "//mojo/platform_handle", "//mojo/public/cpp/bindings:bindings", "//mojo/shell/public/interfaces", "//testing/gtest", - "//third_party/mojo/src/mojo/edk/test:run_all_unittests", "//ui/events", "//ui/gfx", "//ui/gfx:test_support", diff --git a/components/nacl/loader/BUILD.gn b/components/nacl/loader/BUILD.gn index 6a8c161..7b28bf0 100644 --- a/components/nacl/loader/BUILD.gn +++ b/components/nacl/loader/BUILD.gn @@ -62,7 +62,6 @@ source_set("loader") { "//components/nacl/common", "//content/public/common", "//ppapi/shared_impl", - "//third_party/mojo/src/mojo/edk/system", ] data_deps = [ diff --git a/components/nacl/loader/DEPS b/components/nacl/loader/DEPS index a576f05..3bd1ff1 100644 --- a/components/nacl/loader/DEPS +++ b/components/nacl/loader/DEPS @@ -29,6 +29,4 @@ include_rules = [ # For sending PpapiHostMsg_ChannelCreated in nacl_ipc_adapter.cc: "+ppapi/proxy/ppapi_messages.h", - - "+third_party/mojo/src/mojo/edk", ] diff --git a/components/resource_provider/BUILD.gn b/components/resource_provider/BUILD.gn index fd2d6d1..e8bd971 100644 --- a/components/resource_provider/BUILD.gn +++ b/components/resource_provider/BUILD.gn @@ -118,10 +118,10 @@ test("resource_provider_unittests") { "//base", "//base/test:test_config", "//components/resource_provider/public/interfaces", + "//mojo/edk/test:run_all_unittests", "//mojo/environment:chromium", "//mojo/platform_handle:for_shared_library", "//testing/gtest", - "//third_party/mojo/src/mojo/edk/test:run_all_unittests", "//url", ] } diff --git a/components/test/DEPS b/components/test/DEPS index b29feef..5fe4887 100644 --- a/components/test/DEPS +++ b/components/test/DEPS @@ -11,6 +11,6 @@ include_rules = [ specific_include_rules = { "run_all_unittests\.cc": [ - "+third_party/mojo/src/mojo/edk/embedder/embedder.h", + "+mojo/edk/embedder/embedder.h", ], } diff --git a/components/test/run_all_unittests.cc b/components/test/run_all_unittests.cc index bb8caa4..4263b42 100644 --- a/components/test/run_all_unittests.cc +++ b/components/test/run_all_unittests.cc @@ -36,7 +36,7 @@ #endif #if defined(OS_CHROMEOS) -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/embedder.h" #endif namespace { @@ -138,10 +138,6 @@ class ComponentsUnitTestEventListener : public testing::EmptyTestEventListener { int main(int argc, char** argv) { ComponentsTestSuite test_suite(argc, argv); - // TODO(use_chrome_edk): This flag will go away and be default behavior soon, - // but we explicitly add it here for test coverage. - base::CommandLine::ForCurrentProcess()->AppendSwitch("use-new-edk"); - // The listener will set up common test environment for all components unit // tests. testing::TestEventListeners& listeners = @@ -149,7 +145,7 @@ int main(int argc, char** argv) { listeners.Append(new ComponentsUnitTestEventListener()); #if defined(OS_CHROMEOS) - mojo::embedder::Init(); + mojo::edk::Init(); #endif return base::LaunchUnitTests( diff --git a/components/webusb.gypi b/components/webusb.gypi index a86c548..0581395 100644 --- a/components/webusb.gypi +++ b/components/webusb.gypi @@ -34,7 +34,7 @@ ], }, 'includes': [ - '../third_party/mojo/mojom_bindings_generator_explicit.gypi', + '../mojo/mojom_bindings_generator_explicit.gypi', ], }, { diff --git a/content/DEPS b/content/DEPS index 66c8738..b7cda85 100644 --- a/content/DEPS +++ b/content/DEPS @@ -29,6 +29,9 @@ include_rules = [ "+dbus", "+gpu", "+mojo/common", + "+mojo/edk/embedder", + "+mojo/edk/js", + "+mojo/edk/test", "+mojo/message_pump", "+mojo/public", "+net", @@ -57,9 +60,6 @@ include_rules = [ "+third_party/angle", "+third_party/flac", "+third_party/libjingle", - "+third_party/mojo/src/mojo/edk/embedder", - "+third_party/mojo/src/mojo/edk/js", - "+third_party/mojo/src/mojo/edk/test", "+third_party/mozilla", "+third_party/npapi/bindings", "+third_party/ocmock", diff --git a/content/app/BUILD.gn b/content/app/BUILD.gn index f3d476c..435a39e 100644 --- a/content/app/BUILD.gn +++ b/content/app/BUILD.gn @@ -58,8 +58,8 @@ if (is_ios) { } else { content_app_deps += [ "//mojo/shell/public/interfaces", + "//mojo/edk/system", "//mojo/environment:chromium", - "//third_party/mojo/src/mojo/edk/system", ] } diff --git a/content/app/mojo/mojo_init.cc b/content/app/mojo/mojo_init.cc index 07e4d5a..828887d 100644 --- a/content/app/mojo/mojo_init.cc +++ b/content/app/mojo/mojo_init.cc @@ -9,11 +9,7 @@ #include "base/memory/scoped_ptr.h" #include "content/public/common/content_switches.h" #include "ipc/ipc_channel.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" - -#if defined(MOJO_SHELL_CLIENT) -#include "content/common/mojo/mojo_shell_connection_impl.h" -#endif +#include "mojo/edk/embedder/embedder.h" namespace content { @@ -22,30 +18,8 @@ namespace { class MojoInitializer { public: MojoInitializer() { - const base::CommandLine& command_line = - *base::CommandLine::ForCurrentProcess(); - std::string process_type = - command_line.GetSwitchValueASCII(switches::kProcessType); - if (process_type.empty() && !command_line.HasSwitch("use-old-edk")) { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - "use-new-edk"); - } - - if (command_line.HasSwitch("use-new-edk")) { - bool initialize_as_parent = process_type.empty(); -#if defined(MOJO_SHELL_CLIENT) - if (IsRunningInMojoShell()) - initialize_as_parent = false; -#endif - if (initialize_as_parent) { - mojo::embedder::PreInitializeParentProcess(); - } else { - mojo::embedder::PreInitializeChildProcess(); - } - } - - mojo::embedder::SetMaxMessageSize(IPC::Channel::kMaximumMessageSize); - mojo::embedder::Init(); + mojo::edk::SetMaxMessageSize(IPC::Channel::kMaximumMessageSize); + mojo::edk::Init(); } }; diff --git a/content/browser/browser_child_process_host_impl.cc b/content/browser/browser_child_process_host_impl.cc index fee0a1f..5380cd7 100644 --- a/content/browser/browser_child_process_host_impl.cc +++ b/content/browser/browser_child_process_host_impl.cc @@ -35,7 +35,7 @@ #include "content/public/common/result_codes.h" #include "ipc/attachment_broker.h" #include "ipc/attachment_broker_privileged.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/embedder.h" #if defined(OS_MACOSX) #include "content/browser/mach_broker_mac.h" @@ -195,7 +195,6 @@ void BrowserChildProcessHostImpl::Launch( switches::kTraceToConsole, switches::kV, switches::kVModule, - "use-new-edk", // TODO(use_chrome_edk): temporary. }; cmd_line->CopySwitchesFrom(browser_command_line, kForwardSwitches, arraysize(kForwardSwitches)); @@ -414,18 +413,10 @@ void BrowserChildProcessHostImpl::OnProcessLaunched() { const base::Process& process = child_process_->GetProcess(); DCHECK(process.IsValid()); - if (base::CommandLine::ForCurrentProcess()->HasSwitch("use-new-edk")) { - mojo::embedder::ScopedPlatformHandle client_pipe = - mojo::embedder::ChildProcessLaunched(process.Handle()); - Send(new ChildProcessMsg_SetMojoParentPipeHandle( - IPC::GetFileHandleForProcess( -#if defined(OS_WIN) - client_pipe.release().handle, -#else - client_pipe.release().fd, -#endif - process.Handle(), true))); - } + mojo::edk::ScopedPlatformHandle client_pipe = + mojo::edk::ChildProcessLaunched(process.Handle()); + Send(new ChildProcessMsg_SetMojoParentPipeHandle(IPC::GetFileHandleForProcess( + client_pipe.release().handle, process.Handle(), true))); #if defined(OS_WIN) // Start a WaitableEventWatcher that will invoke OnProcessExitedEarly if the diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 82861af..43f6288 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc @@ -180,7 +180,6 @@ #include "content/common/mojo/mojo_shell_connection_impl.h" #include "mojo/converters/network/network_type_converters.h" #include "mojo/shell/public/cpp/shell.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" #include "ui/views/mus/window_manager_connection.h" #endif @@ -918,7 +917,6 @@ int BrowserMainLoop::CreateThreads() { int BrowserMainLoop::PreMainMessageLoopRun() { #if defined(MOJO_SHELL_CLIENT) if (IsRunningInMojoShell()) { - mojo::embedder::PreInitializeChildProcess(); MojoShellConnectionImpl::Create(); MojoShellConnectionImpl::Get()->BindToCommandLinePlatformChannel(); #if defined(USE_AURA) diff --git a/content/browser/mojo/mojo_application_host.cc b/content/browser/mojo/mojo_application_host.cc index cc2c74a..1c3ed37 100644 --- a/content/browser/mojo/mojo_application_host.cc +++ b/content/browser/mojo/mojo_application_host.cc @@ -10,20 +10,11 @@ #include "content/common/mojo/mojo_messages.h" #include "content/public/browser/browser_thread.h" #include "ipc/ipc_sender.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" +#include "mojo/edk/embedder/platform_channel_pair.h" namespace content { namespace { -base::PlatformFile PlatformFileFromScopedPlatformHandle( - mojo::embedder::ScopedPlatformHandle handle) { -#if defined(OS_POSIX) - return handle.release().fd; -#elif defined(OS_WIN) - return handle.release().handle; -#endif -} - class ApplicationSetupImpl : public ApplicationSetup { public: ApplicationSetupImpl(ServiceRegistryImpl* service_registry, @@ -62,7 +53,7 @@ MojoApplicationHost::~MojoApplicationHost() { bool MojoApplicationHost::Init() { DCHECK(!client_handle_.is_valid()) << "Already initialized!"; - mojo::embedder::PlatformChannelPair channel_pair; + mojo::edk::PlatformChannelPair channel_pair; scoped_refptr<base::TaskRunner> io_task_runner; if (io_task_runner_override_) { @@ -76,8 +67,7 @@ bool MojoApplicationHost::Init() { // Forward this to the client once we know its process handle. client_handle_ = channel_pair.PassClientHandle(); mojo::ScopedMessagePipeHandle pipe = channel_init_.Init( - PlatformFileFromScopedPlatformHandle(channel_pair.PassServerHandle()), - io_task_runner); + channel_pair.PassServerHandle().release().handle, io_task_runner); application_setup_.reset(new ApplicationSetupImpl( &service_registry_, mojo::MakeRequest<ApplicationSetup>(std::move(pipe)))); @@ -89,16 +79,11 @@ void MojoApplicationHost::Activate(IPC::Sender* sender, DCHECK(!did_activate_); DCHECK(client_handle_.is_valid()); - base::PlatformFile client_file = - PlatformFileFromScopedPlatformHandle(std::move(client_handle_)); + base::PlatformFile client_file = client_handle_.release().handle; did_activate_ = sender->Send(new MojoMsg_Activate( IPC::GetFileHandleForProcess(client_file, process_handle, true))); } -void MojoApplicationHost::WillDestroySoon() { - channel_init_.WillDestroySoon(); -} - void MojoApplicationHost::OverrideIOTaskRunnerForTest( scoped_refptr<base::TaskRunner> io_task_runner) { io_task_runner_override_ = io_task_runner; diff --git a/content/browser/mojo/mojo_application_host.h b/content/browser/mojo/mojo_application_host.h index 1b6c523..850f088 100644 --- a/content/browser/mojo/mojo_application_host.h +++ b/content/browser/mojo/mojo_application_host.h @@ -12,8 +12,8 @@ #include "content/common/application_setup.mojom.h" #include "content/common/mojo/channel_init.h" #include "content/common/mojo/service_registry_impl.h" +#include "mojo/edk/embedder/scoped_platform_handle.h" #include "mojo/public/cpp/system/message_pipe.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" #if defined(OS_ANDROID) #include "content/browser/mojo/service_registry_android.h" @@ -41,8 +41,6 @@ class CONTENT_EXPORT MojoApplicationHost { bool Init(); void Activate(IPC::Sender* sender, base::ProcessHandle process_handle); - void WillDestroySoon(); - ServiceRegistry* service_registry() { return &service_registry_; } #if defined(OS_ANDROID) @@ -56,7 +54,7 @@ class CONTENT_EXPORT MojoApplicationHost { private: ChannelInit channel_init_; - mojo::embedder::ScopedPlatformHandle client_handle_; + mojo::edk::ScopedPlatformHandle client_handle_; bool did_activate_; diff --git a/content/browser/mojo/mojo_shell_client_host.h b/content/browser/mojo/mojo_shell_client_host.h index 25539a3..8b945fa 100644 --- a/content/browser/mojo/mojo_shell_client_host.h +++ b/content/browser/mojo/mojo_shell_client_host.h @@ -9,7 +9,6 @@ #include "base/process/process_handle.h" #include "mojo/shell/public/interfaces/shell.mojom.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" namespace content { diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 29073e0..4a714dc 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc @@ -164,12 +164,12 @@ #include "ipc/ipc_switches.h" #include "ipc/mojo/ipc_channel_mojo.h" #include "media/base/media_switches.h" +#include "mojo/edk/embedder/embedder.h" #include "net/url_request/url_request_context_getter.h" #include "ppapi/shared_impl/ppapi_switches.h" #include "storage/browser/fileapi/sandbox_file_system_backend.h" #include "third_party/icu/source/common/unicode/unistr.h" #include "third_party/icu/source/i18n/unicode/timezone.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/ui_base_switches.h" #include "ui/events/event_switches.h" @@ -1569,7 +1569,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( #if defined(OS_CHROMEOS) switches::kDisableVaapiAcceleratedVideoEncode, #endif - "use-new-edk", // TODO(use_chrome_edk): temporary. }; renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames, arraysize(kSwitchNames)); @@ -2377,7 +2376,6 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead, } RendererClosedDetails details(status, exit_code); - mojo_application_host_->WillDestroySoon(); child_process_launcher_.reset(); #if USE_ATTACHMENT_BROKER @@ -2465,8 +2463,6 @@ void RenderProcessHostImpl::OnShutdownRequest() { FOR_EACH_OBSERVER(RenderProcessHostObserver, observers_, RenderProcessWillExit(this)); - mojo_application_host_->WillDestroySoon(); - Send(new ChildProcessMsg_Shutdown()); } @@ -2562,19 +2558,13 @@ void RenderProcessHostImpl::OnProcessLaunched() { Source<RenderProcessHost>(this), NotificationService::NoDetails()); - if (base::CommandLine::ForCurrentProcess()->HasSwitch("use-new-edk") && - child_process_launcher_.get()) { + if (child_process_launcher_.get()) { base::ProcessHandle process_handle = child_process_launcher_->GetProcess().Handle(); - mojo::embedder::ScopedPlatformHandle client_pipe = - mojo::embedder::ChildProcessLaunched(process_handle); + mojo::edk::ScopedPlatformHandle client_pipe = + mojo::edk::ChildProcessLaunched(process_handle); Send(new ChildProcessMsg_SetMojoParentPipeHandle( - IPC::GetFileHandleForProcess( -#if defined(OS_WIN) - client_pipe.release().handle, -#else - client_pipe.release().fd, -#endif + IPC::GetFileHandleForProcess(client_pipe.release().handle, process_handle, true))); } diff --git a/content/child/BUILD.gn b/content/child/BUILD.gn index 52e5133..0ab48e1 100644 --- a/content/child/BUILD.gn +++ b/content/child/BUILD.gn @@ -21,7 +21,7 @@ source_set("child") { ] public_deps = [ - "//third_party/mojo/src/mojo/edk/system", + "//mojo/edk/system", ] deps = [ diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc index 7e815ba..dbf6c3b 100644 --- a/content/child/child_thread_impl.cc +++ b/content/child/child_thread_impl.cc @@ -62,7 +62,7 @@ #include "ipc/ipc_sync_channel.h" #include "ipc/ipc_sync_message_filter.h" #include "ipc/mojo/ipc_channel_mojo.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/embedder.h" #if defined(USE_OZONE) #include "ui/ozone/public/client_native_pixmap_factory.h" @@ -696,8 +696,8 @@ void ChildThreadImpl::OnBindExternalMojoShellHandle( void ChildThreadImpl::OnSetMojoParentPipeHandle( const IPC::PlatformFileForTransit& file) { - mojo::embedder::SetParentPipeHandle( - mojo::embedder::ScopedPlatformHandle(mojo::embedder::PlatformHandle( + mojo::edk::SetParentPipeHandle( + mojo::edk::ScopedPlatformHandle(mojo::edk::PlatformHandle( IPC::PlatformFileForTransitToPlatformFile(file)))); } diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn index 9b57a55..6534ca2 100644 --- a/content/common/BUILD.gn +++ b/content/common/BUILD.gn @@ -200,12 +200,12 @@ source_set("common") { "//media:shared_memory_support", "//media/midi", "//mojo/common:common_base", + "//mojo/edk/system", "//mojo/environment:chromium", "//mojo/shell/public/interfaces", "//sandbox", "//storage/common", "//third_party/boringssl", - "//third_party/mojo/src/mojo/edk/system", "//ui/gl", ] diff --git a/content/common/mojo/channel_init.cc b/content/common/mojo/channel_init.cc index 503dc81..72a7a6e 100644 --- a/content/common/mojo/channel_init.cc +++ b/content/common/mojo/channel_init.cc @@ -15,57 +15,19 @@ #include "base/task_runner.h" #include "base/thread_task_runner_handle.h" #include "mojo/edk/embedder/embedder.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" namespace content { -ChannelInit::ChannelInit() : channel_info_(nullptr), weak_factory_(this) {} +ChannelInit::ChannelInit() {} -ChannelInit::~ChannelInit() { - if (channel_info_) - mojo::embedder::DestroyChannel(channel_info_, - base::Bind(&base::DoNothing), nullptr); -} +ChannelInit::~ChannelInit() {} mojo::ScopedMessagePipeHandle ChannelInit::Init( base::PlatformFile file, scoped_refptr<base::TaskRunner> io_thread_task_runner) { - scoped_ptr<IPC::ScopedIPCSupport> ipc_support( - new IPC::ScopedIPCSupport(io_thread_task_runner)); - if (base::CommandLine::ForCurrentProcess()->HasSwitch("use-new-edk")) { - ipc_support_ = std::move(ipc_support); - return mojo::edk::CreateMessagePipe( - mojo::edk::ScopedPlatformHandle(mojo::edk::PlatformHandle(file))); - } else { - return mojo::embedder::CreateChannel( - mojo::embedder::ScopedPlatformHandle( - mojo::embedder::PlatformHandle(file)), - base::Bind(&ChannelInit::OnCreatedChannel, weak_factory_.GetWeakPtr(), - base::Passed(&ipc_support)), - base::ThreadTaskRunnerHandle::Get()); - } -} - -void ChannelInit::WillDestroySoon() { - if (channel_info_) - mojo::embedder::WillDestroyChannelSoon(channel_info_); -} - -// static -void ChannelInit::OnCreatedChannel( - base::WeakPtr<ChannelInit> self, - scoped_ptr<IPC::ScopedIPCSupport> ipc_support, - mojo::embedder::ChannelInfo* channel) { - // If |self| was already destroyed, shut the channel down. - if (!self) { - mojo::embedder::DestroyChannel(channel, - base::Bind(&base::DoNothing), nullptr); - return; - } - - DCHECK(!self->channel_info_); - self->channel_info_ = channel; - self->ipc_support_ = std::move(ipc_support); + ipc_support_.reset(new IPC::ScopedIPCSupport(io_thread_task_runner)); + return mojo::edk::CreateMessagePipe( + mojo::edk::ScopedPlatformHandle(mojo::edk::PlatformHandle(file))); } } // namespace content diff --git a/content/common/mojo/channel_init.h b/content/common/mojo/channel_init.h index bebac06..3f4c191 100644 --- a/content/common/mojo/channel_init.h +++ b/content/common/mojo/channel_init.h @@ -8,11 +8,9 @@ #include "base/files/file.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" #include "content/common/content_export.h" #include "ipc/mojo/scoped_ipc_support.h" #include "mojo/public/cpp/system/message_pipe.h" -#include "third_party/mojo/src/mojo/edk/embedder/channel_info_forward.h" namespace base { class TaskRunner; @@ -32,23 +30,8 @@ class CONTENT_EXPORT ChannelInit { base::PlatformFile file, scoped_refptr<base::TaskRunner> io_thread_task_runner); - // Notifies the channel that we (hence it) will soon be destroyed. - void WillDestroySoon(); - private: - // Invoked on the thread on which this object lives once the channel has been - // established. This is a static method that takes a weak pointer to self, - // since we want to destroy the channel if we were destroyed first. - static void OnCreatedChannel( - base::WeakPtr<ChannelInit> self, - scoped_ptr<IPC::ScopedIPCSupport> ipc_support, - mojo::embedder::ChannelInfo* channel); - - // If non-null the channel has been established. - mojo::embedder::ChannelInfo* channel_info_; - scoped_ptr<IPC::ScopedIPCSupport> ipc_support_; - base::WeakPtrFactory<ChannelInit> weak_factory_; DISALLOW_COPY_AND_ASSIGN(ChannelInit); }; diff --git a/content/content.gyp b/content/content.gyp index 6d5f893..6b11ac2 100644 --- a/content/content.gyp +++ b/content/content.gyp @@ -463,9 +463,9 @@ '../media/media.gyp:media_java', '../mojo/mojo_base.gyp:mojo_application_bindings', '../mojo/mojo_base.gyp:mojo_system_java', + '../mojo/mojo_public.gyp:mojo_bindings_java', '../net/net.gyp:net', '../skia/skia.gyp:skia_mojo', - '../third_party/mojo/mojo_public.gyp:mojo_bindings_java', '../ui/android/ui_android.gyp:ui_java', '../ui/touch_selection/ui_touch_selection.gyp:selection_event_type_java', '../ui/touch_selection/ui_touch_selection.gyp:touch_handle_orientation_java', diff --git a/content/content_app.gypi b/content/content_app.gypi index 293781b..e93f550 100644 --- a/content/content_app.gypi +++ b/content/content_app.gypi @@ -11,7 +11,7 @@ '../base/base.gyp:base_i18n', '../crypto/crypto.gyp:crypto', '../mojo/mojo_base.gyp:mojo_environment_chromium', - '../third_party/mojo/mojo_edk.gyp:mojo_system_impl', + '../mojo/mojo_edk.gyp:mojo_system_impl', '../ui/base/ui_base.gyp:ui_base', '../ui/gfx/gfx.gyp:gfx', '../ui/gfx/gfx.gyp:gfx_geometry', diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 79ccbeb..29b033b 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -15,6 +15,7 @@ '../mojo/mojo_base.gyp:mojo_application_base', '../mojo/mojo_base.gyp:mojo_geometry_lib', '../mojo/mojo_base.gyp:mojo_url_type_converters', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', '../mojo/mojo_services.gyp:network_service_bindings_lib', '../mojo/mojo_services.gyp:updater_bindings_lib', '../mojo/mojo_shell.gyp:mojo_shell_lib', @@ -25,7 +26,6 @@ '../skia/skia.gyp:skia_mojo', '../sql/sql.gyp:sql', '../third_party/kasko/kasko.gyp:kasko_features', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', '../third_party/re2/re2.gyp:re2', '../third_party/zlib/google/zip.gyp:zip', '../third_party/zlib/zlib.gyp:zlib', @@ -1872,19 +1872,19 @@ '../device/bluetooth/bluetooth.gyp:device_bluetooth', '../device/usb/usb.gyp:device_usb', '../gin/gin.gyp:gin', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', + '../mojo/mojo_public.gyp:mojo_js_bindings', '../net/net.gyp:http_server', '../storage/storage_browser.gyp:storage', '../storage/storage_common.gyp:storage_common', '../third_party/angle/src/angle.gyp:commit_id', '../third_party/leveldatabase/leveldatabase.gyp:leveldatabase', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', - '../third_party/mojo/mojo_public.gyp:mojo_js_bindings', '../ui/events/blink/events_blink.gyp:events_blink', '../ui/surface/surface.gyp:surface', '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection', ], 'export_dependent_settings': [ - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', ], }], ['debug_devtools==1', { diff --git a/content/content_common.gypi b/content/content_common.gypi index 9e22df6..0393e1d 100644 --- a/content/content_common.gypi +++ b/content/content_common.gypi @@ -639,17 +639,17 @@ '../media/midi/midi.gyp:midi', '../mojo/mojo_base.gyp:mojo_application_bindings', '../mojo/mojo_base.gyp:mojo_environment_chromium', + '../mojo/mojo_edk.gyp:mojo_system_impl', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', '../storage/storage_common.gyp:storage_common', '../third_party/WebKit/public/blink.gyp:blink', '../third_party/boringssl/boringssl.gyp:boringssl', - '../third_party/mojo/mojo_edk.gyp:mojo_system_impl', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', '../ui/gl/gl.gyp:gl', 'content_common_mojo_bindings.gyp:content_common_mojo_bindings', ], 'export_dependent_settings' : [ '../mojo/mojo_base.gyp:mojo_application_bindings', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', ], 'actions': [ { diff --git a/content/content_common_mojo_bindings.gyp b/content/content_common_mojo_bindings.gyp index 80fccab..aba33f1c 100644 --- a/content/content_common_mojo_bindings.gyp +++ b/content/content_common_mojo_bindings.gyp @@ -35,11 +35,11 @@ 'dependencies': [ '../mojo/mojo_base.gyp:mojo_application_bindings', '../mojo/mojo_base.gyp:mojo_environment_chromium', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', '../skia/skia.gyp:skia_mojo', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', '../ui/mojo/geometry/mojo_bindings.gyp:mojo_geometry_bindings', ], - 'includes': [ '../third_party/mojo/mojom_bindings_generator.gypi' ], + 'includes': [ '../mojo/mojom_bindings_generator.gypi' ], }, ] } diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi index 88461b2..35618ef 100644 --- a/content/content_renderer.gypi +++ b/content/content_renderer.gypi @@ -26,6 +26,7 @@ '../mojo/mojo_base.gyp:mojo_environment_chromium', '../mojo/mojo_base.gyp:mojo_geometry_lib', '../mojo/mojo_base.gyp:mojo_url_type_converters', + '../mojo/mojo_edk.gyp:mojo_js_lib', '../net/net.gyp:net', '../skia/skia.gyp:skia', '../skia/skia.gyp:skia_mojo', @@ -35,7 +36,6 @@ '../third_party/icu/icu.gyp:icuuc', '../third_party/libjingle/libjingle.gyp:libjingle', '../third_party/libyuv/libyuv.gyp:libyuv', - '../third_party/mojo/mojo_edk.gyp:mojo_js_lib', '../third_party/npapi/npapi.gyp:npapi', '../third_party/widevine/cdm/widevine_cdm.gyp:widevine_cdm_version_h', '../ui/accessibility/accessibility.gyp:accessibility', diff --git a/content/content_tests.gypi b/content/content_tests.gypi index 9041d2a..566d2bd 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi @@ -837,13 +837,13 @@ 'dependencies': [ '../mojo/mojo_base.gyp:mojo_application_base', '../mojo/mojo_base.gyp:mojo_environment_chromium', + '../mojo/mojo_edk.gyp:mojo_system_impl', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', '../net/net.gyp:net_test_support', '../skia/skia.gyp:skia', '../storage/storage_common.gyp:storage_common', '../testing/gmock.gyp:gmock', '../testing/gtest.gyp:gtest', - '../third_party/mojo/mojo_edk.gyp:mojo_system_impl', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', '../ui/accessibility/accessibility.gyp:ax_gen', '../ui/base/ime/ui_base_ime.gyp:ui_base_ime', '../ui/base/ui_base.gyp:ui_base', @@ -929,6 +929,8 @@ '../media/midi/midi.gyp:midi', '../mojo/mojo_base.gyp:mojo_application_base', '../mojo/mojo_base.gyp:mojo_environment_chromium', + '../mojo/mojo_edk.gyp:mojo_common_test_support', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', '../ppapi/ppapi_internal.gyp:ppapi_host', '../ppapi/ppapi_internal.gyp:ppapi_proxy', '../ppapi/ppapi_internal.gyp:ppapi_shared', @@ -936,8 +938,6 @@ '../storage/storage_browser.gyp:storage', '../storage/storage_common.gyp:storage_common', '../third_party/WebKit/public/blink.gyp:blink', - '../third_party/mojo/mojo_edk.gyp:mojo_common_test_support', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', '../ui/compositor/compositor.gyp:compositor_test_support', '../ui/surface/surface.gyp:surface', '../v8/tools/gyp/v8.gyp:v8', @@ -1158,6 +1158,8 @@ '../media/media.gyp:media_test_support', '../media/media.gyp:shared_memory_support', '../mojo/mojo_base.gyp:mojo_environment_chromium', + '../mojo/mojo_edk.gyp:mojo_common_test_support', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', '../net/net.gyp:net_extras', '../net/net.gyp:net_test_support', '../skia/skia.gyp:skia', @@ -1171,8 +1173,6 @@ '../third_party/icu/icu.gyp:icuuc', '../third_party/leveldatabase/leveldatabase.gyp:leveldatabase', '../third_party/libjingle/libjingle.gyp:libjingle', - '../third_party/mojo/mojo_edk.gyp:mojo_common_test_support', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', '../third_party/re2/re2.gyp:re2', '../third_party/WebKit/public/blink.gyp:blink', '../ui/accessibility/accessibility.gyp:accessibility', @@ -1457,21 +1457,21 @@ 'sources': [ 'public/test/test_mojo_service.mojom', ], - 'includes': [ '../third_party/mojo/mojom_bindings_generator.gypi' ], + 'includes': [ '../mojo/mojom_bindings_generator.gypi' ], }, { # GN version: //content/test:web_ui_test_mojo_bindings 'target_name': 'web_ui_test_mojo_bindings', 'type': 'static_library', 'dependencies': [ - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', ], 'sources': [ 'test/data/web_ui_test_mojo_bindings.mojom', ], - 'includes': [ '../third_party/mojo/mojom_bindings_generator.gypi' ], + 'includes': [ '../mojo/mojom_bindings_generator.gypi' ], 'export_dependent_settings': [ - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', ], }, { @@ -1504,6 +1504,10 @@ '../mojo/mojo_base.gyp:mojo_application_base', '../mojo/mojo_base.gyp:mojo_environment_chromium', '../mojo/mojo_base.gyp:mojo_test_support', + '../mojo/mojo_edk.gyp:mojo_common_test_support', + '../mojo/mojo_edk.gyp:mojo_system_impl', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', + '../mojo/mojo_public.gyp:mojo_js_bindings', '../net/net.gyp:net_test_support', '../ppapi/ppapi_internal.gyp:ppapi_host', '../ppapi/ppapi_internal.gyp:ppapi_ipc', @@ -1515,10 +1519,6 @@ '../third_party/WebKit/public/blink.gyp:blink', '../third_party/leveldatabase/leveldatabase.gyp:leveldatabase', '../third_party/mesa/mesa.gyp:osmesa', - '../third_party/mojo/mojo_edk.gyp:mojo_common_test_support', - '../third_party/mojo/mojo_edk.gyp:mojo_system_impl', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', - '../third_party/mojo/mojo_public.gyp:mojo_js_bindings', '../third_party/zlib/zlib.gyp:zlib', '../ui/accessibility/accessibility.gyp:accessibility', '../ui/base/ui_base.gyp:ui_base', @@ -2147,12 +2147,12 @@ '../device/battery/battery.gyp:device_battery_javatests', '../media/media.gyp:media_java', '../media/media.gyp:media_test_support', + '../mojo/mojo_public.gyp:mojo_public_test_interfaces', '../net/net.gyp:net_java', '../net/net.gyp:net_javatests', '../net/net.gyp:net_java_test_support', '../testing/android/on_device_instrumentation.gyp:broker_java', '../testing/android/on_device_instrumentation.gyp:require_driver_apk', - '../third_party/mojo/mojo_public.gyp:mojo_public_test_interfaces', ], 'variables': { 'apk_name': 'ContentShellTest', diff --git a/content/content_utility.gypi b/content/content_utility.gypi index 6eb535f..c1980da 100644 --- a/content/content_utility.gypi +++ b/content/content_utility.gypi @@ -10,8 +10,8 @@ '../mojo/mojo_base.gyp:mojo_application_bindings', '../mojo/mojo_base.gyp:mojo_common_lib', '../mojo/mojo_base.gyp:mojo_message_pump_lib', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', '../mojo/mojo_shell.gyp:mojo_shell_lib', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', '../url/url.gyp:url_lib', ], 'variables': { diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc index d5d5fa5..2706d71 100644 --- a/content/public/test/render_view_test.cc +++ b/content/public/test/render_view_test.cc @@ -369,12 +369,9 @@ void RenderViewTest::SetUp() { #if !defined(OS_IOS) InitializeMojo(); - if (base::CommandLine::ForCurrentProcess()->HasSwitch("use-new-edk")) { - test_io_thread_.reset(new base::TestIOThread( - base::TestIOThread::kAutoStart)); - ipc_support_.reset(new mojo::test::ScopedIPCSupport( - test_io_thread_->task_runner())); - } + test_io_thread_.reset(new base::TestIOThread(base::TestIOThread::kAutoStart)); + ipc_support_.reset( + new mojo::edk::test::ScopedIPCSupport(test_io_thread_->task_runner())); #endif // This needs to pass the mock render thread to the view. diff --git a/content/public/test/render_view_test.h b/content/public/test/render_view_test.h index 1e081eb..3c3b3f8 100644 --- a/content/public/test/render_view_test.h +++ b/content/public/test/render_view_test.h @@ -19,11 +19,11 @@ #include "content/public/common/main_function_params.h" #include "content/public/common/page_state.h" #include "content/public/test/mock_render_thread.h" +#include "mojo/edk/test/scoped_ipc_support.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/platform/Platform.h" #include "third_party/WebKit/public/web/WebFrame.h" #include "third_party/WebKit/public/web/WebLeakDetector.h" -#include "third_party/mojo/src/mojo/edk/test/scoped_ipc_support.h" namespace blink { class WebInputElement; @@ -206,7 +206,7 @@ class RenderViewTest : public testing::Test, blink::WebLeakDetectorClient { // For Mojo. scoped_ptr<base::TestIOThread> test_io_thread_; - scoped_ptr<mojo::test::ScopedIPCSupport> ipc_support_; + scoped_ptr<mojo::edk::test::ScopedIPCSupport> ipc_support_; #if defined(OS_MACOSX) scoped_ptr<base::mac::ScopedNSAutoreleasePool> autorelease_pool_; diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index 3b51c57..fa2c337 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn @@ -58,6 +58,7 @@ source_set("renderer") { "//media/midi", "//mojo/common", "//mojo/converters/geometry", + "//mojo/edk/js", "//mojo/environment:chromium", "//mojo/public/cpp/bindings", "//mojo/public/js", @@ -72,7 +73,6 @@ source_set("renderer") { "//third_party/icu", "//third_party/libjingle", "//third_party/libyuv", - "//third_party/mojo/src/mojo/edk/js", "//third_party/npapi", "//third_party/widevine/cdm:version_h", "//ui/accessibility", diff --git a/content/renderer/mojo/service_registry_js_wrapper.cc b/content/renderer/mojo/service_registry_js_wrapper.cc index 3dc56cf..e45decc 100644 --- a/content/renderer/mojo/service_registry_js_wrapper.cc +++ b/content/renderer/mojo/service_registry_js_wrapper.cc @@ -9,7 +9,7 @@ #include "base/memory/scoped_ptr.h" #include "content/common/mojo/service_registry_impl.h" #include "content/public/common/service_registry.h" -#include "third_party/mojo/src/mojo/edk/js/handle.h" +#include "mojo/edk/js/handle.h" #include "v8/include/v8.h" namespace content { diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index bbe270a..24747fa 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc @@ -140,6 +140,8 @@ #include "media/blink/webmediaplayer_impl.h" #include "media/renderers/gpu_video_accelerator_factories.h" #include "mojo/common/url_type_converters.h" +#include "mojo/edk/js/core.h" +#include "mojo/edk/js/support.h" #include "net/base/data_url.h" #include "net/base/net_errors.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" @@ -178,8 +180,6 @@ #include "third_party/WebKit/public/web/WebSurroundingText.h" #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" #include "third_party/WebKit/public/web/WebView.h" -#include "third_party/mojo/src/mojo/edk/js/core.h" -#include "third_party/mojo/src/mojo/edk/js/support.h" #include "url/url_util.h" #if defined(ENABLE_PLUGINS) @@ -2381,15 +2381,14 @@ void RenderFrameImpl::EnsureMojoBuiltinsAreAvailable( v8::Isolate* isolate, v8::Local<v8::Context> context) { gin::ModuleRegistry* registry = gin::ModuleRegistry::From(context); - if (registry->available_modules().count(mojo::js::Core::kModuleName)) + if (registry->available_modules().count(mojo::edk::js::Core::kModuleName)) return; v8::HandleScope handle_scope(isolate); - registry->AddBuiltinModule( - isolate, mojo::js::Core::kModuleName, mojo::js::Core::GetModule(isolate)); - registry->AddBuiltinModule(isolate, - mojo::js::Support::kModuleName, - mojo::js::Support::GetModule(isolate)); + registry->AddBuiltinModule(isolate, mojo::edk::js::Core::kModuleName, + mojo::edk::js::Core::GetModule(isolate)); + registry->AddBuiltinModule(isolate, mojo::edk::js::Support::kModuleName, + mojo::edk::js::Support::GetModule(isolate)); registry->AddBuiltinModule( isolate, ServiceRegistryJsWrapper::kModuleName, diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 91a9cfc..fcb2063 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn @@ -99,11 +99,11 @@ source_set("test_support") { "//ipc:test_support", "//ipc/mojo", "//media", + "//mojo/edk/test:test_support", "//mojo/environment:chromium", "//mojo/shell/public/cpp:cpp_for_chromium", "//storage/browser", "//storage/common", - "//third_party/mojo/src/mojo/edk/test:test_support", "//ui/compositor:test_support", "//ui/surface", "//v8", @@ -287,8 +287,8 @@ if (!is_ios) { "//cc/blink", "//components/test_runner:test_runner", "//content/public/common", + "//mojo/edk/test:test_support", "//skia", - "//third_party/mojo/src/mojo/edk/test:test_support", "//ui/accessibility:ax_gen", "//v8", ] @@ -427,6 +427,8 @@ test("content_browsertests") { "//media:test_support", "//media/audio:test_support", "//media/base:test_support", + "//mojo/edk/system", + "//mojo/edk/test:test_support", "//mojo/environment:chromium", "//mojo/public/cpp/bindings", "//mojo/public/js", @@ -438,8 +440,6 @@ test("content_browsertests") { "//third_party/WebKit/public:blink", "//third_party/leveldatabase", "//third_party/mesa:osmesa", - "//third_party/mojo/src/mojo/edk/system", - "//third_party/mojo/src/mojo/edk/test:test_support", "//third_party/zlib", "//ui/accessibility", "//ui/accessibility:ax_gen", @@ -602,6 +602,7 @@ test("content_unittests") { "//device/battery", "//device/battery:mojo_bindings", "//device/bluetooth", + "//mojo/edk/test:test_support", "//mojo/environment:chromium", "//mojo/public/cpp/bindings", "//net:extras", @@ -611,7 +612,6 @@ test("content_unittests") { "//sql:test_support", "//testing/gmock", "//testing/gtest", - "//third_party/mojo/src/mojo/edk/test:test_support", "//third_party/re2", "//ui/accessibility", "//ui/base", diff --git a/content/test/run_all_unittests.cc b/content/test/run_all_unittests.cc index 8b40346..ac655a4 100644 --- a/content/test/run_all_unittests.cc +++ b/content/test/run_all_unittests.cc @@ -10,7 +10,7 @@ #include "content/app/mojo/mojo_init.h" #include "content/public/test/unittest_test_suite.h" #include "content/test/content_test_suite.h" -#include "third_party/mojo/src/mojo/edk/test/scoped_ipc_support.h" +#include "mojo/edk/test/scoped_ipc_support.h" #if defined(OS_ANDROID) #include "base/android/jni_android.h" @@ -28,11 +28,9 @@ int main(int argc, char** argv) { #if !defined(OS_IOS) content::InitializeMojo(); base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); - scoped_ptr<mojo::test::ScopedIPCSupport> ipc_support; - if (base::CommandLine::ForCurrentProcess()->HasSwitch("use-new-edk")) { - ipc_support.reset(new mojo::test::ScopedIPCSupport( - test_io_thread.task_runner())); - } + scoped_ptr<mojo::edk::test::ScopedIPCSupport> ipc_support; + ipc_support.reset( + new mojo::edk::test::ScopedIPCSupport(test_io_thread.task_runner())); #endif return base::LaunchUnitTests( diff --git a/device/BUILD.gn b/device/BUILD.gn index c197c59..463e77f 100644 --- a/device/BUILD.gn +++ b/device/BUILD.gn @@ -57,12 +57,12 @@ test("device_unittests") { "//device/bluetooth:mocks", "//device/nfc", "//mojo/common", + "//mojo/edk/system", "//mojo/environment:chromium", "//mojo/public/cpp/bindings", "//net", "//testing/gmock", "//testing/gtest", - "//third_party/mojo/src/mojo/edk/system", "//tools/usb_gadget", "//url", ] diff --git a/device/battery/BUILD.gn b/device/battery/BUILD.gn index 17cd64d..158dce3 100644 --- a/device/battery/BUILD.gn +++ b/device/battery/BUILD.gn @@ -31,9 +31,9 @@ if (!is_android) { ":mojo_bindings", "//base", "//base/third_party/dynamic_annotations", + "//mojo/edk/system", "//mojo/environment:chromium", "//mojo/public/cpp/bindings", - "//third_party/mojo/src/mojo/edk/system", ] if (is_chromeos) { diff --git a/device/battery/battery.gyp b/device/battery/battery.gyp index 679630f..32f7adf 100644 --- a/device/battery/battery.gyp +++ b/device/battery/battery.gyp @@ -12,7 +12,7 @@ 'target_name': 'device_battery_mojo_bindings', 'type': 'static_library', 'includes': [ - '../../third_party/mojo/mojom_bindings_generator.gypi', + '../../mojo/mojom_bindings_generator.gypi', ], 'sources': [ 'battery_monitor.mojom', @@ -57,7 +57,7 @@ 'type': 'none', 'dependencies': [ '../../base/base.gyp:base', - '../../third_party/mojo/mojo_public.gyp:mojo_bindings_java', + '../../mojo/mojo_public.gyp:mojo_bindings_java', 'device_battery_mojo_bindings', ], 'variables': { @@ -90,8 +90,8 @@ '../../base/base.gyp:base', '../../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', '../../mojo/mojo_base.gyp:mojo_environment_chromium', - '../../third_party/mojo/mojo_edk.gyp:mojo_system_impl', - '../../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + '../../mojo/mojo_edk.gyp:mojo_system_impl', + '../../mojo/mojo_public.gyp:mojo_cpp_bindings', 'device_battery_mojo_bindings', ], 'defines': [ diff --git a/device/device_tests.gyp b/device/device_tests.gyp index e73991b..4503e12 100644 --- a/device/device_tests.gyp +++ b/device/device_tests.gyp @@ -13,10 +13,10 @@ 'dependencies': [ '../base/base.gyp:test_support_base', '../mojo/mojo_base.gyp:mojo_environment_chromium', + '../mojo/mojo_edk.gyp:mojo_system_impl', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', '../testing/gmock.gyp:gmock', '../testing/gtest.gyp:gtest', - '../third_party/mojo/mojo_edk.gyp:mojo_system_impl', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', '../tools/usb_gadget/usb_gadget.gyp:usb_gadget', 'battery/battery.gyp:device_battery', 'battery/battery.gyp:device_battery_mojo_bindings', diff --git a/device/devices_app/devices_app.gyp b/device/devices_app/devices_app.gyp index 7f8e21c..6027a85 100644 --- a/device/devices_app/devices_app.gyp +++ b/device/devices_app/devices_app.gyp @@ -30,12 +30,12 @@ '<(DEPTH)/mojo/mojo_base.gyp:mojo_application_base', '<(DEPTH)/mojo/mojo_base.gyp:mojo_application_bindings', '<(DEPTH)/mojo/mojo_base.gyp:mojo_url_type_converters', - '<(DEPTH)/third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + '<(DEPTH)/mojo/mojo_public.gyp:mojo_cpp_bindings', ], 'export_dependent_settings': [ '<(DEPTH)/mojo/mojo_base.gyp:mojo_application_base', '<(DEPTH)/mojo/mojo_base.gyp:mojo_application_bindings', - '<(DEPTH)/third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + '<(DEPTH)/mojo/mojo_public.gyp:mojo_cpp_bindings', ], }, { @@ -49,7 +49,7 @@ ], }, 'includes': [ - '../../third_party/mojo/mojom_bindings_generator_explicit.gypi', + '../../mojo/mojom_bindings_generator_explicit.gypi', ], }, { diff --git a/device/nfc/nfc.gyp b/device/nfc/nfc.gyp index 710bd22..9f17565 100644 --- a/device/nfc/nfc.gyp +++ b/device/nfc/nfc.gyp @@ -54,7 +54,7 @@ 'target_name': 'device_nfc_mojo_bindings', 'type': 'static_library', 'includes': [ - '../../third_party/mojo/mojom_bindings_generator.gypi', + '../../mojo/mojom_bindings_generator.gypi', ], 'sources': [ 'nfc.mojom', diff --git a/device/serial/serial.gyp b/device/serial/serial.gyp index 62cfb69..519263b 100644 --- a/device/serial/serial.gyp +++ b/device/serial/serial.gyp @@ -15,7 +15,7 @@ # generated cpp files must be listed explicitly in device_serial 'type': 'none', 'includes': [ - '../../third_party/mojo/mojom_bindings_generator.gypi', + '../../mojo/mojom_bindings_generator.gypi', ], 'sources': [ 'data_stream.mojom', @@ -74,14 +74,14 @@ ], 'dependencies': [ 'device_serial_mojo', + '../../mojo/mojo_public.gyp:mojo_cpp_bindings', '../../net/net.gyp:net', - '../../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', '../../third_party/re2/re2.gyp:re2', '../core/core.gyp:device_core', ], 'export_dependent_settings': [ 'device_serial_mojo', - '../../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + '../../mojo/mojo_public.gyp:mojo_cpp_bindings', ], 'sources': [ '<(SHARED_INTERMEDIATE_DIR)/device/serial/data_stream.mojom.cc', diff --git a/device/test/DEPS b/device/test/DEPS index c144476..b4a8f73 100644 --- a/device/test/DEPS +++ b/device/test/DEPS @@ -1,6 +1,6 @@ include_rules = [ + "+mojo/edk/embedder", "+net/base", "+net/proxy", "+net/url_request", - "+third_party/mojo/src/mojo/edk/embedder", ] diff --git a/device/test/run_all_unittests.cc b/device/test/run_all_unittests.cc index 76a4996..06b32a8 100644 --- a/device/test/run_all_unittests.cc +++ b/device/test/run_all_unittests.cc @@ -6,7 +6,7 @@ #include "base/test/launcher/unit_test_launcher.h" #include "base/test/test_suite.h" #include "build/build_config.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/embedder.h" #if defined(OS_ANDROID) #include "base/android/jni_android.h" @@ -22,7 +22,7 @@ int main(int argc, char** argv) { base::TestSuite test_suite(argc, argv); - mojo::embedder::Init(); + mojo::edk::Init(); return base::LaunchUnitTests( argc, argv, diff --git a/device/vibration/BUILD.gn b/device/vibration/BUILD.gn index 0f54123..d783940 100644 --- a/device/vibration/BUILD.gn +++ b/device/vibration/BUILD.gn @@ -20,9 +20,9 @@ component("vibration") { ":mojo_bindings", "//base", "//base/third_party/dynamic_annotations", + "//mojo/edk/system", "//mojo/environment:chromium", "//mojo/public/cpp/bindings", - "//third_party/mojo/src/mojo/edk/system", ] if (is_android) { diff --git a/device/vibration/vibration.gyp b/device/vibration/vibration.gyp index 99d75ba..acef5d5 100644 --- a/device/vibration/vibration.gyp +++ b/device/vibration/vibration.gyp @@ -12,7 +12,7 @@ 'target_name': 'device_vibration_mojo_bindings', 'type': 'static_library', 'includes': [ - '../../third_party/mojo/mojom_bindings_generator.gypi', + '../../mojo/mojom_bindings_generator.gypi', ], 'sources': [ 'vibration_manager.mojom', @@ -26,8 +26,8 @@ '../../base/base.gyp:base', '../../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', '../../mojo/mojo_base.gyp:mojo_environment_chromium', - '../../third_party/mojo/mojo_edk.gyp:mojo_system_impl', - '../../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + '../../mojo/mojo_edk.gyp:mojo_system_impl', + '../../mojo/mojo_public.gyp:mojo_cpp_bindings', 'device_vibration_mojo_bindings', ], 'defines': [ @@ -57,7 +57,7 @@ 'type': 'none', 'dependencies': [ '../../base/base.gyp:base', - '../../third_party/mojo/mojo_public.gyp:mojo_bindings_java', + '../../mojo/mojo_public.gyp:mojo_bindings_java', 'device_vibration_mojo_bindings', ], 'variables': { diff --git a/extensions/BUILD.gn b/extensions/BUILD.gn index a624a45..3d97214 100644 --- a/extensions/BUILD.gn +++ b/extensions/BUILD.gn @@ -182,14 +182,14 @@ test("extensions_unittests") { "//extensions/renderer", "//extensions/strings", "//extensions/utility", + "//mojo/edk/js", + "//mojo/edk/system", "//mojo/environment:chromium", "//mojo/public/cpp/bindings", "//mojo/shell/public/interfaces", "//testing/gmock", "//testing/gtest", "//third_party/leveldatabase", - "//third_party/mojo/src/mojo/edk/js", - "//third_party/mojo/src/mojo/edk/system", ] data_deps = [ @@ -242,12 +242,12 @@ test("extensions_browsertests") { "//device/core:mocks", "//device/hid:mocks", "//device/usb:mocks", + "//mojo/edk/js", + "//mojo/edk/system", "//mojo/environment:chromium", "//mojo/public/cpp/bindings", "//testing/gmock", "//testing/gtest", - "//third_party/mojo/src/mojo/edk/js", - "//third_party/mojo/src/mojo/edk/system", ] data_deps = [ diff --git a/extensions/common/api/api.gyp b/extensions/common/api/api.gyp index ea7e4c1..3a2696f 100644 --- a/extensions/common/api/api.gyp +++ b/extensions/common/api/api.gyp @@ -12,7 +12,7 @@ # generated cpp files must be listed explicitly in chrome_api. 'type': 'none', 'includes': [ - '../../../third_party/mojo/mojom_bindings_generator.gypi', + '../../../mojo/mojom_bindings_generator.gypi', ], 'sources': [ 'mime_handler.mojom', @@ -31,7 +31,7 @@ ], 'dependencies': [ 'extensions_api_mojom', - '../../../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + '../../../mojo/mojo_public.gyp:mojo_cpp_bindings', ], 'sources': [ '<(SHARED_INTERMEDIATE_DIR)/extensions/common/api/mime_handler.mojom.cc', diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp index 59ee0072..0dda3f7 100644 --- a/extensions/extensions.gyp +++ b/extensions/extensions.gyp @@ -32,7 +32,7 @@ # generated cpp files must be listed explicitly in extensions_common 'type': 'none', 'includes': [ - '../third_party/mojo/mojom_bindings_generator.gypi', + '../mojo/mojom_bindings_generator.gypi', ], 'sources': [ '<@(extensions_common_mojo_sources)', @@ -204,8 +204,8 @@ '../components/components.gyp:guest_view_renderer', '../content/content.gyp:content_resources', '../gin/gin.gyp:gin', + '../mojo/mojo_public.gyp:mojo_js_bindings', '../third_party/WebKit/public/blink.gyp:blink', - '../third_party/mojo/mojo_public.gyp:mojo_js_bindings', ], 'include_dirs': [ '..', diff --git a/extensions/extensions_tests.gyp b/extensions/extensions_tests.gyp index b4185cd..87ef374 100644 --- a/extensions/extensions_tests.gyp +++ b/extensions/extensions_tests.gyp @@ -28,12 +28,12 @@ '../device/serial/serial.gyp:device_serial_test_util', '../mojo/mojo_base.gyp:mojo_application_bindings', '../mojo/mojo_base.gyp:mojo_environment_chromium', + '../mojo/mojo_edk.gyp:mojo_js_lib', + '../mojo/mojo_edk.gyp:mojo_system_impl', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', '../testing/gmock.gyp:gmock', '../testing/gtest.gyp:gtest', '../third_party/leveldatabase/leveldatabase.gyp:leveldatabase', - '../third_party/mojo/mojo_edk.gyp:mojo_js_lib', - '../third_party/mojo/mojo_edk.gyp:mojo_system_impl', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', 'common/api/api.gyp:cast_channel_proto', 'extensions.gyp:extensions_browser', 'extensions.gyp:extensions_common', diff --git a/extensions/renderer/BUILD.gn b/extensions/renderer/BUILD.gn index 7ed31fe..9606e85 100644 --- a/extensions/renderer/BUILD.gn +++ b/extensions/renderer/BUILD.gn @@ -26,9 +26,9 @@ source_set("renderer") { "//content:resources", "//extensions:extensions_resources", "//gin", + "//mojo/edk/js", "//mojo/public/js", "//skia", "//third_party/WebKit/public:blink", - "//third_party/mojo/src/mojo/edk/js", ] } diff --git a/extensions/renderer/DEPS b/extensions/renderer/DEPS index 5a27869..bd0ed52 100644 --- a/extensions/renderer/DEPS +++ b/extensions/renderer/DEPS @@ -4,7 +4,7 @@ include_rules = [ "+content/public/renderer", "+gin", - "+third_party/mojo/src/mojo/edk/js", + "+mojo/edk/js", "+third_party/skia/include/core", "+third_party/cld_2/src/public/compact_lang_det.h", diff --git a/extensions/renderer/api/serial/data_receiver_unittest.cc b/extensions/renderer/api/serial/data_receiver_unittest.cc index 126b041..0827a8a 100644 --- a/extensions/renderer/api/serial/data_receiver_unittest.cc +++ b/extensions/renderer/api/serial/data_receiver_unittest.cc @@ -14,6 +14,7 @@ #include "gin/dictionary.h" #include "gin/wrappable.h" #include "grit/extensions_renderer_resources.h" +#include "mojo/edk/js/handle.h" namespace extensions { diff --git a/extensions/renderer/api_test_base.cc b/extensions/renderer/api_test_base.cc index 3ce3d5d..abf868b 100644 --- a/extensions/renderer/api_test_base.cc +++ b/extensions/renderer/api_test_base.cc @@ -13,11 +13,11 @@ #include "extensions/renderer/process_info_native_handler.h" #include "gin/converter.h" #include "gin/dictionary.h" +#include "mojo/edk/js/core.h" +#include "mojo/edk/js/handle.h" +#include "mojo/edk/js/support.h" #include "mojo/public/cpp/bindings/interface_request.h" #include "mojo/public/cpp/system/core.h" -#include "third_party/mojo/src/mojo/edk/js/core.h" -#include "third_party/mojo/src/mojo/edk/js/handle.h" -#include "third_party/mojo/src/mojo/edk/js/support.h" namespace extensions { namespace { @@ -155,13 +155,11 @@ void ApiTestEnvironment::RegisterModules() { "exports.$set('MatchAgainstEventFilter', function() { return [] });"); gin::ModuleRegistry::From(env()->context()->v8_context()) - ->AddBuiltinModule(env()->isolate(), - mojo::js::Core::kModuleName, - mojo::js::Core::GetModule(env()->isolate())); + ->AddBuiltinModule(env()->isolate(), mojo::edk::js::Core::kModuleName, + mojo::edk::js::Core::GetModule(env()->isolate())); gin::ModuleRegistry::From(env()->context()->v8_context()) - ->AddBuiltinModule(env()->isolate(), - mojo::js::Support::kModuleName, - mojo::js::Support::GetModule(env()->isolate())); + ->AddBuiltinModule(env()->isolate(), mojo::edk::js::Support::kModuleName, + mojo::edk::js::Support::GetModule(env()->isolate())); gin::Handle<TestServiceProvider> service_provider = TestServiceProvider::Create(env()->isolate()); service_provider_ = service_provider.get(); diff --git a/extensions/renderer/api_test_base.h b/extensions/renderer/api_test_base.h index 2bfc4cc..8b62049 100644 --- a/extensions/renderer/api_test_base.h +++ b/extensions/renderer/api_test_base.h @@ -19,7 +19,6 @@ #include "gin/wrappable.h" #include "mojo/public/cpp/bindings/interface_request.h" #include "mojo/public/cpp/system/core.h" -#include "third_party/mojo/src/mojo/edk/js/handle.h" namespace extensions { diff --git a/extensions/shell/BUILD.gn b/extensions/shell/BUILD.gn index a98d704..c2f57e9 100644 --- a/extensions/shell/BUILD.gn +++ b/extensions/shell/BUILD.gn @@ -54,10 +54,10 @@ source_set("app_shell_lib") { "//extensions/shell/common/api", "//extensions/shell/common/api:api_registration", "//extensions/utility", + "//mojo/edk/system", "//mojo/environment:chromium", "//skia", "//third_party/WebKit/public:blink", - "//third_party/mojo/src/mojo/edk/system", "//ui/base", "//ui/base/ime", "//v8", diff --git a/extensions/shell/app_shell.gyp b/extensions/shell/app_shell.gyp index 695bb32..9d085db 100644 --- a/extensions/shell/app_shell.gyp +++ b/extensions/shell/app_shell.gyp @@ -47,9 +47,9 @@ '<(DEPTH)/extensions/shell/browser/api/api_registration.gyp:shell_api_registration', '<(DEPTH)/extensions/shell/common/api/api.gyp:shell_api', '<(DEPTH)/mojo/mojo_base.gyp:mojo_environment_chromium', + '<(DEPTH)/mojo/mojo_edk.gyp:mojo_system_impl', '<(DEPTH)/skia/skia.gyp:skia', '<(DEPTH)/third_party/WebKit/public/blink.gyp:blink', - '<(DEPTH)/third_party/mojo/mojo_edk.gyp:mojo_system_impl', '<(DEPTH)/ui/base/ime/ui_base_ime.gyp:ui_base_ime', '<(DEPTH)/ui/base/ui_base.gyp:ui_base', '<(DEPTH)/v8/tools/gyp/v8.gyp:v8', diff --git a/extensions/test/DEPS b/extensions/test/DEPS index b334588..27ef4ea 100644 --- a/extensions/test/DEPS +++ b/extensions/test/DEPS @@ -1,5 +1,5 @@ include_rules = [ "+content/public", - "+third_party/mojo/src/mojo/edk/embedder", + "+mojo/edk/embedder", "+ui/gl", ] diff --git a/extensions/test/extensions_unittests_main.cc b/extensions/test/extensions_unittests_main.cc index ac9e8dd..bb9cc00 100644 --- a/extensions/test/extensions_unittests_main.cc +++ b/extensions/test/extensions_unittests_main.cc @@ -13,7 +13,7 @@ #include "extensions/common/constants.h" #include "extensions/common/extension_paths.h" #include "extensions/test/test_extensions_client.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/embedder.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gl/test/gl_surface_test_support.h" #include "url/url_util.h" @@ -110,7 +110,7 @@ void ExtensionsTestSuite::Shutdown() { int main(int argc, char** argv) { content::UnitTestTestSuite test_suite(new ExtensionsTestSuite(argc, argv)); - mojo::embedder::Init(); + mojo::edk::Init(); return base::LaunchUnitTests(argc, argv, base::Bind(&content::UnitTestTestSuite::Run, diff --git a/ipc/mojo/BUILD.gn b/ipc/mojo/BUILD.gn index 29e3a95..5555141 100644 --- a/ipc/mojo/BUILD.gn +++ b/ipc/mojo/BUILD.gn @@ -39,17 +39,21 @@ component("mojo") { "//base", "//base/third_party/dynamic_annotations", "//ipc", + "//mojo/edk/system", "//mojo/environment:chromium", "//mojo/public/c/environment:environment", "//mojo/public/cpp/bindings", - "//third_party/mojo/src/mojo/edk/system", ] } test("ipc_mojo_unittests") { sources = [ "async_handle_waiter_unittest.cc", - "ipc_channel_mojo_unittest.cc", + + # TODO(rockot): Re-enable these when we're ready to start using ChannelMojo + # again. They need to be updated to support multiprocess testing with the + # current Mojo EDK implementation. + #"ipc_channel_mojo_unittest.cc", "ipc_mojo_bootstrap_unittest.cc", "run_all_unittests.cc", ] @@ -61,9 +65,9 @@ test("ipc_mojo_unittests") { "//ipc", "//ipc:test_support", "//ipc/mojo", + "//mojo/edk/system", "//mojo/environment:chromium", "//testing/gtest", - "//third_party/mojo/src/mojo/edk/system", "//url", ] } @@ -81,8 +85,8 @@ test("ipc_mojo_perftests") { "//ipc", "//ipc:test_support", "//ipc/mojo", + "//mojo/edk/system", "//mojo/environment:chromium", - "//third_party/mojo/src/mojo/edk/system", "//url", ] } diff --git a/ipc/mojo/DEPS b/ipc/mojo/DEPS index 59e80a9..348fd9f 100644 --- a/ipc/mojo/DEPS +++ b/ipc/mojo/DEPS @@ -1,5 +1,4 @@ include_rules = [ "+mojo/edk/embedder", "+mojo/public", - "+third_party/mojo/src/mojo/edk/embedder", ] diff --git a/ipc/mojo/async_handle_waiter.cc b/ipc/mojo/async_handle_waiter.cc index 4e07480..a4247fd 100644 --- a/ipc/mojo/async_handle_waiter.cc +++ b/ipc/mojo/async_handle_waiter.cc @@ -10,7 +10,7 @@ #include "base/location.h" #include "base/logging.h" #include "base/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/embedder.h" namespace IPC { namespace internal { @@ -142,8 +142,8 @@ AsyncHandleWaiter::~AsyncHandleWaiter() { MojoResult AsyncHandleWaiter::Wait(MojoHandle handle, MojoHandleSignals signals) { - return mojo::embedder::AsyncWait( - handle, signals, base::Bind(&Context::HandleIsReady, context_)); + return mojo::edk::AsyncWait(handle, signals, + base::Bind(&Context::HandleIsReady, context_)); } void AsyncHandleWaiter::InvokeCallback(MojoResult result) { diff --git a/ipc/mojo/ipc_channel_mojo.cc b/ipc/mojo/ipc_channel_mojo.cc index 404c814..872fa74 100644 --- a/ipc/mojo/ipc_channel_mojo.cc +++ b/ipc/mojo/ipc_channel_mojo.cc @@ -23,8 +23,8 @@ #include "ipc/mojo/client_channel.mojom.h" #include "ipc/mojo/ipc_mojo_bootstrap.h" #include "ipc/mojo/ipc_mojo_handle_attachment.h" +#include "mojo/edk/embedder/embedder.h" #include "mojo/public/cpp/bindings/binding.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" #if defined(OS_POSIX) && !defined(OS_NACL) #include "ipc/ipc_platform_file_attachment_posix.h" @@ -73,20 +73,9 @@ class ClientChannelMojo : public ChannelMojo, public ClientChannel { ~ClientChannelMojo() override {} // MojoBootstrap::Delegate implementation - void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle, + void OnPipeAvailable(mojo::edk::ScopedPlatformHandle handle, int32_t peer_pid) override { - if (base::CommandLine::ForCurrentProcess()->HasSwitch("use-new-edk")) { - InitMessageReader( - mojo::embedder::CreateChannel( - std::move(handle), - base::Callback<void(mojo::embedder::ChannelInfo*)>(), - scoped_refptr<base::TaskRunner>()), - peer_pid); - return; - } - CreateMessagingPipe( - std::move(handle), - base::Bind(&ClientChannelMojo::BindPipe, weak_factory_.GetWeakPtr())); + BindPipe(mojo::edk::CreateMessagePipe(std::move(handle))); } // ClientChannel implementation @@ -127,22 +116,8 @@ class ServerChannelMojo : public ChannelMojo { } // MojoBootstrap::Delegate implementation - void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle, + void OnPipeAvailable(mojo::edk::ScopedPlatformHandle handle, int32_t peer_pid) override { - if (base::CommandLine::ForCurrentProcess()->HasSwitch("use-new-edk")) { - message_pipe_ = mojo::embedder::CreateChannel( - std::move(handle), - base::Callback<void(mojo::embedder::ChannelInfo*)>(), - scoped_refptr<base::TaskRunner>()); - if (!message_pipe_.is_valid()) { - LOG(WARNING) << "mojo::CreateMessagePipe failed: "; - listener()->OnChannelError(); - return; - } - InitMessageReader(std::move(message_pipe_), peer_pid); - return; - } - mojo::ScopedMessagePipeHandle peer; MojoResult create_result = mojo::CreateMessagePipe(nullptr, &message_pipe_, &peer); @@ -151,10 +126,8 @@ class ServerChannelMojo : public ChannelMojo { listener()->OnChannelError(); return; } - CreateMessagingPipe( - std::move(handle), - base::Bind(&ServerChannelMojo::InitClientChannel, - weak_factory_.GetWeakPtr(), base::Passed(&peer))); + InitClientChannel(std::move(peer), + mojo::edk::CreateMessagePipe(std::move(handle))); } // Channel override void Close() override { @@ -205,26 +178,6 @@ base::ScopedFD TakeOrDupFile(internal::PlatformFileAttachment* attachment) { //------------------------------------------------------------------------------ -ChannelMojo::ChannelInfoDeleter::ChannelInfoDeleter( - scoped_refptr<base::TaskRunner> io_runner) - : io_runner(io_runner) { -} - -ChannelMojo::ChannelInfoDeleter::~ChannelInfoDeleter() { -} - -void ChannelMojo::ChannelInfoDeleter::operator()( - mojo::embedder::ChannelInfo* ptr) const { - if (base::ThreadTaskRunnerHandle::Get() == io_runner) { - mojo::embedder::DestroyChannelOnIOThread(ptr); - } else { - io_runner->PostTask( - FROM_HERE, base::Bind(&mojo::embedder::DestroyChannelOnIOThread, ptr)); - } -} - -//------------------------------------------------------------------------------ - // static bool ChannelMojo::ShouldBeUsed() { // TODO(rockot): Investigate performance bottlenecks and hopefully reenable @@ -274,7 +227,6 @@ ChannelMojo::ChannelMojo(scoped_refptr<base::TaskRunner> io_runner, : listener_(listener), peer_pid_(base::kNullProcessId), io_runner_(io_runner), - channel_info_(nullptr, ChannelInfoDeleter(nullptr)), waiting_connect_(true), weak_factory_(this) { // Create MojoBootstrap after all members are set as it touches @@ -298,51 +250,6 @@ void ChannelMojo::InitOnIOThread() { new ScopedIPCSupport(base::MessageLoop::current()->task_runner())); } -void ChannelMojo::CreateMessagingPipe( - mojo::embedder::ScopedPlatformHandle handle, - const CreateMessagingPipeCallback& callback) { - auto return_callback = base::Bind(&ChannelMojo::OnMessagingPipeCreated, - weak_factory_.GetWeakPtr(), callback); - if (!g_use_channel_on_io_thread_only || - base::ThreadTaskRunnerHandle::Get() == io_runner_) { - CreateMessagingPipeOnIOThread(std::move(handle), - base::ThreadTaskRunnerHandle::Get(), - return_callback); - } else { - io_runner_->PostTask( - FROM_HERE, - base::Bind(&ChannelMojo::CreateMessagingPipeOnIOThread, - base::Passed(&handle), base::ThreadTaskRunnerHandle::Get(), - return_callback)); - } -} - -// static -void ChannelMojo::CreateMessagingPipeOnIOThread( - mojo::embedder::ScopedPlatformHandle handle, - scoped_refptr<base::TaskRunner> callback_runner, - const CreateMessagingPipeOnIOThreadCallback& callback) { - mojo::embedder::ChannelInfo* channel_info; - mojo::ScopedMessagePipeHandle pipe = - mojo::embedder::CreateChannelOnIOThread(std::move(handle), &channel_info); - if (base::ThreadTaskRunnerHandle::Get() == callback_runner) { - callback.Run(std::move(pipe), channel_info); - } else { - callback_runner->PostTask( - FROM_HERE, base::Bind(callback, base::Passed(&pipe), channel_info)); - } -} - -void ChannelMojo::OnMessagingPipeCreated( - const CreateMessagingPipeCallback& callback, - mojo::ScopedMessagePipeHandle handle, - mojo::embedder::ChannelInfo* channel_info) { - DCHECK(!channel_info_.get()); - channel_info_ = scoped_ptr<mojo::embedder::ChannelInfo, ChannelInfoDeleter>( - channel_info, ChannelInfoDeleter(io_runner_)); - callback.Run(std::move(handle)); -} - bool ChannelMojo::Connect() { DCHECK(!message_reader_); return bootstrap_->Connect(); @@ -360,7 +267,6 @@ void ChannelMojo::Close() { waiting_connect_ = false; } - channel_info_.reset(); ipc_support_.reset(); to_be_deleted.reset(); } @@ -495,9 +401,9 @@ MojoResult ChannelMojo::ReadFromMessageAttachmentSet( } MojoHandle wrapped_handle; - MojoResult wrap_result = mojo::embedder::CreatePlatformHandleWrapper( - mojo::embedder::ScopedPlatformHandle( - mojo::embedder::PlatformHandle(file.release())), + MojoResult wrap_result = mojo::edk::CreatePlatformHandleWrapper( + mojo::edk::ScopedPlatformHandle( + mojo::edk::PlatformHandle(file.release())), &wrapped_handle); if (MOJO_RESULT_OK != wrap_result) { LOG(WARNING) << "Pipe failed to wrap handles. Closing: " diff --git a/ipc/mojo/ipc_channel_mojo.h b/ipc/mojo/ipc_channel_mojo.h index a5ddf1e..ccd28c2 100644 --- a/ipc/mojo/ipc_channel_mojo.h +++ b/ipc/mojo/ipc_channel_mojo.h @@ -22,7 +22,6 @@ #include "ipc/mojo/ipc_mojo_bootstrap.h" #include "ipc/mojo/scoped_ipc_support.h" #include "mojo/public/cpp/system/core.h" -#include "third_party/mojo/src/mojo/edk/embedder/channel_info_forward.h" namespace IPC { @@ -55,12 +54,6 @@ class IPC_MOJO_EXPORT ChannelMojo public MojoBootstrap::Delegate, public NON_EXPORTED_BASE(internal::MessagePipeReader::Delegate) { public: - using CreateMessagingPipeCallback = - base::Callback<void(mojo::ScopedMessagePipeHandle)>; - using CreateMessagingPipeOnIOThreadCallback = - base::Callback<void(mojo::ScopedMessagePipeHandle, - mojo::embedder::ChannelInfo*)>; - // True if ChannelMojo should be used regardless of the flag. static bool ShouldBeUsed(); @@ -120,23 +113,12 @@ class IPC_MOJO_EXPORT ChannelMojo Mode mode, Listener* listener); - void CreateMessagingPipe(mojo::embedder::ScopedPlatformHandle handle, - const CreateMessagingPipeCallback& callback); void InitMessageReader(mojo::ScopedMessagePipeHandle pipe, int32_t peer_pid); Listener* listener() const { return listener_; } void set_peer_pid(base::ProcessId pid) { peer_pid_ = pid; } private: - struct ChannelInfoDeleter { - explicit ChannelInfoDeleter(scoped_refptr<base::TaskRunner> io_runner); - ~ChannelInfoDeleter(); - - void operator()(mojo::embedder::ChannelInfo* ptr) const; - - scoped_refptr<base::TaskRunner> io_runner; - }; - // ChannelMojo needs to kill its MessagePipeReader in delayed manner // because the channel wants to kill these readers during the // notifications invoked by them. @@ -144,20 +126,10 @@ class IPC_MOJO_EXPORT ChannelMojo void InitOnIOThread(); - static void CreateMessagingPipeOnIOThread( - mojo::embedder::ScopedPlatformHandle handle, - scoped_refptr<base::TaskRunner> callback_runner, - const CreateMessagingPipeOnIOThreadCallback& callback); - void OnMessagingPipeCreated(const CreateMessagingPipeCallback& callback, - mojo::ScopedMessagePipeHandle handle, - mojo::embedder::ChannelInfo* channel_info); - scoped_ptr<MojoBootstrap> bootstrap_; Listener* listener_; base::ProcessId peer_pid_; scoped_refptr<base::TaskRunner> io_runner_; - scoped_ptr<mojo::embedder::ChannelInfo, - ChannelInfoDeleter> channel_info_; // Guards |message_reader_|, |waiting_connect_| and |pending_messages_| // diff --git a/ipc/mojo/ipc_mojo.gyp b/ipc/mojo/ipc_mojo.gyp index 313ecb2..5925546 100644 --- a/ipc/mojo/ipc_mojo.gyp +++ b/ipc/mojo/ipc_mojo.gyp @@ -17,14 +17,14 @@ 'defines': [ 'IPC_MOJO_IMPLEMENTATION', ], - 'includes': [ '../../third_party/mojo/mojom_bindings_generator.gypi' ], + 'includes': [ '../../mojo/mojom_bindings_generator.gypi' ], 'dependencies': [ '../ipc.gyp:ipc', '../../base/base.gyp:base', '../../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', '../../mojo/mojo_base.gyp:mojo_environment_chromium', - '../../third_party/mojo/mojo_edk.gyp:mojo_system_impl', - '../../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + '../../mojo/mojo_edk.gyp:mojo_system_impl', + '../../mojo/mojo_public.gyp:mojo_cpp_bindings', ], 'sources': [ 'client_channel.mojom', @@ -63,9 +63,9 @@ '../../base/base.gyp:base_i18n', '../../base/base.gyp:test_support_base', '../../mojo/mojo_base.gyp:mojo_environment_chromium', + '../../mojo/mojo_edk.gyp:mojo_system_impl', + '../../mojo/mojo_public.gyp:mojo_cpp_bindings', '../../testing/gtest.gyp:gtest', - '../../third_party/mojo/mojo_edk.gyp:mojo_system_impl', - '../../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', 'ipc_mojo', ], 'include_dirs': [ @@ -74,6 +74,11 @@ 'sources': [ 'async_handle_waiter_unittest.cc', 'run_all_unittests.cc', + + # TODO(rockot): Re-enable these when we're ready to start using + # ChannelMojo again. They need to be updated to support multiprocess + # testing with the current Mojo EDK implementation. + #"ipc_channel_mojo_unittest.cc", 'ipc_channel_mojo_unittest.cc', 'ipc_mojo_bootstrap_unittest.cc', ], @@ -91,9 +96,9 @@ '../../base/base.gyp:test_support_base', '../../base/base.gyp:test_support_perf', '../../mojo/mojo_base.gyp:mojo_environment_chromium', + '../../mojo/mojo_edk.gyp:mojo_system_impl', + '../../mojo/mojo_public.gyp:mojo_cpp_bindings', '../../testing/gtest.gyp:gtest', - '../../third_party/mojo/mojo_edk.gyp:mojo_system_impl', - '../../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', 'ipc_mojo', ], 'include_dirs': [ diff --git a/ipc/mojo/ipc_mojo_bootstrap.cc b/ipc/mojo/ipc_mojo_bootstrap.cc index d296675..74b3009 100644 --- a/ipc/mojo/ipc_mojo_bootstrap.cc +++ b/ipc/mojo/ipc_mojo_bootstrap.cc @@ -13,7 +13,7 @@ #include "build/build_config.h" #include "ipc/ipc_message_utils.h" #include "ipc/ipc_platform_file.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" +#include "mojo/edk/embedder/platform_channel_pair.h" namespace IPC { @@ -32,7 +32,7 @@ class MojoServerBootstrap : public MojoBootstrap { bool OnMessageReceived(const Message& message) override; void OnChannelConnected(int32_t peer_pid) override; - mojo::embedder::ScopedPlatformHandle server_pipe_; + mojo::edk::ScopedPlatformHandle server_pipe_; bool connected_; int32_t peer_pid_; @@ -46,7 +46,7 @@ void MojoServerBootstrap::SendClientPipe(int32_t peer_pid) { DCHECK_EQ(state(), STATE_INITIALIZED); DCHECK(connected_); - mojo::embedder::PlatformChannelPair channel_pair; + mojo::edk::PlatformChannelPair channel_pair; server_pipe_ = channel_pair.PassServerHandle(); base::Process peer_process = @@ -56,11 +56,7 @@ void MojoServerBootstrap::SendClientPipe(int32_t peer_pid) { base::Process::Open(peer_pid); #endif PlatformFileForTransit client_pipe = GetFileHandleForProcess( -#if defined(OS_POSIX) - channel_pair.PassClientHandle().release().fd, -#else channel_pair.PassClientHandle().release().handle, -#endif peer_process.Handle(), true); if (client_pipe == IPC::InvalidPlatformFileForTransit()) { #if !defined(OS_WIN) @@ -96,7 +92,7 @@ bool MojoServerBootstrap::OnMessageReceived(const Message&) { set_state(STATE_READY); CHECK(server_pipe_.is_valid()); delegate()->OnPipeAvailable( - mojo::embedder::ScopedPlatformHandle(server_pipe_.release()), peer_pid_); + mojo::edk::ScopedPlatformHandle(server_pipe_.release()), peer_pid_); return true; } @@ -139,8 +135,9 @@ bool MojoClientBootstrap::OnMessageReceived(const Message& message) { Send(new Message()); set_state(STATE_READY); delegate()->OnPipeAvailable( - mojo::embedder::ScopedPlatformHandle(mojo::embedder::PlatformHandle( - PlatformFileForTransitToPlatformFile(pipe))), peer_pid_); + mojo::edk::ScopedPlatformHandle(mojo::edk::PlatformHandle( + PlatformFileForTransitToPlatformFile(pipe))), + peer_pid_); return true; } diff --git a/ipc/mojo/ipc_mojo_bootstrap.h b/ipc/mojo/ipc_mojo_bootstrap.h index 4b5ccfb..e4d2d27 100644 --- a/ipc/mojo/ipc_mojo_bootstrap.h +++ b/ipc/mojo/ipc_mojo_bootstrap.h @@ -13,7 +13,7 @@ #include "build/build_config.h" #include "ipc/ipc_channel.h" #include "ipc/ipc_listener.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" +#include "mojo/edk/embedder/scoped_platform_handle.h" namespace IPC { @@ -31,7 +31,7 @@ class IPC_MOJO_EXPORT MojoBootstrap : public Listener { public: class Delegate { public: - virtual void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle, + virtual void OnPipeAvailable(mojo::edk::ScopedPlatformHandle handle, int32_t peer_pid) = 0; virtual void OnBootstrapError() = 0; }; diff --git a/ipc/mojo/ipc_mojo_bootstrap_unittest.cc b/ipc/mojo/ipc_mojo_bootstrap_unittest.cc index 60046d1..8ee5556 100644 --- a/ipc/mojo/ipc_mojo_bootstrap_unittest.cc +++ b/ipc/mojo/ipc_mojo_bootstrap_unittest.cc @@ -26,7 +26,7 @@ class TestingDelegate : public IPC::MojoBootstrap::Delegate { public: TestingDelegate() : passed_(false) {} - void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle, + void OnPipeAvailable(mojo::edk::ScopedPlatformHandle handle, int32_t peer_pid) override; void OnBootstrapError() override; @@ -36,9 +36,8 @@ class TestingDelegate : public IPC::MojoBootstrap::Delegate { bool passed_; }; -void TestingDelegate::OnPipeAvailable( - mojo::embedder::ScopedPlatformHandle handle, - int32_t peer_pid) { +void TestingDelegate::OnPipeAvailable(mojo::edk::ScopedPlatformHandle handle, + int32_t peer_pid) { passed_ = true; base::MessageLoop::current()->QuitWhenIdle(); } diff --git a/ipc/mojo/ipc_mojo_handle_attachment.cc b/ipc/mojo/ipc_mojo_handle_attachment.cc index 70b80c5..ccce0d9 100644 --- a/ipc/mojo/ipc_mojo_handle_attachment.cc +++ b/ipc/mojo/ipc_mojo_handle_attachment.cc @@ -8,7 +8,7 @@ #include "build/build_config.h" #include "ipc/ipc_message_attachment_set.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/embedder.h" namespace IPC { namespace internal { @@ -25,8 +25,8 @@ MessageAttachment::Type MojoHandleAttachment::GetType() const { #if defined(OS_POSIX) base::PlatformFile MojoHandleAttachment::TakePlatformFile() { - mojo::embedder::ScopedPlatformHandle platform_handle; - MojoResult unwrap_result = mojo::embedder::PassWrappedPlatformHandle( + mojo::edk::ScopedPlatformHandle platform_handle; + MojoResult unwrap_result = mojo::edk::PassWrappedPlatformHandle( handle_.get().value(), &platform_handle); handle_.reset(); if (unwrap_result != MOJO_RESULT_OK) { @@ -34,7 +34,7 @@ base::PlatformFile MojoHandleAttachment::TakePlatformFile() { return -1; } - return platform_handle.release().fd; + return platform_handle.release().handle; } #endif // OS_POSIX diff --git a/ipc/mojo/ipc_mojo_perftest.cc b/ipc/mojo/ipc_mojo_perftest.cc index d782c77..577c1c4 100644 --- a/ipc/mojo/ipc_mojo_perftest.cc +++ b/ipc/mojo/ipc_mojo_perftest.cc @@ -9,8 +9,8 @@ #include "build/build_config.h" #include "ipc/ipc_perftest_support.h" #include "ipc/mojo/ipc_channel_mojo.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" +#include "mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/platform_channel_pair.h" namespace { @@ -18,9 +18,7 @@ namespace { // it provides main() which doesn't have Mojo initialization. We need // some way to call Init() only once before using Mojo. struct MojoInitialier { - MojoInitialier() { - mojo::embedder::Init(); - } + MojoInitialier() { mojo::edk::Init(); } }; base::LazyInstance<MojoInitialier> g_mojo_initializer @@ -75,10 +73,10 @@ TEST_F(MojoChannelPerfTest, DISABLED_MaxChannelCount) { base::SetFdLimit(20000); #endif - std::vector<mojo::embedder::PlatformChannelPair*> channels; + std::vector<mojo::edk::PlatformChannelPair*> channels; for (size_t i = 0; i < 10000; ++i) { LOG(INFO) << "channels size: " << channels.size(); - channels.push_back(new mojo::embedder::PlatformChannelPair()); + channels.push_back(new mojo::edk::PlatformChannelPair()); } } diff --git a/ipc/mojo/run_all_unittests.cc b/ipc/mojo/run_all_unittests.cc index 43a1e4e..f0b5dbc 100644 --- a/ipc/mojo/run_all_unittests.cc +++ b/ipc/mojo/run_all_unittests.cc @@ -7,7 +7,7 @@ #include "base/test/launcher/unit_test_launcher.h" #include "base/test/test_suite.h" #include "build/build_config.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/embedder.h" #if defined(OS_ANDROID) #include "base/android/jni_android.h" @@ -20,7 +20,7 @@ int main(int argc, char** argv) { base::RegisterContentUriTestUtils(env); #endif base::TestSuite test_suite(argc, argv); - mojo::embedder::Init(); + mojo::edk::Init(); return base::LaunchUnitTestsSerially( argc, argv, base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite))); diff --git a/ipc/mojo/scoped_ipc_support.cc b/ipc/mojo/scoped_ipc_support.cc index 1557544..bcaa3a1 100644 --- a/ipc/mojo/scoped_ipc_support.cc +++ b/ipc/mojo/scoped_ipc_support.cc @@ -15,15 +15,13 @@ #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" #include "base/thread_task_runner_handle.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" -#include "third_party/mojo/src/mojo/edk/embedder/process_delegate.h" +#include "mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/process_delegate.h" namespace IPC { namespace { -// TODO(use_chrome_edk) -//class IPCSupportInitializer : public mojo::edk::ProcessDelegate { -class IPCSupportInitializer : public mojo::embedder::ProcessDelegate { +class IPCSupportInitializer : public mojo::edk::ProcessDelegate { public: IPCSupportInitializer() : init_count_(0), @@ -62,7 +60,7 @@ class IPCSupportInitializer : public mojo::embedder::ProcessDelegate { void ShutDownOnIOThread(); - // mojo::embedder::ProcessDelegate: + // mojo::edk::ProcessDelegate: void OnShutdownComplete() override {} static void WatchMessageLoopOnIOThread(MessageLoopObserver* observer); @@ -106,9 +104,7 @@ void IPCSupportInitializer::Init( io_thread_task_runner_ = io_thread_task_runner; io_thread_task_runner_->PostTask( FROM_HERE, base::Bind(&WatchMessageLoopOnIOThread, observer_)); - mojo::embedder::InitIPCSupport( - mojo::embedder::ProcessType::NONE, this, io_thread_task_runner_, - mojo::embedder::ScopedPlatformHandle()); + mojo::edk::InitIPCSupport(this, io_thread_task_runner_); } } @@ -137,7 +133,7 @@ void IPCSupportInitializer::ShutDown(bool force) { void IPCSupportInitializer::ShutDownOnIOThread() { base::AutoLock locker(lock_); if (shutting_down_ && !was_shut_down_) { - mojo::embedder::ShutdownIPCSupportOnIOThread(); + mojo::edk::ShutdownIPCSupportOnIOThread(); init_count_ = 0; shutting_down_ = false; io_thread_task_runner_ = nullptr; diff --git a/ipc/mojo/scoped_ipc_support.h b/ipc/mojo/scoped_ipc_support.h index 21013fa..0ed1b4e 100644 --- a/ipc/mojo/scoped_ipc_support.h +++ b/ipc/mojo/scoped_ipc_support.h @@ -18,7 +18,7 @@ namespace IPC { // the current process and that it is shutdown cleanly when no longer in use. // // NOTE: Unless you are making explicit calls to functions in the -// mojo::embedder namespace, you almost definitely DO NOT need this and should +// mojo::edk namespace, you almost definitely DO NOT need this and should // not be using it. class IPC_MOJO_EXPORT ScopedIPCSupport { public: diff --git a/mash/example/window_type_launcher/BUILD.gn b/mash/example/window_type_launcher/BUILD.gn index d05b7e6..9a4c4d3 100644 --- a/mash/example/window_type_launcher/BUILD.gn +++ b/mash/example/window_type_launcher/BUILD.gn @@ -26,6 +26,7 @@ executable("window_type_launcher") { "//mash/shell/public/interfaces", "//mojo/common:common_base", "//mojo/converters/geometry", + "//mojo/edk/system", "//mojo/message_pump", "//mojo/public/cpp/bindings", "//mojo/shell/public/cpp", @@ -33,7 +34,6 @@ executable("window_type_launcher") { "//mojo/shell/runner:init", "//mojo/shell/runner/child:lib", "//skia", - "//third_party/mojo/src/mojo/edk/system", "//ui/aura", "//ui/gfx", "//ui/gfx/geometry", diff --git a/mash/example/window_type_launcher/DEPS b/mash/example/window_type_launcher/DEPS index 68bd975..9b87a7d 100644 --- a/mash/example/window_type_launcher/DEPS +++ b/mash/example/window_type_launcher/DEPS @@ -1,5 +1,5 @@ include_rules = [ + "+mojo/edk/embedder", "+mojo/message_pump", "+mojo/runner", - "+third_party/mojo/src/mojo/edk/embedder", ] diff --git a/mash/example/window_type_launcher/main.cc b/mash/example/window_type_launcher/main.cc index 289b56c..f41e6bc 100644 --- a/mash/example/window_type_launcher/main.cc +++ b/mash/example/window_type_launcher/main.cc @@ -14,17 +14,17 @@ #include "base/threading/thread.h" #include "build/build_config.h" #include "mash/example/window_type_launcher/window_type_launcher.h" +#include "mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/process_delegate.h" #include "mojo/message_pump/message_pump_mojo.h" #include "mojo/shell/public/cpp/shell_connection.h" #include "mojo/shell/public/interfaces/shell_client.mojom.h" #include "mojo/shell/runner/child/runner_connection.h" #include "mojo/shell/runner/init.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" -#include "third_party/mojo/src/mojo/edk/embedder/process_delegate.h" namespace { -class ProcessDelegate : public mojo::embedder::ProcessDelegate { +class ProcessDelegate : public mojo::edk::ProcessDelegate { public: ProcessDelegate() {} ~ProcessDelegate() override {} @@ -52,18 +52,14 @@ int main(int argc, char** argv) { #endif { - mojo::embedder::PreInitializeChildProcess(); - mojo::embedder::Init(); + mojo::edk::Init(); ProcessDelegate process_delegate; base::Thread io_thread("io_thread"); base::Thread::Options io_thread_options(base::MessageLoop::TYPE_IO, 0); CHECK(io_thread.StartWithOptions(io_thread_options)); - mojo::embedder::InitIPCSupport(mojo::embedder::ProcessType::NONE, - &process_delegate, - io_thread.task_runner().get(), - mojo::embedder::ScopedPlatformHandle()); + mojo::edk::InitIPCSupport(&process_delegate, io_thread.task_runner().get()); mojo::ShellClientRequest request; scoped_ptr<mojo::shell::RunnerConnection> connection( @@ -74,7 +70,7 @@ int main(int argc, char** argv) { mojo::ShellConnection impl(&delegate, std::move(request)); loop.Run(); - mojo::embedder::ShutdownIPCSupport(); + mojo::edk::ShutdownIPCSupport(); } return 0; diff --git a/mash/wm/BUILD.gn b/mash/wm/BUILD.gn index 427c11e..347c0f1 100644 --- a/mash/wm/BUILD.gn +++ b/mash/wm/BUILD.gn @@ -186,11 +186,11 @@ source_set("unittests") { "//components/mus/public/cpp/tests:unittest_support", "//mojo/converters/geometry", "//mojo/converters/input_events", + "//mojo/edk/system", "//mojo/gles2", "//mojo/platform_handle", "//mojo/public/cpp/system", "//testing/gtest", - "//third_party/mojo/src/mojo/edk/system", "//ui/base", "//ui/events", "//ui/gfx:test_support", diff --git a/media/mojo/interfaces/mojo_bindings.gyp b/media/mojo/interfaces/mojo_bindings.gyp index f0ce5c0..c4d0679 100644 --- a/media/mojo/interfaces/mojo_bindings.gyp +++ b/media/mojo/interfaces/mojo_bindings.gyp @@ -10,7 +10,7 @@ 'sources': [ 'platform_verification.mojom', ], - 'includes': [ '../../../third_party/mojo/mojom_bindings_generator.gypi' ], + 'includes': [ '../../../mojo/mojom_bindings_generator.gypi' ], }, { 'target_name': 'platform_verification_api', @@ -19,7 +19,7 @@ 'platform_verification_mojo_bindings', '../../../mojo/mojo_base.gyp:mojo_application_bindings', '../../../mojo/mojo_base.gyp:mojo_environment_chromium', - '../../../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + '../../../mojo/mojo_public.gyp:mojo_cpp_bindings', ], 'sources': [ '<(SHARED_INTERMEDIATE_DIR)/media/mojo/interfaces/platform_verification.mojom.cc', @@ -33,7 +33,7 @@ 'sources': [ 'provision_fetcher.mojom', ], - 'includes': [ '../../../third_party/mojo/mojom_bindings_generator.gypi' ], + 'includes': [ '../../../mojo/mojom_bindings_generator.gypi' ], }, { 'target_name': 'provision_fetcher_api', @@ -42,7 +42,7 @@ 'provision_fetcher_mojo_bindings', '../../../mojo/mojo_base.gyp:mojo_application_bindings', '../../../mojo/mojo_base.gyp:mojo_environment_chromium', - '../../../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + '../../../mojo/mojo_public.gyp:mojo_cpp_bindings', ], 'sources': [ '<(SHARED_INTERMEDIATE_DIR)/media/mojo/interfaces/provision_fetcher.mojom.cc', diff --git a/media/mojo/services/BUILD.gn b/media/mojo/services/BUILD.gn index 670f18d..0f68858 100644 --- a/media/mojo/services/BUILD.gn +++ b/media/mojo/services/BUILD.gn @@ -189,11 +189,11 @@ test("media_mojo_unittests") { "//media", "//media/base:test_support", "//media/mojo/interfaces", + "//mojo/edk/system", + "//mojo/edk/test:run_all_unittests", "//mojo/environment:chromium", "//testing/gmock", "//testing/gtest", - "//third_party/mojo/src/mojo/edk/system", - "//third_party/mojo/src/mojo/edk/test:run_all_unittests", ] } diff --git a/mojo/BUILD.gn b/mojo/BUILD.gn index 4afccf7..66ce039 100644 --- a/mojo/BUILD.gn +++ b/mojo/BUILD.gn @@ -35,28 +35,19 @@ group("tests") { "//mojo/converters/surfaces/tests:mojo_surfaces_lib_unittests", "//mojo/edk/js/test:js_integration_tests", "//mojo/edk/js/test:js_unittests", + "//mojo/edk/system:mojo_message_pipe_perftests", + "//mojo/edk/system:mojo_system_unittests", + "//mojo/edk/test:mojo_public_bindings_unittests", + "//mojo/edk/test:mojo_public_environment_unittests", + "//mojo/edk/test:mojo_public_system_perftests", + "//mojo/edk/test:mojo_public_system_unittests", + "//mojo/edk/test:mojo_public_utility_unittests", "//mojo/services/network:apptests", "//mojo/shell:apptests", "//mojo/shell:mojo_shell_unittests", "//mojo/shell/package_manager:unittests", "//mojo/shell/public/cpp/tests:mojo_public_application_unittests", "//mojo/shell/runner/host:mojo_runner_host_unittests", - - # TODO(use_chrome_edk): - #"//mojo/edk/system:mojo_message_pipe_perftests", - #"//mojo/edk/system:mojo_system_unittests", - #"//mojo/edk/test:mojo_public_bindings_unittests", - #"//mojo/edk/test:mojo_public_environment_unittests", - #"//mojo/edk/test:mojo_public_system_perftests", - #"//mojo/edk/test:mojo_public_system_unittests", - #"//mojo/edk/test:mojo_public_utility_unittests", - "//third_party/mojo/src/mojo/edk/system:mojo_message_pipe_perftests", - "//third_party/mojo/src/mojo/edk/system:mojo_system_unittests", - "//third_party/mojo/src/mojo/edk/test:mojo_public_bindings_unittests", - "//third_party/mojo/src/mojo/edk/test:mojo_public_environment_unittests", - "//third_party/mojo/src/mojo/edk/test:mojo_public_system_perftests", - "//third_party/mojo/src/mojo/edk/test:mojo_public_system_unittests", - "//third_party/mojo/src/mojo/edk/test:mojo_public_utility_unittests", ] if (is_android) { @@ -2,6 +2,4 @@ include_rules = [ "+base", "+build", "+testing", - "+third_party/mojo/src/mojo/edk", - "-third_party/mojo/src/mojo/edk/system", ] diff --git a/mojo/android/BUILD.gn b/mojo/android/BUILD.gn index c1a78b2..368c716 100644 --- a/mojo/android/BUILD.gn +++ b/mojo/android/BUILD.gn @@ -45,10 +45,10 @@ source_set("libsystem_java") { deps = [ ":system_java_jni_headers", "//base", + "//mojo/edk/system", "//mojo/environment:chromium", "//mojo/message_pump", "//mojo/public/cpp/environment", - "//third_party/mojo/src/mojo/edk/system", ] } @@ -123,11 +123,11 @@ shared_library("mojo_java_unittests") { "//base", "//base/test/:test_support", "//build/config/sanitizers:deps", + "//mojo/edk/system", "//mojo/message_pump", "//mojo/public/cpp/bindings/tests:mojo_public_bindings_test_utils", "//mojo/public/cpp/environment", "//mojo/public/cpp/test_support:test_utils", - "//third_party/mojo/src/mojo/edk/system", ] defines = [ "UNIT_TEST" ] } diff --git a/mojo/android/javatests/init_library.cc b/mojo/android/javatests/init_library.cc index 8615897..d2d9423 100644 --- a/mojo/android/javatests/init_library.cc +++ b/mojo/android/javatests/init_library.cc @@ -10,7 +10,7 @@ #include "mojo/android/javatests/mojo_test_case.h" #include "mojo/android/javatests/validation_test_util.h" #include "mojo/android/system/core_impl.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/embedder.h" namespace { @@ -27,7 +27,7 @@ bool RegisterJNI(JNIEnv* env) { } bool Init() { - mojo::embedder::Init(); + mojo::edk::Init(); return true; } diff --git a/mojo/common/BUILD.gn b/mojo/common/BUILD.gn index d541ae1..4f3d8f7 100644 --- a/mojo/common/BUILD.gn +++ b/mojo/common/BUILD.gn @@ -53,8 +53,6 @@ source_set("url_type_converters") { "url_type_converters.h", ] - include_dirs = [ "//third_party/mojo/src/" ] - deps = [ ":common_base", "//base", @@ -71,13 +69,13 @@ test("mojo_common_unittests") { "//base", "//base:message_loop_tests", "//base/test:test_support", + "//mojo/edk/test:run_all_unittests", + "//mojo/edk/test:test_support", "//mojo/environment:chromium", "//mojo/message_pump", "//mojo/public/cpp/bindings", "//mojo/public/cpp/test_support:test_utils", "//testing/gtest", - "//third_party/mojo/src/mojo/edk/test:run_all_unittests", - "//third_party/mojo/src/mojo/edk/test:test_support", "//url", ] @@ -100,11 +98,11 @@ test("mojo_common_perftests") { deps = [ ":common", "//base", + "//mojo/edk/test:run_all_perftests", "//mojo/environment:chromium", "//mojo/message_pump", "//mojo/public/cpp/test_support:test_utils", "//testing/gtest", - "//third_party/mojo/src/mojo/edk/test:run_all_perftests", ] sources = [ diff --git a/mojo/converters/surfaces/tests/BUILD.gn b/mojo/converters/surfaces/tests/BUILD.gn index 95cad2b..edfe3ba 100644 --- a/mojo/converters/surfaces/tests/BUILD.gn +++ b/mojo/converters/surfaces/tests/BUILD.gn @@ -16,10 +16,10 @@ test("mojo_surfaces_lib_unittests") { "//mojo/converters/geometry", "//mojo/converters/surfaces", "//mojo/converters/transform", + "//mojo/edk/test:run_all_unittests", "//mojo/environment:chromium", "//skia", "//testing/gtest", - "//third_party/mojo/src/mojo/edk/test:run_all_unittests", "//ui/gfx", "//ui/gfx:test_support", "//ui/gfx/geometry", diff --git a/mojo/edk/embedder/BUILD.gn b/mojo/edk/embedder/BUILD.gn index 620d1c9..5e645db 100644 --- a/mojo/edk/embedder/BUILD.gn +++ b/mojo/edk/embedder/BUILD.gn @@ -2,6 +2,24 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +source_set("headers") { + sources = [ + "configuration.h", + "embedder.h", + "embedder_internal.h", + "platform_channel_pair.h", + "platform_handle.h", + "platform_handle_utils.h", + "process_delegate.h", + "scoped_platform_handle.h", + ] + + public_deps = [ + "//base", + "//mojo/public/cpp/system", + ] +} + source_set("embedder") { # This isn't really a standalone target; it must be linked into the # mojo_system_impl component. @@ -34,12 +52,13 @@ source_set("embedder") { public_deps = [ ":delegates", + ":headers", ":platform", + "//base", "//mojo/public/cpp/system", ] deps = [ - "//base", "//crypto", ] } @@ -112,13 +131,11 @@ source_set("delegates") { ] } -# TODO(use_chrome_edk): remove "2" -source_set("embedder_unittests2") { +source_set("embedder_unittests") { testonly = true - # TODO(use_chrome_edk): remove "2". Also enable this visibility check when we - # figure out why it's failing just on Android. - #visibility = [ "//mojo/edk/system:mojo_system_unittests2" ] + # TODO: Figure out why this visibility check fails on Android. + # visibility = [ "//mojo/edk/system:mojo_system_unittests" ] sources = [ "embedder_unittest.cc", @@ -129,17 +146,10 @@ source_set("embedder_unittests2") { deps = [ "//base", "//base/test:test_support", - "//mojo/message_pump", - - # TODO(use_chrome_edk): temporary since the Mojo wrapper primitives are - # declared in third party only for now. + "//mojo/edk/system", "//mojo/edk/system:test_utils", "//mojo/edk/test:test_support", + "//mojo/message_pump", "//testing/gtest", - "//third_party/mojo/src/mojo/edk/system", - - # TODO(use_chrome_edk): temporary since the Mojo wrapper primitives are - # declared in third party only for now. - "//third_party/mojo/src/mojo/edk/system", ] } diff --git a/mojo/edk/embedder/embedder.cc b/mojo/edk/embedder/embedder.cc index 696424e..37c3ddc 100644 --- a/mojo/edk/embedder/embedder.cc +++ b/mojo/edk/embedder/embedder.cc @@ -39,12 +39,6 @@ Core* GetCore() { return g_core; } void SetMaxMessageSize(size_t bytes) { } -void PreInitializeParentProcess() { -} - -void PreInitializeChildProcess() { -} - ScopedPlatformHandle ChildProcessLaunched(base::ProcessHandle child_process) { PlatformChannelPair channel; ChildProcessLaunched(child_process, channel.PassServerHandle()); diff --git a/mojo/edk/embedder/embedder.h b/mojo/edk/embedder/embedder.h index 81d098f..1adbc79 100644 --- a/mojo/edk/embedder/embedder.h +++ b/mojo/edk/embedder/embedder.h @@ -33,12 +33,6 @@ class ProcessDelegate; // Allows changing the default max message size. Must be called before Init. MOJO_SYSTEM_IMPL_EXPORT void SetMaxMessageSize(size_t bytes); -// Must be called before Init in the parent (unsandboxed) process. -MOJO_SYSTEM_IMPL_EXPORT void PreInitializeParentProcess(); - -// Must be called before Init in the child (sandboxed) process. -MOJO_SYSTEM_IMPL_EXPORT void PreInitializeChildProcess(); - // Called in the parent process for each child process that is launched. The // returned handle must be sent to the child process which then calls // SetParentPipeHandle. diff --git a/mojo/edk/embedder/embedder_internal.h b/mojo/edk/embedder/embedder_internal.h index 9c11f84..6b2c3b3 100644 --- a/mojo/edk/embedder/embedder_internal.h +++ b/mojo/edk/embedder/embedder_internal.h @@ -35,13 +35,10 @@ extern Broker* g_broker; extern PlatformSupport* g_platform_support; // Instance of |Core| used by the system functions (|Mojo...()|). -extern Core* g_core; +extern MOJO_SYSTEM_IMPL_EXPORT Core* g_core; extern base::TaskRunner* g_delegate_thread_task_runner; extern ProcessDelegate* g_process_delegate; -// TODO(use_chrome_edk): temporary until we have only one SDK. -MOJO_SYSTEM_IMPL_EXPORT Core* GetCore(); - } // namespace internal } // namepace edk diff --git a/mojo/edk/embedder/embedder_unittest.cc b/mojo/edk/embedder/embedder_unittest.cc index 09794e3..86cfc5b 100644 --- a/mojo/edk/embedder/embedder_unittest.cc +++ b/mojo/edk/embedder/embedder_unittest.cc @@ -190,6 +190,8 @@ TEST_F(EmbedderTest, ChannelsHandlePassing) { // 11. (wait/cl.) // 12. (wait/cl.) +#if !defined(OS_IOS) + #if defined(OS_ANDROID) // Android multi-process tests are not executing the new process. This is flaky. #define MAYBE_MultiprocessChannels DISABLED_MultiprocessChannels @@ -285,6 +287,8 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MultiprocessChannelsClient, EmbedderTest, // TODO(vtl): Test immediate write & close. // TODO(vtl): Test broken-connection cases. +#endif // !defined(OS_IOS) + } // namespace } // namespace edk } // namespace mojo diff --git a/mojo/edk/embedder/entrypoints.cc b/mojo/edk/embedder/entrypoints.cc index 3a68dcd..102b25f 100644 --- a/mojo/edk/embedder/entrypoints.cc +++ b/mojo/edk/embedder/entrypoints.cc @@ -10,15 +10,13 @@ #include "mojo/public/c/system/data_pipe.h" #include "mojo/public/c/system/functions.h" #include "mojo/public/c/system/message_pipe.h" +#include "mojo/public/c/system/wait_set.h" using mojo::edk::internal::g_core; -// TODO(use_chrome_edk): commented out since for now we use the entrypoints in -// third_party and that checks the command line to redirect here. -/* - // Definitions of the system functions. extern "C" { + MojoTimeTicks MojoGetTimeTicksNow() { return g_core->GetTimeTicksNow(); } @@ -44,6 +42,29 @@ MojoResult MojoWaitMany(const MojoHandle* handles, signals_states); } +MojoResult MojoCreateWaitSet(MojoHandle* wait_set_handle) { + return g_core->CreateWaitSet(wait_set_handle); +} + +MojoResult MojoAddHandle(MojoHandle wait_set_handle, + MojoHandle handle, + MojoHandleSignals signals) { + return g_core->AddHandle(wait_set_handle, handle, signals); +} + +MojoResult MojoRemoveHandle(MojoHandle wait_set_handle, MojoHandle handle) { + return g_core->RemoveHandle(wait_set_handle, handle); +} + +MojoResult MojoGetReadyHandles(MojoHandle wait_set_handle, + uint32_t* count, + MojoHandle* handles, + MojoResult* results, + struct MojoHandleSignalsState* signals_states) { + return g_core->GetReadyHandles(wait_set_handle, count, handles, results, + signals_states); +} + MojoResult MojoCreateMessagePipe(const MojoCreateMessagePipeOptions* options, MojoHandle* message_pipe_handle0, MojoHandle* message_pipe_handle1) { @@ -148,4 +169,3 @@ MojoResult MojoUnmapBuffer(void* buffer) { } } // extern "C" -*/ diff --git a/mojo/edk/js/core.cc b/mojo/edk/js/core.cc index c4c4656..f1fc916 100644 --- a/mojo/edk/js/core.cc +++ b/mojo/edk/js/core.cc @@ -24,6 +24,7 @@ namespace mojo { namespace edk { +namespace js { namespace { @@ -285,8 +286,8 @@ v8::Handle<v8::Value> DoDrainData(gin::Arguments* args, } bool IsHandle(gin::Arguments* args, v8::Handle<v8::Value> val) { - gin::Handle<mojo::edk::HandleWrapper> ignore_handle; - return gin::Converter<gin::Handle<mojo::edk::HandleWrapper>>::FromV8( + gin::Handle<mojo::edk::js::HandleWrapper> ignore_handle; + return gin::Converter<gin::Handle<mojo::edk::js::HandleWrapper>>::FromV8( args->isolate(), val, &ignore_handle); } @@ -378,5 +379,6 @@ v8::Local<v8::Value> Core::GetModule(v8::Isolate* isolate) { return templ->NewInstance(); } +} // namespace js } // namespace edk } // namespace mojo diff --git a/mojo/edk/js/core.h b/mojo/edk/js/core.h index c13b2da..ca203ea 100644 --- a/mojo/edk/js/core.h +++ b/mojo/edk/js/core.h @@ -9,6 +9,7 @@ namespace mojo { namespace edk { +namespace js { class Core { public: @@ -16,6 +17,7 @@ class Core { static v8::Local<v8::Value> GetModule(v8::Isolate* isolate); }; +} // namespace js } // namespace edk } // namespace mojo diff --git a/mojo/edk/js/drain_data.cc b/mojo/edk/js/drain_data.cc index 49c0552..bc5d223 100644 --- a/mojo/edk/js/drain_data.cc +++ b/mojo/edk/js/drain_data.cc @@ -17,6 +17,7 @@ namespace mojo { namespace edk { +namespace js { DrainData::DrainData(v8::Isolate* isolate, mojo::Handle handle) : isolate_(isolate), @@ -130,5 +131,6 @@ void DrainData::DeliverData(MojoResult result) { delete this; } +} // namespace js } // namespace edk } // namespace mojo diff --git a/mojo/edk/js/drain_data.h b/mojo/edk/js/drain_data.h index 63c9e49..9fcdba2 100644 --- a/mojo/edk/js/drain_data.h +++ b/mojo/edk/js/drain_data.h @@ -13,6 +13,7 @@ namespace mojo { namespace edk { +namespace js { // This class is the implementation of the Mojo JavaScript core module's // drainData() method. It is not intended to be used directly. The caller @@ -58,6 +59,7 @@ class DrainData { ScopedVector<DataBuffer> data_buffers_; }; +} // namespace js } // namespace edk } // namespace mojo diff --git a/mojo/edk/js/handle.cc b/mojo/edk/js/handle.cc index c465f46..9f9f161 100644 --- a/mojo/edk/js/handle.cc +++ b/mojo/edk/js/handle.cc @@ -8,6 +8,7 @@ namespace mojo { namespace edk { +namespace js { gin::WrapperInfo HandleWrapper::kWrapperInfo = { gin::kEmbedderNativeGin }; @@ -39,6 +40,7 @@ void HandleWrapper::NotifyCloseObservers() { FOR_EACH_OBSERVER(HandleCloseObserver, close_observers_, OnWillCloseHandle()); } +} // namespace js } // namespace edk } // namespace mojo @@ -48,7 +50,7 @@ v8::Handle<v8::Value> Converter<mojo::Handle>::ToV8(v8::Isolate* isolate, const mojo::Handle& val) { if (!val.is_valid()) return v8::Null(isolate); - return mojo::edk::HandleWrapper::Create(isolate, val.value()).ToV8(); + return mojo::edk::js::HandleWrapper::Create(isolate, val.value()).ToV8(); } bool Converter<mojo::Handle>::FromV8(v8::Isolate* isolate, @@ -59,9 +61,9 @@ bool Converter<mojo::Handle>::FromV8(v8::Isolate* isolate, return true; } - gin::Handle<mojo::edk::HandleWrapper> handle; - if (!Converter<gin::Handle<mojo::edk::HandleWrapper> >::FromV8( - isolate, val, &handle)) + gin::Handle<mojo::edk::js::HandleWrapper> handle; + if (!Converter<gin::Handle<mojo::edk::js::HandleWrapper>>::FromV8( + isolate, val, &handle)) return false; *out = handle->get(); @@ -79,5 +81,4 @@ bool Converter<mojo::MessagePipeHandle>::FromV8(v8::Isolate* isolate, return Converter<mojo::Handle>::FromV8(isolate, val, out); } - } // namespace gin diff --git a/mojo/edk/js/handle.h b/mojo/edk/js/handle.h index 3b95b17..2470fac 100644 --- a/mojo/edk/js/handle.h +++ b/mojo/edk/js/handle.h @@ -15,6 +15,8 @@ namespace mojo { namespace edk { +namespace js { + class HandleCloseObserver; // Wrapper for mojo Handles exposed to JavaScript. This ensures the Handle @@ -44,6 +46,7 @@ class HandleWrapper : public gin::Wrappable<HandleWrapper> { base::ObserverList<HandleCloseObserver> close_observers_; }; +} // namespace js } // namespace edk } // namespace mojo @@ -72,26 +75,28 @@ struct Converter<mojo::MessagePipeHandle> { // We need to specialize the normal gin::Handle converter in order to handle // converting |null| to a wrapper for an empty mojo::Handle. -template<> -struct Converter<gin::Handle<mojo::edk::HandleWrapper> > { +template <> +struct Converter<gin::Handle<mojo::edk::js::HandleWrapper>> { static v8::Handle<v8::Value> ToV8( v8::Isolate* isolate, - const gin::Handle<mojo::edk::HandleWrapper>& val) { + const gin::Handle<mojo::edk::js::HandleWrapper>& val) { return val.ToV8(); } - static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val, - gin::Handle<mojo::edk::HandleWrapper>* out) { + static bool FromV8(v8::Isolate* isolate, + v8::Handle<v8::Value> val, + gin::Handle<mojo::edk::js::HandleWrapper>* out) { if (val->IsNull()) { - *out = mojo::edk::HandleWrapper::Create(isolate, MOJO_HANDLE_INVALID); + *out = mojo::edk::js::HandleWrapper::Create(isolate, MOJO_HANDLE_INVALID); return true; } - mojo::edk::HandleWrapper* object = NULL; - if (!Converter<mojo::edk::HandleWrapper*>::FromV8(isolate, val, &object)) { + mojo::edk::js::HandleWrapper* object = NULL; + if (!Converter<mojo::edk::js::HandleWrapper*>::FromV8(isolate, val, + &object)) { return false; } - *out = gin::Handle<mojo::edk::HandleWrapper>(val, object); + *out = gin::Handle<mojo::edk::js::HandleWrapper>(val, object); return true; } }; diff --git a/mojo/edk/js/handle_close_observer.h b/mojo/edk/js/handle_close_observer.h index b507350..c7b935e 100644 --- a/mojo/edk/js/handle_close_observer.h +++ b/mojo/edk/js/handle_close_observer.h @@ -7,6 +7,7 @@ namespace mojo { namespace edk { +namespace js { class HandleCloseObserver { public: @@ -16,6 +17,7 @@ class HandleCloseObserver { virtual ~HandleCloseObserver() {} }; +} // namespace js } // namespace edk } // namespace mojo diff --git a/mojo/edk/js/handle_unittest.cc b/mojo/edk/js/handle_unittest.cc index 6ee4444..dd2562f 100644 --- a/mojo/edk/js/handle_unittest.cc +++ b/mojo/edk/js/handle_unittest.cc @@ -10,6 +10,7 @@ namespace mojo { namespace edk { +namespace js { class HandleWrapperTest : public testing::Test, public HandleCloseObserver { @@ -86,5 +87,6 @@ TEST_F(HandleWrapperTest, DestroyWithValidHandle) { EXPECT_EQ(1, closes_observed_); } +} // namespace js } // namespace edk } // namespace mojo diff --git a/mojo/edk/js/mojo_runner_delegate.cc b/mojo/edk/js/mojo_runner_delegate.cc index 9b18b55..dda0b2c 100644 --- a/mojo/edk/js/mojo_runner_delegate.cc +++ b/mojo/edk/js/mojo_runner_delegate.cc @@ -18,6 +18,7 @@ namespace mojo { namespace edk { +namespace js { namespace { @@ -74,5 +75,6 @@ void MojoRunnerDelegate::UnhandledException(gin::ShellRunner* runner, LOG(ERROR) << try_catch.GetStackTrace(); } +} // namespace js } // namespace edk } // namespace mojo diff --git a/mojo/edk/js/mojo_runner_delegate.h b/mojo/edk/js/mojo_runner_delegate.h index 7b50b30..a76460c 100644 --- a/mojo/edk/js/mojo_runner_delegate.h +++ b/mojo/edk/js/mojo_runner_delegate.h @@ -11,6 +11,7 @@ namespace mojo { namespace edk { +namespace js { class MojoRunnerDelegate : public gin::ModuleRunnerDelegate { public: @@ -27,6 +28,7 @@ class MojoRunnerDelegate : public gin::ModuleRunnerDelegate { DISALLOW_COPY_AND_ASSIGN(MojoRunnerDelegate); }; +} // namespace js } // namespace edk } // namespace mojo diff --git a/mojo/edk/js/support.cc b/mojo/edk/js/support.cc index 3e4391c..66d84a0 100644 --- a/mojo/edk/js/support.cc +++ b/mojo/edk/js/support.cc @@ -18,6 +18,7 @@ namespace mojo { namespace edk { +namespace js { namespace { @@ -56,5 +57,6 @@ v8::Local<v8::Value> Support::GetModule(v8::Isolate* isolate) { return templ->NewInstance(); } +} // namespace js } // namespace edk } // namespace mojo diff --git a/mojo/edk/js/support.h b/mojo/edk/js/support.h index 1edc00c..c57cf7a 100644 --- a/mojo/edk/js/support.h +++ b/mojo/edk/js/support.h @@ -9,6 +9,7 @@ namespace mojo { namespace edk { +namespace js { class Support { public: @@ -16,6 +17,7 @@ class Support { static v8::Local<v8::Value> GetModule(v8::Isolate* isolate); }; +} // namespace js } // namespace edk } // namespace mojo diff --git a/mojo/edk/js/test/run_js_integration_tests.cc b/mojo/edk/js/test/run_js_integration_tests.cc index 11fd74b..00d3e96 100644 --- a/mojo/edk/js/test/run_js_integration_tests.cc +++ b/mojo/edk/js/test/run_js_integration_tests.cc @@ -17,6 +17,7 @@ namespace mojo { namespace edk { +namespace js { namespace { class TestRunnerDelegate : public gin::FileRunnerDelegate { @@ -53,5 +54,6 @@ TEST(JSTest, sample_service) { } } // namespace +} // namespace js } // namespace edk } // namespace mojo diff --git a/mojo/edk/js/test/run_js_tests.cc b/mojo/edk/js/test/run_js_tests.cc index 73df40c..eb41b89 100644 --- a/mojo/edk/js/test/run_js_tests.cc +++ b/mojo/edk/js/test/run_js_tests.cc @@ -16,6 +16,7 @@ namespace mojo { namespace edk { +namespace js { namespace { class TestRunnerDelegate : public gin::FileRunnerDelegate { @@ -63,5 +64,6 @@ TEST(JSTest, validation) { } } // namespace +} // namespace js } // namespace edk } // namespace mojo diff --git a/mojo/edk/js/tests/js_to_cpp_tests.cc b/mojo/edk/js/tests/js_to_cpp_tests.cc index 2f55f31..08f3a0c 100644 --- a/mojo/edk/js/tests/js_to_cpp_tests.cc +++ b/mojo/edk/js/tests/js_to_cpp_tests.cc @@ -29,6 +29,7 @@ namespace mojo { namespace edk { +namespace js { // Global value updated by some checks to prevent compilers from optimizing // reads out of existence. @@ -440,5 +441,6 @@ TEST_F(JsToCppTest, BackPointer) { EXPECT_TRUE(cpp_side_connection.DidSucceed()); } +} // namespace js } // namespace edk } // namespace mojo diff --git a/mojo/edk/js/threading.cc b/mojo/edk/js/threading.cc index 1e6c9a6..db9f12d 100644 --- a/mojo/edk/js/threading.cc +++ b/mojo/edk/js/threading.cc @@ -11,6 +11,7 @@ namespace mojo { namespace edk { +namespace js { namespace { @@ -43,5 +44,6 @@ v8::Local<v8::Value> Threading::GetModule(v8::Isolate* isolate) { Threading::Threading() { } +} // namespace js } // namespace edk } // namespace mojo diff --git a/mojo/edk/js/threading.h b/mojo/edk/js/threading.h index 1a1803d..10404d5 100644 --- a/mojo/edk/js/threading.h +++ b/mojo/edk/js/threading.h @@ -10,6 +10,7 @@ namespace mojo { namespace edk { +namespace js { class Threading { public: @@ -19,6 +20,7 @@ class Threading { Threading(); }; +} // namespace js } // namespace edk } // namespace mojo diff --git a/mojo/edk/js/waiting_callback.cc b/mojo/edk/js/waiting_callback.cc index 4d017fe..a28791c 100644 --- a/mojo/edk/js/waiting_callback.cc +++ b/mojo/edk/js/waiting_callback.cc @@ -11,6 +11,7 @@ namespace mojo { namespace edk { +namespace js { namespace { @@ -117,5 +118,6 @@ void WaitingCallback::OnWillCloseHandle() { MOJO_RESULT_INVALID_ARGUMENT)); } +} // namespace js } // namespace edk } // namespace mojo diff --git a/mojo/edk/js/waiting_callback.h b/mojo/edk/js/waiting_callback.h index 454585d..b11fcc3 100644 --- a/mojo/edk/js/waiting_callback.h +++ b/mojo/edk/js/waiting_callback.h @@ -17,6 +17,7 @@ namespace mojo { namespace edk { +namespace js { class WaitingCallback : public gin::Wrappable<WaitingCallback>, public HandleCloseObserver { @@ -63,6 +64,7 @@ class WaitingCallback : public gin::Wrappable<WaitingCallback>, DISALLOW_COPY_AND_ASSIGN(WaitingCallback); }; +} // namespace js } // namespace edk } // namespace mojo diff --git a/mojo/edk/system/BUILD.gn b/mojo/edk/system/BUILD.gn index 112dac2..75a097d 100644 --- a/mojo/edk/system/BUILD.gn +++ b/mojo/edk/system/BUILD.gn @@ -17,13 +17,8 @@ config("system_config") { ] } -static_library("system") { - # TODO(use_chrome_edk): this should be a component to match third_party, - # but since third_party includes it, we either make it a static library - # or we have to change the export macros to be different than third_party. - #component("system") { - # TODO(use_chrome_edk): remove "2" - output_name = "mojo_system_impl2" +component("system") { + output_name = "mojo_system_impl" sources = [ "async_waiter.cc", @@ -85,12 +80,12 @@ static_library("system") { all_dependent_configs = [ ":system_config" ] public_deps = [ - "../../../mojo/public/c/system", - "../../../mojo/public/cpp/system", - "../embedder", - "../embedder:delegates", - "../embedder:platform", - "ports", + "//mojo/edk/embedder", + "//mojo/edk/embedder:delegates", + "//mojo/edk/embedder:platform", + "//mojo/edk/system/ports", + "//mojo/public/c/system", + "//mojo/public/cpp/system", ] deps = [ @@ -104,15 +99,14 @@ static_library("system") { # which is uninteresting. } - allow_circular_includes_from = [ "../embedder" ] + allow_circular_includes_from = [ "//mojo/edk/embedder" ] } group("tests") { testonly = true deps = [ - # TODO(use_chrome_edk): remove "2" - ":mojo_message_pipe_perftests2", - ":mojo_system_unittests2", + ":mojo_message_pipe_perftests", + ":mojo_system_unittests", ] } @@ -137,18 +131,14 @@ source_set("test_utils") { ] } -# TODO(use_chrome_edk): remove "2" -test("mojo_system_unittests2") { +test("mojo_system_unittests") { sources = [ "awakable_list_unittest.cc", "core_test_base.cc", "core_test_base.h", "core_unittest.cc", "data_pipe_unittest.cc", - "message_pipe_test_utils.cc", - "message_pipe_test_utils.h", "message_pipe_unittest.cc", - "multiprocess_message_pipe_unittest.cc", "options_validation_unittest.cc", "platform_handle_dispatcher_unittest.cc", "shared_buffer_dispatcher_unittest.cc", @@ -159,46 +149,38 @@ test("mojo_system_unittests2") { "waiter_unittest.cc", ] + if (!is_ios) { + sources += [ "multiprocess_message_pipe_unittest.cc" ] + } + deps = [ ":test_utils", - - # TODO(use_chrome_edk): remove "2" - "../../../mojo/public/cpp/environment:standalone", - "../embedder:embedder_unittests2", - "../test:test_support", "//base", "//base/test:test_support", + "//mojo/edk/embedder:embedder_unittests", + "//mojo/edk/system", "//mojo/edk/test:run_all_unittests", + "//mojo/edk/test:test_support", + "//mojo/public/cpp/environment:standalone", "//testing/gtest", - - # TODO(use_chrome_edk): temporary since the Mojo wrapper primitives are - # declared in third party only for now. - "//third_party/mojo/src/mojo/edk/system", ] - # TODO(use_chrome_edk): remove "2" - allow_circular_includes_from = [ "../embedder:embedder_unittests2" ] + allow_circular_includes_from = [ "//mojo/edk/embedder:embedder_unittests" ] } -# TODO(use_chrome_edk): remove "2" -test("mojo_message_pipe_perftests2") { +test("mojo_message_pipe_perftests") { sources = [ "message_pipe_perftest.cc", - "message_pipe_test_utils.cc", - "message_pipe_test_utils.h", ] deps = [ ":test_utils", - "../../../mojo/public/cpp/environment:standalone", - "../test:run_all_perftests", - "../test:test_support", "//base", "//base/test:test_support", + "//mojo/edk/system", + "//mojo/edk/test:run_all_perftests", + "//mojo/edk/test:test_support", + "//mojo/public/cpp/environment:standalone", "//testing/gtest", - - # TODO(use_chrome_edk): temporary since the Mojo wrapper primitives are - # declared in third party only for now. - "//third_party/mojo/src/mojo/edk/system", ] } diff --git a/mojo/edk/system/core_test_base.cc b/mojo/edk/system/core_test_base.cc index 6d94f1c..96c3f4da 100644 --- a/mojo/edk/system/core_test_base.cc +++ b/mojo/edk/system/core_test_base.cc @@ -11,6 +11,7 @@ #include "base/logging.h" #include "base/memory/ref_counted.h" +#include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/system/configuration.h" #include "mojo/edk/system/core.h" #include "mojo/edk/system/dispatcher.h" @@ -158,7 +159,7 @@ MojoHandle CoreTestBase::CreateMockHandle(CoreTestBase::MockHandleInfo* info) { } Core* CoreTestBase::core() { - return mojo::edk::internal::GetCore(); + return mojo::edk::internal::g_core; } // CoreTestBase_MockHandleInfo ------------------------------------------------- diff --git a/mojo/edk/system/data_pipe_unittest.cc b/mojo/edk/system/data_pipe_unittest.cc index 06c35a3..8ee5299 100644 --- a/mojo/edk/system/data_pipe_unittest.cc +++ b/mojo/edk/system/data_pipe_unittest.cc @@ -1656,6 +1656,8 @@ bool ReadAllData(MojoHandle consumer, return num_bytes == 0; } +#if !defined(OS_IOS) + #if defined(OS_ANDROID) // Android multi-process tests are not executing the new process. This is flaky. #define MAYBE_Multiprocess DISABLED_Multiprocess @@ -1835,7 +1837,13 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadAndCloseConsumer, DataPipeTest, h) { EXPECT_EQ("quit", ReadMessage(h)); } -TEST_F(DataPipeTest, SendConsumerAndCloseProducer) { +#if defined(OS_ANDROID) +// Android multi-process tests are not executing the new process. This is flaky. +#define MAYBE_SendConsumerAndCloseProducer DISABLED_SendConsumerAndCloseProducer +#else +#define MAYBE_SendConsumerAndCloseProducer SendConsumerAndCloseProducer +#endif // defined(OS_ANDROID) +TEST_F(DataPipeTest, MAYBE_SendConsumerAndCloseProducer) { // Create a new data pipe. MojoHandle p, c; EXPECT_EQ(MOJO_RESULT_OK, MojoCreateDataPipe(nullptr, &p ,&c)); @@ -1878,7 +1886,13 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateAndWrite, DataPipeTest, h) { EXPECT_EQ("quit", ReadMessage(h)); } -TEST_F(DataPipeTest, CreateInChild) { +#if defined(OS_ANDROID) +// Android multi-process tests are not executing the new process. This is flaky. +#define MAYBE_CreateInChild DISABLED_CreateInChild +#else +#define MAYBE_CreateInChild CreateInChild +#endif // defined(OS_ANDROID) +TEST_F(DataPipeTest, MAYBE_CreateInChild) { RUN_CHILD_ON_PIPE(CreateAndWrite, child) MojoHandle c; std::string expected_message = ReadMessageWithHandles(child, &c, 1); @@ -1902,6 +1916,8 @@ TEST_F(DataPipeTest, CreateInChild) { END_CHILD() } +#endif // !defined(OS_IOS) + } // namespace } // namespace edk } // namespace mojo diff --git a/mojo/edk/system/dispatcher_unittest.cc b/mojo/edk/system/dispatcher_unittest.cc deleted file mode 100644 index 1dc454a..0000000 --- a/mojo/edk/system/dispatcher_unittest.cc +++ /dev/null @@ -1,297 +0,0 @@ -// Copyright 2013 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 "mojo/edk/system/dispatcher.h" - -#include <stddef.h> - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_vector.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/simple_thread.h" -#include "mojo/edk/embedder/platform_shared_buffer.h" -#include "mojo/edk/system/waiter.h" -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace edk { -namespace { - -// Trivial subclass that makes the constructor public. -class TrivialDispatcher final : public Dispatcher { - public: - TrivialDispatcher() {} - - Type GetType() const override { return Type::UNKNOWN; } - - private: - friend class base::RefCountedThreadSafe<TrivialDispatcher>; - ~TrivialDispatcher() override {} - - scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock() - override { - lock().AssertAcquired(); - return scoped_refptr<Dispatcher>(new TrivialDispatcher()); - } - - MOJO_DISALLOW_COPY_AND_ASSIGN(TrivialDispatcher); -}; - -TEST(DispatcherTest, Basic) { - scoped_refptr<Dispatcher> d(new TrivialDispatcher()); - - EXPECT_EQ(Dispatcher::Type::UNKNOWN, d->GetType()); - - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->WriteMessage(nullptr, 0, nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->ReadMessage(nullptr, nullptr, nullptr, nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->WriteData(nullptr, nullptr, MOJO_WRITE_DATA_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->BeginWriteData(nullptr, nullptr, MOJO_WRITE_DATA_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndWriteData(0)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->ReadData(nullptr, nullptr, MOJO_READ_DATA_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->BeginReadData(nullptr, nullptr, MOJO_READ_DATA_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndReadData(0)); - Waiter w; - w.Init(); - HandleSignalsState hss; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - d->AddAwakable(&w, ~MOJO_HANDLE_SIGNAL_NONE, 0, &hss)); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - // Okay to remove even if it wasn't added (or was already removed). - hss = HandleSignalsState(); - d->RemoveAwakable(&w, &hss); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - hss = HandleSignalsState(); - d->RemoveAwakable(&w, &hss); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->WriteMessage(nullptr, 0, nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->ReadMessage(nullptr, nullptr, nullptr, nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->WriteData(nullptr, nullptr, MOJO_WRITE_DATA_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->BeginWriteData(nullptr, nullptr, MOJO_WRITE_DATA_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndWriteData(0)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->ReadData(nullptr, nullptr, MOJO_READ_DATA_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->BeginReadData(nullptr, nullptr, MOJO_READ_DATA_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndReadData(0)); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->AddAwakable(&w, ~MOJO_HANDLE_SIGNAL_NONE, 0, &hss)); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - hss = HandleSignalsState(); - d->RemoveAwakable(&w, &hss); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); -} - -class ThreadSafetyStressThread : public base::SimpleThread { - public: - enum DispatcherOp { - CLOSE = 0, - WRITE_MESSAGE, - READ_MESSAGE, - WRITE_DATA, - BEGIN_WRITE_DATA, - END_WRITE_DATA, - READ_DATA, - BEGIN_READ_DATA, - END_READ_DATA, - DUPLICATE_BUFFER_HANDLE, - MAP_BUFFER, - ADD_WAITER, - REMOVE_WAITER, - DISPATCHER_OP_COUNT - }; - - ThreadSafetyStressThread(base::WaitableEvent* event, - scoped_refptr<Dispatcher> dispatcher, - DispatcherOp op) - : base::SimpleThread("thread_safety_stress_thread"), - event_(event), - dispatcher_(dispatcher), - op_(op) { - CHECK_LE(0, op_); - CHECK_LT(op_, DISPATCHER_OP_COUNT); - } - - ~ThreadSafetyStressThread() override { Join(); } - - private: - void Run() override { - event_->Wait(); - - waiter_.Init(); - switch (op_) { - case CLOSE: { - MojoResult r = dispatcher_->Close(); - EXPECT_TRUE(r == MOJO_RESULT_OK || r == MOJO_RESULT_INVALID_ARGUMENT) - << "Result: " << r; - break; - } - case WRITE_MESSAGE: - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - dispatcher_->WriteMessage(nullptr, 0, nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - break; - case READ_MESSAGE: - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - dispatcher_->ReadMessage(nullptr, nullptr, nullptr, nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - break; - case WRITE_DATA: - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - dispatcher_->WriteData(nullptr, nullptr, - MOJO_WRITE_DATA_FLAG_NONE)); - break; - case BEGIN_WRITE_DATA: - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - dispatcher_->BeginWriteData(nullptr, nullptr, - MOJO_WRITE_DATA_FLAG_NONE)); - break; - case END_WRITE_DATA: - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dispatcher_->EndWriteData(0)); - break; - case READ_DATA: - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - dispatcher_->ReadData(nullptr, nullptr, - MOJO_READ_DATA_FLAG_NONE)); - break; - case BEGIN_READ_DATA: - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - dispatcher_->BeginReadData(nullptr, nullptr, - MOJO_READ_DATA_FLAG_NONE)); - break; - case END_READ_DATA: - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dispatcher_->EndReadData(0)); - break; - case DUPLICATE_BUFFER_HANDLE: { - scoped_refptr<Dispatcher> unused; - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - dispatcher_->DuplicateBufferHandle(nullptr, &unused)); - break; - } - case MAP_BUFFER: { - scoped_ptr<PlatformSharedBufferMapping> unused; - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - dispatcher_->MapBuffer(0u, 0u, MOJO_MAP_BUFFER_FLAG_NONE, &unused)); - break; - } - case ADD_WAITER: { - HandleSignalsState hss; - MojoResult r = dispatcher_->AddAwakable( - &waiter_, ~MOJO_HANDLE_SIGNAL_NONE, 0, &hss); - EXPECT_TRUE(r == MOJO_RESULT_FAILED_PRECONDITION || - r == MOJO_RESULT_INVALID_ARGUMENT); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - break; - } - case REMOVE_WAITER: { - HandleSignalsState hss; - dispatcher_->RemoveAwakable(&waiter_, &hss); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - break; - } - default: - NOTREACHED(); - break; - } - - // Always try to remove the waiter, in case we added it. - HandleSignalsState hss; - dispatcher_->RemoveAwakable(&waiter_, &hss); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - } - - base::WaitableEvent* const event_; - const scoped_refptr<Dispatcher> dispatcher_; - const DispatcherOp op_; - - Waiter waiter_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ThreadSafetyStressThread); -}; - -TEST(DispatcherTest, ThreadSafetyStress) { - static const size_t kRepeatCount = 20; - static const size_t kNumThreads = 100; - - for (size_t i = 0; i < kRepeatCount; i++) { - // Manual reset, not initially signalled. - base::WaitableEvent event(true, false); - scoped_refptr<Dispatcher> d(new TrivialDispatcher()); - - { - ScopedVector<ThreadSafetyStressThread> threads; - for (size_t j = 0; j < kNumThreads; j++) { - ThreadSafetyStressThread::DispatcherOp op = - static_cast<ThreadSafetyStressThread::DispatcherOp>( - (i + j) % ThreadSafetyStressThread::DISPATCHER_OP_COUNT); - threads.push_back(new ThreadSafetyStressThread(&event, d, op)); - threads.back()->Start(); - } - // Kicks off real work on the threads: - event.Signal(); - } // Joins all the threads. - - // One of the threads should already have closed the dispatcher. - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->Close()); - } -} - -TEST(DispatcherTest, ThreadSafetyStressNoClose) { - static const size_t kRepeatCount = 20; - static const size_t kNumThreads = 100; - - for (size_t i = 0; i < kRepeatCount; i++) { - // Manual reset, not initially signalled. - base::WaitableEvent event(true, false); - scoped_refptr<Dispatcher> d(new TrivialDispatcher()); - - { - ScopedVector<ThreadSafetyStressThread> threads; - for (size_t j = 0; j < kNumThreads; j++) { - ThreadSafetyStressThread::DispatcherOp op = - static_cast<ThreadSafetyStressThread::DispatcherOp>( - (i + j) % (ThreadSafetyStressThread::DISPATCHER_OP_COUNT - 1) + - 1); - threads.push_back(new ThreadSafetyStressThread(&event, d, op)); - threads.back()->Start(); - } - // Kicks off real work on the threads: - event.Signal(); - } // Joins all the threads. - - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - } -} - -} // namespace -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/message_pipe_test_utils.cc b/mojo/edk/system/message_pipe_test_utils.cc deleted file mode 100644 index c752abc..0000000 --- a/mojo/edk/system/message_pipe_test_utils.cc +++ /dev/null @@ -1,23 +0,0 @@ -// 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 "mojo/edk/system/message_pipe_test_utils.h" - -#include "mojo/edk/system/test_utils.h" - -namespace mojo { -namespace edk { -namespace test { - -#if !defined(OS_IOS) -MultiprocessMessagePipeTestBase::MultiprocessMessagePipeTestBase() { -} - -MultiprocessMessagePipeTestBase::~MultiprocessMessagePipeTestBase() { -} -#endif - -} // namespace test -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/message_pipe_test_utils.h b/mojo/edk/system/message_pipe_test_utils.h deleted file mode 100644 index 837d534..0000000 --- a/mojo/edk/system/message_pipe_test_utils.h +++ /dev/null @@ -1,39 +0,0 @@ -// 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. - -#ifndef MOJO_EDK_SYSTEM_MESSAGE_PIPE_TEST_UTILS_H_ -#define MOJO_EDK_SYSTEM_MESSAGE_PIPE_TEST_UTILS_H_ - -#include "mojo/edk/test/multiprocess_test_helper.h" -#include "mojo/public/cpp/system/macros.h" - -namespace mojo { -namespace edk { - -class ChannelEndpoint; -class MessagePipe; - -namespace test { - -#if !defined(OS_IOS) -class MultiprocessMessagePipeTestBase : public testing::Test { - public: - MultiprocessMessagePipeTestBase(); - ~MultiprocessMessagePipeTestBase() override; - - protected: - test::MultiprocessTestHelper* helper() { return &helper_; } - - private: - test::MultiprocessTestHelper helper_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(MultiprocessMessagePipeTestBase); -}; -#endif - -} // namespace test -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_MESSAGE_PIPE_TEST_UTILS_H_ diff --git a/mojo/edk/system/message_pipe_unittest.cc b/mojo/edk/system/message_pipe_unittest.cc index 2b8af2e..63fd634 100644 --- a/mojo/edk/system/message_pipe_unittest.cc +++ b/mojo/edk/system/message_pipe_unittest.cc @@ -407,6 +407,8 @@ TEST_F(MessagePipeTest, BasicWaiting) { ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); } +#if !defined(OS_IOS) + const size_t kPingPongIterations = 50000; DEFINE_TEST_CLIENT_TEST_WITH_PIPE(DataPipeHandlePingPong, MessagePipeTest, h) { @@ -460,6 +462,8 @@ TEST_F(MessagePipeTest, SharedBufferHandlePingPong) { MojoClose(buffer); } +#endif // !defined(OS_IOS) + } // namespace } // namespace edk } // namespace mojo diff --git a/mojo/edk/system/shared_buffer_unittest.cc b/mojo/edk/system/shared_buffer_unittest.cc index 9809ebd..1ea8aa0 100644 --- a/mojo/edk/system/shared_buffer_unittest.cc +++ b/mojo/edk/system/shared_buffer_unittest.cc @@ -50,6 +50,8 @@ TEST_F(SharedBufferTest, PassSharedBufferLocal) { ExpectBufferContents(dupe, 0, message); } +#if !defined(OS_IOS) + // Reads a single message with a shared buffer handle, maps the buffer, copies // the message contents into it, then exits. DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CopyToBufferClient, SharedBufferTest, h) { @@ -159,7 +161,6 @@ TEST_F(SharedBufferTest, PassSharedBufferFromChildToChild) { ExpectBufferContents(b, 0, message); } - DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateAndPassBufferParent, SharedBufferTest, parent) { RUN_CHILD_ON_PIPE(CreateAndPassBuffer, child) @@ -226,6 +227,8 @@ TEST_F(SharedBufferTest, PassHandleBetweenCousins) { ExpectBufferContents(b, 0, message); } +#endif // !defined(OS_IOS) + } // namespace } // namespace edk } // namespace mojo diff --git a/mojo/edk/system/wait_set_dispatcher_unittest.cc b/mojo/edk/system/wait_set_dispatcher_unittest.cc index d1fccf5a..1034705 100644 --- a/mojo/edk/system/wait_set_dispatcher_unittest.cc +++ b/mojo/edk/system/wait_set_dispatcher_unittest.cc @@ -59,7 +59,7 @@ class WaitSetDispatcherTest : public ::testing::Test { MojoHandle h0, h1; EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &h0, &h1)); - Core* core = mojo::edk::internal::GetCore(); + Core* core = mojo::edk::internal::g_core; *d0 = scoped_refptr<MessagePipeDispatcher>( static_cast<MessagePipeDispatcher*>(core->GetDispatcher(h0).get())); *d1 = scoped_refptr<MessagePipeDispatcher>( diff --git a/mojo/edk/test/BUILD.gn b/mojo/edk/test/BUILD.gn index 09ce416..ed92c92c 100644 --- a/mojo/edk/test/BUILD.gn +++ b/mojo/edk/test/BUILD.gn @@ -21,12 +21,9 @@ source_set("test_support") { deps = [ "//base", "//base/test:test_support", + "//mojo/edk/system", "//mojo/public/cpp/system", "//testing/gtest", - - # TODO(use_chrome_edk): temporary since the Mojo wrapper primitives are - # declared in third party only for now. - "//third_party/mojo/src/mojo/edk/system", ] } @@ -41,12 +38,9 @@ source_set("run_all_unittests") { ":test_support_impl", "//base", "//base/test:test_support", + "//mojo/edk/system", "//mojo/public/c/test_support", "//testing/gtest", - - # TODO(use_chrome_edk): temporary since the Mojo wrapper primitives are - # declared in third party only for now. - "//third_party/mojo/src/mojo/edk/system", ] } @@ -56,12 +50,9 @@ source_set("run_all_perftests") { ":test_support_impl", "//base", "//base/test:test_support", + "//mojo/edk/system", "//mojo/edk/test:test_support", "//mojo/public/c/test_support", - - # TODO(use_chrome_edk): temporary since the Mojo wrapper primitives are - # declared in third party only for now. - "//third_party/mojo/src/mojo/edk/system", ] sources = [ @@ -92,51 +83,66 @@ source_set("test_support_impl") { group("public_tests") { testonly = true deps = [ - # TODO(use_chrome_edk): remove "2" - ":mojo_public_bindings_unittests2", - ":mojo_public_environment_unittests2", - ":mojo_public_system_perftests2", - ":mojo_public_system_unittests2", - ":mojo_public_utility_unittests2", + ":mojo_public_bindings_unittests", + ":mojo_public_environment_unittests", + ":mojo_public_system_perftests", + ":mojo_public_system_unittests", + ":mojo_public_utility_unittests", ] } -# TODO(use_chrome_edk): remove "2" -test("mojo_public_bindings_unittests2") { +test("mojo_public_bindings_unittests") { deps = [ ":run_all_unittests", + "//mojo/edk/test:test_support", "//mojo/public/cpp/bindings/tests", ] + + if (is_linux && !is_component_build) { + configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ] + } } -# TODO(use_chrome_edk): remove "2" -test("mojo_public_environment_unittests2") { +test("mojo_public_environment_unittests") { deps = [ ":run_all_unittests", "//mojo/public/cpp/environment/tests", ] + + if (is_linux && !is_component_build) { + configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ] + } } -# TODO(use_chrome_edk): remove "2" -test("mojo_public_system_perftests2") { +test("mojo_public_system_perftests") { deps = [ ":run_all_perftests", "//mojo/public/c/system/tests:perftests", ] + + if (is_linux && !is_component_build) { + configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ] + } } -# TODO(use_chrome_edk): remove "2" -test("mojo_public_system_unittests2") { +test("mojo_public_system_unittests") { deps = [ ":run_all_unittests", "//mojo/public/cpp/system/tests", ] + + if (is_linux && !is_component_build) { + configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ] + } } -# TODO(use_chrome_edk): remove "2" -test("mojo_public_utility_unittests2") { +test("mojo_public_utility_unittests") { deps = [ ":run_all_unittests", "//mojo/public/cpp/utility/tests", ] + + if (is_linux && !is_component_build) { + configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ] + } } diff --git a/mojo/edk/test/mojo_test_base.cc b/mojo/edk/test/mojo_test_base.cc index 028f5d0..27c92bb 100644 --- a/mojo/edk/test/mojo_test_base.cc +++ b/mojo/edk/test/mojo_test_base.cc @@ -30,8 +30,12 @@ MojoTestBase::ClientController& MojoTestBase::StartClient( MojoTestBase::ClientController::ClientController(const std::string& client_name, MojoTestBase* test) - : test_(test), - pipe_(helper_.StartChild(client_name)) { + : test_(test) +#if !defined(OS_IOS) + , + pipe_(helper_.StartChild(client_name)) +#endif +{ } MojoTestBase::ClientController::~ClientController() { @@ -41,7 +45,12 @@ MojoTestBase::ClientController::~ClientController() { int MojoTestBase::ClientController::WaitForShutdown() { was_shutdown_ = true; +#if !defined(OS_IOS) return helper_.WaitForChildShutdown(); +#else + NOTREACHED(); + return 1; +#endif } // static diff --git a/mojo/edk/test/mojo_test_base.h b/mojo/edk/test/mojo_test_base.h index c158fb0..e44316d 100644 --- a/mojo/edk/test/mojo_test_base.h +++ b/mojo/edk/test/mojo_test_base.h @@ -49,7 +49,9 @@ class MojoTestBase : public testing::Test { friend class MojoTestBase; MojoTestBase* test_; +#if !defined(OS_IOS) MultiprocessTestHelper helper_; +#endif ScopedMessagePipeHandle pipe_; bool was_shutdown_ = false; @@ -169,6 +171,7 @@ class MojoTestBase : public testing::Test { // |pipe_name| will be bound to the MojoHandle of a message pipe connected // to the parent process (see RUN_CHILD_ON_PIPE above.) This pipe handle is // automatically closed on test client teardown. +#if !defined(OS_IOS) #define DEFINE_TEST_CLIENT_WITH_PIPE(client_name, test_base, pipe_name) \ class client_name##_MainFixture : public test_base { \ void TestBody() override {} \ @@ -203,8 +206,10 @@ class MojoTestBase : public testing::Test { base::Unretained(&test))); \ } \ void client_name##_MainFixture::Main(MojoHandle pipe_name) - - +#else // !defined(OS_IOS) +#define DEFINE_TEST_CLIENT_WITH_PIPE(client_name, test_base, pipe_name) +#define DEFINE_TEST_CLIENT_TEST_WITH_PIPE(client_name, test_base, pipe_name) +#endif // !defined(OS_IOS) } // namespace test } // namespace edk diff --git a/mojo/edk/test/run_all_perftests.cc b/mojo/edk/test/run_all_perftests.cc index 9c1765a..38f79da53 100644 --- a/mojo/edk/test/run_all_perftests.cc +++ b/mojo/edk/test/run_all_perftests.cc @@ -14,9 +14,6 @@ int main(int argc, char** argv) { base::PerfTestSuite test(argc, argv); - // TODO(use_chrome_edk): temporary to force new EDK. - base::CommandLine::ForCurrentProcess()->AppendSwitch("--use-new-edk"); - mojo::edk::Init(); base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); // Leak this because its destructor calls mojo::edk::ShutdownIPCSupport which diff --git a/mojo/edk/test/run_all_unittests.cc b/mojo/edk/test/run_all_unittests.cc index f45242e..0afc2ff 100644 --- a/mojo/edk/test/run_all_unittests.cc +++ b/mojo/edk/test/run_all_unittests.cc @@ -34,9 +34,6 @@ int main(int argc, char** argv) { base::TestSuite test_suite(argc, argv); - // TODO(use_chrome_edk): temporary to force new EDK. - base::CommandLine::ForCurrentProcess()->AppendSwitch("--use-new-edk"); - mojo::edk::Init(); mojo::test::TestSupport::Init(new mojo::edk::test::TestSupportImpl()); diff --git a/mojo/mojo.gyp b/mojo/mojo.gyp index f367977..d14a4de 100644 --- a/mojo/mojo.gyp +++ b/mojo/mojo.gyp @@ -4,7 +4,7 @@ { 'includes': [ - '../third_party/mojo/mojo_variables.gypi', + 'mojo_variables.gypi', ], 'targets': [ { @@ -13,8 +13,8 @@ 'type': 'none', 'dependencies': [ 'mojo_base.gyp:mojo_base', - '../third_party/mojo/mojo_edk_tests.gyp:mojo_edk_tests', - '../third_party/mojo/mojo_public.gyp:mojo_public', + 'mojo_edk_tests.gyp:mojo_edk_tests', + 'mojo_public.gyp:mojo_public', ], }, ] diff --git a/mojo/mojo_base.gyp b/mojo/mojo_base.gyp index 208e702..f921c55 100644 --- a/mojo/mojo_base.gyp +++ b/mojo/mojo_base.gyp @@ -7,7 +7,7 @@ # Mojo land like mojo_shell should be in mojo.gyp. { 'includes': [ - '../third_party/mojo/mojo_variables.gypi', + 'mojo_variables.gypi', ], 'targets': [ { @@ -25,8 +25,8 @@ 'conditions': [ ['OS == "android"', { 'dependencies': [ - '../third_party/mojo/mojo_public.gyp:mojo_bindings_java', - '../third_party/mojo/mojo_public.gyp:mojo_public_java', + 'mojo_public.gyp:mojo_bindings_java', + 'mojo_public.gyp:mojo_public_java', ], }], ] @@ -130,14 +130,14 @@ '../base/base.gyp:base_message_loop_tests', '../testing/gtest.gyp:gtest', '../url/url.gyp:url_lib', - '../third_party/mojo/mojo_edk.gyp:mojo_system_impl', - '../third_party/mojo/mojo_edk.gyp:mojo_common_test_support', - '../third_party/mojo/mojo_edk.gyp:mojo_run_all_unittests', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', - '../third_party/mojo/mojo_public.gyp:mojo_public_test_utils', 'mojo_common_lib', + 'mojo_edk.gyp:mojo_system_impl', + 'mojo_edk.gyp:mojo_common_test_support', + 'mojo_edk.gyp:mojo_run_all_unittests', 'mojo_environment_chromium', 'mojo_message_pump_lib', + 'mojo_public.gyp:mojo_cpp_bindings', + 'mojo_public.gyp:mojo_public_test_utils', 'mojo_url_type_converters', ], 'sources': [ @@ -152,7 +152,7 @@ 'type': 'static_library', 'dependencies': [ 'mojo_environment_chromium_impl', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + 'mojo_public.gyp:mojo_cpp_bindings', ], 'sources': [ # TODO(vtl): This is kind of ugly. (See TODO in logging.h.) @@ -217,7 +217,7 @@ 'export_dependent_settings': [ 'mojo_services.gyp:network_service_bindings_generation', ], - 'includes': [ '../third_party/mojo/mojom_bindings_generator_explicit.gypi' ], + 'includes': [ 'mojom_bindings_generator_explicit.gypi' ], }, { # GN version: //mojo/shell/public/cpp @@ -257,8 +257,8 @@ 'type': 'static_library', 'dependencies': [ 'mojo_application_bindings_mojom', + 'mojo_public.gyp:mojo_cpp_bindings', 'mojo_services.gyp:network_service_bindings_lib', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', ], 'export_dependent_settings': [ 'mojo_services.gyp:network_service_bindings_lib', @@ -282,12 +282,12 @@ 'target_name': 'mojo_public_application_unittests', 'type': 'executable', 'dependencies': [ - 'mojo_application_base', '../base/base.gyp:base', '../testing/gtest.gyp:gtest', - '../third_party/mojo/mojo_edk.gyp:mojo_run_all_unittests', - '../third_party/mojo/mojo_public.gyp:mojo_utility', - '../third_party/mojo/mojo_public.gyp:mojo_environment_standalone', + 'mojo_application_base', + 'mojo_edk.gyp:mojo_run_all_unittests', + 'mojo_public.gyp:mojo_utility', + 'mojo_public.gyp:mojo_environment_standalone', ], 'sources': [ 'shell/public/cpp/tests/connection_impl_unittest.cc', @@ -320,7 +320,7 @@ '../base/base.gyp:base', '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', 'mojo_common_lib', - '../third_party/mojo/mojo_edk.gyp:mojo_system_impl', + 'mojo_edk.gyp:mojo_system_impl', 'mojo_environment_chromium', 'mojo_jni_headers', ], @@ -344,7 +344,7 @@ 'dependencies': [ '../base/base.gyp:base_java', 'libmojo_system_java', - '../third_party/mojo/mojo_public.gyp:mojo_public_java', + 'mojo_public.gyp:mojo_public_java', ], 'variables': { 'java_in_dir': '<(DEPTH)/mojo/android/system', diff --git a/mojo/mojo_edk.gyp b/mojo/mojo_edk.gyp index 5bfda65..7ff26f5 100644 --- a/mojo/mojo_edk.gyp +++ b/mojo/mojo_edk.gyp @@ -4,7 +4,7 @@ { 'includes': [ - '../third_party/mojo/mojo_variables.gypi', + 'mojo_variables.gypi', ], 'target_defaults' : { 'include_dirs': [ @@ -19,17 +19,13 @@ 'targets': [ { # GN version: //mojo/edk/system - 'target_name': 'mojo_system_impl2', - 'type': 'static_library', - # TODO(use_chrome_edk): this should be a component to match third_party, - # but since third_party includes it, we either make it a static library - # or we have to change the export macros to be different than third_party. - #'type': '<(component)', + 'target_name': 'mojo_system_impl', + 'type': '<(component)', 'dependencies': [ '../base/base.gyp:base', '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', '../crypto/crypto.gyp:crypto', - '../third_party/mojo/mojo_public.gyp:mojo_system_headers', + 'mojo_public.gyp:mojo_system_headers', ], 'defines': [ 'MOJO_SYSTEM_IMPL_IMPLEMENTATION', @@ -152,8 +148,7 @@ }, { # GN version: //mojo/edk/js - # TODO(use_chrome_edk): remove "2" - 'target_name': 'mojo_js_lib2', + 'target_name': 'mojo_js_lib', 'type': 'static_library', 'dependencies': [ '../base/base.gyp:base', @@ -185,8 +180,7 @@ }, { # GN version: //mojo/edk/test:test_support_impl - # TODO(use_chrome_edk): remove "2" - 'target_name': 'mojo_test_support_impl2', + 'target_name': 'mojo_test_support_impl', 'type': 'static_library', 'dependencies': [ '../base/base.gyp:base', @@ -198,13 +192,13 @@ }, { # GN version: //mojo/edk/test:test_support - 'target_name': 'mojo_common_test_support2', + 'target_name': 'mojo_common_test_support', 'type': 'static_library', 'dependencies': [ '../base/base.gyp:base', '../base/base.gyp:test_support_base', '../testing/gtest.gyp:gtest', - 'mojo_system_impl2', + 'mojo_system_impl', ], 'sources': [ 'edk/test/mojo_test_base.cc', @@ -227,20 +221,37 @@ }, { # GN version: //mojo/edk/test:run_all_unittests - # TODO(use_chrome_edk): remove "2" - 'target_name': 'mojo_run_all_unittests2', + 'target_name': 'mojo_run_all_unittests', 'type': 'static_library', 'dependencies': [ '../base/base.gyp:base', '../base/base.gyp:test_support_base', '../testing/gtest.gyp:gtest', - '../third_party/mojo/mojo_public.gyp:mojo_public_test_support', - 'mojo_system_impl2', - 'mojo_test_support_impl2', + 'mojo_common_test_support', + 'mojo_public.gyp:mojo_public_test_support', + 'mojo_system_impl', + 'mojo_test_support_impl', ], 'sources': [ 'edk/test/run_all_unittests.cc', ], }, + { + # GN version: //mojo/edk/test:run_all_perftests + 'target_name': 'mojo_run_all_perftests', + 'type': 'static_library', + 'dependencies': [ + '../base/base.gyp:base', + '../base/base.gyp:test_support_base', + '../testing/gtest.gyp:gtest', + 'mojo_common_test_support', + 'mojo_public.gyp:mojo_public_test_support', + 'mojo_system_impl', + 'mojo_test_support_impl', + ], + 'sources': [ + 'edk/test/run_all_perftests.cc', + ], + }, ], } diff --git a/mojo/mojo_edk_tests.gyp b/mojo/mojo_edk_tests.gyp index fc185e3..9d8b1af 100644 --- a/mojo/mojo_edk_tests.gyp +++ b/mojo/mojo_edk_tests.gyp @@ -4,7 +4,7 @@ { 'includes': [ - '../third_party/mojo/mojo_variables.gypi', + 'mojo_variables.gypi', ], 'targets': [ { @@ -16,8 +16,14 @@ # build/all.gyp:All on iOS, as All cannot depend on the mojo_base # target on iOS due to the presence of the js targets, which cause v8 # to be built. - 'mojo_message_pipe_perftests2', - 'mojo_system_unittests2', + 'mojo_message_pipe_perftests', + 'mojo_public_bindings_perftests', + 'mojo_public_bindings_unittests', + 'mojo_public_environment_unittests', + 'mojo_public_system_perftests', + 'mojo_public_system_unittests', + 'mojo_public_utility_unittests', + 'mojo_system_unittests', 'mojo_js_unittests', 'mojo_js_integration_tests', ], @@ -29,21 +35,172 @@ 'dependencies': [ '../testing/gtest.gyp:gtest', '../testing/gtest.gyp:gtest_main', - 'mojo_edk.gyp:mojo_system_impl2', + 'mojo_edk.gyp:mojo_system_impl', ], 'sources': [ 'edk/system/ports/ports_unittest.cc', ], - } + }, + { + # GN version: //mojo/edk/test:mojo_public_bindings_unittests + 'target_name': 'mojo_public_bindings_unittests', + 'type': 'executable', + 'dependencies': [ + '../testing/gtest.gyp:gtest', + 'mojo_base.gyp:mojo_environment_chromium', + 'mojo_base.gyp:mojo_message_pump_lib', + 'mojo_edk.gyp:mojo_run_all_unittests', + 'mojo_public.gyp:mojo_cpp_bindings', + 'mojo_public.gyp:mojo_public_bindings_test_utils', + 'mojo_public.gyp:mojo_public_test_associated_interfaces', + 'mojo_public.gyp:mojo_public_test_interfaces', + 'mojo_public.gyp:mojo_public_test_interfaces_blink', + 'mojo_public.gyp:mojo_public_test_interfaces_chromium', + 'mojo_public.gyp:mojo_public_test_utils', + 'mojo_public.gyp:mojo_utility', + ], + 'sources': [ + 'public/cpp/bindings/tests/array_unittest.cc', + 'public/cpp/bindings/tests/associated_interface_unittest.cc', + 'public/cpp/bindings/tests/binding_callback_unittest.cc', + 'public/cpp/bindings/tests/binding_unittest.cc', + 'public/cpp/bindings/tests/bounds_checker_unittest.cc', + 'public/cpp/bindings/tests/buffer_unittest.cc', + 'public/cpp/bindings/tests/callback_unittest.cc', + 'public/cpp/bindings/tests/connector_unittest.cc', + 'public/cpp/bindings/tests/constant_unittest.cc', + 'public/cpp/bindings/tests/container_test_util.cc', + 'public/cpp/bindings/tests/equals_unittest.cc', + 'public/cpp/bindings/tests/handle_passing_unittest.cc', + 'public/cpp/bindings/tests/interface_ptr_unittest.cc', + 'public/cpp/bindings/tests/map_unittest.cc', + 'public/cpp/bindings/tests/message_queue.cc', + 'public/cpp/bindings/tests/message_queue.h', + 'public/cpp/bindings/tests/multiplex_router_unittest.cc', + 'public/cpp/bindings/tests/pickle_unittest.cc', + 'public/cpp/bindings/tests/pickled_struct_blink.cc', + 'public/cpp/bindings/tests/pickled_struct_blink.h', + 'public/cpp/bindings/tests/pickled_struct_chromium.cc', + 'public/cpp/bindings/tests/pickled_struct_chromium.h', + 'public/cpp/bindings/tests/rect_blink.h', + 'public/cpp/bindings/tests/rect_chromium.h', + 'public/cpp/bindings/tests/request_response_unittest.cc', + 'public/cpp/bindings/tests/router_test_util.cc', + 'public/cpp/bindings/tests/router_test_util.h', + 'public/cpp/bindings/tests/router_unittest.cc', + 'public/cpp/bindings/tests/sample_service_unittest.cc', + 'public/cpp/bindings/tests/serialization_warning_unittest.cc', + 'public/cpp/bindings/tests/string_unittest.cc', + 'public/cpp/bindings/tests/struct_traits_unittest.cc', + 'public/cpp/bindings/tests/struct_unittest.cc', + 'public/cpp/bindings/tests/type_conversion_unittest.cc', + 'public/cpp/bindings/tests/union_unittest.cc', + 'public/cpp/bindings/tests/validation_unittest.cc', + ], + }, + { + # GN version: //mojo/edk/test:mojo_public_bindings_perftests + 'target_name': 'mojo_public_bindings_perftests', + 'type': 'executable', + 'dependencies': [ + '../testing/gtest.gyp:gtest', + 'mojo_base.gyp:mojo_common_lib', + 'mojo_edk.gyp:mojo_run_all_unittests', + 'mojo_public.gyp:mojo_cpp_bindings', + 'mojo_public.gyp:mojo_environment_standalone', + 'mojo_public.gyp:mojo_public_bindings_test_utils', + 'mojo_public.gyp:mojo_public_test_interfaces', + 'mojo_public.gyp:mojo_public_test_utils', + 'mojo_public.gyp:mojo_utility', + ], + 'sources': [ + 'public/cpp/bindings/tests/bindings_perftest.cc', + ], + }, + { + # GN version: //mojo/edk/test:mojo_public_environment_unittests + 'target_name': 'mojo_public_environment_unittests', + 'type': 'executable', + 'dependencies': [ + '../testing/gtest.gyp:gtest', + 'mojo_edk.gyp:mojo_run_all_unittests', + 'mojo_public.gyp:mojo_cpp_bindings', + 'mojo_public.gyp:mojo_environment_standalone', + 'mojo_public.gyp:mojo_public_test_utils', + 'mojo_public.gyp:mojo_utility', + ], + 'sources': [ + 'public/cpp/environment/tests/async_wait_unittest.cc', + 'public/cpp/environment/tests/async_waiter_unittest.cc', + 'public/cpp/environment/tests/logger_unittest.cc', + 'public/cpp/environment/tests/logging_unittest.cc', + ], + }, + { + # GN version: //mojo/public/cpp/system/tests:mojo_public_system_unittests + # and //mojo/public/c/system/tests + 'target_name': 'mojo_public_system_unittests', + 'type': 'executable', + 'dependencies': [ + '../testing/gtest.gyp:gtest', + 'mojo_edk.gyp:mojo_run_all_unittests', + 'mojo_public.gyp:mojo_public_test_utils', + ], + 'sources': [ + '<@(mojo_public_system_unittest_sources)', + ], + }, + { + # GN version: //mojo/public/cpp/application/tests:mojo_public_utility_unittests + 'target_name': 'mojo_public_utility_unittests', + 'type': 'executable', + 'dependencies': [ + '../testing/gtest.gyp:gtest', + 'mojo_edk.gyp:mojo_run_all_unittests', + 'mojo_public.gyp:mojo_cpp_bindings', + 'mojo_public.gyp:mojo_public_test_utils', + 'mojo_public.gyp:mojo_utility', + ], + 'sources': [ + 'public/cpp/utility/tests/mutex_unittest.cc', + 'public/cpp/utility/tests/run_loop_unittest.cc', + 'public/cpp/utility/tests/thread_unittest.cc', + ], + 'conditions': [ + # See crbug.com/342893: + ['OS=="win"', { + 'sources!': [ + 'public/cpp/utility/tests/mutex_unittest.cc', + 'public/cpp/utility/tests/thread_unittest.cc', + ], + }], + ], + }, + { + # GN version: //mojo/edk/test:mojo_public_system_perftests + 'target_name': 'mojo_public_system_perftests', + 'type': 'executable', + 'dependencies': [ + '../base/base.gyp:base', + '../testing/gtest.gyp:gtest', + 'mojo_edk.gyp:mojo_run_all_perftests', + 'mojo_public.gyp:mojo_public_test_utils', + 'mojo_public.gyp:mojo_utility', + ], + 'sources': [ + 'public/c/system/tests/core_perftest.cc', + ], + }, { # GN version: //mojo/edk/system:mojo_system_unittests - 'target_name': 'mojo_system_unittests2', + 'target_name': 'mojo_system_unittests', 'type': 'executable', 'dependencies': [ '../base/base.gyp:base', '../testing/gtest.gyp:gtest', - 'mojo_edk.gyp:mojo_common_test_support2', - 'mojo_edk.gyp:mojo_system_impl2', + 'mojo_edk.gyp:mojo_common_test_support', + 'mojo_edk.gyp:mojo_run_all_unittests', + 'mojo_edk.gyp:mojo_system_impl', ], 'sources': [ 'edk/embedder/embedder_unittest.cc', @@ -53,14 +210,10 @@ 'edk/system/core_test_base.cc', 'edk/system/core_test_base.h', 'edk/system/core_unittest.cc', - 'edk/system/data_pipe_unittest.cc', - 'edk/system/message_pipe_test_utils.cc', - 'edk/system/message_pipe_test_utils.h', 'edk/system/message_pipe_unittest.cc', 'edk/system/multiprocess_message_pipe_unittest.cc', 'edk/system/options_validation_unittest.cc', 'edk/system/platform_handle_dispatcher_unittest.cc', - 'edk/system/run_all_unittests.cc', 'edk/system/shared_buffer_dispatcher_unittest.cc', 'edk/system/shared_buffer_unittest.cc', 'edk/system/test_utils.cc', @@ -69,34 +222,29 @@ 'edk/system/waiter_test_utils.cc', 'edk/system/waiter_test_utils.h', 'edk/system/waiter_unittest.cc', - 'edk/test/multiprocess_test_helper_unittest.cc', ], 'conditions': [ ['OS=="ios"', { 'sources!': [ - 'edk/embedder/embedder_unittest.cc', 'edk/system/multiprocess_message_pipe_unittest.cc', - 'edk/system/shared_buffer_unittest.cc', ], }], ], }, { # GN version: //mojo/edk/system:mojo_message_pipe_perftests - 'target_name': 'mojo_message_pipe_perftests2', + 'target_name': 'mojo_message_pipe_perftests', 'type': 'executable', 'dependencies': [ '../base/base.gyp:base', '../base/base.gyp:test_support_base', - '../base/base.gyp:test_support_perf', '../testing/gtest.gyp:gtest', - 'mojo_edk.gyp:mojo_common_test_support2', - 'mojo_edk.gyp:mojo_system_impl2', + 'mojo_edk.gyp:mojo_common_test_support', + 'mojo_edk.gyp:mojo_run_all_perftests', + 'mojo_edk.gyp:mojo_system_impl', ], 'sources': [ 'edk/system/message_pipe_perftest.cc', - 'edk/system/message_pipe_test_utils.cc', - 'edk/system/message_pipe_test_utils.h', 'edk/system/test_utils.cc', 'edk/system/test_utils.h', ], @@ -108,12 +256,12 @@ 'type': 'executable', 'dependencies': [ '../gin/gin.gyp:gin_test', - '../third_party/mojo/mojo_public.gyp:mojo_environment_standalone', - '../third_party/mojo/mojo_public.gyp:mojo_public_test_interfaces', - '../third_party/mojo/mojo_public.gyp:mojo_utility', - 'mojo_edk.gyp:mojo_common_test_support2', - 'mojo_edk.gyp:mojo_run_all_unittests2', - 'mojo_edk.gyp:mojo_js_lib2', + 'mojo_edk.gyp:mojo_common_test_support', + 'mojo_edk.gyp:mojo_run_all_unittests', + 'mojo_edk.gyp:mojo_js_lib', + 'mojo_public.gyp:mojo_environment_standalone', + 'mojo_public.gyp:mojo_public_test_interfaces', + 'mojo_public.gyp:mojo_utility', ], 'sources': [ 'edk/js/handle_unittest.cc', @@ -127,17 +275,86 @@ 'dependencies': [ '../base/base.gyp:base', '../gin/gin.gyp:gin_test', - '../third_party/mojo/mojo_public.gyp:mojo_environment_standalone', - '../third_party/mojo/mojo_public.gyp:mojo_public_test_interfaces', - '../third_party/mojo/mojo_public.gyp:mojo_utility', - 'mojo_edk.gyp:mojo_js_lib2', - 'mojo_edk.gyp:mojo_run_all_unittests2', + 'mojo_base.gyp:mojo_common_lib', + 'mojo_edk.gyp:mojo_js_lib', + 'mojo_edk.gyp:mojo_run_all_unittests', 'mojo_js_to_cpp_bindings', + 'mojo_public.gyp:mojo_environment_standalone', + 'mojo_public.gyp:mojo_public_test_interfaces', + 'mojo_public.gyp:mojo_utility', ], 'sources': [ 'edk/js/test/run_js_integration_tests.cc', 'edk/js/tests/js_to_cpp_tests.cc', ], }, + { + 'target_name': 'mojo_js_to_cpp_bindings', + 'type': 'none', + 'variables': { + 'mojom_files': [ + 'edk/js/tests/js_to_cpp.mojom', + ], + }, + 'includes': [ 'mojom_bindings_generator_explicit.gypi' ], + }, + ], + 'conditions': [ + ['test_isolation_mode != "noop"', { + 'targets': [ + { + 'target_name': 'mojo_public_bindings_unittests_run', + 'type': 'none', + 'dependencies': [ + 'mojo_public_bindings_unittests', + ], + 'includes': [ + '../build/isolate.gypi', + ], + 'sources': [ + 'mojo_public_bindings_unittests.isolate', + ], + }, + { + 'target_name': 'mojo_public_environment_unittests_run', + 'type': 'none', + 'dependencies': [ + 'mojo_public_environment_unittests', + ], + 'includes': [ + '../build/isolate.gypi', + ], + 'sources': [ + 'mojo_public_environment_unittests.isolate', + ], + }, + { + 'target_name': 'mojo_public_system_unittests_run', + 'type': 'none', + 'dependencies': [ + 'mojo_public_system_unittests', + ], + 'includes': [ + '../build/isolate.gypi', + ], + 'sources': [ + 'mojo_public_system_unittests.isolate', + ], + }, + { + 'target_name': 'mojo_public_utility_unittests_run', + 'type': 'none', + 'dependencies': [ + 'mojo_public_utility_unittests', + ], + 'includes': [ + '../build/isolate.gypi', + ], + 'sources': [ + 'mojo_public_utility_unittests.isolate', + ], + }, + ], + }], ], } diff --git a/mojo/mojo_public.gyp b/mojo/mojo_public.gyp new file mode 100644 index 0000000..906119a --- /dev/null +++ b/mojo/mojo_public.gyp @@ -0,0 +1,507 @@ +# 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. + +{ + 'includes': [ + 'mojo_variables.gypi', + ], + 'target_defaults' : { + 'include_dirs': [ + '..', + ], + }, + 'targets': [ + { + 'target_name': 'mojo_public', + 'type': 'none', + 'dependencies': [ + 'mojo_js_bindings', + 'mojo_public_test_interfaces', + 'mojo_public_test_utils', + 'mojo_system', + 'mojo_utility', + ], + }, + { + # Targets that (a) need to obtain the settings that mojo_system passes on + # to its direct dependents but (b) are not themselves in a position to + # hardcode a dependency to mojo_system vs. mojo_system_impl (e.g., + # because they are components) should depend on this target. + 'target_name': 'mojo_system_placeholder', + 'type': 'none', + }, + { + 'target_name': 'mojo_system', + 'type': 'static_library', + 'defines': [ + 'MOJO_SYSTEM_IMPLEMENTATION', + ], + 'all_dependent_settings': { + 'conditions': [ + # We need to be able to call the MojoSetSystemThunks() function in + # system_thunks.cc + ['OS=="android"', { + 'ldflags!': [ + '-Wl,--exclude-libs=ALL', + ], + }], + ], + }, + 'sources': [ + 'public/platform/native/system_thunks.cc', + 'public/platform/native/system_thunks.h', + ], + 'dependencies': [ + 'mojo_system_headers', + ], + }, + { + # GN version: //mojo/public/c/system + 'target_name': 'mojo_system_headers', + 'type': 'none', + 'sources': [ + 'public/c/system/buffer.h', + 'public/c/system/core.h', + 'public/c/system/data_pipe.h', + 'public/c/system/functions.h', + 'public/c/system/macros.h', + 'public/c/system/message_pipe.h', + 'public/c/system/system_export.h', + 'public/c/system/types.h', + 'public/c/system/wait_set.h', + ], + }, + { + # GN version: //mojo/public/cpp/system + 'target_name': 'mojo_system_cpp_headers', + 'type': 'none', + 'sources': [ + 'public/cpp/system/buffer.h', + 'public/cpp/system/core.h', + 'public/cpp/system/data_pipe.h', + 'public/cpp/system/functions.h', + 'public/cpp/system/handle.h', + 'public/cpp/system/macros.h', + 'public/cpp/system/message_pipe.h', + ], + 'dependencies': [ + 'mojo_system_headers', + ], + }, + { + # GN version: //mojo/public/cpp/bindings + 'target_name': 'mojo_cpp_bindings', + 'type': 'static_library', + 'include_dirs': [ + '..' + ], + 'sources': [ + 'public/cpp/bindings/array.h', + 'public/cpp/bindings/associated_binding.h', + 'public/cpp/bindings/associated_group.h', + 'public/cpp/bindings/associated_interface_ptr.h', + 'public/cpp/bindings/associated_interface_ptr_info.h', + 'public/cpp/bindings/associated_interface_request.h', + 'public/cpp/bindings/binding.h', + 'public/cpp/bindings/callback.h', + 'public/cpp/bindings/interface_ptr.h', + 'public/cpp/bindings/interface_request.h', + 'public/cpp/bindings/lib/array_internal.cc', + 'public/cpp/bindings/lib/array_internal.h', + 'public/cpp/bindings/lib/array_serialization.h', + 'public/cpp/bindings/lib/associated_group.cc', + 'public/cpp/bindings/lib/associated_interface_ptr_state.h', + 'public/cpp/bindings/lib/binding_state.h', + 'public/cpp/bindings/lib/bindings_internal.h', + 'public/cpp/bindings/lib/bindings_serialization.cc', + 'public/cpp/bindings/lib/bindings_serialization.h', + 'public/cpp/bindings/lib/bounds_checker.cc', + 'public/cpp/bindings/lib/bounds_checker.h', + 'public/cpp/bindings/lib/buffer.h', + 'public/cpp/bindings/lib/callback_internal.h', + 'public/cpp/bindings/lib/connector.cc', + 'public/cpp/bindings/lib/connector.h', + 'public/cpp/bindings/lib/control_message_handler.cc', + 'public/cpp/bindings/lib/control_message_handler.h', + 'public/cpp/bindings/lib/control_message_proxy.cc', + 'public/cpp/bindings/lib/control_message_proxy.h', + 'public/cpp/bindings/lib/filter_chain.cc', + 'public/cpp/bindings/lib/filter_chain.h', + 'public/cpp/bindings/lib/fixed_buffer.cc', + 'public/cpp/bindings/lib/interface_id.h', + 'public/cpp/bindings/lib/fixed_buffer.h', + 'public/cpp/bindings/lib/interface_endpoint_client.cc', + 'public/cpp/bindings/lib/interface_endpoint_client.h', + 'public/cpp/bindings/lib/interface_ptr_state.h', + 'public/cpp/bindings/lib/map_data_internal.h', + 'public/cpp/bindings/lib/map_internal.h', + 'public/cpp/bindings/lib/map_serialization.h', + 'public/cpp/bindings/lib/message.cc', + 'public/cpp/bindings/lib/message_builder.cc', + 'public/cpp/bindings/lib/message_builder.h', + 'public/cpp/bindings/lib/message_filter.cc', + 'public/cpp/bindings/lib/message_header_validator.cc', + 'public/cpp/bindings/lib/message_header_validator.h', + 'public/cpp/bindings/lib/message_internal.h', + 'public/cpp/bindings/lib/multiplex_router.cc', + 'public/cpp/bindings/lib/multiplex_router.h', + 'public/cpp/bindings/lib/no_interface.cc', + 'public/cpp/bindings/lib/pickle_buffer.cc', + 'public/cpp/bindings/lib/pickle_buffer.h', + 'public/cpp/bindings/lib/pipe_control_message_handler.cc', + 'public/cpp/bindings/lib/pipe_control_message_handler.h', + 'public/cpp/bindings/lib/pipe_control_message_handler_delegate.h', + 'public/cpp/bindings/lib/pipe_control_message_proxy.cc', + 'public/cpp/bindings/lib/pipe_control_message_proxy.h', + 'public/cpp/bindings/lib/router.cc', + 'public/cpp/bindings/lib/router.h', + 'public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc', + 'public/cpp/bindings/lib/scoped_interface_endpoint_handle.h', + 'public/cpp/bindings/lib/shared_data.h', + 'public/cpp/bindings/lib/shared_ptr.h', + 'public/cpp/bindings/lib/string_serialization.cc', + 'public/cpp/bindings/lib/string_serialization.h', + 'public/cpp/bindings/lib/validate_params.h', + 'public/cpp/bindings/lib/validation_errors.cc', + 'public/cpp/bindings/lib/validation_errors.h', + 'public/cpp/bindings/lib/validation_util.cc', + 'public/cpp/bindings/lib/validation_util.h', + 'public/cpp/bindings/lib/value_traits.h', + 'public/cpp/bindings/message.h', + 'public/cpp/bindings/message_filter.h', + 'public/cpp/bindings/no_interface.h', + 'public/cpp/bindings/string.h', + 'public/cpp/bindings/strong_binding.h', + 'public/cpp/bindings/type_converter.h', + # This comes from the mojo_interface_bindings_cpp_sources dependency. + '>@(mojom_generated_sources)', + ], + 'dependencies': [ + '../base/base.gyp:base', + 'mojo_interface_bindings_cpp_sources', + ], + }, + { + # GN version: //mojo/public/js + 'target_name': 'mojo_js_bindings', + 'type': 'static_library', + 'include_dirs': [ + '..' + ], + 'sources': [ + 'public/js/constants.cc', + 'public/js/constants.h', + ], + }, + { + # GN version: //mojo/public/cpp/environment:standalone + 'target_name': 'mojo_environment_standalone', + 'type': 'static_library', + 'sources': [ + 'public/c/environment/async_waiter.h', + 'public/c/environment/logger.h', + 'public/cpp/environment/async_waiter.h', + 'public/cpp/environment/environment.h', + 'public/cpp/environment/lib/async_waiter.cc', + 'public/cpp/environment/lib/default_async_waiter.cc', + 'public/cpp/environment/lib/default_async_waiter.h', + 'public/cpp/environment/lib/default_logger.cc', + 'public/cpp/environment/lib/default_logger.h', + 'public/cpp/environment/lib/default_task_tracker.cc', + 'public/cpp/environment/lib/default_task_tracker.h', + 'public/cpp/environment/lib/environment.cc', + 'public/cpp/environment/lib/logging.cc', + 'public/cpp/environment/lib/scoped_task_tracking.cc', + 'public/cpp/environment/lib/scoped_task_tracking.h', + 'public/cpp/environment/logging.h', + 'public/cpp/environment/task_tracker.h', + ], + 'include_dirs': [ + '..', + ], + }, + { + # GN version: //mojo/public/cpp/utility + 'target_name': 'mojo_utility', + 'type': 'static_library', + 'sources': [ + 'public/cpp/utility/lib/mutex.cc', + 'public/cpp/utility/lib/run_loop.cc', + 'public/cpp/utility/lib/thread.cc', + 'public/cpp/utility/lib/thread_local.h', + 'public/cpp/utility/lib/thread_local_posix.cc', + 'public/cpp/utility/lib/thread_local_win.cc', + 'public/cpp/utility/mutex.h', + 'public/cpp/utility/run_loop.h', + 'public/cpp/utility/run_loop_handler.h', + 'public/cpp/utility/thread.h', + ], + 'conditions': [ + # See crbug.com/342893: + ['OS=="win"', { + 'sources!': [ + 'public/cpp/utility/lib/mutex.cc', + 'public/cpp/utility/lib/thread.cc', + 'public/cpp/utility/mutex.h', + 'public/cpp/utility/thread.h', + ], + }], + ], + 'include_dirs': [ + '..', + ], + }, + { + 'target_name': 'mojo_interface_bindings_mojom', + 'type': 'none', + 'variables': { + 'require_interface_bindings': 0, + 'mojom_files': [ + 'public/interfaces/bindings/interface_control_messages.mojom', + 'public/interfaces/bindings/pipe_control_messages.mojom', + ], + }, + 'includes': [ 'mojom_bindings_generator_explicit.gypi' ], + }, + { + 'target_name': 'mojo_interface_bindings_cpp_sources', + 'type': 'none', + 'dependencies': [ + 'mojo_interface_bindings_mojom', + ], + }, + { + # This target can be used to introduce a dependency on interface bindings + # generation without introducing any side-effects in the dependent + # target's configuration. + 'target_name': 'mojo_interface_bindings_generation', + 'type': 'none', + 'dependencies': [ + 'mojo_interface_bindings_cpp_sources', + ], + }, + { + # GN version: //mojo/public/c/test_support + 'target_name': 'mojo_public_test_support', + 'defines': [ + 'MOJO_TEST_SUPPORT_IMPLEMENTATION', + ], + 'include_dirs': [ + '..', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '..', + ], + }, + 'sources': [ + 'public/c/test_support/test_support.h', + 'public/c/test_support/test_support_export.h', + # TODO(vtl): Convert this to thunks http://crbug.com/386799 + 'public/tests/test_support_private.cc', + 'public/tests/test_support_private.h', + ], + 'conditions': [ + ['OS=="ios"', { + 'type': 'static_library', + }, { + 'type': 'shared_library', + }], + ['OS=="mac"', { + 'xcode_settings': { + # Make it a run-path dependent library. + 'DYLIB_INSTALL_NAME_BASE': '@loader_path', + }, + }], + ], + }, + { + # GN version: //mojo/public/cpp/test_support:test_utils + 'target_name': 'mojo_public_test_utils', + 'type': 'static_library', + 'dependencies': [ + '../base/base.gyp:base', + '../testing/gtest.gyp:gtest', + 'mojo_public_test_support', + ], + 'sources': [ + 'public/cpp/test_support/lib/test_support.cc', + 'public/cpp/test_support/lib/test_utils.cc', + 'public/cpp/test_support/test_utils.h', + ], + }, + { + # GN version: //mojo/public/cpp/bindings/tests:mojo_public_bindings_test_utils + 'target_name': 'mojo_public_bindings_test_utils', + 'type': 'static_library', + 'dependencies': [ + '../base/base.gyp:base', + ], + 'sources': [ + 'public/cpp/bindings/tests/validation_test_input_parser.cc', + 'public/cpp/bindings/tests/validation_test_input_parser.h', + ], + }, + { + 'target_name': 'mojo_public_test_interfaces_mojom', + 'type': 'none', + 'variables': { + 'mojom_files': [ + 'public/interfaces/bindings/tests/math_calculator.mojom', + 'public/interfaces/bindings/tests/no_module.mojom', + 'public/interfaces/bindings/tests/ping_service.mojom', + 'public/interfaces/bindings/tests/rect.mojom', + 'public/interfaces/bindings/tests/regression_tests.mojom', + 'public/interfaces/bindings/tests/sample_factory.mojom', + 'public/interfaces/bindings/tests/sample_import.mojom', + 'public/interfaces/bindings/tests/sample_import2.mojom', + 'public/interfaces/bindings/tests/sample_interfaces.mojom', + 'public/interfaces/bindings/tests/sample_service.mojom', + 'public/interfaces/bindings/tests/scoping.mojom', + 'public/interfaces/bindings/tests/serialization_test_structs.mojom', + 'public/interfaces/bindings/tests/test_constants.mojom', + 'public/interfaces/bindings/tests/test_native_types.mojom', + 'public/interfaces/bindings/tests/test_structs.mojom', + 'public/interfaces/bindings/tests/test_unions.mojom', + 'public/interfaces/bindings/tests/validation_test_interfaces.mojom', + ], + }, + 'includes': [ 'mojom_bindings_generator_explicit.gypi' ], + }, + { + 'target_name': 'mojo_public_test_interfaces_mojom_blink', + 'type': 'none', + 'variables': { + 'mojom_variant': 'blink', + 'mojom_extra_generator_args': [ + '--typemap', '<(DEPTH)/mojo/public/interfaces/bindings/tests/blink_test.typemap', + ], + 'mojom_files': [ + 'public/interfaces/bindings/tests/test_native_types.mojom', + ], + }, + 'includes': [ 'mojom_bindings_generator_explicit.gypi' ], + 'dependencies': [ + 'mojo_public_test_interfaces_mojom', + ], + }, + { + 'target_name': 'mojo_public_test_interfaces_mojom_chromium', + 'type': 'none', + 'variables': { + 'mojom_variant': 'chromium', + 'mojom_extra_generator_args': [ + '--typemap', '<(DEPTH)/mojo/public/interfaces/bindings/tests/chromium_test.typemap', + ], + 'mojom_files': [ + 'public/interfaces/bindings/tests/test_native_types.mojom', + ], + }, + 'includes': [ 'mojom_bindings_generator_explicit.gypi' ], + 'dependencies': [ + 'mojo_public_test_interfaces_mojom', + ], + }, + { + # GN version: //mojo/public/interfaces/bindings/tests:test_interfaces + 'target_name': 'mojo_public_test_interfaces', + 'type': 'static_library', + 'export_dependent_settings': [ + 'mojo_cpp_bindings', + ], + 'dependencies': [ + 'mojo_public_test_interfaces_mojom', + 'mojo_cpp_bindings', + ], + }, + { + # GN version: //mojo/public/interfaces/bindings/tests:test_interfaces_blink + 'target_name': 'mojo_public_test_interfaces_blink', + 'type': 'static_library', + 'export_dependent_settings': [ + 'mojo_cpp_bindings', + ], + 'dependencies': [ + 'mojo_public_test_interfaces_mojom_blink', + 'mojo_cpp_bindings', + ], + }, + { + # GN version: //mojo/public/interfaces/bindings/tests:test_interfaces_chromium + 'target_name': 'mojo_public_test_interfaces_chromium', + 'type': 'static_library', + 'export_dependent_settings': [ + 'mojo_cpp_bindings', + ], + 'dependencies': [ + 'mojo_public_test_interfaces_mojom_chromium', + 'mojo_cpp_bindings', + ], + }, + { + 'target_name': 'mojo_public_test_associated_interfaces_mojom', + 'type': 'none', + 'variables': { + # These files are not included in the mojo_public_test_interfaces_mojom + # target because associated interfaces are not supported by all bindings + # languages yet. + 'mojom_files': [ + 'public/interfaces/bindings/tests/test_associated_interfaces.mojom', + 'public/interfaces/bindings/tests/validation_test_associated_interfaces.mojom', + ], + }, + 'includes': [ 'mojom_bindings_generator_explicit.gypi' ], + }, + { + # GN version: //mojo/public/interfaces/bindings/tests:test_associated_interfaces + 'target_name': 'mojo_public_test_associated_interfaces', + 'type': 'static_library', + 'export_dependent_settings': [ + 'mojo_cpp_bindings', + ], + 'dependencies': [ + 'mojo_public_test_associated_interfaces_mojom', + 'mojo_cpp_bindings', + ], + }, + ], + 'conditions': [ + ['OS == "android"', { + 'targets': [ + { + # GN version: //mojo/public/java:system + 'target_name': 'mojo_public_java', + 'type': 'none', + 'variables': { + 'chromium_code': 0, + 'java_in_dir': 'public/java/system', + }, + 'includes': [ '../build/java.gypi' ], + }, + { + 'target_name': 'mojo_interface_bindings_java_sources', + 'type': 'none', + 'dependencies': [ + 'mojo_interface_bindings_mojom', + ], + }, + { + # GN version: //mojo/public/java:bindings + 'target_name': 'mojo_bindings_java', + 'type': 'none', + 'variables': { + 'chromium_code': 0, + 'java_in_dir': 'public/java/bindings', + }, + 'dependencies': [ + 'mojo_interface_bindings_java_sources', + 'mojo_public_java', + '<(DEPTH)/base/base.gyp:base_java', + ], + 'includes': [ '../build/java.gypi' ], + }, + ], + }], + ], +} diff --git a/third_party/mojo/mojo_public_bindings_unittests.isolate b/mojo/mojo_public_bindings_unittests.isolate index e771e74..4c1ffaa 100644 --- a/third_party/mojo/mojo_public_bindings_unittests.isolate +++ b/mojo/mojo_public_bindings_unittests.isolate @@ -3,19 +3,19 @@ # found in the LICENSE file. { 'includes': [ - '../../base/base.isolate', + '../base/base.isolate', ], 'conditions': [ ['OS=="win" or OS=="mac" or OS=="linux"', { 'variables': { 'command': [ - '../../testing/test_env.py', + '../testing/test_env.py', '<(PRODUCT_DIR)/mojo_public_bindings_unittests<(EXECUTABLE_SUFFIX)', '--brave-new-test-launcher', '--test-launcher-bot-mode', ], 'files': [ - '../../testing/test_env.py', + '../testing/test_env.py', ], }, }], diff --git a/third_party/mojo/mojo_public_environment_unittests.isolate b/mojo/mojo_public_environment_unittests.isolate index 3f20b22..d492271 100644 --- a/third_party/mojo/mojo_public_environment_unittests.isolate +++ b/mojo/mojo_public_environment_unittests.isolate @@ -3,19 +3,19 @@ # found in the LICENSE file. { 'includes': [ - '../../base/base.isolate', + '../base/base.isolate', ], 'conditions': [ ['OS=="win" or OS=="mac" or OS=="linux"', { 'variables': { 'command': [ - '../../testing/test_env.py', + '../testing/test_env.py', '<(PRODUCT_DIR)/mojo_public_environment_unittests<(EXECUTABLE_SUFFIX)', '--brave-new-test-launcher', '--test-launcher-bot-mode', ], 'files': [ - '../../testing/test_env.py', + '../testing/test_env.py', ], }, }], diff --git a/third_party/mojo/mojo_public_system_unittests.isolate b/mojo/mojo_public_system_unittests.isolate index 083510f..73b8c00 100644 --- a/third_party/mojo/mojo_public_system_unittests.isolate +++ b/mojo/mojo_public_system_unittests.isolate @@ -3,19 +3,19 @@ # found in the LICENSE file. { 'includes': [ - '../../base/base.isolate', + '../base/base.isolate', ], 'conditions': [ ['OS=="win" or OS=="mac" or OS=="linux"', { 'variables': { 'command': [ - '../../testing/test_env.py', + '../testing/test_env.py', '<(PRODUCT_DIR)/mojo_public_system_unittests<(EXECUTABLE_SUFFIX)', '--brave-new-test-launcher', '--test-launcher-bot-mode', ], 'files': [ - '../../testing/test_env.py', + '../testing/test_env.py', ], }, }], diff --git a/third_party/mojo/mojo_public_utility_unittests.isolate b/mojo/mojo_public_utility_unittests.isolate index 50d5348..d3fccf9 100644 --- a/third_party/mojo/mojo_public_utility_unittests.isolate +++ b/mojo/mojo_public_utility_unittests.isolate @@ -3,19 +3,19 @@ # found in the LICENSE file. { 'includes': [ - '../../base/base.isolate', + '../base/base.isolate', ], 'conditions': [ ['OS=="win" or OS=="mac" or OS=="linux"', { 'variables': { 'command': [ - '../../testing/test_env.py', + '../testing/test_env.py', '<(PRODUCT_DIR)/mojo_public_utility_unittests<(EXECUTABLE_SUFFIX)', '--brave-new-test-launcher', '--test-launcher-bot-mode', ], 'files': [ - '../../testing/test_env.py', + '../testing/test_env.py', ], }, }], diff --git a/mojo/mojo_services.gyp b/mojo/mojo_services.gyp index 652b7e6..23de8b9 100644 --- a/mojo/mojo_services.gyp +++ b/mojo/mojo_services.gyp @@ -28,7 +28,7 @@ 'mojom_include_path': '<(DEPTH)/mojo/services', }, 'includes': [ - '../third_party/mojo/mojom_bindings_generator_explicit.gypi', + 'mojom_bindings_generator_explicit.gypi', ], }, { @@ -71,7 +71,7 @@ 'mojom_include_path': '<(DEPTH)/mojo/services', }, 'includes': [ - '../third_party/mojo/mojom_bindings_generator_explicit.gypi', + 'mojom_bindings_generator_explicit.gypi', ], }, { diff --git a/mojo/mojo_shell.gyp b/mojo/mojo_shell.gyp index 8315a6c..fb477ab 100644 --- a/mojo/mojo_shell.gyp +++ b/mojo/mojo_shell.gyp @@ -103,8 +103,8 @@ '<(DEPTH)/mojo/mojo_base.gyp:mojo_common_lib', '<(DEPTH)/mojo/mojo_base.gyp:mojo_environment_chromium', '<(DEPTH)/mojo/mojo_base.gyp:mojo_url_type_converters', - '<(DEPTH)/third_party/mojo/mojo_edk.gyp:mojo_run_all_unittests', - '<(DEPTH)/third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + '<(DEPTH)/mojo/mojo_edk.gyp:mojo_run_all_unittests', + '<(DEPTH)/mojo/mojo_public.gyp:mojo_cpp_bindings', '<(DEPTH)/testing/gtest.gyp:gtest', '<(DEPTH)/url/url.gyp:url_lib', ] @@ -118,7 +118,7 @@ ], }, 'includes': [ - '../third_party/mojo/mojom_bindings_generator_explicit.gypi', + 'mojom_bindings_generator_explicit.gypi', ], }], } diff --git a/third_party/mojo/mojo_variables.gypi b/mojo/mojo_variables.gypi index f76ad6d..4ebb177 100644 --- a/third_party/mojo/mojo_variables.gypi +++ b/mojo/mojo_variables.gypi @@ -33,12 +33,12 @@ # ['component=="shared_library"', { 'mojo_gles2_for_component': "<(DEPTH)/mojo/mojo_base.gyp:mojo_gles2_impl", - 'mojo_system_for_component': "<(DEPTH)/third_party/mojo/mojo_edk.gyp:mojo_system_impl", - 'mojo_system_for_loadable_module': "<(DEPTH)/third_party/mojo/mojo_edk.gyp:mojo_system_impl", + 'mojo_system_for_component': "<(DEPTH)/mojo/mojo_edk.gyp:mojo_system_impl", + 'mojo_system_for_loadable_module': "<(DEPTH)/mojo/mojo_edk.gyp:mojo_system_impl", }, { 'mojo_gles2_for_component': "<(DEPTH)/mojo/mojo_base.gyp:mojo_none", - 'mojo_system_for_component': "<(DEPTH)/third_party/mojo/mojo_public.gyp:mojo_system_placeholder", - 'mojo_system_for_loadable_module': "<(DEPTH)/third_party/mojo/mojo_public.gyp:mojo_system", + 'mojo_system_for_component': "<(DEPTH)/mojo/mojo_public.gyp:mojo_system_placeholder", + 'mojo_system_for_loadable_module': "<(DEPTH)/mojo/mojo_public.gyp:mojo_system", }], ], 'mojo_public_system_unittest_sources': [ diff --git a/third_party/mojo/mojom_bindings_generator.gypi b/mojo/mojom_bindings_generator.gypi index cebc6ba..3b2e1bb 100644 --- a/third_party/mojo/mojom_bindings_generator.gypi +++ b/mojo/mojom_bindings_generator.gypi @@ -107,8 +107,8 @@ ], 'dependencies': [ '<(DEPTH)/base/base.gyp:base', + '<(DEPTH)/mojo/mojo_public.gyp:mojo_interface_bindings_generation', '<(DEPTH)/mojo/public/tools/bindings/bindings.gyp:precompile_mojom_bindings_generator_templates', - '<(DEPTH)/third_party/mojo/mojo_public.gyp:mojo_interface_bindings_generation', '<@(mojom_typemap_dependencies)', ], 'export_dependent_settings': [ diff --git a/third_party/mojo/mojom_bindings_generator_explicit.gypi b/mojo/mojom_bindings_generator_explicit.gypi index 000785a..8686cc2 100644 --- a/third_party/mojo/mojom_bindings_generator_explicit.gypi +++ b/mojo/mojom_bindings_generator_explicit.gypi @@ -93,8 +93,8 @@ ['require_interface_bindings==1', { 'dependencies': [ '<(DEPTH)/base/base.gyp:base', + '<(DEPTH)/mojo/mojo_public.gyp:mojo_interface_bindings_generation', '<(DEPTH)/mojo/public/tools/bindings/bindings.gyp:precompile_mojom_bindings_generator_templates', - '<(DEPTH)/third_party/mojo/mojo_public.gyp:mojo_interface_bindings_generation', ], }], ], diff --git a/third_party/mojo/mojom_bindings_generator_variables.gypi b/mojo/mojom_bindings_generator_variables.gypi index 9e3c400..9e3c400 100644 --- a/third_party/mojo/mojom_bindings_generator_variables.gypi +++ b/mojo/mojom_bindings_generator_variables.gypi diff --git a/mojo/platform_handle/BUILD.gn b/mojo/platform_handle/BUILD.gn index d5818f7..16829ab 100644 --- a/mojo/platform_handle/BUILD.gn +++ b/mojo/platform_handle/BUILD.gn @@ -30,8 +30,8 @@ component("platform_handle_impl") { defines = [ "PLATFORM_HANDLE_IMPLEMENTATION" ] deps = [ "//base", + "//mojo/edk/embedder:headers", "//mojo/public/c/system:for_component", - "//third_party/mojo/src/mojo/edk/embedder:headers", ] } diff --git a/mojo/platform_handle/platform_handle_functions.cc b/mojo/platform_handle/platform_handle_functions.cc index 7b721b0..942b633 100644 --- a/mojo/platform_handle/platform_handle_functions.cc +++ b/mojo/platform_handle/platform_handle_functions.cc @@ -6,35 +6,29 @@ #include <utility> -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/embedder.h" extern "C" { MojoResult MojoCreatePlatformHandleWrapper(MojoPlatformHandle platform_handle, MojoHandle* wrapper) { - mojo::embedder::PlatformHandle platform_handle_wrapper(platform_handle); - mojo::embedder::ScopedPlatformHandle scoped_platform_handle( + mojo::edk::PlatformHandle platform_handle_wrapper(platform_handle); + mojo::edk::ScopedPlatformHandle scoped_platform_handle( platform_handle_wrapper); - return mojo::embedder::CreatePlatformHandleWrapper( + return mojo::edk::CreatePlatformHandleWrapper( std::move(scoped_platform_handle), wrapper); } MojoResult MojoExtractPlatformHandle(MojoHandle wrapper, MojoPlatformHandle* platform_handle) { - mojo::embedder::ScopedPlatformHandle scoped_platform_handle; - MojoResult result = mojo::embedder::PassWrappedPlatformHandle( - wrapper, &scoped_platform_handle); + mojo::edk::ScopedPlatformHandle scoped_platform_handle; + MojoResult result = + mojo::edk::PassWrappedPlatformHandle(wrapper, &scoped_platform_handle); if (result != MOJO_RESULT_OK) return result; DCHECK(scoped_platform_handle.is_valid()); -#if defined(OS_POSIX) - *platform_handle = scoped_platform_handle.release().fd; -#elif defined(OS_WIN) *platform_handle = scoped_platform_handle.release().handle; -#else -#error "Platform not yet supported." -#endif return MOJO_RESULT_OK; } diff --git a/mojo/public/c/system/BUILD.gn b/mojo/public/c/system/BUILD.gn index 78e7ab6..c2f149b 100644 --- a/mojo/public/c/system/BUILD.gn +++ b/mojo/public/c/system/BUILD.gn @@ -38,7 +38,7 @@ group("for_shared_library") { ] if (is_component_build) { deps = [ - "//third_party/mojo/src/mojo/edk/system", + "//mojo/edk/system", ] } else { deps = [ @@ -53,7 +53,7 @@ group("for_component") { ] if (is_component_build) { deps = [ - "//third_party/mojo/src/mojo/edk/system", + "//mojo/edk/system", ] } } diff --git a/mojo/public/c/test_support/BUILD.gn b/mojo/public/c/test_support/BUILD.gn index 3b11a60..592e80a 100644 --- a/mojo/public/c/test_support/BUILD.gn +++ b/mojo/public/c/test_support/BUILD.gn @@ -4,7 +4,7 @@ # GYP version: mojo/public/mojo_public.gyp:mojo_test_support shared_library("test_support") { - output_name = "mojo_test_support" + output_name = "mojo_public_test_support" defines = [ "MOJO_TEST_SUPPORT_IMPLEMENTATION" ] diff --git a/mojo/public/tools/bindings/bindings.gyp b/mojo/public/tools/bindings/bindings.gyp index 5e2b265..668df35 100644 --- a/mojo/public/tools/bindings/bindings.gyp +++ b/mojo/public/tools/bindings/bindings.gyp @@ -4,7 +4,7 @@ { 'includes': [ - '../../../../third_party/mojo/mojom_bindings_generator_variables.gypi', + '../../../mojom_bindings_generator_variables.gypi', ], 'targets': [ { diff --git a/mojo/shell/BUILD.gn b/mojo/shell/BUILD.gn index bd3ee6e..1adf800 100644 --- a/mojo/shell/BUILD.gn +++ b/mojo/shell/BUILD.gn @@ -61,10 +61,10 @@ source_set("shell") { deps = [ "//base/third_party/dynamic_annotations", "//crypto:crypto", + "//mojo/edk/system", "//mojo/environment:chromium", "//mojo/shell/public/cpp:sources", "//mojo/util:filename_util", - "//third_party/mojo/src/mojo/edk/system", "//url", ] } @@ -107,13 +107,13 @@ test("mojo_shell_unittests") { ":test_support", "//base", "//mojo/edk/system:test_utils", + "//mojo/edk/test:run_all_unittests", "//mojo/public/cpp/system", "//mojo/shell/fetcher", "//mojo/shell/package_manager", "//mojo/shell/public/cpp", "//mojo/util:filename_util", "//testing/gtest", - "//third_party/mojo/src/mojo/edk/test:run_all_unittests", "//url", ] } @@ -192,12 +192,12 @@ executable("application_manager_apptest_driver") { "//build/config/sanitizers:deps", "//mojo/common:common_base", "//mojo/converters/network", + "//mojo/edk/system", "//mojo/shell/public/cpp", "//mojo/shell/public/interfaces", "//mojo/shell/runner:init", "//mojo/shell/runner/child:test_native_main", "//mojo/shell/runner/common", - "//third_party/mojo/src/mojo/edk/system", ] } diff --git a/mojo/shell/application_manager_apptest_driver.cc b/mojo/shell/application_manager_apptest_driver.cc index 5c755a1..453f3d5 100644 --- a/mojo/shell/application_manager_apptest_driver.cc +++ b/mojo/shell/application_manager_apptest_driver.cc @@ -69,9 +69,6 @@ class TargetApplicationDelegate : public mojo::ShellClient, child_command_line.AppendSwitch(switches::kWaitForDebugger); } - DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch("use-new-edk")); - child_command_line.AppendSwitch("use-new-edk"); - mojo::shell::mojom::PIDReceiverPtr receiver; mojo::InterfaceRequest<mojo::shell::mojom::PIDReceiver> request = GetProxy(&receiver); diff --git a/mojo/shell/fetcher/BUILD.gn b/mojo/shell/fetcher/BUILD.gn index 48cfe0f5..61dd583 100644 --- a/mojo/shell/fetcher/BUILD.gn +++ b/mojo/shell/fetcher/BUILD.gn @@ -32,12 +32,12 @@ source_set("fetcher") { deps = [ "//base/third_party/dynamic_annotations", "//crypto:crypto", + "//mojo/edk/system", "//mojo/environment:chromium", "//mojo/shell", "//mojo/shell/public/cpp:sources", "//mojo/util:filename_util", "//net", - "//third_party/mojo/src/mojo/edk/system", "//url", ] } diff --git a/mojo/shell/package_manager/BUILD.gn b/mojo/shell/package_manager/BUILD.gn index f49cd8c..761b835d 100644 --- a/mojo/shell/package_manager/BUILD.gn +++ b/mojo/shell/package_manager/BUILD.gn @@ -31,11 +31,11 @@ test("unittests") { deps = [ ":package_manager", "//base", + "//mojo/edk/test:run_all_unittests", "//mojo/shell", "//mojo/shell:test_support", "//mojo/shell/public/cpp", "//testing/gtest", - "//third_party/mojo/src/mojo/edk/test:run_all_unittests", "//url", ] } diff --git a/mojo/shell/public/cpp/tests/BUILD.gn b/mojo/shell/public/cpp/tests/BUILD.gn index e4ad1f2..ef9bbbd 100644 --- a/mojo/shell/public/cpp/tests/BUILD.gn +++ b/mojo/shell/public/cpp/tests/BUILD.gn @@ -11,8 +11,8 @@ test("mojo_public_application_unittests") { deps = [ "//base", + "//mojo/edk/test:run_all_unittests", "//mojo/shell/public/cpp", "//testing/gtest", - "//third_party/mojo/src/mojo/edk/test:run_all_unittests", ] } diff --git a/mojo/shell/runner/child/BUILD.gn b/mojo/shell/runner/child/BUILD.gn index 0ea9929..55779bf 100644 --- a/mojo/shell/runner/child/BUILD.gn +++ b/mojo/shell/runner/child/BUILD.gn @@ -22,11 +22,11 @@ source_set("lib") { deps = [ ":interfaces", "//base", + "//mojo/edk/system", "//mojo/message_pump", "//mojo/platform_handle:platform_handle_impl", "//mojo/shell/public/interfaces", "//mojo/shell/runner/common", - "//third_party/mojo/src/mojo/edk/system", ] } @@ -54,11 +54,11 @@ source_set("test_native_main") { deps = [ "//base", + "//mojo/edk/system", "//mojo/gles2", "//mojo/message_pump", "//mojo/shell/public/cpp", "//mojo/shell/runner/child:lib", - "//third_party/mojo/src/mojo/edk/system", ] } diff --git a/mojo/shell/runner/child/test_native_main.cc b/mojo/shell/runner/child/test_native_main.cc index 8b4cbd8..db735ec 100644 --- a/mojo/shell/runner/child/test_native_main.cc +++ b/mojo/shell/runner/child/test_native_main.cc @@ -12,19 +12,19 @@ #include "base/process/launch.h" #include "base/threading/thread.h" #include "build/build_config.h" +#include "mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/process_delegate.h" #include "mojo/message_pump/message_pump_mojo.h" #include "mojo/shell/public/cpp/shell_client.h" #include "mojo/shell/public/cpp/shell_connection.h" #include "mojo/shell/runner/child/runner_connection.h" #include "mojo/shell/runner/init.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" -#include "third_party/mojo/src/mojo/edk/embedder/process_delegate.h" namespace mojo { namespace shell { namespace { -class ProcessDelegate : public mojo::embedder::ProcessDelegate { +class ProcessDelegate : public mojo::edk::ProcessDelegate { public: ProcessDelegate() {} ~ProcessDelegate() override {} @@ -48,17 +48,14 @@ int TestNativeMain(mojo::ShellClient* shell_client) { #endif { - mojo::embedder::PreInitializeChildProcess(); - mojo::embedder::Init(); + mojo::edk::Init(); ProcessDelegate process_delegate; base::Thread io_thread("io_thread"); base::Thread::Options io_thread_options(base::MessageLoop::TYPE_IO, 0); CHECK(io_thread.StartWithOptions(io_thread_options)); - mojo::embedder::InitIPCSupport( - mojo::embedder::ProcessType::NONE, &process_delegate, - io_thread.task_runner().get(), mojo::embedder::ScopedPlatformHandle()); + mojo::edk::InitIPCSupport(&process_delegate, io_thread.task_runner()); mojo::ShellClientRequest request; scoped_ptr<mojo::shell::RunnerConnection> connection( @@ -68,7 +65,7 @@ int TestNativeMain(mojo::ShellClient* shell_client) { mojo::ShellConnection impl(shell_client, std::move(request)); loop.Run(); - mojo::embedder::ShutdownIPCSupport(); + mojo::edk::ShutdownIPCSupport(); } return 0; diff --git a/mojo/shell/runner/host/BUILD.gn b/mojo/shell/runner/host/BUILD.gn index a4e4b10..8741563 100644 --- a/mojo/shell/runner/host/BUILD.gn +++ b/mojo/shell/runner/host/BUILD.gn @@ -54,6 +54,7 @@ source_set("lib") { "//base", "//base:base_static", "//base:i18n", + "//mojo/edk/system", "//mojo/gles2", "//mojo/message_pump", "//mojo/platform_handle:platform_handle_impl", @@ -61,7 +62,6 @@ source_set("lib") { "//mojo/shell/runner:init", "//mojo/shell/runner/child:interfaces", "//mojo/shell/runner/common", - "//third_party/mojo/src/mojo/edk/system", ] if (is_linux && !is_android) { @@ -91,11 +91,11 @@ test("mojo_runner_host_unittests") { "//base", "//base/test:test_support", "//mojo/common", + "//mojo/edk/system", "//mojo/environment:chromium", "//mojo/message_pump", "//mojo/shell/runner:init", "//mojo/shell/runner/common", "//testing/gtest", - "//third_party/mojo/src/mojo/edk/system", ] } diff --git a/mojo/shell/runner/host/child_process.cc b/mojo/shell/runner/host/child_process.cc index 75230f0..8f8c8a1 100644 --- a/mojo/shell/runner/host/child_process.cc +++ b/mojo/shell/runner/host/child_process.cc @@ -28,6 +28,8 @@ #include "base/threading/thread_checker.h" #include "mojo/edk/embedder/embedder.h" #include "mojo/edk/embedder/platform_channel_pair.h" +#include "mojo/edk/embedder/process_delegate.h" +#include "mojo/edk/embedder/scoped_platform_handle.h" #include "mojo/message_pump/message_pump_mojo.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/system/core.h" @@ -35,10 +37,6 @@ #include "mojo/shell/runner/common/switches.h" #include "mojo/shell/runner/host/native_application_support.h" #include "mojo/shell/runner/init.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" -#include "third_party/mojo/src/mojo/edk/embedder/process_delegate.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" #if defined(OS_LINUX) && !defined(OS_ANDROID) #include "base/rand_util.h" @@ -100,18 +98,15 @@ class Blocker { class ChildControllerImpl; // Should be created and initialized on the main thread. -// TODO(use_chrome_edk) -// class AppContext : public edk::ProcessDelegate { -class AppContext : public embedder::ProcessDelegate { +class AppContext : public edk::ProcessDelegate { public: AppContext() : io_thread_("io_thread"), controller_thread_("controller_thread") {} ~AppContext() override {} void Init() { - embedder::PreInitializeChildProcess(); // Initialize Mojo before starting any threads. - embedder::Init(); + edk::Init(); // Create and start our I/O thread. base::Thread::Options io_thread_options(base::MessageLoop::TYPE_IO, 0); @@ -122,8 +117,7 @@ class AppContext : public embedder::ProcessDelegate { // TODO(vtl): This should be SLAVE, not NONE. // This must be created before controller_thread_ since MessagePumpMojo will // create a message pipe which requires this code to be run first. - embedder::InitIPCSupport(embedder::ProcessType::NONE, this, io_runner_, - embedder::ScopedPlatformHandle()); + edk::InitIPCSupport(this, io_runner_); } void StartControllerThread() { @@ -165,7 +159,7 @@ class AppContext : public embedder::ProcessDelegate { controller_.reset(); // Next shutdown IPC. We'll unblock the main thread in OnShutdownComplete(). - embedder::ShutdownIPCSupport(); + edk::ShutdownIPCSupport(); } // ProcessDelegate implementation. @@ -337,8 +331,7 @@ int ChildProcessMain() { #endif edk::ScopedPlatformHandle platform_channel = - edk::PlatformChannelPair::PassClientHandleFromParentProcess( - command_line); + edk::PlatformChannelPair::PassClientHandleFromParentProcess(command_line); CHECK(platform_channel.is_valid()); DCHECK(!base::MessageLoop::current()); diff --git a/mojo/shell/runner/host/child_process_host.cc b/mojo/shell/runner/host/child_process_host.cc index 2b3cfc9..df45660 100644 --- a/mojo/shell/runner/host/child_process_host.cc +++ b/mojo/shell/runner/host/child_process_host.cc @@ -22,7 +22,6 @@ #include "mojo/public/cpp/bindings/interface_ptr_info.h" #include "mojo/public/cpp/system/core.h" #include "mojo/shell/runner/common/switches.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" #if defined(OS_LINUX) && !defined(OS_ANDROID) #include "sandbox/linux/services/namespace_sandbox.h" @@ -197,9 +196,9 @@ void ChildProcessHost::DoLaunch() { platform_channel_pair_.ChildProcessLaunched(); if (node_channel_.get()) { node_channel_->ChildProcessLaunched(); - mojo::embedder::ChildProcessLaunched( + mojo::edk::ChildProcessLaunched( child_process_.Handle(), - mojo::embedder::ScopedPlatformHandle(mojo::embedder::PlatformHandle( + mojo::edk::ScopedPlatformHandle(mojo::edk::PlatformHandle( node_channel_->PassServerHandle().release().handle))); } } diff --git a/mojo/shell/runner/host/child_process_host.h b/mojo/shell/runner/host/child_process_host.h index 2664d30..27e0196 100644 --- a/mojo/shell/runner/host/child_process_host.h +++ b/mojo/shell/runner/host/child_process_host.h @@ -21,9 +21,6 @@ #include "mojo/public/cpp/system/message_pipe.h" #include "mojo/shell/runner/child/child_controller.mojom.h" #include "mojo/shell/runner/host/child_process_host.h" -#include "third_party/mojo/src/mojo/edk/embedder/channel_info_forward.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" namespace base { class TaskRunner; diff --git a/mojo/shell/runner/host/child_process_host_unittest.cc b/mojo/shell/runner/host/child_process_host_unittest.cc index c96b834..01789bc 100644 --- a/mojo/shell/runner/host/child_process_host_unittest.cc +++ b/mojo/shell/runner/host/child_process_host_unittest.cc @@ -15,10 +15,10 @@ #include "base/path_service.h" #include "base/run_loop.h" #include "base/threading/thread.h" +#include "mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/process_delegate.h" #include "mojo/message_pump/message_pump_mojo.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" -#include "third_party/mojo/src/mojo/edk/embedder/process_delegate.h" namespace mojo { namespace shell { @@ -29,7 +29,7 @@ void ProcessReadyCallbackAdapater(const base::Closure& callback, callback.Run(); } -class ProcessDelegate : public embedder::ProcessDelegate { +class ProcessDelegate : public edk::ProcessDelegate { public: ProcessDelegate() {} ~ProcessDelegate() override {} @@ -48,8 +48,6 @@ class ProcessDelegate : public embedder::ProcessDelegate { // Just tests starting the child process and joining it (without starting an // app). TEST(ChildProcessHostTest, MAYBE_StartJoin) { - base::CommandLine::ForCurrentProcess()->AppendSwitch("use-new-edk"); - base::FilePath shell_dir; PathService::Get(base::DIR_MODULE, &shell_dir); base::MessageLoop message_loop( @@ -63,9 +61,7 @@ TEST(ChildProcessHostTest, MAYBE_StartJoin) { io_thread.StartWithOptions(options); ProcessDelegate delegate; - embedder::InitIPCSupport( - embedder::ProcessType::NONE, &delegate, io_thread.task_runner(), - embedder::ScopedPlatformHandle()); + edk::InitIPCSupport(&delegate, io_thread.task_runner()); ChildProcessHost child_process_host(blocking_pool.get(), false, base::FilePath()); @@ -79,7 +75,7 @@ TEST(ChildProcessHostTest, MAYBE_StartJoin) { VLOG(2) << "Joined child: exit_code = " << exit_code; EXPECT_EQ(123, exit_code); blocking_pool->Shutdown(); - embedder::ShutdownIPCSupport(); + edk::ShutdownIPCSupport(); } } // namespace diff --git a/mojo/shell/runner/host/host_unittests.cc b/mojo/shell/runner/host/host_unittests.cc index 6600d11..3daf4a0 100644 --- a/mojo/shell/runner/host/host_unittests.cc +++ b/mojo/shell/runner/host/host_unittests.cc @@ -8,11 +8,11 @@ #include "base/logging.h" #include "base/test/launcher/unit_test_launcher.h" #include "base/test/test_suite.h" +#include "mojo/edk/embedder/embedder.h" #include "mojo/shell/runner/common/switches.h" #include "mojo/shell/runner/host/child_process.h" #include "mojo/shell/runner/init.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" int main(int argc, char** argv) { base::CommandLine::Init(argc, argv); @@ -27,7 +27,7 @@ int main(int argc, char** argv) { return mojo::shell::ChildProcessMain(); } - mojo::embedder::Init(); + mojo::edk::Init(); base::TestSuite test_suite(argc, argv); return base::LaunchUnitTests( diff --git a/mojo/shell/shell_application_delegate.cc b/mojo/shell/shell_application_delegate.cc index 47df9d4..b4886104 100644 --- a/mojo/shell/shell_application_delegate.cc +++ b/mojo/shell/shell_application_delegate.cc @@ -11,7 +11,6 @@ #include "base/process/process.h" #include "mojo/shell/application_manager.h" #include "mojo/shell/public/cpp/connection.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" namespace mojo { namespace shell { diff --git a/mojo/shell/standalone/BUILD.gn b/mojo/shell/standalone/BUILD.gn index b84fb32..eccb693 100644 --- a/mojo/shell/standalone/BUILD.gn +++ b/mojo/shell/standalone/BUILD.gn @@ -80,7 +80,7 @@ executable("standalone") { deps += [ ":lib", ":register_local_aliases_fwd", - "//third_party/mojo/src/mojo/edk/system", + "//mojo/edk/system", ] # On android, the executable is also the native library used by the apk. @@ -106,6 +106,7 @@ source_set("lib") { "//base:base_static", "//base/third_party/dynamic_annotations", "//components/tracing:startup_tracing", + "//mojo/edk/system", "//mojo/message_pump", "//mojo/services/network/public/interfaces", "//mojo/services/tracing/public/cpp", @@ -117,7 +118,6 @@ source_set("lib") { "//mojo/shell/runner/child:interfaces", "//mojo/shell/runner/host:lib", "//mojo/util:filename_util", - "//third_party/mojo/src/mojo/edk/system", "//ui/gl", "//url", ] diff --git a/mojo/shell/standalone/context.cc b/mojo/shell/standalone/context.cc index 9b16856..b443b97 100644 --- a/mojo/shell/standalone/context.cc +++ b/mojo/shell/standalone/context.cc @@ -25,6 +25,7 @@ #include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "components/tracing/tracing_switches.h" +#include "mojo/edk/embedder/embedder.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/services/tracing/public/cpp/switches.h" #include "mojo/services/tracing/public/cpp/trace_provider_impl.h" @@ -41,7 +42,6 @@ #include "mojo/shell/standalone/tracer.h" #include "mojo/shell/switches.h" #include "mojo/util/filename_util.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" #include "url/gurl.h" namespace mojo { @@ -51,10 +51,7 @@ namespace { // Used to ensure we only init once. class Setup { public: - Setup() { - embedder::PreInitializeParentProcess(); - embedder::Init(); - } + Setup() { edk::Init(); } ~Setup() {} @@ -170,9 +167,7 @@ void Context::Init(const base::FilePath& shell_file_root) { new TaskRunners(base::MessageLoop::current()->task_runner())); // TODO(vtl): This should be MASTER, not NONE. - embedder::InitIPCSupport(embedder::ProcessType::NONE, this, - task_runners_->io_runner(), - embedder::ScopedPlatformHandle()); + edk::InitIPCSupport(this, task_runners_->io_runner()); package_manager_ = new PackageManagerImpl( shell_file_root, task_runners_->blocking_pool(), nullptr); @@ -244,8 +239,8 @@ void Context::Shutdown() { DCHECK_EQ(base::MessageLoop::current()->task_runner(), task_runners_->shell_runner()); // Post a task in case OnShutdownComplete is called synchronously. - base::MessageLoop::current()->PostTask( - FROM_HERE, base::Bind(embedder::ShutdownIPCSupport)); + base::MessageLoop::current()->PostTask(FROM_HERE, + base::Bind(edk::ShutdownIPCSupport)); // We'll quit when we get OnShutdownComplete(). base::MessageLoop::current()->Run(); } diff --git a/mojo/shell/standalone/context.h b/mojo/shell/standalone/context.h index c01670b..fc923d2 100644 --- a/mojo/shell/standalone/context.h +++ b/mojo/shell/standalone/context.h @@ -11,11 +11,11 @@ #include "base/callback_forward.h" #include "base/macros.h" #include "base/time/time.h" +#include "mojo/edk/embedder/process_delegate.h" #include "mojo/shell/application_manager.h" #include "mojo/shell/standalone/scoped_user_data_dir.h" #include "mojo/shell/standalone/task_runners.h" #include "mojo/shell/standalone/tracer.h" -#include "third_party/mojo/src/mojo/edk/embedder/process_delegate.h" #include "url/gurl.h" namespace mojo { @@ -24,9 +24,7 @@ class NativeApplicationLoader; class PackageManagerImpl; // The "global" context for the shell's main process. -// TODO(use_chrome_edk) -// class Context : public edk::ProcessDelegate { -class Context : public embedder::ProcessDelegate { +class Context : public edk::ProcessDelegate { public: Context(); ~Context() override; diff --git a/mojo/shell/standalone/desktop/launcher_process.cc b/mojo/shell/standalone/desktop/launcher_process.cc index 9332d94..3787a57 100644 --- a/mojo/shell/standalone/desktop/launcher_process.cc +++ b/mojo/shell/standalone/desktop/launcher_process.cc @@ -33,7 +33,6 @@ int LauncherProcessMain(const GURL& mojo_url, const base::Closure& callback) { if (!command_line->HasSwitch(switches::kMojoSingleProcess) && !command_line->HasSwitch("gtest_list_tests")) command_line->AppendSwitch(switches::kEnableMultiprocess); - command_line->AppendSwitch("use-new-edk"); // http://crbug.com/546644 command_line->AppendSwitch(switches::kMojoNoSandbox); diff --git a/net/BUILD.gn b/net/BUILD.gn index 3c062f4..9078f02 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn @@ -1582,8 +1582,8 @@ test("net_unittests") { deps += [ ":net_browser_services", ":net_utility_services", + "//mojo/edk/system", "//mojo/environment:chromium", - "//third_party/mojo/src/mojo/edk/system", ] } else { sources -= [ @@ -54,7 +54,7 @@ specific_include_rules = { ], "run_all_unittests\.cc": [ - "+third_party/mojo/src/mojo/edk", + "+mojo/edk", ], "brotli_filter\.cc": [ diff --git a/net/net.gyp b/net/net.gyp index 6cff8ca..0a13905 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -319,7 +319,7 @@ 'net_with_v8', 'net_browser_services', 'net_utility_services', - '../third_party/mojo/mojo_edk.gyp:mojo_system_impl', + '../mojo/mojo_edk.gyp:mojo_system_impl', ], }, { # else 'sources!': [ @@ -906,7 +906,7 @@ 'interfaces/proxy_resolver_service.mojom', ], 'includes': [ - '../third_party/mojo/mojom_bindings_generator.gypi', + '../mojo/mojom_bindings_generator.gypi', ], }, { @@ -931,7 +931,7 @@ '../mojo/mojo_base.gyp:mojo_common_lib', '../mojo/mojo_base.gyp:mojo_environment_chromium', '../mojo/mojo_base.gyp:mojo_url_type_converters', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', # NOTE(amistry): As long as we support in-process Mojo v8 PAC, we # need this dependency since in_process_mojo_proxy_resolver_factory @@ -959,7 +959,7 @@ 'net_interfaces', 'net_with_v8', '../mojo/mojo_base.gyp:mojo_url_type_converters', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', ], }, { @@ -975,7 +975,7 @@ 'dependencies': [ 'net', 'net_interfaces', - '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + '../mojo/mojo_public.gyp:mojo_cpp_bindings', ], }, ], diff --git a/net/test/run_all_unittests.cc b/net/test/run_all_unittests.cc index a502eb6..2cfb258 100644 --- a/net/test/run_all_unittests.cc +++ b/net/test/run_all_unittests.cc @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/command_line.h" #include "base/metrics/statistics_recorder.h" #include "base/test/launcher/unit_test_launcher.h" #include "build/build_config.h" @@ -26,7 +25,7 @@ #endif #if !defined(OS_ANDROID) && !defined(OS_IOS) -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/embedder.h" #endif using net::internal::ClientSocketPoolBaseHelper; @@ -59,10 +58,6 @@ int main(int argc, char** argv) { NetTestSuite test_suite(argc, argv); ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(false); - // TODO(use_chrome_edk): This flag will go away and be default behavior soon, - // but we explicitly add it here for test coverage. - base::CommandLine::ForCurrentProcess()->AppendSwitch("use-new-edk"); - #if defined(OS_WIN) && !defined(USE_OPENSSL) // We want to be sure to init NSPR on the main thread. crypto::EnsureNSPRInit(); @@ -73,7 +68,7 @@ int main(int argc, char** argv) { net::EnableSSLServerSockets(); #if !defined(OS_ANDROID) && !defined(OS_IOS) - mojo::embedder::Init(); + mojo::edk::Init(); #endif return base::LaunchUnitTests( diff --git a/skia/skia.gyp b/skia/skia.gyp index ce0aae1..2103c4b 100644 --- a/skia/skia.gyp +++ b/skia/skia.gyp @@ -14,7 +14,7 @@ 'target_name': 'skia_library', 'type': 'static_library', # The optimize: 'max' scattered throughout are particularly - # important when compiled by MSVC 2013, which seems + # important when compiled by MSVC 2013, which seems # to mis-link-time-compile code that's built with # different optimization levels. http://crbug.com/543583 'variables': { @@ -37,7 +37,7 @@ { 'target_name': 'skia', # The optimize: 'max' scattered throughout are particularly - # important when compiled by MSVC 2013, which seems + # important when compiled by MSVC 2013, which seems # to mis-link-time-compile code that's built with # different optimization levels. http://crbug.com/543583 'variables': { @@ -78,7 +78,7 @@ { 'target_name': 'skia', # The optimize: 'max' scattered throughout are particularly - # important when compiled by MSVC 2013, which seems + # important when compiled by MSVC 2013, which seems # to mis-link-time-compile code that's built with # different optimization levels. http://crbug.com/543583 'variables': { @@ -130,7 +130,7 @@ { 'target_name': 'image_operations_bench', # The optimize: 'max' scattered throughout are particularly - # important when compiled by MSVC 2013, which seems + # important when compiled by MSVC 2013, which seems # to mis-link-time-compile code that's built with # different optimization levels. http://crbug.com/543583 'variables': { @@ -152,7 +152,7 @@ 'target_name': 'filter_fuzz_stub', 'type': 'executable', # The optimize: 'max' scattered throughout are particularly - # important when compiled by MSVC 2013, which seems + # important when compiled by MSVC 2013, which seems # to mis-link-time-compile code that's built with # different optimization levels. http://crbug.com/543583 'variables': { @@ -174,7 +174,7 @@ 'target_name': 'skia_mojo', 'type': 'static_library', # The optimize: 'max' scattered throughout are particularly - # important when compiled by MSVC 2013, which seems + # important when compiled by MSVC 2013, which seems # to mis-link-time-compile code that's built with # different optimization levels. http://crbug.com/543583 'variables': { @@ -185,7 +185,7 @@ '../base/base.gyp:base', ], 'includes': [ - '../third_party/mojo/mojom_bindings_generator.gypi', + '../mojo/mojom_bindings_generator.gypi', ], 'sources': [ # Note: file list duplicated in GN build. diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index 026f12e..37c46f8 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl @@ -350,23 +350,23 @@ "type": "console_test_launcher", }, "mojo_public_application_unittests": { - "label": "//third_party/mojo/src/mojo/edk/test:mojo_public_applicaiton_unittests", + "label": "//mojo/edk/test:mojo_public_applicaiton_unittests", "type": "unknown", }, "mojo_public_bindings_unittests": { - "label": "//third_party/mojo/src/mojo/edk/test:mojo_public_bindings_unittests", + "label": "//mojo/edk/test:mojo_public_bindings_unittests", "type": "console_test_launcher", }, "mojo_public_environment_unittests": { - "label": "//third_party/mojo/src/mojo/edk/test:mojo_public_environment_unittests", + "label": "//mojo/edk/test:mojo_public_environment_unittests", "type": "console_test_launcher", }, "mojo_public_system_unittests": { - "label": "//third_party/mojo/src/mojo/edk/test:mojo_public_system_unittests", + "label": "//mojo/edk/test:mojo_public_system_unittests", "type": "console_test_launcher", }, "mojo_public_utility_unittests": { - "label": "//third_party/mojo/src/mojo/edk/test:mojo_public_utility_unittests", + "label": "//mojo/edk/test:mojo_public_utility_unittests", "type": "console_test_launcher", }, "mojo_runner_host_unittests": { @@ -382,7 +382,7 @@ "type": "unknown", }, "mojo_system_unittests": { - "label": "//third_party/mojo/src/mojo/edk/system:mojo_system_unittests", + "label": "//mojo/edk/system:mojo_system_unittests", "type": "unknown", }, "mojo_view_manager_lib_unittests": { diff --git a/third_party/mojo/LICENSE b/third_party/mojo/LICENSE deleted file mode 100644 index 972bb2e..0000000 --- a/third_party/mojo/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/third_party/mojo/OWNERS b/third_party/mojo/OWNERS deleted file mode 100644 index fd99575..0000000 --- a/third_party/mojo/OWNERS +++ /dev/null @@ -1,5 +0,0 @@ -ben@chromium.org -jam@chromium.org -jamesr@chromium.org -rockot@chromium.org -yzshen@chromium.org diff --git a/third_party/mojo/README.chromium b/third_party/mojo/README.chromium deleted file mode 100644 index c429d21..0000000 --- a/third_party/mojo/README.chromium +++ /dev/null @@ -1,16 +0,0 @@ -Name: Mojo -Short Name: mojo -URL: https://github.com/domokit/mojo -Version: Unknown -Security Critical: Yes -License: Chromium -License Android Compatible: yes - -Description: -Mojo is an effort to extract a common platform out of Chrome's renderer and -plugin processes that can support multiple types of sandboxed content, such as -HTML, Pepper, or NaCl. - -Local Modifications: -This library has been forked from the Mojo repository and will be moved out of -third_party soon. diff --git a/third_party/mojo/mojo_edk.gyp b/third_party/mojo/mojo_edk.gyp deleted file mode 100644 index 5f17552..0000000 --- a/third_party/mojo/mojo_edk.gyp +++ /dev/null @@ -1,160 +0,0 @@ -# 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. - -{ - 'includes': [ - 'mojo_variables.gypi', - ], - 'target_defaults' : { - 'include_dirs': [ - # TODO(use_chrome_edk): since we include a few headers from src/mojo/edk, - # we need their includes to be searched first (i.e. otherwise when - # embedder.cc in third_party includes core.h from src/mojo/edk, and the - # latter includes mojo/edk/system/memory.h, the header from third_party - # would incorrectly get chosen). - '../..', - ], - }, - 'targets': [ - { - # GN version: //mojo/edk/system - 'target_name': 'mojo_system_impl', - 'type': '<(component)', - 'dependencies': [ - '../../base/base.gyp:base', - '../../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', - # TODO(use_chrome_edk): so that EDK in third_party can choose the EDK in - # src/mojo if the command line flag is specified. It has to since we can - # only have one definition of the Mojo primitives. - '../../mojo/mojo_edk.gyp:mojo_system_impl2', - ], - 'includes': [ - 'mojo_edk_system_impl.gypi', - ], - }, - { - # GN version: //mojo/edk/js - 'target_name': 'mojo_js_lib', - 'type': 'static_library', - 'dependencies': [ - '../../base/base.gyp:base', - '../../gin/gin.gyp:gin', - '../../v8/tools/gyp/v8.gyp:v8', - ], - 'export_dependent_settings': [ - '../../base/base.gyp:base', - '../../gin/gin.gyp:gin', - ], - 'sources': [ - # Sources list duplicated in GN build. - 'src/mojo/edk/js/core.cc', - 'src/mojo/edk/js/core.h', - 'src/mojo/edk/js/drain_data.cc', - 'src/mojo/edk/js/drain_data.h', - 'src/mojo/edk/js/handle.cc', - 'src/mojo/edk/js/handle.h', - 'src/mojo/edk/js/handle_close_observer.h', - 'src/mojo/edk/js/mojo_runner_delegate.cc', - 'src/mojo/edk/js/mojo_runner_delegate.h', - 'src/mojo/edk/js/support.cc', - 'src/mojo/edk/js/support.h', - 'src/mojo/edk/js/threading.cc', - 'src/mojo/edk/js/threading.h', - 'src/mojo/edk/js/waiting_callback.cc', - 'src/mojo/edk/js/waiting_callback.h', - ], - }, - { - # GN version: //mojo/edk/test:test_support_impl - 'target_name': 'mojo_test_support_impl', - 'type': 'static_library', - 'dependencies': [ - '../../base/base.gyp:base', - ], - 'sources': [ - 'src/mojo/edk/test/test_support_impl.cc', - 'src/mojo/edk/test/test_support_impl.h', - ], - }, - { - # GN version: //mojo/edk/test:test_support - 'target_name': 'mojo_common_test_support', - 'type': 'static_library', - 'dependencies': [ - '../../base/base.gyp:base', - '../../base/base.gyp:test_support_base', - '../../testing/gtest.gyp:gtest', - 'mojo_system_impl', - ], - 'sources': [ - 'src/mojo/edk/test/multiprocess_test_helper.cc', - 'src/mojo/edk/test/multiprocess_test_helper.h', - 'src/mojo/edk/test/scoped_ipc_support.cc', - 'src/mojo/edk/test/scoped_ipc_support.h', - 'src/mojo/edk/test/test_utils.h', - 'src/mojo/edk/test/test_utils_posix.cc', - 'src/mojo/edk/test/test_utils_win.cc', - ], - 'conditions': [ - ['OS=="ios"', { - 'sources!': [ - 'src/mojo/edk/test/multiprocess_test_helper.cc', - ], - }], - ], - }, - { - # GN version: //mojo/edk/test:run_all_unittests - 'target_name': 'mojo_run_all_unittests', - 'type': 'static_library', - 'dependencies': [ - '../../base/base.gyp:base', - '../../base/base.gyp:test_support_base', - '../../testing/gtest.gyp:gtest', - 'mojo_system_impl', - 'mojo_public.gyp:mojo_public_test_support', - 'mojo_test_support_impl', - ], - 'sources': [ - 'src/mojo/edk/test/run_all_unittests.cc', - ], - }, - { - # GN version: //mojo/edk/test:run_all_perftests - 'target_name': 'mojo_run_all_perftests', - 'type': 'static_library', - 'dependencies': [ - '../../base/base.gyp:test_support_base', - 'mojo_edk.gyp:mojo_system_impl', - 'mojo_public.gyp:mojo_public_test_support', - 'mojo_test_support_impl', - ], - 'sources': [ - 'src/mojo/edk/test/run_all_perftests.cc', - ], - }, - ], - 'conditions': [ - ['OS=="win" and target_arch=="ia32"', { - 'targets': [ - { - 'target_name': 'mojo_system_impl_win64', - 'type': '<(component)', - 'dependencies': [ - '../../base/base.gyp:base_win64', - '../../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations_win64', - ], - 'includes': [ - 'mojo_edk_system_impl.gypi', - ], - 'configurations': { - 'Common_Base': { - 'msvs_target_platform': 'x64', - }, - }, - }, - ], - }], - ], -} diff --git a/third_party/mojo/mojo_edk_system_impl.gypi b/third_party/mojo/mojo_edk_system_impl.gypi deleted file mode 100644 index bdb629c..0000000 --- a/third_party/mojo/mojo_edk_system_impl.gypi +++ /dev/null @@ -1,155 +0,0 @@ -# Copyright (c) 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. - -# The dictionary here is defined for use by the "mojo_system_impl" and -# "mojo_system_impl_win64" targets in third_party/mojo/mojo_edk.gyp. It's defined in this -# .gypi file so the sections aren't duplicated. -{ - 'defines': [ - 'MOJO_SYSTEM_IMPL_IMPLEMENTATION', - 'MOJO_SYSTEM_IMPLEMENTATION', - 'MOJO_USE_SYSTEM_IMPL', - ], - 'sources': [ - 'src/mojo/edk/embedder/configuration.h', - 'src/mojo/edk/embedder/channel_info_forward.h', - 'src/mojo/edk/embedder/embedder.cc', - 'src/mojo/edk/embedder/embedder.h', - 'src/mojo/edk/embedder/embedder_internal.h', - 'src/mojo/edk/embedder/entrypoints.cc', - 'src/mojo/edk/embedder/platform_channel_pair.cc', - 'src/mojo/edk/embedder/platform_channel_pair.h', - 'src/mojo/edk/embedder/platform_channel_pair_posix.cc', - 'src/mojo/edk/embedder/platform_channel_pair_win.cc', - 'src/mojo/edk/embedder/platform_channel_utils_posix.cc', - 'src/mojo/edk/embedder/platform_channel_utils_posix.h', - 'src/mojo/edk/embedder/platform_handle.cc', - 'src/mojo/edk/embedder/platform_handle.h', - 'src/mojo/edk/embedder/platform_handle_utils.h', - 'src/mojo/edk/embedder/platform_handle_utils_posix.cc', - 'src/mojo/edk/embedder/platform_handle_utils_win.cc', - 'src/mojo/edk/embedder/platform_handle_vector.h', - 'src/mojo/edk/embedder/platform_shared_buffer.h', - 'src/mojo/edk/embedder/platform_support.h', - 'src/mojo/edk/embedder/scoped_platform_handle.h', - 'src/mojo/edk/embedder/simple_platform_shared_buffer.cc', - 'src/mojo/edk/embedder/simple_platform_shared_buffer.h', - 'src/mojo/edk/embedder/simple_platform_shared_buffer_android.cc', - 'src/mojo/edk/embedder/simple_platform_shared_buffer_posix.cc', - 'src/mojo/edk/embedder/simple_platform_shared_buffer_win.cc', - 'src/mojo/edk/embedder/simple_platform_support.cc', - 'src/mojo/edk/embedder/simple_platform_support.h', - 'src/mojo/edk/system/awakable.h', - 'src/mojo/edk/system/awakable_list.cc', - 'src/mojo/edk/system/awakable_list.h', - 'src/mojo/edk/system/async_waiter.cc', - 'src/mojo/edk/system/async_waiter.h', - 'src/mojo/edk/system/channel.cc', - 'src/mojo/edk/system/channel.h', - 'src/mojo/edk/system/channel_endpoint.cc', - 'src/mojo/edk/system/channel_endpoint.h', - 'src/mojo/edk/system/channel_endpoint_client.h', - 'src/mojo/edk/system/channel_endpoint_id.cc', - 'src/mojo/edk/system/channel_endpoint_id.h', - 'src/mojo/edk/system/channel_id.h', - 'src/mojo/edk/system/channel_manager.cc', - 'src/mojo/edk/system/channel_manager.h', - 'src/mojo/edk/system/configuration.cc', - 'src/mojo/edk/system/configuration.h', - 'src/mojo/edk/system/connection_identifier.h', - 'src/mojo/edk/system/connection_manager.cc', - 'src/mojo/edk/system/connection_manager.h', - 'src/mojo/edk/system/connection_manager_messages.h', - 'src/mojo/edk/system/core.cc', - 'src/mojo/edk/system/core.h', - 'src/mojo/edk/system/data_pipe.cc', - 'src/mojo/edk/system/data_pipe.h', - 'src/mojo/edk/system/data_pipe_consumer_dispatcher.cc', - 'src/mojo/edk/system/data_pipe_consumer_dispatcher.h', - 'src/mojo/edk/system/data_pipe_impl.cc', - 'src/mojo/edk/system/data_pipe_impl.h', - 'src/mojo/edk/system/data_pipe_producer_dispatcher.cc', - 'src/mojo/edk/system/data_pipe_producer_dispatcher.h', - 'src/mojo/edk/system/dispatcher.cc', - 'src/mojo/edk/system/dispatcher.h', - 'src/mojo/edk/system/endpoint_relayer.cc', - 'src/mojo/edk/system/endpoint_relayer.h', - 'src/mojo/edk/system/handle_signals_state.h', - 'src/mojo/edk/system/handle_table.cc', - 'src/mojo/edk/system/handle_table.h', - 'src/mojo/edk/system/incoming_endpoint.cc', - 'src/mojo/edk/system/incoming_endpoint.h', - 'src/mojo/edk/system/ipc_support.cc', - 'src/mojo/edk/system/ipc_support.h', - 'src/mojo/edk/system/local_data_pipe_impl.cc', - 'src/mojo/edk/system/local_data_pipe_impl.h', - 'src/mojo/edk/system/local_message_pipe_endpoint.cc', - 'src/mojo/edk/system/local_message_pipe_endpoint.h', - 'src/mojo/edk/system/mapping_table.cc', - 'src/mojo/edk/system/mapping_table.h', - 'src/mojo/edk/system/master_connection_manager.cc', - 'src/mojo/edk/system/master_connection_manager.h', - 'src/mojo/edk/system/memory.cc', - 'src/mojo/edk/system/memory.h', - 'src/mojo/edk/system/message_in_transit.cc', - 'src/mojo/edk/system/message_in_transit.h', - 'src/mojo/edk/system/message_in_transit_queue.cc', - 'src/mojo/edk/system/message_in_transit_queue.h', - 'src/mojo/edk/system/message_pipe.cc', - 'src/mojo/edk/system/message_pipe.h', - 'src/mojo/edk/system/message_pipe_dispatcher.cc', - 'src/mojo/edk/system/message_pipe_dispatcher.h', - 'src/mojo/edk/system/message_pipe_endpoint.cc', - 'src/mojo/edk/system/message_pipe_endpoint.h', - 'src/mojo/edk/system/mutex.cc', - 'src/mojo/edk/system/mutex.h', - 'src/mojo/edk/system/options_validation.h', - 'src/mojo/edk/system/platform_handle_dispatcher.cc', - 'src/mojo/edk/system/platform_handle_dispatcher.h', - 'src/mojo/edk/system/process_identifier.h', - 'src/mojo/edk/system/proxy_message_pipe_endpoint.cc', - 'src/mojo/edk/system/proxy_message_pipe_endpoint.h', - 'src/mojo/edk/system/remote_consumer_data_pipe_impl.cc', - 'src/mojo/edk/system/remote_consumer_data_pipe_impl.h', - 'src/mojo/edk/system/remote_data_pipe_ack.h', - 'src/mojo/edk/system/remote_producer_data_pipe_impl.cc', - 'src/mojo/edk/system/remote_producer_data_pipe_impl.h', - 'src/mojo/edk/system/raw_channel.cc', - 'src/mojo/edk/system/raw_channel.h', - 'src/mojo/edk/system/raw_channel_posix.cc', - 'src/mojo/edk/system/raw_channel_win.cc', - 'src/mojo/edk/system/shared_buffer_dispatcher.cc', - 'src/mojo/edk/system/shared_buffer_dispatcher.h', - 'src/mojo/edk/system/simple_dispatcher.cc', - 'src/mojo/edk/system/simple_dispatcher.h', - 'src/mojo/edk/system/slave_connection_manager.cc', - 'src/mojo/edk/system/slave_connection_manager.h', - 'src/mojo/edk/system/thread_annotations.h', - 'src/mojo/edk/system/transport_data.cc', - 'src/mojo/edk/system/transport_data.h', - 'src/mojo/edk/system/unique_identifier.cc', - 'src/mojo/edk/system/unique_identifier.h', - 'src/mojo/edk/system/wait_set_dispatcher.cc', - 'src/mojo/edk/system/wait_set_dispatcher.h', - 'src/mojo/edk/system/waiter.cc', - 'src/mojo/edk/system/waiter.h', - # Test-only code: - # TODO(vtl): It's a little unfortunate that these end up in the same - # component as non-test-only code. In the static build, this code - # should hopefully be dead-stripped. - 'src/mojo/edk/embedder/test_embedder.cc', - 'src/mojo/edk/embedder/test_embedder.h', - ], - 'all_dependent_settings': { - # Ensures that dependent projects import the core functions on Windows. - 'defines': ['MOJO_USE_SYSTEM_IMPL'], - }, - 'conditions': [ - ['OS=="android"', { - 'dependencies': [ - '<(DEPTH)/third_party/ashmem/ashmem.gyp:ashmem', - ], - }], - ], -} diff --git a/third_party/mojo/mojo_edk_tests.gyp b/third_party/mojo/mojo_edk_tests.gyp deleted file mode 100644 index 263e47d..0000000 --- a/third_party/mojo/mojo_edk_tests.gyp +++ /dev/null @@ -1,342 +0,0 @@ -# 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. - -{ - 'includes': [ - 'mojo_variables.gypi', - ], - 'targets': [ - { - 'target_name': 'mojo_edk_tests', - 'type': 'none', - 'dependencies': [ - # NOTE: If adding a new dependency here, please consider whether it - # should also be added to the list of Mojo-related dependencies of - # build/all.gyp:All on iOS, as All cannot depend on the mojo_base - # target on iOS due to the presence of the js targets, which cause v8 - # to be built. - 'mojo_message_pipe_perftests', - 'mojo_public_bindings_perftests', - 'mojo_public_bindings_unittests', - 'mojo_public_environment_unittests', - 'mojo_public_system_perftests', - 'mojo_public_system_unittests', - 'mojo_public_utility_unittests', - 'mojo_system_unittests', - ], - }, - # TODO(vtl): Reorganize the mojo_public_*_unittests. - { - # GN version: //mojo/edk/test:mojo_public_bindings_unittests - 'target_name': 'mojo_public_bindings_unittests', - 'type': 'executable', - 'dependencies': [ - '../../mojo/mojo_base.gyp:mojo_environment_chromium', - '../../mojo/mojo_base.gyp:mojo_message_pump_lib', - '../../testing/gtest.gyp:gtest', - 'mojo_edk.gyp:mojo_run_all_unittests', - 'mojo_public.gyp:mojo_cpp_bindings', - 'mojo_public.gyp:mojo_public_bindings_test_utils', - 'mojo_public.gyp:mojo_public_test_associated_interfaces', - 'mojo_public.gyp:mojo_public_test_interfaces', - 'mojo_public.gyp:mojo_public_test_interfaces_blink', - 'mojo_public.gyp:mojo_public_test_interfaces_chromium', - 'mojo_public.gyp:mojo_public_test_utils', - 'mojo_public.gyp:mojo_utility', - ], - 'sources': [ - '../../mojo/public/cpp/bindings/tests/array_unittest.cc', - '../../mojo/public/cpp/bindings/tests/associated_interface_unittest.cc', - '../../mojo/public/cpp/bindings/tests/binding_callback_unittest.cc', - '../../mojo/public/cpp/bindings/tests/binding_unittest.cc', - '../../mojo/public/cpp/bindings/tests/bounds_checker_unittest.cc', - '../../mojo/public/cpp/bindings/tests/buffer_unittest.cc', - '../../mojo/public/cpp/bindings/tests/callback_unittest.cc', - '../../mojo/public/cpp/bindings/tests/connector_unittest.cc', - '../../mojo/public/cpp/bindings/tests/constant_unittest.cc', - '../../mojo/public/cpp/bindings/tests/container_test_util.cc', - '../../mojo/public/cpp/bindings/tests/equals_unittest.cc', - '../../mojo/public/cpp/bindings/tests/handle_passing_unittest.cc', - '../../mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc', - '../../mojo/public/cpp/bindings/tests/map_unittest.cc', - '../../mojo/public/cpp/bindings/tests/message_queue.cc', - '../../mojo/public/cpp/bindings/tests/message_queue.h', - '../../mojo/public/cpp/bindings/tests/multiplex_router_unittest.cc', - '../../mojo/public/cpp/bindings/tests/pickle_unittest.cc', - '../../mojo/public/cpp/bindings/tests/pickled_struct_blink.cc', - '../../mojo/public/cpp/bindings/tests/pickled_struct_blink.h', - '../../mojo/public/cpp/bindings/tests/pickled_struct_chromium.cc', - '../../mojo/public/cpp/bindings/tests/pickled_struct_chromium.h', - '../../mojo/public/cpp/bindings/tests/rect_blink.h', - '../../mojo/public/cpp/bindings/tests/rect_chromium.h', - '../../mojo/public/cpp/bindings/tests/request_response_unittest.cc', - '../../mojo/public/cpp/bindings/tests/router_test_util.cc', - '../../mojo/public/cpp/bindings/tests/router_test_util.h', - '../../mojo/public/cpp/bindings/tests/router_unittest.cc', - '../../mojo/public/cpp/bindings/tests/sample_service_unittest.cc', - '../../mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc', - '../../mojo/public/cpp/bindings/tests/string_unittest.cc', - '../../mojo/public/cpp/bindings/tests/struct_traits_unittest.cc', - '../../mojo/public/cpp/bindings/tests/struct_unittest.cc', - '../../mojo/public/cpp/bindings/tests/type_conversion_unittest.cc', - '../../mojo/public/cpp/bindings/tests/union_unittest.cc', - '../../mojo/public/cpp/bindings/tests/validation_unittest.cc', - ], - }, - { - # GN version: //mojo/edk/test:mojo_public_bindings_perftests - 'target_name': 'mojo_public_bindings_perftests', - 'type': 'executable', - 'dependencies': [ - '../../mojo/mojo_base.gyp:mojo_common_lib', - '../../testing/gtest.gyp:gtest', - 'mojo_edk.gyp:mojo_run_all_unittests', - 'mojo_public.gyp:mojo_cpp_bindings', - 'mojo_public.gyp:mojo_environment_standalone', - 'mojo_public.gyp:mojo_public_bindings_test_utils', - 'mojo_public.gyp:mojo_public_test_interfaces', - 'mojo_public.gyp:mojo_public_test_utils', - 'mojo_public.gyp:mojo_utility', - ], - 'sources': [ - '../../mojo/public/cpp/bindings/tests/bindings_perftest.cc', - ], - }, - { - # GN version: //mojo/edk/test:mojo_public_environment_unittests - 'target_name': 'mojo_public_environment_unittests', - 'type': 'executable', - 'dependencies': [ - '../../testing/gtest.gyp:gtest', - 'mojo_edk.gyp:mojo_run_all_unittests', - 'mojo_public.gyp:mojo_cpp_bindings', - 'mojo_public.gyp:mojo_environment_standalone', - 'mojo_public.gyp:mojo_public_test_utils', - 'mojo_public.gyp:mojo_utility', - ], - 'include_dirs': [ '../..' ], - 'sources': [ - '../../mojo/public/cpp/environment/tests/async_wait_unittest.cc', - '../../mojo/public/cpp/environment/tests/async_waiter_unittest.cc', - '../../mojo/public/cpp/environment/tests/logger_unittest.cc', - '../../mojo/public/cpp/environment/tests/logging_unittest.cc', - ], - }, - { - # GN version: //mojo/public/cpp/system/tests:mojo_public_system_unittests - # and //mojo/public/c/system/tests - 'target_name': 'mojo_public_system_unittests', - 'type': 'executable', - 'dependencies': [ - '../../testing/gtest.gyp:gtest', - 'mojo_edk.gyp:mojo_run_all_unittests', - 'mojo_public.gyp:mojo_public_test_utils', - ], - 'include_dirs': [ '../..' ], - 'sources': [ - '<@(mojo_public_system_unittest_sources)', - ], - }, - { - # GN version: //mojo/public/cpp/application/tests:mojo_public_utility_unittests - 'target_name': 'mojo_public_utility_unittests', - 'type': 'executable', - 'dependencies': [ - '../../testing/gtest.gyp:gtest', - 'mojo_edk.gyp:mojo_run_all_unittests', - 'mojo_public.gyp:mojo_cpp_bindings', - 'mojo_public.gyp:mojo_public_test_utils', - 'mojo_public.gyp:mojo_utility', - ], - 'include_dirs': [ '../..' ], - 'sources': [ - '../../mojo/public/cpp/utility/tests/mutex_unittest.cc', - '../../mojo/public/cpp/utility/tests/run_loop_unittest.cc', - '../../mojo/public/cpp/utility/tests/thread_unittest.cc', - ], - 'conditions': [ - # See crbug.com/342893: - ['OS=="win"', { - 'sources!': [ - '../../mojo/public/cpp/utility/tests/mutex_unittest.cc', - '../../mojo/public/cpp/utility/tests/thread_unittest.cc', - ], - }], - ], - }, - { - # GN version: //mojo/edk/test:mojo_public_system_perftests - 'target_name': 'mojo_public_system_perftests', - 'type': 'executable', - 'dependencies': [ - '../../base/base.gyp:base', - '../../testing/gtest.gyp:gtest', - 'mojo_edk.gyp:mojo_run_all_perftests', - 'mojo_public.gyp:mojo_public_test_utils', - 'mojo_public.gyp:mojo_utility', - ], - 'sources': [ - '../../mojo/public/c/system/tests/core_perftest.cc', - ], - }, - { - # GN version: //mojo/edk/system:mojo_system_unittests - 'target_name': 'mojo_system_unittests', - 'type': 'executable', - 'dependencies': [ - '../../base/base.gyp:base', - '../../testing/gtest.gyp:gtest', - 'mojo_edk.gyp:mojo_common_test_support', - 'mojo_edk.gyp:mojo_system_impl', - ], - 'sources': [ - 'src/mojo/edk/embedder/embedder_unittest.cc', - 'src/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc', - 'src/mojo/edk/embedder/simple_platform_shared_buffer_unittest.cc', - 'src/mojo/edk/system/awakable_list_unittest.cc', - 'src/mojo/edk/system/channel_endpoint_id_unittest.cc', - 'src/mojo/edk/system/channel_endpoint_unittest.cc', - 'src/mojo/edk/system/channel_manager_unittest.cc', - 'src/mojo/edk/system/channel_test_base.cc', - 'src/mojo/edk/system/channel_test_base.h', - 'src/mojo/edk/system/channel_unittest.cc', - 'src/mojo/edk/system/core_test_base.cc', - 'src/mojo/edk/system/core_test_base.h', - 'src/mojo/edk/system/core_unittest.cc', - 'src/mojo/edk/system/data_pipe_impl_unittest.cc', - 'src/mojo/edk/system/data_pipe_unittest.cc', - 'src/mojo/edk/system/dispatcher_unittest.cc', - 'src/mojo/edk/system/endpoint_relayer_unittest.cc', - 'src/mojo/edk/system/ipc_support_unittest.cc', - 'src/mojo/edk/system/memory_unittest.cc', - 'src/mojo/edk/system/message_in_transit_queue_unittest.cc', - 'src/mojo/edk/system/message_in_transit_test_utils.cc', - 'src/mojo/edk/system/message_in_transit_test_utils.h', - 'src/mojo/edk/system/message_pipe_dispatcher_unittest.cc', - 'src/mojo/edk/system/message_pipe_test_utils.cc', - 'src/mojo/edk/system/message_pipe_test_utils.h', - 'src/mojo/edk/system/message_pipe_unittest.cc', - 'src/mojo/edk/system/multiprocess_message_pipe_unittest.cc', - 'src/mojo/edk/system/mutex_unittest.cc', - 'src/mojo/edk/system/options_validation_unittest.cc', - 'src/mojo/edk/system/platform_handle_dispatcher_unittest.cc', - 'src/mojo/edk/system/raw_channel_unittest.cc', - 'src/mojo/edk/system/remote_data_pipe_impl_unittest.cc', - 'src/mojo/edk/system/remote_message_pipe_unittest.cc', - 'src/mojo/edk/system/run_all_unittests.cc', - 'src/mojo/edk/system/shared_buffer_dispatcher_unittest.cc', - 'src/mojo/edk/system/simple_dispatcher_unittest.cc', - 'src/mojo/edk/system/test_channel_endpoint_client.cc', - 'src/mojo/edk/system/test_channel_endpoint_client.h', - 'src/mojo/edk/system/test_utils.cc', - 'src/mojo/edk/system/test_utils.h', - 'src/mojo/edk/system/thread_annotations_unittest.cc', - 'src/mojo/edk/system/unique_identifier_unittest.cc', - 'src/mojo/edk/system/wait_set_dispatcher_unittest.cc', - 'src/mojo/edk/system/waiter_test_utils.cc', - 'src/mojo/edk/system/waiter_test_utils.h', - 'src/mojo/edk/system/waiter_unittest.cc', - 'src/mojo/edk/test/multiprocess_test_helper_unittest.cc', - ], - 'conditions': [ - ['OS=="ios"', { - 'sources!': [ - 'src/mojo/edk/embedder/embedder_unittest.cc', - 'src/mojo/edk/system/ipc_support_unittest.cc', - 'src/mojo/edk/system/multiprocess_message_pipe_unittest.cc', - 'src/mojo/edk/test/multiprocess_test_helper_unittest.cc', - ], - }], - ], - }, - { - # GN version: //mojo/edk/system:mojo_message_pipe_perftests - 'target_name': 'mojo_message_pipe_perftests', - 'type': 'executable', - 'dependencies': [ - '../../base/base.gyp:base', - '../../base/base.gyp:test_support_base', - '../../base/base.gyp:test_support_perf', - '../../testing/gtest.gyp:gtest', - 'mojo_edk.gyp:mojo_common_test_support', - 'mojo_edk.gyp:mojo_system_impl', - ], - 'sources': [ - 'src/mojo/edk/system/message_pipe_perftest.cc', - 'src/mojo/edk/system/message_pipe_test_utils.cc', - 'src/mojo/edk/system/message_pipe_test_utils.h', - 'src/mojo/edk/system/test_utils.cc', - 'src/mojo/edk/system/test_utils.h', - ], - }, - { - 'target_name': 'mojo_js_to_cpp_bindings', - 'type': 'none', - 'variables': { - 'mojom_files': [ - 'src/mojo/edk/js/tests/js_to_cpp.mojom', - ], - }, - 'includes': [ 'mojom_bindings_generator_explicit.gypi' ], - }, - ], - 'conditions': [ - ['test_isolation_mode != "noop"', { - 'targets': [ - { - 'target_name': 'mojo_public_bindings_unittests_run', - 'type': 'none', - 'dependencies': [ - 'mojo_public_bindings_unittests', - ], - 'includes': [ - '../../build/isolate.gypi', - ], - 'sources': [ - 'mojo_public_bindings_unittests.isolate', - ], - }, - { - 'target_name': 'mojo_public_environment_unittests_run', - 'type': 'none', - 'dependencies': [ - 'mojo_public_environment_unittests', - ], - 'includes': [ - '../../build/isolate.gypi', - ], - 'sources': [ - 'mojo_public_environment_unittests.isolate', - ], - }, - { - 'target_name': 'mojo_public_system_unittests_run', - 'type': 'none', - 'dependencies': [ - 'mojo_public_system_unittests', - ], - 'includes': [ - '../../build/isolate.gypi', - ], - 'sources': [ - 'mojo_public_system_unittests.isolate', - ], - }, - { - 'target_name': 'mojo_public_utility_unittests_run', - 'type': 'none', - 'dependencies': [ - 'mojo_public_utility_unittests', - ], - 'includes': [ - '../../build/isolate.gypi', - ], - 'sources': [ - 'mojo_public_utility_unittests.isolate', - ], - }, - ], - }], - ], -} diff --git a/third_party/mojo/mojo_public.gyp b/third_party/mojo/mojo_public.gyp deleted file mode 100644 index d9d77ea..0000000 --- a/third_party/mojo/mojo_public.gyp +++ /dev/null @@ -1,507 +0,0 @@ -# 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. - -{ - 'includes': [ - 'mojo_variables.gypi', - ], - 'target_defaults' : { - 'include_dirs': [ - '../..', - ], - }, - 'targets': [ - { - 'target_name': 'mojo_public', - 'type': 'none', - 'dependencies': [ - 'mojo_js_bindings', - 'mojo_public_test_interfaces', - 'mojo_public_test_utils', - 'mojo_system', - 'mojo_utility', - ], - }, - { - # Targets that (a) need to obtain the settings that mojo_system passes on - # to its direct dependents but (b) are not themselves in a position to - # hardcode a dependency to mojo_system vs. mojo_system_impl (e.g., - # because they are components) should depend on this target. - 'target_name': 'mojo_system_placeholder', - 'type': 'none', - }, - { - 'target_name': 'mojo_system', - 'type': 'static_library', - 'defines': [ - 'MOJO_SYSTEM_IMPLEMENTATION', - ], - 'all_dependent_settings': { - 'conditions': [ - # We need to be able to call the MojoSetSystemThunks() function in - # system_thunks.cc - ['OS=="android"', { - 'ldflags!': [ - '-Wl,--exclude-libs=ALL', - ], - }], - ], - }, - 'sources': [ - '../../mojo/public/platform/native/system_thunks.cc', - '../../mojo/public/platform/native/system_thunks.h', - ], - 'dependencies': [ - 'mojo_system_headers', - ], - }, - { - # GN version: //mojo/public/c/system - 'target_name': 'mojo_system_headers', - 'type': 'none', - 'sources': [ - '../../mojo/public/c/system/buffer.h', - '../../mojo/public/c/system/core.h', - '../../mojo/public/c/system/data_pipe.h', - '../../mojo/public/c/system/functions.h', - '../../mojo/public/c/system/macros.h', - '../../mojo/public/c/system/message_pipe.h', - '../../mojo/public/c/system/system_export.h', - '../../mojo/public/c/system/types.h', - '../../mojo/public/c/system/wait_set.h', - ], - }, - { - # GN version: //mojo/public/cpp/system - 'target_name': 'mojo_system_cpp_headers', - 'type': 'none', - 'sources': [ - '../../mojo/public/cpp/system/buffer.h', - '../../mojo/public/cpp/system/core.h', - '../../mojo/public/cpp/system/data_pipe.h', - '../../mojo/public/cpp/system/functions.h', - '../../mojo/public/cpp/system/handle.h', - '../../mojo/public/cpp/system/macros.h', - '../../mojo/public/cpp/system/message_pipe.h', - ], - 'dependencies': [ - 'mojo_system_headers', - ], - }, - { - # GN version: //mojo/public/cpp/bindings - 'target_name': 'mojo_cpp_bindings', - 'type': 'static_library', - 'include_dirs': [ - '../..' - ], - 'sources': [ - '../../mojo/public/cpp/bindings/array.h', - '../../mojo/public/cpp/bindings/associated_binding.h', - '../../mojo/public/cpp/bindings/associated_group.h', - '../../mojo/public/cpp/bindings/associated_interface_ptr.h', - '../../mojo/public/cpp/bindings/associated_interface_ptr_info.h', - '../../mojo/public/cpp/bindings/associated_interface_request.h', - '../../mojo/public/cpp/bindings/binding.h', - '../../mojo/public/cpp/bindings/callback.h', - '../../mojo/public/cpp/bindings/interface_ptr.h', - '../../mojo/public/cpp/bindings/interface_request.h', - '../../mojo/public/cpp/bindings/lib/array_internal.cc', - '../../mojo/public/cpp/bindings/lib/array_internal.h', - '../../mojo/public/cpp/bindings/lib/array_serialization.h', - '../../mojo/public/cpp/bindings/lib/associated_group.cc', - '../../mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h', - '../../mojo/public/cpp/bindings/lib/binding_state.h', - '../../mojo/public/cpp/bindings/lib/bindings_internal.h', - '../../mojo/public/cpp/bindings/lib/bindings_serialization.cc', - '../../mojo/public/cpp/bindings/lib/bindings_serialization.h', - '../../mojo/public/cpp/bindings/lib/bounds_checker.cc', - '../../mojo/public/cpp/bindings/lib/bounds_checker.h', - '../../mojo/public/cpp/bindings/lib/buffer.h', - '../../mojo/public/cpp/bindings/lib/callback_internal.h', - '../../mojo/public/cpp/bindings/lib/connector.cc', - '../../mojo/public/cpp/bindings/lib/connector.h', - '../../mojo/public/cpp/bindings/lib/control_message_handler.cc', - '../../mojo/public/cpp/bindings/lib/control_message_handler.h', - '../../mojo/public/cpp/bindings/lib/control_message_proxy.cc', - '../../mojo/public/cpp/bindings/lib/control_message_proxy.h', - '../../mojo/public/cpp/bindings/lib/filter_chain.cc', - '../../mojo/public/cpp/bindings/lib/filter_chain.h', - '../../mojo/public/cpp/bindings/lib/fixed_buffer.cc', - '../../mojo/public/cpp/bindings/lib/interface_id.h', - '../../mojo/public/cpp/bindings/lib/fixed_buffer.h', - '../../mojo/public/cpp/bindings/lib/interface_endpoint_client.cc', - '../../mojo/public/cpp/bindings/lib/interface_endpoint_client.h', - '../../mojo/public/cpp/bindings/lib/interface_ptr_state.h', - '../../mojo/public/cpp/bindings/lib/map_data_internal.h', - '../../mojo/public/cpp/bindings/lib/map_internal.h', - '../../mojo/public/cpp/bindings/lib/map_serialization.h', - '../../mojo/public/cpp/bindings/lib/message.cc', - '../../mojo/public/cpp/bindings/lib/message_builder.cc', - '../../mojo/public/cpp/bindings/lib/message_builder.h', - '../../mojo/public/cpp/bindings/lib/message_filter.cc', - '../../mojo/public/cpp/bindings/lib/message_header_validator.cc', - '../../mojo/public/cpp/bindings/lib/message_header_validator.h', - '../../mojo/public/cpp/bindings/lib/message_internal.h', - '../../mojo/public/cpp/bindings/lib/multiplex_router.cc', - '../../mojo/public/cpp/bindings/lib/multiplex_router.h', - '../../mojo/public/cpp/bindings/lib/no_interface.cc', - '../../mojo/public/cpp/bindings/lib/pickle_buffer.cc', - '../../mojo/public/cpp/bindings/lib/pickle_buffer.h', - '../../mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc', - '../../mojo/public/cpp/bindings/lib/pipe_control_message_handler.h', - '../../mojo/public/cpp/bindings/lib/pipe_control_message_handler_delegate.h', - '../../mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc', - '../../mojo/public/cpp/bindings/lib/pipe_control_message_proxy.h', - '../../mojo/public/cpp/bindings/lib/router.cc', - '../../mojo/public/cpp/bindings/lib/router.h', - '../../mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc', - '../../mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h', - '../../mojo/public/cpp/bindings/lib/shared_data.h', - '../../mojo/public/cpp/bindings/lib/shared_ptr.h', - '../../mojo/public/cpp/bindings/lib/string_serialization.cc', - '../../mojo/public/cpp/bindings/lib/string_serialization.h', - '../../mojo/public/cpp/bindings/lib/validate_params.h', - '../../mojo/public/cpp/bindings/lib/validation_errors.cc', - '../../mojo/public/cpp/bindings/lib/validation_errors.h', - '../../mojo/public/cpp/bindings/lib/validation_util.cc', - '../../mojo/public/cpp/bindings/lib/validation_util.h', - '../../mojo/public/cpp/bindings/lib/value_traits.h', - '../../mojo/public/cpp/bindings/message.h', - '../../mojo/public/cpp/bindings/message_filter.h', - '../../mojo/public/cpp/bindings/no_interface.h', - '../../mojo/public/cpp/bindings/string.h', - '../../mojo/public/cpp/bindings/strong_binding.h', - '../../mojo/public/cpp/bindings/type_converter.h', - # This comes from the mojo_interface_bindings_cpp_sources dependency. - '>@(mojom_generated_sources)', - ], - 'dependencies': [ - '../../base/base.gyp:base', - 'mojo_interface_bindings_cpp_sources', - ], - }, - { - # GN version: //mojo/public/js - 'target_name': 'mojo_js_bindings', - 'type': 'static_library', - 'include_dirs': [ - '../..' - ], - 'sources': [ - '../../mojo/public/js/constants.cc', - '../../mojo/public/js/constants.h', - ], - }, - { - # GN version: //mojo/public/cpp/environment:standalone - 'target_name': 'mojo_environment_standalone', - 'type': 'static_library', - 'sources': [ - '../../mojo/public/c/environment/async_waiter.h', - '../../mojo/public/c/environment/logger.h', - '../../mojo/public/cpp/environment/async_waiter.h', - '../../mojo/public/cpp/environment/environment.h', - '../../mojo/public/cpp/environment/lib/async_waiter.cc', - '../../mojo/public/cpp/environment/lib/default_async_waiter.cc', - '../../mojo/public/cpp/environment/lib/default_async_waiter.h', - '../../mojo/public/cpp/environment/lib/default_logger.cc', - '../../mojo/public/cpp/environment/lib/default_logger.h', - '../../mojo/public/cpp/environment/lib/default_task_tracker.cc', - '../../mojo/public/cpp/environment/lib/default_task_tracker.h', - '../../mojo/public/cpp/environment/lib/environment.cc', - '../../mojo/public/cpp/environment/lib/logging.cc', - '../../mojo/public/cpp/environment/lib/scoped_task_tracking.cc', - '../../mojo/public/cpp/environment/lib/scoped_task_tracking.h', - '../../mojo/public/cpp/environment/logging.h', - '../../mojo/public/cpp/environment/task_tracker.h', - ], - 'include_dirs': [ - '../..', - ], - }, - { - # GN version: //mojo/public/cpp/utility - 'target_name': 'mojo_utility', - 'type': 'static_library', - 'sources': [ - '../../mojo/public/cpp/utility/lib/mutex.cc', - '../../mojo/public/cpp/utility/lib/run_loop.cc', - '../../mojo/public/cpp/utility/lib/thread.cc', - '../../mojo/public/cpp/utility/lib/thread_local.h', - '../../mojo/public/cpp/utility/lib/thread_local_posix.cc', - '../../mojo/public/cpp/utility/lib/thread_local_win.cc', - '../../mojo/public/cpp/utility/mutex.h', - '../../mojo/public/cpp/utility/run_loop.h', - '../../mojo/public/cpp/utility/run_loop_handler.h', - '../../mojo/public/cpp/utility/thread.h', - ], - 'conditions': [ - # See crbug.com/342893: - ['OS=="win"', { - 'sources!': [ - '../../mojo/public/cpp/utility/lib/mutex.cc', - '../../mojo/public/cpp/utility/lib/thread.cc', - '../../mojo/public/cpp/utility/mutex.h', - '../../mojo/public/cpp/utility/thread.h', - ], - }], - ], - 'include_dirs': [ - '../..', - ], - }, - { - 'target_name': 'mojo_interface_bindings_mojom', - 'type': 'none', - 'variables': { - 'require_interface_bindings': 0, - 'mojom_files': [ - '../../mojo/public/interfaces/bindings/interface_control_messages.mojom', - '../../mojo/public/interfaces/bindings/pipe_control_messages.mojom', - ], - }, - 'includes': [ 'mojom_bindings_generator_explicit.gypi' ], - }, - { - 'target_name': 'mojo_interface_bindings_cpp_sources', - 'type': 'none', - 'dependencies': [ - 'mojo_interface_bindings_mojom', - ], - }, - { - # This target can be used to introduce a dependency on interface bindings - # generation without introducing any side-effects in the dependent - # target's configuration. - 'target_name': 'mojo_interface_bindings_generation', - 'type': 'none', - 'dependencies': [ - 'mojo_interface_bindings_cpp_sources', - ], - }, - { - # GN version: //mojo/public/c/test_support - 'target_name': 'mojo_public_test_support', - 'defines': [ - 'MOJO_TEST_SUPPORT_IMPLEMENTATION', - ], - 'include_dirs': [ - '../..', - ], - 'direct_dependent_settings': { - 'include_dirs': [ - '../..', - ], - }, - 'sources': [ - '../../mojo/public/c/test_support/test_support.h', - '../../mojo/public/c/test_support/test_support_export.h', - # TODO(vtl): Convert this to thunks http://crbug.com/386799 - '../../mojo/public/tests/test_support_private.cc', - '../../mojo/public/tests/test_support_private.h', - ], - 'conditions': [ - ['OS=="ios"', { - 'type': 'static_library', - }, { - 'type': 'shared_library', - }], - ['OS=="mac"', { - 'xcode_settings': { - # Make it a run-path dependent library. - 'DYLIB_INSTALL_NAME_BASE': '@loader_path', - }, - }], - ], - }, - { - # GN version: //mojo/public/cpp/test_support:test_utils - 'target_name': 'mojo_public_test_utils', - 'type': 'static_library', - 'dependencies': [ - '../../base/base.gyp:base', - '../../testing/gtest.gyp:gtest', - 'mojo_public_test_support', - ], - 'sources': [ - '../../mojo/public/cpp/test_support/lib/test_support.cc', - '../../mojo/public/cpp/test_support/lib/test_utils.cc', - '../../mojo/public/cpp/test_support/test_utils.h', - ], - }, - { - # GN version: //mojo/public/cpp/bindings/tests:mojo_public_bindings_test_utils - 'target_name': 'mojo_public_bindings_test_utils', - 'type': 'static_library', - 'dependencies': [ - '../../base/base.gyp:base', - ], - 'sources': [ - '../../mojo/public/cpp/bindings/tests/validation_test_input_parser.cc', - '../../mojo/public/cpp/bindings/tests/validation_test_input_parser.h', - ], - }, - { - 'target_name': 'mojo_public_test_interfaces_mojom', - 'type': 'none', - 'variables': { - 'mojom_files': [ - '../../mojo/public/interfaces/bindings/tests/math_calculator.mojom', - '../../mojo/public/interfaces/bindings/tests/no_module.mojom', - '../../mojo/public/interfaces/bindings/tests/ping_service.mojom', - '../../mojo/public/interfaces/bindings/tests/rect.mojom', - '../../mojo/public/interfaces/bindings/tests/regression_tests.mojom', - '../../mojo/public/interfaces/bindings/tests/sample_factory.mojom', - '../../mojo/public/interfaces/bindings/tests/sample_import.mojom', - '../../mojo/public/interfaces/bindings/tests/sample_import2.mojom', - '../../mojo/public/interfaces/bindings/tests/sample_interfaces.mojom', - '../../mojo/public/interfaces/bindings/tests/sample_service.mojom', - '../../mojo/public/interfaces/bindings/tests/scoping.mojom', - '../../mojo/public/interfaces/bindings/tests/serialization_test_structs.mojom', - '../../mojo/public/interfaces/bindings/tests/test_constants.mojom', - '../../mojo/public/interfaces/bindings/tests/test_native_types.mojom', - '../../mojo/public/interfaces/bindings/tests/test_structs.mojom', - '../../mojo/public/interfaces/bindings/tests/test_unions.mojom', - '../../mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom', - ], - }, - 'includes': [ 'mojom_bindings_generator_explicit.gypi' ], - }, - { - 'target_name': 'mojo_public_test_interfaces_mojom_blink', - 'type': 'none', - 'variables': { - 'mojom_variant': 'blink', - 'mojom_extra_generator_args': [ - '--typemap', '<(DEPTH)/mojo/public/interfaces/bindings/tests/blink_test.typemap', - ], - 'mojom_files': [ - '../../mojo/public/interfaces/bindings/tests/test_native_types.mojom', - ], - }, - 'includes': [ 'mojom_bindings_generator_explicit.gypi' ], - 'dependencies': [ - 'mojo_public_test_interfaces_mojom', - ], - }, - { - 'target_name': 'mojo_public_test_interfaces_mojom_chromium', - 'type': 'none', - 'variables': { - 'mojom_variant': 'chromium', - 'mojom_extra_generator_args': [ - '--typemap', '<(DEPTH)/mojo/public/interfaces/bindings/tests/chromium_test.typemap', - ], - 'mojom_files': [ - '../../mojo/public/interfaces/bindings/tests/test_native_types.mojom', - ], - }, - 'includes': [ 'mojom_bindings_generator_explicit.gypi' ], - 'dependencies': [ - 'mojo_public_test_interfaces_mojom', - ], - }, - { - # GN version: //mojo/public/interfaces/bindings/tests:test_interfaces - 'target_name': 'mojo_public_test_interfaces', - 'type': 'static_library', - 'export_dependent_settings': [ - 'mojo_cpp_bindings', - ], - 'dependencies': [ - 'mojo_public_test_interfaces_mojom', - 'mojo_cpp_bindings', - ], - }, - { - # GN version: //mojo/public/interfaces/bindings/tests:test_interfaces_blink - 'target_name': 'mojo_public_test_interfaces_blink', - 'type': 'static_library', - 'export_dependent_settings': [ - 'mojo_cpp_bindings', - ], - 'dependencies': [ - 'mojo_public_test_interfaces_mojom_blink', - 'mojo_cpp_bindings', - ], - }, - { - # GN version: //mojo/public/interfaces/bindings/tests:test_interfaces_chromium - 'target_name': 'mojo_public_test_interfaces_chromium', - 'type': 'static_library', - 'export_dependent_settings': [ - 'mojo_cpp_bindings', - ], - 'dependencies': [ - 'mojo_public_test_interfaces_mojom_chromium', - 'mojo_cpp_bindings', - ], - }, - { - 'target_name': 'mojo_public_test_associated_interfaces_mojom', - 'type': 'none', - 'variables': { - # These files are not included in the mojo_public_test_interfaces_mojom - # target because associated interfaces are not supported by all bindings - # languages yet. - 'mojom_files': [ - '../../mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom', - '../../mojo/public/interfaces/bindings/tests/validation_test_associated_interfaces.mojom', - ], - }, - 'includes': [ 'mojom_bindings_generator_explicit.gypi' ], - }, - { - # GN version: //mojo/public/interfaces/bindings/tests:test_associated_interfaces - 'target_name': 'mojo_public_test_associated_interfaces', - 'type': 'static_library', - 'export_dependent_settings': [ - 'mojo_cpp_bindings', - ], - 'dependencies': [ - 'mojo_public_test_associated_interfaces_mojom', - 'mojo_cpp_bindings', - ], - }, - ], - 'conditions': [ - ['OS == "android"', { - 'targets': [ - { - # GN version: //mojo/public/java:system - 'target_name': 'mojo_public_java', - 'type': 'none', - 'variables': { - 'chromium_code': 0, - 'java_in_dir': '../../mojo/public/java/system', - }, - 'includes': [ '../../build/java.gypi' ], - }, - { - 'target_name': 'mojo_interface_bindings_java_sources', - 'type': 'none', - 'dependencies': [ - 'mojo_interface_bindings_mojom', - ], - }, - { - # GN version: //mojo/public/java:bindings - 'target_name': 'mojo_bindings_java', - 'type': 'none', - 'variables': { - 'chromium_code': 0, - 'java_in_dir': '../../mojo/public/java/bindings', - }, - 'dependencies': [ - 'mojo_interface_bindings_java_sources', - 'mojo_public_java', - '<(DEPTH)/base/base.gyp:base_java', - ], - 'includes': [ '../../build/java.gypi' ], - }, - ], - }], - ], -} diff --git a/third_party/mojo/src/mojo/edk/DEPS b/third_party/mojo/src/mojo/edk/DEPS deleted file mode 100644 index 472ff42..0000000 --- a/third_party/mojo/src/mojo/edk/DEPS +++ /dev/null @@ -1,17 +0,0 @@ -include_rules = [ - # This code is checked into the chromium repo so it's fine to depend on this. - "+base", - "+crypto", - "+build", - "+gin", - "+testing", - "+v8", - - # internal includes. - "+mojo", - - # TODO(use_chrome_edk): temporary - "+../../../../../../mojo/edk/system/core.h", - "+../../../../../../mojo/edk/embedder/embedder_internal.h", - "+../../../../../../mojo/edk/embedder/simple_platform_support.h", -] diff --git a/third_party/mojo/src/mojo/edk/embedder/BUILD.gn b/third_party/mojo/src/mojo/edk/embedder/BUILD.gn deleted file mode 100644 index d12b953..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/BUILD.gn +++ /dev/null @@ -1,145 +0,0 @@ -# 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. - -source_set("headers") { - sources = [ - "channel_info_forward.h", - "configuration.h", - "embedder.h", - "embedder_internal.h", - ] -} - -source_set("embedder") { - # This isn't really a standalone target; it must be linked into the - # mojo_system_impl component. - visibility = [ - "//components/nacl", - "//third_party/mojo/src/mojo/edk/system", - ] - - sources = [ - "embedder.cc", - "entrypoints.cc", - - # Test-only code: - # TODO(vtl): It's a little unfortunate that these end up in the same - # component as non-test-only code. In the static build, this code should - # hopefully be dead-stripped. - "test_embedder.cc", - "test_embedder.h", - ] - - defines = [ - "MOJO_SYSTEM_IMPL_IMPLEMENTATION", - "MOJO_SYSTEM_IMPLEMENTATION", - ] - - configs += [ "//third_party/mojo/src/mojo/edk/system:system_config" ] - - public_deps = [ - ":delegates", - ":headers", - ":platform", - "//mojo/public/cpp/system", - ] - - deps = [ - "//base", - ] -} - -source_set("platform") { - # This isn't really a standalone target; it must be linked into the - # mojo_system_impl component. - visibility = [ - ":embedder", - "//third_party/mojo/src/mojo/edk/system", - ] - - sources = [ - "platform_channel_pair.cc", - "platform_channel_pair.h", - "platform_channel_pair_posix.cc", - "platform_channel_pair_win.cc", - "platform_channel_utils_posix.cc", - "platform_channel_utils_posix.h", - "platform_handle.cc", - "platform_handle.h", - "platform_handle_utils.h", - "platform_handle_utils_posix.cc", - "platform_handle_utils_win.cc", - "platform_handle_vector.h", - "platform_shared_buffer.h", - "platform_support.h", - "scoped_platform_handle.h", - "simple_platform_shared_buffer.cc", - "simple_platform_shared_buffer.h", - "simple_platform_shared_buffer_android.cc", - "simple_platform_shared_buffer_posix.cc", - "simple_platform_shared_buffer_win.cc", - "simple_platform_support.cc", - "simple_platform_support.h", - ] - - defines = [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ] - - configs += [ "//third_party/mojo/src/mojo/edk/system:system_config" ] - - public_deps = [ - "//mojo/public/cpp/system", - ] - - deps = [ - "//base", - ] - - if (is_android) { - deps += [ "//third_party/ashmem" ] - } -} - -source_set("delegates") { - # This isn't really a standalone target; it must be linked into the - # mojo_system_impl component. - visibility = [ - ":embedder", - "//third_party/mojo/src/mojo/edk/system", - ] - - sources = [ - "master_process_delegate.h", - "process_delegate.h", - "process_type.h", - "slave_info.h", - "slave_process_delegate.h", - ] - - defines = [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ] - - configs += [ "//third_party/mojo/src/mojo/edk/system:system_config" ] - - public_deps = [ - "//mojo/public/cpp/system", - ] -} - -source_set("embedder_unittests") { - testonly = true - - sources = [ - "embedder_unittest.cc", - "platform_channel_pair_posix_unittest.cc", - "simple_platform_shared_buffer_unittest.cc", - ] - - deps = [ - "//base", - "//base/test:test_support", - "//testing/gtest", - "//third_party/mojo/src/mojo/edk/system", - "//third_party/mojo/src/mojo/edk/system:test_utils", - "//third_party/mojo/src/mojo/edk/test:test_support", - ] -} diff --git a/third_party/mojo/src/mojo/edk/embedder/README.md b/third_party/mojo/src/mojo/edk/embedder/README.md deleted file mode 100644 index f976fcb..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/README.md +++ /dev/null @@ -1,13 +0,0 @@ -Mojo Embedder API -================= - -The Mojo Embedder API is an unstable, internal API to the Mojo system -implementation. It should be used by code running on top of the system-level -APIs to set up the Mojo environment (instead of directly instantiating things -from src/mojo/edk/system). - -Example uses: Mojo shell, to set up the Mojo environment for Mojo apps; Chromium -code, to set up the Mojo IPC system for use between processes. Note that most -code should use the Mojo Public API (under src/mojo/public) instead. The -Embedder API should only be used to initialize the environment, set up the -initial MessagePipe between two processes, etc. diff --git a/third_party/mojo/src/mojo/edk/embedder/channel_info_forward.h b/third_party/mojo/src/mojo/edk/embedder/channel_info_forward.h deleted file mode 100644 index f4b8f21..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/channel_info_forward.h +++ /dev/null @@ -1,22 +0,0 @@ -// 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. - -// This file simply (forward) declares |mojo::embedder::ChannelInfo|, which is -// meant to be opaque to users of the embedder API. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_CHANNEL_INFO_FORWARD_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_CHANNEL_INFO_FORWARD_H_ - -namespace mojo { -namespace embedder { - -// This is an opaque type. The embedder API uses (returns and takes as -// arguments) pointers to this type. (We don't simply use |void*|, so that -// custom deleters and such can be used without additional wrappers. -struct ChannelInfo; - -} // namespace embedder -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_CHANNEL_INFO_FORWARD_H_ diff --git a/third_party/mojo/src/mojo/edk/embedder/configuration.h b/third_party/mojo/src/mojo/edk/embedder/configuration.h deleted file mode 100644 index f02a13d..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/configuration.h +++ /dev/null @@ -1,68 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_CONFIGURATION_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_CONFIGURATION_H_ - -#include <stddef.h> - -namespace mojo { -namespace embedder { - -// A set of constants that the Mojo system internally uses. These values should -// be consistent across all processes on the same system. -// -// In general, there should be no need to change these values from their -// defaults. However, if you do change them, you must do so before -// initialization. -struct Configuration { - // Maximum number of open (Mojo) handles. The default is 1,000,000. - // - // TODO(vtl): This doesn't count "live" handles, some of which may live in - // messages. - size_t max_handle_table_size; - - // Maximum number of active memory mappings. The default is 1,000,000. - size_t max_mapping_table_sze; - - // Upper limit of |MojoWaitMany()|'s |num_handles|. The default is 1,000,000. - // Must be same as or smaller than |max_handle_table_size|. - size_t max_wait_many_num_handles; - - // Maximum data size of messages sent over message pipes, in bytes. The - // default is 4MB. - size_t max_message_num_bytes; - - // Maximum number of handles that can be attached to messages sent over - // message pipes. The default is 10,000. - size_t max_message_num_handles; - - // Maximum capacity of a data pipe, in bytes. The default is 256MB. This value - // must fit into a |uint32_t|. WARNING: If you bump it closer to 2^32, you - // must audit all the code to check that we don't overflow (2^31 would - // definitely be risky; up to 2^30 is probably okay). - size_t max_data_pipe_capacity_bytes; - - // Default data pipe capacity, if not specified explicitly in the creation - // options. The default is 1MB. - size_t default_data_pipe_capacity_bytes; - - // Alignment for the "start" of the data buffer used by data pipes. (The - // alignment of elements will depend on this and the element size.) The - // default is 16 bytes. - size_t data_pipe_buffer_alignment_bytes; - - // Maximum size of a single shared memory segment, in bytes. The default is - // 1GB. - // - // TODO(vtl): Set this hard limit appropriately (e.g., higher on 64-bit). - // (This will also entail some auditing to make sure I'm not messing up my - // checks anywhere.) - size_t max_shared_memory_num_bytes; -}; - -} // namespace embedder -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_CONFIGURATION_H_ diff --git a/third_party/mojo/src/mojo/edk/embedder/embedder.cc b/third_party/mojo/src/mojo/edk/embedder/embedder.cc deleted file mode 100644 index aa189bb..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/embedder.cc +++ /dev/null @@ -1,419 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/embedder/embedder.h" - -#include <utility> - -#include "base/atomicops.h" -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/command_line.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/task_runner.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/embedder_internal.h" -#include "mojo/edk/embedder/process_delegate.h" -#include "mojo/edk/system/core.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder_internal.h" -#include "third_party/mojo/src/mojo/edk/embedder/master_process_delegate.h" -#include "third_party/mojo/src/mojo/edk/embedder/process_delegate.h" -#include "third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h" -#include "third_party/mojo/src/mojo/edk/embedder/slave_process_delegate.h" -#include "third_party/mojo/src/mojo/edk/system/channel.h" -#include "third_party/mojo/src/mojo/edk/system/channel_manager.h" -#include "third_party/mojo/src/mojo/edk/system/configuration.h" -#include "third_party/mojo/src/mojo/edk/system/core.h" -#include "third_party/mojo/src/mojo/edk/system/ipc_support.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/raw_channel.h" - -namespace mojo { -namespace embedder { - -namespace internal { - -// Declared in embedder_internal.h. -PlatformSupport* g_platform_support = nullptr; -system::Core* g_core = nullptr; -system::IPCSupport* g_ipc_support = nullptr; - -} // namespace internal - -namespace { - -bool UseNewEDK() { - static bool checked = false; - static bool use_new = false; - if (!checked) { - use_new = base::CommandLine::ForCurrentProcess()->HasSwitch("use-new-edk"); - checked = true; - } - return use_new; -} - -// TODO(use_chrome_edk): temporary wrapper. -class NewEDKProcessDelegate : public mojo::edk::ProcessDelegate { - public: - NewEDKProcessDelegate(mojo::embedder::ProcessDelegate* passed_in_delegate) - : passed_in_delegate_(passed_in_delegate) {} - ~NewEDKProcessDelegate() {} - - void OnShutdownComplete() { - passed_in_delegate_->OnShutdownComplete(); - delete this; - } - - private: - mojo::embedder::ProcessDelegate* passed_in_delegate_; -}; - -NewEDKProcessDelegate* g_wrapper_process_delegate = nullptr; - -// TODO(vtl): For now, we need this to be thread-safe (since theoretically we -// currently support multiple channel creation threads -- possibly one per -// channel). Eventually, we won't need it to be thread-safe (we'll require a -// single I/O thread), and eventually we won't need it at all. Remember to -// remove the base/atomicops.h include. -system::ChannelId MakeChannelId() { - // Note that |AtomicWord| is signed. - static base::subtle::AtomicWord counter = 0; - - base::subtle::AtomicWord new_counter_value = - base::subtle::NoBarrier_AtomicIncrement(&counter, 1); - // Don't allow the counter to wrap. Note that any (strictly) positive value is - // a valid |ChannelId| (and |NoBarrier_AtomicIncrement()| returns the value - // post-increment). - CHECK_GT(new_counter_value, 0); - // Use "negative" values for these IDs, so that we'll also be able to use - // "positive" "process identifiers" (see connection_manager.h) as IDs (and - // they won't conflict). - return static_cast<system::ChannelId>(-new_counter_value); -} - -edk::ScopedPlatformHandle CreateEDKHandle(ScopedPlatformHandle handle) { - return edk::ScopedPlatformHandle(edk::PlatformHandle( -#if defined(OS_WIN) - handle.release().handle)); -#else - handle.release().fd)); -#endif -} - -ScopedPlatformHandle CreateHandle(edk::ScopedPlatformHandle handle) { - return ScopedPlatformHandle(PlatformHandle(handle.release().handle)); -} - -} // namespace - -void PreInitializeParentProcess() { - edk::PreInitializeParentProcess(); -} - -void PreInitializeChildProcess() { - edk::PreInitializeChildProcess(); -} - -ScopedPlatformHandle ChildProcessLaunched(base::ProcessHandle child_process) { - return CreateHandle(edk::ChildProcessLaunched(child_process)); -} - -void ChildProcessLaunched(base::ProcessHandle child_process, - ScopedPlatformHandle server_pipe) { - return edk::ChildProcessLaunched(child_process, - CreateEDKHandle(std::move(server_pipe))); -} - -void SetParentPipeHandle(ScopedPlatformHandle pipe) { - edk::SetParentPipeHandle(CreateEDKHandle(std::move(pipe))); -} - -void SetMaxMessageSize(size_t bytes) { - system::GetMutableConfiguration()->max_message_num_bytes = bytes; - // TODO(use_chrome_edk): also set this in the new EDK. - mojo::edk::SetMaxMessageSize(bytes); -} - -void Init() { - DCHECK(!internal::g_platform_support); - internal::g_platform_support = new SimplePlatformSupport(); - - DCHECK(!internal::g_core); - internal::g_core = new system::Core(internal::g_platform_support); - // TODO(use_chrome_edk): also initialize the new EDK. - mojo::edk::Init(); -} - -MojoResult AsyncWait(MojoHandle handle, - MojoHandleSignals signals, - const base::Callback<void(MojoResult)>& callback) { - if (UseNewEDK()) - return mojo::edk::internal::g_core->AsyncWait(handle, signals, callback); - return internal::g_core->AsyncWait(handle, signals, callback); -} - -MojoResult CreatePlatformHandleWrapper( - ScopedPlatformHandle platform_handle, - MojoHandle* platform_handle_wrapper_handle) { - DCHECK(platform_handle_wrapper_handle); - if (UseNewEDK()) { - return mojo::edk::CreatePlatformHandleWrapper( - CreateEDKHandle(std::move(platform_handle)), - platform_handle_wrapper_handle); - } - - scoped_refptr<system::Dispatcher> dispatcher = - system::PlatformHandleDispatcher::Create(std::move(platform_handle)); - - DCHECK(internal::g_core); - MojoHandle h = internal::g_core->AddDispatcher(dispatcher); - if (h == MOJO_HANDLE_INVALID) { - LOG(ERROR) << "Handle table full"; - dispatcher->Close(); - return MOJO_RESULT_RESOURCE_EXHAUSTED; - } - - *platform_handle_wrapper_handle = h; - return MOJO_RESULT_OK; -} - -MojoResult PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle, - ScopedPlatformHandle* platform_handle) { - DCHECK(platform_handle); - if (UseNewEDK()) { - mojo::edk::ScopedPlatformHandle edk_handle; - MojoResult rv = mojo::edk::PassWrappedPlatformHandle( - platform_handle_wrapper_handle, &edk_handle); - platform_handle->reset(mojo::embedder::PlatformHandle( - edk_handle.release().handle)); - return rv; - } - - DCHECK(internal::g_core); - scoped_refptr<system::Dispatcher> dispatcher( - internal::g_core->GetDispatcher(platform_handle_wrapper_handle)); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (dispatcher->GetType() != system::Dispatcher::Type::PLATFORM_HANDLE) - return MOJO_RESULT_INVALID_ARGUMENT; - - *platform_handle = - static_cast<system::PlatformHandleDispatcher*>(dispatcher.get()) - ->PassPlatformHandle(); - return MOJO_RESULT_OK; -} - -void InitIPCSupport(ProcessType process_type, - ProcessDelegate* process_delegate, - scoped_refptr<base::TaskRunner> io_thread_task_runner, - ScopedPlatformHandle platform_handle) { - if (!UseNewEDK()) { - // |Init()| must have already been called. - DCHECK(internal::g_core); - // And not |InitIPCSupport()| (without |ShutdownIPCSupport()|). - DCHECK(!internal::g_ipc_support); - - internal::g_ipc_support = new system::IPCSupport( - internal::g_platform_support, process_type, process_delegate, - io_thread_task_runner, std::move(platform_handle)); - - // TODO(use_chrome_edk) at this point the command line to switch to the new - // EDK might not be set yet. There's no harm in always intializing the new - // EDK though. - } - g_wrapper_process_delegate = new NewEDKProcessDelegate(process_delegate); - mojo::edk::InitIPCSupport(g_wrapper_process_delegate, io_thread_task_runner); -} - -void ShutdownIPCSupportOnIOThread() { - if (!UseNewEDK()) { - DCHECK(internal::g_ipc_support); - - internal::g_ipc_support->ShutdownOnIOThread(); - delete internal::g_ipc_support; - internal::g_ipc_support = nullptr; - delete g_wrapper_process_delegate; - g_wrapper_process_delegate = nullptr; - } - mojo::edk::ShutdownIPCSupportOnIOThread(); -} - -void ShutdownIPCSupport() { - if (!UseNewEDK()) { - DCHECK(internal::g_ipc_support); - - ProcessDelegate* delegate = internal::g_ipc_support->process_delegate(); - bool ok = internal::g_ipc_support->io_thread_task_runner()->PostTaskAndReply( - FROM_HERE, - base::Bind(&ShutdownIPCSupportOnIOThread), - base::Bind(&ProcessDelegate::OnShutdownComplete, - base::Unretained(delegate))); - DCHECK(ok); - } else { - mojo::edk::ShutdownIPCSupport(); - } -} - -ScopedMessagePipeHandle ConnectToSlave( - SlaveInfo slave_info, - ScopedPlatformHandle platform_handle, - const base::Closure& did_connect_to_slave_callback, - scoped_refptr<base::TaskRunner> did_connect_to_slave_runner, - std::string* platform_connection_id, - ChannelInfo** channel_info) { - DCHECK(platform_connection_id); - DCHECK(channel_info); - DCHECK(internal::g_ipc_support); - - system::ConnectionIdentifier connection_id = - internal::g_ipc_support->GenerateConnectionIdentifier(); - *platform_connection_id = connection_id.ToString(); - system::ChannelId channel_id = system::kInvalidChannelId; - scoped_refptr<system::MessagePipeDispatcher> dispatcher = - internal::g_ipc_support->ConnectToSlave( - connection_id, slave_info, std::move(platform_handle), - did_connect_to_slave_callback, std::move(did_connect_to_slave_runner), - &channel_id); - *channel_info = new ChannelInfo(channel_id); - - ScopedMessagePipeHandle rv( - MessagePipeHandle(internal::g_core->AddDispatcher(dispatcher))); - CHECK(rv.is_valid()); - // TODO(vtl): The |.Pass()| below is only needed due to an MSVS bug; remove it - // once that's fixed. - return rv; -} - -ScopedMessagePipeHandle ConnectToMaster( - const std::string& platform_connection_id, - const base::Closure& did_connect_to_master_callback, - scoped_refptr<base::TaskRunner> did_connect_to_master_runner, - ChannelInfo** channel_info) { - DCHECK(channel_info); - DCHECK(internal::g_ipc_support); - - bool ok = false; - system::ConnectionIdentifier connection_id = - system::ConnectionIdentifier::FromString(platform_connection_id, &ok); - CHECK(ok); - - system::ChannelId channel_id = system::kInvalidChannelId; - scoped_refptr<system::MessagePipeDispatcher> dispatcher = - internal::g_ipc_support->ConnectToMaster( - connection_id, did_connect_to_master_callback, - std::move(did_connect_to_master_runner), &channel_id); - *channel_info = new ChannelInfo(channel_id); - - ScopedMessagePipeHandle rv( - MessagePipeHandle(internal::g_core->AddDispatcher(dispatcher))); - CHECK(rv.is_valid()); - // TODO(vtl): The |.Pass()| below is only needed due to an MSVS bug; remove it - // once that's fixed. - return rv; -} - -// TODO(vtl): Write tests for this. -ScopedMessagePipeHandle CreateChannelOnIOThread( - ScopedPlatformHandle platform_handle, - ChannelInfo** channel_info) { - DCHECK(platform_handle.is_valid()); - DCHECK(channel_info); - DCHECK(internal::g_ipc_support); - - system::ChannelManager* channel_manager = - internal::g_ipc_support->channel_manager(); - - *channel_info = new ChannelInfo(MakeChannelId()); - scoped_refptr<system::MessagePipeDispatcher> dispatcher = - channel_manager->CreateChannelOnIOThread((*channel_info)->channel_id, - std::move(platform_handle)); - - ScopedMessagePipeHandle rv( - MessagePipeHandle(internal::g_core->AddDispatcher(dispatcher))); - CHECK(rv.is_valid()); - // TODO(vtl): The |.Pass()| below is only needed due to an MSVS bug; remove it - // once that's fixed. - return rv; -} - -ScopedMessagePipeHandle CreateChannel( - ScopedPlatformHandle platform_handle, - const base::Callback<void(ChannelInfo*)>& did_create_channel_callback, - scoped_refptr<base::TaskRunner> did_create_channel_runner) { - DCHECK(platform_handle.is_valid()); - DCHECK(!did_create_channel_callback.is_null()); - DCHECK(internal::g_ipc_support); - - if (UseNewEDK()) { - if (!did_create_channel_callback.is_null()) - did_create_channel_callback.Run(nullptr); - return mojo::edk::CreateMessagePipe( - CreateEDKHandle(std::move(platform_handle))); - } - - system::ChannelManager* channel_manager = - internal::g_ipc_support->channel_manager(); - - system::ChannelId channel_id = MakeChannelId(); - scoped_ptr<ChannelInfo> channel_info(new ChannelInfo(channel_id)); - scoped_refptr<system::MessagePipeDispatcher> dispatcher = - channel_manager->CreateChannel( - channel_id, std::move(platform_handle), - base::Bind(did_create_channel_callback, - base::Unretained(channel_info.release())), - did_create_channel_runner); - - ScopedMessagePipeHandle rv( - MessagePipeHandle(internal::g_core->AddDispatcher(dispatcher))); - CHECK(rv.is_valid()); - // TODO(vtl): The |.Pass()| below is only needed due to an MSVS bug; remove it - // once that's fixed. - return rv; -} - -// TODO(vtl): Write tests for this. -void DestroyChannelOnIOThread(ChannelInfo* channel_info) { - DCHECK(channel_info); - DCHECK(channel_info->channel_id); - DCHECK(internal::g_ipc_support); - - system::ChannelManager* channel_manager = - internal::g_ipc_support->channel_manager(); - channel_manager->ShutdownChannelOnIOThread(channel_info->channel_id); - delete channel_info; -} - -// TODO(vtl): Write tests for this. -void DestroyChannel( - ChannelInfo* channel_info, - const base::Closure& did_destroy_channel_callback, - scoped_refptr<base::TaskRunner> did_destroy_channel_runner) { - DCHECK(channel_info); - DCHECK(channel_info->channel_id); - DCHECK(!did_destroy_channel_callback.is_null()); - DCHECK(internal::g_ipc_support); - - system::ChannelManager* channel_manager = - internal::g_ipc_support->channel_manager(); - channel_manager->ShutdownChannel(channel_info->channel_id, - did_destroy_channel_callback, - did_destroy_channel_runner); - delete channel_info; -} - -void WillDestroyChannelSoon(ChannelInfo* channel_info) { - DCHECK(channel_info); - DCHECK(internal::g_ipc_support); - - system::ChannelManager* channel_manager = - internal::g_ipc_support->channel_manager(); - channel_manager->WillShutdownChannel(channel_info->channel_id); -} - -} // namespace embedder -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/embedder/embedder.h b/third_party/mojo/src/mojo/edk/embedder/embedder.h deleted file mode 100644 index 8737101..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/embedder.h +++ /dev/null @@ -1,249 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_EMBEDDER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_EMBEDDER_H_ - -#include <string> - -#include "base/callback.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/process/process_handle.h" -#include "base/task_runner.h" -#include "mojo/public/cpp/system/message_pipe.h" -#include "third_party/mojo/src/mojo/edk/embedder/channel_info_forward.h" -#include "third_party/mojo/src/mojo/edk/embedder/process_type.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" -#include "third_party/mojo/src/mojo/edk/embedder/slave_info.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { - -namespace embedder { - -class ProcessDelegate; - -// Wrapper functions around the ones in src/mojo/edk for component builds. -MOJO_SYSTEM_IMPL_EXPORT void PreInitializeParentProcess(); -MOJO_SYSTEM_IMPL_EXPORT void PreInitializeChildProcess(); -MOJO_SYSTEM_IMPL_EXPORT ScopedPlatformHandle ChildProcessLaunched( - base::ProcessHandle child_process); -MOJO_SYSTEM_IMPL_EXPORT void ChildProcessLaunched( - base::ProcessHandle child_process, ScopedPlatformHandle server_pipe); -MOJO_SYSTEM_IMPL_EXPORT void SetParentPipeHandle(ScopedPlatformHandle pipe); - -// Basic configuration/initialization ------------------------------------------ - -// |Init()| sets up the basic Mojo system environment, making the |Mojo...()| -// functions available and functional. This is never shut down (except in tests -// -- see test_embedder.h). - -// Allows changing the default max message size. Must be called before Init. -MOJO_SYSTEM_IMPL_EXPORT void SetMaxMessageSize(size_t bytes); - -// Must be called first, or just after setting configuration parameters, to -// initialize the (global, singleton) system. -MOJO_SYSTEM_IMPL_EXPORT void Init(); - -// Basic functions ------------------------------------------------------------- - -// The functions in this section are available once |Init()| has been called. - -// Start waiting on the handle asynchronously. On success, |callback| will be -// called exactly once, when |handle| satisfies a signal in |signals| or it -// becomes known that it will never do so. |callback| will be executed on an -// arbitrary thread, so it must not call any Mojo system or embedder functions. -MOJO_SYSTEM_IMPL_EXPORT MojoResult -AsyncWait(MojoHandle handle, - MojoHandleSignals signals, - const base::Callback<void(MojoResult)>& callback); - -// Creates a |MojoHandle| that wraps the given |PlatformHandle| (taking -// ownership of it). This |MojoHandle| can then, e.g., be passed through message -// pipes. Note: This takes ownership (and thus closes) |platform_handle| even on -// failure, which is different from what you'd expect from a Mojo API, but it -// makes for a more convenient embedder API. -MOJO_SYSTEM_IMPL_EXPORT MojoResult -CreatePlatformHandleWrapper(ScopedPlatformHandle platform_handle, - MojoHandle* platform_handle_wrapper_handle); - -// Retrieves the |PlatformHandle| that was wrapped into a |MojoHandle| (using -// |CreatePlatformHandleWrapper()| above). Note that the |MojoHandle| must still -// be closed separately. -MOJO_SYSTEM_IMPL_EXPORT MojoResult -PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle, - ScopedPlatformHandle* platform_handle); - -// Initialialization/shutdown for interprocess communication (IPC) ------------- - -// |InitIPCSupport()| sets up the subsystem for interprocess communication, -// making the IPC functions (in the following section) available and functional. -// (This may only be done after |Init()|.) -// -// This subsystem may be shut down, using |ShutdownIPCSupportOnIOThread()| or -// |ShutdownIPCSupport()|. None of the IPC functions may be called while or -// after either of these is called. - -// Initializes a process of the given type; to be called after |Init()|. -// - |process_delegate| must be a process delegate of the appropriate type -// corresponding to |process_type|; its methods will be called on the same -// thread as Shutdown. -// - |process_delegate|, and |io_thread_task_runner| should live at least -// until |ShutdownIPCSupport()|'s callback has been run or -// |ShutdownIPCSupportOnIOThread()| has completed. -// - For slave processes (i.e., |process_type| is |ProcessType::SLAVE|), -// |platform_handle| should be connected to the handle passed to -// |ConnectToSlave()| (in the master process). For other processes, -// |platform_handle| is ignored (and should not be valid). -MOJO_SYSTEM_IMPL_EXPORT void InitIPCSupport( - ProcessType process_type, - ProcessDelegate* process_delegate, - scoped_refptr<base::TaskRunner> io_thread_task_runner, - ScopedPlatformHandle platform_handle); - -// Shuts down the subsystem initialized by |InitIPCSupport()|. This must be -// called on the I/O thread (given to |InitIPCSupport()|). This completes -// synchronously and does not result in a call to the process delegate's -// |OnShutdownComplete()|. -MOJO_SYSTEM_IMPL_EXPORT void ShutdownIPCSupportOnIOThread(); - -// Like |ShutdownIPCSupportOnIOThread()|, but may be called from any thread, -// signalling shutdown completion via the process delegate's -// |OnShutdownComplete()|. -MOJO_SYSTEM_IMPL_EXPORT void ShutdownIPCSupport(); - -// Interprocess communication (IPC) functions ---------------------------------- - -// Called in the master process to connect to a slave process to the IPC system. -// (This should only be called in a process initialized (using -// |InitIPCSupport()|) with process type |ProcessType::MASTER|.) -// -// This should typically be called *before* the slave process is even created. -// It requires an OS "pipe" to be established between the master and slave -// processes, with |platform_handle| being a handle to the end that remains on -// the master. -// -// This will establish a channel and an initial message pipe (to which it -// returns a handle), an ID string (returned in |*platform_connection_id|) that -// must be passed to the slave (e.g., on the command line), and a -// |ChannelInfo*| (in |*channel_info|) which should eventually be given to -// |DestroyChannel()|/|DestroyChannelOnIOThread()|, but only after -// |did_connect_to_slave_callback| has been run. -// -// |did_connect_to_slave_callback| will be run either using -// |did_connect_to_slave_runner| (if non-null) or on the I/O thread, once the -// |ChannelInfo*| is valid. -// -// TODO(vtl): The API is a little crazy with respect to the |ChannelInfo*|. -MOJO_SYSTEM_IMPL_EXPORT ScopedMessagePipeHandle -ConnectToSlave(SlaveInfo slave_info, - ScopedPlatformHandle platform_handle, - const base::Closure& did_connect_to_slave_callback, - scoped_refptr<base::TaskRunner> did_connect_to_slave_runner, - std::string* platform_connection_id, - ChannelInfo** channel_info); - -// Called in a slave process to connect it to the IPC system. (This should only -// be called in a process initialized (using |InitIPCSupport()|) with process -// type |ProcessType::SLAVE|.) This should be called exactly once in each slave -// process. -// -// See |ConnectToSlave()| for details. (Note that if this fails in any way, -// e.g., if |platform_connection_id| is invalid, this will CHECK-fail and -// terminate the process.) |channel_info|, |did_connect_to_master_callback|, and -// |did_connect_to_master_runner| are analagous to in |ConnectToSlave()|. -// -// TODO(vtl): The API is a little crazy with respect to the |ChannelInfo*|. -MOJO_SYSTEM_IMPL_EXPORT ScopedMessagePipeHandle -ConnectToMaster(const std::string& platform_connection_id, - const base::Closure& did_connect_to_master_callback, - scoped_refptr<base::TaskRunner> did_connect_to_master_runner, - ChannelInfo** channel_info); - -// A "channel" is a connection on top of an OS "pipe", on top of which Mojo -// message pipes (etc.) can be multiplexed. It must "live" on some I/O thread. -// -// There are two channel creation APIs: |CreateChannelOnIOThread()| creates a -// channel synchronously and must be called from the I/O thread, while -// |CreateChannel()| is asynchronous and may be called from any thread. -// |DestroyChannel()| is used to destroy the channel in either case and may be -// called from any thread, but completes synchronously when called from the I/O -// thread. -// -// Both creation functions have a |platform_handle| argument, which should be an -// OS-dependent handle to one side of a suitable bidirectional OS "pipe" (e.g., -// a file descriptor to a socket on POSIX, a handle to a named pipe on Windows); -// this "pipe" should be connected and ready for operation (e.g., to be written -// to or read from). -// -// Both (synchronously) return a handle to the bootstrap message pipe on the -// channel that was (or is to be) created, or |MOJO_HANDLE_INVALID| on error -// (but note that this will happen only if, e.g., the handle table is full). -// This message pipe may be used immediately, but since channel operation -// actually begins asynchronously, other errors may still occur (e.g., if the -// other end of the "pipe" is closed) and be reported in the usual way to the -// returned handle. -// -// (E.g., a message written immediately to the returned handle will be queued -// and the handle immediately closed, before the channel begins operation. In -// this case, the channel should connect as usual, send the queued message, and -// report that the handle was closed to the other side. The message sent may -// have other handles, so there may still be message pipes "on" this channel.) -// -// Both also produce a |ChannelInfo*| (a pointer to an opaque object) -- the -// first synchronously and second asynchronously. -// -// The destruction functions are similarly synchronous and asynchronous, -// respectively, and take the |ChannelInfo*| produced by the creation functions. - -// Creates a channel; must only be called from the I/O thread. |platform_handle| -// should be a handle to a connected OS "pipe". Eventually (even on failure), -// the "out" value |*channel_info| should be passed to |DestoryChannel()| to -// tear down the channel. Returns a handle to the bootstrap message pipe. -MOJO_SYSTEM_IMPL_EXPORT ScopedMessagePipeHandle -CreateChannelOnIOThread(ScopedPlatformHandle platform_handle, - ChannelInfo** channel_info); - -// Creates a channel asynchronously; may be called from any thread. -// |platform_handle| should be a handle to a connected OS "pipe". -// |did_create_channel_callback| should be the callback to call with the -// |ChannelInfo*|, which should eventually be passed to |DestroyChannel()| to -// tear down the channel; the callback will be called using -// |did_create_channel_runner| if that is non-null, or otherwise it will be -// posted to the I/O thread. Returns a handle to the bootstrap message pipe. -// -// Note: This should only be used to establish a channel with a process of type -// |ProcessType::NONE|. This function may be removed in the future. -MOJO_SYSTEM_IMPL_EXPORT ScopedMessagePipeHandle CreateChannel( - ScopedPlatformHandle platform_handle, - const base::Callback<void(ChannelInfo*)>& did_create_channel_callback, - scoped_refptr<base::TaskRunner> did_create_channel_runner); - -// Destroys a channel that was created using |ConnectToMaster()|, -// |ConnectToSlave()|, |CreateChannel()|, or |CreateChannelOnIOThread()|; must -// be called from the channel's I'O thread. Completes synchronously (and posts -// no tasks). -MOJO_SYSTEM_IMPL_EXPORT void DestroyChannelOnIOThread( - ChannelInfo* channel_info); - -// Like |DestroyChannelOnIOThread()|, but asynchronous and may be called from -// any thread. The callback will be called using |did_destroy_channel_runner| -// if that is non-null, or otherwise it will be called on the "channel thread". -// The "channel thread" must remain alive and continue to process tasks until -// the callback has been executed. -MOJO_SYSTEM_IMPL_EXPORT void DestroyChannel( - ChannelInfo* channel_info, - const base::Closure& did_destroy_channel_callback, - scoped_refptr<base::TaskRunner> did_destroy_channel_runner); - -// Inform the channel that it will soon be destroyed (doing so is optional). -// This may be called from any thread, but the caller must ensure that this is -// called before |DestroyChannel()|. -MOJO_SYSTEM_IMPL_EXPORT void WillDestroyChannelSoon(ChannelInfo* channel_info); - -} // namespace embedder -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_EMBEDDER_H_ diff --git a/third_party/mojo/src/mojo/edk/embedder/embedder_internal.h b/third_party/mojo/src/mojo/edk/embedder/embedder_internal.h deleted file mode 100644 index c66d01b..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/embedder_internal.h +++ /dev/null @@ -1,65 +0,0 @@ -// 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. - -// This header contains internal details for the *implementation* of the -// embedder API. It should not be included by any public header (nor by users of -// the embedder API). - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_EMBEDDER_INTERNAL_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_EMBEDDER_INTERNAL_H_ - -#include <stdint.h> - -#include "third_party/mojo/src/mojo/edk/system/channel_id.h" - -namespace base { -class TaskRunner; -} - -namespace mojo { - -namespace system { - -class ChannelManager; -class Core; -class IPCSupport; - -} // namespace system - -namespace embedder { - -class PlatformSupport; -class ProcessDelegate; - -// This is a type that's opaque to users of the embedder API (which only -// gives/takes |ChannelInfo*|s). We make it a struct to make it -// template-friendly. -struct ChannelInfo { - explicit ChannelInfo(system::ChannelId channel_id = 0) - : channel_id(channel_id) {} - - system::ChannelId channel_id; -}; - -namespace internal { - -// Instance of |PlatformSupport| to use. -extern PlatformSupport* g_platform_support; - -// Instance of |Core| used by the system functions (|Mojo...()|). -extern system::Core* g_core; - -// Instance of |IPCSupport|, initialized by |InitIPCSupport()| and reset by -// |ShutdownIPCSupport()|. This is declared here so that -// |mojo::embedder::test::Shutdown()| can check that it's only called after -// |ShutdownIPCSupport()|. -extern system::IPCSupport* g_ipc_support; - -} // namespace internal - -} // namepace embedder - -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_EMBEDDER_INTERNAL_H_ diff --git a/third_party/mojo/src/mojo/edk/embedder/embedder_unittest.cc b/third_party/mojo/src/mojo/edk/embedder/embedder_unittest.cc deleted file mode 100644 index fe93b51..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/embedder_unittest.cc +++ /dev/null @@ -1,819 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/embedder/embedder.h" - -#include <string.h> -#include <utility> - -#include "base/bind.h" -#include "base/command_line.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "base/synchronization/waitable_event.h" -#include "base/test/test_io_thread.h" -#include "base/test/test_timeouts.h" -#include "mojo/public/c/system/core.h" -#include "mojo/public/cpp/system/handle.h" -#include "mojo/public/cpp/system/macros.h" -#include "mojo/public/cpp/system/message_pipe.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" -#include "third_party/mojo/src/mojo/edk/embedder/test_embedder.h" -#include "third_party/mojo/src/mojo/edk/system/mutex.h" -#include "third_party/mojo/src/mojo/edk/system/test_utils.h" -#include "third_party/mojo/src/mojo/edk/test/multiprocess_test_helper.h" -#include "third_party/mojo/src/mojo/edk/test/scoped_ipc_support.h" - -namespace mojo { -namespace embedder { -namespace { - -const MojoHandleSignals kSignalReadadableWritable = - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE; - -const MojoHandleSignals kSignalAll = MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED; - -const char kConnectionIdFlag[] = "test-connection-id"; - -void DoNothing() {} - -class ScopedTestChannel { - public: - // Creates a channel, which lives on the I/O thread given to - // |InitIPCSupport()|. After construction, |bootstrap_message_pipe()| gives - // the Mojo handle for the bootstrap message pipe on this channel; it is up to - // the caller to close this handle. Note: The I/O thread must outlive this - // object (and its message loop must continue pumping messages while this - // object is alive). - explicit ScopedTestChannel(ScopedPlatformHandle platform_handle) - : bootstrap_message_pipe_(MOJO_HANDLE_INVALID), - event_(true, false), // Manual reset. - channel_info_(nullptr), - wait_on_shutdown_(true) { - bootstrap_message_pipe_ = - CreateChannel(std::move(platform_handle), - base::Bind(&ScopedTestChannel::DidCreateChannel, - base::Unretained(this)), - nullptr) - .release() - .value(); - CHECK_NE(bootstrap_message_pipe_, MOJO_HANDLE_INVALID); - } - - // Destructor: Shuts down the channel. (As noted above, for this to happen, - // the I/O thread must be alive and pumping messages.) - ~ScopedTestChannel() { - // |WaitForChannelCreationCompletion()| must be called before destruction. - CHECK(event_.IsSignaled()); - event_.Reset(); - if (wait_on_shutdown_) { - DestroyChannel(channel_info_, - base::Bind(&ScopedTestChannel::DidDestroyChannel, - base::Unretained(this)), - nullptr); - event_.Wait(); - } else { - DestroyChannel(channel_info_, base::Bind(&DoNothing), nullptr); - } - } - - // Waits for channel creation to be completed. - void WaitForChannelCreationCompletion() { event_.Wait(); } - - MojoHandle bootstrap_message_pipe() const { return bootstrap_message_pipe_; } - - // Call only after |WaitForChannelCreationCompletion()|. Use only to check - // that it's not null. - const ChannelInfo* channel_info() const { return channel_info_; } - - // Don't wait for the channel shutdown to finish on destruction. Used to - // exercise races. - void NoWaitOnShutdown() { wait_on_shutdown_ = false; } - - private: - void DidCreateChannel(ChannelInfo* channel_info) { - CHECK(channel_info); - CHECK(!channel_info_); - channel_info_ = channel_info; - event_.Signal(); - } - - void DidDestroyChannel() { event_.Signal(); } - - // Valid from creation until whenever it gets closed (by the "owner" of this - // object). - // Note: We don't want use the C++ wrappers here, since we want to test the - // API at the lowest level. - MojoHandle bootstrap_message_pipe_; - - // Set after channel creation has been completed (i.e., the callback to - // |CreateChannel()| has been called). Also used in the destructor to wait for - // |DestroyChannel()| completion. - base::WaitableEvent event_; - - // Valid after channel creation completion until destruction. - ChannelInfo* channel_info_; - - // Whether the destructor should wait until the channel is destroyed. - bool wait_on_shutdown_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedTestChannel); -}; - -class EmbedderTest : public testing::Test { - public: - EmbedderTest() : test_io_thread_(base::TestIOThread::kAutoStart) {} - ~EmbedderTest() override {} - - protected: - base::TestIOThread& test_io_thread() { return test_io_thread_; } - scoped_refptr<base::TaskRunner> test_io_task_runner() { - return test_io_thread_.task_runner(); - } - - private: - void SetUp() override { Init(); } - - void TearDown() override { EXPECT_TRUE(test::Shutdown()); } - - base::MessageLoop message_loop_; - base::TestIOThread test_io_thread_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(EmbedderTest); -}; - -TEST_F(EmbedderTest, ChannelsBasic) { - mojo::test::ScopedIPCSupport ipc_support(test_io_task_runner()); - - PlatformChannelPair channel_pair; - ScopedTestChannel server_channel(channel_pair.PassServerHandle()); - MojoHandle server_mp = server_channel.bootstrap_message_pipe(); - EXPECT_NE(server_mp, MOJO_HANDLE_INVALID); - ScopedTestChannel client_channel(channel_pair.PassClientHandle()); - MojoHandle client_mp = client_channel.bootstrap_message_pipe(); - EXPECT_NE(client_mp, MOJO_HANDLE_INVALID); - - // We can write to a message pipe handle immediately. - const char kHello[] = "hello"; - EXPECT_EQ( - MOJO_RESULT_OK, - MojoWriteMessage(server_mp, kHello, static_cast<uint32_t>(sizeof(kHello)), - nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Now wait for the other side to become readable. - MojoHandleSignalsState state; - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, &state)); - EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); - EXPECT_EQ(kSignalAll, state.satisfiable_signals); - - char buffer[1000] = {}; - uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoReadMessage(client_mp, buffer, &num_bytes, nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kHello), num_bytes); - EXPECT_STREQ(kHello, buffer); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(server_mp)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(client_mp)); - - // By this point, these waits should basically be no-ops (since we've waited - // for the client message pipe to become readable, which implies that both - // the server and client channels were completely created). - server_channel.WaitForChannelCreationCompletion(); - client_channel.WaitForChannelCreationCompletion(); - EXPECT_TRUE(server_channel.channel_info()); - EXPECT_TRUE(client_channel.channel_info()); -} - -class TestAsyncWaiter { - public: - TestAsyncWaiter() : event_(true, false), wait_result_(MOJO_RESULT_UNKNOWN) {} - - void Awake(MojoResult result) { - system::MutexLocker l(&wait_result_mutex_); - wait_result_ = result; - event_.Signal(); - } - - bool TryWait() { return event_.TimedWait(TestTimeouts::action_timeout()); } - - MojoResult wait_result() const { - system::MutexLocker l(&wait_result_mutex_); - return wait_result_; - } - - private: - base::WaitableEvent event_; - - mutable system::Mutex wait_result_mutex_; - MojoResult wait_result_ MOJO_GUARDED_BY(wait_result_mutex_); - - MOJO_DISALLOW_COPY_AND_ASSIGN(TestAsyncWaiter); -}; - -void WriteHello(MessagePipeHandle pipe) { - static const char kHello[] = "hello"; - CHECK_EQ(MOJO_RESULT_OK, - WriteMessageRaw(pipe, kHello, static_cast<uint32_t>(sizeof(kHello)), - nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); -} - -void CloseScopedHandle(ScopedMessagePipeHandle handle) { - // Do nothing and the destructor will close it. -} - -TEST_F(EmbedderTest, AsyncWait) { - ScopedMessagePipeHandle client_mp; - ScopedMessagePipeHandle server_mp; - EXPECT_EQ(MOJO_RESULT_OK, CreateMessagePipe(nullptr, &client_mp, &server_mp)); - - TestAsyncWaiter waiter; - EXPECT_EQ(MOJO_RESULT_OK, - AsyncWait(client_mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, - base::Bind(&TestAsyncWaiter::Awake, - base::Unretained(&waiter)))); - - test_io_task_runner()->PostTask(FROM_HERE, - base::Bind(&WriteHello, server_mp.get())); - EXPECT_TRUE(waiter.TryWait()); - EXPECT_EQ(MOJO_RESULT_OK, waiter.wait_result()); - - // If message is in the queue, it does't allow us to wait. - TestAsyncWaiter waiter_that_doesnt_wait; - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - AsyncWait(client_mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, - base::Bind(&TestAsyncWaiter::Awake, - base::Unretained(&waiter_that_doesnt_wait)))); - - char buffer[1000]; - uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer)); - CHECK_EQ(MOJO_RESULT_OK, - ReadMessageRaw(client_mp.get(), buffer, &num_bytes, nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - - TestAsyncWaiter unsatisfiable_waiter; - EXPECT_EQ(MOJO_RESULT_OK, - AsyncWait(client_mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, - base::Bind(&TestAsyncWaiter::Awake, - base::Unretained(&unsatisfiable_waiter)))); - - test_io_task_runner()->PostTask( - FROM_HERE, - base::Bind(&CloseScopedHandle, base::Passed(std::move(server_mp)))); - - EXPECT_TRUE(unsatisfiable_waiter.TryWait()); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - unsatisfiable_waiter.wait_result()); -} - -TEST_F(EmbedderTest, ChannelsHandlePassing) { - mojo::test::ScopedIPCSupport ipc_support(test_io_task_runner()); - - PlatformChannelPair channel_pair; - ScopedTestChannel server_channel(channel_pair.PassServerHandle()); - MojoHandle server_mp = server_channel.bootstrap_message_pipe(); - EXPECT_NE(server_mp, MOJO_HANDLE_INVALID); - ScopedTestChannel client_channel(channel_pair.PassClientHandle()); - MojoHandle client_mp = client_channel.bootstrap_message_pipe(); - EXPECT_NE(client_mp, MOJO_HANDLE_INVALID); - - MojoHandle h0, h1; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &h0, &h1)); - - // Write a message to |h0| (attaching nothing). - const char kHello[] = "hello"; - EXPECT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(h0, kHello, static_cast<uint32_t>(sizeof(kHello)), - nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Write one message to |server_mp|, attaching |h1|. - const char kWorld[] = "world!!!"; - EXPECT_EQ( - MOJO_RESULT_OK, - MojoWriteMessage(server_mp, kWorld, static_cast<uint32_t>(sizeof(kWorld)), - &h1, 1, MOJO_WRITE_MESSAGE_FLAG_NONE)); - h1 = MOJO_HANDLE_INVALID; - - // Write another message to |h0|. - const char kFoo[] = "foo"; - EXPECT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(h0, kFoo, static_cast<uint32_t>(sizeof(kFoo)), - nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Wait for |client_mp| to become readable. - MojoHandleSignalsState state; - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, &state)); - EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); - EXPECT_EQ(kSignalAll, state.satisfiable_signals); - - // Read a message from |client_mp|. - char buffer[1000] = {}; - uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer)); - MojoHandle handles[10] = {}; - uint32_t num_handles = MOJO_ARRAYSIZE(handles); - EXPECT_EQ(MOJO_RESULT_OK, - MojoReadMessage(client_mp, buffer, &num_bytes, handles, - &num_handles, MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kWorld), num_bytes); - EXPECT_STREQ(kWorld, buffer); - EXPECT_EQ(1u, num_handles); - EXPECT_NE(handles[0], MOJO_HANDLE_INVALID); - h1 = handles[0]; - - // Wait for |h1| to become readable. - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(h1, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, &state)); - EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); - EXPECT_EQ(kSignalAll, state.satisfiable_signals); - - // Read a message from |h1|. - memset(buffer, 0, sizeof(buffer)); - num_bytes = static_cast<uint32_t>(sizeof(buffer)); - memset(handles, 0, sizeof(handles)); - num_handles = MOJO_ARRAYSIZE(handles); - EXPECT_EQ(MOJO_RESULT_OK, - MojoReadMessage(h1, buffer, &num_bytes, handles, &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kHello), num_bytes); - EXPECT_STREQ(kHello, buffer); - EXPECT_EQ(0u, num_handles); - - // Wait for |h1| to become readable (again). - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(h1, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, &state)); - EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); - EXPECT_EQ(kSignalAll, state.satisfiable_signals); - - // Read the second message from |h1|. - memset(buffer, 0, sizeof(buffer)); - num_bytes = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoReadMessage(h1, buffer, &num_bytes, nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kFoo), num_bytes); - EXPECT_STREQ(kFoo, buffer); - - // Write a message to |h1|. - const char kBarBaz[] = "barbaz"; - EXPECT_EQ( - MOJO_RESULT_OK, - MojoWriteMessage(h1, kBarBaz, static_cast<uint32_t>(sizeof(kBarBaz)), - nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Wait for |h0| to become readable. - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(h0, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, &state)); - EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); - EXPECT_EQ(kSignalAll, state.satisfiable_signals); - - // Read a message from |h0|. - memset(buffer, 0, sizeof(buffer)); - num_bytes = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoReadMessage(h0, buffer, &num_bytes, nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kBarBaz), num_bytes); - EXPECT_STREQ(kBarBaz, buffer); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(server_mp)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(client_mp)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1)); - - server_channel.WaitForChannelCreationCompletion(); - client_channel.WaitForChannelCreationCompletion(); - EXPECT_TRUE(server_channel.channel_info()); - EXPECT_TRUE(client_channel.channel_info()); -} - -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -// TODO(vtl): I'm guessing this is true of this test too? -#define MAYBE_MultiprocessMasterSlave DISABLED_MultiprocessMasterSlave -#else -#define MAYBE_MultiprocessMasterSlave MultiprocessMasterSlave -#endif // defined(OS_ANDROID) -TEST_F(EmbedderTest, MAYBE_MultiprocessMasterSlave) { - mojo::test::ScopedMasterIPCSupport ipc_support(test_io_task_runner()); - - mojo::test::MultiprocessTestHelper multiprocess_test_helper; - std::string connection_id; - base::WaitableEvent event(true, false); - ChannelInfo* channel_info = nullptr; - ScopedMessagePipeHandle mp = ConnectToSlave( - nullptr, std::move(multiprocess_test_helper.server_platform_handle), - base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)), - nullptr, &connection_id, &channel_info); - ASSERT_TRUE(mp.is_valid()); - EXPECT_TRUE(channel_info); - ASSERT_FALSE(connection_id.empty()); - - multiprocess_test_helper.StartChildWithExtraSwitch( - "MultiprocessMasterSlave", kConnectionIdFlag, connection_id); - - // Send a message saying "hello". - EXPECT_EQ(MOJO_RESULT_OK, WriteMessageRaw(mp.get(), "hello", 5, nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Wait for a response. - EXPECT_EQ(MOJO_RESULT_OK, - Wait(mp.get(), MOJO_HANDLE_SIGNAL_READABLE, - mojo::system::test::ActionDeadline(), nullptr)); - - // The response message should say "world". - char buffer[100]; - uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - ReadMessageRaw(mp.get(), buffer, &num_bytes, nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(5u, num_bytes); - EXPECT_EQ(0, memcmp(buffer, "world", 5)); - - mp.reset(); - - EXPECT_TRUE(multiprocess_test_helper.WaitForChildTestShutdown()); - - EXPECT_TRUE(event.TimedWait(TestTimeouts::action_timeout())); - test_io_thread().PostTaskAndWait( - FROM_HERE, - base::Bind(&DestroyChannelOnIOThread, base::Unretained(channel_info))); -} - -TEST_F(EmbedderTest, ChannelShutdownRace_MessagePipeClose) { - const size_t kIterations = 1000; - mojo::test::ScopedIPCSupport ipc_support(test_io_task_runner()); - - for (size_t i = 0; i < kIterations; i++) { - PlatformChannelPair channel_pair; - scoped_ptr<ScopedTestChannel> server_channel( - new ScopedTestChannel(channel_pair.PassServerHandle())); - server_channel->WaitForChannelCreationCompletion(); - server_channel->NoWaitOnShutdown(); - - MojoHandle server_mp = server_channel->bootstrap_message_pipe(); - EXPECT_NE(server_mp, MOJO_HANDLE_INVALID); - - // Race between channel shutdown and closing a message pipe. The message - // pipe doesn't have to be the bootstrap pipe. It just has to be bound to - // the channel. - server_channel.reset(); - MojoClose(server_mp); - } -} - -TEST_F(EmbedderTest, ChannelShutdownRace_MessagePipePassing) { - const size_t kIterations = 1000; - mojo::test::ScopedIPCSupport ipc_support(test_io_task_runner()); - - for (size_t i = 0; i < kIterations; i++) { - PlatformChannelPair channel_pair; - scoped_ptr<ScopedTestChannel> server_channel( - new ScopedTestChannel(channel_pair.PassServerHandle())); - server_channel->WaitForChannelCreationCompletion(); - server_channel->NoWaitOnShutdown(); - - MojoHandle server_mp = server_channel->bootstrap_message_pipe(); - EXPECT_NE(server_mp, MOJO_HANDLE_INVALID); - - MessagePipe test_pipe; - MojoHandle passing_handle = test_pipe.handle0.release().value(); - - // Race between channel shutdown and passing a message pipe. - server_channel.reset(); - MojoWriteMessage(server_mp, nullptr, 0, &passing_handle, 1, - MOJO_WRITE_MESSAGE_FLAG_NONE); - MojoClose(server_mp); - MojoClose(passing_handle); - } -} - -MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessMasterSlave) { - base::MessageLoop message_loop; - ScopedPlatformHandle client_platform_handle = - std::move(mojo::test::MultiprocessTestHelper::client_platform_handle); - EXPECT_TRUE(client_platform_handle.is_valid()); - - base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); - Init(); - - { - mojo::test::ScopedSlaveIPCSupport ipc_support( - test_io_thread.task_runner(), std::move(client_platform_handle)); - - const base::CommandLine& command_line = - *base::CommandLine::ForCurrentProcess(); - ASSERT_TRUE(command_line.HasSwitch(kConnectionIdFlag)); - std::string connection_id = - command_line.GetSwitchValueASCII(kConnectionIdFlag); - ASSERT_FALSE(connection_id.empty()); - base::WaitableEvent event(true, false); - ChannelInfo* channel_info = nullptr; - ScopedMessagePipeHandle mp = ConnectToMaster( - connection_id, - base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)), - nullptr, &channel_info); - ASSERT_TRUE(mp.is_valid()); - EXPECT_TRUE(channel_info); - - // Wait for the master to send us a message. - EXPECT_EQ(MOJO_RESULT_OK, - Wait(mp.get(), MOJO_HANDLE_SIGNAL_READABLE, - mojo::system::test::ActionDeadline(), nullptr)); - - // It should say "hello". - char buffer[100]; - uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - ReadMessageRaw(mp.get(), buffer, &num_bytes, nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(5u, num_bytes); - EXPECT_EQ(0, memcmp(buffer, "hello", 5)); - - // In response send a message saying "world". - EXPECT_EQ(MOJO_RESULT_OK, WriteMessageRaw(mp.get(), "world", 5, nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - mp.reset(); - - EXPECT_TRUE(event.TimedWait(TestTimeouts::action_timeout())); - test_io_thread.PostTaskAndWait( - FROM_HERE, - base::Bind(&DestroyChannelOnIOThread, base::Unretained(channel_info))); - } - - EXPECT_TRUE(test::Shutdown()); -} - -// The sequence of messages sent is: -// server_mp client_mp mp0 mp1 mp2 mp3 -// 1. "hello" -// 2. "world!" -// 3. "FOO" -// 4. "Bar"+mp1 -// 5. (close) -// 6. (close) -// 7. "baz" -// 8. (closed) -// 9. "quux"+mp2 -// 10. (close) -// 11. (wait/cl.) -// 12. (wait/cl.) - -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_MultiprocessChannels DISABLED_MultiprocessChannels -#else -#define MAYBE_MultiprocessChannels MultiprocessChannels -#endif // defined(OS_ANDROID) -TEST_F(EmbedderTest, MAYBE_MultiprocessChannels) { - // TODO(vtl): This should eventually initialize a master process instead, - // probably. - mojo::test::ScopedIPCSupport ipc_support(test_io_task_runner()); - - mojo::test::MultiprocessTestHelper multiprocess_test_helper; - multiprocess_test_helper.StartChild("MultiprocessChannelsClient"); - - { - ScopedTestChannel server_channel( - std::move(multiprocess_test_helper.server_platform_handle)); - MojoHandle server_mp = server_channel.bootstrap_message_pipe(); - EXPECT_NE(server_mp, MOJO_HANDLE_INVALID); - server_channel.WaitForChannelCreationCompletion(); - EXPECT_TRUE(server_channel.channel_info()); - - // 1. Write a message to |server_mp| (attaching nothing). - const char kHello[] = "hello"; - EXPECT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(server_mp, kHello, - static_cast<uint32_t>(sizeof(kHello)), nullptr, - 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // TODO(vtl): If the scope were ended immediately here (maybe after closing - // |server_mp|), we die with a fatal error in |Channel::HandleLocalError()|. - - // 2. Read a message from |server_mp|. - MojoHandleSignalsState state; - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(server_mp, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, &state)); - EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); - EXPECT_EQ(kSignalAll, state.satisfiable_signals); - - char buffer[1000] = {}; - uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoReadMessage(server_mp, buffer, &num_bytes, nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - const char kWorld[] = "world!"; - EXPECT_EQ(sizeof(kWorld), num_bytes); - EXPECT_STREQ(kWorld, buffer); - - // Create a new message pipe (endpoints |mp0| and |mp1|). - MojoHandle mp0, mp1; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mp0, &mp1)); - - // 3. Write something to |mp0|. - const char kFoo[] = "FOO"; - EXPECT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(mp0, kFoo, static_cast<uint32_t>(sizeof(kFoo)), - nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // 4. Write a message to |server_mp|, attaching |mp1|. - const char kBar[] = "Bar"; - EXPECT_EQ( - MOJO_RESULT_OK, - MojoWriteMessage(server_mp, kBar, static_cast<uint32_t>(sizeof(kBar)), - &mp1, 1, MOJO_WRITE_MESSAGE_FLAG_NONE)); - mp1 = MOJO_HANDLE_INVALID; - - // 5. Close |server_mp|. - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(server_mp)); - - // 9. Read a message from |mp0|, which should have |mp2| attached. - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(mp0, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, &state)); - EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); - EXPECT_EQ(kSignalAll, state.satisfiable_signals); - - memset(buffer, 0, sizeof(buffer)); - num_bytes = static_cast<uint32_t>(sizeof(buffer)); - MojoHandle mp2 = MOJO_HANDLE_INVALID; - uint32_t num_handles = 1; - EXPECT_EQ(MOJO_RESULT_OK, - MojoReadMessage(mp0, buffer, &num_bytes, &mp2, &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE)); - const char kQuux[] = "quux"; - EXPECT_EQ(sizeof(kQuux), num_bytes); - EXPECT_STREQ(kQuux, buffer); - EXPECT_EQ(1u, num_handles); - EXPECT_NE(mp2, MOJO_HANDLE_INVALID); - - // 7. Read a message from |mp2|. - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(mp2, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, &state)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - state.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - state.satisfiable_signals); - - memset(buffer, 0, sizeof(buffer)); - num_bytes = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoReadMessage(mp2, buffer, &num_bytes, nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - const char kBaz[] = "baz"; - EXPECT_EQ(sizeof(kBaz), num_bytes); - EXPECT_STREQ(kBaz, buffer); - - // 10. Close |mp0|. - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mp0)); - -// 12. Wait on |mp2| (which should eventually fail) and then close it. -// TODO(vtl): crbug.com/351768 -#if 0 - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoWait(mp2, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, - &state)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_NONE, state.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_NONE, state.satisfiable_signals); -#endif - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mp2)); - } - - EXPECT_TRUE(multiprocess_test_helper.WaitForChildTestShutdown()); -} - -MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessChannelsClient) { - base::MessageLoop message_loop; - ScopedPlatformHandle client_platform_handle = - std::move(mojo::test::MultiprocessTestHelper::client_platform_handle); - EXPECT_TRUE(client_platform_handle.is_valid()); - - base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); - Init(); - - { - // TODO(vtl): This should eventually initialize a slave process instead, - // probably. - mojo::test::ScopedIPCSupport ipc_support(test_io_thread.task_runner()); - - ScopedTestChannel client_channel(std::move(client_platform_handle)); - MojoHandle client_mp = client_channel.bootstrap_message_pipe(); - EXPECT_NE(client_mp, MOJO_HANDLE_INVALID); - client_channel.WaitForChannelCreationCompletion(); - CHECK(client_channel.channel_info() != nullptr); - - // 1. Read the first message from |client_mp|. - MojoHandleSignalsState state; - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, &state)); - EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); - EXPECT_EQ(kSignalAll, state.satisfiable_signals); - - char buffer[1000] = {}; - uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoReadMessage(client_mp, buffer, &num_bytes, nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - const char kHello[] = "hello"; - EXPECT_EQ(sizeof(kHello), num_bytes); - EXPECT_STREQ(kHello, buffer); - - // 2. Write a message to |client_mp| (attaching nothing). - const char kWorld[] = "world!"; - EXPECT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(client_mp, kWorld, - static_cast<uint32_t>(sizeof(kWorld)), nullptr, - 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // 4. Read a message from |client_mp|, which should have |mp1| attached. - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, &state)); - // The other end of the handle may or may not be closed at this point, so we - // can't test MOJO_HANDLE_SIGNAL_WRITABLE or MOJO_HANDLE_SIGNAL_PEER_CLOSED. - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, - state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, - state.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE); - // TODO(vtl): If the scope were to end here (and |client_mp| closed), we'd - // die (again due to |Channel::HandleLocalError()|). - memset(buffer, 0, sizeof(buffer)); - num_bytes = static_cast<uint32_t>(sizeof(buffer)); - MojoHandle mp1 = MOJO_HANDLE_INVALID; - uint32_t num_handles = 1; - EXPECT_EQ(MOJO_RESULT_OK, - MojoReadMessage(client_mp, buffer, &num_bytes, &mp1, &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE)); - const char kBar[] = "Bar"; - EXPECT_EQ(sizeof(kBar), num_bytes); - EXPECT_STREQ(kBar, buffer); - EXPECT_EQ(1u, num_handles); - EXPECT_NE(mp1, MOJO_HANDLE_INVALID); - // TODO(vtl): If the scope were to end here (and the two handles closed), - // we'd die due to |Channel::RunRemoteMessagePipeEndpoint()| not handling - // write errors (assuming the parent had closed the pipe). - - // 6. Close |client_mp|. - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(client_mp)); - - // Create a new message pipe (endpoints |mp2| and |mp3|). - MojoHandle mp2, mp3; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mp2, &mp3)); - - // 7. Write a message to |mp3|. - const char kBaz[] = "baz"; - EXPECT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(mp3, kBaz, static_cast<uint32_t>(sizeof(kBaz)), - nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // 8. Close |mp3|. - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mp3)); - - // 9. Write a message to |mp1|, attaching |mp2|. - const char kQuux[] = "quux"; - EXPECT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(mp1, kQuux, static_cast<uint32_t>(sizeof(kQuux)), - &mp2, 1, MOJO_WRITE_MESSAGE_FLAG_NONE)); - mp2 = MOJO_HANDLE_INVALID; - - // 3. Read a message from |mp1|. - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, &state)); - EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); - EXPECT_EQ(kSignalAll, state.satisfiable_signals); - - memset(buffer, 0, sizeof(buffer)); - num_bytes = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoReadMessage(mp1, buffer, &num_bytes, nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - const char kFoo[] = "FOO"; - EXPECT_EQ(sizeof(kFoo), num_bytes); - EXPECT_STREQ(kFoo, buffer); - - // 11. Wait on |mp1| (which should eventually fail) and then close it. - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, &state)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mp1)); - } - - EXPECT_TRUE(test::Shutdown()); -} - -// TODO(vtl): Test immediate write & close. -// TODO(vtl): Test broken-connection cases. - -} // namespace -} // namespace embedder -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/embedder/entrypoints.cc b/third_party/mojo/src/mojo/edk/embedder/entrypoints.cc deleted file mode 100644 index 992bbd6..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/entrypoints.cc +++ /dev/null @@ -1,267 +0,0 @@ -// 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 "../../../../../../mojo/edk/embedder/embedder_internal.h" -#include "../../../../../../mojo/edk/system/core.h" -#include "base/command_line.h" -#include "base/lazy_instance.h" -#include "mojo/public/c/system/buffer.h" -#include "mojo/public/c/system/data_pipe.h" -#include "mojo/public/c/system/functions.h" -#include "mojo/public/c/system/message_pipe.h" -#include "mojo/public/c/system/wait_set.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder_internal.h" -#include "third_party/mojo/src/mojo/edk/system/core.h" - -using mojo::embedder::internal::g_core; -using mojo::system::MakeUserPointer; - -namespace { - -struct UseNewEDKChecker { - UseNewEDKChecker() { - use_new = base::CommandLine::ForCurrentProcess()->HasSwitch("use-new-edk"); - } - - bool use_new; -}; - -// This is Leaky to avoid a recursive lock acquisition in AtExitManager. -base::LazyInstance<UseNewEDKChecker>::Leaky g_use_new_checker = - LAZY_INSTANCE_INITIALIZER; - -bool UseNewEDK() { - return g_use_new_checker.Get().use_new; -} - -} // namespace - -// Definitions of the system functions. -extern "C" { -MojoTimeTicks MojoGetTimeTicksNow() { - if (UseNewEDK()) - return mojo::edk::internal::g_core->GetTimeTicksNow(); - return g_core->GetTimeTicksNow(); -} - -MojoResult MojoClose(MojoHandle handle) { - if (UseNewEDK()) - return mojo::edk::internal::g_core->Close(handle); - return g_core->Close(handle); -} - -MojoResult MojoWait(MojoHandle handle, - MojoHandleSignals signals, - MojoDeadline deadline, - MojoHandleSignalsState* signals_state) { - if (UseNewEDK()) - return mojo::edk::internal::g_core->Wait( - handle, signals, deadline, signals_state); - return g_core->Wait(handle, signals, deadline, - MakeUserPointer(signals_state)); -} - -MojoResult MojoWaitMany(const MojoHandle* handles, - const MojoHandleSignals* signals, - uint32_t num_handles, - MojoDeadline deadline, - uint32_t* result_index, - MojoHandleSignalsState* signals_states) { - if (UseNewEDK()) - return mojo::edk::internal::g_core->WaitMany( - handles, signals, num_handles, deadline, result_index, signals_states); - return g_core->WaitMany(MakeUserPointer(handles), MakeUserPointer(signals), - num_handles, deadline, MakeUserPointer(result_index), - MakeUserPointer(signals_states)); -} - -MojoResult MojoCreateWaitSet(MojoHandle* wait_set_handle) { - if (UseNewEDK()) - return mojo::edk::internal::g_core->CreateWaitSet(wait_set_handle); - return g_core->CreateWaitSet(MakeUserPointer(wait_set_handle)); -} - -MojoResult MojoAddHandle(MojoHandle wait_set_handle, - MojoHandle handle, - MojoHandleSignals signals) { - if (UseNewEDK()) - return mojo::edk::internal::g_core->AddHandle(wait_set_handle, handle, - signals); - return g_core->AddHandle(wait_set_handle, handle, signals); -} - -MojoResult MojoRemoveHandle(MojoHandle wait_set_handle, - MojoHandle handle) { - if (UseNewEDK()) - return mojo::edk::internal::g_core->RemoveHandle(wait_set_handle, handle); - return g_core->RemoveHandle(wait_set_handle, handle); -} - -MojoResult MojoGetReadyHandles(MojoHandle wait_set_handle, - uint32_t* count, - MojoHandle* handles, - MojoResult* results, - struct MojoHandleSignalsState *signals_states) { - if (UseNewEDK()) - return mojo::edk::internal::g_core->GetReadyHandles( - wait_set_handle, count, handles, results, signals_states); - return g_core->GetReadyHandles(wait_set_handle, MakeUserPointer(count), - MakeUserPointer(handles), - MakeUserPointer(results), - MakeUserPointer(signals_states)); -} - -MojoResult MojoCreateMessagePipe(const MojoCreateMessagePipeOptions* options, - MojoHandle* message_pipe_handle0, - MojoHandle* message_pipe_handle1) { - if (UseNewEDK()) - return mojo::edk::internal::g_core->CreateMessagePipe( - options, message_pipe_handle0, message_pipe_handle1); - return g_core->CreateMessagePipe(MakeUserPointer(options), - MakeUserPointer(message_pipe_handle0), - MakeUserPointer(message_pipe_handle1)); -} - -MojoResult MojoWriteMessage(MojoHandle message_pipe_handle, - const void* bytes, - uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, - MojoWriteMessageFlags flags) { - if (UseNewEDK()) - return mojo::edk::internal::g_core->WriteMessage( - message_pipe_handle, bytes, num_bytes, handles, num_handles, flags); - return g_core->WriteMessage(message_pipe_handle, MakeUserPointer(bytes), - num_bytes, MakeUserPointer(handles), num_handles, - flags); -} - -MojoResult MojoReadMessage(MojoHandle message_pipe_handle, - void* bytes, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoReadMessageFlags flags) { - if (UseNewEDK()) - return mojo::edk::internal::g_core->ReadMessage( - message_pipe_handle, bytes, num_bytes, handles, num_handles, flags); - return g_core->ReadMessage( - message_pipe_handle, MakeUserPointer(bytes), MakeUserPointer(num_bytes), - MakeUserPointer(handles), MakeUserPointer(num_handles), flags); -} - -MojoResult MojoCreateDataPipe(const MojoCreateDataPipeOptions* options, - MojoHandle* data_pipe_producer_handle, - MojoHandle* data_pipe_consumer_handle) { - if (UseNewEDK()) - return mojo::edk::internal::g_core->CreateDataPipe( - options, data_pipe_producer_handle, data_pipe_consumer_handle); - return g_core->CreateDataPipe(MakeUserPointer(options), - MakeUserPointer(data_pipe_producer_handle), - MakeUserPointer(data_pipe_consumer_handle)); -} - -MojoResult MojoWriteData(MojoHandle data_pipe_producer_handle, - const void* elements, - uint32_t* num_elements, - MojoWriteDataFlags flags) { - if (UseNewEDK()) - return mojo::edk::internal::g_core->WriteData( - data_pipe_producer_handle, elements, num_elements, flags); - return g_core->WriteData(data_pipe_producer_handle, MakeUserPointer(elements), - MakeUserPointer(num_elements), flags); -} - -MojoResult MojoBeginWriteData(MojoHandle data_pipe_producer_handle, - void** buffer, - uint32_t* buffer_num_elements, - MojoWriteDataFlags flags) { - if (UseNewEDK()) - return mojo::edk::internal::g_core->BeginWriteData( - data_pipe_producer_handle, buffer, buffer_num_elements, flags); - return g_core->BeginWriteData(data_pipe_producer_handle, - MakeUserPointer(buffer), - MakeUserPointer(buffer_num_elements), flags); -} - -MojoResult MojoEndWriteData(MojoHandle data_pipe_producer_handle, - uint32_t num_elements_written) { - if (UseNewEDK()) - return mojo::edk::internal::g_core->EndWriteData( - data_pipe_producer_handle, num_elements_written); - return g_core->EndWriteData(data_pipe_producer_handle, num_elements_written); -} - -MojoResult MojoReadData(MojoHandle data_pipe_consumer_handle, - void* elements, - uint32_t* num_elements, - MojoReadDataFlags flags) { - if (UseNewEDK()) - return mojo::edk::internal::g_core->ReadData( - data_pipe_consumer_handle, elements, num_elements, flags); - return g_core->ReadData(data_pipe_consumer_handle, MakeUserPointer(elements), - MakeUserPointer(num_elements), flags); -} - -MojoResult MojoBeginReadData(MojoHandle data_pipe_consumer_handle, - const void** buffer, - uint32_t* buffer_num_elements, - MojoReadDataFlags flags) { - if (UseNewEDK()) - return mojo::edk::internal::g_core->BeginReadData( - data_pipe_consumer_handle, buffer, buffer_num_elements, flags); - return g_core->BeginReadData(data_pipe_consumer_handle, - MakeUserPointer(buffer), - MakeUserPointer(buffer_num_elements), flags); -} - -MojoResult MojoEndReadData(MojoHandle data_pipe_consumer_handle, - uint32_t num_elements_read) { - if (UseNewEDK()) - return mojo::edk::internal::g_core->EndReadData( - data_pipe_consumer_handle, num_elements_read); - return g_core->EndReadData(data_pipe_consumer_handle, num_elements_read); -} - -MojoResult MojoCreateSharedBuffer( - const struct MojoCreateSharedBufferOptions* options, - uint64_t num_bytes, - MojoHandle* shared_buffer_handle) { - if (UseNewEDK()) - return mojo::edk::internal::g_core->CreateSharedBuffer( - options, num_bytes, shared_buffer_handle); - return g_core->CreateSharedBuffer(MakeUserPointer(options), num_bytes, - MakeUserPointer(shared_buffer_handle)); -} - -MojoResult MojoDuplicateBufferHandle( - MojoHandle buffer_handle, - const struct MojoDuplicateBufferHandleOptions* options, - MojoHandle* new_buffer_handle) { - if (UseNewEDK()) - return mojo::edk::internal::g_core->DuplicateBufferHandle( - buffer_handle, options, new_buffer_handle); - return g_core->DuplicateBufferHandle(buffer_handle, MakeUserPointer(options), - MakeUserPointer(new_buffer_handle)); -} - -MojoResult MojoMapBuffer(MojoHandle buffer_handle, - uint64_t offset, - uint64_t num_bytes, - void** buffer, - MojoMapBufferFlags flags) { - if (UseNewEDK()) - return mojo::edk::internal::g_core->MapBuffer( - buffer_handle, offset, num_bytes, buffer, flags); - return g_core->MapBuffer(buffer_handle, offset, num_bytes, - MakeUserPointer(buffer), flags); -} - -MojoResult MojoUnmapBuffer(void* buffer) { - if (UseNewEDK()) - return mojo::edk::internal::g_core->UnmapBuffer(buffer); - return g_core->UnmapBuffer(MakeUserPointer(buffer)); -} - -} // extern "C" diff --git a/third_party/mojo/src/mojo/edk/embedder/master_process_delegate.h b/third_party/mojo/src/mojo/edk/embedder/master_process_delegate.h deleted file mode 100644 index beb59c8..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/master_process_delegate.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2015 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_MASTER_PROCESS_DELEGATE_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_MASTER_PROCESS_DELEGATE_H_ - -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/process_delegate.h" -#include "third_party/mojo/src/mojo/edk/embedder/slave_info.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace embedder { - -// An interface for the master process delegate (which lives in the master -// process). -class MOJO_SYSTEM_IMPL_EXPORT MasterProcessDelegate : public ProcessDelegate { - public: - ProcessType GetType() const override; - - // Called when contact with the slave process specified by |slave_info| has - // been lost. - // TODO(vtl): Obviously, there needs to be a suitable embedder API for - // connecting to a process. What will it be? Mention that here once it exists. - virtual void OnSlaveDisconnect(SlaveInfo slave_info) = 0; - - protected: - MasterProcessDelegate() {} - ~MasterProcessDelegate() override {} - - private: - MOJO_DISALLOW_COPY_AND_ASSIGN(MasterProcessDelegate); -}; - -inline ProcessType MasterProcessDelegate::GetType() const { - return ProcessType::MASTER; -} - -} // namespace embedder -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_MASTER_PROCESS_DELEGATE_H_ diff --git a/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.cc b/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.cc deleted file mode 100644 index 5689dae..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.cc +++ /dev/null @@ -1,34 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" - -#include <utility> - -#include "base/logging.h" - -namespace mojo { -namespace embedder { - -const char PlatformChannelPair::kMojoPlatformChannelHandleSwitch[] = - "mojo-platform-channel-handle"; - -PlatformChannelPair::~PlatformChannelPair() { -} - -ScopedPlatformHandle PlatformChannelPair::PassServerHandle() { - return std::move(server_handle_); -} - -ScopedPlatformHandle PlatformChannelPair::PassClientHandle() { - return std::move(client_handle_); -} - -void PlatformChannelPair::ChildProcessLaunched() { - DCHECK(client_handle_.is_valid()); - client_handle_.reset(); -} - -} // namespace embedder -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h b/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h deleted file mode 100644 index fa32226..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h +++ /dev/null @@ -1,94 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_PAIR_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_PAIR_H_ - -#include "base/memory/scoped_ptr.h" -#include "base/process/launch.h" -#include "build/build_config.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace base { -class CommandLine; -} - -namespace mojo { -namespace embedder { - -// It would be nice to refactor base/process/launch.h to have a more platform- -// independent way of representing handles that are passed to child processes. -#if defined(OS_WIN) -using HandlePassingInformation = base::HandlesToInheritVector; -#elif defined(OS_POSIX) -using HandlePassingInformation = base::FileHandleMappingVector; -#else -#error "Unsupported." -#endif - -// This is used to create a pair of |PlatformHandle|s that are connected by a -// suitable (platform-specific) bidirectional "pipe" (e.g., socket on POSIX, -// named pipe on Windows). The resulting handles can then be used in the same -// process (e.g., in tests) or between processes. (The "server" handle is the -// one that will be used in the process that created the pair, whereas the -// "client" handle is the one that will be used in a different process.) -// -// This class provides facilities for passing the client handle to a child -// process. The parent should call |PrepareToPassClientHandlelToChildProcess()| -// to get the data needed to do this, spawn the child using that data, and then -// call |ChildProcessLaunched()|. Note that on Windows this facility (will) only -// work on Vista and later (TODO(vtl)). -// -// Note: |PlatformChannelPair()|, |PassClientHandleFromParentProcess()| and -// |PrepareToPassClientHandleToChildProcess()| have platform-specific -// implementations. -// -// Note: On POSIX platforms, to write to the "pipe", use -// |PlatformChannel{Write,Writev}()| (from platform_channel_utils_posix.h) -// instead of |write()|, |writev()|, etc. Otherwise, you have to worry about -// platform differences in suppressing |SIGPIPE|. -class MOJO_SYSTEM_IMPL_EXPORT PlatformChannelPair { - public: - PlatformChannelPair(); - ~PlatformChannelPair(); - - ScopedPlatformHandle PassServerHandle(); - - // For in-process use (e.g., in tests or to pass over another channel). - ScopedPlatformHandle PassClientHandle(); - - // To be called in the child process, after the parent process called - // |PrepareToPassClientHandleToChildProcess()| and launched the child (using - // the provided data), to create a client handle connected to the server - // handle (in the parent process). - static ScopedPlatformHandle PassClientHandleFromParentProcess( - const base::CommandLine& command_line); - - // Prepares to pass the client channel to a new child process, to be launched - // using |LaunchProcess()| (from base/launch.h). Modifies |*command_line| and - // |*handle_passing_info| as needed. - // Note: For Windows, this method only works on Vista and later. - void PrepareToPassClientHandleToChildProcess( - base::CommandLine* command_line, - HandlePassingInformation* handle_passing_info) const; - - // To be called once the child process has been successfully launched, to do - // any cleanup necessary. - void ChildProcessLaunched(); - - private: - static const char kMojoPlatformChannelHandleSwitch[]; - - ScopedPlatformHandle server_handle_; - ScopedPlatformHandle client_handle_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(PlatformChannelPair); -}; - -} // namespace embedder -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_PAIR_H_ diff --git a/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair_posix.cc b/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair_posix.cc deleted file mode 100644 index 91dfe6b..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair_posix.cc +++ /dev/null @@ -1,111 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" - -#include <fcntl.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <unistd.h> - -#include "base/command_line.h" -#include "base/logging.h" -#include "base/posix/global_descriptors.h" -#include "base/strings/string_number_conversions.h" -#include "build/build_config.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle.h" - -namespace mojo { -namespace embedder { - -namespace { - -bool IsTargetDescriptorUsed( - const base::FileHandleMappingVector& file_handle_mapping, - int target_fd) { - for (size_t i = 0; i < file_handle_mapping.size(); i++) { - if (file_handle_mapping[i].second == target_fd) - return true; - } - return false; -} - -} // namespace - -PlatformChannelPair::PlatformChannelPair() { - // Create the Unix domain socket and set the ends to nonblocking. - int fds[2]; - // TODO(vtl): Maybe fail gracefully if |socketpair()| fails. - PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0); - PCHECK(fcntl(fds[0], F_SETFL, O_NONBLOCK) == 0); - PCHECK(fcntl(fds[1], F_SETFL, O_NONBLOCK) == 0); - -#if defined(OS_MACOSX) - // This turns off |SIGPIPE| when writing to a closed socket (causing it to - // fail with |EPIPE| instead). On Linux, we have to use |send...()| with - // |MSG_NOSIGNAL| -- which is not supported on Mac -- instead. - int no_sigpipe = 1; - PCHECK(setsockopt(fds[0], SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe, - sizeof(no_sigpipe)) == 0); - PCHECK(setsockopt(fds[1], SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe, - sizeof(no_sigpipe)) == 0); -#endif // defined(OS_MACOSX) - - server_handle_.reset(PlatformHandle(fds[0])); - DCHECK(server_handle_.is_valid()); - client_handle_.reset(PlatformHandle(fds[1])); - DCHECK(client_handle_.is_valid()); -} - -// static -ScopedPlatformHandle PlatformChannelPair::PassClientHandleFromParentProcess( - const base::CommandLine& command_line) { - std::string client_fd_string = - command_line.GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); - int client_fd = -1; - if (client_fd_string.empty() || - !base::StringToInt(client_fd_string, &client_fd) || - client_fd < base::GlobalDescriptors::kBaseDescriptor) { - LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch; - return ScopedPlatformHandle(); - } - - return ScopedPlatformHandle(PlatformHandle(client_fd)); -} - -void PlatformChannelPair::PrepareToPassClientHandleToChildProcess( - base::CommandLine* command_line, - base::FileHandleMappingVector* handle_passing_info) const { - DCHECK(command_line); - DCHECK(handle_passing_info); - // This is an arbitrary sanity check. (Note that this guarantees that the loop - // below will terminate sanely.) - CHECK_LT(handle_passing_info->size(), 1000u); - - DCHECK(client_handle_.is_valid()); - - // Find a suitable FD to map our client handle to in the child process. - // This has quadratic time complexity in the size of |*handle_passing_info|, - // but |*handle_passing_info| should be very small (usually/often empty). - int target_fd = base::GlobalDescriptors::kBaseDescriptor; - while (IsTargetDescriptorUsed(*handle_passing_info, target_fd)) - target_fd++; - - handle_passing_info->push_back( - std::pair<int, int>(client_handle_.get().fd, target_fd)); - // Log a warning if the command line already has the switch, but "clobber" it - // anyway, since it's reasonably likely that all the switches were just copied - // from the parent. - LOG_IF(WARNING, command_line->HasSwitch(kMojoPlatformChannelHandleSwitch)) - << "Child command line already has switch --" - << kMojoPlatformChannelHandleSwitch << "=" - << command_line->GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); - // (Any existing switch won't actually be removed from the command line, but - // the last one appended takes precedence.) - command_line->AppendSwitchASCII(kMojoPlatformChannelHandleSwitch, - base::IntToString(target_fd)); -} - -} // namespace embedder -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc b/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc deleted file mode 100644 index 3bd3f4fa..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc +++ /dev/null @@ -1,269 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" - -#include <errno.h> -#include <poll.h> -#include <signal.h> -#include <stdio.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <sys/uio.h> -#include <unistd.h> -#include <deque> -#include <utility> - -#include "base/files/scoped_file.h" -#include "base/logging.h" -#include "build/build_config.h" -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_utils_posix.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle_vector.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" -#include "third_party/mojo/src/mojo/edk/test/test_utils.h" - -#if defined(OS_ANDROID) -#include "base/android/path_utils.h" -#include "base/files/file_path.h" -#endif - -namespace mojo { -namespace embedder { -namespace { - -void WaitReadable(PlatformHandle h) { - struct pollfd pfds = {}; - pfds.fd = h.fd; - pfds.events = POLLIN; - CHECK_EQ(poll(&pfds, 1, -1), 1); -} - -FILE* NewTmpFile() { -#if defined(OS_ANDROID) - base::FilePath tmpdir; - if (!base::android::GetCacheDirectory(&tmpdir)) - return nullptr; - std::string templ = tmpdir.Append("XXXXXXXX").value(); - int fd = mkstemp(const_cast<char*>(templ.c_str())); - if (fd == -1) - return nullptr; - CHECK(unlink(templ.c_str()) == 0); - return fdopen(fd, "w+"); -#else - return tmpfile(); -#endif -} - -class PlatformChannelPairPosixTest : public testing::Test { - public: - PlatformChannelPairPosixTest() {} - ~PlatformChannelPairPosixTest() override {} - - void SetUp() override { - // Make sure |SIGPIPE| isn't being ignored. - struct sigaction action = {}; - action.sa_handler = SIG_DFL; - ASSERT_EQ(0, sigaction(SIGPIPE, &action, &old_action_)); - } - - void TearDown() override { - // Restore the |SIGPIPE| handler. - ASSERT_EQ(0, sigaction(SIGPIPE, &old_action_, nullptr)); - } - - private: - struct sigaction old_action_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(PlatformChannelPairPosixTest); -}; - -TEST_F(PlatformChannelPairPosixTest, NoSigPipe) { - PlatformChannelPair channel_pair; - ScopedPlatformHandle server_handle = channel_pair.PassServerHandle(); - ScopedPlatformHandle client_handle = channel_pair.PassClientHandle(); - - // Write to the client. - static const char kHello[] = "hello"; - EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)), - write(client_handle.get().fd, kHello, sizeof(kHello))); - - // Close the client. - client_handle.reset(); - - // Read from the server; this should be okay. - char buffer[100] = {}; - EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)), - read(server_handle.get().fd, buffer, sizeof(buffer))); - EXPECT_STREQ(kHello, buffer); - - // Try reading again. - ssize_t result = read(server_handle.get().fd, buffer, sizeof(buffer)); - // We should probably get zero (for "end of file"), but -1 would also be okay. - EXPECT_TRUE(result == 0 || result == -1); - if (result == -1) - PLOG(WARNING) << "read (expected 0 for EOF)"; - - // Test our replacement for |write()|/|send()|. - result = PlatformChannelWrite(server_handle.get(), kHello, sizeof(kHello)); - EXPECT_EQ(-1, result); - if (errno != EPIPE) - PLOG(WARNING) << "write (expected EPIPE)"; - - // Test our replacement for |writev()|/|sendv()|. - struct iovec iov[2] = {{const_cast<char*>(kHello), sizeof(kHello)}, - {const_cast<char*>(kHello), sizeof(kHello)}}; - result = PlatformChannelWritev(server_handle.get(), iov, 2); - EXPECT_EQ(-1, result); - if (errno != EPIPE) - PLOG(WARNING) << "write (expected EPIPE)"; -} - -TEST_F(PlatformChannelPairPosixTest, SendReceiveData) { - PlatformChannelPair channel_pair; - ScopedPlatformHandle server_handle = channel_pair.PassServerHandle(); - ScopedPlatformHandle client_handle = channel_pair.PassClientHandle(); - - for (size_t i = 0; i < 10; i++) { - std::string send_string(1 << i, 'A' + i); - - EXPECT_EQ(static_cast<ssize_t>(send_string.size()), - PlatformChannelWrite(server_handle.get(), send_string.data(), - send_string.size())); - - WaitReadable(client_handle.get()); - - char buf[10000] = {}; - std::deque<PlatformHandle> received_handles; - ssize_t result = PlatformChannelRecvmsg(client_handle.get(), buf, - sizeof(buf), &received_handles); - EXPECT_EQ(static_cast<ssize_t>(send_string.size()), result); - EXPECT_EQ(send_string, std::string(buf, static_cast<size_t>(result))); - EXPECT_TRUE(received_handles.empty()); - } -} - -TEST_F(PlatformChannelPairPosixTest, SendReceiveFDs) { - static const char kHello[] = "hello"; - - PlatformChannelPair channel_pair; - ScopedPlatformHandle server_handle = channel_pair.PassServerHandle(); - ScopedPlatformHandle client_handle = channel_pair.PassClientHandle(); - -// Reduce the number of FDs opened on OS X to avoid test flake. -#if defined(OS_MACOSX) - const size_t kNumHandlesToSend = kPlatformChannelMaxNumHandles / 2; -#else - const size_t kNumHandlesToSend = kPlatformChannelMaxNumHandles; -#endif - - for (size_t i = 1; i < kNumHandlesToSend; i++) { - // Make |i| files, with the j-th file consisting of j copies of the digit - // |c|. - const char c = '0' + (i % 10); - ScopedPlatformHandleVectorPtr platform_handles(new PlatformHandleVector); - for (size_t j = 1; j <= i; j++) { - base::ScopedFILE fp(NewTmpFile()); - ASSERT_TRUE(fp); - ASSERT_EQ(j, fwrite(std::string(j, c).data(), 1, j, fp.get())); - platform_handles->push_back( - test::PlatformHandleFromFILE(std::move(fp)).release()); - ASSERT_TRUE(platform_handles->back().is_valid()); - } - - // Send the FDs (+ "hello"). - struct iovec iov = {const_cast<char*>(kHello), sizeof(kHello)}; - // We assume that the |sendmsg()| actually sends all the data. - EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)), - PlatformChannelSendmsgWithHandles(server_handle.get(), &iov, 1, - &platform_handles->at(0), - platform_handles->size())); - - WaitReadable(client_handle.get()); - - char buf[10000] = {}; - std::deque<PlatformHandle> received_handles; - // We assume that the |recvmsg()| actually reads all the data. - EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)), - PlatformChannelRecvmsg(client_handle.get(), buf, sizeof(buf), - &received_handles)); - EXPECT_STREQ(kHello, buf); - EXPECT_EQ(i, received_handles.size()); - - for (size_t j = 0; !received_handles.empty(); j++) { - base::ScopedFILE fp(test::FILEFromPlatformHandle( - ScopedPlatformHandle(received_handles.front()), "rb")); - received_handles.pop_front(); - ASSERT_TRUE(fp); - rewind(fp.get()); - char read_buf[kNumHandlesToSend]; - size_t bytes_read = fread(read_buf, 1, sizeof(read_buf), fp.get()); - EXPECT_EQ(j + 1, bytes_read); - EXPECT_EQ(std::string(j + 1, c), std::string(read_buf, bytes_read)); - } - } -} - -TEST_F(PlatformChannelPairPosixTest, AppendReceivedFDs) { - static const char kHello[] = "hello"; - - PlatformChannelPair channel_pair; - ScopedPlatformHandle server_handle = channel_pair.PassServerHandle(); - ScopedPlatformHandle client_handle = channel_pair.PassClientHandle(); - - const std::string file_contents("hello world"); - - { - base::ScopedFILE fp(NewTmpFile()); - ASSERT_TRUE(fp); - ASSERT_EQ(file_contents.size(), - fwrite(file_contents.data(), 1, file_contents.size(), fp.get())); - ScopedPlatformHandleVectorPtr platform_handles(new PlatformHandleVector); - platform_handles->push_back( - test::PlatformHandleFromFILE(std::move(fp)).release()); - ASSERT_TRUE(platform_handles->back().is_valid()); - - // Send the FD (+ "hello"). - struct iovec iov = {const_cast<char*>(kHello), sizeof(kHello)}; - // We assume that the |sendmsg()| actually sends all the data. - EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)), - PlatformChannelSendmsgWithHandles(server_handle.get(), &iov, 1, - &platform_handles->at(0), - platform_handles->size())); - } - - WaitReadable(client_handle.get()); - - // Start with an invalid handle in the deque. - std::deque<PlatformHandle> received_handles; - received_handles.push_back(PlatformHandle()); - - char buf[100] = {}; - // We assume that the |recvmsg()| actually reads all the data. - EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)), - PlatformChannelRecvmsg(client_handle.get(), buf, sizeof(buf), - &received_handles)); - EXPECT_STREQ(kHello, buf); - ASSERT_EQ(2u, received_handles.size()); - EXPECT_FALSE(received_handles[0].is_valid()); - EXPECT_TRUE(received_handles[1].is_valid()); - - { - base::ScopedFILE fp(test::FILEFromPlatformHandle( - ScopedPlatformHandle(received_handles[1]), "rb")); - received_handles[1] = PlatformHandle(); - ASSERT_TRUE(fp); - rewind(fp.get()); - char read_buf[100]; - size_t bytes_read = fread(read_buf, 1, sizeof(read_buf), fp.get()); - EXPECT_EQ(file_contents.size(), bytes_read); - EXPECT_EQ(file_contents, std::string(read_buf, bytes_read)); - } -} - -} // namespace -} // namespace embedder -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair_win.cc b/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair_win.cc deleted file mode 100644 index 2073ebb..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair_win.cc +++ /dev/null @@ -1,111 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" - -#include <windows.h> - -#include <string> - -#include "base/command_line.h" -#include "base/logging.h" -#include "base/rand_util.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" -#include "base/win/windows_version.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle.h" - -namespace mojo { -namespace embedder { - -namespace { - -std::wstring GeneratePipeName() { - return base::StringPrintf(L"\\\\.\\pipe\\mojo.%u.%u.%I64u", - GetCurrentProcessId(), GetCurrentThreadId(), - base::RandUint64()); -} - -} // namespace - -PlatformChannelPair::PlatformChannelPair() { - std::wstring pipe_name = GeneratePipeName(); - - const DWORD kOpenMode = - PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE; - const DWORD kPipeMode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE; - server_handle_.reset(PlatformHandle( - CreateNamedPipeW(pipe_name.c_str(), kOpenMode, kPipeMode, - 1, // Max instances. - 4096, // Out buffer size. - 4096, // In buffer size. - 5000, // Timeout in milliseconds. - nullptr))); // Default security descriptor. - PCHECK(server_handle_.is_valid()); - - const DWORD kDesiredAccess = GENERIC_READ | GENERIC_WRITE; - // The SECURITY_ANONYMOUS flag means that the server side cannot impersonate - // the client. - const DWORD kFlags = - SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS | FILE_FLAG_OVERLAPPED; - // Allow the handle to be inherited by child processes. - SECURITY_ATTRIBUTES security_attributes = { - sizeof(SECURITY_ATTRIBUTES), nullptr, TRUE}; - client_handle_.reset( - PlatformHandle(CreateFileW(pipe_name.c_str(), kDesiredAccess, - 0, // No sharing. - &security_attributes, OPEN_EXISTING, kFlags, - nullptr))); // No template file. - PCHECK(client_handle_.is_valid()); - - // Since a client has connected, ConnectNamedPipe() should return zero and - // GetLastError() should return ERROR_PIPE_CONNECTED. - CHECK(!ConnectNamedPipe(server_handle_.get().handle, nullptr)); - PCHECK(GetLastError() == ERROR_PIPE_CONNECTED); -} - -// static -ScopedPlatformHandle PlatformChannelPair::PassClientHandleFromParentProcess( - const base::CommandLine& command_line) { - std::string client_handle_string = - command_line.GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); - - int client_handle_value = 0; - if (client_handle_string.empty() || - !base::StringToInt(client_handle_string, &client_handle_value)) { - LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch; - return ScopedPlatformHandle(); - } - - return ScopedPlatformHandle( - PlatformHandle(LongToHandle(client_handle_value))); -} - -void PlatformChannelPair::PrepareToPassClientHandleToChildProcess( - base::CommandLine* command_line, - base::HandlesToInheritVector* handle_passing_info) const { - DCHECK(command_line); - DCHECK(handle_passing_info); - DCHECK(client_handle_.is_valid()); - - CHECK_GE(base::win::GetVersion(), base::win::VERSION_VISTA); - - handle_passing_info->push_back(client_handle_.get().handle); - - // Log a warning if the command line already has the switch, but "clobber" it - // anyway, since it's reasonably likely that all the switches were just copied - // from the parent. - LOG_IF(WARNING, command_line->HasSwitch(kMojoPlatformChannelHandleSwitch)) - << "Child command line already has switch --" - << kMojoPlatformChannelHandleSwitch << "=" - << command_line->GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); - // (Any existing switch won't actually be removed from the command line, but - // the last one appended takes precedence.) - command_line->AppendSwitchASCII( - kMojoPlatformChannelHandleSwitch, - base::IntToString(HandleToLong(client_handle_.get().handle))); -} - -} // namespace embedder -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/embedder/platform_channel_utils_posix.cc b/third_party/mojo/src/mojo/edk/embedder/platform_channel_utils_posix.cc deleted file mode 100644 index 2b2f4c7..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/platform_channel_utils_posix.cc +++ /dev/null @@ -1,186 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/embedder/platform_channel_utils_posix.h" - -#include <sys/socket.h> -#include <sys/uio.h> -#include <unistd.h> - -#include "base/logging.h" -#include "base/posix/eintr_wrapper.h" -#include "build/build_config.h" - -namespace mojo { -namespace embedder { - -// On Linux, |SIGPIPE| is suppressed by passing |MSG_NOSIGNAL| to -// |send()|/|sendmsg()|. (There is no way of suppressing |SIGPIPE| on -// |write()|/|writev().) On Mac, |SIGPIPE| is suppressed by setting the -// |SO_NOSIGPIPE| option on the socket. -// -// Performance notes: -// - On Linux, we have to use |send()|/|sendmsg()| rather than -// |write()|/|writev()| in order to suppress |SIGPIPE|. This is okay, since -// |send()| is (slightly) faster than |write()| (!), while |sendmsg()| is -// quite comparable to |writev()|. -// - On Mac, we may use |write()|/|writev()|. Here, |write()| is considerably -// faster than |send()|, whereas |sendmsg()| is quite comparable to -// |writev()|. -// - On both platforms, an appropriate |sendmsg()|/|writev()| is considerably -// faster than two |send()|s/|write()|s. -// - Relative numbers (minimum real times from 10 runs) for one |write()| of -// 1032 bytes, one |send()| of 1032 bytes, one |writev()| of 32+1000 bytes, -// one |sendmsg()| of 32+1000 bytes, two |write()|s of 32 and 1000 bytes, two -// |send()|s of 32 and 1000 bytes: -// - Linux: 0.81 s, 0.77 s, 0.87 s, 0.89 s, 1.31 s, 1.22 s -// - Mac: 2.21 s, 2.91 s, 2.98 s, 3.08 s, 3.59 s, 4.74 s - -// Flags to use with calling |send()| or |sendmsg()| (see above). -#if defined(OS_MACOSX) -const int kSendFlags = 0; -#else -const int kSendFlags = MSG_NOSIGNAL; -#endif - -ssize_t PlatformChannelWrite(PlatformHandle h, - const void* bytes, - size_t num_bytes) { - DCHECK(h.is_valid()); - DCHECK(bytes); - DCHECK_GT(num_bytes, 0u); - -#if defined(OS_MACOSX) - return HANDLE_EINTR(write(h.fd, bytes, num_bytes)); -#else - return send(h.fd, bytes, num_bytes, kSendFlags); -#endif -} - -ssize_t PlatformChannelWritev(PlatformHandle h, - struct iovec* iov, - size_t num_iov) { - DCHECK(h.is_valid()); - DCHECK(iov); - DCHECK_GT(num_iov, 0u); - -#if defined(OS_MACOSX) - return HANDLE_EINTR(writev(h.fd, iov, static_cast<int>(num_iov))); -#else - struct msghdr msg = {}; - msg.msg_iov = iov; - msg.msg_iovlen = num_iov; - return HANDLE_EINTR(sendmsg(h.fd, &msg, kSendFlags)); -#endif -} - -ssize_t PlatformChannelSendmsgWithHandles(PlatformHandle h, - struct iovec* iov, - size_t num_iov, - PlatformHandle* platform_handles, - size_t num_platform_handles) { - DCHECK(iov); - DCHECK_GT(num_iov, 0u); - DCHECK(platform_handles); - DCHECK_GT(num_platform_handles, 0u); - DCHECK_LE(num_platform_handles, kPlatformChannelMaxNumHandles); - - char cmsg_buf[CMSG_SPACE(kPlatformChannelMaxNumHandles * sizeof(int))]; - struct msghdr msg = {}; - msg.msg_iov = iov; - msg.msg_iovlen = num_iov; - msg.msg_control = cmsg_buf; - msg.msg_controllen = CMSG_LEN(num_platform_handles * sizeof(int)); - struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(num_platform_handles * sizeof(int)); - for (size_t i = 0; i < num_platform_handles; i++) { - DCHECK(platform_handles[i].is_valid()); - reinterpret_cast<int*>(CMSG_DATA(cmsg))[i] = platform_handles[i].fd; - } - - return HANDLE_EINTR(sendmsg(h.fd, &msg, kSendFlags)); -} - -bool PlatformChannelSendHandles(PlatformHandle h, - PlatformHandle* handles, - size_t num_handles) { - DCHECK(handles); - DCHECK_GT(num_handles, 0u); - DCHECK_LE(num_handles, kPlatformChannelMaxNumHandles); - - // Note: |sendmsg()| fails on Mac if we don't write at least one character. - struct iovec iov = {const_cast<char*>(""), 1}; - char cmsg_buf[CMSG_SPACE(kPlatformChannelMaxNumHandles * sizeof(int))]; - struct msghdr msg = {}; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = cmsg_buf; - msg.msg_controllen = CMSG_LEN(num_handles * sizeof(int)); - struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(num_handles * sizeof(int)); - for (size_t i = 0; i < num_handles; i++) { - DCHECK(handles[i].is_valid()); - reinterpret_cast<int*>(CMSG_DATA(cmsg))[i] = handles[i].fd; - } - - ssize_t result = HANDLE_EINTR(sendmsg(h.fd, &msg, kSendFlags)); - if (result < 1) { - DCHECK_EQ(result, -1); - return false; - } - - for (size_t i = 0; i < num_handles; i++) - handles[i].CloseIfNecessary(); - return true; -} - -ssize_t PlatformChannelRecvmsg(PlatformHandle h, - void* buf, - size_t num_bytes, - std::deque<PlatformHandle>* platform_handles) { - DCHECK(buf); - DCHECK_GT(num_bytes, 0u); - DCHECK(platform_handles); - - struct iovec iov = {buf, num_bytes}; - char cmsg_buf[CMSG_SPACE(kPlatformChannelMaxNumHandles * sizeof(int))]; - struct msghdr msg = {}; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = cmsg_buf; - msg.msg_controllen = sizeof(cmsg_buf); - - ssize_t result = HANDLE_EINTR(recvmsg(h.fd, &msg, MSG_DONTWAIT)); - if (result < 0) - return result; - - // Success; no control messages. - if (msg.msg_controllen == 0) - return result; - - DCHECK(!(msg.msg_flags & MSG_CTRUNC)); - - for (cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg; - cmsg = CMSG_NXTHDR(&msg, cmsg)) { - if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { - size_t payload_length = cmsg->cmsg_len - CMSG_LEN(0); - DCHECK_EQ(payload_length % sizeof(int), 0u); - size_t num_fds = payload_length / sizeof(int); - const int* fds = reinterpret_cast<int*>(CMSG_DATA(cmsg)); - for (size_t i = 0; i < num_fds; i++) { - platform_handles->push_back(PlatformHandle(fds[i])); - DCHECK(platform_handles->back().is_valid()); - } - } - } - - return result; -} - -} // namespace embedder -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/embedder/platform_channel_utils_posix.h b/third_party/mojo/src/mojo/edk/embedder/platform_channel_utils_posix.h deleted file mode 100644 index 5ec524a..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/platform_channel_utils_posix.h +++ /dev/null @@ -1,76 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_UTILS_POSIX_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_UTILS_POSIX_H_ - -#include <stddef.h> -#include <sys/types.h> // For |ssize_t|. - -#include <deque> - -#include "base/memory/scoped_ptr.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -struct iovec; // Declared in <sys/uio.h>. - -namespace mojo { -namespace embedder { - -// The maximum number of handles that can be sent "at once" using -// |PlatformChannelSendmsgWithHandles()|. -// TODO(vtl): This number is taken from ipc/ipc_message_attachment_set.h: -// |IPC::MessageAttachmentSet::kMaxDescriptorsPerMessage|. -const size_t kPlatformChannelMaxNumHandles = 128; - -// Use these to write to a socket created using |PlatformChannelPair| (or -// equivalent). These are like |write()| and |writev()|, but handle |EINTR| and -// never raise |SIGPIPE|. (Note: On Mac, the suppression of |SIGPIPE| is set up -// by |PlatformChannelPair|.) -MOJO_SYSTEM_IMPL_EXPORT ssize_t -PlatformChannelWrite(PlatformHandle h, const void* bytes, size_t num_bytes); -MOJO_SYSTEM_IMPL_EXPORT ssize_t -PlatformChannelWritev(PlatformHandle h, struct iovec* iov, size_t num_iov); - -// Writes data, and the given set of |PlatformHandle|s (i.e., file descriptors) -// over the Unix domain socket given by |h| (e.g., created using -// |PlatformChannelPair()|). All the handles must be valid, and there must be at -// least one and at most |kPlatformChannelMaxNumHandles| handles. The return -// value is as for |sendmsg()|, namely -1 on failure and otherwise the number of -// bytes of data sent on success (note that this may not be all the data -// specified by |iov|). (The handles are not closed, regardless of success or -// failure.) -MOJO_SYSTEM_IMPL_EXPORT ssize_t -PlatformChannelSendmsgWithHandles(PlatformHandle h, - struct iovec* iov, - size_t num_iov, - PlatformHandle* platform_handles, - size_t num_platform_handles); - -// TODO(vtl): Remove this once I've switched things over to -// |PlatformChannelSendmsgWithHandles()|. -// Sends |PlatformHandle|s (i.e., file descriptors) over the Unix domain socket -// (e.g., created using PlatformChannelPair|). (These will be sent in a single -// message having one null byte of data and one control message header with all -// the file descriptors.) All of the handles must be valid, and there must be at -// most |kPlatformChannelMaxNumHandles| (and at least one handle). Returns true -// on success, in which case it closes all the handles. -MOJO_SYSTEM_IMPL_EXPORT bool PlatformChannelSendHandles(PlatformHandle h, - PlatformHandle* handles, - size_t num_handles); - -// Wrapper around |recvmsg()|, which will extract any attached file descriptors -// (in the control message) to |PlatformHandle|s (and append them to -// |platform_handles|). (This also handles |EINTR|.) -MOJO_SYSTEM_IMPL_EXPORT ssize_t -PlatformChannelRecvmsg(PlatformHandle h, - void* buf, - size_t num_bytes, - std::deque<PlatformHandle>* platform_handles); - -} // namespace embedder -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_UTILS_POSIX_H_ diff --git a/third_party/mojo/src/mojo/edk/embedder/platform_handle.cc b/third_party/mojo/src/mojo/edk/embedder/platform_handle.cc deleted file mode 100644 index 284cbb5..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/platform_handle.cc +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/embedder/platform_handle.h" - -#include "build/build_config.h" -#if defined(OS_POSIX) -#include <unistd.h> -#elif defined(OS_WIN) -#include <windows.h> -#else -#error "Platform not yet supported." -#endif - -#include "base/logging.h" - -namespace mojo { -namespace embedder { - -void PlatformHandle::CloseIfNecessary() { - if (!is_valid()) - return; - -#if defined(OS_POSIX) - bool success = (close(fd) == 0); - DPCHECK(success); - fd = -1; -#elif defined(OS_WIN) - bool success = !!CloseHandle(handle); - DPCHECK(success); - handle = INVALID_HANDLE_VALUE; -#else -#error "Platform not yet supported." -#endif -} - -} // namespace embedder -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/embedder/platform_handle.h b/third_party/mojo/src/mojo/edk/embedder/platform_handle.h deleted file mode 100644 index aecc58b..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/platform_handle.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_H_ - -#include "build/build_config.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -#if defined(OS_WIN) -#include <windows.h> -#endif - -namespace mojo { -namespace embedder { - -#if defined(OS_POSIX) -struct MOJO_SYSTEM_IMPL_EXPORT PlatformHandle { - PlatformHandle() : fd(-1) {} - explicit PlatformHandle(int fd) : fd(fd) {} - - void CloseIfNecessary(); - - bool is_valid() const { return fd != -1; } - - int fd; -}; -#elif defined(OS_WIN) -struct MOJO_SYSTEM_IMPL_EXPORT PlatformHandle { - PlatformHandle() : handle(INVALID_HANDLE_VALUE) {} - explicit PlatformHandle(HANDLE handle) : handle(handle) {} - - void CloseIfNecessary(); - - bool is_valid() const { return handle != INVALID_HANDLE_VALUE; } - - HANDLE handle; -}; -#else -#error "Platform not yet supported." -#endif - -} // namespace embedder -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_H_ diff --git a/third_party/mojo/src/mojo/edk/embedder/platform_handle_utils.h b/third_party/mojo/src/mojo/edk/embedder/platform_handle_utils.h deleted file mode 100644 index b0118ce..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/platform_handle_utils.h +++ /dev/null @@ -1,33 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_UTILS_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_UTILS_H_ - -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace embedder { - -// Closes all the |PlatformHandle|s in the given container. -template <typename PlatformHandleContainer> -MOJO_SYSTEM_IMPL_EXPORT inline void CloseAllPlatformHandles( - PlatformHandleContainer* platform_handles) { - for (typename PlatformHandleContainer::iterator it = - platform_handles->begin(); - it != platform_handles->end(); ++it) - it->CloseIfNecessary(); -} - -// Duplicates the given |PlatformHandle| (which must be valid). (Returns an -// invalid |ScopedPlatformHandle| on failure.) -MOJO_SYSTEM_IMPL_EXPORT ScopedPlatformHandle -DuplicatePlatformHandle(PlatformHandle platform_handle); - -} // namespace embedder -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_UTILS_H_ diff --git a/third_party/mojo/src/mojo/edk/embedder/platform_handle_utils_posix.cc b/third_party/mojo/src/mojo/edk/embedder/platform_handle_utils_posix.cc deleted file mode 100644 index 2f03def..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/platform_handle_utils_posix.cc +++ /dev/null @@ -1,22 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/embedder/platform_handle_utils.h" - -#include <unistd.h> - -#include "base/logging.h" - -namespace mojo { -namespace embedder { - -ScopedPlatformHandle DuplicatePlatformHandle(PlatformHandle platform_handle) { - DCHECK(platform_handle.is_valid()); - // Note that |dup()| returns -1 on error (which is exactly the value we use - // for invalid |PlatformHandle| FDs). - return ScopedPlatformHandle(PlatformHandle(dup(platform_handle.fd))); -} - -} // namespace embedder -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/embedder/platform_handle_utils_win.cc b/third_party/mojo/src/mojo/edk/embedder/platform_handle_utils_win.cc deleted file mode 100644 index 9e2d67d..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/platform_handle_utils_win.cc +++ /dev/null @@ -1,27 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/embedder/platform_handle_utils.h" - -#include <windows.h> - -#include "base/logging.h" - -namespace mojo { -namespace embedder { - -ScopedPlatformHandle DuplicatePlatformHandle(PlatformHandle platform_handle) { - DCHECK(platform_handle.is_valid()); - - HANDLE new_handle; - if (!DuplicateHandle(GetCurrentProcess(), platform_handle.handle, - GetCurrentProcess(), &new_handle, 0, TRUE, - DUPLICATE_SAME_ACCESS)) - return ScopedPlatformHandle(); - DCHECK_NE(new_handle, INVALID_HANDLE_VALUE); - return ScopedPlatformHandle(PlatformHandle(new_handle)); -} - -} // namespace embedder -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/embedder/platform_handle_vector.h b/third_party/mojo/src/mojo/edk/embedder/platform_handle_vector.h deleted file mode 100644 index e93176b..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/platform_handle_vector.h +++ /dev/null @@ -1,35 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_VECTOR_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_VECTOR_H_ - -#include <vector> - -#include "base/memory/scoped_ptr.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle_utils.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace embedder { - -using PlatformHandleVector = std::vector<PlatformHandle>; - -// A deleter (for use with |scoped_ptr|) which closes all handles and then -// |delete|s the |PlatformHandleVector|. -struct MOJO_SYSTEM_IMPL_EXPORT PlatformHandleVectorDeleter { - void operator()(PlatformHandleVector* platform_handles) const { - CloseAllPlatformHandles(platform_handles); - delete platform_handles; - } -}; - -using ScopedPlatformHandleVectorPtr = - scoped_ptr<PlatformHandleVector, PlatformHandleVectorDeleter>; - -} // namespace embedder -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_VECTOR_H_ diff --git a/third_party/mojo/src/mojo/edk/embedder/platform_shared_buffer.h b/third_party/mojo/src/mojo/edk/embedder/platform_shared_buffer.h deleted file mode 100644 index da22cf5..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/platform_shared_buffer.h +++ /dev/null @@ -1,102 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PLATFORM_SHARED_BUFFER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PLATFORM_SHARED_BUFFER_H_ - -#include <stddef.h> - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace embedder { - -class PlatformSharedBufferMapping; - -// |PlatformSharedBuffer| is an interface for a thread-safe, ref-counted wrapper -// around OS-specific shared memory. It has the following features: -// - A |PlatformSharedBuffer| simply represents a piece of shared memory that -// *may* be mapped and *may* be shared to another process. -// - A single |PlatformSharedBuffer| may be mapped multiple times. The -// lifetime of the mapping (owned by |PlatformSharedBufferMapping|) is -// separate from the lifetime of the |PlatformSharedBuffer|. -// - Sizes/offsets (of the shared memory and mappings) are arbitrary, and not -// restricted by page size. However, more memory may actually be mapped than -// requested. -// -// It currently does NOT support the following: -// - Sharing read-only. (This will probably eventually be supported.) -// -// TODO(vtl): Rectify this with |base::SharedMemory|. -class MOJO_SYSTEM_IMPL_EXPORT PlatformSharedBuffer - : public base::RefCountedThreadSafe<PlatformSharedBuffer> { - public: - // Gets the size of shared buffer (in number of bytes). - virtual size_t GetNumBytes() const = 0; - - // Maps (some) of the shared buffer into memory; [|offset|, |offset + length|] - // must be contained in [0, |num_bytes|], and |length| must be at least 1. - // Returns null on failure. - virtual scoped_ptr<PlatformSharedBufferMapping> Map(size_t offset, - size_t length) = 0; - - // Checks if |offset| and |length| are valid arguments. - virtual bool IsValidMap(size_t offset, size_t length) = 0; - - // Like |Map()|, but doesn't check its arguments (which should have been - // preflighted using |IsValidMap()|). - virtual scoped_ptr<PlatformSharedBufferMapping> MapNoCheck(size_t offset, - size_t length) = 0; - - // Duplicates the underlying platform handle and passes it to the caller. - // TODO(vtl): On POSIX, we'll need two FDs to support sharing read-only. - virtual ScopedPlatformHandle DuplicatePlatformHandle() = 0; - - // Passes the underlying platform handle to the caller. This should only be - // called if there's a unique reference to this object (owned by the caller). - // After calling this, this object should no longer be used, but should only - // be disposed of. - virtual ScopedPlatformHandle PassPlatformHandle() = 0; - - protected: - friend class base::RefCountedThreadSafe<PlatformSharedBuffer>; - - PlatformSharedBuffer() {} - virtual ~PlatformSharedBuffer() {} - - private: - MOJO_DISALLOW_COPY_AND_ASSIGN(PlatformSharedBuffer); -}; - -// An interface for a mapping of a |PlatformSharedBuffer| (compararable to a -// "file view" in Windows); see above. Created by (implementations of) -// |PlatformSharedBuffer::Map()|. Automatically unmaps memory on destruction. -// -// Mappings are NOT thread-safe. -// -// Note: This is an entirely separate class (instead of -// |PlatformSharedBuffer::Mapping|) so that it can be forward-declared. -class MOJO_SYSTEM_IMPL_EXPORT PlatformSharedBufferMapping { - public: - // IMPORTANT: Implementations must implement a destructor that unmaps memory. - virtual ~PlatformSharedBufferMapping() {} - - virtual void* GetBase() const = 0; - virtual size_t GetLength() const = 0; - - protected: - PlatformSharedBufferMapping() {} - - private: - MOJO_DISALLOW_COPY_AND_ASSIGN(PlatformSharedBufferMapping); -}; - -} // namespace embedder -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PLATFORM_SHARED_BUFFER_H_ diff --git a/third_party/mojo/src/mojo/edk/embedder/platform_support.h b/third_party/mojo/src/mojo/edk/embedder/platform_support.h deleted file mode 100644 index fb8259b..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/platform_support.h +++ /dev/null @@ -1,43 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PLATFORM_SUPPORT_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PLATFORM_SUPPORT_H_ - -#include <stddef.h> - -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace embedder { - -class PlatformSharedBuffer; - -// This class is provided by the embedder to implement (typically -// platform-dependent) things needed by the Mojo system implementation. -// Implementations must be thread-safe. -class MOJO_SYSTEM_IMPL_EXPORT PlatformSupport { - public: - virtual ~PlatformSupport() {} - - virtual void GetCryptoRandomBytes(void* bytes, size_t num_bytes) = 0; - - virtual PlatformSharedBuffer* CreateSharedBuffer(size_t num_bytes) = 0; - virtual PlatformSharedBuffer* CreateSharedBufferFromHandle( - size_t num_bytes, - ScopedPlatformHandle platform_handle) = 0; - - protected: - PlatformSupport() {} - - private: - MOJO_DISALLOW_COPY_AND_ASSIGN(PlatformSupport); -}; - -} // namespace embedder -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PLATFORM_SUPPORT_H_ diff --git a/third_party/mojo/src/mojo/edk/embedder/process_delegate.h b/third_party/mojo/src/mojo/edk/embedder/process_delegate.h deleted file mode 100644 index e00591f..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/process_delegate.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2015 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PROCESS_DELEGATE_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PROCESS_DELEGATE_H_ - -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/process_type.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace embedder { - -// An interface for process delegates. -class MOJO_SYSTEM_IMPL_EXPORT ProcessDelegate { - public: - virtual ProcessType GetType() const; - - // Called when |ShutdownIPCSupport()| has "completed". Note that this is NOT - // called if |ShutdownIPCSupportOnIOThread()| is used instead. - virtual void OnShutdownComplete() = 0; - - protected: - ProcessDelegate() {} - virtual ~ProcessDelegate() {} - - private: - MOJO_DISALLOW_COPY_AND_ASSIGN(ProcessDelegate); -}; - -inline ProcessType ProcessDelegate::GetType() const { - return ProcessType::NONE; -} - -} // namespace embedder -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PROCESS_DELEGATE_H_ diff --git a/third_party/mojo/src/mojo/edk/embedder/process_type.h b/third_party/mojo/src/mojo/edk/embedder/process_type.h deleted file mode 100644 index e201c66..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/process_type.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2015 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PROCESS_TYPE_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PROCESS_TYPE_H_ - -#include <ostream> - -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace embedder { - -enum class ProcessType { - // |InitIPCSupport()| has not been called (or |ShutdownIPCSupport()| has been - // called). - UNINITIALIZED, - // Process without connection management. - NONE, - // Master process. - MASTER, - // Slave process. - SLAVE, -}; - -// So logging macros and |DCHECK_EQ()|, etc. work. -MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<( - std::ostream& out, - ProcessType process_type) { - return out << static_cast<int>(process_type); -} - -} // namespace embedder -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_PROCESS_TYPE_H_ diff --git a/third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h b/third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h deleted file mode 100644 index 2f3c001..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h +++ /dev/null @@ -1,62 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_SCOPED_PLATFORM_HANDLE_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_SCOPED_PLATFORM_HANDLE_H_ - -#include "base/move.h" -#include "mojo/public/c/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace embedder { - -class MOJO_SYSTEM_IMPL_EXPORT ScopedPlatformHandle { - DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(ScopedPlatformHandle) - - public: - ScopedPlatformHandle() {} - explicit ScopedPlatformHandle(PlatformHandle handle) : handle_(handle) {} - ~ScopedPlatformHandle() { handle_.CloseIfNecessary(); } - - // Move-only constructor and operator=. - ScopedPlatformHandle(ScopedPlatformHandle&& other) - : handle_(other.release()) {} - - ScopedPlatformHandle& operator=(ScopedPlatformHandle&& other) { - if (this != &other) - handle_ = other.release(); - return *this; - } - - const PlatformHandle& get() const { return handle_; } - - void swap(ScopedPlatformHandle& other) { - PlatformHandle temp = handle_; - handle_ = other.handle_; - other.handle_ = temp; - } - - PlatformHandle release() MOJO_WARN_UNUSED_RESULT { - PlatformHandle rv = handle_; - handle_ = PlatformHandle(); - return rv; - } - - void reset(PlatformHandle handle = PlatformHandle()) { - handle_.CloseIfNecessary(); - handle_ = handle; - } - - bool is_valid() const { return handle_.is_valid(); } - - private: - PlatformHandle handle_; -}; - -} // namespace embedder -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_SCOPED_PLATFORM_HANDLE_H_ diff --git a/third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer.cc b/third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer.cc deleted file mode 100644 index a1dca82..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer.cc +++ /dev/null @@ -1,110 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer.h" - -#include <utility> - -#include "base/logging.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle_utils.h" - -namespace mojo { -namespace embedder { - -// static -SimplePlatformSharedBuffer* SimplePlatformSharedBuffer::Create( - size_t num_bytes) { - DCHECK_GT(num_bytes, 0u); - - SimplePlatformSharedBuffer* rv = new SimplePlatformSharedBuffer(num_bytes); - if (!rv->Init()) { - // We can't just delete it directly, due to the "in destructor" (debug) - // check. - scoped_refptr<SimplePlatformSharedBuffer> deleter(rv); - return nullptr; - } - - return rv; -} - -// static -SimplePlatformSharedBuffer* -SimplePlatformSharedBuffer::CreateFromPlatformHandle( - size_t num_bytes, - ScopedPlatformHandle platform_handle) { - DCHECK_GT(num_bytes, 0u); - - SimplePlatformSharedBuffer* rv = new SimplePlatformSharedBuffer(num_bytes); - if (!rv->InitFromPlatformHandle(std::move(platform_handle))) { - // We can't just delete it directly, due to the "in destructor" (debug) - // check. - scoped_refptr<SimplePlatformSharedBuffer> deleter(rv); - return nullptr; - } - - return rv; -} - -size_t SimplePlatformSharedBuffer::GetNumBytes() const { - return num_bytes_; -} - -scoped_ptr<PlatformSharedBufferMapping> SimplePlatformSharedBuffer::Map( - size_t offset, - size_t length) { - if (!IsValidMap(offset, length)) - return nullptr; - - return MapNoCheck(offset, length); -} - -bool SimplePlatformSharedBuffer::IsValidMap(size_t offset, size_t length) { - if (offset > num_bytes_ || length == 0) - return false; - - // Note: This is an overflow-safe check of |offset + length > num_bytes_| - // (that |num_bytes >= offset| is verified above). - if (length > num_bytes_ - offset) - return false; - - return true; -} - -scoped_ptr<PlatformSharedBufferMapping> SimplePlatformSharedBuffer::MapNoCheck( - size_t offset, - size_t length) { - DCHECK(IsValidMap(offset, length)); - return MapImpl(offset, length); -} - -ScopedPlatformHandle SimplePlatformSharedBuffer::DuplicatePlatformHandle() { - return mojo::embedder::DuplicatePlatformHandle(handle_.get()); -} - -ScopedPlatformHandle SimplePlatformSharedBuffer::PassPlatformHandle() { - DCHECK(HasOneRef()); - return std::move(handle_); -} - -SimplePlatformSharedBuffer::SimplePlatformSharedBuffer(size_t num_bytes) - : num_bytes_(num_bytes) { -} - -SimplePlatformSharedBuffer::~SimplePlatformSharedBuffer() { -} - -SimplePlatformSharedBufferMapping::~SimplePlatformSharedBufferMapping() { - Unmap(); -} - -void* SimplePlatformSharedBufferMapping::GetBase() const { - return base_; -} - -size_t SimplePlatformSharedBufferMapping::GetLength() const { - return length_; -} - -} // namespace embedder -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer.h b/third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer.h deleted file mode 100644 index 90b8dd1..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer.h +++ /dev/null @@ -1,101 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_SIMPLE_PLATFORM_SHARED_BUFFER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_SIMPLE_PLATFORM_SHARED_BUFFER_H_ - -#include <stddef.h> - -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_shared_buffer.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace embedder { - -// A simple implementation of |PlatformSharedBuffer|. -class MOJO_SYSTEM_IMPL_EXPORT SimplePlatformSharedBuffer final - : public PlatformSharedBuffer { - public: - // Creates a shared buffer of size |num_bytes| bytes (initially zero-filled). - // |num_bytes| must be nonzero. Returns null on failure. - static SimplePlatformSharedBuffer* Create(size_t num_bytes); - - static SimplePlatformSharedBuffer* CreateFromPlatformHandle( - size_t num_bytes, - ScopedPlatformHandle platform_handle); - - // |PlatformSharedBuffer| implementation: - size_t GetNumBytes() const override; - scoped_ptr<PlatformSharedBufferMapping> Map(size_t offset, - size_t length) override; - bool IsValidMap(size_t offset, size_t length) override; - scoped_ptr<PlatformSharedBufferMapping> MapNoCheck(size_t offset, - size_t length) override; - ScopedPlatformHandle DuplicatePlatformHandle() override; - ScopedPlatformHandle PassPlatformHandle() override; - - private: - explicit SimplePlatformSharedBuffer(size_t num_bytes); - ~SimplePlatformSharedBuffer() override; - - // Implemented in simple_platform_shared_buffer_{posix,win}.cc: - - // This is called by |Create()| before this object is given to anyone. - bool Init(); - - // This is like |Init()|, but for |CreateFromPlatformHandle()|. (Note: It - // should verify that |platform_handle| is an appropriate handle for the - // claimed |num_bytes_|.) - bool InitFromPlatformHandle(ScopedPlatformHandle platform_handle); - - // The platform-dependent part of |Map()|; doesn't check arguments. - scoped_ptr<PlatformSharedBufferMapping> MapImpl(size_t offset, size_t length); - - const size_t num_bytes_; - - // This is set in |Init()|/|InitFromPlatformHandle()| and never modified - // (except by |PassPlatformHandle()|; see the comments above its declaration), - // hence does not need to be protected by a lock. - ScopedPlatformHandle handle_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(SimplePlatformSharedBuffer); -}; - -// An implementation of |PlatformSharedBufferMapping|, produced by -// |SimplePlatformSharedBuffer|. -class MOJO_SYSTEM_IMPL_EXPORT SimplePlatformSharedBufferMapping - : public PlatformSharedBufferMapping { - public: - ~SimplePlatformSharedBufferMapping() override; - - void* GetBase() const override; - size_t GetLength() const override; - - private: - friend class SimplePlatformSharedBuffer; - - SimplePlatformSharedBufferMapping(void* base, - size_t length, - void* real_base, - size_t real_length) - : base_(base), - length_(length), - real_base_(real_base), - real_length_(real_length) {} - void Unmap(); - - void* const base_; - const size_t length_; - - void* const real_base_; - const size_t real_length_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(SimplePlatformSharedBufferMapping); -}; - -} // namespace embedder -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_SIMPLE_PLATFORM_SHARED_BUFFER_H_ diff --git a/third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer_android.cc b/third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer_android.cc deleted file mode 100644 index 8eb8fb1..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer_android.cc +++ /dev/null @@ -1,72 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer.h" - -#include <stdint.h> -#include <sys/mman.h> // For |PROT_...|. -#include <sys/types.h> // For |off_t|. -#include <limits> -#include <utility> - -#include "base/files/scoped_file.h" -#include "base/logging.h" -#include "third_party/ashmem/ashmem.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle.h" - -namespace mojo { -namespace embedder { - -// SimplePlatformSharedBuffer -------------------------------------------------- - -bool SimplePlatformSharedBuffer::Init() { - DCHECK(!handle_.is_valid()); - - if (static_cast<uint64_t>(num_bytes_) > - static_cast<uint64_t>(std::numeric_limits<off_t>::max())) { - return false; - } - - base::ScopedFD fd(ashmem_create_region(nullptr, num_bytes_)); - if (!fd.is_valid()) { - DPLOG(ERROR) << "ashmem_create_region()"; - return false; - } - - if (ashmem_set_prot_region(fd.get(), PROT_READ | PROT_WRITE) < 0) { - DPLOG(ERROR) << "ashmem_set_prot_region()"; - return false; - } - - handle_.reset(PlatformHandle(fd.release())); - return true; -} - -bool SimplePlatformSharedBuffer::InitFromPlatformHandle( - ScopedPlatformHandle platform_handle) { - DCHECK(!handle_.is_valid()); - - if (static_cast<uint64_t>(num_bytes_) > - static_cast<uint64_t>(std::numeric_limits<off_t>::max())) { - return false; - } - - int size = ashmem_get_size_region(platform_handle.get().fd); - - if (size < 0) { - DPLOG(ERROR) << "ashmem_get_size_region()"; - return false; - } - - if (static_cast<size_t>(size) != num_bytes_) { - LOG(ERROR) << "Shared memory region has the wrong size"; - return false; - } - - handle_ = std::move(platform_handle); - return true; -} - -} // namespace embedder -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer_posix.cc b/third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer_posix.cc deleted file mode 100644 index 1047f55..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer_posix.cc +++ /dev/null @@ -1,158 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer.h" - -#include <stdint.h> -#include <stdio.h> // For |fileno()|. -#include <sys/mman.h> // For |mmap()|/|munmap()|. -#include <sys/stat.h> -#include <sys/types.h> // For |off_t|. -#include <unistd.h> -#include <limits> -#include <utility> - -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/files/scoped_file.h" -#include "base/logging.h" -#include "base/posix/eintr_wrapper.h" -#include "base/sys_info.h" -#include "base/threading/thread_restrictions.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle.h" - -// We assume that |size_t| and |off_t| (type for |ftruncate()|) fits in a -// |uint64_t|. -static_assert(sizeof(size_t) <= sizeof(uint64_t), "size_t too big"); -static_assert(sizeof(off_t) <= sizeof(uint64_t), "off_t too big"); - -namespace mojo { -namespace embedder { - -// SimplePlatformSharedBuffer -------------------------------------------------- - -// The implementation for android uses ashmem to generate the file descriptor -// for the shared memory. See simple_platform_shared_buffer_android.cc -#if !defined(OS_ANDROID) - -bool SimplePlatformSharedBuffer::Init() { - DCHECK(!handle_.is_valid()); - - base::ThreadRestrictions::ScopedAllowIO allow_io; - - if (static_cast<uint64_t>(num_bytes_) > - static_cast<uint64_t>(std::numeric_limits<off_t>::max())) { - return false; - } - - // TODO(vtl): This is stupid. The implementation of - // |CreateAndOpenTemporaryFileInDir()| starts with an FD, |fdopen()|s to get a - // |FILE*|, and then we have to |dup(fileno(fp))| to get back to an FD that we - // can own. (base/memory/shared_memory_posix.cc does this too, with more - // |fstat()|s thrown in for good measure.) - base::FilePath shared_buffer_dir; - if (!base::GetShmemTempDir(false, &shared_buffer_dir)) { - LOG(ERROR) << "Failed to get temporary directory for shared memory"; - return false; - } - base::FilePath shared_buffer_file; - base::ScopedFILE fp(base::CreateAndOpenTemporaryFileInDir( - shared_buffer_dir, &shared_buffer_file)); - if (!fp) { - LOG(ERROR) << "Failed to create/open temporary file for shared memory"; - return false; - } - // Note: |unlink()| is not interruptible. - if (unlink(shared_buffer_file.value().c_str()) != 0) { - PLOG(WARNING) << "unlink"; - // This isn't "fatal" (e.g., someone else may have unlinked the file first), - // so we may as well continue. - } - - // Note: |dup()| is not interruptible (but |dup2()|/|dup3()| are). - base::ScopedFD fd(dup(fileno(fp.get()))); - if (!fd.is_valid()) { - PLOG(ERROR) << "dup"; - return false; - } - - if (HANDLE_EINTR(ftruncate(fd.get(), static_cast<off_t>(num_bytes_))) != 0) { - PLOG(ERROR) << "ftruncate"; - return false; - } - - handle_.reset(PlatformHandle(fd.release())); - return true; -} - -bool SimplePlatformSharedBuffer::InitFromPlatformHandle( - ScopedPlatformHandle platform_handle) { - DCHECK(!handle_.is_valid()); - - if (static_cast<uint64_t>(num_bytes_) > - static_cast<uint64_t>(std::numeric_limits<off_t>::max())) { - return false; - } - - struct stat sb = {}; - // Note: |fstat()| isn't interruptible. - if (fstat(platform_handle.get().fd, &sb) != 0) { - PLOG(ERROR) << "fstat"; - return false; - } - - if (!S_ISREG(sb.st_mode)) { - LOG(ERROR) << "Platform handle not to a regular file"; - return false; - } - - if (sb.st_size != static_cast<off_t>(num_bytes_)) { - LOG(ERROR) << "Shared memory file has the wrong size"; - return false; - } - - // TODO(vtl): More checks? - - handle_ = std::move(platform_handle); - return true; -} - -#endif // !defined(OS_ANDROID) - -scoped_ptr<PlatformSharedBufferMapping> SimplePlatformSharedBuffer::MapImpl( - size_t offset, - size_t length) { - size_t offset_rounding = offset % base::SysInfo::VMAllocationGranularity(); - size_t real_offset = offset - offset_rounding; - size_t real_length = length + offset_rounding; - - // This should hold (since we checked |num_bytes| versus the maximum value of - // |off_t| on creation, but it never hurts to be paranoid. - DCHECK_LE(static_cast<uint64_t>(real_offset), - static_cast<uint64_t>(std::numeric_limits<off_t>::max())); - - void* real_base = - mmap(nullptr, real_length, PROT_READ | PROT_WRITE, MAP_SHARED, - handle_.get().fd, static_cast<off_t>(real_offset)); - // |mmap()| should return |MAP_FAILED| (a.k.a. -1) on error. But it shouldn't - // return null either. - if (real_base == MAP_FAILED || !real_base) { - PLOG(ERROR) << "mmap"; - return nullptr; - } - - void* base = static_cast<char*>(real_base) + offset_rounding; - return make_scoped_ptr(new SimplePlatformSharedBufferMapping( - base, length, real_base, real_length)); -} - -// SimplePlatformSharedBufferMapping ------------------------------------------- - -void SimplePlatformSharedBufferMapping::Unmap() { - int result = munmap(real_base_, real_length_); - PLOG_IF(ERROR, result != 0) << "munmap"; -} - -} // namespace embedder -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer_unittest.cc b/third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer_unittest.cc deleted file mode 100644 index dc15dfa..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer_unittest.cc +++ /dev/null @@ -1,187 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer.h" - -#include <limits> - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace embedder { -namespace { - -TEST(SimplePlatformSharedBufferTest, Basic) { - const size_t kNumInts = 100; - const size_t kNumBytes = kNumInts * sizeof(int); - // A fudge so that we're not just writing zero bytes 75% of the time. - const int kFudge = 1234567890; - - // Make some memory. - scoped_refptr<SimplePlatformSharedBuffer> buffer( - SimplePlatformSharedBuffer::Create(kNumBytes)); - ASSERT_TRUE(buffer); - - // Map it all, scribble some stuff, and then unmap it. - { - EXPECT_TRUE(buffer->IsValidMap(0, kNumBytes)); - scoped_ptr<PlatformSharedBufferMapping> mapping(buffer->Map(0, kNumBytes)); - ASSERT_TRUE(mapping); - ASSERT_TRUE(mapping->GetBase()); - int* stuff = static_cast<int*>(mapping->GetBase()); - for (size_t i = 0; i < kNumInts; i++) - stuff[i] = static_cast<int>(i) + kFudge; - } - - // Map it all again, check that our scribbling is still there, then do a - // partial mapping and scribble on that, check that everything is coherent, - // unmap the first mapping, scribble on some of the second mapping, and then - // unmap it. - { - ASSERT_TRUE(buffer->IsValidMap(0, kNumBytes)); - // Use |MapNoCheck()| this time. - scoped_ptr<PlatformSharedBufferMapping> mapping1( - buffer->MapNoCheck(0, kNumBytes)); - ASSERT_TRUE(mapping1); - ASSERT_TRUE(mapping1->GetBase()); - int* stuff1 = static_cast<int*>(mapping1->GetBase()); - for (size_t i = 0; i < kNumInts; i++) - EXPECT_EQ(static_cast<int>(i) + kFudge, stuff1[i]) << i; - - scoped_ptr<PlatformSharedBufferMapping> mapping2( - buffer->Map((kNumInts / 2) * sizeof(int), 2 * sizeof(int))); - ASSERT_TRUE(mapping2); - ASSERT_TRUE(mapping2->GetBase()); - int* stuff2 = static_cast<int*>(mapping2->GetBase()); - EXPECT_EQ(static_cast<int>(kNumInts / 2) + kFudge, stuff2[0]); - EXPECT_EQ(static_cast<int>(kNumInts / 2) + 1 + kFudge, stuff2[1]); - - stuff2[0] = 123; - stuff2[1] = 456; - EXPECT_EQ(123, stuff1[kNumInts / 2]); - EXPECT_EQ(456, stuff1[kNumInts / 2 + 1]); - - mapping1.reset(); - - EXPECT_EQ(123, stuff2[0]); - EXPECT_EQ(456, stuff2[1]); - stuff2[1] = 789; - } - - // Do another partial mapping and check that everything is the way we expect - // it to be. - { - EXPECT_TRUE(buffer->IsValidMap(sizeof(int), kNumBytes - sizeof(int))); - scoped_ptr<PlatformSharedBufferMapping> mapping( - buffer->Map(sizeof(int), kNumBytes - sizeof(int))); - ASSERT_TRUE(mapping); - ASSERT_TRUE(mapping->GetBase()); - int* stuff = static_cast<int*>(mapping->GetBase()); - - for (size_t j = 0; j < kNumInts - 1; j++) { - int i = static_cast<int>(j) + 1; - if (i == kNumInts / 2) { - EXPECT_EQ(123, stuff[j]); - } else if (i == kNumInts / 2 + 1) { - EXPECT_EQ(789, stuff[j]); - } else { - EXPECT_EQ(i + kFudge, stuff[j]) << i; - } - } - } -} - -// TODO(vtl): Bigger buffers. - -TEST(SimplePlatformSharedBufferTest, InvalidMappings) { - scoped_refptr<SimplePlatformSharedBuffer> buffer( - SimplePlatformSharedBuffer::Create(100)); - ASSERT_TRUE(buffer); - - // Zero length not allowed. - EXPECT_FALSE(buffer->Map(0, 0)); - EXPECT_FALSE(buffer->IsValidMap(0, 0)); - - // Okay: - EXPECT_TRUE(buffer->Map(0, 100)); - EXPECT_TRUE(buffer->IsValidMap(0, 100)); - // Offset + length too big. - EXPECT_FALSE(buffer->Map(0, 101)); - EXPECT_FALSE(buffer->IsValidMap(0, 101)); - EXPECT_FALSE(buffer->Map(1, 100)); - EXPECT_FALSE(buffer->IsValidMap(1, 100)); - - // Okay: - EXPECT_TRUE(buffer->Map(50, 50)); - EXPECT_TRUE(buffer->IsValidMap(50, 50)); - // Offset + length too big. - EXPECT_FALSE(buffer->Map(50, 51)); - EXPECT_FALSE(buffer->IsValidMap(50, 51)); - EXPECT_FALSE(buffer->Map(51, 50)); - EXPECT_FALSE(buffer->IsValidMap(51, 50)); -} - -TEST(SimplePlatformSharedBufferTest, TooBig) { - // If |size_t| is 32-bit, it's quite possible/likely that |Create()| succeeds - // (since it only involves creating a 4 GB file). - const size_t kMaxSizeT = std::numeric_limits<size_t>::max(); - scoped_refptr<SimplePlatformSharedBuffer> buffer( - SimplePlatformSharedBuffer::Create(kMaxSizeT)); - // But, assuming |sizeof(size_t) == sizeof(void*)|, mapping all of it should - // always fail. - if (buffer) - EXPECT_FALSE(buffer->Map(0, kMaxSizeT)); -} - -// Tests that separate mappings get distinct addresses. -// Note: It's not inconceivable that the OS could ref-count identical mappings -// and reuse the same address, in which case we'd have to be more careful about -// using the address as the key for unmapping. -TEST(SimplePlatformSharedBufferTest, MappingsDistinct) { - scoped_refptr<SimplePlatformSharedBuffer> buffer( - SimplePlatformSharedBuffer::Create(100)); - scoped_ptr<PlatformSharedBufferMapping> mapping1(buffer->Map(0, 100)); - scoped_ptr<PlatformSharedBufferMapping> mapping2(buffer->Map(0, 100)); - EXPECT_NE(mapping1->GetBase(), mapping2->GetBase()); -} - -TEST(SimplePlatformSharedBufferTest, BufferZeroInitialized) { - static const size_t kSizes[] = {10, 100, 1000, 10000, 100000}; - for (size_t i = 0; i < MOJO_ARRAYSIZE(kSizes); i++) { - scoped_refptr<SimplePlatformSharedBuffer> buffer( - SimplePlatformSharedBuffer::Create(kSizes[i])); - scoped_ptr<PlatformSharedBufferMapping> mapping(buffer->Map(0, kSizes[i])); - for (size_t j = 0; j < kSizes[i]; j++) { - // "Assert" instead of "expect" so we don't spam the output with thousands - // of failures if we fail. - ASSERT_EQ('\0', static_cast<char*>(mapping->GetBase())[j]) - << "size " << kSizes[i] << ", offset " << j; - } - } -} - -TEST(SimplePlatformSharedBufferTest, MappingsOutliveBuffer) { - scoped_ptr<PlatformSharedBufferMapping> mapping1; - scoped_ptr<PlatformSharedBufferMapping> mapping2; - - { - scoped_refptr<SimplePlatformSharedBuffer> buffer( - SimplePlatformSharedBuffer::Create(100)); - mapping1 = buffer->Map(0, 100); - mapping2 = buffer->Map(50, 50); - static_cast<char*>(mapping1->GetBase())[50] = 'x'; - } - - EXPECT_EQ('x', static_cast<char*>(mapping2->GetBase())[0]); - - static_cast<char*>(mapping2->GetBase())[1] = 'y'; - EXPECT_EQ('y', static_cast<char*>(mapping1->GetBase())[51]); -} - -} // namespace -} // namespace embedder -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer_win.cc b/third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer_win.cc deleted file mode 100644 index be3c282..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer_win.cc +++ /dev/null @@ -1,88 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer.h" - -#include <windows.h> - -#include <limits> - -#include "base/logging.h" -#include "base/sys_info.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" - -namespace mojo { -namespace embedder { - -// SimplePlatformSharedBuffer -------------------------------------------------- - -bool SimplePlatformSharedBuffer::Init() { - DCHECK(!handle_.is_valid()); - - // TODO(vtl): Currently, we only support mapping up to 2^32-1 bytes. - if (static_cast<uint64_t>(num_bytes_) > - static_cast<uint64_t>(std::numeric_limits<DWORD>::max())) { - return false; - } - - // IMPORTANT NOTE: Unnamed objects are NOT SECURABLE. Thus if we ever want to - // share read-only to other processes, we'll have to name our file mapping - // object. - // TODO(vtl): Unlike |base::SharedMemory|, we don't round up the size (to a - // multiple of 64 KB). This may cause problems with NaCl. Cross this bridge - // when we get there. crbug.com/210609 - handle_.reset(PlatformHandle( - CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, - static_cast<DWORD>(num_bytes_), nullptr))); - if (!handle_.is_valid()) { - PLOG(ERROR) << "CreateFileMapping"; - return false; - } - - return true; -} - -bool SimplePlatformSharedBuffer::InitFromPlatformHandle( - ScopedPlatformHandle platform_handle) { - DCHECK(!handle_.is_valid()); - - handle_ = platform_handle.Pass(); - return true; -} - -scoped_ptr<PlatformSharedBufferMapping> SimplePlatformSharedBuffer::MapImpl( - size_t offset, - size_t length) { - size_t offset_rounding = offset % base::SysInfo::VMAllocationGranularity(); - size_t real_offset = offset - offset_rounding; - size_t real_length = length + offset_rounding; - - // This should hold (since we checked |num_bytes| versus the maximum value of - // |off_t| on creation, but it never hurts to be paranoid. - DCHECK_LE(static_cast<uint64_t>(real_offset), - static_cast<uint64_t>(std::numeric_limits<DWORD>::max())); - - void* real_base = - MapViewOfFile(handle_.get().handle, FILE_MAP_READ | FILE_MAP_WRITE, 0, - static_cast<DWORD>(real_offset), real_length); - if (!real_base) { - PLOG(ERROR) << "MapViewOfFile"; - return nullptr; - } - - void* base = static_cast<char*>(real_base) + offset_rounding; - return make_scoped_ptr(new SimplePlatformSharedBufferMapping( - base, length, real_base, real_length)); -} - -// SimplePlatformSharedBufferMapping ------------------------------------------- - -void SimplePlatformSharedBufferMapping::Unmap() { - BOOL result = UnmapViewOfFile(real_base_); - PLOG_IF(ERROR, !result) << "UnmapViewOfFile"; -} - -} // namespace embedder -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/embedder/simple_platform_support.cc b/third_party/mojo/src/mojo/edk/embedder/simple_platform_support.cc deleted file mode 100644 index 3beb7b6..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/simple_platform_support.cc +++ /dev/null @@ -1,33 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h" - -#include <utility> - -#include "base/rand_util.h" -#include "third_party/mojo/src/mojo/edk/embedder/simple_platform_shared_buffer.h" - -namespace mojo { -namespace embedder { - -void SimplePlatformSupport::GetCryptoRandomBytes(void* bytes, - size_t num_bytes) { - base::RandBytes(bytes, num_bytes); -} - -PlatformSharedBuffer* SimplePlatformSupport::CreateSharedBuffer( - size_t num_bytes) { - return SimplePlatformSharedBuffer::Create(num_bytes); -} - -PlatformSharedBuffer* SimplePlatformSupport::CreateSharedBufferFromHandle( - size_t num_bytes, - ScopedPlatformHandle platform_handle) { - return SimplePlatformSharedBuffer::CreateFromPlatformHandle( - num_bytes, std::move(platform_handle)); -} - -} // namespace embedder -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h b/third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h deleted file mode 100644 index 8974d2d..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h +++ /dev/null @@ -1,39 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_SIMPLE_PLATFORM_SUPPORT_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_SIMPLE_PLATFORM_SUPPORT_H_ - -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_support.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace embedder { - -// A simple implementation of |PlatformSupport|, when sandboxing and -// multiprocess support are not issues (e.g., in most tests). Note: This class -// has no state, and different instances of |SimplePlatformSupport| are mutually -// compatible (i.e., you don't need to use a single instance of it everywhere -- -// you may simply create one whenever/wherever you need it). -class MOJO_SYSTEM_IMPL_EXPORT SimplePlatformSupport final - : public PlatformSupport { - public: - SimplePlatformSupport() {} - ~SimplePlatformSupport() override {} - - void GetCryptoRandomBytes(void* bytes, size_t num_bytes) override; - PlatformSharedBuffer* CreateSharedBuffer(size_t num_bytes) override; - PlatformSharedBuffer* CreateSharedBufferFromHandle( - size_t num_bytes, - ScopedPlatformHandle platform_handle) override; - - private: - MOJO_DISALLOW_COPY_AND_ASSIGN(SimplePlatformSupport); -}; - -} // namespace embedder -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_SIMPLE_PLATFORM_SUPPORT_H_ diff --git a/third_party/mojo/src/mojo/edk/embedder/slave_info.h b/third_party/mojo/src/mojo/edk/embedder/slave_info.h deleted file mode 100644 index 573eee8..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/slave_info.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2015 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_SLAVE_INFO_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_SLAVE_INFO_H_ - -namespace mojo { -namespace embedder { - -using SlaveInfo = void*; - -} // namespace embedder -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_SLAVE_INFO_H_ diff --git a/third_party/mojo/src/mojo/edk/embedder/slave_process_delegate.h b/third_party/mojo/src/mojo/edk/embedder/slave_process_delegate.h deleted file mode 100644 index d8fd442..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/slave_process_delegate.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2015 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_SLAVE_PROCESS_DELEGATE_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_SLAVE_PROCESS_DELEGATE_H_ - -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/process_delegate.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace embedder { - -// An interface for the slave process delegate (which lives in each slave -// process). -class MOJO_SYSTEM_IMPL_EXPORT SlaveProcessDelegate : public ProcessDelegate { - public: - ProcessType GetType() const override; - - // Called when contact with the master process has been lost. - // TODO(vtl): Obviously, there needs to be a suitable embedder API for - // connecting to the master process. What will it be? Mention that here once - // it exists. - virtual void OnMasterDisconnect() = 0; - - protected: - SlaveProcessDelegate() {} - ~SlaveProcessDelegate() override {} - - private: - MOJO_DISALLOW_COPY_AND_ASSIGN(SlaveProcessDelegate); -}; - -inline ProcessType SlaveProcessDelegate::GetType() const { - return ProcessType::SLAVE; -} - -} // namespace embedder -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_SLAVE_PROCESS_DELEGATE_H_ diff --git a/third_party/mojo/src/mojo/edk/embedder/test_embedder.cc b/third_party/mojo/src/mojo/edk/embedder/test_embedder.cc deleted file mode 100644 index 23e485e..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/test_embedder.cc +++ /dev/null @@ -1,76 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/embedder/test_embedder.h" - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder_internal.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_support.h" -#include "third_party/mojo/src/mojo/edk/system/channel_manager.h" -#include "third_party/mojo/src/mojo/edk/system/core.h" -#include "third_party/mojo/src/mojo/edk/system/handle_table.h" -#include "../../../../../../mojo/edk/system/core.h" -#include "../../../../../../mojo/edk/embedder/embedder_internal.h" -#include "../../../../../../mojo/edk/embedder/simple_platform_support.h" - -namespace mojo { - -namespace system { -namespace internal { - -bool ShutdownCheckNoLeaks(Core* core) { - // No point in taking the lock. - const HandleTable::HandleToEntryMap& handle_to_entry_map = - core->handle_table_.handle_to_entry_map_; - - if (handle_to_entry_map.empty()) - return true; - - for (HandleTable::HandleToEntryMap::const_iterator it = - handle_to_entry_map.begin(); - it != handle_to_entry_map.end(); ++it) { - LOG(ERROR) << "Mojo embedder shutdown: Leaking handle " << (*it).first; - } - return false; -} - -} // namespace internal -} // namespace system - -namespace embedder { -namespace test { - -bool Shutdown() { - // If |InitIPCSupport()| was called, then |ShutdownIPCSupport()| must have - // been called first. - CHECK(!internal::g_ipc_support); - - CHECK(internal::g_core); - bool rv = system::internal::ShutdownCheckNoLeaks(internal::g_core); - delete internal::g_core; - internal::g_core = nullptr; - - CHECK(internal::g_platform_support); - delete internal::g_platform_support; - internal::g_platform_support = nullptr; - - - // TODO(use_chrome_edk): temporary to match mojo::embedder::Init - CHECK(mojo::edk::internal::g_core); - delete mojo::edk::internal::g_core; - mojo::edk::internal::g_core = nullptr; - - CHECK(mojo::edk::internal::g_platform_support); - delete mojo::edk::internal::g_platform_support; - mojo::edk::internal::g_platform_support = nullptr; - - return rv; -} - -} // namespace test -} // namespace embedder - -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/embedder/test_embedder.h b/third_party/mojo/src/mojo/edk/embedder/test_embedder.h deleted file mode 100644 index 7b87b98..0000000 --- a/third_party/mojo/src/mojo/edk/embedder/test_embedder.h +++ /dev/null @@ -1,28 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_TEST_EMBEDDER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_TEST_EMBEDDER_H_ - -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace embedder { -namespace test { - -// This shuts down the global, singleton instance. (Note: "Real" embedders are -// not expected to ever shut down this instance. This |Shutdown()| function will -// do more work to ensure that tests don't leak, etc.) Returns true if there -// were no problems, false if there were leaks -- i.e., handles still open -- or -// any other problems. -// -// Note: It is up to the caller to ensure that there are not outstanding -// callbacks from |CreateChannel()| before calling this. -MOJO_SYSTEM_IMPL_EXPORT bool Shutdown(); - -} // namespace test -} // namespace embedder -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_EMBEDDER_TEST_EMBEDDER_H_ diff --git a/third_party/mojo/src/mojo/edk/js/BUILD.gn b/third_party/mojo/src/mojo/edk/js/BUILD.gn deleted file mode 100644 index fcd6c70..0000000 --- a/third_party/mojo/src/mojo/edk/js/BUILD.gn +++ /dev/null @@ -1,34 +0,0 @@ -# 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. - -source_set("js") { - sources = [ - "core.cc", - "core.h", - "drain_data.cc", - "drain_data.h", - "handle.cc", - "handle.h", - "handle_close_observer.h", - "mojo_runner_delegate.cc", - "mojo_runner_delegate.h", - "support.cc", - "support.h", - "threading.cc", - "threading.h", - "waiting_callback.cc", - "waiting_callback.h", - ] - - public_deps = [ - "//base", - "//gin", - "//v8", - ] - - deps = [ - "//mojo/public/cpp/environment", - "//mojo/public/cpp/system", - ] -} diff --git a/third_party/mojo/src/mojo/edk/js/core.cc b/third_party/mojo/src/mojo/edk/js/core.cc deleted file mode 100644 index 58bb0e2..0000000 --- a/third_party/mojo/src/mojo/edk/js/core.cc +++ /dev/null @@ -1,379 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/js/core.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "gin/arguments.h" -#include "gin/array_buffer.h" -#include "gin/converter.h" -#include "gin/dictionary.h" -#include "gin/function_template.h" -#include "gin/handle.h" -#include "gin/object_template_builder.h" -#include "gin/per_isolate_data.h" -#include "gin/public/wrapper_info.h" -#include "gin/wrappable.h" -#include "third_party/mojo/src/mojo/edk/js/drain_data.h" -#include "third_party/mojo/src/mojo/edk/js/handle.h" - -namespace mojo { -namespace js { - -namespace { - -MojoResult CloseHandle(gin::Handle<HandleWrapper> handle) { - if (!handle->get().is_valid()) - return MOJO_RESULT_INVALID_ARGUMENT; - handle->Close(); - return MOJO_RESULT_OK; -} - -gin::Dictionary WaitHandle(const gin::Arguments& args, - mojo::Handle handle, - MojoHandleSignals signals, - MojoDeadline deadline) { - v8::Isolate* isolate = args.isolate(); - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(isolate); - - MojoHandleSignalsState signals_state; - MojoResult result = mojo::Wait(handle, signals, deadline, &signals_state); - dictionary.Set("result", result); - - mojo::WaitManyResult wmv(result, 0); - if (!wmv.AreSignalsStatesValid()) { - dictionary.Set("signalsState", v8::Null(isolate).As<v8::Value>()); - } else { - gin::Dictionary signalsStateDict = gin::Dictionary::CreateEmpty(isolate); - signalsStateDict.Set("satisfiedSignals", signals_state.satisfied_signals); - signalsStateDict.Set("satisfiableSignals", - signals_state.satisfiable_signals); - dictionary.Set("signalsState", signalsStateDict); - } - - return dictionary; -} - -gin::Dictionary WaitMany(const gin::Arguments& args, - const std::vector<mojo::Handle>& handles, - const std::vector<MojoHandleSignals>& signals, - MojoDeadline deadline) { - v8::Isolate* isolate = args.isolate(); - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(isolate); - - std::vector<MojoHandleSignalsState> signals_states(signals.size()); - mojo::WaitManyResult wmv = - mojo::WaitMany(handles, signals, deadline, &signals_states); - dictionary.Set("result", wmv.result); - if (wmv.IsIndexValid()) { - dictionary.Set("index", wmv.index); - } else { - dictionary.Set("index", v8::Null(isolate).As<v8::Value>()); - } - if (wmv.AreSignalsStatesValid()) { - std::vector<gin::Dictionary> vec; - for (size_t i = 0; i < handles.size(); ++i) { - gin::Dictionary signalsStateDict = gin::Dictionary::CreateEmpty(isolate); - signalsStateDict.Set("satisfiedSignals", - signals_states[i].satisfied_signals); - signalsStateDict.Set("satisfiableSignals", - signals_states[i].satisfiable_signals); - vec.push_back(signalsStateDict); - } - dictionary.Set("signalsState", vec); - } else { - dictionary.Set("signalsState", v8::Null(isolate).As<v8::Value>()); - } - - return dictionary; -} - -gin::Dictionary CreateMessagePipe(const gin::Arguments& args) { - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate()); - dictionary.Set("result", MOJO_RESULT_INVALID_ARGUMENT); - - MojoHandle handle0 = MOJO_HANDLE_INVALID; - MojoHandle handle1 = MOJO_HANDLE_INVALID; - MojoResult result = MOJO_RESULT_OK; - - v8::Handle<v8::Value> options_value = args.PeekNext(); - if (options_value.IsEmpty() || options_value->IsNull() || - options_value->IsUndefined()) { - result = MojoCreateMessagePipe(NULL, &handle0, &handle1); - } else if (options_value->IsObject()) { - gin::Dictionary options_dict(args.isolate(), options_value->ToObject()); - MojoCreateMessagePipeOptions options; - // For future struct_size, we can probably infer that from the presence of - // properties in options_dict. For now, it's always 8. - options.struct_size = 8; - // Ideally these would be optional. But the interface makes it hard to - // typecheck them then. - if (!options_dict.Get("flags", &options.flags)) { - return dictionary; - } - - result = MojoCreateMessagePipe(&options, &handle0, &handle1); - } else { - return dictionary; - } - - CHECK_EQ(MOJO_RESULT_OK, result); - - dictionary.Set("result", result); - dictionary.Set("handle0", mojo::Handle(handle0)); - dictionary.Set("handle1", mojo::Handle(handle1)); - return dictionary; -} - -MojoResult WriteMessage( - mojo::Handle handle, - const gin::ArrayBufferView& buffer, - const std::vector<gin::Handle<HandleWrapper> >& handles, - MojoWriteMessageFlags flags) { - std::vector<MojoHandle> raw_handles(handles.size()); - for (size_t i = 0; i < handles.size(); ++i) - raw_handles[i] = handles[i]->get().value(); - MojoResult rv = MojoWriteMessage(handle.value(), - buffer.bytes(), - static_cast<uint32_t>(buffer.num_bytes()), - raw_handles.empty() ? NULL : &raw_handles[0], - static_cast<uint32_t>(raw_handles.size()), - flags); - // MojoWriteMessage takes ownership of the handles upon success, so - // release them here. - if (rv == MOJO_RESULT_OK) { - for (size_t i = 0; i < handles.size(); ++i) - ignore_result(handles[i]->release()); - } - return rv; -} - -gin::Dictionary ReadMessage(const gin::Arguments& args, - mojo::Handle handle, - MojoReadMessageFlags flags) { - uint32_t num_bytes = 0; - uint32_t num_handles = 0; - MojoResult result = MojoReadMessage( - handle.value(), NULL, &num_bytes, NULL, &num_handles, flags); - if (result != MOJO_RESULT_RESOURCE_EXHAUSTED) { - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate()); - dictionary.Set("result", result); - return dictionary; - } - - v8::Handle<v8::ArrayBuffer> array_buffer = - v8::ArrayBuffer::New(args.isolate(), num_bytes); - std::vector<mojo::Handle> handles(num_handles); - - gin::ArrayBuffer buffer; - ConvertFromV8(args.isolate(), array_buffer, &buffer); - CHECK(buffer.num_bytes() == num_bytes); - - result = MojoReadMessage(handle.value(), - buffer.bytes(), - &num_bytes, - handles.empty() ? NULL : - reinterpret_cast<MojoHandle*>(&handles[0]), - &num_handles, - flags); - - CHECK(buffer.num_bytes() == num_bytes); - CHECK(handles.size() == num_handles); - - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate()); - dictionary.Set("result", result); - dictionary.Set("buffer", array_buffer); - dictionary.Set("handles", handles); - return dictionary; -} - -gin::Dictionary CreateDataPipe(const gin::Arguments& args) { - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate()); - dictionary.Set("result", MOJO_RESULT_INVALID_ARGUMENT); - - MojoHandle producer_handle = MOJO_HANDLE_INVALID; - MojoHandle consumer_handle = MOJO_HANDLE_INVALID; - MojoResult result = MOJO_RESULT_OK; - - v8::Handle<v8::Value> options_value = args.PeekNext(); - if (options_value.IsEmpty() || options_value->IsNull() || - options_value->IsUndefined()) { - result = MojoCreateDataPipe(NULL, &producer_handle, &consumer_handle); - } else if (options_value->IsObject()) { - gin::Dictionary options_dict(args.isolate(), options_value->ToObject()); - MojoCreateDataPipeOptions options; - // For future struct_size, we can probably infer that from the presence of - // properties in options_dict. For now, it's always 16. - options.struct_size = 16; - // Ideally these would be optional. But the interface makes it hard to - // typecheck them then. - if (!options_dict.Get("flags", &options.flags) || - !options_dict.Get("elementNumBytes", &options.element_num_bytes) || - !options_dict.Get("capacityNumBytes", &options.capacity_num_bytes)) { - return dictionary; - } - - result = MojoCreateDataPipe(&options, &producer_handle, &consumer_handle); - } else { - return dictionary; - } - - CHECK_EQ(MOJO_RESULT_OK, result); - - dictionary.Set("result", result); - dictionary.Set("producerHandle", mojo::Handle(producer_handle)); - dictionary.Set("consumerHandle", mojo::Handle(consumer_handle)); - return dictionary; -} - -gin::Dictionary WriteData(const gin::Arguments& args, - mojo::Handle handle, - const gin::ArrayBufferView& buffer, - MojoWriteDataFlags flags) { - uint32_t num_bytes = static_cast<uint32_t>(buffer.num_bytes()); - MojoResult result = - MojoWriteData(handle.value(), buffer.bytes(), &num_bytes, flags); - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate()); - dictionary.Set("result", result); - dictionary.Set("numBytes", num_bytes); - return dictionary; -} - -gin::Dictionary ReadData(const gin::Arguments& args, - mojo::Handle handle, - MojoReadDataFlags flags) { - uint32_t num_bytes = 0; - MojoResult result = MojoReadData( - handle.value(), NULL, &num_bytes, MOJO_READ_DATA_FLAG_QUERY); - if (result != MOJO_RESULT_OK) { - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate()); - dictionary.Set("result", result); - return dictionary; - } - - v8::Handle<v8::ArrayBuffer> array_buffer = - v8::ArrayBuffer::New(args.isolate(), num_bytes); - gin::ArrayBuffer buffer; - ConvertFromV8(args.isolate(), array_buffer, &buffer); - CHECK_EQ(num_bytes, buffer.num_bytes()); - - result = MojoReadData(handle.value(), buffer.bytes(), &num_bytes, flags); - CHECK_EQ(num_bytes, buffer.num_bytes()); - - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate()); - dictionary.Set("result", result); - dictionary.Set("buffer", array_buffer); - return dictionary; -} - -// Asynchronously read all of the data available for the specified data pipe -// consumer handle until the remote handle is closed or an error occurs. A -// Promise is returned whose settled value is an object like this: -// {result: core.RESULT_OK, buffer: dataArrayBuffer}. If the read failed, -// then the Promise is rejected, the result will be the actual error code, -// and the buffer will contain whatever was read before the error occurred. -// The drainData data pipe handle argument is closed automatically. - -v8::Handle<v8::Value> DoDrainData(gin::Arguments* args, - gin::Handle<HandleWrapper> handle) { - return (new DrainData(args->isolate(), handle->release()))->GetPromise(); -} - -bool IsHandle(gin::Arguments* args, v8::Handle<v8::Value> val) { - gin::Handle<mojo::js::HandleWrapper> ignore_handle; - return gin::Converter<gin::Handle<mojo::js::HandleWrapper>>::FromV8( - args->isolate(), val, &ignore_handle); -} - - -gin::WrapperInfo g_wrapper_info = { gin::kEmbedderNativeGin }; - -} // namespace - -const char Core::kModuleName[] = "mojo/public/js/core"; - -v8::Local<v8::Value> Core::GetModule(v8::Isolate* isolate) { - gin::PerIsolateData* data = gin::PerIsolateData::From(isolate); - v8::Local<v8::ObjectTemplate> templ = data->GetObjectTemplate( - &g_wrapper_info); - - if (templ.IsEmpty()) { - templ = - gin::ObjectTemplateBuilder(isolate) - // TODO(mpcomplete): Should these just be methods on the JS Handle - // object? - .SetMethod("close", CloseHandle) - .SetMethod("wait", WaitHandle) - .SetMethod("waitMany", WaitMany) - .SetMethod("createMessagePipe", CreateMessagePipe) - .SetMethod("writeMessage", WriteMessage) - .SetMethod("readMessage", ReadMessage) - .SetMethod("createDataPipe", CreateDataPipe) - .SetMethod("writeData", WriteData) - .SetMethod("readData", ReadData) - .SetMethod("drainData", DoDrainData) - .SetMethod("isHandle", IsHandle) - - .SetValue("RESULT_OK", MOJO_RESULT_OK) - .SetValue("RESULT_CANCELLED", MOJO_RESULT_CANCELLED) - .SetValue("RESULT_UNKNOWN", MOJO_RESULT_UNKNOWN) - .SetValue("RESULT_INVALID_ARGUMENT", MOJO_RESULT_INVALID_ARGUMENT) - .SetValue("RESULT_DEADLINE_EXCEEDED", MOJO_RESULT_DEADLINE_EXCEEDED) - .SetValue("RESULT_NOT_FOUND", MOJO_RESULT_NOT_FOUND) - .SetValue("RESULT_ALREADY_EXISTS", MOJO_RESULT_ALREADY_EXISTS) - .SetValue("RESULT_PERMISSION_DENIED", MOJO_RESULT_PERMISSION_DENIED) - .SetValue("RESULT_RESOURCE_EXHAUSTED", - MOJO_RESULT_RESOURCE_EXHAUSTED) - .SetValue("RESULT_FAILED_PRECONDITION", - MOJO_RESULT_FAILED_PRECONDITION) - .SetValue("RESULT_ABORTED", MOJO_RESULT_ABORTED) - .SetValue("RESULT_OUT_OF_RANGE", MOJO_RESULT_OUT_OF_RANGE) - .SetValue("RESULT_UNIMPLEMENTED", MOJO_RESULT_UNIMPLEMENTED) - .SetValue("RESULT_INTERNAL", MOJO_RESULT_INTERNAL) - .SetValue("RESULT_UNAVAILABLE", MOJO_RESULT_UNAVAILABLE) - .SetValue("RESULT_DATA_LOSS", MOJO_RESULT_DATA_LOSS) - .SetValue("RESULT_BUSY", MOJO_RESULT_BUSY) - .SetValue("RESULT_SHOULD_WAIT", MOJO_RESULT_SHOULD_WAIT) - - .SetValue("DEADLINE_INDEFINITE", MOJO_DEADLINE_INDEFINITE) - - .SetValue("HANDLE_SIGNAL_NONE", MOJO_HANDLE_SIGNAL_NONE) - .SetValue("HANDLE_SIGNAL_READABLE", MOJO_HANDLE_SIGNAL_READABLE) - .SetValue("HANDLE_SIGNAL_WRITABLE", MOJO_HANDLE_SIGNAL_WRITABLE) - .SetValue("HANDLE_SIGNAL_PEER_CLOSED", - MOJO_HANDLE_SIGNAL_PEER_CLOSED) - - .SetValue("CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE", - MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE) - - .SetValue("WRITE_MESSAGE_FLAG_NONE", MOJO_WRITE_MESSAGE_FLAG_NONE) - - .SetValue("READ_MESSAGE_FLAG_NONE", MOJO_READ_MESSAGE_FLAG_NONE) - .SetValue("READ_MESSAGE_FLAG_MAY_DISCARD", - MOJO_READ_MESSAGE_FLAG_MAY_DISCARD) - - .SetValue("CREATE_DATA_PIPE_OPTIONS_FLAG_NONE", - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE) - - .SetValue("WRITE_DATA_FLAG_NONE", MOJO_WRITE_DATA_FLAG_NONE) - .SetValue("WRITE_DATA_FLAG_ALL_OR_NONE", - MOJO_WRITE_DATA_FLAG_ALL_OR_NONE) - - .SetValue("READ_DATA_FLAG_NONE", MOJO_READ_DATA_FLAG_NONE) - .SetValue("READ_DATA_FLAG_ALL_OR_NONE", - MOJO_READ_DATA_FLAG_ALL_OR_NONE) - .SetValue("READ_DATA_FLAG_DISCARD", MOJO_READ_DATA_FLAG_DISCARD) - .SetValue("READ_DATA_FLAG_QUERY", MOJO_READ_DATA_FLAG_QUERY) - .SetValue("READ_DATA_FLAG_PEEK", MOJO_READ_DATA_FLAG_PEEK) - .Build(); - - data->SetObjectTemplate(&g_wrapper_info, templ); - } - - return templ->NewInstance(); -} - -} // namespace js -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/js/core.h b/third_party/mojo/src/mojo/edk/js/core.h deleted file mode 100644 index 1b67acfb..0000000 --- a/third_party/mojo/src/mojo/edk/js/core.h +++ /dev/null @@ -1,22 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_CORE_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_CORE_H_ - -#include "v8/include/v8.h" - -namespace mojo { -namespace js { - -class Core { - public: - static const char kModuleName[]; - static v8::Local<v8::Value> GetModule(v8::Isolate* isolate); -}; - -} // namespace js -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_CORE_H_ diff --git a/third_party/mojo/src/mojo/edk/js/drain_data.cc b/third_party/mojo/src/mojo/edk/js/drain_data.cc deleted file mode 100644 index 407c5d2..0000000 --- a/third_party/mojo/src/mojo/edk/js/drain_data.cc +++ /dev/null @@ -1,131 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/js/drain_data.h" - -#include "gin/array_buffer.h" -#include "gin/converter.h" -#include "gin/dictionary.h" -#include "gin/per_context_data.h" -#include "gin/per_isolate_data.h" -#include "mojo/public/cpp/environment/environment.h" -#include "mojo/public/cpp/system/core.h" - -namespace mojo { -namespace js { - -DrainData::DrainData(v8::Isolate* isolate, mojo::Handle handle) - : isolate_(isolate), - handle_(DataPipeConsumerHandle(handle.value())), - wait_id_(0) { - - v8::Handle<v8::Context> context(isolate_->GetCurrentContext()); - runner_ = gin::PerContextData::From(context)->runner()->GetWeakPtr(); - - WaitForData(); -} - -v8::Handle<v8::Value> DrainData::GetPromise() { - CHECK(resolver_.IsEmpty()); - v8::Handle<v8::Promise::Resolver> resolver( - v8::Promise::Resolver::New(isolate_)); - resolver_.Reset(isolate_, resolver); - return resolver->GetPromise(); -} - -DrainData::~DrainData() { - if (wait_id_) - Environment::GetDefaultAsyncWaiter()->CancelWait(wait_id_); - resolver_.Reset(); -} - -void DrainData::WaitForData() { - wait_id_ = Environment::GetDefaultAsyncWaiter()->AsyncWait( - handle_.get().value(), - MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, - &DrainData::WaitCompleted, - this); -} - -void DrainData::DataReady(MojoResult result) { - wait_id_ = 0; - if (result != MOJO_RESULT_OK) { - DeliverData(result); - return; - } - while (result == MOJO_RESULT_OK) { - result = ReadData(); - if (result == MOJO_RESULT_SHOULD_WAIT) - WaitForData(); - else if (result != MOJO_RESULT_OK) - DeliverData(result); - } -} - -MojoResult DrainData::ReadData() { - const void* buffer; - uint32_t num_bytes = 0; - MojoResult result = BeginReadDataRaw( - handle_.get(), &buffer, &num_bytes, MOJO_READ_DATA_FLAG_NONE); - if (result != MOJO_RESULT_OK) - return result; - const char* p = static_cast<const char*>(buffer); - DataBuffer* data_buffer = new DataBuffer(p, p + num_bytes); - data_buffers_.push_back(data_buffer); - return EndReadDataRaw(handle_.get(), num_bytes); -} - -void DrainData::DeliverData(MojoResult result) { - if (!runner_) { - delete this; - return; - } - - size_t total_bytes = 0; - for (unsigned i = 0; i < data_buffers_.size(); i++) - total_bytes += data_buffers_[i]->size(); - - // Create a total_bytes length ArrayBuffer return value. - gin::Runner::Scope scope(runner_.get()); - v8::Handle<v8::ArrayBuffer> array_buffer = - v8::ArrayBuffer::New(isolate_, total_bytes); - gin::ArrayBuffer buffer; - ConvertFromV8(isolate_, array_buffer, &buffer); - CHECK_EQ(total_bytes, buffer.num_bytes()); - - // Copy the data_buffers into the ArrayBuffer. - char* array_buffer_ptr = static_cast<char*>(buffer.bytes()); - size_t offset = 0; - for (size_t i = 0; i < data_buffers_.size(); i++) { - size_t num_bytes = data_buffers_[i]->size(); - if (num_bytes == 0) - continue; - const char* data_buffer_ptr = &((*data_buffers_[i])[0]); - memcpy(array_buffer_ptr + offset, data_buffer_ptr, num_bytes); - offset += num_bytes; - } - - // The "settled" value of the promise always includes all of the data - // that was read before either an error occurred or the remote pipe handle - // was closed. The latter is indicated by MOJO_RESULT_FAILED_PRECONDITION. - - v8::Handle<v8::Promise::Resolver> resolver( - v8::Local<v8::Promise::Resolver>::New(isolate_, resolver_)); - - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(isolate_); - dictionary.Set("result", result); - dictionary.Set("buffer", array_buffer); - v8::Handle<v8::Value> settled_value(ConvertToV8(isolate_, dictionary)); - - if (result == MOJO_RESULT_FAILED_PRECONDITION) - resolver->Resolve(settled_value); - else - resolver->Reject(settled_value); - - delete this; -} - -} // namespace js -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/js/drain_data.h b/third_party/mojo/src/mojo/edk/js/drain_data.h deleted file mode 100644 index 9767f2dd..0000000 --- a/third_party/mojo/src/mojo/edk/js/drain_data.h +++ /dev/null @@ -1,64 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_DRAIN_DATA_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_DRAIN_DATA_H_ - -#include "base/memory/scoped_vector.h" -#include "gin/runner.h" -#include "mojo/public/c/environment/async_waiter.h" -#include "mojo/public/cpp/system/core.h" -#include "v8/include/v8.h" - -namespace mojo { -namespace js { - -// This class is the implementation of the Mojo JavaScript core module's -// drainData() method. It is not intended to be used directly. The caller -// allocates a DrainData on the heap and returns GetPromise() to JS. The -// implementation deletes itself after reading as much data as possible -// and rejecting or resolving the Promise. - -class DrainData { - public: - // Starts waiting for data on the specified data pipe consumer handle. - // See WaitForData(). The constructor does not block. - DrainData(v8::Isolate* isolate, mojo::Handle handle); - - // Returns a Promise that will be settled when no more data can be read. - // Should be called just once on a newly allocated DrainData object. - v8::Handle<v8::Value> GetPromise(); - - private: - ~DrainData(); - - // Registers an "async waiter" that calls DataReady() via WaitCompleted(). - void WaitForData(); - static void WaitCompleted(void* self, MojoResult result) { - static_cast<DrainData*>(self)->DataReady(result); - } - - // Use ReadData() to read whatever is availble now on handle_ and save - // it in data_buffers_. - void DataReady(MojoResult result); - MojoResult ReadData(); - - // When the remote data pipe handle is closed, or an error occurs, deliver - // all of the buffered data to the JS Promise and then delete this. - void DeliverData(MojoResult result); - - using DataBuffer = std::vector<char>; - - v8::Isolate* isolate_; - ScopedDataPipeConsumerHandle handle_; - MojoAsyncWaitID wait_id_; - base::WeakPtr<gin::Runner> runner_; - v8::UniquePersistent<v8::Promise::Resolver> resolver_; - ScopedVector<DataBuffer> data_buffers_; -}; - -} // namespace js -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_DRAIN_DATA_H_ diff --git a/third_party/mojo/src/mojo/edk/js/handle.cc b/third_party/mojo/src/mojo/edk/js/handle.cc deleted file mode 100644 index f669e9b..0000000 --- a/third_party/mojo/src/mojo/edk/js/handle.cc +++ /dev/null @@ -1,83 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/js/handle.h" - -#include "third_party/mojo/src/mojo/edk/js/handle_close_observer.h" - -namespace mojo { -namespace js { - -gin::WrapperInfo HandleWrapper::kWrapperInfo = { gin::kEmbedderNativeGin }; - -HandleWrapper::HandleWrapper(MojoHandle handle) - : handle_(mojo::Handle(handle)) { -} - -HandleWrapper::~HandleWrapper() { - NotifyCloseObservers(); -} - -void HandleWrapper::Close() { - NotifyCloseObservers(); - handle_.reset(); -} - -void HandleWrapper::AddCloseObserver(HandleCloseObserver* observer) { - close_observers_.AddObserver(observer); -} - -void HandleWrapper::RemoveCloseObserver(HandleCloseObserver* observer) { - close_observers_.RemoveObserver(observer); -} - -void HandleWrapper::NotifyCloseObservers() { - if (!handle_.is_valid()) - return; - - FOR_EACH_OBSERVER(HandleCloseObserver, close_observers_, OnWillCloseHandle()); -} - -} // namespace js -} // namespace mojo - -namespace gin { - -v8::Handle<v8::Value> Converter<mojo::Handle>::ToV8(v8::Isolate* isolate, - const mojo::Handle& val) { - if (!val.is_valid()) - return v8::Null(isolate); - return mojo::js::HandleWrapper::Create(isolate, val.value()).ToV8(); -} - -bool Converter<mojo::Handle>::FromV8(v8::Isolate* isolate, - v8::Handle<v8::Value> val, - mojo::Handle* out) { - if (val->IsNull()) { - *out = mojo::Handle(); - return true; - } - - gin::Handle<mojo::js::HandleWrapper> handle; - if (!Converter<gin::Handle<mojo::js::HandleWrapper> >::FromV8( - isolate, val, &handle)) - return false; - - *out = handle->get(); - return true; -} - -v8::Handle<v8::Value> Converter<mojo::MessagePipeHandle>::ToV8( - v8::Isolate* isolate, mojo::MessagePipeHandle val) { - return Converter<mojo::Handle>::ToV8(isolate, val); -} - -bool Converter<mojo::MessagePipeHandle>::FromV8(v8::Isolate* isolate, - v8::Handle<v8::Value> val, - mojo::MessagePipeHandle* out) { - return Converter<mojo::Handle>::FromV8(isolate, val, out); -} - - -} // namespace gin diff --git a/third_party/mojo/src/mojo/edk/js/handle.h b/third_party/mojo/src/mojo/edk/js/handle.h deleted file mode 100644 index 9c10466..0000000 --- a/third_party/mojo/src/mojo/edk/js/handle.h +++ /dev/null @@ -1,98 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_HANDLE_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_HANDLE_H_ - -#include "base/observer_list.h" -#include "gin/converter.h" -#include "gin/handle.h" -#include "gin/wrappable.h" -#include "mojo/public/cpp/system/core.h" - -namespace mojo { -namespace js { -class HandleCloseObserver; - -// Wrapper for mojo Handles exposed to JavaScript. This ensures the Handle -// is Closed when its JS object is garbage collected. -class HandleWrapper : public gin::Wrappable<HandleWrapper> { - public: - static gin::WrapperInfo kWrapperInfo; - - static gin::Handle<HandleWrapper> Create(v8::Isolate* isolate, - MojoHandle handle) { - return gin::CreateHandle(isolate, new HandleWrapper(handle)); - } - - mojo::Handle get() const { return handle_.get(); } - mojo::Handle release() { return handle_.release(); } - void Close(); - - void AddCloseObserver(HandleCloseObserver* observer); - void RemoveCloseObserver(HandleCloseObserver* observer); - - protected: - HandleWrapper(MojoHandle handle); - ~HandleWrapper() override; - void NotifyCloseObservers(); - - mojo::ScopedHandle handle_; - base::ObserverList<HandleCloseObserver> close_observers_; -}; - -} // namespace js -} // namespace mojo - -namespace gin { - -// Note: It's important to use this converter rather than the one for -// MojoHandle, since that will do a simple int32_t conversion. It's unfortunate -// there's no way to prevent against accidental use. -// TODO(mpcomplete): define converters for all Handle subtypes. -template<> -struct Converter<mojo::Handle> { - static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate, - const mojo::Handle& val); - static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val, - mojo::Handle* out); -}; - -template<> -struct Converter<mojo::MessagePipeHandle> { - static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate, - mojo::MessagePipeHandle val); - static bool FromV8(v8::Isolate* isolate, - v8::Handle<v8::Value> val, - mojo::MessagePipeHandle* out); -}; - -// We need to specialize the normal gin::Handle converter in order to handle -// converting |null| to a wrapper for an empty mojo::Handle. -template<> -struct Converter<gin::Handle<mojo::js::HandleWrapper> > { - static v8::Handle<v8::Value> ToV8( - v8::Isolate* isolate, const gin::Handle<mojo::js::HandleWrapper>& val) { - return val.ToV8(); - } - - static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val, - gin::Handle<mojo::js::HandleWrapper>* out) { - if (val->IsNull()) { - *out = mojo::js::HandleWrapper::Create(isolate, MOJO_HANDLE_INVALID); - return true; - } - - mojo::js::HandleWrapper* object = NULL; - if (!Converter<mojo::js::HandleWrapper*>::FromV8(isolate, val, &object)) { - return false; - } - *out = gin::Handle<mojo::js::HandleWrapper>(val, object); - return true; - } -}; - -} // namespace gin - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_HANDLE_H_ diff --git a/third_party/mojo/src/mojo/edk/js/handle_close_observer.h b/third_party/mojo/src/mojo/edk/js/handle_close_observer.h deleted file mode 100644 index a7442047..0000000 --- a/third_party/mojo/src/mojo/edk/js/handle_close_observer.h +++ /dev/null @@ -1,22 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_HANDLE_CLOSE_OBSERVER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_HANDLE_CLOSE_OBSERVER_H_ - -namespace mojo { -namespace js { - -class HandleCloseObserver { - public: - virtual void OnWillCloseHandle() = 0; - - protected: - virtual ~HandleCloseObserver() {} -}; - -} // namespace js -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_HANDLE_CLOSE_OBSERVER_H_ diff --git a/third_party/mojo/src/mojo/edk/js/handle_unittest.cc b/third_party/mojo/src/mojo/edk/js/handle_unittest.cc deleted file mode 100644 index 7a10d61..0000000 --- a/third_party/mojo/src/mojo/edk/js/handle_unittest.cc +++ /dev/null @@ -1,90 +0,0 @@ -// 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 "base/macros.h" -#include "mojo/public/cpp/system/core.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/js/handle.h" -#include "third_party/mojo/src/mojo/edk/js/handle_close_observer.h" - -namespace mojo { -namespace js { - -class HandleWrapperTest : public testing::Test, - public HandleCloseObserver { - public: - HandleWrapperTest() : closes_observed_(0) {} - - void OnWillCloseHandle() override { closes_observed_++; } - - protected: - int closes_observed_; - - private: - DISALLOW_COPY_AND_ASSIGN(HandleWrapperTest); -}; - -class TestHandleWrapper : public HandleWrapper { - public: - explicit TestHandleWrapper(MojoHandle handle) : HandleWrapper(handle) {} - - private: - DISALLOW_COPY_AND_ASSIGN(TestHandleWrapper); -}; - -// Test that calling Close() on a HandleWrapper for an invalid handle does not -// notify observers. -TEST_F(HandleWrapperTest, CloseWithInvalidHandle) { - { - TestHandleWrapper wrapper(MOJO_HANDLE_INVALID); - wrapper.AddCloseObserver(this); - ASSERT_EQ(0, closes_observed_); - wrapper.Close(); - EXPECT_EQ(0, closes_observed_); - } - EXPECT_EQ(0, closes_observed_); -} - -// Test that destroying a HandleWrapper for an invalid handle does not notify -// observers. -TEST_F(HandleWrapperTest, DestroyWithInvalidHandle) { - { - TestHandleWrapper wrapper(MOJO_HANDLE_INVALID); - wrapper.AddCloseObserver(this); - ASSERT_EQ(0, closes_observed_); - } - EXPECT_EQ(0, closes_observed_); -} - -// Test that calling Close on a HandleWrapper for a valid handle notifies -// observers once. -TEST_F(HandleWrapperTest, CloseWithValidHandle) { - { - mojo::MessagePipe pipe; - TestHandleWrapper wrapper(pipe.handle0.release().value()); - wrapper.AddCloseObserver(this); - ASSERT_EQ(0, closes_observed_); - wrapper.Close(); - EXPECT_EQ(1, closes_observed_); - // Check that calling close again doesn't notify observers. - wrapper.Close(); - EXPECT_EQ(1, closes_observed_); - } - // Check that destroying a closed HandleWrapper doesn't notify observers. - EXPECT_EQ(1, closes_observed_); -} - -// Test that destroying a HandleWrapper for a valid handle notifies observers. -TEST_F(HandleWrapperTest, DestroyWithValidHandle) { - { - mojo::MessagePipe pipe; - TestHandleWrapper wrapper(pipe.handle0.release().value()); - wrapper.AddCloseObserver(this); - ASSERT_EQ(0, closes_observed_); - } - EXPECT_EQ(1, closes_observed_); -} - -} // namespace js -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/js/mojo_runner_delegate.cc b/third_party/mojo/src/mojo/edk/js/mojo_runner_delegate.cc deleted file mode 100644 index e95d995..0000000 --- a/third_party/mojo/src/mojo/edk/js/mojo_runner_delegate.cc +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/js/mojo_runner_delegate.h" - -#include "base/bind.h" -#include "base/path_service.h" -#include "gin/converter.h" -#include "gin/modules/console.h" -#include "gin/modules/module_registry.h" -#include "gin/modules/timer.h" -#include "gin/try_catch.h" -#include "third_party/mojo/src/mojo/edk/js/core.h" -#include "third_party/mojo/src/mojo/edk/js/handle.h" -#include "third_party/mojo/src/mojo/edk/js/support.h" -#include "third_party/mojo/src/mojo/edk/js/threading.h" - -namespace mojo { -namespace js { - -namespace { - -// TODO(abarth): Rather than loading these modules from the file system, we -// should load them from the network via Mojo IPC. -std::vector<base::FilePath> GetModuleSearchPaths() { - std::vector<base::FilePath> search_paths(2); - PathService::Get(base::DIR_SOURCE_ROOT, &search_paths[0]); - PathService::Get(base::DIR_EXE, &search_paths[1]); - search_paths[1] = search_paths[1].AppendASCII("gen"); - return search_paths; -} - -void StartCallback(base::WeakPtr<gin::Runner> runner, - MojoHandle pipe, - v8::Handle<v8::Value> module) { - v8::Isolate* isolate = runner->GetContextHolder()->isolate(); - v8::Handle<v8::Function> start; - CHECK(gin::ConvertFromV8(isolate, module, &start)); - - v8::Handle<v8::Value> args[] = { - gin::ConvertToV8(isolate, Handle(pipe)) }; - runner->Call(start, runner->global(), 1, args); -} - -} // namespace - -MojoRunnerDelegate::MojoRunnerDelegate() - : ModuleRunnerDelegate(GetModuleSearchPaths()) { - AddBuiltinModule(gin::Console::kModuleName, gin::Console::GetModule); - AddBuiltinModule(gin::TimerModule::kName, gin::TimerModule::GetModule); - AddBuiltinModule(js::Core::kModuleName, js::Core::GetModule); - AddBuiltinModule(js::Support::kModuleName, js::Support::GetModule); - AddBuiltinModule(js::Threading::kModuleName, js::Threading::GetModule); -} - -MojoRunnerDelegate::~MojoRunnerDelegate() { -} - -void MojoRunnerDelegate::Start(gin::Runner* runner, - MojoHandle pipe, - const std::string& module) { - gin::Runner::Scope scope(runner); - gin::ModuleRegistry* registry = - gin::ModuleRegistry::From(runner->GetContextHolder()->context()); - registry->LoadModule(runner->GetContextHolder()->isolate(), module, - base::Bind(StartCallback, runner->GetWeakPtr(), pipe)); - AttemptToLoadMoreModules(runner); -} - -void MojoRunnerDelegate::UnhandledException(gin::ShellRunner* runner, - gin::TryCatch& try_catch) { - gin::ModuleRunnerDelegate::UnhandledException(runner, try_catch); - LOG(ERROR) << try_catch.GetStackTrace(); -} - -} // namespace js -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/js/mojo_runner_delegate.h b/third_party/mojo/src/mojo/edk/js/mojo_runner_delegate.h deleted file mode 100644 index 2890a10..0000000 --- a/third_party/mojo/src/mojo/edk/js/mojo_runner_delegate.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_MOJO_RUNNER_DELEGATE_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_MOJO_RUNNER_DELEGATE_H_ - -#include "base/macros.h" -#include "gin/modules/module_runner_delegate.h" -#include "mojo/public/c/system/core.h" - -namespace mojo { -namespace js { - -class MojoRunnerDelegate : public gin::ModuleRunnerDelegate { - public: - MojoRunnerDelegate(); - ~MojoRunnerDelegate() override; - - void Start(gin::Runner* runner, MojoHandle pipe, const std::string& module); - - private: - // From ModuleRunnerDelegate: - void UnhandledException(gin::ShellRunner* runner, - gin::TryCatch& try_catch) override; - - DISALLOW_COPY_AND_ASSIGN(MojoRunnerDelegate); -}; - -} // namespace js -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_MOJO_RUNNER_DELEGATE_H_ diff --git a/third_party/mojo/src/mojo/edk/js/support.cc b/third_party/mojo/src/mojo/edk/js/support.cc deleted file mode 100644 index e739eeb..0000000 --- a/third_party/mojo/src/mojo/edk/js/support.cc +++ /dev/null @@ -1,60 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/js/support.h" - -#include "base/bind.h" -#include "gin/arguments.h" -#include "gin/converter.h" -#include "gin/function_template.h" -#include "gin/object_template_builder.h" -#include "gin/per_isolate_data.h" -#include "gin/public/wrapper_info.h" -#include "gin/wrappable.h" -#include "mojo/public/cpp/system/core.h" -#include "third_party/mojo/src/mojo/edk/js/handle.h" -#include "third_party/mojo/src/mojo/edk/js/waiting_callback.h" - -namespace mojo { -namespace js { - -namespace { - -WaitingCallback* AsyncWait(const gin::Arguments& args, - gin::Handle<HandleWrapper> handle, - MojoHandleSignals signals, - v8::Handle<v8::Function> callback) { - return WaitingCallback::Create(args.isolate(), callback, handle, signals) - .get(); -} - -void CancelWait(WaitingCallback* waiting_callback) { - waiting_callback->Cancel(); -} - -gin::WrapperInfo g_wrapper_info = { gin::kEmbedderNativeGin }; - -} // namespace - -const char Support::kModuleName[] = "mojo/public/js/support"; - -v8::Local<v8::Value> Support::GetModule(v8::Isolate* isolate) { - gin::PerIsolateData* data = gin::PerIsolateData::From(isolate); - v8::Local<v8::ObjectTemplate> templ = data->GetObjectTemplate( - &g_wrapper_info); - - if (templ.IsEmpty()) { - templ = gin::ObjectTemplateBuilder(isolate) - .SetMethod("asyncWait", AsyncWait) - .SetMethod("cancelWait", CancelWait) - .Build(); - - data->SetObjectTemplate(&g_wrapper_info, templ); - } - - return templ->NewInstance(); -} - -} // namespace js -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/js/support.h b/third_party/mojo/src/mojo/edk/js/support.h deleted file mode 100644 index 2b9147d..0000000 --- a/third_party/mojo/src/mojo/edk/js/support.h +++ /dev/null @@ -1,22 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_SUPPORT_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_SUPPORT_H_ - -#include "v8/include/v8.h" - -namespace mojo { -namespace js { - -class Support { - public: - static const char kModuleName[]; - static v8::Local<v8::Value> GetModule(v8::Isolate* isolate); -}; - -} // namespace js -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_SUPPORT_H_ diff --git a/third_party/mojo/src/mojo/edk/js/test/hexdump.js b/third_party/mojo/src/mojo/edk/js/test/hexdump.js deleted file mode 100644 index b36c47f..0000000 --- a/third_party/mojo/src/mojo/edk/js/test/hexdump.js +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2013 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. - -define(function() { - function hexify(value, length) { - var hex = value.toString(16); - while (hex.length < length) - hex = "0" + hex; - return hex; - } - - function dumpArray(bytes) { - var dumped = ""; - for (var i = 0; i < bytes.length; ++i) { - dumped += hexify(bytes[i], 2); - - if (i % 16 == 15) { - dumped += "\n"; - continue; - } - - if (i % 2 == 1) - dumped += " "; - if (i % 8 == 7) - dumped += " "; - } - return dumped; - } - - var exports = {}; - exports.dumpArray = dumpArray; - return exports; -}); diff --git a/third_party/mojo/src/mojo/edk/js/test/run_js_integration_tests.cc b/third_party/mojo/src/mojo/edk/js/test/run_js_integration_tests.cc deleted file mode 100644 index e0d2831..0000000 --- a/third_party/mojo/src/mojo/edk/js/test/run_js_integration_tests.cc +++ /dev/null @@ -1,57 +0,0 @@ -// 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 "base/files/file_path.h" -#include "base/path_service.h" -#include "gin/modules/console.h" -#include "gin/modules/module_registry.h" -#include "gin/modules/timer.h" -#include "gin/test/file_runner.h" -#include "gin/test/gtest.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/js/core.h" -#include "third_party/mojo/src/mojo/edk/js/support.h" -#include "third_party/mojo/src/mojo/edk/js/threading.h" - -namespace mojo { -namespace js { -namespace { - -class TestRunnerDelegate : public gin::FileRunnerDelegate { - public: - TestRunnerDelegate() { - AddBuiltinModule(gin::Console::kModuleName, gin::Console::GetModule); - AddBuiltinModule(Core::kModuleName, Core::GetModule); - AddBuiltinModule(gin::TimerModule::kName, gin::TimerModule::GetModule); - AddBuiltinModule(Threading::kModuleName, Threading::GetModule); - } - private: - DISALLOW_COPY_AND_ASSIGN(TestRunnerDelegate); -}; - -void RunTest(std::string test, bool addSupportModule) { - base::FilePath path; - PathService::Get(base::DIR_SOURCE_ROOT, &path); - path = path.AppendASCII("mojo") - .AppendASCII("edk") - .AppendASCII("js") - .AppendASCII("tests") - .AppendASCII(test); - TestRunnerDelegate delegate; - if (addSupportModule) - delegate.AddBuiltinModule(Support::kModuleName, Support::GetModule); - gin::RunTestFromFile(path, &delegate, true); -} - -TEST(JSTest, connection) { - RunTest("connection_tests.js", false); -} - -TEST(JSTest, sample_service) { - RunTest("sample_service_tests.js", true); -} - -} // namespace -} // namespace js -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/js/test/run_js_tests.cc b/third_party/mojo/src/mojo/edk/js/test/run_js_tests.cc deleted file mode 100644 index 3fab0ef..0000000 --- a/third_party/mojo/src/mojo/edk/js/test/run_js_tests.cc +++ /dev/null @@ -1,66 +0,0 @@ -// 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 "base/files/file_path.h" -#include "base/path_service.h" -#include "gin/modules/console.h" -#include "gin/modules/module_registry.h" -#include "gin/test/file_runner.h" -#include "gin/test/gtest.h" -#include "mojo/public/cpp/environment/environment.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/js/core.h" -#include "third_party/mojo/src/mojo/edk/js/support.h" - -namespace mojo { -namespace js { -namespace { - -class TestRunnerDelegate : public gin::FileRunnerDelegate { - public: - TestRunnerDelegate() { - AddBuiltinModule(gin::Console::kModuleName, gin::Console::GetModule); - AddBuiltinModule(Core::kModuleName, Core::GetModule); - AddBuiltinModule(Support::kModuleName, Support::GetModule); - } - - private: - DISALLOW_COPY_AND_ASSIGN(TestRunnerDelegate); -}; - -void RunTest(std::string test, bool run_until_idle) { - base::FilePath path; - PathService::Get(base::DIR_SOURCE_ROOT, &path); - path = path.AppendASCII("mojo") - .AppendASCII("public") - .AppendASCII("js") - .AppendASCII(test); - TestRunnerDelegate delegate; - gin::RunTestFromFile(path, &delegate, run_until_idle); -} - -// TODO(abarth): Should we autogenerate these stubs from GYP? -TEST(JSTest, core) { - RunTest("core_unittests.js", true); -} - -TEST(JSTest, codec) { - RunTest("codec_unittests.js", true); -} - -TEST(JSTest, struct) { - RunTest("struct_unittests.js", true); -} - -TEST(JSTest, union) { - RunTest("union_unittests.js", true); -} - -TEST(JSTest, validation) { - RunTest("validation_unittests.js", true); -} - -} // namespace -} // namespace js -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/js/tests/BUILD.gn b/third_party/mojo/src/mojo/edk/js/tests/BUILD.gn deleted file mode 100644 index 883cf4e..0000000 --- a/third_party/mojo/src/mojo/edk/js/tests/BUILD.gn +++ /dev/null @@ -1,32 +0,0 @@ -# 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. - -import("//mojo/public/tools/bindings/mojom.gni") - -source_set("js_to_cpp_tests") { - testonly = true - - deps = [ - ":js_to_cpp_bindings", - "//gin:gin_test", - "//mojo/public/cpp/bindings", - "//mojo/public/cpp/system", - "//mojo/public/interfaces/bindings/tests:test_interfaces", - "//mojo/public/interfaces/bindings/tests:test_interfaces_experimental", - "//third_party/mojo/src/mojo/edk/js", - "//third_party/mojo/src/mojo/edk/test:test_support", - ] - - sources = [ - "js_to_cpp_tests.cc", - ] -} - -mojom("js_to_cpp_bindings") { - sources = [ - "js_to_cpp.mojom", - ] - - with_environment = false -} diff --git a/third_party/mojo/src/mojo/edk/js/tests/connection_tests.js b/third_party/mojo/src/mojo/edk/js/tests/connection_tests.js deleted file mode 100644 index ff59aeb..0000000 --- a/third_party/mojo/src/mojo/edk/js/tests/connection_tests.js +++ /dev/null @@ -1,240 +0,0 @@ -// Copyright 2013 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. - -// Mock out the support module to avoid depending on the message loop. -define("mojo/public/js/support", ["timer"], function(timer) { - var waitingCallbacks = []; - - function WaitCookie(id) { - this.id = id; - } - - function asyncWait(handle, flags, callback) { - var id = waitingCallbacks.length; - waitingCallbacks.push(callback); - return new WaitCookie(id); - } - - function cancelWait(cookie) { - waitingCallbacks[cookie.id] = null; - } - - function numberOfWaitingCallbacks() { - var count = 0; - for (var i = 0; i < waitingCallbacks.length; ++i) { - if (waitingCallbacks[i]) - ++count; - } - return count; - } - - function pumpOnce(result) { - var callbacks = waitingCallbacks; - waitingCallbacks = []; - for (var i = 0; i < callbacks.length; ++i) { - if (callbacks[i]) - callbacks[i](result); - } - } - - // Queue up a pumpOnce call to execute after the stack unwinds. Use - // this to trigger a pump after all Promises are executed. - function queuePump(result) { - timer.createOneShot(0, pumpOnce.bind(undefined, result)); - } - - var exports = {}; - exports.asyncWait = asyncWait; - exports.cancelWait = cancelWait; - exports.numberOfWaitingCallbacks = numberOfWaitingCallbacks; - exports.pumpOnce = pumpOnce; - exports.queuePump = queuePump; - return exports; -}); - -define([ - "gin/test/expect", - "mojo/public/js/support", - "mojo/public/js/core", - "mojo/public/js/connection", - "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom", - "mojo/public/interfaces/bindings/tests/sample_service.mojom", - "mojo/public/js/threading", - "gc", -], function(expect, - mockSupport, - core, - connection, - sample_interfaces, - sample_service, - threading, - gc) { - testClientServer(); - testWriteToClosedPipe(); - testRequestResponse().then(function() { - this.result = "PASS"; - gc.collectGarbage(); // should not crash - threading.quit(); - }.bind(this)).catch(function(e) { - this.result = "FAIL: " + (e.stack || e); - threading.quit(); - }.bind(this)); - - function createPeerConnection(handle, stubClass, proxyClass) { - var c = new connection.Connection(handle, stubClass, proxyClass); - if (c.local) - c.local.peer = c.remote; - if (c.remote) - c.remote.peer = c.local; - return c; - } - - function testClientServer() { - var receivedFrobinate = false; - - // ServiceImpl ------------------------------------------------------------ - - function ServiceImpl() { - } - - ServiceImpl.prototype = Object.create( - sample_service.Service.stubClass.prototype); - - ServiceImpl.prototype.frobinate = function(foo, baz, port) { - receivedFrobinate = true; - - expect(foo.name).toBe("Example name"); - expect(baz).toBeTruthy(); - expect(core.close(port)).toBe(core.RESULT_OK); - - return Promise.resolve(42); - }; - - var pipe = core.createMessagePipe(); - var anotherPipe = core.createMessagePipe(); - var sourcePipe = core.createMessagePipe(); - - var connection0 = createPeerConnection( - pipe.handle0, ServiceImpl); - - var connection1 = createPeerConnection( - pipe.handle1, undefined, sample_service.Service.proxyClass); - - var foo = new sample_service.Foo(); - foo.bar = new sample_service.Bar(); - foo.name = "Example name"; - foo.source = sourcePipe.handle0; - connection1.remote.frobinate(foo, true, anotherPipe.handle0); - - mockSupport.pumpOnce(core.RESULT_OK); - - expect(receivedFrobinate).toBeTruthy(); - - connection0.close(); - connection1.close(); - - expect(mockSupport.numberOfWaitingCallbacks()).toBe(0); - - // sourcePipe.handle0 was closed automatically when sent over IPC. - expect(core.close(sourcePipe.handle0)).toBe(core.RESULT_INVALID_ARGUMENT); - // sourcePipe.handle1 hasn't been closed yet. - expect(core.close(sourcePipe.handle1)).toBe(core.RESULT_OK); - - // anotherPipe.handle0 was closed automatically when sent over IPC. - expect(core.close(anotherPipe.handle0)).toBe(core.RESULT_INVALID_ARGUMENT); - // anotherPipe.handle1 hasn't been closed yet. - expect(core.close(anotherPipe.handle1)).toBe(core.RESULT_OK); - - // The Connection object is responsible for closing these handles. - expect(core.close(pipe.handle0)).toBe(core.RESULT_INVALID_ARGUMENT); - expect(core.close(pipe.handle1)).toBe(core.RESULT_INVALID_ARGUMENT); - } - - function testWriteToClosedPipe() { - var pipe = core.createMessagePipe(); - - var connection1 = createPeerConnection( - pipe.handle1, function() {}, sample_service.Service.proxyClass); - - // Close the other end of the pipe. - core.close(pipe.handle0); - - // Not observed yet because we haven't pumped events yet. - expect(connection1.encounteredError()).toBeFalsy(); - - var foo = new sample_service.Foo(); - foo.bar = new sample_service.Bar(); - connection1.remote.frobinate(null, true, null); - - // Write failures are not reported. - expect(connection1.encounteredError()).toBeFalsy(); - - // Pump events, and then we should start observing the closed pipe. - mockSupport.pumpOnce(core.RESULT_OK); - - expect(connection1.encounteredError()).toBeTruthy(); - - connection1.close(); - } - - function testRequestResponse() { - - // ProviderImpl ------------------------------------------------------------ - - function ProviderImpl() { - } - - ProviderImpl.prototype = - Object.create(sample_interfaces.Provider.stubClass.prototype); - - ProviderImpl.prototype.echoString = function(a) { - mockSupport.queuePump(core.RESULT_OK); - return Promise.resolve({a: a}); - }; - - ProviderImpl.prototype.echoStrings = function(a, b) { - mockSupport.queuePump(core.RESULT_OK); - return Promise.resolve({a: a, b: b}); - }; - - var pipe = core.createMessagePipe(); - - var connection0 = createPeerConnection( - pipe.handle0, - ProviderImpl); - - var connection1 = createPeerConnection( - pipe.handle1, - undefined, - sample_interfaces.Provider.proxyClass); - - var origReadMessage = core.readMessage; - // echoString - mockSupport.queuePump(core.RESULT_OK); - return connection1.remote.echoString("hello").then(function(response) { - expect(response.a).toBe("hello"); - }).then(function() { - // echoStrings - mockSupport.queuePump(core.RESULT_OK); - return connection1.remote.echoStrings("hello", "world"); - }).then(function(response) { - expect(response.a).toBe("hello"); - expect(response.b).toBe("world"); - }).then(function() { - // Mock a read failure, expect it to fail. - core.readMessage = function() { - return { result: core.RESULT_UNKNOWN }; - }; - mockSupport.queuePump(core.RESULT_OK); - return connection1.remote.echoString("goodbye"); - }).then(function() { - throw Error("Expected echoString to fail."); - }, function(error) { - expect(error.message).toBe("Connection error: " + core.RESULT_UNKNOWN); - - // Clean up. - core.readMessage = origReadMessage; - }); - } -}); diff --git a/third_party/mojo/src/mojo/edk/js/tests/js_to_cpp.mojom b/third_party/mojo/src/mojo/edk/js/tests/js_to_cpp.mojom deleted file mode 100644 index 688b22b..0000000 --- a/third_party/mojo/src/mojo/edk/js/tests/js_to_cpp.mojom +++ /dev/null @@ -1,54 +0,0 @@ -module js_to_cpp; - -// This struct encompasses all of the basic types, so that they -// may be sent from C++ to JS and back for validation. -struct EchoArgs { - int64 si64; - int32 si32; - int16 si16; - int8 si8; - uint64 ui64; - uint32 ui32; - uint16 ui16; - uint8 ui8; - float float_val; - float float_inf; - float float_nan; - double double_val; - double double_inf; - double double_nan; - string? name; - array<string>? string_array; - handle<message_pipe>? message_handle; - handle<data_pipe_consumer>? data_handle; -}; - -struct EchoArgsList { - EchoArgsList? next; - EchoArgs? item; -}; - -// Note: For messages which control test flow, pick numbers that are unlikely -// to be hit as a result of our deliberate corruption of response messages. -interface CppSide { - // Sent for all tests to notify that the JS side is now ready. - StartTest@88888888(); - - // Indicates end for echo, bit-flip, and back-pointer tests. - TestFinished@99999999(); - - // Responses from specific tests. - PingResponse(); - EchoResponse(EchoArgsList list); - BitFlipResponse(EchoArgsList arg); - BackPointerResponse(EchoArgsList arg); -}; - -interface JsSide { - SetCppSide(CppSide cpp); - - Ping(); - Echo(int32 numIterations, EchoArgs arg); - BitFlip(EchoArgs arg); - BackPointer(EchoArgs arg); -}; diff --git a/third_party/mojo/src/mojo/edk/js/tests/js_to_cpp_tests.cc b/third_party/mojo/src/mojo/edk/js/tests/js_to_cpp_tests.cc deleted file mode 100644 index a3cc2af..0000000 --- a/third_party/mojo/src/mojo/edk/js/tests/js_to_cpp_tests.cc +++ /dev/null @@ -1,430 +0,0 @@ -// 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 <utility> - -#include "base/at_exit.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/strings/utf_string_conversions.h" -#include "gin/array_buffer.h" -#include "gin/public/isolate_holder.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/js/mojo_runner_delegate.h" -#include "third_party/mojo/src/mojo/edk/js/tests/js_to_cpp.mojom.h" -#include "third_party/mojo/src/mojo/edk/test/test_utils.h" - -namespace mojo { -namespace js { - -// Global value updated by some checks to prevent compilers from optimizing -// reads out of existence. -uint32_t g_waste_accumulator = 0; - -namespace { - -// Negative numbers with different values in each byte, the last of -// which can survive promotion to double and back. -const int8_t kExpectedInt8Value = -65; -const int16_t kExpectedInt16Value = -16961; -const int32_t kExpectedInt32Value = -1145258561; -const int64_t kExpectedInt64Value = -77263311946305LL; - -// Positive numbers with different values in each byte, the last of -// which can survive promotion to double and back. -const uint8_t kExpectedUInt8Value = 65; -const uint16_t kExpectedUInt16Value = 16961; -const uint32_t kExpectedUInt32Value = 1145258561; -const uint64_t kExpectedUInt64Value = 77263311946305LL; - -// Double/float values, including special case constants. -const double kExpectedDoubleVal = 3.14159265358979323846; -const double kExpectedDoubleInf = std::numeric_limits<double>::infinity(); -const double kExpectedDoubleNan = std::numeric_limits<double>::quiet_NaN(); -const float kExpectedFloatVal = static_cast<float>(kExpectedDoubleVal); -const float kExpectedFloatInf = std::numeric_limits<float>::infinity(); -const float kExpectedFloatNan = std::numeric_limits<float>::quiet_NaN(); - -// NaN has the property that it is not equal to itself. -#define EXPECT_NAN(x) EXPECT_NE(x, x) - -void CheckDataPipe(MojoHandle data_pipe_handle) { - unsigned char buffer[100]; - uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); - MojoResult result = MojoReadData( - data_pipe_handle, buffer, &buffer_size, MOJO_READ_DATA_FLAG_NONE); - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(64u, buffer_size); - for (int i = 0; i < 64; ++i) { - EXPECT_EQ(i, buffer[i]); - } -} - -void CheckMessagePipe(MojoHandle message_pipe_handle) { - unsigned char buffer[100]; - uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); - MojoResult result = MojoReadMessage( - message_pipe_handle, buffer, &buffer_size, 0, 0, 0); - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(64u, buffer_size); - for (int i = 0; i < 64; ++i) { - EXPECT_EQ(255 - i, buffer[i]); - } -} - -js_to_cpp::EchoArgsPtr BuildSampleEchoArgs() { - js_to_cpp::EchoArgsPtr args(js_to_cpp::EchoArgs::New()); - args->si64 = kExpectedInt64Value; - args->si32 = kExpectedInt32Value; - args->si16 = kExpectedInt16Value; - args->si8 = kExpectedInt8Value; - args->ui64 = kExpectedUInt64Value; - args->ui32 = kExpectedUInt32Value; - args->ui16 = kExpectedUInt16Value; - args->ui8 = kExpectedUInt8Value; - args->float_val = kExpectedFloatVal; - args->float_inf = kExpectedFloatInf; - args->float_nan = kExpectedFloatNan; - args->double_val = kExpectedDoubleVal; - args->double_inf = kExpectedDoubleInf; - args->double_nan = kExpectedDoubleNan; - args->name = "coming"; - Array<String> string_array(3); - string_array[0] = "one"; - string_array[1] = "two"; - string_array[2] = "three"; - args->string_array = std::move(string_array); - return args; -} - -void CheckSampleEchoArgs(const js_to_cpp::EchoArgs& arg) { - EXPECT_EQ(kExpectedInt64Value, arg.si64); - EXPECT_EQ(kExpectedInt32Value, arg.si32); - EXPECT_EQ(kExpectedInt16Value, arg.si16); - EXPECT_EQ(kExpectedInt8Value, arg.si8); - EXPECT_EQ(kExpectedUInt64Value, arg.ui64); - EXPECT_EQ(kExpectedUInt32Value, arg.ui32); - EXPECT_EQ(kExpectedUInt16Value, arg.ui16); - EXPECT_EQ(kExpectedUInt8Value, arg.ui8); - EXPECT_EQ(kExpectedFloatVal, arg.float_val); - EXPECT_EQ(kExpectedFloatInf, arg.float_inf); - EXPECT_NAN(arg.float_nan); - EXPECT_EQ(kExpectedDoubleVal, arg.double_val); - EXPECT_EQ(kExpectedDoubleInf, arg.double_inf); - EXPECT_NAN(arg.double_nan); - EXPECT_EQ(std::string("coming"), arg.name.get()); - EXPECT_EQ(std::string("one"), arg.string_array[0].get()); - EXPECT_EQ(std::string("two"), arg.string_array[1].get()); - EXPECT_EQ(std::string("three"), arg.string_array[2].get()); - CheckDataPipe(arg.data_handle.get().value()); - CheckMessagePipe(arg.message_handle.get().value()); -} - -void CheckSampleEchoArgsList(const js_to_cpp::EchoArgsListPtr& list) { - if (list.is_null()) - return; - CheckSampleEchoArgs(*list->item); - CheckSampleEchoArgsList(list->next); -} - -// More forgiving checks are needed in the face of potentially corrupt -// messages. The values don't matter so long as all accesses are within -// bounds. -void CheckCorruptedString(const String& arg) { - if (arg.is_null()) - return; - for (size_t i = 0; i < arg.size(); ++i) - g_waste_accumulator += arg[i]; -} - -void CheckCorruptedStringArray(const Array<String>& string_array) { - if (string_array.is_null()) - return; - for (size_t i = 0; i < string_array.size(); ++i) - CheckCorruptedString(string_array[i]); -} - -void CheckCorruptedDataPipe(MojoHandle data_pipe_handle) { - unsigned char buffer[100]; - uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); - MojoResult result = MojoReadData( - data_pipe_handle, buffer, &buffer_size, MOJO_READ_DATA_FLAG_NONE); - if (result != MOJO_RESULT_OK) - return; - for (uint32_t i = 0; i < buffer_size; ++i) - g_waste_accumulator += buffer[i]; -} - -void CheckCorruptedMessagePipe(MojoHandle message_pipe_handle) { - unsigned char buffer[100]; - uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); - MojoResult result = MojoReadMessage( - message_pipe_handle, buffer, &buffer_size, 0, 0, 0); - if (result != MOJO_RESULT_OK) - return; - for (uint32_t i = 0; i < buffer_size; ++i) - g_waste_accumulator += buffer[i]; -} - -void CheckCorruptedEchoArgs(const js_to_cpp::EchoArgsPtr& arg) { - if (arg.is_null()) - return; - CheckCorruptedString(arg->name); - CheckCorruptedStringArray(arg->string_array); - if (arg->data_handle.is_valid()) - CheckCorruptedDataPipe(arg->data_handle.get().value()); - if (arg->message_handle.is_valid()) - CheckCorruptedMessagePipe(arg->message_handle.get().value()); -} - -void CheckCorruptedEchoArgsList(const js_to_cpp::EchoArgsListPtr& list) { - if (list.is_null()) - return; - CheckCorruptedEchoArgs(list->item); - CheckCorruptedEchoArgsList(list->next); -} - -// Base Provider implementation class. It's expected that tests subclass and -// override the appropriate Provider functions. When test is done quit the -// run_loop(). -class CppSideConnection : public js_to_cpp::CppSide { - public: - CppSideConnection() - : run_loop_(nullptr), - js_side_(nullptr), - mishandled_messages_(0), - binding_(this) {} - ~CppSideConnection() override {} - - void set_run_loop(base::RunLoop* run_loop) { run_loop_ = run_loop; } - base::RunLoop* run_loop() { return run_loop_; } - - void set_js_side(js_to_cpp::JsSide* js_side) { js_side_ = js_side; } - js_to_cpp::JsSide* js_side() { return js_side_; } - - void Bind(InterfaceRequest<js_to_cpp::CppSide> request) { - binding_.Bind(std::move(request)); - // Keep the pipe open even after validation errors. - binding_.EnableTestingMode(); - } - - // js_to_cpp::CppSide: - void StartTest() override { NOTREACHED(); } - - void TestFinished() override { NOTREACHED(); } - - void PingResponse() override { mishandled_messages_ += 1; } - - void EchoResponse(js_to_cpp::EchoArgsListPtr list) override { - mishandled_messages_ += 1; - } - - void BitFlipResponse(js_to_cpp::EchoArgsListPtr list) override { - mishandled_messages_ += 1; - } - - void BackPointerResponse(js_to_cpp::EchoArgsListPtr list) override { - mishandled_messages_ += 1; - } - - protected: - base::RunLoop* run_loop_; - js_to_cpp::JsSide* js_side_; - int mishandled_messages_; - mojo::Binding<js_to_cpp::CppSide> binding_; - - private: - DISALLOW_COPY_AND_ASSIGN(CppSideConnection); -}; - -// Trivial test to verify a message sent from JS is received. -class PingCppSideConnection : public CppSideConnection { - public: - PingCppSideConnection() : got_message_(false) {} - ~PingCppSideConnection() override {} - - // js_to_cpp::CppSide: - void StartTest() override { js_side_->Ping(); } - - void PingResponse() override { - got_message_ = true; - run_loop()->Quit(); - } - - bool DidSucceed() { - return got_message_ && !mishandled_messages_; - } - - private: - bool got_message_; - DISALLOW_COPY_AND_ASSIGN(PingCppSideConnection); -}; - -// Test that parameters are passed with correct values. -class EchoCppSideConnection : public CppSideConnection { - public: - EchoCppSideConnection() : - message_count_(0), - termination_seen_(false) { - } - ~EchoCppSideConnection() override {} - - // js_to_cpp::CppSide: - void StartTest() override { - js_side_->Echo(kExpectedMessageCount, BuildSampleEchoArgs()); - } - - void EchoResponse(js_to_cpp::EchoArgsListPtr list) override { - const js_to_cpp::EchoArgsPtr& special_arg = list->item; - message_count_ += 1; - EXPECT_EQ(-1, special_arg->si64); - EXPECT_EQ(-1, special_arg->si32); - EXPECT_EQ(-1, special_arg->si16); - EXPECT_EQ(-1, special_arg->si8); - EXPECT_EQ(std::string("going"), special_arg->name.To<std::string>()); - CheckSampleEchoArgsList(list->next); - } - - void TestFinished() override { - termination_seen_ = true; - run_loop()->Quit(); - } - - bool DidSucceed() { - return termination_seen_ && - !mishandled_messages_ && - message_count_ == kExpectedMessageCount; - } - - private: - static const int kExpectedMessageCount = 10; - int message_count_; - bool termination_seen_; - DISALLOW_COPY_AND_ASSIGN(EchoCppSideConnection); -}; - -// Test that corrupted messages don't wreak havoc. -class BitFlipCppSideConnection : public CppSideConnection { - public: - BitFlipCppSideConnection() : termination_seen_(false) {} - ~BitFlipCppSideConnection() override {} - - // js_to_cpp::CppSide: - void StartTest() override { js_side_->BitFlip(BuildSampleEchoArgs()); } - - void BitFlipResponse(js_to_cpp::EchoArgsListPtr list) override { - CheckCorruptedEchoArgsList(list); - } - - void TestFinished() override { - termination_seen_ = true; - run_loop()->Quit(); - } - - bool DidSucceed() { - return termination_seen_; - } - - private: - bool termination_seen_; - DISALLOW_COPY_AND_ASSIGN(BitFlipCppSideConnection); -}; - -// Test that severely random messages don't wreak havoc. -class BackPointerCppSideConnection : public CppSideConnection { - public: - BackPointerCppSideConnection() : termination_seen_(false) {} - ~BackPointerCppSideConnection() override {} - - // js_to_cpp::CppSide: - void StartTest() override { js_side_->BackPointer(BuildSampleEchoArgs()); } - - void BackPointerResponse(js_to_cpp::EchoArgsListPtr list) override { - CheckCorruptedEchoArgsList(list); - } - - void TestFinished() override { - termination_seen_ = true; - run_loop()->Quit(); - } - - bool DidSucceed() { - return termination_seen_; - } - - private: - bool termination_seen_; - DISALLOW_COPY_AND_ASSIGN(BackPointerCppSideConnection); -}; - -} // namespace - -class JsToCppTest : public testing::Test { - public: - JsToCppTest() {} - - void RunTest(const std::string& test, CppSideConnection* cpp_side) { - cpp_side->set_run_loop(&run_loop_); - - js_to_cpp::JsSidePtr js_side; - auto js_side_proxy = GetProxy(&js_side); - - cpp_side->set_js_side(js_side.get()); - js_to_cpp::CppSidePtr cpp_side_ptr; - cpp_side->Bind(GetProxy(&cpp_side_ptr)); - - js_side->SetCppSide(std::move(cpp_side_ptr)); - - gin::IsolateHolder::Initialize(gin::IsolateHolder::kStrictMode, - gin::IsolateHolder::kStableV8Extras, - gin::ArrayBufferAllocator::SharedInstance()); - gin::IsolateHolder instance; - MojoRunnerDelegate delegate; - gin::ShellRunner runner(&delegate, instance.isolate()); - delegate.Start(&runner, js_side_proxy.PassMessagePipe().release().value(), - test); - - run_loop_.Run(); - } - - private: - base::ShadowingAtExitManager at_exit_; - base::MessageLoop loop; - base::RunLoop run_loop_; - - DISALLOW_COPY_AND_ASSIGN(JsToCppTest); -}; - -TEST_F(JsToCppTest, Ping) { - PingCppSideConnection cpp_side_connection; - RunTest("mojo/edk/js/tests/js_to_cpp_tests", &cpp_side_connection); - EXPECT_TRUE(cpp_side_connection.DidSucceed()); -} - -TEST_F(JsToCppTest, Echo) { - EchoCppSideConnection cpp_side_connection; - RunTest("mojo/edk/js/tests/js_to_cpp_tests", &cpp_side_connection); - EXPECT_TRUE(cpp_side_connection.DidSucceed()); -} - -TEST_F(JsToCppTest, BitFlip) { - BitFlipCppSideConnection cpp_side_connection; - RunTest("mojo/edk/js/tests/js_to_cpp_tests", &cpp_side_connection); - EXPECT_TRUE(cpp_side_connection.DidSucceed()); -} - -TEST_F(JsToCppTest, BackPointer) { - BackPointerCppSideConnection cpp_side_connection; - RunTest("mojo/edk/js/tests/js_to_cpp_tests", &cpp_side_connection); - EXPECT_TRUE(cpp_side_connection.DidSucceed()); -} - -} // namespace js -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/js/tests/js_to_cpp_tests.js b/third_party/mojo/src/mojo/edk/js/tests/js_to_cpp_tests.js deleted file mode 100644 index ddecc4b..0000000 --- a/third_party/mojo/src/mojo/edk/js/tests/js_to_cpp_tests.js +++ /dev/null @@ -1,228 +0,0 @@ -// 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. - -define('mojo/edk/js/tests/js_to_cpp_tests', [ - 'console', - 'mojo/edk/js/tests/js_to_cpp.mojom', - 'mojo/public/js/bindings', - 'mojo/public/js/connection', - 'mojo/public/js/connector', - 'mojo/public/js/core', -], function (console, jsToCpp, bindings, connection, connector, core) { - var retainedJsSide; - var retainedJsSideStub; - var sampleData; - var sampleMessage; - var BAD_VALUE = 13; - var DATA_PIPE_PARAMS = { - flags: core.CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, - elementNumBytes: 1, - capacityNumBytes: 64 - }; - - function JsSideConnection() { - } - - JsSideConnection.prototype = - Object.create(jsToCpp.JsSide.stubClass.prototype); - - JsSideConnection.prototype.setCppSide = function(cppSide) { - this.cppSide_ = cppSide; - this.cppSide_.startTest(); - }; - - JsSideConnection.prototype.ping = function (arg) { - this.cppSide_.pingResponse(); - }; - - JsSideConnection.prototype.echo = function (numIterations, arg) { - var dataPipe1; - var dataPipe2; - var i; - var messagePipe1; - var messagePipe2; - var specialArg; - - // Ensure expected negative values are negative. - if (arg.si64 > 0) - arg.si64 = BAD_VALUE; - - if (arg.si32 > 0) - arg.si32 = BAD_VALUE; - - if (arg.si16 > 0) - arg.si16 = BAD_VALUE; - - if (arg.si8 > 0) - arg.si8 = BAD_VALUE; - - for (i = 0; i < numIterations; ++i) { - dataPipe1 = core.createDataPipe(DATA_PIPE_PARAMS); - dataPipe2 = core.createDataPipe(DATA_PIPE_PARAMS); - messagePipe1 = core.createMessagePipe(); - messagePipe2 = core.createMessagePipe(); - - arg.data_handle = dataPipe1.consumerHandle; - arg.message_handle = messagePipe1.handle1; - - specialArg = new jsToCpp.EchoArgs(); - specialArg.si64 = -1; - specialArg.si32 = -1; - specialArg.si16 = -1; - specialArg.si8 = -1; - specialArg.name = 'going'; - specialArg.data_handle = dataPipe2.consumerHandle; - specialArg.message_handle = messagePipe2.handle1; - - writeDataPipe(dataPipe1, sampleData); - writeDataPipe(dataPipe2, sampleData); - writeMessagePipe(messagePipe1, sampleMessage); - writeMessagePipe(messagePipe2, sampleMessage); - - this.cppSide_.echoResponse(createEchoArgsList(specialArg, arg)); - - core.close(dataPipe1.producerHandle); - core.close(dataPipe2.producerHandle); - core.close(messagePipe1.handle0); - core.close(messagePipe2.handle0); - } - this.cppSide_.testFinished(); - }; - - JsSideConnection.prototype.bitFlip = function (arg) { - var iteration = 0; - var dataPipe; - var messagePipe; - var proto = connector.Connector.prototype; - var stopSignalled = false; - - proto.realAccept = proto.accept; - proto.accept = function (message) { - var offset = iteration / 8; - var mask; - var value; - if (offset < message.buffer.arrayBuffer.byteLength) { - mask = 1 << (iteration % 8); - value = message.buffer.getUint8(offset) ^ mask; - message.buffer.setUint8(offset, value); - return this.realAccept(message); - } - stopSignalled = true; - return false; - }; - - while (!stopSignalled) { - dataPipe = core.createDataPipe(DATA_PIPE_PARAMS); - messagePipe = core.createMessagePipe(); - writeDataPipe(dataPipe, sampleData); - writeMessagePipe(messagePipe, sampleMessage); - arg.data_handle = dataPipe.consumerHandle; - arg.message_handle = messagePipe.handle1; - - this.cppSide_.bitFlipResponse(createEchoArgsList(arg)); - - core.close(dataPipe.producerHandle); - core.close(messagePipe.handle0); - iteration += 1; - } - - proto.accept = proto.realAccept; - proto.realAccept = null; - this.cppSide_.testFinished(); - }; - - JsSideConnection.prototype.backPointer = function (arg) { - var iteration = 0; - var dataPipe; - var messagePipe; - var proto = connector.Connector.prototype; - var stopSignalled = false; - - proto.realAccept = proto.accept; - proto.accept = function (message) { - var delta = 8 * (1 + iteration % 32); - var offset = 8 * ((iteration / 32) | 0); - if (offset < message.buffer.arrayBuffer.byteLength - 4) { - message.buffer.dataView.setUint32(offset, 0x100000000 - delta, true); - message.buffer.dataView.setUint32(offset + 4, 0xffffffff, true); - return this.realAccept(message); - } - stopSignalled = true; - return false; - }; - - while (!stopSignalled) { - dataPipe = core.createDataPipe(DATA_PIPE_PARAMS); - messagePipe = core.createMessagePipe(); - writeDataPipe(dataPipe, sampleData); - writeMessagePipe(messagePipe, sampleMessage); - arg.data_handle = dataPipe.consumerHandle; - arg.message_handle = messagePipe.handle1; - - this.cppSide_.backPointerResponse(createEchoArgsList(arg)); - - core.close(dataPipe.producerHandle); - core.close(messagePipe.handle0); - iteration += 1; - } - - proto.accept = proto.realAccept; - proto.realAccept = null; - this.cppSide_.testFinished(); - }; - - function writeDataPipe(pipe, data) { - var writeResult = core.writeData( - pipe.producerHandle, data, core.WRITE_DATA_FLAG_ALL_OR_NONE); - - if (writeResult.result != core.RESULT_OK) { - console.log('ERROR: Data pipe write result was ' + writeResult.result); - return false; - } - if (writeResult.numBytes != data.length) { - console.log('ERROR: Data pipe write length was ' + writeResult.numBytes); - return false; - } - return true; - } - - function writeMessagePipe(pipe, arrayBuffer) { - var result = core.writeMessage(pipe.handle0, arrayBuffer, [], 0); - if (result != core.RESULT_OK) { - console.log('ERROR: Message pipe write result was ' + result); - return false; - } - return true; - } - - function createEchoArgsListElement(item, next) { - var list = new jsToCpp.EchoArgsList(); - list.item = item; - list.next = next; - return list; - } - - function createEchoArgsList() { - var genuineArray = Array.prototype.slice.call(arguments); - return genuineArray.reduceRight(function (previous, current) { - return createEchoArgsListElement(current, previous); - }, null); - } - - return function(jsSideRequestHandle) { - var i; - sampleData = new Uint8Array(DATA_PIPE_PARAMS.capacityNumBytes); - for (i = 0; i < sampleData.length; ++i) { - sampleData[i] = i; - } - sampleMessage = new Uint8Array(DATA_PIPE_PARAMS.capacityNumBytes); - for (i = 0; i < sampleMessage.length; ++i) { - sampleMessage[i] = 255 - i; - } - retainedJsSideStub = - connection.bindHandleToStub(jsSideRequestHandle, jsToCpp.JsSide); - retainedJsSide = new JsSideConnection; - bindings.StubBindings(retainedJsSideStub).delegate = retainedJsSide; - }; -}); diff --git a/third_party/mojo/src/mojo/edk/js/tests/sample_service_tests.js b/third_party/mojo/src/mojo/edk/js/tests/sample_service_tests.js deleted file mode 100644 index ac8ce2e..0000000 --- a/third_party/mojo/src/mojo/edk/js/tests/sample_service_tests.js +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2013 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. - -define([ - "console", - "mojo/edk/js/test/hexdump", - "gin/test/expect", - "mojo/public/interfaces/bindings/tests/sample_service.mojom", - "mojo/public/interfaces/bindings/tests/sample_import.mojom", - "mojo/public/interfaces/bindings/tests/sample_import2.mojom", - "mojo/public/js/core", - ], function(console, hexdump, expect, sample, imported, imported2, core) { - - var global = this; - - // Set this variable to true to print the binary message in hex. - var dumpMessageAsHex = false; - - function makeFoo() { - var bar = new sample.Bar(); - bar.alpha = 20; - bar.beta = 40; - bar.gamma = 60; - bar.type = sample.Bar.Type.VERTICAL; - - var extra_bars = new Array(3); - for (var i = 0; i < extra_bars.length; ++i) { - var base = i * 100; - var type = i % 2 ? - sample.Bar.Type.VERTICAL : sample.Bar.Type.HORIZONTAL; - extra_bars[i] = new sample.Bar(); - extra_bars[i].alpha = base; - extra_bars[i].beta = base + 20; - extra_bars[i].gamma = base + 40; - extra_bars[i].type = type; - } - - var data = new Array(10); - for (var i = 0; i < data.length; ++i) { - data[i] = data.length - i; - } - - var source = 0xFFFF; // Invent a dummy handle. - - var foo = new sample.Foo(); - foo.name = "foopy"; - foo.x = 1; - foo.y = 2; - foo.a = false; - foo.b = true; - foo.c = false; - foo.bar = bar; - foo.extra_bars = extra_bars; - foo.data = data; - foo.source = source; - return foo; - } - - // Check that the given |Foo| is identical to the one made by |MakeFoo()|. - function checkFoo(foo) { - expect(foo.name).toBe("foopy"); - expect(foo.x).toBe(1); - expect(foo.y).toBe(2); - expect(foo.a).toBeFalsy(); - expect(foo.b).toBeTruthy(); - expect(foo.c).toBeFalsy(); - expect(foo.bar.alpha).toBe(20); - expect(foo.bar.beta).toBe(40); - expect(foo.bar.gamma).toBe(60); - expect(foo.bar.type).toBe(sample.Bar.Type.VERTICAL); - - expect(foo.extra_bars.length).toBe(3); - for (var i = 0; i < foo.extra_bars.length; ++i) { - var base = i * 100; - var type = i % 2 ? - sample.Bar.Type.VERTICAL : sample.Bar.Type.HORIZONTAL; - expect(foo.extra_bars[i].alpha).toBe(base); - expect(foo.extra_bars[i].beta).toBe(base + 20); - expect(foo.extra_bars[i].gamma).toBe(base + 40); - expect(foo.extra_bars[i].type).toBe(type); - } - - expect(foo.data.length).toBe(10); - for (var i = 0; i < foo.data.length; ++i) - expect(foo.data[i]).toBe(foo.data.length - i); - - expect(foo.source).toBe(0xFFFF); - } - - // Check that values are set to the defaults if we don't override them. - function checkDefaultValues() { - var bar = new sample.Bar(); - expect(bar.alpha).toBe(255); - expect(bar.type).toBe(sample.Bar.Type.VERTICAL); - - var foo = new sample.Foo(); - expect(foo.name).toBe("Fooby"); - expect(foo.a).toBeTruthy(); - expect(foo.data).toBeNull(); - - var defaults = new sample.DefaultsTest(); - expect(defaults.a0).toBe(-12); - expect(defaults.a1).toBe(sample.kTwelve); - expect(defaults.a2).toBe(1234); - expect(defaults.a3).toBe(34567); - expect(defaults.a4).toBe(123456); - expect(defaults.a5).toBe(3456789012); - expect(defaults.a6).toBe(-111111111111); - // JS doesn't have a 64 bit integer type so this is just checking that the - // expected and actual values have the same closest double value. - expect(defaults.a7).toBe(9999999999999999999); - expect(defaults.a8).toBe(0x12345); - expect(defaults.a9).toBe(-0x12345); - expect(defaults.a10).toBe(1234); - expect(defaults.a11).toBe(true); - expect(defaults.a12).toBe(false); - expect(defaults.a13).toBe(123.25); - expect(defaults.a14).toBe(1234567890.123); - expect(defaults.a15).toBe(1E10); - expect(defaults.a16).toBe(-1.2E+20); - expect(defaults.a17).toBe(1.23E-20); - expect(defaults.a20).toBe(sample.Bar.Type.BOTH); - expect(defaults.a21).toBeNull(); - expect(defaults.a22).toBeTruthy(); - expect(defaults.a22.shape).toBe(imported.Shape.RECTANGLE); - expect(defaults.a22.color).toBe(imported2.Color.BLACK); - expect(defaults.a21).toBeNull(); - expect(defaults.a23).toBe(0xFFFFFFFFFFFFFFFF); - expect(defaults.a24).toBe(0x123456789); - expect(defaults.a25).toBe(-0x123456789); - } - - function ServiceImpl() { - } - - ServiceImpl.prototype = Object.create(sample.Service.stubClass.prototype); - - ServiceImpl.prototype.frobinate = function(foo, baz, port) { - checkFoo(foo); - expect(baz).toBe(sample.Service.BazOptions.EXTRA); - expect(core.isHandle(port)).toBeTruthy(); - global.result = "PASS"; - }; - - function SimpleMessageReceiver() { - } - - SimpleMessageReceiver.prototype.acceptAndExpectResponse = function(message) { - if (dumpMessageAsHex) { - var uint8Array = new Uint8Array(message.buffer.arrayBuffer); - console.log(hexdump.dumpArray(uint8Array)); - } - // Imagine some IPC happened here. - var serviceImpl = new ServiceImpl(); - return serviceImpl.acceptWithResponder(message, { accept: function() {} }); - }; - - var serviceProxy = new sample.Service.proxyClass; - serviceProxy.receiver_ = new SimpleMessageReceiver; - - checkDefaultValues(); - - var foo = makeFoo(); - checkFoo(foo); - - var pipe = core.createMessagePipe(); - serviceProxy.frobinate(foo, sample.Service.BazOptions.EXTRA, pipe.handle0); - expect(core.close(pipe.handle0)).toBe(core.RESULT_OK); - expect(core.close(pipe.handle1)).toBe(core.RESULT_OK); -}); diff --git a/third_party/mojo/src/mojo/edk/js/threading.cc b/third_party/mojo/src/mojo/edk/js/threading.cc deleted file mode 100644 index 6989276..0000000 --- a/third_party/mojo/src/mojo/edk/js/threading.cc +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/js/threading.h" - -#include "base/message_loop/message_loop.h" -#include "gin/object_template_builder.h" -#include "gin/per_isolate_data.h" -#include "third_party/mojo/src/mojo/edk/js/handle.h" - -namespace mojo { -namespace js { - -namespace { - -void Quit() { - base::MessageLoop::current()->QuitNow(); -} - -gin::WrapperInfo g_wrapper_info = { gin::kEmbedderNativeGin }; - -} // namespace - -const char Threading::kModuleName[] = "mojo/public/js/threading"; - -v8::Local<v8::Value> Threading::GetModule(v8::Isolate* isolate) { - gin::PerIsolateData* data = gin::PerIsolateData::From(isolate); - v8::Local<v8::ObjectTemplate> templ = data->GetObjectTemplate( - &g_wrapper_info); - - if (templ.IsEmpty()) { - templ = gin::ObjectTemplateBuilder(isolate) - .SetMethod("quit", Quit) - .Build(); - - data->SetObjectTemplate(&g_wrapper_info, templ); - } - - return templ->NewInstance(); -} - -Threading::Threading() { -} - -} // namespace js -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/js/threading.h b/third_party/mojo/src/mojo/edk/js/threading.h deleted file mode 100644 index ef8f722..0000000 --- a/third_party/mojo/src/mojo/edk/js/threading.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_THREADING_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_THREADING_H_ - -#include "gin/public/wrapper_info.h" -#include "v8/include/v8.h" - -namespace mojo { -namespace js { - -class Threading { - public: - static const char kModuleName[]; - static v8::Local<v8::Value> GetModule(v8::Isolate* isolate); - private: - Threading(); -}; - -} // namespace js -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_THREADING_H_ diff --git a/third_party/mojo/src/mojo/edk/js/waiting_callback.cc b/third_party/mojo/src/mojo/edk/js/waiting_callback.cc deleted file mode 100644 index 65833f3..0000000 --- a/third_party/mojo/src/mojo/edk/js/waiting_callback.cc +++ /dev/null @@ -1,121 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/js/waiting_callback.h" - -#include "base/bind.h" -#include "base/message_loop/message_loop.h" -#include "gin/per_context_data.h" -#include "mojo/public/cpp/environment/environment.h" - -namespace mojo { -namespace js { - -namespace { - -v8::Handle<v8::Private> GetHiddenPropertyName(v8::Isolate* isolate) { - return v8::Private::ForApi( - isolate, gin::StringToV8(isolate, "::mojo::js::WaitingCallback")); -} - -} // namespace - -gin::WrapperInfo WaitingCallback::kWrapperInfo = { gin::kEmbedderNativeGin }; - -// static -gin::Handle<WaitingCallback> WaitingCallback::Create( - v8::Isolate* isolate, - v8::Handle<v8::Function> callback, - gin::Handle<HandleWrapper> handle_wrapper, - MojoHandleSignals signals) { - gin::Handle<WaitingCallback> waiting_callback = gin::CreateHandle( - isolate, new WaitingCallback(isolate, callback, handle_wrapper)); - waiting_callback->wait_id_ = Environment::GetDefaultAsyncWaiter()->AsyncWait( - handle_wrapper->get().value(), - signals, - MOJO_DEADLINE_INDEFINITE, - &WaitingCallback::CallOnHandleReady, - waiting_callback.get()); - return waiting_callback; -} - -void WaitingCallback::Cancel() { - if (!wait_id_) - return; - - handle_wrapper_->RemoveCloseObserver(this); - handle_wrapper_ = NULL; - Environment::GetDefaultAsyncWaiter()->CancelWait(wait_id_); - wait_id_ = 0; -} - -WaitingCallback::WaitingCallback(v8::Isolate* isolate, - v8::Handle<v8::Function> callback, - gin::Handle<HandleWrapper> handle_wrapper) - : wait_id_(0), handle_wrapper_(handle_wrapper.get()), weak_factory_(this) { - handle_wrapper_->AddCloseObserver(this); - v8::Handle<v8::Context> context = isolate->GetCurrentContext(); - runner_ = gin::PerContextData::From(context)->runner()->GetWeakPtr(); - GetWrapper(isolate) - ->SetPrivate(context, GetHiddenPropertyName(isolate), callback) - .FromJust(); -} - -WaitingCallback::~WaitingCallback() { - Cancel(); -} - -// static -void WaitingCallback::CallOnHandleReady(void* closure, MojoResult result) { - static_cast<WaitingCallback*>(closure)->OnHandleReady(result); -} - -void WaitingCallback::ClearWaitId() { - wait_id_ = 0; - handle_wrapper_->RemoveCloseObserver(this); - handle_wrapper_ = nullptr; -} - -void WaitingCallback::OnHandleReady(MojoResult result) { - ClearWaitId(); - CallCallback(result); -} - -void WaitingCallback::CallCallback(MojoResult result) { - // ClearWaitId must already have been called. - DCHECK(!wait_id_); - DCHECK(!handle_wrapper_); - - if (!runner_) - return; - - gin::Runner::Scope scope(runner_.get()); - v8::Isolate* isolate = runner_->GetContextHolder()->isolate(); - - v8::Handle<v8::Value> hidden_value = - GetWrapper(isolate) - ->GetPrivate(runner_->GetContextHolder()->context(), - GetHiddenPropertyName(isolate)) - .ToLocalChecked(); - v8::Handle<v8::Function> callback; - CHECK(gin::ConvertFromV8(isolate, hidden_value, &callback)); - - v8::Handle<v8::Value> args[] = { gin::ConvertToV8(isolate, result) }; - runner_->Call(callback, runner_->global(), 1, args); -} - -void WaitingCallback::OnWillCloseHandle() { - Environment::GetDefaultAsyncWaiter()->CancelWait(wait_id_); - - // This may be called from GC, so we can't execute Javascript now, call - // ClearWaitId explicitly, and CallCallback asynchronously. - ClearWaitId(); - base::MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&WaitingCallback::CallCallback, weak_factory_.GetWeakPtr(), - MOJO_RESULT_INVALID_ARGUMENT)); -} - -} // namespace js -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/js/waiting_callback.h b/third_party/mojo/src/mojo/edk/js/waiting_callback.h deleted file mode 100644 index 63f4d0c..0000000 --- a/third_party/mojo/src/mojo/edk/js/waiting_callback.h +++ /dev/null @@ -1,68 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_WAITING_CALLBACK_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_WAITING_CALLBACK_H_ - -#include "base/memory/weak_ptr.h" -#include "gin/handle.h" -#include "gin/runner.h" -#include "gin/wrappable.h" -#include "mojo/public/c/environment/async_waiter.h" -#include "mojo/public/cpp/system/core.h" -#include "third_party/mojo/src/mojo/edk/js/handle.h" -#include "third_party/mojo/src/mojo/edk/js/handle_close_observer.h" - -namespace mojo { -namespace js { - -class WaitingCallback : public gin::Wrappable<WaitingCallback>, - public HandleCloseObserver { - public: - static gin::WrapperInfo kWrapperInfo; - - // Creates a new WaitingCallback. - static gin::Handle<WaitingCallback> Create( - v8::Isolate* isolate, - v8::Handle<v8::Function> callback, - gin::Handle<HandleWrapper> handle_wrapper, - MojoHandleSignals signals); - - // Cancels the callback. Does nothing if a callback is not pending. This is - // implicitly invoked from the destructor but can be explicitly invoked as - // necessary. - void Cancel(); - - private: - WaitingCallback(v8::Isolate* isolate, - v8::Handle<v8::Function> callback, - gin::Handle<HandleWrapper> handle_wrapper); - ~WaitingCallback() override; - - // Callback from MojoAsyncWaiter. |closure| is the WaitingCallback. - static void CallOnHandleReady(void* closure, MojoResult result); - - // Invoked from CallOnHandleReady() (CallOnHandleReady() must be static). - void OnHandleReady(MojoResult result); - - // Invoked by the HandleWrapper if the handle is closed while this wait is - // still in progress. - void OnWillCloseHandle() override; - - void ClearWaitId(); - void CallCallback(MojoResult result); - - base::WeakPtr<gin::Runner> runner_; - MojoAsyncWaitID wait_id_; - - HandleWrapper* handle_wrapper_; - base::WeakPtrFactory<WaitingCallback> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(WaitingCallback); -}; - -} // namespace js -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_JS_WAITING_CALLBACK_H_ diff --git a/third_party/mojo/src/mojo/edk/system/BUILD.gn b/third_party/mojo/src/mojo/edk/system/BUILD.gn deleted file mode 100644 index 656ac72..0000000 --- a/third_party/mojo/src/mojo/edk/system/BUILD.gn +++ /dev/null @@ -1,252 +0,0 @@ -# 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. - -import("//testing/test.gni") - -if (is_android) { - import("//build/config/android/config.gni") - import("//build/config/android/rules.gni") -} - -config("system_config") { - defines = [ - # Ensures that dependent projects import the core functions on Windows. - "MOJO_USE_SYSTEM_IMPL", - ] -} - -component("system") { - output_name = "mojo_system_impl" - - sources = [ - "async_waiter.cc", - "async_waiter.h", - "awakable.h", - "awakable_list.cc", - "awakable_list.h", - "channel.cc", - "channel.h", - "channel_endpoint.cc", - "channel_endpoint.h", - "channel_endpoint_client.h", - "channel_endpoint_id.cc", - "channel_endpoint_id.h", - "channel_id.h", - "channel_manager.cc", - "channel_manager.h", - "configuration.cc", - "configuration.h", - "connection_identifier.h", - "connection_manager.cc", - "connection_manager.h", - "connection_manager_messages.h", - "core.cc", - "core.h", - "data_pipe.cc", - "data_pipe.h", - "data_pipe_consumer_dispatcher.cc", - "data_pipe_consumer_dispatcher.h", - "data_pipe_impl.cc", - "data_pipe_impl.h", - "data_pipe_producer_dispatcher.cc", - "data_pipe_producer_dispatcher.h", - "dispatcher.cc", - "dispatcher.h", - "endpoint_relayer.cc", - "endpoint_relayer.h", - "handle_signals_state.h", - "handle_table.cc", - "handle_table.h", - "incoming_endpoint.cc", - "incoming_endpoint.h", - "ipc_support.cc", - "ipc_support.h", - "local_data_pipe_impl.cc", - "local_data_pipe_impl.h", - "local_message_pipe_endpoint.cc", - "local_message_pipe_endpoint.h", - "mapping_table.cc", - "mapping_table.h", - "master_connection_manager.cc", - "master_connection_manager.h", - "memory.cc", - "memory.h", - "message_in_transit.cc", - "message_in_transit.h", - "message_in_transit_queue.cc", - "message_in_transit_queue.h", - "message_pipe.cc", - "message_pipe.h", - "message_pipe_dispatcher.cc", - "message_pipe_dispatcher.h", - "message_pipe_endpoint.cc", - "message_pipe_endpoint.h", - "mutex.cc", - "mutex.h", - "options_validation.h", - "platform_handle_dispatcher.cc", - "platform_handle_dispatcher.h", - "process_identifier.h", - "proxy_message_pipe_endpoint.cc", - "proxy_message_pipe_endpoint.h", - "raw_channel.cc", - "raw_channel.h", - "raw_channel_posix.cc", - "raw_channel_win.cc", - "remote_consumer_data_pipe_impl.cc", - "remote_consumer_data_pipe_impl.h", - "remote_data_pipe_ack.h", - "remote_producer_data_pipe_impl.cc", - "remote_producer_data_pipe_impl.h", - "shared_buffer_dispatcher.cc", - "shared_buffer_dispatcher.h", - "simple_dispatcher.cc", - "simple_dispatcher.h", - "slave_connection_manager.cc", - "slave_connection_manager.h", - "thread_annotations.h", - "transport_data.cc", - "transport_data.h", - "unique_identifier.cc", - "unique_identifier.h", - "wait_set_dispatcher.cc", - "wait_set_dispatcher.h", - "waiter.cc", - "waiter.h", - ] - - defines = [ - "MOJO_SYSTEM_IMPL_IMPLEMENTATION", - "MOJO_SYSTEM_IMPLEMENTATION", - ] - - all_dependent_configs = [ ":system_config" ] - - public_deps = [ - "../embedder", - "../embedder:delegates", - "../embedder:platform", - - # TODO(use_chrome_edk): so that EDK in third_party can choose the EDK in - # src/mojo if the command line flag is specified. It has to since we can - # only have one definition of the Mojo primitives. - "//mojo/edk/system", - "//mojo/public/c/system", - "//mojo/public/cpp/system", - ] - - deps = [ - "//base", - "//base/third_party/dynamic_annotations", - ] - - allow_circular_includes_from = [ "../embedder" ] -} - -group("tests") { - testonly = true - deps = [ - ":mojo_message_pipe_perftests", - ":mojo_system_unittests", - ] -} - -source_set("test_utils") { - testonly = true - - sources = [ - "test_utils.cc", - "test_utils.h", - ] - - public_deps = [ - "//mojo/public/c/system", - "//mojo/public/cpp/system", - ] - - deps = [ - "//base", - "//base/test:test_support", - ] -} - -test("mojo_system_unittests") { - sources = [ - "../test/multiprocess_test_helper_unittest.cc", - "awakable_list_unittest.cc", - "channel_endpoint_id_unittest.cc", - "channel_endpoint_unittest.cc", - "channel_manager_unittest.cc", - "channel_test_base.cc", - "channel_test_base.h", - "channel_unittest.cc", - "connection_manager_unittest.cc", - "core_test_base.cc", - "core_test_base.h", - "core_unittest.cc", - "data_pipe_impl_unittest.cc", - "data_pipe_unittest.cc", - "dispatcher_unittest.cc", - "endpoint_relayer_unittest.cc", - "ipc_support_unittest.cc", - "memory_unittest.cc", - "message_in_transit_queue_unittest.cc", - "message_in_transit_test_utils.cc", - "message_in_transit_test_utils.h", - "message_pipe_dispatcher_unittest.cc", - "message_pipe_test_utils.cc", - "message_pipe_test_utils.h", - "message_pipe_unittest.cc", - "multiprocess_message_pipe_unittest.cc", - "mutex_unittest.cc", - "options_validation_unittest.cc", - "platform_handle_dispatcher_unittest.cc", - "raw_channel_unittest.cc", - "remote_data_pipe_impl_unittest.cc", - "remote_message_pipe_unittest.cc", - "run_all_unittests.cc", - "shared_buffer_dispatcher_unittest.cc", - "simple_dispatcher_unittest.cc", - "test_channel_endpoint_client.cc", - "test_channel_endpoint_client.h", - "thread_annotations_unittest.cc", - "unique_identifier_unittest.cc", - "wait_set_dispatcher_unittest.cc", - "waiter_test_utils.cc", - "waiter_test_utils.h", - "waiter_unittest.cc", - ] - - deps = [ - ":system", - ":test_utils", - "../embedder:embedder_unittests", - "../test:test_support", - "//base", - "//base/test:test_support", - "//mojo/public/cpp/environment:standalone", - "//testing/gtest", - ] - - allow_circular_includes_from = [ "../embedder:embedder_unittests" ] -} - -test("mojo_message_pipe_perftests") { - sources = [ - "message_pipe_perftest.cc", - "message_pipe_test_utils.cc", - "message_pipe_test_utils.h", - ] - - deps = [ - ":system", - ":test_utils", - "../test:test_support", - "//base", - "//base/test:test_support", - "//base/test:test_support_perf", - "//mojo/public/cpp/environment:standalone", - "//testing/gtest", - ] -} diff --git a/third_party/mojo/src/mojo/edk/system/async_waiter.cc b/third_party/mojo/src/mojo/edk/system/async_waiter.cc deleted file mode 100644 index 9f42624..0000000 --- a/third_party/mojo/src/mojo/edk/system/async_waiter.cc +++ /dev/null @@ -1,23 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/async_waiter.h" - -namespace mojo { -namespace system { - -AsyncWaiter::AsyncWaiter(const AwakeCallback& callback) : callback_(callback) { -} - -AsyncWaiter::~AsyncWaiter() { -} - -bool AsyncWaiter::Awake(MojoResult result, uintptr_t context) { - callback_.Run(result); - delete this; - return false; -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/async_waiter.h b/third_party/mojo/src/mojo/edk/system/async_waiter.h deleted file mode 100644 index 3dd96ac..0000000 --- a/third_party/mojo/src/mojo/edk/system/async_waiter.h +++ /dev/null @@ -1,38 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_ASYNC_WAITER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_ASYNC_WAITER_H_ - -#include "base/callback.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/awakable.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -// An |Awakable| implementation that just calls a given callback object. -class MOJO_SYSTEM_IMPL_EXPORT AsyncWaiter final : public Awakable { - public: - using AwakeCallback = base::Callback<void(MojoResult)>; - - // |callback| must satisfy the same contract as |Awakable::Awake()|. - explicit AsyncWaiter(const AwakeCallback& callback); - virtual ~AsyncWaiter(); - - private: - // |Awakable| implementation: - bool Awake(MojoResult result, uintptr_t context) override; - - AwakeCallback callback_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(AsyncWaiter); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_ASYNC_WAITER_H_ diff --git a/third_party/mojo/src/mojo/edk/system/awakable.h b/third_party/mojo/src/mojo/edk/system/awakable.h deleted file mode 100644 index ae1376c..0000000 --- a/third_party/mojo/src/mojo/edk/system/awakable.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_AWAKABLE_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_AWAKABLE_H_ - -#include <stdint.h> - -#include "mojo/public/c/system/types.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -// An interface that may be waited on |AwakableList|. -class MOJO_SYSTEM_IMPL_EXPORT Awakable { - public: - // |Awake()| must satisfy the following contract: - // * As this is called from any thread, this must be thread-safe. - // * As this is called inside a lock, this must not call anything that takes - // "non-terminal" locks, i.e., those which are always safe to take. - // This should return false if this must not be called again for the same - // reason (e.g., for the same call to |AwakableList::Add()|). - virtual bool Awake(MojoResult result, uintptr_t context) = 0; - - protected: - Awakable() {} -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_AWAKABLE_H_ diff --git a/third_party/mojo/src/mojo/edk/system/awakable_list.cc b/third_party/mojo/src/mojo/edk/system/awakable_list.cc deleted file mode 100644 index f20e88a..0000000 --- a/third_party/mojo/src/mojo/edk/system/awakable_list.cc +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/awakable_list.h" - -#include <algorithm> - -#include "base/logging.h" -#include "third_party/mojo/src/mojo/edk/system/awakable.h" -#include "third_party/mojo/src/mojo/edk/system/handle_signals_state.h" - -namespace mojo { -namespace system { - -AwakableList::AwakableList() { -} - -AwakableList::~AwakableList() { - DCHECK(awakables_.empty()); -} - -void AwakableList::AwakeForStateChange(const HandleSignalsState& state) { - // Instead of deleting elements in-place, swap them with the last element and - // erase the elements from the end. - auto last = awakables_.end(); - for (AwakeInfoList::iterator it = awakables_.begin(); it != last;) { - bool keep = true; - if (state.satisfies(it->signals)) - keep = it->awakable->Awake(MOJO_RESULT_OK, it->context); - else if (!state.can_satisfy(it->signals)) - keep = it->awakable->Awake(MOJO_RESULT_FAILED_PRECONDITION, it->context); - - if (!keep) { - --last; - std::swap(*it, *last); - } else { - ++it; - } - } - awakables_.erase(last, awakables_.end()); -} - -void AwakableList::CancelAll() { - for (AwakeInfoList::iterator it = awakables_.begin(); it != awakables_.end(); - ++it) { - it->awakable->Awake(MOJO_RESULT_CANCELLED, it->context); - } - awakables_.clear(); -} - -void AwakableList::Add(Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context) { - awakables_.push_back(AwakeInfo(awakable, signals, context)); -} - -void AwakableList::Remove(Awakable* awakable) { - // We allow a thread to wait on the same handle multiple times simultaneously, - // so we need to scan the entire list and remove all occurrences of |waiter|. - auto last = awakables_.end(); - for (AwakeInfoList::iterator it = awakables_.begin(); it != last;) { - if (it->awakable == awakable) { - --last; - std::swap(*it, *last); - } else { - ++it; - } - } - awakables_.erase(last, awakables_.end()); -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/awakable_list.h b/third_party/mojo/src/mojo/edk/system/awakable_list.h deleted file mode 100644 index 5eedc56..0000000 --- a/third_party/mojo/src/mojo/edk/system/awakable_list.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_AWAKABLE_LIST_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_AWAKABLE_LIST_H_ - -#include <stdint.h> - -#include <vector> - -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -class Awakable; -struct HandleSignalsState; - -// |AwakableList| tracks all the |Waiter|s that are waiting on a given -// handle/|Dispatcher|. There should be a |AwakableList| for each handle that -// can be waited on (in any way). In the simple case, the |AwakableList| is -// owned by the |Dispatcher|, whereas in more complex cases it is owned by the -// secondary object (see simple_dispatcher.* and the explanatory comment in -// core.cc). This class is thread-unsafe (all concurrent access must be -// protected by some lock). -class MOJO_SYSTEM_IMPL_EXPORT AwakableList { - public: - AwakableList(); - ~AwakableList(); - - void AwakeForStateChange(const HandleSignalsState& state); - void CancelAll(); - void Add(Awakable* awakable, MojoHandleSignals signals, uintptr_t context); - void Remove(Awakable* awakable); - - private: - struct AwakeInfo { - AwakeInfo(Awakable* awakable, MojoHandleSignals signals, uintptr_t context) - : awakable(awakable), signals(signals), context(context) {} - - Awakable* awakable; - MojoHandleSignals signals; - uintptr_t context; - }; - using AwakeInfoList = std::vector<AwakeInfo>; - - AwakeInfoList awakables_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(AwakableList); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_AWAKABLE_LIST_H_ diff --git a/third_party/mojo/src/mojo/edk/system/awakable_list_unittest.cc b/third_party/mojo/src/mojo/edk/system/awakable_list_unittest.cc deleted file mode 100644 index 9255fa9..0000000 --- a/third_party/mojo/src/mojo/edk/system/awakable_list_unittest.cc +++ /dev/null @@ -1,356 +0,0 @@ -// Copyright 2013 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. - -// NOTE(vtl): Some of these tests are inherently flaky (e.g., if run on a -// heavily-loaded system). Sorry. |test::EpsilonDeadline()| may be increased to -// increase tolerance and reduce observed flakiness (though doing so reduces the -// meaningfulness of the test). - -#include "third_party/mojo/src/mojo/edk/system/awakable_list.h" - -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/system/handle_signals_state.h" -#include "third_party/mojo/src/mojo/edk/system/test_utils.h" -#include "third_party/mojo/src/mojo/edk/system/waiter.h" -#include "third_party/mojo/src/mojo/edk/system/waiter_test_utils.h" - -namespace mojo { -namespace system { -namespace { - -TEST(AwakableListTest, BasicCancel) { - MojoResult result; - uintptr_t context; - - // Cancel immediately after thread start. - { - AwakableList awakable_list; - test::SimpleWaiterThread thread(&result, &context); - awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1); - thread.Start(); - awakable_list.CancelAll(); - // Double-remove okay: - awakable_list.Remove(thread.waiter()); - } // Join |thread|. - EXPECT_EQ(MOJO_RESULT_CANCELLED, result); - EXPECT_EQ(1u, context); - - // Cancel before after thread start. - { - AwakableList awakable_list; - test::SimpleWaiterThread thread(&result, &context); - awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2); - awakable_list.CancelAll(); - thread.Start(); - } // Join |thread|. - EXPECT_EQ(MOJO_RESULT_CANCELLED, result); - EXPECT_EQ(2u, context); - - // Cancel some time after thread start. - { - AwakableList awakable_list; - test::SimpleWaiterThread thread(&result, &context); - awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3); - thread.Start(); - test::Sleep(2 * test::EpsilonDeadline()); - awakable_list.CancelAll(); - } // Join |thread|. - EXPECT_EQ(MOJO_RESULT_CANCELLED, result); - EXPECT_EQ(3u, context); -} - -TEST(AwakableListTest, BasicAwakeSatisfied) { - MojoResult result; - uintptr_t context; - - // Awake immediately after thread start. - { - AwakableList awakable_list; - test::SimpleWaiterThread thread(&result, &context); - awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1); - thread.Start(); - awakable_list.AwakeForStateChange(HandleSignalsState( - MOJO_HANDLE_SIGNAL_READABLE, - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE)); - awakable_list.Remove(thread.waiter()); - } // Join |thread|. - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(1u, context); - - // Awake before after thread start. - { - AwakableList awakable_list; - test::SimpleWaiterThread thread(&result, &context); - awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2); - awakable_list.AwakeForStateChange(HandleSignalsState( - MOJO_HANDLE_SIGNAL_WRITABLE, - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE)); - awakable_list.Remove(thread.waiter()); - // Double-remove okay: - awakable_list.Remove(thread.waiter()); - thread.Start(); - } // Join |thread|. - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(2u, context); - - // Awake some time after thread start. - { - AwakableList awakable_list; - test::SimpleWaiterThread thread(&result, &context); - awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3); - thread.Start(); - test::Sleep(2 * test::EpsilonDeadline()); - awakable_list.AwakeForStateChange(HandleSignalsState( - MOJO_HANDLE_SIGNAL_READABLE, - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE)); - awakable_list.Remove(thread.waiter()); - } // Join |thread|. - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(3u, context); -} - -TEST(AwakableListTest, BasicAwakeUnsatisfiable) { - MojoResult result; - uintptr_t context; - - // Awake (for unsatisfiability) immediately after thread start. - { - AwakableList awakable_list; - test::SimpleWaiterThread thread(&result, &context); - awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1); - thread.Start(); - awakable_list.AwakeForStateChange(HandleSignalsState( - MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_WRITABLE)); - awakable_list.Remove(thread.waiter()); - } // Join |thread|. - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); - EXPECT_EQ(1u, context); - - // Awake (for unsatisfiability) before after thread start. - { - AwakableList awakable_list; - test::SimpleWaiterThread thread(&result, &context); - awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2); - awakable_list.AwakeForStateChange(HandleSignalsState( - MOJO_HANDLE_SIGNAL_READABLE, MOJO_HANDLE_SIGNAL_READABLE)); - awakable_list.Remove(thread.waiter()); - thread.Start(); - } // Join |thread|. - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); - EXPECT_EQ(2u, context); - - // Awake (for unsatisfiability) some time after thread start. - { - AwakableList awakable_list; - test::SimpleWaiterThread thread(&result, &context); - awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3); - thread.Start(); - test::Sleep(2 * test::EpsilonDeadline()); - awakable_list.AwakeForStateChange(HandleSignalsState( - MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_WRITABLE)); - awakable_list.Remove(thread.waiter()); - // Double-remove okay: - awakable_list.Remove(thread.waiter()); - } // Join |thread|. - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); - EXPECT_EQ(3u, context); -} - -TEST(AwakableListTest, MultipleAwakables) { - MojoResult result1; - MojoResult result2; - MojoResult result3; - MojoResult result4; - uintptr_t context1; - uintptr_t context2; - uintptr_t context3; - uintptr_t context4; - - // Cancel two awakables. - { - AwakableList awakable_list; - test::SimpleWaiterThread thread1(&result1, &context1); - awakable_list.Add(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1); - thread1.Start(); - test::SimpleWaiterThread thread2(&result2, &context2); - awakable_list.Add(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2); - thread2.Start(); - test::Sleep(2 * test::EpsilonDeadline()); - awakable_list.CancelAll(); - } // Join threads. - EXPECT_EQ(MOJO_RESULT_CANCELLED, result1); - EXPECT_EQ(1u, context1); - EXPECT_EQ(MOJO_RESULT_CANCELLED, result2); - EXPECT_EQ(2u, context2); - - // Awake one awakable, cancel other. - { - AwakableList awakable_list; - test::SimpleWaiterThread thread1(&result1, &context1); - awakable_list.Add(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3); - thread1.Start(); - test::SimpleWaiterThread thread2(&result2, &context2); - awakable_list.Add(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 4); - thread2.Start(); - test::Sleep(2 * test::EpsilonDeadline()); - awakable_list.AwakeForStateChange(HandleSignalsState( - MOJO_HANDLE_SIGNAL_READABLE, - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE)); - awakable_list.Remove(thread1.waiter()); - awakable_list.CancelAll(); - } // Join threads. - EXPECT_EQ(MOJO_RESULT_OK, result1); - EXPECT_EQ(3u, context1); - EXPECT_EQ(MOJO_RESULT_CANCELLED, result2); - EXPECT_EQ(4u, context2); - - // Cancel one awakable, awake other for unsatisfiability. - { - AwakableList awakable_list; - test::SimpleWaiterThread thread1(&result1, &context1); - awakable_list.Add(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 5); - thread1.Start(); - test::SimpleWaiterThread thread2(&result2, &context2); - awakable_list.Add(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 6); - thread2.Start(); - test::Sleep(2 * test::EpsilonDeadline()); - awakable_list.AwakeForStateChange(HandleSignalsState( - MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_READABLE)); - awakable_list.Remove(thread2.waiter()); - awakable_list.CancelAll(); - } // Join threads. - EXPECT_EQ(MOJO_RESULT_CANCELLED, result1); - EXPECT_EQ(5u, context1); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result2); - EXPECT_EQ(6u, context2); - - // Cancel one awakable, awake other for unsatisfiability. - { - AwakableList awakable_list; - test::SimpleWaiterThread thread1(&result1, &context1); - awakable_list.Add(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 7); - thread1.Start(); - - test::Sleep(1 * test::EpsilonDeadline()); - - // Should do nothing. - awakable_list.AwakeForStateChange(HandleSignalsState( - MOJO_HANDLE_SIGNAL_NONE, - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE)); - - test::SimpleWaiterThread thread2(&result2, &context2); - awakable_list.Add(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 8); - thread2.Start(); - - test::Sleep(1 * test::EpsilonDeadline()); - - // Awake #1. - awakable_list.AwakeForStateChange(HandleSignalsState( - MOJO_HANDLE_SIGNAL_READABLE, - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE)); - awakable_list.Remove(thread1.waiter()); - - test::Sleep(1 * test::EpsilonDeadline()); - - test::SimpleWaiterThread thread3(&result3, &context3); - awakable_list.Add(thread3.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 9); - thread3.Start(); - - test::SimpleWaiterThread thread4(&result4, &context4); - awakable_list.Add(thread4.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 10); - thread4.Start(); - - test::Sleep(1 * test::EpsilonDeadline()); - - // Awake #2 and #3 for unsatisfiability. - awakable_list.AwakeForStateChange(HandleSignalsState( - MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_READABLE)); - awakable_list.Remove(thread2.waiter()); - awakable_list.Remove(thread3.waiter()); - - // Cancel #4. - awakable_list.CancelAll(); - } // Join threads. - EXPECT_EQ(MOJO_RESULT_OK, result1); - EXPECT_EQ(7u, context1); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result2); - EXPECT_EQ(8u, context2); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result3); - EXPECT_EQ(9u, context3); - EXPECT_EQ(MOJO_RESULT_CANCELLED, result4); - EXPECT_EQ(10u, context4); -} - -class KeepAwakable : public Awakable { - public: - KeepAwakable() : awake_count(0) {} - - bool Awake(MojoResult result, uintptr_t context) override { - awake_count++; - return true; - } - - int awake_count; - - MOJO_DISALLOW_COPY_AND_ASSIGN(KeepAwakable); -}; - -class RemoveAwakable : public Awakable { - public: - RemoveAwakable() : awake_count(0) {} - - bool Awake(MojoResult result, uintptr_t context) override { - awake_count++; - return false; - } - - int awake_count; - - MOJO_DISALLOW_COPY_AND_ASSIGN(RemoveAwakable); -}; - -TEST(AwakableListTest, KeepAwakablesReturningTrue) { - KeepAwakable keep0; - KeepAwakable keep1; - RemoveAwakable remove0; - RemoveAwakable remove1; - RemoveAwakable remove2; - - HandleSignalsState hss(MOJO_HANDLE_SIGNAL_WRITABLE, - MOJO_HANDLE_SIGNAL_WRITABLE); - - AwakableList remove_all; - remove_all.Add(&remove0, MOJO_HANDLE_SIGNAL_WRITABLE, 0); - remove_all.Add(&remove1, MOJO_HANDLE_SIGNAL_WRITABLE, 0); - - remove_all.AwakeForStateChange(hss); - EXPECT_EQ(remove0.awake_count, 1); - EXPECT_EQ(remove1.awake_count, 1); - - remove_all.AwakeForStateChange(hss); - EXPECT_EQ(remove0.awake_count, 1); - EXPECT_EQ(remove1.awake_count, 1); - - AwakableList remove_first; - remove_first.Add(&remove2, MOJO_HANDLE_SIGNAL_WRITABLE, 0); - remove_first.Add(&keep0, MOJO_HANDLE_SIGNAL_WRITABLE, 0); - remove_first.Add(&keep1, MOJO_HANDLE_SIGNAL_WRITABLE, 0); - - remove_first.AwakeForStateChange(hss); - EXPECT_EQ(keep0.awake_count, 1); - EXPECT_EQ(keep1.awake_count, 1); - EXPECT_EQ(remove2.awake_count, 1); - - remove_first.AwakeForStateChange(hss); - EXPECT_EQ(keep0.awake_count, 2); - EXPECT_EQ(keep1.awake_count, 2); - EXPECT_EQ(remove2.awake_count, 1); - - remove_first.Remove(&keep0); - remove_first.Remove(&keep1); -} - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/channel.cc b/third_party/mojo/src/mojo/edk/system/channel.cc deleted file mode 100644 index d50da13..0000000 --- a/third_party/mojo/src/mojo/edk/system/channel.cc +++ /dev/null @@ -1,675 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/channel.h" - -#include <algorithm> -#include <utility> - -#include "base/bind.h" -#include "base/logging.h" -#include "base/strings/stringprintf.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle_vector.h" -#include "third_party/mojo/src/mojo/edk/system/endpoint_relayer.h" -#include "third_party/mojo/src/mojo/edk/system/transport_data.h" - -namespace mojo { -namespace system { - -namespace { - -struct SerializedEndpoint { - // This is the endpoint ID on the receiving side, and should be a "remote ID". - // (The receiving side should already have had an endpoint attached and been - // run via the |Channel|s. This endpoint will have both IDs assigned, so this - // ID is only needed to associate that endpoint with a particular dispatcher.) - ChannelEndpointId receiver_endpoint_id; -}; - -} // namespace - -Channel::Channel(embedder::PlatformSupport* platform_support) - : platform_support_(platform_support), - is_running_(false), - is_shutting_down_(false), - channel_manager_(nullptr) { -} - -void Channel::Init(scoped_ptr<RawChannel> raw_channel) { - DCHECK(creation_thread_checker_.CalledOnValidThread()); - DCHECK(raw_channel); - - // No need to take |mutex_|, since this must be called before this object - // becomes thread-safe. - DCHECK(!is_running_); - raw_channel_ = std::move(raw_channel); - raw_channel_->Init(this); - is_running_ = true; -} - -void Channel::SetChannelManager(ChannelManager* channel_manager) { - DCHECK(channel_manager); - - MutexLocker locker(&mutex_); - DCHECK(!is_shutting_down_); - DCHECK(!channel_manager_); - channel_manager_ = channel_manager; -} - -void Channel::Shutdown() { - DCHECK(creation_thread_checker_.CalledOnValidThread()); - - IdToEndpointMap to_destroy; - { - MutexLocker locker(&mutex_); - if (!is_running_) - return; - - // Note: Don't reset |raw_channel_|, in case we're being called from within - // |OnReadMessage()| or |OnError()|. - raw_channel_->Shutdown(); - is_running_ = false; - // |WillShutdownSoon()| may not have been called (i.e. on a channel error), - // and this flag is relied on to prevent a race with - // |AttachAndRunEndpoint()|. - is_shutting_down_ = true; - - // We need to deal with it outside the lock. - std::swap(to_destroy, local_id_to_endpoint_map_); - } - - size_t num_live = 0; - size_t num_zombies = 0; - for (IdToEndpointMap::iterator it = to_destroy.begin(); - it != to_destroy.end(); ++it) { - if (it->second) { - num_live++; - it->second->DetachFromChannel(); - } else { - num_zombies++; - } - } - DVLOG_IF(2, num_live || num_zombies) << "Shut down Channel with " << num_live - << " live endpoints and " << num_zombies - << " zombies"; - // At this point, there should be no attached endpoints. However, it is - // possible for this |Channel| to have created new endpoints. These have not - // been attached, but are tracked in |aborted_endpoints_| and also need to be - // detached. - // It is also important to note that because there are no attached endpoints, - // it should not be possible for anything to race with the rest of this - // function and create more endpoints. - EndpointList to_abort; - { - MutexLocker locker(&mutex_); - DCHECK(local_id_to_endpoint_map_.empty()); - std::swap(to_abort, aborted_endpoints_); - } - for (auto& endpoint : to_abort) - endpoint->DetachFromChannel(); - DVLOG_IF(2, !to_abort.empty()) << "Endpoints created while shutting down " - << "Channel: " << to_abort.size(); -#if DCHECK_IS_ON() - { - MutexLocker locker(&mutex_); - DCHECK(aborted_endpoints_.empty()); - } -#endif -} - -void Channel::WillShutdownSoon() { - MutexLocker locker(&mutex_); - is_shutting_down_ = true; - channel_manager_ = nullptr; -} - -void Channel::SetBootstrapEndpoint(scoped_refptr<ChannelEndpoint> endpoint) { - // Used for both local and remote IDs. - ChannelEndpointId bootstrap_id = ChannelEndpointId::GetBootstrap(); - SetBootstrapEndpointWithIds(std::move(endpoint), bootstrap_id, bootstrap_id); -} - -void Channel::SetBootstrapEndpointWithIds( - scoped_refptr<ChannelEndpoint> endpoint, - ChannelEndpointId local_id, - ChannelEndpointId remote_id) { - DCHECK(endpoint); - - { - MutexLocker locker(&mutex_); - - DLOG_IF(WARNING, is_shutting_down_) - << "SetBootstrapEndpoint() while shutting down"; - - // There must not be an endpoint with that ID already. - DCHECK(local_id_to_endpoint_map_.find(local_id) == - local_id_to_endpoint_map_.end()); - - local_id_to_endpoint_map_[local_id] = endpoint; - } - - endpoint->AttachAndRun(this, local_id, remote_id); -} - -bool Channel::WriteMessage(scoped_ptr<MessageInTransit> message) { - MutexLocker locker(&mutex_); - if (!is_running_) { - // TODO(vtl): I think this is probably not an error condition, but I should - // think about it (and the shutdown sequence) more carefully. - VLOG(2) << "WriteMessage() after shutdown"; - return false; - } - - DVLOG_IF(2, is_shutting_down_) << "WriteMessage() while shutting down"; - return raw_channel_->WriteMessage(std::move(message)); -} - -bool Channel::IsWriteBufferEmpty() { - MutexLocker locker(&mutex_); - if (!is_running_) - return true; - return raw_channel_->IsWriteBufferEmpty(); -} - -void Channel::DetachEndpoint(ChannelEndpoint* endpoint, - ChannelEndpointId local_id, - ChannelEndpointId remote_id) { - // Keep a reference to |this| to prevent this |Channel| from being deleted - // while this function is running. Without this, if |Shutdown()| is started - // on the IO thread immediately after |mutex_| is released below and finishes - // before |SendControlMessage()| gets to run, |this| could be deleted while - // this function is still running. - scoped_refptr<Channel> self(this); - - DCHECK(endpoint); - DCHECK(local_id.is_valid()); - - if (!remote_id.is_valid()) - return; // Nothing to do. - - { - MutexLocker locker_(&mutex_); - if (!is_running_) - return; - - IdToEndpointMap::iterator it = local_id_to_endpoint_map_.find(local_id); - // We detach immediately if we receive a remove message, so it's possible - // that the local ID is no longer in |local_id_to_endpoint_map_|, or even - // that it's since been reused for another endpoint. In both cases, there's - // nothing more to do. - if (it == local_id_to_endpoint_map_.end() || it->second.get() != endpoint) - return; - - DCHECK(it->second); - it->second = nullptr; - - // Send a remove message outside the lock. - } - - if (!SendControlMessage(MessageInTransit::Subtype::CHANNEL_REMOVE_ENDPOINT, - local_id, remote_id)) { - HandleLocalError(base::StringPrintf( - "Failed to send message to remove remote endpoint " - "(local ID %u, remote ID %u)", - static_cast<unsigned>(local_id.value()), - static_cast<unsigned>(remote_id.value())).c_str()); - } -} - -size_t Channel::GetSerializedEndpointSize() const { - return sizeof(SerializedEndpoint); -} - -void Channel::SerializeEndpointWithClosedPeer( - void* destination, - MessageInTransitQueue* message_queue) { - // We can actually just pass no client to |SerializeEndpointWithLocalPeer()|. - SerializeEndpointWithLocalPeer(destination, message_queue, nullptr, 0); -} - -scoped_refptr<ChannelEndpoint> Channel::SerializeEndpointWithLocalPeer( - void* destination, - MessageInTransitQueue* message_queue, - ChannelEndpointClient* endpoint_client, - unsigned endpoint_client_port) { - DCHECK(destination); - // Allow |endpoint_client| to be null, for use by - // |SerializeEndpointWithClosedPeer()|. - - scoped_refptr<ChannelEndpoint> endpoint(new ChannelEndpoint( - endpoint_client, endpoint_client_port, message_queue)); - - SerializedEndpoint* s = static_cast<SerializedEndpoint*>(destination); - s->receiver_endpoint_id = AttachAndRunEndpoint(endpoint); - DVLOG(2) << "Serializing endpoint with local or closed peer (remote ID = " - << s->receiver_endpoint_id << ")"; - - return endpoint; -} - -void Channel::SerializeEndpointWithRemotePeer( - void* destination, - MessageInTransitQueue* message_queue, - scoped_refptr<ChannelEndpoint> peer_endpoint) { - DCHECK(destination); - DCHECK(peer_endpoint); - - // Create and set up an |EndpointRelayer| to proxy. - // TODO(vtl): If we were to own/track the relayer directly (rather than owning - // it via its |ChannelEndpoint|s), then we might be able to make - // |ChannelEndpoint|'s |client_| pointer a raw pointer. - scoped_refptr<EndpointRelayer> relayer(new EndpointRelayer()); - scoped_refptr<ChannelEndpoint> endpoint( - new ChannelEndpoint(relayer.get(), 0, message_queue)); - relayer->Init(endpoint.get(), peer_endpoint.get()); - peer_endpoint->ReplaceClient(relayer.get(), 1); - - SerializedEndpoint* s = static_cast<SerializedEndpoint*>(destination); - s->receiver_endpoint_id = AttachAndRunEndpoint(endpoint); - DVLOG(2) << "Serializing endpoint with remote peer (remote ID = " - << s->receiver_endpoint_id << ")"; -} - -scoped_refptr<IncomingEndpoint> Channel::DeserializeEndpoint( - const void* source) { - const SerializedEndpoint* s = static_cast<const SerializedEndpoint*>(source); - ChannelEndpointId local_id = s->receiver_endpoint_id; - // No need to check the validity of |local_id| -- if it's not valid, it simply - // won't be in |incoming_endpoints_|. - DVLOG_IF(2, !local_id.is_valid() || !local_id.is_remote()) - << "Attempt to get incoming endpoint for invalid ID " << local_id; - - MutexLocker locker(&mutex_); - - auto it = incoming_endpoints_.find(local_id); - if (it == incoming_endpoints_.end()) { - LOG(ERROR) << "Failed to deserialize endpoint (ID = " << local_id << ")"; - return nullptr; - } - - DVLOG(2) << "Deserializing endpoint (new local ID = " << local_id << ")"; - - scoped_refptr<IncomingEndpoint> rv; - rv.swap(it->second); - incoming_endpoints_.erase(it); - return rv; -} - -size_t Channel::GetSerializedPlatformHandleSize() const { - // TODO(vtl): Having to lock |mutex_| here is a bit unfortunate. Maybe we - // should get the size in |Init()| and cache it? - MutexLocker locker(&mutex_); - return raw_channel_->GetSerializedPlatformHandleSize(); -} - -Channel::~Channel() { - // The channel should have been shut down first. - DCHECK(!is_running_); -} - -void Channel::OnReadMessage( - const MessageInTransit::View& message_view, - embedder::ScopedPlatformHandleVectorPtr platform_handles) { - DCHECK(creation_thread_checker_.CalledOnValidThread()); - - switch (message_view.type()) { - case MessageInTransit::Type::ENDPOINT_CLIENT: - case MessageInTransit::Type::ENDPOINT: - OnReadMessageForEndpoint(message_view, std::move(platform_handles)); - break; - case MessageInTransit::Type::CHANNEL: - OnReadMessageForChannel(message_view, std::move(platform_handles)); - break; - default: - HandleRemoteError( - base::StringPrintf("Received message of invalid type %u", - static_cast<unsigned>(message_view.type())) - .c_str()); - break; - } -} - -void Channel::OnError(Error error) { - DCHECK(creation_thread_checker_.CalledOnValidThread()); - - switch (error) { - case ERROR_READ_SHUTDOWN: - // The other side was cleanly closed, so this isn't actually an error. - DVLOG(1) << "RawChannel read error (shutdown)"; - break; - case ERROR_READ_BROKEN: { - MutexLocker locker(&mutex_); - // The other side likely crashed or was killed. - VLOG_IF(2, !is_shutting_down_) - << "RawChannel read error (connection broken)"; - break; - } - case ERROR_READ_BAD_MESSAGE: - // Receiving a bad message means either a bug, data corruption, or - // malicious attack (probably due to some other bug). - LOG(ERROR) << "RawChannel read error (received bad message)"; - break; - case ERROR_READ_UNKNOWN: - LOG(ERROR) << "RawChannel read error (unknown)"; - break; - case ERROR_WRITE: - // Write errors are slightly notable: they probably shouldn't happen under - // normal operation (but maybe the other side crashed). - LOG(WARNING) << "RawChannel write error"; - break; - } - Shutdown(); -} - -void Channel::OnReadMessageForEndpoint( - const MessageInTransit::View& message_view, - embedder::ScopedPlatformHandleVectorPtr platform_handles) { - DCHECK(creation_thread_checker_.CalledOnValidThread()); - DCHECK(message_view.type() == MessageInTransit::Type::ENDPOINT_CLIENT || - message_view.type() == MessageInTransit::Type::ENDPOINT); - - ChannelEndpointId local_id = message_view.destination_id(); - if (!local_id.is_valid()) { - HandleRemoteError("Received message with no destination ID"); - return; - } - - scoped_refptr<ChannelEndpoint> endpoint; - { - MutexLocker locker(&mutex_); - - // Since we own |raw_channel_|, and this method and |Shutdown()| should only - // be called from the creation thread, |raw_channel_| should never be null - // here. - DCHECK(is_running_); - - IdToEndpointMap::const_iterator it = - local_id_to_endpoint_map_.find(local_id); - if (it != local_id_to_endpoint_map_.end()) { - // Ignore messages for zombie endpoints (not an error). - if (!it->second) { - DVLOG(2) << "Ignoring downstream message for zombie endpoint (local ID " - "= " << local_id - << ", remote ID = " << message_view.source_id() << ")"; - return; - } - - endpoint = it->second; - } - } - if (!endpoint) { - HandleRemoteError( - base::StringPrintf( - "Received a message for nonexistent local destination ID %u", - static_cast<unsigned>(local_id.value())).c_str()); - // This is strongly indicative of some problem. However, it's not a fatal - // error, since it may indicate a buggy (or hostile) remote process. Don't - // die even for Debug builds, since handling this properly needs to be - // tested (TODO(vtl)). - DLOG(ERROR) << "This should not happen under normal operation."; - return; - } - - scoped_ptr<MessageInTransit> message(new MessageInTransit(message_view)); - if (message_view.transport_data_buffer_size() > 0) { - DCHECK(message_view.transport_data_buffer()); - message->SetDispatchers(TransportData::DeserializeDispatchers( - message_view.transport_data_buffer(), - message_view.transport_data_buffer_size(), std::move(platform_handles), - this)); - } - - endpoint->OnReadMessage(std::move(message)); -} - -void Channel::OnReadMessageForChannel( - const MessageInTransit::View& message_view, - embedder::ScopedPlatformHandleVectorPtr platform_handles) { - DCHECK(creation_thread_checker_.CalledOnValidThread()); - DCHECK_EQ(message_view.type(), MessageInTransit::Type::CHANNEL); - - // Currently, no channel messages take platform handles. - if (platform_handles) { - HandleRemoteError( - "Received invalid channel message (has platform handles)"); - NOTREACHED(); - return; - } - - switch (message_view.subtype()) { - case MessageInTransit::Subtype::CHANNEL_ATTACH_AND_RUN_ENDPOINT: - DVLOG(2) << "Handling channel message to attach and run endpoint (local " - "ID " << message_view.destination_id() << ", remote ID " - << message_view.source_id() << ")"; - if (!OnAttachAndRunEndpoint(message_view.destination_id(), - message_view.source_id())) { - HandleRemoteError( - "Received invalid channel message to attach and run endpoint"); - } - break; - case MessageInTransit::Subtype::CHANNEL_REMOVE_ENDPOINT: - DVLOG(2) << "Handling channel message to remove endpoint (local ID " - << message_view.destination_id() << ", remote ID " - << message_view.source_id() << ")"; - if (!OnRemoveEndpoint(message_view.destination_id(), - message_view.source_id())) { - HandleRemoteError( - "Received invalid channel message to remove endpoint"); - } - break; - case MessageInTransit::Subtype::CHANNEL_REMOVE_ENDPOINT_ACK: - DVLOG(2) << "Handling channel message to ack remove endpoint (local ID " - << message_view.destination_id() << ", remote ID " - << message_view.source_id() << ")"; - if (!OnRemoveEndpointAck(message_view.destination_id())) { - HandleRemoteError( - "Received invalid channel message to ack remove endpoint"); - } - break; - default: - HandleRemoteError("Received invalid channel message"); - NOTREACHED(); - break; - } -} - -bool Channel::OnAttachAndRunEndpoint(ChannelEndpointId local_id, - ChannelEndpointId remote_id) { - // We should only get this for remotely-created local endpoints, so our local - // ID should be "remote". - if (!local_id.is_valid() || !local_id.is_remote()) { - DVLOG(2) << "Received attach and run endpoint with invalid local ID"; - return false; - } - - // Conversely, the remote end should be "local". - if (!remote_id.is_valid() || remote_id.is_remote()) { - DVLOG(2) << "Received attach and run endpoint with invalid remote ID"; - return false; - } - - // Create/initialize an |IncomingEndpoint| and thus an endpoint (outside the - // lock). - scoped_refptr<IncomingEndpoint> incoming_endpoint(new IncomingEndpoint()); - scoped_refptr<ChannelEndpoint> endpoint = incoming_endpoint->Init(); - - bool success = true; - { - MutexLocker locker(&mutex_); - - if (local_id_to_endpoint_map_.find(local_id) == - local_id_to_endpoint_map_.end()) { - DCHECK(incoming_endpoints_.find(local_id) == incoming_endpoints_.end()); - - // TODO(vtl): Use emplace when we move to C++11 unordered_maps. (It'll - // avoid some refcount churn.) - local_id_to_endpoint_map_[local_id] = endpoint; - incoming_endpoints_[local_id] = incoming_endpoint; - } else { - // We need to call |Close()| outside the lock. - success = false; - } - } - if (!success) { - DVLOG(2) << "Received attach and run endpoint for existing local ID"; - incoming_endpoint->Close(); - return false; - } - - endpoint->AttachAndRun(this, local_id, remote_id); - return true; -} - -bool Channel::OnRemoveEndpoint(ChannelEndpointId local_id, - ChannelEndpointId remote_id) { - DCHECK(creation_thread_checker_.CalledOnValidThread()); - - scoped_refptr<ChannelEndpoint> endpoint; - { - MutexLocker locker(&mutex_); - - IdToEndpointMap::iterator it = local_id_to_endpoint_map_.find(local_id); - if (it == local_id_to_endpoint_map_.end()) { - DVLOG(2) << "Remove endpoint error: not found"; - return false; - } - - if (!it->second) { - // Remove messages "crossed"; we have to wait for the ack. - return true; - } - - endpoint = it->second; - local_id_to_endpoint_map_.erase(it); - // Detach and send the remove ack message outside the lock. - } - - endpoint->DetachFromChannel(); - - if (!SendControlMessage( - MessageInTransit::Subtype::CHANNEL_REMOVE_ENDPOINT_ACK, local_id, - remote_id)) { - HandleLocalError(base::StringPrintf( - "Failed to send message to ack remove remote endpoint " - "(local ID %u, remote ID %u)", - static_cast<unsigned>(local_id.value()), - static_cast<unsigned>(remote_id.value())).c_str()); - } - - return true; -} - -bool Channel::OnRemoveEndpointAck(ChannelEndpointId local_id) { - DCHECK(creation_thread_checker_.CalledOnValidThread()); - - MutexLocker locker(&mutex_); - - IdToEndpointMap::iterator it = local_id_to_endpoint_map_.find(local_id); - if (it == local_id_to_endpoint_map_.end()) { - DVLOG(2) << "Remove endpoint ack error: not found"; - return false; - } - - if (it->second) { - DVLOG(2) << "Remove endpoint ack error: wrong state"; - return false; - } - - local_id_to_endpoint_map_.erase(it); - return true; -} - -void Channel::HandleRemoteError(const char* error_message) { - // TODO(vtl): Is this how we really want to handle this? Probably we want to - // terminate the connection, since it's spewing invalid stuff. - VLOG(2) << error_message; -} - -void Channel::HandleLocalError(const char* error_message) { - // TODO(vtl): Is this how we really want to handle this? - // Sometimes we'll want to propagate the error back to the message pipe - // (endpoint), and notify it that the remote is (effectively) closed. - // Sometimes we'll want to kill the channel (and notify all the endpoints that - // their remotes are dead. - VLOG(2) << error_message; -} - -// Note: |endpoint| being a |scoped_refptr| makes this function safe, since it -// keeps the endpoint alive even after the lock is released. Otherwise, there's -// the temptation to simply pass the result of |new ChannelEndpoint(...)| -// directly to this function, which wouldn't be sufficient for safety. -ChannelEndpointId Channel::AttachAndRunEndpoint( - scoped_refptr<ChannelEndpoint> endpoint) { - DCHECK(endpoint); - - ChannelEndpointId local_id; - ChannelEndpointId remote_id; - { - MutexLocker locker(&mutex_); - - DLOG_IF(WARNING, is_shutting_down_) - << "AttachAndRunEndpoint() while shutting down"; - // Returning an invalid ID here prevents a race from occuring when - // |Shutdown()| is run at the same time on the IO thread. The race happens - // after |Shutdown()| has released |mutex_| and is iterating through the - // endpoints. It is possible for a new endpoint to be added while - // |Shutdown()| is iterating, which results in the new endpoint having a - // reference to this Channel. Since |ChannelEndpoint| holds a reference to a - // |Channel| by pointer (and not |scoped_refptr|), this |Channel| will - // likely be deleted after |Shutdown()|, causing a use-after-free when the - // endpoint later tries to send a message or even just close. The invalid - // ID will be serialized and the receiving end will parse it in - // |DeserializeEndpoint()|, which handles invalid IDs (see comment in - // |DeserializeEndpoint()|). - if (is_shutting_down_) { - // The |ChannelEndpoint| is now in a half-created state. Where it may have - // a |ChannelEndpointClient|, but is not attached to a |Channel|. The - // endpoint needs to be shut down by calling - // |ChannelEndpoint::DetachFromChannel()|, but doing so inside this - // function can lead to a deadlock. Instead, record the endpoint in a list - // and let the racing call to |Shutdown()| take care of it. - aborted_endpoints_.push_back(endpoint); - return ChannelEndpointId(); - } - - do { - local_id = local_id_generator_.GetNext(); - } while (local_id_to_endpoint_map_.find(local_id) != - local_id_to_endpoint_map_.end()); - - // TODO(vtl): We also need to check for collisions of remote IDs here. - remote_id = remote_id_generator_.GetNext(); - - local_id_to_endpoint_map_[local_id] = endpoint; - } - - if (!SendControlMessage( - MessageInTransit::Subtype::CHANNEL_ATTACH_AND_RUN_ENDPOINT, local_id, - remote_id)) { - HandleLocalError(base::StringPrintf( - "Failed to send message to run remote endpoint (local " - "ID %u, remote ID %u)", - static_cast<unsigned>(local_id.value()), - static_cast<unsigned>(remote_id.value())).c_str()); - // TODO(vtl): Should we continue on to |AttachAndRun()|? - } - - endpoint->AttachAndRun(this, local_id, remote_id); - return remote_id; -} - -bool Channel::SendControlMessage(MessageInTransit::Subtype subtype, - ChannelEndpointId local_id, - ChannelEndpointId remote_id) { - DVLOG(2) << "Sending channel control message: subtype " << subtype - << ", local ID " << local_id << ", remote ID " << remote_id; - scoped_ptr<MessageInTransit> message(new MessageInTransit( - MessageInTransit::Type::CHANNEL, subtype, 0, nullptr)); - message->set_source_id(local_id); - message->set_destination_id(remote_id); - return WriteMessage(std::move(message)); -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/channel.h b/third_party/mojo/src/mojo/edk/system/channel.h deleted file mode 100644 index 9feda95..0000000 --- a/third_party/mojo/src/mojo/edk/system/channel.h +++ /dev/null @@ -1,286 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CHANNEL_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CHANNEL_H_ - -#include <stdint.h> - -#include <vector> - -#include "base/containers/hash_tables.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/threading/thread_checker.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint_id.h" -#include "third_party/mojo/src/mojo/edk/system/incoming_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit.h" -#include "third_party/mojo/src/mojo/edk/system/mutex.h" -#include "third_party/mojo/src/mojo/edk/system/raw_channel.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { - -namespace embedder { -class PlatformSupport; -} - -namespace system { - -class ChannelEndpointClient; -class ChannelManager; -class MessageInTransitQueue; - -// This class is mostly thread-safe. It must be created on an I/O thread. -// |Init()| must be called on that same thread before it becomes thread-safe (in -// particular, before references are given to any other thread) and |Shutdown()| -// must be called on that same thread before destruction. Its public methods are -// otherwise thread-safe. (Many private methods are restricted to the creation -// thread.) It may be destroyed on any thread, in the sense that the last -// reference to it may be released on any thread, with the proviso that -// |Shutdown()| must have been called first (so the pattern is that a "main" -// reference is kept on its creation thread and is released after |Shutdown()| -// is called, but other threads may have temporarily "dangling" references). -// -// Note the lock order (in order of allowable acquisition): -// |ChannelEndpointClient| (e.g., |MessagePipe|), |ChannelEndpoint|, |Channel|. -// Thus |Channel| may not call into |ChannelEndpoint| with |Channel|'s lock -// held. -class MOJO_SYSTEM_IMPL_EXPORT Channel final - : public base::RefCountedThreadSafe<Channel>, - public RawChannel::Delegate { - public: - // |platform_support| must remain alive until after |Shutdown()| is called. - explicit Channel(embedder::PlatformSupport* platform_support); - - // This must be called on the creation thread before any other methods are - // called, and before references to this object are given to any other - // threads. |raw_channel| should be uninitialized. - void Init(scoped_ptr<RawChannel> raw_channel) MOJO_NOT_THREAD_SAFE; - - // Sets the channel manager associated with this channel. This should be set - // at most once and only called before |WillShutdownSoon()| (and - // |Shutdown()|). (This is called by the channel manager when adding a - // channel; this should not be called before the channel is managed by the - // channel manager.) - void SetChannelManager(ChannelManager* channel_manager); - - // This must be called on the creation thread before destruction (which can - // happen on any thread). - void Shutdown(); - - // Signals that |Shutdown()| will be called soon (this may be called from any - // thread, unlike |Shutdown()|). Warnings will be issued if, e.g., messages - // are written after this is called; other warnings may be suppressed. (This - // may be called multiple times, or not at all.) - // - // If set, the channel manager associated with this channel will be reset. - void WillShutdownSoon(); - - // Called to set (i.e., attach and run) the bootstrap (first) endpoint on the - // channel. Both the local and remote IDs are the bootstrap ID (given by - // |ChannelEndpointId::GetBootstrap()|). - // - // (Bootstrapping is symmetric: Both sides call this, which will establish the - // first connection across a channel.) - void SetBootstrapEndpoint(scoped_refptr<ChannelEndpoint> endpoint); - - // Like |SetBootstrapEndpoint()|, but with explicitly-specified local and - // remote IDs. - // - // (Bootstrapping is still symmetric, though the sides should obviously - // interchange local and remote IDs. This can be used to allow multiple - // "bootstrap" endpoints, though this is really most useful for testing.) - void SetBootstrapEndpointWithIds(scoped_refptr<ChannelEndpoint> endpoint, - ChannelEndpointId local_id, - ChannelEndpointId remote_id); - - // This forwards |message| verbatim to |raw_channel_|. - bool WriteMessage(scoped_ptr<MessageInTransit> message); - - // See |RawChannel::IsWriteBufferEmpty()|. - // TODO(vtl): Maybe we shouldn't expose this, and instead have a - // |FlushWriteBufferAndShutdown()| or something like that. - bool IsWriteBufferEmpty(); - - // Removes the given endpoint from this channel (|local_id| and |remote_id| - // are specified as an optimization; the latter should be an invalid - // |ChannelEndpointId| if the endpoint is not yet running). Note: If this is - // called, the |Channel| will *not* call - // |ChannelEndpoint::DetachFromChannel()|. - void DetachEndpoint(ChannelEndpoint* endpoint, - ChannelEndpointId local_id, - ChannelEndpointId remote_id); - - // Returns the size of a serialized endpoint (see |SerializeEndpoint...()| and - // |DeserializeEndpoint()| below). This value will remain constant for a given - // instance of |Channel|. - size_t GetSerializedEndpointSize() const; - - // Endpoint serialization methods: From the |Channel|'s point of view, there - // are three cases (discussed further below) and thus three methods. - // - // All three methods have a |destination| argument, which should be a buffer - // to which auxiliary information will be written and which should be - // transmitted to the peer |Channel| by some other means, but using this - // |Channel|. It should be a buffer of (at least) the size returned by - // |GetSerializedEndpointSize()| (exactly that much data will be written). - // - // All three also have a |message_queue| argument, which if non-null is the - // queue of messages already received by the endpoint to be serialized. - // - // Note that "serialize" really means "send" -- the |endpoint| will be sent - // "immediately". The contents of the |destination| buffer can then be used to - // claim the rematerialized endpoint from the peer |Channel|. (|destination| - // must be sent using this |Channel|, since otherwise it may be received - // before it is valid to the peer |Channel|.) - // - // Case 1: The endpoint's peer is already closed. - // - // Case 2: The endpoint's peer is local (i.e., it has a - // |ChannelEndpointClient| but no peer |ChannelEndpoint|). - // - // Case 3: The endpoint's peer is remote (i.e., it has a peer - // |ChannelEndpoint|). (This has two subcases: the peer endpoint may be on - // this |Channel| or another |Channel|.) - void SerializeEndpointWithClosedPeer(void* destination, - MessageInTransitQueue* message_queue); - // This one returns the |ChannelEndpoint| for the serialized endpoint (which - // can be used by, e.g., a |ProxyMessagePipeEndpoint|. - scoped_refptr<ChannelEndpoint> SerializeEndpointWithLocalPeer( - void* destination, - MessageInTransitQueue* message_queue, - ChannelEndpointClient* endpoint_client, - unsigned endpoint_client_port); - void SerializeEndpointWithRemotePeer( - void* destination, - MessageInTransitQueue* message_queue, - scoped_refptr<ChannelEndpoint> peer_endpoint); - - // Deserializes an endpoint that was sent from the peer |Channel| (using - // |SerializeEndpoint...()|. |source| should be (a copy of) the data that - // |SerializeEndpoint...()| wrote, and must be (at least) - // |GetSerializedEndpointSize()| bytes. This returns the deserialized - // |IncomingEndpoint| (which can be converted into a |MessagePipe|) or null on - // error. - scoped_refptr<IncomingEndpoint> DeserializeEndpoint(const void* source); - - // See |RawChannel::GetSerializedPlatformHandleSize()|. - size_t GetSerializedPlatformHandleSize() const; - - embedder::PlatformSupport* platform_support() const { - return platform_support_; - } - - private: - friend class base::RefCountedThreadSafe<Channel>; - ~Channel() override; - - // |RawChannel::Delegate| implementation (only called on the creation thread): - void OnReadMessage( - const MessageInTransit::View& message_view, - embedder::ScopedPlatformHandleVectorPtr platform_handles) override; - void OnError(Error error) override; - - // Helpers for |OnReadMessage| (only called on the creation thread): - void OnReadMessageForEndpoint( - const MessageInTransit::View& message_view, - embedder::ScopedPlatformHandleVectorPtr platform_handles); - void OnReadMessageForChannel( - const MessageInTransit::View& message_view, - embedder::ScopedPlatformHandleVectorPtr platform_handles); - - // Handles "attach and run endpoint" messages. - bool OnAttachAndRunEndpoint(ChannelEndpointId local_id, - ChannelEndpointId remote_id); - // Handles "remove endpoint" messages. - bool OnRemoveEndpoint(ChannelEndpointId local_id, - ChannelEndpointId remote_id); - // Handles "remove endpoint ack" messages. - bool OnRemoveEndpointAck(ChannelEndpointId local_id); - - // Handles errors (e.g., invalid messages) from the remote side. Callable from - // any thread. - void HandleRemoteError(const char* error_message); - // Handles internal errors/failures from the local side. Callable from any - // thread. - void HandleLocalError(const char* error_message); - - // Helper for |SerializeEndpoint...()|: Attaches the given (non-bootstrap) - // endpoint to this channel and runs it. This assigns the endpoint both local - // and remote IDs. This will also send a - // |Subtype::CHANNEL_ATTACH_AND_RUN_ENDPOINT| message to the remote side to - // tell it to create an endpoint as well. This returns the *remote* ID (one - // for which |is_remote()| returns true). If |WillShutdownSoon()| has been - // called, |endpoint| will not be attached to this channel, and this will - // return an invalid ID. - // - // TODO(vtl): Maybe limit the number of attached message pipes. - ChannelEndpointId AttachAndRunEndpoint( - scoped_refptr<ChannelEndpoint> endpoint); - - // Helper to send channel control messages. Returns true on success. Callable - // from any thread. - bool SendControlMessage(MessageInTransit::Subtype subtype, - ChannelEndpointId source_id, - ChannelEndpointId destination_id) - MOJO_LOCKS_EXCLUDED(mutex_); - - base::ThreadChecker creation_thread_checker_; - - embedder::PlatformSupport* const platform_support_; - - // Note: |ChannelEndpointClient|s (in particular, |MessagePipe|s) MUST NOT be - // used under |mutex_|. E.g., |mutex_| can only be acquired after - // |MessagePipe::lock_|, never before. Thus to call into a - // |ChannelEndpointClient|, a reference should be acquired from - // |local_id_to_endpoint_map_| under |mutex_| and then the lock released. - // TODO(vtl): Annotate the above rule using |MOJO_ACQUIRED_{BEFORE,AFTER}()|, - // once clang actually checks such annotations. - // https://github.com/domokit/mojo/issues/313 - mutable Mutex mutex_; - - scoped_ptr<RawChannel> raw_channel_ MOJO_GUARDED_BY(mutex_); - bool is_running_ MOJO_GUARDED_BY(mutex_); - // Set when |WillShutdownSoon()| is called. - bool is_shutting_down_ MOJO_GUARDED_BY(mutex_); - - // Has a reference to us. - ChannelManager* channel_manager_ MOJO_GUARDED_BY(mutex_); - - using IdToEndpointMap = - base::hash_map<ChannelEndpointId, scoped_refptr<ChannelEndpoint>>; - // Map from local IDs to endpoints. If the endpoint is null, this means that - // we're just waiting for the remove ack before removing the entry. - IdToEndpointMap local_id_to_endpoint_map_ MOJO_GUARDED_BY(mutex_); - // Note: The IDs generated by this should be checked for existence before use. - LocalChannelEndpointIdGenerator local_id_generator_ MOJO_GUARDED_BY(mutex_); - - using IdToIncomingEndpointMap = - base::hash_map<ChannelEndpointId, scoped_refptr<IncomingEndpoint>>; - // Map from local IDs to incoming endpoints (i.e., those received inside other - // messages, but not yet claimed via |DeserializeEndpoint()|). - IdToIncomingEndpointMap incoming_endpoints_ MOJO_GUARDED_BY(mutex_); - // TODO(vtl): We need to keep track of remote IDs (so that we don't collide - // if/when we wrap). - RemoteChannelEndpointIdGenerator remote_id_generator_ MOJO_GUARDED_BY(mutex_); - - using EndpointList = std::vector<scoped_refptr<ChannelEndpoint>>; - // List of endpoints that were created while this |Channel| was being shut - // down. These are created, but have not been attached to this |Channel| and - // need to be shut down after all attached |ChannelEndpoint|s have been - // detached. - EndpointList aborted_endpoints_ MOJO_GUARDED_BY(mutex_); - - MOJO_DISALLOW_COPY_AND_ASSIGN(Channel); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CHANNEL_H_ diff --git a/third_party/mojo/src/mojo/edk/system/channel_endpoint.cc b/third_party/mojo/src/mojo/edk/system/channel_endpoint.cc deleted file mode 100644 index 7850421..0000000 --- a/third_party/mojo/src/mojo/edk/system/channel_endpoint.cc +++ /dev/null @@ -1,226 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/channel_endpoint.h" - -#include <utility> - -#include "base/logging.h" -#include "base/threading/platform_thread.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/channel.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint_client.h" - -namespace mojo { -namespace system { - -ChannelEndpoint::ChannelEndpoint(ChannelEndpointClient* client, - unsigned client_port, - MessageInTransitQueue* message_queue) - : state_(State::PAUSED), - client_(client), - client_port_(client_port), - channel_(nullptr) { - DCHECK(client_ || message_queue); - - if (message_queue) - channel_message_queue_.Swap(message_queue); -} - -bool ChannelEndpoint::EnqueueMessage(scoped_ptr<MessageInTransit> message) { - DCHECK(message); - - MutexLocker locker(&mutex_); - - switch (state_) { - case State::PAUSED: - channel_message_queue_.AddMessage(std::move(message)); - return true; - case State::RUNNING: - return WriteMessageNoLock(std::move(message)); - case State::DEAD: - return false; - } - - NOTREACHED(); - return false; -} - -bool ChannelEndpoint::ReplaceClient(ChannelEndpointClient* client, - unsigned client_port) { - DCHECK(client); - - MutexLocker locker(&mutex_); - DCHECK(client_); - DCHECK(client != client_.get() || client_port != client_port_); - client_ = client; - client_port_ = client_port; - return state_ != State::DEAD; -} - -void ChannelEndpoint::DetachFromClient() { - MutexLocker locker(&mutex_); - DCHECK(client_); - client_ = nullptr; - - if (!channel_) - return; - channel_->DetachEndpoint(this, local_id_, remote_id_); - DieNoLock(); -} - -void ChannelEndpoint::AttachAndRun(Channel* channel, - ChannelEndpointId local_id, - ChannelEndpointId remote_id) { - DCHECK(channel); - DCHECK(local_id.is_valid()); - DCHECK(remote_id.is_valid()); - - MutexLocker locker(&mutex_); - DCHECK(state_ == State::PAUSED); - DCHECK(!channel_); - DCHECK(!local_id_.is_valid()); - DCHECK(!remote_id_.is_valid()); - state_ = State::RUNNING; - channel_ = channel; - local_id_ = local_id; - remote_id_ = remote_id; - - while (!channel_message_queue_.IsEmpty()) { - bool ok = WriteMessageNoLock(channel_message_queue_.GetMessage()); - LOG_IF(WARNING, !ok) << "Failed to write enqueue message to channel"; - } - - if (!client_) { - channel_->DetachEndpoint(this, local_id_, remote_id_); - DieNoLock(); - } -} - -void ChannelEndpoint::OnReadMessage(scoped_ptr<MessageInTransit> message) { - if (message->type() == MessageInTransit::Type::ENDPOINT_CLIENT) { - OnReadMessageForClient(std::move(message)); - return; - } - - DCHECK_EQ(message->type(), MessageInTransit::Type::ENDPOINT); - - // TODO(vtl) - // Note that this won't crash on Release builds, which is important (since the - // other side may be malicious). Doing nothing is safe and will dispose of the - // message. - NOTREACHED(); -} - -void ChannelEndpoint::DetachFromChannel() { - scoped_refptr<ChannelEndpointClient> client; - unsigned client_port = 0; - { - MutexLocker locker(&mutex_); - - if (client_) { - // Take a ref, and call |OnDetachFromChannel()| outside the lock. - client = client_; - client_port = client_port_; - } - - // |channel_| may already be null if we already detached from the channel in - // |DetachFromClient()| by calling |Channel::DetachEndpoint()| (and there - // are racing detaches). - if (channel_) - DieNoLock(); - else - DCHECK(state_ != State::RUNNING); - } - - // If |ReplaceClient()| is called (from another thread) after the above locked - // section but before we call |OnDetachFromChannel()|, |ReplaceClient()| - // returns false to notify the caller that the channel was already detached. - // (The old client has to accept the arguably-spurious call to - // |OnDetachFromChannel()|.) - if (client) - client->OnDetachFromChannel(client_port); -} - -ChannelEndpoint::~ChannelEndpoint() { - DCHECK(!client_); - DCHECK(!channel_); - DCHECK(!local_id_.is_valid()); - DCHECK(!remote_id_.is_valid()); -} - -bool ChannelEndpoint::WriteMessageNoLock(scoped_ptr<MessageInTransit> message) { - DCHECK(message); - - mutex_.AssertHeld(); - - DCHECK(channel_); - DCHECK(local_id_.is_valid()); - DCHECK(remote_id_.is_valid()); - - message->SerializeAndCloseDispatchers(channel_); - message->set_source_id(local_id_); - message->set_destination_id(remote_id_); - return channel_->WriteMessage(std::move(message)); -} - -void ChannelEndpoint::OnReadMessageForClient( - scoped_ptr<MessageInTransit> message) { - DCHECK_EQ(message->type(), MessageInTransit::Type::ENDPOINT_CLIENT); - - scoped_refptr<ChannelEndpointClient> client; - unsigned client_port = 0; - - // This loop is to make |ReplaceClient()| work. We can't call the client's - // |OnReadMessage()| under our lock, so by the time we do that, |client| may - // no longer be our client. - // - // In that case, |client| must return false. We'll then yield, and retry with - // the new client. (Theoretically, the client could be replaced again.) - // - // This solution isn't terribly elegant, but it's the least costly way of - // handling/avoiding this (very unlikely) race. (Other solutions -- e.g., - // adding a client message queue, which the client only fetches messages from - // -- impose significant cost in the common case.) - for (;;) { - { - MutexLocker locker(&mutex_); - if (!channel_ || !client_) { - // This isn't a failure per se. (It just means that, e.g., the other end - // of the message pipe closed first.) - return; - } - - // If we get here in a second (third, etc.) iteration of the loop, it's - // because |ReplaceClient()| was called. - DCHECK(client_ != client || client_port_ != client_port); - - // Take a ref, and call |OnReadMessage()| outside the lock. - client = client_; - client_port = client_port_; - } - - if (client->OnReadMessage(client_port, message.get())) { - ignore_result(message.release()); - break; - } - - base::PlatformThread::YieldCurrentThread(); - } -} - -void ChannelEndpoint::DieNoLock() { - DCHECK(state_ == State::RUNNING); - DCHECK(channel_); - DCHECK(local_id_.is_valid()); - DCHECK(remote_id_.is_valid()); - - state_ = State::DEAD; - channel_ = nullptr; - local_id_ = ChannelEndpointId(); - remote_id_ = ChannelEndpointId(); -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/channel_endpoint.h b/third_party/mojo/src/mojo/edk/system/channel_endpoint.h deleted file mode 100644 index 6f5e06d..0000000 --- a/third_party/mojo/src/mojo/edk/system/channel_endpoint.h +++ /dev/null @@ -1,223 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_H_ - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint_id.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit_queue.h" -#include "third_party/mojo/src/mojo/edk/system/mutex.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -class Channel; -class ChannelEndpointClient; -class MessageInTransit; - -// TODO(vtl): The plan: -// - (Done.) Move |Channel::Endpoint| to |ChannelEndpoint|. Make it -// refcounted, and not copyable. Make |Channel| a friend. Make things work. -// - (Done.) Give |ChannelEndpoint| a lock. The lock order (in order of -// allowable acquisition) is: |MessagePipe|, |ChannelEndpoint|, |Channel|. -// - (Done) Stop having |Channel| as a friend. -// - (Done) Move logic from |ProxyMessagePipeEndpoint| into |ChannelEndpoint|. -// Right now, we have to go through lots of contortions to manipulate state -// owned by |ProxyMessagePipeEndpoint| (in particular, |Channel::Endpoint| -// doesn't know about the remote ID; the local ID is duplicated in two -// places). Hollow out |ProxyMessagePipeEndpoint|, and have it just own a -// reference to |ChannelEndpoint| (hence the refcounting). -// - In essence, |ChannelEndpoint| becomes the thing that knows about -// channel-specific aspects of an endpoint (notably local and remote IDs, -// and knowledge about handshaking), and mediates between the |Channel| and -// the |MessagePipe|. -// - In the end state, |Channel| should no longer need to know about -// |MessagePipe| and ports (but only |ChannelEndpoint|) and -// |ProxyMessagePipeEndpoint| should no longer need to know about |Channel| -// (ditto). -// -// Things as they are now, before I change everything (TODO(vtl): update this -// comment appropriately): -// -// Terminology: -// - "Message pipe endpoint": In the implementation, a |MessagePipe| owns -// two |MessagePipeEndpoint| objects, one for each port. The -// |MessagePipeEndpoint| objects are only accessed via the |MessagePipe| -// (which has the lock), with the additional information of the port -// number. So as far as the channel is concerned, a message pipe endpoint -// is a pointer to a |MessagePipe| together with the port number. -// - The value of |port| in |EndpointInfo| refers to the -// |ProxyMessagePipeEndpoint| (i.e., the endpoint that is logically on -// the other side). Messages received by a channel for a message pipe -// are thus written to the *peer* of this port. -// - "Attached"/"detached": A message pipe endpoint is attached to a channel -// if it has a pointer to it. It must be detached before the channel gives -// up its pointer to it in order to break a reference cycle. (This cycle -// is needed to allow a channel to be shut down cleanly, without shutting -// down everything else first.) -// - "Running" (message pipe endpoint): A message pipe endpoint is running -// if messages written to it (via some |MessagePipeDispatcher|, to which -// some |MojoHandle| is assigned) are being transmitted through the -// channel. -// - Before a message pipe endpoint is run, it will queue messages. -// - When a message pipe endpoint is detached from a channel, it is also -// taken out of the running state. After that point, messages should -// no longer be written to it. -// - "Normal" message pipe endpoint (state): The channel itself does not -// have knowledge of whether a message pipe endpoint has started running -// yet. It will *receive* messages for a message pipe in either state (but -// the message pipe endpoint won't *send* messages to the channel if it -// has not started running). -// - "Zombie" message pipe endpoint (state): A message pipe endpoint is a -// zombie if it is still in |local_id_to_endpoint_info_map_|, but the -// channel is no longer forwarding messages to it (even if it may still be -// receiving messages for it). -// - There are various types of zombies, depending on the reason the -// message pipe endpoint cannot yet be removed. -// - If the remote side is closed, it will send a "remove" control -// message. After the channel receives that message (to which it -// responds with a "remove ack" control message), it knows that it -// shouldn't receive any more messages for that message pipe endpoint -// (local ID), but it must wait for the endpoint to detach. (It can't -// do so without a race, since it can't call into the message pipe -// under |mutex_|.) [TODO(vtl): When I add remotely-allocated IDs, -// we'll have to remove the |EndpointInfo| from -// |local_id_to_endpoint_info_map_| -- i.e., remove the local ID, -// since it's no longer valid and may be reused by the remote side -- -// and keep the |EndpointInfo| alive in some other way.] -// - If the local side is closed and the message pipe endpoint was -// already running (so there are no queued messages left to send), it -// will detach the endpoint, and send a "remove" control message. -// However, the channel may still receive messages for that endpoint -// until it receives a "remove ack" control message. -// - If the local side is closed but the message pipe endpoint was not -// yet running , the detaching is delayed until after it is run and -// all the queued messages are sent to the channel. On being detached, -// things proceed as in one of the above cases. The endpoint is *not* -// a zombie until it is detached (or a "remove" message is received). -// [TODO(vtl): Maybe we can get rid of this case? It'd only not yet be -// running since under the current scheme it wouldn't have a remote ID -// yet.] -// - Note that even if the local side is closed, it may still receive a -// "remove" message from the other side (if the other side is closed -// simultaneously, and both sides send "remove" messages). In that -// case, it must still remain alive until it receives the "remove -// ack" (and it must ack the "remove" message that it received). -class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpoint final - : public base::RefCountedThreadSafe<ChannelEndpoint> { - public: - // Constructor for a |ChannelEndpoint| with the given client (specified by - // |client| and |client_port|). Optionally takes messages from - // |*message_queue| if |message_queue| is non-null. - // - // |client| may be null if this endpoint will never need to receive messages, - // in which case |message_queue| should not be null. In that case, this - // endpoint will simply send queued messages upon being attached to a - // |Channel| and immediately detach itself. - ChannelEndpoint(ChannelEndpointClient* client, - unsigned client_port, - MessageInTransitQueue* message_queue = nullptr); - - // Methods called by |ChannelEndpointClient|: - - // Called to enqueue an outbound message. (If |AttachAndRun()| has not yet - // been called, the message will be enqueued and sent when |AttachAndRun()| is - // called.) - bool EnqueueMessage(scoped_ptr<MessageInTransit> message); - - // Called to *replace* current client with a new client (which must differ - // from the existing client). This must not be called after - // |DetachFromClient()| has been called. - // - // This returns true in the typical case, and false if this endpoint has been - // detached from the channel, in which case the caller should probably call - // its (new) client's |OnDetachFromChannel()|. - bool ReplaceClient(ChannelEndpointClient* client, unsigned client_port); - - // Called before the |ChannelEndpointClient| gives up its reference to this - // object. - void DetachFromClient(); - - // Methods called by |Channel|: - - // Called when the |Channel| takes a reference to this object. This will send - // all queue messages (in |channel_message_queue_|). - // TODO(vtl): Maybe rename this "OnAttach"? - void AttachAndRun(Channel* channel, - ChannelEndpointId local_id, - ChannelEndpointId remote_id); - - // Called when the |Channel| receives a message for the |ChannelEndpoint|. - void OnReadMessage(scoped_ptr<MessageInTransit> message); - - // Called before the |Channel| gives up its reference to this object. - void DetachFromChannel(); - - private: - friend class base::RefCountedThreadSafe<ChannelEndpoint>; - ~ChannelEndpoint(); - - bool WriteMessageNoLock(scoped_ptr<MessageInTransit> message) - MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Helper for |OnReadMessage()|, handling messages for the client. - void OnReadMessageForClient(scoped_ptr<MessageInTransit> message); - - // Moves |state_| from |RUNNING| to |DEAD|. |channel_| must be non-null, but - // this does not call |channel_->DetachEndpoint()|. - void DieNoLock() MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - Mutex mutex_; - - enum class State { - // |AttachAndRun()| has not been called yet (|channel_| is null). - PAUSED, - // |AttachAndRun()| has been called, but not |DetachFromChannel()| - // (|channel_| is non-null and valid). - RUNNING, - // |DetachFromChannel()| has been called (|channel_| is null). - DEAD - }; - State state_ MOJO_GUARDED_BY(mutex_); - - // |client_| must be valid whenever it is non-null. Before |*client_| gives up - // its reference to this object, it must call |DetachFromClient()|. - // NOTE: This is a |scoped_refptr<>|, rather than a raw pointer, since the - // |Channel| needs to keep the |MessagePipe| alive for the "proxy-proxy" case. - // Possibly we'll be able to eliminate that case when we have full - // multiprocess support. - // WARNING: |ChannelEndpointClient| methods must not be called under |mutex_|. - // Thus to make such a call, a reference must first be taken under |mutex_| - // and the lock released. - // TODO(vtl): Annotate the above rule using |MOJO_ACQUIRED_{BEFORE,AFTER}()|, - // once clang actually checks such annotations. - // https://github.com/domokit/mojo/issues/313 - // WARNING: Beware of interactions with |ReplaceClient()|. By the time the - // call is made, the client may have changed. This must be detected and dealt - // with. - scoped_refptr<ChannelEndpointClient> client_ MOJO_GUARDED_BY(mutex_); - unsigned client_port_ MOJO_GUARDED_BY(mutex_); - - // |channel_| must be valid whenever it is non-null. Before |*channel_| gives - // up its reference to this object, it must call |DetachFromChannel()|. - // |local_id_| and |remote_id_| are valid if and only |channel_| is non-null. - Channel* channel_ MOJO_GUARDED_BY(mutex_); - ChannelEndpointId local_id_ MOJO_GUARDED_BY(mutex_); - ChannelEndpointId remote_id_ MOJO_GUARDED_BY(mutex_); - - // This queue is used before we're running on a channel and ready to send - // messages to the channel. - MessageInTransitQueue channel_message_queue_ MOJO_GUARDED_BY(mutex_); - - MOJO_DISALLOW_COPY_AND_ASSIGN(ChannelEndpoint); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_H_ diff --git a/third_party/mojo/src/mojo/edk/system/channel_endpoint_client.h b/third_party/mojo/src/mojo/edk/system/channel_endpoint_client.h deleted file mode 100644 index d250b28..0000000 --- a/third_party/mojo/src/mojo/edk/system/channel_endpoint_client.h +++ /dev/null @@ -1,63 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_CLIENT_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_CLIENT_H_ - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -class MessageInTransit; - -// Interface for receivers of messages from |ChannelEndpoint| (hence from -// |Channel|). |port| is simply the value passed to |ChannelEndpoint| on -// construction, and provides a lightweight way for an object to be the client -// of multiple |ChannelEndpoint|s. (|MessagePipe| implements this interface, in -// which case |port| is the port number for the |ProxyMessagePipeEndpoint| -// corresdponding to the |ChannelEndpoint|.) -// -// Implementations of this class should be thread-safe. |ChannelEndpointClient| -// *precedes* |ChannelEndpoint| in the lock order, so |ChannelEndpoint| should -// never call into this class with its lock held. (Instead, it should take a -// reference under its lock, release its lock, and make any needed call(s).) -// -// Note: As a consequence of this, all the client methods may be called even -// after |ChannelEndpoint::DetachFromClient()| has been called (so the -// |ChannelEndpoint| has apparently relinquished its pointer to the -// |ChannelEndpointClient|). -class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpointClient - : public base::RefCountedThreadSafe<ChannelEndpointClient> { - public: - // Called by |ChannelEndpoint| in response to its |OnReadMessage()|, which is - // called by |Channel| when it receives a message for the |ChannelEndpoint|. - // (|port| is the value passed to |ChannelEndpoint|'s constructor as - // |client_port|.) - // - // This should return true if it accepted (and took ownership of) |message|. - virtual bool OnReadMessage(unsigned port, MessageInTransit* message) = 0; - - // Called by |ChannelEndpoint| when the |Channel| is relinquishing its pointer - // to the |ChannelEndpoint| (and vice versa). After this is called, - // |OnReadMessage()| will no longer be called. - virtual void OnDetachFromChannel(unsigned port) = 0; - - protected: - ChannelEndpointClient() {} - - virtual ~ChannelEndpointClient() {} - friend class base::RefCountedThreadSafe<ChannelEndpointClient>; - - private: - MOJO_DISALLOW_COPY_AND_ASSIGN(ChannelEndpointClient); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_CLIENT_H_ diff --git a/third_party/mojo/src/mojo/edk/system/channel_endpoint_id.cc b/third_party/mojo/src/mojo/edk/system/channel_endpoint_id.cc deleted file mode 100644 index d7f01e4..0000000 --- a/third_party/mojo/src/mojo/edk/system/channel_endpoint_id.cc +++ /dev/null @@ -1,29 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/channel_endpoint_id.h" - -namespace mojo { -namespace system { - -MOJO_STATIC_CONST_MEMBER_DEFINITION const uint32_t - ChannelEndpointId::kRemoteFlag; - -ChannelEndpointId LocalChannelEndpointIdGenerator::GetNext() { - ChannelEndpointId rv = next_; - next_.value_ = (next_.value_ + 1) & ~ChannelEndpointId::kRemoteFlag; - // Skip over the invalid value, in case we wrap. - if (!next_.is_valid()) - next_.value_++; - return rv; -} - -ChannelEndpointId RemoteChannelEndpointIdGenerator::GetNext() { - ChannelEndpointId rv = next_; - next_.value_ = (next_.value_ + 1) | ChannelEndpointId::kRemoteFlag; - return rv; -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/channel_endpoint_id.h b/third_party/mojo/src/mojo/edk/system/channel_endpoint_id.h deleted file mode 100644 index 6d767aa2..0000000 --- a/third_party/mojo/src/mojo/edk/system/channel_endpoint_id.h +++ /dev/null @@ -1,148 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_ID_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_ID_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <ostream> - -#include "base/containers/hash_tables.h" -#include "base/gtest_prod_util.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -// ChannelEndpointId ----------------------------------------------------------- - -class LocalChannelEndpointIdGenerator; -FORWARD_DECLARE_TEST(LocalChannelEndpointIdGeneratorTest, WrapAround); -FORWARD_DECLARE_TEST(RemoteChannelEndpointIdGeneratorTest, WrapAround); - -// Represents an ID for an endpoint (i.e., one side of a message pipe) on a -// |Channel|. This class must be POD. -// -// Note: The terminology "remote" for a |ChannelEndpointId| means a destination -// ID that was actually allocated by the sender, or similarly a source ID that -// was allocated by the receiver. -// -// From the standpoint of the |Channel| with such a remote ID in its endpoint -// table, such an ID is a "remotely-allocated local ID". From the standpoint of -// the |Channel| allocating such a remote ID (for its peer |Channel|), it's a -// "locally-allocated remote ID". -class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpointId { - public: - ChannelEndpointId() : value_(0) {} - ChannelEndpointId(const ChannelEndpointId& other) : value_(other.value_) {} - - // Returns the local ID to use for the first message pipe endpoint on a - // channel. - static ChannelEndpointId GetBootstrap() { return ChannelEndpointId(1); } - - bool operator==(const ChannelEndpointId& other) const { - return value_ == other.value_; - } - bool operator!=(const ChannelEndpointId& other) const { - return !operator==(other); - } - // So that we can be used in |std::map|, etc. - bool operator<(const ChannelEndpointId& other) const { - return value_ < other.value_; - } - - bool is_valid() const { return !!value_; } - bool is_remote() const { return !!(value_ & kRemoteFlag); } - const uint32_t& value() const { return value_; } - - // Flag set in |value()| if this is a remote ID. - static const uint32_t kRemoteFlag = 0x80000000u; - - private: - friend class LocalChannelEndpointIdGenerator; - FRIEND_TEST_ALL_PREFIXES(LocalChannelEndpointIdGeneratorTest, WrapAround); - friend class RemoteChannelEndpointIdGenerator; - FRIEND_TEST_ALL_PREFIXES(RemoteChannelEndpointIdGeneratorTest, WrapAround); - - explicit ChannelEndpointId(uint32_t value) : value_(value) {} - - uint32_t value_; - - // Copying and assignment allowed. -}; -// This wrapper should add no overhead. -// TODO(vtl): Rewrite |sizeof(uint32_t)| as |sizeof(ChannelEndpointId::value)| -// once we have sufficient C++11 support. -static_assert(sizeof(ChannelEndpointId) == sizeof(uint32_t), - "ChannelEndpointId has incorrect size"); - -// So logging macros and |DCHECK_EQ()|, etc. work. -MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<( - std::ostream& out, - const ChannelEndpointId& channel_endpoint_id) { - return out << channel_endpoint_id.value(); -} - -// LocalChannelEndpointIdGenerator --------------------------------------------- - -// A generator for "new" local |ChannelEndpointId|s. It does not track -// used/existing IDs; that must be done separately. (This class is not -// thread-safe.) -class MOJO_SYSTEM_IMPL_EXPORT LocalChannelEndpointIdGenerator { - public: - LocalChannelEndpointIdGenerator() - : next_(ChannelEndpointId::GetBootstrap()) {} - - ChannelEndpointId GetNext(); - - private: - FRIEND_TEST_ALL_PREFIXES(LocalChannelEndpointIdGeneratorTest, WrapAround); - - ChannelEndpointId next_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(LocalChannelEndpointIdGenerator); -}; - -// RemoteChannelEndpointIdGenerator -------------------------------------------- - -// A generator for "new" remote |ChannelEndpointId|s, for |Channel|s to -// locally allocate remote IDs. (See the comment above |ChannelEndpointId| for -// an explanatory note.) It does not track used/existing IDs; that must be done -// separately. (This class is not thread-safe.) -class MOJO_SYSTEM_IMPL_EXPORT RemoteChannelEndpointIdGenerator { - public: - RemoteChannelEndpointIdGenerator() : next_(ChannelEndpointId::kRemoteFlag) {} - - ChannelEndpointId GetNext(); - - private: - FRIEND_TEST_ALL_PREFIXES(RemoteChannelEndpointIdGeneratorTest, WrapAround); - - ChannelEndpointId next_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(RemoteChannelEndpointIdGenerator); -}; - -} // namespace system -} // namespace mojo - -// Define "hash" functions for |ChannelEndpointId|s, so they can be used in hash -// tables. -// TODO(vtl): Once we can use |std::unordered_{map,set}|, update this (and -// remove the base/containers/hash_tables.h include). -namespace BASE_HASH_NAMESPACE { - -template <> -struct hash<mojo::system::ChannelEndpointId> { - size_t operator()(mojo::system::ChannelEndpointId channel_endpoint_id) const { - return static_cast<size_t>(channel_endpoint_id.value()); - } -}; - -} // namespace BASE_HASH_NAMESPACE - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_ID_H_ diff --git a/third_party/mojo/src/mojo/edk/system/channel_endpoint_id_unittest.cc b/third_party/mojo/src/mojo/edk/system/channel_endpoint_id_unittest.cc deleted file mode 100644 index c238cb8..0000000 --- a/third_party/mojo/src/mojo/edk/system/channel_endpoint_id_unittest.cc +++ /dev/null @@ -1,155 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/channel_endpoint_id.h" - -#include <sstream> - -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace system { -namespace { - -TEST(ChannelEndpointIdTest, Basic) { - ChannelEndpointId invalid; - ChannelEndpointId bootstrap(ChannelEndpointId::GetBootstrap()); - - EXPECT_EQ(invalid, invalid); - EXPECT_EQ(bootstrap, bootstrap); - EXPECT_FALSE(invalid == bootstrap); - - EXPECT_FALSE(invalid != invalid); - EXPECT_FALSE(bootstrap != bootstrap); - EXPECT_NE(invalid, bootstrap); - - EXPECT_FALSE(invalid < invalid); - EXPECT_LT(invalid, bootstrap); - - EXPECT_FALSE(invalid.is_valid()); - EXPECT_TRUE(bootstrap.is_valid()); - - EXPECT_FALSE(invalid.is_remote()); - EXPECT_FALSE(bootstrap.is_remote()); - - // Test assignment. - ChannelEndpointId copy; - copy = bootstrap; - EXPECT_EQ(copy, bootstrap); - copy = invalid; - EXPECT_EQ(copy, invalid); -} - -// Tests values of invalid and bootstrap IDs. (This tests implementation -// details.) -TEST(ChannelEndpointIdTest, Value) { - EXPECT_EQ(0u, ChannelEndpointId().value()); - EXPECT_EQ(1u, ChannelEndpointId::GetBootstrap().value()); -} - -// Tests ostream output. (This tests implementation details.) -TEST(ChannelEndpointIdTest, Ostream) { - { - std::ostringstream stream; - stream << ChannelEndpointId(); - EXPECT_EQ("0", stream.str()); - } - { - std::ostringstream stream; - stream << ChannelEndpointId::GetBootstrap(); - EXPECT_EQ("1", stream.str()); - } -} - -TEST(LocalChannelEndpointIdGeneratorTest, Basic) { - LocalChannelEndpointIdGenerator gen; - - ChannelEndpointId id1; - EXPECT_FALSE(id1.is_valid()); // Check sanity. - - id1 = gen.GetNext(); - EXPECT_TRUE(id1.is_valid()); - EXPECT_FALSE(id1.is_remote()); - - EXPECT_EQ(ChannelEndpointId::GetBootstrap().value(), id1.value()); - - ChannelEndpointId id2 = gen.GetNext(); - EXPECT_TRUE(id2.is_valid()); - EXPECT_FALSE(id2.is_remote()); - // Technically, nonequality here is an implementation detail, since, e.g., - // random generation of IDs would be a valid implementation. - EXPECT_NE(id2, id1); - // ... but right now we just increment to generate IDs. - EXPECT_EQ(2u, id2.value()); -} - -// Note: LocalChannelEndpointIdGeneratorTest.WrapAround is defined further -// below, outside the anonymous namespace. - -TEST(RemoteChannelEndpointIdGeneratorTest, Basic) { - RemoteChannelEndpointIdGenerator gen; - - ChannelEndpointId id1; - EXPECT_FALSE(id1.is_valid()); // Check sanity. - - id1 = gen.GetNext(); - EXPECT_TRUE(id1.is_valid()); - EXPECT_TRUE(id1.is_remote()); - - // This tests an implementation detail. - EXPECT_EQ(ChannelEndpointId::kRemoteFlag, id1.value()); - - ChannelEndpointId id2 = gen.GetNext(); - EXPECT_TRUE(id2.is_valid()); - EXPECT_TRUE(id2.is_remote()); - // Technically, nonequality here is an implementation detail, since, e.g., - // random generation of IDs would be a valid implementation. - EXPECT_NE(id2, id1); - // ... but right now we just increment to generate IDs. - EXPECT_EQ(ChannelEndpointId::kRemoteFlag + 1, id2.value()); -} - -// Note: RemoteChannelEndpointIdGeneratorTest.WrapAround is defined further -// below, outside the anonymous namespace. - -} // namespace - -// Tests that |LocalChannelEndpointIdGenerator| handles wrap-around correctly. -// (This tests implementation details.) This test isn't in an anonymous -// namespace, since it needs to be friended. -TEST(LocalChannelEndpointIdGeneratorTest, WrapAround) { - LocalChannelEndpointIdGenerator gen; - gen.next_ = ChannelEndpointId(ChannelEndpointId::kRemoteFlag - 1); - - ChannelEndpointId id = gen.GetNext(); - EXPECT_TRUE(id.is_valid()); - EXPECT_FALSE(id.is_remote()); - EXPECT_EQ(ChannelEndpointId::kRemoteFlag - 1, id.value()); - - id = gen.GetNext(); - EXPECT_TRUE(id.is_valid()); - EXPECT_FALSE(id.is_remote()); - EXPECT_EQ(1u, id.value()); -} - -// Tests that |RemoteChannelEndpointIdGenerator| handles wrap-around correctly. -// (This tests implementation details.) This test isn't in an anonymous -// namespace, since it needs to be friended. -TEST(RemoteChannelEndpointIdGeneratorTest, WrapAround) { - RemoteChannelEndpointIdGenerator gen; - gen.next_ = ChannelEndpointId(~0u); - - ChannelEndpointId id = gen.GetNext(); - EXPECT_TRUE(id.is_valid()); - EXPECT_TRUE(id.is_remote()); - EXPECT_EQ(~0u, id.value()); - - id = gen.GetNext(); - EXPECT_TRUE(id.is_valid()); - EXPECT_TRUE(id.is_remote()); - EXPECT_EQ(ChannelEndpointId::kRemoteFlag, id.value()); -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/channel_endpoint_unittest.cc b/third_party/mojo/src/mojo/edk/system/channel_endpoint_unittest.cc deleted file mode 100644 index 4782b62..0000000 --- a/third_party/mojo/src/mojo/edk/system/channel_endpoint_unittest.cc +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2015 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 "third_party/mojo/src/mojo/edk/system/channel_endpoint.h" - -#include <utility> - -#include "base/synchronization/waitable_event.h" -#include "base/test/test_timeouts.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/channel_test_base.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit_queue.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit_test_utils.h" -#include "third_party/mojo/src/mojo/edk/system/test_channel_endpoint_client.h" - -namespace mojo { -namespace system { -namespace { - -class ChannelEndpointTest : public test::ChannelTestBase { - public: - ChannelEndpointTest() {} - ~ChannelEndpointTest() override {} - - void SetUp() override { - test::ChannelTestBase::SetUp(); - - PostMethodToIOThreadAndWait( - FROM_HERE, &ChannelEndpointTest::CreateAndInitChannelOnIOThread, 0); - PostMethodToIOThreadAndWait( - FROM_HERE, &ChannelEndpointTest::CreateAndInitChannelOnIOThread, 1); - } - - void TearDown() override { - PostMethodToIOThreadAndWait( - FROM_HERE, &ChannelEndpointTest::ShutdownChannelOnIOThread, 0); - PostMethodToIOThreadAndWait( - FROM_HERE, &ChannelEndpointTest::ShutdownChannelOnIOThread, 1); - - test::ChannelTestBase::TearDown(); - } - - private: - MOJO_DISALLOW_COPY_AND_ASSIGN(ChannelEndpointTest); -}; - -TEST_F(ChannelEndpointTest, Basic) { - scoped_refptr<test::TestChannelEndpointClient> client0( - new test::TestChannelEndpointClient()); - scoped_refptr<ChannelEndpoint> endpoint0( - new ChannelEndpoint(client0.get(), 0)); - client0->Init(0, endpoint0.get()); - channel(0)->SetBootstrapEndpoint(endpoint0); - - scoped_refptr<test::TestChannelEndpointClient> client1( - new test::TestChannelEndpointClient()); - scoped_refptr<ChannelEndpoint> endpoint1( - new ChannelEndpoint(client1.get(), 1)); - client1->Init(1, endpoint1.get()); - channel(1)->SetBootstrapEndpoint(endpoint1); - - // We'll receive a message on channel/client 0. - base::WaitableEvent read_event(true, false); - client0->SetReadEvent(&read_event); - - // Make a test message. - unsigned message_id = 0x12345678; - scoped_ptr<MessageInTransit> send_message = test::MakeTestMessage(message_id); - // Check that our test utility works (at least in one direction). - test::VerifyTestMessage(send_message.get(), message_id); - - // Event shouldn't be signalled yet. - EXPECT_FALSE(read_event.IsSignaled()); - - // Send it through channel/endpoint 1. - EXPECT_TRUE(endpoint1->EnqueueMessage(std::move(send_message))); - - // Wait to receive it. - EXPECT_TRUE(read_event.TimedWait(TestTimeouts::tiny_timeout())); - client0->SetReadEvent(nullptr); - - // Check the received message. - ASSERT_EQ(1u, client0->NumMessages()); - scoped_ptr<MessageInTransit> read_message = client0->PopMessage(); - ASSERT_TRUE(read_message); - test::VerifyTestMessage(read_message.get(), message_id); -} - -// Checks that prequeued messages and messages sent at various stages later on -// are all sent/received (and in the correct order). (Note: Due to the way -// bootstrap endpoints work, the receiving side has to be set up first.) -TEST_F(ChannelEndpointTest, Prequeued) { - scoped_refptr<test::TestChannelEndpointClient> client0( - new test::TestChannelEndpointClient()); - scoped_refptr<ChannelEndpoint> endpoint0( - new ChannelEndpoint(client0.get(), 0)); - client0->Init(0, endpoint0.get()); - - channel(0)->SetBootstrapEndpoint(endpoint0); - MessageInTransitQueue prequeued_messages; - prequeued_messages.AddMessage(test::MakeTestMessage(1)); - prequeued_messages.AddMessage(test::MakeTestMessage(2)); - - scoped_refptr<test::TestChannelEndpointClient> client1( - new test::TestChannelEndpointClient()); - scoped_refptr<ChannelEndpoint> endpoint1( - new ChannelEndpoint(client1.get(), 1, &prequeued_messages)); - client1->Init(1, endpoint1.get()); - - EXPECT_TRUE(endpoint1->EnqueueMessage(test::MakeTestMessage(3))); - EXPECT_TRUE(endpoint1->EnqueueMessage(test::MakeTestMessage(4))); - - channel(1)->SetBootstrapEndpoint(endpoint1); - - EXPECT_TRUE(endpoint1->EnqueueMessage(test::MakeTestMessage(5))); - EXPECT_TRUE(endpoint1->EnqueueMessage(test::MakeTestMessage(6))); - - // Wait for the messages. - base::WaitableEvent read_event(true, false); - client0->SetReadEvent(&read_event); - for (size_t i = 0; client0->NumMessages() < 6 && i < 6; i++) { - EXPECT_TRUE(read_event.TimedWait(TestTimeouts::tiny_timeout())); - read_event.Reset(); - } - client0->SetReadEvent(nullptr); - - // Check the received messages. - ASSERT_EQ(6u, client0->NumMessages()); - for (unsigned message_id = 1; message_id <= 6; message_id++) { - scoped_ptr<MessageInTransit> read_message = client0->PopMessage(); - ASSERT_TRUE(read_message); - test::VerifyTestMessage(read_message.get(), message_id); - } -} - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/channel_id.h b/third_party/mojo/src/mojo/edk/system/channel_id.h deleted file mode 100644 index fa35298..0000000 --- a/third_party/mojo/src/mojo/edk/system/channel_id.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2015 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CHANNEL_ID_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CHANNEL_ID_H_ - -#include <stdint.h> - -namespace mojo { -namespace system { - -// IDs for |Channel|s managed by a |ChannelManager|. (IDs should be thought of -// as specific to a given |ChannelManager|.) -using ChannelId = uint64_t; - -// 0 is never a valid |ChannelId|. -const ChannelId kInvalidChannelId = 0; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CHANNEL_ID_H_ diff --git a/third_party/mojo/src/mojo/edk/system/channel_manager.cc b/third_party/mojo/src/mojo/edk/system/channel_manager.cc deleted file mode 100644 index 49aeaf7..0000000 --- a/third_party/mojo/src/mojo/edk/system/channel_manager.cc +++ /dev/null @@ -1,216 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/channel_manager.h" - -#include <utility> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/location.h" -#include "base/task_runner.h" -#include "third_party/mojo/src/mojo/edk/system/channel.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.h" - -namespace mojo { -namespace system { - -ChannelManager::ChannelManager( - embedder::PlatformSupport* platform_support, - scoped_refptr<base::TaskRunner> io_thread_task_runner, - ConnectionManager* connection_manager) - : platform_support_(platform_support), - io_thread_task_runner_(io_thread_task_runner), - connection_manager_(connection_manager), - weak_factory_(this) { - DCHECK(platform_support_); - DCHECK(io_thread_task_runner_); - // (|connection_manager_| may be null.) - weak_ptr_ = weak_factory_.GetWeakPtr(); -} - -ChannelManager::~ChannelManager() { - // |Shutdown()| must be called before destruction and have been completed. - // TODO(vtl): This doesn't verify the above condition very strictly at all - // (e.g., we may never have had any channels, or we may have manually shut all - // the channels down). - DCHECK(channels_.empty()); - DCHECK(!weak_factory_.HasWeakPtrs()); -} - -void ChannelManager::ShutdownOnIOThread() { - // Taking this lock really shouldn't be necessary, but we do it for - // consistency. - ChannelIdToChannelMap channels; - { - MutexLocker locker(&mutex_); - channels.swap(channels_); - } - - for (auto& channel : channels) - channel.second->Shutdown(); - - weak_factory_.InvalidateWeakPtrs(); -} - -void ChannelManager::Shutdown( - const base::Closure& callback, - scoped_refptr<base::TaskRunner> callback_thread_task_runner) { - bool ok = io_thread_task_runner_->PostTask( - FROM_HERE, - base::Bind(&ChannelManager::ShutdownHelper, base::Unretained(this), - callback, callback_thread_task_runner)); - DCHECK(ok); -} - -scoped_refptr<MessagePipeDispatcher> ChannelManager::CreateChannelOnIOThread( - ChannelId channel_id, - embedder::ScopedPlatformHandle platform_handle) { - scoped_refptr<system::ChannelEndpoint> bootstrap_channel_endpoint; - scoped_refptr<system::MessagePipeDispatcher> dispatcher = - system::MessagePipeDispatcher::CreateRemoteMessagePipe( - &bootstrap_channel_endpoint); - CreateChannelOnIOThreadHelper(channel_id, std::move(platform_handle), - bootstrap_channel_endpoint); - return dispatcher; -} - -scoped_refptr<Channel> ChannelManager::CreateChannelWithoutBootstrapOnIOThread( - ChannelId channel_id, - embedder::ScopedPlatformHandle platform_handle) { - return CreateChannelOnIOThreadHelper(channel_id, std::move(platform_handle), - nullptr); -} - -scoped_refptr<MessagePipeDispatcher> ChannelManager::CreateChannel( - ChannelId channel_id, - embedder::ScopedPlatformHandle platform_handle, - const base::Closure& callback, - scoped_refptr<base::TaskRunner> callback_thread_task_runner) { - DCHECK(!callback.is_null()); - // (|callback_thread_task_runner| may be null.) - - scoped_refptr<system::ChannelEndpoint> bootstrap_channel_endpoint; - scoped_refptr<system::MessagePipeDispatcher> dispatcher = - system::MessagePipeDispatcher::CreateRemoteMessagePipe( - &bootstrap_channel_endpoint); - bool ok = io_thread_task_runner_->PostTask( - FROM_HERE, - base::Bind(&ChannelManager::CreateChannelHelper, weak_ptr_, - channel_id, base::Passed(&platform_handle), - bootstrap_channel_endpoint, callback, - callback_thread_task_runner)); - DCHECK(ok); - return dispatcher; -} - -scoped_refptr<Channel> ChannelManager::GetChannel(ChannelId channel_id) const { - MutexLocker locker(&mutex_); - auto it = channels_.find(channel_id); - DCHECK(it != channels_.end()); - return it->second; -} - -void ChannelManager::WillShutdownChannel(ChannelId channel_id) { - GetChannel(channel_id)->WillShutdownSoon(); -} - -void ChannelManager::ShutdownChannelOnIOThread(ChannelId channel_id) { - scoped_refptr<Channel> channel; - { - MutexLocker locker(&mutex_); - auto it = channels_.find(channel_id); - DCHECK(it != channels_.end()); - channel.swap(it->second); - channels_.erase(it); - } - channel->Shutdown(); -} - -void ChannelManager::ShutdownChannel( - ChannelId channel_id, - const base::Closure& callback, - scoped_refptr<base::TaskRunner> callback_thread_task_runner) { - WillShutdownChannel(channel_id); - bool ok = io_thread_task_runner_->PostTask( - FROM_HERE, base::Bind( - &ChannelManager::ShutdownChannelHelper, weak_ptr_, - channel_id, callback, callback_thread_task_runner)); - DCHECK(ok); -} - -void ChannelManager::ShutdownChannelHelper( - ChannelId channel_id, - const base::Closure& callback, - scoped_refptr<base::TaskRunner> callback_thread_task_runner) { - ShutdownChannelOnIOThread(channel_id); - if (callback_thread_task_runner) { - bool ok = callback_thread_task_runner->PostTask(FROM_HERE, callback); - DCHECK(ok); - } else { - callback.Run(); - } -} - -void ChannelManager::ShutdownHelper( - const base::Closure& callback, - scoped_refptr<base::TaskRunner> callback_thread_task_runner) { - ShutdownOnIOThread(); - if (callback_thread_task_runner) { - bool ok = callback_thread_task_runner->PostTask(FROM_HERE, callback); - DCHECK(ok); - } else { - callback.Run(); - } -} - -scoped_refptr<Channel> ChannelManager::CreateChannelOnIOThreadHelper( - ChannelId channel_id, - embedder::ScopedPlatformHandle platform_handle, - scoped_refptr<system::ChannelEndpoint> bootstrap_channel_endpoint) { - DCHECK_NE(channel_id, kInvalidChannelId); - DCHECK(platform_handle.is_valid()); - - // Create and initialize a |system::Channel|. - scoped_refptr<system::Channel> channel = - new system::Channel(platform_support_); - channel->Init(system::RawChannel::Create(std::move(platform_handle))); - if (bootstrap_channel_endpoint) - channel->SetBootstrapEndpoint(bootstrap_channel_endpoint); - - { - MutexLocker locker(&mutex_); - CHECK(channels_.find(channel_id) == channels_.end()); - channels_[channel_id] = channel; - } - channel->SetChannelManager(this); - return channel; -} - -// static -void ChannelManager::CreateChannelHelper( - base::WeakPtr<ChannelManager> channel_manager, - ChannelId channel_id, - embedder::ScopedPlatformHandle platform_handle, - scoped_refptr<system::ChannelEndpoint> bootstrap_channel_endpoint, - const base::Closure& callback, - scoped_refptr<base::TaskRunner> callback_thread_task_runner) { - // TODO(amistry): Handle this gracefully after determining exactly what cases - // can cause this. There appear to be crashes caused by ChannelManager being - // destroyed before this point, which shouldn't be possible in the current - // uses of ChannelManager. - CHECK(channel_manager); - channel_manager->CreateChannelOnIOThreadHelper( - channel_id, std::move(platform_handle), bootstrap_channel_endpoint); - if (callback_thread_task_runner) { - bool ok = callback_thread_task_runner->PostTask(FROM_HERE, callback); - DCHECK(ok); - } else { - callback.Run(); - } -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/channel_manager.h b/third_party/mojo/src/mojo/edk/system/channel_manager.h deleted file mode 100644 index 360996f..0000000 --- a/third_party/mojo/src/mojo/edk/system/channel_manager.h +++ /dev/null @@ -1,178 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CHANNEL_MANAGER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CHANNEL_MANAGER_H_ - -#include <stdint.h> - -#include "base/callback_forward.h" -#include "base/containers/hash_tables.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" -#include "third_party/mojo/src/mojo/edk/system/channel_id.h" -#include "third_party/mojo/src/mojo/edk/system/mutex.h" - -namespace base { -class TaskRunner; -} - -namespace mojo { - -namespace embedder { -class PlatformSupport; -} - -namespace system { - -class Channel; -class ChannelEndpoint; -class ConnectionManager; -class MessagePipeDispatcher; - -// This class manages and "owns" |Channel|s (which typically connect to other -// processes) for a given process. This class is thread-safe, except as -// specifically noted. -class MOJO_SYSTEM_IMPL_EXPORT ChannelManager { - public: - // |io_thread_task_runner| should be the |TaskRunner| for the I/O thread, on - // which this channel manager will create all channels. Connection manager is - // optional and may be null. All arguments (if non-null) must remain alive at - // least until after shutdown completion. - ChannelManager(embedder::PlatformSupport* platform_support, - scoped_refptr<base::TaskRunner> io_thread_task_runner, - ConnectionManager* connection_manager); - ~ChannelManager(); - - // Shuts down the channel manager, including shutting down all channels (as if - // |ShutdownChannelOnIOThread()| were called for each channel). This must be - // called from the I/O thread (given to the constructor) and completes - // synchronously. This, or |Shutdown()|, must be called before destroying this - // object. - void ShutdownOnIOThread(); - - // Like |ShutdownOnIOThread()|, but may be called from any thread. On - // completion, will call |callback| ("on" |io_thread_task_runner| if - // |callback_thread_task_runner| is null else by posted using - // |callback_thread_task_runner|). Note: This will always post a task to the - // I/O thread, even it is the current thread. - // TODO(vtl): Consider if this is really necessary, since it only has one use - // (in tests). - void Shutdown(const base::Closure& callback, - scoped_refptr<base::TaskRunner> callback_thread_task_runner); - - // Creates a |Channel| and adds it to the set of channels managed by this - // |ChannelManager|. This must be called from the I/O thread (given to the - // constructor). |channel_id| should be a valid |ChannelId| (i.e., nonzero) - // not "assigned" to any other |Channel| being managed by this - // |ChannelManager|. - scoped_refptr<MessagePipeDispatcher> CreateChannelOnIOThread( - ChannelId channel_id, - embedder::ScopedPlatformHandle platform_handle); - - // Like |CreateChannelOnIOThread()|, but doesn't create a bootstrap message - // pipe. Returns the newly-created |Channel|. - // TODO(vtl): Maybe get rid of the others (and bootstrap message pipes in - // general). - scoped_refptr<Channel> CreateChannelWithoutBootstrapOnIOThread( - ChannelId channel_id, - embedder::ScopedPlatformHandle platform_handle); - - // Like |CreateChannelOnIOThread()|, but may be called from any thread. On - // completion, will call |callback| (using |callback_thread_task_runner| if it - // is non-null, else on the I/O thread). Note: This will always post a task to - // the I/O thread, even if called from that thread. - scoped_refptr<MessagePipeDispatcher> CreateChannel( - ChannelId channel_id, - embedder::ScopedPlatformHandle platform_handle, - const base::Closure& callback, - scoped_refptr<base::TaskRunner> callback_thread_task_runner); - - // Gets the |Channel| with the given ID (which must exist). - scoped_refptr<Channel> GetChannel(ChannelId channel_id) const; - - // Informs the channel manager (and thus channel) that it will be shutdown - // soon (by calling |ShutdownChannel()|). Calling this is optional (and may in - // fact be called multiple times) but it will suppress certain warnings (e.g., - // for the channel being broken) and enable others (if messages are written to - // the channel). - void WillShutdownChannel(ChannelId channel_id); - - // Shuts down the channel specified by the given ID. This, or - // |ShutdownChannel()|, should be called once per channel (created using - // |CreateChannelOnIOThread()| or |CreateChannel()|). This must be called from - // the I/O thread. - void ShutdownChannelOnIOThread(ChannelId channel_id); - - // Like |ShutdownChannelOnIOThread()|, but may be called from any thread. It - // will always post a task to the I/O thread, and post |callback| to - // |callback_thread_task_runner| (or execute it directly on the I/O thread if - // |callback_thread_task_runner| is null) on completion. - void ShutdownChannel( - ChannelId channel_id, - const base::Closure& callback, - scoped_refptr<base::TaskRunner> callback_thread_task_runner); - - ConnectionManager* connection_manager() const { return connection_manager_; } - - private: - // Used by |ShutdownChannel()|. Called on the I/O thread. - void ShutdownChannelHelper( - ChannelId channel_id, - const base::Closure& callback, - scoped_refptr<base::TaskRunner> callback_thread_task_runner); - - // Used by |Shutdown()|. Called on the I/O thread. - void ShutdownHelper( - const base::Closure& callback, - scoped_refptr<base::TaskRunner> callback_thread_task_runner); - - // Used by |CreateChannelOnIOThread()| and |CreateChannelHelper()|. Called on - // the I/O thread. |bootstrap_channel_endpoint| is optional and may be null. - // Returns the newly-created |Channel|. - scoped_refptr<Channel> CreateChannelOnIOThreadHelper( - ChannelId channel_id, - embedder::ScopedPlatformHandle platform_handle, - scoped_refptr<system::ChannelEndpoint> bootstrap_channel_endpoint); - - // Used by |CreateChannel()|. Called on the I/O thread. - static void CreateChannelHelper( - base::WeakPtr<ChannelManager> channel_manager, - ChannelId channel_id, - embedder::ScopedPlatformHandle platform_handle, - scoped_refptr<system::ChannelEndpoint> bootstrap_channel_endpoint, - const base::Closure& callback, - scoped_refptr<base::TaskRunner> callback_thread_task_runner); - - // Note: These must not be used after shutdown. - embedder::PlatformSupport* const platform_support_; - const scoped_refptr<base::TaskRunner> io_thread_task_runner_; - ConnectionManager* const connection_manager_; - - // Note: |Channel| methods should not be called under |mutex_|. - // TODO(vtl): Annotate the above rule using |MOJO_ACQUIRED_{BEFORE,AFTER}()|, - // once clang actually checks such annotations. - // https://github.com/domokit/mojo/issues/313 - mutable Mutex mutex_; - - using ChannelIdToChannelMap = - base::hash_map<ChannelId, scoped_refptr<Channel>>; - ChannelIdToChannelMap channels_ MOJO_GUARDED_BY(mutex_); - - // Weak pointer for posting a task to the IO thread. Must only be dereferenced - // on the IO thread. - base::WeakPtr<ChannelManager> weak_ptr_; - // Factory for weak pointer. Must be invalidated on the IO thread prior to - // destruction. - base::WeakPtrFactory<ChannelManager> weak_factory_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ChannelManager); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CHANNEL_MANAGER_H_ diff --git a/third_party/mojo/src/mojo/edk/system/channel_manager_unittest.cc b/third_party/mojo/src/mojo/edk/system/channel_manager_unittest.cc deleted file mode 100644 index 807ec0b..0000000 --- a/third_party/mojo/src/mojo/edk/system/channel_manager_unittest.cc +++ /dev/null @@ -1,178 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/channel_manager.h" - -#include "base/callback.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/task_runner.h" -#include "base/thread_task_runner_handle.h" -#include "base/threading/simple_thread.h" -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" -#include "third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h" -#include "third_party/mojo/src/mojo/edk/system/channel.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.h" - -namespace mojo { -namespace system { -namespace { - -class ChannelManagerTest : public testing::Test { - public: - ChannelManagerTest() - : message_loop_(base::MessageLoop::TYPE_IO), - channel_manager_(&platform_support_, - message_loop_.task_runner(), - nullptr) {} - ~ChannelManagerTest() override { - channel_manager_.ShutdownOnIOThread(); - } - - protected: - ChannelManager& channel_manager() { return channel_manager_; } - - private: - embedder::SimplePlatformSupport platform_support_; - base::MessageLoop message_loop_; - // Note: This should be *after* the above, since they must be initialized - // before it (and should outlive it). - ChannelManager channel_manager_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ChannelManagerTest); -}; - -TEST_F(ChannelManagerTest, Basic) { - embedder::PlatformChannelPair channel_pair; - - const ChannelId id = 1; - scoped_refptr<MessagePipeDispatcher> d = - channel_manager().CreateChannelOnIOThread( - id, channel_pair.PassServerHandle()); - - scoped_refptr<Channel> ch = channel_manager().GetChannel(id); - EXPECT_TRUE(ch); - // |ChannelManager| should have a ref. - EXPECT_FALSE(ch->HasOneRef()); - - channel_manager().WillShutdownChannel(id); - // |ChannelManager| should still have a ref. - EXPECT_FALSE(ch->HasOneRef()); - - channel_manager().ShutdownChannelOnIOThread(id); - // |ChannelManager| should have given up its ref. - EXPECT_TRUE(ch->HasOneRef()); - - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); -} - -TEST_F(ChannelManagerTest, TwoChannels) { - embedder::PlatformChannelPair channel_pair; - - const ChannelId id1 = 1; - scoped_refptr<MessagePipeDispatcher> d1 = - channel_manager().CreateChannelOnIOThread( - id1, channel_pair.PassServerHandle()); - - const ChannelId id2 = 2; - scoped_refptr<MessagePipeDispatcher> d2 = - channel_manager().CreateChannelOnIOThread( - id2, channel_pair.PassClientHandle()); - - scoped_refptr<Channel> ch1 = channel_manager().GetChannel(id1); - EXPECT_TRUE(ch1); - - scoped_refptr<Channel> ch2 = channel_manager().GetChannel(id2); - EXPECT_TRUE(ch2); - - // Calling |WillShutdownChannel()| multiple times (on |id1|) is okay. - channel_manager().WillShutdownChannel(id1); - channel_manager().WillShutdownChannel(id1); - EXPECT_FALSE(ch1->HasOneRef()); - // Not calling |WillShutdownChannel()| (on |id2|) is okay too. - - channel_manager().ShutdownChannelOnIOThread(id1); - EXPECT_TRUE(ch1->HasOneRef()); - channel_manager().ShutdownChannelOnIOThread(id2); - EXPECT_TRUE(ch2->HasOneRef()); - - EXPECT_EQ(MOJO_RESULT_OK, d1->Close()); - EXPECT_EQ(MOJO_RESULT_OK, d2->Close()); -} - -class OtherThread : public base::SimpleThread { - public: - // Note: There should be no other refs to the channel identified by - // |channel_id| outside the channel manager. - OtherThread(scoped_refptr<base::TaskRunner> task_runner, - ChannelManager* channel_manager, - ChannelId channel_id, - const base::Closure& quit_closure) - : base::SimpleThread("other_thread"), - task_runner_(task_runner), - channel_manager_(channel_manager), - channel_id_(channel_id), - quit_closure_(quit_closure) {} - ~OtherThread() override {} - - private: - void Run() override { - // TODO(vtl): Once we have a way of creating a channel from off the I/O - // thread, do that here instead. - - // You can use any unique, nonzero value as the ID. - scoped_refptr<Channel> ch = channel_manager_->GetChannel(channel_id_); - // |ChannelManager| should have a ref. - EXPECT_FALSE(ch->HasOneRef()); - - channel_manager_->WillShutdownChannel(channel_id_); - // |ChannelManager| should still have a ref. - EXPECT_FALSE(ch->HasOneRef()); - - { - base::MessageLoop message_loop; - base::RunLoop run_loop; - channel_manager_->ShutdownChannel(channel_id_, run_loop.QuitClosure(), - message_loop.task_runner()); - run_loop.Run(); - } - - CHECK(task_runner_->PostTask(FROM_HERE, quit_closure_)); - } - - scoped_refptr<base::TaskRunner> task_runner_; - ChannelManager* channel_manager_; - ChannelId channel_id_; - base::Closure quit_closure_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(OtherThread); -}; - -TEST_F(ChannelManagerTest, CallsFromOtherThread) { - embedder::PlatformChannelPair channel_pair; - - const ChannelId id = 1; - scoped_refptr<MessagePipeDispatcher> d = - channel_manager().CreateChannelOnIOThread( - id, channel_pair.PassServerHandle()); - - base::RunLoop run_loop; - OtherThread thread(base::ThreadTaskRunnerHandle::Get(), &channel_manager(), - id, run_loop.QuitClosure()); - thread.Start(); - run_loop.Run(); - thread.Join(); - - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); -} - -// TODO(vtl): Test |CreateChannelWithoutBootstrapOnIOThread()|. (This will -// require additional functionality in |Channel|.) - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/channel_test_base.cc b/third_party/mojo/src/mojo/edk/system/channel_test_base.cc deleted file mode 100644 index bfe429d..0000000 --- a/third_party/mojo/src/mojo/edk/system/channel_test_base.cc +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2015 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 "third_party/mojo/src/mojo/edk/system/channel_test_base.h" - -#include <utility> - -#include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" -#include "third_party/mojo/src/mojo/edk/system/raw_channel.h" - -namespace mojo { -namespace system { -namespace test { - -ChannelTestBase::ChannelTestBase() - : io_thread_(base::TestIOThread::kAutoStart) { -} - -ChannelTestBase::~ChannelTestBase() { -} - -void ChannelTestBase::SetUp() { - PostMethodToIOThreadAndWait(FROM_HERE, &ChannelTestBase::SetUpOnIOThread); -} - -void ChannelTestBase::CreateChannelOnIOThread(unsigned i) { - CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); - - CHECK(!channels_[i]); - channels_[i] = new Channel(&platform_support_); -} - -void ChannelTestBase::InitChannelOnIOThread(unsigned i) { - CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); - - CHECK(raw_channels_[i]); - CHECK(channels_[i]); - channels_[i]->Init(std::move(raw_channels_[i])); -} - -void ChannelTestBase::CreateAndInitChannelOnIOThread(unsigned i) { - CreateChannelOnIOThread(i); - InitChannelOnIOThread(i); -} - -void ChannelTestBase::ShutdownChannelOnIOThread(unsigned i) { - CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); - - CHECK(channels_[i]); - channels_[i]->Shutdown(); -} - -void ChannelTestBase::ShutdownAndReleaseChannelOnIOThread(unsigned i) { - ShutdownChannelOnIOThread(i); - channels_[i] = nullptr; -} - -void ChannelTestBase::SetUpOnIOThread() { - CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); - - embedder::PlatformChannelPair channel_pair; - raw_channels_[0] = RawChannel::Create(channel_pair.PassServerHandle()); - raw_channels_[1] = RawChannel::Create(channel_pair.PassClientHandle()); -} - -} // namespace test -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/channel_test_base.h b/third_party/mojo/src/mojo/edk/system/channel_test_base.h deleted file mode 100644 index 2bc5970..0000000 --- a/third_party/mojo/src/mojo/edk/system/channel_test_base.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2015 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CHANNEL_TEST_BASE_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CHANNEL_TEST_BASE_H_ - -#include "base/bind.h" -#include "base/location.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/test/test_io_thread.h" -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h" -#include "third_party/mojo/src/mojo/edk/system/channel.h" - -namespace mojo { -namespace system { - -class RawChannel; - -namespace test { - -// A base class for tests that need a |Channel| set up in a simple way. -class ChannelTestBase : public testing::Test { - public: - ChannelTestBase(); - ~ChannelTestBase() override; - - void SetUp() override; - - template <typename Functor, typename... Args> - void PostMethodToIOThreadAndWait(const tracked_objects::Location& from_here, - Functor functor, - const Args&... args) { - io_thread_.PostTaskAndWait( - from_here, base::Bind(functor, base::Unretained(this), args...)); - } - - // These should only be called from |io_thread()|: - void CreateChannelOnIOThread(unsigned i); - void InitChannelOnIOThread(unsigned i); - void CreateAndInitChannelOnIOThread(unsigned i); - void ShutdownChannelOnIOThread(unsigned i); - void ShutdownAndReleaseChannelOnIOThread(unsigned i); - - base::TestIOThread* io_thread() { return &io_thread_; } - Channel* channel(unsigned i) { return channels_[i].get(); } - scoped_refptr<Channel>* mutable_channel(unsigned i) { return &channels_[i]; } - - private: - void SetUpOnIOThread(); - - embedder::SimplePlatformSupport platform_support_; - base::TestIOThread io_thread_; - scoped_ptr<RawChannel> raw_channels_[2]; - scoped_refptr<Channel> channels_[2]; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ChannelTestBase); -}; - -} // namespace test -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CHANNEL_TEST_BASE_H_ diff --git a/third_party/mojo/src/mojo/edk/system/channel_unittest.cc b/third_party/mojo/src/mojo/edk/system/channel_unittest.cc deleted file mode 100644 index 0e601fd..0000000 --- a/third_party/mojo/src/mojo/edk/system/channel_unittest.cc +++ /dev/null @@ -1,151 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/channel.h" - -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint_id.h" -#include "third_party/mojo/src/mojo/edk/system/channel_test_base.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/test_utils.h" -#include "third_party/mojo/src/mojo/edk/system/waiter.h" - -namespace mojo { -namespace system { -namespace { - -using ChannelTest = test::ChannelTestBase; - -void DoNothing() {} - -// ChannelTest.InitShutdown ---------------------------------------------------- - -TEST_F(ChannelTest, InitShutdown) { - PostMethodToIOThreadAndWait(FROM_HERE, - &ChannelTest::CreateAndInitChannelOnIOThread, 0); - PostMethodToIOThreadAndWait(FROM_HERE, - &ChannelTest::ShutdownChannelOnIOThread, 0); - - // Okay to destroy |Channel| on not-the-I/O-thread. - EXPECT_TRUE(channel(0)->HasOneRef()); - *mutable_channel(0) = nullptr; -} - -// ChannelTest.CloseBeforeAttachAndRun ----------------------------------------- - -TEST_F(ChannelTest, CloseBeforeRun) { - PostMethodToIOThreadAndWait(FROM_HERE, - &ChannelTest::CreateAndInitChannelOnIOThread, 0); - - scoped_refptr<ChannelEndpoint> channel_endpoint; - scoped_refptr<MessagePipe> mp( - MessagePipe::CreateLocalProxy(&channel_endpoint)); - - mp->Close(0); - - channel(0)->SetBootstrapEndpoint(channel_endpoint); - - PostMethodToIOThreadAndWait(FROM_HERE, - &ChannelTest::ShutdownChannelOnIOThread, 0); - - EXPECT_TRUE(channel(0)->HasOneRef()); -} - -// ChannelTest.ShutdownAfterAttachAndRun --------------------------------------- - -TEST_F(ChannelTest, ShutdownAfterAttach) { - PostMethodToIOThreadAndWait(FROM_HERE, - &ChannelTest::CreateAndInitChannelOnIOThread, 0); - - scoped_refptr<ChannelEndpoint> channel_endpoint; - scoped_refptr<MessagePipe> mp( - MessagePipe::CreateLocalProxy(&channel_endpoint)); - - channel(0)->SetBootstrapEndpoint(channel_endpoint); - - Waiter waiter; - waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - mp->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); - - // Don't wait for the shutdown to run ... - PostMethodToIOThreadAndWait(FROM_HERE, - &ChannelTest::ShutdownChannelOnIOThread, 0); - - // ... since this |Wait()| should fail once the channel is shut down. - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - waiter.Wait(MOJO_DEADLINE_INDEFINITE, nullptr)); - HandleSignalsState hss; - mp->RemoveAwakable(0, &waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - mp->Close(0); - - EXPECT_TRUE(channel(0)->HasOneRef()); -} - -// ChannelTest.WaitAfterAttachRunAndShutdown ----------------------------------- - -TEST_F(ChannelTest, WaitAfterAttachRunAndShutdown) { - PostMethodToIOThreadAndWait(FROM_HERE, - &ChannelTest::CreateAndInitChannelOnIOThread, 0); - - scoped_refptr<ChannelEndpoint> channel_endpoint; - scoped_refptr<MessagePipe> mp( - MessagePipe::CreateLocalProxy(&channel_endpoint)); - - channel(0)->SetBootstrapEndpoint(channel_endpoint); - - PostMethodToIOThreadAndWait(FROM_HERE, - &ChannelTest::ShutdownChannelOnIOThread, 0); - - Waiter waiter; - waiter.Init(); - HandleSignalsState hss; - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - mp->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - mp->Close(0); - - EXPECT_TRUE(channel(0)->HasOneRef()); -} - -// ChannelTest.EndpointChannelShutdownRace ------------------------------------- - -TEST_F(ChannelTest, EndpointChannelShutdownRace) { - const size_t kIterations = 1000; - - for (size_t i = 0; i < kIterations; i++) { - // Need a new set of |RawChannel|s on every iteration. - SetUp(); - PostMethodToIOThreadAndWait( - FROM_HERE, &ChannelTest::CreateAndInitChannelOnIOThread, 0); - - scoped_refptr<ChannelEndpoint> channel_endpoint; - scoped_refptr<MessagePipe> mp( - MessagePipe::CreateLocalProxy(&channel_endpoint)); - - channel(0)->SetBootstrapEndpoint(channel_endpoint); - - io_thread()->PostTask( - FROM_HERE, base::Bind(&ChannelTest::ShutdownAndReleaseChannelOnIOThread, - base::Unretained(this), 0)); - mp->Close(0); - - // Wait for the IO thread to finish shutting down the channel. - io_thread()->PostTaskAndWait(FROM_HERE, base::Bind(&DoNothing)); - EXPECT_FALSE(channel(0)); - } -} - -// TODO(vtl): More. ------------------------------------------------------------ - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/configuration.cc b/third_party/mojo/src/mojo/edk/system/configuration.cc deleted file mode 100644 index 040c476..0000000 --- a/third_party/mojo/src/mojo/edk/system/configuration.cc +++ /dev/null @@ -1,26 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/configuration.h" - -namespace mojo { -namespace system { -namespace internal { - -// These default values should be synced with the documentation in -// mojo/edk/embedder/configuration.h. -embedder::Configuration g_configuration = { - 1000000, // max_handle_table_size - 1000000, // max_mapping_table_sze - 1000000, // max_wait_many_num_handles - 4 * 1024 * 1024, // max_message_num_bytes - 10000, // max_message_num_handles - 256 * 1024 * 1024, // max_data_pipe_capacity_bytes - 1024 * 1024, // default_data_pipe_capacity_bytes - 16, // data_pipe_buffer_alignment_bytes - 1024 * 1024 * 1024}; // max_shared_memory_num_bytes - -} // namespace internal -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/configuration.h b/third_party/mojo/src/mojo/edk/system/configuration.h deleted file mode 100644 index 866582f..0000000 --- a/third_party/mojo/src/mojo/edk/system/configuration.h +++ /dev/null @@ -1,31 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CONFIGURATION_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CONFIGURATION_H_ - -#include "third_party/mojo/src/mojo/edk/embedder/configuration.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -namespace internal { -MOJO_SYSTEM_IMPL_EXPORT extern embedder::Configuration g_configuration; -} // namespace internal - -MOJO_SYSTEM_IMPL_EXPORT inline const embedder::Configuration& -GetConfiguration() { - return internal::g_configuration; -} - -MOJO_SYSTEM_IMPL_EXPORT inline embedder::Configuration* -GetMutableConfiguration() { - return &internal::g_configuration; -} - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CONFIGURATION_H_ diff --git a/third_party/mojo/src/mojo/edk/system/connection_identifier.h b/third_party/mojo/src/mojo/edk/system/connection_identifier.h deleted file mode 100644 index eed40ef..0000000 --- a/third_party/mojo/src/mojo/edk/system/connection_identifier.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2015 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CONNECTION_IDENTIFIER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CONNECTION_IDENTIFIER_H_ - -#include "third_party/mojo/src/mojo/edk/system/unique_identifier.h" - -namespace mojo { -namespace system { - -// (Temporary, unique) identifiers for connections (for used with -// |ConnectionManager|s), used as they are being brought up: -using ConnectionIdentifier = UniqueIdentifier; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CONNECTION_IDENTIFIER_H_ diff --git a/third_party/mojo/src/mojo/edk/system/connection_manager.cc b/third_party/mojo/src/mojo/edk/system/connection_manager.cc deleted file mode 100644 index 18c36d1..0000000 --- a/third_party/mojo/src/mojo/edk/system/connection_manager.cc +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2015 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 "third_party/mojo/src/mojo/edk/system/connection_manager.h" - -namespace mojo { -namespace system { - -ConnectionIdentifier ConnectionManager::GenerateConnectionIdentifier() { - return UniqueIdentifier::Generate(platform_support_); -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/connection_manager.h b/third_party/mojo/src/mojo/edk/system/connection_manager.h deleted file mode 100644 index 7e569d9..0000000 --- a/third_party/mojo/src/mojo/edk/system/connection_manager.h +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2015 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CONNECTION_MANAGER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CONNECTION_MANAGER_H_ - -#include <ostream> - -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/connection_identifier.h" -#include "third_party/mojo/src/mojo/edk/system/process_identifier.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" -#include "third_party/mojo/src/mojo/edk/system/thread_annotations.h" - -namespace mojo { - -namespace embedder { -class PlatformSupport; -class ScopedPlatformHandle; -} // namespace embedder - -namespace system { - -// |ConnectionManager| is an interface for the system that allows "connections" -// (i.e., native "pipes") to be established between different processes. -// -// The starting point for establishing such a connection is that the two -// processes (not necessarily distinct) are provided with a common -// |ConnectionIdentifier|, and also some (probably indirect, temporary) way of -// communicating. -// -// (The usual case for this are processes A, B, C, with connections A <-> B <-> -// C, with the goal being to establish a direct connection A <-> C. Process B -// generates a |ConnectionIdentifier| that it transmits to A and C, and serves -// as an intermediary until A and C are directly connected.) -// -// To establish such a connection, each process calls |AllowConnect()| with the -// common |ConnectionIdentifier|. Each process then informs the other process -// that it has done so. Once a process knows that both processes have called -// |AllowConnect()|, it proceeds to call |Connect()|. -// -// On success, if the two processes are in fact distinct, |Connect()| provides a -// native (platform) handle for a "pipe" that connects/will connect the two -// processes. (If they are in fact the same process, success will simply yield -// no valid handle, to indicate this case.) -// -// Additionally, on success |Connect()| also provides a unique identifier for -// the peer process. In this way, processes may recognize when they already have -// a direct connection and reuse that, disposing of the new one provided by -// |Connect()|. (TODO(vtl): This is somewhat wasteful, but removes the need to -// handle various race conditions, and for the "master" process -- see below -- -// to track connection teardowns.) -// -// Implementation notes: We implement this using a "star topology", with a -// single trusted "master" (broker) process and an arbitrary number of untrusted -// "slave" (client) processes. The former is implemented by -// |MasterConnectionManager| (master_connection_manager.*) and the latter by -// |SlaveConnectionManager| (slave_connection_manager.*). Each slave is -// connected to the master by a special dedicated |RawChannel|, on which it does -// synchronous IPC (note, however, that the master should never block on any -// slave). -class MOJO_SYSTEM_IMPL_EXPORT ConnectionManager { - public: - enum class Result { - FAILURE = 0, - SUCCESS, - // These results are used for |Connect()| (which also uses |FAILURE|, but - // not |SUCCESS|). - SUCCESS_CONNECT_SAME_PROCESS, - SUCCESS_CONNECT_NEW_CONNECTION, - SUCCESS_CONNECT_REUSE_CONNECTION - }; - - virtual ~ConnectionManager() {} - - ConnectionIdentifier GenerateConnectionIdentifier(); - - // Shuts down this connection manager. No other methods may be called after - // this is (or while it is being) called. - virtual void Shutdown() MOJO_NOT_THREAD_SAFE = 0; - - // TODO(vtl): Add a "get my own process identifier" method? - - // All of the methods below return true on success or false on failure. - // Failure is obviously fatal for the establishment of a particular - // connection, but should not be treated as fatal to the process. Failure may, - // e.g., be caused by a misbehaving (malicious) untrusted peer process. - - // Allows a process who makes the identical call (with equal |connection_id|) - // to connect to the calling process. (On success, there will be a "pending - // connection" for the given |connection_id| for the calling process.) - virtual bool AllowConnect(const ConnectionIdentifier& connection_id) = 0; - - // Cancels a pending connection for the calling process. (Note that this may - // fail even if |AllowConnect()| succeeded; regardless, |Connect()| should not - // be called.) - virtual bool CancelConnect(const ConnectionIdentifier& connection_id) = 0; - - // Connects a pending connection; to be called only after both parties have - // called |AllowConnect()|. On success, |Result::SUCCESS_CONNECT_...| is - // returned, |peer_process_identifier| is set to an unique identifier for the - // peer process, and |is_first| is set to true if this is the first party to - // call |Connect()|. In the case of |SUCCESS_CONNECT_SAME_PROCESS|, - // |*platform_handle| is set to a suitable native handle connecting the two - // parties. - virtual Result Connect(const ConnectionIdentifier& connection_id, - ProcessIdentifier* peer_process_identifier, - bool* is_first, - embedder::ScopedPlatformHandle* platform_handle) = 0; - - protected: - // |platform_support| must be valid and remain alive until after |Shutdown()| - // has completed. - explicit ConnectionManager(embedder::PlatformSupport* platform_support) - : platform_support_(platform_support) {} - - private: - embedder::PlatformSupport* const platform_support_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ConnectionManager); -}; - -// So logging macros and |DCHECK_EQ()|, etc. work. -MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<( - std::ostream& out, - ConnectionManager::Result result) { - return out << static_cast<int>(result); -} - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CONNECTION_MANAGER_H_ diff --git a/third_party/mojo/src/mojo/edk/system/connection_manager_messages.h b/third_party/mojo/src/mojo/edk/system/connection_manager_messages.h deleted file mode 100644 index 8ca7c82..0000000 --- a/third_party/mojo/src/mojo/edk/system/connection_manager_messages.h +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2015 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CONNECTION_MANAGER_MESSAGES_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CONNECTION_MANAGER_MESSAGES_H_ - -#include <string.h> - -#include "third_party/mojo/src/mojo/edk/system/process_identifier.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -struct ConnectionManagerAckSuccessConnectData { - // Set to the process identifier of the process that the receiver of this ack - // ack should connect to. - ProcessIdentifier peer_process_identifier; - - // Whether the receiver of this ack is the first party in the connection. This - // is typically used to decide whether the receiver should initiate the - // message (or data) pipe (i.e., allocate endpoint IDs, etc.). - bool is_first; -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CONNECTION_MANAGER_MESSAGES_H_ diff --git a/third_party/mojo/src/mojo/edk/system/connection_manager_unittest.cc b/third_party/mojo/src/mojo/edk/system/connection_manager_unittest.cc deleted file mode 100644 index 905193c..0000000 --- a/third_party/mojo/src/mojo/edk/system/connection_manager_unittest.cc +++ /dev/null @@ -1,688 +0,0 @@ -// Copyright 2015 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. - -// This is really a unit test for |MasterConnectionManager| and -// |SlaveConnectionManager| (since they need to be tested together). - -#include "third_party/mojo/src/mojo/edk/system/connection_manager.h" - -#include <stdint.h> - -#include <string> - -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/threading/thread_checker.h" -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/embedder/master_process_delegate.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" -#include "third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h" -#include "third_party/mojo/src/mojo/edk/embedder/slave_process_delegate.h" -#include "third_party/mojo/src/mojo/edk/system/master_connection_manager.h" -#include "third_party/mojo/src/mojo/edk/system/slave_connection_manager.h" -#include "third_party/mojo/src/mojo/edk/test/test_utils.h" - -namespace mojo { -namespace system { -namespace { - -bool ArePlatformHandlesConnected(const embedder::PlatformHandle& h1, - const embedder::PlatformHandle& h2) { - const uint32_t w1 = 0xdeadbeef; - size_t num_bytes = 0; - if (!mojo::test::BlockingWrite(h1, &w1, sizeof(w1), &num_bytes) || - num_bytes != sizeof(w1)) - return false; - uint32_t r = 0; - num_bytes = 0; - if (!mojo::test::BlockingRead(h2, &r, sizeof(r), &num_bytes) || - num_bytes != sizeof(r)) - return false; - if (r != w1) - return false; - - const uint32_t w2 = 0xfeedface; - num_bytes = 0; - if (!mojo::test::BlockingWrite(h1, &w2, sizeof(w2), &num_bytes) || - num_bytes != sizeof(w2)) - return false; - r = 0; - num_bytes = 0; - if (!mojo::test::BlockingRead(h2, &r, sizeof(r), &num_bytes) || - num_bytes != sizeof(r)) - return false; - if (r != w2) - return false; - - return true; -} - -bool IsValidSlaveProcessIdentifier(ProcessIdentifier process_identifier) { - return process_identifier != kInvalidProcessIdentifier && - process_identifier != kMasterProcessIdentifier; -} - -class TestSlaveInfo { - public: - explicit TestSlaveInfo(const std::string& name) : name_(name) {} - ~TestSlaveInfo() { CHECK(thread_checker_.CalledOnValidThread()); } - - const std::string& name() const { return name_; } - - private: - base::ThreadChecker thread_checker_; - std::string name_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(TestSlaveInfo); -}; - -// Connects the given |slave| (with the given |slave_process_delegate|) to the -// given master, creating and using a |TestSlaveInfo| with the given -// |slave_name|, and returns the process identifier for the slave. -ProcessIdentifier ConnectSlave( - MasterConnectionManager* master, - embedder::SlaveProcessDelegate* slave_process_delegate, - SlaveConnectionManager* slave, - const std::string& slave_name) { - embedder::PlatformChannelPair platform_channel_pair; - ProcessIdentifier slave_process_identifier = master->AddSlave( - new TestSlaveInfo(slave_name), platform_channel_pair.PassServerHandle()); - slave->Init(slave_process_delegate, platform_channel_pair.PassClientHandle()); - return slave_process_identifier; -} - -class MockMasterProcessDelegate : public embedder::MasterProcessDelegate { - public: - MockMasterProcessDelegate() - : current_run_loop_(), on_slave_disconnect_calls_(0) {} - ~MockMasterProcessDelegate() override {} - - void RunUntilNotified() { - CHECK(!current_run_loop_); - base::RunLoop run_loop; - current_run_loop_ = &run_loop; - run_loop.Run(); - current_run_loop_ = nullptr; - } - - unsigned on_slave_disconnect_calls() const { - return on_slave_disconnect_calls_; - } - const std::string& last_slave_disconnect_name() const { - return last_slave_disconnect_name_; - } - - // |embedder::MasterProcessDelegate| implementation: - void OnShutdownComplete() override { NOTREACHED(); } - - void OnSlaveDisconnect(embedder::SlaveInfo slave_info) override { - CHECK(thread_checker_.CalledOnValidThread()); - on_slave_disconnect_calls_++; - last_slave_disconnect_name_ = - static_cast<TestSlaveInfo*>(slave_info)->name(); - DVLOG(1) << "Disconnected from slave process " - << last_slave_disconnect_name_; - delete static_cast<TestSlaveInfo*>(slave_info); - - if (current_run_loop_) - current_run_loop_->Quit(); - } - - private: - base::ThreadChecker thread_checker_; - base::RunLoop* current_run_loop_; - - unsigned on_slave_disconnect_calls_; - std::string last_slave_disconnect_name_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(MockMasterProcessDelegate); -}; - -class MockSlaveProcessDelegate : public embedder::SlaveProcessDelegate { - public: - MockSlaveProcessDelegate() - : current_run_loop_(), on_master_disconnect_calls_(0) {} - ~MockSlaveProcessDelegate() override {} - - void RunUntilNotified() { - CHECK(!current_run_loop_); - base::RunLoop run_loop; - current_run_loop_ = &run_loop; - run_loop.Run(); - current_run_loop_ = nullptr; - } - - unsigned on_master_disconnect_calls() const { - return on_master_disconnect_calls_; - } - - // |embedder::SlaveProcessDelegate| implementation: - void OnShutdownComplete() override { NOTREACHED(); } - - void OnMasterDisconnect() override { - CHECK(thread_checker_.CalledOnValidThread()); - on_master_disconnect_calls_++; - DVLOG(1) << "Disconnected from master process"; - - if (current_run_loop_) - current_run_loop_->Quit(); - } - - private: - base::ThreadChecker thread_checker_; - base::RunLoop* current_run_loop_; - - unsigned on_master_disconnect_calls_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(MockSlaveProcessDelegate); -}; - -class ConnectionManagerTest : public testing::Test { - protected: - ConnectionManagerTest() {} - ~ConnectionManagerTest() override {} - - embedder::PlatformSupport* platform_support() { return &platform_support_; } - - base::MessageLoop& message_loop() { return message_loop_; } - MockMasterProcessDelegate& master_process_delegate() { - return master_process_delegate_; - } - - private: - embedder::SimplePlatformSupport platform_support_; - base::MessageLoop message_loop_; - MockMasterProcessDelegate master_process_delegate_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ConnectionManagerTest); -}; - -TEST_F(ConnectionManagerTest, BasicConnectSlaves) { - MasterConnectionManager master(platform_support()); - master.Init(&master_process_delegate()); - - MockSlaveProcessDelegate slave1_process_delegate; - SlaveConnectionManager slave1(platform_support()); - ProcessIdentifier slave1_id = - ConnectSlave(&master, &slave1_process_delegate, &slave1, "slave1"); - EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave1_id)); - - MockSlaveProcessDelegate slave2_process_delegate; - SlaveConnectionManager slave2(platform_support()); - ProcessIdentifier slave2_id = - ConnectSlave(&master, &slave2_process_delegate, &slave2, "slave2"); - EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave2_id)); - // TODO(vtl): If/when I add the ability to get one's own process identifier, - // there'll be more we can check. - EXPECT_NE(slave1_id, slave2_id); - - ConnectionIdentifier connection_id = master.GenerateConnectionIdentifier(); - EXPECT_TRUE(slave1.AllowConnect(connection_id)); - EXPECT_TRUE(slave2.AllowConnect(connection_id)); - - ProcessIdentifier peer1 = kInvalidProcessIdentifier; - bool is_first = false; - embedder::ScopedPlatformHandle h1; - EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION, - slave1.Connect(connection_id, &peer1, &is_first, &h1)); - EXPECT_EQ(slave2_id, peer1); - EXPECT_TRUE(is_first); - EXPECT_TRUE(h1.is_valid()); - ProcessIdentifier peer2 = kInvalidProcessIdentifier; - embedder::ScopedPlatformHandle h2; - EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION, - slave2.Connect(connection_id, &peer2, &is_first, &h2)); - EXPECT_EQ(slave1_id, peer2); - EXPECT_FALSE(is_first); - EXPECT_TRUE(h2.is_valid()); - - EXPECT_TRUE(ArePlatformHandlesConnected(h1.get(), h2.get())); - - // The process manager shouldn't have gotten any notifications yet. (Spin the - // message loop to make sure none were enqueued.) - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0u, master_process_delegate().on_slave_disconnect_calls()); - - slave1.Shutdown(); - - // |OnSlaveDisconnect()| should be called once. - master_process_delegate().RunUntilNotified(); - EXPECT_EQ(1u, master_process_delegate().on_slave_disconnect_calls()); - EXPECT_EQ("slave1", master_process_delegate().last_slave_disconnect_name()); - - slave2.Shutdown(); - - // |OnSlaveDisconnect()| should be called again. - master_process_delegate().RunUntilNotified(); - EXPECT_EQ(2u, master_process_delegate().on_slave_disconnect_calls()); - EXPECT_EQ("slave2", master_process_delegate().last_slave_disconnect_name()); - - master.Shutdown(); - - // None of the above should result in |OnMasterDisconnect()| being called. - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0u, slave1_process_delegate.on_master_disconnect_calls()); - EXPECT_EQ(0u, slave2_process_delegate.on_master_disconnect_calls()); -} - -TEST_F(ConnectionManagerTest, ShutdownMasterBeforeSlave) { - MasterConnectionManager master(platform_support()); - master.Init(&master_process_delegate()); - - MockSlaveProcessDelegate slave_process_delegate; - SlaveConnectionManager slave(platform_support()); - ProcessIdentifier slave_id = - ConnectSlave(&master, &slave_process_delegate, &slave, "slave"); - EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave_id)); - - // The process manager shouldn't have gotten any notifications yet. (Spin the - // message loop to make sure none were enqueued.) - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0u, master_process_delegate().on_slave_disconnect_calls()); - - master.Shutdown(); - - // |OnSlaveDisconnect()| should be called. - master_process_delegate().RunUntilNotified(); - EXPECT_EQ(1u, master_process_delegate().on_slave_disconnect_calls()); - EXPECT_EQ("slave", master_process_delegate().last_slave_disconnect_name()); - - // |OnMasterDisconnect()| should also be (or have been) called. - slave_process_delegate.RunUntilNotified(); - EXPECT_EQ(1u, slave_process_delegate.on_master_disconnect_calls()); - - slave.Shutdown(); -} - -TEST_F(ConnectionManagerTest, SlaveCancelConnect) { - MasterConnectionManager master(platform_support()); - master.Init(&master_process_delegate()); - - MockSlaveProcessDelegate slave1_process_delegate; - SlaveConnectionManager slave1(platform_support()); - ProcessIdentifier slave1_id = - ConnectSlave(&master, &slave1_process_delegate, &slave1, "slave1"); - EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave1_id)); - - MockSlaveProcessDelegate slave2_process_delegate; - SlaveConnectionManager slave2(platform_support()); - ProcessIdentifier slave2_id = - ConnectSlave(&master, &slave2_process_delegate, &slave2, "slave2"); - EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave2_id)); - EXPECT_NE(slave1_id, slave2_id); - - ConnectionIdentifier connection_id = master.GenerateConnectionIdentifier(); - EXPECT_TRUE(slave1.AllowConnect(connection_id)); - EXPECT_TRUE(slave2.AllowConnect(connection_id)); - - EXPECT_TRUE(slave1.CancelConnect(connection_id)); - ProcessIdentifier peer2 = kInvalidProcessIdentifier; - bool is_first = false; - embedder::ScopedPlatformHandle h2; - EXPECT_EQ(ConnectionManager::Result::FAILURE, - slave2.Connect(connection_id, &peer2, &is_first, &h2)); - EXPECT_EQ(kInvalidProcessIdentifier, peer2); - EXPECT_FALSE(is_first); - EXPECT_FALSE(h2.is_valid()); - - slave1.Shutdown(); - slave2.Shutdown(); - master.Shutdown(); -} - -// Tests that pending connections are removed on error. -TEST_F(ConnectionManagerTest, ErrorRemovePending) { - MasterConnectionManager master(platform_support()); - master.Init(&master_process_delegate()); - - MockSlaveProcessDelegate slave1_process_delegate; - SlaveConnectionManager slave1(platform_support()); - ProcessIdentifier slave1_id = - ConnectSlave(&master, &slave1_process_delegate, &slave1, "slave1"); - EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave1_id)); - - MockSlaveProcessDelegate slave2_process_delegate; - SlaveConnectionManager slave2(platform_support()); - ProcessIdentifier slave2_id = - ConnectSlave(&master, &slave2_process_delegate, &slave2, "slave2"); - EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave2_id)); - EXPECT_NE(slave1_id, slave2_id); - - ConnectionIdentifier connection_id = master.GenerateConnectionIdentifier(); - EXPECT_TRUE(slave1.AllowConnect(connection_id)); - EXPECT_TRUE(slave2.AllowConnect(connection_id)); - - slave1.Shutdown(); - - // |OnSlaveDisconnect()| should be called. After it's called, this means that - // the disconnect has been detected and handled, including the removal of the - // pending connection. - master_process_delegate().RunUntilNotified(); - EXPECT_EQ(1u, master_process_delegate().on_slave_disconnect_calls()); - - ProcessIdentifier peer2 = kInvalidProcessIdentifier; - bool is_first = false; - embedder::ScopedPlatformHandle h2; - EXPECT_EQ(ConnectionManager::Result::FAILURE, - slave2.Connect(connection_id, &peer2, &is_first, &h2)); - EXPECT_EQ(kInvalidProcessIdentifier, peer2); - EXPECT_FALSE(is_first); - EXPECT_FALSE(h2.is_valid()); - - slave2.Shutdown(); - master.Shutdown(); -} - -TEST_F(ConnectionManagerTest, ConnectSlaveToSelf) { - MasterConnectionManager master(platform_support()); - master.Init(&master_process_delegate()); - - MockSlaveProcessDelegate slave_process_delegate; - SlaveConnectionManager slave(platform_support()); - ProcessIdentifier slave_id = - ConnectSlave(&master, &slave_process_delegate, &slave, "slave"); - EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave_id)); - - ConnectionIdentifier connection_id = master.GenerateConnectionIdentifier(); - EXPECT_TRUE(slave.AllowConnect(connection_id)); - EXPECT_TRUE(slave.AllowConnect(connection_id)); - - ProcessIdentifier peer1 = kInvalidProcessIdentifier; - bool is_first = false; - embedder::ScopedPlatformHandle h1; - EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_SAME_PROCESS, - slave.Connect(connection_id, &peer1, &is_first, &h1)); - EXPECT_EQ(slave_id, peer1); - EXPECT_TRUE(is_first); - EXPECT_FALSE(h1.is_valid()); - ProcessIdentifier peer2 = kInvalidProcessIdentifier; - embedder::ScopedPlatformHandle h2; - EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_SAME_PROCESS, - slave.Connect(connection_id, &peer2, &is_first, &h2)); - EXPECT_EQ(slave_id, peer2); - EXPECT_FALSE(is_first); - EXPECT_FALSE(h2.is_valid()); - - slave.Shutdown(); - master.Shutdown(); -} - -TEST_F(ConnectionManagerTest, ConnectSlavesTwice) { - MasterConnectionManager master(platform_support()); - master.Init(&master_process_delegate()); - - MockSlaveProcessDelegate slave1_process_delegate; - SlaveConnectionManager slave1(platform_support()); - ProcessIdentifier slave1_id = - ConnectSlave(&master, &slave1_process_delegate, &slave1, "slave1"); - EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave1_id)); - - MockSlaveProcessDelegate slave2_process_delegate; - SlaveConnectionManager slave2(platform_support()); - ProcessIdentifier slave2_id = - ConnectSlave(&master, &slave2_process_delegate, &slave2, "slave2"); - EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave2_id)); - EXPECT_NE(slave1_id, slave2_id); - - ConnectionIdentifier connection_id = master.GenerateConnectionIdentifier(); - EXPECT_TRUE(slave1.AllowConnect(connection_id)); - EXPECT_TRUE(slave2.AllowConnect(connection_id)); - - ProcessIdentifier peer1 = kInvalidProcessIdentifier; - bool is_first = false; - embedder::ScopedPlatformHandle h1; - EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION, - slave1.Connect(connection_id, &peer1, &is_first, &h1)); - EXPECT_EQ(slave2_id, peer1); - EXPECT_TRUE(is_first); - ProcessIdentifier peer2 = kInvalidProcessIdentifier; - embedder::ScopedPlatformHandle h2; - EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION, - slave2.Connect(connection_id, &peer2, &is_first, &h2)); - EXPECT_EQ(slave1_id, peer2); - EXPECT_FALSE(is_first); - - EXPECT_TRUE(ArePlatformHandlesConnected(h1.get(), h2.get())); - - // TODO(vtl): Currently, the master doesn't detect the case of connecting a - // pair of slaves that are already connected. (Doing so would require more - // careful tracking and is prone to races -- especially if we want slaves to - // be able to tear down no-longer-needed connections.) But the slaves should - // be able to do the tracking themselves (using the peer process identifiers). - connection_id = master.GenerateConnectionIdentifier(); - EXPECT_TRUE(slave1.AllowConnect(connection_id)); - EXPECT_TRUE(slave2.AllowConnect(connection_id)); - - h1.reset(); - h2.reset(); - ProcessIdentifier second_peer2 = kInvalidProcessIdentifier; - EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_REUSE_CONNECTION, - slave2.Connect(connection_id, &second_peer2, &is_first, &h2)); - EXPECT_EQ(peer2, second_peer2); - EXPECT_TRUE(is_first); - EXPECT_FALSE(h2.is_valid()); - ProcessIdentifier second_peer1 = kInvalidProcessIdentifier; - EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_REUSE_CONNECTION, - slave1.Connect(connection_id, &second_peer1, &is_first, &h1)); - EXPECT_EQ(peer1, second_peer1); - EXPECT_FALSE(is_first); - EXPECT_FALSE(h1.is_valid()); - - slave2.Shutdown(); - slave1.Shutdown(); - master.Shutdown(); -} - -TEST_F(ConnectionManagerTest, OverlappingSlaveConnects) { - MasterConnectionManager master(platform_support()); - master.Init(&master_process_delegate()); - - MockSlaveProcessDelegate slave1_process_delegate; - SlaveConnectionManager slave1(platform_support()); - ProcessIdentifier slave1_id = - ConnectSlave(&master, &slave1_process_delegate, &slave1, "slave1"); - EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave1_id)); - - MockSlaveProcessDelegate slave2_process_delegate; - SlaveConnectionManager slave2(platform_support()); - ProcessIdentifier slave2_id = - ConnectSlave(&master, &slave2_process_delegate, &slave2, "slave2"); - EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave2_id)); - EXPECT_NE(slave1_id, slave2_id); - - ConnectionIdentifier connection_id1 = master.GenerateConnectionIdentifier(); - EXPECT_TRUE(slave1.AllowConnect(connection_id1)); - EXPECT_TRUE(slave2.AllowConnect(connection_id1)); - - ConnectionIdentifier connection_id2 = master.GenerateConnectionIdentifier(); - EXPECT_TRUE(slave1.AllowConnect(connection_id2)); - EXPECT_TRUE(slave2.AllowConnect(connection_id2)); - - ProcessIdentifier peer1 = kInvalidProcessIdentifier; - bool is_first = false; - embedder::ScopedPlatformHandle h1; - EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION, - slave1.Connect(connection_id1, &peer1, &is_first, &h1)); - EXPECT_EQ(slave2_id, peer1); - EXPECT_TRUE(is_first); - ProcessIdentifier peer2 = kInvalidProcessIdentifier; - embedder::ScopedPlatformHandle h2; - EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION, - slave2.Connect(connection_id2, &peer2, &is_first, &h2)); - EXPECT_EQ(slave1_id, peer2); - EXPECT_TRUE(is_first); - - EXPECT_TRUE(ArePlatformHandlesConnected(h1.get(), h2.get())); - - h1.reset(); - h2.reset(); - ProcessIdentifier second_peer1 = kInvalidProcessIdentifier; - EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_REUSE_CONNECTION, - slave1.Connect(connection_id2, &second_peer1, &is_first, &h1)); - EXPECT_EQ(peer1, second_peer1); - EXPECT_FALSE(is_first); - EXPECT_FALSE(h1.is_valid()); - ProcessIdentifier second_peer2 = kInvalidProcessIdentifier; - EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_REUSE_CONNECTION, - slave2.Connect(connection_id1, &second_peer2, &is_first, &h2)); - EXPECT_EQ(peer2, second_peer2); - EXPECT_FALSE(is_first); - EXPECT_FALSE(h2.is_valid()); - - slave2.Shutdown(); - slave1.Shutdown(); - master.Shutdown(); -} - -TEST_F(ConnectionManagerTest, ConnectMasterToSlave) { - MasterConnectionManager master(platform_support()); - master.Init(&master_process_delegate()); - - MockSlaveProcessDelegate slave_process_delegate; - SlaveConnectionManager slave(platform_support()); - ProcessIdentifier slave_id = - ConnectSlave(&master, &slave_process_delegate, &slave, "slave"); - EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave_id)); - - ConnectionIdentifier connection_id = master.GenerateConnectionIdentifier(); - EXPECT_TRUE(master.AllowConnect(connection_id)); - EXPECT_TRUE(slave.AllowConnect(connection_id)); - - ProcessIdentifier master_peer = kInvalidProcessIdentifier; - bool is_first = false; - embedder::ScopedPlatformHandle master_h; - EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION, - master.Connect(connection_id, &master_peer, &is_first, &master_h)); - EXPECT_EQ(slave_id, master_peer); - EXPECT_TRUE(is_first); - EXPECT_TRUE(master_h.is_valid()); - ProcessIdentifier slave_peer = kInvalidProcessIdentifier; - embedder::ScopedPlatformHandle slave_h; - EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION, - slave.Connect(connection_id, &slave_peer, &is_first, &slave_h)); - EXPECT_EQ(kMasterProcessIdentifier, slave_peer); - EXPECT_FALSE(is_first); - EXPECT_TRUE(slave_h.is_valid()); - - EXPECT_TRUE(ArePlatformHandlesConnected(master_h.get(), slave_h.get())); - - slave.Shutdown(); - master.Shutdown(); -} - -TEST_F(ConnectionManagerTest, ConnectMasterToSelf) { - MasterConnectionManager master(platform_support()); - master.Init(&master_process_delegate()); - - ConnectionIdentifier connection_id = master.GenerateConnectionIdentifier(); - EXPECT_TRUE(master.AllowConnect(connection_id)); - EXPECT_TRUE(master.AllowConnect(connection_id)); - - ProcessIdentifier peer1 = kInvalidProcessIdentifier; - bool is_first = false; - embedder::ScopedPlatformHandle h1; - EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_SAME_PROCESS, - master.Connect(connection_id, &peer1, &is_first, &h1)); - EXPECT_EQ(kMasterProcessIdentifier, peer1); - EXPECT_TRUE(is_first); - EXPECT_FALSE(h1.is_valid()); - ProcessIdentifier peer2 = kInvalidProcessIdentifier; - embedder::ScopedPlatformHandle h2; - EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_SAME_PROCESS, - master.Connect(connection_id, &peer2, &is_first, &h2)); - EXPECT_EQ(kMasterProcessIdentifier, peer2); - EXPECT_FALSE(is_first); - EXPECT_FALSE(h2.is_valid()); - - EXPECT_EQ(peer1, peer2); - - master.Shutdown(); -} - -TEST_F(ConnectionManagerTest, MasterCancelConnect) { - MasterConnectionManager master(platform_support()); - master.Init(&master_process_delegate()); - - MockSlaveProcessDelegate slave_process_delegate; - SlaveConnectionManager slave(platform_support()); - ProcessIdentifier slave_id = - ConnectSlave(&master, &slave_process_delegate, &slave, "slave"); - EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave_id)); - - ConnectionIdentifier connection_id = master.GenerateConnectionIdentifier(); - EXPECT_TRUE(master.AllowConnect(connection_id)); - EXPECT_TRUE(slave.AllowConnect(connection_id)); - - EXPECT_TRUE(master.CancelConnect(connection_id)); - ProcessIdentifier peer = kInvalidProcessIdentifier; - bool is_first = false; - embedder::ScopedPlatformHandle h; - EXPECT_EQ(ConnectionManager::Result::FAILURE, - slave.Connect(connection_id, &peer, &is_first, &h)); - EXPECT_EQ(kInvalidProcessIdentifier, peer); - EXPECT_FALSE(is_first); - EXPECT_FALSE(h.is_valid()); - - slave.Shutdown(); - master.Shutdown(); -} - -TEST_F(ConnectionManagerTest, AddSlaveThenImmediateShutdown) { - MasterConnectionManager master(platform_support()); - master.Init(&master_process_delegate()); - - MockSlaveProcessDelegate slave_process_delegate; - SlaveConnectionManager slave(platform_support()); - embedder::PlatformChannelPair platform_channel_pair; - ProcessIdentifier slave_id = master.AddSlave( - new TestSlaveInfo("slave"), platform_channel_pair.PassServerHandle()); - master.Shutdown(); - EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave_id)); - // Since we never initialized |slave|, we don't have to shut it down. -} - -TEST_F(ConnectionManagerTest, AddSlaveAndBootstrap) { - MasterConnectionManager master(platform_support()); - master.Init(&master_process_delegate()); - - embedder::PlatformChannelPair platform_channel_pair; - ConnectionIdentifier connection_id = master.GenerateConnectionIdentifier(); - ProcessIdentifier slave_id = master.AddSlaveAndBootstrap( - new TestSlaveInfo("slave"), platform_channel_pair.PassServerHandle(), - connection_id); - EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave_id)); - - embedder::ScopedPlatformHandle h1; - ProcessIdentifier master_peer = kInvalidProcessIdentifier; - bool is_first = false; - EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION, - master.Connect(connection_id, &master_peer, &is_first, &h1)); - EXPECT_EQ(slave_id, master_peer); - EXPECT_TRUE(is_first); - EXPECT_TRUE(h1.is_valid()); - - // We can delay creating/initializing |slave| for quite a while. - MockSlaveProcessDelegate slave_process_delegate; - SlaveConnectionManager slave(platform_support()); - slave.Init(&slave_process_delegate, platform_channel_pair.PassClientHandle()); - - ProcessIdentifier slave_peer = kInvalidProcessIdentifier; - embedder::ScopedPlatformHandle h2; - EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION, - slave.Connect(connection_id, &slave_peer, &is_first, &h2)); - EXPECT_EQ(kMasterProcessIdentifier, slave_peer); - EXPECT_FALSE(is_first); - - EXPECT_TRUE(ArePlatformHandlesConnected(h1.get(), h2.get())); - - slave.Shutdown(); - master.Shutdown(); -} - -// TODO(vtl): More shutdown cases for |AddSlaveAndBootstrap()|? - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/core.cc b/third_party/mojo/src/mojo/edk/system/core.cc deleted file mode 100644 index b7f875e..0000000 --- a/third_party/mojo/src/mojo/edk/system/core.cc +++ /dev/null @@ -1,689 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/core.h" - -#include <utility> -#include <vector> - -#include "base/containers/stack_container.h" -#include "base/logging.h" -#include "base/time/time.h" -#include "mojo/public/c/system/macros.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_shared_buffer.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_support.h" -#include "third_party/mojo/src/mojo/edk/system/async_waiter.h" -#include "third_party/mojo/src/mojo/edk/system/configuration.h" -#include "third_party/mojo/src/mojo/edk/system/data_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/handle_signals_state.h" -#include "third_party/mojo/src/mojo/edk/system/memory.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/wait_set_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/waiter.h" - -namespace mojo { -namespace system { - -// Implementation notes -// -// Mojo primitives are implemented by the singleton |Core| object. Most calls -// are for a "primary" handle (the first argument). |Core::GetDispatcher()| is -// used to look up a |Dispatcher| object for a given handle. That object -// implements most primitives for that object. The wait primitives are not -// attached to objects and are implemented by |Core| itself. -// -// Some objects have multiple handles associated to them, e.g., message pipes -// (which have two). In such a case, there is still a |Dispatcher| (e.g., -// |MessagePipeDispatcher|) for each handle, with each handle having a strong -// reference to the common "secondary" object (e.g., |MessagePipe|). This -// secondary object does NOT have any references to the |Dispatcher|s (even if -// it did, it wouldn't be able to do anything with them due to lock order -// requirements -- see below). -// -// Waiting is implemented by having the thread that wants to wait call the -// |Dispatcher|s for the handles that it wants to wait on with a |Waiter| -// object; this |Waiter| object may be created on the stack of that thread or be -// kept in thread local storage for that thread (TODO(vtl): future improvement). -// The |Dispatcher| then adds the |Waiter| to an |AwakableList| that's either -// owned by that |Dispatcher| (see |SimpleDispatcher|) or by a secondary object -// (e.g., |MessagePipe|). To signal/wake a |Waiter|, the object in question -- -// either a |SimpleDispatcher| or a secondary object -- talks to its -// |AwakableList|. - -// Thread-safety notes -// -// Mojo primitives calls are thread-safe. We achieve this with relatively -// fine-grained locking. There is a global handle table lock. This lock should -// be held as briefly as possible (TODO(vtl): a future improvement would be to -// switch it to a reader-writer lock). Each |Dispatcher| object then has a lock -// (which subclasses can use to protect their data). -// -// The lock ordering is as follows: -// 1. global handle table lock, global mapping table lock -// 2. |Dispatcher| locks -// 3. secondary object locks -// ... -// INF. |Waiter| locks -// -// Notes: -// - While holding a |Dispatcher| lock, you may not unconditionally attempt -// to take another |Dispatcher| lock. (This has consequences on the -// concurrency semantics of |MojoWriteMessage()| when passing handles.) -// Doing so would lead to deadlock. -// - Locks at the "INF" level may not have any locks taken while they are -// held. - -// TODO(vtl): This should take a |scoped_ptr<PlatformSupport>| as a parameter. -Core::Core(embedder::PlatformSupport* platform_support) - : platform_support_(platform_support) { -} - -Core::~Core() { -} - -MojoHandle Core::AddDispatcher(const scoped_refptr<Dispatcher>& dispatcher) { - MutexLocker locker(&handle_table_mutex_); - return handle_table_.AddDispatcher(dispatcher); -} - -scoped_refptr<Dispatcher> Core::GetDispatcher(MojoHandle handle) { - if (handle == MOJO_HANDLE_INVALID) - return nullptr; - - MutexLocker locker(&handle_table_mutex_); - return handle_table_.GetDispatcher(handle); -} - -MojoResult Core::AsyncWait(MojoHandle handle, - MojoHandleSignals signals, - const base::Callback<void(MojoResult)>& callback) { - scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle); - DCHECK(dispatcher); - - scoped_ptr<AsyncWaiter> waiter = make_scoped_ptr(new AsyncWaiter(callback)); - MojoResult rv = dispatcher->AddAwakable(waiter.get(), signals, 0, nullptr); - if (rv == MOJO_RESULT_OK) - ignore_result(waiter.release()); - return rv; -} - -MojoTimeTicks Core::GetTimeTicksNow() { - return base::TimeTicks::Now().ToInternalValue(); -} - -MojoResult Core::Close(MojoHandle handle) { - if (handle == MOJO_HANDLE_INVALID) - return MOJO_RESULT_INVALID_ARGUMENT; - - scoped_refptr<Dispatcher> dispatcher; - { - MutexLocker locker(&handle_table_mutex_); - MojoResult result = - handle_table_.GetAndRemoveDispatcher(handle, &dispatcher); - if (result != MOJO_RESULT_OK) - return result; - } - - // The dispatcher doesn't have a say in being closed, but gets notified of it. - // Note: This is done outside of |handle_table_mutex_|. As a result, there's a - // race condition that the dispatcher must handle; see the comment in - // |Dispatcher| in dispatcher.h. - return dispatcher->Close(); -} - -MojoResult Core::Wait(MojoHandle handle, - MojoHandleSignals signals, - MojoDeadline deadline, - UserPointer<MojoHandleSignalsState> signals_state) { - uint32_t unused = static_cast<uint32_t>(-1); - HandleSignalsState hss; - MojoResult rv = WaitManyInternal(&handle, &signals, 1, deadline, &unused, - signals_state.IsNull() ? nullptr : &hss); - if (rv != MOJO_RESULT_INVALID_ARGUMENT && !signals_state.IsNull()) - signals_state.Put(hss); - return rv; -} - -MojoResult Core::WaitMany(UserPointer<const MojoHandle> handles, - UserPointer<const MojoHandleSignals> signals, - uint32_t num_handles, - MojoDeadline deadline, - UserPointer<uint32_t> result_index, - UserPointer<MojoHandleSignalsState> signals_states) { - if (num_handles < 1) - return MOJO_RESULT_INVALID_ARGUMENT; - if (num_handles > GetConfiguration().max_wait_many_num_handles) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - - UserPointer<const MojoHandle>::Reader handles_reader(handles, num_handles); - UserPointer<const MojoHandleSignals>::Reader signals_reader(signals, - num_handles); - uint32_t index = static_cast<uint32_t>(-1); - MojoResult rv; - if (signals_states.IsNull()) { - rv = WaitManyInternal(handles_reader.GetPointer(), - signals_reader.GetPointer(), num_handles, deadline, - &index, nullptr); - } else { - UserPointer<MojoHandleSignalsState>::Writer signals_states_writer( - signals_states, num_handles); - // Note: The |reinterpret_cast| is safe, since |HandleSignalsState| is a - // subclass of |MojoHandleSignalsState| that doesn't add any data members. - rv = WaitManyInternal(handles_reader.GetPointer(), - signals_reader.GetPointer(), num_handles, deadline, - &index, reinterpret_cast<HandleSignalsState*>( - signals_states_writer.GetPointer())); - if (rv != MOJO_RESULT_INVALID_ARGUMENT) - signals_states_writer.Commit(); - } - if (index != static_cast<uint32_t>(-1) && !result_index.IsNull()) - result_index.Put(index); - return rv; -} - -MojoResult Core::CreateWaitSet(UserPointer<MojoHandle> wait_set_handle) { - if (wait_set_handle.IsNull()) - return MOJO_RESULT_INVALID_ARGUMENT; - - scoped_refptr<WaitSetDispatcher> dispatcher = new WaitSetDispatcher(); - MojoHandle h = AddDispatcher(dispatcher); - if (h == MOJO_HANDLE_INVALID) { - LOG(ERROR) << "Handle table full"; - dispatcher->Close(); - return MOJO_RESULT_RESOURCE_EXHAUSTED; - } - - wait_set_handle.Put(h); - return MOJO_RESULT_OK; -} - -MojoResult Core::AddHandle(MojoHandle wait_set_handle, - MojoHandle handle, - MojoHandleSignals signals) { - scoped_refptr<Dispatcher> wait_set_dispatcher(GetDispatcher(wait_set_handle)); - if (!wait_set_dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - scoped_refptr<Dispatcher> dispatcher(GetDispatcher(handle)); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - return wait_set_dispatcher->AddWaitingDispatcher(dispatcher, signals, handle); -} - -MojoResult Core::RemoveHandle(MojoHandle wait_set_handle, - MojoHandle handle) { - scoped_refptr<Dispatcher> wait_set_dispatcher(GetDispatcher(wait_set_handle)); - if (!wait_set_dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - scoped_refptr<Dispatcher> dispatcher(GetDispatcher(handle)); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - return wait_set_dispatcher->RemoveWaitingDispatcher(dispatcher); -} - -MojoResult Core::GetReadyHandles( - MojoHandle wait_set_handle, - UserPointer<uint32_t> count, - UserPointer<MojoHandle> handles, - UserPointer<MojoResult> results, - UserPointer<MojoHandleSignalsState> signals_states) { - if (count.IsNull() || !count.Get() || handles.IsNull() || results.IsNull()) - return MOJO_RESULT_INVALID_ARGUMENT; - - scoped_refptr<Dispatcher> wait_set_dispatcher(GetDispatcher(wait_set_handle)); - if (!wait_set_dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - const uint32_t in_count = count.Get(); - DispatcherVector awoken_dispatchers; - base::StackVector<uintptr_t, 16> contexts; - contexts->assign(in_count, MOJO_HANDLE_INVALID); - - MojoResult result = wait_set_dispatcher->GetReadyDispatchers( - count, &awoken_dispatchers, results, MakeUserPointer(contexts->data())); - - const uint32_t out_count = count.Get(); - for (uint32_t i = 0; i < out_count; i++) { - handles.At(i).Put(static_cast<MojoHandle>(contexts[i])); - if (!signals_states.IsNull()) - signals_states.At(i).Put(awoken_dispatchers[i]->GetHandleSignalsState()); - } - - return result; -} - -MojoResult Core::CreateMessagePipe( - UserPointer<const MojoCreateMessagePipeOptions> options, - UserPointer<MojoHandle> message_pipe_handle0, - UserPointer<MojoHandle> message_pipe_handle1) { - MojoCreateMessagePipeOptions validated_options = {}; - MojoResult result = - MessagePipeDispatcher::ValidateCreateOptions(options, &validated_options); - if (result != MOJO_RESULT_OK) - return result; - - scoped_refptr<MessagePipeDispatcher> dispatcher0 = - MessagePipeDispatcher::Create(validated_options); - scoped_refptr<MessagePipeDispatcher> dispatcher1 = - MessagePipeDispatcher::Create(validated_options); - - std::pair<MojoHandle, MojoHandle> handle_pair; - { - MutexLocker locker(&handle_table_mutex_); - handle_pair = handle_table_.AddDispatcherPair(dispatcher0, dispatcher1); - } - if (handle_pair.first == MOJO_HANDLE_INVALID) { - DCHECK_EQ(handle_pair.second, MOJO_HANDLE_INVALID); - LOG(ERROR) << "Handle table full"; - dispatcher0->Close(); - dispatcher1->Close(); - return MOJO_RESULT_RESOURCE_EXHAUSTED; - } - - scoped_refptr<MessagePipe> message_pipe(MessagePipe::CreateLocalLocal()); - dispatcher0->Init(message_pipe, 0); - dispatcher1->Init(message_pipe, 1); - - message_pipe_handle0.Put(handle_pair.first); - message_pipe_handle1.Put(handle_pair.second); - return MOJO_RESULT_OK; -} - -// Implementation note: To properly cancel waiters and avoid other races, this -// does not transfer dispatchers from one handle to another, even when sending a -// message in-process. Instead, it must transfer the "contents" of the -// dispatcher to a new dispatcher, and then close the old dispatcher. If this -// isn't done, in the in-process case, calls on the old handle may complete -// after the the message has been received and a new handle created (and -// possibly even after calls have been made on the new handle). -MojoResult Core::WriteMessage(MojoHandle message_pipe_handle, - UserPointer<const void> bytes, - uint32_t num_bytes, - UserPointer<const MojoHandle> handles, - uint32_t num_handles, - MojoWriteMessageFlags flags) { - scoped_refptr<Dispatcher> dispatcher(GetDispatcher(message_pipe_handle)); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - // Easy case: not sending any handles. - if (num_handles == 0) - return dispatcher->WriteMessage(bytes, num_bytes, nullptr, flags); - - // We have to handle |handles| here, since we have to mark them busy in the - // global handle table. We can't delegate this to the dispatcher, since the - // handle table lock must be acquired before the dispatcher lock. - // - // (This leads to an oddity: |handles|/|num_handles| are always verified for - // validity, even for dispatchers that don't support |WriteMessage()| and will - // simply return failure unconditionally. It also breaks the usual - // left-to-right verification order of arguments.) - if (num_handles > GetConfiguration().max_message_num_handles) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - - UserPointer<const MojoHandle>::Reader handles_reader(handles, num_handles); - - // We'll need to hold on to the dispatchers so that we can pass them on to - // |WriteMessage()| and also so that we can unlock their locks afterwards - // without accessing the handle table. These can be dumb pointers, since their - // entries in the handle table won't get removed (since they'll be marked as - // busy). - std::vector<DispatcherTransport> transports(num_handles); - - // When we pass handles, we have to try to take all their dispatchers' locks - // and mark the handles as busy. If the call succeeds, we then remove the - // handles from the handle table. - { - MutexLocker locker(&handle_table_mutex_); - MojoResult result = handle_table_.MarkBusyAndStartTransport( - message_pipe_handle, handles_reader.GetPointer(), num_handles, - &transports); - if (result != MOJO_RESULT_OK) - return result; - } - - MojoResult rv = - dispatcher->WriteMessage(bytes, num_bytes, &transports, flags); - - // We need to release the dispatcher locks before we take the handle table - // lock. - for (uint32_t i = 0; i < num_handles; i++) - transports[i].End(); - - { - MutexLocker locker(&handle_table_mutex_); - if (rv == MOJO_RESULT_OK) { - handle_table_.RemoveBusyHandles(handles_reader.GetPointer(), num_handles); - } else { - handle_table_.RestoreBusyHandles(handles_reader.GetPointer(), - num_handles); - } - } - - return rv; -} - -MojoResult Core::ReadMessage(MojoHandle message_pipe_handle, - UserPointer<void> bytes, - UserPointer<uint32_t> num_bytes, - UserPointer<MojoHandle> handles, - UserPointer<uint32_t> num_handles, - MojoReadMessageFlags flags) { - scoped_refptr<Dispatcher> dispatcher(GetDispatcher(message_pipe_handle)); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - uint32_t num_handles_value = num_handles.IsNull() ? 0 : num_handles.Get(); - - MojoResult rv; - if (num_handles_value == 0) { - // Easy case: won't receive any handles. - rv = dispatcher->ReadMessage(bytes, num_bytes, nullptr, &num_handles_value, - flags); - } else { - DispatcherVector dispatchers; - rv = dispatcher->ReadMessage(bytes, num_bytes, &dispatchers, - &num_handles_value, flags); - if (!dispatchers.empty()) { - DCHECK_EQ(rv, MOJO_RESULT_OK); - DCHECK(!num_handles.IsNull()); - DCHECK_LE(dispatchers.size(), static_cast<size_t>(num_handles_value)); - - bool success; - UserPointer<MojoHandle>::Writer handles_writer(handles, - dispatchers.size()); - { - MutexLocker locker(&handle_table_mutex_); - success = handle_table_.AddDispatcherVector( - dispatchers, handles_writer.GetPointer()); - } - if (success) { - handles_writer.Commit(); - } else { - LOG(ERROR) << "Received message with " << dispatchers.size() - << " handles, but handle table full"; - // Close dispatchers (outside the lock). - for (size_t i = 0; i < dispatchers.size(); i++) { - if (dispatchers[i]) - dispatchers[i]->Close(); - } - if (rv == MOJO_RESULT_OK) - rv = MOJO_RESULT_RESOURCE_EXHAUSTED; - } - } - } - - if (!num_handles.IsNull()) - num_handles.Put(num_handles_value); - return rv; -} - -MojoResult Core::CreateDataPipe( - UserPointer<const MojoCreateDataPipeOptions> options, - UserPointer<MojoHandle> data_pipe_producer_handle, - UserPointer<MojoHandle> data_pipe_consumer_handle) { - MojoCreateDataPipeOptions validated_options = {}; - MojoResult result = - DataPipe::ValidateCreateOptions(options, &validated_options); - if (result != MOJO_RESULT_OK) - return result; - - scoped_refptr<DataPipeProducerDispatcher> producer_dispatcher = - DataPipeProducerDispatcher::Create(); - scoped_refptr<DataPipeConsumerDispatcher> consumer_dispatcher = - DataPipeConsumerDispatcher::Create(); - - std::pair<MojoHandle, MojoHandle> handle_pair; - { - MutexLocker locker(&handle_table_mutex_); - handle_pair = handle_table_.AddDispatcherPair(producer_dispatcher, - consumer_dispatcher); - } - if (handle_pair.first == MOJO_HANDLE_INVALID) { - DCHECK_EQ(handle_pair.second, MOJO_HANDLE_INVALID); - LOG(ERROR) << "Handle table full"; - producer_dispatcher->Close(); - consumer_dispatcher->Close(); - return MOJO_RESULT_RESOURCE_EXHAUSTED; - } - DCHECK_NE(handle_pair.second, MOJO_HANDLE_INVALID); - - scoped_refptr<DataPipe> data_pipe(DataPipe::CreateLocal(validated_options)); - producer_dispatcher->Init(data_pipe); - consumer_dispatcher->Init(data_pipe); - - data_pipe_producer_handle.Put(handle_pair.first); - data_pipe_consumer_handle.Put(handle_pair.second); - return MOJO_RESULT_OK; -} - -MojoResult Core::WriteData(MojoHandle data_pipe_producer_handle, - UserPointer<const void> elements, - UserPointer<uint32_t> num_bytes, - MojoWriteDataFlags flags) { - scoped_refptr<Dispatcher> dispatcher( - GetDispatcher(data_pipe_producer_handle)); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - return dispatcher->WriteData(elements, num_bytes, flags); -} - -MojoResult Core::BeginWriteData(MojoHandle data_pipe_producer_handle, - UserPointer<void*> buffer, - UserPointer<uint32_t> buffer_num_bytes, - MojoWriteDataFlags flags) { - scoped_refptr<Dispatcher> dispatcher( - GetDispatcher(data_pipe_producer_handle)); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - return dispatcher->BeginWriteData(buffer, buffer_num_bytes, flags); -} - -MojoResult Core::EndWriteData(MojoHandle data_pipe_producer_handle, - uint32_t num_bytes_written) { - scoped_refptr<Dispatcher> dispatcher( - GetDispatcher(data_pipe_producer_handle)); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - return dispatcher->EndWriteData(num_bytes_written); -} - -MojoResult Core::ReadData(MojoHandle data_pipe_consumer_handle, - UserPointer<void> elements, - UserPointer<uint32_t> num_bytes, - MojoReadDataFlags flags) { - scoped_refptr<Dispatcher> dispatcher( - GetDispatcher(data_pipe_consumer_handle)); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - return dispatcher->ReadData(elements, num_bytes, flags); -} - -MojoResult Core::BeginReadData(MojoHandle data_pipe_consumer_handle, - UserPointer<const void*> buffer, - UserPointer<uint32_t> buffer_num_bytes, - MojoReadDataFlags flags) { - scoped_refptr<Dispatcher> dispatcher( - GetDispatcher(data_pipe_consumer_handle)); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - return dispatcher->BeginReadData(buffer, buffer_num_bytes, flags); -} - -MojoResult Core::EndReadData(MojoHandle data_pipe_consumer_handle, - uint32_t num_bytes_read) { - scoped_refptr<Dispatcher> dispatcher( - GetDispatcher(data_pipe_consumer_handle)); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - return dispatcher->EndReadData(num_bytes_read); -} - -MojoResult Core::CreateSharedBuffer( - UserPointer<const MojoCreateSharedBufferOptions> options, - uint64_t num_bytes, - UserPointer<MojoHandle> shared_buffer_handle) { - MojoCreateSharedBufferOptions validated_options = {}; - MojoResult result = SharedBufferDispatcher::ValidateCreateOptions( - options, &validated_options); - if (result != MOJO_RESULT_OK) - return result; - - scoped_refptr<SharedBufferDispatcher> dispatcher; - result = SharedBufferDispatcher::Create(platform_support_, validated_options, - num_bytes, &dispatcher); - if (result != MOJO_RESULT_OK) { - DCHECK(!dispatcher); - return result; - } - - MojoHandle h = AddDispatcher(dispatcher); - if (h == MOJO_HANDLE_INVALID) { - LOG(ERROR) << "Handle table full"; - dispatcher->Close(); - return MOJO_RESULT_RESOURCE_EXHAUSTED; - } - - shared_buffer_handle.Put(h); - return MOJO_RESULT_OK; -} - -MojoResult Core::DuplicateBufferHandle( - MojoHandle buffer_handle, - UserPointer<const MojoDuplicateBufferHandleOptions> options, - UserPointer<MojoHandle> new_buffer_handle) { - scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle)); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - // Don't verify |options| here; that's the dispatcher's job. - scoped_refptr<Dispatcher> new_dispatcher; - MojoResult result = - dispatcher->DuplicateBufferHandle(options, &new_dispatcher); - if (result != MOJO_RESULT_OK) - return result; - - MojoHandle new_handle = AddDispatcher(new_dispatcher); - if (new_handle == MOJO_HANDLE_INVALID) { - LOG(ERROR) << "Handle table full"; - dispatcher->Close(); - return MOJO_RESULT_RESOURCE_EXHAUSTED; - } - - new_buffer_handle.Put(new_handle); - return MOJO_RESULT_OK; -} - -MojoResult Core::MapBuffer(MojoHandle buffer_handle, - uint64_t offset, - uint64_t num_bytes, - UserPointer<void*> buffer, - MojoMapBufferFlags flags) { - scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle)); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - scoped_ptr<embedder::PlatformSharedBufferMapping> mapping; - MojoResult result = dispatcher->MapBuffer(offset, num_bytes, flags, &mapping); - if (result != MOJO_RESULT_OK) - return result; - - DCHECK(mapping); - void* address = mapping->GetBase(); - { - MutexLocker locker(&mapping_table_mutex_); - result = mapping_table_.AddMapping(std::move(mapping)); - } - if (result != MOJO_RESULT_OK) - return result; - - buffer.Put(address); - return MOJO_RESULT_OK; -} - -MojoResult Core::UnmapBuffer(UserPointer<void> buffer) { - MutexLocker locker(&mapping_table_mutex_); - return mapping_table_.RemoveMapping(buffer.GetPointerValue()); -} - -// Note: We allow |handles| to repeat the same handle multiple times, since -// different flags may be specified. -// TODO(vtl): This incurs a performance cost in |Remove()|. Analyze this -// more carefully and address it if necessary. -MojoResult Core::WaitManyInternal(const MojoHandle* handles, - const MojoHandleSignals* signals, - uint32_t num_handles, - MojoDeadline deadline, - uint32_t* result_index, - HandleSignalsState* signals_states) { - DCHECK_GT(num_handles, 0u); - DCHECK_EQ(*result_index, static_cast<uint32_t>(-1)); - - DispatcherVector dispatchers; - dispatchers.reserve(num_handles); - for (uint32_t i = 0; i < num_handles; i++) { - scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handles[i]); - if (!dispatcher) { - *result_index = i; - return MOJO_RESULT_INVALID_ARGUMENT; - } - dispatchers.push_back(dispatcher); - } - - // TODO(vtl): Should make the waiter live (permanently) in TLS. - Waiter waiter; - waiter.Init(); - - uint32_t i; - MojoResult rv = MOJO_RESULT_OK; - for (i = 0; i < num_handles; i++) { - rv = dispatchers[i]->AddAwakable( - &waiter, signals[i], i, signals_states ? &signals_states[i] : nullptr); - if (rv != MOJO_RESULT_OK) { - *result_index = i; - break; - } - } - uint32_t num_added = i; - - if (rv == MOJO_RESULT_ALREADY_EXISTS) { - rv = MOJO_RESULT_OK; // The i-th one is already "triggered". - } else if (rv == MOJO_RESULT_OK) { - uintptr_t uintptr_result = *result_index; - rv = waiter.Wait(deadline, &uintptr_result); - *result_index = static_cast<uint32_t>(uintptr_result); - } - - // Make sure no other dispatchers try to wake |waiter| for the current - // |Wait()|/|WaitMany()| call. (Only after doing this can |waiter| be - // destroyed, but this would still be required if the waiter were in TLS.) - for (i = 0; i < num_added; i++) { - dispatchers[i]->RemoveAwakable( - &waiter, signals_states ? &signals_states[i] : nullptr); - } - if (signals_states) { - for (; i < num_handles; i++) - signals_states[i] = dispatchers[i]->GetHandleSignalsState(); - } - - return rv; -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/core.h b/third_party/mojo/src/mojo/edk/system/core.h deleted file mode 100644 index 4d670d3..0000000 --- a/third_party/mojo/src/mojo/edk/system/core.h +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CORE_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CORE_H_ - -#include <stdint.h> - -#include "base/callback.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/public/c/system/buffer.h" -#include "mojo/public/c/system/data_pipe.h" -#include "mojo/public/c/system/message_pipe.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/handle_table.h" -#include "third_party/mojo/src/mojo/edk/system/mapping_table.h" -#include "third_party/mojo/src/mojo/edk/system/memory.h" -#include "third_party/mojo/src/mojo/edk/system/mutex.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { - -namespace embedder { -class PlatformSupport; -} - -namespace system { - -class Dispatcher; -struct HandleSignalsState; - -// |Core| is an object that implements the Mojo system calls. All public methods -// are thread-safe. -class MOJO_SYSTEM_IMPL_EXPORT Core { - public: - // --------------------------------------------------------------------------- - - // These methods are only to be used by via the embedder API (and internally): - - // |*platform_support| must outlive this object. - explicit Core(embedder::PlatformSupport* platform_support); - virtual ~Core(); - - // Adds |dispatcher| to the handle table, returning the handle for it. Returns - // |MOJO_HANDLE_INVALID| on failure, namely if the handle table is full. - MojoHandle AddDispatcher(const scoped_refptr<Dispatcher>& dispatcher); - - // Looks up the dispatcher for the given handle. Returns null if the handle is - // invalid. - scoped_refptr<Dispatcher> GetDispatcher(MojoHandle handle); - - // Watches on the given handle for the given signals, calling |callback| when - // a signal is satisfied or when all signals become unsatisfiable. |callback| - // must satisfy stringent requirements -- see |Awakable::Awake()| in - // awakable.h. In particular, it must not call any Mojo system functions. - MojoResult AsyncWait(MojoHandle handle, - MojoHandleSignals signals, - const base::Callback<void(MojoResult)>& callback); - - embedder::PlatformSupport* platform_support() const { - return platform_support_; - } - - // --------------------------------------------------------------------------- - - // The following methods are essentially implementations of the Mojo Core - // functions of the Mojo API, with the C interface translated to C++ by - // "mojo/edk/embedder/entrypoints.cc". The best way to understand the contract - // of these methods is to look at the header files defining the corresponding - // API functions, referenced below. - - // These methods correspond to the API functions defined in - // "mojo/public/c/system/functions.h": - MojoTimeTicks GetTimeTicksNow(); - MojoResult Close(MojoHandle handle); - MojoResult Wait(MojoHandle handle, - MojoHandleSignals signals, - MojoDeadline deadline, - UserPointer<MojoHandleSignalsState> signals_state); - MojoResult WaitMany(UserPointer<const MojoHandle> handles, - UserPointer<const MojoHandleSignals> signals, - uint32_t num_handles, - MojoDeadline deadline, - UserPointer<uint32_t> result_index, - UserPointer<MojoHandleSignalsState> signals_states); - - // These methods correspond to the API functions defined in - // "mojo/public/c/system/wait_set.h": - MojoResult CreateWaitSet(UserPointer<MojoHandle> wait_set_handle); - MojoResult AddHandle(MojoHandle wait_set_handle, - MojoHandle handle, - MojoHandleSignals signals); - MojoResult RemoveHandle(MojoHandle wait_set_handle, - MojoHandle handle); - MojoResult GetReadyHandles( - MojoHandle wait_set_handle, - UserPointer<uint32_t> count, - UserPointer<MojoHandle> handles, - UserPointer<MojoResult> results, - UserPointer<MojoHandleSignalsState> signals_states); - - // These methods correspond to the API functions defined in - // "mojo/public/c/system/message_pipe.h": - MojoResult CreateMessagePipe( - UserPointer<const MojoCreateMessagePipeOptions> options, - UserPointer<MojoHandle> message_pipe_handle0, - UserPointer<MojoHandle> message_pipe_handle1); - MojoResult WriteMessage(MojoHandle message_pipe_handle, - UserPointer<const void> bytes, - uint32_t num_bytes, - UserPointer<const MojoHandle> handles, - uint32_t num_handles, - MojoWriteMessageFlags flags); - MojoResult ReadMessage(MojoHandle message_pipe_handle, - UserPointer<void> bytes, - UserPointer<uint32_t> num_bytes, - UserPointer<MojoHandle> handles, - UserPointer<uint32_t> num_handles, - MojoReadMessageFlags flags); - - // These methods correspond to the API functions defined in - // "mojo/public/c/system/data_pipe.h": - MojoResult CreateDataPipe( - UserPointer<const MojoCreateDataPipeOptions> options, - UserPointer<MojoHandle> data_pipe_producer_handle, - UserPointer<MojoHandle> data_pipe_consumer_handle); - MojoResult WriteData(MojoHandle data_pipe_producer_handle, - UserPointer<const void> elements, - UserPointer<uint32_t> num_bytes, - MojoWriteDataFlags flags); - MojoResult BeginWriteData(MojoHandle data_pipe_producer_handle, - UserPointer<void*> buffer, - UserPointer<uint32_t> buffer_num_bytes, - MojoWriteDataFlags flags); - MojoResult EndWriteData(MojoHandle data_pipe_producer_handle, - uint32_t num_bytes_written); - MojoResult ReadData(MojoHandle data_pipe_consumer_handle, - UserPointer<void> elements, - UserPointer<uint32_t> num_bytes, - MojoReadDataFlags flags); - MojoResult BeginReadData(MojoHandle data_pipe_consumer_handle, - UserPointer<const void*> buffer, - UserPointer<uint32_t> buffer_num_bytes, - MojoReadDataFlags flags); - MojoResult EndReadData(MojoHandle data_pipe_consumer_handle, - uint32_t num_bytes_read); - - // These methods correspond to the API functions defined in - // "mojo/public/c/system/buffer.h": - MojoResult CreateSharedBuffer( - UserPointer<const MojoCreateSharedBufferOptions> options, - uint64_t num_bytes, - UserPointer<MojoHandle> shared_buffer_handle); - MojoResult DuplicateBufferHandle( - MojoHandle buffer_handle, - UserPointer<const MojoDuplicateBufferHandleOptions> options, - UserPointer<MojoHandle> new_buffer_handle); - MojoResult MapBuffer(MojoHandle buffer_handle, - uint64_t offset, - uint64_t num_bytes, - UserPointer<void*> buffer, - MojoMapBufferFlags flags); - MojoResult UnmapBuffer(UserPointer<void> buffer); - - private: - friend bool internal::ShutdownCheckNoLeaks(Core*); - - // Internal implementation of |Wait()| and |WaitMany()|; doesn't do basic - // validation of arguments. |*result_index| is only set if the result (whether - // success or failure) applies to a specific handle, so its value should be - // preinitialized to |static_cast<uint32_t>(-1)|. - MojoResult WaitManyInternal(const MojoHandle* handles, - const MojoHandleSignals* signals, - uint32_t num_handles, - MojoDeadline deadline, - uint32_t* result_index, - HandleSignalsState* signals_states); - - embedder::PlatformSupport* const platform_support_; - - // TODO(vtl): |handle_table_mutex_| should be a reader-writer lock (if only we - // had them). - Mutex handle_table_mutex_; - HandleTable handle_table_ MOJO_GUARDED_BY(handle_table_mutex_); - - Mutex mapping_table_mutex_; - MappingTable mapping_table_ MOJO_GUARDED_BY(mapping_table_mutex_); - - MOJO_DISALLOW_COPY_AND_ASSIGN(Core); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CORE_H_ diff --git a/third_party/mojo/src/mojo/edk/system/core_test_base.cc b/third_party/mojo/src/mojo/edk/system/core_test_base.cc deleted file mode 100644 index 712b10a..0000000 --- a/third_party/mojo/src/mojo/edk/system/core_test_base.cc +++ /dev/null @@ -1,384 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/core_test_base.h" - -#include <vector> - -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/configuration.h" -#include "third_party/mojo/src/mojo/edk/system/core.h" -#include "third_party/mojo/src/mojo/edk/system/dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/memory.h" - -namespace mojo { -namespace system { -namespace test { - -namespace { - -// MockDispatcher -------------------------------------------------------------- - -class MockDispatcher : public Dispatcher { - public: - static scoped_refptr<MockDispatcher> Create( - CoreTestBase::MockHandleInfo* info) { - return make_scoped_refptr(new MockDispatcher(info)); - } - - // |Dispatcher| private methods: - Type GetType() const override { return Type::UNKNOWN; } - - private: - explicit MockDispatcher(CoreTestBase::MockHandleInfo* info) : info_(info) { - CHECK(info_); - info_->IncrementCtorCallCount(); - } - - ~MockDispatcher() override { info_->IncrementDtorCallCount(); } - - // |Dispatcher| protected methods: - void CloseImplNoLock() override { - info_->IncrementCloseCallCount(); - mutex().AssertHeld(); - } - - MojoResult WriteMessageImplNoLock( - UserPointer<const void> bytes, - uint32_t num_bytes, - std::vector<DispatcherTransport>* transports, - MojoWriteMessageFlags /*flags*/) override { - info_->IncrementWriteMessageCallCount(); - mutex().AssertHeld(); - - if (num_bytes > GetConfiguration().max_message_num_bytes) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - - if (transports) - return MOJO_RESULT_UNIMPLEMENTED; - - return MOJO_RESULT_OK; - } - - MojoResult ReadMessageImplNoLock(UserPointer<void> bytes, - UserPointer<uint32_t> num_bytes, - DispatcherVector* dispatchers, - uint32_t* num_dispatchers, - MojoReadMessageFlags /*flags*/) override { - info_->IncrementReadMessageCallCount(); - mutex().AssertHeld(); - - if (num_dispatchers) { - *num_dispatchers = 1; - if (dispatchers) { - // Okay to leave an invalid dispatcher. - dispatchers->resize(1); - } - } - - return MOJO_RESULT_OK; - } - - MojoResult WriteDataImplNoLock(UserPointer<const void> /*elements*/, - UserPointer<uint32_t> /*num_bytes*/, - MojoWriteDataFlags /*flags*/) override { - info_->IncrementWriteDataCallCount(); - mutex().AssertHeld(); - return MOJO_RESULT_UNIMPLEMENTED; - } - - MojoResult BeginWriteDataImplNoLock( - UserPointer<void*> /*buffer*/, - UserPointer<uint32_t> /*buffer_num_bytes*/, - MojoWriteDataFlags /*flags*/) override { - info_->IncrementBeginWriteDataCallCount(); - mutex().AssertHeld(); - return MOJO_RESULT_UNIMPLEMENTED; - } - - MojoResult EndWriteDataImplNoLock(uint32_t /*num_bytes_written*/) override { - info_->IncrementEndWriteDataCallCount(); - mutex().AssertHeld(); - return MOJO_RESULT_UNIMPLEMENTED; - } - - MojoResult ReadDataImplNoLock(UserPointer<void> /*elements*/, - UserPointer<uint32_t> /*num_bytes*/, - MojoReadDataFlags /*flags*/) override { - info_->IncrementReadDataCallCount(); - mutex().AssertHeld(); - return MOJO_RESULT_UNIMPLEMENTED; - } - - MojoResult BeginReadDataImplNoLock(UserPointer<const void*> /*buffer*/, - UserPointer<uint32_t> /*buffer_num_bytes*/, - MojoReadDataFlags /*flags*/) override { - info_->IncrementBeginReadDataCallCount(); - mutex().AssertHeld(); - return MOJO_RESULT_UNIMPLEMENTED; - } - - MojoResult EndReadDataImplNoLock(uint32_t /*num_bytes_read*/) override { - info_->IncrementEndReadDataCallCount(); - mutex().AssertHeld(); - return MOJO_RESULT_UNIMPLEMENTED; - } - - MojoResult AddAwakableImplNoLock(Awakable* awakable, - MojoHandleSignals /*signals*/, - uintptr_t /*context*/, - HandleSignalsState* signals_state) override { - info_->IncrementAddAwakableCallCount(); - mutex().AssertHeld(); - if (signals_state) - *signals_state = HandleSignalsState(); - if (info_->IsAddAwakableAllowed()) { - info_->AwakableWasAdded(awakable); - return MOJO_RESULT_OK; - } - - return MOJO_RESULT_FAILED_PRECONDITION; - } - - void RemoveAwakableImplNoLock(Awakable* /*awakable*/, - HandleSignalsState* signals_state) override { - info_->IncrementRemoveAwakableCallCount(); - mutex().AssertHeld(); - if (signals_state) - *signals_state = HandleSignalsState(); - } - - void CancelAllAwakablesNoLock() override { - info_->IncrementCancelAllAwakablesCallCount(); - mutex().AssertHeld(); - } - - scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock() - override { - return Create(info_); - } - - CoreTestBase::MockHandleInfo* const info_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(MockDispatcher); -}; - -} // namespace - -// CoreTestBase ---------------------------------------------------------------- - -CoreTestBase::CoreTestBase() { -} - -CoreTestBase::~CoreTestBase() { -} - -void CoreTestBase::SetUp() { - core_ = new Core(&platform_support_); -} - -void CoreTestBase::TearDown() { - delete core_; - core_ = nullptr; -} - -MojoHandle CoreTestBase::CreateMockHandle(CoreTestBase::MockHandleInfo* info) { - CHECK(core_); - scoped_refptr<MockDispatcher> dispatcher = MockDispatcher::Create(info); - return core_->AddDispatcher(dispatcher); -} - -// CoreTestBase_MockHandleInfo ------------------------------------------------- - -CoreTestBase_MockHandleInfo::CoreTestBase_MockHandleInfo() - : ctor_call_count_(0), - dtor_call_count_(0), - close_call_count_(0), - write_message_call_count_(0), - read_message_call_count_(0), - write_data_call_count_(0), - begin_write_data_call_count_(0), - end_write_data_call_count_(0), - read_data_call_count_(0), - begin_read_data_call_count_(0), - end_read_data_call_count_(0), - add_awakable_call_count_(0), - remove_awakable_call_count_(0), - cancel_all_awakables_call_count_(0), - add_awakable_allowed_(false) { -} - -CoreTestBase_MockHandleInfo::~CoreTestBase_MockHandleInfo() { -} - -unsigned CoreTestBase_MockHandleInfo::GetCtorCallCount() const { - MutexLocker locker(&mutex_); - return ctor_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetDtorCallCount() const { - MutexLocker locker(&mutex_); - return dtor_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetCloseCallCount() const { - MutexLocker locker(&mutex_); - return close_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetWriteMessageCallCount() const { - MutexLocker locker(&mutex_); - return write_message_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetReadMessageCallCount() const { - MutexLocker locker(&mutex_); - return read_message_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetWriteDataCallCount() const { - MutexLocker locker(&mutex_); - return write_data_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetBeginWriteDataCallCount() const { - MutexLocker locker(&mutex_); - return begin_write_data_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetEndWriteDataCallCount() const { - MutexLocker locker(&mutex_); - return end_write_data_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetReadDataCallCount() const { - MutexLocker locker(&mutex_); - return read_data_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetBeginReadDataCallCount() const { - MutexLocker locker(&mutex_); - return begin_read_data_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetEndReadDataCallCount() const { - MutexLocker locker(&mutex_); - return end_read_data_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetAddAwakableCallCount() const { - MutexLocker locker(&mutex_); - return add_awakable_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetRemoveAwakableCallCount() const { - MutexLocker locker(&mutex_); - return remove_awakable_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetCancelAllAwakablesCallCount() const { - MutexLocker locker(&mutex_); - return cancel_all_awakables_call_count_; -} - -size_t CoreTestBase_MockHandleInfo::GetAddedAwakableSize() const { - MutexLocker locker(&mutex_); - return added_awakables_.size(); -} - -Awakable* CoreTestBase_MockHandleInfo::GetAddedAwakableAt(unsigned i) const { - MutexLocker locker(&mutex_); - return added_awakables_[i]; -} - -void CoreTestBase_MockHandleInfo::IncrementCtorCallCount() { - MutexLocker locker(&mutex_); - ctor_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementDtorCallCount() { - MutexLocker locker(&mutex_); - dtor_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementCloseCallCount() { - MutexLocker locker(&mutex_); - close_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementWriteMessageCallCount() { - MutexLocker locker(&mutex_); - write_message_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementReadMessageCallCount() { - MutexLocker locker(&mutex_); - read_message_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementWriteDataCallCount() { - MutexLocker locker(&mutex_); - write_data_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementBeginWriteDataCallCount() { - MutexLocker locker(&mutex_); - begin_write_data_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementEndWriteDataCallCount() { - MutexLocker locker(&mutex_); - end_write_data_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementReadDataCallCount() { - MutexLocker locker(&mutex_); - read_data_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementBeginReadDataCallCount() { - MutexLocker locker(&mutex_); - begin_read_data_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementEndReadDataCallCount() { - MutexLocker locker(&mutex_); - end_read_data_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementAddAwakableCallCount() { - MutexLocker locker(&mutex_); - add_awakable_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementRemoveAwakableCallCount() { - MutexLocker locker(&mutex_); - remove_awakable_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementCancelAllAwakablesCallCount() { - MutexLocker locker(&mutex_); - cancel_all_awakables_call_count_++; -} - -void CoreTestBase_MockHandleInfo::AllowAddAwakable(bool alllow) { - MutexLocker locker(&mutex_); - add_awakable_allowed_ = alllow; -} - -bool CoreTestBase_MockHandleInfo::IsAddAwakableAllowed() const { - MutexLocker locker(&mutex_); - return add_awakable_allowed_; -} - -void CoreTestBase_MockHandleInfo::AwakableWasAdded(Awakable* awakable) { - MutexLocker locker(&mutex_); - added_awakables_.push_back(awakable); -} - -} // namespace test -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/core_test_base.h b/third_party/mojo/src/mojo/edk/system/core_test_base.h deleted file mode 100644 index 5798cb6..0000000 --- a/third_party/mojo/src/mojo/edk/system/core_test_base.h +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CORE_TEST_BASE_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CORE_TEST_BASE_H_ - -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h" -#include "third_party/mojo/src/mojo/edk/system/mutex.h" - -namespace mojo { -namespace system { - -class Core; -class Awakable; - -namespace test { - -class CoreTestBase_MockHandleInfo; - -class CoreTestBase : public testing::Test { - public: - using MockHandleInfo = CoreTestBase_MockHandleInfo; - - CoreTestBase(); - ~CoreTestBase() override; - - void SetUp() override; - void TearDown() override; - - protected: - // |info| must remain alive until the returned handle is closed. - MojoHandle CreateMockHandle(MockHandleInfo* info); - - Core* core() { return core_; } - - private: - embedder::SimplePlatformSupport platform_support_; - Core* core_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(CoreTestBase); -}; - -class CoreTestBase_MockHandleInfo { - public: - CoreTestBase_MockHandleInfo(); - ~CoreTestBase_MockHandleInfo(); - - unsigned GetCtorCallCount() const; - unsigned GetDtorCallCount() const; - unsigned GetCloseCallCount() const; - unsigned GetWriteMessageCallCount() const; - unsigned GetReadMessageCallCount() const; - unsigned GetWriteDataCallCount() const; - unsigned GetBeginWriteDataCallCount() const; - unsigned GetEndWriteDataCallCount() const; - unsigned GetReadDataCallCount() const; - unsigned GetBeginReadDataCallCount() const; - unsigned GetEndReadDataCallCount() const; - unsigned GetAddAwakableCallCount() const; - unsigned GetRemoveAwakableCallCount() const; - unsigned GetCancelAllAwakablesCallCount() const; - - size_t GetAddedAwakableSize() const; - Awakable* GetAddedAwakableAt(unsigned i) const; - - // For use by |MockDispatcher|: - void IncrementCtorCallCount(); - void IncrementDtorCallCount(); - void IncrementCloseCallCount(); - void IncrementWriteMessageCallCount(); - void IncrementReadMessageCallCount(); - void IncrementWriteDataCallCount(); - void IncrementBeginWriteDataCallCount(); - void IncrementEndWriteDataCallCount(); - void IncrementReadDataCallCount(); - void IncrementBeginReadDataCallCount(); - void IncrementEndReadDataCallCount(); - void IncrementAddAwakableCallCount(); - void IncrementRemoveAwakableCallCount(); - void IncrementCancelAllAwakablesCallCount(); - - void AllowAddAwakable(bool alllow); - bool IsAddAwakableAllowed() const; - void AwakableWasAdded(Awakable*); - - private: - mutable Mutex mutex_; - unsigned ctor_call_count_ MOJO_GUARDED_BY(mutex_); - unsigned dtor_call_count_ MOJO_GUARDED_BY(mutex_); - unsigned close_call_count_ MOJO_GUARDED_BY(mutex_); - unsigned write_message_call_count_ MOJO_GUARDED_BY(mutex_); - unsigned read_message_call_count_ MOJO_GUARDED_BY(mutex_); - unsigned write_data_call_count_ MOJO_GUARDED_BY(mutex_); - unsigned begin_write_data_call_count_ MOJO_GUARDED_BY(mutex_); - unsigned end_write_data_call_count_ MOJO_GUARDED_BY(mutex_); - unsigned read_data_call_count_ MOJO_GUARDED_BY(mutex_); - unsigned begin_read_data_call_count_ MOJO_GUARDED_BY(mutex_); - unsigned end_read_data_call_count_ MOJO_GUARDED_BY(mutex_); - unsigned add_awakable_call_count_ MOJO_GUARDED_BY(mutex_); - unsigned remove_awakable_call_count_ MOJO_GUARDED_BY(mutex_); - unsigned cancel_all_awakables_call_count_ MOJO_GUARDED_BY(mutex_); - - bool add_awakable_allowed_ MOJO_GUARDED_BY(mutex_); - std::vector<Awakable*> added_awakables_ MOJO_GUARDED_BY(mutex_); - - MOJO_DISALLOW_COPY_AND_ASSIGN(CoreTestBase_MockHandleInfo); -}; - -} // namespace test -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_CORE_TEST_BASE_H_ diff --git a/third_party/mojo/src/mojo/edk/system/core_unittest.cc b/third_party/mojo/src/mojo/edk/system/core_unittest.cc deleted file mode 100644 index 979cfbd..0000000 --- a/third_party/mojo/src/mojo/edk/system/core_unittest.cc +++ /dev/null @@ -1,1317 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/core.h" - -#include <stdint.h> - -#include <limits> - -#include "base/bind.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/awakable.h" -#include "third_party/mojo/src/mojo/edk/system/core_test_base.h" -#include "third_party/mojo/src/mojo/edk/system/test_utils.h" - -namespace mojo { -namespace system { -namespace { - -const MojoHandleSignalsState kEmptyMojoHandleSignalsState = {0u, 0u}; -const MojoHandleSignalsState kFullMojoHandleSignalsState = {~0u, ~0u}; -const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED; - -using CoreTest = test::CoreTestBase; - -TEST_F(CoreTest, GetTimeTicksNow) { - const MojoTimeTicks start = core()->GetTimeTicksNow(); - EXPECT_NE(static_cast<MojoTimeTicks>(0), start) - << "GetTimeTicksNow should return nonzero value"; - test::Sleep(test::DeadlineFromMilliseconds(15)); - const MojoTimeTicks finish = core()->GetTimeTicksNow(); - // Allow for some fuzz in sleep. - EXPECT_GE((finish - start), static_cast<MojoTimeTicks>(8000)) - << "Sleeping should result in increasing time ticks"; -} - -TEST_F(CoreTest, Basic) { - MockHandleInfo info; - - EXPECT_EQ(0u, info.GetCtorCallCount()); - MojoHandle h = CreateMockHandle(&info); - EXPECT_EQ(1u, info.GetCtorCallCount()); - EXPECT_NE(h, MOJO_HANDLE_INVALID); - - EXPECT_EQ(0u, info.GetWriteMessageCallCount()); - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h, NullUserPointer(), 0, NullUserPointer(), 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(1u, info.GetWriteMessageCallCount()); - - EXPECT_EQ(0u, info.GetReadMessageCallCount()); - uint32_t num_bytes = 0; - EXPECT_EQ( - MOJO_RESULT_OK, - core()->ReadMessage(h, NullUserPointer(), MakeUserPointer(&num_bytes), - NullUserPointer(), NullUserPointer(), - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(1u, info.GetReadMessageCallCount()); - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadMessage(h, NullUserPointer(), NullUserPointer(), - NullUserPointer(), NullUserPointer(), - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(2u, info.GetReadMessageCallCount()); - - EXPECT_EQ(0u, info.GetWriteDataCallCount()); - EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, - core()->WriteData(h, NullUserPointer(), NullUserPointer(), - MOJO_WRITE_DATA_FLAG_NONE)); - EXPECT_EQ(1u, info.GetWriteDataCallCount()); - - EXPECT_EQ(0u, info.GetBeginWriteDataCallCount()); - EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, - core()->BeginWriteData(h, NullUserPointer(), NullUserPointer(), - MOJO_WRITE_DATA_FLAG_NONE)); - EXPECT_EQ(1u, info.GetBeginWriteDataCallCount()); - - EXPECT_EQ(0u, info.GetEndWriteDataCallCount()); - EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, core()->EndWriteData(h, 0)); - EXPECT_EQ(1u, info.GetEndWriteDataCallCount()); - - EXPECT_EQ(0u, info.GetReadDataCallCount()); - EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, - core()->ReadData(h, NullUserPointer(), NullUserPointer(), - MOJO_READ_DATA_FLAG_NONE)); - EXPECT_EQ(1u, info.GetReadDataCallCount()); - - EXPECT_EQ(0u, info.GetBeginReadDataCallCount()); - EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, - core()->BeginReadData(h, NullUserPointer(), NullUserPointer(), - MOJO_READ_DATA_FLAG_NONE)); - EXPECT_EQ(1u, info.GetBeginReadDataCallCount()); - - EXPECT_EQ(0u, info.GetEndReadDataCallCount()); - EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, core()->EndReadData(h, 0)); - EXPECT_EQ(1u, info.GetEndReadDataCallCount()); - - EXPECT_EQ(0u, info.GetAddAwakableCallCount()); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, MOJO_DEADLINE_INDEFINITE, - NullUserPointer())); - EXPECT_EQ(1u, info.GetAddAwakableCallCount()); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, 0, NullUserPointer())); - EXPECT_EQ(2u, info.GetAddAwakableCallCount()); - MojoHandleSignalsState hss = kFullMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, MOJO_DEADLINE_INDEFINITE, - MakeUserPointer(&hss))); - EXPECT_EQ(3u, info.GetAddAwakableCallCount()); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, 10 * 1000, NullUserPointer())); - EXPECT_EQ(4u, info.GetAddAwakableCallCount()); - hss = kFullMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, 10 * 1000, - MakeUserPointer(&hss))); - EXPECT_EQ(5u, info.GetAddAwakableCallCount()); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - - MojoHandleSignals handle_signals = ~MOJO_HANDLE_SIGNAL_NONE; - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - core()->WaitMany(MakeUserPointer(&h), MakeUserPointer(&handle_signals), 1, - MOJO_DEADLINE_INDEFINITE, NullUserPointer(), - NullUserPointer())); - EXPECT_EQ(6u, info.GetAddAwakableCallCount()); - uint32_t result_index = static_cast<uint32_t>(-1); - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - core()->WaitMany(MakeUserPointer(&h), MakeUserPointer(&handle_signals), 1, - MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index), - NullUserPointer())); - EXPECT_EQ(7u, info.GetAddAwakableCallCount()); - EXPECT_EQ(0u, result_index); - hss = kFullMojoHandleSignalsState; - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - core()->WaitMany(MakeUserPointer(&h), MakeUserPointer(&handle_signals), 1, - MOJO_DEADLINE_INDEFINITE, NullUserPointer(), - MakeUserPointer(&hss))); - EXPECT_EQ(8u, info.GetAddAwakableCallCount()); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - result_index = static_cast<uint32_t>(-1); - hss = kFullMojoHandleSignalsState; - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - core()->WaitMany(MakeUserPointer(&h), MakeUserPointer(&handle_signals), 1, - MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index), - MakeUserPointer(&hss))); - EXPECT_EQ(9u, info.GetAddAwakableCallCount()); - EXPECT_EQ(0u, result_index); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - - EXPECT_EQ(0u, info.GetDtorCallCount()); - EXPECT_EQ(0u, info.GetCloseCallCount()); - EXPECT_EQ(0u, info.GetCancelAllAwakablesCallCount()); - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h)); - EXPECT_EQ(1u, info.GetCancelAllAwakablesCallCount()); - EXPECT_EQ(1u, info.GetCloseCallCount()); - EXPECT_EQ(1u, info.GetDtorCallCount()); - - // No awakables should ever have ever been added. - EXPECT_EQ(0u, info.GetRemoveAwakableCallCount()); -} - -TEST_F(CoreTest, InvalidArguments) { - // |Close()|: - { - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(MOJO_HANDLE_INVALID)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(10)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(1000000000)); - - // Test a double-close. - MockHandleInfo info; - MojoHandle h = CreateMockHandle(&info); - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h)); - EXPECT_EQ(1u, info.GetCloseCallCount()); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(h)); - EXPECT_EQ(1u, info.GetCloseCallCount()); - } - - // |Wait()|: - { - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->Wait(MOJO_HANDLE_INVALID, ~MOJO_HANDLE_SIGNAL_NONE, - MOJO_DEADLINE_INDEFINITE, NullUserPointer())); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->Wait(10, ~MOJO_HANDLE_SIGNAL_NONE, - MOJO_DEADLINE_INDEFINITE, NullUserPointer())); - - MojoHandleSignalsState hss = kFullMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->Wait(MOJO_HANDLE_INVALID, ~MOJO_HANDLE_SIGNAL_NONE, - MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&hss))); - // On invalid argument, it shouldn't modify the handle signals state. - EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals, - hss.satisfied_signals); - EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals, - hss.satisfiable_signals); - hss = kFullMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->Wait(10, ~MOJO_HANDLE_SIGNAL_NONE, - MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&hss))); - // On invalid argument, it shouldn't modify the handle signals state. - EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals, - hss.satisfied_signals); - EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals, - hss.satisfiable_signals); - } - - // |WaitMany()|: - { - MojoHandle handles[2] = {MOJO_HANDLE_INVALID, MOJO_HANDLE_INVALID}; - MojoHandleSignals signals[2] = {~MOJO_HANDLE_SIGNAL_NONE, - ~MOJO_HANDLE_SIGNAL_NONE}; - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->WaitMany(MakeUserPointer(handles), MakeUserPointer(signals), 0, - MOJO_DEADLINE_INDEFINITE, NullUserPointer(), - NullUserPointer())); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->WaitMany(NullUserPointer(), MakeUserPointer(signals), 0, - MOJO_DEADLINE_INDEFINITE, NullUserPointer(), - NullUserPointer())); - // If |num_handles| is invalid, it should leave |result_index| and - // |signals_states| alone. - // (We use -1 internally; make sure that doesn't leak.) - uint32_t result_index = 123; - MojoHandleSignalsState hss = kFullMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->WaitMany(NullUserPointer(), MakeUserPointer(signals), 0, - MOJO_DEADLINE_INDEFINITE, - MakeUserPointer(&result_index), - MakeUserPointer(&hss))); - EXPECT_EQ(123u, result_index); - EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals, - hss.satisfied_signals); - EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals, - hss.satisfiable_signals); - - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->WaitMany(MakeUserPointer(handles), NullUserPointer(), 0, - MOJO_DEADLINE_INDEFINITE, NullUserPointer(), - NullUserPointer())); - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->WaitMany(MakeUserPointer(handles), MakeUserPointer(signals), 1, - MOJO_DEADLINE_INDEFINITE, NullUserPointer(), - NullUserPointer())); - // But if a handle is bad, then it should set |result_index| but still leave - // |signals_states| alone. - result_index = static_cast<uint32_t>(-1); - hss = kFullMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->WaitMany( - MakeUserPointer(handles), MakeUserPointer(signals), 1, - MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index), - MakeUserPointer(&hss))); - EXPECT_EQ(0u, result_index); - EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals, - hss.satisfied_signals); - EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals, - hss.satisfiable_signals); - - MockHandleInfo info[2]; - handles[0] = CreateMockHandle(&info[0]); - - result_index = static_cast<uint32_t>(-1); - hss = kFullMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - core()->WaitMany( - MakeUserPointer(handles), MakeUserPointer(signals), 1, - MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index), - MakeUserPointer(&hss))); - EXPECT_EQ(0u, result_index); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - - // On invalid argument, it'll leave |signals_states| alone. - result_index = static_cast<uint32_t>(-1); - hss = kFullMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->WaitMany( - MakeUserPointer(handles), MakeUserPointer(signals), 2, - MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index), - MakeUserPointer(&hss))); - EXPECT_EQ(1u, result_index); - EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals, - hss.satisfied_signals); - EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals, - hss.satisfiable_signals); - handles[1] = handles[0] + 1; // Invalid handle. - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->WaitMany(MakeUserPointer(handles), MakeUserPointer(signals), 2, - MOJO_DEADLINE_INDEFINITE, NullUserPointer(), - NullUserPointer())); - handles[1] = CreateMockHandle(&info[1]); - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - core()->WaitMany(MakeUserPointer(handles), MakeUserPointer(signals), 2, - MOJO_DEADLINE_INDEFINITE, NullUserPointer(), - NullUserPointer())); - - // TODO(vtl): Test one where we get "failed precondition" only for the - // second handle (and the first one is valid to wait on). - - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(handles[0])); - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(handles[1])); - } - - // |CreateMessagePipe()|: Nothing to check (apart from things that cause - // death). - - // |WriteMessage()|: - // Only check arguments checked by |Core|, namely |handle|, |handles|, and - // |num_handles|. - { - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->WriteMessage(MOJO_HANDLE_INVALID, NullUserPointer(), 0, - NullUserPointer(), 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - MockHandleInfo info; - MojoHandle h = CreateMockHandle(&info); - MojoHandle handles[2] = {MOJO_HANDLE_INVALID, MOJO_HANDLE_INVALID}; - - // Huge handle count (implausibly big on some systems -- more than can be - // stored in a 32-bit address space). - // Note: This may return either |MOJO_RESULT_INVALID_ARGUMENT| or - // |MOJO_RESULT_RESOURCE_EXHAUSTED|, depending on whether it's plausible or - // not. - EXPECT_NE( - MOJO_RESULT_OK, - core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles), - std::numeric_limits<uint32_t>::max(), - MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(0u, info.GetWriteMessageCallCount()); - - // Huge handle count (plausibly big). - EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, - core()->WriteMessage( - h, NullUserPointer(), 0, MakeUserPointer(handles), - std::numeric_limits<uint32_t>::max() / sizeof(handles[0]), - MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(0u, info.GetWriteMessageCallCount()); - - // Invalid handle in |handles|. - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles), - 1, MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(0u, info.GetWriteMessageCallCount()); - - // Two invalid handles in |handles|. - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles), - 2, MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(0u, info.GetWriteMessageCallCount()); - - // Can't send a handle over itself. - handles[0] = h; - EXPECT_EQ( - MOJO_RESULT_BUSY, - core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles), - 1, MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(0u, info.GetWriteMessageCallCount()); - - MockHandleInfo info2; - MojoHandle h2 = CreateMockHandle(&info2); - - // This is "okay", but |MockDispatcher| doesn't implement it. - handles[0] = h2; - EXPECT_EQ( - MOJO_RESULT_UNIMPLEMENTED, - core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles), - 1, MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(1u, info.GetWriteMessageCallCount()); - - // One of the |handles| is still invalid. - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles), - 2, MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(1u, info.GetWriteMessageCallCount()); - - // One of the |handles| is the same as |handle|. - handles[1] = h; - EXPECT_EQ( - MOJO_RESULT_BUSY, - core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles), - 2, MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(1u, info.GetWriteMessageCallCount()); - - // Can't send a handle twice in the same message. - handles[1] = h2; - EXPECT_EQ( - MOJO_RESULT_BUSY, - core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles), - 2, MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(1u, info.GetWriteMessageCallCount()); - - // Note: Since we never successfully sent anything with it, |h2| should - // still be valid. - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h2)); - - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h)); - } - - // |ReadMessage()|: - // Only check arguments checked by |Core|, namely |handle|, |handles|, and - // |num_handles|. - { - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->ReadMessage(MOJO_HANDLE_INVALID, NullUserPointer(), - NullUserPointer(), NullUserPointer(), - NullUserPointer(), MOJO_READ_MESSAGE_FLAG_NONE)); - - MockHandleInfo info; - MojoHandle h = CreateMockHandle(&info); - - // Okay. - uint32_t handle_count = 0; - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h, NullUserPointer(), NullUserPointer(), NullUserPointer(), - MakeUserPointer(&handle_count), MOJO_READ_MESSAGE_FLAG_NONE)); - // Checked by |Core|, shouldn't go through to the dispatcher. - EXPECT_EQ(1u, info.GetReadMessageCallCount()); - - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h)); - } -} - -// These test invalid arguments that should cause death if we're being paranoid -// about checking arguments (which we would want to do if, e.g., we were in a -// true "kernel" situation, but we might not want to do otherwise for -// performance reasons). Probably blatant errors like passing in null pointers -// (for required pointer arguments) will still cause death, but perhaps not -// predictably. -TEST_F(CoreTest, InvalidArgumentsDeath) { - const char kMemoryCheckFailedRegex[] = "Check failed"; - - // |WaitMany()|: - { - MojoHandle handle = MOJO_HANDLE_INVALID; - MojoHandleSignals signals = ~MOJO_HANDLE_SIGNAL_NONE; - EXPECT_DEATH_IF_SUPPORTED( - core()->WaitMany(NullUserPointer(), MakeUserPointer(&signals), 1, - MOJO_DEADLINE_INDEFINITE, NullUserPointer(), - NullUserPointer()), - kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED( - core()->WaitMany(MakeUserPointer(&handle), NullUserPointer(), 1, - MOJO_DEADLINE_INDEFINITE, NullUserPointer(), - NullUserPointer()), - kMemoryCheckFailedRegex); - // TODO(vtl): |result_index| and |signals_states| are optional. Test them - // with non-null invalid pointers? - } - - // |CreateMessagePipe()|: - { - MojoHandle h; - EXPECT_DEATH_IF_SUPPORTED( - core()->CreateMessagePipe(NullUserPointer(), NullUserPointer(), - NullUserPointer()), - kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED( - core()->CreateMessagePipe(NullUserPointer(), MakeUserPointer(&h), - NullUserPointer()), - kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED( - core()->CreateMessagePipe(NullUserPointer(), NullUserPointer(), - MakeUserPointer(&h)), - kMemoryCheckFailedRegex); - } - - // |WriteMessage()|: - // Only check arguments checked by |Core|, namely |handle|, |handles|, and - // |num_handles|. - { - MockHandleInfo info; - MojoHandle h = CreateMockHandle(&info); - - // Null |handles| with nonzero |num_handles|. - EXPECT_DEATH_IF_SUPPORTED( - core()->WriteMessage(h, NullUserPointer(), 0, NullUserPointer(), 1, - MOJO_WRITE_MESSAGE_FLAG_NONE), - kMemoryCheckFailedRegex); - - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h)); - } - - // |ReadMessage()|: - // Only check arguments checked by |Core|, namely |handle|, |handles|, and - // |num_handles|. - { - MockHandleInfo info; - MojoHandle h = CreateMockHandle(&info); - - uint32_t handle_count = 1; - EXPECT_DEATH_IF_SUPPORTED( - core()->ReadMessage(h, NullUserPointer(), NullUserPointer(), - NullUserPointer(), MakeUserPointer(&handle_count), - MOJO_READ_MESSAGE_FLAG_NONE), - kMemoryCheckFailedRegex); - - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h)); - } -} - -// TODO(vtl): test |Wait()| and |WaitMany()| properly -// - including |WaitMany()| with the same handle more than once (with -// same/different signals) - -TEST_F(CoreTest, MessagePipe) { - MojoHandle h[2]; - MojoHandleSignalsState hss[2]; - uint32_t result_index; - - EXPECT_EQ(MOJO_RESULT_OK, - core()->CreateMessagePipe(NullUserPointer(), MakeUserPointer(&h[0]), - MakeUserPointer(&h[1]))); - // Should get two distinct, valid handles. - EXPECT_NE(h[0], MOJO_HANDLE_INVALID); - EXPECT_NE(h[1], MOJO_HANDLE_INVALID); - EXPECT_NE(h[0], h[1]); - - // Neither should be readable. - MojoHandleSignals signals[2] = {MOJO_HANDLE_SIGNAL_READABLE, - MOJO_HANDLE_SIGNAL_READABLE}; - result_index = static_cast<uint32_t>(-1); - hss[0] = kEmptyMojoHandleSignalsState; - hss[1] = kEmptyMojoHandleSignalsState; - EXPECT_EQ( - MOJO_RESULT_DEADLINE_EXCEEDED, - core()->WaitMany(MakeUserPointer(h), MakeUserPointer(signals), 2, 0, - MakeUserPointer(&result_index), MakeUserPointer(hss))); - EXPECT_EQ(static_cast<uint32_t>(-1), result_index); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals); - EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals); - EXPECT_EQ(kAllSignals, hss[1].satisfiable_signals); - - // Try to read anyway. - char buffer[1] = {'a'}; - uint32_t buffer_size = 1; - EXPECT_EQ( - MOJO_RESULT_SHOULD_WAIT, - core()->ReadMessage(h[0], UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), NullUserPointer(), - NullUserPointer(), MOJO_READ_MESSAGE_FLAG_NONE)); - // Check that it left its inputs alone. - EXPECT_EQ('a', buffer[0]); - EXPECT_EQ(1u, buffer_size); - - // Both should be writable. - hss[0] = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(h[0], MOJO_HANDLE_SIGNAL_WRITABLE, - 1000000000, MakeUserPointer(&hss[0]))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals); - EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals); - hss[0] = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(h[1], MOJO_HANDLE_SIGNAL_WRITABLE, - 1000000000, MakeUserPointer(&hss[0]))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals); - EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals); - - // Also check that |h[1]| is writable using |WaitMany()|. - signals[0] = MOJO_HANDLE_SIGNAL_READABLE; - signals[1] = MOJO_HANDLE_SIGNAL_WRITABLE; - result_index = static_cast<uint32_t>(-1); - hss[0] = kEmptyMojoHandleSignalsState; - hss[1] = kEmptyMojoHandleSignalsState; - EXPECT_EQ( - MOJO_RESULT_OK, - core()->WaitMany(MakeUserPointer(h), MakeUserPointer(signals), 2, - MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index), - MakeUserPointer(hss))); - EXPECT_EQ(1u, result_index); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals); - EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals); - EXPECT_EQ(kAllSignals, hss[1].satisfiable_signals); - - // Write to |h[1]|. - buffer[0] = 'b'; - EXPECT_EQ( - MOJO_RESULT_OK, - core()->WriteMessage(h[1], UserPointer<const void>(buffer), 1, - NullUserPointer(), 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Check that |h[0]| is now readable. - signals[0] = MOJO_HANDLE_SIGNAL_READABLE; - signals[1] = MOJO_HANDLE_SIGNAL_READABLE; - result_index = static_cast<uint32_t>(-1); - hss[0] = kEmptyMojoHandleSignalsState; - hss[1] = kEmptyMojoHandleSignalsState; - EXPECT_EQ( - MOJO_RESULT_OK, - core()->WaitMany(MakeUserPointer(h), MakeUserPointer(signals), 2, - MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index), - MakeUserPointer(hss))); - EXPECT_EQ(0u, result_index); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss[0].satisfied_signals); - EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals); - EXPECT_EQ(kAllSignals, hss[1].satisfiable_signals); - - // Read from |h[0]|. - // First, get only the size. - buffer_size = 0; - EXPECT_EQ( - MOJO_RESULT_RESOURCE_EXHAUSTED, - core()->ReadMessage(h[0], NullUserPointer(), - MakeUserPointer(&buffer_size), NullUserPointer(), - NullUserPointer(), MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(1u, buffer_size); - // Then actually read it. - buffer[0] = 'c'; - buffer_size = 1; - EXPECT_EQ( - MOJO_RESULT_OK, - core()->ReadMessage(h[0], UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), NullUserPointer(), - NullUserPointer(), MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ('b', buffer[0]); - EXPECT_EQ(1u, buffer_size); - - // |h[0]| should no longer be readable. - hss[0] = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, - core()->Wait(h[0], MOJO_HANDLE_SIGNAL_READABLE, 0, - MakeUserPointer(&hss[0]))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals); - EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals); - - // Write to |h[0]|. - buffer[0] = 'd'; - EXPECT_EQ( - MOJO_RESULT_OK, - core()->WriteMessage(h[0], UserPointer<const void>(buffer), 1, - NullUserPointer(), 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Close |h[0]|. - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h[0])); - - // Check that |h[1]| is no longer writable (and will never be). - hss[0] = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - core()->Wait(h[1], MOJO_HANDLE_SIGNAL_WRITABLE, 1000000000, - MakeUserPointer(&hss[0]))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss[0].satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss[0].satisfiable_signals); - - // Check that |h[1]| is still readable (for the moment). - hss[0] = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(h[1], MOJO_HANDLE_SIGNAL_READABLE, - 1000000000, MakeUserPointer(&hss[0]))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss[0].satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss[0].satisfiable_signals); - - // Discard a message from |h[1]|. - EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, - core()->ReadMessage(h[1], NullUserPointer(), NullUserPointer(), - NullUserPointer(), NullUserPointer(), - MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); - - // |h[1]| is no longer readable (and will never be). - hss[0] = kFullMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - core()->Wait(h[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000, - MakeUserPointer(&hss[0]))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss[0].satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss[0].satisfiable_signals); - - // Try writing to |h[1]|. - buffer[0] = 'e'; - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - core()->WriteMessage(h[1], UserPointer<const void>(buffer), 1, - NullUserPointer(), 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h[1])); -} - -// Tests passing a message pipe handle. -TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) { - const char kHello[] = "hello"; - const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello)); - const char kWorld[] = "world!!!"; - const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld)); - char buffer[100]; - const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); - uint32_t num_bytes; - MojoHandle handles[10]; - uint32_t num_handles; - MojoHandleSignalsState hss; - MojoHandle h_received; - - MojoHandle h_passing[2]; - EXPECT_EQ(MOJO_RESULT_OK, - core()->CreateMessagePipe(NullUserPointer(), - MakeUserPointer(&h_passing[0]), - MakeUserPointer(&h_passing[1]))); - - // Make sure that |h_passing[]| work properly. - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello), - kHelloSize, NullUserPointer(), 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, - core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000, - MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - num_bytes = kBufferSize; - num_handles = MOJO_ARRAYSIZE(handles); - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_passing[1], UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), MakeUserPointer(handles), - MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kHelloSize, num_bytes); - EXPECT_STREQ(kHello, buffer); - EXPECT_EQ(0u, num_handles); - - // Make sure that you can't pass either of the message pipe's handles over - // itself. - EXPECT_EQ(MOJO_RESULT_BUSY, - core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello), - kHelloSize, MakeUserPointer(&h_passing[0]), 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello), - kHelloSize, MakeUserPointer(&h_passing[1]), 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - MojoHandle h_passed[2]; - EXPECT_EQ(MOJO_RESULT_OK, - core()->CreateMessagePipe(NullUserPointer(), - MakeUserPointer(&h_passed[0]), - MakeUserPointer(&h_passed[1]))); - - // Make sure that |h_passed[]| work properly. - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passed[0], UserPointer<const void>(kHello), - kHelloSize, NullUserPointer(), 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, - core()->Wait(h_passed[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000, - MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - num_bytes = kBufferSize; - num_handles = MOJO_ARRAYSIZE(handles); - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_passed[1], UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), MakeUserPointer(handles), - MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kHelloSize, num_bytes); - EXPECT_STREQ(kHello, buffer); - EXPECT_EQ(0u, num_handles); - - // Send |h_passed[1]| from |h_passing[0]| to |h_passing[1]|. - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passing[0], UserPointer<const void>(kWorld), - kWorldSize, MakeUserPointer(&h_passed[1]), 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, - core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000, - MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - num_bytes = kBufferSize; - num_handles = MOJO_ARRAYSIZE(handles); - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_passing[1], UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), MakeUserPointer(handles), - MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kWorldSize, num_bytes); - EXPECT_STREQ(kWorld, buffer); - EXPECT_EQ(1u, num_handles); - h_received = handles[0]; - EXPECT_NE(h_received, MOJO_HANDLE_INVALID); - EXPECT_NE(h_received, h_passing[0]); - EXPECT_NE(h_received, h_passing[1]); - EXPECT_NE(h_received, h_passed[0]); - - // Note: We rely on the Mojo system not re-using handle values very often. - EXPECT_NE(h_received, h_passed[1]); - - // |h_passed[1]| should no longer be valid; check that trying to close it - // fails. See above note. - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(h_passed[1])); - - // Write to |h_passed[0]|. Should receive on |h_received|. - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passed[0], UserPointer<const void>(kHello), - kHelloSize, NullUserPointer(), 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, - core()->Wait(h_received, MOJO_HANDLE_SIGNAL_READABLE, 1000000000, - MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - num_bytes = kBufferSize; - num_handles = MOJO_ARRAYSIZE(handles); - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_received, UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), MakeUserPointer(handles), - MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kHelloSize, num_bytes); - EXPECT_STREQ(kHello, buffer); - EXPECT_EQ(0u, num_handles); - - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h_passing[0])); - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h_passing[1])); - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h_passed[0])); - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h_received)); -} - -TEST_F(CoreTest, DataPipe) { - MojoHandle ph, ch; // p is for producer and c is for consumer. - MojoHandleSignalsState hss; - - EXPECT_EQ(MOJO_RESULT_OK, - core()->CreateDataPipe(NullUserPointer(), MakeUserPointer(&ph), - MakeUserPointer(&ch))); - // Should get two distinct, valid handles. - EXPECT_NE(ph, MOJO_HANDLE_INVALID); - EXPECT_NE(ch, MOJO_HANDLE_INVALID); - EXPECT_NE(ph, ch); - - // Producer should be never-readable, but already writable. - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - core()->Wait(ph, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(ph, MOJO_HANDLE_SIGNAL_WRITABLE, 0, - MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Consumer should be never-writable, and not yet readable. - hss = kFullMojoHandleSignalsState; - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - core()->Wait(ch, MOJO_HANDLE_SIGNAL_WRITABLE, 0, MakeUserPointer(&hss))); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - hss = kFullMojoHandleSignalsState; - EXPECT_EQ( - MOJO_RESULT_DEADLINE_EXCEEDED, - core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss))); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Write. - signed char elements[2] = {'A', 'B'}; - uint32_t num_bytes = 2u; - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteData(ph, UserPointer<const void>(elements), - MakeUserPointer(&num_bytes), - MOJO_WRITE_DATA_FLAG_NONE)); - EXPECT_EQ(2u, num_bytes); - - // Consumer should now be readable. - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, - MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Peek one character. - elements[0] = -1; - elements[1] = -1; - num_bytes = 1u; - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadData( - ch, UserPointer<void>(elements), MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_NONE | MOJO_READ_DATA_FLAG_PEEK)); - EXPECT_EQ('A', elements[0]); - EXPECT_EQ(-1, elements[1]); - - // Read one character. - elements[0] = -1; - elements[1] = -1; - num_bytes = 1u; - EXPECT_EQ(MOJO_RESULT_OK, core()->ReadData(ch, UserPointer<void>(elements), - MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_NONE)); - EXPECT_EQ('A', elements[0]); - EXPECT_EQ(-1, elements[1]); - - // Two-phase write. - void* write_ptr = nullptr; - num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_OK, - core()->BeginWriteData(ph, MakeUserPointer(&write_ptr), - MakeUserPointer(&num_bytes), - MOJO_WRITE_DATA_FLAG_NONE)); - // We count on the default options providing a decent buffer size. - ASSERT_GE(num_bytes, 3u); - - // Trying to do a normal write during a two-phase write should fail. - elements[0] = 'X'; - num_bytes = 1u; - EXPECT_EQ(MOJO_RESULT_BUSY, - core()->WriteData(ph, UserPointer<const void>(elements), - MakeUserPointer(&num_bytes), - MOJO_WRITE_DATA_FLAG_NONE)); - - // Actually write the data, and complete it now. - static_cast<char*>(write_ptr)[0] = 'C'; - static_cast<char*>(write_ptr)[1] = 'D'; - static_cast<char*>(write_ptr)[2] = 'E'; - EXPECT_EQ(MOJO_RESULT_OK, core()->EndWriteData(ph, 3u)); - - // Query how much data we have. - num_bytes = 0; - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadData(ch, NullUserPointer(), MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_QUERY)); - EXPECT_EQ(4u, num_bytes); - - // Try to query with peek. Should fail. - num_bytes = 0; - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->ReadData(ch, NullUserPointer(), MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_QUERY | MOJO_READ_DATA_FLAG_PEEK)); - EXPECT_EQ(0u, num_bytes); - - // Try to discard ten characters, in all-or-none mode. Should fail. - num_bytes = 10; - EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, - core()->ReadData( - ch, NullUserPointer(), MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_ALL_OR_NONE)); - - // Try to discard two characters, in peek mode. Should fail. - num_bytes = 2; - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->ReadData(ch, NullUserPointer(), MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_PEEK)); - - // Discard two characters. - num_bytes = 2; - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadData( - ch, NullUserPointer(), MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_ALL_OR_NONE)); - - // Try a two-phase read of the remaining two bytes with peek. Should fail. - const void* read_ptr = nullptr; - num_bytes = 2; - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->BeginReadData(ch, MakeUserPointer(&read_ptr), - MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_PEEK)); - - // Read the remaining two characters, in two-phase mode (all-or-none). - num_bytes = 2; - ASSERT_EQ(MOJO_RESULT_OK, - core()->BeginReadData(ch, MakeUserPointer(&read_ptr), - MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_ALL_OR_NONE)); - // Note: Count on still being able to do the contiguous read here. - ASSERT_EQ(2u, num_bytes); - - // Discarding right now should fail. - num_bytes = 1; - EXPECT_EQ(MOJO_RESULT_BUSY, - core()->ReadData(ch, NullUserPointer(), MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_DISCARD)); - - // Actually check our data and end the two-phase read. - EXPECT_EQ('D', static_cast<const char*>(read_ptr)[0]); - EXPECT_EQ('E', static_cast<const char*>(read_ptr)[1]); - EXPECT_EQ(MOJO_RESULT_OK, core()->EndReadData(ch, 2u)); - - // Consumer should now be no longer readable. - hss = kFullMojoHandleSignalsState; - EXPECT_EQ( - MOJO_RESULT_DEADLINE_EXCEEDED, - core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss))); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // TODO(vtl): More. - - // Close the producer. - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(ph)); - - // The consumer should now be never-readable. - hss = kFullMojoHandleSignalsState; - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(ch)); -} - -// Tests passing data pipe producer and consumer handles. -TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) { - const char kHello[] = "hello"; - const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello)); - const char kWorld[] = "world!!!"; - const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld)); - char buffer[100]; - const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); - uint32_t num_bytes; - MojoHandle handles[10]; - uint32_t num_handles; - MojoHandleSignalsState hss; - - MojoHandle h_passing[2]; - EXPECT_EQ(MOJO_RESULT_OK, - core()->CreateMessagePipe(NullUserPointer(), - MakeUserPointer(&h_passing[0]), - MakeUserPointer(&h_passing[1]))); - - MojoHandle ph, ch; - EXPECT_EQ(MOJO_RESULT_OK, - core()->CreateDataPipe(NullUserPointer(), MakeUserPointer(&ph), - MakeUserPointer(&ch))); - - // Send |ch| from |h_passing[0]| to |h_passing[1]|. - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello), - kHelloSize, MakeUserPointer(&ch), 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, - core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000, - MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - num_bytes = kBufferSize; - num_handles = MOJO_ARRAYSIZE(handles); - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_passing[1], UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), MakeUserPointer(handles), - MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kHelloSize, num_bytes); - EXPECT_STREQ(kHello, buffer); - EXPECT_EQ(1u, num_handles); - MojoHandle ch_received = handles[0]; - EXPECT_NE(ch_received, MOJO_HANDLE_INVALID); - EXPECT_NE(ch_received, h_passing[0]); - EXPECT_NE(ch_received, h_passing[1]); - EXPECT_NE(ch_received, ph); - - // Note: We rely on the Mojo system not re-using handle values very often. - EXPECT_NE(ch_received, ch); - - // |ch| should no longer be valid; check that trying to close it fails. See - // above note. - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(ch)); - - // Write to |ph|. Should receive on |ch_received|. - num_bytes = kWorldSize; - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteData(ph, UserPointer<const void>(kWorld), - MakeUserPointer(&num_bytes), - MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)); - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, - core()->Wait(ch_received, MOJO_HANDLE_SIGNAL_READABLE, 1000000000, - MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - num_bytes = kBufferSize; - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadData(ch_received, UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kWorldSize, num_bytes); - EXPECT_STREQ(kWorld, buffer); - - // Now pass |ph| in the same direction. - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passing[0], UserPointer<const void>(kWorld), - kWorldSize, MakeUserPointer(&ph), 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, - core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000, - MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - num_bytes = kBufferSize; - num_handles = MOJO_ARRAYSIZE(handles); - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_passing[1], UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), MakeUserPointer(handles), - MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kWorldSize, num_bytes); - EXPECT_STREQ(kWorld, buffer); - EXPECT_EQ(1u, num_handles); - MojoHandle ph_received = handles[0]; - EXPECT_NE(ph_received, MOJO_HANDLE_INVALID); - EXPECT_NE(ph_received, h_passing[0]); - EXPECT_NE(ph_received, h_passing[1]); - EXPECT_NE(ph_received, ch_received); - - // Again, rely on the Mojo system not re-using handle values very often. - EXPECT_NE(ph_received, ph); - - // |ph| should no longer be valid; check that trying to close it fails. See - // above note. - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(ph)); - - // Write to |ph_received|. Should receive on |ch_received|. - num_bytes = kHelloSize; - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteData(ph_received, UserPointer<const void>(kHello), - MakeUserPointer(&num_bytes), - MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)); - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, - core()->Wait(ch_received, MOJO_HANDLE_SIGNAL_READABLE, 1000000000, - MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - num_bytes = kBufferSize; - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadData(ch_received, UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kHelloSize, num_bytes); - EXPECT_STREQ(kHello, buffer); - - ph = ph_received; - ph_received = MOJO_HANDLE_INVALID; - ch = ch_received; - ch_received = MOJO_HANDLE_INVALID; - - // Make sure that |ph| can't be sent if it's in a two-phase write. - void* write_ptr = nullptr; - num_bytes = 0; - ASSERT_EQ(MOJO_RESULT_OK, - core()->BeginWriteData(ph, MakeUserPointer(&write_ptr), - MakeUserPointer(&num_bytes), - MOJO_WRITE_DATA_FLAG_NONE)); - ASSERT_GE(num_bytes, 1u); - EXPECT_EQ(MOJO_RESULT_BUSY, - core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello), - kHelloSize, MakeUserPointer(&ph), 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // But |ch| can, even if |ph| is in a two-phase write. - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello), - kHelloSize, MakeUserPointer(&ch), 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ch = MOJO_HANDLE_INVALID; - EXPECT_EQ(MOJO_RESULT_OK, - core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000, - NullUserPointer())); - num_bytes = kBufferSize; - num_handles = MOJO_ARRAYSIZE(handles); - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_passing[1], UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), MakeUserPointer(handles), - MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kHelloSize, num_bytes); - EXPECT_STREQ(kHello, buffer); - EXPECT_EQ(1u, num_handles); - ch = handles[0]; - EXPECT_NE(ch, MOJO_HANDLE_INVALID); - - // Complete the two-phase write. - static_cast<char*>(write_ptr)[0] = 'x'; - EXPECT_EQ(MOJO_RESULT_OK, core()->EndWriteData(ph, 1)); - - // Wait for |ch| to be readable. - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, - 1000000000, MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Make sure that |ch| can't be sent if it's in a two-phase read. - const void* read_ptr = nullptr; - num_bytes = 1; - ASSERT_EQ(MOJO_RESULT_OK, - core()->BeginReadData(ch, MakeUserPointer(&read_ptr), - MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_ALL_OR_NONE)); - EXPECT_EQ(MOJO_RESULT_BUSY, - core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello), - kHelloSize, MakeUserPointer(&ch), 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // But |ph| can, even if |ch| is in a two-phase read. - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passing[0], UserPointer<const void>(kWorld), - kWorldSize, MakeUserPointer(&ph), 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ph = MOJO_HANDLE_INVALID; - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, - core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000, - MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - num_bytes = kBufferSize; - num_handles = MOJO_ARRAYSIZE(handles); - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_passing[1], UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), MakeUserPointer(handles), - MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kWorldSize, num_bytes); - EXPECT_STREQ(kWorld, buffer); - EXPECT_EQ(1u, num_handles); - ph = handles[0]; - EXPECT_NE(ph, MOJO_HANDLE_INVALID); - - // Complete the two-phase read. - EXPECT_EQ('x', static_cast<const char*>(read_ptr)[0]); - EXPECT_EQ(MOJO_RESULT_OK, core()->EndReadData(ch, 1)); - - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h_passing[0])); - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h_passing[1])); - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(ph)); - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(ch)); -} - -struct TestAsyncWaiter { - TestAsyncWaiter() : result(MOJO_RESULT_UNKNOWN) {} - - void Awake(MojoResult r) { result = r; } - - MojoResult result; -}; - -TEST_F(CoreTest, AsyncWait) { - TestAsyncWaiter waiter; - MockHandleInfo info; - MojoHandle h = CreateMockHandle(&info); - - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - core()->AsyncWait(h, MOJO_HANDLE_SIGNAL_READABLE, - base::Bind(&TestAsyncWaiter::Awake, - base::Unretained(&waiter)))); - EXPECT_EQ(0u, info.GetAddedAwakableSize()); - - info.AllowAddAwakable(true); - EXPECT_EQ(MOJO_RESULT_OK, - core()->AsyncWait(h, MOJO_HANDLE_SIGNAL_READABLE, - base::Bind(&TestAsyncWaiter::Awake, - base::Unretained(&waiter)))); - EXPECT_EQ(1u, info.GetAddedAwakableSize()); - - EXPECT_FALSE(info.GetAddedAwakableAt(0)->Awake(MOJO_RESULT_BUSY, 0)); - EXPECT_EQ(MOJO_RESULT_BUSY, waiter.result); - - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h)); -} - -// TODO(vtl): Test |DuplicateBufferHandle()| and |MapBuffer()|. - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/data_pipe.cc b/third_party/mojo/src/mojo/edk/system/data_pipe.cc deleted file mode 100644 index 396a160..0000000 --- a/third_party/mojo/src/mojo/edk/system/data_pipe.cc +++ /dev/null @@ -1,809 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/data_pipe.h" - -#include <string.h> -#include <algorithm> -#include <limits> -#include <utility> - -#include "base/logging.h" -#include "base/memory/aligned_memory.h" -#include "third_party/mojo/src/mojo/edk/system/awakable_list.h" -#include "third_party/mojo/src/mojo/edk/system/channel.h" -#include "third_party/mojo/src/mojo/edk/system/configuration.h" -#include "third_party/mojo/src/mojo/edk/system/data_pipe_impl.h" -#include "third_party/mojo/src/mojo/edk/system/incoming_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/local_data_pipe_impl.h" -#include "third_party/mojo/src/mojo/edk/system/memory.h" -#include "third_party/mojo/src/mojo/edk/system/options_validation.h" -#include "third_party/mojo/src/mojo/edk/system/remote_consumer_data_pipe_impl.h" -#include "third_party/mojo/src/mojo/edk/system/remote_producer_data_pipe_impl.h" - -namespace mojo { -namespace system { - -// static -MojoCreateDataPipeOptions DataPipe::GetDefaultCreateOptions() { - MojoCreateDataPipeOptions result = { - static_cast<uint32_t>(sizeof(MojoCreateDataPipeOptions)), - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, - 1u, - static_cast<uint32_t>( - GetConfiguration().default_data_pipe_capacity_bytes)}; - return result; -} - -// static -MojoResult DataPipe::ValidateCreateOptions( - UserPointer<const MojoCreateDataPipeOptions> in_options, - MojoCreateDataPipeOptions* out_options) { - const MojoCreateDataPipeOptionsFlags kKnownFlags = - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; - - *out_options = GetDefaultCreateOptions(); - if (in_options.IsNull()) - return MOJO_RESULT_OK; - - UserOptionsReader<MojoCreateDataPipeOptions> reader(in_options); - if (!reader.is_valid()) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, flags, reader)) - return MOJO_RESULT_OK; - if ((reader.options().flags & ~kKnownFlags)) - return MOJO_RESULT_UNIMPLEMENTED; - out_options->flags = reader.options().flags; - - // Checks for fields beyond |flags|: - - if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, element_num_bytes, - reader)) - return MOJO_RESULT_OK; - if (reader.options().element_num_bytes == 0) - return MOJO_RESULT_INVALID_ARGUMENT; - out_options->element_num_bytes = reader.options().element_num_bytes; - - if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, capacity_num_bytes, - reader) || - reader.options().capacity_num_bytes == 0) { - // Round the default capacity down to a multiple of the element size (but at - // least one element). - size_t default_data_pipe_capacity_bytes = - GetConfiguration().default_data_pipe_capacity_bytes; - out_options->capacity_num_bytes = - std::max(static_cast<uint32_t>(default_data_pipe_capacity_bytes - - (default_data_pipe_capacity_bytes % - out_options->element_num_bytes)), - out_options->element_num_bytes); - return MOJO_RESULT_OK; - } - if (reader.options().capacity_num_bytes % out_options->element_num_bytes != 0) - return MOJO_RESULT_INVALID_ARGUMENT; - if (reader.options().capacity_num_bytes > - GetConfiguration().max_data_pipe_capacity_bytes) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - out_options->capacity_num_bytes = reader.options().capacity_num_bytes; - - return MOJO_RESULT_OK; -} - -// static -DataPipe* DataPipe::CreateLocal( - const MojoCreateDataPipeOptions& validated_options) { - return new DataPipe(true, true, validated_options, - make_scoped_ptr(new LocalDataPipeImpl())); -} - -// static -DataPipe* DataPipe::CreateRemoteProducerFromExisting( - const MojoCreateDataPipeOptions& validated_options, - MessageInTransitQueue* message_queue, - ChannelEndpoint* channel_endpoint) { - scoped_ptr<char, base::AlignedFreeDeleter> buffer; - size_t buffer_num_bytes = 0; - if (!RemoteProducerDataPipeImpl::ProcessMessagesFromIncomingEndpoint( - validated_options, message_queue, &buffer, &buffer_num_bytes)) - return nullptr; - - // Important: This is called under |IncomingEndpoint|'s (which is a - // |ChannelEndpointClient|) lock, in particular from - // |IncomingEndpoint::ConvertToDataPipeConsumer()|. Before releasing that - // lock, it will reset its |endpoint_| member, which makes any later or - // ongoing call to |IncomingEndpoint::OnReadMessage()| return false. This will - // make |ChannelEndpoint::OnReadMessage()| retry, until its |ReplaceClient()| - // is called. - DataPipe* data_pipe = new DataPipe( - false, true, validated_options, - make_scoped_ptr(new RemoteProducerDataPipeImpl( - channel_endpoint, std::move(buffer), 0, buffer_num_bytes))); - if (channel_endpoint) { - if (!channel_endpoint->ReplaceClient(data_pipe, 0)) - data_pipe->OnDetachFromChannel(0); - } else { - data_pipe->SetProducerClosed(); - } - return data_pipe; -} - -// static -DataPipe* DataPipe::CreateRemoteConsumerFromExisting( - const MojoCreateDataPipeOptions& validated_options, - size_t consumer_num_bytes, - MessageInTransitQueue* message_queue, - ChannelEndpoint* channel_endpoint) { - if (!RemoteConsumerDataPipeImpl::ProcessMessagesFromIncomingEndpoint( - validated_options, &consumer_num_bytes, message_queue)) - return nullptr; - - // Important: This is called under |IncomingEndpoint|'s (which is a - // |ChannelEndpointClient|) lock, in particular from - // |IncomingEndpoint::ConvertToDataPipeProducer()|. Before releasing that - // lock, it will reset its |endpoint_| member, which makes any later or - // ongoing call to |IncomingEndpoint::OnReadMessage()| return false. This will - // make |ChannelEndpoint::OnReadMessage()| retry, until its |ReplaceClient()| - // is called. - DataPipe* data_pipe = - new DataPipe(true, false, validated_options, - make_scoped_ptr(new RemoteConsumerDataPipeImpl( - channel_endpoint, consumer_num_bytes, nullptr, 0))); - if (channel_endpoint) { - if (!channel_endpoint->ReplaceClient(data_pipe, 0)) - data_pipe->OnDetachFromChannel(0); - } else { - data_pipe->SetConsumerClosed(); - } - return data_pipe; -} - -// static -bool DataPipe::ProducerDeserialize(Channel* channel, - const void* source, - size_t size, - scoped_refptr<DataPipe>* data_pipe) { - DCHECK(!*data_pipe); // Not technically wrong, but unlikely. - - bool consumer_open = false; - if (size == sizeof(SerializedDataPipeProducerDispatcher)) { - consumer_open = false; - } else if (size == - sizeof(SerializedDataPipeProducerDispatcher) + - channel->GetSerializedEndpointSize()) { - consumer_open = true; - } else { - LOG(ERROR) << "Invalid serialized data pipe producer"; - return false; - } - - const SerializedDataPipeProducerDispatcher* s = - static_cast<const SerializedDataPipeProducerDispatcher*>(source); - MojoCreateDataPipeOptions revalidated_options = {}; - if (ValidateCreateOptions(MakeUserPointer(&s->validated_options), - &revalidated_options) != MOJO_RESULT_OK) { - LOG(ERROR) << "Invalid serialized data pipe producer (bad options)"; - return false; - } - - if (!consumer_open) { - if (s->consumer_num_bytes != static_cast<uint32_t>(-1)) { - LOG(ERROR) - << "Invalid serialized data pipe producer (bad consumer_num_bytes)"; - return false; - } - - *data_pipe = new DataPipe(true, false, revalidated_options, - make_scoped_ptr(new RemoteConsumerDataPipeImpl( - nullptr, 0, nullptr, 0))); - (*data_pipe)->SetConsumerClosed(); - - return true; - } - - if (s->consumer_num_bytes > revalidated_options.capacity_num_bytes || - s->consumer_num_bytes % revalidated_options.element_num_bytes != 0) { - LOG(ERROR) - << "Invalid serialized data pipe producer (bad consumer_num_bytes)"; - return false; - } - - const void* endpoint_source = static_cast<const char*>(source) + - sizeof(SerializedDataPipeProducerDispatcher); - scoped_refptr<IncomingEndpoint> incoming_endpoint = - channel->DeserializeEndpoint(endpoint_source); - if (!incoming_endpoint) - return false; - - *data_pipe = incoming_endpoint->ConvertToDataPipeProducer( - revalidated_options, s->consumer_num_bytes); - if (!*data_pipe) - return false; - - return true; -} - -// static -bool DataPipe::ConsumerDeserialize(Channel* channel, - const void* source, - size_t size, - scoped_refptr<DataPipe>* data_pipe) { - DCHECK(!*data_pipe); // Not technically wrong, but unlikely. - - if (size != - sizeof(SerializedDataPipeConsumerDispatcher) + - channel->GetSerializedEndpointSize()) { - LOG(ERROR) << "Invalid serialized data pipe consumer"; - return false; - } - - const SerializedDataPipeConsumerDispatcher* s = - static_cast<const SerializedDataPipeConsumerDispatcher*>(source); - MojoCreateDataPipeOptions revalidated_options = {}; - if (ValidateCreateOptions(MakeUserPointer(&s->validated_options), - &revalidated_options) != MOJO_RESULT_OK) { - LOG(ERROR) << "Invalid serialized data pipe consumer (bad options)"; - return false; - } - - const void* endpoint_source = static_cast<const char*>(source) + - sizeof(SerializedDataPipeConsumerDispatcher); - scoped_refptr<IncomingEndpoint> incoming_endpoint = - channel->DeserializeEndpoint(endpoint_source); - if (!incoming_endpoint) - return false; - - *data_pipe = - incoming_endpoint->ConvertToDataPipeConsumer(revalidated_options); - if (!*data_pipe) - return false; - - return true; -} - -void DataPipe::ProducerCancelAllAwakables() { - base::AutoLock locker(lock_); - DCHECK(has_local_producer_no_lock()); - producer_awakable_list_->CancelAll(); -} - -void DataPipe::ProducerClose() { - base::AutoLock locker(lock_); - ProducerCloseNoLock(); -} - -MojoResult DataPipe::ProducerWriteData(UserPointer<const void> elements, - UserPointer<uint32_t> num_bytes, - bool all_or_none) { - base::AutoLock locker(lock_); - DCHECK(has_local_producer_no_lock()); - - if (producer_in_two_phase_write_no_lock()) - return MOJO_RESULT_BUSY; - if (!consumer_open_no_lock()) - return MOJO_RESULT_FAILED_PRECONDITION; - - // Returning "busy" takes priority over "invalid argument". - uint32_t max_num_bytes_to_write = num_bytes.Get(); - if (max_num_bytes_to_write % element_num_bytes() != 0) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (max_num_bytes_to_write == 0) - return MOJO_RESULT_OK; // Nothing to do. - - uint32_t min_num_bytes_to_write = all_or_none ? max_num_bytes_to_write : 0; - - HandleSignalsState old_consumer_state = - impl_->ConsumerGetHandleSignalsState(); - MojoResult rv = impl_->ProducerWriteData( - elements, num_bytes, max_num_bytes_to_write, min_num_bytes_to_write); - HandleSignalsState new_consumer_state = - impl_->ConsumerGetHandleSignalsState(); - if (!new_consumer_state.equals(old_consumer_state)) - AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state); - return rv; -} - -MojoResult DataPipe::ProducerBeginWriteData( - UserPointer<void*> buffer, - UserPointer<uint32_t> buffer_num_bytes) { - base::AutoLock locker(lock_); - DCHECK(has_local_producer_no_lock()); - - if (producer_in_two_phase_write_no_lock()) - return MOJO_RESULT_BUSY; - if (!consumer_open_no_lock()) - return MOJO_RESULT_FAILED_PRECONDITION; - - MojoResult rv = impl_->ProducerBeginWriteData(buffer, buffer_num_bytes); - if (rv != MOJO_RESULT_OK) - return rv; - // Note: No need to awake producer awakables, even though we're going from - // writable to non-writable (since you can't wait on non-writability). - // Similarly, though this may have discarded data (in "may discard" mode), - // making it non-readable, there's still no need to awake consumer awakables. - DCHECK(producer_in_two_phase_write_no_lock()); - return MOJO_RESULT_OK; -} - -MojoResult DataPipe::ProducerEndWriteData(uint32_t num_bytes_written) { - base::AutoLock locker(lock_); - DCHECK(has_local_producer_no_lock()); - - if (!producer_in_two_phase_write_no_lock()) - return MOJO_RESULT_FAILED_PRECONDITION; - // Note: Allow successful completion of the two-phase write even if the - // consumer has been closed. - - HandleSignalsState old_consumer_state = - impl_->ConsumerGetHandleSignalsState(); - MojoResult rv; - if (num_bytes_written > producer_two_phase_max_num_bytes_written_ || - num_bytes_written % element_num_bytes() != 0) { - rv = MOJO_RESULT_INVALID_ARGUMENT; - producer_two_phase_max_num_bytes_written_ = 0; - } else { - rv = impl_->ProducerEndWriteData(num_bytes_written); - } - // Two-phase write ended even on failure. - DCHECK(!producer_in_two_phase_write_no_lock()); - // If we're now writable, we *became* writable (since we weren't writable - // during the two-phase write), so awake producer awakables. - HandleSignalsState new_producer_state = - impl_->ProducerGetHandleSignalsState(); - if (new_producer_state.satisfies(MOJO_HANDLE_SIGNAL_WRITABLE)) - AwakeProducerAwakablesForStateChangeNoLock(new_producer_state); - HandleSignalsState new_consumer_state = - impl_->ConsumerGetHandleSignalsState(); - if (!new_consumer_state.equals(old_consumer_state)) - AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state); - return rv; -} - -HandleSignalsState DataPipe::ProducerGetHandleSignalsState() { - base::AutoLock locker(lock_); - DCHECK(has_local_producer_no_lock()); - return impl_->ProducerGetHandleSignalsState(); -} - -MojoResult DataPipe::ProducerAddAwakable(Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state) { - base::AutoLock locker(lock_); - DCHECK(has_local_producer_no_lock()); - - HandleSignalsState producer_state = impl_->ProducerGetHandleSignalsState(); - if (producer_state.satisfies(signals)) { - if (signals_state) - *signals_state = producer_state; - return MOJO_RESULT_ALREADY_EXISTS; - } - if (!producer_state.can_satisfy(signals)) { - if (signals_state) - *signals_state = producer_state; - return MOJO_RESULT_FAILED_PRECONDITION; - } - - producer_awakable_list_->Add(awakable, signals, context); - return MOJO_RESULT_OK; -} - -void DataPipe::ProducerRemoveAwakable(Awakable* awakable, - HandleSignalsState* signals_state) { - base::AutoLock locker(lock_); - DCHECK(has_local_producer_no_lock()); - producer_awakable_list_->Remove(awakable); - if (signals_state) - *signals_state = impl_->ProducerGetHandleSignalsState(); -} - -void DataPipe::ProducerStartSerialize(Channel* channel, - size_t* max_size, - size_t* max_platform_handles) { - base::AutoLock locker(lock_); - DCHECK(has_local_producer_no_lock()); - impl_->ProducerStartSerialize(channel, max_size, max_platform_handles); -} - -bool DataPipe::ProducerEndSerialize( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) { - base::AutoLock locker(lock_); - DCHECK(has_local_producer_no_lock()); - // Warning: After |ProducerEndSerialize()|, quite probably |impl_| has - // changed. - bool rv = impl_->ProducerEndSerialize(channel, destination, actual_size, - platform_handles); - - // TODO(vtl): The code below is similar to, but not quite the same as, - // |ProducerCloseNoLock()|. - DCHECK(has_local_producer_no_lock()); - producer_awakable_list_->CancelAll(); - producer_awakable_list_.reset(); - // Not a bug, except possibly in "user" code. - DVLOG_IF(2, producer_in_two_phase_write_no_lock()) - << "Producer transferred with active two-phase write"; - producer_two_phase_max_num_bytes_written_ = 0; - if (!has_local_consumer_no_lock()) - producer_open_ = false; - - return rv; -} - -bool DataPipe::ProducerIsBusy() const { - base::AutoLock locker(lock_); - return producer_in_two_phase_write_no_lock(); -} - -void DataPipe::ConsumerCancelAllAwakables() { - base::AutoLock locker(lock_); - DCHECK(has_local_consumer_no_lock()); - consumer_awakable_list_->CancelAll(); -} - -void DataPipe::ConsumerClose() { - base::AutoLock locker(lock_); - ConsumerCloseNoLock(); -} - -MojoResult DataPipe::ConsumerReadData(UserPointer<void> elements, - UserPointer<uint32_t> num_bytes, - bool all_or_none, - bool peek) { - base::AutoLock locker(lock_); - DCHECK(has_local_consumer_no_lock()); - - if (consumer_in_two_phase_read_no_lock()) - return MOJO_RESULT_BUSY; - - uint32_t max_num_bytes_to_read = num_bytes.Get(); - if (max_num_bytes_to_read % element_num_bytes() != 0) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (max_num_bytes_to_read == 0) - return MOJO_RESULT_OK; // Nothing to do. - - uint32_t min_num_bytes_to_read = all_or_none ? max_num_bytes_to_read : 0; - - HandleSignalsState old_producer_state = - impl_->ProducerGetHandleSignalsState(); - MojoResult rv = impl_->ConsumerReadData( - elements, num_bytes, max_num_bytes_to_read, min_num_bytes_to_read, peek); - HandleSignalsState new_producer_state = - impl_->ProducerGetHandleSignalsState(); - if (!new_producer_state.equals(old_producer_state)) - AwakeProducerAwakablesForStateChangeNoLock(new_producer_state); - return rv; -} - -MojoResult DataPipe::ConsumerDiscardData(UserPointer<uint32_t> num_bytes, - bool all_or_none) { - base::AutoLock locker(lock_); - DCHECK(has_local_consumer_no_lock()); - - if (consumer_in_two_phase_read_no_lock()) - return MOJO_RESULT_BUSY; - - uint32_t max_num_bytes_to_discard = num_bytes.Get(); - if (max_num_bytes_to_discard % element_num_bytes() != 0) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (max_num_bytes_to_discard == 0) - return MOJO_RESULT_OK; // Nothing to do. - - uint32_t min_num_bytes_to_discard = - all_or_none ? max_num_bytes_to_discard : 0; - - HandleSignalsState old_producer_state = - impl_->ProducerGetHandleSignalsState(); - MojoResult rv = impl_->ConsumerDiscardData( - num_bytes, max_num_bytes_to_discard, min_num_bytes_to_discard); - HandleSignalsState new_producer_state = - impl_->ProducerGetHandleSignalsState(); - if (!new_producer_state.equals(old_producer_state)) - AwakeProducerAwakablesForStateChangeNoLock(new_producer_state); - return rv; -} - -MojoResult DataPipe::ConsumerQueryData(UserPointer<uint32_t> num_bytes) { - base::AutoLock locker(lock_); - DCHECK(has_local_consumer_no_lock()); - - if (consumer_in_two_phase_read_no_lock()) - return MOJO_RESULT_BUSY; - - // Note: Don't need to validate |*num_bytes| for query. - return impl_->ConsumerQueryData(num_bytes); -} - -MojoResult DataPipe::ConsumerBeginReadData( - UserPointer<const void*> buffer, - UserPointer<uint32_t> buffer_num_bytes) { - base::AutoLock locker(lock_); - DCHECK(has_local_consumer_no_lock()); - - if (consumer_in_two_phase_read_no_lock()) - return MOJO_RESULT_BUSY; - - MojoResult rv = impl_->ConsumerBeginReadData(buffer, buffer_num_bytes); - if (rv != MOJO_RESULT_OK) - return rv; - DCHECK(consumer_in_two_phase_read_no_lock()); - return MOJO_RESULT_OK; -} - -MojoResult DataPipe::ConsumerEndReadData(uint32_t num_bytes_read) { - base::AutoLock locker(lock_); - DCHECK(has_local_consumer_no_lock()); - - if (!consumer_in_two_phase_read_no_lock()) - return MOJO_RESULT_FAILED_PRECONDITION; - - HandleSignalsState old_consumer_state = - impl_->ConsumerGetHandleSignalsState(); - HandleSignalsState old_producer_state = - impl_->ProducerGetHandleSignalsState(); - MojoResult rv; - if (num_bytes_read > consumer_two_phase_max_num_bytes_read_ || - num_bytes_read % element_num_bytes() != 0) { - rv = MOJO_RESULT_INVALID_ARGUMENT; - consumer_two_phase_max_num_bytes_read_ = 0; - } else { - rv = impl_->ConsumerEndReadData(num_bytes_read); - } - // Two-phase read ended even on failure. - DCHECK(!consumer_in_two_phase_read_no_lock()); - // If we're now readable, we *became* readable (since we weren't readable - // during the two-phase read), so awake consumer awakables. - HandleSignalsState new_consumer_state = - impl_->ConsumerGetHandleSignalsState(); - if (!new_consumer_state.equals(old_consumer_state)) - AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state); - HandleSignalsState new_producer_state = - impl_->ProducerGetHandleSignalsState(); - if (!new_producer_state.equals(old_producer_state)) - AwakeProducerAwakablesForStateChangeNoLock(new_producer_state); - return rv; -} - -HandleSignalsState DataPipe::ConsumerGetHandleSignalsState() { - base::AutoLock locker(lock_); - DCHECK(has_local_consumer_no_lock()); - return impl_->ConsumerGetHandleSignalsState(); -} - -MojoResult DataPipe::ConsumerAddAwakable(Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state) { - base::AutoLock locker(lock_); - DCHECK(has_local_consumer_no_lock()); - - HandleSignalsState consumer_state = impl_->ConsumerGetHandleSignalsState(); - if (consumer_state.satisfies(signals)) { - if (signals_state) - *signals_state = consumer_state; - return MOJO_RESULT_ALREADY_EXISTS; - } - if (!consumer_state.can_satisfy(signals)) { - if (signals_state) - *signals_state = consumer_state; - return MOJO_RESULT_FAILED_PRECONDITION; - } - - consumer_awakable_list_->Add(awakable, signals, context); - return MOJO_RESULT_OK; -} - -void DataPipe::ConsumerRemoveAwakable(Awakable* awakable, - HandleSignalsState* signals_state) { - base::AutoLock locker(lock_); - DCHECK(has_local_consumer_no_lock()); - consumer_awakable_list_->Remove(awakable); - if (signals_state) - *signals_state = impl_->ConsumerGetHandleSignalsState(); -} - -void DataPipe::ConsumerStartSerialize(Channel* channel, - size_t* max_size, - size_t* max_platform_handles) { - base::AutoLock locker(lock_); - DCHECK(has_local_consumer_no_lock()); - impl_->ConsumerStartSerialize(channel, max_size, max_platform_handles); -} - -bool DataPipe::ConsumerEndSerialize( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) { - base::AutoLock locker(lock_); - DCHECK(has_local_consumer_no_lock()); - // Warning: After |ConsumerEndSerialize()|, quite probably |impl_| has - // changed. - bool rv = impl_->ConsumerEndSerialize(channel, destination, actual_size, - platform_handles); - - // TODO(vtl): The code below is similar to, but not quite the same as, - // |ConsumerCloseNoLock()|. - consumer_awakable_list_->CancelAll(); - consumer_awakable_list_.reset(); - // Not a bug, except possibly in "user" code. - DVLOG_IF(2, consumer_in_two_phase_read_no_lock()) - << "Consumer transferred with active two-phase read"; - consumer_two_phase_max_num_bytes_read_ = 0; - if (!has_local_producer_no_lock()) - consumer_open_ = false; - - return rv; -} - -bool DataPipe::ConsumerIsBusy() const { - base::AutoLock locker(lock_); - return consumer_in_two_phase_read_no_lock(); -} - -DataPipe::DataPipe(bool has_local_producer, - bool has_local_consumer, - const MojoCreateDataPipeOptions& validated_options, - scoped_ptr<DataPipeImpl> impl) - : validated_options_(validated_options), - producer_open_(true), - consumer_open_(true), - producer_awakable_list_(has_local_producer ? new AwakableList() - : nullptr), - consumer_awakable_list_(has_local_consumer ? new AwakableList() - : nullptr), - producer_two_phase_max_num_bytes_written_(0), - consumer_two_phase_max_num_bytes_read_(0), - impl_(std::move(impl)) { - impl_->set_owner(this); - -#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) - // Check that the passed in options actually are validated. - MojoCreateDataPipeOptions unused = {}; - DCHECK_EQ(ValidateCreateOptions(MakeUserPointer(&validated_options), &unused), - MOJO_RESULT_OK); -#endif // !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) -} - -DataPipe::~DataPipe() { - DCHECK(!producer_open_); - DCHECK(!consumer_open_); - DCHECK(!producer_awakable_list_); - DCHECK(!consumer_awakable_list_); -} - -scoped_ptr<DataPipeImpl> DataPipe::ReplaceImplNoLock( - scoped_ptr<DataPipeImpl> new_impl) { - lock_.AssertAcquired(); - DCHECK(new_impl); - - impl_->set_owner(nullptr); - scoped_ptr<DataPipeImpl> rv(std::move(impl_)); - impl_ = std::move(new_impl); - impl_->set_owner(this); - return rv; -} - -void DataPipe::SetProducerClosedNoLock() { - lock_.AssertAcquired(); - DCHECK(!has_local_producer_no_lock()); - DCHECK(producer_open_); - producer_open_ = false; -} - -void DataPipe::SetConsumerClosedNoLock() { - lock_.AssertAcquired(); - DCHECK(!has_local_consumer_no_lock()); - DCHECK(consumer_open_); - consumer_open_ = false; -} - -void DataPipe::ProducerCloseNoLock() { - lock_.AssertAcquired(); - DCHECK(producer_open_); - producer_open_ = false; - if (has_local_producer_no_lock()) { - producer_awakable_list_.reset(); - // Not a bug, except possibly in "user" code. - DVLOG_IF(2, producer_in_two_phase_write_no_lock()) - << "Producer closed with active two-phase write"; - producer_two_phase_max_num_bytes_written_ = 0; - impl_->ProducerClose(); - AwakeConsumerAwakablesForStateChangeNoLock( - impl_->ConsumerGetHandleSignalsState()); - } -} - -void DataPipe::ConsumerCloseNoLock() { - lock_.AssertAcquired(); - DCHECK(consumer_open_); - consumer_open_ = false; - if (has_local_consumer_no_lock()) { - consumer_awakable_list_.reset(); - // Not a bug, except possibly in "user" code. - DVLOG_IF(2, consumer_in_two_phase_read_no_lock()) - << "Consumer closed with active two-phase read"; - consumer_two_phase_max_num_bytes_read_ = 0; - impl_->ConsumerClose(); - AwakeProducerAwakablesForStateChangeNoLock( - impl_->ProducerGetHandleSignalsState()); - } -} - -bool DataPipe::OnReadMessage(unsigned port, MessageInTransit* message) { - base::AutoLock locker(lock_); - DCHECK(!has_local_producer_no_lock() || !has_local_consumer_no_lock()); - - HandleSignalsState old_producer_state = - impl_->ProducerGetHandleSignalsState(); - HandleSignalsState old_consumer_state = - impl_->ConsumerGetHandleSignalsState(); - - bool rv = impl_->OnReadMessage(port, message); - - HandleSignalsState new_producer_state = - impl_->ProducerGetHandleSignalsState(); - if (!new_producer_state.equals(old_producer_state)) - AwakeProducerAwakablesForStateChangeNoLock(new_producer_state); - HandleSignalsState new_consumer_state = - impl_->ConsumerGetHandleSignalsState(); - if (!new_consumer_state.equals(old_consumer_state)) - AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state); - - return rv; -} - -void DataPipe::OnDetachFromChannel(unsigned port) { - base::AutoLock locker(lock_); - DCHECK(!has_local_producer_no_lock() || !has_local_consumer_no_lock()); - - HandleSignalsState old_producer_state = - impl_->ProducerGetHandleSignalsState(); - HandleSignalsState old_consumer_state = - impl_->ConsumerGetHandleSignalsState(); - - impl_->OnDetachFromChannel(port); - - HandleSignalsState new_producer_state = - impl_->ProducerGetHandleSignalsState(); - if (!new_producer_state.equals(old_producer_state)) - AwakeProducerAwakablesForStateChangeNoLock(new_producer_state); - HandleSignalsState new_consumer_state = - impl_->ConsumerGetHandleSignalsState(); - if (!new_consumer_state.equals(old_consumer_state)) - AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state); -} - -void DataPipe::AwakeProducerAwakablesForStateChangeNoLock( - const HandleSignalsState& new_producer_state) { - lock_.AssertAcquired(); - if (!has_local_producer_no_lock()) - return; - producer_awakable_list_->AwakeForStateChange(new_producer_state); -} - -void DataPipe::AwakeConsumerAwakablesForStateChangeNoLock( - const HandleSignalsState& new_consumer_state) { - lock_.AssertAcquired(); - if (!has_local_consumer_no_lock()) - return; - consumer_awakable_list_->AwakeForStateChange(new_consumer_state); -} - -void DataPipe::SetProducerClosed() { - base::AutoLock locker(lock_); - SetProducerClosedNoLock(); -} - -void DataPipe::SetConsumerClosed() { - base::AutoLock locker(lock_); - SetConsumerClosedNoLock(); -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/data_pipe.h b/third_party/mojo/src/mojo/edk/system/data_pipe.h deleted file mode 100644 index de340c9..0000000 --- a/third_party/mojo/src/mojo/edk/system/data_pipe.h +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_DATA_PIPE_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_DATA_PIPE_H_ - -#include <stdint.h> - -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "base/synchronization/lock.h" -#include "mojo/public/c/system/data_pipe.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle_vector.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint_client.h" -#include "third_party/mojo/src/mojo/edk/system/handle_signals_state.h" -#include "third_party/mojo/src/mojo/edk/system/memory.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -class Awakable; -class AwakableList; -class Channel; -class ChannelEndpoint; -class DataPipeImpl; -class MessageInTransitQueue; - -// |DataPipe| is a base class for secondary objects implementing data pipes, -// similar to |MessagePipe| (see the explanatory comment in core.cc). It is -// typically owned by the dispatcher(s) corresponding to the local endpoints. -// Its subclasses implement the three cases: local producer and consumer, local -// producer and remote consumer, and remote producer and local consumer. This -// class is thread-safe. -class MOJO_SYSTEM_IMPL_EXPORT DataPipe final : public ChannelEndpointClient { - public: - // The default options for |MojoCreateDataPipe()|. (Real uses should obtain - // this via |ValidateCreateOptions()| with a null |in_options|; this is - // exposed directly for testing convenience.) - static MojoCreateDataPipeOptions GetDefaultCreateOptions(); - - // Validates and/or sets default options for |MojoCreateDataPipeOptions|. If - // non-null, |in_options| must point to a struct of at least - // |in_options->struct_size| bytes. |out_options| must point to a (current) - // |MojoCreateDataPipeOptions| and will be entirely overwritten on success (it - // may be partly overwritten on failure). - static MojoResult ValidateCreateOptions( - UserPointer<const MojoCreateDataPipeOptions> in_options, - MojoCreateDataPipeOptions* out_options); - - // Creates a local (both producer and consumer) data pipe (using - // |LocalDataPipeImpl|. |validated_options| should be the output of - // |ValidateOptions()|. In particular: |struct_size| is ignored (so - // |validated_options| must be the current version of the struct) and - // |capacity_num_bytes| must be nonzero. - static DataPipe* CreateLocal( - const MojoCreateDataPipeOptions& validated_options); - - // Creates a data pipe with a remote producer and a local consumer, using an - // existing |ChannelEndpoint| (whose |ReplaceClient()| it'll call) and taking - // |message_queue|'s contents as already-received incoming messages. If - // |channel_endpoint| is null, this will create a "half-open" data pipe (with - // only the consumer open). Note that this may fail, in which case it returns - // null. - static DataPipe* CreateRemoteProducerFromExisting( - const MojoCreateDataPipeOptions& validated_options, - MessageInTransitQueue* message_queue, - ChannelEndpoint* channel_endpoint); - - // Creates a data pipe with a local producer and a remote consumer, using an - // existing |ChannelEndpoint| (whose |ReplaceClient()| it'll call) and taking - // |message_queue|'s contents as already-received incoming messages - // (|message_queue| may be null). If |channel_endpoint| is null, this will - // create a "half-open" data pipe (with only the producer open). Note that - // this may fail, in which case it returns null. - static DataPipe* CreateRemoteConsumerFromExisting( - const MojoCreateDataPipeOptions& validated_options, - size_t consumer_num_bytes, - MessageInTransitQueue* message_queue, - ChannelEndpoint* channel_endpoint); - - // Used by |DataPipeProducerDispatcher::Deserialize()|. Returns true on - // success (in which case, |*data_pipe| is set appropriately) and false on - // failure (in which case |*data_pipe| may or may not be set to null). - static bool ProducerDeserialize(Channel* channel, - const void* source, - size_t size, - scoped_refptr<DataPipe>* data_pipe); - - // Used by |DataPipeConsumerDispatcher::Deserialize()|. Returns true on - // success (in which case, |*data_pipe| is set appropriately) and false on - // failure (in which case |*data_pipe| may or may not be set to null). - static bool ConsumerDeserialize(Channel* channel, - const void* source, - size_t size, - scoped_refptr<DataPipe>* data_pipe); - - // These are called by the producer dispatcher to implement its methods of - // corresponding names. - void ProducerCancelAllAwakables(); - void ProducerClose(); - MojoResult ProducerWriteData(UserPointer<const void> elements, - UserPointer<uint32_t> num_bytes, - bool all_or_none); - MojoResult ProducerBeginWriteData(UserPointer<void*> buffer, - UserPointer<uint32_t> buffer_num_bytes); - MojoResult ProducerEndWriteData(uint32_t num_bytes_written); - HandleSignalsState ProducerGetHandleSignalsState(); - MojoResult ProducerAddAwakable(Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state); - void ProducerRemoveAwakable(Awakable* awakable, - HandleSignalsState* signals_state); - void ProducerStartSerialize(Channel* channel, - size_t* max_size, - size_t* max_platform_handles); - bool ProducerEndSerialize(Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles); - bool ProducerIsBusy() const; - - // These are called by the consumer dispatcher to implement its methods of - // corresponding names. - void ConsumerCancelAllAwakables(); - void ConsumerClose(); - // This does not validate its arguments, except to check that |*num_bytes| is - // a multiple of |element_num_bytes_|. - MojoResult ConsumerReadData(UserPointer<void> elements, - UserPointer<uint32_t> num_bytes, - bool all_or_none, - bool peek); - MojoResult ConsumerDiscardData(UserPointer<uint32_t> num_bytes, - bool all_or_none); - MojoResult ConsumerQueryData(UserPointer<uint32_t> num_bytes); - MojoResult ConsumerBeginReadData(UserPointer<const void*> buffer, - UserPointer<uint32_t> buffer_num_bytes); - MojoResult ConsumerEndReadData(uint32_t num_bytes_read); - HandleSignalsState ConsumerGetHandleSignalsState(); - MojoResult ConsumerAddAwakable(Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state); - void ConsumerRemoveAwakable(Awakable* awakable, - HandleSignalsState* signals_state); - void ConsumerStartSerialize(Channel* channel, - size_t* max_size, - size_t* max_platform_handles); - bool ConsumerEndSerialize(Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles); - bool ConsumerIsBusy() const; - - // The following are only to be used by |DataPipeImpl| (and its subclasses): - - // Replaces |impl_| with |new_impl| (which must not be null). For use when - // serializing data pipe dispatchers (i.e., in |ProducerEndSerialize()| and - // |ConsumerEndSerialize()|). Returns the old value of |impl_| (in case the - // caller needs to manage its lifetime). - scoped_ptr<DataPipeImpl> ReplaceImplNoLock(scoped_ptr<DataPipeImpl> new_impl); - void SetProducerClosedNoLock(); - void SetConsumerClosedNoLock(); - - void ProducerCloseNoLock(); - void ConsumerCloseNoLock(); - - // Thread-safe and fast (they don't take the lock): - const MojoCreateDataPipeOptions& validated_options() const { - return validated_options_; - } - size_t element_num_bytes() const { - return validated_options_.element_num_bytes; - } - size_t capacity_num_bytes() const { - return validated_options_.capacity_num_bytes; - } - - // Must be called under lock. - bool producer_open_no_lock() const { - lock_.AssertAcquired(); - return producer_open_; - } - bool consumer_open_no_lock() const { - lock_.AssertAcquired(); - return consumer_open_; - } - uint32_t producer_two_phase_max_num_bytes_written_no_lock() const { - lock_.AssertAcquired(); - return producer_two_phase_max_num_bytes_written_; - } - uint32_t consumer_two_phase_max_num_bytes_read_no_lock() const { - lock_.AssertAcquired(); - return consumer_two_phase_max_num_bytes_read_; - } - void set_producer_two_phase_max_num_bytes_written_no_lock( - uint32_t num_bytes) { - lock_.AssertAcquired(); - producer_two_phase_max_num_bytes_written_ = num_bytes; - } - void set_consumer_two_phase_max_num_bytes_read_no_lock(uint32_t num_bytes) { - lock_.AssertAcquired(); - consumer_two_phase_max_num_bytes_read_ = num_bytes; - } - bool producer_in_two_phase_write_no_lock() const { - lock_.AssertAcquired(); - return producer_two_phase_max_num_bytes_written_ > 0; - } - bool consumer_in_two_phase_read_no_lock() const { - lock_.AssertAcquired(); - return consumer_two_phase_max_num_bytes_read_ > 0; - } - - private: - // |validated_options| should be the output of |ValidateOptions()|. In - // particular: |struct_size| is ignored (so |validated_options| must be the - // current version of the struct) and |capacity_num_bytes| must be nonzero. - // TODO(vtl): |has_local_producer|/|has_local_consumer| shouldn't really be - // arguments here. Instead, they should be determined from the |impl| ... but - // the |impl|'s typically figures these out by examining the owner, i.e., the - // |DataPipe| object. Probably, this indicates that more stuff should be moved - // to |DataPipeImpl|, but for now we'll live with this. - DataPipe(bool has_local_producer, - bool has_local_consumer, - const MojoCreateDataPipeOptions& validated_options, - scoped_ptr<DataPipeImpl> impl); - ~DataPipe() override; - - // |ChannelEndpointClient| implementation: - bool OnReadMessage(unsigned port, MessageInTransit* message) override; - void OnDetachFromChannel(unsigned port) override; - - void AwakeProducerAwakablesForStateChangeNoLock( - const HandleSignalsState& new_producer_state); - void AwakeConsumerAwakablesForStateChangeNoLock( - const HandleSignalsState& new_consumer_state); - - void SetProducerClosed(); - void SetConsumerClosed(); - - bool has_local_producer_no_lock() const { - lock_.AssertAcquired(); - return !!producer_awakable_list_; - } - bool has_local_consumer_no_lock() const { - lock_.AssertAcquired(); - return !!consumer_awakable_list_; - } - - MSVC_SUPPRESS_WARNING(4324) - const MojoCreateDataPipeOptions validated_options_; - - mutable base::Lock lock_; // Protects the following members. - // *Known* state of producer or consumer. - bool producer_open_; - bool consumer_open_; - // Non-null only if the producer or consumer, respectively, is local. - scoped_ptr<AwakableList> producer_awakable_list_; - scoped_ptr<AwakableList> consumer_awakable_list_; - // These are nonzero if and only if a two-phase write/read is in progress. - uint32_t producer_two_phase_max_num_bytes_written_; - uint32_t consumer_two_phase_max_num_bytes_read_; - scoped_ptr<DataPipeImpl> impl_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(DataPipe); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_DATA_PIPE_H_ diff --git a/third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.cc b/third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.cc deleted file mode 100644 index c31e462..0000000 --- a/third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.cc +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.h" - -#include "base/logging.h" -#include "third_party/mojo/src/mojo/edk/system/data_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/memory.h" - -namespace mojo { -namespace system { - -void DataPipeConsumerDispatcher::Init(scoped_refptr<DataPipe> data_pipe) { - DCHECK(data_pipe); - data_pipe_ = data_pipe; -} - -Dispatcher::Type DataPipeConsumerDispatcher::GetType() const { - return Type::DATA_PIPE_CONSUMER; -} - -// static -scoped_refptr<DataPipeConsumerDispatcher> -DataPipeConsumerDispatcher::Deserialize(Channel* channel, - const void* source, - size_t size) { - scoped_refptr<DataPipe> data_pipe; - if (!DataPipe::ConsumerDeserialize(channel, source, size, &data_pipe)) - return nullptr; - DCHECK(data_pipe); - - scoped_refptr<DataPipeConsumerDispatcher> dispatcher = Create(); - dispatcher->Init(data_pipe); - return dispatcher; -} - -DataPipe* DataPipeConsumerDispatcher::GetDataPipeForTest() { - MutexLocker locker(&mutex()); - return data_pipe_.get(); -} - -DataPipeConsumerDispatcher::DataPipeConsumerDispatcher() { -} - -DataPipeConsumerDispatcher::~DataPipeConsumerDispatcher() { - // |Close()|/|CloseImplNoLock()| should have taken care of the pipe. - DCHECK(!data_pipe_); -} - -void DataPipeConsumerDispatcher::CancelAllAwakablesNoLock() { - mutex().AssertHeld(); - data_pipe_->ConsumerCancelAllAwakables(); -} - -void DataPipeConsumerDispatcher::CloseImplNoLock() { - mutex().AssertHeld(); - data_pipe_->ConsumerClose(); - data_pipe_ = nullptr; -} - -scoped_refptr<Dispatcher> -DataPipeConsumerDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() { - mutex().AssertHeld(); - - scoped_refptr<DataPipeConsumerDispatcher> rv = Create(); - rv->Init(data_pipe_); - data_pipe_ = nullptr; - return scoped_refptr<Dispatcher>(rv.get()); -} - -MojoResult DataPipeConsumerDispatcher::ReadDataImplNoLock( - UserPointer<void> elements, - UserPointer<uint32_t> num_bytes, - MojoReadDataFlags flags) { - mutex().AssertHeld(); - - if ((flags & MOJO_READ_DATA_FLAG_DISCARD)) { - // These flags are mutally exclusive. - if ((flags & MOJO_READ_DATA_FLAG_QUERY) || - (flags & MOJO_READ_DATA_FLAG_PEEK)) - return MOJO_RESULT_INVALID_ARGUMENT; - DVLOG_IF(2, !elements.IsNull()) - << "Discard mode: ignoring non-null |elements|"; - return data_pipe_->ConsumerDiscardData( - num_bytes, (flags & MOJO_READ_DATA_FLAG_ALL_OR_NONE)); - } - - if ((flags & MOJO_READ_DATA_FLAG_QUERY)) { - if ((flags & MOJO_READ_DATA_FLAG_PEEK)) - return MOJO_RESULT_INVALID_ARGUMENT; - DCHECK(!(flags & MOJO_READ_DATA_FLAG_DISCARD)); // Handled above. - DVLOG_IF(2, !elements.IsNull()) - << "Query mode: ignoring non-null |elements|"; - return data_pipe_->ConsumerQueryData(num_bytes); - } - - return data_pipe_->ConsumerReadData( - elements, num_bytes, !!(flags & MOJO_READ_DATA_FLAG_ALL_OR_NONE), - !!(flags & MOJO_READ_DATA_FLAG_PEEK)); -} - -MojoResult DataPipeConsumerDispatcher::BeginReadDataImplNoLock( - UserPointer<const void*> buffer, - UserPointer<uint32_t> buffer_num_bytes, - MojoReadDataFlags flags) { - mutex().AssertHeld(); - - // These flags may not be used in two-phase mode. - if ((flags & MOJO_READ_DATA_FLAG_DISCARD) || - (flags & MOJO_READ_DATA_FLAG_QUERY) || (flags & MOJO_READ_DATA_FLAG_PEEK)) - return MOJO_RESULT_INVALID_ARGUMENT; - - return data_pipe_->ConsumerBeginReadData(buffer, buffer_num_bytes); -} - -MojoResult DataPipeConsumerDispatcher::EndReadDataImplNoLock( - uint32_t num_bytes_read) { - mutex().AssertHeld(); - - return data_pipe_->ConsumerEndReadData(num_bytes_read); -} - -HandleSignalsState DataPipeConsumerDispatcher::GetHandleSignalsStateImplNoLock() - const { - mutex().AssertHeld(); - return data_pipe_->ConsumerGetHandleSignalsState(); -} - -MojoResult DataPipeConsumerDispatcher::AddAwakableImplNoLock( - Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state) { - mutex().AssertHeld(); - return data_pipe_->ConsumerAddAwakable(awakable, signals, context, - signals_state); -} - -void DataPipeConsumerDispatcher::RemoveAwakableImplNoLock( - Awakable* awakable, - HandleSignalsState* signals_state) { - mutex().AssertHeld(); - data_pipe_->ConsumerRemoveAwakable(awakable, signals_state); -} - -void DataPipeConsumerDispatcher::StartSerializeImplNoLock( - Channel* channel, - size_t* max_size, - size_t* max_platform_handles) { - DCHECK(HasOneRef()); // Only one ref => no need to take the lock. - data_pipe_->ConsumerStartSerialize(channel, max_size, max_platform_handles); -} - -bool DataPipeConsumerDispatcher::EndSerializeAndCloseImplNoLock( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) { - DCHECK(HasOneRef()); // Only one ref => no need to take the lock. - - bool rv = data_pipe_->ConsumerEndSerialize(channel, destination, actual_size, - platform_handles); - data_pipe_ = nullptr; - return rv; -} - -bool DataPipeConsumerDispatcher::IsBusyNoLock() const { - mutex().AssertHeld(); - return data_pipe_->ConsumerIsBusy(); -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.h b/third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.h deleted file mode 100644 index 138c629..0000000 --- a/third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.h +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_DATA_PIPE_CONSUMER_DISPATCHER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_DATA_PIPE_CONSUMER_DISPATCHER_H_ - -#include "base/memory/ref_counted.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -class DataPipe; - -// This is the |Dispatcher| implementation for the consumer handle for data -// pipes (created by the Mojo primitive |MojoCreateDataPipe()|). This class is -// thread-safe. -class MOJO_SYSTEM_IMPL_EXPORT DataPipeConsumerDispatcher final - : public Dispatcher { - public: - static scoped_refptr<DataPipeConsumerDispatcher> Create() { - return make_scoped_refptr(new DataPipeConsumerDispatcher()); - } - - // Must be called before any other methods. - void Init(scoped_refptr<DataPipe> data_pipe) MOJO_NOT_THREAD_SAFE; - - // |Dispatcher| public methods: - Type GetType() const override; - - // The "opposite" of |SerializeAndClose()|. (Typically this is called by - // |Dispatcher::Deserialize()|.) - static scoped_refptr<DataPipeConsumerDispatcher> - Deserialize(Channel* channel, const void* source, size_t size); - - // Get access to the |DataPipe| for testing. - DataPipe* GetDataPipeForTest(); - - private: - DataPipeConsumerDispatcher(); - ~DataPipeConsumerDispatcher() override; - - // |Dispatcher| protected methods: - void CancelAllAwakablesNoLock() override; - void CloseImplNoLock() override; - scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock() - override; - MojoResult ReadDataImplNoLock(UserPointer<void> elements, - UserPointer<uint32_t> num_bytes, - MojoReadDataFlags flags) override; - MojoResult BeginReadDataImplNoLock(UserPointer<const void*> buffer, - UserPointer<uint32_t> buffer_num_bytes, - MojoReadDataFlags flags) override; - MojoResult EndReadDataImplNoLock(uint32_t num_bytes_read) override; - HandleSignalsState GetHandleSignalsStateImplNoLock() const override; - MojoResult AddAwakableImplNoLock(Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state) override; - void RemoveAwakableImplNoLock(Awakable* awakable, - HandleSignalsState* signals_state) override; - void StartSerializeImplNoLock(Channel* channel, - size_t* max_size, - size_t* max_platform_handles) override - MOJO_NOT_THREAD_SAFE; - bool EndSerializeAndCloseImplNoLock( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) override - MOJO_NOT_THREAD_SAFE; - bool IsBusyNoLock() const override; - - // This will be null if closed. - scoped_refptr<DataPipe> data_pipe_ MOJO_GUARDED_BY(mutex()); - - MOJO_DISALLOW_COPY_AND_ASSIGN(DataPipeConsumerDispatcher); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_DATA_PIPE_CONSUMER_DISPATCHER_H_ diff --git a/third_party/mojo/src/mojo/edk/system/data_pipe_impl.cc b/third_party/mojo/src/mojo/edk/system/data_pipe_impl.cc deleted file mode 100644 index c7b534c..0000000 --- a/third_party/mojo/src/mojo/edk/system/data_pipe_impl.cc +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2015 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 "third_party/mojo/src/mojo/edk/system/data_pipe_impl.h" - -#include <algorithm> -#include <utility> - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "third_party/mojo/src/mojo/edk/system/configuration.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit_queue.h" - -namespace mojo { -namespace system { - -void DataPipeImpl::ConvertDataToMessages(const char* buffer, - size_t* start_index, - size_t* current_num_bytes, - MessageInTransitQueue* message_queue) { - // The maximum amount of data to send per message (make it a multiple of the - // element size. - size_t max_message_num_bytes = GetConfiguration().max_message_num_bytes; - max_message_num_bytes -= max_message_num_bytes % element_num_bytes(); - DCHECK_GT(max_message_num_bytes, 0u); - - while (*current_num_bytes > 0) { - size_t current_contiguous_num_bytes = - (*start_index + *current_num_bytes > capacity_num_bytes()) - ? (capacity_num_bytes() - *start_index) - : *current_num_bytes; - size_t message_num_bytes = - std::min(max_message_num_bytes, current_contiguous_num_bytes); - - // Note: |message_num_bytes| fits in a |uint32_t| since the capacity does. - scoped_ptr<MessageInTransit> message(new MessageInTransit( - MessageInTransit::Type::ENDPOINT_CLIENT, - MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, - static_cast<uint32_t>(message_num_bytes), buffer + *start_index)); - message_queue->AddMessage(std::move(message)); - - DCHECK_LE(message_num_bytes, *current_num_bytes); - *start_index += message_num_bytes; - *start_index %= capacity_num_bytes(); - *current_num_bytes -= message_num_bytes; - } -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/data_pipe_impl.h b/third_party/mojo/src/mojo/edk/system/data_pipe_impl.h deleted file mode 100644 index 391bb34..0000000 --- a/third_party/mojo/src/mojo/edk/system/data_pipe_impl.h +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2015 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_DATA_PIPE_IMPL_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_DATA_PIPE_IMPL_H_ - -#include <stdint.h> - -#include "mojo/public/c/system/data_pipe.h" -#include "mojo/public/c/system/macros.h" -#include "mojo/public/c/system/types.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle_vector.h" -#include "third_party/mojo/src/mojo/edk/system/data_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/handle_signals_state.h" -#include "third_party/mojo/src/mojo/edk/system/memory.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -class Channel; -class MessageInTransit; - -// Base class/interface for classes that "implement" |DataPipe| for various -// situations (local versus remote). The methods, other than the constructor, -// |set_owner()|, and the destructor, are always protected by |DataPipe|'s -// |lock_|. -class MOJO_SYSTEM_IMPL_EXPORT DataPipeImpl { - public: - virtual ~DataPipeImpl() {} - - // This is only called by |DataPipe| during its construction. - void set_owner(DataPipe* owner) { owner_ = owner; } - - virtual void ProducerClose() = 0; - // |num_bytes.Get()| will be a nonzero multiple of |element_num_bytes()|. - virtual MojoResult ProducerWriteData(UserPointer<const void> elements, - UserPointer<uint32_t> num_bytes, - uint32_t max_num_bytes_to_write, - uint32_t min_num_bytes_to_write) = 0; - virtual MojoResult ProducerBeginWriteData( - UserPointer<void*> buffer, - UserPointer<uint32_t> buffer_num_bytes) = 0; - virtual MojoResult ProducerEndWriteData(uint32_t num_bytes_written) = 0; - // Note: A producer should not be writable during a two-phase write. - virtual HandleSignalsState ProducerGetHandleSignalsState() const = 0; - virtual void ProducerStartSerialize(Channel* channel, - size_t* max_size, - size_t* max_platform_handles) = 0; - virtual bool ProducerEndSerialize( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) = 0; - - virtual void ConsumerClose() = 0; - // |num_bytes.Get()| will be a nonzero multiple of |element_num_bytes()|. - virtual MojoResult ConsumerReadData(UserPointer<void> elements, - UserPointer<uint32_t> num_bytes, - uint32_t max_num_bytes_to_read, - uint32_t min_num_bytes_to_read, - bool peek) = 0; - virtual MojoResult ConsumerDiscardData(UserPointer<uint32_t> num_bytes, - uint32_t max_num_bytes_to_discard, - uint32_t min_num_bytes_to_discard) = 0; - // |num_bytes.Get()| will be a nonzero multiple of |element_num_bytes()|. - virtual MojoResult ConsumerQueryData(UserPointer<uint32_t> num_bytes) = 0; - virtual MojoResult ConsumerBeginReadData( - UserPointer<const void*> buffer, - UserPointer<uint32_t> buffer_num_bytes) = 0; - virtual MojoResult ConsumerEndReadData(uint32_t num_bytes_read) = 0; - // Note: A consumer should not be writable during a two-phase read. - virtual HandleSignalsState ConsumerGetHandleSignalsState() const = 0; - virtual void ConsumerStartSerialize(Channel* channel, - size_t* max_size, - size_t* max_platform_handles) = 0; - virtual bool ConsumerEndSerialize( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) = 0; - - virtual bool OnReadMessage(unsigned port, MessageInTransit* message) = 0; - virtual void OnDetachFromChannel(unsigned port) = 0; - - protected: - DataPipeImpl() : owner_() {} - - // Helper to convert the given circular buffer into messages. The input is a - // circular buffer |buffer| (with appropriate element size and capacity), with - // current contents starting at |start_index| of length |current_num_bytes|. - // This will convert all of the contents. - void ConvertDataToMessages(const char* buffer, - size_t* start_index, - size_t* current_num_bytes, - MessageInTransitQueue* message_queue); - - DataPipe* owner() const { return owner_; } - - const MojoCreateDataPipeOptions& validated_options() const { - return owner_->validated_options(); - } - size_t element_num_bytes() const { return owner_->element_num_bytes(); } - size_t capacity_num_bytes() const { return owner_->capacity_num_bytes(); } - bool producer_open() const { return owner_->producer_open_no_lock(); } - bool consumer_open() const { return owner_->consumer_open_no_lock(); } - uint32_t producer_two_phase_max_num_bytes_written() const { - return owner_->producer_two_phase_max_num_bytes_written_no_lock(); - } - uint32_t consumer_two_phase_max_num_bytes_read() const { - return owner_->consumer_two_phase_max_num_bytes_read_no_lock(); - } - void set_producer_two_phase_max_num_bytes_written(uint32_t num_bytes) { - owner_->set_producer_two_phase_max_num_bytes_written_no_lock(num_bytes); - } - void set_consumer_two_phase_max_num_bytes_read(uint32_t num_bytes) { - owner_->set_consumer_two_phase_max_num_bytes_read_no_lock(num_bytes); - } - bool producer_in_two_phase_write() const { - return owner_->producer_in_two_phase_write_no_lock(); - } - bool consumer_in_two_phase_read() const { - return owner_->consumer_in_two_phase_read_no_lock(); - } - - private: - DataPipe* owner_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(DataPipeImpl); -}; - -// TODO(vtl): This is not the ideal place for the following structs; find -// somewhere better. - -// Serialized form of a producer dispatcher. This will actually be followed by a -// serialized |ChannelEndpoint|; we want to preserve alignment guarantees. -struct MOJO_ALIGNAS(8) SerializedDataPipeProducerDispatcher { - // Only validated (and thus canonicalized) options should be serialized. - // However, the deserializer must revalidate (as with everything received). - MojoCreateDataPipeOptions validated_options; - // Number of bytes already enqueued to the consumer. Set to - // |static_cast<uint32_t>(-1)| if the consumer is already closed, in which - // case this will *not* be followed by a serialized |ChannelEndpoint|. - uint32_t consumer_num_bytes; -}; - -// Serialized form of a consumer dispatcher. This will actually be followed by a -// serialized |ChannelEndpoint|; we want to preserve alignment guarantees. -struct MOJO_ALIGNAS(8) SerializedDataPipeConsumerDispatcher { - // Only validated (and thus canonicalized) options should be serialized. - // However, the deserializer must revalidate (as with everything received). - MojoCreateDataPipeOptions validated_options; -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_DATA_PIPE_IMPL_H_ diff --git a/third_party/mojo/src/mojo/edk/system/data_pipe_impl_unittest.cc b/third_party/mojo/src/mojo/edk/system/data_pipe_impl_unittest.cc deleted file mode 100644 index efe8bb5..0000000 --- a/third_party/mojo/src/mojo/edk/system/data_pipe_impl_unittest.cc +++ /dev/null @@ -1,2438 +0,0 @@ -// Copyright 2015 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. - -// This file contains tests that are shared between different implementations of -// |DataPipeImpl|. - -#include "third_party/mojo/src/mojo/edk/system/data_pipe_impl.h" - -#include <stdint.h> - -#include "base/bind.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" -#include "base/test/test_io_thread.h" -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" -#include "third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h" -#include "third_party/mojo/src/mojo/edk/system/channel.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/data_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/memory.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/raw_channel.h" -#include "third_party/mojo/src/mojo/edk/system/test_utils.h" -#include "third_party/mojo/src/mojo/edk/system/waiter.h" - -namespace mojo { -namespace system { -namespace { - -const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED; -const uint32_t kSizeOfOptions = - static_cast<uint32_t>(sizeof(MojoCreateDataPipeOptions)); - -// In various places, we have to poll (since, e.g., we can't yet wait for a -// certain amount of data to be available). This is the maximum number of -// iterations (separated by a short sleep). -// TODO(vtl): Get rid of this. -const size_t kMaxPoll = 100; - -// DataPipeImplTestHelper ------------------------------------------------------ - -class DataPipeImplTestHelper { - public: - virtual ~DataPipeImplTestHelper() {} - - virtual void SetUp() = 0; - virtual void TearDown() = 0; - - virtual void Create(const MojoCreateDataPipeOptions& validated_options) = 0; - - // Returns true if the producer and consumer exhibit the behavior that you'd - // expect from a pure circular buffer implementation (reflected to two-phase - // reads and writes). - virtual bool IsStrictCircularBuffer() const = 0; - - // Possibly transfers the producer/consumer. - virtual void DoTransfer() = 0; - - // Returns the |DataPipe| object for the producer and consumer, respectively. - virtual DataPipe* DataPipeForProducer() = 0; - virtual DataPipe* DataPipeForConsumer() = 0; - - // Closes the producer and consumer, respectively. (Other operations go - // through the above accessors; closing is special since it may require that a - // dispatcher be closed.) - virtual void ProducerClose() = 0; - virtual void ConsumerClose() = 0; - - protected: - DataPipeImplTestHelper() {} - - private: - MOJO_DISALLOW_COPY_AND_ASSIGN(DataPipeImplTestHelper); -}; - -// DataPipeImplTest ------------------------------------------------------------ - -template <class Helper> -class DataPipeImplTest : public testing::Test { - public: - DataPipeImplTest() {} - ~DataPipeImplTest() override {} - - void SetUp() override { Reset(); } - void TearDown() override { helper_->TearDown(); } - - protected: - void Create(const MojoCreateDataPipeOptions& options) { - MojoCreateDataPipeOptions validated_options = {}; - ASSERT_EQ(MOJO_RESULT_OK, - DataPipe::ValidateCreateOptions(MakeUserPointer(&options), - &validated_options)); - helper_->Create(validated_options); - } - - bool IsStrictCircularBuffer() const { - return helper_->IsStrictCircularBuffer(); - } - - void DoTransfer() { return helper_->DoTransfer(); } - - void Reset() { - if (helper_) - helper_->TearDown(); - - helper_.reset(new Helper()); - helper_->SetUp(); - } - - void ProducerClose() { helper_->ProducerClose(); } - MojoResult ProducerWriteData(UserPointer<const void> elements, - UserPointer<uint32_t> num_bytes, - bool all_or_none) { - return dpp()->ProducerWriteData(elements, num_bytes, all_or_none); - } - MojoResult ProducerBeginWriteData(UserPointer<void*> buffer, - UserPointer<uint32_t> buffer_num_bytes) { - return dpp()->ProducerBeginWriteData(buffer, buffer_num_bytes); - } - MojoResult ProducerEndWriteData(uint32_t num_bytes_written) { - return dpp()->ProducerEndWriteData(num_bytes_written); - } - MojoResult ProducerAddAwakable(Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state) { - return dpp()->ProducerAddAwakable(awakable, signals, context, - signals_state); - } - void ProducerRemoveAwakable(Awakable* awakable, - HandleSignalsState* signals_state) { - return dpp()->ProducerRemoveAwakable(awakable, signals_state); - } - - void ConsumerClose() { helper_->ConsumerClose(); } - MojoResult ConsumerReadData(UserPointer<void> elements, - UserPointer<uint32_t> num_bytes, - bool all_or_none, - bool peek) { - return dpc()->ConsumerReadData(elements, num_bytes, all_or_none, peek); - } - MojoResult ConsumerDiscardData(UserPointer<uint32_t> num_bytes, - bool all_or_none) { - return dpc()->ConsumerDiscardData(num_bytes, all_or_none); - } - MojoResult ConsumerQueryData(UserPointer<uint32_t> num_bytes) { - return dpc()->ConsumerQueryData(num_bytes); - } - MojoResult ConsumerBeginReadData(UserPointer<const void*> buffer, - UserPointer<uint32_t> buffer_num_bytes) { - return dpc()->ConsumerBeginReadData(buffer, buffer_num_bytes); - } - MojoResult ConsumerEndReadData(uint32_t num_bytes_read) { - return dpc()->ConsumerEndReadData(num_bytes_read); - } - MojoResult ConsumerAddAwakable(Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state) { - return dpc()->ConsumerAddAwakable(awakable, signals, context, - signals_state); - } - void ConsumerRemoveAwakable(Awakable* awakable, - HandleSignalsState* signals_state) { - return dpc()->ConsumerRemoveAwakable(awakable, signals_state); - } - - private: - DataPipe* dpp() { return helper_->DataPipeForProducer(); } - DataPipe* dpc() { return helper_->DataPipeForConsumer(); } - - scoped_ptr<Helper> helper_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(DataPipeImplTest); -}; - -// LocalDataPipeImplTestHelper ------------------------------------------------- - -class LocalDataPipeImplTestHelper : public DataPipeImplTestHelper { - public: - LocalDataPipeImplTestHelper() {} - ~LocalDataPipeImplTestHelper() override {} - - void SetUp() override {} - void TearDown() override {} - - void Create(const MojoCreateDataPipeOptions& validated_options) override { - CHECK(!dp_); - dp_ = DataPipe::CreateLocal(validated_options); - } - - bool IsStrictCircularBuffer() const override { return true; } - - void DoTransfer() override {} - - // Returns the |DataPipe| object for the producer and consumer, respectively. - DataPipe* DataPipeForProducer() override { return dp_.get(); } - DataPipe* DataPipeForConsumer() override { return dp_.get(); } - - void ProducerClose() override { dp_->ProducerClose(); } - void ConsumerClose() override { dp_->ConsumerClose(); } - - private: - scoped_refptr<DataPipe> dp_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(LocalDataPipeImplTestHelper); -}; - -// RemoteDataPipeImplTestHelper ------------------------------------------------ - -// Base class for |Remote{Producer,Consumer}DataPipeImplTestHelper|. -class RemoteDataPipeImplTestHelper : public DataPipeImplTestHelper { - public: - RemoteDataPipeImplTestHelper() : io_thread_(base::TestIOThread::kAutoStart) {} - ~RemoteDataPipeImplTestHelper() override {} - - void SetUp() override { - scoped_refptr<ChannelEndpoint> ep[2]; - message_pipes_[0] = MessagePipe::CreateLocalProxy(&ep[0]); - message_pipes_[1] = MessagePipe::CreateLocalProxy(&ep[1]); - - io_thread_.PostTaskAndWait( - FROM_HERE, base::Bind(&RemoteDataPipeImplTestHelper::SetUpOnIOThread, - base::Unretained(this), ep[0], ep[1])); - } - - void TearDown() override { - EnsureMessagePipeClosed(0); - EnsureMessagePipeClosed(1); - io_thread_.PostTaskAndWait( - FROM_HERE, base::Bind(&RemoteDataPipeImplTestHelper::TearDownOnIOThread, - base::Unretained(this))); - } - - void Create(const MojoCreateDataPipeOptions& validated_options) override { - CHECK(!dp_); - dp_ = DataPipe::CreateLocal(validated_options); - } - - bool IsStrictCircularBuffer() const override { return false; } - - protected: - void SendDispatcher(size_t source_i, - scoped_refptr<Dispatcher> to_send, - scoped_refptr<Dispatcher>* to_receive) { - DCHECK(source_i == 0 || source_i == 1); - size_t dest_i = source_i ^ 1; - - // Write the dispatcher to MP |source_i| (port 0). Wait and receive on MP - // |dest_i| (port 0). (Add the waiter first, to avoid any handling the case - // where it's already readable.) - Waiter waiter; - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - message_pipe(dest_i)->AddAwakable( - 0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 987, nullptr)); - { - DispatcherTransport transport( - test::DispatcherTryStartTransport(to_send.get())); - ASSERT_TRUE(transport.is_valid()); - - std::vector<DispatcherTransport> transports; - transports.push_back(transport); - ASSERT_EQ(MOJO_RESULT_OK, message_pipe(source_i)->WriteMessage( - 0, NullUserPointer(), 0, &transports, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - transport.End(); - } - uintptr_t context = 0; - ASSERT_EQ(MOJO_RESULT_OK, waiter.Wait(test::ActionDeadline(), &context)); - EXPECT_EQ(987u, context); - HandleSignalsState hss = HandleSignalsState(); - message_pipe(dest_i)->RemoveAwakable(0, &waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - char read_buffer[100] = {}; - uint32_t read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); - DispatcherVector read_dispatchers; - uint32_t read_num_dispatchers = 10; // Maximum to get. - ASSERT_EQ(MOJO_RESULT_OK, - message_pipe(dest_i)->ReadMessage( - 0, UserPointer<void>(read_buffer), - MakeUserPointer(&read_buffer_size), &read_dispatchers, - &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(0u, static_cast<size_t>(read_buffer_size)); - ASSERT_EQ(1u, read_dispatchers.size()); - ASSERT_EQ(1u, read_num_dispatchers); - ASSERT_TRUE(read_dispatchers[0]); - EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); - - *to_receive = read_dispatchers[0]; - } - - scoped_refptr<MessagePipe> message_pipe(size_t i) { - return message_pipes_[i]; - } - scoped_refptr<DataPipe> dp() { return dp_; } - - private: - void EnsureMessagePipeClosed(size_t i) { - if (!message_pipes_[i]) - return; - message_pipes_[i]->Close(0); - message_pipes_[i] = nullptr; - } - - void SetUpOnIOThread(scoped_refptr<ChannelEndpoint> ep0, - scoped_refptr<ChannelEndpoint> ep1) { - CHECK_EQ(base::MessageLoop::current(), io_thread_.message_loop()); - - embedder::PlatformChannelPair channel_pair; - channels_[0] = new Channel(&platform_support_); - channels_[0]->Init(RawChannel::Create(channel_pair.PassServerHandle())); - channels_[0]->SetBootstrapEndpoint(ep0); - channels_[1] = new Channel(&platform_support_); - channels_[1]->Init(RawChannel::Create(channel_pair.PassClientHandle())); - channels_[1]->SetBootstrapEndpoint(ep1); - } - - void TearDownOnIOThread() { - CHECK_EQ(base::MessageLoop::current(), io_thread_.message_loop()); - - if (channels_[0]) { - channels_[0]->Shutdown(); - channels_[0] = nullptr; - } - if (channels_[1]) { - channels_[1]->Shutdown(); - channels_[1] = nullptr; - } - } - - embedder::SimplePlatformSupport platform_support_; - base::TestIOThread io_thread_; - scoped_refptr<Channel> channels_[2]; - scoped_refptr<MessagePipe> message_pipes_[2]; - - scoped_refptr<DataPipe> dp_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(RemoteDataPipeImplTestHelper); -}; - -// RemoteProducerDataPipeImplTestHelper ---------------------------------------- - -// Note about naming confusion: This class is named after the "local" class, -// i.e., |dp_| will have a |RemoteProducerDataPipeImpl|. The remote side, of -// course, will have a |RemoteConsumerDataPipeImpl|. -class RemoteProducerDataPipeImplTestHelper - : public RemoteDataPipeImplTestHelper { - public: - RemoteProducerDataPipeImplTestHelper() {} - ~RemoteProducerDataPipeImplTestHelper() override {} - - void DoTransfer() override { - // This is the producer dispatcher we'll send. - scoped_refptr<DataPipeProducerDispatcher> to_send = - DataPipeProducerDispatcher::Create(); - to_send->Init(dp()); - scoped_refptr<Dispatcher> to_receive; - SendDispatcher(0, to_send, &to_receive); - // |to_send| should have been closed. This is |DCHECK()|ed when it is - // destroyed. - EXPECT_TRUE(to_send->HasOneRef()); - to_send = nullptr; - - ASSERT_EQ(Dispatcher::Type::DATA_PIPE_PRODUCER, to_receive->GetType()); - producer_dispatcher_ = - static_cast<DataPipeProducerDispatcher*>(to_receive.get()); - } - - DataPipe* DataPipeForProducer() override { - if (producer_dispatcher_) - return producer_dispatcher_->GetDataPipeForTest(); - return dp().get(); - } - DataPipe* DataPipeForConsumer() override { return dp().get(); } - - void ProducerClose() override { - if (producer_dispatcher_) - ASSERT_EQ(MOJO_RESULT_OK, producer_dispatcher_->Close()); - else - dp()->ProducerClose(); - } - void ConsumerClose() override { dp()->ConsumerClose(); } - - protected: - scoped_refptr<DataPipeProducerDispatcher> producer_dispatcher_; - - private: - MOJO_DISALLOW_COPY_AND_ASSIGN(RemoteProducerDataPipeImplTestHelper); -}; - -// RemoteConsumerDataPipeImplTestHelper ---------------------------------------- - -// Note about naming confusion: This class is named after the "local" class, -// i.e., |dp_| will have a |RemoteConsumerDataPipeImpl|. The remote side, of -// course, will have a |RemoteProducerDataPipeImpl|. -class RemoteConsumerDataPipeImplTestHelper - : public RemoteDataPipeImplTestHelper { - public: - RemoteConsumerDataPipeImplTestHelper() {} - ~RemoteConsumerDataPipeImplTestHelper() override {} - - void DoTransfer() override { - // This is the consumer dispatcher we'll send. - scoped_refptr<DataPipeConsumerDispatcher> to_send = - DataPipeConsumerDispatcher::Create(); - to_send->Init(dp()); - scoped_refptr<Dispatcher> to_receive; - SendDispatcher(0, to_send, &to_receive); - // |to_send| should have been closed. This is |DCHECK()|ed when it is - // destroyed. - EXPECT_TRUE(to_send->HasOneRef()); - to_send = nullptr; - - ASSERT_EQ(Dispatcher::Type::DATA_PIPE_CONSUMER, to_receive->GetType()); - consumer_dispatcher_ = - static_cast<DataPipeConsumerDispatcher*>(to_receive.get()); - } - - DataPipe* DataPipeForProducer() override { return dp().get(); } - DataPipe* DataPipeForConsumer() override { - if (consumer_dispatcher_) - return consumer_dispatcher_->GetDataPipeForTest(); - return dp().get(); - } - - void ProducerClose() override { dp()->ProducerClose(); } - void ConsumerClose() override { - if (consumer_dispatcher_) - ASSERT_EQ(MOJO_RESULT_OK, consumer_dispatcher_->Close()); - else - dp()->ConsumerClose(); - } - - protected: - scoped_refptr<DataPipeConsumerDispatcher> consumer_dispatcher_; - - private: - MOJO_DISALLOW_COPY_AND_ASSIGN(RemoteConsumerDataPipeImplTestHelper); -}; - -// RemoteProducerDataPipeImplTestHelper2 --------------------------------------- - -// This is like |RemoteProducerDataPipeImplTestHelper|, but |DoTransfer()| does -// a second transfer. This thus tests passing a producer handle twice, and in -// particular tests (some of) |RemoteConsumerDataPipeImpl|'s -// |ProducerEndSerialize()| (instead of |LocalDataPipeImpl|'s). -// -// Note about naming confusion: This class is named after the "local" class, -// i.e., |dp_| will have a |RemoteProducerDataPipeImpl|. The remote side, of -// course, will have a |RemoteConsumerDataPipeImpl|. -class RemoteProducerDataPipeImplTestHelper2 - : public RemoteProducerDataPipeImplTestHelper { - public: - RemoteProducerDataPipeImplTestHelper2() {} - ~RemoteProducerDataPipeImplTestHelper2() override {} - - void DoTransfer() override { - // This is the producer dispatcher we'll send. - scoped_refptr<DataPipeProducerDispatcher> to_send = - DataPipeProducerDispatcher::Create(); - to_send->Init(dp()); - scoped_refptr<Dispatcher> to_receive; - SendDispatcher(0, to_send, &to_receive); - // |to_send| should have been closed. This is |DCHECK()|ed when it is - // destroyed. - EXPECT_TRUE(to_send->HasOneRef()); - to_send = nullptr; - ASSERT_EQ(Dispatcher::Type::DATA_PIPE_PRODUCER, to_receive->GetType()); - to_send = static_cast<DataPipeProducerDispatcher*>(to_receive.get()); - to_receive = nullptr; - - // Now send it back the other way. - SendDispatcher(1, to_send, &to_receive); - // |producer_dispatcher_| should have been closed. This is |DCHECK()|ed when - // it is destroyed. - EXPECT_TRUE(to_send->HasOneRef()); - to_send = nullptr; - - ASSERT_EQ(Dispatcher::Type::DATA_PIPE_PRODUCER, to_receive->GetType()); - producer_dispatcher_ = - static_cast<DataPipeProducerDispatcher*>(to_receive.get()); - } - - private: - MOJO_DISALLOW_COPY_AND_ASSIGN(RemoteProducerDataPipeImplTestHelper2); -}; - -// RemoteConsumerDataPipeImplTestHelper2 --------------------------------------- - -// This is like |RemoteConsumerDataPipeImplTestHelper|, but |DoTransfer()| does -// a second transfer. This thus tests passing a consumer handle twice, and in -// particular tests (some of) |RemoteProducerDataPipeImpl|'s -// |ConsumerEndSerialize()| (instead of |LocalDataPipeImpl|'s). -// -// Note about naming confusion: This class is named after the "local" class, -// i.e., |dp_| will have a |RemoteConsumerDataPipeImpl|. The remote side, of -// course, will have a |RemoteProducerDataPipeImpl|. -class RemoteConsumerDataPipeImplTestHelper2 - : public RemoteConsumerDataPipeImplTestHelper { - public: - RemoteConsumerDataPipeImplTestHelper2() {} - ~RemoteConsumerDataPipeImplTestHelper2() override {} - - void DoTransfer() override { - // This is the consumer dispatcher we'll send. - scoped_refptr<DataPipeConsumerDispatcher> to_send = - DataPipeConsumerDispatcher::Create(); - to_send->Init(dp()); - scoped_refptr<Dispatcher> to_receive; - SendDispatcher(0, to_send, &to_receive); - // |to_send| should have been closed. This is |DCHECK()|ed when it is - // destroyed. - EXPECT_TRUE(to_send->HasOneRef()); - to_send = nullptr; - ASSERT_EQ(Dispatcher::Type::DATA_PIPE_CONSUMER, to_receive->GetType()); - to_send = static_cast<DataPipeConsumerDispatcher*>(to_receive.get()); - to_receive = nullptr; - - // Now send it back the other way. - SendDispatcher(1, to_send, &to_receive); - // |consumer_dispatcher_| should have been closed. This is |DCHECK()|ed when - // it is destroyed. - EXPECT_TRUE(to_send->HasOneRef()); - to_send = nullptr; - - ASSERT_EQ(Dispatcher::Type::DATA_PIPE_CONSUMER, to_receive->GetType()); - consumer_dispatcher_ = - static_cast<DataPipeConsumerDispatcher*>(to_receive.get()); - } - - private: - MOJO_DISALLOW_COPY_AND_ASSIGN(RemoteConsumerDataPipeImplTestHelper2); -}; - -// Test case instantiation ----------------------------------------------------- - -using HelperTypes = testing::Types<LocalDataPipeImplTestHelper, - RemoteProducerDataPipeImplTestHelper, - RemoteConsumerDataPipeImplTestHelper, - RemoteProducerDataPipeImplTestHelper2, - RemoteConsumerDataPipeImplTestHelper2>; - -TYPED_TEST_CASE(DataPipeImplTest, HelperTypes); - -// Tests ----------------------------------------------------------------------- - -// Tests creation (and possibly also transferring) of data pipes with various -// (valid) options. -TYPED_TEST(DataPipeImplTest, CreateAndMaybeTransfer) { - MojoCreateDataPipeOptions test_options[] = { - // Default options -- we'll initialize this below. - {}, - // Trivial element size, non-default capacity. - {kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 1, // |element_num_bytes|. - 1000}, // |capacity_num_bytes|. - // Nontrivial element size, non-default capacity. - {kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 4, // |element_num_bytes|. - 4000}, // |capacity_num_bytes|. - // Nontrivial element size, default capacity. - {kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 100, // |element_num_bytes|. - 0} // |capacity_num_bytes|. - }; - - // Initialize the first element of |test_options| to the default options. - EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(NullUserPointer(), - &test_options[0])); - - for (size_t i = 0; i < MOJO_ARRAYSIZE(test_options); i++) { - this->Create(test_options[i]); - this->DoTransfer(); - this->ProducerClose(); - this->ConsumerClose(); - this->Reset(); - } -} - -TYPED_TEST(DataPipeImplTest, SimpleReadWrite) { - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. - 1000 * sizeof(int32_t) // |capacity_num_bytes|. - }; - this->Create(options); - this->DoTransfer(); - - Waiter waiter; - HandleSignalsState hss; - uintptr_t context; - - int32_t elements[10] = {}; - uint32_t num_bytes = 0u; - - // Try reading; nothing there yet. - num_bytes = - static_cast<uint32_t>(MOJO_ARRAYSIZE(elements) * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - this->ConsumerReadData(UserPointer<void>(elements), - MakeUserPointer(&num_bytes), false, false)); - - // Query; nothing there yet. - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerQueryData(MakeUserPointer(&num_bytes))); - EXPECT_EQ(0u, num_bytes); - - // Discard; nothing there yet. - num_bytes = static_cast<uint32_t>(5u * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - this->ConsumerDiscardData(MakeUserPointer(&num_bytes), false)); - - // Read with invalid |num_bytes|. - num_bytes = sizeof(elements[0]) + 1; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - this->ConsumerReadData(UserPointer<void>(elements), - MakeUserPointer(&num_bytes), false, false)); - - // For remote data pipes, we'll have to wait; add the waiter before writing. - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, - nullptr)); - - // Write two elements. - elements[0] = 123; - elements[1] = 456; - num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerWriteData(UserPointer<const void>(elements), - MakeUserPointer(&num_bytes), false)); - // It should have written everything (even without "all or none"). - EXPECT_EQ(2u * sizeof(elements[0]), num_bytes); - - // Wait. - context = 0; - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::ActionDeadline(), &context)); - EXPECT_EQ(123u, context); - hss = HandleSignalsState(); - this->ConsumerRemoveAwakable(&waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Query. - // TODO(vtl): It's theoretically possible (though not with the current - // implementation/configured limits) that not all the data has arrived yet. - // (The theoretically-correct assertion here is that |num_bytes| is |1 * ...| - // or |2 * ...|.) - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerQueryData(MakeUserPointer(&num_bytes))); - EXPECT_EQ(2 * sizeof(elements[0]), num_bytes); - - // Read one element. - elements[0] = -1; - elements[1] = -1; - num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerReadData(UserPointer<void>(elements), - MakeUserPointer(&num_bytes), false, false)); - EXPECT_EQ(1u * sizeof(elements[0]), num_bytes); - EXPECT_EQ(123, elements[0]); - EXPECT_EQ(-1, elements[1]); - - // Query. - // TODO(vtl): See previous TODO. (If we got 2 elements there, however, we - // should get 1 here.) - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerQueryData(MakeUserPointer(&num_bytes))); - EXPECT_EQ(1 * sizeof(elements[0]), num_bytes); - - // Peek one element. - elements[0] = -1; - elements[1] = -1; - num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerReadData(UserPointer<void>(elements), - MakeUserPointer(&num_bytes), false, true)); - EXPECT_EQ(1u * sizeof(elements[0]), num_bytes); - EXPECT_EQ(456, elements[0]); - EXPECT_EQ(-1, elements[1]); - - // Query. Still has 1 element remaining. - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerQueryData(MakeUserPointer(&num_bytes))); - EXPECT_EQ(1 * sizeof(elements[0]), num_bytes); - - // Try to read two elements, with "all or none". - elements[0] = -1; - elements[1] = -1; - num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, - this->ConsumerReadData(UserPointer<void>(elements), - MakeUserPointer(&num_bytes), true, false)); - EXPECT_EQ(-1, elements[0]); - EXPECT_EQ(-1, elements[1]); - - // Try to read two elements, without "all or none". - elements[0] = -1; - elements[1] = -1; - num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerReadData(UserPointer<void>(elements), - MakeUserPointer(&num_bytes), false, false)); - EXPECT_EQ(1u * sizeof(elements[0]), num_bytes); - EXPECT_EQ(456, elements[0]); - EXPECT_EQ(-1, elements[1]); - - // Query. - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerQueryData(MakeUserPointer(&num_bytes))); - EXPECT_EQ(0u, num_bytes); - - this->ProducerClose(); - this->ConsumerClose(); -} - -// Note: The "basic" waiting tests test that the "wait states" are correct in -// various situations; they don't test that waiters are properly awoken on state -// changes. (For that, we need to use multiple threads.) -TYPED_TEST(DataPipeImplTest, BasicProducerWaiting) { - // Note: We take advantage of the fact that current for current - // implementations capacities are strict maximums. This is not guaranteed by - // the API. - - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. - 2 * sizeof(int32_t) // |capacity_num_bytes|. - }; - this->Create(options); - this->DoTransfer(); - - Waiter pwaiter; // For producer. - Waiter cwaiter; // For consumer. - HandleSignalsState hss; - uintptr_t context; - - // Never readable. - pwaiter.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - this->ProducerAddAwakable(&pwaiter, MOJO_HANDLE_SIGNAL_READABLE, 12, - &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Already writable. - pwaiter.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - this->ProducerAddAwakable(&pwaiter, MOJO_HANDLE_SIGNAL_WRITABLE, 34, - &hss)); - - // We'll need to wait for readability for the remote cases. - cwaiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ConsumerAddAwakable(&cwaiter, MOJO_HANDLE_SIGNAL_READABLE, - 1234, nullptr)); - - // Write two elements. - int32_t elements[2] = {123, 456}; - uint32_t num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerWriteData(UserPointer<const void>(elements), - MakeUserPointer(&num_bytes), true)); - EXPECT_EQ(static_cast<uint32_t>(2u * sizeof(elements[0])), num_bytes); - - // Adding a waiter should now succeed. - pwaiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ProducerAddAwakable(&pwaiter, MOJO_HANDLE_SIGNAL_WRITABLE, 56, - nullptr)); - // And it shouldn't be writable yet. - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, pwaiter.Wait(0, nullptr)); - hss = HandleSignalsState(); - this->ProducerRemoveAwakable(&pwaiter, &hss); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Wait for data to become available to the consumer. - context = 0; - EXPECT_EQ(MOJO_RESULT_OK, cwaiter.Wait(test::TinyDeadline(), &context)); - EXPECT_EQ(1234u, context); - hss = HandleSignalsState(); - this->ConsumerRemoveAwakable(&cwaiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Peek one element. - elements[0] = -1; - elements[1] = -1; - num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerReadData(UserPointer<void>(elements), - MakeUserPointer(&num_bytes), true, true)); - EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); - EXPECT_EQ(123, elements[0]); - EXPECT_EQ(-1, elements[1]); - - // Add a waiter. - pwaiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ProducerAddAwakable(&pwaiter, MOJO_HANDLE_SIGNAL_WRITABLE, 56, - nullptr)); - // And it still shouldn't be writable yet. - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, pwaiter.Wait(0, nullptr)); - hss = HandleSignalsState(); - this->ProducerRemoveAwakable(&pwaiter, &hss); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Do it again. - pwaiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ProducerAddAwakable(&pwaiter, MOJO_HANDLE_SIGNAL_WRITABLE, 78, - nullptr)); - - // Read one element. - elements[0] = -1; - elements[1] = -1; - num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerReadData(UserPointer<void>(elements), - MakeUserPointer(&num_bytes), true, false)); - EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); - EXPECT_EQ(123, elements[0]); - EXPECT_EQ(-1, elements[1]); - - // Waiting should now succeed. - context = 0; - EXPECT_EQ(MOJO_RESULT_OK, pwaiter.Wait(test::TinyDeadline(), &context)); - EXPECT_EQ(78u, context); - hss = HandleSignalsState(); - this->ProducerRemoveAwakable(&pwaiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Try writing, using a two-phase write. - void* buffer = nullptr; - num_bytes = static_cast<uint32_t>(3u * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerBeginWriteData(MakeUserPointer(&buffer), - MakeUserPointer(&num_bytes))); - EXPECT_TRUE(buffer); - EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); - - static_cast<int32_t*>(buffer)[0] = 789; - EXPECT_EQ(MOJO_RESULT_OK, this->ProducerEndWriteData(static_cast<uint32_t>( - 1u * sizeof(elements[0])))); - - // Add a waiter. - pwaiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ProducerAddAwakable(&pwaiter, MOJO_HANDLE_SIGNAL_WRITABLE, 90, - nullptr)); - - // Read one element, using a two-phase read. - const void* read_buffer = nullptr; - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerBeginReadData(MakeUserPointer(&read_buffer), - MakeUserPointer(&num_bytes))); - EXPECT_TRUE(read_buffer); - // Since we only read one element (after having written three in all), the - // two-phase read should only allow us to read one. This checks an - // implementation detail! - EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); - EXPECT_EQ(456, static_cast<const int32_t*>(read_buffer)[0]); - EXPECT_EQ(MOJO_RESULT_OK, this->ConsumerEndReadData(static_cast<uint32_t>( - 1u * sizeof(elements[0])))); - - // Waiting should succeed. - context = 0; - EXPECT_EQ(MOJO_RESULT_OK, pwaiter.Wait(test::TinyDeadline(), &context)); - EXPECT_EQ(90u, context); - hss = HandleSignalsState(); - this->ProducerRemoveAwakable(&pwaiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Write one element. - elements[0] = 123; - num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerWriteData(UserPointer<const void>(elements), - MakeUserPointer(&num_bytes), false)); - EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); - - // Add a waiter. - pwaiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ProducerAddAwakable(&pwaiter, MOJO_HANDLE_SIGNAL_WRITABLE, 12, - nullptr)); - - // Close the consumer. - this->ConsumerClose(); - - // It should now be never-writable. - context = 0; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - pwaiter.Wait(test::TinyDeadline(), &context)); - EXPECT_EQ(12u, context); - hss = HandleSignalsState(); - this->ProducerRemoveAwakable(&pwaiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - this->ProducerClose(); -} - -TYPED_TEST(DataPipeImplTest, PeerClosedProducerWaiting) { - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. - 2 * sizeof(int32_t) // |capacity_num_bytes|. - }; - this->Create(options); - this->DoTransfer(); - - Waiter waiter; - HandleSignalsState hss; - uintptr_t context; - - // Add a waiter. - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, - 12, nullptr)); - - // Close the consumer. - this->ConsumerClose(); - - // It should be signaled. - context = 0; - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), &context)); - EXPECT_EQ(12u, context); - hss = HandleSignalsState(); - this->ProducerRemoveAwakable(&waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - this->ProducerClose(); -} - -TYPED_TEST(DataPipeImplTest, PeerClosedConsumerWaiting) { - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. - 2 * sizeof(int32_t) // |capacity_num_bytes|. - }; - this->Create(options); - this->DoTransfer(); - - Waiter waiter; - HandleSignalsState hss; - uintptr_t context; - - // Add a waiter. - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, - 12, nullptr)); - - // Close the producer. - this->ProducerClose(); - - // It should be signaled. - context = 0; - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), &context)); - EXPECT_EQ(12u, context); - hss = HandleSignalsState(); - this->ConsumerRemoveAwakable(&waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - this->ConsumerClose(); -} - -TYPED_TEST(DataPipeImplTest, BasicConsumerWaiting) { - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. - 1000 * sizeof(int32_t) // |capacity_num_bytes|. - }; - this->Create(options); - this->DoTransfer(); - - Waiter waiter; - Waiter waiter2; - HandleSignalsState hss; - uintptr_t context; - - // Never writable. - waiter.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 12, - &hss)); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Add waiter: not yet readable. - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34, - nullptr)); - - // Write two elements. - int32_t elements[2] = {123, 456}; - uint32_t num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerWriteData(UserPointer<const void>(elements), - MakeUserPointer(&num_bytes), true)); - - // Wait for readability (needed for remote cases). - context = 0; - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), &context)); - EXPECT_EQ(34u, context); - hss = HandleSignalsState(); - this->ConsumerRemoveAwakable(&waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Discard one element. - num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerDiscardData(MakeUserPointer(&num_bytes), true)); - EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); - - // Should still be readable. - waiter.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 78, - &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Peek one element. - elements[0] = -1; - elements[1] = -1; - num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerReadData(UserPointer<void>(elements), - MakeUserPointer(&num_bytes), true, true)); - EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); - EXPECT_EQ(456, elements[0]); - EXPECT_EQ(-1, elements[1]); - - // Should still be readable. - waiter.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 78, - &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Read one element. - elements[0] = -1; - elements[1] = -1; - num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerReadData(UserPointer<void>(elements), - MakeUserPointer(&num_bytes), true, false)); - EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); - EXPECT_EQ(456, elements[0]); - EXPECT_EQ(-1, elements[1]); - - // Adding a waiter should now succeed. - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 90, - nullptr)); - - // Write one element. - elements[0] = 789; - elements[1] = -1; - num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerWriteData(UserPointer<const void>(elements), - MakeUserPointer(&num_bytes), true)); - - // Waiting should now succeed. - context = 0; - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), &context)); - EXPECT_EQ(90u, context); - hss = HandleSignalsState(); - this->ConsumerRemoveAwakable(&waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // We'll want to wait for the peer closed signal to propagate. - waiter.Init(); - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, - 12, nullptr)); - - // Close the producer. - this->ProducerClose(); - - // Should still be readable, even if the peer closed signal hasn't propagated - // yet. - waiter2.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - this->ConsumerAddAwakable(&waiter2, MOJO_HANDLE_SIGNAL_READABLE, 34, - &hss)); - // We don't know if the peer closed signal has propagated yet (for the remote - // cases). - EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Wait for the peer closed signal. - context = 0; - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), &context)); - EXPECT_EQ(12u, context); - hss = HandleSignalsState(); - this->ConsumerRemoveAwakable(&waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Read one element. - elements[0] = -1; - elements[1] = -1; - num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerReadData(UserPointer<void>(elements), - MakeUserPointer(&num_bytes), true, false)); - EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); - EXPECT_EQ(789, elements[0]); - EXPECT_EQ(-1, elements[1]); - - // Should be never-readable. - waiter.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 56, - &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - this->ConsumerClose(); -} - -// Test with two-phase APIs and also closing the producer with an active -// consumer waiter. -TYPED_TEST(DataPipeImplTest, ConsumerWaitingTwoPhase) { - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. - 1000 * sizeof(int32_t) // |capacity_num_bytes|. - }; - this->Create(options); - this->DoTransfer(); - - Waiter waiter; - HandleSignalsState hss; - uintptr_t context; - - // Add waiter: not yet readable. - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12, - nullptr)); - - // Write two elements. - int32_t* elements = nullptr; - void* buffer = nullptr; - uint32_t num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerBeginWriteData(MakeUserPointer(&buffer), - MakeUserPointer(&num_bytes))); - EXPECT_TRUE(buffer); - EXPECT_GE(num_bytes, static_cast<uint32_t>(3u * sizeof(elements[0]))); - elements = static_cast<int32_t*>(buffer); - elements[0] = 123; - elements[1] = 456; - EXPECT_EQ(MOJO_RESULT_OK, this->ProducerEndWriteData(static_cast<uint32_t>( - 2u * sizeof(elements[0])))); - - // Wait for readability (needed for remote cases). - context = 0; - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), &context)); - EXPECT_EQ(12u, context); - hss = HandleSignalsState(); - this->ConsumerRemoveAwakable(&waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Read one element. - const void* read_buffer = nullptr; - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerBeginReadData(MakeUserPointer(&read_buffer), - MakeUserPointer(&num_bytes))); - EXPECT_TRUE(read_buffer); - EXPECT_EQ(static_cast<uint32_t>(2u * sizeof(elements[0])), num_bytes); - const int32_t* read_elements = static_cast<const int32_t*>(read_buffer); - EXPECT_EQ(123, read_elements[0]); - EXPECT_EQ(MOJO_RESULT_OK, this->ConsumerEndReadData(static_cast<uint32_t>( - 1u * sizeof(elements[0])))); - - // Should still be readable. - waiter.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34, - &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Read one element. - // Request three, but not in all-or-none mode. - read_buffer = nullptr; - num_bytes = static_cast<uint32_t>(3u * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerBeginReadData(MakeUserPointer(&read_buffer), - MakeUserPointer(&num_bytes))); - EXPECT_TRUE(read_buffer); - EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); - read_elements = static_cast<const int32_t*>(read_buffer); - EXPECT_EQ(456, read_elements[0]); - EXPECT_EQ(MOJO_RESULT_OK, this->ConsumerEndReadData(static_cast<uint32_t>( - 1u * sizeof(elements[0])))); - - // Adding a waiter should now succeed. - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 56, - nullptr)); - - // Close the producer. - this->ProducerClose(); - - // Should be never-readable. - context = 0; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - waiter.Wait(test::TinyDeadline(), &context)); - EXPECT_EQ(56u, context); - hss = HandleSignalsState(); - this->ConsumerRemoveAwakable(&waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - this->ConsumerClose(); -} - -// Tests that data pipes aren't writable/readable during two-phase writes/reads. -TYPED_TEST(DataPipeImplTest, BasicTwoPhaseWaiting) { - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. - 1000 * sizeof(int32_t) // |capacity_num_bytes|. - }; - this->Create(options); - this->DoTransfer(); - - Waiter pwaiter; // For producer. - Waiter cwaiter; // For consumer. - HandleSignalsState hss; - - // It should be writable. - pwaiter.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - this->ProducerAddAwakable(&pwaiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0, - &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - void* write_ptr = nullptr; - uint32_t num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerBeginWriteData(MakeUserPointer(&write_ptr), - MakeUserPointer(&num_bytes))); - EXPECT_TRUE(write_ptr); - EXPECT_GE(num_bytes, static_cast<uint32_t>(1u * sizeof(int32_t))); - - // At this point, it shouldn't be writable. - pwaiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ProducerAddAwakable(&pwaiter, MOJO_HANDLE_SIGNAL_WRITABLE, 1, - nullptr)); - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, pwaiter.Wait(0, nullptr)); - hss = HandleSignalsState(); - this->ProducerRemoveAwakable(&pwaiter, &hss); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // It shouldn't be readable yet either (we'll wait later). - cwaiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ConsumerAddAwakable(&cwaiter, MOJO_HANDLE_SIGNAL_READABLE, 2, - nullptr)); - - static_cast<int32_t*>(write_ptr)[0] = 123; - EXPECT_EQ(MOJO_RESULT_OK, this->ProducerEndWriteData( - static_cast<uint32_t>(1u * sizeof(int32_t)))); - - // It should immediately be writable again. - pwaiter.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - this->ProducerAddAwakable(&pwaiter, MOJO_HANDLE_SIGNAL_WRITABLE, 3, - &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // It should become readable. - EXPECT_EQ(MOJO_RESULT_OK, cwaiter.Wait(test::TinyDeadline(), nullptr)); - hss = HandleSignalsState(); - this->ConsumerRemoveAwakable(&cwaiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Start another two-phase write and check that it's readable even in the - // middle of it. - write_ptr = nullptr; - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerBeginWriteData(MakeUserPointer(&write_ptr), - MakeUserPointer(&num_bytes))); - EXPECT_TRUE(write_ptr); - EXPECT_GE(num_bytes, static_cast<uint32_t>(1u * sizeof(int32_t))); - - // It should be readable. - cwaiter.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - this->ConsumerAddAwakable(&cwaiter, MOJO_HANDLE_SIGNAL_READABLE, 5, - &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // End the two-phase write without writing anything. - EXPECT_EQ(MOJO_RESULT_OK, this->ProducerEndWriteData(0u)); - - // Start a two-phase read. - const void* read_ptr = nullptr; - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerBeginReadData(MakeUserPointer(&read_ptr), - MakeUserPointer(&num_bytes))); - EXPECT_TRUE(read_ptr); - EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(int32_t)), num_bytes); - - // At this point, it should still be writable. - pwaiter.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - this->ProducerAddAwakable(&pwaiter, MOJO_HANDLE_SIGNAL_WRITABLE, 6, - &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // But not readable. - cwaiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ConsumerAddAwakable(&cwaiter, MOJO_HANDLE_SIGNAL_READABLE, 7, - nullptr)); - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, cwaiter.Wait(0, nullptr)); - hss = HandleSignalsState(); - this->ConsumerRemoveAwakable(&cwaiter, &hss); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // End the two-phase read without reading anything. - EXPECT_EQ(MOJO_RESULT_OK, this->ConsumerEndReadData(0u)); - - // It should be readable again. - cwaiter.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - this->ConsumerAddAwakable(&cwaiter, MOJO_HANDLE_SIGNAL_READABLE, 8, - &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - this->ProducerClose(); - this->ConsumerClose(); -} - -void Seq(int32_t start, size_t count, int32_t* out) { - for (size_t i = 0; i < count; i++) - out[i] = start + static_cast<int32_t>(i); -} - -TYPED_TEST(DataPipeImplTest, AllOrNone) { - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. - 10 * sizeof(int32_t) // |capacity_num_bytes|. - }; - this->Create(options); - this->DoTransfer(); - - Waiter waiter; - HandleSignalsState hss; - - // Try writing way too much. - uint32_t num_bytes = 20u * sizeof(int32_t); - int32_t buffer[100]; - Seq(0, MOJO_ARRAYSIZE(buffer), buffer); - EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, - this->ProducerWriteData(UserPointer<const void>(buffer), - MakeUserPointer(&num_bytes), true)); - - // Should still be empty. - num_bytes = ~0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerQueryData(MakeUserPointer(&num_bytes))); - EXPECT_EQ(0u, num_bytes); - - // Add waiter. - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 1, - nullptr)); - - // Write some data. - num_bytes = 5u * sizeof(int32_t); - Seq(100, MOJO_ARRAYSIZE(buffer), buffer); - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerWriteData(UserPointer<const void>(buffer), - MakeUserPointer(&num_bytes), true)); - EXPECT_EQ(5u * sizeof(int32_t), num_bytes); - - // Wait for data. - // TODO(vtl): There's no real guarantee that all the data will become - // available at once (except that in current implementations, with reasonable - // limits, it will). Eventually, we'll be able to wait for a specified amount - // of data to become available. - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), nullptr)); - hss = HandleSignalsState(); - this->ConsumerRemoveAwakable(&waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Half full. - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerQueryData(MakeUserPointer(&num_bytes))); - EXPECT_EQ(5u * sizeof(int32_t), num_bytes); - - // Too much. - num_bytes = 6u * sizeof(int32_t); - Seq(200, MOJO_ARRAYSIZE(buffer), buffer); - EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, - this->ProducerWriteData(UserPointer<const void>(buffer), - MakeUserPointer(&num_bytes), true)); - - // Try reading too much. - num_bytes = 11u * sizeof(int32_t); - memset(buffer, 0xab, sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, - this->ConsumerReadData(UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), true, false)); - int32_t expected_buffer[100]; - memset(expected_buffer, 0xab, sizeof(expected_buffer)); - EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); - - // Try discarding too much. - num_bytes = 11u * sizeof(int32_t); - EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, - this->ConsumerDiscardData(MakeUserPointer(&num_bytes), true)); - - // Just a little. - num_bytes = 2u * sizeof(int32_t); - Seq(300, MOJO_ARRAYSIZE(buffer), buffer); - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerWriteData(UserPointer<const void>(buffer), - MakeUserPointer(&num_bytes), true)); - EXPECT_EQ(2u * sizeof(int32_t), num_bytes); - - // Just right. - num_bytes = 3u * sizeof(int32_t); - Seq(400, MOJO_ARRAYSIZE(buffer), buffer); - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerWriteData(UserPointer<const void>(buffer), - MakeUserPointer(&num_bytes), true)); - EXPECT_EQ(3u * sizeof(int32_t), num_bytes); - - // TODO(vtl): Hack (see also the TODO above): We can't currently wait for a - // specified amount of data to be available, so poll. - for (size_t i = 0; i < kMaxPoll; i++) { - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerQueryData(MakeUserPointer(&num_bytes))); - if (num_bytes >= 10u * sizeof(int32_t)) - break; - - test::Sleep(test::EpsilonDeadline()); - } - EXPECT_EQ(10u * sizeof(int32_t), num_bytes); - - // Read half. - num_bytes = 5u * sizeof(int32_t); - memset(buffer, 0xab, sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerReadData(UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), true, false)); - EXPECT_EQ(5u * sizeof(int32_t), num_bytes); - memset(expected_buffer, 0xab, sizeof(expected_buffer)); - Seq(100, 5, expected_buffer); - EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); - - // Try reading too much again. - num_bytes = 6u * sizeof(int32_t); - memset(buffer, 0xab, sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, - this->ConsumerReadData(UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), true, false)); - memset(expected_buffer, 0xab, sizeof(expected_buffer)); - EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); - - // Try discarding too much again. - num_bytes = 6u * sizeof(int32_t); - EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, - this->ConsumerDiscardData(MakeUserPointer(&num_bytes), true)); - - // Discard a little. - num_bytes = 2u * sizeof(int32_t); - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerDiscardData(MakeUserPointer(&num_bytes), true)); - EXPECT_EQ(2u * sizeof(int32_t), num_bytes); - - // Three left. - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerQueryData(MakeUserPointer(&num_bytes))); - EXPECT_EQ(3u * sizeof(int32_t), num_bytes); - - // We'll need to wait for the peer closed to propagate. - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, - 2, nullptr)); - - // Close the producer, then test producer-closed cases. - this->ProducerClose(); - - // Wait. - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), nullptr)); - hss = HandleSignalsState(); - this->ConsumerRemoveAwakable(&waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Try reading too much; "failed precondition" since the producer is closed. - num_bytes = 4u * sizeof(int32_t); - memset(buffer, 0xab, sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - this->ConsumerReadData(UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), true, false)); - memset(expected_buffer, 0xab, sizeof(expected_buffer)); - EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); - - // Try discarding too much; "failed precondition" again. - num_bytes = 4u * sizeof(int32_t); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - this->ConsumerDiscardData(MakeUserPointer(&num_bytes), true)); - - // Read a little. - num_bytes = 2u * sizeof(int32_t); - memset(buffer, 0xab, sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerReadData(UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), true, false)); - EXPECT_EQ(2u * sizeof(int32_t), num_bytes); - memset(expected_buffer, 0xab, sizeof(expected_buffer)); - Seq(400, 2, expected_buffer); - EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); - - // Discard the remaining element. - num_bytes = 1u * sizeof(int32_t); - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerDiscardData(MakeUserPointer(&num_bytes), true)); - EXPECT_EQ(1u * sizeof(int32_t), num_bytes); - - // Empty again. - num_bytes = ~0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerQueryData(MakeUserPointer(&num_bytes))); - EXPECT_EQ(0u, num_bytes); - - this->ConsumerClose(); -} - -// Tests that |ProducerWriteData()| and |ConsumerReadData()| writes and reads, -// respectively, as much as possible, even if it may have to "wrap around" the -// internal circular buffer. (Note that the two-phase write and read need not do -// this.) -TYPED_TEST(DataPipeImplTest, WrapAround) { - unsigned char test_data[1000]; - for (size_t i = 0; i < MOJO_ARRAYSIZE(test_data); i++) - test_data[i] = static_cast<unsigned char>(i); - - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 1u, // |element_num_bytes|. - 100u // |capacity_num_bytes|. - }; - MojoCreateDataPipeOptions validated_options = {}; - // This test won't be valid if |ValidateCreateOptions()| decides to give the - // pipe more space. - EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions( - MakeUserPointer(&options), &validated_options)); - ASSERT_EQ(100u, validated_options.capacity_num_bytes); - this->Create(options); - this->DoTransfer(); - - Waiter waiter; - HandleSignalsState hss; - - // Add waiter. - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 1, - nullptr)); - - // Write 20 bytes. - uint32_t num_bytes = 20u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerWriteData(UserPointer<const void>(&test_data[0]), - MakeUserPointer(&num_bytes), false)); - EXPECT_EQ(20u, num_bytes); - - // Wait for data. - // TODO(vtl): (See corresponding TODO in AllOrNone.) - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), nullptr)); - hss = HandleSignalsState(); - this->ConsumerRemoveAwakable(&waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Read 10 bytes. - unsigned char read_buffer[1000] = {0}; - num_bytes = 10u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerReadData(UserPointer<void>(read_buffer), - MakeUserPointer(&num_bytes), false, false)); - EXPECT_EQ(10u, num_bytes); - EXPECT_EQ(0, memcmp(read_buffer, &test_data[0], 10u)); - - if (this->IsStrictCircularBuffer()) { - // Check that a two-phase write can now only write (at most) 80 bytes. (This - // checks an implementation detail; this behavior is not guaranteed.) - void* write_buffer_ptr = nullptr; - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerBeginWriteData(MakeUserPointer(&write_buffer_ptr), - MakeUserPointer(&num_bytes))); - EXPECT_TRUE(write_buffer_ptr); - EXPECT_EQ(80u, num_bytes); - EXPECT_EQ(MOJO_RESULT_OK, this->ProducerEndWriteData(0u)); - } - - // TODO(vtl): (See corresponding TODO in TwoPhaseAllOrNone.) - size_t total_num_bytes = 0u; - for (size_t i = 0; i < kMaxPoll; i++) { - // Write as much data as we can (using |ProducerWriteData()|). We should - // write 90 bytes (eventually). - num_bytes = 200u; - MojoResult result = this->ProducerWriteData( - UserPointer<const void>(&test_data[20 + total_num_bytes]), - MakeUserPointer(&num_bytes), false); - if (result == MOJO_RESULT_OK) { - total_num_bytes += num_bytes; - if (total_num_bytes >= 90u) - break; - } else { - EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, result); - } - - test::Sleep(test::EpsilonDeadline()); - } - EXPECT_EQ(90u, total_num_bytes); - - // TODO(vtl): (See corresponding TODO in TwoPhaseAllOrNone.) - for (size_t i = 0; i < kMaxPoll; i++) { - // We have 100. - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerQueryData(MakeUserPointer(&num_bytes))); - if (num_bytes >= 100u) - break; - - test::Sleep(test::EpsilonDeadline()); - } - EXPECT_EQ(100u, num_bytes); - - if (this->IsStrictCircularBuffer()) { - // Check that a two-phase read can now only read (at most) 90 bytes. (This - // checks an implementation detail; this behavior is not guaranteed.) - const void* read_buffer_ptr = nullptr; - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerBeginReadData(MakeUserPointer(&read_buffer_ptr), - MakeUserPointer(&num_bytes))); - EXPECT_TRUE(read_buffer_ptr); - EXPECT_EQ(90u, num_bytes); - EXPECT_EQ(MOJO_RESULT_OK, this->ConsumerEndReadData(0u)); - } - - // Read as much as possible (using |ConsumerReadData()|). We should read 100 - // bytes. - num_bytes = static_cast<uint32_t>(MOJO_ARRAYSIZE(read_buffer) * - sizeof(read_buffer[0])); - memset(read_buffer, 0, num_bytes); - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerReadData(UserPointer<void>(read_buffer), - MakeUserPointer(&num_bytes), false, false)); - EXPECT_EQ(100u, num_bytes); - EXPECT_EQ(0, memcmp(read_buffer, &test_data[10], 100u)); - - this->ProducerClose(); - this->ConsumerClose(); -} - -// Tests the behavior of writing (simple and two-phase), closing the producer, -// then reading (simple and two-phase). -TYPED_TEST(DataPipeImplTest, WriteCloseProducerRead) { - const char kTestData[] = "hello world"; - const uint32_t kTestDataSize = static_cast<uint32_t>(sizeof(kTestData)); - - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 1u, // |element_num_bytes|. - 1000u // |capacity_num_bytes|. - }; - this->Create(options); - this->DoTransfer(); - - // Write some data, so we'll have something to read. - uint32_t num_bytes = kTestDataSize; - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerWriteData(UserPointer<const void>(kTestData), - MakeUserPointer(&num_bytes), false)); - EXPECT_EQ(kTestDataSize, num_bytes); - - // Write it again, so we'll have something left over. - num_bytes = kTestDataSize; - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerWriteData(UserPointer<const void>(kTestData), - MakeUserPointer(&num_bytes), false)); - EXPECT_EQ(kTestDataSize, num_bytes); - - // Start two-phase write. - void* write_buffer_ptr = nullptr; - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerBeginWriteData(MakeUserPointer(&write_buffer_ptr), - MakeUserPointer(&num_bytes))); - EXPECT_TRUE(write_buffer_ptr); - EXPECT_GT(num_bytes, 0u); - - // TODO(vtl): (See corresponding TODO in TwoPhaseAllOrNone.) - for (size_t i = 0; i < kMaxPoll; i++) { - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerQueryData(MakeUserPointer(&num_bytes))); - if (num_bytes >= 2u * kTestDataSize) - break; - - test::Sleep(test::EpsilonDeadline()); - } - EXPECT_EQ(2u * kTestDataSize, num_bytes); - - // Start two-phase read. - const void* read_buffer_ptr = nullptr; - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerBeginReadData(MakeUserPointer(&read_buffer_ptr), - MakeUserPointer(&num_bytes))); - EXPECT_TRUE(read_buffer_ptr); - EXPECT_EQ(2u * kTestDataSize, num_bytes); - - // Close the producer. - this->ProducerClose(); - - // The consumer can finish its two-phase read. - EXPECT_EQ(0, memcmp(read_buffer_ptr, kTestData, kTestDataSize)); - EXPECT_EQ(MOJO_RESULT_OK, this->ConsumerEndReadData(kTestDataSize)); - - // And start another. - read_buffer_ptr = nullptr; - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerBeginReadData(MakeUserPointer(&read_buffer_ptr), - MakeUserPointer(&num_bytes))); - EXPECT_TRUE(read_buffer_ptr); - EXPECT_EQ(kTestDataSize, num_bytes); - - // Close the consumer, which cancels the two-phase read. - this->ConsumerClose(); -} - -// Tests the behavior of interrupting a two-phase read and write by closing the -// consumer. -TYPED_TEST(DataPipeImplTest, TwoPhaseWriteReadCloseConsumer) { - const char kTestData[] = "hello world"; - const uint32_t kTestDataSize = static_cast<uint32_t>(sizeof(kTestData)); - - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 1u, // |element_num_bytes|. - 1000u // |capacity_num_bytes|. - }; - this->Create(options); - this->DoTransfer(); - - Waiter waiter; - HandleSignalsState hss; - - // Add waiter. - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 1, - nullptr)); - - // Write some data, so we'll have something to read. - uint32_t num_bytes = kTestDataSize; - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerWriteData(UserPointer<const void>(kTestData), - MakeUserPointer(&num_bytes), false)); - EXPECT_EQ(kTestDataSize, num_bytes); - - // Start two-phase write. - void* write_buffer_ptr = nullptr; - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerBeginWriteData(MakeUserPointer(&write_buffer_ptr), - MakeUserPointer(&num_bytes))); - EXPECT_TRUE(write_buffer_ptr); - ASSERT_GT(num_bytes, kTestDataSize); - - // Wait for data. - // TODO(vtl): (See corresponding TODO in AllOrNone.) - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), nullptr)); - hss = HandleSignalsState(); - this->ConsumerRemoveAwakable(&waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Start two-phase read. - const void* read_buffer_ptr = nullptr; - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerBeginReadData(MakeUserPointer(&read_buffer_ptr), - MakeUserPointer(&num_bytes))); - EXPECT_TRUE(read_buffer_ptr); - EXPECT_EQ(kTestDataSize, num_bytes); - - // Add waiter. - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, - 1, nullptr)); - - // Close the consumer. - this->ConsumerClose(); - - // Wait for producer to know that the consumer is closed. - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), nullptr)); - hss = HandleSignalsState(); - this->ProducerRemoveAwakable(&waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - // Actually write some data. (Note: Premature freeing of the buffer would - // probably only be detected under ASAN or similar.) - memcpy(write_buffer_ptr, kTestData, kTestDataSize); - // Note: Even though the consumer has been closed, ending the two-phase - // write will report success. - EXPECT_EQ(MOJO_RESULT_OK, this->ProducerEndWriteData(kTestDataSize)); - - // But trying to write should result in failure. - num_bytes = kTestDataSize; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - this->ProducerWriteData(UserPointer<const void>(kTestData), - MakeUserPointer(&num_bytes), false)); - - // As will trying to start another two-phase write. - write_buffer_ptr = nullptr; - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - this->ProducerBeginWriteData(MakeUserPointer(&write_buffer_ptr), - MakeUserPointer(&num_bytes))); - - this->ProducerClose(); -} - -// Tests the behavior of "interrupting" a two-phase write by closing both the -// producer and the consumer. -TYPED_TEST(DataPipeImplTest, TwoPhaseWriteCloseBoth) { - const uint32_t kTestDataSize = 15u; - - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 1u, // |element_num_bytes|. - 1000u // |capacity_num_bytes|. - }; - this->Create(options); - this->DoTransfer(); - - // Start two-phase write. - void* write_buffer_ptr = nullptr; - uint32_t num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerBeginWriteData(MakeUserPointer(&write_buffer_ptr), - MakeUserPointer(&num_bytes))); - EXPECT_TRUE(write_buffer_ptr); - ASSERT_GT(num_bytes, kTestDataSize); - - this->ConsumerClose(); - this->ProducerClose(); -} - -// Tests the behavior of writing, closing the producer, and then reading (with -// and without data remaining). -TYPED_TEST(DataPipeImplTest, WriteCloseProducerReadNoData) { - const char kTestData[] = "hello world"; - const uint32_t kTestDataSize = static_cast<uint32_t>(sizeof(kTestData)); - - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 1u, // |element_num_bytes|. - 1000u // |capacity_num_bytes|. - }; - this->Create(options); - this->DoTransfer(); - - Waiter waiter; - HandleSignalsState hss; - - // Write some data, so we'll have something to read. - uint32_t num_bytes = kTestDataSize; - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerWriteData(UserPointer<const void>(kTestData), - MakeUserPointer(&num_bytes), false)); - EXPECT_EQ(kTestDataSize, num_bytes); - - // Add waiter. - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, - 1, nullptr)); - - // Close the producer. - this->ProducerClose(); - - // Wait. (Note that once the consumer knows that the producer is closed, it - // must also know about all the data that was sent.) - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), nullptr)); - hss = HandleSignalsState(); - this->ConsumerRemoveAwakable(&waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Peek that data. - char buffer[1000]; - num_bytes = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerReadData(UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), false, true)); - EXPECT_EQ(kTestDataSize, num_bytes); - EXPECT_EQ(0, memcmp(buffer, kTestData, kTestDataSize)); - - // Read that data. - memset(buffer, 0, 1000); - num_bytes = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerReadData(UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), false, false)); - EXPECT_EQ(kTestDataSize, num_bytes); - EXPECT_EQ(0, memcmp(buffer, kTestData, kTestDataSize)); - - // A second read should fail. - num_bytes = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - this->ConsumerReadData(UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), false, false)); - - // A two-phase read should also fail. - const void* read_buffer_ptr = nullptr; - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - this->ConsumerBeginReadData(MakeUserPointer(&read_buffer_ptr), - MakeUserPointer(&num_bytes))); - - // Ditto for discard. - num_bytes = 10u; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - this->ConsumerDiscardData(MakeUserPointer(&num_bytes), false)); - - this->ConsumerClose(); -} - -// Tests the behavior of writing, reading (all the data), closing the producer, -// and then waiting for more data (with no data remaining). -TYPED_TEST(DataPipeImplTest, WriteReadCloseProducerWaitNoData) { - const int64_t kTestData = 123456789012345LL; - const uint32_t kTestDataSize = static_cast<uint32_t>(sizeof(kTestData)); - - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - kTestDataSize, // |element_num_bytes|. - 100u * kTestDataSize // |capacity_num_bytes|. - }; - this->Create(options); - this->DoTransfer(); - - Waiter waiter; - HandleSignalsState hss; - - // Add waiter. - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 0, - nullptr)); - - // Write some data, so we'll have something to read. - uint32_t num_bytes = kTestDataSize; - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerWriteData(UserPointer<const void>(&kTestData), - MakeUserPointer(&num_bytes), false)); - EXPECT_EQ(kTestDataSize, num_bytes); - - // Wait. - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), nullptr)); - hss = HandleSignalsState(); - this->ConsumerRemoveAwakable(&waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Read that data. - int64_t data[10] = {}; - num_bytes = static_cast<uint32_t>(sizeof(data)); - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerReadData(UserPointer<void>(data), - MakeUserPointer(&num_bytes), false, false)); - EXPECT_EQ(kTestDataSize, num_bytes); - EXPECT_EQ(kTestData, data[0]); - - // Add waiter again. - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 0, - nullptr)); - - // Close the producer. - this->ProducerClose(); - - // Wait. - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - waiter.Wait(test::TinyDeadline(), nullptr)); - hss = HandleSignalsState(); - this->ConsumerRemoveAwakable(&waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - this->ConsumerClose(); -} - -// During a two-phase read, the consumer is not readable so it may be waited -// upon (to become readable again). If the producer is closed and the two-phase -// read consumes the remaining data, that wait should become unsatisfiable. -TYPED_TEST(DataPipeImplTest, BeginReadCloseProducerWaitEndReadNoData) { - const int64_t kTestData = 123456789012345LL; - const uint32_t kTestDataSize = static_cast<uint32_t>(sizeof(kTestData)); - - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - kTestDataSize, // |element_num_bytes|. - 100u * kTestDataSize // |capacity_num_bytes|. - }; - this->Create(options); - this->DoTransfer(); - - Waiter waiter; - HandleSignalsState hss; - - // Add waiter (for the consumer to become readable). - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 0, - nullptr)); - - // Write some data, so we'll have something to read. - uint32_t num_bytes = kTestDataSize; - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerWriteData(UserPointer<const void>(&kTestData), - MakeUserPointer(&num_bytes), false)); - EXPECT_EQ(kTestDataSize, num_bytes); - - // Wait. - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), nullptr)); - hss = HandleSignalsState(); - this->ConsumerRemoveAwakable(&waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Start a two-phase read. - num_bytes = 0u; - const void* read_ptr = nullptr; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerBeginReadData(MakeUserPointer(&read_ptr), - MakeUserPointer(&num_bytes))); - EXPECT_EQ(kTestDataSize, num_bytes); - EXPECT_EQ(kTestData, static_cast<const int64_t*>(read_ptr)[0]); - - // Add waiter (for the producer to be closed). - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, - 0, nullptr)); - - // Close the producer. - this->ProducerClose(); - - // Wait for producer close to be detected. - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), nullptr)); - hss = HandleSignalsState(); - this->ConsumerRemoveAwakable(&waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Add waiter (for the consumer to become readable). - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 0, - nullptr)); - - // Complete the two-phase read. - EXPECT_EQ(MOJO_RESULT_OK, this->ConsumerEndReadData(kTestDataSize)); - - // Wait. - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - waiter.Wait(test::TinyDeadline(), nullptr)); - hss = HandleSignalsState(); - this->ConsumerRemoveAwakable(&waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - this->ConsumerClose(); -} - -// During a two-phase write, the producer is not writable so it may be waited -// upon (to become writable again). If the consumer is closed, that wait should -// become unsatisfiable. -TYPED_TEST(DataPipeImplTest, BeginWriteCloseConsumerWaitEndWrite) { - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 1u, // |element_num_bytes|. - 100u // |capacity_num_bytes|. - }; - this->Create(options); - this->DoTransfer(); - - Waiter waiter1; - Waiter waiter2; - HandleSignalsState hss; - - // Start a two-phase write. - void* write_ptr = nullptr; - uint32_t num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerBeginWriteData(MakeUserPointer(&write_ptr), - MakeUserPointer(&num_bytes))); - - // Add waiter (for the consumer to be closed). - waiter1.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ProducerAddAwakable(&waiter1, MOJO_HANDLE_SIGNAL_PEER_CLOSED, - 0, nullptr)); - - // Add a separate waiter (for the producer to become writable). - waiter2.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ProducerAddAwakable(&waiter2, MOJO_HANDLE_SIGNAL_WRITABLE, 0, - nullptr)); - - // Close the consumer. - this->ConsumerClose(); - - // Wait for the consumer close to be detected. - // Note: If we didn't wait for the consumer close to be detected before - // completing the two-phase write, wait might succeed (in the remote cases). - // This is because the first |Awake()| "wins". - EXPECT_EQ(MOJO_RESULT_OK, waiter1.Wait(test::TinyDeadline(), nullptr)); - hss = HandleSignalsState(); - this->ProducerRemoveAwakable(&waiter1, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - // Complete the two-phase write (with nothing written). - EXPECT_EQ(MOJO_RESULT_OK, this->ProducerEndWriteData(0u)); - - // Wait. - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - waiter2.Wait(test::TinyDeadline(), nullptr)); - hss = HandleSignalsState(); - this->ProducerRemoveAwakable(&waiter2, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - this->ProducerClose(); -} - -// Test that two-phase reads/writes behave correctly when given invalid -// arguments. -TYPED_TEST(DataPipeImplTest, TwoPhaseMoreInvalidArguments) { - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. - 10 * sizeof(int32_t) // |capacity_num_bytes|. - }; - this->Create(options); - this->DoTransfer(); - - Waiter waiter; - HandleSignalsState hss; - - // No data. - uint32_t num_bytes = 1000u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerQueryData(MakeUserPointer(&num_bytes))); - EXPECT_EQ(0u, num_bytes); - - // Try "ending" a two-phase write when one isn't active. - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - this->ProducerEndWriteData(1u * sizeof(int32_t))); - - // Wait a bit, to make sure that if a signal were (incorrectly) sent, it'd - // have time to propagate. - test::Sleep(test::EpsilonDeadline()); - - // Still no data. - num_bytes = 1000u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerQueryData(MakeUserPointer(&num_bytes))); - EXPECT_EQ(0u, num_bytes); - - // Try ending a two-phase write with an invalid amount (too much). - void* write_ptr = nullptr; - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerBeginWriteData(MakeUserPointer(&write_ptr), - MakeUserPointer(&num_bytes))); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - this->ProducerEndWriteData(num_bytes + - static_cast<uint32_t>(sizeof(int32_t)))); - - // But the two-phase write still ended. - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, this->ProducerEndWriteData(0u)); - - // Wait a bit (as above). - test::Sleep(test::EpsilonDeadline()); - - // Still no data. - num_bytes = 1000u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerQueryData(MakeUserPointer(&num_bytes))); - EXPECT_EQ(0u, num_bytes); - - // Try ending a two-phase write with an invalid amount (not a multiple of the - // element size). - write_ptr = nullptr; - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerBeginWriteData(MakeUserPointer(&write_ptr), - MakeUserPointer(&num_bytes))); - EXPECT_GE(num_bytes, 1u); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, this->ProducerEndWriteData(1u)); - - // But the two-phase write still ended. - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, this->ProducerEndWriteData(0u)); - - // Wait a bit (as above). - test::Sleep(test::EpsilonDeadline()); - - // Still no data. - num_bytes = 1000u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerQueryData(MakeUserPointer(&num_bytes))); - EXPECT_EQ(0u, num_bytes); - - // Add waiter. - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 1, - nullptr)); - - // Now write some data, so we'll be able to try reading. - int32_t element = 123; - num_bytes = 1u * sizeof(int32_t); - EXPECT_EQ(MOJO_RESULT_OK, - this->ProducerWriteData(UserPointer<const void>(&element), - MakeUserPointer(&num_bytes), false)); - - // Wait for data. - // TODO(vtl): (See corresponding TODO in AllOrNone.) - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), nullptr)); - hss = HandleSignalsState(); - this->ConsumerRemoveAwakable(&waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // One element available. - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerQueryData(MakeUserPointer(&num_bytes))); - EXPECT_EQ(1u * sizeof(int32_t), num_bytes); - - // Try "ending" a two-phase read when one isn't active. - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - this->ConsumerEndReadData(1u * sizeof(int32_t))); - - // Still one element available. - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerQueryData(MakeUserPointer(&num_bytes))); - EXPECT_EQ(1u * sizeof(int32_t), num_bytes); - - // Try ending a two-phase read with an invalid amount (too much). - num_bytes = 0u; - const void* read_ptr = nullptr; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerBeginReadData(MakeUserPointer(&read_ptr), - MakeUserPointer(&num_bytes))); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - this->ConsumerEndReadData(num_bytes + - static_cast<uint32_t>(sizeof(int32_t)))); - - // Still one element available. - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerQueryData(MakeUserPointer(&num_bytes))); - EXPECT_EQ(1u * sizeof(int32_t), num_bytes); - - // Try ending a two-phase read with an invalid amount (not a multiple of the - // element size). - num_bytes = 0u; - read_ptr = nullptr; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerBeginReadData(MakeUserPointer(&read_ptr), - MakeUserPointer(&num_bytes))); - EXPECT_EQ(1u * sizeof(int32_t), num_bytes); - EXPECT_EQ(123, static_cast<const int32_t*>(read_ptr)[0]); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, this->ConsumerEndReadData(1u)); - - // Still one element available. - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - this->ConsumerQueryData(MakeUserPointer(&num_bytes))); - EXPECT_EQ(1u * sizeof(int32_t), num_bytes); - - this->ProducerClose(); - this->ConsumerClose(); -} - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.cc b/third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.cc deleted file mode 100644 index 0495c97..0000000 --- a/third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.cc +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.h" - -#include "base/logging.h" -#include "third_party/mojo/src/mojo/edk/system/data_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/memory.h" - -namespace mojo { -namespace system { - -void DataPipeProducerDispatcher::Init(scoped_refptr<DataPipe> data_pipe) { - DCHECK(data_pipe); - data_pipe_ = data_pipe; -} - -Dispatcher::Type DataPipeProducerDispatcher::GetType() const { - return Type::DATA_PIPE_PRODUCER; -} - -// static -scoped_refptr<DataPipeProducerDispatcher> -DataPipeProducerDispatcher::Deserialize(Channel* channel, - const void* source, - size_t size) { - scoped_refptr<DataPipe> data_pipe; - if (!DataPipe::ProducerDeserialize(channel, source, size, &data_pipe)) - return nullptr; - DCHECK(data_pipe); - - scoped_refptr<DataPipeProducerDispatcher> dispatcher = Create(); - dispatcher->Init(data_pipe); - return dispatcher; -} - -DataPipe* DataPipeProducerDispatcher::GetDataPipeForTest() { - MutexLocker locker(&mutex()); - return data_pipe_.get(); -} - -DataPipeProducerDispatcher::DataPipeProducerDispatcher() { -} - -DataPipeProducerDispatcher::~DataPipeProducerDispatcher() { - // |Close()|/|CloseImplNoLock()| should have taken care of the pipe. - DCHECK(!data_pipe_); -} - -void DataPipeProducerDispatcher::CancelAllAwakablesNoLock() { - mutex().AssertHeld(); - data_pipe_->ProducerCancelAllAwakables(); -} - -void DataPipeProducerDispatcher::CloseImplNoLock() { - mutex().AssertHeld(); - data_pipe_->ProducerClose(); - data_pipe_ = nullptr; -} - -scoped_refptr<Dispatcher> -DataPipeProducerDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() { - mutex().AssertHeld(); - - scoped_refptr<DataPipeProducerDispatcher> rv = Create(); - rv->Init(data_pipe_); - data_pipe_ = nullptr; - return scoped_refptr<Dispatcher>(rv.get()); -} - -MojoResult DataPipeProducerDispatcher::WriteDataImplNoLock( - UserPointer<const void> elements, - UserPointer<uint32_t> num_bytes, - MojoWriteDataFlags flags) { - mutex().AssertHeld(); - return data_pipe_->ProducerWriteData( - elements, num_bytes, (flags & MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)); -} - -MojoResult DataPipeProducerDispatcher::BeginWriteDataImplNoLock( - UserPointer<void*> buffer, - UserPointer<uint32_t> buffer_num_bytes, - MojoWriteDataFlags flags) { - mutex().AssertHeld(); - - return data_pipe_->ProducerBeginWriteData(buffer, buffer_num_bytes); -} - -MojoResult DataPipeProducerDispatcher::EndWriteDataImplNoLock( - uint32_t num_bytes_written) { - mutex().AssertHeld(); - - return data_pipe_->ProducerEndWriteData(num_bytes_written); -} - -HandleSignalsState DataPipeProducerDispatcher::GetHandleSignalsStateImplNoLock() - const { - mutex().AssertHeld(); - return data_pipe_->ProducerGetHandleSignalsState(); -} - -MojoResult DataPipeProducerDispatcher::AddAwakableImplNoLock( - Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state) { - mutex().AssertHeld(); - return data_pipe_->ProducerAddAwakable(awakable, signals, context, - signals_state); -} - -void DataPipeProducerDispatcher::RemoveAwakableImplNoLock( - Awakable* awakable, - HandleSignalsState* signals_state) { - mutex().AssertHeld(); - data_pipe_->ProducerRemoveAwakable(awakable, signals_state); -} - -void DataPipeProducerDispatcher::StartSerializeImplNoLock( - Channel* channel, - size_t* max_size, - size_t* max_platform_handles) { - DCHECK(HasOneRef()); // Only one ref => no need to take the lock. - data_pipe_->ProducerStartSerialize(channel, max_size, max_platform_handles); -} - -bool DataPipeProducerDispatcher::EndSerializeAndCloseImplNoLock( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) { - DCHECK(HasOneRef()); // Only one ref => no need to take the lock. - - bool rv = data_pipe_->ProducerEndSerialize(channel, destination, actual_size, - platform_handles); - data_pipe_ = nullptr; - return rv; -} - -bool DataPipeProducerDispatcher::IsBusyNoLock() const { - mutex().AssertHeld(); - return data_pipe_->ProducerIsBusy(); -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.h b/third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.h deleted file mode 100644 index 0685683..0000000 --- a/third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.h +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_DATA_PIPE_PRODUCER_DISPATCHER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_DATA_PIPE_PRODUCER_DISPATCHER_H_ - -#include "base/memory/ref_counted.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -class DataPipe; - -// This is the |Dispatcher| implementation for the producer handle for data -// pipes (created by the Mojo primitive |MojoCreateDataPipe()|). This class is -// thread-safe. -class MOJO_SYSTEM_IMPL_EXPORT DataPipeProducerDispatcher final - : public Dispatcher { - public: - static scoped_refptr<DataPipeProducerDispatcher> Create() { - return make_scoped_refptr(new DataPipeProducerDispatcher()); - } - - // Must be called before any other methods. - void Init(scoped_refptr<DataPipe> data_pipe) MOJO_NOT_THREAD_SAFE; - - // |Dispatcher| public methods: - Type GetType() const override; - - // The "opposite" of |SerializeAndClose()|. (Typically this is called by - // |Dispatcher::Deserialize()|.) - static scoped_refptr<DataPipeProducerDispatcher> - Deserialize(Channel* channel, const void* source, size_t size); - - // Get access to the |DataPipe| for testing. - DataPipe* GetDataPipeForTest(); - - private: - DataPipeProducerDispatcher(); - ~DataPipeProducerDispatcher() override; - - // |Dispatcher| protected methods: - void CancelAllAwakablesNoLock() override; - void CloseImplNoLock() override; - scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock() - override; - MojoResult WriteDataImplNoLock(UserPointer<const void> elements, - UserPointer<uint32_t> num_bytes, - MojoWriteDataFlags flags) override; - MojoResult BeginWriteDataImplNoLock(UserPointer<void*> buffer, - UserPointer<uint32_t> buffer_num_bytes, - MojoWriteDataFlags flags) override; - MojoResult EndWriteDataImplNoLock(uint32_t num_bytes_written) override; - HandleSignalsState GetHandleSignalsStateImplNoLock() const override; - MojoResult AddAwakableImplNoLock(Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state) override; - void RemoveAwakableImplNoLock(Awakable* awakable, - HandleSignalsState* signals_state) override; - void StartSerializeImplNoLock(Channel* channel, - size_t* max_size, - size_t* max_platform_handles) override - MOJO_NOT_THREAD_SAFE; - bool EndSerializeAndCloseImplNoLock( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) override - MOJO_NOT_THREAD_SAFE; - bool IsBusyNoLock() const override; - - // This will be null if closed. - scoped_refptr<DataPipe> data_pipe_ MOJO_GUARDED_BY(mutex()); - - MOJO_DISALLOW_COPY_AND_ASSIGN(DataPipeProducerDispatcher); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_DATA_PIPE_PRODUCER_DISPATCHER_H_ diff --git a/third_party/mojo/src/mojo/edk/system/data_pipe_unittest.cc b/third_party/mojo/src/mojo/edk/system/data_pipe_unittest.cc deleted file mode 100644 index 2cb2bbd..0000000 --- a/third_party/mojo/src/mojo/edk/system/data_pipe_unittest.cc +++ /dev/null @@ -1,375 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/data_pipe.h" - -#include <stddef.h> -#include <stdint.h> - -#include <limits> - -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/system/configuration.h" - -namespace mojo { -namespace system { -namespace { - -const uint32_t kSizeOfCreateOptions = - static_cast<uint32_t>(sizeof(MojoCreateDataPipeOptions)); - -// Does a cursory sanity check of |validated_options|. Calls -// |ValidateCreateOptions()| on already-validated options. The validated options -// should be valid, and the revalidated copy should be the same. -void RevalidateCreateOptions( - const MojoCreateDataPipeOptions& validated_options) { - EXPECT_EQ(kSizeOfCreateOptions, validated_options.struct_size); - // Nothing to check for flags. - EXPECT_GT(validated_options.element_num_bytes, 0u); - EXPECT_GT(validated_options.capacity_num_bytes, 0u); - EXPECT_EQ(0u, validated_options.capacity_num_bytes % - validated_options.element_num_bytes); - - MojoCreateDataPipeOptions revalidated_options = {}; - EXPECT_EQ(MOJO_RESULT_OK, - DataPipe::ValidateCreateOptions(MakeUserPointer(&validated_options), - &revalidated_options)); - EXPECT_EQ(validated_options.struct_size, revalidated_options.struct_size); - EXPECT_EQ(validated_options.element_num_bytes, - revalidated_options.element_num_bytes); - EXPECT_EQ(validated_options.capacity_num_bytes, - revalidated_options.capacity_num_bytes); - EXPECT_EQ(validated_options.flags, revalidated_options.flags); -} - -// Checks that a default-computed capacity is correct. (Does not duplicate the -// checks done by |RevalidateCreateOptions()|.) -void CheckDefaultCapacity(const MojoCreateDataPipeOptions& validated_options) { - EXPECT_LE(validated_options.capacity_num_bytes, - GetConfiguration().default_data_pipe_capacity_bytes); - EXPECT_GT(validated_options.capacity_num_bytes + - validated_options.element_num_bytes, - GetConfiguration().default_data_pipe_capacity_bytes); -} - -// Tests valid inputs to |ValidateCreateOptions()|. -TEST(DataPipeTest, ValidateCreateOptionsValid) { - // Default options. - { - MojoCreateDataPipeOptions validated_options = {}; - EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions( - NullUserPointer(), &validated_options)); - RevalidateCreateOptions(validated_options); - CheckDefaultCapacity(validated_options); - } - - // Size member, but nothing beyond. - { - MojoCreateDataPipeOptions options = { - offsetof(MojoCreateDataPipeOptions, flags) // |struct_size|. - }; - MojoCreateDataPipeOptions validated_options = {}; - EXPECT_EQ(MOJO_RESULT_OK, - DataPipe::ValidateCreateOptions(MakeUserPointer(&options), - &validated_options)); - RevalidateCreateOptions(validated_options); - CheckDefaultCapacity(validated_options); - } - - // Different flags. - MojoCreateDataPipeOptionsFlags flags_values[] = { - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE}; - for (size_t i = 0; i < MOJO_ARRAYSIZE(flags_values); i++) { - const MojoCreateDataPipeOptionsFlags flags = flags_values[i]; - - // Flags member, but nothing beyond. - { - MojoCreateDataPipeOptions options = { - // |struct_size|. - offsetof(MojoCreateDataPipeOptions, element_num_bytes), - flags // |flags|. - }; - MojoCreateDataPipeOptions validated_options = {}; - EXPECT_EQ(MOJO_RESULT_OK, - DataPipe::ValidateCreateOptions(MakeUserPointer(&options), - &validated_options)); - RevalidateCreateOptions(validated_options); - EXPECT_EQ(options.flags, validated_options.flags); - CheckDefaultCapacity(validated_options); - } - - // Different capacities (size 1). - for (uint32_t capacity = 1; capacity <= 100 * 1000 * 1000; capacity *= 10) { - MojoCreateDataPipeOptions options = { - kSizeOfCreateOptions, // |struct_size|. - flags, // |flags|. - 1, // |element_num_bytes|. - capacity // |capacity_num_bytes|. - }; - MojoCreateDataPipeOptions validated_options = {}; - EXPECT_EQ(MOJO_RESULT_OK, - DataPipe::ValidateCreateOptions(MakeUserPointer(&options), - &validated_options)) - << capacity; - RevalidateCreateOptions(validated_options); - EXPECT_EQ(options.flags, validated_options.flags); - EXPECT_EQ(options.element_num_bytes, validated_options.element_num_bytes); - EXPECT_EQ(options.capacity_num_bytes, - validated_options.capacity_num_bytes); - } - - // Small sizes. - for (uint32_t size = 1; size < 100; size++) { - // Different capacities. - for (uint32_t elements = 1; elements <= 1000 * 1000; elements *= 10) { - MojoCreateDataPipeOptions options = { - kSizeOfCreateOptions, // |struct_size|. - flags, // |flags|. - size, // |element_num_bytes|. - size * elements // |capacity_num_bytes|. - }; - MojoCreateDataPipeOptions validated_options = {}; - EXPECT_EQ(MOJO_RESULT_OK, - DataPipe::ValidateCreateOptions(MakeUserPointer(&options), - &validated_options)) - << size << ", " << elements; - RevalidateCreateOptions(validated_options); - EXPECT_EQ(options.flags, validated_options.flags); - EXPECT_EQ(options.element_num_bytes, - validated_options.element_num_bytes); - EXPECT_EQ(options.capacity_num_bytes, - validated_options.capacity_num_bytes); - } - - // Default capacity. - { - MojoCreateDataPipeOptions options = { - kSizeOfCreateOptions, // |struct_size|. - flags, // |flags|. - size, // |element_num_bytes|. - 0 // |capacity_num_bytes|. - }; - MojoCreateDataPipeOptions validated_options = {}; - EXPECT_EQ(MOJO_RESULT_OK, - DataPipe::ValidateCreateOptions(MakeUserPointer(&options), - &validated_options)) - << size; - RevalidateCreateOptions(validated_options); - EXPECT_EQ(options.flags, validated_options.flags); - EXPECT_EQ(options.element_num_bytes, - validated_options.element_num_bytes); - CheckDefaultCapacity(validated_options); - } - - // No capacity field. - { - MojoCreateDataPipeOptions options = { - // |struct_size|. - offsetof(MojoCreateDataPipeOptions, capacity_num_bytes), - flags, // |flags|. - size // |element_num_bytes|. - }; - MojoCreateDataPipeOptions validated_options = {}; - EXPECT_EQ(MOJO_RESULT_OK, - DataPipe::ValidateCreateOptions(MakeUserPointer(&options), - &validated_options)) - << size; - RevalidateCreateOptions(validated_options); - EXPECT_EQ(options.flags, validated_options.flags); - EXPECT_EQ(options.element_num_bytes, - validated_options.element_num_bytes); - CheckDefaultCapacity(validated_options); - } - } - - // Larger sizes. - for (uint32_t size = 100; size <= 100 * 1000; size *= 10) { - // Capacity of 1000 elements. - { - MojoCreateDataPipeOptions options = { - kSizeOfCreateOptions, // |struct_size|. - flags, // |flags|. - size, // |element_num_bytes|. - 1000 * size // |capacity_num_bytes|. - }; - MojoCreateDataPipeOptions validated_options = {}; - EXPECT_EQ(MOJO_RESULT_OK, - DataPipe::ValidateCreateOptions(MakeUserPointer(&options), - &validated_options)) - << size; - RevalidateCreateOptions(validated_options); - EXPECT_EQ(options.flags, validated_options.flags); - EXPECT_EQ(options.element_num_bytes, - validated_options.element_num_bytes); - EXPECT_EQ(options.capacity_num_bytes, - validated_options.capacity_num_bytes); - } - - // Default capacity. - { - MojoCreateDataPipeOptions options = { - kSizeOfCreateOptions, // |struct_size|. - flags, // |flags|. - size, // |element_num_bytes|. - 0 // |capacity_num_bytes|. - }; - MojoCreateDataPipeOptions validated_options = {}; - EXPECT_EQ(MOJO_RESULT_OK, - DataPipe::ValidateCreateOptions(MakeUserPointer(&options), - &validated_options)) - << size; - RevalidateCreateOptions(validated_options); - EXPECT_EQ(options.flags, validated_options.flags); - EXPECT_EQ(options.element_num_bytes, - validated_options.element_num_bytes); - CheckDefaultCapacity(validated_options); - } - - // No capacity field. - { - MojoCreateDataPipeOptions options = { - // |struct_size|. - offsetof(MojoCreateDataPipeOptions, capacity_num_bytes), - flags, // |flags|. - size // |element_num_bytes|. - }; - MojoCreateDataPipeOptions validated_options = {}; - EXPECT_EQ(MOJO_RESULT_OK, - DataPipe::ValidateCreateOptions(MakeUserPointer(&options), - &validated_options)) - << size; - RevalidateCreateOptions(validated_options); - EXPECT_EQ(options.flags, validated_options.flags); - EXPECT_EQ(options.element_num_bytes, - validated_options.element_num_bytes); - CheckDefaultCapacity(validated_options); - } - } - } -} - -TEST(DataPipeTest, ValidateCreateOptionsInvalid) { - // Invalid |struct_size|. - { - MojoCreateDataPipeOptions options = { - 1, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 1, // |element_num_bytes|. - 0 // |capacity_num_bytes|. - }; - MojoCreateDataPipeOptions unused; - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused)); - } - - // Unknown |flags|. - { - MojoCreateDataPipeOptions options = { - kSizeOfCreateOptions, // |struct_size|. - ~0u, // |flags|. - 1, // |element_num_bytes|. - 0 // |capacity_num_bytes|. - }; - MojoCreateDataPipeOptions unused; - EXPECT_EQ( - MOJO_RESULT_UNIMPLEMENTED, - DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused)); - } - - // Invalid |element_num_bytes|. - { - MojoCreateDataPipeOptions options = { - kSizeOfCreateOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 0, // |element_num_bytes|. - 1000 // |capacity_num_bytes|. - }; - MojoCreateDataPipeOptions unused; - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused)); - } - // |element_num_bytes| too big. - { - MojoCreateDataPipeOptions options = { - kSizeOfCreateOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - std::numeric_limits<uint32_t>::max(), // |element_num_bytes|. - std::numeric_limits<uint32_t>::max() // |capacity_num_bytes|. - }; - MojoCreateDataPipeOptions unused; - EXPECT_EQ( - MOJO_RESULT_RESOURCE_EXHAUSTED, - DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused)); - } - { - MojoCreateDataPipeOptions options = { - kSizeOfCreateOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - std::numeric_limits<uint32_t>::max() - 1000, // |element_num_bytes|. - std::numeric_limits<uint32_t>::max() - 1000 // |capacity_num_bytes|. - }; - MojoCreateDataPipeOptions unused; - EXPECT_EQ( - MOJO_RESULT_RESOURCE_EXHAUSTED, - DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused)); - } - - // Invalid |capacity_num_bytes|. - { - MojoCreateDataPipeOptions options = { - kSizeOfCreateOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 2, // |element_num_bytes|. - 1 // |capacity_num_bytes|. - }; - MojoCreateDataPipeOptions unused; - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused)); - } - { - MojoCreateDataPipeOptions options = { - kSizeOfCreateOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 2, // |element_num_bytes|. - 111 // |capacity_num_bytes|. - }; - MojoCreateDataPipeOptions unused; - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused)); - } - { - MojoCreateDataPipeOptions options = { - kSizeOfCreateOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 5, // |element_num_bytes|. - 104 // |capacity_num_bytes|. - }; - MojoCreateDataPipeOptions unused; - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused)); - } - // |capacity_num_bytes| too big. - { - MojoCreateDataPipeOptions options = { - kSizeOfCreateOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 8, // |element_num_bytes|. - 0xffff0000 // |capacity_num_bytes|. - }; - MojoCreateDataPipeOptions unused; - EXPECT_EQ( - MOJO_RESULT_RESOURCE_EXHAUSTED, - DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused)); - } -} - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/dispatcher.cc b/third_party/mojo/src/mojo/edk/system/dispatcher.cc deleted file mode 100644 index ba4fe18..0000000 --- a/third_party/mojo/src/mojo/edk/system/dispatcher.cc +++ /dev/null @@ -1,557 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/dispatcher.h" - -#include "base/logging.h" -#include "third_party/mojo/src/mojo/edk/system/configuration.h" -#include "third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher.h" - -namespace mojo { -namespace system { - -namespace test { - -// TODO(vtl): Maybe this should be defined in a test-only file instead. -DispatcherTransport DispatcherTryStartTransport(Dispatcher* dispatcher) { - return Dispatcher::HandleTableAccess::TryStartTransport(dispatcher); -} - -} // namespace test - -// Dispatcher ------------------------------------------------------------------ - -// TODO(vtl): The thread-safety analyzer isn't smart enough to deal with the -// fact that we give up if |TryLock()| fails. -// static -DispatcherTransport Dispatcher::HandleTableAccess::TryStartTransport( - Dispatcher* dispatcher) MOJO_NO_THREAD_SAFETY_ANALYSIS { - DCHECK(dispatcher); - - if (!dispatcher->mutex_.TryLock()) - return DispatcherTransport(); - - // We shouldn't race with things that close dispatchers, since closing can - // only take place either under |handle_table_mutex_| or when the handle is - // marked as busy. - DCHECK(!dispatcher->is_closed_); - - return DispatcherTransport(dispatcher); -} - -// static -void Dispatcher::TransportDataAccess::StartSerialize( - Dispatcher* dispatcher, - Channel* channel, - size_t* max_size, - size_t* max_platform_handles) { - DCHECK(dispatcher); - dispatcher->StartSerialize(channel, max_size, max_platform_handles); -} - -// static -bool Dispatcher::TransportDataAccess::EndSerializeAndClose( - Dispatcher* dispatcher, - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) { - DCHECK(dispatcher); - return dispatcher->EndSerializeAndClose(channel, destination, actual_size, - platform_handles); -} - -// static -scoped_refptr<Dispatcher> Dispatcher::TransportDataAccess::Deserialize( - Channel* channel, - int32_t type, - const void* source, - size_t size, - embedder::PlatformHandleVector* platform_handles) { - switch (static_cast<Dispatcher::Type>(type)) { - case Type::WAIT_SET: - case Type::UNKNOWN: - DVLOG(2) << "Deserializing invalid handle"; - return nullptr; - case Type::MESSAGE_PIPE: - return scoped_refptr<Dispatcher>( - MessagePipeDispatcher::Deserialize(channel, source, size)); - case Type::DATA_PIPE_PRODUCER: - return scoped_refptr<Dispatcher>( - DataPipeProducerDispatcher::Deserialize(channel, source, size)); - case Type::DATA_PIPE_CONSUMER: - return scoped_refptr<Dispatcher>( - DataPipeConsumerDispatcher::Deserialize(channel, source, size)); - case Type::SHARED_BUFFER: - return scoped_refptr<Dispatcher>(SharedBufferDispatcher::Deserialize( - channel, source, size, platform_handles)); - case Type::PLATFORM_HANDLE: - return scoped_refptr<Dispatcher>(PlatformHandleDispatcher::Deserialize( - channel, source, size, platform_handles)); - } - LOG(WARNING) << "Unknown dispatcher type " << type; - return nullptr; -} - -MojoResult Dispatcher::Close() { - MutexLocker locker(&mutex_); - if (is_closed_) - return MOJO_RESULT_INVALID_ARGUMENT; - - CloseNoLock(); - return MOJO_RESULT_OK; -} - -MojoResult Dispatcher::WriteMessage( - UserPointer<const void> bytes, - uint32_t num_bytes, - std::vector<DispatcherTransport>* transports, - MojoWriteMessageFlags flags) { - DCHECK(!transports || - (transports->size() > 0 && - transports->size() < GetConfiguration().max_message_num_handles)); - - MutexLocker locker(&mutex_); - if (is_closed_) - return MOJO_RESULT_INVALID_ARGUMENT; - - return WriteMessageImplNoLock(bytes, num_bytes, transports, flags); -} - -MojoResult Dispatcher::ReadMessage(UserPointer<void> bytes, - UserPointer<uint32_t> num_bytes, - DispatcherVector* dispatchers, - uint32_t* num_dispatchers, - MojoReadMessageFlags flags) { - DCHECK(!num_dispatchers || *num_dispatchers == 0 || - (dispatchers && dispatchers->empty())); - - MutexLocker locker(&mutex_); - if (is_closed_) - return MOJO_RESULT_INVALID_ARGUMENT; - - return ReadMessageImplNoLock(bytes, num_bytes, dispatchers, num_dispatchers, - flags); -} - -MojoResult Dispatcher::WriteData(UserPointer<const void> elements, - UserPointer<uint32_t> num_bytes, - MojoWriteDataFlags flags) { - MutexLocker locker(&mutex_); - if (is_closed_) - return MOJO_RESULT_INVALID_ARGUMENT; - - return WriteDataImplNoLock(elements, num_bytes, flags); -} - -MojoResult Dispatcher::BeginWriteData(UserPointer<void*> buffer, - UserPointer<uint32_t> buffer_num_bytes, - MojoWriteDataFlags flags) { - MutexLocker locker(&mutex_); - if (is_closed_) - return MOJO_RESULT_INVALID_ARGUMENT; - - return BeginWriteDataImplNoLock(buffer, buffer_num_bytes, flags); -} - -MojoResult Dispatcher::EndWriteData(uint32_t num_bytes_written) { - MutexLocker locker(&mutex_); - if (is_closed_) - return MOJO_RESULT_INVALID_ARGUMENT; - - return EndWriteDataImplNoLock(num_bytes_written); -} - -MojoResult Dispatcher::ReadData(UserPointer<void> elements, - UserPointer<uint32_t> num_bytes, - MojoReadDataFlags flags) { - MutexLocker locker(&mutex_); - if (is_closed_) - return MOJO_RESULT_INVALID_ARGUMENT; - - return ReadDataImplNoLock(elements, num_bytes, flags); -} - -MojoResult Dispatcher::BeginReadData(UserPointer<const void*> buffer, - UserPointer<uint32_t> buffer_num_bytes, - MojoReadDataFlags flags) { - MutexLocker locker(&mutex_); - if (is_closed_) - return MOJO_RESULT_INVALID_ARGUMENT; - - return BeginReadDataImplNoLock(buffer, buffer_num_bytes, flags); -} - -MojoResult Dispatcher::EndReadData(uint32_t num_bytes_read) { - MutexLocker locker(&mutex_); - if (is_closed_) - return MOJO_RESULT_INVALID_ARGUMENT; - - return EndReadDataImplNoLock(num_bytes_read); -} - -MojoResult Dispatcher::DuplicateBufferHandle( - UserPointer<const MojoDuplicateBufferHandleOptions> options, - scoped_refptr<Dispatcher>* new_dispatcher) { - MutexLocker locker(&mutex_); - if (is_closed_) - return MOJO_RESULT_INVALID_ARGUMENT; - - return DuplicateBufferHandleImplNoLock(options, new_dispatcher); -} - -MojoResult Dispatcher::MapBuffer( - uint64_t offset, - uint64_t num_bytes, - MojoMapBufferFlags flags, - scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping) { - MutexLocker locker(&mutex_); - if (is_closed_) - return MOJO_RESULT_INVALID_ARGUMENT; - - return MapBufferImplNoLock(offset, num_bytes, flags, mapping); -} - -HandleSignalsState Dispatcher::GetHandleSignalsState() const { - MutexLocker locker(&mutex_); - if (is_closed_) - return HandleSignalsState(); - - return GetHandleSignalsStateImplNoLock(); -} - -MojoResult Dispatcher::AddAwakable(Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state) { - MutexLocker locker(&mutex_); - if (is_closed_) { - if (signals_state) - *signals_state = HandleSignalsState(); - return MOJO_RESULT_INVALID_ARGUMENT; - } - - return AddAwakableImplNoLock(awakable, signals, context, signals_state); -} - -void Dispatcher::RemoveAwakable(Awakable* awakable, - HandleSignalsState* handle_signals_state) { - MutexLocker locker(&mutex_); - if (is_closed_) { - if (handle_signals_state) - *handle_signals_state = HandleSignalsState(); - return; - } - - RemoveAwakableImplNoLock(awakable, handle_signals_state); -} - -MojoResult Dispatcher::AddWaitingDispatcher( - const scoped_refptr<Dispatcher>& dispatcher, - MojoHandleSignals signals, - uintptr_t context) { - MutexLocker locker(&mutex_); - if (is_closed_) - return MOJO_RESULT_INVALID_ARGUMENT; - - return AddWaitingDispatcherImplNoLock(dispatcher, signals, context); -} - -MojoResult Dispatcher::RemoveWaitingDispatcher( - const scoped_refptr<Dispatcher>& dispatcher) { - MutexLocker locker(&mutex_); - if (is_closed_) - return MOJO_RESULT_INVALID_ARGUMENT; - - return RemoveWaitingDispatcherImplNoLock(dispatcher); -} - -MojoResult Dispatcher::GetReadyDispatchers(UserPointer<uint32_t> count, - DispatcherVector* dispatchers, - UserPointer<MojoResult> results, - UserPointer<uintptr_t> contexts) { - MutexLocker locker(&mutex_); - if (is_closed_) - return MOJO_RESULT_INVALID_ARGUMENT; - - return GetReadyDispatchersImplNoLock(count, dispatchers, results, contexts); -} - -Dispatcher::Dispatcher() : is_closed_(false) { -} - -Dispatcher::~Dispatcher() { - // Make sure that |Close()| was called. - DCHECK(is_closed_); -} - -void Dispatcher::CancelAllAwakablesNoLock() { - mutex_.AssertHeld(); - DCHECK(is_closed_); - // By default, waiting isn't supported. Only dispatchers that can be waited on - // will do something nontrivial. -} - -void Dispatcher::CloseImplNoLock() { - mutex_.AssertHeld(); - DCHECK(is_closed_); - // This may not need to do anything. Dispatchers should override this to do - // any actual close-time cleanup necessary. -} - -MojoResult Dispatcher::WriteMessageImplNoLock( - UserPointer<const void> /*bytes*/, - uint32_t /*num_bytes*/, - std::vector<DispatcherTransport>* /*transports*/, - MojoWriteMessageFlags /*flags*/) { - mutex_.AssertHeld(); - DCHECK(!is_closed_); - // By default, not supported. Only needed for message pipe dispatchers. - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::ReadMessageImplNoLock( - UserPointer<void> /*bytes*/, - UserPointer<uint32_t> /*num_bytes*/, - DispatcherVector* /*dispatchers*/, - uint32_t* /*num_dispatchers*/, - MojoReadMessageFlags /*flags*/) { - mutex_.AssertHeld(); - DCHECK(!is_closed_); - // By default, not supported. Only needed for message pipe dispatchers. - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::WriteDataImplNoLock(UserPointer<const void> /*elements*/, - UserPointer<uint32_t> /*num_bytes*/, - MojoWriteDataFlags /*flags*/) { - mutex_.AssertHeld(); - DCHECK(!is_closed_); - // By default, not supported. Only needed for data pipe dispatchers. - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::BeginWriteDataImplNoLock( - UserPointer<void*> /*buffer*/, - UserPointer<uint32_t> /*buffer_num_bytes*/, - MojoWriteDataFlags /*flags*/) { - mutex_.AssertHeld(); - DCHECK(!is_closed_); - // By default, not supported. Only needed for data pipe dispatchers. - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::EndWriteDataImplNoLock(uint32_t /*num_bytes_written*/) { - mutex_.AssertHeld(); - DCHECK(!is_closed_); - // By default, not supported. Only needed for data pipe dispatchers. - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::ReadDataImplNoLock(UserPointer<void> /*elements*/, - UserPointer<uint32_t> /*num_bytes*/, - MojoReadDataFlags /*flags*/) { - mutex_.AssertHeld(); - DCHECK(!is_closed_); - // By default, not supported. Only needed for data pipe dispatchers. - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::BeginReadDataImplNoLock( - UserPointer<const void*> /*buffer*/, - UserPointer<uint32_t> /*buffer_num_bytes*/, - MojoReadDataFlags /*flags*/) { - mutex_.AssertHeld(); - DCHECK(!is_closed_); - // By default, not supported. Only needed for data pipe dispatchers. - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::EndReadDataImplNoLock(uint32_t /*num_bytes_read*/) { - mutex_.AssertHeld(); - DCHECK(!is_closed_); - // By default, not supported. Only needed for data pipe dispatchers. - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::DuplicateBufferHandleImplNoLock( - UserPointer<const MojoDuplicateBufferHandleOptions> /*options*/, - scoped_refptr<Dispatcher>* /*new_dispatcher*/) { - mutex_.AssertHeld(); - DCHECK(!is_closed_); - // By default, not supported. Only needed for buffer dispatchers. - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::MapBufferImplNoLock( - uint64_t /*offset*/, - uint64_t /*num_bytes*/, - MojoMapBufferFlags /*flags*/, - scoped_ptr<embedder::PlatformSharedBufferMapping>* /*mapping*/) { - mutex_.AssertHeld(); - DCHECK(!is_closed_); - // By default, not supported. Only needed for buffer dispatchers. - return MOJO_RESULT_INVALID_ARGUMENT; -} - -HandleSignalsState Dispatcher::GetHandleSignalsStateImplNoLock() const { - mutex_.AssertHeld(); - DCHECK(!is_closed_); - // By default, waiting isn't supported. Only dispatchers that can be waited on - // will do something nontrivial. - return HandleSignalsState(); -} - -MojoResult Dispatcher::AddAwakableImplNoLock( - Awakable* /*awakable*/, - MojoHandleSignals /*signals*/, - uintptr_t /*context*/, - HandleSignalsState* signals_state) { - mutex_.AssertHeld(); - DCHECK(!is_closed_); - // By default, waiting isn't supported. Only dispatchers that can be waited on - // will do something nontrivial. - if (signals_state) - *signals_state = HandleSignalsState(); - return MOJO_RESULT_FAILED_PRECONDITION; -} - -MojoResult Dispatcher::AddWaitingDispatcherImplNoLock( - const scoped_refptr<Dispatcher>& /*dispatcher*/, - MojoHandleSignals /*signals*/, - uintptr_t /*context*/) { - mutex_.AssertHeld(); - DCHECK(!is_closed_); - // By default, not supported. Only needed for wait set dispatchers. - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::RemoveWaitingDispatcherImplNoLock( - const scoped_refptr<Dispatcher>& /*dispatcher*/) { - mutex_.AssertHeld(); - DCHECK(!is_closed_); - // By default, not supported. Only needed for wait set dispatchers. - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::GetReadyDispatchersImplNoLock( - UserPointer<uint32_t> /*count*/, - DispatcherVector* /*dispatchers*/, - UserPointer<MojoResult> /*results*/, - UserPointer<uintptr_t> /*contexts*/) { - mutex_.AssertHeld(); - DCHECK(!is_closed_); - // By default, not supported. Only needed for wait set dispatchers. - return MOJO_RESULT_INVALID_ARGUMENT; -} - -void Dispatcher::RemoveAwakableImplNoLock(Awakable* /*awakable*/, - HandleSignalsState* signals_state) { - mutex_.AssertHeld(); - DCHECK(!is_closed_); - // By default, waiting isn't supported. Only dispatchers that can be waited on - // will do something nontrivial. - if (signals_state) - *signals_state = HandleSignalsState(); -} - -void Dispatcher::StartSerializeImplNoLock(Channel* /*channel*/, - size_t* max_size, - size_t* max_platform_handles) { - DCHECK(HasOneRef()); // Only one ref => no need to take the lock. - DCHECK(!is_closed_); - *max_size = 0; - *max_platform_handles = 0; -} - -bool Dispatcher::EndSerializeAndCloseImplNoLock( - Channel* /*channel*/, - void* /*destination*/, - size_t* /*actual_size*/, - embedder::PlatformHandleVector* /*platform_handles*/) { - DCHECK(HasOneRef()); // Only one ref => no need to take the lock. - DCHECK(is_closed_); - // By default, serializing isn't supported, so just close. - CloseImplNoLock(); - return false; -} - -bool Dispatcher::IsBusyNoLock() const { - mutex_.AssertHeld(); - DCHECK(!is_closed_); - // Most dispatchers support only "atomic" operations, so they are never busy - // (in this sense). - return false; -} - -void Dispatcher::CloseNoLock() { - mutex_.AssertHeld(); - DCHECK(!is_closed_); - - is_closed_ = true; - CancelAllAwakablesNoLock(); - CloseImplNoLock(); -} - -scoped_refptr<Dispatcher> -Dispatcher::CreateEquivalentDispatcherAndCloseNoLock() { - mutex_.AssertHeld(); - DCHECK(!is_closed_); - - is_closed_ = true; - CancelAllAwakablesNoLock(); - return CreateEquivalentDispatcherAndCloseImplNoLock(); -} - -void Dispatcher::StartSerialize(Channel* channel, - size_t* max_size, - size_t* max_platform_handles) { - DCHECK(channel); - DCHECK(max_size); - DCHECK(max_platform_handles); - DCHECK(HasOneRef()); // Only one ref => no need to take the lock. - DCHECK(!is_closed_); - StartSerializeImplNoLock(channel, max_size, max_platform_handles); -} - -bool Dispatcher::EndSerializeAndClose( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) { - DCHECK(channel); - DCHECK(actual_size); - DCHECK(HasOneRef()); // Only one ref => no need to take the lock. - DCHECK(!is_closed_); - - // Like other |...Close()| methods, we mark ourselves as closed before calling - // the impl. But there's no need to cancel waiters: we shouldn't have any (and - // shouldn't be in |Core|'s handle table. - is_closed_ = true; - -#if !defined(NDEBUG) - // See the comment above |EndSerializeAndCloseImplNoLock()|. In brief: Locking - // isn't actually needed, but we need to satisfy assertions (which we don't - // want to remove or weaken). - MutexLocker locker(&mutex_); -#endif - - return EndSerializeAndCloseImplNoLock(channel, destination, actual_size, - platform_handles); -} - -// DispatcherTransport --------------------------------------------------------- - -void DispatcherTransport::End() { - DCHECK(dispatcher_); - dispatcher_->mutex_.Unlock(); - dispatcher_ = nullptr; -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/dispatcher.h b/third_party/mojo/src/mojo/edk/system/dispatcher.h deleted file mode 100644 index e9af1c0..0000000 --- a/third_party/mojo/src/mojo/edk/system/dispatcher.h +++ /dev/null @@ -1,466 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_DISPATCHER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_DISPATCHER_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <ostream> -#include <vector> - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/public/c/system/buffer.h" -#include "mojo/public/c/system/data_pipe.h" -#include "mojo/public/c/system/message_pipe.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle_vector.h" -#include "third_party/mojo/src/mojo/edk/system/handle_signals_state.h" -#include "third_party/mojo/src/mojo/edk/system/memory.h" -#include "third_party/mojo/src/mojo/edk/system/mutex.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { - -namespace embedder { -class PlatformSharedBufferMapping; -} - -namespace system { - -class Channel; -class Core; -class Dispatcher; -class DispatcherTransport; -class HandleTable; -class LocalMessagePipeEndpoint; -class ProxyMessagePipeEndpoint; -class TransportData; -class Awakable; - -using DispatcherVector = std::vector<scoped_refptr<Dispatcher>>; - -namespace test { - -// Test helper. We need to declare it here so we can friend it. -MOJO_SYSTEM_IMPL_EXPORT DispatcherTransport -DispatcherTryStartTransport(Dispatcher* dispatcher); - -} // namespace test - -// A |Dispatcher| implements Mojo primitives that are "attached" to a particular -// handle. This includes most (all?) primitives except for |MojoWait...()|. This -// object is thread-safe, with its state being protected by a single mutex -// |mutex_|, which is also made available to implementation subclasses (via the -// |mutex()| method). -class MOJO_SYSTEM_IMPL_EXPORT Dispatcher - : public base::RefCountedThreadSafe<Dispatcher> { - public: - enum class Type { - UNKNOWN = 0, - MESSAGE_PIPE, - DATA_PIPE_PRODUCER, - DATA_PIPE_CONSUMER, - SHARED_BUFFER, - WAIT_SET, - - // "Private" types (not exposed via the public interface): - PLATFORM_HANDLE = -1 - }; - virtual Type GetType() const = 0; - - // These methods implement the various primitives named |Mojo...()|. These - // take |mutex_| and handle races with |Close()|. Then they call out to - // subclasses' |...ImplNoLock()| methods (still under |mutex_|), which - // actually implement the primitives. - // NOTE(vtl): This puts a big lock around each dispatcher (i.e., handle), and - // prevents the various |...ImplNoLock()|s from releasing the lock as soon as - // possible. If this becomes an issue, we can rethink this. - MojoResult Close(); - - // |transports| may be non-null if and only if there are handles to be - // written; not that |this| must not be in |transports|. On success, all the - // dispatchers in |transports| must have been moved to a closed state; on - // failure, they should remain in their original state. - MojoResult WriteMessage(UserPointer<const void> bytes, - uint32_t num_bytes, - std::vector<DispatcherTransport>* transports, - MojoWriteMessageFlags flags); - // |dispatchers| must be non-null but empty, if |num_dispatchers| is non-null - // and nonzero. On success, it will be set to the dispatchers to be received - // (and assigned handles) as part of the message. - MojoResult ReadMessage(UserPointer<void> bytes, - UserPointer<uint32_t> num_bytes, - DispatcherVector* dispatchers, - uint32_t* num_dispatchers, - MojoReadMessageFlags flags); - MojoResult WriteData(UserPointer<const void> elements, - UserPointer<uint32_t> elements_num_bytes, - MojoWriteDataFlags flags); - MojoResult BeginWriteData(UserPointer<void*> buffer, - UserPointer<uint32_t> buffer_num_bytes, - MojoWriteDataFlags flags); - MojoResult EndWriteData(uint32_t num_bytes_written); - MojoResult ReadData(UserPointer<void> elements, - UserPointer<uint32_t> num_bytes, - MojoReadDataFlags flags); - MojoResult BeginReadData(UserPointer<const void*> buffer, - UserPointer<uint32_t> buffer_num_bytes, - MojoReadDataFlags flags); - MojoResult EndReadData(uint32_t num_bytes_read); - // |options| may be null. |new_dispatcher| must not be null, but - // |*new_dispatcher| should be null (and will contain the dispatcher for the - // new handle on success). - MojoResult DuplicateBufferHandle( - UserPointer<const MojoDuplicateBufferHandleOptions> options, - scoped_refptr<Dispatcher>* new_dispatcher); - MojoResult MapBuffer( - uint64_t offset, - uint64_t num_bytes, - MojoMapBufferFlags flags, - scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping); - - // Gets the current handle signals state. (The default implementation simply - // returns a default-constructed |HandleSignalsState|, i.e., no signals - // satisfied or satisfiable.) Note: The state is subject to change from other - // threads. - HandleSignalsState GetHandleSignalsState() const; - - // Adds an awakable to this dispatcher, which will be woken up when this - // object changes state to satisfy |signals| with context |context|. It will - // also be woken up when it becomes impossible for the object to ever satisfy - // |signals| with a suitable error status. - // - // If |signals_state| is non-null, on *failure* |*signals_state| will be set - // to the current handle signals state (on success, it is left untouched). - // - // Returns: - // - |MOJO_RESULT_OK| if the awakable was added; - // - |MOJO_RESULT_ALREADY_EXISTS| if |signals| is already satisfied; - // - |MOJO_RESULT_INVALID_ARGUMENT| if the dispatcher has been closed; and - // - |MOJO_RESULT_FAILED_PRECONDITION| if it is not (or no longer) possible - // that |signals| will ever be satisfied. - MojoResult AddAwakable(Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state); - // Removes an awakable from this dispatcher. (It is valid to call this - // multiple times for the same |awakable| on the same object, so long as - // |AddAwakable()| was called at most once.) If |signals_state| is non-null, - // |*signals_state| will be set to the current handle signals state. - void RemoveAwakable(Awakable* awakable, HandleSignalsState* signals_state); - - // Adds a dispatcher to wait on. When the dispatcher satisfies |signals|, it - // will be returned in the next call to |GetReadyDispatchers()|. If - // |dispatcher| has been added, it must be removed before adding again, - // otherwise |MOJO_RESULT_ALREADY_EXISTS| will be returned. - MojoResult AddWaitingDispatcher(const scoped_refptr<Dispatcher>& dispatcher, - MojoHandleSignals signals, - uintptr_t context); - // Removes a dispatcher to wait on. If |dispatcher| has not been added, - // |MOJO_RESULT_NOT_FOUND| will be returned. - MojoResult RemoveWaitingDispatcher( - const scoped_refptr<Dispatcher>& dispatcher); - // Returns a set of ready dispatchers. |*count| is the maximum number of - // dispatchers to return, and will contain the number of dispatchers returned - // in |dispatchers| on completion. - MojoResult GetReadyDispatchers(UserPointer<uint32_t> count, - DispatcherVector* dispatchers, - UserPointer<MojoResult> results, - UserPointer<uintptr_t> contexts); - - // A dispatcher must be put into a special state in order to be sent across a - // message pipe. Outside of tests, only |HandleTableAccess| is allowed to do - // this, since there are requirements on the handle table (see below). - // - // In this special state, only a restricted set of operations is allowed. - // These are the ones available as |DispatcherTransport| methods. Other - // |Dispatcher| methods must not be called until |DispatcherTransport::End()| - // has been called. - class HandleTableAccess { - private: - friend class Core; - friend class HandleTable; - // Tests also need this, to avoid needing |Core|. - friend DispatcherTransport test::DispatcherTryStartTransport(Dispatcher*); - - // This must be called under the handle table lock and only if the handle - // table entry is not marked busy. The caller must maintain a reference to - // |dispatcher| until |DispatcherTransport::End()| is called. - static DispatcherTransport TryStartTransport(Dispatcher* dispatcher); - }; - - // A |TransportData| may serialize dispatchers that are given to it (and which - // were previously attached to the |MessageInTransit| that is creating it) to - // a given |Channel| and then (probably in a different process) deserialize. - // Note that the |MessageInTransit| "owns" (i.e., has the only ref to) these - // dispatchers, so there are no locking issues. (There's no lock ordering - // issue, and in fact no need to take dispatcher locks at all.) - // TODO(vtl): Consider making another wrapper similar to |DispatcherTransport| - // (but with an owning, unique reference), and having - // |CreateEquivalentDispatcherAndCloseImplNoLock()| return that wrapper (and - // |MessageInTransit|, etc. only holding on to such wrappers). - class TransportDataAccess { - private: - friend class TransportData; - - // Serialization API. These functions may only be called on such - // dispatchers. (|channel| is the |Channel| to which the dispatcher is to be - // serialized.) See the |Dispatcher| methods of the same names for more - // details. - static void StartSerialize(Dispatcher* dispatcher, - Channel* channel, - size_t* max_size, - size_t* max_platform_handles); - static bool EndSerializeAndClose( - Dispatcher* dispatcher, - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles); - - // Deserialization API. - // Note: This "clears" (i.e., reset to the invalid handle) any platform - // handles that it takes ownership of. - static scoped_refptr<Dispatcher> Deserialize( - Channel* channel, - int32_t type, - const void* source, - size_t size, - embedder::PlatformHandleVector* platform_handles); - }; - - protected: - friend class base::RefCountedThreadSafe<Dispatcher>; - - Dispatcher(); - virtual ~Dispatcher(); - - // These are to be overridden by subclasses (if necessary). They are called - // exactly once (first |CancelAllAwakablesNoLock()|, then |CloseImplNoLock()|) - // when the dispatcher is being closed. - virtual void CancelAllAwakablesNoLock() MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - virtual void CloseImplNoLock() MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - virtual scoped_refptr<Dispatcher> - CreateEquivalentDispatcherAndCloseImplNoLock() - MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_) = 0; - - // These are to be overridden by subclasses (if necessary). They are never - // called after the dispatcher has been closed. See the descriptions of the - // methods without the "ImplNoLock" for more information. - virtual MojoResult WriteMessageImplNoLock( - UserPointer<const void> bytes, - uint32_t num_bytes, - std::vector<DispatcherTransport>* transports, - MojoWriteMessageFlags flags) MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - virtual MojoResult ReadMessageImplNoLock(UserPointer<void> bytes, - UserPointer<uint32_t> num_bytes, - DispatcherVector* dispatchers, - uint32_t* num_dispatchers, - MojoReadMessageFlags flags) - MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - virtual MojoResult WriteDataImplNoLock(UserPointer<const void> elements, - UserPointer<uint32_t> num_bytes, - MojoWriteDataFlags flags) - MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - virtual MojoResult BeginWriteDataImplNoLock( - UserPointer<void*> buffer, - UserPointer<uint32_t> buffer_num_bytes, - MojoWriteDataFlags flags) MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - virtual MojoResult EndWriteDataImplNoLock(uint32_t num_bytes_written) - MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - virtual MojoResult ReadDataImplNoLock(UserPointer<void> elements, - UserPointer<uint32_t> num_bytes, - MojoReadDataFlags flags) - MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - virtual MojoResult BeginReadDataImplNoLock( - UserPointer<const void*> buffer, - UserPointer<uint32_t> buffer_num_bytes, - MojoReadDataFlags flags) MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - virtual MojoResult EndReadDataImplNoLock(uint32_t num_bytes_read) - MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - virtual MojoResult DuplicateBufferHandleImplNoLock( - UserPointer<const MojoDuplicateBufferHandleOptions> options, - scoped_refptr<Dispatcher>* new_dispatcher) - MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - virtual MojoResult MapBufferImplNoLock( - uint64_t offset, - uint64_t num_bytes, - MojoMapBufferFlags flags, - scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping) - MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - virtual HandleSignalsState GetHandleSignalsStateImplNoLock() const - MOJO_SHARED_LOCKS_REQUIRED(mutex_); - virtual MojoResult AddAwakableImplNoLock(Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state) - MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - virtual void RemoveAwakableImplNoLock(Awakable* awakable, - HandleSignalsState* signals_state) - MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - virtual MojoResult AddWaitingDispatcherImplNoLock( - const scoped_refptr<Dispatcher>& dispatcher, - MojoHandleSignals signals, - uintptr_t context) MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - virtual MojoResult RemoveWaitingDispatcherImplNoLock( - const scoped_refptr<Dispatcher>& dispatcher) - MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - virtual MojoResult GetReadyDispatchersImplNoLock( - UserPointer<uint32_t> count, - DispatcherVector* dispatchers, - UserPointer<MojoResult> results, - UserPointer<uintptr_t> contexts) MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // These implement the API used to serialize dispatchers to a |Channel| - // (described below). They will only be called on a dispatcher that's attached - // to and "owned" by a |MessageInTransit|. See the non-"impl" versions for - // more information. - // - // Note: |StartSerializeImplNoLock()| is actually called with |mutex_| NOT - // held, since the dispatcher should only be accessible to the calling thread. - // On Debug builds, |EndSerializeAndCloseImplNoLock()| is called with |mutex_| - // held, to satisfy any |mutex_.AssertHeld()| (e.g., in |CloseImplNoLock()| -- - // and anything it calls); disentangling those assertions is - // difficult/fragile, and would weaken our general checking of invariants. - // - // TODO(vtl): Consider making these pure virtual once most things support - // being passed over a message pipe. - virtual void StartSerializeImplNoLock(Channel* channel, - size_t* max_size, - size_t* max_platform_handles) - MOJO_NOT_THREAD_SAFE; - virtual bool EndSerializeAndCloseImplNoLock( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) MOJO_NOT_THREAD_SAFE; - - // This should be overridden to return true if/when there's an ongoing - // operation (e.g., two-phase read/writes on data pipes) that should prevent a - // handle from being sent over a message pipe (with status "busy"). - virtual bool IsBusyNoLock() const MOJO_SHARED_LOCKS_REQUIRED(mutex_); - - Mutex& mutex() const MOJO_LOCK_RETURNED(mutex_) { return mutex_; } - - private: - friend class DispatcherTransport; - - // Closes the dispatcher. This must be done under lock, and unlike |Close()|, - // the dispatcher must not be closed already. (This is the "equivalent" of - // |CreateEquivalentDispatcherAndCloseNoLock()|, for situations where the - // dispatcher must be disposed of instead of "transferred".) - void CloseNoLock() MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Creates an equivalent dispatcher -- representing the same resource as this - // dispatcher -- and close (i.e., disable) this dispatcher. I.e., this - // dispatcher will look as though it was closed, but the resource it - // represents will be assigned to the new dispatcher. This must be called - // under the dispatcher's lock. - scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseNoLock() - MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // API to serialize dispatchers to a |Channel|, exposed to only - // |TransportData| (via |TransportData|). They may only be called on a - // dispatcher attached to a |MessageInTransit| (and in particular not in - // |CoreImpl|'s handle table). - // - // TODO(vtl): The serialization API (and related implementation methods, - // including |DispatcherTransport|'s methods) is marked - // |MOJO_NOT_THREAD_SAFE|. This is because the threading requirements are - // somewhat complicated (e.g., |HandleTableAccess::TryStartTransport()| is - // really a try-lock function, amongst other things). We could/should do a - // more careful job annotating these methods. - // https://github.com/domokit/mojo/issues/322 - // - // Starts the serialization. Returns (via the two "out" parameters) the - // maximum amount of space that may be needed to serialize this dispatcher to - // the given |Channel| (no more than - // |TransportData::kMaxSerializedDispatcherSize|) and the maximum number of - // |PlatformHandle|s that may need to be attached (no more than - // |TransportData::kMaxSerializedDispatcherPlatformHandles|). If this - // dispatcher cannot be serialized to the given |Channel|, |*max_size| and - // |*max_platform_handles| should be set to zero. A call to this method will - // ALWAYS be followed by a call to |EndSerializeAndClose()| (even if this - // dispatcher cannot be serialized to the given |Channel|). - void StartSerialize(Channel* channel, - size_t* max_size, - size_t* max_platform_handles) MOJO_NOT_THREAD_SAFE; - // Completes the serialization of this dispatcher to the given |Channel| and - // closes it. (This call will always follow an earlier call to - // |StartSerialize()|, with the same |Channel|.) This does so by writing to - // |destination| and appending any |PlatformHandle|s needed to - // |platform_handles| (which may be null if no platform handles were indicated - // to be required to |StartSerialize()|). This may write no more than the - // amount indicated by |StartSerialize()|. (WARNING: Beware of races, e.g., if - // something can be mutated between the two calls!) Returns true on success, - // in which case |*actual_size| is set to the amount it actually wrote to - // |destination|. On failure, |*actual_size| should not be modified; however, - // the dispatcher will still be closed. - bool EndSerializeAndClose(Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) - MOJO_NOT_THREAD_SAFE; - - // This protects the following members as well as any state added by - // subclasses. - mutable Mutex mutex_; - bool is_closed_ MOJO_GUARDED_BY(mutex_); - - MOJO_DISALLOW_COPY_AND_ASSIGN(Dispatcher); -}; - -// Wrapper around a |Dispatcher| pointer, while it's being processed to be -// passed in a message pipe. See the comment about -// |Dispatcher::HandleTableAccess| for more details. -// -// Note: This class is deliberately "thin" -- no more expensive than a -// |Dispatcher*|. -class MOJO_SYSTEM_IMPL_EXPORT DispatcherTransport { - public: - DispatcherTransport() : dispatcher_(nullptr) {} - - void End() MOJO_NOT_THREAD_SAFE; - - Dispatcher::Type GetType() const { return dispatcher_->GetType(); } - bool IsBusy() const MOJO_NOT_THREAD_SAFE { - return dispatcher_->IsBusyNoLock(); - } - void Close() MOJO_NOT_THREAD_SAFE { dispatcher_->CloseNoLock(); } - scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndClose() - MOJO_NOT_THREAD_SAFE { - return dispatcher_->CreateEquivalentDispatcherAndCloseNoLock(); - } - - bool is_valid() const { return !!dispatcher_; } - - protected: - Dispatcher* dispatcher() { return dispatcher_; } - - private: - friend class Dispatcher::HandleTableAccess; - - explicit DispatcherTransport(Dispatcher* dispatcher) - : dispatcher_(dispatcher) {} - - Dispatcher* dispatcher_; - - // Copy and assign allowed. -}; - -// So logging macros and |DCHECK_EQ()|, etc. work. -MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<(std::ostream& out, - Dispatcher::Type type) { - return out << static_cast<int>(type); -} - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_DISPATCHER_H_ diff --git a/third_party/mojo/src/mojo/edk/system/dispatcher_unittest.cc b/third_party/mojo/src/mojo/edk/system/dispatcher_unittest.cc deleted file mode 100644 index a9a413b..0000000 --- a/third_party/mojo/src/mojo/edk/system/dispatcher_unittest.cc +++ /dev/null @@ -1,307 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/dispatcher.h" - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_vector.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/simple_thread.h" -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_shared_buffer.h" -#include "third_party/mojo/src/mojo/edk/system/memory.h" -#include "third_party/mojo/src/mojo/edk/system/waiter.h" - -namespace mojo { -namespace system { -namespace { - -// Trivial subclass that makes the constructor public. -class TrivialDispatcher final : public Dispatcher { - public: - TrivialDispatcher() {} - - Type GetType() const override { return Type::UNKNOWN; } - - private: - friend class base::RefCountedThreadSafe<TrivialDispatcher>; - ~TrivialDispatcher() override {} - - scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock() - override { - mutex().AssertHeld(); - return scoped_refptr<Dispatcher>(new TrivialDispatcher()); - } - - MOJO_DISALLOW_COPY_AND_ASSIGN(TrivialDispatcher); -}; - -TEST(DispatcherTest, Basic) { - scoped_refptr<Dispatcher> d(new TrivialDispatcher()); - - EXPECT_EQ(Dispatcher::Type::UNKNOWN, d->GetType()); - - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->WriteMessage(NullUserPointer(), 0, nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->ReadMessage(NullUserPointer(), NullUserPointer(), nullptr, - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->WriteData(NullUserPointer(), NullUserPointer(), - MOJO_WRITE_DATA_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->BeginWriteData(NullUserPointer(), NullUserPointer(), - MOJO_WRITE_DATA_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndWriteData(0)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->ReadData(NullUserPointer(), NullUserPointer(), - MOJO_READ_DATA_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->BeginReadData(NullUserPointer(), NullUserPointer(), - MOJO_READ_DATA_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndReadData(0)); - Waiter w; - w.Init(); - HandleSignalsState hss; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - d->AddAwakable(&w, ~MOJO_HANDLE_SIGNAL_NONE, 0, &hss)); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - // Okay to remove even if it wasn't added (or was already removed). - hss = HandleSignalsState(); - d->RemoveAwakable(&w, &hss); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - hss = HandleSignalsState(); - d->RemoveAwakable(&w, &hss); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->WriteMessage(NullUserPointer(), 0, nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->ReadMessage(NullUserPointer(), NullUserPointer(), nullptr, - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->WriteData(NullUserPointer(), NullUserPointer(), - MOJO_WRITE_DATA_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->BeginWriteData(NullUserPointer(), NullUserPointer(), - MOJO_WRITE_DATA_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndWriteData(0)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->ReadData(NullUserPointer(), NullUserPointer(), - MOJO_READ_DATA_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->BeginReadData(NullUserPointer(), NullUserPointer(), - MOJO_READ_DATA_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndReadData(0)); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->AddAwakable(&w, ~MOJO_HANDLE_SIGNAL_NONE, 0, &hss)); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - hss = HandleSignalsState(); - d->RemoveAwakable(&w, &hss); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); -} - -class ThreadSafetyStressThread : public base::SimpleThread { - public: - enum DispatcherOp { - CLOSE = 0, - WRITE_MESSAGE, - READ_MESSAGE, - WRITE_DATA, - BEGIN_WRITE_DATA, - END_WRITE_DATA, - READ_DATA, - BEGIN_READ_DATA, - END_READ_DATA, - DUPLICATE_BUFFER_HANDLE, - MAP_BUFFER, - ADD_WAITER, - REMOVE_WAITER, - DISPATCHER_OP_COUNT - }; - - ThreadSafetyStressThread(base::WaitableEvent* event, - scoped_refptr<Dispatcher> dispatcher, - DispatcherOp op) - : base::SimpleThread("thread_safety_stress_thread"), - event_(event), - dispatcher_(dispatcher), - op_(op) { - CHECK_LE(0, op_); - CHECK_LT(op_, DISPATCHER_OP_COUNT); - } - - ~ThreadSafetyStressThread() override { Join(); } - - private: - void Run() override { - event_->Wait(); - - waiter_.Init(); - switch (op_) { - case CLOSE: { - MojoResult r = dispatcher_->Close(); - EXPECT_TRUE(r == MOJO_RESULT_OK || r == MOJO_RESULT_INVALID_ARGUMENT) - << "Result: " << r; - break; - } - case WRITE_MESSAGE: - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - dispatcher_->WriteMessage(NullUserPointer(), 0, nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - break; - case READ_MESSAGE: - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - dispatcher_->ReadMessage(NullUserPointer(), NullUserPointer(), - nullptr, nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - break; - case WRITE_DATA: - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - dispatcher_->WriteData(NullUserPointer(), NullUserPointer(), - MOJO_WRITE_DATA_FLAG_NONE)); - break; - case BEGIN_WRITE_DATA: - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - dispatcher_->BeginWriteData(NullUserPointer(), NullUserPointer(), - MOJO_WRITE_DATA_FLAG_NONE)); - break; - case END_WRITE_DATA: - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dispatcher_->EndWriteData(0)); - break; - case READ_DATA: - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - dispatcher_->ReadData(NullUserPointer(), NullUserPointer(), - MOJO_READ_DATA_FLAG_NONE)); - break; - case BEGIN_READ_DATA: - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - dispatcher_->BeginReadData(NullUserPointer(), NullUserPointer(), - MOJO_READ_DATA_FLAG_NONE)); - break; - case END_READ_DATA: - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dispatcher_->EndReadData(0)); - break; - case DUPLICATE_BUFFER_HANDLE: { - scoped_refptr<Dispatcher> unused; - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - dispatcher_->DuplicateBufferHandle(NullUserPointer(), &unused)); - break; - } - case MAP_BUFFER: { - scoped_ptr<embedder::PlatformSharedBufferMapping> unused; - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - dispatcher_->MapBuffer(0u, 0u, MOJO_MAP_BUFFER_FLAG_NONE, &unused)); - break; - } - case ADD_WAITER: { - HandleSignalsState hss; - MojoResult r = dispatcher_->AddAwakable( - &waiter_, ~MOJO_HANDLE_SIGNAL_NONE, 0, &hss); - EXPECT_TRUE(r == MOJO_RESULT_FAILED_PRECONDITION || - r == MOJO_RESULT_INVALID_ARGUMENT); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - break; - } - case REMOVE_WAITER: { - HandleSignalsState hss; - dispatcher_->RemoveAwakable(&waiter_, &hss); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - break; - } - default: - NOTREACHED(); - break; - } - - // Always try to remove the waiter, in case we added it. - HandleSignalsState hss; - dispatcher_->RemoveAwakable(&waiter_, &hss); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - } - - base::WaitableEvent* const event_; - const scoped_refptr<Dispatcher> dispatcher_; - const DispatcherOp op_; - - Waiter waiter_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ThreadSafetyStressThread); -}; - -TEST(DispatcherTest, ThreadSafetyStress) { - static const size_t kRepeatCount = 20; - static const size_t kNumThreads = 100; - - for (size_t i = 0; i < kRepeatCount; i++) { - // Manual reset, not initially signalled. - base::WaitableEvent event(true, false); - scoped_refptr<Dispatcher> d(new TrivialDispatcher()); - - { - ScopedVector<ThreadSafetyStressThread> threads; - for (size_t j = 0; j < kNumThreads; j++) { - ThreadSafetyStressThread::DispatcherOp op = - static_cast<ThreadSafetyStressThread::DispatcherOp>( - (i + j) % ThreadSafetyStressThread::DISPATCHER_OP_COUNT); - threads.push_back(new ThreadSafetyStressThread(&event, d, op)); - threads.back()->Start(); - } - // Kicks off real work on the threads: - event.Signal(); - } // Joins all the threads. - - // One of the threads should already have closed the dispatcher. - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->Close()); - } -} - -TEST(DispatcherTest, ThreadSafetyStressNoClose) { - static const size_t kRepeatCount = 20; - static const size_t kNumThreads = 100; - - for (size_t i = 0; i < kRepeatCount; i++) { - // Manual reset, not initially signalled. - base::WaitableEvent event(true, false); - scoped_refptr<Dispatcher> d(new TrivialDispatcher()); - - { - ScopedVector<ThreadSafetyStressThread> threads; - for (size_t j = 0; j < kNumThreads; j++) { - ThreadSafetyStressThread::DispatcherOp op = - static_cast<ThreadSafetyStressThread::DispatcherOp>( - (i + j) % (ThreadSafetyStressThread::DISPATCHER_OP_COUNT - 1) + - 1); - threads.push_back(new ThreadSafetyStressThread(&event, d, op)); - threads.back()->Start(); - } - // Kicks off real work on the threads: - event.Signal(); - } // Joins all the threads. - - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - } -} - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/endpoint_relayer.cc b/third_party/mojo/src/mojo/edk/system/endpoint_relayer.cc deleted file mode 100644 index 382be15..0000000 --- a/third_party/mojo/src/mojo/edk/system/endpoint_relayer.cc +++ /dev/null @@ -1,84 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/endpoint_relayer.h" - -#include <utility> - -#include "base/logging.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit.h" - -namespace mojo { -namespace system { - -EndpointRelayer::EndpointRelayer() { -} - -// static -unsigned EndpointRelayer::GetPeerPort(unsigned port) { - DCHECK(port == 0 || port == 1); - return port ^ 1; -} - -void EndpointRelayer::Init(ChannelEndpoint* endpoint0, - ChannelEndpoint* endpoint1) { - DCHECK(endpoint0); - DCHECK(endpoint1); - DCHECK(!endpoints_[0]); - DCHECK(!endpoints_[1]); - endpoints_[0] = endpoint0; - endpoints_[1] = endpoint1; -} - -void EndpointRelayer::SetFilter(scoped_ptr<Filter> filter) { - MutexLocker locker(&mutex_); - filter_ = std::move(filter); -} - -bool EndpointRelayer::OnReadMessage(unsigned port, MessageInTransit* message) { - DCHECK(message); - - MutexLocker locker(&mutex_); - - // If we're no longer the client, then reject the message. - if (!endpoints_[port]) - return false; - - unsigned peer_port = GetPeerPort(port); - - if (filter_ && message->type() == MessageInTransit::Type::ENDPOINT_CLIENT) { - if (filter_->OnReadMessage(endpoints_[port].get(), - endpoints_[peer_port].get(), message)) - return true; - } - - // Otherwise, consume it even if the peer port is closed. - if (endpoints_[peer_port]) - endpoints_[peer_port]->EnqueueMessage(make_scoped_ptr(message)); - return true; -} - -void EndpointRelayer::OnDetachFromChannel(unsigned port) { - MutexLocker locker(&mutex_); - - if (endpoints_[port]) { - endpoints_[port]->DetachFromClient(); - endpoints_[port] = nullptr; - } - - unsigned peer_port = GetPeerPort(port); - if (endpoints_[peer_port]) { - endpoints_[peer_port]->DetachFromClient(); - endpoints_[peer_port] = nullptr; - } -} - -EndpointRelayer::~EndpointRelayer() { - DCHECK(!endpoints_[0]); - DCHECK(!endpoints_[1]); -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/endpoint_relayer.h b/third_party/mojo/src/mojo/edk/system/endpoint_relayer.h deleted file mode 100644 index acff700..0000000 --- a/third_party/mojo/src/mojo/edk/system/endpoint_relayer.h +++ /dev/null @@ -1,95 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_ENDPOINT_RELAYER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_ENDPOINT_RELAYER_H_ - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint_client.h" -#include "third_party/mojo/src/mojo/edk/system/mutex.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -class ChannelEndpoint; - -// This is a simple |ChannelEndpointClient| that just relays messages between -// two |ChannelEndpoint|s (without the overhead of |MessagePipe|). -class MOJO_SYSTEM_IMPL_EXPORT EndpointRelayer final - : public ChannelEndpointClient { - public: - // A class that can inspect and optionally handle messages of type - // |Type::ENDPOINT_CLIENT| received from either |ChannelEndpoint|. - // - // Instances of implementations of this class will be owned by - // |EndpointRelayer|s. - // - // Destructors may not call methods of the |EndpointRelayer| (nor of the - // |ChannelEndpoint|s). - class MOJO_SYSTEM_IMPL_EXPORT Filter { - public: - virtual ~Filter() {} - - // Called by |EndpointRelayer::OnReadMessage()| for messages of type - // |Type::ENDPOINT_CLIENT|. This is only called by the |EndpointRelayer| if - // it is still the client of the sending endpoint. - // - // |endpoint| (which will not be null) is the |ChannelEndpoint| - // corresponding to |port| (i.e., the endpoint the message was received - // from), whereas |peer_endpoint| (which may be null) is that corresponding - // to the peer port (i.e., the endpoint to which the message would be - // relayed). - // - // This should return true if the message is consumed (in which case - // ownership is transferred), and false if not (in which case the message - // will be relayed as usual). - // - // This will always be called under |EndpointRelayer|'s lock. This may call - // |ChannelEndpoint| methods. However, it may not call any of - // |EndpointRelayer|'s methods. - virtual bool OnReadMessage(ChannelEndpoint* endpoint, - ChannelEndpoint* peer_endpoint, - MessageInTransit* message) = 0; - - protected: - Filter() {} - - private: - MOJO_DISALLOW_COPY_AND_ASSIGN(Filter); - }; - - EndpointRelayer(); - - // Gets the other port number (i.e., 0 -> 1, 1 -> 0). - static unsigned GetPeerPort(unsigned port); - - // Initialize this object. This must be called before any other method. - void Init(ChannelEndpoint* endpoint0, - ChannelEndpoint* endpoint1) MOJO_NOT_THREAD_SAFE; - - // Sets (or resets) the filter, which can (optionally) handle/filter - // |Type::ENDPOINT_CLIENT| messages (see |Filter| above). - void SetFilter(scoped_ptr<Filter> filter); - - // |ChannelEndpointClient| methods: - bool OnReadMessage(unsigned port, MessageInTransit* message) override; - void OnDetachFromChannel(unsigned port) override; - - private: - ~EndpointRelayer() override; - - Mutex mutex_; - scoped_refptr<ChannelEndpoint> endpoints_[2] MOJO_GUARDED_BY(mutex_); - scoped_ptr<Filter> filter_ MOJO_GUARDED_BY(mutex_); - - MOJO_DISALLOW_COPY_AND_ASSIGN(EndpointRelayer); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_ENDPOINT_RELAYER_H_ diff --git a/third_party/mojo/src/mojo/edk/system/endpoint_relayer_unittest.cc b/third_party/mojo/src/mojo/edk/system/endpoint_relayer_unittest.cc deleted file mode 100644 index 29096e1..0000000 --- a/third_party/mojo/src/mojo/edk/system/endpoint_relayer_unittest.cc +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright 2015 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 "third_party/mojo/src/mojo/edk/system/endpoint_relayer.h" - -#include "base/logging.h" -#include "base/synchronization/waitable_event.h" -#include "base/test/test_timeouts.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint_id.h" -#include "third_party/mojo/src/mojo/edk/system/channel_test_base.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit_queue.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit_test_utils.h" -#include "third_party/mojo/src/mojo/edk/system/test_channel_endpoint_client.h" - -namespace mojo { -namespace system { -namespace { - -class EndpointRelayerTest : public test::ChannelTestBase { - public: - EndpointRelayerTest() {} - ~EndpointRelayerTest() override {} - - void SetUp() override { - test::ChannelTestBase::SetUp(); - - PostMethodToIOThreadAndWait( - FROM_HERE, &EndpointRelayerTest::CreateAndInitChannelOnIOThread, 0); - PostMethodToIOThreadAndWait( - FROM_HERE, &EndpointRelayerTest::CreateAndInitChannelOnIOThread, 1); - - // The set up: - // * Across the pair of channels, we'll have a pair of connections (call - // them "a" and "b"). - // * On channel 0, we'll have a pair of endpoints ("0a" and "0b") hooked up - // to an |EndpointRelayer|. - // * On channel 1, we'll have a pair of endpoints hooked up to test endpoint - // clients ("1a" and "1b"). - LocalChannelEndpointIdGenerator id_generator; - ChannelEndpointId ida = id_generator.GetNext(); - ChannelEndpointId idb = id_generator.GetNext(); - - relayer_ = new EndpointRelayer(); - endpoint0a_ = new ChannelEndpoint(relayer_.get(), 0); - endpoint0b_ = new ChannelEndpoint(relayer_.get(), 1); - relayer_->Init(endpoint0a_.get(), endpoint0b_.get()); - channel(0)->SetBootstrapEndpointWithIds(endpoint0a_, ida, ida); - channel(0)->SetBootstrapEndpointWithIds(endpoint0b_, idb, idb); - - client1a_ = new test::TestChannelEndpointClient(); - client1b_ = new test::TestChannelEndpointClient(); - endpoint1a_ = new ChannelEndpoint(client1a_.get(), 0); - endpoint1b_ = new ChannelEndpoint(client1b_.get(), 0); - client1a_->Init(0, endpoint1a_.get()); - client1b_->Init(0, endpoint1b_.get()); - channel(1)->SetBootstrapEndpointWithIds(endpoint1a_, ida, ida); - channel(1)->SetBootstrapEndpointWithIds(endpoint1b_, idb, idb); - } - - void TearDown() override { - PostMethodToIOThreadAndWait( - FROM_HERE, &EndpointRelayerTest::ShutdownChannelOnIOThread, 0); - PostMethodToIOThreadAndWait( - FROM_HERE, &EndpointRelayerTest::ShutdownChannelOnIOThread, 1); - - test::ChannelTestBase::TearDown(); - } - - protected: - EndpointRelayer* relayer() { return relayer_.get(); } - test::TestChannelEndpointClient* client1a() { return client1a_.get(); } - test::TestChannelEndpointClient* client1b() { return client1b_.get(); } - ChannelEndpoint* endpoint1a() { return endpoint1a_.get(); } - ChannelEndpoint* endpoint1b() { return endpoint1b_.get(); } - - private: - scoped_refptr<EndpointRelayer> relayer_; - scoped_refptr<ChannelEndpoint> endpoint0a_; - scoped_refptr<ChannelEndpoint> endpoint0b_; - scoped_refptr<test::TestChannelEndpointClient> client1a_; - scoped_refptr<test::TestChannelEndpointClient> client1b_; - scoped_refptr<ChannelEndpoint> endpoint1a_; - scoped_refptr<ChannelEndpoint> endpoint1b_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(EndpointRelayerTest); -}; - -TEST_F(EndpointRelayerTest, Basic) { - base::WaitableEvent read_event(true, false); - client1b()->SetReadEvent(&read_event); - EXPECT_EQ(0u, client1b()->NumMessages()); - - EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(12345))); - - EXPECT_TRUE(read_event.TimedWait(TestTimeouts::tiny_timeout())); - client1b()->SetReadEvent(nullptr); - - ASSERT_EQ(1u, client1b()->NumMessages()); - scoped_ptr<MessageInTransit> read_message = client1b()->PopMessage(); - ASSERT_TRUE(read_message); - test::VerifyTestMessage(read_message.get(), 12345); - - // Now do the same thing in the opposite direction. - read_event.Reset(); - client1a()->SetReadEvent(&read_event); - EXPECT_EQ(0u, client1a()->NumMessages()); - - EXPECT_TRUE(endpoint1b()->EnqueueMessage(test::MakeTestMessage(67890))); - - EXPECT_TRUE(read_event.TimedWait(TestTimeouts::tiny_timeout())); - client1a()->SetReadEvent(nullptr); - - ASSERT_EQ(1u, client1a()->NumMessages()); - read_message = client1a()->PopMessage(); - ASSERT_TRUE(read_message); - test::VerifyTestMessage(read_message.get(), 67890); -} - -TEST_F(EndpointRelayerTest, MultipleMessages) { - EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(1))); - EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(2))); - EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(3))); - EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(4))); - EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(5))); - - base::WaitableEvent read_event(true, false); - client1b()->SetReadEvent(&read_event); - for (size_t i = 0; client1b()->NumMessages() < 5 && i < 5; i++) { - EXPECT_TRUE(read_event.TimedWait(TestTimeouts::tiny_timeout())); - read_event.Reset(); - } - client1b()->SetReadEvent(nullptr); - - // Check the received messages. - ASSERT_EQ(5u, client1b()->NumMessages()); - for (unsigned message_id = 1; message_id <= 5; message_id++) { - scoped_ptr<MessageInTransit> read_message = client1b()->PopMessage(); - ASSERT_TRUE(read_message); - test::VerifyTestMessage(read_message.get(), message_id); - } -} - -// A simple test filter. It will filter test messages made with -// |test::MakeTestMessage()| with |id >= 1000|, and not filter other messages. -class TestFilter : public EndpointRelayer::Filter { - public: - // |filtered_messages| will receive (and own) filtered messages; it will be - // accessed under the owning |EndpointRelayer|'s lock, and must outlive this - // filter. - // - // (Outside this class, you should only access |filtered_messages| once this - // filter is no longer the |EndpointRelayer|'s filter.) - explicit TestFilter(MessageInTransitQueue* filtered_messages) - : filtered_messages_(filtered_messages) { - CHECK(filtered_messages_); - } - - ~TestFilter() override {} - - // Note: Recall that this is called under the |EndpointRelayer|'s lock. - bool OnReadMessage(ChannelEndpoint* endpoint, - ChannelEndpoint* peer_endpoint, - MessageInTransit* message) override { - CHECK(endpoint); - CHECK(peer_endpoint); - CHECK(message); - - unsigned id = 0; - if (test::IsTestMessage(message, &id) && id >= 1000) { - filtered_messages_->AddMessage(make_scoped_ptr(message)); - return true; - } - - return false; - } - - private: - MessageInTransitQueue* const filtered_messages_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(TestFilter); -}; - -TEST_F(EndpointRelayerTest, Filter) { - MessageInTransitQueue filtered_messages; - relayer()->SetFilter(make_scoped_ptr(new TestFilter(&filtered_messages))); - - EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(1))); - EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(2))); - EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(1001))); - EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(3))); - EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(4))); - EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(1002))); - EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(1003))); - EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(5))); - - base::WaitableEvent read_event(true, false); - client1b()->SetReadEvent(&read_event); - for (size_t i = 0; client1b()->NumMessages() < 5 && i < 5; i++) { - EXPECT_TRUE(read_event.TimedWait(TestTimeouts::tiny_timeout())); - read_event.Reset(); - } - client1b()->SetReadEvent(nullptr); - - // Check the received messages: We should get "1"-"5". - ASSERT_EQ(5u, client1b()->NumMessages()); - for (unsigned message_id = 1; message_id <= 5; message_id++) { - scoped_ptr<MessageInTransit> read_message = client1b()->PopMessage(); - ASSERT_TRUE(read_message); - test::VerifyTestMessage(read_message.get(), message_id); - } - - // Reset the filter, so we can safely examine |filtered_messages|. - relayer()->SetFilter(nullptr); - - // Note that since "5" was sent after "1003" and it the former was received, - // the latter must have also been "received"/filtered. - ASSERT_EQ(3u, filtered_messages.Size()); - for (unsigned message_id = 1001; message_id <= 1003; message_id++) { - scoped_ptr<MessageInTransit> message = filtered_messages.GetMessage(); - ASSERT_TRUE(message); - test::VerifyTestMessage(message.get(), message_id); - } -} - -// TODO(vtl): Add some "shutdown" tests. - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/handle_signals_state.h b/third_party/mojo/src/mojo/edk/system/handle_signals_state.h deleted file mode 100644 index bec6e74..0000000 --- a/third_party/mojo/src/mojo/edk/system/handle_signals_state.h +++ /dev/null @@ -1,49 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_HANDLE_SIGNALS_STATE_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_HANDLE_SIGNALS_STATE_H_ - -#include "mojo/public/c/system/types.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -// Just "add" some constructors and methods to the C struct -// |MojoHandleSignalsState| (for convenience). This should add no overhead. -struct MOJO_SYSTEM_IMPL_EXPORT HandleSignalsState final - : public MojoHandleSignalsState { - HandleSignalsState() { - satisfied_signals = MOJO_HANDLE_SIGNAL_NONE; - satisfiable_signals = MOJO_HANDLE_SIGNAL_NONE; - } - HandleSignalsState(MojoHandleSignals satisfied, - MojoHandleSignals satisfiable) { - satisfied_signals = satisfied; - satisfiable_signals = satisfiable; - } - - bool equals(const HandleSignalsState& other) const { - return satisfied_signals == other.satisfied_signals && - satisfiable_signals == other.satisfiable_signals; - } - - bool satisfies(MojoHandleSignals signals) const { - return !!(satisfied_signals & signals); - } - - bool can_satisfy(MojoHandleSignals signals) const { - return !!(satisfiable_signals & signals); - } - - // (Copy and assignment allowed.) -}; -static_assert(sizeof(HandleSignalsState) == sizeof(MojoHandleSignalsState), - "HandleSignalsState should add no overhead"); - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_HANDLE_SIGNALS_STATE_H_ diff --git a/third_party/mojo/src/mojo/edk/system/handle_table.cc b/third_party/mojo/src/mojo/edk/system/handle_table.cc deleted file mode 100644 index c26c6ba..0000000 --- a/third_party/mojo/src/mojo/edk/system/handle_table.cc +++ /dev/null @@ -1,243 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/handle_table.h" - -#include <limits> - -#include "base/logging.h" -#include "third_party/mojo/src/mojo/edk/system/configuration.h" -#include "third_party/mojo/src/mojo/edk/system/dispatcher.h" - -namespace mojo { -namespace system { - -HandleTable::Entry::Entry() : busy(false) { -} - -HandleTable::Entry::Entry(const scoped_refptr<Dispatcher>& dispatcher) - : dispatcher(dispatcher), busy(false) { -} - -HandleTable::Entry::~Entry() { - DCHECK(!busy); -} - -HandleTable::HandleTable() : next_handle_(MOJO_HANDLE_INVALID + 1) { -} - -HandleTable::~HandleTable() { - // This should usually not be reached (the only instance should be owned by - // the singleton |Core|, which lives forever), except in tests. -} - -Dispatcher* HandleTable::GetDispatcher(MojoHandle handle) { - DCHECK_NE(handle, MOJO_HANDLE_INVALID); - - HandleToEntryMap::iterator it = handle_to_entry_map_.find(handle); - if (it == handle_to_entry_map_.end()) - return nullptr; - return it->second.dispatcher.get(); -} - -MojoResult HandleTable::GetAndRemoveDispatcher( - MojoHandle handle, - scoped_refptr<Dispatcher>* dispatcher) { - DCHECK_NE(handle, MOJO_HANDLE_INVALID); - DCHECK(dispatcher); - - HandleToEntryMap::iterator it = handle_to_entry_map_.find(handle); - if (it == handle_to_entry_map_.end()) - return MOJO_RESULT_INVALID_ARGUMENT; - if (it->second.busy) - return MOJO_RESULT_BUSY; - *dispatcher = it->second.dispatcher; - handle_to_entry_map_.erase(it); - - return MOJO_RESULT_OK; -} - -MojoHandle HandleTable::AddDispatcher( - const scoped_refptr<Dispatcher>& dispatcher) { - if (handle_to_entry_map_.size() >= GetConfiguration().max_handle_table_size) - return MOJO_HANDLE_INVALID; - return AddDispatcherNoSizeCheck(dispatcher); -} - -std::pair<MojoHandle, MojoHandle> HandleTable::AddDispatcherPair( - const scoped_refptr<Dispatcher>& dispatcher0, - const scoped_refptr<Dispatcher>& dispatcher1) { - if (handle_to_entry_map_.size() + 1 >= - GetConfiguration().max_handle_table_size) - return std::make_pair(MOJO_HANDLE_INVALID, MOJO_HANDLE_INVALID); - return std::make_pair(AddDispatcherNoSizeCheck(dispatcher0), - AddDispatcherNoSizeCheck(dispatcher1)); -} - -bool HandleTable::AddDispatcherVector(const DispatcherVector& dispatchers, - MojoHandle* handles) { - size_t max_message_num_handles = GetConfiguration().max_message_num_handles; - size_t max_handle_table_size = GetConfiguration().max_handle_table_size; - - DCHECK_LE(dispatchers.size(), max_message_num_handles); - DCHECK(handles); - DCHECK_LT( - static_cast<uint64_t>(max_handle_table_size) + max_message_num_handles, - std::numeric_limits<size_t>::max()) - << "Addition may overflow"; - - if (handle_to_entry_map_.size() + dispatchers.size() > max_handle_table_size) - return false; - - for (size_t i = 0; i < dispatchers.size(); i++) { - if (dispatchers[i]) { - handles[i] = AddDispatcherNoSizeCheck(dispatchers[i]); - } else { - LOG(WARNING) << "Invalid dispatcher at index " << i; - handles[i] = MOJO_HANDLE_INVALID; - } - } - return true; -} - -MojoResult HandleTable::MarkBusyAndStartTransport( - MojoHandle disallowed_handle, - const MojoHandle* handles, - uint32_t num_handles, - std::vector<DispatcherTransport>* transports) { - DCHECK_NE(disallowed_handle, MOJO_HANDLE_INVALID); - DCHECK(handles); - DCHECK_LE(num_handles, GetConfiguration().max_message_num_handles); - DCHECK(transports); - DCHECK_EQ(transports->size(), num_handles); - - std::vector<Entry*> entries(num_handles); - - // First verify all the handles and get their dispatchers. - uint32_t i; - MojoResult error_result = MOJO_RESULT_INTERNAL; - for (i = 0; i < num_handles; i++) { - // Sending your own handle is not allowed (and, for consistency, returns - // "busy"). - if (handles[i] == disallowed_handle) { - error_result = MOJO_RESULT_BUSY; - break; - } - - HandleToEntryMap::iterator it = handle_to_entry_map_.find(handles[i]); - if (it == handle_to_entry_map_.end()) { - error_result = MOJO_RESULT_INVALID_ARGUMENT; - break; - } - - entries[i] = &it->second; - if (entries[i]->busy) { - error_result = MOJO_RESULT_BUSY; - break; - } - // Note: By marking the handle as busy here, we're also preventing the - // same handle from being sent multiple times in the same message. - entries[i]->busy = true; - - // Try to start the transport. - DispatcherTransport transport = - Dispatcher::HandleTableAccess::TryStartTransport( - entries[i]->dispatcher.get()); - if (!transport.is_valid()) { - // Only log for Debug builds, since this is not a problem with the system - // code, but with user code. - DLOG(WARNING) << "Likely race condition in user code detected: attempt " - "to transfer handle " << handles[i] - << " while it is in use on a different thread"; - - // Unset the busy flag (since it won't be unset below). - entries[i]->busy = false; - error_result = MOJO_RESULT_BUSY; - break; - } - - // Check if the dispatcher is busy (e.g., in a two-phase read/write). - // (Note that this must be done after the dispatcher's lock is acquired.) - if (transport.IsBusy()) { - // Unset the busy flag and end the transport (since it won't be done - // below). - entries[i]->busy = false; - transport.End(); - error_result = MOJO_RESULT_BUSY; - break; - } - - // Hang on to the transport (which we'll need to end the transport). - (*transports)[i] = transport; - } - if (i < num_handles) { - DCHECK_NE(error_result, MOJO_RESULT_INTERNAL); - - // Unset the busy flags and release the locks. - for (uint32_t j = 0; j < i; j++) { - DCHECK(entries[j]->busy); - entries[j]->busy = false; - (*transports)[j].End(); - } - return error_result; - } - - return MOJO_RESULT_OK; -} - -MojoHandle HandleTable::AddDispatcherNoSizeCheck( - const scoped_refptr<Dispatcher>& dispatcher) { - DCHECK(dispatcher); - DCHECK_LT(handle_to_entry_map_.size(), - GetConfiguration().max_handle_table_size); - DCHECK_NE(next_handle_, MOJO_HANDLE_INVALID); - - // TODO(vtl): Maybe we want to do something different/smarter. (Or maybe try - // assigning randomly?) - while (handle_to_entry_map_.find(next_handle_) != - handle_to_entry_map_.end()) { - next_handle_++; - if (next_handle_ == MOJO_HANDLE_INVALID) - next_handle_++; - } - - MojoHandle new_handle = next_handle_; - handle_to_entry_map_[new_handle] = Entry(dispatcher); - - next_handle_++; - if (next_handle_ == MOJO_HANDLE_INVALID) - next_handle_++; - - return new_handle; -} - -void HandleTable::RemoveBusyHandles(const MojoHandle* handles, - uint32_t num_handles) { - DCHECK(handles); - DCHECK_LE(num_handles, GetConfiguration().max_message_num_handles); - - for (uint32_t i = 0; i < num_handles; i++) { - HandleToEntryMap::iterator it = handle_to_entry_map_.find(handles[i]); - DCHECK(it != handle_to_entry_map_.end()); - DCHECK(it->second.busy); - it->second.busy = false; // For the sake of a |DCHECK()|. - handle_to_entry_map_.erase(it); - } -} - -void HandleTable::RestoreBusyHandles(const MojoHandle* handles, - uint32_t num_handles) { - DCHECK(handles); - DCHECK_LE(num_handles, GetConfiguration().max_message_num_handles); - - for (uint32_t i = 0; i < num_handles; i++) { - HandleToEntryMap::iterator it = handle_to_entry_map_.find(handles[i]); - DCHECK(it != handle_to_entry_map_.end()); - DCHECK(it->second.busy); - it->second.busy = false; - } -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/handle_table.h b/third_party/mojo/src/mojo/edk/system/handle_table.h deleted file mode 100644 index 65b81eb..0000000 --- a/third_party/mojo/src/mojo/edk/system/handle_table.h +++ /dev/null @@ -1,144 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_HANDLE_TABLE_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_HANDLE_TABLE_H_ - -#include <utility> -#include <vector> - -#include "base/containers/hash_tables.h" -#include "base/memory/ref_counted.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -class Core; -class Dispatcher; -class DispatcherTransport; - -using DispatcherVector = std::vector<scoped_refptr<Dispatcher>>; - -// Test-only function (defined/used in embedder/test_embedder.cc). Declared here -// so it can be friended. -namespace internal { -bool ShutdownCheckNoLeaks(Core*); -} - -// This class provides the (global) handle table (owned by |Core|), which maps -// (valid) |MojoHandle|s to |Dispatcher|s. This is abstracted so that, e.g., -// caching may be added. -// -// This class is NOT thread-safe; locking is left to |Core| (since it may need -// to make several changes -- "atomically" or in rapid successsion, in which -// case the extra locking/unlocking would be unnecessary overhead). - -class MOJO_SYSTEM_IMPL_EXPORT HandleTable { - public: - HandleTable(); - ~HandleTable(); - - // Gets the dispatcher for a given handle (which should not be - // |MOJO_HANDLE_INVALID|). Returns null if there's no dispatcher for the given - // handle. - // WARNING: For efficiency, this returns a dumb pointer. If you're going to - // use the result outside |Core|'s lock, you MUST take a reference (e.g., by - // storing the result inside a |scoped_refptr|). - Dispatcher* GetDispatcher(MojoHandle handle); - - // On success, gets the dispatcher for a given handle (which should not be - // |MOJO_HANDLE_INVALID|) and removes it. (On failure, returns an appropriate - // result (and leaves |dispatcher| alone), namely - // |MOJO_RESULT_INVALID_ARGUMENT| if there's no dispatcher for the given - // handle or |MOJO_RESULT_BUSY| if the handle is marked as busy.) - MojoResult GetAndRemoveDispatcher(MojoHandle handle, - scoped_refptr<Dispatcher>* dispatcher); - - // Adds a dispatcher (which must be valid), returning the handle for it. - // Returns |MOJO_HANDLE_INVALID| on failure (if the handle table is full). - MojoHandle AddDispatcher(const scoped_refptr<Dispatcher>& dispatcher); - - // Adds a pair of dispatchers (which must be valid), return a pair of handles - // for them. On failure (if the handle table is full), the first (and second) - // handles will be |MOJO_HANDLE_INVALID|, and neither dispatcher will be - // added. - std::pair<MojoHandle, MojoHandle> AddDispatcherPair( - const scoped_refptr<Dispatcher>& dispatcher0, - const scoped_refptr<Dispatcher>& dispatcher1); - - // Adds the given vector of dispatchers (of size at most - // |kMaxMessageNumHandles|). |handles| must point to an array of size at least - // |dispatchers.size()|. Unlike the other |AddDispatcher...()| functions, some - // of the dispatchers may be invalid (null). Returns true on success and false - // on failure (if the handle table is full), in which case it leaves - // |handles[...]| untouched (and all dispatchers unadded). - bool AddDispatcherVector(const DispatcherVector& dispatchers, - MojoHandle* handles); - - // Tries to mark the given handles as busy and start transport on them (i.e., - // take their dispatcher locks); |transports| must be sized to contain - // |num_handles| elements. On failure, returns them to their original - // (non-busy, unlocked state). - MojoResult MarkBusyAndStartTransport( - MojoHandle disallowed_handle, - const MojoHandle* handles, - uint32_t num_handles, - std::vector<DispatcherTransport>* transports); - - // Remove the given handles, which must all be present and which should have - // previously been marked busy by |MarkBusyAndStartTransport()|. - void RemoveBusyHandles(const MojoHandle* handles, uint32_t num_handles); - - // Restores the given handles, which must all be present and which should have - // previously been marked busy by |MarkBusyAndStartTransport()|, to a non-busy - // state. - void RestoreBusyHandles(const MojoHandle* handles, uint32_t num_handles); - - private: - friend bool internal::ShutdownCheckNoLeaks(Core*); - - // The |busy| member is used only to deal with functions (in particular - // |Core::WriteMessage()|) that want to hold on to a dispatcher and later - // remove it from the handle table, without holding on to the handle table - // lock. - // - // For example, if |Core::WriteMessage()| is called with a handle to be sent, - // (under the handle table lock) it must first check that that handle is not - // busy (if it is busy, then it fails with |MOJO_RESULT_BUSY|) and then marks - // it as busy. To avoid deadlock, it should also try to acquire the locks for - // all the dispatchers for the handles that it is sending (and fail with - // |MOJO_RESULT_BUSY| if the attempt fails). At this point, it can release the - // handle table lock. - // - // If |Core::Close()| is simultaneously called on that handle, it too checks - // if the handle is marked busy. If it is, it fails (with |MOJO_RESULT_BUSY|). - // This prevents |Core::WriteMessage()| from sending a handle that has been - // closed (or learning about this too late). - struct Entry { - Entry(); - explicit Entry(const scoped_refptr<Dispatcher>& dispatcher); - ~Entry(); - - scoped_refptr<Dispatcher> dispatcher; - bool busy; - }; - using HandleToEntryMap = base::hash_map<MojoHandle, Entry>; - - // Adds the given dispatcher to the handle table, not doing any size checks. - MojoHandle AddDispatcherNoSizeCheck( - const scoped_refptr<Dispatcher>& dispatcher); - - HandleToEntryMap handle_to_entry_map_; - MojoHandle next_handle_; // Invariant: never |MOJO_HANDLE_INVALID|. - - MOJO_DISALLOW_COPY_AND_ASSIGN(HandleTable); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_HANDLE_TABLE_H_ diff --git a/third_party/mojo/src/mojo/edk/system/incoming_endpoint.cc b/third_party/mojo/src/mojo/edk/system/incoming_endpoint.cc deleted file mode 100644 index caa9dbe..0000000 --- a/third_party/mojo/src/mojo/edk/system/incoming_endpoint.cc +++ /dev/null @@ -1,82 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/incoming_endpoint.h" - -#include "base/logging.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/data_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/remote_producer_data_pipe_impl.h" - -namespace mojo { -namespace system { - -IncomingEndpoint::IncomingEndpoint() { -} - -scoped_refptr<ChannelEndpoint> IncomingEndpoint::Init() { - endpoint_ = new ChannelEndpoint(this, 0); - return endpoint_; -} - -scoped_refptr<MessagePipe> IncomingEndpoint::ConvertToMessagePipe() { - MutexLocker locker(&mutex_); - scoped_refptr<MessagePipe> message_pipe( - MessagePipe::CreateLocalProxyFromExisting(&message_queue_, - endpoint_.get())); - DCHECK(message_queue_.IsEmpty()); - endpoint_ = nullptr; - return message_pipe; -} - -scoped_refptr<DataPipe> IncomingEndpoint::ConvertToDataPipeProducer( - const MojoCreateDataPipeOptions& validated_options, - size_t consumer_num_bytes) { - MutexLocker locker(&mutex_); - scoped_refptr<DataPipe> data_pipe(DataPipe::CreateRemoteConsumerFromExisting( - validated_options, consumer_num_bytes, &message_queue_, endpoint_.get())); - DCHECK(message_queue_.IsEmpty()); - endpoint_ = nullptr; - return data_pipe; -} - -scoped_refptr<DataPipe> IncomingEndpoint::ConvertToDataPipeConsumer( - const MojoCreateDataPipeOptions& validated_options) { - MutexLocker locker(&mutex_); - scoped_refptr<DataPipe> data_pipe(DataPipe::CreateRemoteProducerFromExisting( - validated_options, &message_queue_, endpoint_.get())); - DCHECK(message_queue_.IsEmpty()); - endpoint_ = nullptr; - return data_pipe; -} - -void IncomingEndpoint::Close() { - MutexLocker locker(&mutex_); - if (endpoint_) { - endpoint_->DetachFromClient(); - endpoint_ = nullptr; - } -} - -bool IncomingEndpoint::OnReadMessage(unsigned /*port*/, - MessageInTransit* message) { - MutexLocker locker(&mutex_); - if (!endpoint_) - return false; - - message_queue_.AddMessage(make_scoped_ptr(message)); - return true; -} - -void IncomingEndpoint::OnDetachFromChannel(unsigned /*port*/) { - Close(); -} - -IncomingEndpoint::~IncomingEndpoint() { -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/incoming_endpoint.h b/third_party/mojo/src/mojo/edk/system/incoming_endpoint.h deleted file mode 100644 index 18f76ea..0000000 --- a/third_party/mojo/src/mojo/edk/system/incoming_endpoint.h +++ /dev/null @@ -1,65 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_INCOMING_ENDPOINT_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_INCOMING_ENDPOINT_H_ - -#include <stddef.h> - -#include "base/memory/ref_counted.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint_client.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit_queue.h" -#include "third_party/mojo/src/mojo/edk/system/mutex.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -struct MojoCreateDataPipeOptions; - -namespace mojo { -namespace system { - -class ChannelEndpoint; -class DataPipe; -class MessagePipe; - -// This is a simple |ChannelEndpointClient| that only receives messages. It's -// used for endpoints that are "received" by |Channel|, but not yet turned into -// |MessagePipe|s or |DataPipe|s. -class MOJO_SYSTEM_IMPL_EXPORT IncomingEndpoint final - : public ChannelEndpointClient { - public: - IncomingEndpoint(); - - // Must be called before any other method. - scoped_refptr<ChannelEndpoint> Init() MOJO_NOT_THREAD_SAFE; - - scoped_refptr<MessagePipe> ConvertToMessagePipe(); - scoped_refptr<DataPipe> ConvertToDataPipeProducer( - const MojoCreateDataPipeOptions& validated_options, - size_t consumer_num_bytes); - scoped_refptr<DataPipe> ConvertToDataPipeConsumer( - const MojoCreateDataPipeOptions& validated_options); - - // Must be called before destroying this object if |ConvertToMessagePipe()| - // wasn't called (but |Init()| was). - void Close(); - - // |ChannelEndpointClient| methods: - bool OnReadMessage(unsigned port, MessageInTransit* message) override; - void OnDetachFromChannel(unsigned port) override; - - private: - ~IncomingEndpoint() override; - - Mutex mutex_; - scoped_refptr<ChannelEndpoint> endpoint_ MOJO_GUARDED_BY(mutex_); - MessageInTransitQueue message_queue_ MOJO_GUARDED_BY(mutex_); - - MOJO_DISALLOW_COPY_AND_ASSIGN(IncomingEndpoint); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_INCOMING_ENDPOINT_H_ diff --git a/third_party/mojo/src/mojo/edk/system/ipc_support.cc b/third_party/mojo/src/mojo/edk/system/ipc_support.cc deleted file mode 100644 index 26a5511..0000000 --- a/third_party/mojo/src/mojo/edk/system/ipc_support.cc +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2015 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 "third_party/mojo/src/mojo/edk/system/ipc_support.h" - -#include <utility> - -#include "base/logging.h" -#include "third_party/mojo/src/mojo/edk/embedder/master_process_delegate.h" -#include "third_party/mojo/src/mojo/edk/embedder/slave_process_delegate.h" -#include "third_party/mojo/src/mojo/edk/system/channel_manager.h" -#include "third_party/mojo/src/mojo/edk/system/master_connection_manager.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/slave_connection_manager.h" - -namespace mojo { -namespace system { - -IPCSupport::IPCSupport(embedder::PlatformSupport* platform_support, - embedder::ProcessType process_type, - embedder::ProcessDelegate* process_delegate, - scoped_refptr<base::TaskRunner> io_thread_task_runner, - embedder::ScopedPlatformHandle platform_handle) - : process_type_(process_type), - process_delegate_(process_delegate), - io_thread_task_runner_(std::move(io_thread_task_runner)) { - DCHECK(io_thread_task_runner_); - - switch (process_type_) { - case embedder::ProcessType::UNINITIALIZED: - CHECK(false); - break; - case embedder::ProcessType::NONE: - DCHECK(!platform_handle.is_valid()); // We wouldn't do anything with it. - // Nothing to do. - break; - case embedder::ProcessType::MASTER: - DCHECK(!platform_handle.is_valid()); // We wouldn't do anything with it. - connection_manager_.reset( - new system::MasterConnectionManager(platform_support)); - static_cast<system::MasterConnectionManager*>(connection_manager_.get()) - ->Init( - static_cast<embedder::MasterProcessDelegate*>(process_delegate_)); - break; - case embedder::ProcessType::SLAVE: - connection_manager_.reset( - new system::SlaveConnectionManager(platform_support)); - static_cast<system::SlaveConnectionManager*>(connection_manager_.get()) - ->Init( - static_cast<embedder::SlaveProcessDelegate*>(process_delegate_), - std::move(platform_handle)); - break; - } - - channel_manager_.reset(new ChannelManager( - platform_support, io_thread_task_runner_, connection_manager_.get())); -} - -IPCSupport::~IPCSupport() { - DCHECK_EQ(process_type_, embedder::ProcessType::UNINITIALIZED); -} - -void IPCSupport::ShutdownOnIOThread() { - DCHECK_NE(process_type_, embedder::ProcessType::UNINITIALIZED); - - channel_manager_->ShutdownOnIOThread(); - channel_manager_.reset(); - - if (connection_manager_) { - connection_manager_->Shutdown(); - connection_manager_.reset(); - } - - io_thread_task_runner_ = nullptr; - process_delegate_ = nullptr; - process_type_ = embedder::ProcessType::UNINITIALIZED; -} - -ConnectionIdentifier IPCSupport::GenerateConnectionIdentifier() { - return connection_manager()->GenerateConnectionIdentifier(); -} - -scoped_refptr<system::MessagePipeDispatcher> IPCSupport::ConnectToSlave( - const ConnectionIdentifier& connection_id, - embedder::SlaveInfo slave_info, - embedder::ScopedPlatformHandle platform_handle, - const base::Closure& callback, - scoped_refptr<base::TaskRunner> callback_thread_task_runner, - ChannelId* channel_id) { - DCHECK(channel_id); - - // We rely on |ChannelId| and |ProcessIdentifier| being identical types. - // TODO(vtl): Use std::is_same instead when we are allowed to (C++11 library). - static_assert(sizeof(ChannelId) == sizeof(ProcessIdentifier), - "ChannelId and ProcessIdentifier types don't match"); - - embedder::ScopedPlatformHandle platform_connection_handle = - ConnectToSlaveInternal(connection_id, slave_info, - std::move(platform_handle), channel_id); - return channel_manager()->CreateChannel( - *channel_id, std::move(platform_connection_handle), callback, - callback_thread_task_runner); -} - -scoped_refptr<system::MessagePipeDispatcher> IPCSupport::ConnectToMaster( - const ConnectionIdentifier& connection_id, - const base::Closure& callback, - scoped_refptr<base::TaskRunner> callback_thread_task_runner, - ChannelId* channel_id) { - DCHECK(channel_id); - - // TODO(vtl): Use std::is_same instead when we are allowed to (C++11 library). - static_assert(sizeof(ChannelId) == sizeof(ProcessIdentifier), - "ChannelId and ProcessIdentifier types don't match"); - embedder::ScopedPlatformHandle platform_connection_handle = - ConnectToMasterInternal(connection_id); - *channel_id = kMasterProcessIdentifier; - return channel_manager()->CreateChannel( - *channel_id, std::move(platform_connection_handle), callback, - callback_thread_task_runner); -} - -embedder::ScopedPlatformHandle IPCSupport::ConnectToSlaveInternal( - const ConnectionIdentifier& connection_id, - embedder::SlaveInfo slave_info, - embedder::ScopedPlatformHandle platform_handle, - ProcessIdentifier* slave_process_identifier) { - DCHECK(slave_process_identifier); - DCHECK_EQ(process_type_, embedder::ProcessType::MASTER); - - *slave_process_identifier = - static_cast<system::MasterConnectionManager*>(connection_manager()) - ->AddSlaveAndBootstrap(slave_info, std::move(platform_handle), - connection_id); - - system::ProcessIdentifier peer_id = system::kInvalidProcessIdentifier; - bool is_first; - embedder::ScopedPlatformHandle platform_connection_handle; - CHECK_EQ(connection_manager()->Connect(connection_id, &peer_id, &is_first, - &platform_connection_handle), - ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION); - DCHECK_EQ(peer_id, *slave_process_identifier); - DCHECK(platform_connection_handle.is_valid()); - return platform_connection_handle; -} - -embedder::ScopedPlatformHandle IPCSupport::ConnectToMasterInternal( - const ConnectionIdentifier& connection_id) { - DCHECK_EQ(process_type_, embedder::ProcessType::SLAVE); - - system::ProcessIdentifier peer_id = system::kInvalidProcessIdentifier; - bool is_first; - embedder::ScopedPlatformHandle platform_connection_handle; - CHECK_EQ(connection_manager()->Connect(connection_id, &peer_id, &is_first, - &platform_connection_handle), - ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION); - DCHECK_EQ(peer_id, system::kMasterProcessIdentifier); - DCHECK(platform_connection_handle.is_valid()); - return platform_connection_handle; -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/ipc_support.h b/third_party/mojo/src/mojo/edk/system/ipc_support.h deleted file mode 100644 index 953673ef..0000000 --- a/third_party/mojo/src/mojo/edk/system/ipc_support.h +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright 2015 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_IPC_SUPPORT_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_IPC_SUPPORT_H_ - -#include "base/callback_forward.h" -#include "base/gtest_prod_util.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/task_runner.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/process_type.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" -#include "third_party/mojo/src/mojo/edk/embedder/slave_info.h" -#include "third_party/mojo/src/mojo/edk/system/channel_id.h" -#include "third_party/mojo/src/mojo/edk/system/connection_identifier.h" -#include "third_party/mojo/src/mojo/edk/system/process_identifier.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { - -namespace embedder { -class PlatformSupport; -class ProcessDelegate; -} - -namespace system { - -class ChannelManager; -class ConnectionManager; -class MessagePipeDispatcher; - -// This test (and its helper function) need to be friended. -FORWARD_DECLARE_TEST(IPCSupportTest, MasterSlaveInternal); -FORWARD_DECLARE_TEST(IPCSupportTest, MultiprocessMasterSlaveInternal); -void MultiprocessMasterSlaveInternalTestChildTest(); - -// |IPCSupport| encapsulates all the objects that are needed to support IPC for -// a single "process" (whether that be a master or a slave). -// -// ("Process" typically means a real process, but for testing purposes, multiple -// instances can coexist within a single real process.) -// -// Each "process" must have an |embedder::PlatformSupport| and a suitable -// |embedder::ProcessDelegate|, together with an I/O thread and a thread on -// which to call delegate methods (which may be the same as the I/O thread). -// -// For testing purposes within a single real process, except for the I/O thread, -// these may be shared between "processes" (i.e., instances of |IPCSupport|) -- -// there must be a separate I/O thread for each |IPCSupport|. -// -// Except for |ShutdownOnIOThread()|, this class is thread-safe. (No methods may -// be called during/after |ShutdownOnIOThread()|.) -class MOJO_SYSTEM_IMPL_EXPORT IPCSupport { - public: - // Constructor: initializes for the given |process_type|; |process_delegate| - // must match the process type. |platform_handle| is only used for slave - // processes. - // - // All the (pointer) arguments must remain alive (and, in the case of task - // runners, continue to process tasks) until |ShutdownOnIOThread()| has been - // called. - IPCSupport(embedder::PlatformSupport* platform_support, - embedder::ProcessType process_type, - embedder::ProcessDelegate* process_delegate, - scoped_refptr<base::TaskRunner> io_thread_task_runner, - embedder::ScopedPlatformHandle platform_handle); - // Note: This object must be shut down before destruction (see - // |ShutdownOnIOThread()|). - ~IPCSupport(); - - // This must be called (exactly once) on the I/O thread before this object is - // destroyed (which may happen on any thread). Note: This does *not* call the - // process delegate's |OnShutdownComplete()|. - void ShutdownOnIOThread(); - - // Generates a new (unique) connection identifier, for use with - // |ConnectToSlave()| and |ConnectToMaster()|, below. - ConnectionIdentifier GenerateConnectionIdentifier(); - - // Called in the master process to connect a slave process to the IPC system. - // - // |connection_id| should be a unique connection identifier, which will also - // be given to the slave (in |ConnectToMaster()|, below). |slave_info| is - // context for the caller (it is treated as an opaque value by this class). - // |platform_handle| should be the master's handle to an OS "pipe" between - // master and slave. This will then bootstrap a |Channel| between master and - // slave together with an initial message pipe (returning a dispatcher for the - // master's side). - // - // |callback| will be run after the |Channel| is created, either using - // |callback_thread_task_runner| (if it is non-null) or on the I/O thread. - // |*channel_id| will be set to the ID for the channel (immediately); the - // channel may be destroyed using this ID, but only after the callback has - // been run. - // - // TODO(vtl): Add some more channel management functionality to this class. - // Maybe make this callback interface more sane. - scoped_refptr<system::MessagePipeDispatcher> ConnectToSlave( - const ConnectionIdentifier& connection_id, - embedder::SlaveInfo slave_info, - embedder::ScopedPlatformHandle platform_handle, - const base::Closure& callback, - scoped_refptr<base::TaskRunner> callback_thread_task_runner, - ChannelId* channel_id); - - // Called in a slave process to connect it to the master process and thus the - // IPC system, creating a |Channel| and an initial message pipe (return a - // dispatcher for the slave's side). See |ConnectToSlave()|, above. - // - // |callback|, |callback_thread_task_runner|, and |channel_id| are as in - // |ConnectToSlave()|. - // - // TODO(vtl): |ConnectToSlave()|'s channel management TODO also applies here. - scoped_refptr<system::MessagePipeDispatcher> ConnectToMaster( - const ConnectionIdentifier& connection_id, - const base::Closure& callback, - scoped_refptr<base::TaskRunner> callback_thread_task_runner, - ChannelId* channel_id); - - embedder::ProcessType process_type() const { return process_type_; } - embedder::ProcessDelegate* process_delegate() const { - return process_delegate_; - } - base::TaskRunner* io_thread_task_runner() const { - return io_thread_task_runner_.get(); - } - // TODO(vtl): The things that use the following should probably be moved into - // this class. - ChannelManager* channel_manager() const { return channel_manager_.get(); } - - private: - // These test |ConnectToSlaveInternal()| and |ConnectToMasterInternal()|. - FRIEND_TEST_ALL_PREFIXES(IPCSupportTest, MasterSlaveInternal); - FRIEND_TEST_ALL_PREFIXES(IPCSupportTest, MultiprocessMasterSlaveInternal); - friend void MultiprocessMasterSlaveInternalTestChildTest(); - - // Helper for |ConnectToSlave()|. Connects (using the connection manager) to - // the slave using |platform_handle| (a handle to an OS "pipe" between master - // and slave) and creates a second OS "pipe" between the master and slave - // (returning the master's handle). |*slave_process_identifier| will be set to - // the process identifier assigned to the slave. - embedder::ScopedPlatformHandle ConnectToSlaveInternal( - const ConnectionIdentifier& connection_id, - embedder::SlaveInfo slave_info, - embedder::ScopedPlatformHandle platform_handle, - ProcessIdentifier* slave_process_identifier); - - // Helper for |ConnectToMaster()|. Connects (using the connection manager) to - // the master (using the handle to the OS "pipe" that was given to - // |SlaveConnectionManager::Init()|) and creates a second OS "pipe" between - // the master and slave (returning the slave's handle). - embedder::ScopedPlatformHandle ConnectToMasterInternal( - const ConnectionIdentifier& connection_id); - - ConnectionManager* connection_manager() const { - return connection_manager_.get(); - } - - // These are all set on construction and reset by |ShutdownOnIOThread()|. - embedder::ProcessType process_type_; - embedder::ProcessDelegate* process_delegate_; - scoped_refptr<base::TaskRunner> io_thread_task_runner_; - - scoped_ptr<ConnectionManager> connection_manager_; - scoped_ptr<ChannelManager> channel_manager_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(IPCSupport); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_IPC_SUPPORT_H_ diff --git a/third_party/mojo/src/mojo/edk/system/ipc_support_unittest.cc b/third_party/mojo/src/mojo/edk/system/ipc_support_unittest.cc deleted file mode 100644 index 31a1ac5..0000000 --- a/third_party/mojo/src/mojo/edk/system/ipc_support_unittest.cc +++ /dev/null @@ -1,732 +0,0 @@ -// Copyright 2015 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 "third_party/mojo/src/mojo/edk/system/ipc_support.h" - -#include <utility> -#include <vector> - -#include "base/bind.h" -#include "base/command_line.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/run_loop.h" -#include "base/synchronization/waitable_event.h" -#include "base/test/test_io_thread.h" -#include "base/test/test_timeouts.h" -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/embedder/master_process_delegate.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" -#include "third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h" -#include "third_party/mojo/src/mojo/edk/embedder/slave_process_delegate.h" -#include "third_party/mojo/src/mojo/edk/system/channel_manager.h" -#include "third_party/mojo/src/mojo/edk/system/connection_identifier.h" -#include "third_party/mojo/src/mojo/edk/system/dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/process_identifier.h" -#include "third_party/mojo/src/mojo/edk/system/test_utils.h" -#include "third_party/mojo/src/mojo/edk/system/waiter.h" -#include "third_party/mojo/src/mojo/edk/test/multiprocess_test_helper.h" -#include "third_party/mojo/src/mojo/edk/test/test_utils.h" - -namespace mojo { -namespace system { -namespace { - -const char kConnectionIdFlag[] = "test-connection-id"; - -// Tests writing a message (containing just data) to |write_mp| and then reading -// it from |read_mp| (it should be the next message, i.e., there should be no -// other messages already enqueued in that direction). -void TestWriteReadMessage(scoped_refptr<MessagePipeDispatcher> write_mp, - scoped_refptr<MessagePipeDispatcher> read_mp) { - // Set up waiting on the read end first (to avoid racing). - Waiter waiter; - waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - read_mp->AddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 0, nullptr)); - - // Write a message with just 'x' through the write end. - EXPECT_EQ(MOJO_RESULT_OK, - write_mp->WriteMessage(UserPointer<const void>("x"), 1, nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Wait for it to arrive. - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::ActionDeadline(), nullptr)); - read_mp->RemoveAwakable(&waiter, nullptr); - - // Read the message from the read end. - char buffer[10] = {}; - uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - read_mp->ReadMessage(UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(1u, buffer_size); - EXPECT_EQ('x', buffer[0]); -} - -// Writes a message pipe dispatcher (in a message) to |write_mp| and reads it -// from |read_mp| (it should be the next message, i.e., there should be no other -// other messages already enqueued in that direction). -scoped_refptr<MessagePipeDispatcher> SendMessagePipeDispatcher( - scoped_refptr<MessagePipeDispatcher> write_mp, - scoped_refptr<MessagePipeDispatcher> read_mp, - scoped_refptr<MessagePipeDispatcher> mp_to_send) { - CHECK_NE(mp_to_send, write_mp); - CHECK_NE(mp_to_send, read_mp); - - // Set up waiting on the read end first (to avoid racing). - Waiter waiter; - waiter.Init(); - CHECK_EQ( - read_mp->AddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 0, nullptr), - MOJO_RESULT_OK); - - // Write a message with just |mp_to_send| through the write end. - DispatcherTransport transport( - test::DispatcherTryStartTransport(mp_to_send.get())); - CHECK(transport.is_valid()); - std::vector<DispatcherTransport> transports; - transports.push_back(transport); - CHECK_EQ(write_mp->WriteMessage(NullUserPointer(), 0, &transports, - MOJO_WRITE_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - transport.End(); - - // Wait for it to arrive. - CHECK_EQ(waiter.Wait(test::ActionDeadline(), nullptr), MOJO_RESULT_OK); - read_mp->RemoveAwakable(&waiter, nullptr); - - // Read the message from the read end. - DispatcherVector dispatchers; - uint32_t num_dispatchers = 10; - CHECK_EQ( - read_mp->ReadMessage(NullUserPointer(), NullUserPointer(), &dispatchers, - &num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - CHECK_EQ(dispatchers.size(), 1u); - CHECK_EQ(num_dispatchers, 1u); - CHECK_EQ(dispatchers[0]->GetType(), Dispatcher::Type::MESSAGE_PIPE); - return scoped_refptr<MessagePipeDispatcher>( - static_cast<MessagePipeDispatcher*>(dispatchers[0].get())); -} - -class TestMasterProcessDelegate : public embedder::MasterProcessDelegate { - public: - TestMasterProcessDelegate() : slave_disconnected_(false) {} - ~TestMasterProcessDelegate() override {} - - // Warning: There's only one slave disconnect event (which resets - // automatically). - void TryWaitForOnSlaveDisconnect() { - if (!slave_disconnected_) - run_loop_.Run(); - } - - private: - // |embedder::MasterProcessDelegate| methods: - void OnShutdownComplete() override { NOTREACHED(); } - - void OnSlaveDisconnect(embedder::SlaveInfo /*slave_info*/) override { - slave_disconnected_ = true; - if (run_loop_.running()) - run_loop_.Quit(); - } - - bool slave_disconnected_; - base::RunLoop run_loop_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(TestMasterProcessDelegate); -}; - -class TestSlaveProcessDelegate : public embedder::SlaveProcessDelegate { - public: - TestSlaveProcessDelegate() {} - ~TestSlaveProcessDelegate() override {} - - private: - // |embedder::SlaveProcessDelegate| methods: - void OnShutdownComplete() override { NOTREACHED(); } - - void OnMasterDisconnect() override { NOTREACHED(); } - - MOJO_DISALLOW_COPY_AND_ASSIGN(TestSlaveProcessDelegate); -}; - -// Represents the master's side of its connection to a slave. -class TestSlaveConnection { - public: - TestSlaveConnection(base::TestIOThread* test_io_thread, - IPCSupport* master_ipc_support) - : test_io_thread_(test_io_thread), - master_ipc_support_(master_ipc_support), - connection_id_(master_ipc_support_->GenerateConnectionIdentifier()), - slave_id_(kInvalidProcessIdentifier), - event_(true, false) {} - ~TestSlaveConnection() {} - - // After this is called, |ShutdownChannelToSlave()| must be called (possibly - // after |WaitForChannelToSlave()|) before destruction. - scoped_refptr<MessagePipeDispatcher> ConnectToSlave() { - embedder::PlatformChannelPair channel_pair; - // Note: |ChannelId|s and |ProcessIdentifier|s are interchangeable. - scoped_refptr<MessagePipeDispatcher> mp = - master_ipc_support_->ConnectToSlave( - connection_id_, nullptr, channel_pair.PassServerHandle(), - base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event_)), - nullptr, &slave_id_); - EXPECT_TRUE(mp); - EXPECT_NE(slave_id_, kInvalidProcessIdentifier); - EXPECT_NE(slave_id_, kMasterProcessIdentifier); - slave_platform_handle_ = channel_pair.PassClientHandle(); - return mp; - } - - void WaitForChannelToSlave() { - EXPECT_TRUE(event_.TimedWait(TestTimeouts::action_timeout())); - } - - void ShutdownChannelToSlave() { - // Since |event_| is manual-reset, calling this multiple times is OK. - WaitForChannelToSlave(); - - test_io_thread_->PostTaskAndWait( - FROM_HERE, - base::Bind(&ChannelManager::ShutdownChannelOnIOThread, - base::Unretained(master_ipc_support_->channel_manager()), - slave_id_)); - } - - embedder::ScopedPlatformHandle PassSlavePlatformHandle() { - return std::move(slave_platform_handle_); - } - - const ConnectionIdentifier& connection_id() const { return connection_id_; } - - private: - base::TestIOThread* const test_io_thread_; - IPCSupport* const master_ipc_support_; - const ConnectionIdentifier connection_id_; - // The master's message pipe dispatcher. - scoped_refptr<MessagePipeDispatcher> message_pipe_; - ProcessIdentifier slave_id_; - base::WaitableEvent event_; - embedder::ScopedPlatformHandle slave_platform_handle_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(TestSlaveConnection); -}; - -// Encapsulates the state of a slave. (Note, however, that we share a -// |PlatformSupport| and an I/O thread.) -class TestSlave { - public: - // Note: Before destruction, |ShutdownIPCSupport()| must be called. - TestSlave(embedder::PlatformSupport* platform_support, - base::TestIOThread* test_io_thread, - embedder::ScopedPlatformHandle platform_handle) - : test_io_thread_(test_io_thread), - slave_ipc_support_(platform_support, - embedder::ProcessType::SLAVE, - &slave_process_delegate_, - test_io_thread->task_runner(), - std::move(platform_handle)), - event_(true, false) {} - ~TestSlave() {} - - // After this is called, |ShutdownChannelToMaster()| must be called (possibly - // after |WaitForChannelToMaster()|) before destruction. - scoped_refptr<MessagePipeDispatcher> ConnectToMaster( - const ConnectionIdentifier& connection_id) { - ProcessIdentifier master_id = kInvalidProcessIdentifier; - scoped_refptr<MessagePipeDispatcher> mp = - slave_ipc_support_.ConnectToMaster( - connection_id, - base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event_)), - nullptr, &master_id); - EXPECT_TRUE(mp); - EXPECT_EQ(kMasterProcessIdentifier, master_id); - return mp; - } - - void WaitForChannelToMaster() { - EXPECT_TRUE(event_.TimedWait(TestTimeouts::action_timeout())); - } - - void ShutdownChannelToMaster() { - // Since |event_| is manual-reset, calling this multiple times is OK. - WaitForChannelToMaster(); - - test_io_thread_->PostTaskAndWait( - FROM_HERE, - base::Bind(&ChannelManager::ShutdownChannelOnIOThread, - base::Unretained(slave_ipc_support_.channel_manager()), - kMasterProcessIdentifier)); - } - - // No other methods may be called after this. - void ShutdownIPCSupport() { - test_io_thread_->PostTaskAndWait( - FROM_HERE, base::Bind(&IPCSupport::ShutdownOnIOThread, - base::Unretained(&slave_ipc_support_))); - } - - private: - base::TestIOThread* const test_io_thread_; - TestSlaveProcessDelegate slave_process_delegate_; - IPCSupport slave_ipc_support_; - base::WaitableEvent event_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(TestSlave); -}; - -// Encapsulates both the master and slave sides for each slave. -class TestSlaveSetup { - public: - TestSlaveSetup(embedder::SimplePlatformSupport* platform_support, - base::TestIOThread* test_io_thread, - TestMasterProcessDelegate* master_process_delegate, - IPCSupport* master_ipc_support) - : platform_support_(platform_support), - test_io_thread_(test_io_thread), - master_process_delegate_(master_process_delegate), - master_ipc_support_(master_ipc_support) {} - ~TestSlaveSetup() { - CHECK(!slave_connection_); - CHECK(!slave_); - } - - void Init() { - // Set up the master side entirely before the slave side, since this - // simulates what's likely to happen "in reality" more closely. - slave_connection_.reset( - new TestSlaveConnection(test_io_thread_, master_ipc_support_)); - master_mp_ = slave_connection_->ConnectToSlave(); - - slave_.reset(new TestSlave(platform_support_, test_io_thread_, - slave_connection_->PassSlavePlatformHandle())); - slave_mp_ = slave_->ConnectToMaster(slave_connection_->connection_id()); - } - - void TestConnection() { - TestWriteReadMessage(master_mp_, slave_mp_); - TestWriteReadMessage(slave_mp_, master_mp_); - } - - scoped_refptr<MessagePipeDispatcher> PassMasterMessagePipe() { - return std::move(master_mp_); - } - - scoped_refptr<MessagePipeDispatcher> PassSlaveMessagePipe() { - return std::move(slave_mp_); - } - - void Shutdown() { - if (master_mp_) { - master_mp_->Close(); - master_mp_ = nullptr; - } - if (slave_mp_) { - slave_mp_->Close(); - slave_mp_ = nullptr; - } - - slave_->ShutdownChannelToMaster(); - slave_->ShutdownIPCSupport(); - master_process_delegate_->TryWaitForOnSlaveDisconnect(); - slave_connection_->ShutdownChannelToSlave(); - - slave_.reset(); - slave_connection_.reset(); - } - - TestSlaveConnection* slave_connection() { return slave_connection_.get(); } - // Note: To close the master message pipe, use |PassMasterMessagePipe()|. - MessagePipeDispatcher* master_mp() { return master_mp_.get(); } - - TestSlave* slave() { return slave_.get(); } - // Note: To close the slave message pipe, use |PassSlaveMessagePipe()|. - MessagePipeDispatcher* slave_mp() { return slave_mp_.get(); } - - private: - embedder::SimplePlatformSupport* const platform_support_; - base::TestIOThread* const test_io_thread_; - TestMasterProcessDelegate* const master_process_delegate_; - IPCSupport* const master_ipc_support_; - - scoped_ptr<TestSlaveConnection> slave_connection_; - scoped_refptr<MessagePipeDispatcher> master_mp_; - - scoped_ptr<TestSlave> slave_; - scoped_refptr<MessagePipeDispatcher> slave_mp_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(TestSlaveSetup); -}; - -class IPCSupportTest : public testing::Test { - public: - // Note: Run master process delegate methods on the I/O thread. - IPCSupportTest() - : test_io_thread_(base::TestIOThread::kAutoStart), - master_ipc_support_(&platform_support_, - embedder::ProcessType::MASTER, - &master_process_delegate_, - test_io_thread_.task_runner(), - embedder::ScopedPlatformHandle()) {} - ~IPCSupportTest() override {} - - scoped_ptr<TestSlaveSetup> SetupSlave() { - scoped_ptr<TestSlaveSetup> s( - new TestSlaveSetup(&platform_support_, &test_io_thread_, - &master_process_delegate_, &master_ipc_support_)); - s->Init(); - return s; - } - - void ShutdownMasterIPCSupport() { - test_io_thread_.PostTaskAndWait( - FROM_HERE, base::Bind(&IPCSupport::ShutdownOnIOThread, - base::Unretained(&master_ipc_support_))); - } - - embedder::SimplePlatformSupport& platform_support() { - return platform_support_; - } - base::TestIOThread& test_io_thread() { return test_io_thread_; } - TestMasterProcessDelegate& master_process_delegate() { - return master_process_delegate_; - } - IPCSupport& master_ipc_support() { return master_ipc_support_; } - - private: - base::MessageLoop message_loop_; - embedder::SimplePlatformSupport platform_support_; - base::TestIOThread test_io_thread_; - - // All tests require a master. - TestMasterProcessDelegate master_process_delegate_; - IPCSupport master_ipc_support_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(IPCSupportTest); -}; - -using MessagePipeDispatcherPair = - std::pair<scoped_refptr<MessagePipeDispatcher>, - scoped_refptr<MessagePipeDispatcher>>; -MessagePipeDispatcherPair CreateMessagePipe() { - MessagePipeDispatcherPair rv; - rv.first = MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - rv.second = MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); - rv.first->Init(mp, 0); - rv.second->Init(mp, 1); - return rv; -} - -TEST_F(IPCSupportTest, MasterSlave) { - scoped_ptr<TestSlaveSetup> s(SetupSlave()); - - s->TestConnection(); - - // Don't need the message pipe anymore. - s->PassMasterMessagePipe()->Close(); - s->PassSlaveMessagePipe()->Close(); - - // A message was sent through the message pipe, |Channel|s must have been - // established on both sides. The events have thus almost certainly been - // signalled, but we'll wait just to be sure. - s->slave_connection()->WaitForChannelToSlave(); - s->slave()->WaitForChannelToMaster(); - - s->Shutdown(); - - ShutdownMasterIPCSupport(); -} - -// Simulates a master and two slaves. Initially, there are just message pipes -// from the master to the slaves. This tests the master creating a message pipe -// and sending an end to each slave, which should result in a direct connection -// between the two slaves (TODO(vtl): this part doesn't happen yet). -// TODO(vtl): There are various other similar scenarios we'll need to test, so -// we'll need to factor out some of the code. -// TODO(vtl): In this scenario, we can't test the intermediary (the master) -// going away. -TEST_F(IPCSupportTest, ConnectTwoSlaves) { - scoped_ptr<TestSlaveSetup> s1(SetupSlave()); - scoped_ptr<TestSlaveSetup> s2(SetupSlave()); - s1->TestConnection(); - s2->TestConnection(); - - // Make a message pipe (logically "in" the master) and send one end to each - // slave. - MessagePipeDispatcherPair send_mp = CreateMessagePipe(); - scoped_refptr<MessagePipeDispatcher> slave1_received_mp = - SendMessagePipeDispatcher(s1->master_mp(), s1->slave_mp(), send_mp.first); - scoped_refptr<MessagePipeDispatcher> slave2_received_mp = - SendMessagePipeDispatcher(s2->master_mp(), s2->slave_mp(), - send_mp.second); - - // These should be connected. - TestWriteReadMessage(slave1_received_mp, slave2_received_mp); - TestWriteReadMessage(slave2_received_mp, slave1_received_mp); - - s1->PassMasterMessagePipe()->Close(); - s2->PassMasterMessagePipe()->Close(); - s1->PassSlaveMessagePipe()->Close(); - s2->PassSlaveMessagePipe()->Close(); - - // They should still be connected. - TestWriteReadMessage(slave1_received_mp, slave2_received_mp); - TestWriteReadMessage(slave2_received_mp, slave1_received_mp); - - slave1_received_mp->Close(); - slave2_received_mp->Close(); - - s1->Shutdown(); - s2->Shutdown(); - - ShutdownMasterIPCSupport(); -} - -// Like |ConnectTwoSlaves|, but does it twice, to test reusing a connection. -TEST_F(IPCSupportTest, ConnectTwoSlavesTwice) { - scoped_ptr<TestSlaveSetup> s1(SetupSlave()); - scoped_ptr<TestSlaveSetup> s2(SetupSlave()); - s1->TestConnection(); - s2->TestConnection(); - - MessagePipeDispatcherPair send_mp1 = CreateMessagePipe(); - scoped_refptr<MessagePipeDispatcher> slave1_received_mp1 = - SendMessagePipeDispatcher(s1->master_mp(), s1->slave_mp(), - send_mp1.first); - scoped_refptr<MessagePipeDispatcher> slave2_received_mp1 = - SendMessagePipeDispatcher(s2->master_mp(), s2->slave_mp(), - send_mp1.second); - - MessagePipeDispatcherPair send_mp2 = CreateMessagePipe(); - scoped_refptr<MessagePipeDispatcher> slave1_received_mp2 = - SendMessagePipeDispatcher(s1->master_mp(), s1->slave_mp(), - send_mp2.first); - scoped_refptr<MessagePipeDispatcher> slave2_received_mp2 = - SendMessagePipeDispatcher(s2->master_mp(), s2->slave_mp(), - send_mp2.second); - - s1->PassMasterMessagePipe()->Close(); - s2->PassMasterMessagePipe()->Close(); - s1->PassSlaveMessagePipe()->Close(); - s2->PassSlaveMessagePipe()->Close(); - - TestWriteReadMessage(slave1_received_mp1, slave2_received_mp1); - TestWriteReadMessage(slave2_received_mp1, slave1_received_mp1); - - TestWriteReadMessage(slave1_received_mp2, slave2_received_mp2); - TestWriteReadMessage(slave2_received_mp2, slave1_received_mp2); - - slave1_received_mp1->Close(); - slave2_received_mp1->Close(); - - TestWriteReadMessage(slave1_received_mp2, slave2_received_mp2); - TestWriteReadMessage(slave2_received_mp2, slave1_received_mp2); - - slave1_received_mp2->Close(); - slave2_received_mp2->Close(); - - s1->Shutdown(); - s2->Shutdown(); - - ShutdownMasterIPCSupport(); -} - -// Creates a message pipe in the slave, which sends both ends (in separate -// messages) to the master. -TEST_F(IPCSupportTest, SlavePassBackToMaster) { - scoped_ptr<TestSlaveSetup> s(SetupSlave()); - - s->TestConnection(); - - // Make a message pipe (logically "in" the slave) and send both ends - // (separately) to the master. - MessagePipeDispatcherPair send_mp = CreateMessagePipe(); - scoped_refptr<MessagePipeDispatcher> received_mp1 = - SendMessagePipeDispatcher(s->slave_mp(), s->master_mp(), send_mp.first); - - TestWriteReadMessage(received_mp1, send_mp.second); - TestWriteReadMessage(send_mp.second, received_mp1); - - scoped_refptr<MessagePipeDispatcher> received_mp2 = - SendMessagePipeDispatcher(s->slave_mp(), s->master_mp(), send_mp.second); - - s->PassMasterMessagePipe()->Close(); - s->PassSlaveMessagePipe()->Close(); - - TestWriteReadMessage(received_mp1, received_mp2); - TestWriteReadMessage(received_mp2, received_mp1); - - s->Shutdown(); - - // These should still be connected. - // TODO(vtl): This is not yet implemented, thus will fail here! - // TestWriteReadMessage(received_mp1, received_mp2); - // TestWriteReadMessage(received_mp2, received_mp1); - - received_mp1->Close(); - received_mp2->Close(); - - ShutdownMasterIPCSupport(); -} - -} // namespace - -// Note: This test isn't in an anonymous namespace, since it needs to be -// friended by |IPCSupport|. -TEST_F(IPCSupportTest, MasterSlaveInternal) { - ConnectionIdentifier connection_id = - master_ipc_support().GenerateConnectionIdentifier(); - - embedder::PlatformChannelPair channel_pair; - ProcessIdentifier slave_id = kInvalidProcessIdentifier; - embedder::ScopedPlatformHandle master_second_platform_handle = - master_ipc_support().ConnectToSlaveInternal( - connection_id, nullptr, channel_pair.PassServerHandle(), &slave_id); - ASSERT_TRUE(master_second_platform_handle.is_valid()); - EXPECT_NE(slave_id, kInvalidProcessIdentifier); - EXPECT_NE(slave_id, kMasterProcessIdentifier); - - TestSlaveProcessDelegate slave_process_delegate; - // Note: Run process delegate methods on the I/O thread. - IPCSupport slave_ipc_support( - &platform_support(), embedder::ProcessType::SLAVE, - &slave_process_delegate, test_io_thread().task_runner(), - channel_pair.PassClientHandle()); - - embedder::ScopedPlatformHandle slave_second_platform_handle = - slave_ipc_support.ConnectToMasterInternal(connection_id); - ASSERT_TRUE(slave_second_platform_handle.is_valid()); - - // Write an 'x' through the master's end. - size_t n = 0; - EXPECT_TRUE(mojo::test::BlockingWrite(master_second_platform_handle.get(), - "x", 1, &n)); - EXPECT_EQ(1u, n); - - // Read it from the slave's end. - char c = '\0'; - n = 0; - EXPECT_TRUE( - mojo::test::BlockingRead(slave_second_platform_handle.get(), &c, 1, &n)); - EXPECT_EQ(1u, n); - EXPECT_EQ('x', c); - - test_io_thread().PostTaskAndWait( - FROM_HERE, base::Bind(&IPCSupport::ShutdownOnIOThread, - base::Unretained(&slave_ipc_support))); - - master_process_delegate().TryWaitForOnSlaveDisconnect(); - - ShutdownMasterIPCSupport(); -} - -// This is a true multiprocess version of IPCSupportTest.MasterSlaveInternal. -// Note: This test isn't in an anonymous namespace, since it needs to be -// friended by |IPCSupport|. -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -// TODO(vtl): I'm guessing this is true of this test too? -#define MAYBE_MultiprocessMasterSlaveInternal \ - DISABLED_MultiprocessMasterSlaveInternal -#else -#define MAYBE_MultiprocessMasterSlaveInternal MultiprocessMasterSlaveInternal -#endif // defined(OS_ANDROID) -TEST_F(IPCSupportTest, MAYBE_MultiprocessMasterSlaveInternal) { - ConnectionIdentifier connection_id = - master_ipc_support().GenerateConnectionIdentifier(); - mojo::test::MultiprocessTestHelper multiprocess_test_helper; - ProcessIdentifier slave_id = kInvalidProcessIdentifier; - embedder::ScopedPlatformHandle second_platform_handle = - master_ipc_support().ConnectToSlaveInternal( - connection_id, nullptr, - std::move(multiprocess_test_helper.server_platform_handle), - &slave_id); - ASSERT_TRUE(second_platform_handle.is_valid()); - EXPECT_NE(slave_id, kInvalidProcessIdentifier); - EXPECT_NE(slave_id, kMasterProcessIdentifier); - - multiprocess_test_helper.StartChildWithExtraSwitch( - "MultiprocessMasterSlaveInternal", kConnectionIdFlag, - connection_id.ToString()); - - // We write a '?'. The slave should write a '!' in response. - size_t n = 0; - EXPECT_TRUE( - mojo::test::BlockingWrite(second_platform_handle.get(), "?", 1, &n)); - EXPECT_EQ(1u, n); - - char c = '\0'; - n = 0; - EXPECT_TRUE( - mojo::test::BlockingRead(second_platform_handle.get(), &c, 1, &n)); - EXPECT_EQ(1u, n); - EXPECT_EQ('!', c); - - master_process_delegate().TryWaitForOnSlaveDisconnect(); - EXPECT_TRUE(multiprocess_test_helper.WaitForChildTestShutdown()); - - ShutdownMasterIPCSupport(); -} - -MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessMasterSlaveInternal) { - embedder::ScopedPlatformHandle client_platform_handle = - std::move(mojo::test::MultiprocessTestHelper::client_platform_handle); - ASSERT_TRUE(client_platform_handle.is_valid()); - - embedder::SimplePlatformSupport platform_support; - base::MessageLoop message_loop; - base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); - TestSlaveProcessDelegate slave_process_delegate; - // Note: Run process delegate methods on the I/O thread. - IPCSupport ipc_support(&platform_support, embedder::ProcessType::SLAVE, - &slave_process_delegate, test_io_thread.task_runner(), - std::move(client_platform_handle)); - - const base::CommandLine& command_line = - *base::CommandLine::ForCurrentProcess(); - ASSERT_TRUE(command_line.HasSwitch(kConnectionIdFlag)); - bool ok = false; - ConnectionIdentifier connection_id = ConnectionIdentifier::FromString( - command_line.GetSwitchValueASCII(kConnectionIdFlag), &ok); - ASSERT_TRUE(ok); - - embedder::ScopedPlatformHandle second_platform_handle = - ipc_support.ConnectToMasterInternal(connection_id); - ASSERT_TRUE(second_platform_handle.is_valid()); - - // The master should write a '?'. We'll write a '!' in response. - char c = '\0'; - size_t n = 0; - EXPECT_TRUE( - mojo::test::BlockingRead(second_platform_handle.get(), &c, 1, &n)); - EXPECT_EQ(1u, n); - EXPECT_EQ('?', c); - - n = 0; - EXPECT_TRUE( - mojo::test::BlockingWrite(second_platform_handle.get(), "!", 1, &n)); - EXPECT_EQ(1u, n); - - test_io_thread.PostTaskAndWait(FROM_HERE, - base::Bind(&IPCSupport::ShutdownOnIOThread, - base::Unretained(&ipc_support))); -} - -// TODO(vtl): Also test the case of the master "dying" before the slave. (The -// slave should get OnMasterDisconnect(), which we currently don't test.) - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/local_data_pipe_impl.cc b/third_party/mojo/src/mojo/edk/system/local_data_pipe_impl.cc deleted file mode 100644 index 415d186..0000000 --- a/third_party/mojo/src/mojo/edk/system/local_data_pipe_impl.cc +++ /dev/null @@ -1,433 +0,0 @@ -// Copyright 2013 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. - -// TODO(vtl): I currently potentially overflow in doing index calculations. -// E.g., |start_index_| and |current_num_bytes_| fit into a |uint32_t|, but -// their sum may not. This is bad and poses a security risk. (We're currently -// saved by the limit on capacity -- the maximum size of the buffer, checked in -// |DataPipe::ValidateOptions()|, is currently sufficiently small.) - -#include "third_party/mojo/src/mojo/edk/system/local_data_pipe_impl.h" - -#include <string.h> -#include <algorithm> -#include <limits> -#include <utility> - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "third_party/mojo/src/mojo/edk/system/channel.h" -#include "third_party/mojo/src/mojo/edk/system/configuration.h" -#include "third_party/mojo/src/mojo/edk/system/data_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit_queue.h" -#include "third_party/mojo/src/mojo/edk/system/remote_consumer_data_pipe_impl.h" -#include "third_party/mojo/src/mojo/edk/system/remote_producer_data_pipe_impl.h" - -namespace mojo { -namespace system { - -// Assert some things about some things defined in data_pipe_impl.h (don't make -// the assertions there, to avoid including message_in_transit.h). -static_assert(MOJO_ALIGNOF(SerializedDataPipeConsumerDispatcher) == - MessageInTransit::kMessageAlignment, - "Wrong alignment"); -static_assert(sizeof(SerializedDataPipeConsumerDispatcher) % - MessageInTransit::kMessageAlignment == - 0, - "Wrong size"); - -LocalDataPipeImpl::LocalDataPipeImpl() - : start_index_(0), current_num_bytes_(0) { - // Note: |buffer_| is lazily allocated, since a common case will be that one - // of the handles is immediately passed off to another process. -} - -LocalDataPipeImpl::~LocalDataPipeImpl() { -} - -void LocalDataPipeImpl::ProducerClose() { - // If the consumer is still open and we still have data, we have to keep the - // buffer around. Currently, we won't free it even if it empties later. (We - // could do this -- requiring a check on every read -- but that seems to be - // optimizing for the uncommon case.) - if (!consumer_open() || !current_num_bytes_) { - // Note: There can only be a two-phase *read* (by the consumer) if we still - // have data. - DCHECK(!consumer_in_two_phase_read()); - DestroyBuffer(); - } -} - -MojoResult LocalDataPipeImpl::ProducerWriteData( - UserPointer<const void> elements, - UserPointer<uint32_t> num_bytes, - uint32_t max_num_bytes_to_write, - uint32_t min_num_bytes_to_write) { - DCHECK_EQ(max_num_bytes_to_write % element_num_bytes(), 0u); - DCHECK_EQ(min_num_bytes_to_write % element_num_bytes(), 0u); - DCHECK_GT(max_num_bytes_to_write, 0u); - DCHECK_GE(max_num_bytes_to_write, min_num_bytes_to_write); - DCHECK(consumer_open()); - - if (min_num_bytes_to_write > capacity_num_bytes() - current_num_bytes_) { - // Don't return "should wait" since you can't wait for a specified amount - // of data. - return MOJO_RESULT_OUT_OF_RANGE; - } - - size_t num_bytes_to_write = - std::min(static_cast<size_t>(max_num_bytes_to_write), - capacity_num_bytes() - current_num_bytes_); - if (num_bytes_to_write == 0) - return MOJO_RESULT_SHOULD_WAIT; - - // The amount we can write in our first copy. - size_t num_bytes_to_write_first = - std::min(num_bytes_to_write, GetMaxNumBytesToWrite()); - // Do the first (and possibly only) copy. - size_t first_write_index = - (start_index_ + current_num_bytes_) % capacity_num_bytes(); - EnsureBuffer(); - elements.GetArray(buffer_.get() + first_write_index, - num_bytes_to_write_first); - - if (num_bytes_to_write_first < num_bytes_to_write) { - // The "second write index" is zero. - elements.At(num_bytes_to_write_first) - .GetArray(buffer_.get(), num_bytes_to_write - num_bytes_to_write_first); - } - - current_num_bytes_ += num_bytes_to_write; - DCHECK_LE(current_num_bytes_, capacity_num_bytes()); - num_bytes.Put(static_cast<uint32_t>(num_bytes_to_write)); - return MOJO_RESULT_OK; -} - -MojoResult LocalDataPipeImpl::ProducerBeginWriteData( - UserPointer<void*> buffer, - UserPointer<uint32_t> buffer_num_bytes) { - DCHECK(consumer_open()); - - // The index we need to start writing at. - size_t write_index = - (start_index_ + current_num_bytes_) % capacity_num_bytes(); - - size_t max_num_bytes_to_write = GetMaxNumBytesToWrite(); - // Don't go into a two-phase write if there's no room. - if (max_num_bytes_to_write == 0) - return MOJO_RESULT_SHOULD_WAIT; - - EnsureBuffer(); - buffer.Put(buffer_.get() + write_index); - buffer_num_bytes.Put(static_cast<uint32_t>(max_num_bytes_to_write)); - set_producer_two_phase_max_num_bytes_written( - static_cast<uint32_t>(max_num_bytes_to_write)); - return MOJO_RESULT_OK; -} - -MojoResult LocalDataPipeImpl::ProducerEndWriteData(uint32_t num_bytes_written) { - DCHECK_LE(num_bytes_written, producer_two_phase_max_num_bytes_written()); - DCHECK_EQ(num_bytes_written % element_num_bytes(), 0u); - current_num_bytes_ += num_bytes_written; - DCHECK_LE(current_num_bytes_, capacity_num_bytes()); - set_producer_two_phase_max_num_bytes_written(0); - return MOJO_RESULT_OK; -} - -HandleSignalsState LocalDataPipeImpl::ProducerGetHandleSignalsState() const { - HandleSignalsState rv; - if (consumer_open()) { - if (current_num_bytes_ < capacity_num_bytes() && - !producer_in_two_phase_write()) - rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_WRITABLE; - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_WRITABLE; - } else { - rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED; - } - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED; - return rv; -} - -void LocalDataPipeImpl::ProducerStartSerialize(Channel* channel, - size_t* max_size, - size_t* max_platform_handles) { - *max_size = sizeof(SerializedDataPipeProducerDispatcher) + - channel->GetSerializedEndpointSize(); - *max_platform_handles = 0; -} - -bool LocalDataPipeImpl::ProducerEndSerialize( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) { - SerializedDataPipeProducerDispatcher* s = - static_cast<SerializedDataPipeProducerDispatcher*>(destination); - s->validated_options = validated_options(); - void* destination_for_endpoint = static_cast<char*>(destination) + - sizeof(SerializedDataPipeProducerDispatcher); - - if (!consumer_open()) { - // Case 1: The consumer is closed. - s->consumer_num_bytes = static_cast<uint32_t>(-1); - *actual_size = sizeof(SerializedDataPipeProducerDispatcher); - return true; - } - - // Case 2: The consumer isn't closed. We'll replace ourselves with a - // |RemoteProducerDataPipeImpl|. - - DCHECK(current_num_bytes_ < std::numeric_limits<uint32_t>::max()); - s->consumer_num_bytes = static_cast<uint32_t>(current_num_bytes_); - // Note: We don't use |port|. - scoped_refptr<ChannelEndpoint> channel_endpoint = - channel->SerializeEndpointWithLocalPeer(destination_for_endpoint, nullptr, - owner(), 0); - // Note: Keep |*this| alive until the end of this method, to make things - // slightly easier on ourselves. - scoped_ptr<DataPipeImpl> self(owner()->ReplaceImplNoLock(make_scoped_ptr( - new RemoteProducerDataPipeImpl(channel_endpoint.get(), std::move(buffer_), - start_index_, current_num_bytes_)))); - - *actual_size = sizeof(SerializedDataPipeProducerDispatcher) + - channel->GetSerializedEndpointSize(); - return true; -} - -void LocalDataPipeImpl::ConsumerClose() { - // If the producer is around and in a two-phase write, we have to keep the - // buffer around. (We then don't free it until the producer is closed. This - // could be rectified, but again seems like optimizing for the uncommon case.) - if (!producer_open() || !producer_in_two_phase_write()) - DestroyBuffer(); - current_num_bytes_ = 0; -} - -MojoResult LocalDataPipeImpl::ConsumerReadData(UserPointer<void> elements, - UserPointer<uint32_t> num_bytes, - uint32_t max_num_bytes_to_read, - uint32_t min_num_bytes_to_read, - bool peek) { - DCHECK_EQ(max_num_bytes_to_read % element_num_bytes(), 0u); - DCHECK_EQ(min_num_bytes_to_read % element_num_bytes(), 0u); - DCHECK_GT(max_num_bytes_to_read, 0u); - - if (min_num_bytes_to_read > current_num_bytes_) { - // Don't return "should wait" since you can't wait for a specified amount of - // data. - return producer_open() ? MOJO_RESULT_OUT_OF_RANGE - : MOJO_RESULT_FAILED_PRECONDITION; - } - - size_t num_bytes_to_read = - std::min(static_cast<size_t>(max_num_bytes_to_read), current_num_bytes_); - if (num_bytes_to_read == 0) { - return producer_open() ? MOJO_RESULT_SHOULD_WAIT - : MOJO_RESULT_FAILED_PRECONDITION; - } - - // The amount we can read in our first copy. - size_t num_bytes_to_read_first = - std::min(num_bytes_to_read, GetMaxNumBytesToRead()); - elements.PutArray(buffer_.get() + start_index_, num_bytes_to_read_first); - - if (num_bytes_to_read_first < num_bytes_to_read) { - // The "second read index" is zero. - elements.At(num_bytes_to_read_first) - .PutArray(buffer_.get(), num_bytes_to_read - num_bytes_to_read_first); - } - - if (!peek) - MarkDataAsConsumed(num_bytes_to_read); - num_bytes.Put(static_cast<uint32_t>(num_bytes_to_read)); - return MOJO_RESULT_OK; -} - -MojoResult LocalDataPipeImpl::ConsumerDiscardData( - UserPointer<uint32_t> num_bytes, - uint32_t max_num_bytes_to_discard, - uint32_t min_num_bytes_to_discard) { - DCHECK_EQ(max_num_bytes_to_discard % element_num_bytes(), 0u); - DCHECK_EQ(min_num_bytes_to_discard % element_num_bytes(), 0u); - DCHECK_GT(max_num_bytes_to_discard, 0u); - - if (min_num_bytes_to_discard > current_num_bytes_) { - // Don't return "should wait" since you can't wait for a specified amount of - // data. - return producer_open() ? MOJO_RESULT_OUT_OF_RANGE - : MOJO_RESULT_FAILED_PRECONDITION; - } - - // Be consistent with other operations; error if no data available. - if (current_num_bytes_ == 0) { - return producer_open() ? MOJO_RESULT_SHOULD_WAIT - : MOJO_RESULT_FAILED_PRECONDITION; - } - - size_t num_bytes_to_discard = std::min( - static_cast<size_t>(max_num_bytes_to_discard), current_num_bytes_); - MarkDataAsConsumed(num_bytes_to_discard); - num_bytes.Put(static_cast<uint32_t>(num_bytes_to_discard)); - return MOJO_RESULT_OK; -} - -MojoResult LocalDataPipeImpl::ConsumerQueryData( - UserPointer<uint32_t> num_bytes) { - // Note: This cast is safe, since the capacity fits into a |uint32_t|. - num_bytes.Put(static_cast<uint32_t>(current_num_bytes_)); - return MOJO_RESULT_OK; -} - -MojoResult LocalDataPipeImpl::ConsumerBeginReadData( - UserPointer<const void*> buffer, - UserPointer<uint32_t> buffer_num_bytes) { - size_t max_num_bytes_to_read = GetMaxNumBytesToRead(); - // Don't go into a two-phase read if there's no data. - if (max_num_bytes_to_read == 0) { - return producer_open() ? MOJO_RESULT_SHOULD_WAIT - : MOJO_RESULT_FAILED_PRECONDITION; - } - - buffer.Put(buffer_.get() + start_index_); - buffer_num_bytes.Put(static_cast<uint32_t>(max_num_bytes_to_read)); - set_consumer_two_phase_max_num_bytes_read( - static_cast<uint32_t>(max_num_bytes_to_read)); - return MOJO_RESULT_OK; -} - -MojoResult LocalDataPipeImpl::ConsumerEndReadData(uint32_t num_bytes_read) { - DCHECK_LE(num_bytes_read, consumer_two_phase_max_num_bytes_read()); - DCHECK_EQ(num_bytes_read % element_num_bytes(), 0u); - DCHECK_LE(start_index_ + num_bytes_read, capacity_num_bytes()); - MarkDataAsConsumed(num_bytes_read); - set_consumer_two_phase_max_num_bytes_read(0); - return MOJO_RESULT_OK; -} - -HandleSignalsState LocalDataPipeImpl::ConsumerGetHandleSignalsState() const { - HandleSignalsState rv; - if (current_num_bytes_ > 0) { - if (!consumer_in_two_phase_read()) - rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_READABLE; - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_READABLE; - } else if (producer_open()) { - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_READABLE; - } - if (!producer_open()) - rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED; - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED; - return rv; -} - -void LocalDataPipeImpl::ConsumerStartSerialize(Channel* channel, - size_t* max_size, - size_t* max_platform_handles) { - *max_size = sizeof(SerializedDataPipeConsumerDispatcher) + - channel->GetSerializedEndpointSize(); - *max_platform_handles = 0; -} - -bool LocalDataPipeImpl::ConsumerEndSerialize( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) { - SerializedDataPipeConsumerDispatcher* s = - static_cast<SerializedDataPipeConsumerDispatcher*>(destination); - s->validated_options = validated_options(); - void* destination_for_endpoint = static_cast<char*>(destination) + - sizeof(SerializedDataPipeConsumerDispatcher); - - size_t old_num_bytes = current_num_bytes_; - MessageInTransitQueue message_queue; - ConvertDataToMessages(buffer_.get(), &start_index_, ¤t_num_bytes_, - &message_queue); - - if (!producer_open()) { - // Case 1: The producer is closed. - DestroyBuffer(); - channel->SerializeEndpointWithClosedPeer(destination_for_endpoint, - &message_queue); - *actual_size = sizeof(SerializedDataPipeConsumerDispatcher) + - channel->GetSerializedEndpointSize(); - return true; - } - - // Case 2: The producer isn't closed. We'll replace ourselves with a - // |RemoteConsumerDataPipeImpl|. - - // Note: We don't use |port|. - scoped_refptr<ChannelEndpoint> channel_endpoint = - channel->SerializeEndpointWithLocalPeer(destination_for_endpoint, - &message_queue, owner(), 0); - // Note: Keep |*this| alive until the end of this method, to make things - // slightly easier on ourselves. - scoped_ptr<DataPipeImpl> self(owner()->ReplaceImplNoLock(make_scoped_ptr( - new RemoteConsumerDataPipeImpl(channel_endpoint.get(), old_num_bytes, - std::move(buffer_), start_index_)))); - - *actual_size = sizeof(SerializedDataPipeConsumerDispatcher) + - channel->GetSerializedEndpointSize(); - return true; -} - -bool LocalDataPipeImpl::OnReadMessage(unsigned /*port*/, - MessageInTransit* /*message*/) { - NOTREACHED(); - return false; -} - -void LocalDataPipeImpl::OnDetachFromChannel(unsigned /*port*/) { - NOTREACHED(); -} - -void LocalDataPipeImpl::EnsureBuffer() { - DCHECK(producer_open()); - if (buffer_) - return; - buffer_.reset(static_cast<char*>( - base::AlignedAlloc(capacity_num_bytes(), - GetConfiguration().data_pipe_buffer_alignment_bytes))); -} - -void LocalDataPipeImpl::DestroyBuffer() { -#ifndef NDEBUG - // Scribble on the buffer to help detect use-after-frees. (This also helps the - // unit test detect certain bugs without needing ASAN or similar.) - if (buffer_) - memset(buffer_.get(), 0xcd, capacity_num_bytes()); -#endif - buffer_.reset(); - start_index_ = 0; - current_num_bytes_ = 0; -} - -size_t LocalDataPipeImpl::GetMaxNumBytesToWrite() { - size_t next_index = start_index_ + current_num_bytes_; - if (next_index >= capacity_num_bytes()) { - next_index %= capacity_num_bytes(); - DCHECK_GE(start_index_, next_index); - DCHECK_EQ(start_index_ - next_index, - capacity_num_bytes() - current_num_bytes_); - return start_index_ - next_index; - } - return capacity_num_bytes() - next_index; -} - -size_t LocalDataPipeImpl::GetMaxNumBytesToRead() { - if (start_index_ + current_num_bytes_ > capacity_num_bytes()) - return capacity_num_bytes() - start_index_; - return current_num_bytes_; -} - -void LocalDataPipeImpl::MarkDataAsConsumed(size_t num_bytes) { - DCHECK_LE(num_bytes, current_num_bytes_); - start_index_ += num_bytes; - start_index_ %= capacity_num_bytes(); - current_num_bytes_ -= num_bytes; -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/local_data_pipe_impl.h b/third_party/mojo/src/mojo/edk/system/local_data_pipe_impl.h deleted file mode 100644 index c144204..0000000 --- a/third_party/mojo/src/mojo/edk/system/local_data_pipe_impl.h +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_LOCAL_DATA_PIPE_IMPL_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_LOCAL_DATA_PIPE_IMPL_H_ - -#include "base/memory/aligned_memory.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/data_pipe_impl.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -class MessageInTransitQueue; - -// |LocalDataPipeImpl| is a subclass that "implements" |DataPipe| for data pipes -// whose producer and consumer are both local. See |DataPipeImpl| for more -// details. -class MOJO_SYSTEM_IMPL_EXPORT LocalDataPipeImpl final : public DataPipeImpl { - public: - LocalDataPipeImpl(); - ~LocalDataPipeImpl() override; - - private: - // |DataPipeImpl| implementation: - void ProducerClose() override; - MojoResult ProducerWriteData(UserPointer<const void> elements, - UserPointer<uint32_t> num_bytes, - uint32_t max_num_bytes_to_write, - uint32_t min_num_bytes_to_write) override; - MojoResult ProducerBeginWriteData( - UserPointer<void*> buffer, - UserPointer<uint32_t> buffer_num_bytes) override; - MojoResult ProducerEndWriteData(uint32_t num_bytes_written) override; - HandleSignalsState ProducerGetHandleSignalsState() const override; - void ProducerStartSerialize(Channel* channel, - size_t* max_size, - size_t* max_platform_handles) override; - bool ProducerEndSerialize( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) override; - void ConsumerClose() override; - MojoResult ConsumerReadData(UserPointer<void> elements, - UserPointer<uint32_t> num_bytes, - uint32_t max_num_bytes_to_read, - uint32_t min_num_bytes_to_read, - bool peek) override; - MojoResult ConsumerDiscardData(UserPointer<uint32_t> num_bytes, - uint32_t max_num_bytes_to_discard, - uint32_t min_num_bytes_to_discard) override; - MojoResult ConsumerQueryData(UserPointer<uint32_t> num_bytes) override; - MojoResult ConsumerBeginReadData( - UserPointer<const void*> buffer, - UserPointer<uint32_t> buffer_num_bytes) override; - MojoResult ConsumerEndReadData(uint32_t num_bytes_read) override; - HandleSignalsState ConsumerGetHandleSignalsState() const override; - void ConsumerStartSerialize(Channel* channel, - size_t* max_size, - size_t* max_platform_handles) override; - bool ConsumerEndSerialize( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) override; - bool OnReadMessage(unsigned port, MessageInTransit* message) override; - void OnDetachFromChannel(unsigned port) override; - - void EnsureBuffer(); - void DestroyBuffer(); - - // Get the maximum (single) write/read size right now (in number of elements); - // result fits in a |uint32_t|. - size_t GetMaxNumBytesToWrite(); - size_t GetMaxNumBytesToRead(); - - // Marks the given number of bytes as consumed/discarded. |num_bytes| must be - // no greater than |current_num_bytes_|. - void MarkDataAsConsumed(size_t num_bytes); - - scoped_ptr<char, base::AlignedFreeDeleter> buffer_; - // Circular buffer. - size_t start_index_; - size_t current_num_bytes_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(LocalDataPipeImpl); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_LOCAL_DATA_PIPE_IMPL_H_ diff --git a/third_party/mojo/src/mojo/edk/system/local_message_pipe_endpoint.cc b/third_party/mojo/src/mojo/edk/system/local_message_pipe_endpoint.cc deleted file mode 100644 index c9614bc..0000000 --- a/third_party/mojo/src/mojo/edk/system/local_message_pipe_endpoint.cc +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/local_message_pipe_endpoint.h" - -#include <string.h> -#include <utility> - -#include "base/logging.h" -#include "third_party/mojo/src/mojo/edk/system/dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit.h" - -namespace mojo { -namespace system { - -LocalMessagePipeEndpoint::LocalMessagePipeEndpoint( - MessageInTransitQueue* message_queue) - : is_open_(true), is_peer_open_(true) { - if (message_queue) - message_queue_.Swap(message_queue); -} - -LocalMessagePipeEndpoint::~LocalMessagePipeEndpoint() { - DCHECK(!is_open_); - DCHECK(message_queue_.IsEmpty()); // Should be implied by not being open. -} - -MessagePipeEndpoint::Type LocalMessagePipeEndpoint::GetType() const { - return kTypeLocal; -} - -bool LocalMessagePipeEndpoint::OnPeerClose() { - DCHECK(is_open_); - DCHECK(is_peer_open_); - - HandleSignalsState old_state = GetHandleSignalsState(); - is_peer_open_ = false; - HandleSignalsState new_state = GetHandleSignalsState(); - - if (!new_state.equals(old_state)) - awakable_list_.AwakeForStateChange(new_state); - - return true; -} - -void LocalMessagePipeEndpoint::EnqueueMessage( - scoped_ptr<MessageInTransit> message) { - DCHECK(is_open_); - DCHECK(is_peer_open_); - - bool was_empty = message_queue_.IsEmpty(); - message_queue_.AddMessage(std::move(message)); - if (was_empty) - awakable_list_.AwakeForStateChange(GetHandleSignalsState()); -} - -void LocalMessagePipeEndpoint::Close() { - DCHECK(is_open_); - is_open_ = false; - message_queue_.Clear(); -} - -void LocalMessagePipeEndpoint::CancelAllAwakables() { - DCHECK(is_open_); - awakable_list_.CancelAll(); -} - -MojoResult LocalMessagePipeEndpoint::ReadMessage( - UserPointer<void> bytes, - UserPointer<uint32_t> num_bytes, - DispatcherVector* dispatchers, - uint32_t* num_dispatchers, - MojoReadMessageFlags flags) { - DCHECK(is_open_); - DCHECK(!dispatchers || dispatchers->empty()); - - const uint32_t max_bytes = num_bytes.IsNull() ? 0 : num_bytes.Get(); - const uint32_t max_num_dispatchers = num_dispatchers ? *num_dispatchers : 0; - - if (message_queue_.IsEmpty()) { - return is_peer_open_ ? MOJO_RESULT_SHOULD_WAIT - : MOJO_RESULT_FAILED_PRECONDITION; - } - - // TODO(vtl): If |flags & MOJO_READ_MESSAGE_FLAG_MAY_DISCARD|, we could pop - // and release the lock immediately. - bool enough_space = true; - MessageInTransit* message = message_queue_.PeekMessage(); - if (!num_bytes.IsNull()) - num_bytes.Put(message->num_bytes()); - if (message->num_bytes() <= max_bytes) - bytes.PutArray(message->bytes(), message->num_bytes()); - else - enough_space = false; - - if (DispatcherVector* queued_dispatchers = message->dispatchers()) { - if (num_dispatchers) - *num_dispatchers = static_cast<uint32_t>(queued_dispatchers->size()); - if (enough_space) { - if (queued_dispatchers->empty()) { - // Nothing to do. - } else if (queued_dispatchers->size() <= max_num_dispatchers) { - DCHECK(dispatchers); - dispatchers->swap(*queued_dispatchers); - } else { - enough_space = false; - } - } - } else { - if (num_dispatchers) - *num_dispatchers = 0; - } - - message = nullptr; - - if (enough_space || (flags & MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)) { - message_queue_.DiscardMessage(); - - // Now it's empty, thus no longer readable. - if (message_queue_.IsEmpty()) { - // It's currently not possible to wait for non-readability, but we should - // do the state change anyway. - awakable_list_.AwakeForStateChange(GetHandleSignalsState()); - } - } - - if (!enough_space) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - - return MOJO_RESULT_OK; -} - -HandleSignalsState LocalMessagePipeEndpoint::GetHandleSignalsState() const { - HandleSignalsState rv; - if (!message_queue_.IsEmpty()) { - rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_READABLE; - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_READABLE; - } - if (is_peer_open_) { - rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_WRITABLE; - rv.satisfiable_signals |= - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE; - } else { - rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED; - } - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED; - return rv; -} - -MojoResult LocalMessagePipeEndpoint::AddAwakable( - Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state) { - DCHECK(is_open_); - - HandleSignalsState state = GetHandleSignalsState(); - if (state.satisfies(signals)) { - if (signals_state) - *signals_state = state; - return MOJO_RESULT_ALREADY_EXISTS; - } - if (!state.can_satisfy(signals)) { - if (signals_state) - *signals_state = state; - return MOJO_RESULT_FAILED_PRECONDITION; - } - - awakable_list_.Add(awakable, signals, context); - return MOJO_RESULT_OK; -} - -void LocalMessagePipeEndpoint::RemoveAwakable( - Awakable* awakable, - HandleSignalsState* signals_state) { - DCHECK(is_open_); - awakable_list_.Remove(awakable); - if (signals_state) - *signals_state = GetHandleSignalsState(); -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/local_message_pipe_endpoint.h b/third_party/mojo/src/mojo/edk/system/local_message_pipe_endpoint.h deleted file mode 100644 index c273631..0000000 --- a/third_party/mojo/src/mojo/edk/system/local_message_pipe_endpoint.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_LOCAL_MESSAGE_PIPE_ENDPOINT_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_LOCAL_MESSAGE_PIPE_ENDPOINT_H_ - -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/awakable_list.h" -#include "third_party/mojo/src/mojo/edk/system/handle_signals_state.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit_queue.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -class MOJO_SYSTEM_IMPL_EXPORT LocalMessagePipeEndpoint final - : public MessagePipeEndpoint { - public: - // If |message_queue| is non-null, its contents will be taken as the queue of - // (already-received) messages. - explicit LocalMessagePipeEndpoint( - MessageInTransitQueue* message_queue = nullptr); - ~LocalMessagePipeEndpoint() override; - - // |MessagePipeEndpoint| implementation: - Type GetType() const override; - bool OnPeerClose() override; - void EnqueueMessage(scoped_ptr<MessageInTransit> message) override; - - // There's a dispatcher for |LocalMessagePipeEndpoint|s, so we have to - // implement/override these: - void Close() override; - void CancelAllAwakables() override; - MojoResult ReadMessage(UserPointer<void> bytes, - UserPointer<uint32_t> num_bytes, - DispatcherVector* dispatchers, - uint32_t* num_dispatchers, - MojoReadMessageFlags flags) override; - HandleSignalsState GetHandleSignalsState() const override; - MojoResult AddAwakable(Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state) override; - void RemoveAwakable(Awakable* awakable, - HandleSignalsState* signals_state) override; - - // This is only to be used by |MessagePipe|: - MessageInTransitQueue* message_queue() { return &message_queue_; } - - private: - bool is_open_; - bool is_peer_open_; - - // Queue of incoming messages. - MessageInTransitQueue message_queue_; - AwakableList awakable_list_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(LocalMessagePipeEndpoint); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_LOCAL_MESSAGE_PIPE_ENDPOINT_H_ diff --git a/third_party/mojo/src/mojo/edk/system/mapping_table.cc b/third_party/mojo/src/mojo/edk/system/mapping_table.cc deleted file mode 100644 index fab79c3..0000000 --- a/third_party/mojo/src/mojo/edk/system/mapping_table.cc +++ /dev/null @@ -1,48 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/mapping_table.h" - -#include "base/logging.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_shared_buffer.h" -#include "third_party/mojo/src/mojo/edk/system/configuration.h" - -namespace mojo { -namespace system { - -MappingTable::MappingTable() { -} - -MappingTable::~MappingTable() { - // This should usually not be reached (the only instance should be owned by - // the singleton |Core|, which lives forever), except in tests. -} - -MojoResult MappingTable::AddMapping( - scoped_ptr<embedder::PlatformSharedBufferMapping> mapping) { - DCHECK(mapping); - - if (address_to_mapping_map_.size() >= - GetConfiguration().max_mapping_table_sze) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - - uintptr_t address = reinterpret_cast<uintptr_t>(mapping->GetBase()); - DCHECK(address_to_mapping_map_.find(address) == - address_to_mapping_map_.end()); - address_to_mapping_map_[address] = mapping.release(); - return MOJO_RESULT_OK; -} - -MojoResult MappingTable::RemoveMapping(uintptr_t address) { - AddressToMappingMap::iterator it = address_to_mapping_map_.find(address); - if (it == address_to_mapping_map_.end()) - return MOJO_RESULT_INVALID_ARGUMENT; - embedder::PlatformSharedBufferMapping* mapping_to_delete = it->second; - address_to_mapping_map_.erase(it); - delete mapping_to_delete; - return MOJO_RESULT_OK; -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/mapping_table.h b/third_party/mojo/src/mojo/edk/system/mapping_table.h deleted file mode 100644 index cc74aca..0000000 --- a/third_party/mojo/src/mojo/edk/system/mapping_table.h +++ /dev/null @@ -1,62 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MAPPING_TABLE_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MAPPING_TABLE_H_ - -#include <stdint.h> - -#include <vector> - -#include "base/containers/hash_tables.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { - -namespace embedder { -class PlatformSharedBufferMapping; -} - -namespace system { - -class Core; - -// Test-only function (defined/used in embedder/test_embedder.cc). Declared here -// so it can be friended. -namespace internal { -bool ShutdownCheckNoLeaks(Core*); -} - -// This class provides the (global) table of memory mappings (owned by |Core|), -// which maps mapping base addresses to |PlatformSharedBufferMapping|s. -// -// This class is NOT thread-safe; locking is left to |Core|. -class MOJO_SYSTEM_IMPL_EXPORT MappingTable { - public: - MappingTable(); - ~MappingTable(); - - // Tries to add a mapping. (Takes ownership of the mapping in all cases; on - // failure, it will be destroyed.) - MojoResult AddMapping( - scoped_ptr<embedder::PlatformSharedBufferMapping> mapping); - MojoResult RemoveMapping(uintptr_t address); - - private: - friend bool internal::ShutdownCheckNoLeaks(Core*); - - using AddressToMappingMap = - base::hash_map<uintptr_t, embedder::PlatformSharedBufferMapping*>; - AddressToMappingMap address_to_mapping_map_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(MappingTable); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MAPPING_TABLE_H_ diff --git a/third_party/mojo/src/mojo/edk/system/master_connection_manager.cc b/third_party/mojo/src/mojo/edk/system/master_connection_manager.cc deleted file mode 100644 index ced54ec0..0000000 --- a/third_party/mojo/src/mojo/edk/system/master_connection_manager.cc +++ /dev/null @@ -1,741 +0,0 @@ -// Copyright 2015 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 "third_party/mojo/src/mojo/edk/system/master_connection_manager.h" - -#include <utility> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "base/synchronization/waitable_event.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/master_process_delegate.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle_vector.h" -#include "third_party/mojo/src/mojo/edk/system/connection_manager_messages.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit.h" -#include "third_party/mojo/src/mojo/edk/system/raw_channel.h" -#include "third_party/mojo/src/mojo/edk/system/transport_data.h" - -namespace mojo { -namespace system { - -namespace { - -const ProcessIdentifier kFirstSlaveProcessIdentifier = 2; - -static_assert(kMasterProcessIdentifier != kInvalidProcessIdentifier, - "Bad master process identifier"); -static_assert(kFirstSlaveProcessIdentifier != kInvalidProcessIdentifier, - "Bad first slave process identifier"); -static_assert(kMasterProcessIdentifier != kFirstSlaveProcessIdentifier, - "Master and first slave process identifiers are the same"); - -MessageInTransit::Subtype ConnectionManagerResultToMessageInTransitSubtype( - ConnectionManager::Result result) { - switch (result) { - case ConnectionManager::Result::FAILURE: - return MessageInTransit::Subtype::CONNECTION_MANAGER_ACK_FAILURE; - case ConnectionManager::Result::SUCCESS: - return MessageInTransit::Subtype::CONNECTION_MANAGER_ACK_SUCCESS; - case ConnectionManager::Result::SUCCESS_CONNECT_SAME_PROCESS: - return MessageInTransit::Subtype:: - CONNECTION_MANAGER_ACK_SUCCESS_CONNECT_SAME_PROCESS; - case ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION: - return MessageInTransit::Subtype:: - CONNECTION_MANAGER_ACK_SUCCESS_CONNECT_NEW_CONNECTION; - case ConnectionManager::Result::SUCCESS_CONNECT_REUSE_CONNECTION: - return MessageInTransit::Subtype:: - CONNECTION_MANAGER_ACK_SUCCESS_CONNECT_REUSE_CONNECTION; - } - NOTREACHED(); - return MessageInTransit::Subtype::CONNECTION_MANAGER_ACK_FAILURE; -} - -} // namespace - -// MasterConnectionManager::Helper --------------------------------------------- - -// |MasterConnectionManager::Helper| is not thread-safe, and must only be used -// on its |owner_|'s private thread. -class MOJO_SYSTEM_IMPL_EXPORT MasterConnectionManager::Helper final - : public RawChannel::Delegate { - public: - Helper(MasterConnectionManager* owner, - ProcessIdentifier process_identifier, - embedder::SlaveInfo slave_info, - embedder::ScopedPlatformHandle platform_handle); - ~Helper() override; - - void Init(); - embedder::SlaveInfo Shutdown(); - - private: - // |RawChannel::Delegate| methods: - void OnReadMessage( - const MessageInTransit::View& message_view, - embedder::ScopedPlatformHandleVectorPtr platform_handles) override; - void OnError(Error error) override; - - // Handles an error that's fatal to this object. Note that this probably - // results in |Shutdown()| being called (in the nested context) and then this - // object being destroyed. - void FatalError(); - - MasterConnectionManager* const owner_; - const ProcessIdentifier process_identifier_; - embedder::SlaveInfo const slave_info_; - scoped_ptr<RawChannel> raw_channel_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(Helper); -}; - -MasterConnectionManager::Helper::Helper( - MasterConnectionManager* owner, - ProcessIdentifier process_identifier, - embedder::SlaveInfo slave_info, - embedder::ScopedPlatformHandle platform_handle) - : owner_(owner), - process_identifier_(process_identifier), - slave_info_(slave_info), - raw_channel_(RawChannel::Create(std::move(platform_handle))) {} - -MasterConnectionManager::Helper::~Helper() { - DCHECK(!raw_channel_); -} - -void MasterConnectionManager::Helper::Init() { - raw_channel_->Init(this); -} - -embedder::SlaveInfo MasterConnectionManager::Helper::Shutdown() { - raw_channel_->Shutdown(); - raw_channel_.reset(); - return slave_info_; -} - -void MasterConnectionManager::Helper::OnReadMessage( - const MessageInTransit::View& message_view, - embedder::ScopedPlatformHandleVectorPtr platform_handles) { - if (message_view.type() != MessageInTransit::Type::CONNECTION_MANAGER) { - LOG(ERROR) << "Invalid message type " << message_view.type(); - FatalError(); // WARNING: This destroys us. - return; - } - - // Currently, all the messages simply have a |ConnectionIdentifier| as data. - if (message_view.num_bytes() != sizeof(ConnectionIdentifier)) { - LOG(ERROR) << "Invalid message size " << message_view.num_bytes(); - FatalError(); // WARNING: This destroys us. - return; - } - - // And none of them should have any platform handles attached. - if (message_view.transport_data_buffer()) { - LOG(ERROR) << "Invalid message with transport data"; - FatalError(); // WARNING: This destroys us. - return; - } - - const ConnectionIdentifier* connection_id = - reinterpret_cast<const ConnectionIdentifier*>(message_view.bytes()); - Result result = Result::FAILURE; - // Note: It's important to fully zero-initialize |data|, including padding, - // since it'll be sent to another process. - ConnectionManagerAckSuccessConnectData data = {}; - embedder::ScopedPlatformHandle platform_handle; - uint32_t num_bytes = 0; - const void* bytes = nullptr; - switch (message_view.subtype()) { - case MessageInTransit::Subtype::CONNECTION_MANAGER_ALLOW_CONNECT: - result = owner_->AllowConnectImpl(process_identifier_, *connection_id) - ? Result::SUCCESS - : Result::FAILURE; - break; - case MessageInTransit::Subtype::CONNECTION_MANAGER_CANCEL_CONNECT: - result = owner_->CancelConnectImpl(process_identifier_, *connection_id) - ? Result::SUCCESS - : Result::FAILURE; - break; - case MessageInTransit::Subtype::CONNECTION_MANAGER_CONNECT: { - result = owner_->ConnectImpl(process_identifier_, *connection_id, - &data.peer_process_identifier, - &data.is_first, &platform_handle); - DCHECK_NE(result, Result::SUCCESS); - // Success acks for "connect" have the peer process identifier as data - // (and also a platform handle in the case of "new connection" -- handled - // further below). - if (result != Result::FAILURE) { - num_bytes = static_cast<uint32_t>(sizeof(data)); - bytes = &data; - } - break; - } - default: - LOG(ERROR) << "Invalid message subtype " << message_view.subtype(); - FatalError(); // WARNING: This destroys us. - return; - } - - scoped_ptr<MessageInTransit> response(new MessageInTransit( - MessageInTransit::Type::CONNECTION_MANAGER_ACK, - ConnectionManagerResultToMessageInTransitSubtype(result), num_bytes, - bytes)); - - if (result == Result::SUCCESS_CONNECT_NEW_CONNECTION) { - DCHECK_EQ(message_view.subtype(), - MessageInTransit::Subtype::CONNECTION_MANAGER_CONNECT); - DCHECK(platform_handle.is_valid()); - embedder::ScopedPlatformHandleVectorPtr platform_handles( - new embedder::PlatformHandleVector()); - platform_handles->push_back(platform_handle.release()); - response->SetTransportData(make_scoped_ptr( - new TransportData(std::move(platform_handles), - raw_channel_->GetSerializedPlatformHandleSize()))); - } else { - DCHECK(!platform_handle.is_valid()); - } - - if (!raw_channel_->WriteMessage(std::move(response))) { - LOG(ERROR) << "WriteMessage failed"; - FatalError(); // WARNING: This destroys us. - return; - } -} - -void MasterConnectionManager::Helper::OnError(Error /*error*/) { - // Every error (read or write) is fatal (for that particular connection). Read - // errors are fatal since no more commands will be received from that - // connection. Write errors are fatal since it is no longer possible to send - // responses. - FatalError(); // WARNING: This destroys us. -} - -void MasterConnectionManager::Helper::FatalError() { - owner_->OnError(process_identifier_); // WARNING: This destroys us. -} - -// MasterConnectionManager::PendingConnectInfo --------------------------------- - -struct MOJO_SYSTEM_IMPL_EXPORT MasterConnectionManager::PendingConnectInfo { - // States: - // - This is created upon a first "allow connect" (with |first| set - // immediately). We then wait for a second "allow connect". - // - After the second "allow connect" (and |second| is set), we wait for - // "connects" from both |first| and |second|. - // - We may then receive "connect" from either |first| or |second|, at which - // which point it remains to wait for "connect" from the other. - // I.e., the valid state transitions are: - // AWAITING_SECOND_ALLOW_CONNECT -> AWAITING_CONNECTS_FROM_BOTH - // -> {AWAITING_CONNECT_FROM_FIRST,AWAITING_CONNECT_FROM_SECOND} - enum class State { - AWAITING_SECOND_ALLOW_CONNECT, - AWAITING_CONNECTS_FROM_BOTH, - AWAITING_CONNECT_FROM_FIRST, - AWAITING_CONNECT_FROM_SECOND - }; - - explicit PendingConnectInfo(ProcessIdentifier first) - : state(State::AWAITING_SECOND_ALLOW_CONNECT), - first(first), - second(kInvalidProcessIdentifier) { - DCHECK_NE(first, kInvalidProcessIdentifier); - } - ~PendingConnectInfo() {} - - State state; - - ProcessIdentifier first; - ProcessIdentifier second; -}; - -// MasterConnectionManager::ProcessConnections --------------------------------- - -class MasterConnectionManager::ProcessConnections { - public: - enum class ConnectionStatus { NONE, PENDING, RUNNING }; - - ProcessConnections() {} - ~ProcessConnections() { - // TODO(vtl): Log a warning if there are connections pending? (This might be - // very spammy, since the |MasterConnectionManager| may have many - // |ProcessConnections|. - for (auto& p : process_connections_) - p.second.CloseIfNecessary(); - } - - // If |pending_platform_handle| is non-null and the status is |PENDING| this - // will "return"/pass the stored pending platform handle. Warning: In that - // case, this has the side effect of changing the state to |RUNNING|. - ConnectionStatus GetConnectionStatus( - ProcessIdentifier to_process_identifier, - embedder::ScopedPlatformHandle* pending_platform_handle) { - DCHECK(!pending_platform_handle || !pending_platform_handle->is_valid()); - - auto it = process_connections_.find(to_process_identifier); - if (it == process_connections_.end()) - return ConnectionStatus::NONE; - if (!it->second.is_valid()) - return ConnectionStatus::RUNNING; - // Pending: - if (pending_platform_handle) { - pending_platform_handle->reset(it->second); - it->second = embedder::PlatformHandle(); - } - return ConnectionStatus::PENDING; - } - - void AddConnection(ProcessIdentifier to_process_identifier, - ConnectionStatus status, - embedder::ScopedPlatformHandle pending_platform_handle) { - DCHECK(process_connections_.find(to_process_identifier) == - process_connections_.end()); - - if (status == ConnectionStatus::RUNNING) { - DCHECK(!pending_platform_handle.is_valid()); - process_connections_[to_process_identifier] = embedder::PlatformHandle(); - } else if (status == ConnectionStatus::PENDING) { - DCHECK(pending_platform_handle.is_valid()); - process_connections_[to_process_identifier] = - pending_platform_handle.release(); - } else { - NOTREACHED(); - } - } - - private: - base::hash_map<ProcessIdentifier, embedder::PlatformHandle> - process_connections_; // "Owns" any valid platform handles. - - MOJO_DISALLOW_COPY_AND_ASSIGN(ProcessConnections); -}; - -// MasterConnectionManager ----------------------------------------------------- - -MasterConnectionManager::MasterConnectionManager( - embedder::PlatformSupport* platform_support) - : ConnectionManager(platform_support), - master_process_delegate_(), - private_thread_("MasterConnectionManagerPrivateThread"), - next_process_identifier_(kFirstSlaveProcessIdentifier) { - connections_[kMasterProcessIdentifier] = new ProcessConnections(); -} - -MasterConnectionManager::~MasterConnectionManager() { - DCHECK(!delegate_thread_task_runner_); - DCHECK(!master_process_delegate_); - DCHECK(!private_thread_.message_loop()); - DCHECK(helpers_.empty()); - DCHECK(pending_connects_.empty()); -} - -void MasterConnectionManager::Init( - embedder::MasterProcessDelegate* master_process_delegate) { - DCHECK(master_process_delegate); - DCHECK(!delegate_thread_task_runner_); - DCHECK(!master_process_delegate_); - DCHECK(!private_thread_.message_loop()); - - delegate_thread_task_runner_ = base::MessageLoop::current()->task_runner(); - master_process_delegate_ = master_process_delegate; - CHECK(private_thread_.StartWithOptions( - base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); -} - -ProcessIdentifier MasterConnectionManager::AddSlave( - embedder::SlaveInfo slave_info, - embedder::ScopedPlatformHandle platform_handle) { - // We don't really care if |slave_info| is non-null or not. - DCHECK(platform_handle.is_valid()); - AssertNotOnPrivateThread(); - - ProcessIdentifier slave_process_identifier; - { - MutexLocker locker(&mutex_); - CHECK_NE(next_process_identifier_, kMasterProcessIdentifier); - slave_process_identifier = next_process_identifier_; - next_process_identifier_++; - DCHECK(connections_.find(slave_process_identifier) == connections_.end()); - connections_[slave_process_identifier] = new ProcessConnections(); - } - - // We have to wait for the task to be executed, in case someone calls - // |AddSlave()| followed immediately by |Shutdown()|. - base::WaitableEvent event(false, false); - private_thread_.message_loop()->PostTask( - FROM_HERE, - base::Bind(&MasterConnectionManager::AddSlaveOnPrivateThread, - base::Unretained(this), base::Unretained(slave_info), - base::Passed(&platform_handle), slave_process_identifier, - base::Unretained(&event))); - event.Wait(); - - return slave_process_identifier; -} - -ProcessIdentifier MasterConnectionManager::AddSlaveAndBootstrap( - embedder::SlaveInfo slave_info, - embedder::ScopedPlatformHandle platform_handle, - const ConnectionIdentifier& connection_id) { - ProcessIdentifier slave_process_identifier = - AddSlave(slave_info, std::move(platform_handle)); - - MutexLocker locker(&mutex_); - DCHECK(pending_connects_.find(connection_id) == pending_connects_.end()); - PendingConnectInfo* info = new PendingConnectInfo(kMasterProcessIdentifier); - info->state = PendingConnectInfo::State::AWAITING_CONNECTS_FROM_BOTH; - info->second = slave_process_identifier; - pending_connects_[connection_id] = info; - - return slave_process_identifier; -} - -void MasterConnectionManager::Shutdown() { - AssertNotOnPrivateThread(); - DCHECK(master_process_delegate_); - DCHECK(private_thread_.message_loop()); - - // The |Stop()| will actually finish all posted tasks. - private_thread_.message_loop()->PostTask( - FROM_HERE, base::Bind(&MasterConnectionManager::ShutdownOnPrivateThread, - base::Unretained(this))); - private_thread_.Stop(); - DCHECK(helpers_.empty()); - DCHECK(pending_connects_.empty()); - master_process_delegate_ = nullptr; - delegate_thread_task_runner_ = nullptr; -} - -bool MasterConnectionManager::AllowConnect( - const ConnectionIdentifier& connection_id) { - AssertNotOnPrivateThread(); - return AllowConnectImpl(kMasterProcessIdentifier, connection_id); -} - -bool MasterConnectionManager::CancelConnect( - const ConnectionIdentifier& connection_id) { - AssertNotOnPrivateThread(); - return CancelConnectImpl(kMasterProcessIdentifier, connection_id); -} - -ConnectionManager::Result MasterConnectionManager::Connect( - const ConnectionIdentifier& connection_id, - ProcessIdentifier* peer_process_identifier, - bool* is_first, - embedder::ScopedPlatformHandle* platform_handle) { - return ConnectImpl(kMasterProcessIdentifier, connection_id, - peer_process_identifier, is_first, platform_handle); -} - -bool MasterConnectionManager::AllowConnectImpl( - ProcessIdentifier process_identifier, - const ConnectionIdentifier& connection_id) { - DCHECK_NE(process_identifier, kInvalidProcessIdentifier); - - MutexLocker locker(&mutex_); - - auto it = pending_connects_.find(connection_id); - if (it == pending_connects_.end()) { - pending_connects_[connection_id] = - new PendingConnectInfo(process_identifier); - // TODO(vtl): Track process identifier -> pending connections also (so these - // can be removed efficiently if that process disconnects). - DVLOG(1) << "New pending connection ID " << connection_id.ToString() - << ": AllowConnect() from first process identifier " - << process_identifier; - return true; - } - - PendingConnectInfo* info = it->second; - if (info->state == PendingConnectInfo::State::AWAITING_SECOND_ALLOW_CONNECT) { - info->state = PendingConnectInfo::State::AWAITING_CONNECTS_FROM_BOTH; - info->second = process_identifier; - DVLOG(1) << "Pending connection ID " << connection_id.ToString() - << ": AllowConnect() from second process identifier " - << process_identifier; - return true; - } - - // Someone's behaving badly, but we don't know who (it might not be the - // caller). - LOG(ERROR) << "AllowConnect() from process " << process_identifier - << " for connection ID " << connection_id.ToString() - << " already in state " << static_cast<int>(info->state); - pending_connects_.erase(it); - delete info; - return false; -} - -bool MasterConnectionManager::CancelConnectImpl( - ProcessIdentifier process_identifier, - const ConnectionIdentifier& connection_id) { - DCHECK_NE(process_identifier, kInvalidProcessIdentifier); - - MutexLocker locker(&mutex_); - - auto it = pending_connects_.find(connection_id); - if (it == pending_connects_.end()) { - // Not necessarily the caller's fault, and not necessarily an error. - DVLOG(1) << "CancelConnect() from process " << process_identifier - << " for connection ID " << connection_id.ToString() - << " which is not (or no longer) pending"; - return true; - } - - PendingConnectInfo* info = it->second; - if (process_identifier != info->first && process_identifier != info->second) { - LOG(ERROR) << "CancelConnect() from process " << process_identifier - << " for connection ID " << connection_id.ToString() - << " which is neither connectee"; - return false; - } - - // Just erase it. The other side may also try to cancel, in which case it'll - // "fail" in the first if statement above (we assume that connection IDs never - // collide, so there's no need to carefully track both sides). - pending_connects_.erase(it); - delete info; - return true; -} - -ConnectionManager::Result MasterConnectionManager::ConnectImpl( - ProcessIdentifier process_identifier, - const ConnectionIdentifier& connection_id, - ProcessIdentifier* peer_process_identifier, - bool* is_first, - embedder::ScopedPlatformHandle* platform_handle) { - DCHECK_NE(process_identifier, kInvalidProcessIdentifier); - DCHECK(peer_process_identifier); - DCHECK(is_first); - DCHECK(platform_handle); - DCHECK(!platform_handle->is_valid()); // Not technically wrong, but unlikely. - - MutexLocker locker(&mutex_); - - auto it = pending_connects_.find(connection_id); - if (it == pending_connects_.end()) { - // Not necessarily the caller's fault. - LOG(ERROR) << "Connect() from process " << process_identifier - << " for connection ID " << connection_id.ToString() - << " which is not pending"; - return Result::FAILURE; - } - - PendingConnectInfo* info = it->second; - ProcessIdentifier peer; - if (info->state == PendingConnectInfo::State::AWAITING_CONNECTS_FROM_BOTH) { - if (process_identifier == info->first) { - info->state = PendingConnectInfo::State::AWAITING_CONNECT_FROM_SECOND; - peer = info->second; - } else if (process_identifier == info->second) { - info->state = PendingConnectInfo::State::AWAITING_CONNECT_FROM_FIRST; - peer = info->first; - } else { - LOG(ERROR) << "Connect() from process " << process_identifier - << " for connection ID " << connection_id.ToString() - << " which is neither connectee"; - return Result::FAILURE; - } - - DVLOG(1) << "Connection ID " << connection_id.ToString() - << ": first Connect() from process identifier " - << process_identifier; - *peer_process_identifier = peer; - *is_first = true; - return ConnectImplHelperNoLock(process_identifier, peer, platform_handle); - } - - // The remaining cases all result in |it| being removed from - // |pending_connects_| and deleting |info|. - pending_connects_.erase(it); - scoped_ptr<PendingConnectInfo> info_deleter(info); - - // |remaining_connectee| should be the same as |process_identifier|. - ProcessIdentifier remaining_connectee; - if (info->state == PendingConnectInfo::State::AWAITING_CONNECT_FROM_FIRST) { - remaining_connectee = info->first; - peer = info->second; - } else if (info->state == - PendingConnectInfo::State::AWAITING_CONNECT_FROM_SECOND) { - remaining_connectee = info->second; - peer = info->first; - } else { - // Someone's behaving badly, but we don't know who (it might not be the - // caller). - LOG(ERROR) << "Connect() from process " << process_identifier - << " for connection ID " << connection_id.ToString() - << " in state " << static_cast<int>(info->state); - return Result::FAILURE; - } - - if (process_identifier != remaining_connectee) { - LOG(ERROR) << "Connect() from process " << process_identifier - << " for connection ID " << connection_id.ToString() - << " which is not the remaining connectee"; - return Result::FAILURE; - } - - DVLOG(1) << "Connection ID " << connection_id.ToString() - << ": second Connect() from process identifier " - << process_identifier; - *peer_process_identifier = peer; - *is_first = false; - return ConnectImplHelperNoLock(process_identifier, peer, platform_handle); -} - -ConnectionManager::Result MasterConnectionManager::ConnectImplHelperNoLock( - ProcessIdentifier process_identifier, - ProcessIdentifier peer_process_identifier, - embedder::ScopedPlatformHandle* platform_handle) { - if (process_identifier == peer_process_identifier) { - platform_handle->reset(); - DVLOG(1) << "Connect: same process"; - return Result::SUCCESS_CONNECT_SAME_PROCESS; - } - - // We should know about the process identified by |process_identifier|. - DCHECK(connections_.find(process_identifier) != connections_.end()); - ProcessConnections* process_connections = connections_[process_identifier]; - // We should also know about the peer. - DCHECK(connections_.find(peer_process_identifier) != connections_.end()); - switch (process_connections->GetConnectionStatus(peer_process_identifier, - platform_handle)) { - case ProcessConnections::ConnectionStatus::NONE: { - // TODO(vtl): In the "second connect" case, this should never be reached - // (but it's not easy to DCHECK this invariant here). - process_connections->AddConnection( - peer_process_identifier, - ProcessConnections::ConnectionStatus::RUNNING, - embedder::ScopedPlatformHandle()); - embedder::PlatformChannelPair platform_channel_pair; - *platform_handle = platform_channel_pair.PassServerHandle(); - - connections_[peer_process_identifier]->AddConnection( - process_identifier, ProcessConnections::ConnectionStatus::PENDING, - platform_channel_pair.PassClientHandle()); - break; - } - case ProcessConnections::ConnectionStatus::PENDING: - DCHECK(connections_[peer_process_identifier]->GetConnectionStatus( - process_identifier, nullptr) == - ProcessConnections::ConnectionStatus::RUNNING); - break; - case ProcessConnections::ConnectionStatus::RUNNING: - // |process_identifier| already has a connection to - // |peer_process_identifier|, so it should reuse that. - platform_handle->reset(); - DVLOG(1) << "Connect: reuse connection"; - return Result::SUCCESS_CONNECT_REUSE_CONNECTION; - } - DCHECK(platform_handle->is_valid()); - DVLOG(1) << "Connect: new connection"; - return Result::SUCCESS_CONNECT_NEW_CONNECTION; -} - -void MasterConnectionManager::ShutdownOnPrivateThread() { - AssertOnPrivateThread(); - - if (!pending_connects_.empty()) { - DVLOG(1) << "Shutting down with connections pending"; - for (auto& p : pending_connects_) - delete p.second; - pending_connects_.clear(); - } - - for (auto& p : connections_) - delete p.second; - connections_.clear(); - - if (!helpers_.empty()) { - DVLOG(1) << "Shutting down with slaves still connected"; - for (auto& p : helpers_) { - embedder::SlaveInfo slave_info = p.second->Shutdown(); - delete p.second; - CallOnSlaveDisconnect(slave_info); - } - helpers_.clear(); - } -} - -void MasterConnectionManager::AddSlaveOnPrivateThread( - embedder::SlaveInfo slave_info, - embedder::ScopedPlatformHandle platform_handle, - ProcessIdentifier slave_process_identifier, - base::WaitableEvent* event) { - DCHECK(platform_handle.is_valid()); - DCHECK(event); - AssertOnPrivateThread(); - - scoped_ptr<Helper> helper(new Helper(this, slave_process_identifier, - slave_info, std::move(platform_handle))); - helper->Init(); - - DCHECK(helpers_.find(slave_process_identifier) == helpers_.end()); - helpers_[slave_process_identifier] = helper.release(); - - DVLOG(1) << "Added slave process identifier " << slave_process_identifier; - event->Signal(); -} - -void MasterConnectionManager::OnError(ProcessIdentifier process_identifier) { - DCHECK_NE(process_identifier, kInvalidProcessIdentifier); - AssertOnPrivateThread(); - - auto it = helpers_.find(process_identifier); - DCHECK(it != helpers_.end()); - Helper* helper = it->second; - embedder::SlaveInfo slave_info = helper->Shutdown(); - helpers_.erase(it); - delete helper; - - { - MutexLocker locker(&mutex_); - - // TODO(vtl): This isn't very efficient. - for (auto it = pending_connects_.begin(); it != pending_connects_.end();) { - if (it->second->first == process_identifier || - it->second->second == process_identifier) { - auto it_to_erase = it; - ++it; - delete it_to_erase->second; - pending_connects_.erase(it_to_erase); - } else { - ++it; - } - } - } - - CallOnSlaveDisconnect(slave_info); -} - -void MasterConnectionManager::CallOnSlaveDisconnect( - embedder::SlaveInfo slave_info) { - AssertOnPrivateThread(); - DCHECK(master_process_delegate_); - delegate_thread_task_runner_->PostTask( - FROM_HERE, base::Bind(&embedder::MasterProcessDelegate::OnSlaveDisconnect, - base::Unretained(master_process_delegate_), - base::Unretained(slave_info))); -} - -void MasterConnectionManager::AssertNotOnPrivateThread() const { - // This should only be called after |Init()| and before |Shutdown()|. (If not, - // the subsequent |DCHECK_NE()| is invalid, since the current thread may not - // have a message loop.) - DCHECK(private_thread_.message_loop()); - DCHECK_NE(base::MessageLoop::current(), private_thread_.message_loop()); -} - -void MasterConnectionManager::AssertOnPrivateThread() const { - // This should only be called after |Init()| and before |Shutdown()|. - DCHECK(private_thread_.message_loop()); - DCHECK_EQ(base::MessageLoop::current(), private_thread_.message_loop()); -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/master_connection_manager.h b/third_party/mojo/src/mojo/edk/system/master_connection_manager.h deleted file mode 100644 index 0ebad05..0000000 --- a/third_party/mojo/src/mojo/edk/system/master_connection_manager.h +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright 2015 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MASTER_CONNECTION_MANAGER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MASTER_CONNECTION_MANAGER_H_ - -#include <stdint.h> - -#include "base/containers/hash_tables.h" -#include "base/memory/ref_counted.h" -#include "base/threading/thread.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" -#include "third_party/mojo/src/mojo/edk/system/connection_manager.h" -#include "third_party/mojo/src/mojo/edk/system/mutex.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace base { -class TaskRunner; -class WaitableEvent; -} - -namespace mojo { - -namespace embedder { -class MasterProcessDelegate; -using SlaveInfo = void*; -} - -namespace system { - -// The |ConnectionManager| implementation for the master process. -// -// This class is thread-safe (except that no public methods may be called from -// its internal, private thread), with condition that |Init()| be called before -// anything else and |Shutdown()| be called before destruction (and no other -// public methods may be called during/after |Shutdown()|). -class MOJO_SYSTEM_IMPL_EXPORT MasterConnectionManager final - : public ConnectionManager { - public: - // Note: None of the public methods may be called from |private_thread_|. - - // |platform_support| must be valid and remain alive until after |Shutdown()| - // has completed. - explicit MasterConnectionManager(embedder::PlatformSupport* platform_support); - ~MasterConnectionManager() override; - - // No other methods may be called until after this has been called. - // |delegate_thread_task_runner| should be the task runner for the "delegate - // thread", on which |master_process_delegate|'s methods will be called. Both - // must stay alive at least until after |Shutdown()| has been called. - void Init(embedder::MasterProcessDelegate* master_process_delegate) - MOJO_NOT_THREAD_SAFE; - - // Adds a slave process and sets up/tracks a connection to that slave (using - // |platform_handle|). |slave_info| is used by the caller/implementation of - // |embedder::MasterProcessDelegate| to track this process. It must remain - // alive until the delegate's |OnSlaveDisconnect()| is called with it as the - // argument. |OnSlaveDisconnect()| will always be called for each slave, - // assuming proper shutdown. Returns the process identifier for the - // newly-added slave. - ProcessIdentifier AddSlave(embedder::SlaveInfo slave_info, - embedder::ScopedPlatformHandle platform_handle); - - // Like |AddSlave()|, but allows a connection to be bootstrapped: both the - // master and slave may call |Connect()| with |connection_id| immediately (as - // if both had already called |AllowConnect()|). |connection_id| must be - // unique (i.e., not previously used). - // TODO(vtl): Is |AddSlave()| really needed? (It's probably mostly useful for - // tests.) - ProcessIdentifier AddSlaveAndBootstrap( - embedder::SlaveInfo slave_info, - embedder::ScopedPlatformHandle platform_handle, - const ConnectionIdentifier& connection_id); - - // |ConnectionManager| methods: - void Shutdown() override MOJO_NOT_THREAD_SAFE; - bool AllowConnect(const ConnectionIdentifier& connection_id) override; - bool CancelConnect(const ConnectionIdentifier& connection_id) override; - Result Connect(const ConnectionIdentifier& connection_id, - ProcessIdentifier* peer_process_identifier, - bool* is_first, - embedder::ScopedPlatformHandle* platform_handle) override; - - private: - class Helper; - - // These should be thread-safe and may be called on any thread, including - // |private_thread_|: - bool AllowConnectImpl(ProcessIdentifier process_identifier, - const ConnectionIdentifier& connection_id); - bool CancelConnectImpl(ProcessIdentifier process_identifier, - const ConnectionIdentifier& connection_id); - Result ConnectImpl(ProcessIdentifier process_identifier, - const ConnectionIdentifier& connection_id, - ProcessIdentifier* peer_process_identifier, - bool* is_first, - embedder::ScopedPlatformHandle* platform_handle); - - // Helper for |ConnectImpl()|. This is called when the two process identifiers - // are known (and known to be valid), and all that remains is to determine the - // |Result| and provide a platform handle if appropriate. (This will never - // return |Result::FAILURE|.) - Result ConnectImplHelperNoLock( - ProcessIdentifier process_identifier, - ProcessIdentifier peer_process_identifier, - embedder::ScopedPlatformHandle* platform_handle) - MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // These should only be called on |private_thread_|: - void ShutdownOnPrivateThread() MOJO_NOT_THREAD_SAFE; - // Signals |*event| on completion. - void AddSlaveOnPrivateThread(embedder::SlaveInfo slave_info, - embedder::ScopedPlatformHandle platform_handle, - ProcessIdentifier slave_process_identifier, - base::WaitableEvent* event); - // Called by |Helper::OnError()|. - void OnError(ProcessIdentifier process_identifier); - // Posts a call to |master_process_delegate_->OnSlaveDisconnect()|. - void CallOnSlaveDisconnect(embedder::SlaveInfo slave_info); - - // Asserts that the current thread is *not* |private_thread_| (no-op if - // DCHECKs are not enabled). This should only be called while - // |private_thread_| is alive (i.e., after |Init()| but before |Shutdown()|). - void AssertNotOnPrivateThread() const; - - // Asserts that the current thread is |private_thread_| (no-op if DCHECKs are - // not enabled). This should only be called while |private_thread_| is alive - // (i.e., after |Init()| but before |Shutdown()|). - void AssertOnPrivateThread() const; - - // These are set in |Init()| before |private_thread_| exists and only cleared - // in |Shutdown()| after |private_thread_| is dead. Thus it's safe to "use" on - // |private_thread_|. (Note that |master_process_delegate_| may only be called - // from the delegate thread.) - scoped_refptr<base::TaskRunner> delegate_thread_task_runner_; - embedder::MasterProcessDelegate* master_process_delegate_; - - // This is a private I/O thread on which this class does the bulk of its work. - // It is started in |Init()| and terminated in |Shutdown()|. - base::Thread private_thread_; - - // The following members are only accessed on |private_thread_|: - base::hash_map<ProcessIdentifier, Helper*> helpers_; // Owns its values. - - // Note: |mutex_| is not needed in the constructor, |Init()|, - // |Shutdown()|/|ShutdownOnPrivateThread()|, or the destructor - Mutex mutex_; - - ProcessIdentifier next_process_identifier_ MOJO_GUARDED_BY(mutex_); - - // Stores information on pending calls to |AllowConnect()|/|Connect()| (or - // |CancelConnect()|, namely those for which at least one party has called - // |AllowConnect()| but both have not yet called |Connect()| (or - // |CancelConnect()|). - struct PendingConnectInfo; - base::hash_map<ConnectionIdentifier, PendingConnectInfo*> pending_connects_ - MOJO_GUARDED_BY(mutex_); // Owns its values. - - // A |ProcessConnections| stores information about connections "from" a given - // (fixed, implied) process "to" other processes. A connection may be not - // present, running (meaning that both sides have connected and been given - // platform handles to a connected "pipe"), or pending (meaning that the - // "from" side must still be given a platform handle). - class ProcessConnections; - // This is a map from "from" processes to its |ProcessConnections| (above). - base::hash_map<ProcessIdentifier, ProcessConnections*> connections_ - MOJO_GUARDED_BY(mutex_); // Owns its values. - - MOJO_DISALLOW_COPY_AND_ASSIGN(MasterConnectionManager); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MASTER_CONNECTION_MANAGER_H_ diff --git a/third_party/mojo/src/mojo/edk/system/memory.cc b/third_party/mojo/src/mojo/edk/system/memory.cc deleted file mode 100644 index 92bfd4e..0000000 --- a/third_party/mojo/src/mojo/edk/system/memory.cc +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/memory.h" - -#include <limits> - -#include "base/logging.h" -#include "build/build_config.h" - -namespace mojo { -namespace system { -namespace internal { - -template <size_t alignment> -bool IsAligned(const void* pointer) { - return reinterpret_cast<uintptr_t>(pointer) % alignment == 0; -} - -// MSVS (2010, 2013) sometimes (on the stack) aligns, e.g., |int64_t|s (for -// which |__alignof(int64_t)| is 8) to 4-byte boundaries. http://goo.gl/Y2n56T -#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS) -template <> -bool IsAligned<8>(const void* pointer) { - return reinterpret_cast<uintptr_t>(pointer) % 4 == 0; -} -#endif - -template <size_t size, size_t alignment> -void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer(const void* pointer) { - CHECK(pointer && IsAligned<alignment>(pointer)); -} - -// Explicitly instantiate the sizes we need. Add instantiations as needed. -template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<1, 1>(const void*); -template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<4, 4>(const void*); -template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<8, 4>(const void*); -template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<8, 8>(const void*); - -template <size_t size, size_t alignment> -void MOJO_SYSTEM_IMPL_EXPORT -CheckUserPointerWithCount(const void* pointer, size_t count) { - CHECK_LE(count, std::numeric_limits<size_t>::max() / size); - CHECK(count == 0 || (pointer && IsAligned<alignment>(pointer))); -} - -// Explicitly instantiate the sizes we need. Add instantiations as needed. -template void MOJO_SYSTEM_IMPL_EXPORT -CheckUserPointerWithCount<1, 1>(const void*, size_t); -template void MOJO_SYSTEM_IMPL_EXPORT -CheckUserPointerWithCount<4, 4>(const void*, size_t); -template void MOJO_SYSTEM_IMPL_EXPORT -CheckUserPointerWithCount<8, 4>(const void*, size_t); -template void MOJO_SYSTEM_IMPL_EXPORT -CheckUserPointerWithCount<8, 8>(const void*, size_t); - -template <size_t alignment> -void CheckUserPointerWithSize(const void* pointer, size_t size) { - // TODO(vtl): If running in kernel mode, do a full verification. For now, just - // check that it's non-null and aligned. (A faster user mode implementation is - // also possible if this check is skipped.) - CHECK(size == 0 || (!!pointer && internal::IsAligned<alignment>(pointer))); -} - -// Explicitly instantiate the sizes we need. Add instantiations as needed. -template void MOJO_SYSTEM_IMPL_EXPORT -CheckUserPointerWithSize<1>(const void*, size_t); -template void MOJO_SYSTEM_IMPL_EXPORT -CheckUserPointerWithSize<4>(const void*, size_t); -// Whereas the other |Check...()| functions are usually used with integral typs -// or arrays of integral types, this one is used with Options structs for which -// alignment has been explicitly been specified (using |MOJO_ALIGNAS()|), which -// MSVS *does* respect. -#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS) -template <> -void MOJO_SYSTEM_IMPL_EXPORT -CheckUserPointerWithSize<8>(const void* pointer, size_t size) { - CHECK(size == 0 || - (!!pointer && reinterpret_cast<uintptr_t>(pointer) % 8 == 0)); -} -#else -template void MOJO_SYSTEM_IMPL_EXPORT -CheckUserPointerWithSize<8>(const void*, size_t); -#endif - -} // namespace internal -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/memory.h b/third_party/mojo/src/mojo/edk/system/memory.h deleted file mode 100644 index 3e9f79a..0000000 --- a/third_party/mojo/src/mojo/edk/system/memory.h +++ /dev/null @@ -1,377 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MEMORY_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MEMORY_H_ - -#include <stddef.h> -#include <stdint.h> -#include <string.h> // For |memcpy()|. - -#include "base/memory/scoped_ptr.h" -#include "mojo/public/c/system/macros.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -namespace internal { - -// Removes |const| from |T| (available as |remove_const<T>::type|): -// TODO(vtl): Remove these once we have the C++11 |remove_const|. -template <typename T> -struct remove_const { - using type = T; -}; -template <typename T> -struct remove_const<const T> { - using type = T; -}; - -// Yields |(const) char| if |T| is |(const) void|, else |T|: -template <typename T> -struct VoidToChar { - using type = T; -}; -template <> -struct VoidToChar<void> { - using type = char; -}; -template <> -struct VoidToChar<const void> { - using type = const char; -}; - -// Checks (insofar as appropriate/possible) that |pointer| is a valid pointer to -// a buffer of the given size and alignment (both in bytes). -template <size_t size, size_t alignment> -void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer(const void* pointer); - -// Checks (insofar as appropriate/possible) that |pointer| is a valid pointer to -// a buffer of |count| elements of the given size and alignment (both in bytes). -template <size_t size, size_t alignment> -void MOJO_SYSTEM_IMPL_EXPORT -CheckUserPointerWithCount(const void* pointer, size_t count); - -// Checks (insofar as appropriate/possible) that |pointer| is a valid pointer to -// a buffer of the given size and alignment (both in bytes). -template <size_t alignment> -void MOJO_SYSTEM_IMPL_EXPORT -CheckUserPointerWithSize(const void* pointer, size_t size); - -} // namespace internal - -// Forward declarations so that they can be friended. -template <typename Type> -class UserPointerReader; -template <typename Type> -class UserPointerWriter; -template <typename Type> -class UserPointerReaderWriter; -template <class Options> -class UserOptionsReader; - -// Provides a convenient way to implicitly get null |UserPointer<Type>|s. -struct NullUserPointer {}; - -// Represents a user pointer to a single |Type| (which must be POD), for Mojo -// primitive parameters. -// -// Use a const |Type| for in parameters, and non-const |Type|s for out and -// in-out parameters (in which case the |Put()| method is available). -template <typename Type> -class UserPointer { - private: - using NonVoidType = typename internal::VoidToChar<Type>::type; - - public: - // Instead of explicitly using these constructors, you can often use - // |MakeUserPointer()| (or |NullUserPointer()| for null pointers). (The common - // exception is when you have, e.g., a |char*| and want to get a - // |UserPointer<void>|.) - UserPointer() : pointer_(nullptr) {} - explicit UserPointer(Type* pointer) : pointer_(pointer) {} - // Allow implicit conversion from the "null user pointer". - UserPointer(NullUserPointer) : pointer_(nullptr) {} - ~UserPointer() {} - - // Allow assignment from the "null user pointer". - UserPointer<Type>& operator=(NullUserPointer) { - pointer_ = nullptr; - return *this; - } - - // Allow conversion to a "non-const" |UserPointer|. - operator UserPointer<const Type>() const { - return UserPointer<const Type>(pointer_); - } - - bool IsNull() const { return !pointer_; } - - // "Reinterpret casts" to a |UserPointer<ToType>|. - template <typename ToType> - UserPointer<ToType> ReinterpretCast() const { - return UserPointer<ToType>(reinterpret_cast<ToType*>(pointer_)); - } - - // Checks that this pointer points to a valid |Type| in the same way as - // |Get()| and |Put()|. - // TODO(vtl): Logically, there should be separate read checks and write - // checks. - void Check() const { - internal::CheckUserPointer<sizeof(NonVoidType), MOJO_ALIGNOF(NonVoidType)>( - pointer_); - } - - // Checks that this pointer points to a valid array (of type |Type|, or just a - // buffer if |Type| is |void| or |const void|) of |count| elements (or bytes - // if |Type| is |void| or |const void|) in the same way as |GetArray()| and - // |PutArray()|. - // TODO(vtl): Logically, there should be separate read checks and write - // checks. - // TODO(vtl): Switch more things to use this. - void CheckArray(size_t count) const { - internal::CheckUserPointerWithCount<sizeof(NonVoidType), - MOJO_ALIGNOF(NonVoidType)>(pointer_, - count); - } - - // Gets the value (of type |Type|, or a |char| if |Type| is |void|) pointed to - // by this user pointer. Use this when you'd use the rvalue |*user_pointer|, - // but be aware that this may be costly -- so if the value will be used - // multiple times, you should save it. - // - // (We want to force a copy here, so return |Type| not |const Type&|.) - NonVoidType Get() const { - Check(); - internal::CheckUserPointer<sizeof(NonVoidType), MOJO_ALIGNOF(NonVoidType)>( - pointer_); - return *pointer_; - } - - // Gets an array (of type |Type|, or just a buffer if |Type| is |void| or - // |const void|) of |count| elements (or bytes if |Type| is |void| or |const - // void|) from the location pointed to by this user pointer. Use this when - // you'd do something like |memcpy(destination, user_pointer, count * - // sizeof(Type)|. - void GetArray(typename internal::remove_const<Type>::type* destination, - size_t count) const { - CheckArray(count); - memcpy(destination, pointer_, count * sizeof(NonVoidType)); - } - - // Puts a value (of type |Type|, or of type |char| if |Type| is |void|) to the - // location pointed to by this user pointer. Use this when you'd use the - // lvalue |*user_pointer|. Since this may be costly, you should avoid using - // this (for the same user pointer) more than once. - // - // Note: This |Put()| method is not valid when |T| is const, e.g., |const - // uint32_t|, but it's okay to include them so long as this template is only - // implicitly instantiated (see 14.7.1 of the C++11 standard) and not - // explicitly instantiated. (On implicit instantiation, only the declarations - // need be valid, not the definitions.) - // - // In C++11, we could do something like: - // template <typename _Type = Type> - // typename enable_if<!is_const<_Type>::value && - // !is_void<_Type>::value>::type Put( - // const _Type& value) { ... } - // (which obviously be correct), but C++03 doesn't allow default function - // template arguments. - void Put(const NonVoidType& value) { - Check(); - *pointer_ = value; - } - - // Puts an array (of type |Type|, or just a buffer if |Type| is |void|) with - // |count| elements (or bytes |Type| is |void|) to the location pointed to by - // this user pointer. Use this when you'd do something like - // |memcpy(user_pointer, source, count * sizeof(Type))|. - // - // Note: The same comments about the validity of |Put()| (except for the part - // about |void|) apply here. - void PutArray(const Type* source, size_t count) { - CheckArray(count); - memcpy(pointer_, source, count * sizeof(NonVoidType)); - } - - // Gets a |UserPointer| at offset |i| (in |Type|s) relative to this. - UserPointer At(size_t i) const { - return UserPointer( - static_cast<Type*>(static_cast<NonVoidType*>(pointer_) + i)); - } - - // Gets the value of the |UserPointer| as a |uintptr_t|. This should not be - // casted back to a pointer (and dereferenced), but may be used as a key for - // lookup or passed back to the user. - uintptr_t GetPointerValue() const { - return reinterpret_cast<uintptr_t>(pointer_); - } - - // These provides safe (read-only/write-only/read-and-write) access to a - // |UserPointer<Type>| (probably pointing to an array) using just an ordinary - // pointer (obtained via |GetPointer()|). - // - // The memory returned by |GetPointer()| may be a copy of the original user - // memory, but should be modified only if the user is intended to eventually - // see the change.) If any changes are made, |Commit()| should be called to - // guarantee that the changes are written back to user memory (it may be - // called multiple times). - // - // Note: These classes are designed to allow fast, unsafe implementations (in - // which |GetPointer()| just returns the user pointer) if desired. Thus if - // |Commit()| is *not* called, changes may or may not be made visible to the - // user. - // - // Use these classes in the following way: - // - // MojoResult Core::PutFoos(UserPointer<const uint32_t> foos, - // uint32_t num_foos) { - // UserPointer<const uint32_t>::Reader foos_reader(foos, num_foos); - // return PutFoosImpl(foos_reader.GetPointer(), num_foos); - // } - // - // MojoResult Core::GetFoos(UserPointer<uint32_t> foos, - // uint32_t num_foos) { - // UserPointer<uint32_t>::Writer foos_writer(foos, num_foos); - // MojoResult rv = GetFoosImpl(foos.GetPointer(), num_foos); - // foos_writer.Commit(); - // return rv; - // } - // - // TODO(vtl): Possibly, since we're not really being safe, we should just not - // copy for Release builds. - using Reader = UserPointerReader<Type>; - using Writer = UserPointerWriter<Type>; - using ReaderWriter = UserPointerReaderWriter<Type>; - - private: - friend class UserPointerReader<Type>; - friend class UserPointerReader<const Type>; - friend class UserPointerWriter<Type>; - friend class UserPointerReaderWriter<Type>; - template <class Options> - friend class UserOptionsReader; - - Type* pointer_; - // Allow copy and assignment. -}; - -// Provides a convenient way to make a |UserPointer<Type>|. -template <typename Type> -inline UserPointer<Type> MakeUserPointer(Type* pointer) { - return UserPointer<Type>(pointer); -} - -// Implementation of |UserPointer<Type>::Reader|. -template <typename Type> -class UserPointerReader { - private: - using TypeNoConst = typename internal::remove_const<Type>::type; - - public: - // Note: If |count| is zero, |GetPointer()| will always return null. - UserPointerReader(UserPointer<const Type> user_pointer, size_t count) { - Init(user_pointer.pointer_, count, true); - } - UserPointerReader(UserPointer<TypeNoConst> user_pointer, size_t count) { - Init(user_pointer.pointer_, count, true); - } - - const Type* GetPointer() const { return buffer_.get(); } - - private: - template <class Options> - friend class UserOptionsReader; - - struct NoCheck {}; - UserPointerReader(NoCheck, - UserPointer<const Type> user_pointer, - size_t count) { - Init(user_pointer.pointer_, count, false); - } - - void Init(const Type* user_pointer, size_t count, bool check) { - if (count == 0) - return; - - if (check) { - internal::CheckUserPointerWithCount<sizeof(Type), MOJO_ALIGNOF(Type)>( - user_pointer, count); - } - buffer_.reset(new TypeNoConst[count]); - memcpy(buffer_.get(), user_pointer, count * sizeof(Type)); - } - - scoped_ptr<TypeNoConst[]> buffer_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(UserPointerReader); -}; - -// Implementation of |UserPointer<Type>::Writer|. -template <typename Type> -class UserPointerWriter { - public: - // Note: If |count| is zero, |GetPointer()| will always return null. - UserPointerWriter(UserPointer<Type> user_pointer, size_t count) - : user_pointer_(user_pointer), count_(count) { - if (count_ > 0) { - buffer_.reset(new Type[count_]); - memset(buffer_.get(), 0, count_ * sizeof(Type)); - } - } - - Type* GetPointer() const { return buffer_.get(); } - - void Commit() { - internal::CheckUserPointerWithCount<sizeof(Type), MOJO_ALIGNOF(Type)>( - user_pointer_.pointer_, count_); - memcpy(user_pointer_.pointer_, buffer_.get(), count_ * sizeof(Type)); - } - - private: - UserPointer<Type> user_pointer_; - size_t count_; - scoped_ptr<Type[]> buffer_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(UserPointerWriter); -}; - -// Implementation of |UserPointer<Type>::ReaderWriter|. -template <typename Type> -class UserPointerReaderWriter { - public: - // Note: If |count| is zero, |GetPointer()| will always return null. - UserPointerReaderWriter(UserPointer<Type> user_pointer, size_t count) - : user_pointer_(user_pointer), count_(count) { - if (count_ > 0) { - internal::CheckUserPointerWithCount<sizeof(Type), MOJO_ALIGNOF(Type)>( - user_pointer_.pointer_, count_); - buffer_.reset(new Type[count]); - memcpy(buffer_.get(), user_pointer.pointer_, count * sizeof(Type)); - } - } - - Type* GetPointer() const { return buffer_.get(); } - size_t GetCount() const { return count_; } - - void Commit() { - internal::CheckUserPointerWithCount<sizeof(Type), MOJO_ALIGNOF(Type)>( - user_pointer_.pointer_, count_); - memcpy(user_pointer_.pointer_, buffer_.get(), count_ * sizeof(Type)); - } - - private: - UserPointer<Type> user_pointer_; - size_t count_; - scoped_ptr<Type[]> buffer_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(UserPointerReaderWriter); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MEMORY_H_ diff --git a/third_party/mojo/src/mojo/edk/system/memory_unittest.cc b/third_party/mojo/src/mojo/edk/system/memory_unittest.cc deleted file mode 100644 index 90133e1..0000000 --- a/third_party/mojo/src/mojo/edk/system/memory_unittest.cc +++ /dev/null @@ -1,294 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/memory.h" - -#include <stddef.h> -#include <stdint.h> - -#include <limits> - -#include "mojo/public/c/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace system { -namespace { - -TEST(MemoryTest, Valid) { - char my_char; - int32_t my_int32; - int64_t my_int64_array[5] = {}; // Zero initialize. - - UserPointer<char> my_char_ptr(&my_char); - UserPointer<int32_t> my_int32_ptr(&my_int32); - UserPointer<int64_t> my_int64_array_ptr(my_int64_array); - - // |UserPointer<>::IsNull()|: - EXPECT_FALSE(my_char_ptr.IsNull()); - EXPECT_FALSE(my_int32_ptr.IsNull()); - EXPECT_FALSE(my_int64_array_ptr.IsNull()); - - // |UserPointer<>::Put()| and |UserPointer<>::Get()|: - my_char_ptr.Put('x'); - EXPECT_EQ('x', my_char); - EXPECT_EQ('x', my_char_ptr.Get()); - my_int32_ptr.Put(123); - EXPECT_EQ(123, my_int32); - EXPECT_EQ(123, my_int32_ptr.Get()); - my_int64_array_ptr.Put(456); - EXPECT_EQ(456, my_int64_array[0]); - EXPECT_EQ(456, my_int64_array_ptr.Get()); - - // |UserPointer<>::At()|, etc.: - my_int64_array_ptr.At(3).Put(789); - EXPECT_EQ(789, my_int64_array[3]); - { - // Copy construction: - UserPointer<int64_t> other(my_int64_array_ptr.At(3)); - EXPECT_FALSE(other.IsNull()); - EXPECT_EQ(789, other.Get()); - - // Assignment: - other = my_int64_array_ptr; - EXPECT_FALSE(other.IsNull()); - EXPECT_EQ(456, other.Get()); - - // Assignment to |NullUserPointer()|: - other = NullUserPointer(); - EXPECT_TRUE(other.IsNull()); - - // |MakeUserPointer()|: - other = MakeUserPointer(&my_int64_array[1]); - other.Put(-123); - EXPECT_EQ(-123, my_int64_array_ptr.At(1).Get()); - } - - // "const" |UserPointer<>|: - { - // Explicit constructor from |NullUserPointer()|: - UserPointer<const char> other((NullUserPointer())); - EXPECT_TRUE(other.IsNull()); - - // Conversion to "const": - other = my_char_ptr; - EXPECT_EQ('x', other.Get()); - } - - // Default constructor: - { - UserPointer<int32_t> other; - EXPECT_TRUE(other.IsNull()); - - other = my_int32_ptr; - other.Put(-456); - EXPECT_EQ(-456, my_int32_ptr.Get()); - } - - // |UserPointer<>::CheckArray()|: - my_int64_array_ptr.CheckArray(5); - - // |UserPointer<>::GetArray()|: - { - // From a "const" |UserPointer<>| (why not?): - UserPointer<const int64_t> other(my_int64_array_ptr); - int64_t array[3] = {1, 2, 3}; - other.At(1).GetArray(array, 3); - EXPECT_EQ(-123, array[0]); - EXPECT_EQ(0, array[1]); - EXPECT_EQ(789, array[2]); - } - - // |UserPointer<>::PutArray()|: - { - const int64_t array[2] = {654, 321}; - my_int64_array_ptr.At(3).PutArray(array, 2); - EXPECT_EQ(0, my_int64_array[2]); - EXPECT_EQ(654, my_int64_array[3]); - EXPECT_EQ(321, my_int64_array[4]); - } - - // |UserPointer<>::Reader|: - { - UserPointer<int64_t>::Reader reader(my_int64_array_ptr, 5); - EXPECT_EQ(456, reader.GetPointer()[0]); - EXPECT_EQ(321, reader.GetPointer()[4]); - } - - // Non-const to const: - { - UserPointer<const int64_t>::Reader reader(my_int64_array_ptr.At(3), 1); - const int64_t* ptr = reader.GetPointer(); - EXPECT_EQ(654, *ptr); - } - - // |UserPointer<>::Writer|: - { - UserPointer<int64_t>::Writer writer(my_int64_array_ptr.At(2), 1); - int64_t* ptr = writer.GetPointer(); - *ptr = 1234567890123LL; - writer.Commit(); - EXPECT_EQ(1234567890123LL, my_int64_array[2]); - } - - // |UserPointer<>::ReaderWriter|: - { - UserPointer<int32_t>::ReaderWriter reader_writer(my_int32_ptr, 1); - int32_t* ptr = reader_writer.GetPointer(); - EXPECT_EQ(-456, *ptr); - *ptr = 42; - reader_writer.Commit(); - EXPECT_EQ(42, my_int32); - } - - // |UserPointer<>::ReinterpretCast<>|: - // (This assumes little-endian, etc.) - { - UserPointer<const char> other(my_int32_ptr.ReinterpretCast<char>()); - EXPECT_EQ(42, other.Get()); - EXPECT_EQ(0, other.At(1).Get()); - EXPECT_EQ(0, other.At(2).Get()); - EXPECT_EQ(0, other.At(3).Get()); - } - - // |UserPointer<>::GetPointerValue()|: - { - UserPointer<int32_t> other; - EXPECT_EQ(0u, other.GetPointerValue()); - other = my_int32_ptr; - EXPECT_EQ(reinterpret_cast<uintptr_t>(&my_int32), other.GetPointerValue()); - } -} - -TEST(MemoryTest, InvalidDeath) { - const char kMemoryCheckFailedRegex[] = "Check failed"; - - // Note: |Check...()| are defined to be "best effort" checks (and may always - // return true). Thus these tests of invalid cases only reflect the current - // implementation. - - // These tests depend on |int32_t| and |int64_t| having nontrivial alignment. - static_assert(MOJO_ALIGNOF(int32_t) != 1, - "int32_t does not require nontrivial alignment"); - static_assert(MOJO_ALIGNOF(int64_t) != 1, - "int64_t does not require nontrivial alignment"); - - // Null: - { - UserPointer<char> ptr(nullptr); - char array[5] = {}; - EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.Put('x'), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(array, 5), kMemoryCheckFailedRegex); - } - { - UserPointer<int32_t> ptr(nullptr); - int32_t array[5] = {}; - EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.Put(123), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(array, 5), kMemoryCheckFailedRegex); - } - { - UserPointer<int64_t> ptr(nullptr); - int64_t array[5] = {}; - EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.Put(123), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(array, 5), kMemoryCheckFailedRegex); - } - // Also check a const pointer: - { - UserPointer<const int32_t> ptr(nullptr); - int32_t array[5] = {}; - EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex); - } - - // Unaligned: - { - int32_t x[10]; - UserPointer<int32_t> ptr( - reinterpret_cast<int32_t*>(reinterpret_cast<uintptr_t>(x) + 1)); - int32_t array[5] = {}; - EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.Put(123), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(array, 5), kMemoryCheckFailedRegex); - } - { - int64_t x[10]; - UserPointer<int64_t> ptr( - reinterpret_cast<int64_t*>(reinterpret_cast<uintptr_t>(x) + 1)); - int64_t array[5] = {}; - EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.Put(123), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(array, 5), kMemoryCheckFailedRegex); - } - // Also check a const pointer: - { - int32_t x[10]; - UserPointer<const int32_t> ptr( - reinterpret_cast<const int32_t*>(reinterpret_cast<uintptr_t>(x) + 1)); - int32_t array[5] = {}; - EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex); - } - - // Count too big: - { - const size_t kTooBig = - std::numeric_limits<size_t>::max() / sizeof(int32_t) + 1; - int32_t x = 0; - UserPointer<int32_t> ptr(&x); - EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(kTooBig), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(&x, kTooBig), - kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(&x, kTooBig), - kMemoryCheckFailedRegex); - } - { - const size_t kTooBig = - std::numeric_limits<size_t>::max() / sizeof(int64_t) + 1; - int64_t x = 0; - UserPointer<int64_t> ptr(&x); - EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(kTooBig), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(&x, kTooBig), - kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(&x, kTooBig), - kMemoryCheckFailedRegex); - } - // Also check a const pointer: - { - const size_t kTooBig = - std::numeric_limits<size_t>::max() / sizeof(int32_t) + 1; - int32_t x = 0; - UserPointer<const int32_t> ptr(&x); - EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(kTooBig), kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(&x, kTooBig), - kMemoryCheckFailedRegex); - } - - // TODO(vtl): Tests for |UserPointer{Reader,Writer,ReaderWriter}|. -} - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/message_in_transit.cc b/third_party/mojo/src/mojo/edk/system/message_in_transit.cc deleted file mode 100644 index 000b993..0000000 --- a/third_party/mojo/src/mojo/edk/system/message_in_transit.cc +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/message_in_transit.h" - -#include <string.h> -#include <ostream> -#include <utility> - -#include "base/logging.h" -#include "third_party/mojo/src/mojo/edk/system/configuration.h" -#include "third_party/mojo/src/mojo/edk/system/transport_data.h" - -namespace mojo { -namespace system { - -MOJO_STATIC_CONST_MEMBER_DEFINITION const size_t - MessageInTransit::kMessageAlignment; - -struct MessageInTransit::PrivateStructForCompileAsserts { - // The size of |Header| must be a multiple of the alignment. - static_assert(sizeof(Header) % kMessageAlignment == 0, - "sizeof(MessageInTransit::Header) invalid"); -}; - -MessageInTransit::View::View(size_t message_size, const void* buffer) - : buffer_(buffer) { - size_t next_message_size = 0; - DCHECK(MessageInTransit::GetNextMessageSize(buffer_, message_size, - &next_message_size)); - DCHECK_EQ(message_size, next_message_size); - // This should be equivalent. - DCHECK_EQ(message_size, total_size()); -} - -bool MessageInTransit::View::IsValid(size_t serialized_platform_handle_size, - const char** error_message) const { - size_t max_message_num_bytes = GetConfiguration().max_message_num_bytes; - // Avoid dangerous situations, but making sure that the size of the "header" + - // the size of the data fits into a 31-bit number. - DCHECK_LE(static_cast<uint64_t>(sizeof(Header)) + max_message_num_bytes, - 0x7fffffffULL) - << "GetConfiguration().max_message_num_bytes too big"; - - // We assume (to avoid extra rounding code) that the maximum message (data) - // size is a multiple of the alignment. - DCHECK_EQ(max_message_num_bytes % kMessageAlignment, 0U) - << "GetConfiguration().max_message_num_bytes not a multiple of alignment"; - - // Note: This also implies a check on the |main_buffer_size()|, which is just - // |RoundUpMessageAlignment(sizeof(Header) + num_bytes())|. - if (num_bytes() > max_message_num_bytes) { - *error_message = "Message data payload too large"; - return false; - } - - if (transport_data_buffer_size() > 0) { - const char* e = TransportData::ValidateBuffer( - serialized_platform_handle_size, transport_data_buffer(), - transport_data_buffer_size()); - if (e) { - *error_message = e; - return false; - } - } - - return true; -} - -MessageInTransit::MessageInTransit(Type type, - Subtype subtype, - uint32_t num_bytes, - const void* bytes) - : main_buffer_size_(RoundUpMessageAlignment(sizeof(Header) + num_bytes)), - main_buffer_(static_cast<char*>( - base::AlignedAlloc(main_buffer_size_, kMessageAlignment))) { - ConstructorHelper(type, subtype, num_bytes); - if (bytes) { - memcpy(MessageInTransit::bytes(), bytes, num_bytes); - memset(static_cast<char*>(MessageInTransit::bytes()) + num_bytes, 0, - main_buffer_size_ - sizeof(Header) - num_bytes); - } else { - memset(MessageInTransit::bytes(), 0, main_buffer_size_ - sizeof(Header)); - } -} - -MessageInTransit::MessageInTransit(Type type, - Subtype subtype, - uint32_t num_bytes, - UserPointer<const void> bytes) - : main_buffer_size_(RoundUpMessageAlignment(sizeof(Header) + num_bytes)), - main_buffer_(static_cast<char*>( - base::AlignedAlloc(main_buffer_size_, kMessageAlignment))) { - ConstructorHelper(type, subtype, num_bytes); - bytes.GetArray(MessageInTransit::bytes(), num_bytes); - memset(static_cast<char*>(MessageInTransit::bytes()) + num_bytes, 0, - main_buffer_size_ - sizeof(Header) - num_bytes); -} - -MessageInTransit::MessageInTransit(const View& message_view) - : main_buffer_size_(message_view.main_buffer_size()), - main_buffer_(static_cast<char*>( - base::AlignedAlloc(main_buffer_size_, kMessageAlignment))) { - DCHECK_GE(main_buffer_size_, sizeof(Header)); - DCHECK_EQ(main_buffer_size_ % kMessageAlignment, 0u); - - memcpy(main_buffer_.get(), message_view.main_buffer(), main_buffer_size_); - DCHECK_EQ(main_buffer_size_, - RoundUpMessageAlignment(sizeof(Header) + num_bytes())); -} - -MessageInTransit::~MessageInTransit() { - if (dispatchers_) { - for (size_t i = 0; i < dispatchers_->size(); i++) { - if (!(*dispatchers_)[i]) - continue; - - DCHECK((*dispatchers_)[i]->HasOneRef()); - (*dispatchers_)[i]->Close(); - } - } -} - -// static -bool MessageInTransit::GetNextMessageSize(const void* buffer, - size_t buffer_size, - size_t* next_message_size) { - DCHECK(next_message_size); - if (!buffer_size) - return false; - DCHECK(buffer); - DCHECK_EQ( - reinterpret_cast<uintptr_t>(buffer) % MessageInTransit::kMessageAlignment, - 0u); - - if (buffer_size < sizeof(Header)) - return false; - - const Header* header = static_cast<const Header*>(buffer); - *next_message_size = header->total_size; - DCHECK_EQ(*next_message_size % kMessageAlignment, 0u); - return true; -} - -void MessageInTransit::SetDispatchers( - scoped_ptr<DispatcherVector> dispatchers) { - DCHECK(dispatchers); - DCHECK(!dispatchers_); - DCHECK(!transport_data_); - - dispatchers_ = std::move(dispatchers); -#ifndef NDEBUG - for (size_t i = 0; i < dispatchers_->size(); i++) - DCHECK(!(*dispatchers_)[i] || (*dispatchers_)[i]->HasOneRef()); -#endif -} - -void MessageInTransit::SetTransportData( - scoped_ptr<TransportData> transport_data) { - DCHECK(transport_data); - DCHECK(!transport_data_); - DCHECK(!dispatchers_); - - transport_data_ = std::move(transport_data); - UpdateTotalSize(); -} - -void MessageInTransit::SerializeAndCloseDispatchers(Channel* channel) { - DCHECK(channel); - DCHECK(!transport_data_); - - if (!dispatchers_ || !dispatchers_->size()) - return; - - transport_data_.reset(new TransportData(std::move(dispatchers_), channel)); - - // Update the sizes in the message header. - UpdateTotalSize(); -} - -void MessageInTransit::ConstructorHelper(Type type, - Subtype subtype, - uint32_t num_bytes) { - DCHECK_LE(num_bytes, GetConfiguration().max_message_num_bytes); - - // |total_size| is updated below, from the other values. - header()->type = type; - header()->subtype = subtype; - header()->source_id = ChannelEndpointId(); - header()->destination_id = ChannelEndpointId(); - header()->num_bytes = num_bytes; - header()->unused = 0; - // Note: If dispatchers are subsequently attached, then |total_size| will have - // to be adjusted. - UpdateTotalSize(); -} - -void MessageInTransit::UpdateTotalSize() { - DCHECK_EQ(main_buffer_size_ % kMessageAlignment, 0u); - header()->total_size = static_cast<uint32_t>(main_buffer_size_); - if (transport_data_) { - header()->total_size += - static_cast<uint32_t>(transport_data_->buffer_size()); - } -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/message_in_transit.h b/third_party/mojo/src/mojo/edk/system/message_in_transit.h deleted file mode 100644 index 7383d21..0000000 --- a/third_party/mojo/src/mojo/edk/system/message_in_transit.h +++ /dev/null @@ -1,309 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MESSAGE_IN_TRANSIT_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MESSAGE_IN_TRANSIT_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <ostream> -#include <vector> - -#include "base/memory/aligned_memory.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint_id.h" -#include "third_party/mojo/src/mojo/edk/system/dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/memory.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -class Channel; -class TransportData; - -// This class is used to represent data in transit. It is thread-unsafe. -// -// |MessageInTransit| buffers: -// -// A |MessageInTransit| can be serialized by writing the main buffer and then, -// if it has one, the transport data buffer. Both buffers are -// |kMessageAlignment|-byte aligned and a multiple of |kMessageAlignment| bytes -// in size. -// -// The main buffer consists of the header (of type |Header|, which is an -// internal detail of this class) followed immediately by the message data -// (accessed by |bytes()| and of size |num_bytes()|, and also -// |kMessageAlignment|-byte aligned), and then any padding needed to make the -// main buffer a multiple of |kMessageAlignment| bytes in size. -// -// See |TransportData| for a description of the (serialized) transport data -// buffer. -class MOJO_SYSTEM_IMPL_EXPORT MessageInTransit { - public: - enum class Type : uint16_t { - // Messages that are forwarded to endpoint clients. - ENDPOINT_CLIENT = 0, - // Messages that are consumed by the |ChannelEndpoint|. - ENDPOINT = 1, - // Messages that are consumed by the |Channel|. - CHANNEL = 2, - // Messages that are consumed by the |RawChannel| (implementation). - RAW_CHANNEL = 3, - // |ConnectionManager| implementations also use |RawChannel|s. - // Messages sent to a |MasterConnectionManager|. - CONNECTION_MANAGER = 4, - // Messages sent by a |MasterConnectionManager| (all responses). - CONNECTION_MANAGER_ACK = 5, - }; - - enum class Subtype : uint16_t { - // Subtypes for type |Type::ENDPOINT_CLIENT|: - // Message pipe or data pipe data (etc.). - ENDPOINT_CLIENT_DATA = 0, - // Data pipe: consumer -> producer message that data was consumed. Payload - // is |RemoteDataPipeAck|. - ENDPOINT_CLIENT_DATA_PIPE_ACK = 1, - // Subtypes for type |Type::ENDPOINT|: - // TODO(vtl): Nothing yet. - // Subtypes for type |Type::CHANNEL|: - CHANNEL_ATTACH_AND_RUN_ENDPOINT = 0, - CHANNEL_REMOVE_ENDPOINT = 1, - CHANNEL_REMOVE_ENDPOINT_ACK = 2, - // Subtypes for type |Type::RAW_CHANNEL|: - RAW_CHANNEL_POSIX_EXTRA_PLATFORM_HANDLES = 0, - // Subtypes for type |Type::CONNECTION_MANAGER| (the message data is always - // a buffer containing the connection ID): - CONNECTION_MANAGER_ALLOW_CONNECT = 0, - CONNECTION_MANAGER_CANCEL_CONNECT = 1, - CONNECTION_MANAGER_CONNECT = 2, - // Subtypes for type |Type::CONNECTION_MANAGER_ACK|, corresponding to - // |ConnectionManager::Result| values (failure and non-"connect" acks never - // have any message contents; success acks for "connect" always have a - // |ConnectionManagerAckSuccessConnectData| as data and also a platform - // handle attached for "new connection"): - CONNECTION_MANAGER_ACK_FAILURE = 0, - CONNECTION_MANAGER_ACK_SUCCESS = 1, - CONNECTION_MANAGER_ACK_SUCCESS_CONNECT_SAME_PROCESS = 2, - CONNECTION_MANAGER_ACK_SUCCESS_CONNECT_NEW_CONNECTION = 3, - CONNECTION_MANAGER_ACK_SUCCESS_CONNECT_REUSE_CONNECTION = 4, - }; - - // Messages (the header and data) must always be aligned to a multiple of this - // quantity (which must be a power of 2). - static const size_t kMessageAlignment = 8; - - // Forward-declare |Header| so that |View| can use it: - private: - struct Header; - - public: - // This represents a view of serialized message data in a raw buffer. - class MOJO_SYSTEM_IMPL_EXPORT View { - public: - // Constructs a view from the given buffer of the given size. (The size must - // be as provided by |MessageInTransit::GetNextMessageSize()|.) The buffer - // must remain alive/unmodified through the lifetime of this object. - // |buffer| should be |kMessageAlignment|-byte aligned. - View(size_t message_size, const void* buffer); - - // Checks that the given |View| appears to be for a valid message, within - // predetermined limits (e.g., |num_bytes()| and |main_buffer_size()|, that - // |transport_data_buffer()|/|transport_data_buffer_size()| is for valid - // transport data -- see |TransportData::ValidateBuffer()|). - // - // It returns true (and leaves |error_message| alone) if this object appears - // to be a valid message (according to the above) and false, pointing - // |*error_message| to a suitable error message, if not. - bool IsValid(size_t serialized_platform_handle_size, - const char** error_message) const; - - // API parallel to that for |MessageInTransit| itself (mostly getters for - // header data). - const void* main_buffer() const { return buffer_; } - size_t main_buffer_size() const { - return RoundUpMessageAlignment(sizeof(Header) + header()->num_bytes); - } - const void* transport_data_buffer() const { - return (total_size() > main_buffer_size()) - ? static_cast<const char*>(buffer_) + main_buffer_size() - : nullptr; - } - size_t transport_data_buffer_size() const { - return total_size() - main_buffer_size(); - } - size_t total_size() const { return header()->total_size; } - uint32_t num_bytes() const { return header()->num_bytes; } - const void* bytes() const { - return static_cast<const char*>(buffer_) + sizeof(Header); - } - Type type() const { return header()->type; } - Subtype subtype() const { return header()->subtype; } - ChannelEndpointId source_id() const { return header()->source_id; } - ChannelEndpointId destination_id() const { - return header()->destination_id; - } - - private: - const Header* header() const { return static_cast<const Header*>(buffer_); } - - const void* const buffer_; - - // Though this struct is trivial, disallow copy and assign, since it doesn't - // own its data. (If you're copying/assigning this, you're probably doing - // something wrong.) - MOJO_DISALLOW_COPY_AND_ASSIGN(View); - }; - - // |bytes| is optional; if null, the message data will be zero-initialized. - MessageInTransit(Type type, - Subtype subtype, - uint32_t num_bytes, - const void* bytes); - // |bytes| should be valid (and non-null), unless |num_bytes| is zero. - MessageInTransit(Type type, - Subtype subtype, - uint32_t num_bytes, - UserPointer<const void> bytes); - // Constructs a |MessageInTransit| from a |View|. - explicit MessageInTransit(const View& message_view); - - ~MessageInTransit(); - - // Gets the size of the next message from |buffer|, which has |buffer_size| - // bytes currently available, returning true and setting |*next_message_size| - // on success. |buffer| should be aligned on a |kMessageAlignment| boundary - // (and on success, |*next_message_size| will be a multiple of - // |kMessageAlignment|). - // TODO(vtl): In |RawChannelPosix|, the alignment requirements are currently - // satisified on a faith-based basis. - static bool GetNextMessageSize(const void* buffer, - size_t buffer_size, - size_t* next_message_size); - - // Makes this message "own" the given set of dispatchers. The dispatchers must - // not be referenced from anywhere else (in particular, not from the handle - // table), i.e., each dispatcher must have a reference count of 1. This - // message must not already have dispatchers. - void SetDispatchers(scoped_ptr<DispatcherVector> dispatchers); - - // Sets the |TransportData| for this message. This should only be done when - // there are no dispatchers and no existing |TransportData|. - void SetTransportData(scoped_ptr<TransportData> transport_data); - - // Serializes any dispatchers to the secondary buffer. This message must not - // already have a secondary buffer (so this must only be called once). The - // caller must ensure (e.g., by holding on to a reference) that |channel| - // stays alive through the call. - void SerializeAndCloseDispatchers(Channel* channel); - - // Gets the main buffer and its size (in number of bytes), respectively. - const void* main_buffer() const { return main_buffer_.get(); } - size_t main_buffer_size() const { return main_buffer_size_; } - - // Gets the transport data buffer (if any). - const TransportData* transport_data() const { return transport_data_.get(); } - TransportData* transport_data() { return transport_data_.get(); } - - // Gets the total size of the message (see comment in |Header|, below). - size_t total_size() const { return header()->total_size; } - - // Gets the size of the message data. - uint32_t num_bytes() const { return header()->num_bytes; } - - // Gets the message data (of size |num_bytes()| bytes). - const void* bytes() const { return main_buffer_.get() + sizeof(Header); } - void* bytes() { return main_buffer_.get() + sizeof(Header); } - - Type type() const { return header()->type; } - Subtype subtype() const { return header()->subtype; } - ChannelEndpointId source_id() const { return header()->source_id; } - ChannelEndpointId destination_id() const { return header()->destination_id; } - - void set_source_id(ChannelEndpointId source_id) { - header()->source_id = source_id; - } - void set_destination_id(ChannelEndpointId destination_id) { - header()->destination_id = destination_id; - } - - // Gets the dispatchers attached to this message; this may return null if - // there are none. Note that the caller may mutate the set of dispatchers - // (e.g., take ownership of all the dispatchers, leaving the vector empty). - DispatcherVector* dispatchers() { return dispatchers_.get(); } - - // Returns true if this message has dispatchers attached. - bool has_dispatchers() const { - return dispatchers_ && !dispatchers_->empty(); - } - - // Rounds |n| up to a multiple of |kMessageAlignment|. - static inline size_t RoundUpMessageAlignment(size_t n) { - return (n + kMessageAlignment - 1) & ~(kMessageAlignment - 1); - } - - private: - // To allow us to make compile-assertions about |Header| in the .cc file. - struct PrivateStructForCompileAsserts; - - // Header for the data (main buffer). Must be a multiple of - // |kMessageAlignment| bytes in size. Must be POD. - struct Header { - // Total size of the message, including the header, the message data - // ("bytes") including padding (to make it a multiple of |kMessageAlignment| - // bytes), and serialized handle information. Note that this may not be the - // correct value if dispatchers are attached but - // |SerializeAndCloseDispatchers()| has not been called. - uint32_t total_size; - Type type; // 2 bytes. - Subtype subtype; // 2 bytes. - ChannelEndpointId source_id; // 4 bytes. - ChannelEndpointId destination_id; // 4 bytes. - // Size of actual message data. - uint32_t num_bytes; - uint32_t unused; - }; - - const Header* header() const { - return reinterpret_cast<const Header*>(main_buffer_.get()); - } - Header* header() { return reinterpret_cast<Header*>(main_buffer_.get()); } - - void ConstructorHelper(Type type, Subtype subtype, uint32_t num_bytes); - void UpdateTotalSize(); - - const size_t main_buffer_size_; - const scoped_ptr<char, base::AlignedFreeDeleter> main_buffer_; // Never null. - - scoped_ptr<TransportData> transport_data_; // May be null. - - // Any dispatchers that may be attached to this message. These dispatchers - // should be "owned" by this message, i.e., have a ref count of exactly 1. (We - // allow a dispatcher entry to be null, in case it couldn't be duplicated for - // some reason.) - scoped_ptr<DispatcherVector> dispatchers_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(MessageInTransit); -}; - -// So logging macros and |DCHECK_EQ()|, etc. work. -MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<( - std::ostream& out, - MessageInTransit::Type type) { - return out << static_cast<uint16_t>(type); -} - -// So logging macros and |DCHECK_EQ()|, etc. work. -MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<( - std::ostream& out, - MessageInTransit::Subtype subtype) { - return out << static_cast<uint16_t>(subtype); -} - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MESSAGE_IN_TRANSIT_H_ diff --git a/third_party/mojo/src/mojo/edk/system/message_in_transit_queue.cc b/third_party/mojo/src/mojo/edk/system/message_in_transit_queue.cc deleted file mode 100644 index db4617f..0000000 --- a/third_party/mojo/src/mojo/edk/system/message_in_transit_queue.cc +++ /dev/null @@ -1,33 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/message_in_transit_queue.h" - -#include "base/logging.h" - -namespace mojo { -namespace system { - -MessageInTransitQueue::MessageInTransitQueue() { -} - -MessageInTransitQueue::~MessageInTransitQueue() { - if (!IsEmpty()) { - LOG(WARNING) << "Destroying nonempty message queue"; - Clear(); - } -} - -void MessageInTransitQueue::Clear() { - for (auto* message : queue_) - delete message; - queue_.clear(); -} - -void MessageInTransitQueue::Swap(MessageInTransitQueue* other) { - queue_.swap(other->queue_); -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/message_in_transit_queue.h b/third_party/mojo/src/mojo/edk/system/message_in_transit_queue.h deleted file mode 100644 index c497341..0000000 --- a/third_party/mojo/src/mojo/edk/system/message_in_transit_queue.h +++ /dev/null @@ -1,62 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MESSAGE_IN_TRANSIT_QUEUE_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MESSAGE_IN_TRANSIT_QUEUE_H_ - -#include <deque> - -#include "base/memory/scoped_ptr.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -// A simple queue for |MessageInTransit|s (that owns its messages). -// This class is not thread-safe. -class MOJO_SYSTEM_IMPL_EXPORT MessageInTransitQueue { - public: - MessageInTransitQueue(); - ~MessageInTransitQueue(); - - bool IsEmpty() const { return queue_.empty(); } - size_t Size() const { return queue_.size(); } - - void AddMessage(scoped_ptr<MessageInTransit> message) { - queue_.push_back(message.release()); - } - - scoped_ptr<MessageInTransit> GetMessage() { - MessageInTransit* rv = queue_.front(); - queue_.pop_front(); - return make_scoped_ptr(rv); - } - - const MessageInTransit* PeekMessage() const { return queue_.front(); } - MessageInTransit* PeekMessage() { return queue_.front(); } - - void DiscardMessage() { - delete queue_.front(); - queue_.pop_front(); - } - - void Clear(); - - // Efficiently swaps contents with |*other|. - void Swap(MessageInTransitQueue* other); - - private: - // TODO(vtl): When C++11 is available, switch this to a deque of - // |scoped_ptr|/|unique_ptr|s. - std::deque<MessageInTransit*> queue_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(MessageInTransitQueue); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MESSAGE_IN_TRANSIT_QUEUE_H_ diff --git a/third_party/mojo/src/mojo/edk/system/message_in_transit_queue_unittest.cc b/third_party/mojo/src/mojo/edk/system/message_in_transit_queue_unittest.cc deleted file mode 100644 index d7fa222..0000000 --- a/third_party/mojo/src/mojo/edk/system/message_in_transit_queue_unittest.cc +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2015 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 "third_party/mojo/src/mojo/edk/system/message_in_transit_queue.h" - -#include "third_party/mojo/src/mojo/edk/system/message_in_transit_test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace system { -namespace { - -TEST(MessageInTransitQueueTest, Basic) { - MessageInTransitQueue queue; - EXPECT_TRUE(queue.IsEmpty()); - - queue.AddMessage(test::MakeTestMessage(1)); - ASSERT_FALSE(queue.IsEmpty()); - EXPECT_EQ(1u, queue.Size()); - - test::VerifyTestMessage(queue.PeekMessage(), 1); - ASSERT_FALSE(queue.IsEmpty()); - EXPECT_EQ(1u, queue.Size()); - - queue.AddMessage(test::MakeTestMessage(2)); - queue.AddMessage(test::MakeTestMessage(3)); - ASSERT_FALSE(queue.IsEmpty()); - EXPECT_EQ(3u, queue.Size()); - - test::VerifyTestMessage(queue.GetMessage().get(), 1); - ASSERT_FALSE(queue.IsEmpty()); - EXPECT_EQ(2u, queue.Size()); - - test::VerifyTestMessage(queue.PeekMessage(), 2); - ASSERT_FALSE(queue.IsEmpty()); - EXPECT_EQ(2u, queue.Size()); - - queue.DiscardMessage(); - ASSERT_FALSE(queue.IsEmpty()); - EXPECT_EQ(1u, queue.Size()); - - test::VerifyTestMessage(queue.GetMessage().get(), 3); - EXPECT_TRUE(queue.IsEmpty()); - EXPECT_EQ(0u, queue.Size()); - - queue.AddMessage(test::MakeTestMessage(4)); - ASSERT_FALSE(queue.IsEmpty()); - EXPECT_EQ(1u, queue.Size()); - - test::VerifyTestMessage(queue.PeekMessage(), 4); - ASSERT_FALSE(queue.IsEmpty()); - EXPECT_EQ(1u, queue.Size()); - - queue.Clear(); - EXPECT_TRUE(queue.IsEmpty()); - EXPECT_EQ(0u, queue.Size()); -} - -TEST(MessageInTransitQueueTest, Swap) { - MessageInTransitQueue queue1; - MessageInTransitQueue queue2; - - queue1.AddMessage(test::MakeTestMessage(1)); - queue1.AddMessage(test::MakeTestMessage(2)); - queue1.AddMessage(test::MakeTestMessage(3)); - EXPECT_EQ(3u, queue1.Size()); - - queue2.AddMessage(test::MakeTestMessage(4)); - queue2.AddMessage(test::MakeTestMessage(5)); - EXPECT_EQ(2u, queue2.Size()); - - queue1.Swap(&queue2); - EXPECT_EQ(2u, queue1.Size()); - EXPECT_EQ(3u, queue2.Size()); - test::VerifyTestMessage(queue1.GetMessage().get(), 4); - test::VerifyTestMessage(queue1.GetMessage().get(), 5); - EXPECT_TRUE(queue1.IsEmpty()); - - queue1.Swap(&queue2); - EXPECT_TRUE(queue2.IsEmpty()); - - test::VerifyTestMessage(queue1.GetMessage().get(), 1); - test::VerifyTestMessage(queue1.GetMessage().get(), 2); - test::VerifyTestMessage(queue1.GetMessage().get(), 3); - EXPECT_TRUE(queue1.IsEmpty()); -} - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/message_in_transit_test_utils.cc b/third_party/mojo/src/mojo/edk/system/message_in_transit_test_utils.cc deleted file mode 100644 index 1a205b4..0000000 --- a/third_party/mojo/src/mojo/edk/system/message_in_transit_test_utils.cc +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2015 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 "third_party/mojo/src/mojo/edk/system/message_in_transit_test_utils.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace system { -namespace test { - -scoped_ptr<MessageInTransit> MakeTestMessage(unsigned id) { - return make_scoped_ptr( - new MessageInTransit(MessageInTransit::Type::ENDPOINT_CLIENT, - MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, - static_cast<uint32_t>(sizeof(id)), &id)); -} - -void VerifyTestMessage(const MessageInTransit* message, unsigned id) { - ASSERT_TRUE(message); - EXPECT_EQ(MessageInTransit::Type::ENDPOINT_CLIENT, message->type()); - EXPECT_EQ(MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, - message->subtype()); - EXPECT_EQ(sizeof(id), message->num_bytes()); - EXPECT_EQ(id, *static_cast<const unsigned*>(message->bytes())); -} - -bool IsTestMessage(MessageInTransit* message, unsigned* id) { - if (message->type() != MessageInTransit::Type::ENDPOINT_CLIENT || - message->subtype() != MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA || - message->num_bytes() != sizeof(*id)) - return false; - - *id = *static_cast<const unsigned*>(message->bytes()); - return true; -} - -} // namespace test -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/message_in_transit_test_utils.h b/third_party/mojo/src/mojo/edk/system/message_in_transit_test_utils.h deleted file mode 100644 index db6759a..0000000 --- a/third_party/mojo/src/mojo/edk/system/message_in_transit_test_utils.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2015 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MESSAGE_IN_TRANSIT_TEST_UTILS_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MESSAGE_IN_TRANSIT_TEST_UTILS_H_ - -#include "base/memory/scoped_ptr.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit.h" - -namespace mojo { -namespace system { -namespace test { - -// Makes a test message. It will be of type -// |MessageInTransit::Type::ENDPOINT_CLIENT| and subtype -// |MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA|, and contain data -// associated with |id| (so that test messages with different |id|s are -// distinguishable). -scoped_ptr<MessageInTransit> MakeTestMessage(unsigned id); - -// Verifies a test message: ASSERTs that |message| is non-null, and EXPECTs that -// it looks like a message created using |MakeTestMessage(id)| (see above). -void VerifyTestMessage(const MessageInTransit* message, unsigned id); - -// Checks if |message| looks like a test message created using -// |MakeTestMessage()|, in which case it returns true and sets |*id|. (Otherwise -// it returns false and leaves |*id| alone.) -bool IsTestMessage(MessageInTransit* message, unsigned* id); - -} // namespace test -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MESSAGE_IN_TRANSIT_TEST_UTILS_H_ diff --git a/third_party/mojo/src/mojo/edk/system/message_pipe.cc b/third_party/mojo/src/mojo/edk/system/message_pipe.cc deleted file mode 100644 index 19c1317..0000000 --- a/third_party/mojo/src/mojo/edk/system/message_pipe.cc +++ /dev/null @@ -1,386 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/message_pipe.h" - -#include <utility> - -#include "base/logging.h" -#include "third_party/mojo/src/mojo/edk/system/channel.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint_id.h" -#include "third_party/mojo/src/mojo/edk/system/incoming_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/local_message_pipe_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/proxy_message_pipe_endpoint.h" - -namespace mojo { -namespace system { - -// static -MessagePipe* MessagePipe::CreateLocalLocal() { - MessagePipe* message_pipe = new MessagePipe(); - message_pipe->endpoints_[0].reset(new LocalMessagePipeEndpoint()); - message_pipe->endpoints_[1].reset(new LocalMessagePipeEndpoint()); - return message_pipe; -} - -// static -MessagePipe* MessagePipe::CreateLocalProxy( - scoped_refptr<ChannelEndpoint>* channel_endpoint) { - DCHECK(!*channel_endpoint); // Not technically wrong, but unlikely. - MessagePipe* message_pipe = new MessagePipe(); - message_pipe->endpoints_[0].reset(new LocalMessagePipeEndpoint()); - *channel_endpoint = new ChannelEndpoint(message_pipe, 1); - message_pipe->endpoints_[1].reset( - new ProxyMessagePipeEndpoint(channel_endpoint->get())); - return message_pipe; -} - -// static -MessagePipe* MessagePipe::CreateLocalProxyFromExisting( - MessageInTransitQueue* message_queue, - ChannelEndpoint* channel_endpoint) { - DCHECK(message_queue); - MessagePipe* message_pipe = new MessagePipe(); - message_pipe->endpoints_[0].reset( - new LocalMessagePipeEndpoint(message_queue)); - if (channel_endpoint) { - bool attached_to_channel = channel_endpoint->ReplaceClient(message_pipe, 1); - message_pipe->endpoints_[1].reset( - new ProxyMessagePipeEndpoint(channel_endpoint)); - if (!attached_to_channel) - message_pipe->OnDetachFromChannel(1); - } else { - // This means that the proxy side was already closed; we only need to inform - // the local side of this. - // TODO(vtl): This is safe to do without locking (but perhaps slightly - // dubious), since no other thread has access to |message_pipe| yet. - message_pipe->endpoints_[0]->OnPeerClose(); - } - return message_pipe; -} - -// static -MessagePipe* MessagePipe::CreateProxyLocal( - scoped_refptr<ChannelEndpoint>* channel_endpoint) { - DCHECK(!*channel_endpoint); // Not technically wrong, but unlikely. - MessagePipe* message_pipe = new MessagePipe(); - *channel_endpoint = new ChannelEndpoint(message_pipe, 0); - message_pipe->endpoints_[0].reset( - new ProxyMessagePipeEndpoint(channel_endpoint->get())); - message_pipe->endpoints_[1].reset(new LocalMessagePipeEndpoint()); - return message_pipe; -} - -// static -unsigned MessagePipe::GetPeerPort(unsigned port) { - DCHECK(port == 0 || port == 1); - return port ^ 1; -} - -// static -bool MessagePipe::Deserialize(Channel* channel, - const void* source, - size_t size, - scoped_refptr<MessagePipe>* message_pipe, - unsigned* port) { - DCHECK(!*message_pipe); // Not technically wrong, but unlikely. - - if (size != channel->GetSerializedEndpointSize()) { - LOG(ERROR) << "Invalid serialized message pipe"; - return false; - } - - scoped_refptr<IncomingEndpoint> incoming_endpoint = - channel->DeserializeEndpoint(source); - if (!incoming_endpoint) - return false; - - *message_pipe = incoming_endpoint->ConvertToMessagePipe(); - DCHECK(*message_pipe); - *port = 0; - return true; -} - -MessagePipeEndpoint::Type MessagePipe::GetType(unsigned port) { - DCHECK(port == 0 || port == 1); - base::AutoLock locker(lock_); - DCHECK(endpoints_[port]); - - return endpoints_[port]->GetType(); -} - -void MessagePipe::CancelAllAwakables(unsigned port) { - DCHECK(port == 0 || port == 1); - - base::AutoLock locker(lock_); - DCHECK(endpoints_[port]); - endpoints_[port]->CancelAllAwakables(); -} - -void MessagePipe::Close(unsigned port) { - DCHECK(port == 0 || port == 1); - - unsigned peer_port = GetPeerPort(port); - - base::AutoLock locker(lock_); - // The endpoint's |OnPeerClose()| may have been called first and returned - // false, which would have resulted in its destruction. - if (!endpoints_[port]) - return; - - endpoints_[port]->Close(); - if (endpoints_[peer_port]) { - if (!endpoints_[peer_port]->OnPeerClose()) - endpoints_[peer_port].reset(); - } - endpoints_[port].reset(); -} - -// TODO(vtl): Handle flags. -MojoResult MessagePipe::WriteMessage( - unsigned port, - UserPointer<const void> bytes, - uint32_t num_bytes, - std::vector<DispatcherTransport>* transports, - MojoWriteMessageFlags flags) { - DCHECK(port == 0 || port == 1); - - base::AutoLock locker(lock_); - return EnqueueMessageNoLock( - GetPeerPort(port), - make_scoped_ptr(new MessageInTransit( - MessageInTransit::Type::ENDPOINT_CLIENT, - MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, num_bytes, bytes)), - transports); -} - -MojoResult MessagePipe::ReadMessage(unsigned port, - UserPointer<void> bytes, - UserPointer<uint32_t> num_bytes, - DispatcherVector* dispatchers, - uint32_t* num_dispatchers, - MojoReadMessageFlags flags) { - DCHECK(port == 0 || port == 1); - - base::AutoLock locker(lock_); - DCHECK(endpoints_[port]); - - return endpoints_[port]->ReadMessage(bytes, num_bytes, dispatchers, - num_dispatchers, flags); -} - -HandleSignalsState MessagePipe::GetHandleSignalsState(unsigned port) const { - DCHECK(port == 0 || port == 1); - - base::AutoLock locker(const_cast<base::Lock&>(lock_)); - DCHECK(endpoints_[port]); - - return endpoints_[port]->GetHandleSignalsState(); -} - -MojoResult MessagePipe::AddAwakable(unsigned port, - Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state) { - DCHECK(port == 0 || port == 1); - - base::AutoLock locker(lock_); - DCHECK(endpoints_[port]); - - return endpoints_[port]->AddAwakable(awakable, signals, context, - signals_state); -} - -void MessagePipe::RemoveAwakable(unsigned port, - Awakable* awakable, - HandleSignalsState* signals_state) { - DCHECK(port == 0 || port == 1); - - base::AutoLock locker(lock_); - DCHECK(endpoints_[port]); - - endpoints_[port]->RemoveAwakable(awakable, signals_state); -} - -void MessagePipe::StartSerialize(unsigned /*port*/, - Channel* channel, - size_t* max_size, - size_t* max_platform_handles) { - *max_size = channel->GetSerializedEndpointSize(); - *max_platform_handles = 0; -} - -bool MessagePipe::EndSerialize( - unsigned port, - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* /*platform_handles*/) { - DCHECK(port == 0 || port == 1); - - base::AutoLock locker(lock_); - DCHECK(endpoints_[port]); - - // The port being serialized must be local. - DCHECK_EQ(endpoints_[port]->GetType(), MessagePipeEndpoint::kTypeLocal); - - unsigned peer_port = GetPeerPort(port); - MessageInTransitQueue* message_queue = - static_cast<LocalMessagePipeEndpoint*>(endpoints_[port].get()) - ->message_queue(); - // The replacement for |endpoints_[port]|, if any. - MessagePipeEndpoint* replacement_endpoint = nullptr; - - // The three cases below correspond to the ones described above - // |Channel::SerializeEndpoint...()| (in channel.h). - if (!endpoints_[peer_port]) { - // Case 1: (known-)closed peer port. There's no reason for us to continue to - // exist afterwards. - channel->SerializeEndpointWithClosedPeer(destination, message_queue); - } else if (endpoints_[peer_port]->GetType() == - MessagePipeEndpoint::kTypeLocal) { - // Case 2: local peer port. We replace |port|'s |LocalMessagePipeEndpoint| - // with a |ProxyMessagePipeEndpoint| hooked up to the |ChannelEndpoint| that - // the |Channel| returns to us. - scoped_refptr<ChannelEndpoint> channel_endpoint = - channel->SerializeEndpointWithLocalPeer(destination, message_queue, - this, port); - replacement_endpoint = new ProxyMessagePipeEndpoint(channel_endpoint.get()); - } else { - // Case 3: remote peer port. We get the |peer_port|'s |ChannelEndpoint| and - // pass it to the |Channel|. There's no reason for us to continue to exist - // afterwards. - DCHECK_EQ(endpoints_[peer_port]->GetType(), - MessagePipeEndpoint::kTypeProxy); - ProxyMessagePipeEndpoint* peer_endpoint = - static_cast<ProxyMessagePipeEndpoint*>(endpoints_[peer_port].get()); - scoped_refptr<ChannelEndpoint> peer_channel_endpoint = - peer_endpoint->ReleaseChannelEndpoint(); - channel->SerializeEndpointWithRemotePeer(destination, message_queue, - peer_channel_endpoint); - // No need to call |Close()| after |ReleaseChannelEndpoint()|. - endpoints_[peer_port].reset(); - } - - endpoints_[port]->Close(); - endpoints_[port].reset(replacement_endpoint); - - *actual_size = channel->GetSerializedEndpointSize(); - return true; -} - -bool MessagePipe::OnReadMessage(unsigned port, MessageInTransit* message) { - base::AutoLock locker(lock_); - - if (!endpoints_[port]) { - // This will happen only on the rare occasion that the call to - // |OnReadMessage()| is racing with us calling - // |ChannelEndpoint::ReplaceClient()|, in which case we reject the message, - // and the |ChannelEndpoint| can retry (calling the new client's - // |OnReadMessage()|). - return false; - } - - // This is called when the |ChannelEndpoint| for the - // |ProxyMessagePipeEndpoint| |port| receives a message (from the |Channel|). - // We need to pass this message on to its peer port (typically a - // |LocalMessagePipeEndpoint|). - MojoResult result = EnqueueMessageNoLock(GetPeerPort(port), - make_scoped_ptr(message), nullptr); - DLOG_IF(WARNING, result != MOJO_RESULT_OK) - << "EnqueueMessageNoLock() failed (result = " << result << ")"; - return true; -} - -void MessagePipe::OnDetachFromChannel(unsigned port) { - Close(port); -} - -MessagePipe::MessagePipe() { -} - -MessagePipe::~MessagePipe() { - // Owned by the dispatchers. The owning dispatchers should only release us via - // their |Close()| method, which should inform us of being closed via our - // |Close()|. Thus these should already be null. - DCHECK(!endpoints_[0]); - DCHECK(!endpoints_[1]); -} - -MojoResult MessagePipe::EnqueueMessageNoLock( - unsigned port, - scoped_ptr<MessageInTransit> message, - std::vector<DispatcherTransport>* transports) { - DCHECK(port == 0 || port == 1); - DCHECK(message); - - DCHECK_EQ(message->type(), MessageInTransit::Type::ENDPOINT_CLIENT); - DCHECK(endpoints_[GetPeerPort(port)]); - - // The destination port need not be open, unlike the source port. - if (!endpoints_[port]) - return MOJO_RESULT_FAILED_PRECONDITION; - - if (transports) { - MojoResult result = AttachTransportsNoLock(port, message.get(), transports); - if (result != MOJO_RESULT_OK) - return result; - } - - // The endpoint's |EnqueueMessage()| may not report failure. - endpoints_[port]->EnqueueMessage(std::move(message)); - return MOJO_RESULT_OK; -} - -MojoResult MessagePipe::AttachTransportsNoLock( - unsigned port, - MessageInTransit* message, - std::vector<DispatcherTransport>* transports) { - DCHECK(!message->has_dispatchers()); - - // You're not allowed to send either handle to a message pipe over the message - // pipe, so check for this. (The case of trying to write a handle to itself is - // taken care of by |Core|. That case kind of makes sense, but leads to - // complications if, e.g., both sides try to do the same thing with their - // respective handles simultaneously. The other case, of trying to write the - // peer handle to a handle, doesn't make sense -- since no handle will be - // available to read the message from.) - for (size_t i = 0; i < transports->size(); i++) { - if (!(*transports)[i].is_valid()) - continue; - if ((*transports)[i].GetType() == Dispatcher::Type::MESSAGE_PIPE) { - MessagePipeDispatcherTransport mp_transport((*transports)[i]); - if (mp_transport.GetMessagePipe() == this) { - // The other case should have been disallowed by |Core|. (Note: |port| - // is the peer port of the handle given to |WriteMessage()|.) - DCHECK_EQ(mp_transport.GetPort(), port); - return MOJO_RESULT_INVALID_ARGUMENT; - } - } - } - - // Clone the dispatchers and attach them to the message. (This must be done as - // a separate loop, since we want to leave the dispatchers alone on failure.) - scoped_ptr<DispatcherVector> dispatchers(new DispatcherVector()); - dispatchers->reserve(transports->size()); - for (size_t i = 0; i < transports->size(); i++) { - if ((*transports)[i].is_valid()) { - dispatchers->push_back( - (*transports)[i].CreateEquivalentDispatcherAndClose()); - } else { - LOG(WARNING) << "Enqueueing null dispatcher"; - dispatchers->push_back(nullptr); - } - } - message->SetDispatchers(std::move(dispatchers)); - return MOJO_RESULT_OK; -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/message_pipe.h b/third_party/mojo/src/mojo/edk/system/message_pipe.h deleted file mode 100644 index 34e2edc..0000000 --- a/third_party/mojo/src/mojo/edk/system/message_pipe.h +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MESSAGE_PIPE_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MESSAGE_PIPE_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <vector> - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/synchronization/lock.h" -#include "mojo/public/c/system/message_pipe.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle_vector.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint_client.h" -#include "third_party/mojo/src/mojo/edk/system/dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/handle_signals_state.h" -#include "third_party/mojo/src/mojo/edk/system/memory.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -class Awakable; -class Channel; -class ChannelEndpoint; -class MessageInTransitQueue; - -// |MessagePipe| is the secondary object implementing a message pipe (see the -// explanatory comment in core.cc). It is typically owned by the dispatcher(s) -// corresponding to the local endpoints. This class is thread-safe. -class MOJO_SYSTEM_IMPL_EXPORT MessagePipe final : public ChannelEndpointClient { - public: - // Creates a |MessagePipe| with two new |LocalMessagePipeEndpoint|s. - static MessagePipe* CreateLocalLocal(); - - // Creates a |MessagePipe| with a |LocalMessagePipeEndpoint| on port 0 and a - // |ProxyMessagePipeEndpoint| on port 1. |*channel_endpoint| is set to the - // (newly-created) |ChannelEndpoint| for the latter. - static MessagePipe* CreateLocalProxy( - scoped_refptr<ChannelEndpoint>* channel_endpoint); - - // Similar to |CreateLocalProxy()|, except that it'll do so from an existing - // |ChannelEndpoint| (whose |ReplaceClient()| it'll call) and take - // |message_queue|'s contents as already-received incoming messages. If - // |channel_endpoint| is null, this will create a "half-open" message pipe. - static MessagePipe* CreateLocalProxyFromExisting( - MessageInTransitQueue* message_queue, - ChannelEndpoint* channel_endpoint); - - // Creates a |MessagePipe| with a |ProxyMessagePipeEndpoint| on port 0 and a - // |LocalMessagePipeEndpoint| on port 1. |*channel_endpoint| is set to the - // (newly-created) |ChannelEndpoint| for the former. - // Note: This is really only needed in tests (outside of tests, this - // configuration arises from a local message pipe having its port 0 - // "converted" using |ConvertLocalToProxy()|). - static MessagePipe* CreateProxyLocal( - scoped_refptr<ChannelEndpoint>* channel_endpoint); - - // Gets the other port number (i.e., 0 -> 1, 1 -> 0). - static unsigned GetPeerPort(unsigned port); - - // Used by |MessagePipeDispatcher::Deserialize()|. Returns true on success (in - // which case, |*message_pipe|/|*port| are set appropriately) and false on - // failure (in which case |*message_pipe| may or may not be set to null). - static bool Deserialize(Channel* channel, - const void* source, - size_t size, - scoped_refptr<MessagePipe>* message_pipe, - unsigned* port); - - // Gets the type of the endpoint (used for assertions, etc.). - MessagePipeEndpoint::Type GetType(unsigned port); - - // These are called by the dispatcher to implement its methods of - // corresponding names. In all cases, the port |port| must be open. - void CancelAllAwakables(unsigned port); - void Close(unsigned port); - // Unlike |MessagePipeDispatcher::WriteMessage()|, this does not validate its - // arguments. - MojoResult WriteMessage(unsigned port, - UserPointer<const void> bytes, - uint32_t num_bytes, - std::vector<DispatcherTransport>* transports, - MojoWriteMessageFlags flags); - MojoResult ReadMessage(unsigned port, - UserPointer<void> bytes, - UserPointer<uint32_t> num_bytes, - DispatcherVector* dispatchers, - uint32_t* num_dispatchers, - MojoReadMessageFlags flags); - HandleSignalsState GetHandleSignalsState(unsigned port) const; - MojoResult AddAwakable(unsigned port, - Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state); - void RemoveAwakable(unsigned port, - Awakable* awakable, - HandleSignalsState* signals_state); - void StartSerialize(unsigned port, - Channel* channel, - size_t* max_size, - size_t* max_platform_handles); - bool EndSerialize(unsigned port, - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles); - - // |ChannelEndpointClient| methods: - bool OnReadMessage(unsigned port, MessageInTransit* message) override; - void OnDetachFromChannel(unsigned port) override; - - private: - MessagePipe(); - ~MessagePipe() override; - - // This is used internally by |WriteMessage()| and by |OnReadMessage()|. - // |transports| may be non-null only if it's nonempty and |message| has no - // dispatchers attached. Must be called with |lock_| held. - MojoResult EnqueueMessageNoLock(unsigned port, - scoped_ptr<MessageInTransit> message, - std::vector<DispatcherTransport>* transports); - - // Helper for |EnqueueMessageNoLock()|. Must be called with |lock_| held. - MojoResult AttachTransportsNoLock( - unsigned port, - MessageInTransit* message, - std::vector<DispatcherTransport>* transports); - - base::Lock lock_; // Protects the following members. - scoped_ptr<MessagePipeEndpoint> endpoints_[2]; - - MOJO_DISALLOW_COPY_AND_ASSIGN(MessagePipe); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MESSAGE_PIPE_H_ diff --git a/third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.cc b/third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.cc deleted file mode 100644 index 3a1d64e..0000000 --- a/third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.cc +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.h" - -#include "base/logging.h" -#include "third_party/mojo/src/mojo/edk/system/configuration.h" -#include "third_party/mojo/src/mojo/edk/system/local_message_pipe_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/memory.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/options_validation.h" -#include "third_party/mojo/src/mojo/edk/system/proxy_message_pipe_endpoint.h" - -namespace mojo { -namespace system { - -const unsigned kInvalidPort = static_cast<unsigned>(-1); - -// MessagePipeDispatcher ------------------------------------------------------- - -// static -const MojoCreateMessagePipeOptions - MessagePipeDispatcher::kDefaultCreateOptions = { - static_cast<uint32_t>(sizeof(MojoCreateMessagePipeOptions)), - MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE}; - -// static -MojoResult MessagePipeDispatcher::ValidateCreateOptions( - UserPointer<const MojoCreateMessagePipeOptions> in_options, - MojoCreateMessagePipeOptions* out_options) { - const MojoCreateMessagePipeOptionsFlags kKnownFlags = - MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE; - - *out_options = kDefaultCreateOptions; - if (in_options.IsNull()) - return MOJO_RESULT_OK; - - UserOptionsReader<MojoCreateMessagePipeOptions> reader(in_options); - if (!reader.is_valid()) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateMessagePipeOptions, flags, reader)) - return MOJO_RESULT_OK; - if ((reader.options().flags & ~kKnownFlags)) - return MOJO_RESULT_UNIMPLEMENTED; - out_options->flags = reader.options().flags; - - // Checks for fields beyond |flags|: - - // (Nothing here yet.) - - return MOJO_RESULT_OK; -} - -void MessagePipeDispatcher::Init(scoped_refptr<MessagePipe> message_pipe, - unsigned port) { - DCHECK(message_pipe); - DCHECK(port == 0 || port == 1); - - message_pipe_ = message_pipe; - port_ = port; -} - -Dispatcher::Type MessagePipeDispatcher::GetType() const { - return Type::MESSAGE_PIPE; -} - -// static -scoped_refptr<MessagePipeDispatcher> -MessagePipeDispatcher::CreateRemoteMessagePipe( - scoped_refptr<ChannelEndpoint>* channel_endpoint) { - scoped_refptr<MessagePipe> message_pipe( - MessagePipe::CreateLocalProxy(channel_endpoint)); - scoped_refptr<MessagePipeDispatcher> dispatcher = - Create(kDefaultCreateOptions); - dispatcher->Init(message_pipe, 0); - return dispatcher; -} - -// static -scoped_refptr<MessagePipeDispatcher> MessagePipeDispatcher::Deserialize( - Channel* channel, - const void* source, - size_t size) { - unsigned port = kInvalidPort; - scoped_refptr<MessagePipe> message_pipe; - if (!MessagePipe::Deserialize(channel, source, size, &message_pipe, &port)) - return nullptr; - DCHECK(message_pipe); - DCHECK(port == 0 || port == 1); - - scoped_refptr<MessagePipeDispatcher> dispatcher = - Create(kDefaultCreateOptions); - dispatcher->Init(message_pipe, port); - return dispatcher; -} - -MessagePipeDispatcher::MessagePipeDispatcher() : port_(kInvalidPort) { -} - -MessagePipeDispatcher::~MessagePipeDispatcher() { - // |Close()|/|CloseImplNoLock()| should have taken care of the pipe. - DCHECK(!message_pipe_); -} - -MessagePipe* MessagePipeDispatcher::GetMessagePipeNoLock() const { - mutex().AssertHeld(); - return message_pipe_.get(); -} - -unsigned MessagePipeDispatcher::GetPortNoLock() const { - mutex().AssertHeld(); - return port_; -} - -void MessagePipeDispatcher::CancelAllAwakablesNoLock() { - mutex().AssertHeld(); - message_pipe_->CancelAllAwakables(port_); -} - -void MessagePipeDispatcher::CloseImplNoLock() { - mutex().AssertHeld(); - message_pipe_->Close(port_); - message_pipe_ = nullptr; - port_ = kInvalidPort; -} - -scoped_refptr<Dispatcher> -MessagePipeDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() { - mutex().AssertHeld(); - - // TODO(vtl): Currently, there are no options, so we just use - // |kDefaultCreateOptions|. Eventually, we'll have to duplicate the options - // too. - scoped_refptr<MessagePipeDispatcher> rv = Create(kDefaultCreateOptions); - rv->Init(message_pipe_, port_); - message_pipe_ = nullptr; - port_ = kInvalidPort; - return scoped_refptr<Dispatcher>(rv.get()); -} - -MojoResult MessagePipeDispatcher::WriteMessageImplNoLock( - UserPointer<const void> bytes, - uint32_t num_bytes, - std::vector<DispatcherTransport>* transports, - MojoWriteMessageFlags flags) { - DCHECK(!transports || - (transports->size() > 0 && - transports->size() <= GetConfiguration().max_message_num_handles)); - - mutex().AssertHeld(); - - if (num_bytes > GetConfiguration().max_message_num_bytes) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - - return message_pipe_->WriteMessage(port_, bytes, num_bytes, transports, - flags); -} - -MojoResult MessagePipeDispatcher::ReadMessageImplNoLock( - UserPointer<void> bytes, - UserPointer<uint32_t> num_bytes, - DispatcherVector* dispatchers, - uint32_t* num_dispatchers, - MojoReadMessageFlags flags) { - mutex().AssertHeld(); - return message_pipe_->ReadMessage(port_, bytes, num_bytes, dispatchers, - num_dispatchers, flags); -} - -HandleSignalsState MessagePipeDispatcher::GetHandleSignalsStateImplNoLock() - const { - mutex().AssertHeld(); - return message_pipe_->GetHandleSignalsState(port_); -} - -MojoResult MessagePipeDispatcher::AddAwakableImplNoLock( - Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state) { - mutex().AssertHeld(); - return message_pipe_->AddAwakable(port_, awakable, signals, context, - signals_state); -} - -void MessagePipeDispatcher::RemoveAwakableImplNoLock( - Awakable* awakable, - HandleSignalsState* signals_state) { - mutex().AssertHeld(); - message_pipe_->RemoveAwakable(port_, awakable, signals_state); -} - -void MessagePipeDispatcher::StartSerializeImplNoLock( - Channel* channel, - size_t* max_size, - size_t* max_platform_handles) { - DCHECK(HasOneRef()); // Only one ref => no need to take the lock. - return message_pipe_->StartSerialize(port_, channel, max_size, - max_platform_handles); -} - -bool MessagePipeDispatcher::EndSerializeAndCloseImplNoLock( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) { - DCHECK(HasOneRef()); // Only one ref => no need to take the lock. - - bool rv = message_pipe_->EndSerialize(port_, channel, destination, - actual_size, platform_handles); - message_pipe_ = nullptr; - port_ = kInvalidPort; - return rv; -} - -// MessagePipeDispatcherTransport ---------------------------------------------- - -MessagePipeDispatcherTransport::MessagePipeDispatcherTransport( - DispatcherTransport transport) - : DispatcherTransport(transport) { - DCHECK_EQ(message_pipe_dispatcher()->GetType(), - Dispatcher::Type::MESSAGE_PIPE); -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.h b/third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.h deleted file mode 100644 index 7caa631..0000000 --- a/third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.h +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MESSAGE_PIPE_DISPATCHER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MESSAGE_PIPE_DISPATCHER_H_ - -#include "base/memory/ref_counted.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/memory.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -class ChannelEndpoint; -class MessagePipe; -class MessagePipeDispatcherTransport; - -// This is the |Dispatcher| implementation for message pipes (created by the -// Mojo primitive |MojoCreateMessagePipe()|). This class is thread-safe. -class MOJO_SYSTEM_IMPL_EXPORT MessagePipeDispatcher final : public Dispatcher { - public: - // The default options to use for |MojoCreateMessagePipe()|. (Real uses - // should obtain this via |ValidateCreateOptions()| with a null |in_options|; - // this is exposed directly for testing convenience.) - static const MojoCreateMessagePipeOptions kDefaultCreateOptions; - - static scoped_refptr<MessagePipeDispatcher> Create( - const MojoCreateMessagePipeOptions& /*validated_options*/) { - return make_scoped_refptr(new MessagePipeDispatcher()); - } - - // Validates and/or sets default options for |MojoCreateMessagePipeOptions|. - // If non-null, |in_options| must point to a struct of at least - // |in_options->struct_size| bytes. |out_options| must point to a (current) - // |MojoCreateMessagePipeOptions| and will be entirely overwritten on success - // (it may be partly overwritten on failure). - static MojoResult ValidateCreateOptions( - UserPointer<const MojoCreateMessagePipeOptions> in_options, - MojoCreateMessagePipeOptions* out_options); - - // Must be called before any other methods. (This method is not thread-safe.) - void Init(scoped_refptr<MessagePipe> message_pipe, - unsigned port) MOJO_NOT_THREAD_SAFE; - - // |Dispatcher| public methods: - Type GetType() const override; - - // Creates a |MessagePipe| with a local endpoint (at port 0) and a proxy - // endpoint, and creates/initializes a |MessagePipeDispatcher| (attached to - // the message pipe, port 0). - // TODO(vtl): This currently uses |kDefaultCreateOptions|, which is okay since - // there aren't any options, but eventually options should be plumbed through. - static scoped_refptr<MessagePipeDispatcher> CreateRemoteMessagePipe( - scoped_refptr<ChannelEndpoint>* channel_endpoint); - - // The "opposite" of |SerializeAndClose()|. (Typically this is called by - // |Dispatcher::Deserialize()|.) - static scoped_refptr<MessagePipeDispatcher> Deserialize(Channel* channel, - const void* source, - size_t size); - - private: - friend class MessagePipeDispatcherTransport; - - MessagePipeDispatcher(); - ~MessagePipeDispatcher() override; - - // Gets a dumb pointer to |message_pipe_|. This must be called under the - // |Dispatcher| lock (that it's a dumb pointer is okay since it's under lock). - // This is needed when sending handles across processes, where nontrivial, - // invasive work needs to be done. - MessagePipe* GetMessagePipeNoLock() const; - // Similarly for the port. - unsigned GetPortNoLock() const; - - // |Dispatcher| protected methods: - void CancelAllAwakablesNoLock() override; - void CloseImplNoLock() override; - scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock() - override; - MojoResult WriteMessageImplNoLock( - UserPointer<const void> bytes, - uint32_t num_bytes, - std::vector<DispatcherTransport>* transports, - MojoWriteMessageFlags flags) override; - MojoResult ReadMessageImplNoLock(UserPointer<void> bytes, - UserPointer<uint32_t> num_bytes, - DispatcherVector* dispatchers, - uint32_t* num_dispatchers, - MojoReadMessageFlags flags) override; - HandleSignalsState GetHandleSignalsStateImplNoLock() const override; - MojoResult AddAwakableImplNoLock(Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state) override; - void RemoveAwakableImplNoLock(Awakable* awakable, - HandleSignalsState* signals_state) override; - void StartSerializeImplNoLock(Channel* channel, - size_t* max_size, - size_t* max_platform_handles) override - MOJO_NOT_THREAD_SAFE; - bool EndSerializeAndCloseImplNoLock( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) override - MOJO_NOT_THREAD_SAFE; - - // This will be null if closed. - scoped_refptr<MessagePipe> message_pipe_ MOJO_GUARDED_BY(mutex()); - unsigned port_ MOJO_GUARDED_BY(mutex()); - - MOJO_DISALLOW_COPY_AND_ASSIGN(MessagePipeDispatcher); -}; - -class MessagePipeDispatcherTransport : public DispatcherTransport { - public: - explicit MessagePipeDispatcherTransport(DispatcherTransport transport); - - MessagePipe* GetMessagePipe() { - return message_pipe_dispatcher()->GetMessagePipeNoLock(); - } - unsigned GetPort() { return message_pipe_dispatcher()->GetPortNoLock(); } - - private: - MessagePipeDispatcher* message_pipe_dispatcher() { - return static_cast<MessagePipeDispatcher*>(dispatcher()); - } - - // Copy and assign allowed. -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MESSAGE_PIPE_DISPATCHER_H_ diff --git a/third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher_unittest.cc b/third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher_unittest.cc deleted file mode 100644 index 53f5223..0000000 --- a/third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher_unittest.cc +++ /dev/null @@ -1,690 +0,0 @@ -// Copyright 2013 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. - -// NOTE(vtl): Some of these tests are inherently flaky (e.g., if run on a -// heavily-loaded system). Sorry. |test::EpsilonDeadline()| may be increased to -// increase tolerance and reduce observed flakiness (though doing so reduces the -// meaningfulness of the test). - -#include "third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.h" - -#include <string.h> - -#include <limits> - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_vector.h" -#include "base/rand_util.h" -#include "base/threading/simple_thread.h" -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/test_utils.h" -#include "third_party/mojo/src/mojo/edk/system/waiter.h" -#include "third_party/mojo/src/mojo/edk/system/waiter_test_utils.h" - -namespace mojo { -namespace system { -namespace { - -const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED; - -TEST(MessagePipeDispatcherTest, Basic) { - test::Stopwatch stopwatch; - int32_t buffer[1]; - const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); - uint32_t buffer_size; - - // Run this test both with |d0| as port 0, |d1| as port 1 and vice versa. - for (unsigned i = 0; i < 2; i++) { - scoped_refptr<MessagePipeDispatcher> d0 = MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - EXPECT_EQ(Dispatcher::Type::MESSAGE_PIPE, d0->GetType()); - scoped_refptr<MessagePipeDispatcher> d1 = MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - { - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); - d0->Init(mp, i); // 0, 1. - d1->Init(mp, i ^ 1); // 1, 0. - } - Waiter w; - uintptr_t context = 0; - HandleSignalsState hss; - - // Try adding a writable waiter when already writable. - w.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - // Shouldn't need to remove the waiter (it was not added). - - // Add a readable waiter to |d0|, then make it readable (by writing to - // |d1|), then wait. - w.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 1, nullptr)); - buffer[0] = 123456789; - EXPECT_EQ(MOJO_RESULT_OK, - d1->WriteMessage(UserPointer<const void>(buffer), kBufferSize, - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - stopwatch.Start(); - EXPECT_EQ(MOJO_RESULT_OK, w.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_EQ(1u, context); - EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); - hss = HandleSignalsState(); - d0->RemoveAwakable(&w, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - // Try adding a readable waiter when already readable (from above). - w.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 2, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - // Shouldn't need to remove the waiter (it was not added). - - // Make |d0| no longer readable (by reading from it). - buffer[0] = 0; - buffer_size = kBufferSize; - EXPECT_EQ(MOJO_RESULT_OK, - d0->ReadMessage(UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kBufferSize, buffer_size); - EXPECT_EQ(123456789, buffer[0]); - - // Wait for zero time for readability on |d0| (will time out). - w.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 3, nullptr)); - stopwatch.Start(); - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0, nullptr)); - EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); - hss = HandleSignalsState(); - d0->RemoveAwakable(&w, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - // Wait for non-zero, finite time for readability on |d0| (will time out). - w.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 3, nullptr)); - stopwatch.Start(); - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, - w.Wait(2 * test::EpsilonDeadline(), nullptr)); - MojoDeadline elapsed = stopwatch.Elapsed(); - EXPECT_GT(elapsed, (2 - 1) * test::EpsilonDeadline()); - EXPECT_LT(elapsed, (2 + 1) * test::EpsilonDeadline()); - hss = HandleSignalsState(); - d0->RemoveAwakable(&w, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - // Check the peer closed signal. - w.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 12, nullptr)); - - // Close the peer. - EXPECT_EQ(MOJO_RESULT_OK, d1->Close()); - - // It should be signaled. - EXPECT_EQ(MOJO_RESULT_OK, w.Wait(test::TinyDeadline(), &context)); - EXPECT_EQ(12u, context); - hss = HandleSignalsState(); - d0->RemoveAwakable(&w, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - EXPECT_EQ(MOJO_RESULT_OK, d0->Close()); - } -} - -TEST(MessagePipeDispatcherTest, InvalidParams) { - char buffer[1]; - - scoped_refptr<MessagePipeDispatcher> d0 = MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - scoped_refptr<MessagePipeDispatcher> d1 = MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - { - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); - d0->Init(mp, 0); - d1->Init(mp, 1); - } - - // |WriteMessage|: - // Huge buffer size. - EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, - d0->WriteMessage(UserPointer<const void>(buffer), - std::numeric_limits<uint32_t>::max(), nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - EXPECT_EQ(MOJO_RESULT_OK, d0->Close()); - EXPECT_EQ(MOJO_RESULT_OK, d1->Close()); -} - -// These test invalid arguments that should cause death if we're being paranoid -// about checking arguments (which we would want to do if, e.g., we were in a -// true "kernel" situation, but we might not want to do otherwise for -// performance reasons). Probably blatant errors like passing in null pointers -// (for required pointer arguments) will still cause death, but perhaps not -// predictably. -TEST(MessagePipeDispatcherTest, InvalidParamsDeath) { - const char kMemoryCheckFailedRegex[] = "Check failed"; - - scoped_refptr<MessagePipeDispatcher> d0 = MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - scoped_refptr<MessagePipeDispatcher> d1 = MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - { - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); - d0->Init(mp, 0); - d1->Init(mp, 1); - } - - // |WriteMessage|: - // Null buffer with nonzero buffer size. - EXPECT_DEATH_IF_SUPPORTED(d0->WriteMessage(NullUserPointer(), 1, nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE), - kMemoryCheckFailedRegex); - - // |ReadMessage|: - // Null buffer with nonzero buffer size. - // First write something so that we actually have something to read. - EXPECT_EQ(MOJO_RESULT_OK, - d1->WriteMessage(UserPointer<const void>("x"), 1, nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - uint32_t buffer_size = 1; - EXPECT_DEATH_IF_SUPPORTED( - d0->ReadMessage(NullUserPointer(), MakeUserPointer(&buffer_size), 0, - nullptr, MOJO_READ_MESSAGE_FLAG_NONE), - kMemoryCheckFailedRegex); - - EXPECT_EQ(MOJO_RESULT_OK, d0->Close()); - EXPECT_EQ(MOJO_RESULT_OK, d1->Close()); -} - -// Test what happens when one end is closed (single-threaded test). -TEST(MessagePipeDispatcherTest, BasicClosed) { - int32_t buffer[1]; - const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); - uint32_t buffer_size; - - // Run this test both with |d0| as port 0, |d1| as port 1 and vice versa. - for (unsigned i = 0; i < 2; i++) { - scoped_refptr<MessagePipeDispatcher> d0 = MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - scoped_refptr<MessagePipeDispatcher> d1 = MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - { - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); - d0->Init(mp, i); // 0, 1. - d1->Init(mp, i ^ 1); // 1, 0. - } - Waiter w; - HandleSignalsState hss; - - // Write (twice) to |d1|. - buffer[0] = 123456789; - EXPECT_EQ(MOJO_RESULT_OK, - d1->WriteMessage(UserPointer<const void>(buffer), kBufferSize, - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - buffer[0] = 234567890; - EXPECT_EQ(MOJO_RESULT_OK, - d1->WriteMessage(UserPointer<const void>(buffer), kBufferSize, - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Try waiting for readable on |d0|; should fail (already satisfied). - w.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - // Try reading from |d1|; should fail (nothing to read). - buffer[0] = 0; - buffer_size = kBufferSize; - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - d1->ReadMessage(UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - - // Close |d1|. - EXPECT_EQ(MOJO_RESULT_OK, d1->Close()); - - // Try waiting for readable on |d0|; should fail (already satisfied). - w.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 1, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Read from |d0|. - buffer[0] = 0; - buffer_size = kBufferSize; - EXPECT_EQ(MOJO_RESULT_OK, - d0->ReadMessage(UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kBufferSize, buffer_size); - EXPECT_EQ(123456789, buffer[0]); - - // Try waiting for readable on |d0|; should fail (already satisfied). - w.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 2, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Read again from |d0|. - buffer[0] = 0; - buffer_size = kBufferSize; - EXPECT_EQ(MOJO_RESULT_OK, - d0->ReadMessage(UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kBufferSize, buffer_size); - EXPECT_EQ(234567890, buffer[0]); - - // Try waiting for readable on |d0|; should fail (unsatisfiable). - w.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 3, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - // Try waiting for writable on |d0|; should fail (unsatisfiable). - w.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - // Try reading from |d0|; should fail (nothing to read and other end - // closed). - buffer[0] = 0; - buffer_size = kBufferSize; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - d0->ReadMessage(UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - - // Try writing to |d0|; should fail (other end closed). - buffer[0] = 345678901; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - d0->WriteMessage(UserPointer<const void>(buffer), kBufferSize, - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - EXPECT_EQ(MOJO_RESULT_OK, d0->Close()); - } -} - -#if defined(OS_WIN) -// http://crbug.com/396386 -#define MAYBE_BasicThreaded DISABLED_BasicThreaded -#else -#define MAYBE_BasicThreaded BasicThreaded -#endif -TEST(MessagePipeDispatcherTest, MAYBE_BasicThreaded) { - test::Stopwatch stopwatch; - int32_t buffer[1]; - const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); - uint32_t buffer_size; - MojoDeadline elapsed; - bool did_wait; - MojoResult result; - uintptr_t context; - HandleSignalsState hss; - - // Run this test both with |d0| as port 0, |d1| as port 1 and vice versa. - for (unsigned i = 0; i < 2; i++) { - scoped_refptr<MessagePipeDispatcher> d0 = MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - scoped_refptr<MessagePipeDispatcher> d1 = MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - { - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); - d0->Init(mp, i); // 0, 1. - d1->Init(mp, i ^ 1); // 1, 0. - } - - // Wait for readable on |d1|, which will become readable after some time. - { - test::WaiterThread thread(d1, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, 1, &did_wait, &result, - &context, &hss); - stopwatch.Start(); - thread.Start(); - test::Sleep(2 * test::EpsilonDeadline()); - // Wake it up by writing to |d0|. - buffer[0] = 123456789; - EXPECT_EQ(MOJO_RESULT_OK, - d0->WriteMessage(UserPointer<const void>(buffer), kBufferSize, - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - } // Joins the thread. - elapsed = stopwatch.Elapsed(); - EXPECT_GT(elapsed, (2 - 1) * test::EpsilonDeadline()); - EXPECT_LT(elapsed, (2 + 1) * test::EpsilonDeadline()); - EXPECT_TRUE(did_wait); - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(1u, context); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - // Now |d1| is already readable. Try waiting for it again. - { - test::WaiterThread thread(d1, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, 2, &did_wait, &result, - &context, &hss); - stopwatch.Start(); - thread.Start(); - } // Joins the thread. - EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); - EXPECT_FALSE(did_wait); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, result); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - // Consume what we wrote to |d0|. - buffer[0] = 0; - buffer_size = kBufferSize; - EXPECT_EQ(MOJO_RESULT_OK, - d1->ReadMessage(UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kBufferSize, buffer_size); - EXPECT_EQ(123456789, buffer[0]); - - // Wait for readable on |d1| and close |d0| after some time, which should - // cancel that wait. - { - test::WaiterThread thread(d1, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, 3, &did_wait, &result, - &context, &hss); - stopwatch.Start(); - thread.Start(); - test::Sleep(2 * test::EpsilonDeadline()); - EXPECT_EQ(MOJO_RESULT_OK, d0->Close()); - } // Joins the thread. - elapsed = stopwatch.Elapsed(); - EXPECT_GT(elapsed, (2 - 1) * test::EpsilonDeadline()); - EXPECT_LT(elapsed, (2 + 1) * test::EpsilonDeadline()); - EXPECT_TRUE(did_wait); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); - EXPECT_EQ(3u, context); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - EXPECT_EQ(MOJO_RESULT_OK, d1->Close()); - } - - for (unsigned i = 0; i < 2; i++) { - scoped_refptr<MessagePipeDispatcher> d0 = MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - scoped_refptr<MessagePipeDispatcher> d1 = MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - { - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); - d0->Init(mp, i); // 0, 1. - d1->Init(mp, i ^ 1); // 1, 0. - } - - // Wait for readable on |d1| and close |d1| after some time, which should - // cancel that wait. - { - test::WaiterThread thread(d1, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, 4, &did_wait, &result, - &context, &hss); - stopwatch.Start(); - thread.Start(); - test::Sleep(2 * test::EpsilonDeadline()); - EXPECT_EQ(MOJO_RESULT_OK, d1->Close()); - } // Joins the thread. - elapsed = stopwatch.Elapsed(); - EXPECT_GT(elapsed, (2 - 1) * test::EpsilonDeadline()); - EXPECT_LT(elapsed, (2 + 1) * test::EpsilonDeadline()); - EXPECT_TRUE(did_wait); - EXPECT_EQ(MOJO_RESULT_CANCELLED, result); - EXPECT_EQ(4u, context); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - - EXPECT_EQ(MOJO_RESULT_OK, d0->Close()); - } -} - -// Stress test ----------------------------------------------------------------- - -const size_t kMaxMessageSize = 2000; - -class WriterThread : public base::SimpleThread { - public: - // |*messages_written| and |*bytes_written| belong to the thread while it's - // alive. - WriterThread(scoped_refptr<Dispatcher> write_dispatcher, - size_t* messages_written, - size_t* bytes_written) - : base::SimpleThread("writer_thread"), - write_dispatcher_(write_dispatcher), - messages_written_(messages_written), - bytes_written_(bytes_written) { - *messages_written_ = 0; - *bytes_written_ = 0; - } - - ~WriterThread() override { Join(); } - - private: - void Run() override { - // Make some data to write. - unsigned char buffer[kMaxMessageSize]; - for (size_t i = 0; i < kMaxMessageSize; i++) - buffer[i] = static_cast<unsigned char>(i); - - // Number of messages to write. - *messages_written_ = static_cast<size_t>(base::RandInt(1000, 6000)); - - // Write messages. - for (size_t i = 0; i < *messages_written_; i++) { - uint32_t bytes_to_write = static_cast<uint32_t>( - base::RandInt(1, static_cast<int>(kMaxMessageSize))); - EXPECT_EQ(MOJO_RESULT_OK, - write_dispatcher_->WriteMessage(UserPointer<const void>(buffer), - bytes_to_write, nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - *bytes_written_ += bytes_to_write; - } - - // Write one last "quit" message. - EXPECT_EQ(MOJO_RESULT_OK, write_dispatcher_->WriteMessage( - UserPointer<const void>("quit"), 4, nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - } - - const scoped_refptr<Dispatcher> write_dispatcher_; - size_t* const messages_written_; - size_t* const bytes_written_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(WriterThread); -}; - -class ReaderThread : public base::SimpleThread { - public: - // |*messages_read| and |*bytes_read| belong to the thread while it's alive. - ReaderThread(scoped_refptr<Dispatcher> read_dispatcher, - size_t* messages_read, - size_t* bytes_read) - : base::SimpleThread("reader_thread"), - read_dispatcher_(read_dispatcher), - messages_read_(messages_read), - bytes_read_(bytes_read) { - *messages_read_ = 0; - *bytes_read_ = 0; - } - - ~ReaderThread() override { Join(); } - - private: - void Run() override { - unsigned char buffer[kMaxMessageSize]; - Waiter w; - HandleSignalsState hss; - MojoResult result; - - // Read messages. - for (;;) { - // Wait for it to be readable. - w.Init(); - hss = HandleSignalsState(); - result = read_dispatcher_->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, - &hss); - EXPECT_TRUE(result == MOJO_RESULT_OK || - result == MOJO_RESULT_ALREADY_EXISTS) - << "result: " << result; - if (result == MOJO_RESULT_OK) { - // Actually need to wait. - EXPECT_EQ(MOJO_RESULT_OK, w.Wait(MOJO_DEADLINE_INDEFINITE, nullptr)); - read_dispatcher_->RemoveAwakable(&w, &hss); - } - // We may not actually be readable, since we're racing with other threads. - EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); - - // Now, try to do the read. - // Clear the buffer so that we can check the result. - memset(buffer, 0, sizeof(buffer)); - uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); - result = read_dispatcher_->ReadMessage( - UserPointer<void>(buffer), MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE); - EXPECT_TRUE(result == MOJO_RESULT_OK || result == MOJO_RESULT_SHOULD_WAIT) - << "result: " << result; - // We're racing with others to read, so maybe we failed. - if (result == MOJO_RESULT_SHOULD_WAIT) - continue; // In which case, try again. - // Check for quit. - if (buffer_size == 4 && memcmp("quit", buffer, 4) == 0) - return; - EXPECT_GE(buffer_size, 1u); - EXPECT_LE(buffer_size, kMaxMessageSize); - EXPECT_TRUE(IsValidMessage(buffer, buffer_size)); - - (*messages_read_)++; - *bytes_read_ += buffer_size; - } - } - - static bool IsValidMessage(const unsigned char* buffer, - uint32_t message_size) { - size_t i; - for (i = 0; i < message_size; i++) { - if (buffer[i] != static_cast<unsigned char>(i)) - return false; - } - // Check that the remaining bytes weren't stomped on. - for (; i < kMaxMessageSize; i++) { - if (buffer[i] != 0) - return false; - } - return true; - } - - const scoped_refptr<Dispatcher> read_dispatcher_; - size_t* const messages_read_; - size_t* const bytes_read_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ReaderThread); -}; - -TEST(MessagePipeDispatcherTest, Stress) { - static const size_t kNumWriters = 30; - static const size_t kNumReaders = kNumWriters; - - scoped_refptr<MessagePipeDispatcher> d_write = MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - scoped_refptr<MessagePipeDispatcher> d_read = MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - { - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); - d_write->Init(mp, 0); - d_read->Init(mp, 1); - } - - size_t messages_written[kNumWriters]; - size_t bytes_written[kNumWriters]; - size_t messages_read[kNumReaders]; - size_t bytes_read[kNumReaders]; - { - // Make writers. - ScopedVector<WriterThread> writers; - for (size_t i = 0; i < kNumWriters; i++) { - writers.push_back( - new WriterThread(d_write, &messages_written[i], &bytes_written[i])); - } - - // Make readers. - ScopedVector<ReaderThread> readers; - for (size_t i = 0; i < kNumReaders; i++) { - readers.push_back( - new ReaderThread(d_read, &messages_read[i], &bytes_read[i])); - } - - // Start writers. - for (size_t i = 0; i < kNumWriters; i++) - writers[i]->Start(); - - // Start readers. - for (size_t i = 0; i < kNumReaders; i++) - readers[i]->Start(); - - // TODO(vtl): Maybe I should have an event that triggers all the threads to - // start doing stuff for real (so that the first ones created/started aren't - // advantaged). - } // Joins all the threads. - - size_t total_messages_written = 0; - size_t total_bytes_written = 0; - for (size_t i = 0; i < kNumWriters; i++) { - total_messages_written += messages_written[i]; - total_bytes_written += bytes_written[i]; - } - size_t total_messages_read = 0; - size_t total_bytes_read = 0; - for (size_t i = 0; i < kNumReaders; i++) { - total_messages_read += messages_read[i]; - total_bytes_read += bytes_read[i]; - // We'd have to be really unlucky to have read no messages on a thread. - EXPECT_GT(messages_read[i], 0u) << "reader: " << i; - EXPECT_GE(bytes_read[i], messages_read[i]) << "reader: " << i; - } - EXPECT_EQ(total_messages_written, total_messages_read); - EXPECT_EQ(total_bytes_written, total_bytes_read); - - EXPECT_EQ(MOJO_RESULT_OK, d_write->Close()); - EXPECT_EQ(MOJO_RESULT_OK, d_read->Close()); -} - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/message_pipe_endpoint.cc b/third_party/mojo/src/mojo/edk/system/message_pipe_endpoint.cc deleted file mode 100644 index 8b1ef38..0000000 --- a/third_party/mojo/src/mojo/edk/system/message_pipe_endpoint.cc +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/message_pipe_endpoint.h" - -#include "base/logging.h" - -namespace mojo { -namespace system { - -void MessagePipeEndpoint::CancelAllAwakables() { - NOTREACHED(); -} - -MojoResult MessagePipeEndpoint::ReadMessage(UserPointer<void> /*bytes*/, - UserPointer<uint32_t> /*num_bytes*/, - DispatcherVector* /*dispatchers*/, - uint32_t* /*num_dispatchers*/, - MojoReadMessageFlags /*flags*/) { - NOTREACHED(); - return MOJO_RESULT_INTERNAL; -} - -HandleSignalsState MessagePipeEndpoint::GetHandleSignalsState() const { - NOTREACHED(); - return HandleSignalsState(); -} - -MojoResult MessagePipeEndpoint::AddAwakable(Awakable* /*awakable*/, - MojoHandleSignals /*signals*/, - uintptr_t /*context*/, - HandleSignalsState* signals_state) { - NOTREACHED(); - if (signals_state) - *signals_state = HandleSignalsState(); - return MOJO_RESULT_INTERNAL; -} - -void MessagePipeEndpoint::RemoveAwakable(Awakable* /*awakable*/, - HandleSignalsState* signals_state) { - NOTREACHED(); - if (signals_state) - *signals_state = HandleSignalsState(); -} - -void MessagePipeEndpoint::Attach(ChannelEndpoint* /*channel_endpoint*/) { - NOTREACHED(); -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/message_pipe_endpoint.h b/third_party/mojo/src/mojo/edk/system/message_pipe_endpoint.h deleted file mode 100644 index c278f56..0000000 --- a/third_party/mojo/src/mojo/edk/system/message_pipe_endpoint.h +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MESSAGE_PIPE_ENDPOINT_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MESSAGE_PIPE_ENDPOINT_H_ - -#include <stdint.h> - -#include <vector> - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/public/c/system/message_pipe.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/memory.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -class ChannelEndpoint; -class Awakable; - -// This is an interface to one of the ends of a message pipe, and is used by -// |MessagePipe|. Its most important role is to provide a sink for messages -// (i.e., a place where messages can be sent). It has a secondary role: When the -// endpoint is local (i.e., in the current process), there'll be a dispatcher -// corresponding to the endpoint. In that case, the implementation of -// |MessagePipeEndpoint| also implements the functionality required by the -// dispatcher, e.g., to read messages and to wait. Implementations of this class -// are not thread-safe; instances are protected by |MesssagePipe|'s lock. -class MOJO_SYSTEM_IMPL_EXPORT MessagePipeEndpoint { - public: - virtual ~MessagePipeEndpoint() {} - - enum Type { kTypeLocal, kTypeProxy }; - virtual Type GetType() const = 0; - - // All implementations must implement these. - // Returns false if the endpoint should be closed and destroyed, else true. - virtual bool OnPeerClose() = 0; - // Implements |MessagePipe::EnqueueMessage()|. The major differences are that: - // a) Dispatchers have been vetted and cloned/attached to the message. - // b) At this point, we cannot report failure (if, e.g., a channel is torn - // down at this point, we should silently swallow the message). - virtual void EnqueueMessage(scoped_ptr<MessageInTransit> message) = 0; - virtual void Close() = 0; - - // Implementations must override these if they represent a local endpoint, - // i.e., one for which there's a |MessagePipeDispatcher| (and thus a handle). - // An implementation for a proxy endpoint (for which there's no dispatcher) - // needs not override these methods, since they should never be called. - // - // These methods implement the methods of the same name in |MessagePipe|, - // though |MessagePipe|'s implementation may have to do a little more if the - // operation involves both endpoints. - virtual void CancelAllAwakables(); - virtual MojoResult ReadMessage(UserPointer<void> bytes, - UserPointer<uint32_t> num_bytes, - DispatcherVector* dispatchers, - uint32_t* num_dispatchers, - MojoReadMessageFlags flags); - virtual HandleSignalsState GetHandleSignalsState() const; - virtual MojoResult AddAwakable(Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state); - virtual void RemoveAwakable(Awakable* awakable, - HandleSignalsState* signals_state); - - // Implementations must override these if they represent a proxy endpoint. An - // implementation for a local endpoint needs not override these methods, since - // they should never be called. - virtual void Attach(ChannelEndpoint* channel_endpoint); - - protected: - MessagePipeEndpoint() {} - - private: - MOJO_DISALLOW_COPY_AND_ASSIGN(MessagePipeEndpoint); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MESSAGE_PIPE_ENDPOINT_H_ diff --git a/third_party/mojo/src/mojo/edk/system/message_pipe_perftest.cc b/third_party/mojo/src/mojo/edk/system/message_pipe_perftest.cc deleted file mode 100644 index dd3b777..0000000 --- a/third_party/mojo/src/mojo/edk/system/message_pipe_perftest.cc +++ /dev/null @@ -1,168 +0,0 @@ -// 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 <stdint.h> -#include <stdio.h> -#include <string.h> -#include <string> -#include <utility> -#include <vector> - -#include "base/bind.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/strings/stringprintf.h" -#include "base/test/perf_time_logger.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" -#include "third_party/mojo/src/mojo/edk/system/channel.h" -#include "third_party/mojo/src/mojo/edk/system/local_message_pipe_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe_test_utils.h" -#include "third_party/mojo/src/mojo/edk/system/proxy_message_pipe_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/raw_channel.h" -#include "third_party/mojo/src/mojo/edk/system/test_utils.h" -#include "third_party/mojo/src/mojo/edk/test/test_utils.h" - -namespace mojo { -namespace system { -namespace { - -class MultiprocessMessagePipePerfTest - : public test::MultiprocessMessagePipeTestBase { - public: - MultiprocessMessagePipePerfTest() : message_count_(0), message_size_(0) {} - - void SetUpMeasurement(int message_count, size_t message_size) { - message_count_ = message_count; - message_size_ = message_size; - payload_ = std::string(message_size, '*'); - read_buffer_.resize(message_size * 2); - } - - protected: - void WriteWaitThenRead(scoped_refptr<MessagePipe> mp) { - CHECK_EQ(mp->WriteMessage(0, UserPointer<const void>(payload_.data()), - static_cast<uint32_t>(payload_.size()), nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - HandleSignalsState hss; - CHECK_EQ(test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss), - MOJO_RESULT_OK); - uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer_.size()); - CHECK_EQ(mp->ReadMessage(0, UserPointer<void>(&read_buffer_[0]), - MakeUserPointer(&read_buffer_size), nullptr, - nullptr, MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - CHECK_EQ(read_buffer_size, static_cast<uint32_t>(payload_.size())); - } - - void SendQuitMessage(scoped_refptr<MessagePipe> mp) { - CHECK_EQ(mp->WriteMessage(0, UserPointer<const void>(""), 0, nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - } - - void Measure(scoped_refptr<MessagePipe> mp) { - // Have one ping-pong to ensure channel being established. - WriteWaitThenRead(mp); - - std::string test_name = - base::StringPrintf("IPC_Perf_%dx_%u", message_count_, - static_cast<unsigned>(message_size_)); - base::PerfTimeLogger logger(test_name.c_str()); - - for (int i = 0; i < message_count_; ++i) - WriteWaitThenRead(mp); - - logger.Done(); - } - - private: - int message_count_; - size_t message_size_; - std::string payload_; - std::string read_buffer_; - scoped_ptr<base::PerfTimeLogger> perf_logger_; -}; - -// For each message received, sends a reply message with the same contents -// repeated twice, until the other end is closed or it receives "quitquitquit" -// (which it doesn't reply to). It'll return the number of messages received, -// not including any "quitquitquit" message, modulo 100. -MOJO_MULTIPROCESS_TEST_CHILD_MAIN(PingPongClient) { - embedder::SimplePlatformSupport platform_support; - test::ChannelThread channel_thread(&platform_support); - embedder::ScopedPlatformHandle client_platform_handle = - std::move(mojo::test::MultiprocessTestHelper::client_platform_handle); - CHECK(client_platform_handle.is_valid()); - scoped_refptr<ChannelEndpoint> ep; - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep)); - channel_thread.Start(std::move(client_platform_handle), ep); - - std::string buffer(1000000, '\0'); - int rv = 0; - while (true) { - // Wait for our end of the message pipe to be readable. - HandleSignalsState hss; - MojoResult result = - test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss); - if (result != MOJO_RESULT_OK) { - rv = result; - break; - } - - uint32_t read_size = static_cast<uint32_t>(buffer.size()); - CHECK_EQ(mp->ReadMessage(0, UserPointer<void>(&buffer[0]), - MakeUserPointer(&read_size), nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - - // Empty message indicates quit. - if (read_size == 0) - break; - - CHECK_EQ(mp->WriteMessage(0, UserPointer<const void>(&buffer[0]), - static_cast<uint32_t>(read_size), nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - } - - mp->Close(0); - return rv; -} - -// Repeatedly sends messages as previous one got replied by the child. -// Waits for the child to close its end before quitting once specified -// number of messages has been sent. -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_PingPong DISABLED_PingPong -#else -#define MAYBE_PingPong PingPong -#endif // defined(OS_ANDROID) -TEST_F(MultiprocessMessagePipePerfTest, MAYBE_PingPong) { - helper()->StartChild("PingPongClient"); - - scoped_refptr<ChannelEndpoint> ep; - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep)); - Init(ep); - - // This values are set to align with one at ipc_pertests.cc for comparison. - const size_t kMsgSize[5] = {12, 144, 1728, 20736, 248832}; - const int kMessageCount[5] = {50000, 50000, 50000, 12000, 1000}; - - for (size_t i = 0; i < 5; i++) { - SetUpMeasurement(kMessageCount[i], kMsgSize[i]); - Measure(mp); - } - - SendQuitMessage(mp); - mp->Close(0); - EXPECT_EQ(0, helper()->WaitForChildShutdown()); -} - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/message_pipe_test_utils.cc b/third_party/mojo/src/mojo/edk/system/message_pipe_test_utils.cc deleted file mode 100644 index c2339e0..0000000 --- a/third_party/mojo/src/mojo/edk/system/message_pipe_test_utils.cc +++ /dev/null @@ -1,111 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/message_pipe_test_utils.h" - -#include <utility> - -#include "base/bind.h" -#include "third_party/mojo/src/mojo/edk/system/channel.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/test_utils.h" -#include "third_party/mojo/src/mojo/edk/system/waiter.h" - -namespace mojo { -namespace system { -namespace test { - -MojoResult WaitIfNecessary(scoped_refptr<MessagePipe> mp, - MojoHandleSignals signals, - HandleSignalsState* signals_state) { - Waiter waiter; - waiter.Init(); - - MojoResult add_result = - mp->AddAwakable(0, &waiter, signals, 0, signals_state); - if (add_result != MOJO_RESULT_OK) { - return (add_result == MOJO_RESULT_ALREADY_EXISTS) ? MOJO_RESULT_OK - : add_result; - } - - MojoResult wait_result = waiter.Wait(MOJO_DEADLINE_INDEFINITE, nullptr); - mp->RemoveAwakable(0, &waiter, signals_state); - return wait_result; -} - -ChannelThread::ChannelThread(embedder::PlatformSupport* platform_support) - : platform_support_(platform_support), - test_io_thread_(base::TestIOThread::kManualStart) { -} - -ChannelThread::~ChannelThread() { - Stop(); -} - -void ChannelThread::Start(embedder::ScopedPlatformHandle platform_handle, - scoped_refptr<ChannelEndpoint> channel_endpoint) { - test_io_thread_.Start(); - test_io_thread_.PostTaskAndWait( - FROM_HERE, - base::Bind(&ChannelThread::InitChannelOnIOThread, base::Unretained(this), - base::Passed(&platform_handle), channel_endpoint)); -} - -void ChannelThread::Stop() { - if (channel_) { - // Hack to flush write buffers before quitting. - // TODO(vtl): Remove this once |Channel| has a - // |FlushWriteBufferAndShutdown()| (or whatever). - while (!channel_->IsWriteBufferEmpty()) - test::Sleep(test::DeadlineFromMilliseconds(20)); - - test_io_thread_.PostTaskAndWait( - FROM_HERE, base::Bind(&ChannelThread::ShutdownChannelOnIOThread, - base::Unretained(this))); - } - test_io_thread_.Stop(); -} - -void ChannelThread::InitChannelOnIOThread( - embedder::ScopedPlatformHandle platform_handle, - scoped_refptr<ChannelEndpoint> channel_endpoint) { - CHECK_EQ(base::MessageLoop::current(), test_io_thread_.message_loop()); - CHECK(platform_handle.is_valid()); - - // Create and initialize |Channel|. - channel_ = new Channel(platform_support_); - channel_->Init(RawChannel::Create(std::move(platform_handle))); - - // Start the bootstrap endpoint. - // Note: On the "server" (parent process) side, we need not attach/run the - // endpoint immediately. However, on the "client" (child process) side, this - // *must* be done here -- otherwise, the |Channel| may receive/process - // messages (which it can do as soon as it's hooked up to the IO thread - // message loop, and that message loop runs) before the endpoint is attached. - channel_->SetBootstrapEndpoint(channel_endpoint); -} - -void ChannelThread::ShutdownChannelOnIOThread() { - CHECK(channel_); - channel_->Shutdown(); - channel_ = nullptr; -} - -#if !defined(OS_IOS) -MultiprocessMessagePipeTestBase::MultiprocessMessagePipeTestBase() - : channel_thread_(&platform_support_) { -} - -MultiprocessMessagePipeTestBase::~MultiprocessMessagePipeTestBase() { -} - -void MultiprocessMessagePipeTestBase::Init(scoped_refptr<ChannelEndpoint> ep) { - channel_thread_.Start(std::move(helper_.server_platform_handle), ep); -} -#endif - -} // namespace test -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/message_pipe_test_utils.h b/third_party/mojo/src/mojo/edk/system/message_pipe_test_utils.h deleted file mode 100644 index 3ee386c..0000000 --- a/third_party/mojo/src/mojo/edk/system/message_pipe_test_utils.h +++ /dev/null @@ -1,74 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MESSAGE_PIPE_TEST_UTILS_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MESSAGE_PIPE_TEST_UTILS_H_ - -#include "base/test/test_io_thread.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h" -#include "third_party/mojo/src/mojo/edk/system/channel.h" -#include "third_party/mojo/src/mojo/edk/system/test_utils.h" -#include "third_party/mojo/src/mojo/edk/test/multiprocess_test_helper.h" - -namespace mojo { -namespace system { - -class Channel; -class ChannelEndpoint; -class MessagePipe; - -namespace test { - -MojoResult WaitIfNecessary(scoped_refptr<MessagePipe> mp, - MojoHandleSignals signals, - HandleSignalsState* signals_state); - -class ChannelThread { - public: - explicit ChannelThread(embedder::PlatformSupport* platform_support); - ~ChannelThread(); - - void Start(embedder::ScopedPlatformHandle platform_handle, - scoped_refptr<ChannelEndpoint> channel_endpoint); - void Stop(); - - private: - void InitChannelOnIOThread(embedder::ScopedPlatformHandle platform_handle, - scoped_refptr<ChannelEndpoint> channel_endpoint); - void ShutdownChannelOnIOThread(); - - embedder::PlatformSupport* const platform_support_; - base::TestIOThread test_io_thread_; - scoped_refptr<Channel> channel_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ChannelThread); -}; - -#if !defined(OS_IOS) -class MultiprocessMessagePipeTestBase : public testing::Test { - public: - MultiprocessMessagePipeTestBase(); - ~MultiprocessMessagePipeTestBase() override; - - protected: - void Init(scoped_refptr<ChannelEndpoint> ep); - - embedder::PlatformSupport* platform_support() { return &platform_support_; } - mojo::test::MultiprocessTestHelper* helper() { return &helper_; } - - private: - embedder::SimplePlatformSupport platform_support_; - ChannelThread channel_thread_; - mojo::test::MultiprocessTestHelper helper_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(MultiprocessMessagePipeTestBase); -}; -#endif - -} // namespace test -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MESSAGE_PIPE_TEST_UTILS_H_ diff --git a/third_party/mojo/src/mojo/edk/system/message_pipe_unittest.cc b/third_party/mojo/src/mojo/edk/system/message_pipe_unittest.cc deleted file mode 100644 index effbb5f..0000000 --- a/third_party/mojo/src/mojo/edk/system/message_pipe_unittest.cc +++ /dev/null @@ -1,572 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/message_pipe.h" - -#include "base/memory/ref_counted.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/system/waiter.h" -#include "third_party/mojo/src/mojo/edk/system/waiter_test_utils.h" - -namespace mojo { -namespace system { -namespace { - -const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED; - -// Tests: -// - only default flags -// - reading messages from a port -// - when there are no/one/two messages available for that port -// - with buffer size 0 (and null buffer) -- should get size -// - with too-small buffer -- should get size -// - also verify that buffers aren't modified when/where they shouldn't be -// - writing messages to a port -// - in the obvious scenarios (as above) -// - to a port that's been closed -// - writing a message to a port, closing the other (would be the source) port, -// and reading it -TEST(MessagePipeTest, Basic) { - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); - - int32_t buffer[2]; - const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); - uint32_t buffer_size; - - // Nothing to read yet on port 0. - buffer[0] = 123; - buffer[1] = 456; - buffer_size = kBufferSize; - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - mp->ReadMessage(0, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kBufferSize, buffer_size); - EXPECT_EQ(123, buffer[0]); - EXPECT_EQ(456, buffer[1]); - - // Ditto for port 1. - buffer[0] = 123; - buffer[1] = 456; - buffer_size = kBufferSize; - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - mp->ReadMessage(1, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - - // Write from port 1 (to port 0). - buffer[0] = 789012345; - buffer[1] = 0; - EXPECT_EQ(MOJO_RESULT_OK, - mp->WriteMessage(1, UserPointer<const void>(buffer), - static_cast<uint32_t>(sizeof(buffer[0])), nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Read from port 0. - buffer[0] = 123; - buffer[1] = 456; - buffer_size = kBufferSize; - EXPECT_EQ(MOJO_RESULT_OK, - mp->ReadMessage(0, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); - EXPECT_EQ(789012345, buffer[0]); - EXPECT_EQ(456, buffer[1]); - - // Read again from port 0 -- it should be empty. - buffer_size = kBufferSize; - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - mp->ReadMessage(0, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - - // Write two messages from port 0 (to port 1). - buffer[0] = 123456789; - buffer[1] = 0; - EXPECT_EQ(MOJO_RESULT_OK, - mp->WriteMessage(0, UserPointer<const void>(buffer), - static_cast<uint32_t>(sizeof(buffer[0])), nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - buffer[0] = 234567890; - buffer[1] = 0; - EXPECT_EQ(MOJO_RESULT_OK, - mp->WriteMessage(0, UserPointer<const void>(buffer), - static_cast<uint32_t>(sizeof(buffer[0])), nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Read from port 1 with buffer size 0 (should get the size of next message). - // Also test that giving a null buffer is okay when the buffer size is 0. - buffer_size = 0; - EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, - mp->ReadMessage(1, NullUserPointer(), MakeUserPointer(&buffer_size), - 0, nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); - - // Read from port 1 with buffer size 1 (too small; should get the size of next - // message). - buffer[0] = 123; - buffer[1] = 456; - buffer_size = 1; - EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, - mp->ReadMessage(1, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); - EXPECT_EQ(123, buffer[0]); - EXPECT_EQ(456, buffer[1]); - - // Read from port 1. - buffer[0] = 123; - buffer[1] = 456; - buffer_size = kBufferSize; - EXPECT_EQ(MOJO_RESULT_OK, - mp->ReadMessage(1, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); - EXPECT_EQ(123456789, buffer[0]); - EXPECT_EQ(456, buffer[1]); - - // Read again from port 1. - buffer[0] = 123; - buffer[1] = 456; - buffer_size = kBufferSize; - EXPECT_EQ(MOJO_RESULT_OK, - mp->ReadMessage(1, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); - EXPECT_EQ(234567890, buffer[0]); - EXPECT_EQ(456, buffer[1]); - - // Read again from port 1 -- it should be empty. - buffer_size = kBufferSize; - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - mp->ReadMessage(1, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - - // Write from port 0 (to port 1). - buffer[0] = 345678901; - buffer[1] = 0; - EXPECT_EQ(MOJO_RESULT_OK, - mp->WriteMessage(0, UserPointer<const void>(buffer), - static_cast<uint32_t>(sizeof(buffer[0])), nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Close port 0. - mp->Close(0); - - // Try to write from port 1 (to port 0). - buffer[0] = 456789012; - buffer[1] = 0; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - mp->WriteMessage(1, UserPointer<const void>(buffer), - static_cast<uint32_t>(sizeof(buffer[0])), nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Read from port 1; should still get message (even though port 0 was closed). - buffer[0] = 123; - buffer[1] = 456; - buffer_size = kBufferSize; - EXPECT_EQ(MOJO_RESULT_OK, - mp->ReadMessage(1, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); - EXPECT_EQ(345678901, buffer[0]); - EXPECT_EQ(456, buffer[1]); - - // Read again from port 1 -- it should be empty (and port 0 is closed). - buffer_size = kBufferSize; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - mp->ReadMessage(1, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - - mp->Close(1); -} - -TEST(MessagePipeTest, CloseWithQueuedIncomingMessages) { - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); - - int32_t buffer[1]; - const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); - uint32_t buffer_size; - - // Write some messages from port 1 (to port 0). - for (int32_t i = 0; i < 5; i++) { - buffer[0] = i; - EXPECT_EQ(MOJO_RESULT_OK, - mp->WriteMessage(1, UserPointer<const void>(buffer), kBufferSize, - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - } - - // Port 0 shouldn't be empty. - buffer_size = 0; - EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, - mp->ReadMessage(0, NullUserPointer(), MakeUserPointer(&buffer_size), - 0, nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kBufferSize, buffer_size); - - // Close port 0 first, which should have outstanding (incoming) messages. - mp->Close(0); - mp->Close(1); -} - -TEST(MessagePipeTest, DiscardMode) { - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); - - int32_t buffer[2]; - const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); - uint32_t buffer_size; - - // Write from port 1 (to port 0). - buffer[0] = 789012345; - buffer[1] = 0; - EXPECT_EQ(MOJO_RESULT_OK, - mp->WriteMessage(1, UserPointer<const void>(buffer), - static_cast<uint32_t>(sizeof(buffer[0])), nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Read/discard from port 0 (no buffer); get size. - buffer_size = 0; - EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, - mp->ReadMessage(0, NullUserPointer(), MakeUserPointer(&buffer_size), - 0, nullptr, MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); - EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); - - // Read again from port 0 -- it should be empty. - buffer_size = kBufferSize; - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - mp->ReadMessage(0, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); - - // Write from port 1 (to port 0). - buffer[0] = 890123456; - buffer[1] = 0; - EXPECT_EQ(MOJO_RESULT_OK, - mp->WriteMessage(1, UserPointer<const void>(buffer), - static_cast<uint32_t>(sizeof(buffer[0])), nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Read from port 0 (buffer big enough). - buffer[0] = 123; - buffer[1] = 456; - buffer_size = kBufferSize; - EXPECT_EQ(MOJO_RESULT_OK, - mp->ReadMessage(0, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); - EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); - EXPECT_EQ(890123456, buffer[0]); - EXPECT_EQ(456, buffer[1]); - - // Read again from port 0 -- it should be empty. - buffer_size = kBufferSize; - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - mp->ReadMessage(0, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); - - // Write from port 1 (to port 0). - buffer[0] = 901234567; - buffer[1] = 0; - EXPECT_EQ(MOJO_RESULT_OK, - mp->WriteMessage(1, UserPointer<const void>(buffer), - static_cast<uint32_t>(sizeof(buffer[0])), nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Read/discard from port 0 (buffer too small); get size. - buffer_size = 1; - EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, - mp->ReadMessage(0, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); - EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); - - // Read again from port 0 -- it should be empty. - buffer_size = kBufferSize; - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - mp->ReadMessage(0, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); - - // Write from port 1 (to port 0). - buffer[0] = 123456789; - buffer[1] = 0; - EXPECT_EQ(MOJO_RESULT_OK, - mp->WriteMessage(1, UserPointer<const void>(buffer), - static_cast<uint32_t>(sizeof(buffer[0])), nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Discard from port 0. - buffer_size = 1; - EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, - mp->ReadMessage(0, NullUserPointer(), NullUserPointer(), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); - - // Read again from port 0 -- it should be empty. - buffer_size = kBufferSize; - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - mp->ReadMessage(0, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); - - mp->Close(0); - mp->Close(1); -} - -TEST(MessagePipeTest, BasicWaiting) { - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); - Waiter waiter; - HandleSignalsState hss; - - int32_t buffer[1]; - const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); - uint32_t buffer_size; - - // Always writable (until the other port is closed). - waiter.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - mp->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - waiter.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - mp->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE, - 0, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - // Not yet readable. - waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - mp->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 1, nullptr)); - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr)); - hss = HandleSignalsState(); - mp->RemoveAwakable(0, &waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - // The peer is not closed. - waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - mp->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 2, nullptr)); - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr)); - hss = HandleSignalsState(); - mp->RemoveAwakable(0, &waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - // Write from port 0 (to port 1), to make port 1 readable. - buffer[0] = 123456789; - EXPECT_EQ(MOJO_RESULT_OK, - mp->WriteMessage(0, UserPointer<const void>(buffer), kBufferSize, - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Port 1 should already be readable now. - waiter.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 3, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - waiter.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE, - 0, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - // ... and still writable. - waiter.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 4, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - // Close port 0. - mp->Close(0); - - // Port 1 should be signaled with peer closed. - waiter.Init(); - hss = HandleSignalsState(); - EXPECT_EQ( - MOJO_RESULT_ALREADY_EXISTS, - mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 5, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Port 1 should not be writable. - waiter.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 6, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // But it should still be readable. - waiter.Init(); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 7, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Read from port 1. - buffer[0] = 0; - buffer_size = kBufferSize; - EXPECT_EQ(MOJO_RESULT_OK, - mp->ReadMessage(1, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), 0, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(123456789, buffer[0]); - - // Now port 1 should no longer be readable. - waiter.Init(); - hss = HandleSignalsState(); - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 8, nullptr)); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - - mp->Close(1); -} - -TEST(MessagePipeTest, ThreadedWaiting) { - int32_t buffer[1]; - const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); - - MojoResult result; - uintptr_t context; - - // Write to wake up waiter waiting for read. - { - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); - test::SimpleWaiterThread thread(&result, &context); - - thread.waiter()->Init(); - ASSERT_EQ(MOJO_RESULT_OK, - mp->AddAwakable(1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, - 1, nullptr)); - thread.Start(); - - buffer[0] = 123456789; - // Write from port 0 (to port 1), which should wake up the waiter. - EXPECT_EQ(MOJO_RESULT_OK, - mp->WriteMessage(0, UserPointer<const void>(buffer), kBufferSize, - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - HandleSignalsState hss; - mp->RemoveAwakable(1, thread.waiter(), &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - mp->Close(0); - mp->Close(1); - } // Joins |thread|. - // The waiter should have woken up successfully. - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(1u, context); - - // Close to cancel waiter. - { - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); - test::SimpleWaiterThread thread(&result, &context); - - thread.waiter()->Init(); - ASSERT_EQ(MOJO_RESULT_OK, - mp->AddAwakable(1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, - 2, nullptr)); - thread.Start(); - - // Close port 1 first -- this should result in the waiter being cancelled. - mp->CancelAllAwakables(1); - mp->Close(1); - - // Port 1 is closed, so |Dispatcher::RemoveAwakable()| wouldn't call into - // the |MessagePipe| to remove any waiter. - - mp->Close(0); - } // Joins |thread|. - EXPECT_EQ(MOJO_RESULT_CANCELLED, result); - EXPECT_EQ(2u, context); - - // Close to cancel waiter using peer closed signal. - { - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); - test::SimpleWaiterThread thread(&result, &context); - - thread.waiter()->Init(); - ASSERT_EQ(MOJO_RESULT_OK, - mp->AddAwakable(1, thread.waiter(), - MOJO_HANDLE_SIGNAL_PEER_CLOSED, 3, nullptr)); - thread.Start(); - - // Close port 1 first -- this should result in the waiter being cancelled. - mp->CancelAllAwakables(1); - mp->Close(1); - - // Port 1 is closed, so |Dispatcher::RemoveAwakable()| wouldn't call into - // the |MessagePipe| to remove any waiter. - - mp->Close(0); - } // Joins |thread|. - EXPECT_EQ(MOJO_RESULT_CANCELLED, result); - EXPECT_EQ(3u, context); - - // Close to make waiter un-wake-up-able. - { - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); - test::SimpleWaiterThread thread(&result, &context); - - thread.waiter()->Init(); - ASSERT_EQ(MOJO_RESULT_OK, - mp->AddAwakable(1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, - 4, nullptr)); - thread.Start(); - - // Close port 0 first -- this should wake the waiter up, since port 1 will - // never be readable. - mp->CancelAllAwakables(0); - mp->Close(0); - - HandleSignalsState hss; - mp->RemoveAwakable(1, thread.waiter(), &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - mp->CancelAllAwakables(1); - mp->Close(1); - } // Joins |thread|. - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); - EXPECT_EQ(4u, context); -} - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/multiprocess_message_pipe_unittest.cc b/third_party/mojo/src/mojo/edk/system/multiprocess_message_pipe_unittest.cc deleted file mode 100644 index 08c4bdb7..0000000 --- a/third_party/mojo/src/mojo/edk/system/multiprocess_message_pipe_unittest.cc +++ /dev/null @@ -1,519 +0,0 @@ -// Copyright 2013 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 <stdint.h> -#include <stdio.h> -#include <string.h> -#include <string> -#include <utility> -#include <vector> - -#include "base/bind.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/files/scoped_file.h" -#include "base/files/scoped_temp_dir.h" -#include "base/location.h" -#include "base/logging.h" -#include "build/build_config.h" // TODO(vtl): Remove this. -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_shared_buffer.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" -#include "third_party/mojo/src/mojo/edk/system/channel.h" -#include "third_party/mojo/src/mojo/edk/system/dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe_test_utils.h" -#include "third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/raw_channel.h" -#include "third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/test_utils.h" -#include "third_party/mojo/src/mojo/edk/test/test_utils.h" - -namespace mojo { -namespace system { -namespace { - -class MultiprocessMessagePipeTest - : public test::MultiprocessMessagePipeTestBase {}; - -// For each message received, sends a reply message with the same contents -// repeated twice, until the other end is closed or it receives "quitquitquit" -// (which it doesn't reply to). It'll return the number of messages received, -// not including any "quitquitquit" message, modulo 100. -MOJO_MULTIPROCESS_TEST_CHILD_MAIN(EchoEcho) { - embedder::SimplePlatformSupport platform_support; - test::ChannelThread channel_thread(&platform_support); - embedder::ScopedPlatformHandle client_platform_handle = - std::move(mojo::test::MultiprocessTestHelper::client_platform_handle); - CHECK(client_platform_handle.is_valid()); - scoped_refptr<ChannelEndpoint> ep; - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep)); - channel_thread.Start(std::move(client_platform_handle), ep); - - const std::string quitquitquit("quitquitquit"); - int rv = 0; - for (;; rv = (rv + 1) % 100) { - // Wait for our end of the message pipe to be readable. - HandleSignalsState hss; - MojoResult result = - test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss); - if (result != MOJO_RESULT_OK) { - // It was closed, probably. - CHECK_EQ(result, MOJO_RESULT_FAILED_PRECONDITION); - CHECK_EQ(hss.satisfied_signals, MOJO_HANDLE_SIGNAL_PEER_CLOSED); - CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_PEER_CLOSED); - break; - } else { - CHECK((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); - CHECK((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); - } - - std::string read_buffer(1000, '\0'); - uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); - CHECK_EQ(mp->ReadMessage(0, UserPointer<void>(&read_buffer[0]), - MakeUserPointer(&read_buffer_size), nullptr, - nullptr, MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - read_buffer.resize(read_buffer_size); - VLOG(2) << "Child got: " << read_buffer; - - if (read_buffer == quitquitquit) { - VLOG(2) << "Child quitting."; - break; - } - - std::string write_buffer = read_buffer + read_buffer; - CHECK_EQ(mp->WriteMessage(0, UserPointer<const void>(write_buffer.data()), - static_cast<uint32_t>(write_buffer.size()), - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - } - - mp->Close(0); - return rv; -} - -// Sends "hello" to child, and expects "hellohello" back. -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_Basic DISABLED_Basic -#else -#define MAYBE_Basic Basic -#endif // defined(OS_ANDROID) -TEST_F(MultiprocessMessagePipeTest, MAYBE_Basic) { - helper()->StartChild("EchoEcho"); - - scoped_refptr<ChannelEndpoint> ep; - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep)); - Init(ep); - - std::string hello("hello"); - EXPECT_EQ(MOJO_RESULT_OK, - mp->WriteMessage(0, UserPointer<const void>(hello.data()), - static_cast<uint32_t>(hello.size()), nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - HandleSignalsState hss; - EXPECT_EQ(MOJO_RESULT_OK, - test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - // The child may or may not have closed its end of the message pipe and died - // (and we may or may not know it yet), so our end may or may not appear as - // writable. - EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); - EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); - - std::string read_buffer(1000, '\0'); - uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); - CHECK_EQ(mp->ReadMessage(0, UserPointer<void>(&read_buffer[0]), - MakeUserPointer(&read_buffer_size), nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - read_buffer.resize(read_buffer_size); - VLOG(2) << "Parent got: " << read_buffer; - EXPECT_EQ(hello + hello, read_buffer); - - mp->Close(0); - - // We sent one message. - EXPECT_EQ(1 % 100, helper()->WaitForChildShutdown()); -} - -// Sends a bunch of messages to the child. Expects them "repeated" back. Waits -// for the child to close its end before quitting. -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_QueueMessages DISABLED_QueueMessages -#else -#define MAYBE_QueueMessages QueueMessages -#endif // defined(OS_ANDROID) -TEST_F(MultiprocessMessagePipeTest, DISABLED_QueueMessages) { - helper()->StartChild("EchoEcho"); - - scoped_refptr<ChannelEndpoint> ep; - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep)); - Init(ep); - - static const size_t kNumMessages = 1001; - for (size_t i = 0; i < kNumMessages; i++) { - std::string write_buffer(i, 'A' + (i % 26)); - EXPECT_EQ(MOJO_RESULT_OK, - mp->WriteMessage(0, UserPointer<const void>(write_buffer.data()), - static_cast<uint32_t>(write_buffer.size()), - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - } - - const std::string quitquitquit("quitquitquit"); - EXPECT_EQ(MOJO_RESULT_OK, - mp->WriteMessage(0, UserPointer<const void>(quitquitquit.data()), - static_cast<uint32_t>(quitquitquit.size()), - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - for (size_t i = 0; i < kNumMessages; i++) { - HandleSignalsState hss; - EXPECT_EQ(MOJO_RESULT_OK, - test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - // The child may or may not have closed its end of the message pipe and died - // (and we may or may not know it yet), so our end may or may not appear as - // writable. - EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); - EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); - - std::string read_buffer(kNumMessages * 2, '\0'); - uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); - CHECK_EQ(mp->ReadMessage(0, UserPointer<void>(&read_buffer[0]), - MakeUserPointer(&read_buffer_size), nullptr, - nullptr, MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - read_buffer.resize(read_buffer_size); - - EXPECT_EQ(std::string(i * 2, 'A' + (i % 26)), read_buffer); - } - - // Wait for it to become readable, which should fail (since we sent - // "quitquitquit"). - HandleSignalsState hss; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - mp->Close(0); - - EXPECT_EQ(static_cast<int>(kNumMessages % 100), - helper()->WaitForChildShutdown()); -} - -MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckSharedBuffer) { - embedder::SimplePlatformSupport platform_support; - test::ChannelThread channel_thread(&platform_support); - embedder::ScopedPlatformHandle client_platform_handle = - std::move(mojo::test::MultiprocessTestHelper::client_platform_handle); - CHECK(client_platform_handle.is_valid()); - scoped_refptr<ChannelEndpoint> ep; - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep)); - channel_thread.Start(std::move(client_platform_handle), ep); - - // Wait for the first message from our parent. - HandleSignalsState hss; - CHECK_EQ(test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss), - MOJO_RESULT_OK); - // In this test, the parent definitely doesn't close its end of the message - // pipe before we do. - CHECK_EQ(hss.satisfied_signals, - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); - CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED); - - // It should have a shared buffer. - std::string read_buffer(100, '\0'); - uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size()); - DispatcherVector dispatchers; - uint32_t num_dispatchers = 10; // Maximum number to receive. - CHECK_EQ(mp->ReadMessage(0, UserPointer<void>(&read_buffer[0]), - MakeUserPointer(&num_bytes), &dispatchers, - &num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - read_buffer.resize(num_bytes); - CHECK_EQ(read_buffer, std::string("go 1")); - CHECK_EQ(num_dispatchers, 1u); - - CHECK_EQ(dispatchers[0]->GetType(), Dispatcher::Type::SHARED_BUFFER); - - scoped_refptr<SharedBufferDispatcher> dispatcher( - static_cast<SharedBufferDispatcher*>(dispatchers[0].get())); - - // Make a mapping. - scoped_ptr<embedder::PlatformSharedBufferMapping> mapping; - CHECK_EQ(dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping), - MOJO_RESULT_OK); - CHECK(mapping); - CHECK(mapping->GetBase()); - CHECK_EQ(mapping->GetLength(), 100u); - - // Write some stuff to the shared buffer. - static const char kHello[] = "hello"; - memcpy(mapping->GetBase(), kHello, sizeof(kHello)); - - // We should be able to close the dispatcher now. - dispatcher->Close(); - - // And send a message to signal that we've written stuff. - const std::string go2("go 2"); - CHECK_EQ(mp->WriteMessage(0, UserPointer<const void>(&go2[0]), - static_cast<uint32_t>(go2.size()), nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - - // Now wait for our parent to send us a message. - hss = HandleSignalsState(); - CHECK_EQ(test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss), - MOJO_RESULT_OK); - CHECK_EQ(hss.satisfied_signals, - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); - CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED); - - read_buffer = std::string(100, '\0'); - num_bytes = static_cast<uint32_t>(read_buffer.size()); - CHECK_EQ(mp->ReadMessage(0, UserPointer<void>(&read_buffer[0]), - MakeUserPointer(&num_bytes), nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - read_buffer.resize(num_bytes); - CHECK_EQ(read_buffer, std::string("go 3")); - - // It should have written something to the shared buffer. - static const char kWorld[] = "world!!!"; - CHECK_EQ(memcmp(mapping->GetBase(), kWorld, sizeof(kWorld)), 0); - - // And we're done. - mp->Close(0); - - return 0; -} - -#if defined(OS_POSIX) && !defined(OS_ANDROID) -#define MAYBE_SharedBufferPassing SharedBufferPassing -#else -// Not yet implemented (on Windows). -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_SharedBufferPassing DISABLED_SharedBufferPassing -#endif -TEST_F(MultiprocessMessagePipeTest, MAYBE_SharedBufferPassing) { - helper()->StartChild("CheckSharedBuffer"); - - scoped_refptr<ChannelEndpoint> ep; - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep)); - Init(ep); - - // Make a shared buffer. - scoped_refptr<SharedBufferDispatcher> dispatcher; - EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create( - platform_support(), - SharedBufferDispatcher::kDefaultCreateOptions, - 100, &dispatcher)); - ASSERT_TRUE(dispatcher); - - // Make a mapping. - scoped_ptr<embedder::PlatformSharedBufferMapping> mapping; - EXPECT_EQ(MOJO_RESULT_OK, - dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); - ASSERT_TRUE(mapping); - ASSERT_TRUE(mapping->GetBase()); - ASSERT_EQ(100u, mapping->GetLength()); - - // Send the shared buffer. - const std::string go1("go 1"); - DispatcherTransport transport( - test::DispatcherTryStartTransport(dispatcher.get())); - ASSERT_TRUE(transport.is_valid()); - - std::vector<DispatcherTransport> transports; - transports.push_back(transport); - EXPECT_EQ(MOJO_RESULT_OK, - mp->WriteMessage(0, UserPointer<const void>(&go1[0]), - static_cast<uint32_t>(go1.size()), &transports, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - transport.End(); - - EXPECT_TRUE(dispatcher->HasOneRef()); - dispatcher = nullptr; - - // Wait for a message from the child. - HandleSignalsState hss; - EXPECT_EQ(MOJO_RESULT_OK, - test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); - EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); - - std::string read_buffer(100, '\0'); - uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size()); - EXPECT_EQ(MOJO_RESULT_OK, - mp->ReadMessage(0, UserPointer<void>(&read_buffer[0]), - MakeUserPointer(&num_bytes), nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - read_buffer.resize(num_bytes); - EXPECT_EQ(std::string("go 2"), read_buffer); - - // After we get it, the child should have written something to the shared - // buffer. - static const char kHello[] = "hello"; - EXPECT_EQ(0, memcmp(mapping->GetBase(), kHello, sizeof(kHello))); - - // Now we'll write some stuff to the shared buffer. - static const char kWorld[] = "world!!!"; - memcpy(mapping->GetBase(), kWorld, sizeof(kWorld)); - - // And send a message to signal that we've written stuff. - const std::string go3("go 3"); - EXPECT_EQ(MOJO_RESULT_OK, - mp->WriteMessage(0, UserPointer<const void>(&go3[0]), - static_cast<uint32_t>(go3.size()), nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Wait for |mp| to become readable, which should fail. - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - mp->Close(0); - - EXPECT_EQ(0, helper()->WaitForChildShutdown()); -} - -MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckPlatformHandleFile) { - embedder::SimplePlatformSupport platform_support; - test::ChannelThread channel_thread(&platform_support); - embedder::ScopedPlatformHandle client_platform_handle = - std::move(mojo::test::MultiprocessTestHelper::client_platform_handle); - CHECK(client_platform_handle.is_valid()); - scoped_refptr<ChannelEndpoint> ep; - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep)); - channel_thread.Start(std::move(client_platform_handle), ep); - - HandleSignalsState hss; - CHECK_EQ(test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss), - MOJO_RESULT_OK); - CHECK_EQ(hss.satisfied_signals, - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); - CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED); - - std::string read_buffer(100, '\0'); - uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size()); - DispatcherVector dispatchers; - uint32_t num_dispatchers = 255; // Maximum number to receive. - CHECK_EQ(mp->ReadMessage(0, UserPointer<void>(&read_buffer[0]), - MakeUserPointer(&num_bytes), &dispatchers, - &num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - mp->Close(0); - - read_buffer.resize(num_bytes); - char hello[32]; - int num_handles = 0; - sscanf(read_buffer.c_str(), "%s %d", hello, &num_handles); - CHECK_EQ(std::string("hello"), std::string(hello)); - CHECK_GT(num_handles, 0); - - for (int i = 0; i < num_handles; ++i) { - CHECK_EQ(dispatchers[i]->GetType(), Dispatcher::Type::PLATFORM_HANDLE); - - scoped_refptr<PlatformHandleDispatcher> dispatcher( - static_cast<PlatformHandleDispatcher*>(dispatchers[i].get())); - embedder::ScopedPlatformHandle h = dispatcher->PassPlatformHandle(); - CHECK(h.is_valid()); - dispatcher->Close(); - - base::ScopedFILE fp(mojo::test::FILEFromPlatformHandle(std::move(h), "r")); - CHECK(fp); - std::string fread_buffer(100, '\0'); - size_t bytes_read = - fread(&fread_buffer[0], 1, fread_buffer.size(), fp.get()); - fread_buffer.resize(bytes_read); - CHECK_EQ(fread_buffer, "world"); - } - - return 0; -} - -class MultiprocessMessagePipeTestWithPipeCount - : public test::MultiprocessMessagePipeTestBase, - public testing::WithParamInterface<size_t> {}; - -TEST_P(MultiprocessMessagePipeTestWithPipeCount, PlatformHandlePassing) { - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - - helper()->StartChild("CheckPlatformHandleFile"); - - scoped_refptr<ChannelEndpoint> ep; - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep)); - Init(ep); - - std::vector<scoped_refptr<PlatformHandleDispatcher>> dispatchers; - std::vector<DispatcherTransport> transports; - - size_t pipe_count = GetParam(); - for (size_t i = 0; i < pipe_count; ++i) { - base::FilePath unused; - base::ScopedFILE fp( - CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused)); - const std::string world("world"); - CHECK_EQ(fwrite(&world[0], 1, world.size(), fp.get()), world.size()); - fflush(fp.get()); - rewind(fp.get()); - - scoped_refptr<PlatformHandleDispatcher> dispatcher = - PlatformHandleDispatcher::Create(embedder::ScopedPlatformHandle( - mojo::test::PlatformHandleFromFILE(std::move(fp)))); - dispatchers.push_back(dispatcher); - DispatcherTransport transport( - test::DispatcherTryStartTransport(dispatcher.get())); - ASSERT_TRUE(transport.is_valid()); - transports.push_back(transport); - } - - char message[128]; - sprintf(message, "hello %d", static_cast<int>(pipe_count)); - EXPECT_EQ(MOJO_RESULT_OK, - mp->WriteMessage(0, UserPointer<const void>(message), - static_cast<uint32_t>(strlen(message)), - &transports, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - for (size_t i = 0; i < pipe_count; ++i) { - transports[i].End(); - EXPECT_TRUE(dispatchers[i]->HasOneRef()); - } - - dispatchers.clear(); - - // Wait for it to become readable, which should fail. - HandleSignalsState hss; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - mp->Close(0); - - EXPECT_EQ(0, helper()->WaitForChildShutdown()); -} - -// Not yet implemented (on Windows). -// Android multi-process tests are not executing the new process. This is flaky. -#if defined(OS_POSIX) && !defined(OS_ANDROID) -INSTANTIATE_TEST_CASE_P(PipeCount, - MultiprocessMessagePipeTestWithPipeCount, - testing::Values(1u, 128u, 140u)); -#endif - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/mutex.cc b/third_party/mojo/src/mojo/edk/system/mutex.cc deleted file mode 100644 index 2c17c70..0000000 --- a/third_party/mojo/src/mojo/edk/system/mutex.cc +++ /dev/null @@ -1,38 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/mutex.h" - -#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) - -#include "base/logging.h" - -namespace mojo { -namespace system { - -Mutex::Mutex() : lock_() { -} - -Mutex::~Mutex() { - DCHECK(owning_thread_ref_.is_null()); -} - -void Mutex::AssertHeld() const { - DCHECK(owning_thread_ref_ == base::PlatformThread::CurrentRef()); -} - -void Mutex::CheckHeldAndUnmark() { - DCHECK(owning_thread_ref_ == base::PlatformThread::CurrentRef()); - owning_thread_ref_ = base::PlatformThreadRef(); -} - -void Mutex::CheckUnheldAndMark() { - DCHECK(owning_thread_ref_.is_null()); - owning_thread_ref_ = base::PlatformThread::CurrentRef(); -} - -} // namespace system -} // namespace mojo - -#endif // !NDEBUG || DCHECK_ALWAYS_ON diff --git a/third_party/mojo/src/mojo/edk/system/mutex.h b/third_party/mojo/src/mojo/edk/system/mutex.h deleted file mode 100644 index 67cda57e..0000000 --- a/third_party/mojo/src/mojo/edk/system/mutex.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2015 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. - -// A mutex class, with support for thread annotations. -// -// TODO(vtl): Currently, this is a fork of Chromium's -// base/synchronization/lock.h (with names changed and minor modifications; it -// still cheats and uses Chromium's lock_impl.*), but eventually we'll want our -// own and, e.g., add support for non-exclusive (reader) locks. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MUTEX_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MUTEX_H_ - -#include "base/synchronization/lock_impl.h" -#include "base/threading/platform_thread.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" -#include "third_party/mojo/src/mojo/edk/system/thread_annotations.h" - -namespace mojo { -namespace system { - -// Mutex ----------------------------------------------------------------------- - -class MOJO_LOCKABLE MOJO_SYSTEM_IMPL_EXPORT Mutex { - public: -#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) - Mutex() : lock_() {} - ~Mutex() {} - - void Lock() MOJO_EXCLUSIVE_LOCK_FUNCTION() { lock_.Lock(); } - void Unlock() MOJO_UNLOCK_FUNCTION() { lock_.Unlock(); } - - bool TryLock() MOJO_EXCLUSIVE_TRYLOCK_FUNCTION(true) { return lock_.Try(); } - - void AssertHeld() const MOJO_ASSERT_EXCLUSIVE_LOCK() {} -#else - Mutex(); - ~Mutex(); - - void Lock() MOJO_EXCLUSIVE_LOCK_FUNCTION() { - lock_.Lock(); - CheckUnheldAndMark(); - } - void Unlock() MOJO_UNLOCK_FUNCTION() { - CheckHeldAndUnmark(); - lock_.Unlock(); - } - - bool TryLock() MOJO_EXCLUSIVE_TRYLOCK_FUNCTION(true) { - bool rv = lock_.Try(); - if (rv) - CheckUnheldAndMark(); - return rv; - } - - void AssertHeld() const MOJO_ASSERT_EXCLUSIVE_LOCK(); -#endif // NDEBUG && !DCHECK_ALWAYS_ON - - private: -#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) - void CheckHeldAndUnmark(); - void CheckUnheldAndMark(); - - base::PlatformThreadRef owning_thread_ref_; -#endif // !NDEBUG || DCHECK_ALWAYS_ON - - base::internal::LockImpl lock_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(Mutex); -}; - -// MutexLocker ----------------------------------------------------------------- - -class MOJO_SCOPED_LOCKABLE MOJO_SYSTEM_IMPL_EXPORT MutexLocker { - public: - explicit MutexLocker(Mutex* mutex) MOJO_EXCLUSIVE_LOCK_FUNCTION(mutex) - : mutex_(mutex) { - this->mutex_->Lock(); - } - ~MutexLocker() MOJO_UNLOCK_FUNCTION() { this->mutex_->Unlock(); } - - private: - Mutex* const mutex_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(MutexLocker); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_MUTEX_H_ diff --git a/third_party/mojo/src/mojo/edk/system/mutex_unittest.cc b/third_party/mojo/src/mojo/edk/system/mutex_unittest.cc deleted file mode 100644 index bcd745a..0000000 --- a/third_party/mojo/src/mojo/edk/system/mutex_unittest.cc +++ /dev/null @@ -1,250 +0,0 @@ -// Copyright 2015 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 "third_party/mojo/src/mojo/edk/system/mutex.h" - -#include <stdlib.h> - -#include "base/threading/platform_thread.h" -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/system/test_utils.h" - -namespace mojo { -namespace system { -namespace { - -// Sleeps for a "very small" amount of time. -void EpsilonRandomSleep() { - test::Sleep(test::DeadlineFromMilliseconds(rand() % 20)); -} - -// Basic test to make sure that Lock()/Unlock()/TryLock() don't crash ---------- - -class BasicMutexTestThread : public base::PlatformThread::Delegate { - public: - explicit BasicMutexTestThread(Mutex* mutex) : mutex_(mutex), acquired_(0) {} - - void ThreadMain() override { - for (int i = 0; i < 10; i++) { - mutex_->Lock(); - mutex_->AssertHeld(); - acquired_++; - mutex_->Unlock(); - } - for (int i = 0; i < 10; i++) { - mutex_->Lock(); - mutex_->AssertHeld(); - acquired_++; - EpsilonRandomSleep(); - mutex_->Unlock(); - } - for (int i = 0; i < 10; i++) { - if (mutex_->TryLock()) { - mutex_->AssertHeld(); - acquired_++; - EpsilonRandomSleep(); - mutex_->Unlock(); - } - } - } - - int acquired() const { return acquired_; } - - private: - Mutex* mutex_; - int acquired_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(BasicMutexTestThread); -}; - -TEST(MutexTest, Basic) { - Mutex mutex; - BasicMutexTestThread thread(&mutex); - base::PlatformThreadHandle handle; - - ASSERT_TRUE(base::PlatformThread::Create(0, &thread, &handle)); - - int acquired = 0; - for (int i = 0; i < 5; i++) { - mutex.Lock(); - mutex.AssertHeld(); - acquired++; - mutex.Unlock(); - } - for (int i = 0; i < 10; i++) { - mutex.Lock(); - mutex.AssertHeld(); - acquired++; - EpsilonRandomSleep(); - mutex.Unlock(); - } - for (int i = 0; i < 10; i++) { - if (mutex.TryLock()) { - mutex.AssertHeld(); - acquired++; - EpsilonRandomSleep(); - mutex.Unlock(); - } - } - for (int i = 0; i < 5; i++) { - mutex.Lock(); - mutex.AssertHeld(); - acquired++; - EpsilonRandomSleep(); - mutex.Unlock(); - } - - base::PlatformThread::Join(handle); - - EXPECT_GE(acquired, 20); - EXPECT_GE(thread.acquired(), 20); -} - -// Test that TryLock() works as expected --------------------------------------- - -class TryLockTestThread : public base::PlatformThread::Delegate { - public: - explicit TryLockTestThread(Mutex* mutex) : mutex_(mutex), got_lock_(false) {} - - void ThreadMain() override MOJO_NO_THREAD_SAFETY_ANALYSIS { - got_lock_ = mutex_->TryLock(); - if (got_lock_) { - mutex_->AssertHeld(); - mutex_->Unlock(); - } - } - - bool got_lock() const { return got_lock_; } - - private: - Mutex* mutex_; - bool got_lock_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(TryLockTestThread); -}; - -TEST(MutexTest, TryLock) MOJO_NO_THREAD_SAFETY_ANALYSIS { - Mutex mutex; - - ASSERT_TRUE(mutex.TryLock()); - // We now have the mutex.... - - // This thread will not be able to get the mutex. - { - TryLockTestThread thread(&mutex); - base::PlatformThreadHandle handle; - - ASSERT_TRUE(base::PlatformThread::Create(0, &thread, &handle)); - - base::PlatformThread::Join(handle); - - ASSERT_FALSE(thread.got_lock()); - } - - mutex.Unlock(); - - // This thread will.... - { - TryLockTestThread thread(&mutex); - base::PlatformThreadHandle handle; - - ASSERT_TRUE(base::PlatformThread::Create(0, &thread, &handle)); - - base::PlatformThread::Join(handle); - - ASSERT_TRUE(thread.got_lock()); - // But it released it.... - ASSERT_TRUE(mutex.TryLock()); - } - - mutex.Unlock(); -} - -// Tests that mutexes actually exclude ----------------------------------------- - -class MutexLockTestThread : public base::PlatformThread::Delegate { - public: - MutexLockTestThread(Mutex* mutex, int* value) - : mutex_(mutex), value_(value) {} - - // Static helper which can also be called from the main thread. - static void DoStuff(Mutex* mutex, int* value) { - for (int i = 0; i < 40; i++) { - mutex->Lock(); - int v = *value; - EpsilonRandomSleep(); - *value = v + 1; - mutex->Unlock(); - } - } - - void ThreadMain() override { DoStuff(mutex_, value_); } - - private: - Mutex* mutex_; - int* value_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(MutexLockTestThread); -}; - -TEST(MutexTest, MutexTwoThreads) { - Mutex mutex; - int value = 0; - - MutexLockTestThread thread(&mutex, &value); - base::PlatformThreadHandle handle; - - ASSERT_TRUE(base::PlatformThread::Create(0, &thread, &handle)); - - MutexLockTestThread::DoStuff(&mutex, &value); - - base::PlatformThread::Join(handle); - - EXPECT_EQ(2 * 40, value); -} - -TEST(MutexTest, MutexFourThreads) { - Mutex mutex; - int value = 0; - - MutexLockTestThread thread1(&mutex, &value); - MutexLockTestThread thread2(&mutex, &value); - MutexLockTestThread thread3(&mutex, &value); - base::PlatformThreadHandle handle1; - base::PlatformThreadHandle handle2; - base::PlatformThreadHandle handle3; - - ASSERT_TRUE(base::PlatformThread::Create(0, &thread1, &handle1)); - ASSERT_TRUE(base::PlatformThread::Create(0, &thread2, &handle2)); - ASSERT_TRUE(base::PlatformThread::Create(0, &thread3, &handle3)); - - MutexLockTestThread::DoStuff(&mutex, &value); - - base::PlatformThread::Join(handle1); - base::PlatformThread::Join(handle2); - base::PlatformThread::Join(handle3); - - EXPECT_EQ(4 * 40, value); -} - -// MutexLocker ----------------------------------------------------------------- - -TEST(MutexTest, MutexLocker) { - Mutex mutex; - - { - MutexLocker locker(&mutex); - mutex.AssertHeld(); - } - - // The destruction of |locker| should unlock |mutex|. - ASSERT_TRUE(mutex.TryLock()); - mutex.AssertHeld(); - mutex.Unlock(); -} - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/options_validation.h b/third_party/mojo/src/mojo/edk/system/options_validation.h deleted file mode 100644 index a325b10..0000000 --- a/third_party/mojo/src/mojo/edk/system/options_validation.h +++ /dev/null @@ -1,102 +0,0 @@ -// 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. - -// Functions to help with verifying various |Mojo...Options| structs from the -// (public, C) API. These are "extensible" structs, which all have |struct_size| -// as their first member. All fields (other than |struct_size|) are optional, -// but any |flags| specified must be known to the system (otherwise, an error of -// |MOJO_RESULT_UNIMPLEMENTED| should be returned). - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_OPTIONS_VALIDATION_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_OPTIONS_VALIDATION_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <algorithm> - -#include "base/logging.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/memory.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -template <class Options> -class UserOptionsReader { - public: - // Constructor from a |UserPointer<const Options>| (which it checks -- this - // constructor has side effects!). - // Note: We initialize |options_reader_| without checking, since we do a check - // in |GetSizeForReader()|. - explicit UserOptionsReader(UserPointer<const Options> options) - : options_reader_(UserPointer<const char>::Reader::NoCheck(), - options.template ReinterpretCast<const char>(), - GetSizeForReader(options)) { - static_assert(offsetof(Options, struct_size) == 0, - "struct_size not first member of Options"); - // TODO(vtl): Enable when MSVC supports this (C++11 extended sizeof): - // static_assert(sizeof(Options::struct_size) == sizeof(uint32_t), - // "Options::struct_size not a uint32_t"); - // (Or maybe assert that its type is uint32_t?) - } - - bool is_valid() const { return !!options_reader_.GetPointer(); } - - const Options& options() const { - DCHECK(is_valid()); - return *reinterpret_cast<const Options*>(options_reader_.GetPointer()); - } - - // Checks that the given (variable-size) |options| passed to the constructor - // (plausibly) has a member at the given offset with the given size. You - // probably want to use |OPTIONS_STRUCT_HAS_MEMBER()| instead. - bool HasMember(size_t offset, size_t size) const { - DCHECK(is_valid()); - // We assume that |offset| and |size| are reasonable, since they should come - // from |offsetof(Options, some_member)| and |sizeof(Options::some_member)|, - // respectively. - return options().struct_size >= offset + size; - } - - private: - static inline size_t GetSizeForReader(UserPointer<const Options> options) { - uint32_t struct_size = - options.template ReinterpretCast<const uint32_t>().Get(); - if (struct_size < sizeof(uint32_t)) - return 0; - - // Check the full requested size. - // Note: Use |MOJO_ALIGNOF()| here to match the exact macro used in the - // declaration of Options structs. - internal::CheckUserPointerWithSize<MOJO_ALIGNOF(Options)>(options.pointer_, - struct_size); - options.template ReinterpretCast<const char>().CheckArray(struct_size); - // But we'll never look at more than |sizeof(Options)| bytes. - return std::min(static_cast<size_t>(struct_size), sizeof(Options)); - } - - UserPointer<const char>::Reader options_reader_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(UserOptionsReader); -}; - -// Macro to invoke |UserOptionsReader<Options>::HasMember()| parametrized by -// member name instead of offset and size. -// -// (We can't just give |HasMember()| a member pointer template argument instead, -// since there's no good/strictly-correct way to get an offset from that.) -// -// TODO(vtl): With C++11, use |sizeof(Options::member)| instead of (the -// contortion below). We might also be able to pull out the type |Options| from -// |reader| (using |decltype|) instead of requiring a parameter. -#define OPTIONS_STRUCT_HAS_MEMBER(Options, member, reader) \ - reader.HasMember(offsetof(Options, member), sizeof(reader.options().member)) - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_OPTIONS_VALIDATION_H_ diff --git a/third_party/mojo/src/mojo/edk/system/options_validation_unittest.cc b/third_party/mojo/src/mojo/edk/system/options_validation_unittest.cc deleted file mode 100644 index dab6597..0000000 --- a/third_party/mojo/src/mojo/edk/system/options_validation_unittest.cc +++ /dev/null @@ -1,130 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/options_validation.h" - -#include <stddef.h> -#include <stdint.h> - -#include "mojo/public/c/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace system { -namespace { - -// Declare a test options struct just as we do in actual public headers. - -using TestOptionsFlags = uint32_t; - -static_assert(MOJO_ALIGNOF(int64_t) == 8, "int64_t has weird alignment"); -struct MOJO_ALIGNAS(8) TestOptions { - uint32_t struct_size; - TestOptionsFlags flags; - uint32_t member1; - uint32_t member2; -}; -static_assert(sizeof(TestOptions) == 16, "TestOptions has wrong size"); - -const uint32_t kSizeOfTestOptions = static_cast<uint32_t>(sizeof(TestOptions)); - -TEST(OptionsValidationTest, Valid) { - { - const TestOptions kOptions = {kSizeOfTestOptions}; - UserOptionsReader<TestOptions> reader(MakeUserPointer(&kOptions)); - EXPECT_TRUE(reader.is_valid()); - EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader)); - EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader)); - EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader)); - } - { - const TestOptions kOptions = {static_cast<uint32_t>( - offsetof(TestOptions, struct_size) + sizeof(uint32_t))}; - UserOptionsReader<TestOptions> reader(MakeUserPointer(&kOptions)); - EXPECT_TRUE(reader.is_valid()); - EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader)); - EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader)); - EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader)); - } - - { - const TestOptions kOptions = { - static_cast<uint32_t>(offsetof(TestOptions, flags) + sizeof(uint32_t))}; - UserOptionsReader<TestOptions> reader(MakeUserPointer(&kOptions)); - EXPECT_TRUE(reader.is_valid()); - EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader)); - EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader)); - EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader)); - } - { - MOJO_ALIGNAS(8) char buf[sizeof(TestOptions) + 100] = {}; - TestOptions* options = reinterpret_cast<TestOptions*>(buf); - options->struct_size = kSizeOfTestOptions + 1; - UserOptionsReader<TestOptions> reader(MakeUserPointer(options)); - EXPECT_TRUE(reader.is_valid()); - EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader)); - EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader)); - EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader)); - } - { - MOJO_ALIGNAS(8) char buf[sizeof(TestOptions) + 100] = {}; - TestOptions* options = reinterpret_cast<TestOptions*>(buf); - options->struct_size = kSizeOfTestOptions + 4; - UserOptionsReader<TestOptions> reader(MakeUserPointer(options)); - EXPECT_TRUE(reader.is_valid()); - EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader)); - EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader)); - EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader)); - } -} - -TEST(OptionsValidationTest, Invalid) { - // Size too small: - for (size_t i = 0; i < sizeof(uint32_t); i++) { - TestOptions options = {static_cast<uint32_t>(i)}; - UserOptionsReader<TestOptions> reader(MakeUserPointer(&options)); - EXPECT_FALSE(reader.is_valid()) << i; - } -} - -// These test invalid arguments that should cause death if we're being paranoid -// about checking arguments (which we would want to do if, e.g., we were in a -// true "kernel" situation, but we might not want to do otherwise for -// performance reasons). Probably blatant errors like passing in null pointers -// (for required pointer arguments) will still cause death, but perhaps not -// predictably. -TEST(OptionsValidationTest, InvalidDeath) { - const char kMemoryCheckFailedRegex[] = "Check failed"; - - // Null: - EXPECT_DEATH_IF_SUPPORTED( - { UserOptionsReader<TestOptions> reader((NullUserPointer())); }, - kMemoryCheckFailedRegex); - - // Unaligned: - EXPECT_DEATH_IF_SUPPORTED( - { - UserOptionsReader<TestOptions> reader( - MakeUserPointer(reinterpret_cast<const TestOptions*>(1))); - }, - kMemoryCheckFailedRegex); - // Note: The current implementation checks the size only after checking the - // alignment versus that required for the |uint32_t| size, so it won't die in - // the expected way if you pass, e.g., 4. So we have to manufacture a valid - // pointer at an offset of alignment 4. - EXPECT_DEATH_IF_SUPPORTED( - { - uint32_t buffer[100] = {}; - TestOptions* options = (reinterpret_cast<uintptr_t>(buffer) % 8 == 0) - ? reinterpret_cast<TestOptions*>(&buffer[1]) - : reinterpret_cast<TestOptions*>(&buffer[0]); - options->struct_size = static_cast<uint32_t>(sizeof(TestOptions)); - UserOptionsReader<TestOptions> reader(MakeUserPointer(options)); - }, - kMemoryCheckFailedRegex); -} - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher.cc b/third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher.cc deleted file mode 100644 index c67e33e..0000000 --- a/third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher.cc +++ /dev/null @@ -1,119 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher.h" - -#include <algorithm> -#include <limits> -#include <utility> - -#include "base/logging.h" - -namespace mojo { -namespace system { - -namespace { - -const uint32_t kInvalidPlatformHandleIndex = static_cast<uint32_t>(-1); - -struct SerializedPlatformHandleDispatcher { - uint32_t platform_handle_index; // (Or |kInvalidPlatformHandleIndex|.) -}; - -} // namespace - -embedder::ScopedPlatformHandle PlatformHandleDispatcher::PassPlatformHandle() { - MutexLocker locker(&mutex()); - return std::move(platform_handle_); -} - -Dispatcher::Type PlatformHandleDispatcher::GetType() const { - return Type::PLATFORM_HANDLE; -} - -// static -scoped_refptr<PlatformHandleDispatcher> PlatformHandleDispatcher::Deserialize( - Channel* channel, - const void* source, - size_t size, - embedder::PlatformHandleVector* platform_handles) { - if (size != sizeof(SerializedPlatformHandleDispatcher)) { - LOG(ERROR) << "Invalid serialized platform handle dispatcher (bad size)"; - return nullptr; - } - - const SerializedPlatformHandleDispatcher* serialization = - static_cast<const SerializedPlatformHandleDispatcher*>(source); - size_t platform_handle_index = serialization->platform_handle_index; - - // Starts off invalid, which is what we want. - embedder::PlatformHandle platform_handle; - - if (platform_handle_index != kInvalidPlatformHandleIndex) { - if (!platform_handles || - platform_handle_index >= platform_handles->size()) { - LOG(ERROR) - << "Invalid serialized platform handle dispatcher (missing handles)"; - return nullptr; - } - - // We take ownership of the handle, so we have to invalidate the one in - // |platform_handles|. - std::swap(platform_handle, (*platform_handles)[platform_handle_index]); - } - - return Create(embedder::ScopedPlatformHandle(platform_handle)); -} - -PlatformHandleDispatcher::PlatformHandleDispatcher( - embedder::ScopedPlatformHandle platform_handle) - : platform_handle_(std::move(platform_handle)) {} - -PlatformHandleDispatcher::~PlatformHandleDispatcher() { -} - -void PlatformHandleDispatcher::CloseImplNoLock() { - mutex().AssertHeld(); - platform_handle_.reset(); -} - -scoped_refptr<Dispatcher> -PlatformHandleDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() { - mutex().AssertHeld(); - return Create(std::move(platform_handle_)); -} - -void PlatformHandleDispatcher::StartSerializeImplNoLock( - Channel* /*channel*/, - size_t* max_size, - size_t* max_platform_handles) { - DCHECK(HasOneRef()); // Only one ref => no need to take the lock. - *max_size = sizeof(SerializedPlatformHandleDispatcher); - *max_platform_handles = 1; -} - -bool PlatformHandleDispatcher::EndSerializeAndCloseImplNoLock( - Channel* /*channel*/, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) { - DCHECK(HasOneRef()); // Only one ref => no need to take the lock. - - SerializedPlatformHandleDispatcher* serialization = - static_cast<SerializedPlatformHandleDispatcher*>(destination); - if (platform_handle_.is_valid()) { - DCHECK(platform_handles->size() < std::numeric_limits<uint32_t>::max()); - serialization->platform_handle_index = - static_cast<uint32_t>(platform_handles->size()); - platform_handles->push_back(platform_handle_.release()); - } else { - serialization->platform_handle_index = kInvalidPlatformHandleIndex; - } - - *actual_size = sizeof(SerializedPlatformHandleDispatcher); - return true; -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher.h b/third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher.h deleted file mode 100644 index 2a2337d..0000000 --- a/third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher.h +++ /dev/null @@ -1,70 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_PLATFORM_HANDLE_DISPATCHER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_PLATFORM_HANDLE_DISPATCHER_H_ - -#include <utility> - -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" -#include "third_party/mojo/src/mojo/edk/system/simple_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -// A dispatcher that simply wraps/transports a |PlatformHandle| (only for use by -// the embedder). -class MOJO_SYSTEM_IMPL_EXPORT PlatformHandleDispatcher final - : public SimpleDispatcher { - public: - static scoped_refptr<PlatformHandleDispatcher> Create( - embedder::ScopedPlatformHandle platform_handle) { - return make_scoped_refptr( - new PlatformHandleDispatcher(std::move(platform_handle))); - } - - embedder::ScopedPlatformHandle PassPlatformHandle(); - - // |Dispatcher| public methods: - Type GetType() const override; - - // The "opposite" of |SerializeAndClose()|. (Typically this is called by - // |Dispatcher::Deserialize()|.) - static scoped_refptr<PlatformHandleDispatcher> Deserialize( - Channel* channel, - const void* source, - size_t size, - embedder::PlatformHandleVector* platform_handles); - - private: - explicit PlatformHandleDispatcher( - embedder::ScopedPlatformHandle platform_handle); - ~PlatformHandleDispatcher() override; - - // |Dispatcher| protected methods: - void CloseImplNoLock() override; - scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock() - override; - void StartSerializeImplNoLock(Channel* channel, - size_t* max_size, - size_t* max_platform_handles) override - MOJO_NOT_THREAD_SAFE; - bool EndSerializeAndCloseImplNoLock( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) override - MOJO_NOT_THREAD_SAFE; - - embedder::ScopedPlatformHandle platform_handle_ MOJO_GUARDED_BY(mutex()); - - MOJO_DISALLOW_COPY_AND_ASSIGN(PlatformHandleDispatcher); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_PLATFORM_HANDLE_DISPATCHER_H_ diff --git a/third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher_unittest.cc b/third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher_unittest.cc deleted file mode 100644 index f52b0ed..0000000 --- a/third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher_unittest.cc +++ /dev/null @@ -1,112 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher.h" - -#include <stdio.h> -#include <utility> - -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/files/scoped_file.h" -#include "base/files/scoped_temp_dir.h" -#include "base/memory/ref_counted.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/test/test_utils.h" - -namespace mojo { -namespace system { -namespace { - -TEST(PlatformHandleDispatcherTest, Basic) { - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - - static const char kHelloWorld[] = "hello world"; - - base::FilePath unused; - base::ScopedFILE fp( - CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused)); - ASSERT_TRUE(fp); - EXPECT_EQ(sizeof(kHelloWorld), - fwrite(kHelloWorld, 1, sizeof(kHelloWorld), fp.get())); - - embedder::ScopedPlatformHandle h( - mojo::test::PlatformHandleFromFILE(std::move(fp))); - EXPECT_FALSE(fp); - ASSERT_TRUE(h.is_valid()); - - scoped_refptr<PlatformHandleDispatcher> dispatcher = - PlatformHandleDispatcher::Create(std::move(h)); - EXPECT_FALSE(h.is_valid()); - EXPECT_EQ(Dispatcher::Type::PLATFORM_HANDLE, dispatcher->GetType()); - - h = dispatcher->PassPlatformHandle(); - EXPECT_TRUE(h.is_valid()); - - fp = mojo::test::FILEFromPlatformHandle(std::move(h), "rb"); - EXPECT_FALSE(h.is_valid()); - EXPECT_TRUE(fp); - - rewind(fp.get()); - char read_buffer[1000] = {}; - EXPECT_EQ(sizeof(kHelloWorld), - fread(read_buffer, 1, sizeof(read_buffer), fp.get())); - EXPECT_STREQ(kHelloWorld, read_buffer); - - // Try getting the handle again. (It should fail cleanly.) - h = dispatcher->PassPlatformHandle(); - EXPECT_FALSE(h.is_valid()); - - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); -} - -TEST(PlatformHandleDispatcherTest, CreateEquivalentDispatcherAndClose) { - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - - static const char kFooBar[] = "foo bar"; - - base::FilePath unused; - base::ScopedFILE fp( - CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused)); - EXPECT_EQ(sizeof(kFooBar), fwrite(kFooBar, 1, sizeof(kFooBar), fp.get())); - - scoped_refptr<PlatformHandleDispatcher> dispatcher = - PlatformHandleDispatcher::Create( - mojo::test::PlatformHandleFromFILE(std::move(fp))); - - DispatcherTransport transport( - test::DispatcherTryStartTransport(dispatcher.get())); - EXPECT_TRUE(transport.is_valid()); - EXPECT_EQ(Dispatcher::Type::PLATFORM_HANDLE, transport.GetType()); - EXPECT_FALSE(transport.IsBusy()); - - scoped_refptr<Dispatcher> generic_dispatcher = - transport.CreateEquivalentDispatcherAndClose(); - ASSERT_TRUE(generic_dispatcher); - - transport.End(); - EXPECT_TRUE(dispatcher->HasOneRef()); - dispatcher = nullptr; - - ASSERT_EQ(Dispatcher::Type::PLATFORM_HANDLE, generic_dispatcher->GetType()); - dispatcher = static_cast<PlatformHandleDispatcher*>(generic_dispatcher.get()); - - fp = mojo::test::FILEFromPlatformHandle(dispatcher->PassPlatformHandle(), - "rb"); - EXPECT_TRUE(fp); - - rewind(fp.get()); - char read_buffer[1000] = {}; - EXPECT_EQ(sizeof(kFooBar), - fread(read_buffer, 1, sizeof(read_buffer), fp.get())); - EXPECT_STREQ(kFooBar, read_buffer); - - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); -} - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/process_identifier.h b/third_party/mojo/src/mojo/edk/system/process_identifier.h deleted file mode 100644 index dd1157a..0000000 --- a/third_party/mojo/src/mojo/edk/system/process_identifier.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2015 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_PROCESS_IDENTIFIER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_PROCESS_IDENTIFIER_H_ - -#include <stdint.h> - -namespace mojo { -namespace system { - -// Identifiers for processes (note that these are not OS process IDs): -using ProcessIdentifier = uint64_t; - -// Zero will never be a process identifier for any process. -const ProcessIdentifier kInvalidProcessIdentifier = 0; - -// The master process will always have this process identifier. -const ProcessIdentifier kMasterProcessIdentifier = 1; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_PROCESS_IDENTIFIER_H_ diff --git a/third_party/mojo/src/mojo/edk/system/proxy_message_pipe_endpoint.cc b/third_party/mojo/src/mojo/edk/system/proxy_message_pipe_endpoint.cc deleted file mode 100644 index a648bfd..0000000 --- a/third_party/mojo/src/mojo/edk/system/proxy_message_pipe_endpoint.cc +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/proxy_message_pipe_endpoint.h" - -#include <string.h> -#include <utility> - -#include "base/logging.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/local_message_pipe_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.h" - -namespace mojo { -namespace system { - -ProxyMessagePipeEndpoint::ProxyMessagePipeEndpoint( - ChannelEndpoint* channel_endpoint) - : channel_endpoint_(channel_endpoint) { -} - -ProxyMessagePipeEndpoint::~ProxyMessagePipeEndpoint() { - DCHECK(!channel_endpoint_); -} - -scoped_refptr<ChannelEndpoint> -ProxyMessagePipeEndpoint::ReleaseChannelEndpoint() { - DCHECK(channel_endpoint_); - scoped_refptr<ChannelEndpoint> rv; - rv.swap(channel_endpoint_); - return rv; -} - -MessagePipeEndpoint::Type ProxyMessagePipeEndpoint::GetType() const { - return kTypeProxy; -} - -bool ProxyMessagePipeEndpoint::OnPeerClose() { - DetachIfNecessary(); - return false; -} - -// Note: We may have to enqueue messages even when our (local) peer isn't open -// -- it may have been written to and closed immediately, before we were ready. -// This case is handled in |Run()| (which will call us). -void ProxyMessagePipeEndpoint::EnqueueMessage( - scoped_ptr<MessageInTransit> message) { - DCHECK(channel_endpoint_); - bool ok = channel_endpoint_->EnqueueMessage(std::move(message)); - LOG_IF(WARNING, !ok) << "Failed to write enqueue message to channel"; -} - -void ProxyMessagePipeEndpoint::Close() { - DetachIfNecessary(); -} - -void ProxyMessagePipeEndpoint::DetachIfNecessary() { - if (channel_endpoint_) { - channel_endpoint_->DetachFromClient(); - channel_endpoint_ = nullptr; - } -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/proxy_message_pipe_endpoint.h b/third_party/mojo/src/mojo/edk/system/proxy_message_pipe_endpoint.h deleted file mode 100644 index 9e649fa..0000000 --- a/third_party/mojo/src/mojo/edk/system/proxy_message_pipe_endpoint.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_PROXY_MESSAGE_PIPE_ENDPOINT_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_PROXY_MESSAGE_PIPE_ENDPOINT_H_ - -#include "base/memory/ref_counted.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -class ChannelEndpoint; -class LocalMessagePipeEndpoint; -class MessagePipe; - -// A |ProxyMessagePipeEndpoint| is an endpoint which delegates everything to a -// |ChannelEndpoint|, which may be co-owned by a |Channel|. Like any -// |MessagePipeEndpoint|, a |ProxyMessagePipeEndpoint| is owned by a -// |MessagePipe|. -// -// For example, a |MessagePipe| with one endpoint local and the other endpoint -// remote consists of a |LocalMessagePipeEndpoint| and a -// |ProxyMessagePipeEndpoint|, with only the local endpoint being accessible via -// a |MessagePipeDispatcher|. -class MOJO_SYSTEM_IMPL_EXPORT ProxyMessagePipeEndpoint final - : public MessagePipeEndpoint { - public: - explicit ProxyMessagePipeEndpoint(ChannelEndpoint* channel_endpoint); - ~ProxyMessagePipeEndpoint() override; - - // Returns |channel_endpoint_| and resets |channel_endpoint_| to null. This - // may be called at most once, after which |Close()| need not be called. - // - // Note: The returned |ChannelEndpoint| must have its client changed while - // still under |MessagePipe|'s lock (which this must have also been called - // under). - scoped_refptr<ChannelEndpoint> ReleaseChannelEndpoint(); - - // |MessagePipeEndpoint| implementation: - Type GetType() const override; - bool OnPeerClose() override; - void EnqueueMessage(scoped_ptr<MessageInTransit> message) override; - void Close() override; - - private: - void DetachIfNecessary(); - - scoped_refptr<ChannelEndpoint> channel_endpoint_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ProxyMessagePipeEndpoint); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_PROXY_MESSAGE_PIPE_ENDPOINT_H_ diff --git a/third_party/mojo/src/mojo/edk/system/raw_channel.cc b/third_party/mojo/src/mojo/edk/system/raw_channel.cc deleted file mode 100644 index 3068dce..0000000 --- a/third_party/mojo/src/mojo/edk/system/raw_channel.cc +++ /dev/null @@ -1,511 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/raw_channel.h" - -#include <string.h> -#include <algorithm> -#include <utility> - -#include "base/bind.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit.h" -#include "third_party/mojo/src/mojo/edk/system/transport_data.h" - -namespace mojo { -namespace system { - -const size_t kReadSize = 4096; - -// RawChannel::ReadBuffer ------------------------------------------------------ - -RawChannel::ReadBuffer::ReadBuffer() : buffer_(kReadSize), num_valid_bytes_(0) { -} - -RawChannel::ReadBuffer::~ReadBuffer() { -} - -void RawChannel::ReadBuffer::GetBuffer(char** addr, size_t* size) { - DCHECK_GE(buffer_.size(), num_valid_bytes_ + kReadSize); - *addr = &buffer_[0] + num_valid_bytes_; - *size = kReadSize; -} - -// RawChannel::WriteBuffer ----------------------------------------------------- - -RawChannel::WriteBuffer::WriteBuffer(size_t serialized_platform_handle_size) - : serialized_platform_handle_size_(serialized_platform_handle_size), - platform_handles_offset_(0), - data_offset_(0) { -} - -RawChannel::WriteBuffer::~WriteBuffer() { - message_queue_.Clear(); -} - -bool RawChannel::WriteBuffer::HavePlatformHandlesToSend() const { - if (message_queue_.IsEmpty()) - return false; - - const TransportData* transport_data = - message_queue_.PeekMessage()->transport_data(); - if (!transport_data) - return false; - - const embedder::PlatformHandleVector* all_platform_handles = - transport_data->platform_handles(); - if (!all_platform_handles) { - DCHECK_EQ(platform_handles_offset_, 0u); - return false; - } - if (platform_handles_offset_ >= all_platform_handles->size()) { - DCHECK_EQ(platform_handles_offset_, all_platform_handles->size()); - return false; - } - - return true; -} - -void RawChannel::WriteBuffer::GetPlatformHandlesToSend( - size_t* num_platform_handles, - embedder::PlatformHandle** platform_handles, - void** serialization_data) { - DCHECK(HavePlatformHandlesToSend()); - - MessageInTransit* message = message_queue_.PeekMessage(); - TransportData* transport_data = message->transport_data(); - embedder::PlatformHandleVector* all_platform_handles = - transport_data->platform_handles(); - *num_platform_handles = - all_platform_handles->size() - platform_handles_offset_; - *platform_handles = &(*all_platform_handles)[platform_handles_offset_]; - - if (serialized_platform_handle_size_ > 0) { - size_t serialization_data_offset = - transport_data->platform_handle_table_offset(); - serialization_data_offset += - platform_handles_offset_ * serialized_platform_handle_size_; - *serialization_data = static_cast<char*>(transport_data->buffer()) + - serialization_data_offset; - } else { - *serialization_data = nullptr; - } -} - -void RawChannel::WriteBuffer::GetBuffers(std::vector<Buffer>* buffers) const { - buffers->clear(); - - if (message_queue_.IsEmpty()) - return; - - const MessageInTransit* message = message_queue_.PeekMessage(); - DCHECK_LT(data_offset_, message->total_size()); - size_t bytes_to_write = message->total_size() - data_offset_; - - size_t transport_data_buffer_size = - message->transport_data() ? message->transport_data()->buffer_size() : 0; - - if (!transport_data_buffer_size) { - // Only write from the main buffer. - DCHECK_LT(data_offset_, message->main_buffer_size()); - DCHECK_LE(bytes_to_write, message->main_buffer_size()); - Buffer buffer = { - static_cast<const char*>(message->main_buffer()) + data_offset_, - bytes_to_write}; - buffers->push_back(buffer); - return; - } - - if (data_offset_ >= message->main_buffer_size()) { - // Only write from the transport data buffer. - DCHECK_LT(data_offset_ - message->main_buffer_size(), - transport_data_buffer_size); - DCHECK_LE(bytes_to_write, transport_data_buffer_size); - Buffer buffer = { - static_cast<const char*>(message->transport_data()->buffer()) + - (data_offset_ - message->main_buffer_size()), - bytes_to_write}; - buffers->push_back(buffer); - return; - } - - // TODO(vtl): We could actually send out buffers from multiple messages, with - // the "stopping" condition being reaching a message with platform handles - // attached. - - // Write from both buffers. - DCHECK_EQ(bytes_to_write, message->main_buffer_size() - data_offset_ + - transport_data_buffer_size); - Buffer buffer1 = { - static_cast<const char*>(message->main_buffer()) + data_offset_, - message->main_buffer_size() - data_offset_}; - buffers->push_back(buffer1); - Buffer buffer2 = { - static_cast<const char*>(message->transport_data()->buffer()), - transport_data_buffer_size}; - buffers->push_back(buffer2); -} - -// RawChannel ------------------------------------------------------------------ - -RawChannel::RawChannel() - : message_loop_for_io_(nullptr), - delegate_(nullptr), - set_on_shutdown_(nullptr), - write_stopped_(false), - weak_ptr_factory_(this) { -} - -RawChannel::~RawChannel() { - DCHECK(!read_buffer_); - DCHECK(!write_buffer_); - - // No need to take the |write_lock_| here -- if there are still weak pointers - // outstanding, then we're hosed anyway (since we wouldn't be able to - // invalidate them cleanly, since we might not be on the I/O thread). - DCHECK(!weak_ptr_factory_.HasWeakPtrs()); -} - -void RawChannel::Init(Delegate* delegate) { - DCHECK(delegate); - - DCHECK(!delegate_); - delegate_ = delegate; - - CHECK_EQ(base::MessageLoop::current()->type(), base::MessageLoop::TYPE_IO); - DCHECK(!message_loop_for_io_); - message_loop_for_io_ = - static_cast<base::MessageLoopForIO*>(base::MessageLoop::current()); - - // No need to take the lock. No one should be using us yet. - DCHECK(!read_buffer_); - read_buffer_.reset(new ReadBuffer); - DCHECK(!write_buffer_); - write_buffer_.reset(new WriteBuffer(GetSerializedPlatformHandleSize())); - - OnInit(); - - IOResult io_result = ScheduleRead(); - if (io_result != IO_PENDING) { - // This will notify the delegate about the read failure. Although we're on - // the I/O thread, don't call it in the nested context. - message_loop_for_io_->PostTask( - FROM_HERE, base::Bind(&RawChannel::OnReadCompleted, - weak_ptr_factory_.GetWeakPtr(), io_result, 0)); - } - // Note: |ScheduleRead()| failure is treated as a read failure (by notifying - // the delegate), not an initialization failure. -} - -void RawChannel::Shutdown() { - DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io_); - - base::AutoLock locker(write_lock_); - - LOG_IF(WARNING, !write_buffer_->message_queue_.IsEmpty()) - << "Shutting down RawChannel with write buffer nonempty"; - - // Reset the delegate so that it won't receive further calls. - delegate_ = nullptr; - if (set_on_shutdown_) { - *set_on_shutdown_ = true; - set_on_shutdown_ = nullptr; - } - write_stopped_ = true; - weak_ptr_factory_.InvalidateWeakPtrs(); - - OnShutdownNoLock(std::move(read_buffer_), std::move(write_buffer_)); -} - -// Reminder: This must be thread-safe. -bool RawChannel::WriteMessage(scoped_ptr<MessageInTransit> message) { - DCHECK(message); - - base::AutoLock locker(write_lock_); - if (write_stopped_) - return false; - - if (!write_buffer_->message_queue_.IsEmpty()) { - EnqueueMessageNoLock(std::move(message)); - return true; - } - - EnqueueMessageNoLock(std::move(message)); - DCHECK_EQ(write_buffer_->data_offset_, 0u); - - size_t platform_handles_written = 0; - size_t bytes_written = 0; - IOResult io_result = WriteNoLock(&platform_handles_written, &bytes_written); - if (io_result == IO_PENDING) - return true; - - bool result = OnWriteCompletedNoLock(io_result, platform_handles_written, - bytes_written); - if (!result) { - // Even if we're on the I/O thread, don't call |OnError()| in the nested - // context. - message_loop_for_io_->PostTask( - FROM_HERE, - base::Bind(&RawChannel::CallOnError, weak_ptr_factory_.GetWeakPtr(), - Delegate::ERROR_WRITE)); - } - - return result; -} - -// Reminder: This must be thread-safe. -bool RawChannel::IsWriteBufferEmpty() { - base::AutoLock locker(write_lock_); - return write_buffer_->message_queue_.IsEmpty(); -} - -void RawChannel::OnReadCompleted(IOResult io_result, size_t bytes_read) { - DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io_); - - // Keep reading data in a loop, and dispatch messages if enough data is - // received. Exit the loop if any of the following happens: - // - one or more messages were dispatched; - // - the last read failed, was a partial read or would block; - // - |Shutdown()| was called. - do { - switch (io_result) { - case IO_SUCCEEDED: - break; - case IO_FAILED_SHUTDOWN: - case IO_FAILED_BROKEN: - case IO_FAILED_UNKNOWN: - CallOnError(ReadIOResultToError(io_result)); - return; // |this| may have been destroyed in |CallOnError()|. - case IO_PENDING: - NOTREACHED(); - return; - } - - read_buffer_->num_valid_bytes_ += bytes_read; - - // Dispatch all the messages that we can. - bool did_dispatch_message = false; - // Tracks the offset of the first undispatched message in |read_buffer_|. - // Currently, we copy data to ensure that this is zero at the beginning. - size_t read_buffer_start = 0; - size_t remaining_bytes = read_buffer_->num_valid_bytes_; - size_t message_size; - // Note that we rely on short-circuit evaluation here: - // - |read_buffer_start| may be an invalid index into - // |read_buffer_->buffer_| if |remaining_bytes| is zero. - // - |message_size| is only valid if |GetNextMessageSize()| returns true. - // TODO(vtl): Use |message_size| more intelligently (e.g., to request the - // next read). - // TODO(vtl): Validate that |message_size| is sane. - while (remaining_bytes > 0 && MessageInTransit::GetNextMessageSize( - &read_buffer_->buffer_[read_buffer_start], - remaining_bytes, &message_size) && - remaining_bytes >= message_size) { - MessageInTransit::View message_view( - message_size, &read_buffer_->buffer_[read_buffer_start]); - DCHECK_EQ(message_view.total_size(), message_size); - - const char* error_message = nullptr; - if (!message_view.IsValid(GetSerializedPlatformHandleSize(), - &error_message)) { - DCHECK(error_message); - LOG(ERROR) << "Received invalid message: " << error_message; - CallOnError(Delegate::ERROR_READ_BAD_MESSAGE); - return; // |this| may have been destroyed in |CallOnError()|. - } - - if (message_view.type() == MessageInTransit::Type::RAW_CHANNEL) { - if (!OnReadMessageForRawChannel(message_view)) { - CallOnError(Delegate::ERROR_READ_BAD_MESSAGE); - return; // |this| may have been destroyed in |CallOnError()|. - } - } else { - embedder::ScopedPlatformHandleVectorPtr platform_handles; - if (message_view.transport_data_buffer()) { - size_t num_platform_handles; - const void* platform_handle_table; - TransportData::GetPlatformHandleTable( - message_view.transport_data_buffer(), &num_platform_handles, - &platform_handle_table); - - if (num_platform_handles > 0) { - platform_handles = GetReadPlatformHandles(num_platform_handles, - platform_handle_table); - if (!platform_handles) { - LOG(ERROR) << "Invalid number of platform handles received"; - CallOnError(Delegate::ERROR_READ_BAD_MESSAGE); - return; // |this| may have been destroyed in |CallOnError()|. - } - } - } - - // TODO(vtl): In the case that we aren't expecting any platform handles, - // for the POSIX implementation, we should confirm that none are stored. - - // Dispatch the message. - // Detect the case when |Shutdown()| is called; subsequent destruction - // is also permitted then. - bool shutdown_called = false; - DCHECK(!set_on_shutdown_); - set_on_shutdown_ = &shutdown_called; - DCHECK(delegate_); - delegate_->OnReadMessage(message_view, std::move(platform_handles)); - if (shutdown_called) - return; - set_on_shutdown_ = nullptr; - } - - did_dispatch_message = true; - - // Update our state. - read_buffer_start += message_size; - remaining_bytes -= message_size; - } - - if (read_buffer_start > 0) { - // Move data back to start. - read_buffer_->num_valid_bytes_ = remaining_bytes; - if (read_buffer_->num_valid_bytes_ > 0) { - memmove(&read_buffer_->buffer_[0], - &read_buffer_->buffer_[read_buffer_start], remaining_bytes); - } - read_buffer_start = 0; - } - - if (read_buffer_->buffer_.size() - read_buffer_->num_valid_bytes_ < - kReadSize) { - // Use power-of-2 buffer sizes. - // TODO(vtl): Make sure the buffer doesn't get too large (and enforce the - // maximum message size to whatever extent necessary). - // TODO(vtl): We may often be able to peek at the header and get the real - // required extra space (which may be much bigger than |kReadSize|). - size_t new_size = std::max(read_buffer_->buffer_.size(), kReadSize); - while (new_size < read_buffer_->num_valid_bytes_ + kReadSize) - new_size *= 2; - - // TODO(vtl): It's suboptimal to zero out the fresh memory. - read_buffer_->buffer_.resize(new_size, 0); - } - - // (1) If we dispatched any messages, stop reading for now (and let the - // message loop do its thing for another round). - // TODO(vtl): Is this the behavior we want? (Alternatives: i. Dispatch only - // a single message. Risks: slower, more complex if we want to avoid lots of - // copying. ii. Keep reading until there's no more data and dispatch all the - // messages we can. Risks: starvation of other users of the message loop.) - // (2) If we didn't max out |kReadSize|, stop reading for now. - bool schedule_for_later = did_dispatch_message || bytes_read < kReadSize; - bytes_read = 0; - io_result = schedule_for_later ? ScheduleRead() : Read(&bytes_read); - } while (io_result != IO_PENDING); -} - -void RawChannel::OnWriteCompleted(IOResult io_result, - size_t platform_handles_written, - size_t bytes_written) { - DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io_); - DCHECK_NE(io_result, IO_PENDING); - - bool did_fail = false; - { - base::AutoLock locker(write_lock_); - DCHECK_EQ(write_stopped_, write_buffer_->message_queue_.IsEmpty()); - - if (write_stopped_) { - NOTREACHED(); - return; - } - - did_fail = !OnWriteCompletedNoLock(io_result, platform_handles_written, - bytes_written); - } - - if (did_fail) { - CallOnError(Delegate::ERROR_WRITE); - return; // |this| may have been destroyed in |CallOnError()|. - } -} - -void RawChannel::EnqueueMessageNoLock(scoped_ptr<MessageInTransit> message) { - write_lock_.AssertAcquired(); - write_buffer_->message_queue_.AddMessage(std::move(message)); -} - -bool RawChannel::OnReadMessageForRawChannel( - const MessageInTransit::View& message_view) { - // No non-implementation specific |RawChannel| control messages. - LOG(ERROR) << "Invalid control message (subtype " << message_view.subtype() - << ")"; - return false; -} - -// static -RawChannel::Delegate::Error RawChannel::ReadIOResultToError( - IOResult io_result) { - switch (io_result) { - case IO_FAILED_SHUTDOWN: - return Delegate::ERROR_READ_SHUTDOWN; - case IO_FAILED_BROKEN: - return Delegate::ERROR_READ_BROKEN; - case IO_FAILED_UNKNOWN: - return Delegate::ERROR_READ_UNKNOWN; - case IO_SUCCEEDED: - case IO_PENDING: - NOTREACHED(); - break; - } - return Delegate::ERROR_READ_UNKNOWN; -} - -void RawChannel::CallOnError(Delegate::Error error) { - DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io_); - // TODO(vtl): Add a "write_lock_.AssertNotAcquired()"? - if (delegate_) { - delegate_->OnError(error); - return; // |this| may have been destroyed in |OnError()|. - } -} - -bool RawChannel::OnWriteCompletedNoLock(IOResult io_result, - size_t platform_handles_written, - size_t bytes_written) { - write_lock_.AssertAcquired(); - - DCHECK(!write_stopped_); - DCHECK(!write_buffer_->message_queue_.IsEmpty()); - - if (io_result == IO_SUCCEEDED) { - write_buffer_->platform_handles_offset_ += platform_handles_written; - write_buffer_->data_offset_ += bytes_written; - - MessageInTransit* message = write_buffer_->message_queue_.PeekMessage(); - if (write_buffer_->data_offset_ >= message->total_size()) { - // Complete write. - CHECK_EQ(write_buffer_->data_offset_, message->total_size()); - write_buffer_->message_queue_.DiscardMessage(); - write_buffer_->platform_handles_offset_ = 0; - write_buffer_->data_offset_ = 0; - - if (write_buffer_->message_queue_.IsEmpty()) - return true; - } - - // Schedule the next write. - io_result = ScheduleWriteNoLock(); - if (io_result == IO_PENDING) - return true; - DCHECK_NE(io_result, IO_SUCCEEDED); - } - - write_stopped_ = true; - write_buffer_->message_queue_.Clear(); - write_buffer_->platform_handles_offset_ = 0; - write_buffer_->data_offset_ = 0; - return false; -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/raw_channel.h b/third_party/mojo/src/mojo/edk/system/raw_channel.h deleted file mode 100644 index 35f7a3e..0000000 --- a/third_party/mojo/src/mojo/edk/system/raw_channel.h +++ /dev/null @@ -1,333 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_RAW_CHANNEL_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_RAW_CHANNEL_H_ - -#include <vector> - -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/synchronization/lock.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle_vector.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit_queue.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace base { -class MessageLoopForIO; -} - -namespace mojo { -namespace system { - -// |RawChannel| is an interface and base class for objects that wrap an OS -// "pipe". It presents the following interface to users: -// - Receives and dispatches messages on an I/O thread (running a -// |MessageLoopForIO|. -// - Provides a thread-safe way of writing messages (|WriteMessage()|); -// writing/queueing messages will not block and is atomic from the point of -// view of the caller. If necessary, messages are queued (to be written on -// the aforementioned thread). -// -// OS-specific implementation subclasses are to be instantiated using the -// |Create()| static factory method. -// -// With the exception of |WriteMessage()|, this class is thread-unsafe (and in -// general its methods should only be used on the I/O thread, i.e., the thread -// on which |Init()| is called). -class MOJO_SYSTEM_IMPL_EXPORT RawChannel { - public: - // This object may be destroyed on any thread (if |Init()| was called, after - // |Shutdown()| was called). - virtual ~RawChannel(); - - // The |Delegate| is only accessed on the same thread as the message loop - // (passed in on creation). - class MOJO_SYSTEM_IMPL_EXPORT Delegate { - public: - enum Error { - // Failed read due to raw channel shutdown (e.g., on the other side). - ERROR_READ_SHUTDOWN, - // Failed read due to raw channel being broken (e.g., if the other side - // died without shutting down). - ERROR_READ_BROKEN, - // Received a bad message. - ERROR_READ_BAD_MESSAGE, - // Unknown read error. - ERROR_READ_UNKNOWN, - // Generic write error. - ERROR_WRITE - }; - - // Called when a message is read. This may call the |RawChannel|'s - // |Shutdown()| and then (if desired) destroy it. - virtual void OnReadMessage( - const MessageInTransit::View& message_view, - embedder::ScopedPlatformHandleVectorPtr platform_handles) = 0; - - // Called when there's a (fatal) error. This may call the |RawChannel|'s - // |Shutdown()| and then (if desired) destroy it. - // - // For each raw channel, there'll be at most one |ERROR_READ_...| and at - // most one |ERROR_WRITE| notification. After |OnError(ERROR_READ_...)|, - // |OnReadMessage()| won't be called again. - virtual void OnError(Error error) = 0; - - protected: - virtual ~Delegate() {} - }; - - // Static factory method. |handle| should be a handle to a - // (platform-appropriate) bidirectional communication channel (e.g., a socket - // on POSIX, a named pipe on Windows). - static scoped_ptr<RawChannel> Create(embedder::ScopedPlatformHandle handle); - - // This must be called (on an I/O thread) before this object is used. Does - // *not* take ownership of |delegate|. Both the I/O thread and |delegate| must - // remain alive until |Shutdown()| is called (unless this fails); |delegate| - // will no longer be used after |Shutdown()|. - void Init(Delegate* delegate); - - // This must be called (on the I/O thread) before this object is destroyed. - void Shutdown(); - - // Writes the given message (or schedules it to be written). |message| must - // have no |Dispatcher|s still attached (i.e., - // |SerializeAndCloseDispatchers()| should have been called). This method is - // thread-safe and may be called from any thread. Returns true on success. - bool WriteMessage(scoped_ptr<MessageInTransit> message); - - // Returns true if the write buffer is empty (i.e., all messages written using - // |WriteMessage()| have actually been sent. - // TODO(vtl): We should really also notify our delegate when the write buffer - // becomes empty (or something like that). - bool IsWriteBufferEmpty(); - - // Returns the amount of space needed in the |MessageInTransit|'s - // |TransportData|'s "platform handle table" per platform handle (to be - // attached to a message). (This amount may be zero.) - virtual size_t GetSerializedPlatformHandleSize() const = 0; - - protected: - // Result of I/O operations. - enum IOResult { - IO_SUCCEEDED, - // Failed due to a (probably) clean shutdown (e.g., of the other end). - IO_FAILED_SHUTDOWN, - // Failed due to the connection being broken (e.g., the other end dying). - IO_FAILED_BROKEN, - // Failed due to some other (unexpected) reason. - IO_FAILED_UNKNOWN, - IO_PENDING - }; - - class MOJO_SYSTEM_IMPL_EXPORT ReadBuffer { - public: - ReadBuffer(); - ~ReadBuffer(); - - void GetBuffer(char** addr, size_t* size); - - private: - friend class RawChannel; - - // We store data from |[Schedule]Read()|s in |buffer_|. The start of - // |buffer_| is always aligned with a message boundary (we will copy memory - // to ensure this), but |buffer_| may be larger than the actual number of - // bytes we have. - std::vector<char> buffer_; - size_t num_valid_bytes_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ReadBuffer); - }; - - class MOJO_SYSTEM_IMPL_EXPORT WriteBuffer { - public: - struct Buffer { - const char* addr; - size_t size; - }; - - explicit WriteBuffer(size_t serialized_platform_handle_size); - ~WriteBuffer(); - - // Returns true if there are (more) platform handles to be sent (from the - // front of |message_queue_|). - bool HavePlatformHandlesToSend() const; - // Gets platform handles to be sent (from the front of |message_queue_|). - // This should only be called if |HavePlatformHandlesToSend()| returned - // true. There are two components to this: the actual |PlatformHandle|s - // (which should be closed once sent) and any additional serialization - // information (which will be embedded in the message's data; there are - // |GetSerializedPlatformHandleSize()| bytes per handle). Once all platform - // handles have been sent, the message data should be written next (see - // |GetBuffers()|). - // TODO(vtl): Maybe this method should be const, but - // |PlatformHandle::CloseIfNecessary()| isn't const (and actually modifies - // state). - void GetPlatformHandlesToSend(size_t* num_platform_handles, - embedder::PlatformHandle** platform_handles, - void** serialization_data); - - // Gets buffers to be written. These buffers will always come from the front - // of |message_queue_|. Once they are completely written, the front - // |MessageInTransit| should be popped (and destroyed); this is done in - // |OnWriteCompletedNoLock()|. - void GetBuffers(std::vector<Buffer>* buffers) const; - - private: - friend class RawChannel; - - const size_t serialized_platform_handle_size_; - - MessageInTransitQueue message_queue_; - // Platform handles are sent before the message data, but doing so may - // require several passes. |platform_handles_offset_| indicates the position - // in the first message's vector of platform handles to send next. - size_t platform_handles_offset_; - // The first message's data may have been partially sent. |data_offset_| - // indicates the position in the first message's data to start the next - // write. - size_t data_offset_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(WriteBuffer); - }; - - RawChannel(); - - // |result| must not be |IO_PENDING|. Must be called on the I/O thread WITHOUT - // |write_lock_| held. This object may be destroyed by this call. - void OnReadCompleted(IOResult io_result, size_t bytes_read); - // |result| must not be |IO_PENDING|. Must be called on the I/O thread WITHOUT - // |write_lock_| held. This object may be destroyed by this call. - void OnWriteCompleted(IOResult io_result, - size_t platform_handles_written, - size_t bytes_written); - - base::MessageLoopForIO* message_loop_for_io() { return message_loop_for_io_; } - base::Lock& write_lock() { return write_lock_; } - - // Should only be called on the I/O thread. - ReadBuffer* read_buffer() { return read_buffer_.get(); } - - // Only called under |write_lock_|. - WriteBuffer* write_buffer_no_lock() { - write_lock_.AssertAcquired(); - return write_buffer_.get(); - } - - // Adds |message| to the write message queue. Implementation subclasses may - // override this to add any additional "control" messages needed. This is - // called (on any thread) with |write_lock_| held. - virtual void EnqueueMessageNoLock(scoped_ptr<MessageInTransit> message); - - // Handles any control messages targeted to the |RawChannel| (or - // implementation subclass). Implementation subclasses may override this to - // handle any implementation-specific control messages, but should call - // |RawChannel::OnReadMessageForRawChannel()| for any remaining messages. - // Returns true on success and false on error (e.g., invalid control message). - // This is only called on the I/O thread. - virtual bool OnReadMessageForRawChannel( - const MessageInTransit::View& message_view); - - // Reads into |read_buffer()|. - // This class guarantees that: - // - the area indicated by |GetBuffer()| will stay valid until read completion - // (but please also see the comments for |OnShutdownNoLock()|); - // - a second read is not started if there is a pending read; - // - the method is called on the I/O thread WITHOUT |write_lock_| held. - // - // The implementing subclass must guarantee that: - // - |bytes_read| is untouched unless |Read()| returns |IO_SUCCEEDED|; - // - if the method returns |IO_PENDING|, |OnReadCompleted()| will be called on - // the I/O thread to report the result, unless |Shutdown()| is called. - virtual IOResult Read(size_t* bytes_read) = 0; - // Similar to |Read()|, except that the implementing subclass must also - // guarantee that the method doesn't succeed synchronously, i.e., it only - // returns |IO_FAILED_...| or |IO_PENDING|. - virtual IOResult ScheduleRead() = 0; - - // Called by |OnReadCompleted()| to get the platform handles associated with - // the given platform handle table (from a message). This should only be - // called when |num_platform_handles| is nonzero. Returns null if the - // |num_platform_handles| handles are not available. Only called on the I/O - // thread (without |write_lock_| held). - virtual embedder::ScopedPlatformHandleVectorPtr GetReadPlatformHandles( - size_t num_platform_handles, - const void* platform_handle_table) = 0; - - // Writes contents in |write_buffer_no_lock()|. - // This class guarantees that: - // - the |PlatformHandle|s given by |GetPlatformHandlesToSend()| and the - // buffer(s) given by |GetBuffers()| will remain valid until write - // completion (see also the comments for |OnShutdownNoLock()|); - // - a second write is not started if there is a pending write; - // - the method is called under |write_lock_|. - // - // The implementing subclass must guarantee that: - // - |platform_handles_written| and |bytes_written| are untouched unless - // |WriteNoLock()| returns |IO_SUCCEEDED|; - // - if the method returns |IO_PENDING|, |OnWriteCompleted()| will be called - // on the I/O thread to report the result, unless |Shutdown()| is called. - virtual IOResult WriteNoLock(size_t* platform_handles_written, - size_t* bytes_written) = 0; - // Similar to |WriteNoLock()|, except that the implementing subclass must also - // guarantee that the method doesn't succeed synchronously, i.e., it only - // returns |IO_FAILED_...| or |IO_PENDING|. - virtual IOResult ScheduleWriteNoLock() = 0; - - // Must be called on the I/O thread WITHOUT |write_lock_| held. - virtual void OnInit() = 0; - // On shutdown, passes the ownership of the buffers to subclasses, which may - // want to preserve them if there are pending read/writes. After this is - // called, |OnReadCompleted()| must no longer be called. Must be called on the - // I/O thread under |write_lock_|. - virtual void OnShutdownNoLock(scoped_ptr<ReadBuffer> read_buffer, - scoped_ptr<WriteBuffer> write_buffer) = 0; - - private: - // Converts an |IO_FAILED_...| for a read to a |Delegate::Error|. - static Delegate::Error ReadIOResultToError(IOResult io_result); - - // Calls |delegate_->OnError(error)|. Must be called on the I/O thread WITHOUT - // |write_lock_| held. This object may be destroyed by this call. - void CallOnError(Delegate::Error error); - - // If |io_result| is |IO_SUCCESS|, updates the write buffer and schedules a - // write operation to run later if there is more to write. If |io_result| is - // failure or any other error occurs, cancels pending writes and returns - // false. Must be called under |write_lock_| and only if |write_stopped_| is - // false. - bool OnWriteCompletedNoLock(IOResult io_result, - size_t platform_handles_written, - size_t bytes_written); - - // Set in |Init()| and never changed (hence usable on any thread without - // locking): - base::MessageLoopForIO* message_loop_for_io_; - - // Only used on the I/O thread: - Delegate* delegate_; - bool* set_on_shutdown_; - scoped_ptr<ReadBuffer> read_buffer_; - - base::Lock write_lock_; // Protects the following members. - bool write_stopped_; - scoped_ptr<WriteBuffer> write_buffer_; - - // This is used for posting tasks from write threads to the I/O thread. It - // must only be accessed under |write_lock_|. The weak pointers it produces - // are only used/invalidated on the I/O thread. - base::WeakPtrFactory<RawChannel> weak_ptr_factory_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(RawChannel); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_RAW_CHANNEL_H_ diff --git a/third_party/mojo/src/mojo/edk/system/raw_channel_posix.cc b/third_party/mojo/src/mojo/edk/system/raw_channel_posix.cc deleted file mode 100644 index 789ab4c..0000000 --- a/third_party/mojo/src/mojo/edk/system/raw_channel_posix.cc +++ /dev/null @@ -1,479 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/raw_channel.h" - -#include <errno.h> -#include <sys/uio.h> -#include <unistd.h> -#include <algorithm> -#include <deque> -#include <utility> - -#include "base/bind.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/message_loop/message_loop.h" -#include "base/synchronization/lock.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_utils_posix.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle_vector.h" -#include "third_party/mojo/src/mojo/edk/system/transport_data.h" - -namespace mojo { -namespace system { - -namespace { - -class RawChannelPosix final : public RawChannel, - public base::MessageLoopForIO::Watcher { - public: - explicit RawChannelPosix(embedder::ScopedPlatformHandle handle); - ~RawChannelPosix() override; - - // |RawChannel| public methods: - size_t GetSerializedPlatformHandleSize() const override; - - private: - // |RawChannel| protected methods: - // Actually override this so that we can send multiple messages with (only) - // FDs if necessary. - void EnqueueMessageNoLock(scoped_ptr<MessageInTransit> message) override; - // Override this to handle those extra FD-only messages. - bool OnReadMessageForRawChannel( - const MessageInTransit::View& message_view) override; - IOResult Read(size_t* bytes_read) override; - IOResult ScheduleRead() override; - embedder::ScopedPlatformHandleVectorPtr GetReadPlatformHandles( - size_t num_platform_handles, - const void* platform_handle_table) override; - IOResult WriteNoLock(size_t* platform_handles_written, - size_t* bytes_written) override; - IOResult ScheduleWriteNoLock() override; - void OnInit() override; - void OnShutdownNoLock(scoped_ptr<ReadBuffer> read_buffer, - scoped_ptr<WriteBuffer> write_buffer) override; - - // |base::MessageLoopForIO::Watcher| implementation: - void OnFileCanReadWithoutBlocking(int fd) override; - void OnFileCanWriteWithoutBlocking(int fd) override; - - // Implements most of |Read()| (except for a bit of clean-up): - IOResult ReadImpl(size_t* bytes_read); - - // Watches for |fd_| to become writable. Must be called on the I/O thread. - void WaitToWrite(); - - embedder::ScopedPlatformHandle fd_; - - // The following members are only used on the I/O thread: - scoped_ptr<base::MessageLoopForIO::FileDescriptorWatcher> read_watcher_; - scoped_ptr<base::MessageLoopForIO::FileDescriptorWatcher> write_watcher_; - - bool pending_read_; - - std::deque<embedder::PlatformHandle> read_platform_handles_; - - // The following members are used on multiple threads and protected by - // |write_lock()|: - bool pending_write_; - - // This is used for posting tasks from write threads to the I/O thread. It - // must only be accessed under |write_lock_|. The weak pointers it produces - // are only used/invalidated on the I/O thread. - base::WeakPtrFactory<RawChannelPosix> weak_ptr_factory_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(RawChannelPosix); -}; - -RawChannelPosix::RawChannelPosix(embedder::ScopedPlatformHandle handle) - : fd_(std::move(handle)), - pending_read_(false), - pending_write_(false), - weak_ptr_factory_(this) { - DCHECK(fd_.is_valid()); -} - -RawChannelPosix::~RawChannelPosix() { - DCHECK(!pending_read_); - DCHECK(!pending_write_); - - // No need to take the |write_lock()| here -- if there are still weak pointers - // outstanding, then we're hosed anyway (since we wouldn't be able to - // invalidate them cleanly, since we might not be on the I/O thread). - DCHECK(!weak_ptr_factory_.HasWeakPtrs()); - - // These must have been shut down/destroyed on the I/O thread. - DCHECK(!read_watcher_); - DCHECK(!write_watcher_); - - embedder::CloseAllPlatformHandles(&read_platform_handles_); -} - -size_t RawChannelPosix::GetSerializedPlatformHandleSize() const { - // We don't actually need any space on POSIX (since we just send FDs). - return 0; -} - -void RawChannelPosix::EnqueueMessageNoLock( - scoped_ptr<MessageInTransit> message) { - if (message->transport_data()) { - embedder::PlatformHandleVector* const platform_handles = - message->transport_data()->platform_handles(); - if (platform_handles && - platform_handles->size() > embedder::kPlatformChannelMaxNumHandles) { - // We can't attach all the FDs to a single message, so we have to "split" - // the message. Send as many control messages as needed first with FDs - // attached (and no data). - size_t i = 0; - for (; platform_handles->size() - i > - embedder::kPlatformChannelMaxNumHandles; - i += embedder::kPlatformChannelMaxNumHandles) { - scoped_ptr<MessageInTransit> fd_message(new MessageInTransit( - MessageInTransit::Type::RAW_CHANNEL, - MessageInTransit::Subtype::RAW_CHANNEL_POSIX_EXTRA_PLATFORM_HANDLES, - 0, nullptr)); - embedder::ScopedPlatformHandleVectorPtr fds( - new embedder::PlatformHandleVector( - platform_handles->begin() + i, - platform_handles->begin() + i + - embedder::kPlatformChannelMaxNumHandles)); - fd_message->SetTransportData(make_scoped_ptr(new TransportData( - std::move(fds), GetSerializedPlatformHandleSize()))); - RawChannel::EnqueueMessageNoLock(std::move(fd_message)); - } - - // Remove the handles that we "moved" into the other messages. - platform_handles->erase(platform_handles->begin(), - platform_handles->begin() + i); - } - } - - RawChannel::EnqueueMessageNoLock(std::move(message)); -} - -bool RawChannelPosix::OnReadMessageForRawChannel( - const MessageInTransit::View& message_view) { - DCHECK_EQ(message_view.type(), MessageInTransit::Type::RAW_CHANNEL); - - if (message_view.subtype() == - MessageInTransit::Subtype::RAW_CHANNEL_POSIX_EXTRA_PLATFORM_HANDLES) { - // We don't need to do anything. |RawChannel| won't extract the platform - // handles, and they'll be accumulated in |Read()|. - return true; - } - - return RawChannel::OnReadMessageForRawChannel(message_view); -} - -RawChannel::IOResult RawChannelPosix::Read(size_t* bytes_read) { - DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); - DCHECK(!pending_read_); - - IOResult rv = ReadImpl(bytes_read); - if (rv != IO_SUCCEEDED && rv != IO_PENDING) { - // Make sure that |OnFileCanReadWithoutBlocking()| won't be called again. - read_watcher_.reset(); - } - return rv; -} - -RawChannel::IOResult RawChannelPosix::ScheduleRead() { - DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); - DCHECK(!pending_read_); - - pending_read_ = true; - - return IO_PENDING; -} - -embedder::ScopedPlatformHandleVectorPtr RawChannelPosix::GetReadPlatformHandles( - size_t num_platform_handles, - const void* /*platform_handle_table*/) { - DCHECK_GT(num_platform_handles, 0u); - - if (read_platform_handles_.size() < num_platform_handles) { - embedder::CloseAllPlatformHandles(&read_platform_handles_); - read_platform_handles_.clear(); - return embedder::ScopedPlatformHandleVectorPtr(); - } - - embedder::ScopedPlatformHandleVectorPtr rv( - new embedder::PlatformHandleVector(num_platform_handles)); - rv->assign(read_platform_handles_.begin(), - read_platform_handles_.begin() + num_platform_handles); - read_platform_handles_.erase( - read_platform_handles_.begin(), - read_platform_handles_.begin() + num_platform_handles); - return rv; -} - -RawChannel::IOResult RawChannelPosix::WriteNoLock( - size_t* platform_handles_written, - size_t* bytes_written) { - write_lock().AssertAcquired(); - - DCHECK(!pending_write_); - - size_t num_platform_handles = 0; - ssize_t write_result; - if (write_buffer_no_lock()->HavePlatformHandlesToSend()) { - embedder::PlatformHandle* platform_handles; - void* serialization_data; // Actually unused. - write_buffer_no_lock()->GetPlatformHandlesToSend( - &num_platform_handles, &platform_handles, &serialization_data); - DCHECK_GT(num_platform_handles, 0u); - DCHECK_LE(num_platform_handles, embedder::kPlatformChannelMaxNumHandles); - DCHECK(platform_handles); - - // TODO(vtl): Reduce code duplication. (This is duplicated from below.) - std::vector<WriteBuffer::Buffer> buffers; - write_buffer_no_lock()->GetBuffers(&buffers); - DCHECK(!buffers.empty()); - const size_t kMaxBufferCount = 10; - iovec iov[kMaxBufferCount]; - size_t buffer_count = std::min(buffers.size(), kMaxBufferCount); - for (size_t i = 0; i < buffer_count; ++i) { - iov[i].iov_base = const_cast<char*>(buffers[i].addr); - iov[i].iov_len = buffers[i].size; - } - - write_result = embedder::PlatformChannelSendmsgWithHandles( - fd_.get(), iov, buffer_count, platform_handles, num_platform_handles); - if (write_result >= 0) { - for (size_t i = 0; i < num_platform_handles; i++) - platform_handles[i].CloseIfNecessary(); - } - } else { - std::vector<WriteBuffer::Buffer> buffers; - write_buffer_no_lock()->GetBuffers(&buffers); - DCHECK(!buffers.empty()); - - if (buffers.size() == 1) { - write_result = embedder::PlatformChannelWrite(fd_.get(), buffers[0].addr, - buffers[0].size); - } else { - const size_t kMaxBufferCount = 10; - iovec iov[kMaxBufferCount]; - size_t buffer_count = std::min(buffers.size(), kMaxBufferCount); - for (size_t i = 0; i < buffer_count; ++i) { - iov[i].iov_base = const_cast<char*>(buffers[i].addr); - iov[i].iov_len = buffers[i].size; - } - - write_result = - embedder::PlatformChannelWritev(fd_.get(), iov, buffer_count); - } - } - - if (write_result >= 0) { - *platform_handles_written = num_platform_handles; - *bytes_written = static_cast<size_t>(write_result); - return IO_SUCCEEDED; - } - - if (errno == EPIPE) - return IO_FAILED_SHUTDOWN; - - if (errno != EAGAIN && errno != EWOULDBLOCK) { - PLOG(WARNING) << "sendmsg/write/writev"; - return IO_FAILED_UNKNOWN; - } - - return ScheduleWriteNoLock(); -} - -RawChannel::IOResult RawChannelPosix::ScheduleWriteNoLock() { - write_lock().AssertAcquired(); - - DCHECK(!pending_write_); - - // Set up to wait for the FD to become writable. - // If we're not on the I/O thread, we have to post a task to do this. - if (base::MessageLoop::current() != message_loop_for_io()) { - message_loop_for_io()->PostTask(FROM_HERE, - base::Bind(&RawChannelPosix::WaitToWrite, - weak_ptr_factory_.GetWeakPtr())); - pending_write_ = true; - return IO_PENDING; - } - - if (message_loop_for_io()->WatchFileDescriptor( - fd_.get().fd, false, base::MessageLoopForIO::WATCH_WRITE, - write_watcher_.get(), this)) { - pending_write_ = true; - return IO_PENDING; - } - - return IO_FAILED_UNKNOWN; -} - -void RawChannelPosix::OnInit() { - DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); - - DCHECK(!read_watcher_); - read_watcher_.reset(new base::MessageLoopForIO::FileDescriptorWatcher()); - DCHECK(!write_watcher_); - write_watcher_.reset(new base::MessageLoopForIO::FileDescriptorWatcher()); - - // I don't know how this can fail (unless |fd_| is bad, in which case it's a - // bug in our code). I also don't know if |WatchFileDescriptor()| actually - // fails cleanly. - CHECK(message_loop_for_io()->WatchFileDescriptor( - fd_.get().fd, true, base::MessageLoopForIO::WATCH_READ, - read_watcher_.get(), this)); -} - -void RawChannelPosix::OnShutdownNoLock( - scoped_ptr<ReadBuffer> /*read_buffer*/, - scoped_ptr<WriteBuffer> /*write_buffer*/) { - DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); - write_lock().AssertAcquired(); - - read_watcher_.reset(); // This will stop watching (if necessary). - write_watcher_.reset(); // This will stop watching (if necessary). - - pending_read_ = false; - pending_write_ = false; - - DCHECK(fd_.is_valid()); - fd_.reset(); - - weak_ptr_factory_.InvalidateWeakPtrs(); -} - -void RawChannelPosix::OnFileCanReadWithoutBlocking(int fd) { - DCHECK_EQ(fd, fd_.get().fd); - DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); - - if (!pending_read_) { - NOTREACHED(); - return; - } - - pending_read_ = false; - size_t bytes_read = 0; - IOResult io_result = Read(&bytes_read); - if (io_result != IO_PENDING) { - OnReadCompleted(io_result, bytes_read); - // TODO(vtl): If we weren't destroyed, we'd like to do - // - // DCHECK(!read_watcher_ || pending_read_); - // - // On failure, |read_watcher_| must have been reset; on success, we assume - // that |OnReadCompleted()| always schedules another read. Otherwise, we - // could end up spinning -- getting |OnFileCanReadWithoutBlocking()| again - // and again but not doing any actual read. - // TODO(yzshen): An alternative is to stop watching if RawChannel doesn't - // schedule a new read. But that code won't be reached under the current - // RawChannel implementation. - return; // |this| may have been destroyed in |OnReadCompleted()|. - } - - DCHECK(pending_read_); -} - -void RawChannelPosix::OnFileCanWriteWithoutBlocking(int fd) { - DCHECK_EQ(fd, fd_.get().fd); - DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); - - IOResult io_result; - size_t platform_handles_written = 0; - size_t bytes_written = 0; - { - base::AutoLock locker(write_lock()); - - DCHECK(pending_write_); - - pending_write_ = false; - io_result = WriteNoLock(&platform_handles_written, &bytes_written); - } - - if (io_result != IO_PENDING) { - OnWriteCompleted(io_result, platform_handles_written, bytes_written); - return; // |this| may have been destroyed in |OnWriteCompleted()|. - } -} - -RawChannel::IOResult RawChannelPosix::ReadImpl(size_t* bytes_read) { - char* buffer = nullptr; - size_t bytes_to_read = 0; - read_buffer()->GetBuffer(&buffer, &bytes_to_read); - - size_t old_num_platform_handles = read_platform_handles_.size(); - ssize_t read_result = embedder::PlatformChannelRecvmsg( - fd_.get(), buffer, bytes_to_read, &read_platform_handles_); - if (read_platform_handles_.size() > old_num_platform_handles) { - DCHECK_LE(read_platform_handles_.size() - old_num_platform_handles, - embedder::kPlatformChannelMaxNumHandles); - - // We should never accumulate more than |TransportData::kMaxPlatformHandles - // + embedder::kPlatformChannelMaxNumHandles| handles. (The latter part is - // possible because we could have accumulated all the handles for a message, - // then received the message data plus the first set of handles for the next - // message in the subsequent |recvmsg()|.) - if (read_platform_handles_.size() > - (TransportData::GetMaxPlatformHandles() + - embedder::kPlatformChannelMaxNumHandles)) { - LOG(ERROR) << "Received too many platform handles"; - embedder::CloseAllPlatformHandles(&read_platform_handles_); - read_platform_handles_.clear(); - return IO_FAILED_UNKNOWN; - } - } - - if (read_result > 0) { - *bytes_read = static_cast<size_t>(read_result); - return IO_SUCCEEDED; - } - - // |read_result == 0| means "end of file". - if (read_result == 0) - return IO_FAILED_SHUTDOWN; - - if (errno == EAGAIN || errno == EWOULDBLOCK) - return ScheduleRead(); - - if (errno == ECONNRESET) - return IO_FAILED_BROKEN; - - PLOG(WARNING) << "recvmsg"; - return IO_FAILED_UNKNOWN; -} - -void RawChannelPosix::WaitToWrite() { - DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); - - DCHECK(write_watcher_); - - if (!message_loop_for_io()->WatchFileDescriptor( - fd_.get().fd, false, base::MessageLoopForIO::WATCH_WRITE, - write_watcher_.get(), this)) { - { - base::AutoLock locker(write_lock()); - - DCHECK(pending_write_); - pending_write_ = false; - } - OnWriteCompleted(IO_FAILED_UNKNOWN, 0, 0); - return; // |this| may have been destroyed in |OnWriteCompleted()|. - } -} - -} // namespace - -// ----------------------------------------------------------------------------- - -// Static factory method declared in raw_channel.h. -// static -scoped_ptr<RawChannel> RawChannel::Create( - embedder::ScopedPlatformHandle handle) { - return make_scoped_ptr(new RawChannelPosix(std::move(handle))); -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/raw_channel_unittest.cc b/third_party/mojo/src/mojo/edk/system/raw_channel_unittest.cc deleted file mode 100644 index 1501eea..0000000 --- a/third_party/mojo/src/mojo/edk/system/raw_channel_unittest.cc +++ /dev/null @@ -1,861 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/raw_channel.h" - -#include <stdint.h> -#include <stdio.h> -#include <utility> -#include <vector> - -#include "base/bind.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/files/scoped_file.h" -#include "base/files/scoped_temp_dir.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/scoped_vector.h" -#include "base/rand_util.h" -#include "base/synchronization/waitable_event.h" -#include "base/test/test_io_thread.h" -#include "base/threading/simple_thread.h" -#include "build/build_config.h" // TODO(vtl): Remove this. -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit.h" -#include "third_party/mojo/src/mojo/edk/system/mutex.h" -#include "third_party/mojo/src/mojo/edk/system/test_utils.h" -#include "third_party/mojo/src/mojo/edk/system/transport_data.h" -#include "third_party/mojo/src/mojo/edk/test/test_utils.h" - -namespace mojo { -namespace system { -namespace { - -scoped_ptr<MessageInTransit> MakeTestMessage(uint32_t num_bytes) { - std::vector<unsigned char> bytes(num_bytes, 0); - for (size_t i = 0; i < num_bytes; i++) - bytes[i] = static_cast<unsigned char>(i + num_bytes); - return make_scoped_ptr( - new MessageInTransit(MessageInTransit::Type::ENDPOINT_CLIENT, - MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, - num_bytes, bytes.empty() ? nullptr : &bytes[0])); -} - -bool CheckMessageData(const void* bytes, uint32_t num_bytes) { - const unsigned char* b = static_cast<const unsigned char*>(bytes); - for (uint32_t i = 0; i < num_bytes; i++) { - if (b[i] != static_cast<unsigned char>(i + num_bytes)) - return false; - } - return true; -} - -void InitOnIOThread(RawChannel* raw_channel, RawChannel::Delegate* delegate) { - raw_channel->Init(delegate); -} - -bool WriteTestMessageToHandle(const embedder::PlatformHandle& handle, - uint32_t num_bytes) { - scoped_ptr<MessageInTransit> message(MakeTestMessage(num_bytes)); - - size_t write_size = 0; - mojo::test::BlockingWrite(handle, message->main_buffer(), - message->main_buffer_size(), &write_size); - return write_size == message->main_buffer_size(); -} - -// ----------------------------------------------------------------------------- - -class RawChannelTest : public testing::Test { - public: - RawChannelTest() : io_thread_(base::TestIOThread::kManualStart) {} - ~RawChannelTest() override {} - - void SetUp() override { - embedder::PlatformChannelPair channel_pair; - handles[0] = channel_pair.PassServerHandle(); - handles[1] = channel_pair.PassClientHandle(); - io_thread_.Start(); - } - - void TearDown() override { - io_thread_.Stop(); - handles[0].reset(); - handles[1].reset(); - } - - protected: - base::TestIOThread* io_thread() { return &io_thread_; } - - embedder::ScopedPlatformHandle handles[2]; - - private: - base::TestIOThread io_thread_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(RawChannelTest); -}; - -// RawChannelTest.WriteMessage ------------------------------------------------- - -class WriteOnlyRawChannelDelegate : public RawChannel::Delegate { - public: - WriteOnlyRawChannelDelegate() {} - ~WriteOnlyRawChannelDelegate() override {} - - // |RawChannel::Delegate| implementation: - void OnReadMessage( - const MessageInTransit::View& /*message_view*/, - embedder::ScopedPlatformHandleVectorPtr /*platform_handles*/) override { - CHECK(false); // Should not get called. - } - void OnError(Error error) override { - // We'll get a read (shutdown) error when the connection is closed. - CHECK_EQ(error, ERROR_READ_SHUTDOWN); - } - - private: - MOJO_DISALLOW_COPY_AND_ASSIGN(WriteOnlyRawChannelDelegate); -}; - -static const unsigned kMessageReaderSleepMs = 1; -static const size_t kMessageReaderMaxPollIterations = 3000; - -class TestMessageReaderAndChecker { - public: - explicit TestMessageReaderAndChecker(embedder::PlatformHandle handle) - : handle_(handle) {} - ~TestMessageReaderAndChecker() { CHECK(bytes_.empty()); } - - bool ReadAndCheckNextMessage(uint32_t expected_size) { - unsigned char buffer[4096]; - - for (size_t i = 0; i < kMessageReaderMaxPollIterations;) { - size_t read_size = 0; - CHECK(mojo::test::NonBlockingRead(handle_, buffer, sizeof(buffer), - &read_size)); - - // Append newly-read data to |bytes_|. - bytes_.insert(bytes_.end(), buffer, buffer + read_size); - - // If we have the header.... - size_t message_size; - if (MessageInTransit::GetNextMessageSize( - bytes_.empty() ? nullptr : &bytes_[0], bytes_.size(), - &message_size)) { - // If we've read the whole message.... - if (bytes_.size() >= message_size) { - bool rv = true; - MessageInTransit::View message_view(message_size, &bytes_[0]); - CHECK_EQ(message_view.main_buffer_size(), message_size); - - if (message_view.num_bytes() != expected_size) { - LOG(ERROR) << "Wrong size: " << message_size << " instead of " - << expected_size << " bytes."; - rv = false; - } else if (!CheckMessageData(message_view.bytes(), - message_view.num_bytes())) { - LOG(ERROR) << "Incorrect message bytes."; - rv = false; - } - - // Erase message data. - bytes_.erase(bytes_.begin(), - bytes_.begin() + message_view.main_buffer_size()); - return rv; - } - } - - if (static_cast<size_t>(read_size) < sizeof(buffer)) { - i++; - test::Sleep(test::DeadlineFromMilliseconds(kMessageReaderSleepMs)); - } - } - - LOG(ERROR) << "Too many iterations."; - return false; - } - - private: - const embedder::PlatformHandle handle_; - - // The start of the received data should always be on a message boundary. - std::vector<unsigned char> bytes_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(TestMessageReaderAndChecker); -}; - -// Tests writing (and verifies reading using our own custom reader). -TEST_F(RawChannelTest, WriteMessage) { - WriteOnlyRawChannelDelegate delegate; - scoped_ptr<RawChannel> rc(RawChannel::Create(std::move(handles[0]))); - TestMessageReaderAndChecker checker(handles[1].get()); - io_thread()->PostTaskAndWait( - FROM_HERE, - base::Bind(&InitOnIOThread, rc.get(), base::Unretained(&delegate))); - - // Write and read, for a variety of sizes. - for (uint32_t size = 1; size < 5 * 1000 * 1000; size += size / 2 + 1) { - EXPECT_TRUE(rc->WriteMessage(MakeTestMessage(size))); - EXPECT_TRUE(checker.ReadAndCheckNextMessage(size)) << size; - } - - // Write/queue and read afterwards, for a variety of sizes. - for (uint32_t size = 1; size < 5 * 1000 * 1000; size += size / 2 + 1) - EXPECT_TRUE(rc->WriteMessage(MakeTestMessage(size))); - for (uint32_t size = 1; size < 5 * 1000 * 1000; size += size / 2 + 1) - EXPECT_TRUE(checker.ReadAndCheckNextMessage(size)) << size; - - io_thread()->PostTaskAndWait( - FROM_HERE, base::Bind(&RawChannel::Shutdown, base::Unretained(rc.get()))); -} - -// RawChannelTest.OnReadMessage ------------------------------------------------ - -class ReadCheckerRawChannelDelegate : public RawChannel::Delegate { - public: - ReadCheckerRawChannelDelegate() : done_event_(false, false), position_(0) {} - ~ReadCheckerRawChannelDelegate() override {} - - // |RawChannel::Delegate| implementation (called on the I/O thread): - void OnReadMessage( - const MessageInTransit::View& message_view, - embedder::ScopedPlatformHandleVectorPtr platform_handles) override { - EXPECT_FALSE(platform_handles); - - size_t position; - size_t expected_size; - bool should_signal = false; - { - MutexLocker locker(&mutex_); - CHECK_LT(position_, expected_sizes_.size()); - position = position_; - expected_size = expected_sizes_[position]; - position_++; - if (position_ >= expected_sizes_.size()) - should_signal = true; - } - - EXPECT_EQ(expected_size, message_view.num_bytes()) << position; - if (message_view.num_bytes() == expected_size) { - EXPECT_TRUE( - CheckMessageData(message_view.bytes(), message_view.num_bytes())) - << position; - } - - if (should_signal) - done_event_.Signal(); - } - void OnError(Error error) override { - // We'll get a read (shutdown) error when the connection is closed. - CHECK_EQ(error, ERROR_READ_SHUTDOWN); - } - - // Waits for all the messages (of sizes |expected_sizes_|) to be seen. - void Wait() { done_event_.Wait(); } - - void SetExpectedSizes(const std::vector<uint32_t>& expected_sizes) { - MutexLocker locker(&mutex_); - CHECK_EQ(position_, expected_sizes_.size()); - expected_sizes_ = expected_sizes; - position_ = 0; - } - - private: - base::WaitableEvent done_event_; - - Mutex mutex_; - std::vector<uint32_t> expected_sizes_ MOJO_GUARDED_BY(mutex_); - size_t position_ MOJO_GUARDED_BY(mutex_); - - MOJO_DISALLOW_COPY_AND_ASSIGN(ReadCheckerRawChannelDelegate); -}; - -// Tests reading (writing using our own custom writer). -TEST_F(RawChannelTest, OnReadMessage) { - ReadCheckerRawChannelDelegate delegate; - scoped_ptr<RawChannel> rc(RawChannel::Create(std::move(handles[0]))); - io_thread()->PostTaskAndWait( - FROM_HERE, - base::Bind(&InitOnIOThread, rc.get(), base::Unretained(&delegate))); - - // Write and read, for a variety of sizes. - for (uint32_t size = 1; size < 5 * 1000 * 1000; size += size / 2 + 1) { - delegate.SetExpectedSizes(std::vector<uint32_t>(1, size)); - - EXPECT_TRUE(WriteTestMessageToHandle(handles[1].get(), size)); - - delegate.Wait(); - } - - // Set up reader and write as fast as we can. - // Write/queue and read afterwards, for a variety of sizes. - std::vector<uint32_t> expected_sizes; - for (uint32_t size = 1; size < 5 * 1000 * 1000; size += size / 2 + 1) - expected_sizes.push_back(size); - delegate.SetExpectedSizes(expected_sizes); - for (uint32_t size = 1; size < 5 * 1000 * 1000; size += size / 2 + 1) - EXPECT_TRUE(WriteTestMessageToHandle(handles[1].get(), size)); - delegate.Wait(); - - io_thread()->PostTaskAndWait( - FROM_HERE, base::Bind(&RawChannel::Shutdown, base::Unretained(rc.get()))); -} - -// RawChannelTest.WriteMessageAndOnReadMessage --------------------------------- - -class RawChannelWriterThread : public base::SimpleThread { - public: - RawChannelWriterThread(RawChannel* raw_channel, size_t write_count) - : base::SimpleThread("raw_channel_writer_thread"), - raw_channel_(raw_channel), - left_to_write_(write_count) {} - - ~RawChannelWriterThread() override { Join(); } - - private: - void Run() override { - static const int kMaxRandomMessageSize = 25000; - - while (left_to_write_-- > 0) { - EXPECT_TRUE(raw_channel_->WriteMessage(MakeTestMessage( - static_cast<uint32_t>(base::RandInt(1, kMaxRandomMessageSize))))); - } - } - - RawChannel* const raw_channel_; - size_t left_to_write_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(RawChannelWriterThread); -}; - -class ReadCountdownRawChannelDelegate : public RawChannel::Delegate { - public: - explicit ReadCountdownRawChannelDelegate(size_t expected_count) - : done_event_(false, false), expected_count_(expected_count), count_(0) {} - ~ReadCountdownRawChannelDelegate() override {} - - // |RawChannel::Delegate| implementation (called on the I/O thread): - void OnReadMessage( - const MessageInTransit::View& message_view, - embedder::ScopedPlatformHandleVectorPtr platform_handles) override { - EXPECT_FALSE(platform_handles); - - EXPECT_LT(count_, expected_count_); - count_++; - - EXPECT_TRUE( - CheckMessageData(message_view.bytes(), message_view.num_bytes())); - - if (count_ >= expected_count_) - done_event_.Signal(); - } - void OnError(Error error) override { - // We'll get a read (shutdown) error when the connection is closed. - CHECK_EQ(error, ERROR_READ_SHUTDOWN); - } - - // Waits for all the messages to have been seen. - void Wait() { done_event_.Wait(); } - - private: - base::WaitableEvent done_event_; - size_t expected_count_; - size_t count_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ReadCountdownRawChannelDelegate); -}; - -TEST_F(RawChannelTest, WriteMessageAndOnReadMessage) { - static const size_t kNumWriterThreads = 10; - static const size_t kNumWriteMessagesPerThread = 4000; - - WriteOnlyRawChannelDelegate writer_delegate; - scoped_ptr<RawChannel> writer_rc(RawChannel::Create(std::move(handles[0]))); - io_thread()->PostTaskAndWait(FROM_HERE, - base::Bind(&InitOnIOThread, writer_rc.get(), - base::Unretained(&writer_delegate))); - - ReadCountdownRawChannelDelegate reader_delegate(kNumWriterThreads * - kNumWriteMessagesPerThread); - scoped_ptr<RawChannel> reader_rc(RawChannel::Create(std::move(handles[1]))); - io_thread()->PostTaskAndWait(FROM_HERE, - base::Bind(&InitOnIOThread, reader_rc.get(), - base::Unretained(&reader_delegate))); - - { - ScopedVector<RawChannelWriterThread> writer_threads; - for (size_t i = 0; i < kNumWriterThreads; i++) { - writer_threads.push_back(new RawChannelWriterThread( - writer_rc.get(), kNumWriteMessagesPerThread)); - } - for (size_t i = 0; i < writer_threads.size(); i++) - writer_threads[i]->Start(); - } // Joins all the writer threads. - - // Sleep a bit, to let any extraneous reads be processed. (There shouldn't be - // any, but we want to know about them.) - test::Sleep(test::DeadlineFromMilliseconds(100)); - - // Wait for reading to finish. - reader_delegate.Wait(); - - io_thread()->PostTaskAndWait( - FROM_HERE, - base::Bind(&RawChannel::Shutdown, base::Unretained(reader_rc.get()))); - - io_thread()->PostTaskAndWait( - FROM_HERE, - base::Bind(&RawChannel::Shutdown, base::Unretained(writer_rc.get()))); -} - -// RawChannelTest.OnError ------------------------------------------------------ - -class ErrorRecordingRawChannelDelegate - : public ReadCountdownRawChannelDelegate { - public: - ErrorRecordingRawChannelDelegate(size_t expected_read_count, - bool expect_read_error, - bool expect_write_error) - : ReadCountdownRawChannelDelegate(expected_read_count), - got_read_error_event_(false, false), - got_write_error_event_(false, false), - expecting_read_error_(expect_read_error), - expecting_write_error_(expect_write_error) {} - - ~ErrorRecordingRawChannelDelegate() override {} - - void OnError(Error error) override { - switch (error) { - case ERROR_READ_SHUTDOWN: - ASSERT_TRUE(expecting_read_error_); - expecting_read_error_ = false; - got_read_error_event_.Signal(); - break; - case ERROR_READ_BROKEN: - // TODO(vtl): Test broken connections. - CHECK(false); - break; - case ERROR_READ_BAD_MESSAGE: - // TODO(vtl): Test reception/detection of bad messages. - CHECK(false); - break; - case ERROR_READ_UNKNOWN: - // TODO(vtl): Test however it is we might get here. - CHECK(false); - break; - case ERROR_WRITE: - ASSERT_TRUE(expecting_write_error_); - expecting_write_error_ = false; - got_write_error_event_.Signal(); - break; - } - } - - void WaitForReadError() { got_read_error_event_.Wait(); } - void WaitForWriteError() { got_write_error_event_.Wait(); } - - private: - base::WaitableEvent got_read_error_event_; - base::WaitableEvent got_write_error_event_; - - bool expecting_read_error_; - bool expecting_write_error_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ErrorRecordingRawChannelDelegate); -}; - -// Tests (fatal) errors. -TEST_F(RawChannelTest, OnError) { - ErrorRecordingRawChannelDelegate delegate(0, true, true); - scoped_ptr<RawChannel> rc(RawChannel::Create(std::move(handles[0]))); - io_thread()->PostTaskAndWait( - FROM_HERE, - base::Bind(&InitOnIOThread, rc.get(), base::Unretained(&delegate))); - - // Close the handle of the other end, which should make writing fail. - handles[1].reset(); - - EXPECT_FALSE(rc->WriteMessage(MakeTestMessage(1))); - - // We should get a write error. - delegate.WaitForWriteError(); - - // We should also get a read error. - delegate.WaitForReadError(); - - EXPECT_FALSE(rc->WriteMessage(MakeTestMessage(2))); - - // Sleep a bit, to make sure we don't get another |OnError()| - // notification. (If we actually get another one, |OnError()| crashes.) - test::Sleep(test::DeadlineFromMilliseconds(20)); - - io_thread()->PostTaskAndWait( - FROM_HERE, base::Bind(&RawChannel::Shutdown, base::Unretained(rc.get()))); -} - -// RawChannelTest.ReadUnaffectedByWriteError ----------------------------------- - -TEST_F(RawChannelTest, ReadUnaffectedByWriteError) { - const size_t kMessageCount = 5; - - // Write a few messages into the other end. - uint32_t message_size = 1; - for (size_t i = 0; i < kMessageCount; - i++, message_size += message_size / 2 + 1) - EXPECT_TRUE(WriteTestMessageToHandle(handles[1].get(), message_size)); - - // Close the other end, which should make writing fail. - handles[1].reset(); - - // Only start up reading here. The system buffer should still contain the - // messages that were written. - ErrorRecordingRawChannelDelegate delegate(kMessageCount, true, true); - scoped_ptr<RawChannel> rc(RawChannel::Create(std::move(handles[0]))); - io_thread()->PostTaskAndWait( - FROM_HERE, - base::Bind(&InitOnIOThread, rc.get(), base::Unretained(&delegate))); - - EXPECT_FALSE(rc->WriteMessage(MakeTestMessage(1))); - - // We should definitely get a write error. - delegate.WaitForWriteError(); - - // Wait for reading to finish. A writing failure shouldn't affect reading. - delegate.Wait(); - - // And then we should get a read error. - delegate.WaitForReadError(); - - io_thread()->PostTaskAndWait( - FROM_HERE, base::Bind(&RawChannel::Shutdown, base::Unretained(rc.get()))); -} - -// RawChannelTest.WriteMessageAfterShutdown ------------------------------------ - -// Makes sure that calling |WriteMessage()| after |Shutdown()| behaves -// correctly. -TEST_F(RawChannelTest, WriteMessageAfterShutdown) { - WriteOnlyRawChannelDelegate delegate; - scoped_ptr<RawChannel> rc(RawChannel::Create(std::move(handles[0]))); - io_thread()->PostTaskAndWait( - FROM_HERE, - base::Bind(&InitOnIOThread, rc.get(), base::Unretained(&delegate))); - io_thread()->PostTaskAndWait( - FROM_HERE, base::Bind(&RawChannel::Shutdown, base::Unretained(rc.get()))); - - EXPECT_FALSE(rc->WriteMessage(MakeTestMessage(1))); -} - -// RawChannelTest.{Shutdown, ShutdownAndDestroy}OnReadMessage ------------------ - -class ShutdownOnReadMessageRawChannelDelegate : public RawChannel::Delegate { - public: - explicit ShutdownOnReadMessageRawChannelDelegate(RawChannel* raw_channel, - bool should_destroy) - : raw_channel_(raw_channel), - should_destroy_(should_destroy), - done_event_(false, false), - did_shutdown_(false) {} - ~ShutdownOnReadMessageRawChannelDelegate() override {} - - // |RawChannel::Delegate| implementation (called on the I/O thread): - void OnReadMessage( - const MessageInTransit::View& message_view, - embedder::ScopedPlatformHandleVectorPtr platform_handles) override { - EXPECT_FALSE(platform_handles); - EXPECT_FALSE(did_shutdown_); - EXPECT_TRUE( - CheckMessageData(message_view.bytes(), message_view.num_bytes())); - raw_channel_->Shutdown(); - if (should_destroy_) - delete raw_channel_; - did_shutdown_ = true; - done_event_.Signal(); - } - void OnError(Error /*error*/) override { - CHECK(false); // Should not get called. - } - - // Waits for shutdown. - void Wait() { - done_event_.Wait(); - EXPECT_TRUE(did_shutdown_); - } - - private: - RawChannel* const raw_channel_; - const bool should_destroy_; - base::WaitableEvent done_event_; - bool did_shutdown_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ShutdownOnReadMessageRawChannelDelegate); -}; - -TEST_F(RawChannelTest, ShutdownOnReadMessage) { - // Write a few messages into the other end. - for (size_t count = 0; count < 5; count++) - EXPECT_TRUE(WriteTestMessageToHandle(handles[1].get(), 10)); - - scoped_ptr<RawChannel> rc(RawChannel::Create(std::move(handles[0]))); - ShutdownOnReadMessageRawChannelDelegate delegate(rc.get(), false); - io_thread()->PostTaskAndWait( - FROM_HERE, - base::Bind(&InitOnIOThread, rc.get(), base::Unretained(&delegate))); - - // Wait for the delegate, which will shut the |RawChannel| down. - delegate.Wait(); -} - -TEST_F(RawChannelTest, ShutdownAndDestroyOnReadMessage) { - // Write a message into the other end. - EXPECT_TRUE(WriteTestMessageToHandle(handles[1].get(), 10)); - - // The delegate will destroy |rc|. - RawChannel* rc = RawChannel::Create(std::move(handles[0])).release(); - ShutdownOnReadMessageRawChannelDelegate delegate(rc, true); - io_thread()->PostTaskAndWait( - FROM_HERE, base::Bind(&InitOnIOThread, rc, base::Unretained(&delegate))); - - // Wait for the delegate, which will shut the |RawChannel| down. - delegate.Wait(); -} - -// RawChannelTest.{Shutdown, ShutdownAndDestroy}OnError{Read, Write} ----------- - -class ShutdownOnErrorRawChannelDelegate : public RawChannel::Delegate { - public: - ShutdownOnErrorRawChannelDelegate(RawChannel* raw_channel, - bool should_destroy, - Error shutdown_on_error_type) - : raw_channel_(raw_channel), - should_destroy_(should_destroy), - shutdown_on_error_type_(shutdown_on_error_type), - done_event_(false, false), - did_shutdown_(false) {} - ~ShutdownOnErrorRawChannelDelegate() override {} - - // |RawChannel::Delegate| implementation (called on the I/O thread): - void OnReadMessage( - const MessageInTransit::View& /*message_view*/, - embedder::ScopedPlatformHandleVectorPtr /*platform_handles*/) override { - CHECK(false); // Should not get called. - } - void OnError(Error error) override { - EXPECT_FALSE(did_shutdown_); - if (error != shutdown_on_error_type_) - return; - raw_channel_->Shutdown(); - if (should_destroy_) - delete raw_channel_; - did_shutdown_ = true; - done_event_.Signal(); - } - - // Waits for shutdown. - void Wait() { - done_event_.Wait(); - EXPECT_TRUE(did_shutdown_); - } - - private: - RawChannel* const raw_channel_; - const bool should_destroy_; - const Error shutdown_on_error_type_; - base::WaitableEvent done_event_; - bool did_shutdown_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ShutdownOnErrorRawChannelDelegate); -}; - -TEST_F(RawChannelTest, ShutdownOnErrorRead) { - scoped_ptr<RawChannel> rc(RawChannel::Create(std::move(handles[0]))); - ShutdownOnErrorRawChannelDelegate delegate( - rc.get(), false, RawChannel::Delegate::ERROR_READ_SHUTDOWN); - io_thread()->PostTaskAndWait( - FROM_HERE, - base::Bind(&InitOnIOThread, rc.get(), base::Unretained(&delegate))); - - // Close the handle of the other end, which should stuff fail. - handles[1].reset(); - - // Wait for the delegate, which will shut the |RawChannel| down. - delegate.Wait(); -} - -TEST_F(RawChannelTest, ShutdownAndDestroyOnErrorRead) { - RawChannel* rc = RawChannel::Create(std::move(handles[0])).release(); - ShutdownOnErrorRawChannelDelegate delegate( - rc, true, RawChannel::Delegate::ERROR_READ_SHUTDOWN); - io_thread()->PostTaskAndWait( - FROM_HERE, base::Bind(&InitOnIOThread, rc, base::Unretained(&delegate))); - - // Close the handle of the other end, which should stuff fail. - handles[1].reset(); - - // Wait for the delegate, which will shut the |RawChannel| down. - delegate.Wait(); -} - -TEST_F(RawChannelTest, ShutdownOnErrorWrite) { - scoped_ptr<RawChannel> rc(RawChannel::Create(std::move(handles[0]))); - ShutdownOnErrorRawChannelDelegate delegate(rc.get(), false, - RawChannel::Delegate::ERROR_WRITE); - io_thread()->PostTaskAndWait( - FROM_HERE, - base::Bind(&InitOnIOThread, rc.get(), base::Unretained(&delegate))); - - // Close the handle of the other end, which should stuff fail. - handles[1].reset(); - - EXPECT_FALSE(rc->WriteMessage(MakeTestMessage(1))); - - // Wait for the delegate, which will shut the |RawChannel| down. - delegate.Wait(); -} - -TEST_F(RawChannelTest, ShutdownAndDestroyOnErrorWrite) { - RawChannel* rc = RawChannel::Create(std::move(handles[0])).release(); - ShutdownOnErrorRawChannelDelegate delegate(rc, true, - RawChannel::Delegate::ERROR_WRITE); - io_thread()->PostTaskAndWait( - FROM_HERE, base::Bind(&InitOnIOThread, rc, base::Unretained(&delegate))); - - // Close the handle of the other end, which should stuff fail. - handles[1].reset(); - - EXPECT_FALSE(rc->WriteMessage(MakeTestMessage(1))); - - // Wait for the delegate, which will shut the |RawChannel| down. - delegate.Wait(); -} - -// RawChannelTest.ReadWritePlatformHandles ------------------------------------- - -class ReadPlatformHandlesCheckerRawChannelDelegate - : public RawChannel::Delegate { - public: - ReadPlatformHandlesCheckerRawChannelDelegate() : done_event_(false, false) {} - ~ReadPlatformHandlesCheckerRawChannelDelegate() override {} - - // |RawChannel::Delegate| implementation (called on the I/O thread): - void OnReadMessage( - const MessageInTransit::View& message_view, - embedder::ScopedPlatformHandleVectorPtr platform_handles) override { - const char kHello[] = "hello"; - - EXPECT_EQ(sizeof(kHello), message_view.num_bytes()); - EXPECT_STREQ(kHello, static_cast<const char*>(message_view.bytes())); - - ASSERT_TRUE(platform_handles); - ASSERT_EQ(2u, platform_handles->size()); - embedder::ScopedPlatformHandle h1(platform_handles->at(0)); - EXPECT_TRUE(h1.is_valid()); - embedder::ScopedPlatformHandle h2(platform_handles->at(1)); - EXPECT_TRUE(h2.is_valid()); - platform_handles->clear(); - - { - char buffer[100] = {}; - - base::ScopedFILE fp( - mojo::test::FILEFromPlatformHandle(std::move(h1), "rb")); - EXPECT_TRUE(fp); - rewind(fp.get()); - EXPECT_EQ(1u, fread(buffer, 1, sizeof(buffer), fp.get())); - EXPECT_EQ('1', buffer[0]); - } - - { - char buffer[100] = {}; - base::ScopedFILE fp( - mojo::test::FILEFromPlatformHandle(std::move(h2), "rb")); - EXPECT_TRUE(fp); - rewind(fp.get()); - EXPECT_EQ(1u, fread(buffer, 1, sizeof(buffer), fp.get())); - EXPECT_EQ('2', buffer[0]); - } - - done_event_.Signal(); - } - void OnError(Error error) override { - // We'll get a read (shutdown) error when the connection is closed. - CHECK_EQ(error, ERROR_READ_SHUTDOWN); - } - - void Wait() { done_event_.Wait(); } - - private: - base::WaitableEvent done_event_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ReadPlatformHandlesCheckerRawChannelDelegate); -}; - -#if defined(OS_POSIX) -#define MAYBE_ReadWritePlatformHandles ReadWritePlatformHandles -#else -// Not yet implemented (on Windows). -#define MAYBE_ReadWritePlatformHandles DISABLED_ReadWritePlatformHandles -#endif -TEST_F(RawChannelTest, MAYBE_ReadWritePlatformHandles) { - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - - WriteOnlyRawChannelDelegate write_delegate; - scoped_ptr<RawChannel> rc_write(RawChannel::Create(std::move(handles[0]))); - io_thread()->PostTaskAndWait(FROM_HERE, - base::Bind(&InitOnIOThread, rc_write.get(), - base::Unretained(&write_delegate))); - - ReadPlatformHandlesCheckerRawChannelDelegate read_delegate; - scoped_ptr<RawChannel> rc_read(RawChannel::Create(std::move(handles[1]))); - io_thread()->PostTaskAndWait(FROM_HERE, - base::Bind(&InitOnIOThread, rc_read.get(), - base::Unretained(&read_delegate))); - - base::FilePath unused; - base::ScopedFILE fp1( - base::CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused)); - EXPECT_EQ(1u, fwrite("1", 1, 1, fp1.get())); - base::ScopedFILE fp2( - base::CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused)); - EXPECT_EQ(1u, fwrite("2", 1, 1, fp2.get())); - - { - const char kHello[] = "hello"; - embedder::ScopedPlatformHandleVectorPtr platform_handles( - new embedder::PlatformHandleVector()); - platform_handles->push_back( - mojo::test::PlatformHandleFromFILE(std::move(fp1)).release()); - platform_handles->push_back( - mojo::test::PlatformHandleFromFILE(std::move(fp2)).release()); - - scoped_ptr<MessageInTransit> message( - new MessageInTransit(MessageInTransit::Type::ENDPOINT_CLIENT, - MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, - sizeof(kHello), kHello)); - message->SetTransportData(make_scoped_ptr( - new TransportData(std::move(platform_handles), - rc_write->GetSerializedPlatformHandleSize()))); - EXPECT_TRUE(rc_write->WriteMessage(std::move(message))); - } - - read_delegate.Wait(); - - io_thread()->PostTaskAndWait( - FROM_HERE, - base::Bind(&RawChannel::Shutdown, base::Unretained(rc_read.get()))); - io_thread()->PostTaskAndWait( - FROM_HERE, - base::Bind(&RawChannel::Shutdown, base::Unretained(rc_write.get()))); -} - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/raw_channel_win.cc b/third_party/mojo/src/mojo/edk/system/raw_channel_win.cc deleted file mode 100644 index b25453f..0000000 --- a/third_party/mojo/src/mojo/edk/system/raw_channel_win.cc +++ /dev/null @@ -1,636 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/raw_channel.h" - -#include <windows.h> - -#include "base/bind.h" -#include "base/lazy_instance.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" -#include "base/process/process.h" -#include "base/synchronization/lock.h" -#include "base/win/windows_version.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle.h" - -namespace mojo { -namespace system { - -namespace { - -struct MOJO_ALIGNAS(8) SerializedHandle { - DWORD handle_pid; - HANDLE handle; -}; - -class VistaOrHigherFunctions { - public: - VistaOrHigherFunctions(); - - bool is_vista_or_higher() const { return is_vista_or_higher_; } - - BOOL SetFileCompletionNotificationModes(HANDLE handle, UCHAR flags) { - return set_file_completion_notification_modes_(handle, flags); - } - - BOOL CancelIoEx(HANDLE handle, LPOVERLAPPED overlapped) { - return cancel_io_ex_(handle, overlapped); - } - - private: - using SetFileCompletionNotificationModesFunc = BOOL(WINAPI*)(HANDLE, UCHAR); - using CancelIoExFunc = BOOL(WINAPI*)(HANDLE, LPOVERLAPPED); - - bool is_vista_or_higher_; - SetFileCompletionNotificationModesFunc - set_file_completion_notification_modes_; - CancelIoExFunc cancel_io_ex_; -}; - -VistaOrHigherFunctions::VistaOrHigherFunctions() - : is_vista_or_higher_(base::win::GetVersion() >= base::win::VERSION_VISTA), - set_file_completion_notification_modes_(nullptr), - cancel_io_ex_(nullptr) { - if (!is_vista_or_higher_) - return; - - HMODULE module = GetModuleHandleW(L"kernel32.dll"); - set_file_completion_notification_modes_ = - reinterpret_cast<SetFileCompletionNotificationModesFunc>( - GetProcAddress(module, "SetFileCompletionNotificationModes")); - DCHECK(set_file_completion_notification_modes_); - - cancel_io_ex_ = - reinterpret_cast<CancelIoExFunc>(GetProcAddress(module, "CancelIoEx")); - DCHECK(cancel_io_ex_); -} - -base::LazyInstance<VistaOrHigherFunctions> g_vista_or_higher_functions = - LAZY_INSTANCE_INITIALIZER; - -class RawChannelWin final : public RawChannel { - public: - RawChannelWin(embedder::ScopedPlatformHandle handle); - ~RawChannelWin() override; - - // |RawChannel| public methods: - size_t GetSerializedPlatformHandleSize() const override; - - private: - // RawChannelIOHandler receives OS notifications for I/O completion. It must - // be created on the I/O thread. - // - // It manages its own destruction. Destruction happens on the I/O thread when - // all the following conditions are satisfied: - // - |DetachFromOwnerNoLock()| has been called; - // - there is no pending read; - // - there is no pending write. - class RawChannelIOHandler : public base::MessageLoopForIO::IOHandler { - public: - RawChannelIOHandler(RawChannelWin* owner, - embedder::ScopedPlatformHandle handle); - - HANDLE handle() const { return handle_.get().handle; } - - // The following methods are only called by the owner on the I/O thread. - bool pending_read() const; - base::MessageLoopForIO::IOContext* read_context(); - // Instructs the object to wait for an |OnIOCompleted()| notification. - void OnPendingReadStarted(); - - // The following methods are only called by the owner under - // |owner_->write_lock()|. - bool pending_write_no_lock() const; - base::MessageLoopForIO::IOContext* write_context_no_lock(); - // Instructs the object to wait for an |OnIOCompleted()| notification. - void OnPendingWriteStartedNoLock(size_t platform_handles_written); - - // |base::MessageLoopForIO::IOHandler| implementation: - // Must be called on the I/O thread. It could be called before or after - // detached from the owner. - void OnIOCompleted(base::MessageLoopForIO::IOContext* context, - DWORD bytes_transferred, - DWORD error) override; - - // Must be called on the I/O thread under |owner_->write_lock()|. - // After this call, the owner must not make any further calls on this - // object, and therefore the object is used on the I/O thread exclusively - // (if it stays alive). - void DetachFromOwnerNoLock(scoped_ptr<ReadBuffer> read_buffer, - scoped_ptr<WriteBuffer> write_buffer); - - private: - ~RawChannelIOHandler() override; - - // Returns true if |owner_| has been reset and there is not pending read or - // write. - // Must be called on the I/O thread. - bool ShouldSelfDestruct() const; - - // Must be called on the I/O thread. It may be called before or after - // detaching from the owner. - void OnReadCompleted(DWORD bytes_read, DWORD error); - // Must be called on the I/O thread. It may be called before or after - // detaching from the owner. - void OnWriteCompleted(DWORD bytes_written, DWORD error); - - embedder::ScopedPlatformHandle handle_; - - // |owner_| is reset on the I/O thread under |owner_->write_lock()|. - // Therefore, it may be used on any thread under lock; or on the I/O thread - // without locking. - RawChannelWin* owner_; - - // The following members must be used on the I/O thread. - scoped_ptr<ReadBuffer> preserved_read_buffer_after_detach_; - scoped_ptr<WriteBuffer> preserved_write_buffer_after_detach_; - bool suppress_self_destruct_; - - bool pending_read_; - base::MessageLoopForIO::IOContext read_context_; - - // The following members must be used under |owner_->write_lock()| while the - // object is still attached to the owner, and only on the I/O thread - // afterwards. - bool pending_write_; - size_t platform_handles_written_; - base::MessageLoopForIO::IOContext write_context_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(RawChannelIOHandler); - }; - - // |RawChannel| private methods: - IOResult Read(size_t* bytes_read) override; - IOResult ScheduleRead() override; - embedder::ScopedPlatformHandleVectorPtr GetReadPlatformHandles( - size_t num_platform_handles, - const void* platform_handle_table) override; - IOResult WriteNoLock(size_t* platform_handles_written, - size_t* bytes_written) override; - IOResult ScheduleWriteNoLock() override; - void OnInit() override; - void OnShutdownNoLock(scoped_ptr<ReadBuffer> read_buffer, - scoped_ptr<WriteBuffer> write_buffer) override; - - // Passed to |io_handler_| during initialization. - embedder::ScopedPlatformHandle handle_; - - RawChannelIOHandler* io_handler_; - - const bool skip_completion_port_on_success_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(RawChannelWin); -}; - -RawChannelWin::RawChannelIOHandler::RawChannelIOHandler( - RawChannelWin* owner, - embedder::ScopedPlatformHandle handle) - : handle_(handle.Pass()), - owner_(owner), - suppress_self_destruct_(false), - pending_read_(false), - pending_write_(false), - platform_handles_written_(0) { - memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped)); - read_context_.handler = this; - memset(&write_context_.overlapped, 0, sizeof(write_context_.overlapped)); - write_context_.handler = this; - - owner_->message_loop_for_io()->RegisterIOHandler(handle_.get().handle, this); -} - -RawChannelWin::RawChannelIOHandler::~RawChannelIOHandler() { - DCHECK(ShouldSelfDestruct()); -} - -bool RawChannelWin::RawChannelIOHandler::pending_read() const { - DCHECK(owner_); - DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); - return pending_read_; -} - -base::MessageLoopForIO::IOContext* -RawChannelWin::RawChannelIOHandler::read_context() { - DCHECK(owner_); - DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); - return &read_context_; -} - -void RawChannelWin::RawChannelIOHandler::OnPendingReadStarted() { - DCHECK(owner_); - DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); - DCHECK(!pending_read_); - pending_read_ = true; -} - -bool RawChannelWin::RawChannelIOHandler::pending_write_no_lock() const { - DCHECK(owner_); - owner_->write_lock().AssertAcquired(); - return pending_write_; -} - -base::MessageLoopForIO::IOContext* -RawChannelWin::RawChannelIOHandler::write_context_no_lock() { - DCHECK(owner_); - owner_->write_lock().AssertAcquired(); - return &write_context_; -} - -void RawChannelWin::RawChannelIOHandler::OnPendingWriteStartedNoLock( - size_t platform_handles_written) { - DCHECK(owner_); - owner_->write_lock().AssertAcquired(); - DCHECK(!pending_write_); - pending_write_ = true; - platform_handles_written_ = platform_handles_written; -} - -void RawChannelWin::RawChannelIOHandler::OnIOCompleted( - base::MessageLoopForIO::IOContext* context, - DWORD bytes_transferred, - DWORD error) { - DCHECK(!owner_ || - base::MessageLoop::current() == owner_->message_loop_for_io()); - - // Suppress self-destruction inside |OnReadCompleted()|, etc. (in case they - // result in a call to |Shutdown()|). - bool old_suppress_self_destruct = suppress_self_destruct_; - suppress_self_destruct_ = true; - - if (context == &read_context_) - OnReadCompleted(bytes_transferred, error); - else if (context == &write_context_) - OnWriteCompleted(bytes_transferred, error); - else - NOTREACHED(); - - // Maybe allow self-destruction again. - suppress_self_destruct_ = old_suppress_self_destruct; - - if (ShouldSelfDestruct()) - delete this; -} - -void RawChannelWin::RawChannelIOHandler::DetachFromOwnerNoLock( - scoped_ptr<ReadBuffer> read_buffer, - scoped_ptr<WriteBuffer> write_buffer) { - DCHECK(owner_); - DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); - owner_->write_lock().AssertAcquired(); - - // If read/write is pending, we have to retain the corresponding buffer. - if (pending_read_) - preserved_read_buffer_after_detach_ = read_buffer.Pass(); - if (pending_write_) - preserved_write_buffer_after_detach_ = write_buffer.Pass(); - - owner_ = nullptr; - if (ShouldSelfDestruct()) - delete this; -} - -bool RawChannelWin::RawChannelIOHandler::ShouldSelfDestruct() const { - if (owner_ || suppress_self_destruct_) - return false; - - // Note: Detached, hence no lock needed for |pending_write_|. - return !pending_read_ && !pending_write_; -} - -void RawChannelWin::RawChannelIOHandler::OnReadCompleted(DWORD bytes_read, - DWORD error) { - DCHECK(!owner_ || - base::MessageLoop::current() == owner_->message_loop_for_io()); - DCHECK(suppress_self_destruct_); - - CHECK(pending_read_); - pending_read_ = false; - if (!owner_) - return; - - // Note: |OnReadCompleted()| may detach us from |owner_|. - if (error == ERROR_SUCCESS) { - DCHECK_GT(bytes_read, 0u); - owner_->OnReadCompleted(IO_SUCCEEDED, bytes_read); - } else if (error == ERROR_BROKEN_PIPE) { - DCHECK_EQ(bytes_read, 0u); - owner_->OnReadCompleted(IO_FAILED_SHUTDOWN, 0); - } else { - DCHECK_EQ(bytes_read, 0u); - LOG(WARNING) << "ReadFile: " << logging::SystemErrorCodeToString(error); - owner_->OnReadCompleted(IO_FAILED_UNKNOWN, 0); - } -} - -void RawChannelWin::RawChannelIOHandler::OnWriteCompleted(DWORD bytes_written, - DWORD error) { - DCHECK(!owner_ || - base::MessageLoop::current() == owner_->message_loop_for_io()); - DCHECK(suppress_self_destruct_); - - if (!owner_) { - // No lock needed. - CHECK(pending_write_); - pending_write_ = false; - return; - } - - { - base::AutoLock locker(owner_->write_lock()); - CHECK(pending_write_); - pending_write_ = false; - } - - // Note: |OnWriteCompleted()| may detach us from |owner_|. - if (error == ERROR_SUCCESS) { - // Reset |platform_handles_written_| before calling |OnWriteCompleted()| - // since that function may call back to this class and set it again. - size_t local_platform_handles_written_ = platform_handles_written_; - platform_handles_written_ = 0; - owner_->OnWriteCompleted(IO_SUCCEEDED, local_platform_handles_written_, - bytes_written); - } else if (error == ERROR_BROKEN_PIPE) { - owner_->OnWriteCompleted(IO_FAILED_SHUTDOWN, 0, 0); - } else { - LOG(WARNING) << "WriteFile: " << logging::SystemErrorCodeToString(error); - owner_->OnWriteCompleted(IO_FAILED_UNKNOWN, 0, 0); - } -} - -RawChannelWin::RawChannelWin(embedder::ScopedPlatformHandle handle) - : handle_(handle.Pass()), - io_handler_(nullptr), - skip_completion_port_on_success_( - g_vista_or_higher_functions.Get().is_vista_or_higher()) { - DCHECK(handle_.is_valid()); -} - -RawChannelWin::~RawChannelWin() { - DCHECK(!io_handler_); -} - -size_t RawChannelWin::GetSerializedPlatformHandleSize() const { - return sizeof(SerializedHandle); -} - -RawChannel::IOResult RawChannelWin::Read(size_t* bytes_read) { - DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); - DCHECK(io_handler_); - DCHECK(!io_handler_->pending_read()); - - char* buffer = nullptr; - size_t bytes_to_read = 0; - read_buffer()->GetBuffer(&buffer, &bytes_to_read); - - BOOL result = - ReadFile(io_handler_->handle(), buffer, static_cast<DWORD>(bytes_to_read), - nullptr, &io_handler_->read_context()->overlapped); - if (!result) { - DWORD error = GetLastError(); - if (error == ERROR_BROKEN_PIPE) - return IO_FAILED_SHUTDOWN; - if (error != ERROR_IO_PENDING) { - LOG(WARNING) << "ReadFile: " << logging::SystemErrorCodeToString(error); - return IO_FAILED_UNKNOWN; - } - } - - if (result && skip_completion_port_on_success_) { - DWORD bytes_read_dword = 0; - BOOL get_size_result = GetOverlappedResult( - io_handler_->handle(), &io_handler_->read_context()->overlapped, - &bytes_read_dword, FALSE); - DPCHECK(get_size_result); - *bytes_read = bytes_read_dword; - return IO_SUCCEEDED; - } - - // If the read is pending or the read has succeeded but we don't skip - // completion port on success, instruct |io_handler_| to wait for the - // completion packet. - // - // TODO(yzshen): It seems there isn't document saying that all error cases - // (other than ERROR_IO_PENDING) are guaranteed to *not* queue a completion - // packet. If we do get one for errors, |RawChannelIOHandler::OnIOCompleted()| - // will crash so we will learn about it. - - io_handler_->OnPendingReadStarted(); - return IO_PENDING; -} - -RawChannel::IOResult RawChannelWin::ScheduleRead() { - DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); - DCHECK(io_handler_); - DCHECK(!io_handler_->pending_read()); - - size_t bytes_read = 0; - IOResult io_result = Read(&bytes_read); - if (io_result == IO_SUCCEEDED) { - DCHECK(skip_completion_port_on_success_); - - // We have finished reading successfully. Queue a notification manually. - io_handler_->OnPendingReadStarted(); - // |io_handler_| won't go away before the task is run, so it is safe to use - // |base::Unretained()|. - message_loop_for_io()->PostTask( - FROM_HERE, base::Bind(&RawChannelIOHandler::OnIOCompleted, - base::Unretained(io_handler_), - base::Unretained(io_handler_->read_context()), - static_cast<DWORD>(bytes_read), ERROR_SUCCESS)); - return IO_PENDING; - } - - return io_result; -} - -embedder::ScopedPlatformHandleVectorPtr RawChannelWin::GetReadPlatformHandles( - size_t num_platform_handles, - const void* platform_handle_table) { - // TODO(jam): this code will have to be updated once it's used in a sandbox - // and the receiving process doesn't have duplicate permission for the - // receiver. Once there's a broker and we have a connection to it (possibly - // through ConnectionManager), then we can make a sync IPC to it here to get a - // token for this handle, and it will duplicate the handle to is process. Then - // we pass the token to the receiver, which will then make a sync call to the - // broker to get a duplicated handle. This will also allow us to avoid leaks - // of the handle if the receiver dies, since the broker can notice that. - DCHECK_GT(num_platform_handles, 0u); - embedder::ScopedPlatformHandleVectorPtr rv( - new embedder::PlatformHandleVector()); - - const SerializedHandle* serialization_data = - static_cast<const SerializedHandle*>(platform_handle_table); - for (size_t i = 0; i < num_platform_handles; i++) { - DWORD pid = serialization_data->handle_pid; - HANDLE source_handle = serialization_data->handle; - serialization_data ++; - base::Process sender = - base::Process::OpenWithAccess(pid, PROCESS_DUP_HANDLE); - DCHECK(sender.IsValid()); - HANDLE target_handle = NULL; - BOOL dup_result = - DuplicateHandle(sender.Handle(), source_handle, - base::GetCurrentProcessHandle(), &target_handle, 0, - FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); - DCHECK(dup_result); - rv->push_back(embedder::PlatformHandle(target_handle)); - } - return rv.Pass(); -} - -RawChannel::IOResult RawChannelWin::WriteNoLock( - size_t* platform_handles_written, - size_t* bytes_written) { - write_lock().AssertAcquired(); - - DCHECK(io_handler_); - DCHECK(!io_handler_->pending_write_no_lock()); - - size_t num_platform_handles = 0; - if (write_buffer_no_lock()->HavePlatformHandlesToSend()) { - // Since we're not sure which process might ultimately deserialize this - // message, we can't duplicate the handle now. Instead, write the process ID - // and handle now and let the receiver duplicate it. - embedder::PlatformHandle* platform_handles; - void* serialization_data_temp; - write_buffer_no_lock()->GetPlatformHandlesToSend( - &num_platform_handles, &platform_handles, &serialization_data_temp); - SerializedHandle* serialization_data = - static_cast<SerializedHandle*>(serialization_data_temp); - DCHECK_GT(num_platform_handles, 0u); - DCHECK(platform_handles); - - DWORD current_process_id = base::GetCurrentProcId(); - for (size_t i = 0; i < num_platform_handles; i++) { - serialization_data->handle_pid = current_process_id; - serialization_data->handle = platform_handles[i].handle; - serialization_data++; - platform_handles[i] = embedder::PlatformHandle(); - } - } - - std::vector<WriteBuffer::Buffer> buffers; - write_buffer_no_lock()->GetBuffers(&buffers); - DCHECK(!buffers.empty()); - - // TODO(yzshen): Handle multi-segment writes more efficiently. - DWORD bytes_written_dword = 0; - BOOL result = - WriteFile(io_handler_->handle(), buffers[0].addr, - static_cast<DWORD>(buffers[0].size), &bytes_written_dword, - &io_handler_->write_context_no_lock()->overlapped); - if (!result) { - DWORD error = GetLastError(); - if (error == ERROR_BROKEN_PIPE) - return IO_FAILED_SHUTDOWN; - if (error != ERROR_IO_PENDING) { - LOG(WARNING) << "WriteFile: " << logging::SystemErrorCodeToString(error); - return IO_FAILED_UNKNOWN; - } - } - - if (result && skip_completion_port_on_success_) { - *platform_handles_written = num_platform_handles; - *bytes_written = bytes_written_dword; - return IO_SUCCEEDED; - } - - // If the write is pending or the write has succeeded but we don't skip - // completion port on success, instruct |io_handler_| to wait for the - // completion packet. - // - // TODO(yzshen): it seems there isn't document saying that all error cases - // (other than ERROR_IO_PENDING) are guaranteed to *not* queue a completion - // packet. If we do get one for errors, |RawChannelIOHandler::OnIOCompleted()| - // will crash so we will learn about it. - - io_handler_->OnPendingWriteStartedNoLock(num_platform_handles); - return IO_PENDING; -} - -RawChannel::IOResult RawChannelWin::ScheduleWriteNoLock() { - write_lock().AssertAcquired(); - - DCHECK(io_handler_); - DCHECK(!io_handler_->pending_write_no_lock()); - - size_t platform_handles_written = 0; - size_t bytes_written = 0; - IOResult io_result = WriteNoLock(&platform_handles_written, &bytes_written); - if (io_result == IO_SUCCEEDED) { - DCHECK(skip_completion_port_on_success_); - - // We have finished writing successfully. Queue a notification manually. - io_handler_->OnPendingWriteStartedNoLock(platform_handles_written); - // |io_handler_| won't go away before that task is run, so it is safe to use - // |base::Unretained()|. - message_loop_for_io()->PostTask( - FROM_HERE, - base::Bind(&RawChannelIOHandler::OnIOCompleted, - base::Unretained(io_handler_), - base::Unretained(io_handler_->write_context_no_lock()), - static_cast<DWORD>(bytes_written), ERROR_SUCCESS)); - return IO_PENDING; - } - - return io_result; -} - -void RawChannelWin::OnInit() { - DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); - - DCHECK(handle_.is_valid()); - if (skip_completion_port_on_success_) { - // I don't know how this can fail (unless |handle_| is bad, in which case - // it's a bug in our code). - CHECK(g_vista_or_higher_functions.Get().SetFileCompletionNotificationModes( - handle_.get().handle, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)); - } - - DCHECK(!io_handler_); - io_handler_ = new RawChannelIOHandler(this, handle_.Pass()); -} - -void RawChannelWin::OnShutdownNoLock(scoped_ptr<ReadBuffer> read_buffer, - scoped_ptr<WriteBuffer> write_buffer) { - DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); - DCHECK(io_handler_); - - write_lock().AssertAcquired(); - - if (io_handler_->pending_read() || io_handler_->pending_write_no_lock()) { - // |io_handler_| will be alive until pending read/write (if any) completes. - // Call |CancelIoEx()| or |CancelIo()| so that resources can be freed up as - // soon as possible. - // Note: |CancelIo()| only cancels read/write requests started from this - // thread. - if (g_vista_or_higher_functions.Get().is_vista_or_higher()) { - g_vista_or_higher_functions.Get().CancelIoEx(io_handler_->handle(), - nullptr); - } else { - CancelIo(io_handler_->handle()); - } - } - - io_handler_->DetachFromOwnerNoLock(read_buffer.Pass(), write_buffer.Pass()); - io_handler_ = nullptr; -} - -} // namespace - -// ----------------------------------------------------------------------------- - -// Static factory method declared in raw_channel.h. -// static -scoped_ptr<RawChannel> RawChannel::Create( - embedder::ScopedPlatformHandle handle) { - return make_scoped_ptr(new RawChannelWin(handle.Pass())); -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/remote_consumer_data_pipe_impl.cc b/third_party/mojo/src/mojo/edk/system/remote_consumer_data_pipe_impl.cc deleted file mode 100644 index 953fae7a..0000000 --- a/third_party/mojo/src/mojo/edk/system/remote_consumer_data_pipe_impl.cc +++ /dev/null @@ -1,430 +0,0 @@ -// Copyright 2015 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 "third_party/mojo/src/mojo/edk/system/remote_consumer_data_pipe_impl.h" - -#include <string.h> -#include <algorithm> -#include <limits> -#include <utility> - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "third_party/mojo/src/mojo/edk/system/channel.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/configuration.h" -#include "third_party/mojo/src/mojo/edk/system/data_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit.h" -#include "third_party/mojo/src/mojo/edk/system/remote_data_pipe_ack.h" - -namespace mojo { -namespace system { - -namespace { - -bool ValidateIncomingMessage(size_t element_num_bytes, - size_t capacity_num_bytes, - size_t consumer_num_bytes, - const MessageInTransit* message) { - // We should only receive endpoint client messages. - DCHECK_EQ(message->type(), MessageInTransit::Type::ENDPOINT_CLIENT); - - // But we should check the subtype; only take data pipe acks. - if (message->subtype() != - MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA_PIPE_ACK) { - LOG(WARNING) << "Received message of unexpected subtype: " - << message->subtype(); - return false; - } - - if (message->num_bytes() != sizeof(RemoteDataPipeAck)) { - LOG(WARNING) << "Incorrect message size: " << message->num_bytes() - << " bytes (expected: " << sizeof(RemoteDataPipeAck) - << " bytes)"; - return false; - } - - const RemoteDataPipeAck* ack = - static_cast<const RemoteDataPipeAck*>(message->bytes()); - size_t num_bytes_consumed = ack->num_bytes_consumed; - - if (num_bytes_consumed > consumer_num_bytes) { - LOG(WARNING) << "Number of bytes consumed too large: " << num_bytes_consumed - << " bytes (outstanding: " << consumer_num_bytes << " bytes)"; - return false; - } - - if (num_bytes_consumed % element_num_bytes != 0) { - LOG(WARNING) << "Number of bytes consumed not a multiple of element size: " - << num_bytes_consumed - << " bytes (element size: " << element_num_bytes << " bytes)"; - return false; - } - - return true; -} - -} // namespace - -RemoteConsumerDataPipeImpl::RemoteConsumerDataPipeImpl( - ChannelEndpoint* channel_endpoint, - size_t consumer_num_bytes, - scoped_ptr<char, base::AlignedFreeDeleter> buffer, - size_t start_index) - : channel_endpoint_(channel_endpoint), - consumer_num_bytes_(consumer_num_bytes), - buffer_(std::move(buffer)), - start_index_(start_index) { - // Note: |buffer_| may be null (in which case it'll be lazily allocated). -} - -RemoteConsumerDataPipeImpl::~RemoteConsumerDataPipeImpl() { -} - -void RemoteConsumerDataPipeImpl::ProducerClose() { - if (!consumer_open()) { - DCHECK(!channel_endpoint_); - return; - } - - Disconnect(); -} - -// static -bool RemoteConsumerDataPipeImpl::ProcessMessagesFromIncomingEndpoint( - const MojoCreateDataPipeOptions& validated_options, - size_t* consumer_num_bytes, - MessageInTransitQueue* messages) { - const size_t element_num_bytes = validated_options.element_num_bytes; - const size_t capacity_num_bytes = validated_options.capacity_num_bytes; - - if (messages) { - while (!messages->IsEmpty()) { - scoped_ptr<MessageInTransit> message(messages->GetMessage()); - if (!ValidateIncomingMessage(element_num_bytes, capacity_num_bytes, - *consumer_num_bytes, message.get())) { - messages->Clear(); - return false; - } - - const RemoteDataPipeAck* ack = - static_cast<const RemoteDataPipeAck*>(message->bytes()); - size_t num_bytes_consumed = ack->num_bytes_consumed; - *consumer_num_bytes -= num_bytes_consumed; - } - } - - return true; -} - -MojoResult RemoteConsumerDataPipeImpl::ProducerWriteData( - UserPointer<const void> elements, - UserPointer<uint32_t> num_bytes, - uint32_t max_num_bytes_to_write, - uint32_t min_num_bytes_to_write) { - DCHECK_EQ(max_num_bytes_to_write % element_num_bytes(), 0u); - DCHECK_EQ(min_num_bytes_to_write % element_num_bytes(), 0u); - DCHECK_GT(max_num_bytes_to_write, 0u); - DCHECK_GE(max_num_bytes_to_write, min_num_bytes_to_write); - DCHECK(consumer_open()); - DCHECK(channel_endpoint_); - - DCHECK_LE(consumer_num_bytes_, capacity_num_bytes()); - DCHECK_EQ(consumer_num_bytes_ % element_num_bytes(), 0u); - - if (min_num_bytes_to_write > capacity_num_bytes() - consumer_num_bytes_) - return MOJO_RESULT_OUT_OF_RANGE; - - size_t num_bytes_to_write = - std::min(static_cast<size_t>(max_num_bytes_to_write), - capacity_num_bytes() - consumer_num_bytes_); - if (num_bytes_to_write == 0) - return MOJO_RESULT_SHOULD_WAIT; - - // The maximum amount of data to send per message (make it a multiple of the - // element size. - // TODO(vtl): Copied from |LocalDataPipeImpl::ConvertDataToMessages()|. - size_t max_message_num_bytes = GetConfiguration().max_message_num_bytes; - max_message_num_bytes -= max_message_num_bytes % element_num_bytes(); - DCHECK_GT(max_message_num_bytes, 0u); - - size_t offset = 0; - while (offset < num_bytes_to_write) { - size_t message_num_bytes = - std::min(max_message_num_bytes, num_bytes_to_write - offset); - scoped_ptr<MessageInTransit> message(new MessageInTransit( - MessageInTransit::Type::ENDPOINT_CLIENT, - MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, - static_cast<uint32_t>(message_num_bytes), elements.At(offset))); - if (!channel_endpoint_->EnqueueMessage(std::move(message))) { - Disconnect(); - break; - } - - offset += message_num_bytes; - consumer_num_bytes_ += message_num_bytes; - } - - DCHECK_LE(consumer_num_bytes_, capacity_num_bytes()); - // TODO(vtl): We report |num_bytes_to_write|, instead of |offset|, even if we - // failed at some point. This is consistent with the idea that writes either - // "succeed" or "fail" (and since some bytes may have been sent, we opt for - // "succeed"). Think about this some more. - num_bytes.Put(static_cast<uint32_t>(num_bytes_to_write)); - return MOJO_RESULT_OK; -} - -MojoResult RemoteConsumerDataPipeImpl::ProducerBeginWriteData( - UserPointer<void*> buffer, - UserPointer<uint32_t> buffer_num_bytes) { - DCHECK(consumer_open()); - DCHECK(channel_endpoint_); - - DCHECK_LE(consumer_num_bytes_, capacity_num_bytes()); - DCHECK_EQ(consumer_num_bytes_ % element_num_bytes(), 0u); - - size_t max_num_bytes_to_write = capacity_num_bytes() - consumer_num_bytes_; - // Don't go into a two-phase write if there's no room. - if (max_num_bytes_to_write == 0) - return MOJO_RESULT_SHOULD_WAIT; - - EnsureBuffer(); - start_index_ = 0; // We always have the full buffer. - buffer.Put(buffer_.get()); - buffer_num_bytes.Put(static_cast<uint32_t>(max_num_bytes_to_write)); - set_producer_two_phase_max_num_bytes_written( - static_cast<uint32_t>(max_num_bytes_to_write)); - return MOJO_RESULT_OK; -} - -MojoResult RemoteConsumerDataPipeImpl::ProducerEndWriteData( - uint32_t num_bytes_written) { - DCHECK(buffer_); - DCHECK_LE(num_bytes_written, producer_two_phase_max_num_bytes_written()); - DCHECK_EQ(num_bytes_written % element_num_bytes(), 0u); - DCHECK_LE(num_bytes_written, capacity_num_bytes() - consumer_num_bytes_); - - if (!consumer_open()) { - set_producer_two_phase_max_num_bytes_written(0); - DestroyBuffer(); - return MOJO_RESULT_OK; - } - - // TODO(vtl): The following code is copied almost verbatim from - // |ProducerWriteData()| (it's touchy to factor it out since it uses a - // |UserPointer| while we have a plain pointer. - - // The maximum amount of data to send per message (make it a multiple of the - // element size. - // TODO(vtl): Mostly copied from |LocalDataPipeImpl::ConvertDataToMessages()|. - size_t max_message_num_bytes = GetConfiguration().max_message_num_bytes; - max_message_num_bytes -= max_message_num_bytes % element_num_bytes(); - DCHECK_GT(max_message_num_bytes, 0u); - - size_t offset = 0; - while (offset < num_bytes_written) { - size_t message_num_bytes = - std::min(max_message_num_bytes, num_bytes_written - offset); - scoped_ptr<MessageInTransit> message( - new MessageInTransit(MessageInTransit::Type::ENDPOINT_CLIENT, - MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, - static_cast<uint32_t>(message_num_bytes), - buffer_.get() + start_index_ + offset)); - if (!channel_endpoint_->EnqueueMessage(std::move(message))) { - set_producer_two_phase_max_num_bytes_written(0); - Disconnect(); - return MOJO_RESULT_OK; - } - - offset += message_num_bytes; - consumer_num_bytes_ += message_num_bytes; - } - - DCHECK_LE(consumer_num_bytes_, capacity_num_bytes()); - // TODO(vtl): (End of mostly copied code.) - - set_producer_two_phase_max_num_bytes_written(0); - return MOJO_RESULT_OK; -} - -HandleSignalsState RemoteConsumerDataPipeImpl::ProducerGetHandleSignalsState() - const { - HandleSignalsState rv; - if (consumer_open()) { - if (consumer_num_bytes_ < capacity_num_bytes() && - !producer_in_two_phase_write()) - rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_WRITABLE; - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_WRITABLE; - } else { - rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED; - } - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED; - return rv; -} - -void RemoteConsumerDataPipeImpl::ProducerStartSerialize( - Channel* channel, - size_t* max_size, - size_t* max_platform_handles) { - *max_size = sizeof(SerializedDataPipeProducerDispatcher) + - channel->GetSerializedEndpointSize(); - *max_platform_handles = 0; -} - -bool RemoteConsumerDataPipeImpl::ProducerEndSerialize( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) { - SerializedDataPipeProducerDispatcher* s = - static_cast<SerializedDataPipeProducerDispatcher*>(destination); - s->validated_options = validated_options(); - void* destination_for_endpoint = static_cast<char*>(destination) + - sizeof(SerializedDataPipeProducerDispatcher); - - if (!consumer_open()) { - // Case 1: The consumer is closed. - s->consumer_num_bytes = static_cast<uint32_t>(-1); - *actual_size = sizeof(SerializedDataPipeProducerDispatcher); - return true; - } - - // Case 2: The consumer isn't closed. We pass |channel_endpoint| back to the - // |Channel|. There's no reason for us to continue to exist afterwards. - - DCHECK(consumer_num_bytes_ < std::numeric_limits<uint32_t>::max()); - s->consumer_num_bytes = static_cast<uint32_t>(consumer_num_bytes_); - // Note: We don't use |port|. - scoped_refptr<ChannelEndpoint> channel_endpoint; - channel_endpoint.swap(channel_endpoint_); - channel->SerializeEndpointWithRemotePeer(destination_for_endpoint, nullptr, - channel_endpoint); - owner()->SetConsumerClosedNoLock(); - - *actual_size = sizeof(SerializedDataPipeProducerDispatcher) + - channel->GetSerializedEndpointSize(); - return true; -} - -void RemoteConsumerDataPipeImpl::ConsumerClose() { - NOTREACHED(); -} - -MojoResult RemoteConsumerDataPipeImpl::ConsumerReadData( - UserPointer<void> /*elements*/, - UserPointer<uint32_t> /*num_bytes*/, - uint32_t /*max_num_bytes_to_read*/, - uint32_t /*min_num_bytes_to_read*/, - bool /*peek*/) { - NOTREACHED(); - return MOJO_RESULT_INTERNAL; -} - -MojoResult RemoteConsumerDataPipeImpl::ConsumerDiscardData( - UserPointer<uint32_t> /*num_bytes*/, - uint32_t /*max_num_bytes_to_discard*/, - uint32_t /*min_num_bytes_to_discard*/) { - NOTREACHED(); - return MOJO_RESULT_INTERNAL; -} - -MojoResult RemoteConsumerDataPipeImpl::ConsumerQueryData( - UserPointer<uint32_t> /*num_bytes*/) { - NOTREACHED(); - return MOJO_RESULT_INTERNAL; -} - -MojoResult RemoteConsumerDataPipeImpl::ConsumerBeginReadData( - UserPointer<const void*> /*buffer*/, - UserPointer<uint32_t> /*buffer_num_bytes*/) { - NOTREACHED(); - return MOJO_RESULT_INTERNAL; -} - -MojoResult RemoteConsumerDataPipeImpl::ConsumerEndReadData( - uint32_t /*num_bytes_read*/) { - NOTREACHED(); - return MOJO_RESULT_INTERNAL; -} - -HandleSignalsState RemoteConsumerDataPipeImpl::ConsumerGetHandleSignalsState() - const { - return HandleSignalsState(); -} - -void RemoteConsumerDataPipeImpl::ConsumerStartSerialize( - Channel* /*channel*/, - size_t* /*max_size*/, - size_t* /*max_platform_handles*/) { - NOTREACHED(); -} - -bool RemoteConsumerDataPipeImpl::ConsumerEndSerialize( - Channel* /*channel*/, - void* /*destination*/, - size_t* /*actual_size*/, - embedder::PlatformHandleVector* /*platform_handles*/) { - NOTREACHED(); - return false; -} - -bool RemoteConsumerDataPipeImpl::OnReadMessage(unsigned /*port*/, - MessageInTransit* message) { - // Always take ownership of the message. (This means that we should always - // return true.) - scoped_ptr<MessageInTransit> msg(message); - - if (!ValidateIncomingMessage(element_num_bytes(), capacity_num_bytes(), - consumer_num_bytes_, msg.get())) { - Disconnect(); - return true; - } - - const RemoteDataPipeAck* ack = - static_cast<const RemoteDataPipeAck*>(msg->bytes()); - size_t num_bytes_consumed = ack->num_bytes_consumed; - consumer_num_bytes_ -= num_bytes_consumed; - return true; -} - -void RemoteConsumerDataPipeImpl::OnDetachFromChannel(unsigned /*port*/) { - if (!consumer_open()) { - DCHECK(!channel_endpoint_); - return; - } - - Disconnect(); -} - -void RemoteConsumerDataPipeImpl::EnsureBuffer() { - DCHECK(producer_open()); - if (buffer_) - return; - buffer_.reset(static_cast<char*>( - base::AlignedAlloc(capacity_num_bytes(), - GetConfiguration().data_pipe_buffer_alignment_bytes))); -} - -void RemoteConsumerDataPipeImpl::DestroyBuffer() { -#ifndef NDEBUG - // Scribble on the buffer to help detect use-after-frees. (This also helps the - // unit test detect certain bugs without needing ASAN or similar.) - if (buffer_) - memset(buffer_.get(), 0xcd, capacity_num_bytes()); -#endif - buffer_.reset(); -} - -void RemoteConsumerDataPipeImpl::Disconnect() { - DCHECK(consumer_open()); - DCHECK(channel_endpoint_); - owner()->SetConsumerClosedNoLock(); - channel_endpoint_->DetachFromClient(); - channel_endpoint_ = nullptr; - if (!producer_in_two_phase_write()) - DestroyBuffer(); -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/remote_consumer_data_pipe_impl.h b/third_party/mojo/src/mojo/edk/system/remote_consumer_data_pipe_impl.h deleted file mode 100644 index c87f232..0000000 --- a/third_party/mojo/src/mojo/edk/system/remote_consumer_data_pipe_impl.h +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2015 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_REMOTE_CONSUMER_DATA_PIPE_IMPL_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_REMOTE_CONSUMER_DATA_PIPE_IMPL_H_ - -#include "base/memory/aligned_memory.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/data_pipe_impl.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -// |RemoteConsumerDataPipeImpl| is a subclass that "implements" |DataPipe| for -// data pipes whose producer is local and whose consumer is remote. See -// |DataPipeImpl| for more details. -class MOJO_SYSTEM_IMPL_EXPORT RemoteConsumerDataPipeImpl final - : public DataPipeImpl { - public: - // |buffer| is only required if |producer_two_phase_max_num_bytes_written()| - // is nonzero (i.e., if we're in the middle of a two-phase write when the - // consumer handle is transferred); |start_index| is ignored if it is zero. - RemoteConsumerDataPipeImpl(ChannelEndpoint* channel_endpoint, - size_t consumer_num_bytes, - scoped_ptr<char, base::AlignedFreeDeleter> buffer, - size_t start_index); - ~RemoteConsumerDataPipeImpl() override; - - // Processes messages that were received and queued by an |IncomingEndpoint|. - // |*consumer_num_bytes| should be set to the value from the - // |SerializedDataPipeProducerDispatcher|. On success, returns true and - // updates |*consumer_num_bytes|. On failure, returns false (it may or may not - // modify |*consumer_num_bytes|). Always clears |*messages|. - static bool ProcessMessagesFromIncomingEndpoint( - const MojoCreateDataPipeOptions& validated_options, - size_t* consumer_num_bytes, - MessageInTransitQueue* messages); - - private: - // |DataPipeImpl| implementation: - // Note: None of the |Consumer...()| methods should be called, except - // |ConsumerGetHandleSignalsState()|. - void ProducerClose() override; - MojoResult ProducerWriteData(UserPointer<const void> elements, - UserPointer<uint32_t> num_bytes, - uint32_t max_num_bytes_to_write, - uint32_t min_num_bytes_to_write) override; - MojoResult ProducerBeginWriteData( - UserPointer<void*> buffer, - UserPointer<uint32_t> buffer_num_bytes) override; - MojoResult ProducerEndWriteData(uint32_t num_bytes_written) override; - HandleSignalsState ProducerGetHandleSignalsState() const override; - void ProducerStartSerialize(Channel* channel, - size_t* max_size, - size_t* max_platform_handles) override; - bool ProducerEndSerialize( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) override; - void ConsumerClose() override; - MojoResult ConsumerReadData(UserPointer<void> elements, - UserPointer<uint32_t> num_bytes, - uint32_t max_num_bytes_to_read, - uint32_t min_num_bytes_to_read, - bool peek) override; - MojoResult ConsumerDiscardData(UserPointer<uint32_t> num_bytes, - uint32_t max_num_bytes_to_discard, - uint32_t min_num_bytes_to_discard) override; - MojoResult ConsumerQueryData(UserPointer<uint32_t> num_bytes) override; - MojoResult ConsumerBeginReadData( - UserPointer<const void*> buffer, - UserPointer<uint32_t> buffer_num_bytes) override; - MojoResult ConsumerEndReadData(uint32_t num_bytes_read) override; - HandleSignalsState ConsumerGetHandleSignalsState() const override; - void ConsumerStartSerialize(Channel* channel, - size_t* max_size, - size_t* max_platform_handles) override; - bool ConsumerEndSerialize( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) override; - bool OnReadMessage(unsigned port, MessageInTransit* message) override; - void OnDetachFromChannel(unsigned port) override; - - void EnsureBuffer(); - void DestroyBuffer(); - - void Disconnect(); - - // Should be valid if and only if |consumer_open()| returns true. - scoped_refptr<ChannelEndpoint> channel_endpoint_; - - // The number of bytes we've sent the consumer, but don't *know* have been - // consumed. - size_t consumer_num_bytes_; - - // Used for two-phase writes. - scoped_ptr<char, base::AlignedFreeDeleter> buffer_; - // This is nearly always zero, except when the two-phase write started on a - // |LocalDataPipeImpl|. - size_t start_index_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(RemoteConsumerDataPipeImpl); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_REMOTE_CONSUMER_DATA_PIPE_IMPL_H_ diff --git a/third_party/mojo/src/mojo/edk/system/remote_data_pipe_ack.h b/third_party/mojo/src/mojo/edk/system/remote_data_pipe_ack.h deleted file mode 100644 index 569cc21..0000000 --- a/third_party/mojo/src/mojo/edk/system/remote_data_pipe_ack.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_REMOTE_DATA_PIPE_ACK_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_REMOTE_DATA_PIPE_ACK_H_ - -#include <stdint.h> - -namespace mojo { -namespace system { - -// Data payload for |MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA_PIPE_ACK| -// messages. -struct RemoteDataPipeAck { - uint32_t num_bytes_consumed; -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_REMOTE_DATA_PIPE_ACK_H_ diff --git a/third_party/mojo/src/mojo/edk/system/remote_data_pipe_impl_unittest.cc b/third_party/mojo/src/mojo/edk/system/remote_data_pipe_impl_unittest.cc deleted file mode 100644 index 1aef0fc..0000000 --- a/third_party/mojo/src/mojo/edk/system/remote_data_pipe_impl_unittest.cc +++ /dev/null @@ -1,509 +0,0 @@ -// Copyright 2015 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. - -// This file tests both |RemoteProducerDataPipeImpl| and -// |RemoteConsumerDataPipeImpl|. - -#include <stdint.h> - -#include "base/bind.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "base/test/test_io_thread.h" -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" -#include "third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h" -#include "third_party/mojo/src/mojo/edk/system/channel.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/data_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/memory.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/raw_channel.h" -#include "third_party/mojo/src/mojo/edk/system/test_utils.h" -#include "third_party/mojo/src/mojo/edk/system/waiter.h" - -namespace mojo { -namespace system { -namespace { - -const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED; - -class RemoteDataPipeImplTest : public testing::Test { - public: - RemoteDataPipeImplTest() : io_thread_(base::TestIOThread::kAutoStart) {} - ~RemoteDataPipeImplTest() override {} - - void SetUp() override { - scoped_refptr<ChannelEndpoint> ep[2]; - message_pipes_[0] = MessagePipe::CreateLocalProxy(&ep[0]); - message_pipes_[1] = MessagePipe::CreateLocalProxy(&ep[1]); - - io_thread_.PostTaskAndWait( - FROM_HERE, base::Bind(&RemoteDataPipeImplTest::SetUpOnIOThread, - base::Unretained(this), ep[0], ep[1])); - } - - void TearDown() override { - EnsureMessagePipeClosed(0); - EnsureMessagePipeClosed(1); - io_thread_.PostTaskAndWait( - FROM_HERE, base::Bind(&RemoteDataPipeImplTest::TearDownOnIOThread, - base::Unretained(this))); - } - - protected: - static DataPipe* CreateLocal(size_t element_size, size_t num_elements) { - const MojoCreateDataPipeOptions options = { - static_cast<uint32_t>(sizeof(MojoCreateDataPipeOptions)), - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, - static_cast<uint32_t>(element_size), - static_cast<uint32_t>(num_elements * element_size)}; - MojoCreateDataPipeOptions validated_options = {}; - CHECK_EQ(DataPipe::ValidateCreateOptions(MakeUserPointer(&options), - &validated_options), - MOJO_RESULT_OK); - return DataPipe::CreateLocal(validated_options); - } - - scoped_refptr<MessagePipe> message_pipe(size_t i) { - return message_pipes_[i]; - } - - void EnsureMessagePipeClosed(size_t i) { - if (!message_pipes_[i]) - return; - message_pipes_[i]->Close(0); - message_pipes_[i] = nullptr; - } - - private: - void SetUpOnIOThread(scoped_refptr<ChannelEndpoint> ep0, - scoped_refptr<ChannelEndpoint> ep1) { - CHECK_EQ(base::MessageLoop::current(), io_thread_.message_loop()); - - embedder::PlatformChannelPair channel_pair; - channels_[0] = new Channel(&platform_support_); - channels_[0]->Init(RawChannel::Create(channel_pair.PassServerHandle())); - channels_[0]->SetBootstrapEndpoint(ep0); - channels_[1] = new Channel(&platform_support_); - channels_[1]->Init(RawChannel::Create(channel_pair.PassClientHandle())); - channels_[1]->SetBootstrapEndpoint(ep1); - } - - void TearDownOnIOThread() { - CHECK_EQ(base::MessageLoop::current(), io_thread_.message_loop()); - - if (channels_[0]) { - channels_[0]->Shutdown(); - channels_[0] = nullptr; - } - if (channels_[1]) { - channels_[1]->Shutdown(); - channels_[1] = nullptr; - } - } - - embedder::SimplePlatformSupport platform_support_; - base::TestIOThread io_thread_; - scoped_refptr<Channel> channels_[2]; - scoped_refptr<MessagePipe> message_pipes_[2]; - - MOJO_DISALLOW_COPY_AND_ASSIGN(RemoteDataPipeImplTest); -}; - -// These tests are heavier-weight than ideal. They test remote data pipes by -// passing data pipe (producer/consumer) dispatchers over remote message pipes. -// Make sure that the test fixture works properly (i.e., that the message pipe -// works properly, and that things are shut down correctly). -// TODO(vtl): Make lighter-weight tests. Ideally, we'd have tests for remote -// data pipes which don't involve message pipes (or even data pipe dispatchers). -TEST_F(RemoteDataPipeImplTest, Sanity) { - static const char kHello[] = "hello"; - char read_buffer[100] = {}; - uint32_t read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); - Waiter waiter; - HandleSignalsState hss; - uintptr_t context = 0; - - // Write on MP 0 (port 0). Wait and receive on MP 1 (port 0). (Add the waiter - // first, to avoid any handling the case where it's already readable.) - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - message_pipe(1)->AddAwakable( - 0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); - EXPECT_EQ(MOJO_RESULT_OK, - message_pipe(0)->WriteMessage(0, UserPointer<const void>(kHello), - sizeof(kHello), nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::ActionDeadline(), &context)); - EXPECT_EQ(123u, context); - hss = HandleSignalsState(); - message_pipe(1)->RemoveAwakable(0, &waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - EXPECT_EQ(MOJO_RESULT_OK, message_pipe(1)->ReadMessage( - 0, UserPointer<void>(read_buffer), - MakeUserPointer(&read_buffer_size), nullptr, - nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size)); - EXPECT_STREQ(kHello, read_buffer); -} - -TEST_F(RemoteDataPipeImplTest, SendConsumerWithClosedProducer) { - char read_buffer[100] = {}; - uint32_t read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); - DispatcherVector read_dispatchers; - uint32_t read_num_dispatchers = 10; // Maximum to get. - Waiter waiter; - HandleSignalsState hss; - uintptr_t context = 0; - - scoped_refptr<DataPipe> dp(CreateLocal(sizeof(int32_t), 1000)); - // This is the consumer dispatcher we'll send. - scoped_refptr<DataPipeConsumerDispatcher> consumer = - DataPipeConsumerDispatcher::Create(); - consumer->Init(dp); - - // Write to the producer and close it, before sending the consumer. - int32_t elements[10] = {123}; - uint32_t num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_OK, - dp->ProducerWriteData(UserPointer<const void>(elements), - MakeUserPointer(&num_bytes), false)); - EXPECT_EQ(1u * sizeof(elements[0]), num_bytes); - dp->ProducerClose(); - - // Write the consumer to MP 0 (port 0). Wait and receive on MP 1 (port 0). - // (Add the waiter first, to avoid any handling the case where it's already - // readable.) - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - message_pipe(1)->AddAwakable( - 0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); - { - DispatcherTransport transport( - test::DispatcherTryStartTransport(consumer.get())); - EXPECT_TRUE(transport.is_valid()); - - std::vector<DispatcherTransport> transports; - transports.push_back(transport); - EXPECT_EQ(MOJO_RESULT_OK, message_pipe(0)->WriteMessage( - 0, NullUserPointer(), 0, &transports, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - transport.End(); - - // |consumer| should have been closed. This is |DCHECK()|ed when it is - // destroyed. - EXPECT_TRUE(consumer->HasOneRef()); - consumer = nullptr; - } - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::ActionDeadline(), &context)); - EXPECT_EQ(123u, context); - hss = HandleSignalsState(); - message_pipe(1)->RemoveAwakable(0, &waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - EXPECT_EQ(MOJO_RESULT_OK, - message_pipe(1)->ReadMessage( - 0, UserPointer<void>(read_buffer), - MakeUserPointer(&read_buffer_size), &read_dispatchers, - &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(0u, static_cast<size_t>(read_buffer_size)); - EXPECT_EQ(1u, read_dispatchers.size()); - EXPECT_EQ(1u, read_num_dispatchers); - ASSERT_TRUE(read_dispatchers[0]); - EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); - - EXPECT_EQ(Dispatcher::Type::DATA_PIPE_CONSUMER, - read_dispatchers[0]->GetType()); - consumer = - static_cast<DataPipeConsumerDispatcher*>(read_dispatchers[0].get()); - read_dispatchers.clear(); - - waiter.Init(); - hss = HandleSignalsState(); - MojoResult result = - consumer->AddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 456, &hss); - if (result == MOJO_RESULT_OK) { - context = 0; - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::ActionDeadline(), &context)); - EXPECT_EQ(456u, context); - consumer->RemoveAwakable(&waiter, &hss); - } else { - ASSERT_EQ(MOJO_RESULT_ALREADY_EXISTS, result); - } - // We don't know if the fact that the producer has been closed is known yet. - EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); - EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); - - // Read one element. - elements[0] = -1; - elements[1] = -1; - num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_OK, consumer->ReadData(UserPointer<void>(elements), - MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_NONE)); - EXPECT_EQ(1u * sizeof(elements[0]), num_bytes); - EXPECT_EQ(123, elements[0]); - EXPECT_EQ(-1, elements[1]); - - waiter.Init(); - hss = HandleSignalsState(); - result = - consumer->AddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, &hss); - if (result == MOJO_RESULT_OK) { - context = 0; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - waiter.Wait(test::ActionDeadline(), &context)); - EXPECT_EQ(789u, context); - consumer->RemoveAwakable(&waiter, &hss); - } else { - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); - } - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - consumer->Close(); -} - -TEST_F(RemoteDataPipeImplTest, SendConsumerDuringTwoPhaseWrite) { - char read_buffer[100] = {}; - uint32_t read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); - DispatcherVector read_dispatchers; - uint32_t read_num_dispatchers = 10; // Maximum to get. - Waiter waiter; - HandleSignalsState hss; - uintptr_t context = 0; - - scoped_refptr<DataPipe> dp(CreateLocal(sizeof(int32_t), 1000)); - // This is the consumer dispatcher we'll send. - scoped_refptr<DataPipeConsumerDispatcher> consumer = - DataPipeConsumerDispatcher::Create(); - consumer->Init(dp); - - void* write_ptr = nullptr; - uint32_t num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr), - MakeUserPointer(&num_bytes))); - ASSERT_GE(num_bytes, 1u * sizeof(int32_t)); - - // Write the consumer to MP 0 (port 0). Wait and receive on MP 1 (port 0). - // (Add the waiter first, to avoid any handling the case where it's already - // readable.) - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - message_pipe(1)->AddAwakable( - 0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); - { - DispatcherTransport transport( - test::DispatcherTryStartTransport(consumer.get())); - EXPECT_TRUE(transport.is_valid()); - - std::vector<DispatcherTransport> transports; - transports.push_back(transport); - EXPECT_EQ(MOJO_RESULT_OK, message_pipe(0)->WriteMessage( - 0, NullUserPointer(), 0, &transports, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - transport.End(); - - // |consumer| should have been closed. This is |DCHECK()|ed when it is - // destroyed. - EXPECT_TRUE(consumer->HasOneRef()); - consumer = nullptr; - } - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::ActionDeadline(), &context)); - EXPECT_EQ(123u, context); - hss = HandleSignalsState(); - message_pipe(1)->RemoveAwakable(0, &waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - EXPECT_EQ(MOJO_RESULT_OK, - message_pipe(1)->ReadMessage( - 0, UserPointer<void>(read_buffer), - MakeUserPointer(&read_buffer_size), &read_dispatchers, - &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(0u, static_cast<size_t>(read_buffer_size)); - EXPECT_EQ(1u, read_dispatchers.size()); - EXPECT_EQ(1u, read_num_dispatchers); - ASSERT_TRUE(read_dispatchers[0]); - EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); - - EXPECT_EQ(Dispatcher::Type::DATA_PIPE_CONSUMER, - read_dispatchers[0]->GetType()); - consumer = - static_cast<DataPipeConsumerDispatcher*>(read_dispatchers[0].get()); - read_dispatchers.clear(); - - // Now actually write the data, complete the two-phase write, and close the - // producer. - *static_cast<int32_t*>(write_ptr) = 123456; - EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData( - static_cast<uint32_t>(1u * sizeof(int32_t)))); - dp->ProducerClose(); - - // Wait for the consumer to be readable. - waiter.Init(); - hss = HandleSignalsState(); - MojoResult result = - consumer->AddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 456, &hss); - if (result == MOJO_RESULT_OK) { - context = 0; - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::ActionDeadline(), &context)); - EXPECT_EQ(456u, context); - consumer->RemoveAwakable(&waiter, &hss); - } else { - ASSERT_EQ(MOJO_RESULT_ALREADY_EXISTS, result); - } - // We don't know if the fact that the producer has been closed is known yet. - EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); - EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); - - // Read one element. - int32_t elements[10] = {-1, -1}; - num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_OK, consumer->ReadData(UserPointer<void>(elements), - MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_NONE)); - EXPECT_EQ(1u * sizeof(elements[0]), num_bytes); - EXPECT_EQ(123456, elements[0]); - EXPECT_EQ(-1, elements[1]); - - consumer->Close(); -} - -// Like |SendConsumerDuringTwoPhaseWrite|, but transfers the consumer during the -// second two-phase write (to try to test that the offset in circular buffer is -// properly preserved). -TEST_F(RemoteDataPipeImplTest, SendConsumerDuringSecondTwoPhaseWrite) { - char read_buffer[100] = {}; - uint32_t read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); - DispatcherVector read_dispatchers; - uint32_t read_num_dispatchers = 10; // Maximum to get. - Waiter waiter; - HandleSignalsState hss; - uintptr_t context = 0; - - scoped_refptr<DataPipe> dp(CreateLocal(sizeof(int32_t), 1000)); - // This is the consumer dispatcher we'll send. - scoped_refptr<DataPipeConsumerDispatcher> consumer = - DataPipeConsumerDispatcher::Create(); - consumer->Init(dp); - - void* write_ptr = nullptr; - uint32_t num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr), - MakeUserPointer(&num_bytes))); - ASSERT_GE(num_bytes, 1u * sizeof(int32_t)); - *static_cast<int32_t*>(write_ptr) = 123456; - EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData( - static_cast<uint32_t>(1u * sizeof(int32_t)))); - - write_ptr = nullptr; - num_bytes = 0u; - EXPECT_EQ(MOJO_RESULT_OK, - dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr), - MakeUserPointer(&num_bytes))); - ASSERT_GE(num_bytes, 1u * sizeof(int32_t)); - - // Write the consumer to MP 0 (port 0). Wait and receive on MP 1 (port 0). - // (Add the waiter first, to avoid any handling the case where it's already - // readable.) - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - message_pipe(1)->AddAwakable( - 0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); - { - DispatcherTransport transport( - test::DispatcherTryStartTransport(consumer.get())); - EXPECT_TRUE(transport.is_valid()); - - std::vector<DispatcherTransport> transports; - transports.push_back(transport); - EXPECT_EQ(MOJO_RESULT_OK, message_pipe(0)->WriteMessage( - 0, NullUserPointer(), 0, &transports, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - transport.End(); - - // |consumer| should have been closed. This is |DCHECK()|ed when it is - // destroyed. - EXPECT_TRUE(consumer->HasOneRef()); - consumer = nullptr; - } - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::ActionDeadline(), &context)); - EXPECT_EQ(123u, context); - hss = HandleSignalsState(); - message_pipe(1)->RemoveAwakable(0, &waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - EXPECT_EQ(MOJO_RESULT_OK, - message_pipe(1)->ReadMessage( - 0, UserPointer<void>(read_buffer), - MakeUserPointer(&read_buffer_size), &read_dispatchers, - &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(0u, static_cast<size_t>(read_buffer_size)); - EXPECT_EQ(1u, read_dispatchers.size()); - EXPECT_EQ(1u, read_num_dispatchers); - ASSERT_TRUE(read_dispatchers[0]); - EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); - - EXPECT_EQ(Dispatcher::Type::DATA_PIPE_CONSUMER, - read_dispatchers[0]->GetType()); - consumer = - static_cast<DataPipeConsumerDispatcher*>(read_dispatchers[0].get()); - read_dispatchers.clear(); - - // Now actually write the data, complete the two-phase write, and close the - // producer. - *static_cast<int32_t*>(write_ptr) = 789012; - EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData( - static_cast<uint32_t>(1u * sizeof(int32_t)))); - dp->ProducerClose(); - - // Wait for the consumer to know that the producer is closed. - waiter.Init(); - hss = HandleSignalsState(); - MojoResult result = - consumer->AddAwakable(&waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 456, &hss); - if (result == MOJO_RESULT_OK) { - context = 0; - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::ActionDeadline(), &context)); - EXPECT_EQ(456u, context); - consumer->RemoveAwakable(&waiter, &hss); - } else { - ASSERT_EQ(MOJO_RESULT_ALREADY_EXISTS, result); - } - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Read some elements. - int32_t elements[10] = {}; - num_bytes = static_cast<uint32_t>(sizeof(elements)); - EXPECT_EQ(MOJO_RESULT_OK, consumer->ReadData(UserPointer<void>(elements), - MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_NONE)); - EXPECT_EQ(2u * sizeof(elements[0]), num_bytes); - EXPECT_EQ(123456, elements[0]); - EXPECT_EQ(789012, elements[1]); - EXPECT_EQ(0, elements[2]); - - consumer->Close(); -} - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/remote_message_pipe_unittest.cc b/third_party/mojo/src/mojo/edk/system/remote_message_pipe_unittest.cc deleted file mode 100644 index ef25086..0000000 --- a/third_party/mojo/src/mojo/edk/system/remote_message_pipe_unittest.cc +++ /dev/null @@ -1,1378 +0,0 @@ -// 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 <stdint.h> -#include <stdio.h> -#include <string.h> -#include <utility> -#include <vector> - -#include "base/bind.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/files/scoped_file.h" -#include "base/files/scoped_temp_dir.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "base/test/test_io_thread.h" -#include "build/build_config.h" // TODO(vtl): Remove this. -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_shared_buffer.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" -#include "third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h" -#include "third_party/mojo/src/mojo/edk/system/channel.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint_id.h" -#include "third_party/mojo/src/mojo/edk/system/incoming_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/raw_channel.h" -#include "third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/test_utils.h" -#include "third_party/mojo/src/mojo/edk/system/waiter.h" -#include "third_party/mojo/src/mojo/edk/test/test_utils.h" - -namespace mojo { -namespace system { -namespace { - -const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED; - -class RemoteMessagePipeTest : public testing::Test { - public: - RemoteMessagePipeTest() : io_thread_(base::TestIOThread::kAutoStart) {} - ~RemoteMessagePipeTest() override {} - - void SetUp() override { - io_thread_.PostTaskAndWait( - FROM_HERE, base::Bind(&RemoteMessagePipeTest::SetUpOnIOThread, - base::Unretained(this))); - } - - void TearDown() override { - io_thread_.PostTaskAndWait( - FROM_HERE, base::Bind(&RemoteMessagePipeTest::TearDownOnIOThread, - base::Unretained(this))); - } - - protected: - // This connects the two given |ChannelEndpoint|s. It assumes/requires that - // this is the bootstrap case (i.e., no other message pipes have ever been - // hosted on the channel). - void BootstrapChannelEndpoints(scoped_refptr<ChannelEndpoint> ep0, - scoped_refptr<ChannelEndpoint> ep1) { - io_thread_.PostTaskAndWait( - FROM_HERE, - base::Bind(&RemoteMessagePipeTest::BootstrapChannelEndpointsOnIOThread, - base::Unretained(this), ep0, ep1)); - } - - // This bootstraps |ep| on |channels_[channel_index]|. It assumes/requires - // that this is the bootstrap case (i.e., no message pipes have ever been - // hosted on the channel). This returns *without* waiting. - void BootstrapChannelEndpointNoWait(unsigned channel_index, - scoped_refptr<ChannelEndpoint> ep) { - io_thread_.PostTask( - FROM_HERE, - base::Bind(&RemoteMessagePipeTest::BootstrapChannelEndpointOnIOThread, - base::Unretained(this), channel_index, ep)); - } - - void RestoreInitialState() { - io_thread_.PostTaskAndWait( - FROM_HERE, - base::Bind(&RemoteMessagePipeTest::RestoreInitialStateOnIOThread, - base::Unretained(this))); - } - - embedder::PlatformSupport* platform_support() { return &platform_support_; } - base::TestIOThread* io_thread() { return &io_thread_; } - // Warning: It's up to the caller to ensure that the returned channel - // is/remains valid. - Channel* channels(size_t i) { return channels_[i].get(); } - - private: - void SetUpOnIOThread() { - CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); - - embedder::PlatformChannelPair channel_pair; - platform_handles_[0] = channel_pair.PassServerHandle(); - platform_handles_[1] = channel_pair.PassClientHandle(); - } - - void TearDownOnIOThread() { - CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); - - if (channels_[0]) { - channels_[0]->Shutdown(); - channels_[0] = nullptr; - } - if (channels_[1]) { - channels_[1]->Shutdown(); - channels_[1] = nullptr; - } - } - - void CreateAndInitChannel(unsigned channel_index) { - CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); - CHECK(channel_index == 0 || channel_index == 1); - CHECK(!channels_[channel_index]); - - channels_[channel_index] = new Channel(&platform_support_); - channels_[channel_index]->Init( - RawChannel::Create(std::move(platform_handles_[channel_index]))); - } - - void BootstrapChannelEndpointsOnIOThread(scoped_refptr<ChannelEndpoint> ep0, - scoped_refptr<ChannelEndpoint> ep1) { - CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); - - if (!channels_[0]) - CreateAndInitChannel(0); - if (!channels_[1]) - CreateAndInitChannel(1); - - channels_[0]->SetBootstrapEndpoint(ep0); - channels_[1]->SetBootstrapEndpoint(ep1); - } - - void BootstrapChannelEndpointOnIOThread(unsigned channel_index, - scoped_refptr<ChannelEndpoint> ep) { - CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); - CHECK(channel_index == 0 || channel_index == 1); - - CreateAndInitChannel(channel_index); - channels_[channel_index]->SetBootstrapEndpoint(ep); - } - - void RestoreInitialStateOnIOThread() { - CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); - - TearDownOnIOThread(); - SetUpOnIOThread(); - } - - embedder::SimplePlatformSupport platform_support_; - base::TestIOThread io_thread_; - embedder::ScopedPlatformHandle platform_handles_[2]; - scoped_refptr<Channel> channels_[2]; - - MOJO_DISALLOW_COPY_AND_ASSIGN(RemoteMessagePipeTest); -}; - -TEST_F(RemoteMessagePipeTest, Basic) { - static const char kHello[] = "hello"; - static const char kWorld[] = "world!!!1!!!1!"; - char buffer[100] = {0}; - uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); - Waiter waiter; - HandleSignalsState hss; - uintptr_t context = 0; - - // Connect message pipes. MP 0, port 1 will be attached to channel 0 and - // connected to MP 1, port 0, which will be attached to channel 1. This leaves - // MP 0, port 0 and MP 1, port 1 as the "user-facing" endpoints. - - scoped_refptr<ChannelEndpoint> ep0; - scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0)); - scoped_refptr<ChannelEndpoint> ep1; - scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1)); - BootstrapChannelEndpoints(ep0, ep1); - - // Write in one direction: MP 0, port 0 -> ... -> MP 1, port 1. - - // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do - // it later, it might already be readable.) - waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); - - // Write to MP 0, port 0. - EXPECT_EQ( - MOJO_RESULT_OK, - mp0->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello), - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Wait. - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_EQ(123u, context); - hss = HandleSignalsState(); - mp1->RemoveAwakable(1, &waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - // Read from MP 1, port 1. - EXPECT_EQ(MOJO_RESULT_OK, - mp1->ReadMessage(1, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kHello), static_cast<size_t>(buffer_size)); - EXPECT_STREQ(kHello, buffer); - - // Write in the other direction: MP 1, port 1 -> ... -> MP 0, port 0. - - waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - mp0->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 456, nullptr)); - - EXPECT_EQ( - MOJO_RESULT_OK, - mp1->WriteMessage(1, UserPointer<const void>(kWorld), sizeof(kWorld), - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_EQ(456u, context); - hss = HandleSignalsState(); - mp0->RemoveAwakable(0, &waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - buffer_size = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - mp0->ReadMessage(0, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kWorld), static_cast<size_t>(buffer_size)); - EXPECT_STREQ(kWorld, buffer); - - // Close MP 0, port 0. - mp0->Close(0); - - // Try to wait for MP 1, port 1 to become readable. This will eventually fail - // when it realizes that MP 0, port 0 has been closed. (It may also fail - // immediately.) - waiter.Init(); - hss = HandleSignalsState(); - MojoResult result = - mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, &hss); - if (result == MOJO_RESULT_OK) { - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_EQ(789u, context); - hss = HandleSignalsState(); - mp1->RemoveAwakable(1, &waiter, &hss); - } - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - // And MP 1, port 1. - mp1->Close(1); -} - -TEST_F(RemoteMessagePipeTest, PeerClosed) { - Waiter waiter; - HandleSignalsState hss; - uintptr_t context = 0; - - // Connect message pipes. MP 0, port 1 will be attached to channel 0 and - // connected to MP 1, port 0, which will be attached to channel 1. This leaves - // MP 0, port 0 and MP 1, port 1 as the "user-facing" endpoints. - - scoped_refptr<ChannelEndpoint> ep0; - scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0)); - scoped_refptr<ChannelEndpoint> ep1; - scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1)); - BootstrapChannelEndpoints(ep0, ep1); - - // Close MP 0, port 0. - mp0->Close(0); - - // Try to wait for MP 1, port 1 to be signaled with peer closed. - waiter.Init(); - hss = HandleSignalsState(); - MojoResult result = - mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 101, &hss); - if (result == MOJO_RESULT_OK) { - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_EQ(101u, context); - hss = HandleSignalsState(); - mp1->RemoveAwakable(1, &waiter, &hss); - } - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - // And MP 1, port 1. - mp1->Close(1); -} - -TEST_F(RemoteMessagePipeTest, Multiplex) { - static const char kHello[] = "hello"; - static const char kWorld[] = "world!!!1!!!1!"; - char buffer[100] = {0}; - uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); - Waiter waiter; - HandleSignalsState hss; - uintptr_t context = 0; - - // Connect message pipes as in the |Basic| test. - - scoped_refptr<ChannelEndpoint> ep0; - scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0)); - scoped_refptr<ChannelEndpoint> ep1; - scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1)); - BootstrapChannelEndpoints(ep0, ep1); - - // Now put another message pipe on the channel. - - // Do this by creating a message pipe (for the |channels(0)| side) and - // attaching and running it, yielding the remote ID. A message is then sent - // via |ep0| (i.e., sent using |mp0|, port 0) with this remote ID. Upon - // receiving this message, |PassIncomingMessagePipe()| is used to obtain the - // message pipe on the other side. - scoped_refptr<MessagePipe> mp2(MessagePipe::CreateLocalLocal()); - ASSERT_TRUE(channels(0)); - size_t max_endpoint_info_size; - size_t max_platform_handle_count; - mp2->StartSerialize(1, channels(0), &max_endpoint_info_size, - &max_platform_handle_count); - EXPECT_GT(max_endpoint_info_size, 0u); - ASSERT_EQ(0u, max_platform_handle_count); - scoped_ptr<char[]> endpoint_info(new char[max_endpoint_info_size]); - size_t endpoint_info_size; - mp2->EndSerialize(1, channels(0), endpoint_info.get(), &endpoint_info_size, - nullptr); - EXPECT_EQ(max_endpoint_info_size, endpoint_info_size); - - waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); - - EXPECT_EQ(MOJO_RESULT_OK, - mp0->WriteMessage(0, UserPointer<const void>(endpoint_info.get()), - static_cast<uint32_t>(endpoint_info_size), - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_EQ(123u, context); - hss = HandleSignalsState(); - mp1->RemoveAwakable(1, &waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - EXPECT_EQ(endpoint_info_size, channels(1)->GetSerializedEndpointSize()); - scoped_ptr<char[]> received_endpoint_info(new char[endpoint_info_size]); - buffer_size = static_cast<uint32_t>(endpoint_info_size); - EXPECT_EQ(MOJO_RESULT_OK, - mp1->ReadMessage(1, UserPointer<void>(received_endpoint_info.get()), - MakeUserPointer(&buffer_size), nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(endpoint_info_size, static_cast<size_t>(buffer_size)); - EXPECT_EQ(0, memcmp(received_endpoint_info.get(), endpoint_info.get(), - endpoint_info_size)); - - // Warning: The local side of mp3 is port 0, not port 1. - scoped_refptr<IncomingEndpoint> incoming_endpoint = - channels(1)->DeserializeEndpoint(received_endpoint_info.get()); - ASSERT_TRUE(incoming_endpoint); - scoped_refptr<MessagePipe> mp3 = incoming_endpoint->ConvertToMessagePipe(); - ASSERT_TRUE(mp3); - - // Write: MP 2, port 0 -> MP 3, port 1. - - waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - mp3->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, nullptr)); - - EXPECT_EQ( - MOJO_RESULT_OK, - mp2->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello), - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_EQ(789u, context); - hss = HandleSignalsState(); - mp3->RemoveAwakable(0, &waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - // Make sure there's nothing on MP 0, port 0 or MP 1, port 1 or MP 2, port 0. - buffer_size = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - mp0->ReadMessage(0, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - buffer_size = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - mp1->ReadMessage(1, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - buffer_size = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - mp2->ReadMessage(0, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - - // Read from MP 3, port 1. - buffer_size = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - mp3->ReadMessage(0, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kHello), static_cast<size_t>(buffer_size)); - EXPECT_STREQ(kHello, buffer); - - // Write: MP 0, port 0 -> MP 1, port 1 again. - - waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); - - EXPECT_EQ( - MOJO_RESULT_OK, - mp0->WriteMessage(0, UserPointer<const void>(kWorld), sizeof(kWorld), - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_EQ(123u, context); - hss = HandleSignalsState(); - mp1->RemoveAwakable(1, &waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Make sure there's nothing on the other ports. - buffer_size = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - mp0->ReadMessage(0, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - buffer_size = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - mp2->ReadMessage(0, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - buffer_size = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - mp3->ReadMessage(0, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - - buffer_size = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - mp1->ReadMessage(1, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kWorld), static_cast<size_t>(buffer_size)); - EXPECT_STREQ(kWorld, buffer); - - mp0->Close(0); - mp1->Close(1); - mp2->Close(0); - mp3->Close(0); -} - -TEST_F(RemoteMessagePipeTest, CloseBeforeAttachAndRun) { - static const char kHello[] = "hello"; - char buffer[100] = {0}; - uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); - Waiter waiter; - HandleSignalsState hss; - uintptr_t context = 0; - - // Connect message pipes. MP 0, port 1 will be attached to channel 0 and - // connected to MP 1, port 0, which will be attached to channel 1. This leaves - // MP 0, port 0 and MP 1, port 1 as the "user-facing" endpoints. - - scoped_refptr<ChannelEndpoint> ep0; - scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0)); - - // Write to MP 0, port 0. - EXPECT_EQ( - MOJO_RESULT_OK, - mp0->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello), - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Close MP 0, port 0 before it's even been attached to the channel and run. - mp0->Close(0); - - BootstrapChannelEndpointNoWait(0, ep0); - - scoped_refptr<ChannelEndpoint> ep1; - scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1)); - - // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do - // it later, it might already be readable.) - waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); - - BootstrapChannelEndpointNoWait(1, ep1); - - // Wait. - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_EQ(123u, context); - hss = HandleSignalsState(); - // Note: MP 1, port 1 should definitely should be readable, but it may or may - // not appear as writable (there's a race, and it may not have noticed that - // the other side was closed yet -- e.g., inserting a sleep here would make it - // much more likely to notice that it's no longer writable). - mp1->RemoveAwakable(1, &waiter, &hss); - EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); - EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); - - // Read from MP 1, port 1. - EXPECT_EQ(MOJO_RESULT_OK, - mp1->ReadMessage(1, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kHello), static_cast<size_t>(buffer_size)); - EXPECT_STREQ(kHello, buffer); - - // And MP 1, port 1. - mp1->Close(1); -} - -TEST_F(RemoteMessagePipeTest, CloseBeforeConnect) { - static const char kHello[] = "hello"; - char buffer[100] = {0}; - uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); - Waiter waiter; - HandleSignalsState hss; - uintptr_t context = 0; - - // Connect message pipes. MP 0, port 1 will be attached to channel 0 and - // connected to MP 1, port 0, which will be attached to channel 1. This leaves - // MP 0, port 0 and MP 1, port 1 as the "user-facing" endpoints. - - scoped_refptr<ChannelEndpoint> ep0; - scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0)); - - // Write to MP 0, port 0. - EXPECT_EQ( - MOJO_RESULT_OK, - mp0->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello), - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - BootstrapChannelEndpointNoWait(0, ep0); - - // Close MP 0, port 0 before channel 1 is even connected. - mp0->Close(0); - - scoped_refptr<ChannelEndpoint> ep1; - scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1)); - - // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do - // it later, it might already be readable.) - waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); - - BootstrapChannelEndpointNoWait(1, ep1); - - // Wait. - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_EQ(123u, context); - hss = HandleSignalsState(); - // Note: MP 1, port 1 should definitely should be readable, but it may or may - // not appear as writable (there's a race, and it may not have noticed that - // the other side was closed yet -- e.g., inserting a sleep here would make it - // much more likely to notice that it's no longer writable). - mp1->RemoveAwakable(1, &waiter, &hss); - EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); - EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); - - // Read from MP 1, port 1. - EXPECT_EQ(MOJO_RESULT_OK, - mp1->ReadMessage(1, UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kHello), static_cast<size_t>(buffer_size)); - EXPECT_STREQ(kHello, buffer); - - // And MP 1, port 1. - mp1->Close(1); -} - -TEST_F(RemoteMessagePipeTest, HandlePassing) { - static const char kHello[] = "hello"; - Waiter waiter; - HandleSignalsState hss; - uintptr_t context = 0; - - scoped_refptr<ChannelEndpoint> ep0; - scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0)); - scoped_refptr<ChannelEndpoint> ep1; - scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1)); - BootstrapChannelEndpoints(ep0, ep1); - - // We'll try to pass this dispatcher. - scoped_refptr<MessagePipeDispatcher> dispatcher = - MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - scoped_refptr<MessagePipe> local_mp(MessagePipe::CreateLocalLocal()); - dispatcher->Init(local_mp, 0); - - // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do - // it later, it might already be readable.) - waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); - - // Write to MP 0, port 0. - { - DispatcherTransport transport( - test::DispatcherTryStartTransport(dispatcher.get())); - EXPECT_TRUE(transport.is_valid()); - - std::vector<DispatcherTransport> transports; - transports.push_back(transport); - EXPECT_EQ( - MOJO_RESULT_OK, - mp0->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello), - &transports, MOJO_WRITE_MESSAGE_FLAG_NONE)); - transport.End(); - - // |dispatcher| should have been closed. This is |DCHECK()|ed when the - // |dispatcher| is destroyed. - EXPECT_TRUE(dispatcher->HasOneRef()); - dispatcher = nullptr; - } - - // Wait. - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_EQ(123u, context); - hss = HandleSignalsState(); - mp1->RemoveAwakable(1, &waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - // Read from MP 1, port 1. - char read_buffer[100] = {0}; - uint32_t read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); - DispatcherVector read_dispatchers; - uint32_t read_num_dispatchers = 10; // Maximum to get. - EXPECT_EQ( - MOJO_RESULT_OK, - mp1->ReadMessage(1, UserPointer<void>(read_buffer), - MakeUserPointer(&read_buffer_size), &read_dispatchers, - &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size)); - EXPECT_STREQ(kHello, read_buffer); - EXPECT_EQ(1u, read_dispatchers.size()); - EXPECT_EQ(1u, read_num_dispatchers); - ASSERT_TRUE(read_dispatchers[0]); - EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); - - EXPECT_EQ(Dispatcher::Type::MESSAGE_PIPE, read_dispatchers[0]->GetType()); - dispatcher = static_cast<MessagePipeDispatcher*>(read_dispatchers[0].get()); - - // Add the waiter now, before it becomes readable to avoid a race. - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - dispatcher->AddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 456, - nullptr)); - - // Write to "local_mp", port 1. - EXPECT_EQ( - MOJO_RESULT_OK, - local_mp->WriteMessage(1, UserPointer<const void>(kHello), sizeof(kHello), - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // TODO(vtl): FIXME -- We (racily) crash if I close |dispatcher| immediately - // here. (We don't crash if I sleep and then close.) - - // Wait for the dispatcher to become readable. - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_EQ(456u, context); - hss = HandleSignalsState(); - dispatcher->RemoveAwakable(&waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - // Read from the dispatcher. - memset(read_buffer, 0, sizeof(read_buffer)); - read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - dispatcher->ReadMessage(UserPointer<void>(read_buffer), - MakeUserPointer(&read_buffer_size), 0, - nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size)); - EXPECT_STREQ(kHello, read_buffer); - - // Prepare to wait on "local_mp", port 1. - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - local_mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, - nullptr)); - - // Write to the dispatcher. - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->WriteMessage( - UserPointer<const void>(kHello), sizeof(kHello), - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Wait. - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_EQ(789u, context); - hss = HandleSignalsState(); - local_mp->RemoveAwakable(1, &waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - // Read from "local_mp", port 1. - memset(read_buffer, 0, sizeof(read_buffer)); - read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - local_mp->ReadMessage(1, UserPointer<void>(read_buffer), - MakeUserPointer(&read_buffer_size), nullptr, - nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size)); - EXPECT_STREQ(kHello, read_buffer); - - // TODO(vtl): Also test that messages queued up before the handle was sent are - // delivered properly. - - // Close everything that belongs to us. - mp0->Close(0); - mp1->Close(1); - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); - // Note that |local_mp|'s port 0 belong to |dispatcher|, which was closed. - local_mp->Close(1); -} - -TEST_F(RemoteMessagePipeTest, HandlePassingHalfClosed) { - static const char kHello[] = "hello"; - static const char kWorld[] = "world!"; - Waiter waiter; - HandleSignalsState hss; - uintptr_t context = 0; - - // We'll try to pass this dispatcher. - scoped_refptr<MessagePipeDispatcher> dispatcher = - MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - scoped_refptr<MessagePipe> local_mp(MessagePipe::CreateLocalLocal()); - dispatcher->Init(local_mp, 0); - - hss = local_mp->GetHandleSignalsState(0); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - // Write to the other end (|local_mp|, port 1), and then close it. - EXPECT_EQ( - MOJO_RESULT_OK, - local_mp->WriteMessage(1, UserPointer<const void>(kHello), sizeof(kHello), - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - hss = local_mp->GetHandleSignalsState(0); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - // Then the second message.... - EXPECT_EQ( - MOJO_RESULT_OK, - local_mp->WriteMessage(1, UserPointer<const void>(kWorld), sizeof(kWorld), - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - hss = local_mp->GetHandleSignalsState(0); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - // Then close it. - local_mp->Close(1); - - scoped_refptr<ChannelEndpoint> ep0; - scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0)); - scoped_refptr<ChannelEndpoint> ep1; - scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1)); - BootstrapChannelEndpoints(ep0, ep1); - - // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do - // it later, it might already be readable.) - waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); - - // Write to MP 0, port 0. - { - DispatcherTransport transport( - test::DispatcherTryStartTransport(dispatcher.get())); - EXPECT_TRUE(transport.is_valid()); - - std::vector<DispatcherTransport> transports; - transports.push_back(transport); - EXPECT_EQ( - MOJO_RESULT_OK, - mp0->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello), - &transports, MOJO_WRITE_MESSAGE_FLAG_NONE)); - transport.End(); - - // |dispatcher| should have been closed. This is |DCHECK()|ed when the - // |dispatcher| is destroyed. - EXPECT_TRUE(dispatcher->HasOneRef()); - dispatcher = nullptr; - } - - // Wait. - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_EQ(123u, context); - hss = HandleSignalsState(); - mp1->RemoveAwakable(1, &waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - // Read from MP 1, port 1. - char read_buffer[100] = {0}; - uint32_t read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); - DispatcherVector read_dispatchers; - uint32_t read_num_dispatchers = 10; // Maximum to get. - EXPECT_EQ( - MOJO_RESULT_OK, - mp1->ReadMessage(1, UserPointer<void>(read_buffer), - MakeUserPointer(&read_buffer_size), &read_dispatchers, - &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size)); - EXPECT_STREQ(kHello, read_buffer); - EXPECT_EQ(1u, read_dispatchers.size()); - EXPECT_EQ(1u, read_num_dispatchers); - ASSERT_TRUE(read_dispatchers[0]); - EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); - - EXPECT_EQ(Dispatcher::Type::MESSAGE_PIPE, read_dispatchers[0]->GetType()); - dispatcher = static_cast<MessagePipeDispatcher*>(read_dispatchers[0].get()); - - // |dispatcher| should already be readable and not writable. - hss = dispatcher->GetHandleSignalsState(); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - // So read from it. - memset(read_buffer, 0, sizeof(read_buffer)); - read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - dispatcher->ReadMessage(UserPointer<void>(read_buffer), - MakeUserPointer(&read_buffer_size), 0, - nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size)); - EXPECT_STREQ(kHello, read_buffer); - // It should still be readable. - hss = dispatcher->GetHandleSignalsState(); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - // So read from it. - memset(read_buffer, 0, sizeof(read_buffer)); - read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - dispatcher->ReadMessage(UserPointer<void>(read_buffer), - MakeUserPointer(&read_buffer_size), 0, - nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kWorld), static_cast<size_t>(read_buffer_size)); - EXPECT_STREQ(kWorld, read_buffer); - // Now it should no longer be readable. - hss = dispatcher->GetHandleSignalsState(); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - // Close everything that belongs to us. - mp0->Close(0); - mp1->Close(1); - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); -} - -#if defined(OS_POSIX) -#define MAYBE_SharedBufferPassing SharedBufferPassing -#else -// Not yet implemented (on Windows). -#define MAYBE_SharedBufferPassing DISABLED_SharedBufferPassing -#endif -TEST_F(RemoteMessagePipeTest, MAYBE_SharedBufferPassing) { - static const char kHello[] = "hello"; - Waiter waiter; - HandleSignalsState hss; - uintptr_t context = 0; - - scoped_refptr<ChannelEndpoint> ep0; - scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0)); - scoped_refptr<ChannelEndpoint> ep1; - scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1)); - BootstrapChannelEndpoints(ep0, ep1); - - // We'll try to pass this dispatcher. - scoped_refptr<SharedBufferDispatcher> dispatcher; - EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create( - platform_support(), - SharedBufferDispatcher::kDefaultCreateOptions, - 100, &dispatcher)); - ASSERT_TRUE(dispatcher); - - // Make a mapping. - scoped_ptr<embedder::PlatformSharedBufferMapping> mapping0; - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer( - 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping0)); - ASSERT_TRUE(mapping0); - ASSERT_TRUE(mapping0->GetBase()); - ASSERT_EQ(100u, mapping0->GetLength()); - static_cast<char*>(mapping0->GetBase())[0] = 'A'; - static_cast<char*>(mapping0->GetBase())[50] = 'B'; - static_cast<char*>(mapping0->GetBase())[99] = 'C'; - - // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do - // it later, it might already be readable.) - waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); - - // Write to MP 0, port 0. - { - DispatcherTransport transport( - test::DispatcherTryStartTransport(dispatcher.get())); - EXPECT_TRUE(transport.is_valid()); - - std::vector<DispatcherTransport> transports; - transports.push_back(transport); - EXPECT_EQ( - MOJO_RESULT_OK, - mp0->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello), - &transports, MOJO_WRITE_MESSAGE_FLAG_NONE)); - transport.End(); - - // |dispatcher| should have been closed. This is |DCHECK()|ed when the - // |dispatcher| is destroyed. - EXPECT_TRUE(dispatcher->HasOneRef()); - dispatcher = nullptr; - } - - // Wait. - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_EQ(123u, context); - hss = HandleSignalsState(); - mp1->RemoveAwakable(1, &waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - // Read from MP 1, port 1. - char read_buffer[100] = {0}; - uint32_t read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); - DispatcherVector read_dispatchers; - uint32_t read_num_dispatchers = 10; // Maximum to get. - EXPECT_EQ( - MOJO_RESULT_OK, - mp1->ReadMessage(1, UserPointer<void>(read_buffer), - MakeUserPointer(&read_buffer_size), &read_dispatchers, - &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size)); - EXPECT_STREQ(kHello, read_buffer); - EXPECT_EQ(1u, read_dispatchers.size()); - EXPECT_EQ(1u, read_num_dispatchers); - ASSERT_TRUE(read_dispatchers[0]); - EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); - - EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, read_dispatchers[0]->GetType()); - dispatcher = static_cast<SharedBufferDispatcher*>(read_dispatchers[0].get()); - - // Make another mapping. - scoped_ptr<embedder::PlatformSharedBufferMapping> mapping1; - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer( - 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping1)); - ASSERT_TRUE(mapping1); - ASSERT_TRUE(mapping1->GetBase()); - ASSERT_EQ(100u, mapping1->GetLength()); - EXPECT_NE(mapping1->GetBase(), mapping0->GetBase()); - EXPECT_EQ('A', static_cast<char*>(mapping1->GetBase())[0]); - EXPECT_EQ('B', static_cast<char*>(mapping1->GetBase())[50]); - EXPECT_EQ('C', static_cast<char*>(mapping1->GetBase())[99]); - - // Write stuff either way. - static_cast<char*>(mapping1->GetBase())[1] = 'x'; - EXPECT_EQ('x', static_cast<char*>(mapping0->GetBase())[1]); - static_cast<char*>(mapping0->GetBase())[2] = 'y'; - EXPECT_EQ('y', static_cast<char*>(mapping1->GetBase())[2]); - - // Kill the first mapping; the second should still be valid. - mapping0.reset(); - EXPECT_EQ('A', static_cast<char*>(mapping1->GetBase())[0]); - - // Close everything that belongs to us. - mp0->Close(0); - mp1->Close(1); - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); - - // The second mapping should still be good. - EXPECT_EQ('x', static_cast<char*>(mapping1->GetBase())[1]); -} - -#if defined(OS_POSIX) -#define MAYBE_PlatformHandlePassing PlatformHandlePassing -#else -// Not yet implemented (on Windows). -#define MAYBE_PlatformHandlePassing DISABLED_PlatformHandlePassing -#endif -TEST_F(RemoteMessagePipeTest, MAYBE_PlatformHandlePassing) { - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - - static const char kHello[] = "hello"; - static const char kWorld[] = "world"; - Waiter waiter; - uintptr_t context = 0; - HandleSignalsState hss; - - scoped_refptr<ChannelEndpoint> ep0; - scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0)); - scoped_refptr<ChannelEndpoint> ep1; - scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1)); - BootstrapChannelEndpoints(ep0, ep1); - - base::FilePath unused; - base::ScopedFILE fp( - base::CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused)); - EXPECT_EQ(sizeof(kHello), fwrite(kHello, 1, sizeof(kHello), fp.get())); - // We'll try to pass this dispatcher, which will cause a |PlatformHandle| to - // be passed. - scoped_refptr<PlatformHandleDispatcher> dispatcher = - PlatformHandleDispatcher::Create( - mojo::test::PlatformHandleFromFILE(std::move(fp))); - - // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do - // it later, it might already be readable.) - waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); - - // Write to MP 0, port 0. - { - DispatcherTransport transport( - test::DispatcherTryStartTransport(dispatcher.get())); - EXPECT_TRUE(transport.is_valid()); - - std::vector<DispatcherTransport> transports; - transports.push_back(transport); - EXPECT_EQ( - MOJO_RESULT_OK, - mp0->WriteMessage(0, UserPointer<const void>(kWorld), sizeof(kWorld), - &transports, MOJO_WRITE_MESSAGE_FLAG_NONE)); - transport.End(); - - // |dispatcher| should have been closed. This is |DCHECK()|ed when the - // |dispatcher| is destroyed. - EXPECT_TRUE(dispatcher->HasOneRef()); - dispatcher = nullptr; - } - - // Wait. - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_EQ(123u, context); - hss = HandleSignalsState(); - mp1->RemoveAwakable(1, &waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - // Read from MP 1, port 1. - char read_buffer[100] = {0}; - uint32_t read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); - DispatcherVector read_dispatchers; - uint32_t read_num_dispatchers = 10; // Maximum to get. - EXPECT_EQ( - MOJO_RESULT_OK, - mp1->ReadMessage(1, UserPointer<void>(read_buffer), - MakeUserPointer(&read_buffer_size), &read_dispatchers, - &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kWorld), static_cast<size_t>(read_buffer_size)); - EXPECT_STREQ(kWorld, read_buffer); - EXPECT_EQ(1u, read_dispatchers.size()); - EXPECT_EQ(1u, read_num_dispatchers); - ASSERT_TRUE(read_dispatchers[0]); - EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); - - EXPECT_EQ(Dispatcher::Type::PLATFORM_HANDLE, read_dispatchers[0]->GetType()); - dispatcher = - static_cast<PlatformHandleDispatcher*>(read_dispatchers[0].get()); - - embedder::ScopedPlatformHandle h = dispatcher->PassPlatformHandle(); - EXPECT_TRUE(h.is_valid()); - - fp = mojo::test::FILEFromPlatformHandle(std::move(h), "rb"); - EXPECT_FALSE(h.is_valid()); - EXPECT_TRUE(fp); - - rewind(fp.get()); - memset(read_buffer, 0, sizeof(read_buffer)); - EXPECT_EQ(sizeof(kHello), - fread(read_buffer, 1, sizeof(read_buffer), fp.get())); - EXPECT_STREQ(kHello, read_buffer); - - // Close everything that belongs to us. - mp0->Close(0); - mp1->Close(1); - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); -} - -// Test racing closes (on each end). -// Note: A flaky failure would almost certainly indicate a problem in the code -// itself (not in the test). Also, any logged warnings/errors would also -// probably be indicative of bugs. -TEST_F(RemoteMessagePipeTest, RacingClosesStress) { - MojoDeadline delay = test::DeadlineFromMilliseconds(5); - - for (unsigned i = 0; i < 256; i++) { - DVLOG(2) << "---------------------------------------- " << i; - scoped_refptr<ChannelEndpoint> ep0; - scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0)); - BootstrapChannelEndpointNoWait(0, ep0); - - scoped_refptr<ChannelEndpoint> ep1; - scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1)); - BootstrapChannelEndpointNoWait(1, ep1); - - if (i & 1u) { - io_thread()->task_runner()->PostTask(FROM_HERE, - base::Bind(&test::Sleep, delay)); - } - if (i & 2u) - test::Sleep(delay); - - mp0->Close(0); - - if (i & 4u) { - io_thread()->task_runner()->PostTask(FROM_HERE, - base::Bind(&test::Sleep, delay)); - } - if (i & 8u) - test::Sleep(delay); - - mp1->Close(1); - - RestoreInitialState(); - } -} - -// Tests passing an end of a message pipe over a remote message pipe, and then -// passing that end back. -// TODO(vtl): Also test passing a message pipe across two remote message pipes. -TEST_F(RemoteMessagePipeTest, PassMessagePipeHandleAcrossAndBack) { - static const char kHello[] = "hello"; - static const char kWorld[] = "world"; - Waiter waiter; - HandleSignalsState hss; - uintptr_t context = 0; - - scoped_refptr<ChannelEndpoint> ep0; - scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0)); - scoped_refptr<ChannelEndpoint> ep1; - scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1)); - BootstrapChannelEndpoints(ep0, ep1); - - // We'll try to pass this dispatcher. - scoped_refptr<MessagePipeDispatcher> dispatcher = - MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - scoped_refptr<MessagePipe> local_mp(MessagePipe::CreateLocalLocal()); - dispatcher->Init(local_mp, 0); - - // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do - // it later, it might already be readable.) - waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); - - // Write to MP 0, port 0. - { - DispatcherTransport transport( - test::DispatcherTryStartTransport(dispatcher.get())); - EXPECT_TRUE(transport.is_valid()); - - std::vector<DispatcherTransport> transports; - transports.push_back(transport); - EXPECT_EQ( - MOJO_RESULT_OK, - mp0->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello), - &transports, MOJO_WRITE_MESSAGE_FLAG_NONE)); - transport.End(); - - // |dispatcher| should have been closed. This is |DCHECK()|ed when the - // |dispatcher| is destroyed. - EXPECT_TRUE(dispatcher->HasOneRef()); - dispatcher = nullptr; - } - - // Wait. - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_EQ(123u, context); - hss = HandleSignalsState(); - mp1->RemoveAwakable(1, &waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - // Read from MP 1, port 1. - char read_buffer[100] = {0}; - uint32_t read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); - DispatcherVector read_dispatchers; - uint32_t read_num_dispatchers = 10; // Maximum to get. - EXPECT_EQ( - MOJO_RESULT_OK, - mp1->ReadMessage(1, UserPointer<void>(read_buffer), - MakeUserPointer(&read_buffer_size), &read_dispatchers, - &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size)); - EXPECT_STREQ(kHello, read_buffer); - EXPECT_EQ(1u, read_dispatchers.size()); - EXPECT_EQ(1u, read_num_dispatchers); - ASSERT_TRUE(read_dispatchers[0]); - EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); - - EXPECT_EQ(Dispatcher::Type::MESSAGE_PIPE, read_dispatchers[0]->GetType()); - dispatcher = static_cast<MessagePipeDispatcher*>(read_dispatchers[0].get()); - read_dispatchers.clear(); - - // Now pass it back. - - // Prepare to wait on MP 0, port 0. (Add the waiter now. Otherwise, if we do - // it later, it might already be readable.) - waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - mp0->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 456, nullptr)); - - // Write to MP 1, port 1. - { - DispatcherTransport transport( - test::DispatcherTryStartTransport(dispatcher.get())); - EXPECT_TRUE(transport.is_valid()); - - std::vector<DispatcherTransport> transports; - transports.push_back(transport); - EXPECT_EQ( - MOJO_RESULT_OK, - mp1->WriteMessage(1, UserPointer<const void>(kWorld), sizeof(kWorld), - &transports, MOJO_WRITE_MESSAGE_FLAG_NONE)); - transport.End(); - - // |dispatcher| should have been closed. This is |DCHECK()|ed when the - // |dispatcher| is destroyed. - EXPECT_TRUE(dispatcher->HasOneRef()); - dispatcher = nullptr; - } - - // Wait. - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_EQ(456u, context); - hss = HandleSignalsState(); - mp0->RemoveAwakable(0, &waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - // Read from MP 0, port 0. - read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); - read_num_dispatchers = 10; // Maximum to get. - EXPECT_EQ( - MOJO_RESULT_OK, - mp0->ReadMessage(0, UserPointer<void>(read_buffer), - MakeUserPointer(&read_buffer_size), &read_dispatchers, - &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kWorld), static_cast<size_t>(read_buffer_size)); - EXPECT_STREQ(kWorld, read_buffer); - EXPECT_EQ(1u, read_dispatchers.size()); - EXPECT_EQ(1u, read_num_dispatchers); - ASSERT_TRUE(read_dispatchers[0]); - EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); - - EXPECT_EQ(Dispatcher::Type::MESSAGE_PIPE, read_dispatchers[0]->GetType()); - dispatcher = static_cast<MessagePipeDispatcher*>(read_dispatchers[0].get()); - read_dispatchers.clear(); - - // Add the waiter now, before it becomes readable to avoid a race. - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - dispatcher->AddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, - nullptr)); - - // Write to "local_mp", port 1. - EXPECT_EQ( - MOJO_RESULT_OK, - local_mp->WriteMessage(1, UserPointer<const void>(kHello), sizeof(kHello), - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Wait for the dispatcher to become readable. - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_EQ(789u, context); - hss = HandleSignalsState(); - dispatcher->RemoveAwakable(&waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - // Read from the dispatcher. - memset(read_buffer, 0, sizeof(read_buffer)); - read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - dispatcher->ReadMessage(UserPointer<void>(read_buffer), - MakeUserPointer(&read_buffer_size), 0, - nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size)); - EXPECT_STREQ(kHello, read_buffer); - - // Prepare to wait on "local_mp", port 1. - waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - local_mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, - nullptr)); - - // Write to the dispatcher. - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->WriteMessage( - UserPointer<const void>(kHello), sizeof(kHello), - nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Wait. - EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_EQ(789u, context); - hss = HandleSignalsState(); - local_mp->RemoveAwakable(1, &waiter, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - - // Read from "local_mp", port 1. - memset(read_buffer, 0, sizeof(read_buffer)); - read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - local_mp->ReadMessage(1, UserPointer<void>(read_buffer), - MakeUserPointer(&read_buffer_size), nullptr, - nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size)); - EXPECT_STREQ(kHello, read_buffer); - - // TODO(vtl): Also test the cases where messages are written and read (at - // various points) on the message pipe being passed around. - - // Close everything that belongs to us. - mp0->Close(0); - mp1->Close(1); - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); - // Note that |local_mp|'s port 0 belong to |dispatcher|, which was closed. - local_mp->Close(1); -} - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/remote_producer_data_pipe_impl.cc b/third_party/mojo/src/mojo/edk/system/remote_producer_data_pipe_impl.cc deleted file mode 100644 index e47d6c1..0000000 --- a/third_party/mojo/src/mojo/edk/system/remote_producer_data_pipe_impl.cc +++ /dev/null @@ -1,466 +0,0 @@ -// Copyright 2015 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 "third_party/mojo/src/mojo/edk/system/remote_producer_data_pipe_impl.h" - -#include <string.h> -#include <algorithm> -#include <utility> - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "third_party/mojo/src/mojo/edk/system/channel.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/configuration.h" -#include "third_party/mojo/src/mojo/edk/system/data_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit_queue.h" -#include "third_party/mojo/src/mojo/edk/system/remote_consumer_data_pipe_impl.h" -#include "third_party/mojo/src/mojo/edk/system/remote_data_pipe_ack.h" - -namespace mojo { -namespace system { - -namespace { - -bool ValidateIncomingMessage(size_t element_num_bytes, - size_t capacity_num_bytes, - size_t current_num_bytes, - const MessageInTransit* message) { - // We should only receive endpoint client messages. - DCHECK_EQ(message->type(), MessageInTransit::Type::ENDPOINT_CLIENT); - - // But we should check the subtype; only take data messages. - if (message->subtype() != MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA) { - LOG(WARNING) << "Received message of unexpected subtype: " - << message->subtype(); - return false; - } - - const size_t num_bytes = message->num_bytes(); - const size_t max_num_bytes = capacity_num_bytes - current_num_bytes; - if (num_bytes > max_num_bytes) { - LOG(WARNING) << "Received too much data: " << num_bytes - << " bytes (maximum: " << max_num_bytes << " bytes)"; - return false; - } - - if (num_bytes % element_num_bytes != 0) { - LOG(WARNING) << "Received data not a multiple of element size: " - << num_bytes << " bytes (element size: " << element_num_bytes - << " bytes)"; - return false; - } - - return true; -} - -} // namespace - -RemoteProducerDataPipeImpl::RemoteProducerDataPipeImpl( - ChannelEndpoint* channel_endpoint) - : channel_endpoint_(channel_endpoint), - start_index_(0), - current_num_bytes_(0) { - // Note: |buffer_| is lazily allocated. -} - -RemoteProducerDataPipeImpl::RemoteProducerDataPipeImpl( - ChannelEndpoint* channel_endpoint, - scoped_ptr<char, base::AlignedFreeDeleter> buffer, - size_t start_index, - size_t current_num_bytes) - : channel_endpoint_(channel_endpoint), - buffer_(std::move(buffer)), - start_index_(start_index), - current_num_bytes_(current_num_bytes) { - DCHECK(buffer_ || !current_num_bytes); -} - -// static -bool RemoteProducerDataPipeImpl::ProcessMessagesFromIncomingEndpoint( - const MojoCreateDataPipeOptions& validated_options, - MessageInTransitQueue* messages, - scoped_ptr<char, base::AlignedFreeDeleter>* buffer, - size_t* buffer_num_bytes) { - DCHECK(!*buffer); // Not wrong, but unlikely. - - const size_t element_num_bytes = validated_options.element_num_bytes; - const size_t capacity_num_bytes = validated_options.capacity_num_bytes; - - scoped_ptr<char, base::AlignedFreeDeleter> new_buffer(static_cast<char*>( - base::AlignedAlloc(capacity_num_bytes, - GetConfiguration().data_pipe_buffer_alignment_bytes))); - - size_t current_num_bytes = 0; - if (messages) { - while (!messages->IsEmpty()) { - scoped_ptr<MessageInTransit> message(messages->GetMessage()); - if (!ValidateIncomingMessage(element_num_bytes, capacity_num_bytes, - current_num_bytes, message.get())) { - messages->Clear(); - return false; - } - - memcpy(new_buffer.get() + current_num_bytes, message->bytes(), - message->num_bytes()); - current_num_bytes += message->num_bytes(); - } - } - - *buffer = std::move(new_buffer); - *buffer_num_bytes = current_num_bytes; - return true; -} - -RemoteProducerDataPipeImpl::~RemoteProducerDataPipeImpl() { -} - -void RemoteProducerDataPipeImpl::ProducerClose() { - NOTREACHED(); -} - -MojoResult RemoteProducerDataPipeImpl::ProducerWriteData( - UserPointer<const void> /*elements*/, - UserPointer<uint32_t> /*num_bytes*/, - uint32_t /*max_num_bytes_to_write*/, - uint32_t /*min_num_bytes_to_write*/) { - NOTREACHED(); - return MOJO_RESULT_INTERNAL; -} - -MojoResult RemoteProducerDataPipeImpl::ProducerBeginWriteData( - UserPointer<void*> /*buffer*/, - UserPointer<uint32_t> /*buffer_num_bytes*/) { - NOTREACHED(); - return MOJO_RESULT_INTERNAL; -} - -MojoResult RemoteProducerDataPipeImpl::ProducerEndWriteData( - uint32_t /*num_bytes_written*/) { - NOTREACHED(); - return MOJO_RESULT_INTERNAL; -} - -HandleSignalsState RemoteProducerDataPipeImpl::ProducerGetHandleSignalsState() - const { - return HandleSignalsState(); -} - -void RemoteProducerDataPipeImpl::ProducerStartSerialize( - Channel* /*channel*/, - size_t* /*max_size*/, - size_t* /*max_platform_handles*/) { - NOTREACHED(); -} - -bool RemoteProducerDataPipeImpl::ProducerEndSerialize( - Channel* /*channel*/, - void* /*destination*/, - size_t* /*actual_size*/, - embedder::PlatformHandleVector* /*platform_handles*/) { - NOTREACHED(); - return false; -} - -void RemoteProducerDataPipeImpl::ConsumerClose() { - if (producer_open()) - Disconnect(); - current_num_bytes_ = 0; -} - -MojoResult RemoteProducerDataPipeImpl::ConsumerReadData( - UserPointer<void> elements, - UserPointer<uint32_t> num_bytes, - uint32_t max_num_bytes_to_read, - uint32_t min_num_bytes_to_read, - bool peek) { - DCHECK_EQ(max_num_bytes_to_read % element_num_bytes(), 0u); - DCHECK_EQ(min_num_bytes_to_read % element_num_bytes(), 0u); - DCHECK_GT(max_num_bytes_to_read, 0u); - - if (min_num_bytes_to_read > current_num_bytes_) { - // Don't return "should wait" since you can't wait for a specified amount of - // data. - return producer_open() ? MOJO_RESULT_OUT_OF_RANGE - : MOJO_RESULT_FAILED_PRECONDITION; - } - - size_t num_bytes_to_read = - std::min(static_cast<size_t>(max_num_bytes_to_read), current_num_bytes_); - if (num_bytes_to_read == 0) { - return producer_open() ? MOJO_RESULT_SHOULD_WAIT - : MOJO_RESULT_FAILED_PRECONDITION; - } - - // The amount we can read in our first |memcpy()|. - size_t num_bytes_to_read_first = - std::min(num_bytes_to_read, GetMaxNumBytesToRead()); - elements.PutArray(buffer_.get() + start_index_, num_bytes_to_read_first); - - if (num_bytes_to_read_first < num_bytes_to_read) { - // The "second read index" is zero. - elements.At(num_bytes_to_read_first) - .PutArray(buffer_.get(), num_bytes_to_read - num_bytes_to_read_first); - } - - if (!peek) - MarkDataAsConsumed(num_bytes_to_read); - num_bytes.Put(static_cast<uint32_t>(num_bytes_to_read)); - return MOJO_RESULT_OK; -} - -MojoResult RemoteProducerDataPipeImpl::ConsumerDiscardData( - UserPointer<uint32_t> num_bytes, - uint32_t max_num_bytes_to_discard, - uint32_t min_num_bytes_to_discard) { - DCHECK_EQ(max_num_bytes_to_discard % element_num_bytes(), 0u); - DCHECK_EQ(min_num_bytes_to_discard % element_num_bytes(), 0u); - DCHECK_GT(max_num_bytes_to_discard, 0u); - - if (min_num_bytes_to_discard > current_num_bytes_) { - // Don't return "should wait" since you can't wait for a specified amount of - // data. - return producer_open() ? MOJO_RESULT_OUT_OF_RANGE - : MOJO_RESULT_FAILED_PRECONDITION; - } - - // Be consistent with other operations; error if no data available. - if (current_num_bytes_ == 0) { - return producer_open() ? MOJO_RESULT_SHOULD_WAIT - : MOJO_RESULT_FAILED_PRECONDITION; - } - - size_t num_bytes_to_discard = std::min( - static_cast<size_t>(max_num_bytes_to_discard), current_num_bytes_); - MarkDataAsConsumed(num_bytes_to_discard); - num_bytes.Put(static_cast<uint32_t>(num_bytes_to_discard)); - return MOJO_RESULT_OK; -} - -MojoResult RemoteProducerDataPipeImpl::ConsumerQueryData( - UserPointer<uint32_t> num_bytes) { - // Note: This cast is safe, since the capacity fits into a |uint32_t|. - num_bytes.Put(static_cast<uint32_t>(current_num_bytes_)); - return MOJO_RESULT_OK; -} - -MojoResult RemoteProducerDataPipeImpl::ConsumerBeginReadData( - UserPointer<const void*> buffer, - UserPointer<uint32_t> buffer_num_bytes) { - size_t max_num_bytes_to_read = GetMaxNumBytesToRead(); - // Don't go into a two-phase read if there's no data. - if (max_num_bytes_to_read == 0) { - return producer_open() ? MOJO_RESULT_SHOULD_WAIT - : MOJO_RESULT_FAILED_PRECONDITION; - } - - buffer.Put(buffer_.get() + start_index_); - buffer_num_bytes.Put(static_cast<uint32_t>(max_num_bytes_to_read)); - set_consumer_two_phase_max_num_bytes_read( - static_cast<uint32_t>(max_num_bytes_to_read)); - return MOJO_RESULT_OK; -} - -MojoResult RemoteProducerDataPipeImpl::ConsumerEndReadData( - uint32_t num_bytes_read) { - DCHECK_LE(num_bytes_read, consumer_two_phase_max_num_bytes_read()); - DCHECK_EQ(num_bytes_read % element_num_bytes(), 0u); - DCHECK_LE(start_index_ + num_bytes_read, capacity_num_bytes()); - MarkDataAsConsumed(num_bytes_read); - set_consumer_two_phase_max_num_bytes_read(0); - return MOJO_RESULT_OK; -} - -HandleSignalsState RemoteProducerDataPipeImpl::ConsumerGetHandleSignalsState() - const { - HandleSignalsState rv; - if (current_num_bytes_ > 0) { - if (!consumer_in_two_phase_read()) - rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_READABLE; - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_READABLE; - } else if (producer_open()) { - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_READABLE; - } - if (!producer_open()) - rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED; - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED; - return rv; -} - -void RemoteProducerDataPipeImpl::ConsumerStartSerialize( - Channel* channel, - size_t* max_size, - size_t* max_platform_handles) { - *max_size = sizeof(SerializedDataPipeConsumerDispatcher) + - channel->GetSerializedEndpointSize(); - *max_platform_handles = 0; -} - -bool RemoteProducerDataPipeImpl::ConsumerEndSerialize( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) { - SerializedDataPipeConsumerDispatcher* s = - static_cast<SerializedDataPipeConsumerDispatcher*>(destination); - s->validated_options = validated_options(); - void* destination_for_endpoint = static_cast<char*>(destination) + - sizeof(SerializedDataPipeConsumerDispatcher); - - MessageInTransitQueue message_queue; - ConvertDataToMessages(buffer_.get(), &start_index_, ¤t_num_bytes_, - &message_queue); - - if (!producer_open()) { - // Case 1: The producer is closed. - channel->SerializeEndpointWithClosedPeer(destination_for_endpoint, - &message_queue); - *actual_size = sizeof(SerializedDataPipeConsumerDispatcher) + - channel->GetSerializedEndpointSize(); - return true; - } - - // Case 2: The producer isn't closed. We pass |channel_endpoint| back to the - // |Channel|. There's no reason for us to continue to exist afterwards. - - // Note: We don't use |port|. - scoped_refptr<ChannelEndpoint> channel_endpoint; - channel_endpoint.swap(channel_endpoint_); - channel->SerializeEndpointWithRemotePeer(destination_for_endpoint, - &message_queue, channel_endpoint); - owner()->SetProducerClosedNoLock(); - - *actual_size = sizeof(SerializedDataPipeConsumerDispatcher) + - channel->GetSerializedEndpointSize(); - return true; -} - -bool RemoteProducerDataPipeImpl::OnReadMessage(unsigned /*port*/, - MessageInTransit* message) { - if (!producer_open()) { - // This will happen only on the rare occasion that the call to - // |OnReadMessage()| is racing with us calling - // |ChannelEndpoint::ReplaceClient()|, in which case we reject the message, - // and the |ChannelEndpoint| can retry (calling the new client's - // |OnReadMessage()|). - DCHECK(!channel_endpoint_); - return false; - } - - // Otherwise, we take ownership of the message. (This means that we should - // always return true below.) - scoped_ptr<MessageInTransit> msg(message); - - if (!ValidateIncomingMessage(element_num_bytes(), capacity_num_bytes(), - current_num_bytes_, msg.get())) { - Disconnect(); - return true; - } - - size_t num_bytes = msg->num_bytes(); - // The amount we can write in our first copy. - size_t num_bytes_to_copy_first = std::min(num_bytes, GetMaxNumBytesToWrite()); - // Do the first (and possibly only) copy. - size_t first_write_index = - (start_index_ + current_num_bytes_) % capacity_num_bytes(); - EnsureBuffer(); - memcpy(buffer_.get() + first_write_index, msg->bytes(), - num_bytes_to_copy_first); - - if (num_bytes_to_copy_first < num_bytes) { - // The "second write index" is zero. - memcpy(buffer_.get(), - static_cast<const char*>(msg->bytes()) + num_bytes_to_copy_first, - num_bytes - num_bytes_to_copy_first); - } - - current_num_bytes_ += num_bytes; - DCHECK_LE(current_num_bytes_, capacity_num_bytes()); - return true; -} - -void RemoteProducerDataPipeImpl::OnDetachFromChannel(unsigned /*port*/) { - if (!producer_open()) { - DCHECK(!channel_endpoint_); - return; - } - - Disconnect(); -} - -void RemoteProducerDataPipeImpl::EnsureBuffer() { - DCHECK(producer_open()); - if (buffer_) - return; - buffer_.reset(static_cast<char*>( - base::AlignedAlloc(capacity_num_bytes(), - GetConfiguration().data_pipe_buffer_alignment_bytes))); -} - -void RemoteProducerDataPipeImpl::DestroyBuffer() { -#ifndef NDEBUG - // Scribble on the buffer to help detect use-after-frees. (This also helps the - // unit test detect certain bugs without needing ASAN or similar.) - if (buffer_) - memset(buffer_.get(), 0xcd, capacity_num_bytes()); -#endif - buffer_.reset(); -} - -size_t RemoteProducerDataPipeImpl::GetMaxNumBytesToWrite() { - size_t next_index = start_index_ + current_num_bytes_; - if (next_index >= capacity_num_bytes()) { - next_index %= capacity_num_bytes(); - DCHECK_GE(start_index_, next_index); - DCHECK_EQ(start_index_ - next_index, - capacity_num_bytes() - current_num_bytes_); - return start_index_ - next_index; - } - return capacity_num_bytes() - next_index; -} - -size_t RemoteProducerDataPipeImpl::GetMaxNumBytesToRead() { - if (start_index_ + current_num_bytes_ > capacity_num_bytes()) - return capacity_num_bytes() - start_index_; - return current_num_bytes_; -} - -void RemoteProducerDataPipeImpl::MarkDataAsConsumed(size_t num_bytes) { - DCHECK_LE(num_bytes, current_num_bytes_); - start_index_ += num_bytes; - start_index_ %= capacity_num_bytes(); - current_num_bytes_ -= num_bytes; - - if (!producer_open()) { - DCHECK(!channel_endpoint_); - return; - } - - RemoteDataPipeAck ack_data = {}; - ack_data.num_bytes_consumed = static_cast<uint32_t>(num_bytes); - scoped_ptr<MessageInTransit> message(new MessageInTransit( - MessageInTransit::Type::ENDPOINT_CLIENT, - MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA_PIPE_ACK, - static_cast<uint32_t>(sizeof(ack_data)), &ack_data)); - if (!channel_endpoint_->EnqueueMessage(std::move(message))) - Disconnect(); -} - -void RemoteProducerDataPipeImpl::Disconnect() { - DCHECK(producer_open()); - DCHECK(channel_endpoint_); - owner()->SetProducerClosedNoLock(); - channel_endpoint_->DetachFromClient(); - channel_endpoint_ = nullptr; - // If the consumer is still open and we still have data, we have to keep the - // buffer around. Currently, we won't free it even if it empties later. (We - // could do this -- requiring a check on every read -- but that seems to be - // optimizing for the uncommon case.) - if (!consumer_open() || !current_num_bytes_) - DestroyBuffer(); -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/remote_producer_data_pipe_impl.h b/third_party/mojo/src/mojo/edk/system/remote_producer_data_pipe_impl.h deleted file mode 100644 index de90cb2..0000000 --- a/third_party/mojo/src/mojo/edk/system/remote_producer_data_pipe_impl.h +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2015 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_REMOTE_PRODUCER_DATA_PIPE_IMPL_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_REMOTE_PRODUCER_DATA_PIPE_IMPL_H_ - -#include "base/memory/aligned_memory.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/data_pipe_impl.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -class MessageInTransitQueue; - -// |RemoteProducerDataPipeImpl| is a subclass that "implements" |DataPipe| for -// data pipes whose producer is remote and whose consumer is local. See -// |DataPipeImpl| for more details. -class MOJO_SYSTEM_IMPL_EXPORT RemoteProducerDataPipeImpl final - : public DataPipeImpl { - public: - explicit RemoteProducerDataPipeImpl(ChannelEndpoint* channel_endpoint); - RemoteProducerDataPipeImpl(ChannelEndpoint* channel_endpoint, - scoped_ptr<char, base::AlignedFreeDeleter> buffer, - size_t start_index, - size_t current_num_bytes); - ~RemoteProducerDataPipeImpl() override; - - // Processes messages that were received and queued by an |IncomingEndpoint|. - // On success, returns true and sets |*buffer| (to a buffer of size - // |validated_options.capacity_num_bytes|) and |*buffer_num_bytes|. On - // failure, returns false. Always clears |*messages|. - static bool ProcessMessagesFromIncomingEndpoint( - const MojoCreateDataPipeOptions& validated_options, - MessageInTransitQueue* messages, - scoped_ptr<char, base::AlignedFreeDeleter>* buffer, - size_t* buffer_num_bytes); - - private: - // |DataPipeImpl| implementation: - // Note: None of the |Producer...()| methods should be called, except - // |ProducerGetHandleSignalsState()|. - void ProducerClose() override; - MojoResult ProducerWriteData(UserPointer<const void> elements, - UserPointer<uint32_t> num_bytes, - uint32_t max_num_bytes_to_write, - uint32_t min_num_bytes_to_write) override; - MojoResult ProducerBeginWriteData( - UserPointer<void*> buffer, - UserPointer<uint32_t> buffer_num_bytes) override; - MojoResult ProducerEndWriteData(uint32_t num_bytes_written) override; - HandleSignalsState ProducerGetHandleSignalsState() const override; - void ProducerStartSerialize(Channel* channel, - size_t* max_size, - size_t* max_platform_handles) override; - bool ProducerEndSerialize( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) override; - void ConsumerClose() override; - MojoResult ConsumerReadData(UserPointer<void> elements, - UserPointer<uint32_t> num_bytes, - uint32_t max_num_bytes_to_read, - uint32_t min_num_bytes_to_read, - bool peek) override; - MojoResult ConsumerDiscardData(UserPointer<uint32_t> num_bytes, - uint32_t max_num_bytes_to_discard, - uint32_t min_num_bytes_to_discard) override; - MojoResult ConsumerQueryData(UserPointer<uint32_t> num_bytes) override; - MojoResult ConsumerBeginReadData( - UserPointer<const void*> buffer, - UserPointer<uint32_t> buffer_num_bytes) override; - MojoResult ConsumerEndReadData(uint32_t num_bytes_read) override; - HandleSignalsState ConsumerGetHandleSignalsState() const override; - void ConsumerStartSerialize(Channel* channel, - size_t* max_size, - size_t* max_platform_handles) override; - bool ConsumerEndSerialize( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) override; - bool OnReadMessage(unsigned port, MessageInTransit* message) override; - void OnDetachFromChannel(unsigned port) override; - - void EnsureBuffer(); - void DestroyBuffer(); - - // Get the maximum (single) write/read size right now (in number of elements); - // result fits in a |uint32_t|. - size_t GetMaxNumBytesToWrite(); - size_t GetMaxNumBytesToRead(); - - // Marks the given number of bytes as consumed/discarded. This will send a - // message to the remote producer. |num_bytes| must be no greater than - // |current_num_bytes_|. - void MarkDataAsConsumed(size_t num_bytes); - - void Disconnect(); - - // Should be valid if and only if |producer_open()| returns true. - scoped_refptr<ChannelEndpoint> channel_endpoint_; - - scoped_ptr<char, base::AlignedFreeDeleter> buffer_; - // Circular buffer. - size_t start_index_; - size_t current_num_bytes_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(RemoteProducerDataPipeImpl); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_REMOTE_PRODUCER_DATA_PIPE_IMPL_H_ diff --git a/third_party/mojo/src/mojo/edk/system/run_all_unittests.cc b/third_party/mojo/src/mojo/edk/system/run_all_unittests.cc deleted file mode 100644 index cd61337..0000000 --- a/third_party/mojo/src/mojo/edk/system/run_all_unittests.cc +++ /dev/null @@ -1,24 +0,0 @@ -// 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 "base/bind.h" -#include "base/test/launcher/unit_test_launcher.h" -#include "base/test/test_suite.h" -#include "testing/gtest/include/gtest/gtest.h" - -int main(int argc, char** argv) { -// Silence death test thread warnings on Linux. We can afford to run our death -// tests a little more slowly (< 10 ms per death test on a Z620). -// On android, we need to run in the default mode, as the threadsafe mode -// relies on execve which is not available. -#if !defined(OS_ANDROID) - testing::GTEST_FLAG(death_test_style) = "threadsafe"; -#endif - - base::TestSuite test_suite(argc, argv); - - return base::LaunchUnitTests( - argc, argv, - base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite))); -} diff --git a/third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher.cc b/third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher.cc deleted file mode 100644 index d31efe4..0000000 --- a/third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher.cc +++ /dev/null @@ -1,280 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher.h" - -#include <algorithm> -#include <limits> -#include <utility> - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/public/c/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_support.h" -#include "third_party/mojo/src/mojo/edk/system/channel.h" -#include "third_party/mojo/src/mojo/edk/system/configuration.h" -#include "third_party/mojo/src/mojo/edk/system/memory.h" -#include "third_party/mojo/src/mojo/edk/system/options_validation.h" - -namespace mojo { -namespace system { - -namespace { - -struct SerializedSharedBufferDispatcher { - uint32_t num_bytes; - uint32_t platform_handle_index; -}; - -} // namespace - -// static -const MojoCreateSharedBufferOptions - SharedBufferDispatcher::kDefaultCreateOptions = { - static_cast<uint32_t>(sizeof(MojoCreateSharedBufferOptions)), - MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE}; - -// static -MojoResult SharedBufferDispatcher::ValidateCreateOptions( - UserPointer<const MojoCreateSharedBufferOptions> in_options, - MojoCreateSharedBufferOptions* out_options) { - const MojoCreateSharedBufferOptionsFlags kKnownFlags = - MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE; - - *out_options = kDefaultCreateOptions; - if (in_options.IsNull()) - return MOJO_RESULT_OK; - - UserOptionsReader<MojoCreateSharedBufferOptions> reader(in_options); - if (!reader.is_valid()) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateSharedBufferOptions, flags, reader)) - return MOJO_RESULT_OK; - if ((reader.options().flags & ~kKnownFlags)) - return MOJO_RESULT_UNIMPLEMENTED; - out_options->flags = reader.options().flags; - - // Checks for fields beyond |flags|: - - // (Nothing here yet.) - - return MOJO_RESULT_OK; -} - -// static -MojoResult SharedBufferDispatcher::Create( - embedder::PlatformSupport* platform_support, - const MojoCreateSharedBufferOptions& /*validated_options*/, - uint64_t num_bytes, - scoped_refptr<SharedBufferDispatcher>* result) { - if (!num_bytes) - return MOJO_RESULT_INVALID_ARGUMENT; - if (num_bytes > GetConfiguration().max_shared_memory_num_bytes) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - - scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer( - platform_support->CreateSharedBuffer(static_cast<size_t>(num_bytes))); - if (!shared_buffer) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - - *result = CreateInternal(std::move(shared_buffer)); - return MOJO_RESULT_OK; -} - -Dispatcher::Type SharedBufferDispatcher::GetType() const { - return Type::SHARED_BUFFER; -} - -// static -scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize( - Channel* channel, - const void* source, - size_t size, - embedder::PlatformHandleVector* platform_handles) { - DCHECK(channel); - - if (size != sizeof(SerializedSharedBufferDispatcher)) { - LOG(ERROR) << "Invalid serialized shared buffer dispatcher (bad size)"; - return nullptr; - } - - const SerializedSharedBufferDispatcher* serialization = - static_cast<const SerializedSharedBufferDispatcher*>(source); - size_t num_bytes = serialization->num_bytes; - size_t platform_handle_index = serialization->platform_handle_index; - - if (!num_bytes) { - LOG(ERROR) - << "Invalid serialized shared buffer dispatcher (invalid num_bytes)"; - return nullptr; - } - - if (!platform_handles || platform_handle_index >= platform_handles->size()) { - LOG(ERROR) - << "Invalid serialized shared buffer dispatcher (missing handles)"; - return nullptr; - } - - // Starts off invalid, which is what we want. - embedder::PlatformHandle platform_handle; - // We take ownership of the handle, so we have to invalidate the one in - // |platform_handles|. - std::swap(platform_handle, (*platform_handles)[platform_handle_index]); - - // Wrapping |platform_handle| in a |ScopedPlatformHandle| means that it'll be - // closed even if creation fails. - scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer( - channel->platform_support()->CreateSharedBufferFromHandle( - num_bytes, embedder::ScopedPlatformHandle(platform_handle))); - if (!shared_buffer) { - LOG(ERROR) - << "Invalid serialized shared buffer dispatcher (invalid num_bytes?)"; - return nullptr; - } - - return CreateInternal(std::move(shared_buffer)); -} - -SharedBufferDispatcher::SharedBufferDispatcher( - scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer) - : shared_buffer_(shared_buffer) { - DCHECK(shared_buffer_); -} - -SharedBufferDispatcher::~SharedBufferDispatcher() { -} - -// static -MojoResult SharedBufferDispatcher::ValidateDuplicateOptions( - UserPointer<const MojoDuplicateBufferHandleOptions> in_options, - MojoDuplicateBufferHandleOptions* out_options) { - const MojoDuplicateBufferHandleOptionsFlags kKnownFlags = - MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE; - static const MojoDuplicateBufferHandleOptions kDefaultOptions = { - static_cast<uint32_t>(sizeof(MojoDuplicateBufferHandleOptions)), - MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE}; - - *out_options = kDefaultOptions; - if (in_options.IsNull()) - return MOJO_RESULT_OK; - - UserOptionsReader<MojoDuplicateBufferHandleOptions> reader(in_options); - if (!reader.is_valid()) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (!OPTIONS_STRUCT_HAS_MEMBER(MojoDuplicateBufferHandleOptions, flags, - reader)) - return MOJO_RESULT_OK; - if ((reader.options().flags & ~kKnownFlags)) - return MOJO_RESULT_UNIMPLEMENTED; - out_options->flags = reader.options().flags; - - // Checks for fields beyond |flags|: - - // (Nothing here yet.) - - return MOJO_RESULT_OK; -} - -void SharedBufferDispatcher::CloseImplNoLock() { - mutex().AssertHeld(); - DCHECK(shared_buffer_); - shared_buffer_ = nullptr; -} - -scoped_refptr<Dispatcher> -SharedBufferDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() { - mutex().AssertHeld(); - DCHECK(shared_buffer_); - return CreateInternal(std::move(shared_buffer_)); -} - -MojoResult SharedBufferDispatcher::DuplicateBufferHandleImplNoLock( - UserPointer<const MojoDuplicateBufferHandleOptions> options, - scoped_refptr<Dispatcher>* new_dispatcher) { - mutex().AssertHeld(); - - MojoDuplicateBufferHandleOptions validated_options; - MojoResult result = ValidateDuplicateOptions(options, &validated_options); - if (result != MOJO_RESULT_OK) - return result; - - // Note: Since this is "duplicate", we keep our ref to |shared_buffer_|. - *new_dispatcher = CreateInternal(shared_buffer_); - return MOJO_RESULT_OK; -} - -MojoResult SharedBufferDispatcher::MapBufferImplNoLock( - uint64_t offset, - uint64_t num_bytes, - MojoMapBufferFlags flags, - scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping) { - mutex().AssertHeld(); - DCHECK(shared_buffer_); - - if (offset > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) - return MOJO_RESULT_INVALID_ARGUMENT; - if (num_bytes > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (!shared_buffer_->IsValidMap(static_cast<size_t>(offset), - static_cast<size_t>(num_bytes))) - return MOJO_RESULT_INVALID_ARGUMENT; - - DCHECK(mapping); - *mapping = shared_buffer_->MapNoCheck(static_cast<size_t>(offset), - static_cast<size_t>(num_bytes)); - if (!*mapping) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - - return MOJO_RESULT_OK; -} - -void SharedBufferDispatcher::StartSerializeImplNoLock( - Channel* /*channel*/, - size_t* max_size, - size_t* max_platform_handles) { - DCHECK(HasOneRef()); // Only one ref => no need to take the lock. - *max_size = sizeof(SerializedSharedBufferDispatcher); - *max_platform_handles = 1; -} - -bool SharedBufferDispatcher::EndSerializeAndCloseImplNoLock( - Channel* /*channel*/, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) { - DCHECK(HasOneRef()); // Only one ref => no need to take the lock. - DCHECK(shared_buffer_); - - SerializedSharedBufferDispatcher* serialization = - static_cast<SerializedSharedBufferDispatcher*>(destination); - // If there's only one reference to |shared_buffer_|, then it's ours (and no - // one else can make any more references to it), so we can just take its - // handle. - embedder::ScopedPlatformHandle platform_handle( - shared_buffer_->HasOneRef() ? shared_buffer_->PassPlatformHandle() - : shared_buffer_->DuplicatePlatformHandle()); - if (!platform_handle.is_valid()) { - shared_buffer_ = nullptr; - return false; - } - - DCHECK(shared_buffer_->GetNumBytes() < std::numeric_limits<uint32_t>::max()); - serialization->num_bytes = - static_cast<uint32_t>(shared_buffer_->GetNumBytes()); - DCHECK(platform_handles->size() < std::numeric_limits<uint32_t>::max()); - serialization->platform_handle_index = - static_cast<uint32_t>(platform_handles->size()); - platform_handles->push_back(platform_handle.release()); - *actual_size = sizeof(SerializedSharedBufferDispatcher); - - shared_buffer_ = nullptr; - - return true; -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher.h b/third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher.h deleted file mode 100644 index 49fda03..0000000 --- a/third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher.h +++ /dev/null @@ -1,117 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_SHARED_BUFFER_DISPATCHER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_SHARED_BUFFER_DISPATCHER_H_ - -#include <utility> - -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_shared_buffer.h" -#include "third_party/mojo/src/mojo/edk/system/memory.h" -#include "third_party/mojo/src/mojo/edk/system/simple_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { - -namespace embedder { -class PlatformSupport; -} - -namespace system { - -// TODO(vtl): We derive from SimpleDispatcher, even though we don't currently -// have anything that's waitable. I want to add a "transferrable" wait flag -// (which would entail overriding |GetHandleSignalsStateImplNoLock()|, etc.). -class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher final - : public SimpleDispatcher { - public: - // The default options to use for |MojoCreateSharedBuffer()|. (Real uses - // should obtain this via |ValidateCreateOptions()| with a null |in_options|; - // this is exposed directly for testing convenience.) - static const MojoCreateSharedBufferOptions kDefaultCreateOptions; - - // Validates and/or sets default options for |MojoCreateSharedBufferOptions|. - // If non-null, |in_options| must point to a struct of at least - // |in_options->struct_size| bytes. |out_options| must point to a (current) - // |MojoCreateSharedBufferOptions| and will be entirely overwritten on success - // (it may be partly overwritten on failure). - static MojoResult ValidateCreateOptions( - UserPointer<const MojoCreateSharedBufferOptions> in_options, - MojoCreateSharedBufferOptions* out_options); - - // Static factory method: |validated_options| must be validated (obviously). - // On failure, |*result| will be left as-is. - // TODO(vtl): This should probably be made to return a scoped_refptr and have - // a MojoResult out parameter instead. - static MojoResult Create( - embedder::PlatformSupport* platform_support, - const MojoCreateSharedBufferOptions& validated_options, - uint64_t num_bytes, - scoped_refptr<SharedBufferDispatcher>* result); - - // |Dispatcher| public methods: - Type GetType() const override; - - // The "opposite" of |SerializeAndClose()|. (Typically this is called by - // |Dispatcher::Deserialize()|.) - static scoped_refptr<SharedBufferDispatcher> Deserialize( - Channel* channel, - const void* source, - size_t size, - embedder::PlatformHandleVector* platform_handles); - - private: - static scoped_refptr<SharedBufferDispatcher> CreateInternal( - scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer) { - return make_scoped_refptr( - new SharedBufferDispatcher(std::move(shared_buffer))); - } - - explicit SharedBufferDispatcher( - scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer); - ~SharedBufferDispatcher() override; - - // Validates and/or sets default options for - // |MojoDuplicateBufferHandleOptions|. If non-null, |in_options| must point to - // a struct of at least |in_options->struct_size| bytes. |out_options| must - // point to a (current) |MojoDuplicateBufferHandleOptions| and will be - // entirely overwritten on success (it may be partly overwritten on failure). - static MojoResult ValidateDuplicateOptions( - UserPointer<const MojoDuplicateBufferHandleOptions> in_options, - MojoDuplicateBufferHandleOptions* out_options); - - // |Dispatcher| protected methods: - void CloseImplNoLock() override; - scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock() - override; - MojoResult DuplicateBufferHandleImplNoLock( - UserPointer<const MojoDuplicateBufferHandleOptions> options, - scoped_refptr<Dispatcher>* new_dispatcher) override; - MojoResult MapBufferImplNoLock( - uint64_t offset, - uint64_t num_bytes, - MojoMapBufferFlags flags, - scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping) override; - void StartSerializeImplNoLock(Channel* channel, - size_t* max_size, - size_t* max_platform_handles) override - MOJO_NOT_THREAD_SAFE; - bool EndSerializeAndCloseImplNoLock( - Channel* channel, - void* destination, - size_t* actual_size, - embedder::PlatformHandleVector* platform_handles) override - MOJO_NOT_THREAD_SAFE; - - scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer_ - MOJO_GUARDED_BY(mutex()); - - MOJO_DISALLOW_COPY_AND_ASSIGN(SharedBufferDispatcher); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_SHARED_BUFFER_DISPATCHER_H_ diff --git a/third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher_unittest.cc b/third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher_unittest.cc deleted file mode 100644 index b96393c..0000000 --- a/third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher_unittest.cc +++ /dev/null @@ -1,279 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher.h" - -#include <limits> - -#include "base/memory/ref_counted.h" -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_shared_buffer.h" -#include "third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h" -#include "third_party/mojo/src/mojo/edk/system/dispatcher.h" - -namespace mojo { -namespace system { -namespace { - -// NOTE(vtl): There's currently not much to test for in -// |SharedBufferDispatcher::ValidateCreateOptions()|, but the tests should be -// expanded if/when options are added, so I've kept the general form of the -// tests from data_pipe_unittest.cc. - -const uint32_t kSizeOfCreateOptions = sizeof(MojoCreateSharedBufferOptions); - -// Does a cursory sanity check of |validated_options|. Calls -// |ValidateCreateOptions()| on already-validated options. The validated options -// should be valid, and the revalidated copy should be the same. -void RevalidateCreateOptions( - const MojoCreateSharedBufferOptions& validated_options) { - EXPECT_EQ(kSizeOfCreateOptions, validated_options.struct_size); - // Nothing to check for flags. - - MojoCreateSharedBufferOptions revalidated_options = {}; - EXPECT_EQ(MOJO_RESULT_OK, - SharedBufferDispatcher::ValidateCreateOptions( - MakeUserPointer(&validated_options), &revalidated_options)); - EXPECT_EQ(validated_options.struct_size, revalidated_options.struct_size); - EXPECT_EQ(validated_options.flags, revalidated_options.flags); -} - -class SharedBufferDispatcherTest : public testing::Test { - public: - SharedBufferDispatcherTest() {} - ~SharedBufferDispatcherTest() override {} - - embedder::PlatformSupport* platform_support() { return &platform_support_; } - - private: - embedder::SimplePlatformSupport platform_support_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(SharedBufferDispatcherTest); -}; - -// Tests valid inputs to |ValidateCreateOptions()|. -TEST_F(SharedBufferDispatcherTest, ValidateCreateOptionsValid) { - // Default options. - { - MojoCreateSharedBufferOptions validated_options = {}; - EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::ValidateCreateOptions( - NullUserPointer(), &validated_options)); - RevalidateCreateOptions(validated_options); - } - - // Different flags. - MojoCreateSharedBufferOptionsFlags flags_values[] = { - MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE}; - for (size_t i = 0; i < MOJO_ARRAYSIZE(flags_values); i++) { - const MojoCreateSharedBufferOptionsFlags flags = flags_values[i]; - - // Different capacities (size 1). - for (uint32_t capacity = 1; capacity <= 100 * 1000 * 1000; capacity *= 10) { - MojoCreateSharedBufferOptions options = { - kSizeOfCreateOptions, // |struct_size|. - flags // |flags|. - }; - MojoCreateSharedBufferOptions validated_options = {}; - EXPECT_EQ(MOJO_RESULT_OK, - SharedBufferDispatcher::ValidateCreateOptions( - MakeUserPointer(&options), &validated_options)) - << capacity; - RevalidateCreateOptions(validated_options); - EXPECT_EQ(options.flags, validated_options.flags); - } - } -} - -TEST_F(SharedBufferDispatcherTest, ValidateCreateOptionsInvalid) { - // Invalid |struct_size|. - { - MojoCreateSharedBufferOptions options = { - 1, // |struct_size|. - MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE // |flags|. - }; - MojoCreateSharedBufferOptions unused; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - SharedBufferDispatcher::ValidateCreateOptions( - MakeUserPointer(&options), &unused)); - } - - // Unknown |flags|. - { - MojoCreateSharedBufferOptions options = { - kSizeOfCreateOptions, // |struct_size|. - ~0u // |flags|. - }; - MojoCreateSharedBufferOptions unused; - EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, - SharedBufferDispatcher::ValidateCreateOptions( - MakeUserPointer(&options), &unused)); - } -} - -TEST_F(SharedBufferDispatcherTest, CreateAndMapBuffer) { - scoped_refptr<SharedBufferDispatcher> dispatcher; - EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create( - platform_support(), - SharedBufferDispatcher::kDefaultCreateOptions, - 100, &dispatcher)); - ASSERT_TRUE(dispatcher); - EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher->GetType()); - - // Make a couple of mappings. - scoped_ptr<embedder::PlatformSharedBufferMapping> mapping1; - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer( - 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping1)); - ASSERT_TRUE(mapping1); - ASSERT_TRUE(mapping1->GetBase()); - EXPECT_EQ(100u, mapping1->GetLength()); - // Write something. - static_cast<char*>(mapping1->GetBase())[50] = 'x'; - - scoped_ptr<embedder::PlatformSharedBufferMapping> mapping2; - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer( - 50, 50, MOJO_MAP_BUFFER_FLAG_NONE, &mapping2)); - ASSERT_TRUE(mapping2); - ASSERT_TRUE(mapping2->GetBase()); - EXPECT_EQ(50u, mapping2->GetLength()); - EXPECT_EQ('x', static_cast<char*>(mapping2->GetBase())[0]); - - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); - - // Check that we can still read/write to mappings after the dispatcher has - // gone away. - static_cast<char*>(mapping2->GetBase())[1] = 'y'; - EXPECT_EQ('y', static_cast<char*>(mapping1->GetBase())[51]); -} - -TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandle) { - scoped_refptr<SharedBufferDispatcher> dispatcher1; - EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create( - platform_support(), - SharedBufferDispatcher::kDefaultCreateOptions, - 100, &dispatcher1)); - - // Map and write something. - scoped_ptr<embedder::PlatformSharedBufferMapping> mapping; - EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->MapBuffer( - 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); - static_cast<char*>(mapping->GetBase())[0] = 'x'; - mapping.reset(); - - // Duplicate |dispatcher1| and then close it. - scoped_refptr<Dispatcher> dispatcher2; - EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->DuplicateBufferHandle( - NullUserPointer(), &dispatcher2)); - ASSERT_TRUE(dispatcher2); - EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher2->GetType()); - - EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close()); - - // Map |dispatcher2| and read something. - EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->MapBuffer( - 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); - EXPECT_EQ('x', static_cast<char*>(mapping->GetBase())[0]); - - EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close()); -} - -TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsValid) { - scoped_refptr<SharedBufferDispatcher> dispatcher1; - EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create( - platform_support(), - SharedBufferDispatcher::kDefaultCreateOptions, - 100, &dispatcher1)); - - MojoDuplicateBufferHandleOptions options[] = { - {sizeof(MojoDuplicateBufferHandleOptions), - MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE}, - {sizeof(MojoDuplicateBufferHandleOptionsFlags), ~0u}}; - for (size_t i = 0; i < MOJO_ARRAYSIZE(options); i++) { - scoped_refptr<Dispatcher> dispatcher2; - EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->DuplicateBufferHandle( - MakeUserPointer(&options[i]), &dispatcher2)); - ASSERT_TRUE(dispatcher2); - EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher2->GetType()); - EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close()); - } - - EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close()); -} - -TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsInvalid) { - scoped_refptr<SharedBufferDispatcher> dispatcher1; - EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create( - platform_support(), - SharedBufferDispatcher::kDefaultCreateOptions, - 100, &dispatcher1)); - - // Invalid |struct_size|. - { - MojoDuplicateBufferHandleOptions options = { - 1u, MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE}; - scoped_refptr<Dispatcher> dispatcher2; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - dispatcher1->DuplicateBufferHandle(MakeUserPointer(&options), - &dispatcher2)); - EXPECT_FALSE(dispatcher2); - } - - // Unknown |flags|. - { - MojoDuplicateBufferHandleOptions options = { - sizeof(MojoDuplicateBufferHandleOptions), ~0u}; - scoped_refptr<Dispatcher> dispatcher2; - EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, - dispatcher1->DuplicateBufferHandle(MakeUserPointer(&options), - &dispatcher2)); - EXPECT_FALSE(dispatcher2); - } - - EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close()); -} - -TEST_F(SharedBufferDispatcherTest, CreateInvalidNumBytes) { - // Size too big. - scoped_refptr<SharedBufferDispatcher> dispatcher; - EXPECT_EQ( - MOJO_RESULT_RESOURCE_EXHAUSTED, - SharedBufferDispatcher::Create( - platform_support(), SharedBufferDispatcher::kDefaultCreateOptions, - std::numeric_limits<uint64_t>::max(), &dispatcher)); - EXPECT_FALSE(dispatcher); - - // Zero size. - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - SharedBufferDispatcher::Create( - platform_support(), - SharedBufferDispatcher::kDefaultCreateOptions, 0, &dispatcher)); - EXPECT_FALSE(dispatcher); -} - -TEST_F(SharedBufferDispatcherTest, MapBufferInvalidArguments) { - scoped_refptr<SharedBufferDispatcher> dispatcher; - EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create( - platform_support(), - SharedBufferDispatcher::kDefaultCreateOptions, - 100, &dispatcher)); - - scoped_ptr<embedder::PlatformSharedBufferMapping> mapping; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - dispatcher->MapBuffer(0, 101, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); - EXPECT_FALSE(mapping); - - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - dispatcher->MapBuffer(1, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); - EXPECT_FALSE(mapping); - - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - dispatcher->MapBuffer(0, 0, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); - EXPECT_FALSE(mapping); - - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); -} - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/simple_dispatcher.cc b/third_party/mojo/src/mojo/edk/system/simple_dispatcher.cc deleted file mode 100644 index 3934860..0000000 --- a/third_party/mojo/src/mojo/edk/system/simple_dispatcher.cc +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/simple_dispatcher.h" - -#include "base/logging.h" - -namespace mojo { -namespace system { - -SimpleDispatcher::SimpleDispatcher() { -} - -SimpleDispatcher::~SimpleDispatcher() { -} - -void SimpleDispatcher::HandleSignalsStateChangedNoLock() { - mutex().AssertHeld(); - awakable_list_.AwakeForStateChange(GetHandleSignalsStateImplNoLock()); -} - -void SimpleDispatcher::CancelAllAwakablesNoLock() { - mutex().AssertHeld(); - awakable_list_.CancelAll(); -} - -MojoResult SimpleDispatcher::AddAwakableImplNoLock( - Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state) { - mutex().AssertHeld(); - - HandleSignalsState state(GetHandleSignalsStateImplNoLock()); - if (state.satisfies(signals)) { - if (signals_state) - *signals_state = state; - return MOJO_RESULT_ALREADY_EXISTS; - } - if (!state.can_satisfy(signals)) { - if (signals_state) - *signals_state = state; - return MOJO_RESULT_FAILED_PRECONDITION; - } - - awakable_list_.Add(awakable, signals, context); - return MOJO_RESULT_OK; -} - -void SimpleDispatcher::RemoveAwakableImplNoLock( - Awakable* awakable, - HandleSignalsState* signals_state) { - mutex().AssertHeld(); - awakable_list_.Remove(awakable); - if (signals_state) - *signals_state = GetHandleSignalsStateImplNoLock(); -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/simple_dispatcher.h b/third_party/mojo/src/mojo/edk/system/simple_dispatcher.h deleted file mode 100644 index 2c790da..0000000 --- a/third_party/mojo/src/mojo/edk/system/simple_dispatcher.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_SIMPLE_DISPATCHER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_SIMPLE_DISPATCHER_H_ - -#include <list> - -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/awakable_list.h" -#include "third_party/mojo/src/mojo/edk/system/dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -// A base class for simple dispatchers. "Simple" means that there's a one-to-one -// correspondence between handles and dispatchers (see the explanatory comment -// in core.cc). This class implements the standard waiter-signalling mechanism -// in that case. -class MOJO_SYSTEM_IMPL_EXPORT SimpleDispatcher : public Dispatcher { - protected: - SimpleDispatcher(); - ~SimpleDispatcher() override; - - // To be called by subclasses when the state changes (so - // |GetHandleSignalsStateImplNoLock()| should be checked again). - void HandleSignalsStateChangedNoLock() MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex()); - - // |Dispatcher| protected methods: - void CancelAllAwakablesNoLock() override; - MojoResult AddAwakableImplNoLock(Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state) override; - void RemoveAwakableImplNoLock(Awakable* awakable, - HandleSignalsState* signals_state) override; - - private: - AwakableList awakable_list_ MOJO_GUARDED_BY(mutex()); - - MOJO_DISALLOW_COPY_AND_ASSIGN(SimpleDispatcher); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_SIMPLE_DISPATCHER_H_ diff --git a/third_party/mojo/src/mojo/edk/system/simple_dispatcher_unittest.cc b/third_party/mojo/src/mojo/edk/system/simple_dispatcher_unittest.cc deleted file mode 100644 index 04d0df7..0000000 --- a/third_party/mojo/src/mojo/edk/system/simple_dispatcher_unittest.cc +++ /dev/null @@ -1,604 +0,0 @@ -// Copyright 2013 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. - -// NOTE(vtl): Some of these tests are inherently flaky (e.g., if run on a -// heavily-loaded system). Sorry. |test::EpsilonDeadline()| may be increased to -// increase tolerance and reduce observed flakiness (though doing so reduces the -// meaningfulness of the test). - -#include "third_party/mojo/src/mojo/edk/system/simple_dispatcher.h" - -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_vector.h" -#include "base/synchronization/lock.h" -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/system/test_utils.h" -#include "third_party/mojo/src/mojo/edk/system/waiter.h" -#include "third_party/mojo/src/mojo/edk/system/waiter_test_utils.h" - -namespace mojo { -namespace system { -namespace { - -class MockSimpleDispatcher final : public SimpleDispatcher { - public: - MockSimpleDispatcher() - : state_(MOJO_HANDLE_SIGNAL_NONE, - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE) {} - explicit MockSimpleDispatcher(const HandleSignalsState& state) - : state_(state) {} - - void SetSatisfiedSignals(MojoHandleSignals new_satisfied_signals) { - MutexLocker locker(&mutex()); - - // Any new signals that are set should be satisfiable. - CHECK_EQ(new_satisfied_signals & ~state_.satisfied_signals, - new_satisfied_signals & ~state_.satisfied_signals & - state_.satisfiable_signals); - - if (new_satisfied_signals == state_.satisfied_signals) - return; - - state_.satisfied_signals = new_satisfied_signals; - HandleSignalsStateChangedNoLock(); - } - - void SetSatisfiableSignals(MojoHandleSignals new_satisfiable_signals) { - MutexLocker locker(&mutex()); - - // Satisfied implies satisfiable. - CHECK_EQ(new_satisfiable_signals & state_.satisfied_signals, - state_.satisfied_signals); - - if (new_satisfiable_signals == state_.satisfiable_signals) - return; - - state_.satisfiable_signals = new_satisfiable_signals; - HandleSignalsStateChangedNoLock(); - } - - Type GetType() const override { return Type::UNKNOWN; } - - private: - friend class base::RefCountedThreadSafe<MockSimpleDispatcher>; - ~MockSimpleDispatcher() override {} - - scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock() - override { - scoped_refptr<MockSimpleDispatcher> rv(new MockSimpleDispatcher(state_)); - return scoped_refptr<Dispatcher>(rv.get()); - } - - // |Dispatcher| override: - HandleSignalsState GetHandleSignalsStateImplNoLock() const override { - mutex().AssertHeld(); - return state_; - } - - HandleSignalsState state_ MOJO_GUARDED_BY(mutex()); - - MOJO_DISALLOW_COPY_AND_ASSIGN(MockSimpleDispatcher); -}; - -#if defined(OS_WIN) -// http://crbug.com/396404 -#define MAYBE_Basic DISABLED_Basic -#else -#define MAYBE_Basic Basic -#endif -TEST(SimpleDispatcherTest, MAYBE_Basic) { - test::Stopwatch stopwatch; - - scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); - Waiter w; - uintptr_t context = 0; - HandleSignalsState hss; - - // Try adding a readable waiter when already readable. - w.Init(); - d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfiable_signals); - // Shouldn't need to remove the waiter (it was not added). - - // Wait (forever) for writable when already writable. - w.Init(); - d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); - ASSERT_EQ(MOJO_RESULT_OK, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1, nullptr)); - d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE); - stopwatch.Start(); - EXPECT_EQ(MOJO_RESULT_OK, w.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); - EXPECT_EQ(1u, context); - hss = HandleSignalsState(); - d->RemoveAwakable(&w, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfiable_signals); - - // Wait for zero time for writable when already writable. - w.Init(); - d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); - ASSERT_EQ(MOJO_RESULT_OK, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, nullptr)); - d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE); - stopwatch.Start(); - EXPECT_EQ(MOJO_RESULT_OK, w.Wait(0, &context)); - EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); - EXPECT_EQ(2u, context); - hss = HandleSignalsState(); - d->RemoveAwakable(&w, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfiable_signals); - - // Wait for non-zero, finite time for writable when already writable. - w.Init(); - d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); - ASSERT_EQ(MOJO_RESULT_OK, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, nullptr)); - d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE); - stopwatch.Start(); - EXPECT_EQ(MOJO_RESULT_OK, w.Wait(2 * test::EpsilonDeadline(), &context)); - EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); - EXPECT_EQ(3u, context); - hss = HandleSignalsState(); - d->RemoveAwakable(&w, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfiable_signals); - - // Wait for zero time for writable when not writable (will time out). - w.Init(); - d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); - ASSERT_EQ(MOJO_RESULT_OK, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, nullptr)); - stopwatch.Start(); - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0, nullptr)); - EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); - hss = HandleSignalsState(); - d->RemoveAwakable(&w, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfiable_signals); - - // Wait for non-zero, finite time for writable when not writable (will time - // out). - w.Init(); - d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); - ASSERT_EQ(MOJO_RESULT_OK, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 5, nullptr)); - stopwatch.Start(); - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, - w.Wait(2 * test::EpsilonDeadline(), nullptr)); - MojoDeadline elapsed = stopwatch.Elapsed(); - EXPECT_GT(elapsed, (2 - 1) * test::EpsilonDeadline()); - EXPECT_LT(elapsed, (2 + 1) * test::EpsilonDeadline()); - hss = HandleSignalsState(); - d->RemoveAwakable(&w, &hss); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfiable_signals); - - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); -} - -TEST(SimpleDispatcherTest, BasicUnsatisfiable) { - test::Stopwatch stopwatch; - - scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); - Waiter w; - uintptr_t context = 0; - HandleSignalsState hss; - - // Try adding a writable waiter when it can never be writable. - w.Init(); - d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); - d->SetSatisfiedSignals(0); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1, &hss)); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); - // Shouldn't need to remove the waiter (it was not added). - - // Wait (forever) for writable and then it becomes never writable. - w.Init(); - d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE); - ASSERT_EQ(MOJO_RESULT_OK, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, nullptr)); - d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); - stopwatch.Start(); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - w.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); - EXPECT_EQ(2u, context); - hss = HandleSignalsState(); - d->RemoveAwakable(&w, &hss); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); - - // Wait for zero time for writable and then it becomes never writable. - w.Init(); - d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE); - ASSERT_EQ(MOJO_RESULT_OK, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, nullptr)); - d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); - stopwatch.Start(); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, w.Wait(0, &context)); - EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); - EXPECT_EQ(3u, context); - hss = HandleSignalsState(); - d->RemoveAwakable(&w, &hss); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); - - // Wait for non-zero, finite time for writable and then it becomes never - // writable. - w.Init(); - d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE); - ASSERT_EQ(MOJO_RESULT_OK, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, nullptr)); - d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); - stopwatch.Start(); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - w.Wait(2 * test::EpsilonDeadline(), &context)); - EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); - EXPECT_EQ(4u, context); - hss = HandleSignalsState(); - d->RemoveAwakable(&w, &hss); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); - - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); -} - -TEST(SimpleDispatcherTest, BasicClosed) { - test::Stopwatch stopwatch; - - scoped_refptr<MockSimpleDispatcher> d; - Waiter w; - uintptr_t context = 0; - HandleSignalsState hss; - - // Try adding a writable waiter when the dispatcher has been closed. - d = new MockSimpleDispatcher(); - w.Init(); - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1, &hss)); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - // Shouldn't need to remove the waiter (it was not added). - - // Wait (forever) for writable and then the dispatcher is closed. - d = new MockSimpleDispatcher(); - w.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, nullptr)); - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - stopwatch.Start(); - EXPECT_EQ(MOJO_RESULT_CANCELLED, w.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); - EXPECT_EQ(2u, context); - // Don't need to remove waiters from closed dispatchers. - - // Wait for zero time for writable and then the dispatcher is closed. - d = new MockSimpleDispatcher(); - w.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, nullptr)); - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - stopwatch.Start(); - EXPECT_EQ(MOJO_RESULT_CANCELLED, w.Wait(0, &context)); - EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); - EXPECT_EQ(3u, context); - // Don't need to remove waiters from closed dispatchers. - - // Wait for non-zero, finite time for writable and then the dispatcher is - // closed. - d = new MockSimpleDispatcher(); - w.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, nullptr)); - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - stopwatch.Start(); - EXPECT_EQ(MOJO_RESULT_CANCELLED, - w.Wait(2 * test::EpsilonDeadline(), &context)); - EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); - EXPECT_EQ(4u, context); - // Don't need to remove waiters from closed dispatchers. -} - -#if defined(OS_WIN) -// http://crbug.com/396393 -#define MAYBE_BasicThreaded DISABLED_BasicThreaded -#else -#define MAYBE_BasicThreaded BasicThreaded -#endif -TEST(SimpleDispatcherTest, MAYBE_BasicThreaded) { - test::Stopwatch stopwatch; - bool did_wait; - MojoResult result; - uintptr_t context; - HandleSignalsState hss; - - // Wait for readable (already readable). - { - scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); - { - d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); - test::WaiterThread thread(d, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, 1, &did_wait, &result, - &context, &hss); - stopwatch.Start(); - thread.Start(); - } // Joins the thread. - // If we closed earlier, then probably we'd get a |MOJO_RESULT_CANCELLED|. - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - } - EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); - EXPECT_FALSE(did_wait); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, result); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfiable_signals); - - // Wait for readable and becomes readable after some time. - { - scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); - { - test::WaiterThread thread(d, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, 2, &did_wait, &result, - &context, &hss); - stopwatch.Start(); - thread.Start(); - test::Sleep(2 * test::EpsilonDeadline()); - d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); - } // Joins the thread. - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - } - MojoDeadline elapsed = stopwatch.Elapsed(); - EXPECT_GT(elapsed, (2 - 1) * test::EpsilonDeadline()); - EXPECT_LT(elapsed, (2 + 1) * test::EpsilonDeadline()); - EXPECT_TRUE(did_wait); - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(2u, context); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfiable_signals); - - // Wait for readable and becomes never-readable after some time. - { - scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); - { - test::WaiterThread thread(d, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, 3, &did_wait, &result, - &context, &hss); - stopwatch.Start(); - thread.Start(); - test::Sleep(2 * test::EpsilonDeadline()); - d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_NONE); - } // Joins the thread. - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - } - elapsed = stopwatch.Elapsed(); - EXPECT_GT(elapsed, (2 - 1) * test::EpsilonDeadline()); - EXPECT_LT(elapsed, (2 + 1) * test::EpsilonDeadline()); - EXPECT_TRUE(did_wait); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); - EXPECT_EQ(3u, context); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - - // Wait for readable and dispatcher gets closed. - { - scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); - test::WaiterThread thread(d, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, 4, &did_wait, &result, - &context, &hss); - stopwatch.Start(); - thread.Start(); - test::Sleep(2 * test::EpsilonDeadline()); - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - } // Joins the thread. - elapsed = stopwatch.Elapsed(); - EXPECT_GT(elapsed, (2 - 1) * test::EpsilonDeadline()); - EXPECT_LT(elapsed, (2 + 1) * test::EpsilonDeadline()); - EXPECT_TRUE(did_wait); - EXPECT_EQ(MOJO_RESULT_CANCELLED, result); - EXPECT_EQ(4u, context); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - - // Wait for readable and times out. - { - scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); - { - test::WaiterThread thread(d, MOJO_HANDLE_SIGNAL_READABLE, - 2 * test::EpsilonDeadline(), 5, &did_wait, - &result, &context, &hss); - stopwatch.Start(); - thread.Start(); - test::Sleep(1 * test::EpsilonDeadline()); - // Not what we're waiting for. - d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE); - } // Joins the thread (after its wait times out). - // If we closed earlier, then probably we'd get a |MOJO_RESULT_CANCELLED|. - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - } - elapsed = stopwatch.Elapsed(); - EXPECT_GT(elapsed, (2 - 1) * test::EpsilonDeadline()); - EXPECT_LT(elapsed, (2 + 1) * test::EpsilonDeadline()); - EXPECT_TRUE(did_wait); - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfiable_signals); -} - -#if defined(OS_WIN) -// http://crbug.com/387124 -#define MAYBE_MultipleWaiters DISABLED_MultipleWaiters -#else -#define MAYBE_MultipleWaiters MultipleWaiters -#endif -TEST(SimpleDispatcherTest, MAYBE_MultipleWaiters) { - static const uint32_t kNumWaiters = 20; - - bool did_wait[kNumWaiters]; - MojoResult result[kNumWaiters]; - uintptr_t context[kNumWaiters]; - HandleSignalsState hss[kNumWaiters]; - - // All wait for readable and becomes readable after some time. - { - scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); - ScopedVector<test::WaiterThread> threads; - for (uint32_t i = 0; i < kNumWaiters; i++) { - threads.push_back(new test::WaiterThread( - d, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, i, - &did_wait[i], &result[i], &context[i], &hss[i])); - threads.back()->Start(); - } - test::Sleep(2 * test::EpsilonDeadline()); - d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - } // Joins the threads. - for (uint32_t i = 0; i < kNumWaiters; i++) { - EXPECT_TRUE(did_wait[i]) << i; - EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i; - EXPECT_EQ(i, context[i]) << i; - // Since we closed before joining, we can't say much about what each thread - // saw as the state. - } - - // Some wait for readable, some for writable, and becomes readable after some - // time. - { - scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); - ScopedVector<test::WaiterThread> threads; - for (uint32_t i = 0; i < kNumWaiters / 2; i++) { - threads.push_back(new test::WaiterThread( - d, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, i, - &did_wait[i], &result[i], &context[i], &hss[i])); - threads.back()->Start(); - } - for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { - threads.push_back(new test::WaiterThread( - d, MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_DEADLINE_INDEFINITE, i, - &did_wait[i], &result[i], &context[i], &hss[i])); - threads.back()->Start(); - } - test::Sleep(2 * test::EpsilonDeadline()); - d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); - // This will wake up the ones waiting to write. - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - } // Joins the threads. - for (uint32_t i = 0; i < kNumWaiters / 2; i++) { - EXPECT_TRUE(did_wait[i]) << i; - EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i; - EXPECT_EQ(i, context[i]) << i; - // Since we closed before joining, we can't say much about what each thread - // saw as the state. - } - for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { - EXPECT_TRUE(did_wait[i]) << i; - EXPECT_EQ(MOJO_RESULT_CANCELLED, result[i]) << i; - EXPECT_EQ(i, context[i]) << i; - // Since we closed before joining, we can't say much about what each thread - // saw as the state. - } - - // Some wait for readable, some for writable, and becomes readable and - // never-writable after some time. - { - scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); - ScopedVector<test::WaiterThread> threads; - for (uint32_t i = 0; i < kNumWaiters / 2; i++) { - threads.push_back(new test::WaiterThread( - d, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, i, - &did_wait[i], &result[i], &context[i], &hss[i])); - threads.back()->Start(); - } - for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { - threads.push_back(new test::WaiterThread( - d, MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_DEADLINE_INDEFINITE, i, - &did_wait[i], &result[i], &context[i], &hss[i])); - threads.back()->Start(); - } - test::Sleep(1 * test::EpsilonDeadline()); - d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); - test::Sleep(1 * test::EpsilonDeadline()); - d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - } // Joins the threads. - for (uint32_t i = 0; i < kNumWaiters / 2; i++) { - EXPECT_TRUE(did_wait[i]) << i; - EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i; - EXPECT_EQ(i, context[i]) << i; - // Since we closed before joining, we can't say much about what each thread - // saw as the state. - } - for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { - EXPECT_TRUE(did_wait[i]) << i; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result[i]) << i; - EXPECT_EQ(i, context[i]) << i; - // Since we closed before joining, we can't say much about what each thread - // saw as the state. - } - - // Some wait for readable, some for writable, and becomes readable after some - // time. - { - scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); - ScopedVector<test::WaiterThread> threads; - for (uint32_t i = 0; i < kNumWaiters / 2; i++) { - threads.push_back(new test::WaiterThread( - d, MOJO_HANDLE_SIGNAL_READABLE, 3 * test::EpsilonDeadline(), i, - &did_wait[i], &result[i], &context[i], &hss[i])); - threads.back()->Start(); - } - for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { - threads.push_back(new test::WaiterThread( - d, MOJO_HANDLE_SIGNAL_WRITABLE, 1 * test::EpsilonDeadline(), i, - &did_wait[i], &result[i], &context[i], &hss[i])); - threads.back()->Start(); - } - test::Sleep(2 * test::EpsilonDeadline()); - d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); - // All those waiting for writable should have timed out. - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - } // Joins the threads. - for (uint32_t i = 0; i < kNumWaiters / 2; i++) { - EXPECT_TRUE(did_wait[i]) << i; - EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i; - EXPECT_EQ(i, context[i]) << i; - // Since we closed before joining, we can't say much about what each thread - // saw as the state. - } - for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { - EXPECT_TRUE(did_wait[i]) << i; - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result[i]) << i; - // Since we closed before joining, we can't say much about what each thread - // saw as the state. - } -} - -// TODO(vtl): Stress test? - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/slave_connection_manager.cc b/third_party/mojo/src/mojo/edk/system/slave_connection_manager.cc deleted file mode 100644 index 0c85965..0000000 --- a/third_party/mojo/src/mojo/edk/system/slave_connection_manager.cc +++ /dev/null @@ -1,344 +0,0 @@ -// Copyright 2015 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 "third_party/mojo/src/mojo/edk/system/slave_connection_manager.h" - -#include <utility> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "third_party/mojo/src/mojo/edk/system/connection_manager_messages.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit.h" - -namespace mojo { -namespace system { - -// SlaveConnectionManager ------------------------------------------------------ - -SlaveConnectionManager::SlaveConnectionManager( - embedder::PlatformSupport* platform_support) - : ConnectionManager(platform_support), - slave_process_delegate_(), - private_thread_("SlaveConnectionManagerPrivateThread"), - awaiting_ack_type_(NOT_AWAITING_ACK), - ack_result_(nullptr), - ack_peer_process_identifier_(nullptr), - ack_is_first_(nullptr), - ack_platform_handle_(nullptr), - event_(false, false) { // Auto-reset, not initially signalled. -} - -SlaveConnectionManager::~SlaveConnectionManager() { - DCHECK(!delegate_thread_task_runner_); - DCHECK(!slave_process_delegate_); - DCHECK(!private_thread_.message_loop()); - DCHECK_EQ(awaiting_ack_type_, NOT_AWAITING_ACK); - DCHECK(!ack_result_); - DCHECK(!ack_peer_process_identifier_); - DCHECK(!ack_is_first_); - DCHECK(!ack_platform_handle_); -} - -void SlaveConnectionManager::Init( - embedder::SlaveProcessDelegate* slave_process_delegate, - embedder::ScopedPlatformHandle platform_handle) { - DCHECK(slave_process_delegate); - DCHECK(platform_handle.is_valid()); - DCHECK(!delegate_thread_task_runner_); - DCHECK(!slave_process_delegate_); - DCHECK(!private_thread_.message_loop()); - - delegate_thread_task_runner_ = base::MessageLoop::current()->task_runner(); - slave_process_delegate_ = slave_process_delegate; - CHECK(private_thread_.StartWithOptions( - base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); - private_thread_.message_loop()->PostTask( - FROM_HERE, - base::Bind(&SlaveConnectionManager::InitOnPrivateThread, - base::Unretained(this), base::Passed(&platform_handle))); - event_.Wait(); -} - -void SlaveConnectionManager::Shutdown() { - AssertNotOnPrivateThread(); - DCHECK(slave_process_delegate_); - DCHECK(private_thread_.message_loop()); - - // The |Stop()| will actually finish all posted tasks. - private_thread_.message_loop()->PostTask( - FROM_HERE, base::Bind(&SlaveConnectionManager::ShutdownOnPrivateThread, - base::Unretained(this))); - private_thread_.Stop(); - slave_process_delegate_ = nullptr; - delegate_thread_task_runner_ = nullptr; -} - -bool SlaveConnectionManager::AllowConnect( - const ConnectionIdentifier& connection_id) { - AssertNotOnPrivateThread(); - - MutexLocker locker(&mutex_); - Result result = Result::FAILURE; - private_thread_.message_loop()->PostTask( - FROM_HERE, - base::Bind(&SlaveConnectionManager::AllowConnectOnPrivateThread, - base::Unretained(this), connection_id, &result)); - event_.Wait(); - DCHECK(result == Result::FAILURE || result == Result::SUCCESS); - return result == Result::SUCCESS; -} - -bool SlaveConnectionManager::CancelConnect( - const ConnectionIdentifier& connection_id) { - AssertNotOnPrivateThread(); - - MutexLocker locker(&mutex_); - Result result = Result::FAILURE; - private_thread_.message_loop()->PostTask( - FROM_HERE, - base::Bind(&SlaveConnectionManager::CancelConnectOnPrivateThread, - base::Unretained(this), connection_id, &result)); - event_.Wait(); - DCHECK(result == Result::FAILURE || result == Result::SUCCESS); - return result == Result::SUCCESS; -} - -ConnectionManager::Result SlaveConnectionManager::Connect( - const ConnectionIdentifier& connection_id, - ProcessIdentifier* peer_process_identifier, - bool* is_first, - embedder::ScopedPlatformHandle* platform_handle) { - AssertNotOnPrivateThread(); - DCHECK(peer_process_identifier); - DCHECK(is_first); - DCHECK(platform_handle); - DCHECK(!platform_handle->is_valid()); // Not technically wrong, but unlikely. - - MutexLocker locker(&mutex_); - Result result = Result::FAILURE; - private_thread_.message_loop()->PostTask( - FROM_HERE, - base::Bind(&SlaveConnectionManager::ConnectOnPrivateThread, - base::Unretained(this), connection_id, &result, - peer_process_identifier, is_first, platform_handle)); - event_.Wait(); - return result; -} - -void SlaveConnectionManager::InitOnPrivateThread( - embedder::ScopedPlatformHandle platform_handle) { - AssertOnPrivateThread(); - - raw_channel_ = RawChannel::Create(std::move(platform_handle)); - raw_channel_->Init(this); - event_.Signal(); -} - -void SlaveConnectionManager::ShutdownOnPrivateThread() { - AssertOnPrivateThread(); - - CHECK_EQ(awaiting_ack_type_, NOT_AWAITING_ACK); - if (raw_channel_) { - raw_channel_->Shutdown(); - raw_channel_.reset(); - } -} - -void SlaveConnectionManager::AllowConnectOnPrivateThread( - const ConnectionIdentifier& connection_id, - Result* result) { - DCHECK(result); - AssertOnPrivateThread(); - // This should only posted (from another thread, to |private_thread_|) with - // the lock held (until this thread triggers |event_|). - DCHECK(!mutex_.TryLock()); - DCHECK_EQ(awaiting_ack_type_, NOT_AWAITING_ACK); - - DVLOG(1) << "Sending AllowConnect: connection ID " - << connection_id.ToString(); - if (!raw_channel_->WriteMessage(make_scoped_ptr(new MessageInTransit( - MessageInTransit::Type::CONNECTION_MANAGER, - MessageInTransit::Subtype::CONNECTION_MANAGER_ALLOW_CONNECT, - sizeof(connection_id), &connection_id)))) { - // Don't tear things down; possibly we'll still read some messages. - *result = Result::FAILURE; - event_.Signal(); - return; - } - awaiting_ack_type_ = AWAITING_ACCEPT_CONNECT_ACK; - ack_result_ = result; -} - -void SlaveConnectionManager::CancelConnectOnPrivateThread( - const ConnectionIdentifier& connection_id, - Result* result) { - DCHECK(result); - AssertOnPrivateThread(); - // This should only posted (from another thread, to |private_thread_|) with - // the lock held (until this thread triggers |event_|). - DCHECK(!mutex_.TryLock()); - DCHECK_EQ(awaiting_ack_type_, NOT_AWAITING_ACK); - - DVLOG(1) << "Sending CancelConnect: connection ID " - << connection_id.ToString(); - if (!raw_channel_->WriteMessage(make_scoped_ptr(new MessageInTransit( - MessageInTransit::Type::CONNECTION_MANAGER, - MessageInTransit::Subtype::CONNECTION_MANAGER_CANCEL_CONNECT, - sizeof(connection_id), &connection_id)))) { - // Don't tear things down; possibly we'll still read some messages. - *result = Result::FAILURE; - event_.Signal(); - return; - } - awaiting_ack_type_ = AWAITING_CANCEL_CONNECT_ACK; - ack_result_ = result; -} - -void SlaveConnectionManager::ConnectOnPrivateThread( - const ConnectionIdentifier& connection_id, - Result* result, - ProcessIdentifier* peer_process_identifier, - bool* is_first, - embedder::ScopedPlatformHandle* platform_handle) { - DCHECK(result); - AssertOnPrivateThread(); - // This should only posted (from another thread, to |private_thread_|) with - // the lock held (until this thread triggers |event_|). - DCHECK(!mutex_.TryLock()); - DCHECK_EQ(awaiting_ack_type_, NOT_AWAITING_ACK); - - DVLOG(1) << "Sending Connect: connection ID " << connection_id.ToString(); - if (!raw_channel_->WriteMessage(make_scoped_ptr(new MessageInTransit( - MessageInTransit::Type::CONNECTION_MANAGER, - MessageInTransit::Subtype::CONNECTION_MANAGER_CONNECT, - sizeof(connection_id), &connection_id)))) { - // Don't tear things down; possibly we'll still read some messages. - *result = Result::FAILURE; - platform_handle->reset(); - event_.Signal(); - return; - } - awaiting_ack_type_ = AWAITING_CONNECT_ACK; - ack_result_ = result; - ack_peer_process_identifier_ = peer_process_identifier; - ack_is_first_ = is_first; - ack_platform_handle_ = platform_handle; -} - -void SlaveConnectionManager::OnReadMessage( - const MessageInTransit::View& message_view, - embedder::ScopedPlatformHandleVectorPtr platform_handles) { - AssertOnPrivateThread(); - - // Set |*ack_result_| to failure by default. - *ack_result_ = Result::FAILURE; - - // Note: Since we should be able to trust the master, simply crash (i.e., - // |CHECK()|-fail) if it sends us something invalid. - - // Unsolicited message. - CHECK_NE(awaiting_ack_type_, NOT_AWAITING_ACK); - // Bad message type. - CHECK_EQ(message_view.type(), MessageInTransit::Type::CONNECTION_MANAGER_ACK); - - size_t num_bytes = message_view.num_bytes(); - size_t num_platform_handles = platform_handles ? platform_handles->size() : 0; - - if (message_view.subtype() == - MessageInTransit::Subtype::CONNECTION_MANAGER_ACK_FAILURE) { - // Failure acks never have any contents. - DCHECK_EQ(num_bytes, 0u); - DCHECK_EQ(num_platform_handles, 0u); - // Leave |*ack_result_| as failure. - } else { - if (awaiting_ack_type_ != AWAITING_CONNECT_ACK) { - // In the non-"connect" case, there's only one type of success ack, which - // never has any contents. - CHECK_EQ(message_view.subtype(), - MessageInTransit::Subtype::CONNECTION_MANAGER_ACK_SUCCESS); - DCHECK_EQ(num_bytes, 0u); - DCHECK_EQ(num_platform_handles, 0u); - *ack_result_ = Result::SUCCESS; - DCHECK(!ack_peer_process_identifier_); - DCHECK(!ack_is_first_); - DCHECK(!ack_platform_handle_); - } else { - // Success acks for "connect" always have a - // |ConnectionManagerAckSuccessConnectData| as data. - CHECK_EQ(num_bytes, sizeof(ConnectionManagerAckSuccessConnectData)); - const ConnectionManagerAckSuccessConnectData& data = - *static_cast<const ConnectionManagerAckSuccessConnectData*>( - message_view.bytes()); - *ack_peer_process_identifier_ = data.peer_process_identifier; - *ack_is_first_ = data.is_first; - - switch (message_view.subtype()) { - case MessageInTransit::Subtype:: - CONNECTION_MANAGER_ACK_SUCCESS_CONNECT_SAME_PROCESS: - DCHECK_EQ(num_platform_handles, 0u); - *ack_result_ = Result::SUCCESS_CONNECT_SAME_PROCESS; - ack_platform_handle_->reset(); - break; - case MessageInTransit::Subtype:: - CONNECTION_MANAGER_ACK_SUCCESS_CONNECT_NEW_CONNECTION: - CHECK_EQ(num_platform_handles, 1u); - *ack_result_ = Result::SUCCESS_CONNECT_NEW_CONNECTION; - ack_platform_handle_->reset(platform_handles->at(0)); - platform_handles->at(0) = embedder::PlatformHandle(); - break; - case MessageInTransit::Subtype:: - CONNECTION_MANAGER_ACK_SUCCESS_CONNECT_REUSE_CONNECTION: - DCHECK_EQ(num_platform_handles, 0u); - *ack_result_ = Result::SUCCESS_CONNECT_REUSE_CONNECTION; - ack_platform_handle_->reset(); - break; - default: - CHECK(false); - } - } - } - - awaiting_ack_type_ = NOT_AWAITING_ACK; - ack_result_ = nullptr; - ack_peer_process_identifier_ = nullptr; - ack_is_first_ = nullptr; - ack_platform_handle_ = nullptr; - event_.Signal(); -} - -void SlaveConnectionManager::OnError(Error error) { - AssertOnPrivateThread(); - - // Ignore write errors, since we may still have some messages to read. - if (error == RawChannel::Delegate::ERROR_WRITE) - return; - - raw_channel_->Shutdown(); - raw_channel_.reset(); - - DCHECK(slave_process_delegate_); - delegate_thread_task_runner_->PostTask( - FROM_HERE, base::Bind(&embedder::SlaveProcessDelegate::OnMasterDisconnect, - base::Unretained(slave_process_delegate_))); -} - -void SlaveConnectionManager::AssertNotOnPrivateThread() const { - // This should only be called after |Init()| and before |Shutdown()|. (If not, - // the subsequent |DCHECK_NE()| is invalid, since the current thread may not - // have a message loop.) - DCHECK(private_thread_.message_loop()); - DCHECK_NE(base::MessageLoop::current(), private_thread_.message_loop()); -} - -void SlaveConnectionManager::AssertOnPrivateThread() const { - // This should only be called after |Init()| and before |Shutdown()|. - DCHECK(private_thread_.message_loop()); - DCHECK_EQ(base::MessageLoop::current(), private_thread_.message_loop()); -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/slave_connection_manager.h b/third_party/mojo/src/mojo/edk/system/slave_connection_manager.h deleted file mode 100644 index 610e02b..0000000 --- a/third_party/mojo/src/mojo/edk/system/slave_connection_manager.h +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2015 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_SLAVE_CONNECTION_MANAGER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_SLAVE_CONNECTION_MANAGER_H_ - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" -#include "third_party/mojo/src/mojo/edk/embedder/slave_process_delegate.h" -#include "third_party/mojo/src/mojo/edk/system/connection_manager.h" -#include "third_party/mojo/src/mojo/edk/system/mutex.h" -#include "third_party/mojo/src/mojo/edk/system/raw_channel.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace base { -class TaskRunner; -} - -namespace mojo { - -namespace embedder { -class SlaveProcessDelegate; -} - -namespace system { - -// The |ConnectionManager| implementation for slave processes. -// -// This class is thread-safe (except that no public methods may be called from -// its internal, private thread), with condition that |Init()| be called before -// anything else and |Shutdown()| be called before destruction (and no other -// public methods may be called during/after |Shutdown()|). -class MOJO_SYSTEM_IMPL_EXPORT SlaveConnectionManager final - : public ConnectionManager, - public RawChannel::Delegate { - public: - // Note: None of the public methods may be called from |private_thread_|. - - // |platform_support| must be valid and remain alive until after |Shutdown()| - // has completed. - explicit SlaveConnectionManager(embedder::PlatformSupport* platform_support); - ~SlaveConnectionManager() override; - - // No other methods may be called until after this has been called. - // |delegate_thread_task_runner| should be the task runner for the "delegate - // thread", on which |slave_process_delegate|'s methods will be called. Both - // must stay alive at least until after |Shutdown()| has been called. - void Init(embedder::SlaveProcessDelegate* slave_process_delegate, - embedder::ScopedPlatformHandle platform_handle); - - // |ConnectionManager| methods: - void Shutdown() override; - bool AllowConnect(const ConnectionIdentifier& connection_id) override; - bool CancelConnect(const ConnectionIdentifier& connection_id) override; - Result Connect(const ConnectionIdentifier& connection_id, - ProcessIdentifier* peer_process_identifier, - bool* is_first, - embedder::ScopedPlatformHandle* platform_handle) override; - - private: - // These should only be called on |private_thread_|: - void InitOnPrivateThread(embedder::ScopedPlatformHandle platform_handle); - void ShutdownOnPrivateThread(); - void AllowConnectOnPrivateThread(const ConnectionIdentifier& connection_id, - Result* result); - void CancelConnectOnPrivateThread(const ConnectionIdentifier& connection_id, - Result* result); - void ConnectOnPrivateThread(const ConnectionIdentifier& connection_id, - Result* result, - ProcessIdentifier* peer_process_identifier, - bool* is_first, - embedder::ScopedPlatformHandle* platform_handle); - - // |RawChannel::Delegate| methods (only called on |private_thread_|): - void OnReadMessage( - const MessageInTransit::View& message_view, - embedder::ScopedPlatformHandleVectorPtr platform_handles) override; - void OnError(Error error) override; - - // Asserts that the current thread is *not* |private_thread_| (no-op if - // DCHECKs are not enabled). This should only be called while - // |private_thread_| is alive (i.e., after |Init()| but before |Shutdown()|). - void AssertNotOnPrivateThread() const; - - // Asserts that the current thread is |private_thread_| (no-op if DCHECKs are - // not enabled). This should only be called while |private_thread_| is alive - // (i.e., after |Init()| but before |Shutdown()|). - void AssertOnPrivateThread() const; - - // These are set in |Init()| before |private_thread_| exists and only cleared - // in |Shutdown()| after |private_thread_| is dead. Thus it's safe to "use" on - // |private_thread_|. (Note that |slave_process_delegate_| may only be called - // from the delegate thread.) - scoped_refptr<base::TaskRunner> delegate_thread_task_runner_; - embedder::SlaveProcessDelegate* slave_process_delegate_; - - // This is a private I/O thread on which this class does the bulk of its work. - // It is started in |Init()| and terminated in |Shutdown()|. - // TODO(vtl): This isn't really necessary. - base::Thread private_thread_; - - // Only accessed on |private_thread_|: - scoped_ptr<RawChannel> raw_channel_; - enum AwaitingAckType { - NOT_AWAITING_ACK, - AWAITING_ACCEPT_CONNECT_ACK, - AWAITING_CANCEL_CONNECT_ACK, - AWAITING_CONNECT_ACK - }; - AwaitingAckType awaiting_ack_type_; - Result* ack_result_; - // Used only when waiting for the ack to "connect": - ProcessIdentifier* ack_peer_process_identifier_; - bool* ack_is_first_; - embedder::ScopedPlatformHandle* ack_platform_handle_; - - // The (synchronous) |ConnectionManager| methods are implemented in the - // following way (T is any thread other than |private_thread_|): - // - // On thread T: - // 1. |F()| is called, where F is one of the |ConnectionManager| methods. - // 2. |lock_| is acquired. - // 3. |FImpl()| is posted to |private_thread_|. - // 4. |event_| is waited on (while holding |lock_|!). - // - // On |private_thread_| (all with |lock_| held!): - // 4.1. |FImpl()| is executed, writes an "F" message to |raw_channel_|, and - // sets |awaiting_ack_type_| appropriately (it must not be "set" - // before). - // 4.2. [Control returns to |private_thread_|'s message loop.] - // 4.3. Eventually, |raw_channel_| calls |OnReadMessage()| with a message, - // which must be response (|awaiting_ack_type_| must still be set). - // 4.4. |*ack_result_| and possibly |*ack_platform_handle_| are written to. - // |awaiting_ack_type_| is "unset". - // 4.5. |event_| is triggered. - // - // Back on thread T: - // 6. |lock_| is released. - // 7. [Return from |F()|.] - // - // TODO(vtl): This is all a hack. It'd really suffice to have a version of - // |RawChannel| with fully synchronous reading and writing. - Mutex mutex_; - base::WaitableEvent event_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(SlaveConnectionManager); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_SLAVE_CONNECTION_MANAGER_H_ diff --git a/third_party/mojo/src/mojo/edk/system/system_impl_export.h b/third_party/mojo/src/mojo/edk/system/system_impl_export.h deleted file mode 100644 index 82482d3..0000000 --- a/third_party/mojo/src/mojo/edk/system/system_impl_export.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_SYSTEM_IMPL_EXPORT_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_SYSTEM_IMPL_EXPORT_H_ - -#if defined(COMPONENT_BUILD) -#if defined(WIN32) - -#if defined(MOJO_SYSTEM_IMPL_IMPLEMENTATION) -#define MOJO_SYSTEM_IMPL_EXPORT __declspec(dllexport) -#else -#define MOJO_SYSTEM_IMPL_EXPORT __declspec(dllimport) -#endif // defined(MOJO_SYSTEM_IMPL_IMPLEMENTATION) - -#else // defined(WIN32) -#if defined(MOJO_SYSTEM_IMPL_IMPLEMENTATION) -#define MOJO_SYSTEM_IMPL_EXPORT __attribute__((visibility("default"))) -#else -#define MOJO_SYSTEM_IMPL_EXPORT -#endif -#endif - -#else // defined(COMPONENT_BUILD) -#define MOJO_SYSTEM_IMPL_EXPORT -#endif - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_SYSTEM_IMPL_EXPORT_H_ diff --git a/third_party/mojo/src/mojo/edk/system/test_channel_endpoint_client.cc b/third_party/mojo/src/mojo/edk/system/test_channel_endpoint_client.cc deleted file mode 100644 index fc60cb3..0000000 --- a/third_party/mojo/src/mojo/edk/system/test_channel_endpoint_client.cc +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2015 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 "third_party/mojo/src/mojo/edk/system/test_channel_endpoint_client.h" - -#include "base/synchronization/waitable_event.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit.h" - -namespace mojo { -namespace system { -namespace test { - -TestChannelEndpointClient::TestChannelEndpointClient() - : port_(0), read_event_(nullptr) { -} - -void TestChannelEndpointClient::Init(unsigned port, ChannelEndpoint* endpoint) { - MutexLocker locker(&mutex_); - ASSERT_EQ(0u, port_); - ASSERT_FALSE(endpoint_); - port_ = port; - endpoint_ = endpoint; -} - -bool TestChannelEndpointClient::IsDetached() const { - MutexLocker locker(&mutex_); - return !endpoint_; -} - -size_t TestChannelEndpointClient::NumMessages() const { - MutexLocker locker(&mutex_); - return messages_.Size(); -} - -scoped_ptr<MessageInTransit> TestChannelEndpointClient::PopMessage() { - MutexLocker locker(&mutex_); - if (messages_.IsEmpty()) - return nullptr; - return messages_.GetMessage(); -} - -void TestChannelEndpointClient::SetReadEvent(base::WaitableEvent* read_event) { - MutexLocker locker(&mutex_); - read_event_ = read_event; -} - -bool TestChannelEndpointClient::OnReadMessage(unsigned port, - MessageInTransit* message) { - MutexLocker locker(&mutex_); - - EXPECT_EQ(port_, port); - EXPECT_TRUE(endpoint_); - messages_.AddMessage(make_scoped_ptr(message)); - - if (read_event_) - read_event_->Signal(); - - return true; -} - -void TestChannelEndpointClient::OnDetachFromChannel(unsigned port) { - MutexLocker locker(&mutex_); - - EXPECT_EQ(port_, port); - ASSERT_TRUE(endpoint_); - endpoint_->DetachFromClient(); - endpoint_ = nullptr; -} - -TestChannelEndpointClient::~TestChannelEndpointClient() { - EXPECT_FALSE(endpoint_); -} - -} // namespace test -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/test_channel_endpoint_client.h b/third_party/mojo/src/mojo/edk/system/test_channel_endpoint_client.h deleted file mode 100644 index 7ec9d0f..0000000 --- a/third_party/mojo/src/mojo/edk/system/test_channel_endpoint_client.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2015 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_TEST_CHANNEL_ENDPOINT_CLIENT_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_TEST_CHANNEL_ENDPOINT_CLIENT_H_ - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint.h" -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint_client.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit_queue.h" -#include "third_party/mojo/src/mojo/edk/system/mutex.h" - -namespace base { -class WaitableEvent; -} - -namespace mojo { -namespace system { -namespace test { - -class TestChannelEndpointClient final : public ChannelEndpointClient { - public: - TestChannelEndpointClient(); - - // Initializes with the given port and endpoint. - void Init(unsigned port, ChannelEndpoint* endpoint); - - // Returns true if we're detached from the |ChannelEndpoint|. - bool IsDetached() const; - - // Gets the current number of messages received (but not dequeued). - size_t NumMessages() const; - - // Gets/removes a message that was received (|NumMessages()| must be - // non-zero), in FIFO order. - scoped_ptr<MessageInTransit> PopMessage(); - - // Sets an event to signal when we receive a message. (|read_event| must live - // until this object is destroyed or the read event is reset to null.) - void SetReadEvent(base::WaitableEvent* read_event); - - // |ChannelEndpointClient| implementation: - bool OnReadMessage(unsigned port, MessageInTransit* message) override; - void OnDetachFromChannel(unsigned port) override; - - private: - ~TestChannelEndpointClient() override; - - mutable Mutex mutex_; - - unsigned port_ MOJO_GUARDED_BY(mutex_); - scoped_refptr<ChannelEndpoint> endpoint_ MOJO_GUARDED_BY(mutex_); - - MessageInTransitQueue messages_ MOJO_GUARDED_BY(mutex_); - - // Event to trigger if we read a message (may be null). - base::WaitableEvent* read_event_ MOJO_GUARDED_BY(mutex_); - - MOJO_DISALLOW_COPY_AND_ASSIGN(TestChannelEndpointClient); -}; - -} // namespace test -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_TEST_CHANNEL_ENDPOINT_CLIENT_H_ diff --git a/third_party/mojo/src/mojo/edk/system/test_utils.cc b/third_party/mojo/src/mojo/edk/system/test_utils.cc deleted file mode 100644 index cb012e8..0000000 --- a/third_party/mojo/src/mojo/edk/system/test_utils.cc +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/test_utils.h" - -#include <limits> - -#include "base/logging.h" -#include "base/test/test_timeouts.h" -#include "base/threading/platform_thread.h" // For |Sleep()|. -#include "build/build_config.h" - -namespace mojo { -namespace system { -namespace test { - -MojoDeadline DeadlineFromMilliseconds(unsigned milliseconds) { - return static_cast<MojoDeadline>(milliseconds) * 1000; -} - -MojoDeadline EpsilonDeadline() { -// Originally, our epsilon timeout was 10 ms, which was mostly fine but flaky on -// some Windows bots. I don't recall ever seeing flakes on other bots. At 30 ms -// tests seem reliable on Windows bots, but not at 25 ms. We'd like this timeout -// to be as small as possible (see the description in the .h file). -// -// Currently, |tiny_timeout()| is usually 100 ms (possibly scaled under ASAN, -// etc.). Based on this, set it to (usually be) 30 ms on Windows and 20 ms -// elsewhere. -#if defined(OS_WIN) || defined(OS_ANDROID) - return (TinyDeadline() * 3) / 10; -#else - return (TinyDeadline() * 2) / 10; -#endif -} - -MojoDeadline TinyDeadline() { - return static_cast<MojoDeadline>( - TestTimeouts::tiny_timeout().InMicroseconds()); -} - -MojoDeadline ActionDeadline() { - return static_cast<MojoDeadline>( - TestTimeouts::action_timeout().InMicroseconds()); -} - -void Sleep(MojoDeadline deadline) { - CHECK_LE(deadline, - static_cast<MojoDeadline>(std::numeric_limits<int64_t>::max())); - base::PlatformThread::Sleep( - base::TimeDelta::FromMicroseconds(static_cast<int64_t>(deadline))); -} - -Stopwatch::Stopwatch() { -} - -Stopwatch::~Stopwatch() { -} - -void Stopwatch::Start() { - start_time_ = base::TimeTicks::Now(); -} - -MojoDeadline Stopwatch::Elapsed() { - int64_t result = (base::TimeTicks::Now() - start_time_).InMicroseconds(); - // |DCHECK_GE|, not |CHECK_GE|, since this may be performance-important. - DCHECK_GE(result, 0); - return static_cast<MojoDeadline>(result); -} - -} // namespace test -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/test_utils.h b/third_party/mojo/src/mojo/edk/system/test_utils.h deleted file mode 100644 index c821dc1..0000000 --- a/third_party/mojo/src/mojo/edk/system/test_utils.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_TEST_UTILS_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_TEST_UTILS_H_ - -#include "base/time/time.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/macros.h" - -namespace mojo { -namespace system { -namespace test { - -MojoDeadline DeadlineFromMilliseconds(unsigned milliseconds); - -// A timeout smaller than |TestTimeouts::tiny_timeout()|, as a |MojoDeadline|. -// Warning: This may lead to flakiness, but this is unavoidable if, e.g., you're -// trying to ensure that functions with timeouts are reasonably accurate. We -// want this to be as small as possible without causing too much flakiness. -MojoDeadline EpsilonDeadline(); - -// |TestTimeouts::tiny_timeout()|, as a |MojoDeadline|. (Expect this to be on -// the order of 100 ms.) -MojoDeadline TinyDeadline(); - -// |TestTimeouts::action_timeout()|, as a |MojoDeadline|. (Expect this to be on -// the order of 10 s.) -MojoDeadline ActionDeadline(); - -// Sleeps for at least the specified duration. -void Sleep(MojoDeadline deadline); - -// Stopwatch ------------------------------------------------------------------- - -// A simple "stopwatch" for measuring time elapsed from a given starting point. -class Stopwatch { - public: - Stopwatch(); - ~Stopwatch(); - - void Start(); - // Returns the amount of time elapsed since the last call to |Start()| (in - // microseconds). - MojoDeadline Elapsed(); - - private: - base::TimeTicks start_time_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(Stopwatch); -}; - -} // namespace test -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_TEST_UTILS_H_ diff --git a/third_party/mojo/src/mojo/edk/system/thread_annotations.h b/third_party/mojo/src/mojo/edk/system/thread_annotations.h deleted file mode 100644 index a3b8377..0000000 --- a/third_party/mojo/src/mojo/edk/system/thread_annotations.h +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2015 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. - -// Macros for static thread-safety analysis. -// -// These are from http://clang.llvm.org/docs/ThreadSafetyAnalysis.html (and thus -// really derive from google3's thread_annotations.h). -// -// TODO(vtl): We're still using the old-fashioned, deprecated annotations -// ("locks" instead of "capabilities"), since the new ones don't work yet (in -// particular, |TRY_ACQUIRE()| doesn't work: b/19264527). -// https://github.com/domokit/mojo/issues/314 - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_THREAD_ANNOTATIONS_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_THREAD_ANNOTATIONS_H_ - -// Enable thread-safety attributes only with clang. -// The attributes can be safely erased when compiling with other compilers. -#if defined(__clang__) -#define MOJO_THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) -#else -#define MOJO_THREAD_ANNOTATION_ATTRIBUTE__(x) -#endif - -#define MOJO_GUARDED_BY(x) MOJO_THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) - -#define MOJO_PT_GUARDED_BY(x) \ - MOJO_THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) - -#define MOJO_ACQUIRED_AFTER(...) \ - MOJO_THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) - -#define MOJO_ACQUIRED_BEFORE(...) \ - MOJO_THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) - -#define MOJO_EXCLUSIVE_LOCKS_REQUIRED(...) \ - MOJO_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__)) - -#define MOJO_SHARED_LOCKS_REQUIRED(...) \ - MOJO_THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__)) - -#define MOJO_LOCKS_EXCLUDED(...) \ - MOJO_THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) - -#define MOJO_LOCK_RETURNED(x) \ - MOJO_THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) - -#define MOJO_LOCKABLE MOJO_THREAD_ANNOTATION_ATTRIBUTE__(lockable) - -#define MOJO_SCOPED_LOCKABLE MOJO_THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) - -#define MOJO_EXCLUSIVE_LOCK_FUNCTION(...) \ - MOJO_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__)) - -#define MOJO_SHARED_LOCK_FUNCTION(...) \ - MOJO_THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__)) - -#define MOJO_ASSERT_EXCLUSIVE_LOCK(...) \ - MOJO_THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__)) - -#define MOJO_ASSERT_SHARED_LOCK(...) \ - MOJO_THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__)) - -#define MOJO_EXCLUSIVE_TRYLOCK_FUNCTION(...) \ - MOJO_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__)) - -#define MOJO_SHARED_TRYLOCK_FUNCTION(...) \ - MOJO_THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__)) - -#define MOJO_UNLOCK_FUNCTION(...) \ - MOJO_THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__)) - -#define MOJO_NO_THREAD_SAFETY_ANALYSIS \ - MOJO_THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) - -// Use this in the header to annotate a function/method as not being -// thread-safe. This is equivalent to |MOJO_NO_THREAD_SAFETY_ANALYSIS|, but -// semantically different: it declares that the caller must abide by additional -// restrictions. Limitation: Unfortunately, you can't apply this to a method in -// an interface (i.e., pure virtual method) and have it applied automatically to -// implementations. -#define MOJO_NOT_THREAD_SAFE MOJO_NO_THREAD_SAFETY_ANALYSIS - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_THREAD_ANNOTATIONS_H_ diff --git a/third_party/mojo/src/mojo/edk/system/thread_annotations_unittest.cc b/third_party/mojo/src/mojo/edk/system/thread_annotations_unittest.cc deleted file mode 100644 index 7b0a4e5..0000000 --- a/third_party/mojo/src/mojo/edk/system/thread_annotations_unittest.cc +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2015 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. - -// Tests of the static thread annotation macros. These fall into two categories, -// positive tests (testing that correct code compiles and works) and negative -// tests (testing that incorrect code does not compile). -// -// Unfortunately, we don't have systematic/automated negative compilation tests. -// So instead we have some cheesy macros that you can define to enable -// individual compilation failures. - -#include "third_party/mojo/src/mojo/edk/system/thread_annotations.h" - -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/system/mutex.h" - -// Uncomment these to enable particular compilation failure tests. -// #define NC_GUARDED_BY -// TODO(vtl): |ACQUIRED_{BEFORE,AFTER}()| are currently unimplemented in clang -// as of 2015-07-06 ("To be fixed in a future update."). So this actually -// compiles! -// #define NC_ACQUIRED_BEFORE - -namespace mojo { -namespace system { -namespace { - -// Test MOJO_GUARDED_BY -------------------------------------------------------- - -class GuardedByClass { - public: - GuardedByClass() : x_() {} - ~GuardedByClass() {} - - void GoodSet(int x) { - mu_.Lock(); - x_ = x; - mu_.Unlock(); - } - -#ifdef NC_GUARDED_BY - void BadSet(int x) { x_ = x; } -#endif - - private: - Mutex mu_; - int x_ MOJO_GUARDED_BY(mu_); - - MOJO_DISALLOW_COPY_AND_ASSIGN(GuardedByClass); -}; - -TEST(ThreadAnnotationsTest, GuardedBy) { - GuardedByClass c; - c.GoodSet(123); -} - -// Test MOJO_ACQUIRED_BEFORE --------------------------------------------------- - -class AcquiredBeforeClass2; - -class AcquiredBeforeClass1 { - public: - AcquiredBeforeClass1() {} - ~AcquiredBeforeClass1() {} - - void NoOp() { - mu_.Lock(); - mu_.Unlock(); - } - -#ifdef NC_ACQUIRED_BEFORE - void BadMethod(AcquiredBeforeClass2* c2) { - mu_.Lock(); - c2->NoOp(); - mu_.Unlock(); - } -#endif - - private: - friend class AcquiredBeforeClass2; - - Mutex mu_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(AcquiredBeforeClass1); -}; - -class AcquiredBeforeClass2 { - public: - AcquiredBeforeClass2() {} - ~AcquiredBeforeClass2() {} - - void NoOp() { - mu_.Lock(); - mu_.Unlock(); - } - - void GoodMethod(AcquiredBeforeClass1* c1) { - mu_.Lock(); - c1->NoOp(); - mu_.Unlock(); - } - - private: - Mutex mu_ MOJO_ACQUIRED_BEFORE(AcquiredBeforeClass1::mu_); - - MOJO_DISALLOW_COPY_AND_ASSIGN(AcquiredBeforeClass2); -}; - -TEST(ThreadAnnotationsTest, AcquiredBefore) { - AcquiredBeforeClass1 c1; - AcquiredBeforeClass2 c2; - c2.GoodMethod(&c1); -#ifdef NC_ACQUIRED_BEFORE - c1.BadMethod(&c2); -#endif -} - -// TODO(vtl): Test more things. - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/transport_data.cc b/third_party/mojo/src/mojo/edk/system/transport_data.cc deleted file mode 100644 index 2605004..0000000 --- a/third_party/mojo/src/mojo/edk/system/transport_data.cc +++ /dev/null @@ -1,343 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/transport_data.h" - -#include <string.h> -#include <utility> - -#include "base/logging.h" -#include "third_party/mojo/src/mojo/edk/system/channel.h" -#include "third_party/mojo/src/mojo/edk/system/configuration.h" -#include "third_party/mojo/src/mojo/edk/system/message_in_transit.h" - -namespace mojo { -namespace system { - -// The maximum amount of space needed per platform handle. -// (|{Channel,RawChannel}::GetSerializedPlatformHandleSize()| should always -// return a value which is at most this. This is only used to calculate -// |TransportData::kMaxBufferSize|. This value should be a multiple of the -// alignment in order to simplify calculations, even though the actual amount of -// space needed need not be a multiple of the alignment. -const size_t kMaxSizePerPlatformHandle = 16; -static_assert(kMaxSizePerPlatformHandle % MessageInTransit::kMessageAlignment == - 0, - "kMaxSizePerPlatformHandle not a multiple of alignment"); - -MOJO_STATIC_CONST_MEMBER_DEFINITION const size_t - TransportData::kMaxSerializedDispatcherSize; -MOJO_STATIC_CONST_MEMBER_DEFINITION const size_t - TransportData::kMaxSerializedDispatcherPlatformHandles; - -// static -size_t TransportData::GetMaxBufferSize() { - // In additional to the header, for each attached (Mojo) handle there'll be a - // handle table entry and serialized dispatcher data. - return sizeof(Header) + - GetConfiguration().max_message_num_handles * - (sizeof(HandleTableEntry) + kMaxSerializedDispatcherSize) + - GetMaxPlatformHandles() * kMaxSizePerPlatformHandle; -} - -// static -size_t TransportData::GetMaxPlatformHandles() { - return GetConfiguration().max_message_num_handles * - kMaxSerializedDispatcherPlatformHandles; -} - -struct TransportData::PrivateStructForCompileAsserts { - static_assert(sizeof(Header) % MessageInTransit::kMessageAlignment == 0, - "sizeof(MessageInTransit::Header) not a multiple of alignment"); - static_assert(kMaxSerializedDispatcherSize % - MessageInTransit::kMessageAlignment == - 0, - "kMaxSerializedDispatcherSize not a multiple of alignment"); - static_assert(sizeof(HandleTableEntry) % - MessageInTransit::kMessageAlignment == - 0, - "sizeof(MessageInTransit::HandleTableEntry) not a multiple of " - "alignment"); -}; - -TransportData::TransportData(scoped_ptr<DispatcherVector> dispatchers, - Channel* channel) - : buffer_size_() { - DCHECK(dispatchers); - DCHECK(channel); - - const size_t num_handles = dispatchers->size(); - DCHECK_GT(num_handles, 0u); - - // The offset to the start of the (Mojo) handle table. - const size_t handle_table_start_offset = sizeof(Header); - // The offset to the start of the serialized dispatcher data. - const size_t serialized_dispatcher_start_offset = - handle_table_start_offset + num_handles * sizeof(HandleTableEntry); - // The estimated size of the secondary buffer. We compute this estimate below. - // It must be at least as big as the (eventual) actual size. - size_t estimated_size = serialized_dispatcher_start_offset; - size_t estimated_num_platform_handles = 0; -#if DCHECK_IS_ON() - std::vector<size_t> all_max_sizes(num_handles); - std::vector<size_t> all_max_platform_handles(num_handles); -#endif - for (size_t i = 0; i < num_handles; i++) { - if (Dispatcher* dispatcher = (*dispatchers)[i].get()) { - size_t max_size = 0; - size_t max_platform_handles = 0; - Dispatcher::TransportDataAccess::StartSerialize( - dispatcher, channel, &max_size, &max_platform_handles); - - DCHECK_LE(max_size, kMaxSerializedDispatcherSize); - estimated_size += MessageInTransit::RoundUpMessageAlignment(max_size); - DCHECK_LE(estimated_size, GetMaxBufferSize()); - - DCHECK_LE(max_platform_handles, kMaxSerializedDispatcherPlatformHandles); - estimated_num_platform_handles += max_platform_handles; - DCHECK_LE(estimated_num_platform_handles, GetMaxPlatformHandles()); - -#if DCHECK_IS_ON() - all_max_sizes[i] = max_size; - all_max_platform_handles[i] = max_platform_handles; -#endif - } - } - - size_t size_per_platform_handle = 0; - if (estimated_num_platform_handles > 0) { - size_per_platform_handle = channel->GetSerializedPlatformHandleSize(); - DCHECK_LE(size_per_platform_handle, kMaxSizePerPlatformHandle); - estimated_size += estimated_num_platform_handles * size_per_platform_handle; - estimated_size = MessageInTransit::RoundUpMessageAlignment(estimated_size); - DCHECK_LE(estimated_size, GetMaxBufferSize()); - } - - buffer_.reset(static_cast<char*>( - base::AlignedAlloc(estimated_size, MessageInTransit::kMessageAlignment))); - // Entirely clear out the secondary buffer, since then we won't have to worry - // about clearing padding or unused space (e.g., if a dispatcher fails to - // serialize). - memset(buffer_.get(), 0, estimated_size); - - if (estimated_num_platform_handles > 0) { - DCHECK(!platform_handles_); - platform_handles_.reset(new embedder::PlatformHandleVector()); - } - - Header* header = reinterpret_cast<Header*>(buffer_.get()); - header->num_handles = static_cast<uint32_t>(num_handles); - // (Okay to leave |platform_handle_table_offset|, |num_platform_handles|, and - // |unused| be zero; we'll set the former two later if necessary.) - - HandleTableEntry* handle_table = reinterpret_cast<HandleTableEntry*>( - buffer_.get() + handle_table_start_offset); - size_t current_offset = serialized_dispatcher_start_offset; - for (size_t i = 0; i < num_handles; i++) { - Dispatcher* dispatcher = (*dispatchers)[i].get(); - if (!dispatcher) { - static_assert(static_cast<int32_t>(Dispatcher::Type::UNKNOWN) == 0, - "Value of Dispatcher::Type::UNKNOWN must be 0"); - continue; - } - -#if DCHECK_IS_ON() - size_t old_platform_handles_size = - platform_handles_ ? platform_handles_->size() : 0; -#endif - - void* destination = buffer_.get() + current_offset; - size_t actual_size = 0; - if (Dispatcher::TransportDataAccess::EndSerializeAndClose( - dispatcher, channel, destination, &actual_size, - platform_handles_.get())) { - handle_table[i].type = static_cast<int32_t>(dispatcher->GetType()); - handle_table[i].offset = static_cast<uint32_t>(current_offset); - handle_table[i].size = static_cast<uint32_t>(actual_size); -// (Okay to not set |unused| since we cleared the entire buffer.) - -#if DCHECK_IS_ON() - DCHECK_LE(actual_size, all_max_sizes[i]); - DCHECK_LE(platform_handles_ - ? (platform_handles_->size() - old_platform_handles_size) - : 0, - all_max_platform_handles[i]); -#endif - } else { - // Nothing to do on failure, since |buffer_| was cleared, and - // |Type::UNKNOWN| is zero. The handle was simply closed. - LOG(ERROR) << "Failed to serialize handle to remote message pipe"; - } - - current_offset += MessageInTransit::RoundUpMessageAlignment(actual_size); - DCHECK_LE(current_offset, estimated_size); - DCHECK_LE(platform_handles_ ? platform_handles_->size() : 0, - estimated_num_platform_handles); - } - - if (platform_handles_ && platform_handles_->size() > 0) { - header->platform_handle_table_offset = - static_cast<uint32_t>(current_offset); - header->num_platform_handles = - static_cast<uint32_t>(platform_handles_->size()); - current_offset += platform_handles_->size() * size_per_platform_handle; - current_offset = MessageInTransit::RoundUpMessageAlignment(current_offset); - } - - // There's no aligned realloc, so it's no good way to release unused space (if - // we overshot our estimated space requirements). - buffer_size_ = current_offset; - - // |dispatchers_| will be destroyed as it goes out of scope. -} - -TransportData::TransportData( - embedder::ScopedPlatformHandleVectorPtr platform_handles, - size_t serialized_platform_handle_size) - : buffer_size_(), platform_handles_(std::move(platform_handles)) { - buffer_size_ = MessageInTransit::RoundUpMessageAlignment( - sizeof(Header) + - platform_handles_->size() * serialized_platform_handle_size); - buffer_.reset(static_cast<char*>( - base::AlignedAlloc(buffer_size_, MessageInTransit::kMessageAlignment))); - memset(buffer_.get(), 0, buffer_size_); - - Header* header = reinterpret_cast<Header*>(buffer_.get()); - header->platform_handle_table_offset = static_cast<uint32_t>(sizeof(Header)); - header->num_platform_handles = - static_cast<uint32_t>(platform_handles_->size()); -} - -TransportData::~TransportData() { -} - -// static -const char* TransportData::ValidateBuffer( - size_t serialized_platform_handle_size, - const void* buffer, - size_t buffer_size) { - DCHECK(buffer); - DCHECK_GT(buffer_size, 0u); - - // Always make sure that the buffer size is sane; if it's not, someone's - // messing with us. - if (buffer_size < sizeof(Header) || buffer_size > GetMaxBufferSize() || - buffer_size % MessageInTransit::kMessageAlignment != 0) - return "Invalid message secondary buffer size"; - - const Header* header = static_cast<const Header*>(buffer); - const size_t num_handles = header->num_handles; - - // Sanity-check |num_handles| (before multiplying it against anything). - if (num_handles > GetConfiguration().max_message_num_handles) - return "Message handle payload too large"; - - if (buffer_size < sizeof(Header) + num_handles * sizeof(HandleTableEntry)) - return "Message secondary buffer too small"; - - if (header->num_platform_handles == 0) { - // Then |platform_handle_table_offset| should also be zero. - if (header->platform_handle_table_offset != 0) { - return "Message has no handles attached, but platform handle table " - "present"; - } - } else { - if (header->num_platform_handles > - GetConfiguration().max_message_num_handles * - kMaxSerializedDispatcherPlatformHandles) - return "Message has too many platform handles attached"; - - static const char kInvalidPlatformHandleTableOffset[] = - "Message has invalid platform handle table offset"; - // This doesn't check that the platform handle table doesn't alias other - // stuff, but it doesn't matter, since it's all read-only. - if (header->platform_handle_table_offset % - MessageInTransit::kMessageAlignment != - 0) - return kInvalidPlatformHandleTableOffset; - - // ">" instead of ">=" since the size per handle may be zero. - if (header->platform_handle_table_offset > buffer_size) - return kInvalidPlatformHandleTableOffset; - - // We already checked |platform_handle_table_offset| and - // |num_platform_handles|, so the addition and multiplication are okay. - if (header->platform_handle_table_offset + - header->num_platform_handles * serialized_platform_handle_size > - buffer_size) - return kInvalidPlatformHandleTableOffset; - } - - const HandleTableEntry* handle_table = - reinterpret_cast<const HandleTableEntry*>( - static_cast<const char*>(buffer) + sizeof(Header)); - static const char kInvalidSerializedDispatcher[] = - "Message contains invalid serialized dispatcher"; - for (size_t i = 0; i < num_handles; i++) { - size_t offset = handle_table[i].offset; - if (offset % MessageInTransit::kMessageAlignment != 0) - return kInvalidSerializedDispatcher; - - size_t size = handle_table[i].size; - if (size > kMaxSerializedDispatcherSize || size > buffer_size) - return kInvalidSerializedDispatcher; - - // Note: This is an overflow-safe check for |offset + size > buffer_size| - // (we know that |size <= buffer_size| from the previous check). - if (offset > buffer_size - size) - return kInvalidSerializedDispatcher; - } - - return nullptr; -} - -// static -void TransportData::GetPlatformHandleTable(const void* transport_data_buffer, - size_t* num_platform_handles, - const void** platform_handle_table) { - DCHECK(transport_data_buffer); - DCHECK(num_platform_handles); - DCHECK(platform_handle_table); - - const Header* header = static_cast<const Header*>(transport_data_buffer); - *num_platform_handles = header->num_platform_handles; - *platform_handle_table = static_cast<const char*>(transport_data_buffer) + - header->platform_handle_table_offset; -} - -// static -scoped_ptr<DispatcherVector> TransportData::DeserializeDispatchers( - const void* buffer, - size_t buffer_size, - embedder::ScopedPlatformHandleVectorPtr platform_handles, - Channel* channel) { - DCHECK(buffer); - DCHECK_GT(buffer_size, 0u); - DCHECK(channel); - - const Header* header = static_cast<const Header*>(buffer); - const size_t num_handles = header->num_handles; - scoped_ptr<DispatcherVector> dispatchers(new DispatcherVector(num_handles)); - - const HandleTableEntry* handle_table = - reinterpret_cast<const HandleTableEntry*>( - static_cast<const char*>(buffer) + sizeof(Header)); - for (size_t i = 0; i < num_handles; i++) { - size_t offset = handle_table[i].offset; - size_t size = handle_table[i].size; - // Should already have been checked by |ValidateBuffer()|: - DCHECK_EQ(offset % MessageInTransit::kMessageAlignment, 0u); - DCHECK_LE(offset, buffer_size); - DCHECK_LE(offset + size, buffer_size); - - const void* source = static_cast<const char*>(buffer) + offset; - (*dispatchers)[i] = Dispatcher::TransportDataAccess::Deserialize( - channel, handle_table[i].type, source, size, platform_handles.get()); - } - - return dispatchers; -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/transport_data.h b/third_party/mojo/src/mojo/edk/system/transport_data.h deleted file mode 100644 index ea94139..0000000 --- a/third_party/mojo/src/mojo/edk/system/transport_data.h +++ /dev/null @@ -1,191 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_TRANSPORT_DATA_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_TRANSPORT_DATA_H_ - -#include <stdint.h> - -#include <vector> - -#include "base/memory/aligned_memory.h" -#include "base/memory/scoped_ptr.h" -#include "build/build_config.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle_vector.h" -#include "third_party/mojo/src/mojo/edk/system/dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -class Channel; - -// This class is used by |MessageInTransit| to represent handles (|Dispatcher|s) -// in various stages of serialization. -// -// The stages are: -// - Before reaching |TransportData|: Turn |DispatcherTransport|s into -// |Dispatcher|s that are "owned" by (and attached to) a |MessageInTransit|. -// This invalidates the handles in the space of the sending application -// (and, e.g., if another thread is waiting on such a handle, it'll be -// notified of this invalidation). -// - Serialize these dispatchers into the |TransportData|: First, for each -// attached dispatcher, there's an entry in the |TransportData|'s "handle -// table", which points to a segment of (dispatcher-type-dependent) data. -// - During the serialization of the dispatchers, |PlatformHandle|s may be -// detached from the dispatchers and attached to the |TransportData|. -// - Before sending the |MessageInTransit|, including its main buffer and the -// |TransportData|'s buffer, the |Channel| sends any |PlatformHandle|s (in a -// platform-, and possibly sandbox-situation-, specific way) first. In doing -// so, it appends a "platform handle table" to the |TransportData| -// containing information about how to deserialize these |PlatformHandle|s. -// - Finally, at this point, to send the |MessageInTransit|, there only -// remains "inert" data: the |MessageInTransit|'s main buffer and data from -// the |TransportData|, consisting of the "handle table" (one entry for each -// attached dispatcher), dispatcher-type-specific data (one segment for each -// entry in the "handle table"), and the "platform handle table" (one entry -// for each attached |PlatformHandle|). -// -// To receive a message (|MessageInTransit|), the "reverse" happens: -// - On POSIX, receive and buffer |PlatformHandle|s (i.e., FDs), which were -// sent before the "inert" data. -// - Receive the "inert" data from the |MessageInTransit|. Examine its -// "platform handle table". On POSIX, match its entries with the buffered -// |PlatformHandle|s, which were previously received. On Windows, do what's -// necessary to obtain |PlatformHandle|s (e.g.: i. if the sender is fully -// trusted and able to duplicate handle into the receiver, then just pick -// out the |HANDLE| value; ii. if the receiver is fully trusted and able to -// duplicate handles from the receiver, do the |DuplicateHandle()|; iii. -// otherwise, talk to a broker to get handles). Reattach all the -// |PlatformHandle|s to the |MessageInTransit|. -// - For each entry in the "handle table", use serialized dispatcher data to -// reconstitute a dispatcher, taking ownership of associated -// |PlatformHandle|s (and detaching them). Attach these dispatchers to the -// |MessageInTransit|. -// - At this point, the |MessageInTransit| consists of its main buffer -// (primarily the data payload) and the attached dispatchers; the -// |TransportData| can be discarded. -// - When |MojoReadMessage()| is to give data to the application, attach the -// dispatchers to the (global, "core") handle table, getting handles; give -// the application the data payload and these handles. -// -// TODO(vtl): Everything above involving |PlatformHandle|s. -class MOJO_SYSTEM_IMPL_EXPORT TransportData { - public: - // The maximum size of a single serialized dispatcher. This must be a multiple - // of |kMessageAlignment|. - static const size_t kMaxSerializedDispatcherSize = 10000; - - // The maximum number of platform handles to attach for a single serialized - // dispatcher. - static const size_t kMaxSerializedDispatcherPlatformHandles = 2; - - // The maximum possible size of a valid transport data buffer. - static size_t GetMaxBufferSize(); - - // The maximum total number of platform handles that may be attached. - static size_t GetMaxPlatformHandles(); - - TransportData(scoped_ptr<DispatcherVector> dispatchers, Channel* channel); - - // This is used for users of |MessageInTransit|/|TransportData|/|RawChannel| - // that want to simply transport data and platform handles, and not - // |Dispatcher|s. (|Header| will be present, and zero except for - // |num_platform_handles|, and |platform_handle_table_offset| if necessary.) - explicit TransportData( - embedder::ScopedPlatformHandleVectorPtr platform_handles, - size_t serialized_platform_handle_size); - - ~TransportData(); - - const void* buffer() const { return buffer_.get(); } - void* buffer() { return buffer_.get(); } - size_t buffer_size() const { return buffer_size_; } - - uint32_t platform_handle_table_offset() const { - return header()->platform_handle_table_offset; - } - - // Gets attached platform-specific handles; this may return null if there are - // none. Note that the caller may mutate the set of platform-specific handles. - const embedder::PlatformHandleVector* platform_handles() const { - return platform_handles_.get(); - } - embedder::PlatformHandleVector* platform_handles() { - return platform_handles_.get(); - } - - // Receive-side functions: - - // Checks if the given buffer (from the "wire") looks like a valid - // |TransportData| buffer. (Should only be called if |buffer_size| is - // nonzero.) Returns null if valid, and a pointer to a human-readable error - // message (for debug/logging purposes) on error. Note: This checks the - // validity of the handle table entries (i.e., does range checking), but does - // not check that the validity of the actual serialized dispatcher - // information. - static const char* ValidateBuffer(size_t serialized_platform_handle_size, - const void* buffer, - size_t buffer_size); - - // Gets the platform handle table from a (valid) |TransportData| buffer (which - // should have been validated using |ValidateBuffer()| first). - static void GetPlatformHandleTable(const void* transport_data_buffer, - size_t* num_platform_handles, - const void** platform_handle_table); - - // Deserializes dispatchers from the given (serialized) transport data buffer - // (typically from a |MessageInTransit::View|) and vector of platform handles. - // |buffer| should be non-null and |buffer_size| should be nonzero. - static scoped_ptr<DispatcherVector> DeserializeDispatchers( - const void* buffer, - size_t buffer_size, - embedder::ScopedPlatformHandleVectorPtr platform_handles, - Channel* channel); - - private: - // To allow us to make compile-assertions about |Header|, etc. in the .cc - // file. - struct PrivateStructForCompileAsserts; - - // Header for the "secondary buffer"/"transport data". Must be a multiple of - // |MessageInTransit::kMessageAlignment| in size. Must be POD. - struct Header { - uint32_t num_handles; - // TODO(vtl): Not used yet: - uint32_t platform_handle_table_offset; - uint32_t num_platform_handles; - uint32_t unused; - }; - - struct HandleTableEntry { - // TODO(vtl): Should I make |Dispatcher::Type| an |int32_t| enum class? - int32_t type; // From |Dispatcher::Type| (|UNKNOWN| for "invalid"). - uint32_t offset; // Relative to the start of the "secondary buffer". - uint32_t size; // (Not including any padding.) - uint32_t unused; - }; - - const Header* header() const { - return reinterpret_cast<const Header*>(buffer_.get()); - } - - size_t buffer_size_; - scoped_ptr<char, base::AlignedFreeDeleter> buffer_; // Never null. - - // Any platform-specific handles attached to this message (for inter-process - // transport). The vector (if any) owns the handles that it contains (and is - // responsible for closing them). - // TODO(vtl): With C++11, change it to a vector of |ScopedPlatformHandle|s. - embedder::ScopedPlatformHandleVectorPtr platform_handles_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(TransportData); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_TRANSPORT_DATA_H_ diff --git a/third_party/mojo/src/mojo/edk/system/unique_identifier.cc b/third_party/mojo/src/mojo/edk/system/unique_identifier.cc deleted file mode 100644 index 22abf22..0000000 --- a/third_party/mojo/src/mojo/edk/system/unique_identifier.cc +++ /dev/null @@ -1,45 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/unique_identifier.h" - -#include <stdint.h> - -#include <vector> - -#include "base/strings/string_number_conversions.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_support.h" - -namespace mojo { -namespace system { - -// static -UniqueIdentifier UniqueIdentifier::Generate( - embedder::PlatformSupport* platform_support) { - UniqueIdentifier rv; - platform_support->GetCryptoRandomBytes(rv.data_, sizeof(rv.data_)); - return rv; -} - -// static -UniqueIdentifier UniqueIdentifier::FromString(const std::string& s, - bool* success) { - UniqueIdentifier rv; - std::vector<uint8_t> bytes; - if (base::HexStringToBytes(s, &bytes) && bytes.size() == sizeof(rv.data_)) { - memcpy(rv.data_, &bytes[0], sizeof(rv.data_)); - *success = true; - } else { - *success = false; - } - return rv; -} - -std::string UniqueIdentifier::ToString() const { - // TODO(vtl): Maybe we should base-64 encode instead? - return base::HexEncode(data_, sizeof(data_)); -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/unique_identifier.h b/third_party/mojo/src/mojo/edk/system/unique_identifier.h deleted file mode 100644 index 0991c38..0000000 --- a/third_party/mojo/src/mojo/edk/system/unique_identifier.h +++ /dev/null @@ -1,104 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_UNIQUE_IDENTIFIER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_UNIQUE_IDENTIFIER_H_ - -#include <stdint.h> -#include <string.h> - -#include <string> - -#include "base/containers/hash_tables.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -class UniqueIdentifier; - -} // namespace system -} // namespace mojo - -namespace BASE_HASH_NAMESPACE { - -// Declare this before |UniqueIdentifier|, so that it can be friended. -template <> -struct hash<mojo::system::UniqueIdentifier>; - -} // BASE_HASH_NAMESPACE - -namespace mojo { - -namespace embedder { - -class PlatformSupport; - -} // namespace embedder - -namespace system { - -// |UniqueIdentifier| is a POD class whose value is used to uniquely identify -// things. -class MOJO_SYSTEM_IMPL_EXPORT UniqueIdentifier { - public: - // This generates a new identifier. Uniqueness is "guaranteed" (i.e., - // probabilistically) for identifiers. - static UniqueIdentifier Generate(embedder::PlatformSupport* platform_support); - - // This reconstitutes an identifier from its representation as a string - // (generated by |ToString()|, below). On success, |*success| is set to true; - // on failure, it is set to false (and the return value is undefined). - static UniqueIdentifier FromString(const std::string& s, bool* success); - - // Yields a string representation of this identifier (which can be - // reconstituted using |FromString()|. The result will consist of printable, - // non-whitespace ASCII characters. It will *not* contain the following - // characters: ", ', or \. - std::string ToString() const; - - bool operator==(const UniqueIdentifier& other) const { - return memcmp(data_, other.data_, sizeof(data_)) == 0; - } - bool operator!=(const UniqueIdentifier& other) const { - return !operator==(other); - } - bool operator<(const UniqueIdentifier& other) const { - return memcmp(data_, other.data_, sizeof(data_)) < 0; - } - - private: - friend BASE_HASH_NAMESPACE::hash<mojo::system::UniqueIdentifier>; - - explicit UniqueIdentifier() {} - - char data_[16]; - - // Copying and assignment allowed. -}; -static_assert(sizeof(UniqueIdentifier) == 16, - "UniqueIdentifier has wrong size."); -// We want to be able to take any buffer and cast it to a |UniqueIdentifier|. -static_assert(MOJO_ALIGNOF(UniqueIdentifier) == 1, - "UniqueIdentifier requires nontrivial alignment."); - -} // namespace system -} // namespace mojo - -namespace BASE_HASH_NAMESPACE { - -template <> -struct hash<mojo::system::UniqueIdentifier> { - size_t operator()(mojo::system::UniqueIdentifier unique_identifier) const { - return base::HashInts64( - *reinterpret_cast<uint64_t*>(unique_identifier.data_), - *reinterpret_cast<uint64_t*>(unique_identifier.data_ + - sizeof(uint64_t))); - } -}; - -} // BASE_HASH_NAMESPACE - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_UNIQUE_IDENTIFIER_H_ diff --git a/third_party/mojo/src/mojo/edk/system/unique_identifier_unittest.cc b/third_party/mojo/src/mojo/edk/system/unique_identifier_unittest.cc deleted file mode 100644 index 76f5db5..0000000 --- a/third_party/mojo/src/mojo/edk/system/unique_identifier_unittest.cc +++ /dev/null @@ -1,168 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/system/unique_identifier.h" - -#include <set> -#include <string> - -#include "base/containers/hash_tables.h" -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h" - -namespace mojo { -namespace system { -namespace { - -class UniqueIdentifierTest : public testing::Test { - public: - UniqueIdentifierTest() {} - ~UniqueIdentifierTest() override {} - - embedder::PlatformSupport* platform_support() { return &platform_support_; } - - private: - embedder::SimplePlatformSupport platform_support_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(UniqueIdentifierTest); -}; - -TEST_F(UniqueIdentifierTest, Basic) { - // (This also checks copy constructibility.) - UniqueIdentifier id1 = UniqueIdentifier::Generate(platform_support()); - - EXPECT_EQ(id1, id1); - EXPECT_FALSE(id1 != id1); - EXPECT_FALSE(id1 < id1); - - UniqueIdentifier id2 = UniqueIdentifier::Generate(platform_support()); - - EXPECT_FALSE(id2 == id1); - EXPECT_NE(id2, id1); - EXPECT_TRUE((id1 < id2) ^ (id2 < id1)); - - // Test copyability. - id2 = id1; -} - -TEST_F(UniqueIdentifierTest, ToString) { - UniqueIdentifier id1 = UniqueIdentifier::Generate(platform_support()); - std::string id1_string = id1.ToString(); - EXPECT_FALSE(id1_string.empty()); - - // The string should be printable, and not contain certain characters. - for (size_t i = 0; i < id1_string.size(); i++) { - char c = id1_string[i]; - // Printable characters, not including space. - EXPECT_GT(c, ' '); - EXPECT_LE(c, '\x7e'); - // Single and double quotes, and backslashes are disallowed. - EXPECT_NE(c, '\''); - EXPECT_NE(c, '"'); - EXPECT_NE(c, '\\'); - } - - UniqueIdentifier id2 = UniqueIdentifier::Generate(platform_support()); - std::string id2_string = id2.ToString(); - EXPECT_FALSE(id2_string.empty()); - - EXPECT_NE(id1, id2); - EXPECT_NE(id1_string, id2_string); -} - -TEST_F(UniqueIdentifierTest, FromString) { - UniqueIdentifier id = UniqueIdentifier::Generate(platform_support()); - std::string id_string = id.ToString(); - EXPECT_FALSE(id_string.empty()); - - bool success = false; - UniqueIdentifier id_restored = - UniqueIdentifier::FromString(id_string, &success); - EXPECT_TRUE(success); - EXPECT_EQ(id, id_restored); -} - -TEST_F(UniqueIdentifierTest, FromStringFailures) { - bool success = true; - UniqueIdentifier::FromString("", &success); - EXPECT_FALSE(success); - - // That the cases below will fail requires *some* knowledge of the (private) - // encoding. So first check something that we know should succeed, to roughly - // confirm our knowledge. - success = false; - UniqueIdentifier::FromString("0123456789abcdef0123456789ABCDEF", &success); - EXPECT_TRUE(success); - - success = true; - UniqueIdentifier::FromString("!@#$%^&*()_+-=/\\,.<>[]{};':\"|", &success); - EXPECT_FALSE(success); - - success = true; - UniqueIdentifier::FromString("0123456789abcdef0123456789ABCDE", &success); - EXPECT_FALSE(success); - - success = true; - UniqueIdentifier::FromString("0123456789abcdef0123456789ABCD", &success); - EXPECT_FALSE(success); -} - -TEST_F(UniqueIdentifierTest, StdSet) { - std::set<UniqueIdentifier> s; - EXPECT_TRUE(s.empty()); - - UniqueIdentifier id1 = UniqueIdentifier::Generate(platform_support()); - EXPECT_TRUE(s.find(id1) == s.end()); - s.insert(id1); - EXPECT_TRUE(s.find(id1) != s.end()); - EXPECT_FALSE(s.empty()); - - UniqueIdentifier id2 = UniqueIdentifier::Generate(platform_support()); - EXPECT_TRUE(s.find(id2) == s.end()); - s.insert(id2); - EXPECT_TRUE(s.find(id2) != s.end()); - // Make sure |id1| is still in |s|. - EXPECT_TRUE(s.find(id1) != s.end()); - - s.erase(id1); - EXPECT_TRUE(s.find(id1) == s.end()); - // Make sure |id2| is still in |s|. - EXPECT_TRUE(s.find(id2) != s.end()); - - s.erase(id2); - EXPECT_TRUE(s.find(id2) == s.end()); - EXPECT_TRUE(s.empty()); -} - -TEST_F(UniqueIdentifierTest, HashSet) { - base::hash_set<UniqueIdentifier> s; - EXPECT_TRUE(s.empty()); - - UniqueIdentifier id1 = UniqueIdentifier::Generate(platform_support()); - EXPECT_TRUE(s.find(id1) == s.end()); - s.insert(id1); - EXPECT_TRUE(s.find(id1) != s.end()); - EXPECT_FALSE(s.empty()); - - UniqueIdentifier id2 = UniqueIdentifier::Generate(platform_support()); - EXPECT_TRUE(s.find(id2) == s.end()); - s.insert(id2); - EXPECT_TRUE(s.find(id2) != s.end()); - // Make sure |id1| is still in |s|. - EXPECT_TRUE(s.find(id1) != s.end()); - - s.erase(id1); - EXPECT_TRUE(s.find(id1) == s.end()); - // Make sure |id2| is still in |s|. - EXPECT_TRUE(s.find(id2) != s.end()); - - s.erase(id2); - EXPECT_TRUE(s.find(id2) == s.end()); - EXPECT_TRUE(s.empty()); -} - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/wait_set_dispatcher.cc b/third_party/mojo/src/mojo/edk/system/wait_set_dispatcher.cc deleted file mode 100644 index 45518e7..0000000 --- a/third_party/mojo/src/mojo/edk/system/wait_set_dispatcher.cc +++ /dev/null @@ -1,277 +0,0 @@ -// Copyright 2015 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 "third_party/mojo/src/mojo/edk/system/wait_set_dispatcher.h" - -#include <algorithm> -#include <utility> - -#include "base/logging.h" -#include "third_party/mojo/src/mojo/edk/system/awakable.h" - -namespace mojo { -namespace system { - -class WaitSetDispatcher::Waiter final : public Awakable { - public: - explicit Waiter(WaitSetDispatcher* dispatcher) : dispatcher_(dispatcher) {} - ~Waiter() {} - - // |Awakable| implementation. - bool Awake(MojoResult result, uintptr_t context) override { - // Note: This is called with various Mojo locks held. - dispatcher_->WakeDispatcher(result, context); - // Removes |this| from the dispatcher's list of waiters. - return false; - } - - private: - WaitSetDispatcher* const dispatcher_; -}; - -WaitSetDispatcher::WaitSetDispatcher() - : waiter_(new WaitSetDispatcher::Waiter(this)) {} - -WaitSetDispatcher::~WaitSetDispatcher() { - DCHECK(waiting_dispatchers_.empty()); - DCHECK(awoken_queue_.empty()); - DCHECK(processed_dispatchers_.empty()); -} - -Dispatcher::Type WaitSetDispatcher::GetType() const { - return Type::WAIT_SET; -} - -void WaitSetDispatcher::CloseImplNoLock() { - mutex().AssertHeld(); - for (const auto& entry : waiting_dispatchers_) - entry.second.dispatcher->RemoveAwakable(waiter_.get(), nullptr); - waiting_dispatchers_.clear(); - - MutexLocker locker(&awoken_mutex_); - awoken_queue_.clear(); - processed_dispatchers_.clear(); -} - -MojoResult WaitSetDispatcher::AddWaitingDispatcherImplNoLock( - const scoped_refptr<Dispatcher>& dispatcher, - MojoHandleSignals signals, - uintptr_t context) { - mutex().AssertHeld(); - if (dispatcher == this) - return MOJO_RESULT_INVALID_ARGUMENT; - - uintptr_t dispatcher_handle = reinterpret_cast<uintptr_t>(dispatcher.get()); - auto it = waiting_dispatchers_.find(dispatcher_handle); - if (it != waiting_dispatchers_.end()) { - return MOJO_RESULT_ALREADY_EXISTS; - } - - const MojoResult result = dispatcher->AddAwakable(waiter_.get(), signals, - dispatcher_handle, nullptr); - if (result == MOJO_RESULT_INVALID_ARGUMENT) { - // Dispatcher is closed. - return result; - } else if (result != MOJO_RESULT_OK) { - WakeDispatcher(result, dispatcher_handle); - } - - WaitState state; - state.dispatcher = dispatcher; - state.context = context; - state.signals = signals; - bool inserted = - waiting_dispatchers_.insert(std::make_pair(dispatcher_handle, state)) - .second; - DCHECK(inserted); - - return MOJO_RESULT_OK; -} - -MojoResult WaitSetDispatcher::RemoveWaitingDispatcherImplNoLock( - const scoped_refptr<Dispatcher>& dispatcher) { - mutex().AssertHeld(); - uintptr_t dispatcher_handle = reinterpret_cast<uintptr_t>(dispatcher.get()); - auto it = waiting_dispatchers_.find(dispatcher_handle); - if (it == waiting_dispatchers_.end()) - return MOJO_RESULT_NOT_FOUND; - - dispatcher->RemoveAwakable(waiter_.get(), nullptr); - // At this point, it should not be possible for |waiter_| to be woken with - // |dispatcher|. - waiting_dispatchers_.erase(it); - - MutexLocker locker(&awoken_mutex_); - int num_erased = 0; - for (auto it = awoken_queue_.begin(); it != awoken_queue_.end();) { - if (it->first == dispatcher_handle) { - it = awoken_queue_.erase(it); - num_erased++; - } else { - ++it; - } - } - // The dispatcher should only exist in the queue once. - DCHECK_LE(num_erased, 1); - processed_dispatchers_.erase( - std::remove(processed_dispatchers_.begin(), processed_dispatchers_.end(), - dispatcher_handle), - processed_dispatchers_.end()); - - return MOJO_RESULT_OK; -} - -MojoResult WaitSetDispatcher::GetReadyDispatchersImplNoLock( - UserPointer<uint32_t> count, - DispatcherVector* dispatchers, - UserPointer<MojoResult> results, - UserPointer<uintptr_t> contexts) { - mutex().AssertHeld(); - dispatchers->clear(); - - // Re-queue any already retrieved dispatchers. These should be the dispatchers - // that were returned on the last call to this function. This loop is - // necessary to preserve the logically level-triggering behaviour of waiting - // in Mojo. In particular, if no action is taken on a signal, that signal - // continues to be satisfied, and therefore a |MojoWait()| on that - // handle/signal continues to return immediately. - std::deque<uintptr_t> pending; - { - MutexLocker locker(&awoken_mutex_); - pending.swap(processed_dispatchers_); - } - for (uintptr_t d : pending) { - auto it = waiting_dispatchers_.find(d); - // Anything in |processed_dispatchers_| should also be in - // |waiting_dispatchers_| since dispatchers are removed from both in - // |RemoveWaitingDispatcherImplNoLock()|. - DCHECK(it != waiting_dispatchers_.end()); - - // |awoken_mutex_| cannot be held here because - // |Dispatcher::AddAwakable()| acquires the Dispatcher's mutex. This - // mutex is held while running |WakeDispatcher()| below, which needs to - // acquire |awoken_mutex_|. Holding |awoken_mutex_| here would result in - // a deadlock. - const MojoResult result = it->second.dispatcher->AddAwakable( - waiter_.get(), it->second.signals, d, nullptr); - - if (result == MOJO_RESULT_INVALID_ARGUMENT) { - // Dispatcher is closed. Implicitly remove it from the wait set since - // it may be impossible to remove using |MojoRemoveHandle()|. - waiting_dispatchers_.erase(it); - } else if (result != MOJO_RESULT_OK) { - WakeDispatcher(result, d); - } - } - - const uint32_t max_woken = count.Get(); - uint32_t num_woken = 0; - - MutexLocker locker(&awoken_mutex_); - while (!awoken_queue_.empty() && num_woken < max_woken) { - uintptr_t d = awoken_queue_.front().first; - MojoResult result = awoken_queue_.front().second; - awoken_queue_.pop_front(); - - auto it = waiting_dispatchers_.find(d); - DCHECK(it != waiting_dispatchers_.end()); - - results.At(num_woken).Put(result); - dispatchers->push_back(it->second.dispatcher); - if (!contexts.IsNull()) - contexts.At(num_woken).Put(it->second.context); - - if (result != MOJO_RESULT_CANCELLED) { - processed_dispatchers_.push_back(d); - } else { - waiting_dispatchers_.erase(it); - } - - num_woken++; - } - - count.Put(num_woken); - if (!num_woken) - return MOJO_RESULT_SHOULD_WAIT; - - return MOJO_RESULT_OK; -} - -void WaitSetDispatcher::CancelAllAwakablesNoLock() { - mutex().AssertHeld(); - MutexLocker locker(&awakable_mutex_); - awakable_list_.CancelAll(); -} - -MojoResult WaitSetDispatcher::AddAwakableImplNoLock( - Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state) { - mutex().AssertHeld(); - - HandleSignalsState state(GetHandleSignalsStateImplNoLock()); - if (state.satisfies(signals)) { - if (signals_state) - *signals_state = state; - return MOJO_RESULT_ALREADY_EXISTS; - } - if (!state.can_satisfy(signals)) { - if (signals_state) - *signals_state = state; - return MOJO_RESULT_FAILED_PRECONDITION; - } - - MutexLocker locker(&awakable_mutex_); - awakable_list_.Add(awakable, signals, context); - return MOJO_RESULT_OK; -} - -void WaitSetDispatcher::RemoveAwakableImplNoLock( - Awakable* awakable, - HandleSignalsState* signals_state) { - mutex().AssertHeld(); - MutexLocker locker(&awakable_mutex_); - awakable_list_.Remove(awakable); - if (signals_state) - *signals_state = GetHandleSignalsStateImplNoLock(); -} - -HandleSignalsState WaitSetDispatcher::GetHandleSignalsStateImplNoLock() const { - mutex().AssertHeld(); - HandleSignalsState rv; - rv.satisfiable_signals = MOJO_HANDLE_SIGNAL_READABLE; - MutexLocker locker(&awoken_mutex_); - if (!awoken_queue_.empty() || !processed_dispatchers_.empty()) - rv.satisfied_signals = MOJO_HANDLE_SIGNAL_READABLE; - return rv; -} - -scoped_refptr<Dispatcher> -WaitSetDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() { - mutex().AssertHeld(); - LOG(ERROR) << "Attempting to serialize WaitSet"; - CloseImplNoLock(); - return new WaitSetDispatcher(); -} - -void WaitSetDispatcher::WakeDispatcher(MojoResult result, uintptr_t context) { - { - MutexLocker locker(&awoken_mutex_); - - if (result == MOJO_RESULT_ALREADY_EXISTS) - result = MOJO_RESULT_OK; - - awoken_queue_.push_back(std::make_pair(context, result)); - } - - MutexLocker locker(&awakable_mutex_); - HandleSignalsState signals_state; - signals_state.satisfiable_signals = MOJO_HANDLE_SIGNAL_READABLE; - signals_state.satisfied_signals = MOJO_HANDLE_SIGNAL_READABLE; - awakable_list_.AwakeForStateChange(signals_state); -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/wait_set_dispatcher.h b/third_party/mojo/src/mojo/edk/system/wait_set_dispatcher.h deleted file mode 100644 index a53f61a..0000000 --- a/third_party/mojo/src/mojo/edk/system/wait_set_dispatcher.h +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2015 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_WAIT_SET_DISPATCHER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_WAIT_SET_DISPATCHER_H_ - -#include <deque> -#include <map> -#include <utility> - -#include "base/memory/scoped_ptr.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/awakable_list.h" -#include "third_party/mojo/src/mojo/edk/system/dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/mutex.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -class MOJO_SYSTEM_IMPL_EXPORT WaitSetDispatcher : public Dispatcher { - public: - WaitSetDispatcher(); - ~WaitSetDispatcher() override; - - // |Dispatcher| public methods: - Type GetType() const override; - - private: - // Internal implementation of Awakable. - class Waiter; - - struct WaitState { - scoped_refptr<Dispatcher> dispatcher; - MojoHandleSignals signals; - uintptr_t context; - }; - - // |Dispatcher| protected methods: - void CloseImplNoLock() override; - void CancelAllAwakablesNoLock() override; - MojoResult AddAwakableImplNoLock(Awakable* awakable, - MojoHandleSignals signals, - uintptr_t context, - HandleSignalsState* signals_state) override; - void RemoveAwakableImplNoLock(Awakable* awakable, - HandleSignalsState* signals_state) override; - MojoResult AddWaitingDispatcherImplNoLock( - const scoped_refptr<Dispatcher>& dispatcher, - MojoHandleSignals signals, - uintptr_t context) override; - MojoResult RemoveWaitingDispatcherImplNoLock( - const scoped_refptr<Dispatcher>& dispatcher) override; - MojoResult GetReadyDispatchersImplNoLock( - UserPointer<uint32_t> count, - DispatcherVector* dispatchers, - UserPointer<MojoResult> results, - UserPointer<uintptr_t> contexts) override; - HandleSignalsState GetHandleSignalsStateImplNoLock() const override; - scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock() - override; - - // Signal that the dispatcher indexed by |context| has been woken up with - // |result| and is now ready. - void WakeDispatcher(MojoResult result, uintptr_t context); - - // Map of dispatchers being waited on. Key is a Dispatcher* casted to a - // uintptr_t, and should be treated as an opaque value and not casted back. - std::map<uintptr_t, WaitState> waiting_dispatchers_ MOJO_GUARDED_BY(mutex()); - - // Separate mutex that can be locked without locking |mutex()|. - mutable Mutex awoken_mutex_ MOJO_ACQUIRED_AFTER(mutex()); - // List of dispatchers that have been woken up. Any dispatcher in this queue - // will NOT currently be waited on. - std::deque<std::pair<uintptr_t, MojoResult>> awoken_queue_ - MOJO_GUARDED_BY(awoken_mutex_); - // List of dispatchers that have been woken up and retrieved on the last call - // to |GetReadyDispatchers()|. - std::deque<uintptr_t> processed_dispatchers_ MOJO_GUARDED_BY(awoken_mutex_); - - // Separate mutex that can be locked without locking |mutex()|. - Mutex awakable_mutex_ MOJO_ACQUIRED_AFTER(mutex()); - // List of dispatchers being waited on. - AwakableList awakable_list_ MOJO_GUARDED_BY(awakable_mutex_); - - // Waiter used to wait on dispatchers. - scoped_ptr<Waiter> waiter_; -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_WAIT_SET_DISPATCHER_H_ diff --git a/third_party/mojo/src/mojo/edk/system/wait_set_dispatcher_unittest.cc b/third_party/mojo/src/mojo/edk/system/wait_set_dispatcher_unittest.cc deleted file mode 100644 index 86f5e36..0000000 --- a/third_party/mojo/src/mojo/edk/system/wait_set_dispatcher_unittest.cc +++ /dev/null @@ -1,459 +0,0 @@ -// Copyright 2015 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 "third_party/mojo/src/mojo/edk/system/wait_set_dispatcher.h" - -#include <algorithm> - -#include "base/memory/ref_counted.h" -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe.h" -#include "third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/test_utils.h" -#include "third_party/mojo/src/mojo/edk/system/waiter.h" - -namespace mojo { -namespace system { -namespace { - -class WaitSetDispatcherTest : public ::testing::Test { - public: - WaitSetDispatcherTest() {} - ~WaitSetDispatcherTest() override {} - - void SetUp() override { - dispatcher0_ = MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - dispatcher1_ = MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); - dispatcher0_->Init(mp, 0); - dispatcher1_->Init(mp, 1); - - dispatchers_to_close_.push_back(dispatcher0_); - dispatchers_to_close_.push_back(dispatcher1_); - } - - void TearDown() override { - for (auto& d : dispatchers_to_close_) - d->Close(); - } - - MojoResult GetOneReadyDispatcher( - const scoped_refptr<WaitSetDispatcher>& wait_set, - scoped_refptr<Dispatcher>* ready_dispatcher, - uintptr_t* context) { - uint32_t count = 1; - MojoResult dispatcher_result = MOJO_RESULT_UNKNOWN; - DispatcherVector dispatchers; - MojoResult result = wait_set->GetReadyDispatchers( - MakeUserPointer(&count), - &dispatchers, - MakeUserPointer(&dispatcher_result), - MakeUserPointer(context)); - if (result == MOJO_RESULT_OK) { - CHECK_EQ(1u, dispatchers.size()); - *ready_dispatcher = dispatchers[0]; - return dispatcher_result; - } - return result; - } - - void CloseOnShutdown(const scoped_refptr<Dispatcher>& dispatcher) { - dispatchers_to_close_.push_back(dispatcher); - } - - protected: - scoped_refptr<MessagePipeDispatcher> dispatcher0_; - scoped_refptr<MessagePipeDispatcher> dispatcher1_; - - DispatcherVector dispatchers_to_close_; - - DISALLOW_COPY_AND_ASSIGN(WaitSetDispatcherTest); -}; - -TEST_F(WaitSetDispatcherTest, Basic) { - scoped_refptr<WaitSetDispatcher> wait_set = new WaitSetDispatcher(); - CloseOnShutdown(wait_set); - ASSERT_EQ(MOJO_RESULT_OK, - wait_set->AddWaitingDispatcher(dispatcher0_, - MOJO_HANDLE_SIGNAL_READABLE, 1)); - ASSERT_EQ(MOJO_RESULT_OK, - wait_set->AddWaitingDispatcher(dispatcher1_, - MOJO_HANDLE_SIGNAL_WRITABLE, 2)); - - Waiter w; - uintptr_t context = 0; - w.Init(); - HandleSignalsState hss; - // |dispatcher1_| should already be writable. - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - wait_set->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); - - scoped_refptr<Dispatcher> woken_dispatcher; - EXPECT_EQ(MOJO_RESULT_OK, - GetOneReadyDispatcher(wait_set, &woken_dispatcher, &context)); - EXPECT_EQ(dispatcher1_, woken_dispatcher); - EXPECT_EQ(2u, context); - // If a ready dispatcher isn't removed, it will continue to be returned. - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - wait_set->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss)); - woken_dispatcher = nullptr; - context = 0; - EXPECT_EQ(MOJO_RESULT_OK, - GetOneReadyDispatcher(wait_set, &woken_dispatcher, &context)); - EXPECT_EQ(dispatcher1_, woken_dispatcher); - EXPECT_EQ(2u, context); - ASSERT_EQ(MOJO_RESULT_OK, wait_set->RemoveWaitingDispatcher(dispatcher1_)); - - // No ready dispatcher. - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_OK, - wait_set->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss)); - EXPECT_FALSE(hss.satisfies(MOJO_HANDLE_SIGNAL_READABLE)); - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0, nullptr)); - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - GetOneReadyDispatcher(wait_set, &woken_dispatcher, nullptr)); - - // Write to |dispatcher1_|, which should make |dispatcher0_| readable. - char buffer[] = "abcd"; - w.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - dispatcher1_->WriteMessage(UserPointer<const void>(buffer), - sizeof(buffer), nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_OK, w.Wait(0, nullptr)); - woken_dispatcher = nullptr; - context = 0; - EXPECT_EQ(MOJO_RESULT_OK, - GetOneReadyDispatcher(wait_set, &woken_dispatcher, &context)); - EXPECT_EQ(dispatcher0_, woken_dispatcher); - EXPECT_EQ(1u, context); - - // Again, if a ready dispatcher isn't removed, it will continue to be - // returned. - woken_dispatcher = nullptr; - EXPECT_EQ(MOJO_RESULT_OK, - GetOneReadyDispatcher(wait_set, &woken_dispatcher, nullptr)); - EXPECT_EQ(dispatcher0_, woken_dispatcher); - - wait_set->RemoveAwakable(&w, nullptr); -} - -TEST_F(WaitSetDispatcherTest, HandleWithoutRemoving) { - scoped_refptr<WaitSetDispatcher> wait_set = new WaitSetDispatcher(); - CloseOnShutdown(wait_set); - ASSERT_EQ(MOJO_RESULT_OK, - wait_set->AddWaitingDispatcher(dispatcher0_, - MOJO_HANDLE_SIGNAL_READABLE, 1)); - - Waiter w; - uintptr_t context = 0; - w.Init(); - HandleSignalsState hss; - // No ready dispatcher. - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_OK, - wait_set->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss)); - EXPECT_FALSE(hss.satisfies(MOJO_HANDLE_SIGNAL_READABLE)); - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0, nullptr)); - scoped_refptr<Dispatcher> woken_dispatcher; - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - GetOneReadyDispatcher(wait_set, &woken_dispatcher, nullptr)); - - // The tested behaviour below should be repeatable. - for (size_t i = 0; i < 3; i++) { - // Write to |dispatcher1_|, which should make |dispatcher0_| readable. - char buffer[] = "abcd"; - w.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - dispatcher1_->WriteMessage(UserPointer<const void>(buffer), - sizeof(buffer), nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_OK, w.Wait(0, nullptr)); - woken_dispatcher = nullptr; - context = 0; - EXPECT_EQ(MOJO_RESULT_OK, - GetOneReadyDispatcher(wait_set, &woken_dispatcher, &context)); - EXPECT_EQ(dispatcher0_, woken_dispatcher); - EXPECT_EQ(1u, context); - - // Read from |dispatcher0_| which should change it's state to non-readable. - char read_buffer[sizeof(buffer) + 5]; - uint32_t num_bytes = sizeof(read_buffer); - ASSERT_EQ(MOJO_RESULT_OK, - dispatcher0_->ReadMessage(UserPointer<void>(read_buffer), - MakeUserPointer(&num_bytes), - nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(sizeof(buffer), num_bytes); - - // No dispatchers are ready. - w.Init(); - woken_dispatcher = nullptr; - context = 0; - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - GetOneReadyDispatcher(wait_set, &woken_dispatcher, &context)); - EXPECT_EQ(nullptr, woken_dispatcher); - EXPECT_EQ(0u, context); - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0, nullptr)); - } - - wait_set->RemoveAwakable(&w, nullptr); -} - -TEST_F(WaitSetDispatcherTest, MultipleReady) { - scoped_refptr<WaitSetDispatcher> wait_set = new WaitSetDispatcher(); - CloseOnShutdown(wait_set); - - scoped_refptr<MessagePipeDispatcher> mp1_dispatcher0 = - MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - scoped_refptr<MessagePipeDispatcher> mp1_dispatcher1 = - MessagePipeDispatcher::Create( - MessagePipeDispatcher::kDefaultCreateOptions); - CloseOnShutdown(mp1_dispatcher0); - CloseOnShutdown(mp1_dispatcher1); - { - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); - mp1_dispatcher0->Init(mp, 0); - mp1_dispatcher1->Init(mp, 1); - } - - ASSERT_EQ(MOJO_RESULT_OK, - wait_set->AddWaitingDispatcher(dispatcher0_, - MOJO_HANDLE_SIGNAL_READABLE, 0)); - ASSERT_EQ(MOJO_RESULT_OK, - wait_set->AddWaitingDispatcher(dispatcher1_, - MOJO_HANDLE_SIGNAL_WRITABLE, 0)); - ASSERT_EQ(MOJO_RESULT_OK, - wait_set->AddWaitingDispatcher(mp1_dispatcher0, - MOJO_HANDLE_SIGNAL_WRITABLE, 0)); - ASSERT_EQ(MOJO_RESULT_OK, - wait_set->AddWaitingDispatcher(mp1_dispatcher1, - MOJO_HANDLE_SIGNAL_WRITABLE, 0)); - - Waiter w; - w.Init(); - HandleSignalsState hss; - // The three writable dispatchers should be ready. - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - wait_set->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); - - scoped_refptr<Dispatcher> woken_dispatcher; - EXPECT_EQ(MOJO_RESULT_OK, - GetOneReadyDispatcher(wait_set, &woken_dispatcher, nullptr)); - // Don't know which dispatcher was returned, just that it was one of the - // writable ones. - EXPECT_TRUE(woken_dispatcher == dispatcher1_ || - woken_dispatcher == mp1_dispatcher0 || - woken_dispatcher == mp1_dispatcher1); - - DispatcherVector dispatchers_vector; - uint32_t count = 4; - MojoResult results[4]; - EXPECT_EQ(MOJO_RESULT_OK, - wait_set->GetReadyDispatchers(MakeUserPointer(&count), - &dispatchers_vector, - MakeUserPointer(results), - MakeUserPointer<uintptr_t>(nullptr))); - EXPECT_EQ(3u, count); - std::sort(dispatchers_vector.begin(), dispatchers_vector.end()); - DispatcherVector expected_dispatchers; - expected_dispatchers.push_back(dispatcher1_); - expected_dispatchers.push_back(mp1_dispatcher0); - expected_dispatchers.push_back(mp1_dispatcher1); - std::sort(expected_dispatchers.begin(), expected_dispatchers.end()); - EXPECT_EQ(expected_dispatchers, dispatchers_vector); - - // If a ready dispatcher isn't removed, it will continue to be returned. - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - wait_set->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); - count = 4; - dispatchers_vector.clear(); - EXPECT_EQ(MOJO_RESULT_OK, - wait_set->GetReadyDispatchers(MakeUserPointer(&count), - &dispatchers_vector, - MakeUserPointer(results), - MakeUserPointer<uintptr_t>(nullptr))); - EXPECT_EQ(3u, count); - std::sort(dispatchers_vector.begin(), dispatchers_vector.end()); - EXPECT_EQ(expected_dispatchers, dispatchers_vector); - - // Remove one. It shouldn't be returned any longer. - ASSERT_EQ(MOJO_RESULT_OK, - wait_set->RemoveWaitingDispatcher(expected_dispatchers.back())); - expected_dispatchers.pop_back(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - wait_set->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); - count = 4; - dispatchers_vector.clear(); - EXPECT_EQ(MOJO_RESULT_OK, - wait_set->GetReadyDispatchers(MakeUserPointer(&count), - &dispatchers_vector, - MakeUserPointer(results), - MakeUserPointer<uintptr_t>(nullptr))); - EXPECT_EQ(2u, count); - std::sort(dispatchers_vector.begin(), dispatchers_vector.end()); - EXPECT_EQ(expected_dispatchers, dispatchers_vector); - - // Write to |dispatcher1_|, which should make |dispatcher0_| readable. - char buffer[] = "abcd"; - w.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - dispatcher1_->WriteMessage(UserPointer<const void>(buffer), - sizeof(buffer), nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - expected_dispatchers.push_back(dispatcher0_); - std::sort(expected_dispatchers.begin(), expected_dispatchers.end()); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - wait_set->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); - count = 4; - dispatchers_vector.clear(); - EXPECT_EQ(MOJO_RESULT_OK, - wait_set->GetReadyDispatchers(MakeUserPointer(&count), - &dispatchers_vector, - MakeUserPointer(results), - MakeUserPointer<uintptr_t>(nullptr))); - EXPECT_EQ(3u, count); - std::sort(dispatchers_vector.begin(), dispatchers_vector.end()); - EXPECT_EQ(expected_dispatchers, dispatchers_vector); -} - -TEST_F(WaitSetDispatcherTest, InvalidParams) { - scoped_refptr<WaitSetDispatcher> wait_set = new WaitSetDispatcher(); - - // Can't add a wait set to itself. - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - wait_set->AddWaitingDispatcher(wait_set, - MOJO_HANDLE_SIGNAL_READABLE, 0)); - - // Can't add twice. - EXPECT_EQ(MOJO_RESULT_OK, - wait_set->AddWaitingDispatcher(dispatcher0_, - MOJO_HANDLE_SIGNAL_READABLE, 0)); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - wait_set->AddWaitingDispatcher(dispatcher0_, - MOJO_HANDLE_SIGNAL_READABLE, 0)); - - // Remove a dispatcher that wasn't added. - EXPECT_EQ(MOJO_RESULT_NOT_FOUND, - wait_set->RemoveWaitingDispatcher(dispatcher1_)); - - // Add to a closed wait set. - wait_set->Close(); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - wait_set->AddWaitingDispatcher(dispatcher0_, - MOJO_HANDLE_SIGNAL_READABLE, 0)); -} - -TEST_F(WaitSetDispatcherTest, NotSatisfiable) { - scoped_refptr<WaitSetDispatcher> wait_set = new WaitSetDispatcher(); - CloseOnShutdown(wait_set); - - // Wait sets can only satisfy MOJO_HANDLE_SIGNAL_READABLE. - Waiter w; - w.Init(); - HandleSignalsState hss; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - wait_set->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_NONE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); - - hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - wait_set->AddAwakable(&w, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 0, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_NONE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); -} - -TEST_F(WaitSetDispatcherTest, ClosedDispatchers) { - scoped_refptr<WaitSetDispatcher> wait_set = new WaitSetDispatcher(); - CloseOnShutdown(wait_set); - - Waiter w; - w.Init(); - HandleSignalsState hss; - // A dispatcher that was added and then closed will be cancelled. - ASSERT_EQ(MOJO_RESULT_OK, - wait_set->AddWaitingDispatcher(dispatcher0_, - MOJO_HANDLE_SIGNAL_READABLE, 0)); - EXPECT_EQ(MOJO_RESULT_OK, - wait_set->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss)); - dispatcher0_->Close(); - EXPECT_EQ(MOJO_RESULT_OK, w.Wait(0, nullptr)); - EXPECT_TRUE(wait_set->GetHandleSignalsState().satisfies( - MOJO_HANDLE_SIGNAL_READABLE)); - scoped_refptr<Dispatcher> woken_dispatcher; - EXPECT_EQ(MOJO_RESULT_CANCELLED, - GetOneReadyDispatcher(wait_set, &woken_dispatcher, nullptr)); - EXPECT_EQ(dispatcher0_, woken_dispatcher); - - // Dispatcher will be implicitly removed because it may be impossible to - // remove explicitly. - woken_dispatcher = nullptr; - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - GetOneReadyDispatcher(wait_set, &woken_dispatcher, nullptr)); - EXPECT_EQ(MOJO_RESULT_NOT_FOUND, - wait_set->RemoveWaitingDispatcher(dispatcher0_)); - - // A dispatcher that's not satisfiable should give an error. - w.Init(); - EXPECT_EQ(MOJO_RESULT_OK, - wait_set->AddWaitingDispatcher(dispatcher1_, - MOJO_HANDLE_SIGNAL_READABLE, 0)); - EXPECT_EQ(MOJO_RESULT_OK, w.Wait(0, nullptr)); - EXPECT_TRUE(wait_set->GetHandleSignalsState().satisfies( - MOJO_HANDLE_SIGNAL_READABLE)); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - GetOneReadyDispatcher(wait_set, &woken_dispatcher, nullptr)); - EXPECT_EQ(dispatcher1_, woken_dispatcher); - - wait_set->RemoveAwakable(&w, nullptr); -} - -TEST_F(WaitSetDispatcherTest, NestedSets) { - scoped_refptr<WaitSetDispatcher> wait_set = new WaitSetDispatcher(); - CloseOnShutdown(wait_set); - scoped_refptr<WaitSetDispatcher> nested_wait_set = new WaitSetDispatcher(); - CloseOnShutdown(nested_wait_set); - - Waiter w; - w.Init(); - EXPECT_EQ(MOJO_RESULT_OK, - wait_set->AddWaitingDispatcher(nested_wait_set, - MOJO_HANDLE_SIGNAL_READABLE, 0)); - EXPECT_EQ(MOJO_RESULT_OK, - wait_set->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, nullptr)); - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0, nullptr)); - - // Writable signal is immediately satisfied by the message pipe. - w.Init(); - EXPECT_EQ(MOJO_RESULT_OK, - nested_wait_set->AddWaitingDispatcher( - dispatcher0_, MOJO_HANDLE_SIGNAL_WRITABLE, 0)); - EXPECT_EQ(MOJO_RESULT_OK, w.Wait(0, nullptr)); - scoped_refptr<Dispatcher> woken_dispatcher; - EXPECT_EQ(MOJO_RESULT_OK, - GetOneReadyDispatcher(wait_set, &woken_dispatcher, nullptr)); - EXPECT_EQ(nested_wait_set, woken_dispatcher); - - wait_set->RemoveAwakable(&w, nullptr); -} - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/waiter.cc b/third_party/mojo/src/mojo/edk/system/waiter.cc deleted file mode 100644 index f1b904e..0000000 --- a/third_party/mojo/src/mojo/edk/system/waiter.cc +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/waiter.h" - -#include <limits> - -#include "base/logging.h" -#include "base/time/time.h" - -namespace mojo { -namespace system { - -Waiter::Waiter() - : cv_(&lock_), -#ifndef NDEBUG - initialized_(false), -#endif - awoken_(false), - awake_result_(MOJO_RESULT_INTERNAL), - awake_context_(static_cast<uintptr_t>(-1)) { -} - -Waiter::~Waiter() { -} - -void Waiter::Init() { -#ifndef NDEBUG - initialized_ = true; -#endif - awoken_ = false; - // NOTE(vtl): If performance ever becomes an issue, we can disable the setting - // of |awake_result_| (except the first one in |Awake()|) in Release builds. - awake_result_ = MOJO_RESULT_INTERNAL; -} - -// TODO(vtl): Fast-path the |deadline == 0| case? -MojoResult Waiter::Wait(MojoDeadline deadline, uintptr_t* context) { - base::AutoLock locker(lock_); - -#ifndef NDEBUG - DCHECK(initialized_); - // It'll need to be re-initialized after this. - initialized_ = false; -#endif - - // Fast-path the already-awoken case: - if (awoken_) { - DCHECK_NE(awake_result_, MOJO_RESULT_INTERNAL); - if (context) - *context = awake_context_; - return awake_result_; - } - - // |MojoDeadline| is actually a |uint64_t|, but we need a signed quantity. - // Treat any out-of-range deadline as "forever" (which is wrong, but okay - // since 2^63 microseconds is ~300000 years). Note that this also takes care - // of the |MOJO_DEADLINE_INDEFINITE| (= 2^64 - 1) case. - if (deadline > static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) { - do { - cv_.Wait(); - } while (!awoken_); - } else { - // NOTE(vtl): This is very inefficient on POSIX, since pthreads condition - // variables take an absolute deadline. - const base::TimeTicks end_time = - base::TimeTicks::Now() + - base::TimeDelta::FromMicroseconds(static_cast<int64_t>(deadline)); - do { - base::TimeTicks now_time = base::TimeTicks::Now(); - if (now_time >= end_time) - return MOJO_RESULT_DEADLINE_EXCEEDED; - - cv_.TimedWait(end_time - now_time); - } while (!awoken_); - } - - DCHECK_NE(awake_result_, MOJO_RESULT_INTERNAL); - if (context) - *context = awake_context_; - return awake_result_; -} - -bool Waiter::Awake(MojoResult result, uintptr_t context) { - base::AutoLock locker(lock_); - - if (awoken_) - return true; - - awoken_ = true; - awake_result_ = result; - awake_context_ = context; - cv_.Signal(); - // |cv_.Wait()|/|cv_.TimedWait()| will return after |lock_| is released. - return true; -} - -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/waiter.h b/third_party/mojo/src/mojo/edk/system/waiter.h deleted file mode 100644 index adb94e9..0000000 --- a/third_party/mojo/src/mojo/edk/system/waiter.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_WAITER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_WAITER_H_ - -#include <stdint.h> - -#include "base/synchronization/condition_variable.h" -#include "base/synchronization/lock.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/awakable.h" -#include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace system { - -// IMPORTANT (all-caps gets your attention, right?): |Waiter| methods are called -// under other locks, in particular, |Dispatcher::lock_|s, so |Waiter| methods -// must never call out to other objects (in particular, |Dispatcher|s). This -// class is thread-safe. -class MOJO_SYSTEM_IMPL_EXPORT Waiter final : public Awakable { - public: - Waiter(); - ~Waiter(); - - // A |Waiter| can be used multiple times; |Init()| should be called before - // each time it's used. - void Init(); - - // Waits until a suitable |Awake()| is called. (|context| may be null, in - // which case, obviously no context is ever returned.) - // Returns: - // - The result given to the first call to |Awake()| (possibly before this - // call to |Wait()|); in this case, |*context| is set to the value passed - // to that call to |Awake()|. - // - |MOJO_RESULT_DEADLINE_EXCEEDED| if the deadline was exceeded; in this - // case |*context| is not modified. - // - // Usually, the context passed to |Awake()| will be the value passed to - // |Dispatcher::AddAwakable()|, which is usually the index to the array of - // handles passed to |MojoWaitMany()| (or 0 for |MojoWait()|). - // - // Typical |Awake()| results are: - // - |MOJO_RESULT_OK| if one of the flags passed to - // |MojoWait()|/|MojoWaitMany()| (hence |Dispatcher::AddAwakable()|) was - // satisfied; - // - |MOJO_RESULT_CANCELLED| if a handle (on which - // |MojoWait()|/|MojoWaitMany()| was called) was closed (hence the - // dispatcher closed); and - // - |MOJO_RESULT_FAILED_PRECONDITION| if one of the set of flags passed to - // |MojoWait()|/|MojoWaitMany()| cannot or can no longer be satisfied by - // the corresponding handle (e.g., if the other end of a message or data - // pipe is closed). - MojoResult Wait(MojoDeadline deadline, uintptr_t* context); - - // Wake the waiter up with the given result and context (or no-op if it's been - // woken up already). - bool Awake(MojoResult result, uintptr_t context) override; - - private: - base::ConditionVariable cv_; // Associated to |lock_|. - base::Lock lock_; // Protects the following members. -#ifndef NDEBUG - bool initialized_; -#endif - bool awoken_; - MojoResult awake_result_; - uintptr_t awake_context_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(Waiter); -}; - -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_WAITER_H_ diff --git a/third_party/mojo/src/mojo/edk/system/waiter_test_utils.cc b/third_party/mojo/src/mojo/edk/system/waiter_test_utils.cc deleted file mode 100644 index d420216..0000000 --- a/third_party/mojo/src/mojo/edk/system/waiter_test_utils.cc +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/waiter_test_utils.h" - -namespace mojo { -namespace system { -namespace test { - -SimpleWaiterThread::SimpleWaiterThread(MojoResult* result, uintptr_t* context) - : base::SimpleThread("waiter_thread"), result_(result), context_(context) { - waiter_.Init(); - *result_ = 5420734; // Totally invalid result. - *context_ = 23489023; // "Random". -} - -SimpleWaiterThread::~SimpleWaiterThread() { - Join(); -} - -void SimpleWaiterThread::Run() { - *result_ = waiter_.Wait(MOJO_DEADLINE_INDEFINITE, context_); -} - -WaiterThread::WaiterThread(scoped_refptr<Dispatcher> dispatcher, - MojoHandleSignals handle_signals, - MojoDeadline deadline, - uintptr_t context, - bool* did_wait_out, - MojoResult* result_out, - uintptr_t* context_out, - HandleSignalsState* signals_state_out) - : base::SimpleThread("waiter_thread"), - dispatcher_(dispatcher), - handle_signals_(handle_signals), - deadline_(deadline), - context_(context), - did_wait_out_(did_wait_out), - result_out_(result_out), - context_out_(context_out), - signals_state_out_(signals_state_out) { - *did_wait_out_ = false; - // Initialize these with invalid results (so that we'll be sure to catch any - // case where they're not set). - *result_out_ = 8542346; - *context_out_ = 89023444; - *signals_state_out_ = HandleSignalsState(~0u, ~0u); -} - -WaiterThread::~WaiterThread() { - Join(); -} - -void WaiterThread::Run() { - waiter_.Init(); - - *result_out_ = dispatcher_->AddAwakable(&waiter_, handle_signals_, context_, - signals_state_out_); - if (*result_out_ != MOJO_RESULT_OK) - return; - - *did_wait_out_ = true; - *result_out_ = waiter_.Wait(deadline_, context_out_); - dispatcher_->RemoveAwakable(&waiter_, signals_state_out_); -} - -} // namespace test -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/waiter_test_utils.h b/third_party/mojo/src/mojo/edk/system/waiter_test_utils.h deleted file mode 100644 index f009893..0000000 --- a/third_party/mojo/src/mojo/edk/system/waiter_test_utils.h +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_WAITER_TEST_UTILS_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_WAITER_TEST_UTILS_H_ - -#include <stdint.h> - -#include "base/memory/ref_counted.h" -#include "base/threading/simple_thread.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/system/dispatcher.h" -#include "third_party/mojo/src/mojo/edk/system/handle_signals_state.h" -#include "third_party/mojo/src/mojo/edk/system/waiter.h" - -namespace mojo { -namespace system { -namespace test { - -// This is a very simple thread that has a |Waiter|, on which it waits -// indefinitely (and records the result). It will create and initialize the -// |Waiter| on creation, but the caller must start the thread with |Start()|. It -// will join the thread on destruction. -// -// One usually uses it like: -// -// MojoResult result; -// { -// AwakableList awakable_list; -// test::SimpleWaiterThread thread(&result); -// awakable_list.Add(thread.waiter(), ...); -// thread.Start(); -// ... some stuff to wake the waiter ... -// awakable_list.Remove(thread.waiter()); -// } // Join |thread|. -// EXPECT_EQ(..., result); -// -// There's a bit of unrealism in its use: In this sort of usage, calls such as -// |Waiter::Init()|, |AddAwakable()|, and |RemoveAwakable()| are done in the -// main (test) thread, not the waiter thread (as would actually happen in real -// code). (We accept this unrealism for simplicity, since |AwakableList| is -// thread-unsafe so making it more realistic would require adding nontrivial -// synchronization machinery.) -class SimpleWaiterThread : public base::SimpleThread { - public: - // For the duration of the lifetime of this object, |*result| belongs to it - // (in the sense that it will write to it whenever it wants). - SimpleWaiterThread(MojoResult* result, uintptr_t* context); - ~SimpleWaiterThread() override; // Joins the thread. - - Waiter* waiter() { return &waiter_; } - - private: - void Run() override; - - MojoResult* const result_; - uintptr_t* const context_; - Waiter waiter_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(SimpleWaiterThread); -}; - -// This is a more complex and realistic thread that has a |Waiter|, on which it -// waits for the given deadline (with the given flags). Unlike -// |SimpleWaiterThread|, it requires the machinery of |Dispatcher|. -class WaiterThread : public base::SimpleThread { - public: - // Note: |*did_wait_out|, |*result_out|, |*context_out| and - // |*signals_state_out| "belong" to this object (i.e., may be modified by, on - // some other thread) while it's alive. - WaiterThread(scoped_refptr<Dispatcher> dispatcher, - MojoHandleSignals handle_signals, - MojoDeadline deadline, - uintptr_t context, - bool* did_wait_out, - MojoResult* result_out, - uintptr_t* context_out, - HandleSignalsState* signals_state_out); - ~WaiterThread() override; - - private: - void Run() override; - - const scoped_refptr<Dispatcher> dispatcher_; - const MojoHandleSignals handle_signals_; - const MojoDeadline deadline_; - const uint32_t context_; - bool* const did_wait_out_; - MojoResult* const result_out_; - uintptr_t* const context_out_; - HandleSignalsState* const signals_state_out_; - - Waiter waiter_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(WaiterThread); -}; - -} // namespace test -} // namespace system -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_SYSTEM_WAITER_TEST_UTILS_H_ diff --git a/third_party/mojo/src/mojo/edk/system/waiter_unittest.cc b/third_party/mojo/src/mojo/edk/system/waiter_unittest.cc deleted file mode 100644 index de0e662..0000000 --- a/third_party/mojo/src/mojo/edk/system/waiter_unittest.cc +++ /dev/null @@ -1,298 +0,0 @@ -// Copyright 2013 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. - -// NOTE(vtl): Some of these tests are inherently flaky (e.g., if run on a -// heavily-loaded system). Sorry. |test::EpsilonDeadline()| may be increased to -// increase tolerance and reduce observed flakiness (though doing so reduces the -// meaningfulness of the test). - -#include "third_party/mojo/src/mojo/edk/system/waiter.h" - -#include <stdint.h> - -#include "base/threading/simple_thread.h" -#include "mojo/public/cpp/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/system/mutex.h" -#include "third_party/mojo/src/mojo/edk/system/test_utils.h" - -namespace mojo { -namespace system { -namespace { - -const unsigned kPollTimeMs = 10; - -class WaitingThread : public base::SimpleThread { - public: - explicit WaitingThread(MojoDeadline deadline) - : base::SimpleThread("waiting_thread"), - deadline_(deadline), - done_(false), - result_(MOJO_RESULT_UNKNOWN), - context_(static_cast<uintptr_t>(-1)) { - waiter_.Init(); - } - - ~WaitingThread() override { Join(); } - - void WaitUntilDone(MojoResult* result, - uintptr_t* context, - MojoDeadline* elapsed) { - for (;;) { - { - MutexLocker locker(&mutex_); - if (done_) { - *result = result_; - *context = context_; - *elapsed = elapsed_; - break; - } - } - - test::Sleep(test::DeadlineFromMilliseconds(kPollTimeMs)); - } - } - - Waiter* waiter() { return &waiter_; } - - private: - void Run() override { - test::Stopwatch stopwatch; - MojoResult result; - uintptr_t context = static_cast<uintptr_t>(-1); - MojoDeadline elapsed; - - stopwatch.Start(); - result = waiter_.Wait(deadline_, &context); - elapsed = stopwatch.Elapsed(); - - { - MutexLocker locker(&mutex_); - done_ = true; - result_ = result; - context_ = context; - elapsed_ = elapsed; - } - } - - const MojoDeadline deadline_; - Waiter waiter_; // Thread-safe. - - Mutex mutex_; - bool done_ MOJO_GUARDED_BY(mutex_); - MojoResult result_ MOJO_GUARDED_BY(mutex_); - uintptr_t context_ MOJO_GUARDED_BY(mutex_); - MojoDeadline elapsed_ MOJO_GUARDED_BY(mutex_); - - MOJO_DISALLOW_COPY_AND_ASSIGN(WaitingThread); -}; - -TEST(WaiterTest, Basic) { - MojoResult result; - uintptr_t context; - MojoDeadline elapsed; - - // Finite deadline. - - // Awake immediately after thread start. - { - WaitingThread thread(10 * test::EpsilonDeadline()); - thread.Start(); - thread.waiter()->Awake(MOJO_RESULT_OK, 1); - thread.WaitUntilDone(&result, &context, &elapsed); - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(1u, context); - EXPECT_LT(elapsed, test::EpsilonDeadline()); - } - - // Awake before after thread start. - { - WaitingThread thread(10 * test::EpsilonDeadline()); - thread.waiter()->Awake(MOJO_RESULT_CANCELLED, 2); - thread.Start(); - thread.WaitUntilDone(&result, &context, &elapsed); - EXPECT_EQ(MOJO_RESULT_CANCELLED, result); - EXPECT_EQ(2u, context); - EXPECT_LT(elapsed, test::EpsilonDeadline()); - } - - // Awake some time after thread start. - { - WaitingThread thread(10 * test::EpsilonDeadline()); - thread.Start(); - test::Sleep(2 * test::EpsilonDeadline()); - thread.waiter()->Awake(1, 3); - thread.WaitUntilDone(&result, &context, &elapsed); - EXPECT_EQ(1u, result); - EXPECT_EQ(3u, context); - EXPECT_GT(elapsed, (2 - 1) * test::EpsilonDeadline()); - EXPECT_LT(elapsed, (2 + 1) * test::EpsilonDeadline()); - } - - // Awake some longer time after thread start. - { - WaitingThread thread(10 * test::EpsilonDeadline()); - thread.Start(); - test::Sleep(5 * test::EpsilonDeadline()); - thread.waiter()->Awake(2, 4); - thread.WaitUntilDone(&result, &context, &elapsed); - EXPECT_EQ(2u, result); - EXPECT_EQ(4u, context); - EXPECT_GT(elapsed, (5 - 1) * test::EpsilonDeadline()); - EXPECT_LT(elapsed, (5 + 1) * test::EpsilonDeadline()); - } - - // Don't awake -- time out (on another thread). - { - WaitingThread thread(2 * test::EpsilonDeadline()); - thread.Start(); - thread.WaitUntilDone(&result, &context, &elapsed); - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result); - EXPECT_EQ(static_cast<uintptr_t>(-1), context); - EXPECT_GT(elapsed, (2 - 1) * test::EpsilonDeadline()); - EXPECT_LT(elapsed, (2 + 1) * test::EpsilonDeadline()); - } - - // No (indefinite) deadline. - - // Awake immediately after thread start. - { - WaitingThread thread(MOJO_DEADLINE_INDEFINITE); - thread.Start(); - thread.waiter()->Awake(MOJO_RESULT_OK, 5); - thread.WaitUntilDone(&result, &context, &elapsed); - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(5u, context); - EXPECT_LT(elapsed, test::EpsilonDeadline()); - } - - // Awake before after thread start. - { - WaitingThread thread(MOJO_DEADLINE_INDEFINITE); - thread.waiter()->Awake(MOJO_RESULT_CANCELLED, 6); - thread.Start(); - thread.WaitUntilDone(&result, &context, &elapsed); - EXPECT_EQ(MOJO_RESULT_CANCELLED, result); - EXPECT_EQ(6u, context); - EXPECT_LT(elapsed, test::EpsilonDeadline()); - } - - // Awake some time after thread start. - { - WaitingThread thread(MOJO_DEADLINE_INDEFINITE); - thread.Start(); - test::Sleep(2 * test::EpsilonDeadline()); - thread.waiter()->Awake(1, 7); - thread.WaitUntilDone(&result, &context, &elapsed); - EXPECT_EQ(1u, result); - EXPECT_EQ(7u, context); - EXPECT_GT(elapsed, (2 - 1) * test::EpsilonDeadline()); - EXPECT_LT(elapsed, (2 + 1) * test::EpsilonDeadline()); - } - - // Awake some longer time after thread start. - { - WaitingThread thread(MOJO_DEADLINE_INDEFINITE); - thread.Start(); - test::Sleep(5 * test::EpsilonDeadline()); - thread.waiter()->Awake(2, 8); - thread.WaitUntilDone(&result, &context, &elapsed); - EXPECT_EQ(2u, result); - EXPECT_EQ(8u, context); - EXPECT_GT(elapsed, (5 - 1) * test::EpsilonDeadline()); - EXPECT_LT(elapsed, (5 + 1) * test::EpsilonDeadline()); - } -} - -TEST(WaiterTest, TimeOut) { - test::Stopwatch stopwatch; - MojoDeadline elapsed; - - Waiter waiter; - uintptr_t context = 123; - - waiter.Init(); - stopwatch.Start(); - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, &context)); - elapsed = stopwatch.Elapsed(); - EXPECT_LT(elapsed, test::EpsilonDeadline()); - EXPECT_EQ(123u, context); - - waiter.Init(); - stopwatch.Start(); - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, - waiter.Wait(2 * test::EpsilonDeadline(), &context)); - elapsed = stopwatch.Elapsed(); - EXPECT_GT(elapsed, (2 - 1) * test::EpsilonDeadline()); - EXPECT_LT(elapsed, (2 + 1) * test::EpsilonDeadline()); - EXPECT_EQ(123u, context); - - waiter.Init(); - stopwatch.Start(); - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, - waiter.Wait(5 * test::EpsilonDeadline(), &context)); - elapsed = stopwatch.Elapsed(); - EXPECT_GT(elapsed, (5 - 1) * test::EpsilonDeadline()); - EXPECT_LT(elapsed, (5 + 1) * test::EpsilonDeadline()); - EXPECT_EQ(123u, context); -} - -// The first |Awake()| should always win. -TEST(WaiterTest, MultipleAwakes) { - MojoResult result; - uintptr_t context; - MojoDeadline elapsed; - - { - WaitingThread thread(MOJO_DEADLINE_INDEFINITE); - thread.Start(); - thread.waiter()->Awake(MOJO_RESULT_OK, 1); - thread.waiter()->Awake(1, 2); - thread.WaitUntilDone(&result, &context, &elapsed); - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(1u, context); - EXPECT_LT(elapsed, test::EpsilonDeadline()); - } - - { - WaitingThread thread(MOJO_DEADLINE_INDEFINITE); - thread.waiter()->Awake(1, 3); - thread.Start(); - thread.waiter()->Awake(MOJO_RESULT_OK, 4); - thread.WaitUntilDone(&result, &context, &elapsed); - EXPECT_EQ(1u, result); - EXPECT_EQ(3u, context); - EXPECT_LT(elapsed, test::EpsilonDeadline()); - } - - { - WaitingThread thread(MOJO_DEADLINE_INDEFINITE); - thread.Start(); - thread.waiter()->Awake(10, 5); - test::Sleep(2 * test::EpsilonDeadline()); - thread.waiter()->Awake(20, 6); - thread.WaitUntilDone(&result, &context, &elapsed); - EXPECT_EQ(10u, result); - EXPECT_EQ(5u, context); - EXPECT_LT(elapsed, test::EpsilonDeadline()); - } - - { - WaitingThread thread(10 * test::EpsilonDeadline()); - thread.Start(); - test::Sleep(1 * test::EpsilonDeadline()); - thread.waiter()->Awake(MOJO_RESULT_FAILED_PRECONDITION, 7); - test::Sleep(2 * test::EpsilonDeadline()); - thread.waiter()->Awake(MOJO_RESULT_OK, 8); - thread.WaitUntilDone(&result, &context, &elapsed); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); - EXPECT_EQ(7u, context); - EXPECT_GT(elapsed, (1 - 1) * test::EpsilonDeadline()); - EXPECT_LT(elapsed, (1 + 1) * test::EpsilonDeadline()); - } -} - -} // namespace -} // namespace system -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/test/BUILD.gn b/third_party/mojo/src/mojo/edk/test/BUILD.gn deleted file mode 100644 index 2232a5e..0000000 --- a/third_party/mojo/src/mojo/edk/test/BUILD.gn +++ /dev/null @@ -1,170 +0,0 @@ -# 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. - -import("//testing/test.gni") - -source_set("test_support") { - testonly = true - sources = [ - "multiprocess_test_helper.cc", - "multiprocess_test_helper.h", - "scoped_ipc_support.cc", - "scoped_ipc_support.h", - "test_utils.h", - "test_utils_posix.cc", - "test_utils_win.cc", - ] - - deps = [ - "//base", - "//base/test:test_support", - "//testing/gtest", - "//third_party/mojo/src/mojo/edk/system", - ] - - public_deps = [ - "//mojo/public/cpp/system", - ] -} - -source_set("run_all_unittests") { - testonly = true - sources = [ - "run_all_unittests.cc", - ] - - deps = [ - ":test_support_impl", - "//base", - "//base/test:test_support", - "//mojo/public/c/test_support", - "//testing/gtest", - "//third_party/mojo/src/mojo/edk/system", - ] -} - -source_set("run_all_perftests") { - testonly = true - deps = [ - ":test_support_impl", - "//base", - "//base/test:test_support", - "//mojo/public/c/test_support", - "//third_party/mojo/src/mojo/edk/system", - ] - - sources = [ - "run_all_perftests.cc", - ] -} - -source_set("test_support_impl") { - testonly = true - deps = [ - "//base", - "//base/test:test_support", - "//mojo/public/c/test_support", - "//mojo/public/cpp/system", - ] - - sources = [ - "test_support_impl.cc", - "test_support_impl.h", - ] -} - -# Public SDK test targets follow. These targets are not defined within the -# public SDK itself as running the unittests requires the EDK. -# TODO(vtl): These don't really belong here. (They should be converted to -# apptests, but even apart from that these targets belong somewhere else.) - -group("public_tests") { - testonly = true - deps = [ - ":mojo_public_bindings_perftests", - ":mojo_public_bindings_unittests", - ":mojo_public_environment_unittests", - ":mojo_public_system_perftests", - ":mojo_public_system_unittests", - ":mojo_public_utility_unittests", - ] -} - -test("mojo_public_bindings_unittests") { - deps = [ - ":run_all_unittests", - "//mojo/public/cpp/bindings/tests", - ] - - if (is_linux && !is_component_build) { - # This tests dynamically loads libmojo_test_support even in non-component - # builds. - configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ] - } -} - -test("mojo_public_bindings_perftests") { - deps = [ - ":run_all_perftests", - "//mojo/public/cpp/bindings/tests:perftests", - ] - - if (is_linux && !is_component_build) { - # This tests dynamically loads libmojo_test_support even in non-component - # builds. - configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ] - } -} - -test("mojo_public_environment_unittests") { - deps = [ - ":run_all_unittests", - "//mojo/public/cpp/environment/tests", - ] - - if (is_linux && !is_component_build) { - # This tests dynamically loads libmojo_test_support even in non-component - # builds. - configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ] - } -} - -test("mojo_public_system_perftests") { - deps = [ - ":run_all_perftests", - "//mojo/public/c/system/tests:perftests", - ] - - if (is_linux && !is_component_build) { - # This tests dynamically loads libmojo_test_support even in non-component - # builds. - configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ] - } -} - -test("mojo_public_system_unittests") { - deps = [ - ":run_all_unittests", - "//mojo/public/cpp/system/tests", - ] - - if (is_linux && !is_component_build) { - # This tests dynamically loads libmojo_test_support even in non-component - # builds. - configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ] - } -} - -test("mojo_public_utility_unittests") { - deps = [ - ":run_all_unittests", - "//mojo/public/cpp/utility/tests", - ] - - if (is_linux && !is_component_build) { - # This tests dynamically loads libmojo_test_support even in non-component - # builds. - configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ] - } -} diff --git a/third_party/mojo/src/mojo/edk/test/multiprocess_test_helper.cc b/third_party/mojo/src/mojo/edk/test/multiprocess_test_helper.cc deleted file mode 100644 index b462893..0000000 --- a/third_party/mojo/src/mojo/edk/test/multiprocess_test_helper.cc +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/test/multiprocess_test_helper.h" - -#include "base/command_line.h" -#include "base/logging.h" -#include "base/process/kill.h" -#include "base/process/process_handle.h" -#include "build/build_config.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" - -namespace mojo { -namespace test { - -MultiprocessTestHelper::MultiprocessTestHelper() { - platform_channel_pair_.reset(new embedder::PlatformChannelPair()); - server_platform_handle = platform_channel_pair_->PassServerHandle(); -} - -MultiprocessTestHelper::~MultiprocessTestHelper() { - CHECK(!test_child_.IsValid()); - server_platform_handle.reset(); - platform_channel_pair_.reset(); -} - -void MultiprocessTestHelper::StartChild(const std::string& test_child_name) { - StartChildWithExtraSwitch(test_child_name, std::string(), std::string()); -} - -void MultiprocessTestHelper::StartChildWithExtraSwitch( - const std::string& test_child_name, - const std::string& switch_string, - const std::string& switch_value) { - CHECK(platform_channel_pair_); - CHECK(!test_child_name.empty()); - CHECK(!test_child_.IsValid()); - - std::string test_child_main = test_child_name + "TestChildMain"; - - base::CommandLine command_line( - base::GetMultiProcessTestChildBaseCommandLine()); - embedder::HandlePassingInformation handle_passing_info; - platform_channel_pair_->PrepareToPassClientHandleToChildProcess( - &command_line, &handle_passing_info); - - if (!switch_string.empty()) { - CHECK(!command_line.HasSwitch(switch_string)); - if (!switch_value.empty()) - command_line.AppendSwitchASCII(switch_string, switch_value); - else - command_line.AppendSwitch(switch_string); - } - - base::LaunchOptions options; -#if defined(OS_POSIX) - options.fds_to_remap = &handle_passing_info; -#elif defined(OS_WIN) - options.start_hidden = true; - options.handles_to_inherit = &handle_passing_info; -#else -#error "Not supported yet." -#endif - - test_child_ = - base::SpawnMultiProcessTestChild(test_child_main, command_line, options); - platform_channel_pair_->ChildProcessLaunched(); - - CHECK(test_child_.IsValid()); -} - -int MultiprocessTestHelper::WaitForChildShutdown() { - CHECK(test_child_.IsValid()); - - int rv = -1; - CHECK( - test_child_.WaitForExitWithTimeout(TestTimeouts::action_timeout(), &rv)); - test_child_.Close(); - return rv; -} - -bool MultiprocessTestHelper::WaitForChildTestShutdown() { - return WaitForChildShutdown() == 0; -} - -// static -void MultiprocessTestHelper::ChildSetup() { - CHECK(base::CommandLine::InitializedForCurrentProcess()); - client_platform_handle = - embedder::PlatformChannelPair::PassClientHandleFromParentProcess( - *base::CommandLine::ForCurrentProcess()); -} - -// static -embedder::ScopedPlatformHandle MultiprocessTestHelper::client_platform_handle; - -} // namespace test -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/test/multiprocess_test_helper.h b/third_party/mojo/src/mojo/edk/test/multiprocess_test_helper.h deleted file mode 100644 index c11d79b..0000000 --- a/third_party/mojo/src/mojo/edk/test/multiprocess_test_helper.h +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2013 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_TEST_MULTIPROCESS_TEST_HELPER_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_TEST_MULTIPROCESS_TEST_HELPER_H_ - -#include <string> - -#include "base/process/process.h" -#include "base/test/multiprocess_test.h" -#include "base/test/test_timeouts.h" -#include "mojo/public/cpp/system/macros.h" -#include "testing/multiprocess_func_list.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" - -namespace mojo { - -namespace embedder { -class PlatformChannelPair; -} - -namespace test { - -class MultiprocessTestHelper { - public: - MultiprocessTestHelper(); - ~MultiprocessTestHelper(); - - // Start a child process and run the "main" function "named" |test_child_name| - // declared using |MOJO_MULTIPROCESS_TEST_CHILD_MAIN()| or - // |MOJO_MULTIPROCESS_TEST_CHILD_TEST()| (below). - void StartChild(const std::string& test_child_name); - // Like |StartChild()|, but appends an extra switch (with ASCII value) to the - // command line. (The switch must not already be present in the default - // command line.) - void StartChildWithExtraSwitch(const std::string& test_child_name, - const std::string& switch_string, - const std::string& switch_value); - // Wait for the child process to terminate. - // Returns the exit code of the child process. Note that, though it's declared - // to be an |int|, the exit code is subject to mangling by the OS. E.g., we - // usually return -1 on error in the child (e.g., if |test_child_name| was not - // found), but this is mangled to 255 on Linux. You should only rely on codes - // 0-127 being preserved, and -1 being outside the range 0-127. - int WaitForChildShutdown(); - - // Like |WaitForChildShutdown()|, but returns true on success (exit code of 0) - // and false otherwise. You probably want to do something like - // |EXPECT_TRUE(WaitForChildTestShutdown());|. Mainly for use with - // |MOJO_MULTIPROCESS_TEST_CHILD_TEST()|. - bool WaitForChildTestShutdown(); - - // For use by |MOJO_MULTIPROCESS_TEST_CHILD_MAIN()| only: - static void ChildSetup(); - - // For use in the main process: - embedder::ScopedPlatformHandle server_platform_handle; - - // For use (and only valid) in the child process: - static embedder::ScopedPlatformHandle client_platform_handle; - - private: - scoped_ptr<embedder::PlatformChannelPair> platform_channel_pair_; - - // Valid after |StartChild()| and before |WaitForChildShutdown()|. - base::Process test_child_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(MultiprocessTestHelper); -}; - -// Use this to declare the child process's "main()" function for tests using -// |MultiprocessTestHelper|. It returns an |int|, which will be the process's -// exit code (but see the comment about |WaitForChildShutdown()|). -#define MOJO_MULTIPROCESS_TEST_CHILD_MAIN(test_child_name) \ - MULTIPROCESS_TEST_MAIN_WITH_SETUP( \ - test_child_name##TestChildMain, \ - ::mojo::test::MultiprocessTestHelper::ChildSetup) - -// Use this (and |WaitForChildTestShutdown()|) for the child process's "main()", -// if you want to use |EXPECT_...()| or |ASSERT_...()|; it has a |void| return -// type. (Note that while an |ASSERT_...()| failure will abort the test in the -// child, it will not abort the test in the parent.) -#define MOJO_MULTIPROCESS_TEST_CHILD_TEST(test_child_name) \ - void test_child_name##TestChildTest(); \ - MOJO_MULTIPROCESS_TEST_CHILD_MAIN(test_child_name) { \ - test_child_name##TestChildTest(); \ - return (::testing::Test::HasFatalFailure() || \ - ::testing::Test::HasNonfatalFailure()) \ - ? 1 \ - : 0; \ - } \ - void test_child_name##TestChildTest() - -} // namespace test -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_TEST_MULTIPROCESS_TEST_HELPER_H_ diff --git a/third_party/mojo/src/mojo/edk/test/multiprocess_test_helper_unittest.cc b/third_party/mojo/src/mojo/edk/test/multiprocess_test_helper_unittest.cc deleted file mode 100644 index 07d0733..0000000 --- a/third_party/mojo/src/mojo/edk/test/multiprocess_test_helper_unittest.cc +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright 2013 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 "third_party/mojo/src/mojo/edk/test/multiprocess_test_helper.h" - -#include <utility> - -#include "base/logging.h" -#include "build/build_config.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" -#include "third_party/mojo/src/mojo/edk/test/test_utils.h" - -#if defined(OS_POSIX) -#include <fcntl.h> -#endif - -namespace mojo { -namespace test { -namespace { - -bool IsNonBlocking(const embedder::PlatformHandle& handle) { -#if defined(OS_WIN) - // Haven't figured out a way to query whether a HANDLE was created with - // FILE_FLAG_OVERLAPPED. - return true; -#else - return fcntl(handle.fd, F_GETFL) & O_NONBLOCK; -#endif -} - -bool WriteByte(const embedder::PlatformHandle& handle, char c) { - size_t bytes_written = 0; - BlockingWrite(handle, &c, 1, &bytes_written); - return bytes_written == 1; -} - -bool ReadByte(const embedder::PlatformHandle& handle, char* c) { - size_t bytes_read = 0; - BlockingRead(handle, c, 1, &bytes_read); - return bytes_read == 1; -} - -using MultiprocessTestHelperTest = testing::Test; - -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_RunChild DISABLED_RunChild -#else -#define MAYBE_RunChild RunChild -#endif // defined(OS_ANDROID) -TEST_F(MultiprocessTestHelperTest, MAYBE_RunChild) { - MultiprocessTestHelper helper; - EXPECT_TRUE(helper.server_platform_handle.is_valid()); - - helper.StartChild("RunChild"); - EXPECT_EQ(123, helper.WaitForChildShutdown()); -} - -MOJO_MULTIPROCESS_TEST_CHILD_MAIN(RunChild) { - CHECK(MultiprocessTestHelper::client_platform_handle.is_valid()); - return 123; -} - -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_TestChildMainNotFound DISABLED_TestChildMainNotFound -#else -#define MAYBE_TestChildMainNotFound TestChildMainNotFound -#endif // defined(OS_ANDROID) -TEST_F(MultiprocessTestHelperTest, MAYBE_TestChildMainNotFound) { - MultiprocessTestHelper helper; - helper.StartChild("NoSuchTestChildMain"); - int result = helper.WaitForChildShutdown(); - EXPECT_FALSE(result >= 0 && result <= 127); -} - -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_PassedChannel DISABLED_PassedChannel -#else -#define MAYBE_PassedChannel PassedChannel -#endif // defined(OS_ANDROID) -TEST_F(MultiprocessTestHelperTest, MAYBE_PassedChannel) { - MultiprocessTestHelper helper; - EXPECT_TRUE(helper.server_platform_handle.is_valid()); - helper.StartChild("PassedChannel"); - - // Take ownership of the handle. - embedder::ScopedPlatformHandle handle = - std::move(helper.server_platform_handle); - - // The handle should be non-blocking. - EXPECT_TRUE(IsNonBlocking(handle.get())); - - // Write a byte. - const char c = 'X'; - EXPECT_TRUE(WriteByte(handle.get(), c)); - - // It'll echo it back to us, incremented. - char d = 0; - EXPECT_TRUE(ReadByte(handle.get(), &d)); - EXPECT_EQ(c + 1, d); - - // And return it, incremented again. - EXPECT_EQ(c + 2, helper.WaitForChildShutdown()); -} - -MOJO_MULTIPROCESS_TEST_CHILD_MAIN(PassedChannel) { - CHECK(MultiprocessTestHelper::client_platform_handle.is_valid()); - - // Take ownership of the handle. - embedder::ScopedPlatformHandle handle = - std::move(MultiprocessTestHelper::client_platform_handle); - - // The handle should be non-blocking. - EXPECT_TRUE(IsNonBlocking(handle.get())); - - // Read a byte. - char c = 0; - EXPECT_TRUE(ReadByte(handle.get(), &c)); - - // Write it back, incremented. - c++; - EXPECT_TRUE(WriteByte(handle.get(), c)); - - // And return it, incremented again. - c++; - return static_cast<int>(c); -} - -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_ChildTestPasses DISABLED_ChildTestPasses -#else -#define MAYBE_ChildTestPasses ChildTestPasses -#endif // defined(OS_ANDROID) -TEST_F(MultiprocessTestHelperTest, MAYBE_ChildTestPasses) { - MultiprocessTestHelper helper; - EXPECT_TRUE(helper.server_platform_handle.is_valid()); - helper.StartChild("ChildTestPasses"); - EXPECT_TRUE(helper.WaitForChildTestShutdown()); -} - -MOJO_MULTIPROCESS_TEST_CHILD_TEST(ChildTestPasses) { - ASSERT_TRUE(MultiprocessTestHelper::client_platform_handle.is_valid()); - EXPECT_TRUE( - IsNonBlocking(MultiprocessTestHelper::client_platform_handle.get())); -} - -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_ChildTestFailsAssert DISABLED_ChildTestFailsAssert -#else -#define MAYBE_ChildTestFailsAssert ChildTestFailsAssert -#endif // defined(OS_ANDROID) -TEST_F(MultiprocessTestHelperTest, MAYBE_ChildTestFailsAssert) { - MultiprocessTestHelper helper; - EXPECT_TRUE(helper.server_platform_handle.is_valid()); - helper.StartChild("ChildTestFailsAssert"); - EXPECT_FALSE(helper.WaitForChildTestShutdown()); -} - -MOJO_MULTIPROCESS_TEST_CHILD_TEST(ChildTestFailsAssert) { - ASSERT_FALSE(MultiprocessTestHelper::client_platform_handle.is_valid()) - << "DISREGARD: Expected failure in child process"; - ASSERT_FALSE( - IsNonBlocking(MultiprocessTestHelper::client_platform_handle.get())) - << "Not reached"; - CHECK(false) << "Not reached"; -} - -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_ChildTestFailsExpect DISABLED_ChildTestFailsExpect -#else -#define MAYBE_ChildTestFailsExpect ChildTestFailsExpect -#endif // defined(OS_ANDROID) -TEST_F(MultiprocessTestHelperTest, MAYBE_ChildTestFailsExpect) { - MultiprocessTestHelper helper; - EXPECT_TRUE(helper.server_platform_handle.is_valid()); - helper.StartChild("ChildTestFailsExpect"); - EXPECT_FALSE(helper.WaitForChildTestShutdown()); -} - -MOJO_MULTIPROCESS_TEST_CHILD_TEST(ChildTestFailsExpect) { - EXPECT_FALSE(MultiprocessTestHelper::client_platform_handle.is_valid()) - << "DISREGARD: Expected failure #1 in child process"; - EXPECT_FALSE( - IsNonBlocking(MultiprocessTestHelper::client_platform_handle.get())) - << "DISREGARD: Expected failure #2 in child process"; -} - -} // namespace -} // namespace test -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/test/run_all_perftests.cc b/third_party/mojo/src/mojo/edk/test/run_all_perftests.cc deleted file mode 100644 index d82df61..0000000 --- a/third_party/mojo/src/mojo/edk/test/run_all_perftests.cc +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2013 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 "base/test/perf_test_suite.h" -#include "mojo/public/tests/test_support_private.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" -#include "third_party/mojo/src/mojo/edk/test/test_support_impl.h" - -int main(int argc, char** argv) { - base::PerfTestSuite test_suite(argc, argv); - mojo::embedder::Init(); - mojo::test::TestSupport::Init(new mojo::test::TestSupportImpl()); - return test_suite.Run(); -} diff --git a/third_party/mojo/src/mojo/edk/test/run_all_unittests.cc b/third_party/mojo/src/mojo/edk/test/run_all_unittests.cc deleted file mode 100644 index 278cfef..0000000 --- a/third_party/mojo/src/mojo/edk/test/run_all_unittests.cc +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2013 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 <signal.h> - -#include "base/bind.h" -#include "base/test/launcher/unit_test_launcher.h" -#include "base/test/test_suite.h" -#include "mojo/public/tests/test_support_private.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" -#include "third_party/mojo/src/mojo/edk/test/test_support_impl.h" - -int main(int argc, char** argv) { -#if !defined(OS_ANDROID) - // Silence death test thread warnings on Linux. We can afford to run our death - // tests a little more slowly (< 10 ms per death test on a Z620). - // On android, we need to run in the default mode, as the threadsafe mode - // relies on execve which is not available. - testing::GTEST_FLAG(death_test_style) = "threadsafe"; -#endif -#if defined(OS_ANDROID) - // On android, the test framework has a signal handler that will print a - // [ CRASH ] line when the application crashes. This breaks death test has the - // test runner will consider the death of the child process a test failure. - // Removing the signal handler solves this issue. - signal(SIGABRT, SIG_DFL); -#endif - - base::TestSuite test_suite(argc, argv); - - mojo::embedder::Init(); - mojo::test::TestSupport::Init(new mojo::test::TestSupportImpl()); - - return base::LaunchUnitTests( - argc, argv, - base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite))); -} diff --git a/third_party/mojo/src/mojo/edk/test/scoped_ipc_support.cc b/third_party/mojo/src/mojo/edk/test/scoped_ipc_support.cc deleted file mode 100644 index e5e338c..0000000 --- a/third_party/mojo/src/mojo/edk/test/scoped_ipc_support.cc +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2015 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 "third_party/mojo/src/mojo/edk/test/scoped_ipc_support.h" - -#include <utility> - -#include "base/message_loop/message_loop.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" - -namespace mojo { -namespace test { - -namespace internal { - -ScopedIPCSupportHelper::ScopedIPCSupportHelper() { -} - -ScopedIPCSupportHelper::~ScopedIPCSupportHelper() { - if (base::MessageLoop::current() && - base::MessageLoop::current()->task_runner() == io_thread_task_runner_) { - embedder::ShutdownIPCSupportOnIOThread(); - } else { - embedder::ShutdownIPCSupport(); - run_loop_.Run(); - } -} - -void ScopedIPCSupportHelper::Init( - embedder::ProcessType process_type, - embedder::ProcessDelegate* process_delegate, - scoped_refptr<base::TaskRunner> io_thread_task_runner, - embedder::ScopedPlatformHandle platform_handle) { - io_thread_task_runner_ = io_thread_task_runner; - // Note: Run delegate methods on the I/O thread. - embedder::InitIPCSupport(process_type, process_delegate, - io_thread_task_runner_, std::move(platform_handle)); -} - -void ScopedIPCSupportHelper::OnShutdownCompleteImpl() { - run_loop_.Quit(); -} - -} // namespace internal - -ScopedIPCSupport::ScopedIPCSupport( - scoped_refptr<base::TaskRunner> io_thread_task_runner) { - helper_.Init(embedder::ProcessType::NONE, this, - std::move(io_thread_task_runner), - embedder::ScopedPlatformHandle()); -} - -ScopedIPCSupport::~ScopedIPCSupport() { -} - -void ScopedIPCSupport::OnShutdownComplete() { - helper_.OnShutdownCompleteImpl(); -} - -ScopedMasterIPCSupport::ScopedMasterIPCSupport( - scoped_refptr<base::TaskRunner> io_thread_task_runner) { - helper_.Init(embedder::ProcessType::MASTER, this, - std::move(io_thread_task_runner), - embedder::ScopedPlatformHandle()); -} - -ScopedMasterIPCSupport::ScopedMasterIPCSupport( - scoped_refptr<base::TaskRunner> io_thread_task_runner, - base::Callback<void(embedder::SlaveInfo slave_info)> on_slave_disconnect) - : on_slave_disconnect_(on_slave_disconnect) { - helper_.Init(embedder::ProcessType::MASTER, this, - std::move(io_thread_task_runner), - embedder::ScopedPlatformHandle()); -} - -ScopedMasterIPCSupport::~ScopedMasterIPCSupport() { -} - -void ScopedMasterIPCSupport::OnShutdownComplete() { - helper_.OnShutdownCompleteImpl(); -} - -void ScopedMasterIPCSupport::OnSlaveDisconnect(embedder::SlaveInfo slave_info) { - if (!on_slave_disconnect_.is_null()) - on_slave_disconnect_.Run(slave_info); -} - -ScopedSlaveIPCSupport::ScopedSlaveIPCSupport( - scoped_refptr<base::TaskRunner> io_thread_task_runner, - embedder::ScopedPlatformHandle platform_handle) { - helper_.Init(embedder::ProcessType::SLAVE, this, - std::move(io_thread_task_runner), std::move(platform_handle)); -} - -ScopedSlaveIPCSupport::ScopedSlaveIPCSupport( - scoped_refptr<base::TaskRunner> io_thread_task_runner, - embedder::ScopedPlatformHandle platform_handle, - base::Closure on_master_disconnect) - : on_master_disconnect_(on_master_disconnect) { - helper_.Init(embedder::ProcessType::SLAVE, this, - std::move(io_thread_task_runner), std::move(platform_handle)); -} - -ScopedSlaveIPCSupport::~ScopedSlaveIPCSupport() { -} - -void ScopedSlaveIPCSupport::OnShutdownComplete() { - helper_.OnShutdownCompleteImpl(); -} - -void ScopedSlaveIPCSupport::OnMasterDisconnect() { - if (!on_master_disconnect_.is_null()) - on_master_disconnect_.Run(); -} - -} // namespace test -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/test/scoped_ipc_support.h b/third_party/mojo/src/mojo/edk/test/scoped_ipc_support.h deleted file mode 100644 index c46accf..0000000 --- a/third_party/mojo/src/mojo/edk/test/scoped_ipc_support.h +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2015 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 THIRD_PARTY_MOJO_SRC_MOJO_EDK_TEST_SCOPED_IPC_SUPPORT_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_TEST_SCOPED_IPC_SUPPORT_H_ - -#include "base/callback.h" -#include "base/memory/ref_counted.h" -#include "base/run_loop.h" -#include "base/task_runner.h" -#include "mojo/public/cpp/system/macros.h" -#include "third_party/mojo/src/mojo/edk/embedder/master_process_delegate.h" -#include "third_party/mojo/src/mojo/edk/embedder/process_delegate.h" -#include "third_party/mojo/src/mojo/edk/embedder/process_type.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" -#include "third_party/mojo/src/mojo/edk/embedder/slave_process_delegate.h" - -namespace mojo { -namespace test { - -namespace internal { - -class ScopedIPCSupportHelper { - public: - ScopedIPCSupportHelper(); - ~ScopedIPCSupportHelper(); - - void Init(embedder::ProcessType process_type, - embedder::ProcessDelegate* process_delegate, - scoped_refptr<base::TaskRunner> io_thread_task_runner, - embedder::ScopedPlatformHandle platform_handle); - - void OnShutdownCompleteImpl(); - - private: - scoped_refptr<base::TaskRunner> io_thread_task_runner_; - - // Set after shut down. - base::RunLoop run_loop_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedIPCSupportHelper); -}; - -} // namespace internal - -// A simple class that calls |mojo::embedder::InitIPCSupport()| (with -// |ProcessType::NONE|) on construction and |ShutdownIPCSupport()| on -// destruction (or |ShutdownIPCSupportOnIOThread()| if destroyed on the I/O -// thread). -class ScopedIPCSupport : public embedder::ProcessDelegate { - public: - explicit ScopedIPCSupport( - scoped_refptr<base::TaskRunner> io_thread_task_runner); - ~ScopedIPCSupport() override; - - private: - // |ProcessDelegate| implementation: - // Note: Executed on the I/O thread. - void OnShutdownComplete() override; - - internal::ScopedIPCSupportHelper helper_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedIPCSupport); -}; - -// Like |ScopedIPCSupport|, but with |ProcessType::MASTER|. It will (optionally) -// call a callback (on the I/O thread) on receiving |OnSlaveDisconnect()|. -class ScopedMasterIPCSupport : public embedder::MasterProcessDelegate { - public: - explicit ScopedMasterIPCSupport( - scoped_refptr<base::TaskRunner> io_thread_task_runner); - ScopedMasterIPCSupport( - scoped_refptr<base::TaskRunner> io_thread_task_runner, - base::Callback<void(embedder::SlaveInfo slave_info)> on_slave_disconnect); - ~ScopedMasterIPCSupport() override; - - private: - // |MasterProcessDelegate| implementation: - // Note: Executed on the I/O thread. - void OnShutdownComplete() override; - void OnSlaveDisconnect(embedder::SlaveInfo slave_info) override; - - internal::ScopedIPCSupportHelper helper_; - base::Callback<void(embedder::SlaveInfo slave_info)> on_slave_disconnect_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedMasterIPCSupport); -}; - -// Like |ScopedIPCSupport|, but with |ProcessType::SLAVE|. It will (optionally) -// call a callback (on the I/O thread) on receiving |OnMasterDisconnect()|. -class ScopedSlaveIPCSupport : public embedder::SlaveProcessDelegate { - public: - ScopedSlaveIPCSupport(scoped_refptr<base::TaskRunner> io_thread_task_runner, - embedder::ScopedPlatformHandle platform_handle); - ScopedSlaveIPCSupport(scoped_refptr<base::TaskRunner> io_thread_task_runner, - embedder::ScopedPlatformHandle platform_handle, - base::Closure on_master_disconnect); - ~ScopedSlaveIPCSupport() override; - - private: - // |SlaveProcessDelegate| implementation: - // Note: Executed on the I/O thread. - void OnShutdownComplete() override; - void OnMasterDisconnect() override; - - internal::ScopedIPCSupportHelper helper_; - base::Closure on_master_disconnect_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedSlaveIPCSupport); -}; - -} // namespace test -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_TEST_SCOPED_IPC_SUPPORT_H_ diff --git a/third_party/mojo/src/mojo/edk/test/test_support_impl.cc b/third_party/mojo/src/mojo/edk/test/test_support_impl.cc deleted file mode 100644 index e3cd762..0000000 --- a/third_party/mojo/src/mojo/edk/test/test_support_impl.cc +++ /dev/null @@ -1,81 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/test/test_support_impl.h" - -#include <stdlib.h> -#include <string.h> - -#include <string> - -#include "base/files/file_enumerator.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/logging.h" -#include "base/path_service.h" -#include "base/strings/string_split.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "base/test/perf_log.h" - -namespace mojo { -namespace test { -namespace { - -base::FilePath ResolveSourceRootRelativePath(const char* relative_path) { - base::FilePath path; - if (!PathService::Get(base::DIR_SOURCE_ROOT, &path)) - return base::FilePath(); - - for (const base::StringPiece& component : base::SplitStringPiece( - relative_path, "/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) { - if (!component.empty()) - path = path.AppendASCII(component); - } - - return path; -} - -} // namespace - -TestSupportImpl::TestSupportImpl() { -} - -TestSupportImpl::~TestSupportImpl() { -} - -void TestSupportImpl::LogPerfResult(const char* test_name, - const char* sub_test_name, - double value, - const char* units) { - DCHECK(test_name); - if (sub_test_name) { - std::string name = base::StringPrintf("%s/%s", test_name, sub_test_name); - base::LogPerfResult(name.c_str(), value, units); - } else { - base::LogPerfResult(test_name, value, units); - } -} - -FILE* TestSupportImpl::OpenSourceRootRelativeFile(const char* relative_path) { - return base::OpenFile(ResolveSourceRootRelativePath(relative_path), "rb"); -} - -char** TestSupportImpl::EnumerateSourceRootRelativeDirectory( - const char* relative_path) { - std::vector<std::string> names; - base::FileEnumerator e(ResolveSourceRootRelativePath(relative_path), false, - base::FileEnumerator::FILES); - for (base::FilePath name = e.Next(); !name.empty(); name = e.Next()) - names.push_back(name.BaseName().AsUTF8Unsafe()); - - // |names.size() + 1| for null terminator. - char** rv = static_cast<char**>(calloc(names.size() + 1, sizeof(char*))); - for (size_t i = 0; i < names.size(); ++i) - rv[i] = base::strdup(names[i].c_str()); - return rv; -} - -} // namespace test -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/test/test_support_impl.h b/third_party/mojo/src/mojo/edk/test/test_support_impl.h deleted file mode 100644 index 3ab5170..0000000 --- a/third_party/mojo/src/mojo/edk/test/test_support_impl.h +++ /dev/null @@ -1,36 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_TEST_TEST_SUPPORT_IMPL_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_TEST_TEST_SUPPORT_IMPL_H_ - -#include <stdio.h> - -#include "mojo/public/cpp/system/macros.h" -#include "mojo/public/tests/test_support_private.h" - -namespace mojo { -namespace test { - -class TestSupportImpl : public TestSupport { - public: - TestSupportImpl(); - ~TestSupportImpl() override; - - void LogPerfResult(const char* test_name, - const char* sub_test_name, - double value, - const char* units) override; - FILE* OpenSourceRootRelativeFile(const char* relative_path) override; - char** EnumerateSourceRootRelativeDirectory( - const char* relative_path) override; - - private: - MOJO_DISALLOW_COPY_AND_ASSIGN(TestSupportImpl); -}; - -} // namespace test -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_TEST_TEST_SUPPORT_IMPL_H_ diff --git a/third_party/mojo/src/mojo/edk/test/test_utils.h b/third_party/mojo/src/mojo/edk/test/test_utils.h deleted file mode 100644 index 355135a..0000000 --- a/third_party/mojo/src/mojo/edk/test/test_utils.h +++ /dev/null @@ -1,53 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_MOJO_SRC_MOJO_EDK_TEST_TEST_UTILS_H_ -#define THIRD_PARTY_MOJO_SRC_MOJO_EDK_TEST_TEST_UTILS_H_ - -#include <stddef.h> -#include <stdio.h> - -#include <string> - -#include "base/files/scoped_file.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_handle.h" -#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" - -namespace mojo { -namespace test { - -// On success, |bytes_written| is updated to the number of bytes written; -// otherwise it is untouched. -bool BlockingWrite(const embedder::PlatformHandle& handle, - const void* buffer, - size_t bytes_to_write, - size_t* bytes_written); - -// On success, |bytes_read| is updated to the number of bytes read; otherwise it -// is untouched. -bool BlockingRead(const embedder::PlatformHandle& handle, - void* buffer, - size_t buffer_size, - size_t* bytes_read); - -// If the read is done successfully or would block, the function returns true -// and updates |bytes_read| to the number of bytes read (0 if the read would -// block); otherwise it returns false and leaves |bytes_read| untouched. -// |handle| must already be in non-blocking mode. -bool NonBlockingRead(const embedder::PlatformHandle& handle, - void* buffer, - size_t buffer_size, - size_t* bytes_read); - -// Gets a (scoped) |PlatformHandle| from the given (scoped) |FILE|. -embedder::ScopedPlatformHandle PlatformHandleFromFILE(base::ScopedFILE fp); - -// Gets a (scoped) |FILE| from a (scoped) |PlatformHandle|. -base::ScopedFILE FILEFromPlatformHandle(embedder::ScopedPlatformHandle h, - const char* mode); - -} // namespace test -} // namespace mojo - -#endif // THIRD_PARTY_MOJO_SRC_MOJO_EDK_TEST_TEST_UTILS_H_ diff --git a/third_party/mojo/src/mojo/edk/test/test_utils_posix.cc b/third_party/mojo/src/mojo/edk/test/test_utils_posix.cc deleted file mode 100644 index 60845f1..0000000 --- a/third_party/mojo/src/mojo/edk/test/test_utils_posix.cc +++ /dev/null @@ -1,91 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/test/test_utils.h" - -#include <fcntl.h> -#include <unistd.h> - -#include "base/posix/eintr_wrapper.h" - -namespace mojo { -namespace test { - -bool BlockingWrite(const embedder::PlatformHandle& handle, - const void* buffer, - size_t bytes_to_write, - size_t* bytes_written) { - int original_flags = fcntl(handle.fd, F_GETFL); - if (original_flags == -1 || - fcntl(handle.fd, F_SETFL, original_flags & (~O_NONBLOCK)) != 0) { - return false; - } - - ssize_t result = HANDLE_EINTR(write(handle.fd, buffer, bytes_to_write)); - - fcntl(handle.fd, F_SETFL, original_flags); - - if (result < 0) - return false; - - *bytes_written = result; - return true; -} - -bool BlockingRead(const embedder::PlatformHandle& handle, - void* buffer, - size_t buffer_size, - size_t* bytes_read) { - int original_flags = fcntl(handle.fd, F_GETFL); - if (original_flags == -1 || - fcntl(handle.fd, F_SETFL, original_flags & (~O_NONBLOCK)) != 0) { - return false; - } - - ssize_t result = HANDLE_EINTR(read(handle.fd, buffer, buffer_size)); - - fcntl(handle.fd, F_SETFL, original_flags); - - if (result < 0) - return false; - - *bytes_read = result; - return true; -} - -bool NonBlockingRead(const embedder::PlatformHandle& handle, - void* buffer, - size_t buffer_size, - size_t* bytes_read) { - ssize_t result = HANDLE_EINTR(read(handle.fd, buffer, buffer_size)); - - if (result < 0) { - if (errno != EAGAIN && errno != EWOULDBLOCK) - return false; - - *bytes_read = 0; - } else { - *bytes_read = result; - } - - return true; -} - -embedder::ScopedPlatformHandle PlatformHandleFromFILE(base::ScopedFILE fp) { - CHECK(fp); - int rv = dup(fileno(fp.get())); - PCHECK(rv != -1) << "dup"; - return embedder::ScopedPlatformHandle(embedder::PlatformHandle(rv)); -} - -base::ScopedFILE FILEFromPlatformHandle(embedder::ScopedPlatformHandle h, - const char* mode) { - CHECK(h.is_valid()); - base::ScopedFILE rv(fdopen(h.release().fd, mode)); - PCHECK(rv) << "fdopen"; - return rv; -} - -} // namespace test -} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/test/test_utils_win.cc b/third_party/mojo/src/mojo/edk/test/test_utils_win.cc deleted file mode 100644 index 27d1b15..0000000 --- a/third_party/mojo/src/mojo/edk/test/test_utils_win.cc +++ /dev/null @@ -1,112 +0,0 @@ -// 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 "third_party/mojo/src/mojo/edk/test/test_utils.h" - -#include <windows.h> -#include <fcntl.h> -#include <io.h> -#include <string.h> - -namespace mojo { -namespace test { - -bool BlockingWrite(const embedder::PlatformHandle& handle, - const void* buffer, - size_t bytes_to_write, - size_t* bytes_written) { - OVERLAPPED overlapped = {0}; - DWORD bytes_written_dword = 0; - - if (!WriteFile(handle.handle, buffer, static_cast<DWORD>(bytes_to_write), - &bytes_written_dword, &overlapped)) { - if (GetLastError() != ERROR_IO_PENDING || - !GetOverlappedResult(handle.handle, &overlapped, &bytes_written_dword, - TRUE)) { - return false; - } - } - - *bytes_written = bytes_written_dword; - return true; -} - -bool BlockingRead(const embedder::PlatformHandle& handle, - void* buffer, - size_t buffer_size, - size_t* bytes_read) { - OVERLAPPED overlapped = {0}; - DWORD bytes_read_dword = 0; - - if (!ReadFile(handle.handle, buffer, static_cast<DWORD>(buffer_size), - &bytes_read_dword, &overlapped)) { - if (GetLastError() != ERROR_IO_PENDING || - !GetOverlappedResult(handle.handle, &overlapped, &bytes_read_dword, - TRUE)) { - return false; - } - } - - *bytes_read = bytes_read_dword; - return true; -} - -bool NonBlockingRead(const embedder::PlatformHandle& handle, - void* buffer, - size_t buffer_size, - size_t* bytes_read) { - OVERLAPPED overlapped = {0}; - DWORD bytes_read_dword = 0; - - if (!ReadFile(handle.handle, buffer, static_cast<DWORD>(buffer_size), - &bytes_read_dword, &overlapped)) { - if (GetLastError() != ERROR_IO_PENDING) - return false; - - CancelIo(handle.handle); - - if (!GetOverlappedResult(handle.handle, &overlapped, &bytes_read_dword, - TRUE)) { - *bytes_read = 0; - return true; - } - } - - *bytes_read = bytes_read_dword; - return true; -} - -embedder::ScopedPlatformHandle PlatformHandleFromFILE(base::ScopedFILE fp) { - CHECK(fp); - - HANDLE rv = INVALID_HANDLE_VALUE; - PCHECK(DuplicateHandle( - GetCurrentProcess(), - reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(fp.get()))), - GetCurrentProcess(), &rv, 0, TRUE, DUPLICATE_SAME_ACCESS)) - << "DuplicateHandle"; - return embedder::ScopedPlatformHandle(embedder::PlatformHandle(rv)); -} - -base::ScopedFILE FILEFromPlatformHandle(embedder::ScopedPlatformHandle h, - const char* mode) { - CHECK(h.is_valid()); - // Microsoft's documentation for |_open_osfhandle()| only discusses these - // flags (and |_O_WTEXT|). Hmmm. - int flags = 0; - if (strchr(mode, 'a')) - flags |= _O_APPEND; - if (strchr(mode, 'r')) - flags |= _O_RDONLY; - if (strchr(mode, 't')) - flags |= _O_TEXT; - base::ScopedFILE rv(_fdopen( - _open_osfhandle(reinterpret_cast<intptr_t>(h.release().handle), flags), - mode)); - PCHECK(rv) << "_fdopen"; - return rv.Pass(); -} - -} // namespace test -} // namespace mojo diff --git a/tools/battor_agent/battor_agent.gyp b/tools/battor_agent/battor_agent.gyp index a96ffc6..86067ed 100644 --- a/tools/battor_agent/battor_agent.gyp +++ b/tools/battor_agent/battor_agent.gyp @@ -14,8 +14,8 @@ 'battor_agent_lib', '../../device/serial/serial.gyp:device_serial', '../../device/serial/serial.gyp:device_serial_mojo', - '../../third_party/mojo/mojo_public.gyp:mojo_environment_standalone', - '../../third_party/mojo/mojo_public.gyp:mojo_public', + '../../mojo/mojo_public.gyp:mojo_environment_standalone', + '../../mojo/mojo_public.gyp:mojo_public', ], 'sources': [ 'battor_agent_bin.cc', @@ -55,11 +55,11 @@ '../../base/base.gyp:run_all_unittests', '../../base/base.gyp:test_support_base', '../../device/serial/serial.gyp:device_serial', - '../../device/serial/serial.gyp:device_serial_test_util', - '../../testing/gmock.gyp:gmock', + '../../device/serial/serial.gyp:device_serial_test_util', + '../../mojo/mojo_public.gyp:mojo_environment_standalone', + '../../mojo/mojo_public.gyp:mojo_public', + '../../testing/gmock.gyp:gmock', '../../testing/gtest.gyp:gtest', - '../../third_party/mojo/mojo_public.gyp:mojo_environment_standalone', - '../../third_party/mojo/mojo_public.gyp:mojo_public', ], 'sources': [ 'battor_agent_unittest.cc', diff --git a/tools/ipc_fuzzer/message_replay/DEPS b/tools/ipc_fuzzer/message_replay/DEPS index 47a9853..7826d21 100644 --- a/tools/ipc_fuzzer/message_replay/DEPS +++ b/tools/ipc_fuzzer/message_replay/DEPS @@ -1,5 +1,5 @@ include_rules = [ "+chrome/common", "+content/public/common", - "+third_party/mojo/src/mojo/edk/embedder" + "+mojo/edk/embedder" ] diff --git a/tools/ipc_fuzzer/message_replay/replay_process.cc b/tools/ipc_fuzzer/message_replay/replay_process.cc index 3c368a1..8641c14 100644 --- a/tools/ipc_fuzzer/message_replay/replay_process.cc +++ b/tools/ipc_fuzzer/message_replay/replay_process.cc @@ -18,15 +18,15 @@ #include "ipc/ipc_descriptors.h" #include "ipc/ipc_switches.h" #include "ipc/mojo/ipc_channel_mojo.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/embedder.h" namespace ipc_fuzzer { // TODO(morrita): content::InitializeMojo() should be used once it becomes // a public API. See src/content/app/mojo/mojo_init.cc void InitializeMojo() { - mojo::embedder::SetMaxMessageSize(64 * 1024 * 1024); - mojo::embedder::Init(); + mojo::edk::SetMaxMessageSize(64 * 1024 * 1024); + mojo::edk::Init(); } ReplayProcess::ReplayProcess() diff --git a/tools/valgrind/drmemory/suppressions.txt b/tools/valgrind/drmemory/suppressions.txt index a4cf060..c7f20d0 100644 --- a/tools/valgrind/drmemory/suppressions.txt +++ b/tools/valgrind/drmemory/suppressions.txt @@ -779,25 +779,11 @@ system call NtCreateNamedPipeFile *!mojo::edk::PlatformChannelPair::PlatformChannelPair ... *!mojo::edk::ChildProcessLaunched -*!mojo::embedder::ChildProcessLaunched *!content::*::OnProcessLaunched *!content::ChildProcessLauncher::Notify *!content::ChildProcessLauncher::DidLaunch *!base::internal::InvokeHelper<>::MakeItSo -HANDLE LEAK -name=bug_561803_b -system call NtDuplicateObject -*!DuplicateHandle -*!DuplicateHandle -*!mojo::edk::ChildBrokerHost::ChildBrokerHost -*!mojo::edk::ChildProcessLaunched -*!mojo::embedder::ChildProcessLaunched -... -*!content::ChildProcessLauncher::Notify -*!content::ChildProcessLauncher::DidLaunch -*!base::internal::InvokeHelper<>::MakeItSo - GDI USAGE ERROR name=bug_573352 system call NtGdiDeleteObjectApp diff --git a/ui/mojo/geometry/mojo_bindings.gyp b/ui/mojo/geometry/mojo_bindings.gyp index e5bfe67..28e1c98 100644 --- a/ui/mojo/geometry/mojo_bindings.gyp +++ b/ui/mojo/geometry/mojo_bindings.gyp @@ -13,14 +13,14 @@ 'geometry.mojom', ], }, - 'includes': [ '../../../third_party/mojo/mojom_bindings_generator_explicit.gypi' ], + 'includes': [ '../../../mojo/mojom_bindings_generator_explicit.gypi' ], }, { 'target_name': 'mojo_geometry_bindings', 'type': 'static_library', 'dependencies': [ 'mojo_geometry_bindings_mojom', - '../../../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + '../../../mojo/mojo_public.gyp:mojo_cpp_bindings', ], }, ], |