diff options
Diffstat (limited to 'mojo')
241 files changed, 7701 insertions, 1309 deletions
diff --git a/mojo/android/DEPS b/mojo/android/DEPS new file mode 100644 index 0000000000..c80012b562 --- /dev/null +++ b/mojo/android/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+jni", +] diff --git a/mojo/android/javatests/AndroidManifest.xml b/mojo/android/javatests/AndroidManifest.xml new file mode 100644 index 0000000000..8968941f5b --- /dev/null +++ b/mojo/android/javatests/AndroidManifest.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> + <!-- Copyright (c) 2012 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. --> + <!-- package name must be unique so suffix with "tests" so package loader + doesn't ignore this. --> + <manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="org.chromium.mojo.tests"> + <!-- We add an application tag here just so that we can indicate that this + package needs to link against the android.test library, which is + needed when building test cases. --> + <application> + <uses-library android:name="android.test.runner" /> + </application> + <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" /> + <instrumentation android:name="android.test.InstrumentationTestRunner" + android:targetPackage="org.chromium.mojo.tests" + android:label="Tests for org.chromium.mojo"/> + <uses-permission android:name="android.permission.RUN_INSTRUMENTATION" /> + <uses-permission android:name="android.permission.INJECT_EVENTS" /> +</manifest> diff --git a/mojo/public/tools/bindings/pylib/generate/__init__.py b/mojo/android/javatests/apk/EMPTY index e69de29bb2..e69de29bb2 100644 --- a/mojo/public/tools/bindings/pylib/generate/__init__.py +++ b/mojo/android/javatests/apk/EMPTY diff --git a/mojo/android/javatests/core_test.cc b/mojo/android/javatests/core_test.cc new file mode 100644 index 0000000000..3d4032fc52 --- /dev/null +++ b/mojo/android/javatests/core_test.cc @@ -0,0 +1,26 @@ +// 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/android/javatests/core_test.h" + +#include "base/android/jni_android.h" +#include "base/android/scoped_java_ref.h" +#include "jni/CoreTest_jni.h" + +namespace mojo { +namespace android { + +static void InitApplicationContext(JNIEnv* env, + jobject jcaller, + jobject context) { + base::android::ScopedJavaLocalRef<jobject> scoped_context(env, context); + base::android::InitApplicationContext(env, scoped_context); +} + +bool RegisterCoreTest(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +} // namespace android +} // namespace mojo diff --git a/mojo/android/javatests/core_test.h b/mojo/android/javatests/core_test.h new file mode 100644 index 0000000000..96c8878ced --- /dev/null +++ b/mojo/android/javatests/core_test.h @@ -0,0 +1,20 @@ +// 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_ANDROID_JAVATESTS_CORE_TEST_H_ +#define MOJO_ANDROID_JAVATESTS_CORE_TEST_H_ + +#include <jni.h> + +#include "base/android/jni_android.h" + +namespace mojo { +namespace android { + +JNI_EXPORT bool RegisterCoreTest(JNIEnv* env); + +} // namespace android +} // namespace mojo + +#endif // MOJO_SYSTEM_ANDROID_JAVATESTS_CORE_TEST_H_ diff --git a/mojo/android/javatests/init_library.cc b/mojo/android/javatests/init_library.cc new file mode 100644 index 0000000000..7b4cbe3517 --- /dev/null +++ b/mojo/android/javatests/init_library.cc @@ -0,0 +1,40 @@ +// 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/android/base_jni_registrar.h" +#include "base/android/jni_android.h" +#include "base/android/jni_registrar.h" +#include "base/android/library_loader/library_loader_hooks.h" +#include "mojo/android/javatests/core_test.h" +#include "mojo/android/system/core_impl.h" + +namespace { + +base::android::RegistrationMethod kMojoRegisteredMethods[] = { + { "CoreImpl", mojo::android::RegisterCoreImpl }, + { "CoreTest", mojo::android::RegisterCoreTest }, +}; + +bool RegisterMojoJni(JNIEnv* env) { + return RegisterNativeMethods(env, kMojoRegisteredMethods, + arraysize(kMojoRegisteredMethods)); +} + +} // namespace + +JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { + base::android::InitVM(vm); + JNIEnv* env = base::android::AttachCurrentThread(); + + if (!base::android::RegisterLibraryLoaderEntryHook(env)) + return -1; + + if (!base::android::RegisterJni(env)) + return -1; + + if (!RegisterMojoJni(env)) + return -1; + + return JNI_VERSION_1_4; +} diff --git a/mojo/android/javatests/src/org/chromium/mojo/system/CoreTest.java b/mojo/android/javatests/src/org/chromium/mojo/system/CoreTest.java new file mode 100644 index 0000000000..97f091245d --- /dev/null +++ b/mojo/android/javatests/src/org/chromium/mojo/system/CoreTest.java @@ -0,0 +1,471 @@ +// 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. + +package org.chromium.mojo.system; + +import android.content.Context; +import android.test.InstrumentationTestCase; +import android.test.suitebuilder.annotation.SmallTest; + +import org.chromium.base.JNINamespace; +import org.chromium.base.library_loader.LibraryLoader; +import org.chromium.mojo.system.Core.WaitFlags; +import org.chromium.mojo.system.Core.WaitManyResult; +import org.chromium.mojo.system.MessagePipeHandle.ReadFlags; +import org.chromium.mojo.system.MessagePipeHandle.ReadMessageResult; +import org.chromium.mojo.system.MessagePipeHandle.WriteFlags; +import org.chromium.mojo.system.SharedBufferHandle.MapFlags; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Random; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +/** + * Testing the core API. + */ +@JNINamespace("mojo::android") +public class CoreTest extends InstrumentationTestCase { + + private static final ScheduledExecutorService WORKER = + Executors.newSingleThreadScheduledExecutor(); + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + LibraryLoader.ensureInitialized(); + nativeInitApplicationContext(getInstrumentation().getTargetContext()); + } + + /** + * Runnable that will close the given handle. + */ + private static class CloseHandle implements Runnable { + private Handle mHandle; + + CloseHandle(Handle handle) { + mHandle = handle; + } + + @Override + public void run() { + mHandle.close(); + } + } + + private static void checkSendingMessage(MessagePipeHandle in, MessagePipeHandle out) { + Random random = new Random(); + + // Writing a random 8 bytes message. + byte[] bytes = new byte[8]; + random.nextBytes(bytes); + ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.length); + buffer.put(bytes); + in.writeMessage(buffer, null, MessagePipeHandle.WriteFlags.none()); + + // Try to read into a small buffer. + ByteBuffer receiveBuffer = ByteBuffer.allocateDirect(bytes.length / 2); + MessagePipeHandle.ReadMessageResult result = out.readMessage(receiveBuffer, 0, + MessagePipeHandle.ReadFlags.none()); + assertFalse(result.getWasMessageRead()); + assertEquals(bytes.length, result.getMessageSize()); + assertEquals(0, result.getHandlesCount()); + + // Read into a correct buffer. + receiveBuffer = ByteBuffer.allocateDirect(bytes.length); + result = out.readMessage(receiveBuffer, 0, + MessagePipeHandle.ReadFlags.none()); + assertTrue(result.getWasMessageRead()); + assertEquals(bytes.length, result.getMessageSize()); + assertEquals(0, result.getHandlesCount()); + assertEquals(0, receiveBuffer.position()); + assertEquals(result.getMessageSize(), receiveBuffer.limit()); + byte[] receivedBytes = new byte[result.getMessageSize()]; + receiveBuffer.get(receivedBytes); + assertTrue(Arrays.equals(bytes, receivedBytes)); + + } + + /** + * Testing {@link Core#waitMany(List, long)}. + */ + @SmallTest + public void testWaitMany() { + Core core = CoreSingleton.getInstance(); + Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(); + + try { + List<Pair<Handle, WaitFlags>> handlesToWaitOn = new ArrayList< + Pair<Handle, WaitFlags>>(); + + handlesToWaitOn.add( + new Pair<Handle, WaitFlags>(handles.second, + WaitFlags.none().setReadable(true))); + handlesToWaitOn.add( + new Pair<Handle, WaitFlags>(handles.first, WaitFlags.none().setWritable(true))); + WaitManyResult result = core.waitMany(handlesToWaitOn, 0); + assertEquals(MojoResult.OK, result.getMojoResult()); + assertEquals(1, result.getHandleIndex()); + + handlesToWaitOn.clear(); + handlesToWaitOn.add( + new Pair<Handle, WaitFlags>(handles.first, WaitFlags.none().setWritable(true))); + handlesToWaitOn.add( + new Pair<Handle, WaitFlags>(handles.second, + WaitFlags.none().setReadable(true))); + result = core.waitMany(handlesToWaitOn, 0); + assertEquals(MojoResult.OK, result.getMojoResult()); + assertEquals(0, result.getHandleIndex()); + } finally { + handles.first.close(); + handles.second.close(); + } + } + + /** + * Testing {@link MessagePipeHandle}. + */ + @SmallTest + public void testMessagePipeEmpty() { + Core core = CoreSingleton.getInstance(); + Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(); + + try { + // Testing wait. + assertEquals(MojoResult.OK, handles.first.wait(WaitFlags.all(), 0)); + assertEquals(MojoResult.OK, handles.first.wait(WaitFlags.none().setWritable(true), 0)); + assertEquals(MojoResult.DEADLINE_EXCEEDED, + handles.first.wait(WaitFlags.none().setReadable(true), 0)); + + // Testing read on an empty pipe. + boolean exception = false; + try { + handles.first.readMessage(null, 0, MessagePipeHandle.ReadFlags.none()); + } catch (MojoException e) { + assertEquals(MojoResult.SHOULD_WAIT, e.getMojoResult()); + exception = true; + } + assertTrue(exception); + + // Closing a pipe while waiting. + WORKER.schedule(new CloseHandle(handles.first), 10, TimeUnit.MILLISECONDS); + assertEquals(MojoResult.CANCELLED, + handles.first.wait(WaitFlags.none().setReadable(true), 1000000L)); + } finally { + handles.first.close(); + handles.second.close(); + } + + handles = core.createMessagePipe(); + + try { + // Closing the other pipe while waiting. + WORKER.schedule(new CloseHandle(handles.first), 10, TimeUnit.MILLISECONDS); + assertEquals(MojoResult.FAILED_PRECONDITION, + handles.second.wait(WaitFlags.none().setReadable(true), 1000000L)); + + // Waiting on a closed pipe. + assertEquals(MojoResult.FAILED_PRECONDITION, + handles.second.wait(WaitFlags.none().setReadable(true), 0)); + assertEquals(MojoResult.FAILED_PRECONDITION, + handles.second.wait(WaitFlags.none().setWritable(true), 0)); + } finally { + handles.first.close(); + handles.second.close(); + } + + } + + /** + * Testing {@link MessagePipeHandle}. + */ + @SmallTest + public void testMessagePipeSend() { + Core core = CoreSingleton.getInstance(); + Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(); + + try { + checkSendingMessage(handles.first, handles.second); + checkSendingMessage(handles.second, handles.first); + } finally { + handles.first.close(); + handles.second.close(); + } + } + + /** + * Testing {@link MessagePipeHandle}. + */ + @SmallTest + public void testMessagePipeReceiveOnSmallBuffer() { + Random random = new Random(); + Core core = CoreSingleton.getInstance(); + Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(); + + try { + // Writing a random 8 bytes message. + byte[] bytes = new byte[8]; + random.nextBytes(bytes); + ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.length); + buffer.put(bytes); + handles.first.writeMessage(buffer, null, MessagePipeHandle.WriteFlags.none()); + + ByteBuffer receiveBuffer = ByteBuffer.allocateDirect(1); + MessagePipeHandle.ReadMessageResult result = handles.second.readMessage(receiveBuffer, + 0, + MessagePipeHandle.ReadFlags.none()); + assertFalse(result.getWasMessageRead()); + assertEquals(bytes.length, result.getMessageSize()); + assertEquals(0, result.getHandlesCount()); + } finally { + handles.first.close(); + handles.second.close(); + } + } + + /** + * Testing {@link MessagePipeHandle}. + */ + @SmallTest + public void testMessagePipeSendHandles() { + Core core = CoreSingleton.getInstance(); + Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(); + Pair<MessagePipeHandle, MessagePipeHandle> handlesToShare = core.createMessagePipe(); + + try { + handles.first.writeMessage(null, + Collections.<Handle> singletonList(handlesToShare.second), + WriteFlags.none()); + assertFalse(handlesToShare.second.isValid()); + ReadMessageResult readMessageResult = handles.second.readMessage(null, 1, + ReadFlags.none()); + assertEquals(1, readMessageResult.getHandlesCount()); + MessagePipeHandle newHandle = readMessageResult.getHandles().get(0) + .toMessagePipeHandle(); + try { + assertTrue(newHandle.isValid()); + checkSendingMessage(handlesToShare.first, newHandle); + checkSendingMessage(newHandle, handlesToShare.first); + } finally { + newHandle.close(); + } + } finally { + handles.first.close(); + handles.second.close(); + handlesToShare.first.close(); + handlesToShare.second.close(); + } + } + + private static void createAndCloseDataPipe(DataPipe.CreateOptions options) { + Core core = CoreSingleton.getInstance(); + Pair<DataPipe.ProducerHandle, DataPipe.ConsumerHandle> handles = core.createDataPipe( + options); + handles.first.close(); + handles.second.close(); + } + + /** + * Testing {@link DataPipe}. + */ + @SmallTest + public void testDataPipeCreation() { + // Create datapipe with null options. + createAndCloseDataPipe(null); + DataPipe.CreateOptions options = new DataPipe.CreateOptions(); + // Create datapipe with element size set. + options.setElementNumBytes(24); + createAndCloseDataPipe(options); + // Create datapipe with a flag set. + options.getFlags().setMayDiscard(true); + createAndCloseDataPipe(options); + // Create datapipe with capacity set. + options.setCapacityNumBytes(1024 * options.getElementNumBytes()); + createAndCloseDataPipe(options); + } + + /** + * Testing {@link DataPipe}. + */ + @SmallTest + public void testDataPipeSend() { + Core core = CoreSingleton.getInstance(); + Random random = new Random(); + + Pair<DataPipe.ProducerHandle, DataPipe.ConsumerHandle> handles = core.createDataPipe(null); + try { + // Writing a random 8 bytes message. + byte[] bytes = new byte[8]; + random.nextBytes(bytes); + ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.length); + buffer.put(bytes); + int result = handles.first.writeData(buffer, DataPipe.WriteFlags.none()); + assertEquals(bytes.length, result); + + // Query number of bytes available. + result = handles.second.readData(null, + DataPipe.ReadFlags.none().query(true)); + assertEquals(bytes.length, result); + + // Read into a buffer. + ByteBuffer receiveBuffer = ByteBuffer.allocateDirect(bytes.length); + result = handles.second.readData(receiveBuffer, + DataPipe.ReadFlags.none()); + assertEquals(bytes.length, result); + assertEquals(0, receiveBuffer.position()); + assertEquals(bytes.length, receiveBuffer.limit()); + byte[] receivedBytes = new byte[bytes.length]; + receiveBuffer.get(receivedBytes); + assertTrue(Arrays.equals(bytes, receivedBytes)); + } finally { + handles.first.close(); + handles.second.close(); + } + } + + /** + * Testing {@link DataPipe}. + */ + @SmallTest + public void testDataPipeTwoPhaseSend() { + Random random = new Random(); + Core core = CoreSingleton.getInstance(); + Pair<DataPipe.ProducerHandle, DataPipe.ConsumerHandle> handles = core.createDataPipe(null); + + try { + // Writing a random 8 bytes message. + byte[] bytes = new byte[8]; + random.nextBytes(bytes); + ByteBuffer buffer = handles.first.beginWriteData(bytes.length, + DataPipe.WriteFlags.none()); + assertTrue(buffer.capacity() >= bytes.length); + buffer.put(bytes); + handles.first.endWriteData(bytes.length); + + // Read into a buffer. + ByteBuffer receiveBuffer = handles.second.beginReadData(bytes.length, + DataPipe.ReadFlags.none()); + assertEquals(0, receiveBuffer.position()); + assertEquals(bytes.length, receiveBuffer.limit()); + byte[] receivedBytes = new byte[bytes.length]; + receiveBuffer.get(receivedBytes); + assertTrue(Arrays.equals(bytes, receivedBytes)); + handles.second.endReadData(bytes.length); + } finally { + handles.first.close(); + handles.second.close(); + } + } + + /** + * Testing {@link DataPipe}. + */ + @SmallTest + public void testDataPipeDiscard() { + Random random = new Random(); + Core core = CoreSingleton.getInstance(); + Pair<DataPipe.ProducerHandle, DataPipe.ConsumerHandle> handles = core.createDataPipe(null); + + try { + // Writing a random 8 bytes message. + byte[] bytes = new byte[8]; + random.nextBytes(bytes); + ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.length); + buffer.put(bytes); + int result = handles.first.writeData(buffer, DataPipe.WriteFlags.none()); + assertEquals(bytes.length, result); + + // Discard bytes. + final int nbBytesToDiscard = 4; + assertEquals(nbBytesToDiscard, + handles.second.discardData(nbBytesToDiscard, DataPipe.ReadFlags.none())); + + // Read into a buffer. + ByteBuffer receiveBuffer = ByteBuffer.allocateDirect(bytes.length - nbBytesToDiscard); + result = handles.second.readData(receiveBuffer, + DataPipe.ReadFlags.none()); + assertEquals(bytes.length - nbBytesToDiscard, result); + assertEquals(0, receiveBuffer.position()); + assertEquals(bytes.length - nbBytesToDiscard, receiveBuffer.limit()); + byte[] receivedBytes = new byte[bytes.length - nbBytesToDiscard]; + receiveBuffer.get(receivedBytes); + assertTrue(Arrays.equals(Arrays.copyOfRange(bytes, nbBytesToDiscard, bytes.length), + receivedBytes)); + } finally { + handles.first.close(); + handles.second.close(); + } + } + + /** + * Testing {@link SharedBufferHandle}. + */ + @SmallTest + public void testSharedBufferCreation() { + Core core = CoreSingleton.getInstance(); + // Test creation with empty options. + core.createSharedBuffer(null, 8).close(); + // Test creation with default options. + core.createSharedBuffer(new SharedBufferHandle.CreateOptions(), 8); + } + + /** + * Testing {@link SharedBufferHandle}. + */ + @SmallTest + public void testSharedBufferDuplication() { + Core core = CoreSingleton.getInstance(); + SharedBufferHandle handle = core.createSharedBuffer(null, 8); + try { + // Test duplication with empty options. + handle.duplicate(null).close(); + // Test creation with default options. + handle.duplicate(new SharedBufferHandle.DuplicateOptions()).close(); + } finally { + handle.close(); + } + } + + /** + * Testing {@link SharedBufferHandle}. + */ + @SmallTest + public void testSharedBufferSending() { + Random random = new Random(); + Core core = CoreSingleton.getInstance(); + SharedBufferHandle handle = core.createSharedBuffer(null, 8); + SharedBufferHandle newHandle = handle.duplicate(null); + + try { + ByteBuffer buffer1 = handle.map(0, 8, MapFlags.none()); + assertEquals(8, buffer1.capacity()); + ByteBuffer buffer2 = newHandle.map(0, 8, MapFlags.none()); + assertEquals(8, buffer2.capacity()); + + byte[] bytes = new byte[8]; + random.nextBytes(bytes); + buffer1.put(bytes); + + byte[] receivedBytes = new byte[bytes.length]; + buffer2.get(receivedBytes); + + assertTrue(Arrays.equals(bytes, receivedBytes)); + + handle.unmap(buffer1); + newHandle.unmap(buffer2); + } finally { + handle.close(); + newHandle.close(); + } + } + + private native void nativeInitApplicationContext(Context context); +} diff --git a/mojo/android/system/core_impl.cc b/mojo/android/system/core_impl.cc new file mode 100644 index 0000000000..d7552c1a29 --- /dev/null +++ b/mojo/android/system/core_impl.cc @@ -0,0 +1,293 @@ +// 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/android/system/core_impl.h" + +#include "base/android/base_jni_registrar.h" +#include "base/android/jni_android.h" +#include "base/android/jni_registrar.h" +#include "base/android/library_loader/library_loader_hooks.h" +#include "base/logging.h" +#include "jni/CoreImpl_jni.h" +#include "mojo/embedder/embedder.h" +#include "mojo/public/c/system/core.h" + +namespace mojo { +namespace android { + +static void Constructor(JNIEnv* env, jobject jcaller) { + mojo::embedder::Init(); +} + +static jlong GetTimeTicksNow(JNIEnv* env, jobject jcaller) { + return MojoGetTimeTicksNow(); +} + +static jint WaitMany(JNIEnv* env, + jobject jcaller, + jobject buffer, + jlong deadline) { + // Buffer contains first the list of handles, then the list of flags. + const void* buffer_start = env->GetDirectBufferAddress(buffer); + DCHECK(buffer_start); + const size_t record_size = 8; + const size_t buffer_size = env->GetDirectBufferCapacity(buffer); + DCHECK_EQ(buffer_size % record_size, 0u); + + const size_t nb_handles = buffer_size / record_size; + const MojoHandle* handle_start = static_cast<const MojoHandle*>(buffer_start); + const MojoWaitFlags* flags_start = + static_cast<const MojoWaitFlags*>(handle_start + nb_handles); + return MojoWaitMany(handle_start, flags_start, nb_handles, deadline); +} + +static jobject CreateMessagePipe(JNIEnv* env, jobject jcaller) { + MojoHandle handle1; + MojoHandle handle2; + MojoResult result = MojoCreateMessagePipe(&handle1, &handle2); + return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2) + .Release(); +} + +static jobject CreateDataPipe(JNIEnv* env, + jobject jcaller, + jobject options_buffer) { + const MojoCreateDataPipeOptions* options = NULL; + if (options_buffer) { + const void* buffer_start = env->GetDirectBufferAddress(options_buffer); + DCHECK(buffer_start); + const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer); + DCHECK_EQ(buffer_size, sizeof(MojoCreateDataPipeOptions)); + options = static_cast<const MojoCreateDataPipeOptions*>(buffer_start); + DCHECK_EQ(options->struct_size, buffer_size); + } + MojoHandle handle1; + MojoHandle handle2; + MojoResult result = MojoCreateDataPipe(options, &handle1, &handle2); + return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2) + .Release(); +} + +static jobject CreateSharedBuffer(JNIEnv* env, + jobject jcaller, + jobject options_buffer, + jlong num_bytes) { + const MojoCreateSharedBufferOptions* options = 0; + if (options_buffer) { + const void* buffer_start = env->GetDirectBufferAddress(options_buffer); + DCHECK(buffer_start); + const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer); + DCHECK_EQ(buffer_size, sizeof(MojoCreateSharedBufferOptions)); + options = static_cast<const MojoCreateSharedBufferOptions*>(buffer_start); + DCHECK_EQ(options->struct_size, buffer_size); + } + MojoHandle handle; + MojoResult result = MojoCreateSharedBuffer(options, num_bytes, &handle); + return Java_CoreImpl_newNativeCreationResult(env, result, handle, 0) + .Release(); +} + +static jint Close(JNIEnv* env, jobject jcaller, jint mojo_handle) { + return MojoClose(mojo_handle); +} + +static jint Wait(JNIEnv* env, + jobject jcaller, + jint mojo_handle, + jint flags, + jlong deadline) { + return MojoWait(mojo_handle, flags, deadline); +} + +static jint WriteMessage(JNIEnv* env, + jobject jcaller, + jint mojo_handle, + jobject bytes, + jint num_bytes, + jobject handles_buffer, + jint flags) { + const void* buffer_start = 0; + uint32_t buffer_size = 0; + if (bytes) { + buffer_start = env->GetDirectBufferAddress(bytes); + DCHECK(buffer_start); + DCHECK(env->GetDirectBufferCapacity(bytes) >= num_bytes); + buffer_size = num_bytes; + } + const MojoHandle* handles = 0; + uint32_t num_handles = 0; + if (handles_buffer) { + handles = + static_cast<MojoHandle*>(env->GetDirectBufferAddress(handles_buffer)); + num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4; + } + // Java code will handle invalidating handles if the write succeeded. + return MojoWriteMessage( + mojo_handle, buffer_start, buffer_size, handles, num_handles, flags); +} + +static jobject ReadMessage(JNIEnv* env, + jobject jcaller, + jint mojo_handle, + jobject bytes, + jobject handles_buffer, + jint flags) { + void* buffer_start = 0; + uint32_t buffer_size = 0; + if (bytes) { + buffer_start = env->GetDirectBufferAddress(bytes); + DCHECK(buffer_start); + buffer_size = env->GetDirectBufferCapacity(bytes); + } + MojoHandle* handles = 0; + uint32_t num_handles = 0; + if (handles_buffer) { + handles = + static_cast<MojoHandle*>(env->GetDirectBufferAddress(handles_buffer)); + num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4; + } + MojoResult result = MojoReadMessage( + mojo_handle, buffer_start, &buffer_size, handles, &num_handles, flags); + // Jave code will handle taking ownership of any received handle. + return Java_CoreImpl_newNativeReadMessageResult( + env, result, buffer_size, num_handles).Release(); +} + +static jint ReadData(JNIEnv* env, + jobject jcaller, + jint mojo_handle, + jobject elements, + jint elements_capacity, + jint flags) { + void* buffer_start = 0; + uint32_t buffer_size = elements_capacity; + if (elements) { + buffer_start = env->GetDirectBufferAddress(elements); + DCHECK(buffer_start); + DCHECK(elements_capacity <= env->GetDirectBufferCapacity(elements)); + } + MojoResult result = + MojoReadData(mojo_handle, buffer_start, &buffer_size, flags); + if (result < 0) { + return result; + } + return buffer_size; +} + +static jobject BeginReadData(JNIEnv* env, + jobject jcaller, + jint mojo_handle, + jint num_bytes, + jint flags) { + void const* buffer = 0; + uint32_t buffer_size = num_bytes; + MojoResult result = + MojoBeginReadData(mojo_handle, &buffer, &buffer_size, flags); + jobject byte_buffer = 0; + if (result == MOJO_RESULT_OK) { + byte_buffer = + env->NewDirectByteBuffer(const_cast<void*>(buffer), buffer_size); + } + return Java_CoreImpl_newNativeCodeAndBufferResult(env, result, byte_buffer) + .Release(); +} + +static jint EndReadData(JNIEnv* env, + jobject jcaller, + jint mojo_handle, + jint num_bytes_read) { + return MojoEndReadData(mojo_handle, num_bytes_read); +} + +static jint WriteData(JNIEnv* env, + jobject jcaller, + jint mojo_handle, + jobject elements, + jint limit, + jint flags) { + void* buffer_start = env->GetDirectBufferAddress(elements); + DCHECK(buffer_start); + DCHECK(limit <= env->GetDirectBufferCapacity(elements)); + uint32_t buffer_size = limit; + MojoResult result = + MojoWriteData(mojo_handle, buffer_start, &buffer_size, flags); + if (result < 0) { + return result; + } + return buffer_size; +} + +static jobject BeginWriteData(JNIEnv* env, + jobject jcaller, + jint mojo_handle, + jint num_bytes, + jint flags) { + void* buffer = 0; + uint32_t buffer_size = num_bytes; + MojoResult result = + MojoBeginWriteData(mojo_handle, &buffer, &buffer_size, flags); + jobject byte_buffer = 0; + if (result == MOJO_RESULT_OK) { + byte_buffer = env->NewDirectByteBuffer(buffer, buffer_size); + } + return Java_CoreImpl_newNativeCodeAndBufferResult(env, result, byte_buffer) + .Release(); +} + +static jint EndWriteData(JNIEnv* env, + jobject jcaller, + jint mojo_handle, + jint num_bytes_written) { + return MojoEndWriteData(mojo_handle, num_bytes_written); +} + +static jobject Duplicate(JNIEnv* env, + jobject jcaller, + jint mojo_handle, + jobject options_buffer) { + const MojoDuplicateBufferHandleOptions* options = 0; + if (options_buffer) { + const void* buffer_start = env->GetDirectBufferAddress(options_buffer); + DCHECK(buffer_start); + const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer); + DCHECK_EQ(buffer_size, sizeof(MojoDuplicateBufferHandleOptions)); + options = + static_cast<const MojoDuplicateBufferHandleOptions*>(buffer_start); + DCHECK_EQ(options->struct_size, buffer_size); + } + MojoHandle handle; + MojoResult result = MojoDuplicateBufferHandle(mojo_handle, options, &handle); + return Java_CoreImpl_newNativeCreationResult(env, result, handle, 0) + .Release(); +} + +static jobject Map(JNIEnv* env, + jobject jcaller, + jint mojo_handle, + jlong offset, + jlong num_bytes, + jint flags) { + void* buffer = 0; + MojoResult result = + MojoMapBuffer(mojo_handle, offset, num_bytes, &buffer, flags); + jobject byte_buffer = 0; + if (result == MOJO_RESULT_OK) { + byte_buffer = env->NewDirectByteBuffer(buffer, num_bytes); + } + return Java_CoreImpl_newNativeCodeAndBufferResult(env, result, byte_buffer) + .Release(); +} + +static int Unmap(JNIEnv* env, jobject jcaller, jobject buffer) { + void* buffer_start = env->GetDirectBufferAddress(buffer); + DCHECK(buffer_start); + return MojoUnmapBuffer(buffer_start); +} + +bool RegisterCoreImpl(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +} // namespace android +} // namespace mojo diff --git a/mojo/android/system/core_impl.h b/mojo/android/system/core_impl.h new file mode 100644 index 0000000000..c6249994e5 --- /dev/null +++ b/mojo/android/system/core_impl.h @@ -0,0 +1,20 @@ +// 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_ANDROID_SYSTEM_CORE_IMPL_H_ +#define MOJO_ANDROID_SYSTEM_CORE_IMPL_H_ + +#include <jni.h> + +#include "base/android/jni_android.h" + +namespace mojo { +namespace android { + +JNI_EXPORT bool RegisterCoreImpl(JNIEnv* env); + +} // namespace android +} // namespace mojo + +#endif // MOJO_ANDROID_SYSTEM_CORE_IMPL_H_ diff --git a/mojo/android/system/src/org/chromium/mojo/system/CoreImpl.java b/mojo/android/system/src/org/chromium/mojo/system/CoreImpl.java new file mode 100644 index 0000000000..1d8e56bcf0 --- /dev/null +++ b/mojo/android/system/src/org/chromium/mojo/system/CoreImpl.java @@ -0,0 +1,584 @@ +// 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. + +package org.chromium.mojo.system; + +import org.chromium.base.CalledByNative; +import org.chromium.base.JNINamespace; +import org.chromium.mojo.system.DataPipe.ConsumerHandle; +import org.chromium.mojo.system.DataPipe.ProducerHandle; +import org.chromium.mojo.system.SharedBufferHandle.DuplicateOptions; +import org.chromium.mojo.system.SharedBufferHandle.MapFlags; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.List; + +/** + * Implementation of {@link Core}. + */ +@JNINamespace("mojo::android") +class CoreImpl implements Core { + + /** + * Discard flag for the |MojoReadData| operation. + */ + private static final int MOJO_READ_DATA_FLAG_DISCARD = 1 << 1; + + /** + * the size of a handle, in bytes. + */ + private static final int HANDLE_SIZE = 4; + + /** + * the size of a flag, in bytes. + */ + private static final int FLAG_SIZE = 4; + + /** + * The singleton instance. + */ + private static Core sINSTANCE = null; + + /** + * @return the instance. + */ + static synchronized Core getInstance() { + if (sINSTANCE == null) { + sINSTANCE = new CoreImpl(); + } + return sINSTANCE; + } + + private CoreImpl() { + nativeConstructor(); + } + + /** + * @see Core#getTimeTicksNow() + */ + @Override + public long getTimeTicksNow() { + return nativeGetTimeTicksNow(); + } + + /** + * @see Core#waitMany(List, long) + */ + @Override + public WaitManyResult waitMany(List<Pair<Handle, WaitFlags>> handles, long deadline) { + // Allocate a direct buffer to allow native code not to reach back to java. Buffer will + // contain all mojo handles, followed by all flags values. + ByteBuffer buffer = allocateDirectBuffer(handles.size() * 8); + int index = 0; + for (Pair<Handle, WaitFlags> handle : handles) { + HandleImpl realHandler = (HandleImpl) handle.first; + buffer.putInt(HANDLE_SIZE * index, realHandler.getMojoHandle()); + buffer.putInt(HANDLE_SIZE * handles.size() + FLAG_SIZE * index, + handle.second.getFlags()); + index++; + } + int code = nativeWaitMany(buffer, deadline); + WaitManyResult result = new WaitManyResult(); + // If result is greater than 0, result is the indexed of the available handle. To make sure + // it cannot be misinterpreted, set handleIndex to a negative number in case of error. + result.setHandleIndex(code); + result.setMojoResult(filterMojoResultForWait(code)); + return result; + } + + /** + * @see Core#wait(Handle, WaitFlags, long) + */ + @Override + public int wait(Handle handle, WaitFlags flags, long deadline) { + return filterMojoResultForWait(nativeWait(((HandleImpl) handle).getMojoHandle(), + flags.getFlags(), deadline)); + } + + /** + * @see Core#createMessagePipe() + */ + @Override + public Pair<MessagePipeHandle, MessagePipeHandle> createMessagePipe() { + NativeCreationResult result = nativeCreateMessagePipe(); + if (result.getMojoResult() != MojoResult.OK) { + throw new MojoException(result.getMojoResult()); + } + return Pair.create( + new MessagePipeHandleImpl(this, result.getMojoHandle1()), + new MessagePipeHandleImpl(this, result.getMojoHandle2())); + } + + /** + * @see Core#createDataPipe(DataPipe.CreateOptions) + */ + @Override + public Pair<ProducerHandle, ConsumerHandle> createDataPipe(DataPipe.CreateOptions options) { + ByteBuffer optionsBuffer = null; + if (options != null) { + optionsBuffer = allocateDirectBuffer(16); + optionsBuffer.putInt(0, 16); + optionsBuffer.putInt(4, options.getFlags().getFlags()); + optionsBuffer.putInt(8, options.getElementNumBytes()); + optionsBuffer.putInt(12, options.getCapacityNumBytes()); + } + NativeCreationResult result = nativeCreateDataPipe(optionsBuffer); + if (result.getMojoResult() != MojoResult.OK) { + throw new MojoException(result.getMojoResult()); + } + return Pair.create( + new DataPipeProducerHandleImpl(this, result.getMojoHandle1()), + new DataPipeConsumerHandleImpl(this, result.getMojoHandle2())); + } + + /** + * @see Core#createSharedBuffer(SharedBufferHandle.CreateOptions, long) + */ + @Override + public SharedBufferHandle createSharedBuffer( + SharedBufferHandle.CreateOptions options, long numBytes) { + ByteBuffer optionsBuffer = null; + if (options != null) { + optionsBuffer = allocateDirectBuffer(8); + optionsBuffer.putInt(0, 8); + optionsBuffer.putInt(4, options.getFlags().getFlags()); + } + NativeCreationResult result = nativeCreateSharedBuffer(optionsBuffer, numBytes); + if (result.getMojoResult() != MojoResult.OK) { + throw new MojoException(result.getMojoResult()); + } + assert result.getMojoHandle2() == 0; + return new SharedBufferHandleImpl(this, result.getMojoHandle1()); + } + + int closeWithResult(int mojoHandle) { + return nativeClose(mojoHandle); + } + + void close(int mojoHandle) { + int mojoResult = nativeClose(mojoHandle); + if (mojoResult != MojoResult.OK) { + throw new MojoException(mojoResult); + } + } + + /** + * @see MessagePipeHandle#writeMessage(ByteBuffer, List, MessagePipeHandle.WriteFlags) + */ + void writeMessage(MessagePipeHandleImpl pipeHandle, ByteBuffer bytes, + List<Handle> handles, MessagePipeHandle.WriteFlags flags) { + ByteBuffer handlesBuffer = null; + if (handles != null && !handles.isEmpty()) { + handlesBuffer = allocateDirectBuffer(handles.size() * HANDLE_SIZE); + for (Handle handle : handles) { + HandleImpl realHandle = (HandleImpl) handle; + handlesBuffer.putInt(realHandle.getMojoHandle()); + } + handlesBuffer.position(0); + } + int mojoResult = nativeWriteMessage(pipeHandle.getMojoHandle(), bytes, + bytes == null ? 0 : bytes.limit(), handlesBuffer, + flags.getFlags()); + if (mojoResult != MojoResult.OK) { + throw new MojoException(mojoResult); + } + // Success means the handles have been invalidated. + if (handles != null) { + for (Handle handle : handles) { + ((HandleImpl) handle).invalidateHandle(); + } + } + } + + /** + * @see MessagePipeHandle#readMessage(ByteBuffer, int, MessagePipeHandle.ReadFlags) + */ + MessagePipeHandle.ReadMessageResult readMessage(MessagePipeHandleImpl handle, + ByteBuffer bytes, int maxNumberOfHandles, + MessagePipeHandle.ReadFlags flags) { + ByteBuffer handlesBuffer = null; + if (maxNumberOfHandles > 0) { + handlesBuffer = allocateDirectBuffer(maxNumberOfHandles * HANDLE_SIZE); + } + NativeReadMessageResult result = nativeReadMessage( + handle.getMojoHandle(), bytes, handlesBuffer, flags.getFlags()); + if (result.getMojoResult() != MojoResult.OK && + result.getMojoResult() != MojoResult.RESOURCE_EXHAUSTED) { + throw new MojoException(result.getMojoResult()); + } + + if (result.getMojoResult() == MojoResult.OK) { + if (bytes != null) { + bytes.position(0); + bytes.limit(result.getReadMessageResult().getMessageSize()); + } + + List<UntypedHandle> handles = new ArrayList<UntypedHandle>( + result.getReadMessageResult().getHandlesCount()); + for (int i = 0; i < result.getReadMessageResult().getHandlesCount(); ++i) { + int mojoHandle = handlesBuffer.getInt(HANDLE_SIZE * i); + handles.add(new UntypedHandleImpl(this, mojoHandle)); + } + result.getReadMessageResult().setHandles(handles); + } + return result.getReadMessageResult(); + } + + /** + * @see DataPipe.ConsumerHandle#discardData(int, DataPipe.ReadFlags) + */ + int discardData(DataPipeConsumerHandleImpl handle, int numBytes, + DataPipe.ReadFlags flags) { + int result = nativeReadData(handle.getMojoHandle(), null, numBytes, + flags.getFlags() | MOJO_READ_DATA_FLAG_DISCARD); + if (result < 0) { + throw new MojoException(result); + } + return result; + } + + /** + * @see DataPipe.ConsumerHandle#readData(ByteBuffer, DataPipe.ReadFlags) + */ + int readData(DataPipeConsumerHandleImpl handle, ByteBuffer elements, + DataPipe.ReadFlags flags) { + int result = nativeReadData(handle.getMojoHandle(), elements, + elements == null ? 0 : elements.capacity(), + flags.getFlags()); + if (result < 0) { + throw new MojoException(result); + } + if (elements != null) { + elements.limit(result); + } + return result; + } + + /** + * @see DataPipe.ConsumerHandle#beginReadData(int, DataPipe.ReadFlags) + */ + ByteBuffer beginReadData(DataPipeConsumerHandleImpl handle, + int numBytes, DataPipe.ReadFlags flags) { + NativeCodeAndBufferResult result = nativeBeginReadData( + handle.getMojoHandle(), + numBytes, + flags.getFlags()); + if (result.getMojoResult() != MojoResult.OK) { + throw new MojoException(result.getMojoResult()); + } + return result.getBuffer().asReadOnlyBuffer(); + } + + /** + * @see DataPipe.ConsumerHandle#endReadData(int) + */ + void endReadData(DataPipeConsumerHandleImpl handle, + int numBytesRead) { + int result = nativeEndReadData(handle.getMojoHandle(), numBytesRead); + if (result != MojoResult.OK) { + throw new MojoException(result); + } + } + + /** + * @see DataPipe.ProducerHandle#writeData(ByteBuffer, DataPipe.WriteFlags) + */ + int writeData(DataPipeProducerHandleImpl handle, ByteBuffer elements, + DataPipe.WriteFlags flags) { + return nativeWriteData(handle.getMojoHandle(), elements, elements.limit(), + flags.getFlags()); + } + + /** + * @see DataPipe.ProducerHandle#beginWriteData(int, DataPipe.WriteFlags) + */ + ByteBuffer beginWriteData(DataPipeProducerHandleImpl handle, + int numBytes, DataPipe.WriteFlags flags) { + NativeCodeAndBufferResult result = nativeBeginWriteData( + handle.getMojoHandle(), + numBytes, + flags.getFlags()); + if (result.getMojoResult() != MojoResult.OK) { + throw new MojoException(result.getMojoResult()); + } + return result.getBuffer(); + } + + /** + * @see DataPipe.ProducerHandle#endWriteData(int) + */ + void endWriteData(DataPipeProducerHandleImpl handle, + int numBytesWritten) { + int result = nativeEndWriteData(handle.getMojoHandle(), numBytesWritten); + if (result != MojoResult.OK) { + throw new MojoException(result); + } + } + + /** + * @see SharedBufferHandle#duplicate(DuplicateOptions) + */ + SharedBufferHandle duplicate(SharedBufferHandleImpl handle, + DuplicateOptions options) { + ByteBuffer optionsBuffer = null; + if (options != null) { + optionsBuffer = allocateDirectBuffer(8); + optionsBuffer.putInt(0, 8); + optionsBuffer.putInt(4, options.getFlags().getFlags()); + } + NativeCreationResult result = nativeDuplicate(handle.getMojoHandle(), + optionsBuffer); + if (result.getMojoResult() != MojoResult.OK) { + throw new MojoException(result.getMojoResult()); + } + assert result.getMojoHandle2() == 0; + return new SharedBufferHandleImpl(this, result.getMojoHandle1()); + } + + /** + * @see SharedBufferHandle#map(long, long, MapFlags) + */ + ByteBuffer map(SharedBufferHandleImpl handle, long offset, long numBytes, + MapFlags flags) { + NativeCodeAndBufferResult result = nativeMap(handle.getMojoHandle(), offset, numBytes, + flags.getFlags()); + if (result.getMojoResult() != MojoResult.OK) { + throw new MojoException(result.getMojoResult()); + } + return result.getBuffer(); + } + + /** + * @see SharedBufferHandle#unmap(ByteBuffer) + */ + void unmap(ByteBuffer buffer) { + int result = nativeUnmap(buffer); + if (result != MojoResult.OK) { + throw new MojoException(result); + } + } + + private static int filterMojoResultForWait(int code) { + if (code >= 0) { + return MojoResult.OK; + } + switch (code) { + case MojoResult.DEADLINE_EXCEEDED: + case MojoResult.CANCELLED: + case MojoResult.FAILED_PRECONDITION: + return code; + default: + throw new MojoException(code); + } + + } + + private static ByteBuffer allocateDirectBuffer(int capacity) { + ByteBuffer buffer = ByteBuffer.allocateDirect(capacity); + buffer.order(ByteOrder.nativeOrder()); + return buffer; + } + + private static class NativeCodeAndBufferResult { + private int mMojoResult; + private ByteBuffer mBuffer; + + /** + * @return the mojoResult + */ + public int getMojoResult() { + return mMojoResult; + } + + /** + * @param mojoResult the mojoResult to set + */ + public void setMojoResult(int mojoResult) { + mMojoResult = mojoResult; + } + + /** + * @return the buffer + */ + public ByteBuffer getBuffer() { + return mBuffer; + } + + /** + * @param buffer the buffer to set + */ + public void setBuffer(ByteBuffer buffer) { + mBuffer = buffer; + } + + } + + @CalledByNative + private static NativeCodeAndBufferResult newNativeCodeAndBufferResult(int mojoResult, + ByteBuffer buffer) { + NativeCodeAndBufferResult result = new NativeCodeAndBufferResult(); + result.setMojoResult(mojoResult); + result.setBuffer(buffer); + return result; + } + + private static class NativeReadMessageResult { + public int mMojoResult; + public MessagePipeHandle.ReadMessageResult mReadMessageResult; + + /** + * @return the mojoResult + */ + public int getMojoResult() { + return mMojoResult; + } + + /** + * @param mojoResult the mojoResult to set + */ + public void setMojoResult(int mojoResult) { + this.mMojoResult = mojoResult; + } + + /** + * @return the readMessageResult + */ + public MessagePipeHandle.ReadMessageResult getReadMessageResult() { + return mReadMessageResult; + } + + /** + * @param readMessageResult the readMessageResult to set + */ + public void setReadMessageResult(MessagePipeHandle.ReadMessageResult readMessageResult) { + this.mReadMessageResult = readMessageResult; + } + } + + @CalledByNative + private static NativeReadMessageResult newNativeReadMessageResult(int mojoResult, + int messageSize, + int handlesCount) { + NativeReadMessageResult result = new NativeReadMessageResult(); + if (mojoResult >= 0) { + result.setMojoResult(MojoResult.OK); + } else { + result.setMojoResult(mojoResult); + } + MessagePipeHandle.ReadMessageResult readMessageResult = + new MessagePipeHandle.ReadMessageResult(); + readMessageResult.setWasMessageRead(result.getMojoResult() == MojoResult.OK); + readMessageResult.setMessageSize(messageSize); + readMessageResult.setHandlesCount(handlesCount); + result.setReadMessageResult(readMessageResult); + return result; + } + + private static class NativeCreationResult { + private int mMojoResult; + private int mMojoHandle1; + private int mMojoHandle2; + + /** + * @return the mojoResult + */ + public int getMojoResult() { + return mMojoResult; + } + + /** + * @param mojoResult the mojoResult to set + */ + public void setMojoResult(int mojoResult) { + mMojoResult = mojoResult; + } + + /** + * @return the mojoHandle1 + */ + public int getMojoHandle1() { + return mMojoHandle1; + } + + /** + * @param mojoHandle1 the mojoHandle1 to set + */ + public void setMojoHandle1(int mojoHandle1) { + mMojoHandle1 = mojoHandle1; + } + + /** + * @return the mojoHandle2 + */ + public int getMojoHandle2() { + return mMojoHandle2; + } + + /** + * @param mojoHandle2 the mojoHandle2 to set + */ + public void setMojoHandle2(int mojoHandle2) { + mMojoHandle2 = mojoHandle2; + } + } + + @CalledByNative + private static NativeCreationResult newNativeCreationResult(int mojoResult, + int mojoHandle1, int mojoHandle2) { + NativeCreationResult result = new NativeCreationResult(); + result.setMojoResult(mojoResult); + result.setMojoHandle1(mojoHandle1); + result.setMojoHandle2(mojoHandle2); + return result; + } + + private native void nativeConstructor(); + + private native long nativeGetTimeTicksNow(); + + private native int nativeWaitMany(ByteBuffer buffer, long deadline); + + private native NativeCreationResult nativeCreateMessagePipe(); + + private native NativeCreationResult nativeCreateDataPipe(ByteBuffer optionsBuffer); + + private native NativeCreationResult nativeCreateSharedBuffer(ByteBuffer optionsBuffer, + long numBytes); + + private native int nativeClose(int mojoHandle); + + private native int nativeWait(int mojoHandle, int flags, long deadline); + + private native int nativeWriteMessage(int mojoHandle, ByteBuffer bytes, int numBytes, + ByteBuffer handlesBuffer, int flags); + + private native NativeReadMessageResult nativeReadMessage(int mojoHandle, ByteBuffer bytes, + ByteBuffer handlesBuffer, + int flags); + + private native int nativeReadData(int mojoHandle, ByteBuffer elements, int elementsSize, + int flags); + + private native NativeCodeAndBufferResult nativeBeginReadData(int mojoHandle, int numBytes, + int flags); + + private native int nativeEndReadData(int mojoHandle, int numBytesRead); + + private native int nativeWriteData(int mojoHandle, ByteBuffer elements, int limit, int flags); + + private native NativeCodeAndBufferResult nativeBeginWriteData(int mojoHandle, int numBytes, + int flags); + + private native int nativeEndWriteData(int mojoHandle, int numBytesWritten); + + private native NativeCreationResult nativeDuplicate(int mojoHandle, ByteBuffer optionsBuffer); + + private native NativeCodeAndBufferResult nativeMap(int mojoHandle, long offset, long numBytes, + int flags); + + private native int nativeUnmap(ByteBuffer buffer); + +} diff --git a/mojo/android/system/src/org/chromium/mojo/system/CoreSingleton.java b/mojo/android/system/src/org/chromium/mojo/system/CoreSingleton.java new file mode 100644 index 0000000000..3cdbf969af --- /dev/null +++ b/mojo/android/system/src/org/chromium/mojo/system/CoreSingleton.java @@ -0,0 +1,18 @@ +// 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. + +package org.chromium.mojo.system; + +/** + * Access to the core singleton. + */ +public class CoreSingleton { + + /** + * Access to the {@link Core} singleton. + */ + public static Core getInstance() { + return CoreImpl.getInstance(); + } +} diff --git a/mojo/android/system/src/org/chromium/mojo/system/DataPipeConsumerHandleImpl.java b/mojo/android/system/src/org/chromium/mojo/system/DataPipeConsumerHandleImpl.java new file mode 100644 index 0000000000..84985bfe82 --- /dev/null +++ b/mojo/android/system/src/org/chromium/mojo/system/DataPipeConsumerHandleImpl.java @@ -0,0 +1,63 @@ +// 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. + +package org.chromium.mojo.system; + +import org.chromium.mojo.system.DataPipe.ConsumerHandle; +import org.chromium.mojo.system.DataPipe.ReadFlags; + +import java.nio.ByteBuffer; + +/** + * Implementation of {@link ConsumerHandle}. + */ +class DataPipeConsumerHandleImpl extends HandleImpl implements ConsumerHandle { + + /** + * @see HandleImpl#HandleImpl(CoreImpl, int) + */ + DataPipeConsumerHandleImpl(CoreImpl core, int mojoHandle) { + super(core, mojoHandle); + } + + /** + * @see HandleImpl#HandleImpl(UntypedHandleImpl) + */ + DataPipeConsumerHandleImpl(UntypedHandleImpl other) { + super(other); + } + + /** + * @see ConsumerHandle#discardData(int, ReadFlags) + */ + @Override + public int discardData(int numBytes, ReadFlags flags) { + return mCore.discardData(this, numBytes, flags); + } + + /** + * @see ConsumerHandle#readData(ByteBuffer, ReadFlags) + */ + @Override + public int readData(ByteBuffer elements, ReadFlags flags) { + return mCore.readData(this, elements, flags); + } + + /** + * @see ConsumerHandle#beginReadData(int, ReadFlags) + */ + @Override + public ByteBuffer beginReadData(int numBytes, ReadFlags flags) { + return mCore.beginReadData(this, numBytes, flags); + } + + /** + * @see ConsumerHandle#endReadData(int) + */ + @Override + public void endReadData(int numBytesRead) { + mCore.endReadData(this, numBytesRead); + } + +} diff --git a/mojo/android/system/src/org/chromium/mojo/system/DataPipeProducerHandleImpl.java b/mojo/android/system/src/org/chromium/mojo/system/DataPipeProducerHandleImpl.java new file mode 100644 index 0000000000..d6e00dfed5 --- /dev/null +++ b/mojo/android/system/src/org/chromium/mojo/system/DataPipeProducerHandleImpl.java @@ -0,0 +1,55 @@ +// 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. + +package org.chromium.mojo.system; + +import org.chromium.mojo.system.DataPipe.ProducerHandle; +import org.chromium.mojo.system.DataPipe.WriteFlags; + +import java.nio.ByteBuffer; + +/** + * Implementation of {@link ProducerHandle}. + */ +class DataPipeProducerHandleImpl extends HandleImpl implements ProducerHandle { + + /** + * @see HandleImpl#HandleImpl(CoreImpl, int) + */ + DataPipeProducerHandleImpl(CoreImpl core, int mojoHandle) { + super(core, mojoHandle); + } + + /** + * @see HandleImpl#HandleImpl(UntypedHandleImpl) + */ + DataPipeProducerHandleImpl(UntypedHandleImpl handle) { + super(handle); + } + + /** + * @see DataPipe.ProducerHandle#writeData(ByteBuffer, WriteFlags) + */ + @Override + public int writeData(ByteBuffer elements, WriteFlags flags) { + return mCore.writeData(this, elements, flags); + } + + /** + * @see DataPipe.ProducerHandle#beginWriteData(int, WriteFlags) + */ + @Override + public ByteBuffer beginWriteData(int numBytes, WriteFlags flags) { + return mCore.beginWriteData(this, numBytes, flags); + } + + /** + * @see DataPipe.ProducerHandle#endWriteData(int) + */ + @Override + public void endWriteData(int numBytesWritten) { + mCore.endWriteData(this, numBytesWritten); + } + +} diff --git a/mojo/android/system/src/org/chromium/mojo/system/HandleImpl.java b/mojo/android/system/src/org/chromium/mojo/system/HandleImpl.java new file mode 100644 index 0000000000..00cb9cd267 --- /dev/null +++ b/mojo/android/system/src/org/chromium/mojo/system/HandleImpl.java @@ -0,0 +1,112 @@ +// 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. + +package org.chromium.mojo.system; + +import android.util.Log; + +import org.chromium.mojo.system.Core.WaitFlags; + +/** + * Implementation of {@link Handle}. + */ +class HandleImpl implements Handle { + + private static final String TAG = "HandleImpl"; + + private static final int INVALID_HANDLE = 0; + + /** + * The pointer to the scoped handle owned by this object. + */ + private int mMojoHandle; + + /** + * the core implementation. Will be used to delegate all behavior. + */ + protected CoreImpl mCore; + + /** + * Base constructor. Takes ownership of the passed handle. + */ + HandleImpl(CoreImpl core, int mojoHandle) { + mCore = core; + mMojoHandle = mojoHandle; + } + + /** + * Constructor for transforming an {@link UntypedHandle} into a specific one. + */ + HandleImpl(UntypedHandleImpl other) { + mCore = other.mCore; + HandleImpl otherAsHandleImpl = other; + int mojoHandle = otherAsHandleImpl.mMojoHandle; + otherAsHandleImpl.mMojoHandle = INVALID_HANDLE; + mMojoHandle = mojoHandle; + } + + /** + * @see org.chromium.mojo.system.Handle#close() + */ + @Override + public void close() { + if (mMojoHandle != INVALID_HANDLE) { + // After a close, the handle is invalid whether the close succeed or not. + int handle = mMojoHandle; + mMojoHandle = INVALID_HANDLE; + mCore.close(handle); + } + } + + /** + * @see org.chromium.mojo.system.Handle#wait(WaitFlags, long) + */ + @Override + public int wait(WaitFlags flags, long deadline) { + return mCore.wait(this, flags, deadline); + } + + /** + * @see org.chromium.mojo.system.Handle#isValid() + */ + @Override + public boolean isValid() { + return mMojoHandle != INVALID_HANDLE; + } + + /** + * Getter for the native scoped handle. + * + * @return the native scoped handle. + */ + int getMojoHandle() { + return mMojoHandle; + } + + /** + * invalidate the handle. The caller must ensures that the handle does not leak. + */ + void invalidateHandle() { + mMojoHandle = INVALID_HANDLE; + } + + /** + * Close the handle if it is valid. Necessary because we cannot let handle leak, and we cannot + * ensure that every handle will be manually closed. + * + * @see java.lang.Object#finalize() + */ + @Override + protected final void finalize() throws Throwable { + if (isValid()) { + // This should not happen, as the user of this class should close the handle. Adding a + // warning. + Log.w(TAG, "Handle was not closed."); + // Ignore result at this point. + mCore.closeWithResult(mMojoHandle); + } + super.finalize(); + } + +} diff --git a/mojo/android/system/src/org/chromium/mojo/system/MessagePipeHandleImpl.java b/mojo/android/system/src/org/chromium/mojo/system/MessagePipeHandleImpl.java new file mode 100644 index 0000000000..6441b1cf42 --- /dev/null +++ b/mojo/android/system/src/org/chromium/mojo/system/MessagePipeHandleImpl.java @@ -0,0 +1,47 @@ +// 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. + +package org.chromium.mojo.system; + +import java.nio.ByteBuffer; +import java.util.List; + +/** + * Implementation of {@link MessagePipeHandle}. + */ +class MessagePipeHandleImpl extends HandleImpl implements MessagePipeHandle { + + /** + * @see HandleImpl#HandleImpl(CoreImpl, int) + */ + MessagePipeHandleImpl(CoreImpl core, int mojoHandle) { + super(core, mojoHandle); + } + + /** + * @see HandleImpl#HandleImpl(UntypedHandleImpl) + */ + MessagePipeHandleImpl(UntypedHandleImpl handle) { + super(handle); + } + + /** + * @see MessagePipeHandle#writeMessage(ByteBuffer, List, WriteFlags) + */ + @Override + public void writeMessage(ByteBuffer bytes, List<Handle> handles, WriteFlags flags) { + mCore.writeMessage(this, bytes, handles, flags); + } + + /** + * @see MessagePipeHandle#readMessage(ByteBuffer, int, ReadFlags) + */ + @Override + public ReadMessageResult readMessage(ByteBuffer bytes, + int maxNumberOfHandles, + ReadFlags flags) { + return mCore.readMessage(this, bytes, maxNumberOfHandles, flags); + } + +} diff --git a/mojo/android/system/src/org/chromium/mojo/system/SharedBufferHandleImpl.java b/mojo/android/system/src/org/chromium/mojo/system/SharedBufferHandleImpl.java new file mode 100644 index 0000000000..4679bd097f --- /dev/null +++ b/mojo/android/system/src/org/chromium/mojo/system/SharedBufferHandleImpl.java @@ -0,0 +1,52 @@ +// 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. + +package org.chromium.mojo.system; + +import java.nio.ByteBuffer; + +/** + * Implementation of {@link SharedBufferHandle}. + */ +class SharedBufferHandleImpl extends HandleImpl implements SharedBufferHandle { + + /** + * @see HandleImpl#HandleImpl(CoreImpl, int) + */ + SharedBufferHandleImpl(CoreImpl core, int mojoHandle) { + super(core, mojoHandle); + } + + /** + * @see HandleImpl#HandleImpl(UntypedHandleImpl) + */ + SharedBufferHandleImpl(UntypedHandleImpl handle) { + super(handle); + } + + /** + * @see SharedBufferHandle#duplicate(DuplicateOptions) + */ + @Override + public SharedBufferHandle duplicate(DuplicateOptions options) { + return mCore.duplicate(this, options); + } + + /** + * @see SharedBufferHandle#map(long, long, MapFlags) + */ + @Override + public ByteBuffer map(long offset, long numBytes, MapFlags flags) { + return mCore.map(this, offset, numBytes, flags); + } + + /** + * @see SharedBufferHandle#unmap(ByteBuffer) + */ + @Override + public void unmap(ByteBuffer buffer) { + mCore.unmap(buffer); + } + +} diff --git a/mojo/android/system/src/org/chromium/mojo/system/UntypedHandleImpl.java b/mojo/android/system/src/org/chromium/mojo/system/UntypedHandleImpl.java new file mode 100644 index 0000000000..85c769132f --- /dev/null +++ b/mojo/android/system/src/org/chromium/mojo/system/UntypedHandleImpl.java @@ -0,0 +1,54 @@ +// 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. + +package org.chromium.mojo.system; + +import org.chromium.mojo.system.DataPipe.ConsumerHandle; +import org.chromium.mojo.system.DataPipe.ProducerHandle; + +/** + * Implementation of {@link UntypedHandle}. + */ +class UntypedHandleImpl extends HandleImpl implements UntypedHandle { + + /** + * @see HandleImpl#HandleImpl(CoreImpl, int) + */ + UntypedHandleImpl(CoreImpl core, int mojoHandle) { + super(core, mojoHandle); + } + + /** + * @see org.chromium.mojo.system.UntypedHandle#toMessagePipeHandle() + */ + @Override + public MessagePipeHandle toMessagePipeHandle() { + return new MessagePipeHandleImpl(this); + } + + /** + * @see org.chromium.mojo.system.UntypedHandle#toDataPipeConsumerHandle() + */ + @Override + public ConsumerHandle toDataPipeConsumerHandle() { + return new DataPipeConsumerHandleImpl(this); + } + + /** + * @see org.chromium.mojo.system.UntypedHandle#toDataPipeProducerHandle() + */ + @Override + public ProducerHandle toDataPipeProducerHandle() { + return new DataPipeProducerHandleImpl(this); + } + + /** + * @see org.chromium.mojo.system.UntypedHandle#toSharedBufferHandle() + */ + @Override + public SharedBufferHandle toSharedBufferHandle() { + return new SharedBufferHandleImpl(this); + } + +} diff --git a/mojo/apps/js/bindings/connection_unittests.js b/mojo/apps/js/bindings/connection_unittests.js index 0ec37b01ff..91ea8e3494 100644 --- a/mojo/apps/js/bindings/connection_unittests.js +++ b/mojo/apps/js/bindings/connection_unittests.js @@ -3,7 +3,7 @@ // found in the LICENSE file. // Mock out the support module to avoid depending on the message loop. -define("mojo/bindings/js/support", ["timer"], function(timer) { +define("mojo/public/js/bindings/support", ["timer"], function(timer) { var waitingCallbacks = []; function WaitCookie(id) { @@ -55,8 +55,8 @@ define("mojo/bindings/js/support", ["timer"], function(timer) { define([ "gin/test/expect", - "mojo/bindings/js/support", - "mojo/bindings/js/core", + "mojo/public/js/bindings/support", + "mojo/public/js/bindings/core", "mojo/public/js/bindings/connection", "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom", "mojo/public/interfaces/bindings/tests/sample_service.mojom", diff --git a/mojo/apps/js/bindings/sample_service_unittests.js b/mojo/apps/js/bindings/sample_service_unittests.js index 1191c8863e..d7c01266b9 100644 --- a/mojo/apps/js/bindings/sample_service_unittests.js +++ b/mojo/apps/js/bindings/sample_service_unittests.js @@ -140,8 +140,10 @@ define([ } SimpleMessageReceiver.prototype.accept = function(message) { - if (dumpMessageAsHex) - console.log(hexdump.dumpArray(message.memory)); + if (dumpMessageAsHex) { + var uint8Array = new Uint8Array(message.buffer.arrayBuffer); + console.log(hexdump.dumpArray(uint8Array)); + } // Imagine some IPC happened here. var serviceImpl = new ServiceImpl(); serviceImpl.accept(message); diff --git a/mojo/apps/js/main.js b/mojo/apps/js/main.js index fb2d15bf2c..a3b3dd2d48 100644 --- a/mojo/apps/js/main.js +++ b/mojo/apps/js/main.js @@ -7,7 +7,7 @@ define([ 'monotonic_clock', 'timer', 'mojo/public/js/bindings/connection', - 'mojo/bindings/js/core', + 'mojo/public/js/bindings/core', 'mojo/apps/js/bindings/gl', 'mojo/apps/js/bindings/threading', 'mojo/services/native_viewport/native_viewport.mojom', diff --git a/mojo/apps/js/test/run_apps_js_tests.cc b/mojo/apps/js/test/run_apps_js_tests.cc index 3d27e47c9c..5037f8a352 100644 --- a/mojo/apps/js/test/run_apps_js_tests.cc +++ b/mojo/apps/js/test/run_apps_js_tests.cc @@ -13,6 +13,7 @@ #include "mojo/apps/js/bindings/monotonic_clock.h" #include "mojo/apps/js/bindings/threading.h" #include "mojo/bindings/js/core.h" +#include "mojo/bindings/js/unicode.h" #include "testing/gtest/include/gtest/gtest.h" namespace mojo { @@ -24,6 +25,7 @@ class TestRunnerDelegate : public gin::FileRunnerDelegate { TestRunnerDelegate() { AddBuiltinModule(gin::Console::kModuleName, gin::Console::GetModule); AddBuiltinModule(Core::kModuleName, Core::GetModule); + AddBuiltinModule(Unicode::kModuleName, Unicode::GetModule); AddBuiltinModule(gin::TimerModule::kName, gin::TimerModule::GetModule); AddBuiltinModule(apps::MonotonicClock::kModuleName, apps::MonotonicClock::GetModule); diff --git a/mojo/bindings/js/codec_unittests.js b/mojo/bindings/js/codec_unittests.js index e2823e0701..b20dbcb47a 100644 --- a/mojo/bindings/js/codec_unittests.js +++ b/mojo/bindings/js/codec_unittests.js @@ -10,6 +10,7 @@ define([ testBar(); testFoo(); testAlign(); + testUtf8(); this.result = "PASS"; function testBar() { @@ -41,7 +42,8 @@ define([ 5, 6, 7, 8, ]); - expect(message.memory).toEqual(expectedMemory); + var actualMemory = new Uint8Array(message.buffer.arrayBuffer); + expect(actualMemory).toEqual(expectedMemory); var reader = new codec.MessageReader(message); @@ -83,7 +85,7 @@ define([ foo.source = 23423782; var messageName = 31; - var payloadSize = 224; + var payloadSize = 240; var builder = new codec.MessageBuilder(messageName, payloadSize); builder.encodeStruct(sample.Foo, foo); @@ -93,13 +95,13 @@ define([ var expectedMemory = new Uint8Array([ /* 0: */ 16, 0, 0, 0, 2, 0, 0, 0, /* 8: */ 31, 0, 0, 0, 0, 0, 0, 0, - /* 16: */ 72, 0, 0, 0, 12, 0, 0, 0, + /* 16: */ 80, 0, 0, 0, 13, 0, 0, 0, /* 24: */ 0xD5, 0xB4, 0x12, 0x02, 0x93, 0x6E, 0x01, 0, /* 32: */ 5, 0, 0, 0, 0, 0, 0, 0, - /* 40: */ 48, 0, 0, 0, 0, 0, 0, 0, + /* 40: */ 56, 0, 0, 0, 0, 0, 0, 0, ]); // TODO(abarth): Test more of the message's raw memory. - var actualMemory = new Uint8Array(message.memory.buffer, + var actualMemory = new Uint8Array(message.buffer.arrayBuffer, 0, expectedMemory.length); expect(actualMemory).toEqual(expectedMemory); @@ -158,4 +160,31 @@ define([ for (var i = 0; i < aligned.length; ++i) expect(codec.align(i)).toBe(aligned[i]); } + + function testUtf8() { + var str = "B\u03ba\u1f79"; // some UCS-2 codepoints + var messageName = 42; + var payloadSize = 24; + + var builder = new codec.MessageBuilder(messageName, payloadSize); + var encoder = builder.createEncoder(8); + encoder.encodeStringPointer(str); + var message = builder.finish(); + var expectedMemory = new Uint8Array([ + /* 0: */ 16, 0, 0, 0, 2, 0, 0, 0, + /* 8: */ 42, 0, 0, 0, 0, 0, 0, 0, + /* 16: */ 8, 0, 0, 0, 0, 0, 0, 0, + /* 24: */ 14, 0, 0, 0, 6, 0, 0, 0, + /* 32: */ 0x42, 0xCE, 0xBA, 0xE1, 0xBD, 0xB9, 0, 0, + ]); + var actualMemory = new Uint8Array(message.buffer.arrayBuffer); + expect(actualMemory.length).toEqual(expectedMemory.length); + expect(actualMemory).toEqual(expectedMemory); + + var reader = new codec.MessageReader(message); + expect(reader.payloadSize).toBe(payloadSize); + expect(reader.messageName).toBe(messageName); + var str2 = reader.decoder.decodeStringPointer(); + expect(str2).toEqual(str); + } }); diff --git a/mojo/bindings/js/core.cc b/mojo/bindings/js/core.cc index de53cfc7e4..855637b920 100644 --- a/mojo/bindings/js/core.cc +++ b/mojo/bindings/js/core.cc @@ -199,7 +199,7 @@ gin::WrapperInfo g_wrapper_info = { gin::kEmbedderNativeGin }; } // namespace -const char Core::kModuleName[] = "mojo/bindings/js/core"; +const char Core::kModuleName[] = "mojo/public/js/bindings/core"; v8::Local<v8::Value> Core::GetModule(v8::Isolate* isolate) { gin::PerIsolateData* data = gin::PerIsolateData::From(isolate); diff --git a/mojo/bindings/js/core_unittests.js b/mojo/bindings/js/core_unittests.js index 62b20d1ac6..20446dbc26 100644 --- a/mojo/bindings/js/core_unittests.js +++ b/mojo/bindings/js/core_unittests.js @@ -4,7 +4,7 @@ define([ "gin/test/expect", - "mojo/bindings/js/core", + "mojo/public/js/bindings/core", "gc", ], function(expect, core, gc) { runWithMessagePipe(testNop); diff --git a/mojo/bindings/js/run_js_tests.cc b/mojo/bindings/js/run_js_tests.cc index d47070d1de..c3349ccf7c 100644 --- a/mojo/bindings/js/run_js_tests.cc +++ b/mojo/bindings/js/run_js_tests.cc @@ -10,6 +10,7 @@ #include "gin/test/file_runner.h" #include "gin/test/gtest.h" #include "mojo/bindings/js/core.h" +#include "mojo/bindings/js/unicode.h" #include "testing/gtest/include/gtest/gtest.h" namespace mojo { @@ -21,6 +22,7 @@ class TestRunnerDelegate : public gin::FileRunnerDelegate { TestRunnerDelegate() { AddBuiltinModule(gin::Console::kModuleName, gin::Console::GetModule); AddBuiltinModule(Core::kModuleName, Core::GetModule); + AddBuiltinModule(Unicode::kModuleName, Unicode::GetModule); } private: diff --git a/mojo/bindings/js/support.cc b/mojo/bindings/js/support.cc index ba62e8a306..cb8cb99665 100644 --- a/mojo/bindings/js/support.cc +++ b/mojo/bindings/js/support.cc @@ -55,7 +55,7 @@ gin::WrapperInfo g_wrapper_info = { gin::kEmbedderNativeGin }; } // namespace -const char Support::kModuleName[] = "mojo/bindings/js/support"; +const char Support::kModuleName[] = "mojo/public/js/bindings/support"; v8::Local<v8::Value> Support::GetModule(v8::Isolate* isolate) { gin::PerIsolateData* data = gin::PerIsolateData::From(isolate); diff --git a/mojo/bindings/js/unicode.cc b/mojo/bindings/js/unicode.cc new file mode 100644 index 0000000000..22f9e9830d --- /dev/null +++ b/mojo/bindings/js/unicode.cc @@ -0,0 +1,69 @@ +// 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/bindings/js/unicode.h" + +#include "gin/arguments.h" +#include "gin/array_buffer.h" +#include "gin/object_template_builder.h" +#include "gin/per_isolate_data.h" +#include "gin/public/wrapper_info.h" + +namespace mojo { +namespace js { + +namespace { + +v8::Handle<v8::Value> DecodeUtf8String(const gin::Arguments& args, + const gin::ArrayBufferView& buffer) { + assert(static_cast<int>(buffer.num_bytes()) >= 0); + return v8::String::NewFromUtf8(args.isolate(), + reinterpret_cast<char*>(buffer.bytes()), + v8::String::kNormalString, + static_cast<int>(buffer.num_bytes())); +} + +int EncodeUtf8String(const gin::Arguments& args, + v8::Handle<v8::Value> str_value, + const gin::ArrayBufferView& buffer) { + assert(static_cast<int>(buffer.num_bytes()) >= 0); + v8::Handle<v8::String> str = str_value->ToString(); + int num_bytes = str->WriteUtf8( + reinterpret_cast<char*>(buffer.bytes()), + static_cast<int>(buffer.num_bytes()), + NULL, + v8::String::NO_NULL_TERMINATION | v8::String::REPLACE_INVALID_UTF8); + return num_bytes; +} + +int Utf8Length(v8::Handle<v8::Value> str_value) { + return str_value->ToString()->Utf8Length(); +} + +gin::WrapperInfo g_wrapper_info = { gin::kEmbedderNativeGin }; + +} // namespace + +const char Unicode::kModuleName[] = "mojo/public/js/bindings/unicode"; + +v8::Local<v8::Value> Unicode::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("decodeUtf8String", DecodeUtf8String) + .SetMethod("encodeUtf8String", EncodeUtf8String) + .SetMethod("utf8Length", Utf8Length) + .Build(); + + data->SetObjectTemplate(&g_wrapper_info, templ); + } + + return templ->NewInstance(); +} + +} // namespace js +} // namespace mojo diff --git a/mojo/bindings/js/unicode.h b/mojo/bindings/js/unicode.h new file mode 100644 index 0000000000..de1e3bb205 --- /dev/null +++ b/mojo/bindings/js/unicode.h @@ -0,0 +1,22 @@ +// 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_BINDINGS_JS_UNICODE_H_ +#define MOJO_BINDINGS_JS_UNICODE_H_ + +#include "v8/include/v8.h" + +namespace mojo { +namespace js { + +class Unicode { + public: + static const char kModuleName[]; + static v8::Local<v8::Value> GetModule(v8::Isolate* isolate); +}; + +} // namespace js +} // namespace mojo + +#endif // MOJO_BINDINGS_JS_UNICODE_H_ diff --git a/mojo/bindings/js/waiting_callback.h b/mojo/bindings/js/waiting_callback.h index bc17d19391..90cf284254 100644 --- a/mojo/bindings/js/waiting_callback.h +++ b/mojo/bindings/js/waiting_callback.h @@ -8,7 +8,7 @@ #include "gin/handle.h" #include "gin/runner.h" #include "gin/wrappable.h" -#include "mojo/public/c/system/async_waiter.h" +#include "mojo/public/c/environment/async_waiter.h" namespace mojo { namespace js { diff --git a/mojo/common/DEPS b/mojo/common/DEPS index a1d21b53ea..26456c6ff0 100644 --- a/mojo/common/DEPS +++ b/mojo/common/DEPS @@ -1,5 +1,6 @@ include_rules = [ "-mojo", "+mojo/common", + "+mojo/embedder", "+mojo/public", ] diff --git a/mojo/common/message_pump_mojo.cc b/mojo/common/message_pump_mojo.cc index 2afa72f1dc..5bc3462b0c 100644 --- a/mojo/common/message_pump_mojo.cc +++ b/mojo/common/message_pump_mojo.cc @@ -68,69 +68,84 @@ void MessagePumpMojo::RemoveHandler(const Handle& handle) { } void MessagePumpMojo::Run(Delegate* delegate) { - RunState* old_state = run_state_; RunState run_state; // TODO: better deal with error handling. CHECK(run_state.read_handle.is_valid()); CHECK(run_state.write_handle.is_valid()); - run_state_ = &run_state; + RunState* old_state = NULL; + { + base::AutoLock auto_lock(run_state_lock_); + old_state = run_state_; + run_state_ = &run_state; + } + DoRunLoop(&run_state, delegate); + { + base::AutoLock auto_lock(run_state_lock_); + run_state_ = old_state; + } +} + +void MessagePumpMojo::Quit() { + base::AutoLock auto_lock(run_state_lock_); + if (run_state_) + run_state_->should_quit = true; +} + +void MessagePumpMojo::ScheduleWork() { + base::AutoLock auto_lock(run_state_lock_); + if (run_state_) + SignalControlPipe(*run_state_); +} + +void MessagePumpMojo::ScheduleDelayedWork( + const base::TimeTicks& delayed_work_time) { + base::AutoLock auto_lock(run_state_lock_); + if (!run_state_) + return; + run_state_->delayed_work_time = delayed_work_time; + SignalControlPipe(*run_state_); +} + +void MessagePumpMojo::DoRunLoop(RunState* run_state, Delegate* delegate) { bool more_work_is_plausible = true; for (;;) { const bool block = !more_work_is_plausible; - DoInternalWork(block); + DoInternalWork(*run_state, block); // There isn't a good way to know if there are more handles ready, we assume // not. more_work_is_plausible = false; - if (run_state.should_quit) + if (run_state->should_quit) break; more_work_is_plausible |= delegate->DoWork(); - if (run_state.should_quit) + if (run_state->should_quit) break; more_work_is_plausible |= delegate->DoDelayedWork( - &run_state.delayed_work_time); - if (run_state.should_quit) + &run_state->delayed_work_time); + if (run_state->should_quit) break; if (more_work_is_plausible) continue; more_work_is_plausible = delegate->DoIdleWork(); - if (run_state.should_quit) + if (run_state->should_quit) break; } - run_state_ = old_state; -} - -void MessagePumpMojo::Quit() { - if (run_state_) - run_state_->should_quit = true; } -void MessagePumpMojo::ScheduleWork() { - SignalControlPipe(); -} - -void MessagePumpMojo::ScheduleDelayedWork( - const base::TimeTicks& delayed_work_time) { - if (!run_state_) - return; - run_state_->delayed_work_time = delayed_work_time; - SignalControlPipe(); -} - -void MessagePumpMojo::DoInternalWork(bool block) { - const MojoDeadline deadline = block ? GetDeadlineForWait() : 0; - const WaitState wait_state = GetWaitState(); +void MessagePumpMojo::DoInternalWork(const RunState& run_state, bool block) { + const MojoDeadline deadline = block ? GetDeadlineForWait(run_state) : 0; + const WaitState wait_state = GetWaitState(run_state); const MojoResult result = WaitMany(wait_state.handles, wait_state.wait_flags, deadline); if (result == 0) { // Control pipe was written to. uint32_t num_bytes = 0; - ReadMessageRaw(run_state_->read_handle.get(), NULL, &num_bytes, NULL, NULL, + ReadMessageRaw(run_state.read_handle.get(), NULL, &num_bytes, NULL, NULL, MOJO_READ_MESSAGE_FLAG_MAY_DISCARD); } else if (result > 0) { const size_t index = static_cast<size_t>(result); @@ -187,18 +202,16 @@ void MessagePumpMojo::RemoveFirstInvalidHandle(const WaitState& wait_state) { } } -void MessagePumpMojo::SignalControlPipe() { - if (!run_state_) - return; - +void MessagePumpMojo::SignalControlPipe(const RunState& run_state) { // TODO(sky): deal with error? - WriteMessageRaw(run_state_->write_handle.get(), NULL, 0, NULL, 0, + WriteMessageRaw(run_state.write_handle.get(), NULL, 0, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE); } -MessagePumpMojo::WaitState MessagePumpMojo::GetWaitState() const { +MessagePumpMojo::WaitState MessagePumpMojo::GetWaitState( + const RunState& run_state) const { WaitState wait_state; - wait_state.handles.push_back(run_state_->read_handle.get()); + wait_state.handles.push_back(run_state.read_handle.get()); wait_state.wait_flags.push_back(MOJO_WAIT_FLAG_READABLE); for (HandleToHandler::const_iterator i = handlers_.begin(); @@ -209,8 +222,9 @@ MessagePumpMojo::WaitState MessagePumpMojo::GetWaitState() const { return wait_state; } -MojoDeadline MessagePumpMojo::GetDeadlineForWait() const { - base::TimeTicks min_time = run_state_->delayed_work_time; +MojoDeadline MessagePumpMojo::GetDeadlineForWait( + const RunState& run_state) const { + base::TimeTicks min_time = run_state.delayed_work_time; for (HandleToHandler::const_iterator i = handlers_.begin(); i != handlers_.end(); ++i) { if (min_time.is_null() && i->second.deadline < min_time) diff --git a/mojo/common/message_pump_mojo.h b/mojo/common/message_pump_mojo.h index cc21565b65..c76110678c 100644 --- a/mojo/common/message_pump_mojo.h +++ b/mojo/common/message_pump_mojo.h @@ -9,6 +9,7 @@ #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_pump.h" +#include "base/synchronization/lock.h" #include "base/time/time.h" #include "mojo/common/mojo_common_export.h" #include "mojo/public/cpp/system/core.h" @@ -61,25 +62,33 @@ class MOJO_COMMON_EXPORT MessagePumpMojo : public base::MessagePump { typedef std::map<Handle, Handler> HandleToHandler; + // Implementation of Run(). + void DoRunLoop(RunState* run_state, Delegate* delegate); + // Services the set of handles ready. If |block| is true this waits for a // handle to become ready, otherwise this does not block. - void DoInternalWork(bool block); + void DoInternalWork(const RunState& run_state, bool block); // Removes the first invalid handle. This is called if MojoWaitMany finds an // invalid handle. void RemoveFirstInvalidHandle(const WaitState& wait_state); - void SignalControlPipe(); + void SignalControlPipe(const RunState& run_state); - WaitState GetWaitState() const; + WaitState GetWaitState(const RunState& run_state) const; // Returns the deadline for the call to MojoWaitMany(). - MojoDeadline GetDeadlineForWait() const; + MojoDeadline GetDeadlineForWait(const RunState& run_state) const; // If non-NULL we're running (inside Run()). Member is reference to value on // stack. RunState* run_state_; + // Lock for accessing |run_state_|. In general the only method that we have to + // worry about is ScheduleWork(). All other methods are invoked on the same + // thread. + base::Lock run_state_lock_; + HandleToHandler handlers_; // An ever increasing value assigned to each Handler::id. Used to detect diff --git a/mojo/common/mojo_channel_init.cc b/mojo/common/mojo_channel_init.cc new file mode 100644 index 0000000000..96190f9d5d --- /dev/null +++ b/mojo/common/mojo_channel_init.cc @@ -0,0 +1,59 @@ +// 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/common/mojo_channel_init.h" + +#include "base/bind.h" +#include "base/message_loop/message_loop.h" +#include "mojo/embedder/embedder.h" + +namespace mojo { +namespace common { + +MojoChannelInit::MojoChannelInit() + : channel_info_(NULL), + weak_factory_(this) { +} + +MojoChannelInit::~MojoChannelInit() { + bootstrap_message_pipe_.reset(); + if (channel_info_) { + io_thread_task_runner_->PostTask( + FROM_HERE, + base::Bind(&mojo::embedder::DestroyChannelOnIOThread, channel_info_)); + } +} + +void MojoChannelInit::Init( + base::PlatformFile file, + scoped_refptr<base::TaskRunner> io_thread_task_runner) { + DCHECK(!io_thread_task_runner_.get()); // Should only init once. + io_thread_task_runner_ = io_thread_task_runner; + bootstrap_message_pipe_ = mojo::embedder::CreateChannel( + mojo::embedder::ScopedPlatformHandle( + mojo::embedder::PlatformHandle(file)), + io_thread_task_runner, + base::Bind(&MojoChannelInit::OnCreatedChannel, weak_factory_.GetWeakPtr(), + io_thread_task_runner), + base::MessageLoop::current()->message_loop_proxy()).Pass(); +} + +// static +void MojoChannelInit::OnCreatedChannel( + base::WeakPtr<MojoChannelInit> host, + scoped_refptr<base::TaskRunner> io_thread, + embedder::ChannelInfo* channel) { + // By the time we get here |host| may have been destroyed. If so, shutdown the + // channel. + if (!host.get()) { + io_thread->PostTask( + FROM_HERE, + base::Bind(&mojo::embedder::DestroyChannelOnIOThread, channel)); + return; + } + host->channel_info_ = channel; +} + +} // namespace common +} // namespace mojo diff --git a/mojo/common/mojo_channel_init.h b/mojo/common/mojo_channel_init.h new file mode 100644 index 0000000000..8fa00941c2 --- /dev/null +++ b/mojo/common/mojo_channel_init.h @@ -0,0 +1,66 @@ +// 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_COMMON_MOJO_CHANNEL_INIT_H_ +#define MOJO_COMMON_MOJO_CHANNEL_INIT_H_ + +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "base/platform_file.h" +#include "mojo/common/mojo_common_export.h" +#include "mojo/public/cpp/system/core.h" + +namespace base { +class MessageLoopProxy; +class TaskRunner; +} + +namespace mojo { +namespace embedder { +struct ChannelInfo; +} + +namespace common { + +// MojoChannelInit handle creation (and destruction) of the mojo channel. It is +// expected that this class is created and destroyed on the main thread. +class MOJO_COMMON_EXPORT MojoChannelInit { + public: + MojoChannelInit(); + ~MojoChannelInit(); + + // Inits the channel. This takes ownership of |file|. + void Init(base::PlatformFile file, + scoped_refptr<base::TaskRunner> io_thread_task_runner); + + bool is_handle_valid() const { return bootstrap_message_pipe_.is_valid(); } + + mojo::ScopedMessagePipeHandle bootstrap_message_pipe() { + return bootstrap_message_pipe_.Pass(); + } + + private: + // Invoked on the main thread once the channel has been established. + static void OnCreatedChannel( + base::WeakPtr<MojoChannelInit> host, + scoped_refptr<base::TaskRunner> io_thread, + embedder::ChannelInfo* channel); + + scoped_refptr<base::TaskRunner> io_thread_task_runner_; + + // If non-null the channel has been established. + embedder::ChannelInfo* channel_info_; + + // The handle from channel creation. + mojo::ScopedMessagePipeHandle bootstrap_message_pipe_; + + base::WeakPtrFactory<MojoChannelInit> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(MojoChannelInit); +}; + +} // namespace common +} // namespace mojo + +#endif // MOJO_COMMON_MOJO_CHANNEL_INIT_H_ diff --git a/mojo/embedder/embedder.cc b/mojo/embedder/embedder.cc index 7698160336..e8c6e8e53b 100644 --- a/mojo/embedder/embedder.cc +++ b/mojo/embedder/embedder.cc @@ -44,6 +44,8 @@ static void CreateChannelOnIOThread( // Attach the message pipe endpoint. system::MessageInTransit::EndpointId endpoint_id = channel_info->channel->AttachMessagePipeEndpoint(message_pipe, 1); + // We shouldn't get |kInvalidEndpointId| here -- since |CreateChannel()| is + // responsible for the local endpoint, and won't close it. DCHECK_EQ(endpoint_id, system::Channel::kBootstrapEndpointId); success = channel_info->channel->RunMessagePipeEndpoint( system::Channel::kBootstrapEndpointId, diff --git a/mojo/environment/default_async_waiter_impl.h b/mojo/environment/default_async_waiter_impl.h index 266a70f687..8e697cb425 100644 --- a/mojo/environment/default_async_waiter_impl.h +++ b/mojo/environment/default_async_waiter_impl.h @@ -6,7 +6,7 @@ #define MOJO_ENVIRONMENT_DEFAULT_ASYNC_WAITER_IMPL_H_ #include "mojo/environment/mojo_environment_impl_export.h" -#include "mojo/public/c/system/async_waiter.h" +#include "mojo/public/c/environment/async_waiter.h" namespace mojo { namespace internal { diff --git a/mojo/examples/sample_view_manager_app/sample_view_manager_app.cc b/mojo/examples/sample_view_manager_app/sample_view_manager_app.cc new file mode 100644 index 0000000000..c6d6e7c779 --- /dev/null +++ b/mojo/examples/sample_view_manager_app/sample_view_manager_app.cc @@ -0,0 +1,74 @@ +// 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 "mojo/public/cpp/bindings/allocation_scope.h" +#include "mojo/public/cpp/bindings/remote_ptr.h" +#include "mojo/public/cpp/environment/environment.h" +#include "mojo/public/cpp/shell/application.h" +#include "mojo/public/cpp/system/core.h" +#include "mojo/public/cpp/system/macros.h" +#include "mojo/public/cpp/utility/run_loop.h" +#include "mojo/public/interfaces/shell/shell.mojom.h" +#include "mojo/services/public/interfaces/view_manager/view_manager.mojom.h" + +#if defined(WIN32) +#if !defined(CDECL) +#define CDECL __cdecl +#endif +#define SAMPLE_APP_EXPORT __declspec(dllexport) +#else +#define CDECL +#define SAMPLE_APP_EXPORT __attribute__((visibility("default"))) +#endif + +namespace mojo { +namespace examples { + +class SampleApp : public Application, + public services::view_manager::ViewManagerClient { + public: + explicit SampleApp(MojoHandle shell_handle) : Application(shell_handle) { + InterfacePipe<services::view_manager::ViewManager, AnyInterface> + view_manager_pipe; + AllocationScope scope; + shell()->Connect("mojo:mojo_view_manager", + view_manager_pipe.handle_to_peer.Pass()); + view_manager_.reset(view_manager_pipe.handle_to_self.Pass(), this); + view_manager_->CreateNode(1, base::Bind(&SampleApp::OnCreatedView, + base::Unretained(this))); + } + + virtual ~SampleApp() { + } + + // ViewManagerClient:: + virtual void OnConnectionEstablished(uint16_t connection_id) OVERRIDE { + } + virtual void OnNodeHierarchyChanged(uint32_t node, + uint32_t new_parent, + uint32_t old_parent, + int32_t change_id) OVERRIDE { + } + + private: + void OnCreatedView(bool success) { + DCHECK(success); + } + + RemotePtr<services::view_manager::ViewManager> view_manager_; +}; + +} // namespace examples +} // namespace mojo + +extern "C" SAMPLE_APP_EXPORT MojoResult CDECL MojoMain( + MojoHandle shell_handle) { + mojo::Environment env; + mojo::RunLoop loop; + + mojo::examples::SampleApp app(shell_handle); + loop.Run(); + return MOJO_RESULT_OK; +} diff --git a/mojo/examples/view_manager/view_manager.cc b/mojo/examples/view_manager/view_manager.cc deleted file mode 100644 index e10363b5af..0000000000 --- a/mojo/examples/view_manager/view_manager.cc +++ /dev/null @@ -1,150 +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 <stdio.h> - -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/scoped_vector.h" -#include "base/message_loop/message_loop.h" -#include "mojo/examples/launcher/launcher.mojom.h" -#include "mojo/examples/view_manager/view_manager.mojom.h" -#include "mojo/public/cpp/bindings/allocation_scope.h" -#include "mojo/public/cpp/bindings/remote_ptr.h" -#include "mojo/public/cpp/shell/application.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/public/interfaces/shell/shell.mojom.h" -#include "mojo/services/native_viewport/geometry_conversions.h" -#include "mojo/services/native_viewport/native_viewport.mojom.h" -#include "ui/events/event_constants.h" -#include "ui/events/keycodes/keyboard_codes.h" -#include "ui/gfx/rect.h" - -#if defined(WIN32) -#if !defined(CDECL) -#define CDECL __cdecl) -#endif -#define VIEW_MANAGER_EXPORT __declspec(dllexport) -#else -#define CDECL -#define VIEW_MANAGER_EXPORT __attribute__((visibility("default"))) -#endif - -namespace mojo { -namespace examples { - -class ViewImpl : public View { - public: - explicit ViewImpl(ScopedViewClientHandle handle) - : id_(-1), - client_(handle.Pass(), this) {} - virtual ~ViewImpl() {} - - private: - // Overridden from View: - virtual void SetId(int view_id) OVERRIDE { - id_ = view_id; - } - virtual void GetId(const mojo::Callback<void(int32_t)>& callback) OVERRIDE { - callback.Run(id_); - } - - int id_; - RemotePtr<ViewClient> client_; - - DISALLOW_COPY_AND_ASSIGN(ViewImpl); -}; - -class ViewManagerImpl : public Service<ViewManager, ViewManagerImpl>, - public NativeViewportClient, - public LauncherClient { - public: - explicit ViewManagerImpl() { - InitNativeViewport(); - } - - private: - // Overridden from ViewManager: - virtual void CreateView(const Callback<void(ScopedViewHandle)>& callback) - OVERRIDE { - InterfacePipe<View> pipe; - views_.push_back(new ViewImpl(pipe.handle_to_peer.Pass())); - callback.Run(pipe.handle_to_self.Pass()); - } - - // Overridden from NativeViewportClient: - virtual void OnCreated() OVERRIDE { - } - virtual void OnDestroyed() OVERRIDE { - base::MessageLoop::current()->Quit(); - } - virtual void OnBoundsChanged(const Rect& bounds) OVERRIDE { - // TODO(beng): - } - virtual void OnEvent(const Event& event, - const mojo::Callback<void()>& callback) OVERRIDE { - if (event.action() == ui::ET_KEY_RELEASED) { - if (event.key_data().key_code() == ui::VKEY_L && - (event.flags() & ui::EF_CONTROL_DOWN)) { - InitLauncher(); - launcher_->Show(); - } - } - callback.Run(); - } - - // Overridden from LauncherClient: - virtual void OnURLEntered(const mojo::String& url) OVERRIDE { - std::string url_spec = url.To<std::string>(); - printf("Received URL from launcher app: %s\n", url_spec.c_str()); - launcher_->Hide(); - } - - void InitNativeViewport() { - InterfacePipe<NativeViewport, AnyInterface> pipe; - - AllocationScope scope; - shell()->Connect("mojo:mojo_native_viewport_service", - pipe.handle_to_peer.Pass()); - - native_viewport_.reset(pipe.handle_to_self.Pass(), this); - native_viewport_->Create(gfx::Rect(50, 50, 800, 600)); - native_viewport_->Show(); - } - - void InitLauncher() { - if (!launcher_.is_null()) - return; - - InterfacePipe<Launcher, AnyInterface> pipe; - - AllocationScope scope; - shell()->Connect("mojo:mojo_launcher", pipe.handle_to_peer.Pass()); - - launcher_.reset(pipe.handle_to_self.Pass(), this); - } - - void DidCreateContext() { - } - - ScopedVector<ViewImpl> views_; - RemotePtr<NativeViewport> native_viewport_; - RemotePtr<Launcher> launcher_; - - DISALLOW_COPY_AND_ASSIGN(ViewManagerImpl); -}; - -} // namespace examples -} // namespace mojo - -extern "C" VIEW_MANAGER_EXPORT MojoResult CDECL MojoMain( - MojoHandle shell_handle) { - base::MessageLoop loop; - mojo::Application app(shell_handle); - app.AddServiceFactory( - new mojo::ServiceFactory<mojo::examples::ViewManagerImpl>); - loop.Run(); - - return MOJO_RESULT_OK; -} diff --git a/mojo/examples/view_manager/view_manager.mojom b/mojo/examples/view_manager/view_manager.mojom deleted file mode 100644 index 56beea48e0..0000000000 --- a/mojo/examples/view_manager/view_manager.mojom +++ /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. - -module mojo { - -[Peer=ViewClient] -interface View { - SetId(int32 id); - GetId() => (int32 id); -}; - -[Peer=View] -interface ViewClient { -}; - -[Peer=ViewManagerClient] -interface ViewManager { - CreateView() => (View view); -}; - -[Peer=ViewManager] -interface ViewManagerClient { -}; - -} diff --git a/mojo/mojo.gyp b/mojo/mojo.gyp index 86c1f9454a..4db1476458 100644 --- a/mojo/mojo.gyp +++ b/mojo/mojo.gyp @@ -59,7 +59,17 @@ 'dependencies': [ 'mojo_aura_demo', 'mojo_launcher', + 'mojo_sample_view_manager_app', 'mojo_view_manager', + 'mojo_view_manager_unittests', + ], + }], + ['OS == "android"', { + 'dependencies': [ + 'mojo_public_java', + 'mojo_system_java', + 'libmojo_system_java', + 'mojo_test_apk', ], }], ] @@ -279,6 +289,8 @@ 'common/message_pump_mojo.cc', 'common/message_pump_mojo.h', 'common/message_pump_mojo_handler.h', + 'common/mojo_channel_init.cc', + 'common/mojo_channel_init.h', 'common/time_helper.cc', 'common/time_helper.h', ], @@ -523,6 +535,8 @@ 'bindings/js/handle.h', 'bindings/js/support.cc', 'bindings/js/support.h', + 'bindings/js/unicode.cc', + 'bindings/js/unicode.h', 'bindings/js/waiting_callback.cc', 'bindings/js/waiting_callback.h', ], @@ -534,7 +548,7 @@ '../gin/gin.gyp:gin_test', 'mojo_js_bindings_lib', 'mojo_run_all_unittests', - 'mojo_sample_service', + 'mojo_public_test_interfaces', ], 'sources': [ 'bindings/js/run_js_tests.cc', @@ -560,41 +574,102 @@ ['OS=="android"', { 'targets': [ { - 'target_name': 'mojo_native_viewport_java', + 'target_name': 'mojo_jni_headers', + 'type': 'none', + 'dependencies': [ + 'mojo_java_set_jni_headers', + ], + 'sources': [ + 'android/javatests/src/org/chromium/mojo/system/CoreTest.java', + 'android/system/src/org/chromium/mojo/system/CoreImpl.java', + 'services/native_viewport/android/src/org/chromium/mojo/NativeViewportAndroid.java', + 'shell/android/apk/src/org/chromium/mojo_shell_apk/MojoMain.java', + ], + 'variables': { + 'jni_gen_package': 'mojo', + 'jni_generator_ptr_type': 'long', + }, + 'includes': [ '../build/jni_generator.gypi' ], + }, + { + 'target_name': 'mojo_system_java', 'type': 'none', 'dependencies': [ '../base/base.gyp:base_java', + 'mojo_public_java', ], 'variables': { - 'java_in_dir': '<(DEPTH)/mojo/services/native_viewport/android', + 'java_in_dir': '<(DEPTH)/mojo/android/system', }, 'includes': [ '../build/java.gypi' ], }, { - 'target_name': 'mojo_java_set_jni_headers', + 'target_name': 'libmojo_system_java', + 'type': 'static_library', + 'dependencies': [ + '../base/base.gyp:base', + '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', + 'mojo_common_lib', + 'mojo_environment_chromium', + 'mojo_jni_headers', + 'mojo_shell_bindings', + 'mojo_shell_lib', + ], + 'sources': [ + 'android/system/core_impl.cc', + 'android/system/core_impl.h', + ], + }, + { + 'target_name': 'libmojo_java_unittest', + 'type': 'shared_library', + 'dependencies': [ + '../base/base.gyp:base', + 'libmojo_system_java', + 'mojo_jni_headers', + ], + 'sources': [ + 'android/javatests/core_test.cc', + 'android/javatests/core_test.h', + 'android/javatests/init_library.cc', + ], + }, + { + 'target_name': 'mojo_test_apk', 'type': 'none', + 'dependencies': [ + 'mojo_system_java', + '../base/base.gyp:base_java_test_support', + ], 'variables': { - 'jni_gen_package': 'mojo', - 'jni_generator_ptr_type': 'long', - 'input_java_class': 'java/util/HashSet.class', + 'apk_name': 'MojoTest', + 'java_in_dir': '<(DEPTH)/mojo/android/javatests', + 'resource_dir': '<(DEPTH)/mojo/android/javatests/apk', + 'native_lib_target': 'libmojo_java_unittest', + 'is_test_apk': 1, }, - 'includes': [ '../build/jar_file_jni_generator.gypi' ], + 'includes': [ '../build/java_apk.gypi' ], }, { - 'target_name': 'mojo_jni_headers', + 'target_name': 'mojo_native_viewport_java', 'type': 'none', 'dependencies': [ - 'mojo_java_set_jni_headers', - ], - 'sources': [ - 'services/native_viewport/android/src/org/chromium/mojo/NativeViewportAndroid.java', - 'shell/android/apk/src/org/chromium/mojo_shell_apk/MojoMain.java', + '../base/base.gyp:base_java', ], 'variables': { + 'java_in_dir': '<(DEPTH)/mojo/services/native_viewport/android', + }, + 'includes': [ '../build/java.gypi' ], + }, + { + 'target_name': 'mojo_java_set_jni_headers', + 'type': 'none', + 'variables': { 'jni_gen_package': 'mojo', 'jni_generator_ptr_type': 'long', - }, - 'includes': [ '../build/jni_generator.gypi' ], + 'input_java_class': 'java/util/HashSet.class', + }, + 'includes': [ '../build/jar_file_jni_generator.gypi' ], }, { 'target_name': 'libmojo_shell', diff --git a/mojo/mojo_apps.gypi b/mojo/mojo_apps.gypi index 62d904d231..66afb47d23 100644 --- a/mojo/mojo_apps.gypi +++ b/mojo/mojo_apps.gypi @@ -43,7 +43,7 @@ '../gin/gin.gyp:gin_test', 'mojo_js_lib', 'mojo_run_all_unittests', - 'mojo_sample_service', + 'mojo_public_test_interfaces', ], 'sources': [ 'apps/js/test/run_apps_js_tests.cc', diff --git a/mojo/mojo_bindings.target.darwin-arm.mk b/mojo/mojo_bindings.target.darwin-arm.mk index 9f6e80f3d2..04f97b853f 100644 --- a/mojo/mojo_bindings.target.darwin-arm.mk +++ b/mojo/mojo_bindings.target.darwin-arm.mk @@ -230,7 +230,6 @@ LOCAL_LDFLAGS_Debug := \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ -Wl,--icf=safe \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_bindings.target.darwin-mips.mk b/mojo/mojo_bindings.target.darwin-mips.mk index 21ef642573..d455f4fa9a 100644 --- a/mojo/mojo_bindings.target.darwin-mips.mk +++ b/mojo/mojo_bindings.target.darwin-mips.mk @@ -226,7 +226,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_bindings.target.darwin-x86.mk b/mojo/mojo_bindings.target.darwin-x86.mk index efd4c43b10..0e0af9f4ee 100644 --- a/mojo/mojo_bindings.target.darwin-x86.mk +++ b/mojo/mojo_bindings.target.darwin-x86.mk @@ -228,7 +228,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_bindings.target.darwin-x86_64.mk b/mojo/mojo_bindings.target.darwin-x86_64.mk index 3cfb6e3e97..6fbbc7b193 100644 --- a/mojo/mojo_bindings.target.darwin-x86_64.mk +++ b/mojo/mojo_bindings.target.darwin-x86_64.mk @@ -228,7 +228,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_bindings.target.linux-arm.mk b/mojo/mojo_bindings.target.linux-arm.mk index 9f6e80f3d2..04f97b853f 100644 --- a/mojo/mojo_bindings.target.linux-arm.mk +++ b/mojo/mojo_bindings.target.linux-arm.mk @@ -230,7 +230,6 @@ LOCAL_LDFLAGS_Debug := \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ -Wl,--icf=safe \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_bindings.target.linux-mips.mk b/mojo/mojo_bindings.target.linux-mips.mk index 21ef642573..d455f4fa9a 100644 --- a/mojo/mojo_bindings.target.linux-mips.mk +++ b/mojo/mojo_bindings.target.linux-mips.mk @@ -226,7 +226,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_bindings.target.linux-x86.mk b/mojo/mojo_bindings.target.linux-x86.mk index efd4c43b10..0e0af9f4ee 100644 --- a/mojo/mojo_bindings.target.linux-x86.mk +++ b/mojo/mojo_bindings.target.linux-x86.mk @@ -228,7 +228,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_bindings.target.linux-x86_64.mk b/mojo/mojo_bindings.target.linux-x86_64.mk index 3cfb6e3e97..6fbbc7b193 100644 --- a/mojo/mojo_bindings.target.linux-x86_64.mk +++ b/mojo/mojo_bindings.target.linux-x86_64.mk @@ -228,7 +228,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_common_lib.target.darwin-arm.mk b/mojo/mojo_common_lib.target.darwin-arm.mk index 68b35f7b6d..ebf534cfe7 100644 --- a/mojo/mojo_common_lib.target.darwin-arm.mk +++ b/mojo/mojo_common_lib.target.darwin-arm.mk @@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \ mojo/common/environment_data.cc \ mojo/common/handle_watcher.cc \ mojo/common/message_pump_mojo.cc \ + mojo/common/mojo_channel_init.cc \ mojo/common/time_helper.cc @@ -227,7 +228,6 @@ LOCAL_LDFLAGS_Debug := \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ -Wl,--icf=safe \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_common_lib.target.darwin-mips.mk b/mojo/mojo_common_lib.target.darwin-mips.mk index b1a8bd7045..f059697b50 100644 --- a/mojo/mojo_common_lib.target.darwin-mips.mk +++ b/mojo/mojo_common_lib.target.darwin-mips.mk @@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \ mojo/common/environment_data.cc \ mojo/common/handle_watcher.cc \ mojo/common/message_pump_mojo.cc \ + mojo/common/mojo_channel_init.cc \ mojo/common/time_helper.cc @@ -223,7 +224,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_common_lib.target.darwin-x86.mk b/mojo/mojo_common_lib.target.darwin-x86.mk index 0909f0ba0d..14e7ed77a5 100644 --- a/mojo/mojo_common_lib.target.darwin-x86.mk +++ b/mojo/mojo_common_lib.target.darwin-x86.mk @@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \ mojo/common/environment_data.cc \ mojo/common/handle_watcher.cc \ mojo/common/message_pump_mojo.cc \ + mojo/common/mojo_channel_init.cc \ mojo/common/time_helper.cc @@ -225,7 +226,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_common_lib.target.darwin-x86_64.mk b/mojo/mojo_common_lib.target.darwin-x86_64.mk index 370d66234b..c777ccc711 100644 --- a/mojo/mojo_common_lib.target.darwin-x86_64.mk +++ b/mojo/mojo_common_lib.target.darwin-x86_64.mk @@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \ mojo/common/environment_data.cc \ mojo/common/handle_watcher.cc \ mojo/common/message_pump_mojo.cc \ + mojo/common/mojo_channel_init.cc \ mojo/common/time_helper.cc @@ -225,7 +226,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_common_lib.target.linux-arm.mk b/mojo/mojo_common_lib.target.linux-arm.mk index 68b35f7b6d..ebf534cfe7 100644 --- a/mojo/mojo_common_lib.target.linux-arm.mk +++ b/mojo/mojo_common_lib.target.linux-arm.mk @@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \ mojo/common/environment_data.cc \ mojo/common/handle_watcher.cc \ mojo/common/message_pump_mojo.cc \ + mojo/common/mojo_channel_init.cc \ mojo/common/time_helper.cc @@ -227,7 +228,6 @@ LOCAL_LDFLAGS_Debug := \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ -Wl,--icf=safe \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_common_lib.target.linux-mips.mk b/mojo/mojo_common_lib.target.linux-mips.mk index b1a8bd7045..f059697b50 100644 --- a/mojo/mojo_common_lib.target.linux-mips.mk +++ b/mojo/mojo_common_lib.target.linux-mips.mk @@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \ mojo/common/environment_data.cc \ mojo/common/handle_watcher.cc \ mojo/common/message_pump_mojo.cc \ + mojo/common/mojo_channel_init.cc \ mojo/common/time_helper.cc @@ -223,7 +224,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_common_lib.target.linux-x86.mk b/mojo/mojo_common_lib.target.linux-x86.mk index 0909f0ba0d..14e7ed77a5 100644 --- a/mojo/mojo_common_lib.target.linux-x86.mk +++ b/mojo/mojo_common_lib.target.linux-x86.mk @@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \ mojo/common/environment_data.cc \ mojo/common/handle_watcher.cc \ mojo/common/message_pump_mojo.cc \ + mojo/common/mojo_channel_init.cc \ mojo/common/time_helper.cc @@ -225,7 +226,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_common_lib.target.linux-x86_64.mk b/mojo/mojo_common_lib.target.linux-x86_64.mk index 370d66234b..c777ccc711 100644 --- a/mojo/mojo_common_lib.target.linux-x86_64.mk +++ b/mojo/mojo_common_lib.target.linux-x86_64.mk @@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \ mojo/common/environment_data.cc \ mojo/common/handle_watcher.cc \ mojo/common/message_pump_mojo.cc \ + mojo/common/mojo_channel_init.cc \ mojo/common/time_helper.cc @@ -225,7 +226,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_environment_chromium.target.darwin-arm.mk b/mojo/mojo_environment_chromium.target.darwin-arm.mk index 60946212b8..b7e5624dfe 100644 --- a/mojo/mojo_environment_chromium.target.darwin-arm.mk +++ b/mojo/mojo_environment_chromium.target.darwin-arm.mk @@ -223,7 +223,6 @@ LOCAL_LDFLAGS_Debug := \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ -Wl,--icf=safe \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_environment_chromium.target.darwin-mips.mk b/mojo/mojo_environment_chromium.target.darwin-mips.mk index c3ed74f1b4..aca1c30c9a 100644 --- a/mojo/mojo_environment_chromium.target.darwin-mips.mk +++ b/mojo/mojo_environment_chromium.target.darwin-mips.mk @@ -219,7 +219,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_environment_chromium.target.darwin-x86.mk b/mojo/mojo_environment_chromium.target.darwin-x86.mk index f59dfba895..435cc4c7ff 100644 --- a/mojo/mojo_environment_chromium.target.darwin-x86.mk +++ b/mojo/mojo_environment_chromium.target.darwin-x86.mk @@ -221,7 +221,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_environment_chromium.target.darwin-x86_64.mk b/mojo/mojo_environment_chromium.target.darwin-x86_64.mk index d408e14d67..8062f990ef 100644 --- a/mojo/mojo_environment_chromium.target.darwin-x86_64.mk +++ b/mojo/mojo_environment_chromium.target.darwin-x86_64.mk @@ -221,7 +221,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_environment_chromium.target.linux-arm.mk b/mojo/mojo_environment_chromium.target.linux-arm.mk index 60946212b8..b7e5624dfe 100644 --- a/mojo/mojo_environment_chromium.target.linux-arm.mk +++ b/mojo/mojo_environment_chromium.target.linux-arm.mk @@ -223,7 +223,6 @@ LOCAL_LDFLAGS_Debug := \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ -Wl,--icf=safe \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_environment_chromium.target.linux-mips.mk b/mojo/mojo_environment_chromium.target.linux-mips.mk index c3ed74f1b4..aca1c30c9a 100644 --- a/mojo/mojo_environment_chromium.target.linux-mips.mk +++ b/mojo/mojo_environment_chromium.target.linux-mips.mk @@ -219,7 +219,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_environment_chromium.target.linux-x86.mk b/mojo/mojo_environment_chromium.target.linux-x86.mk index f59dfba895..435cc4c7ff 100644 --- a/mojo/mojo_environment_chromium.target.linux-x86.mk +++ b/mojo/mojo_environment_chromium.target.linux-x86.mk @@ -221,7 +221,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_environment_chromium.target.linux-x86_64.mk b/mojo/mojo_environment_chromium.target.linux-x86_64.mk index d408e14d67..8062f990ef 100644 --- a/mojo/mojo_environment_chromium.target.linux-x86_64.mk +++ b/mojo/mojo_environment_chromium.target.linux-x86_64.mk @@ -221,7 +221,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_environment_chromium_impl.target.darwin-arm.mk b/mojo/mojo_environment_chromium_impl.target.darwin-arm.mk index aea2ccd664..9b04cb45ad 100644 --- a/mojo/mojo_environment_chromium_impl.target.darwin-arm.mk +++ b/mojo/mojo_environment_chromium_impl.target.darwin-arm.mk @@ -224,7 +224,6 @@ LOCAL_LDFLAGS_Debug := \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ -Wl,--icf=safe \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_environment_chromium_impl.target.darwin-mips.mk b/mojo/mojo_environment_chromium_impl.target.darwin-mips.mk index d3991d51bd..b683e4708f 100644 --- a/mojo/mojo_environment_chromium_impl.target.darwin-mips.mk +++ b/mojo/mojo_environment_chromium_impl.target.darwin-mips.mk @@ -220,7 +220,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_environment_chromium_impl.target.darwin-x86.mk b/mojo/mojo_environment_chromium_impl.target.darwin-x86.mk index f9c06ba959..0ce43342e0 100644 --- a/mojo/mojo_environment_chromium_impl.target.darwin-x86.mk +++ b/mojo/mojo_environment_chromium_impl.target.darwin-x86.mk @@ -222,7 +222,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_environment_chromium_impl.target.darwin-x86_64.mk b/mojo/mojo_environment_chromium_impl.target.darwin-x86_64.mk index 969b92b04e..be57920033 100644 --- a/mojo/mojo_environment_chromium_impl.target.darwin-x86_64.mk +++ b/mojo/mojo_environment_chromium_impl.target.darwin-x86_64.mk @@ -222,7 +222,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_environment_chromium_impl.target.linux-arm.mk b/mojo/mojo_environment_chromium_impl.target.linux-arm.mk index aea2ccd664..9b04cb45ad 100644 --- a/mojo/mojo_environment_chromium_impl.target.linux-arm.mk +++ b/mojo/mojo_environment_chromium_impl.target.linux-arm.mk @@ -224,7 +224,6 @@ LOCAL_LDFLAGS_Debug := \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ -Wl,--icf=safe \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_environment_chromium_impl.target.linux-mips.mk b/mojo/mojo_environment_chromium_impl.target.linux-mips.mk index d3991d51bd..b683e4708f 100644 --- a/mojo/mojo_environment_chromium_impl.target.linux-mips.mk +++ b/mojo/mojo_environment_chromium_impl.target.linux-mips.mk @@ -220,7 +220,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_environment_chromium_impl.target.linux-x86.mk b/mojo/mojo_environment_chromium_impl.target.linux-x86.mk index f9c06ba959..0ce43342e0 100644 --- a/mojo/mojo_environment_chromium_impl.target.linux-x86.mk +++ b/mojo/mojo_environment_chromium_impl.target.linux-x86.mk @@ -222,7 +222,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_environment_chromium_impl.target.linux-x86_64.mk b/mojo/mojo_environment_chromium_impl.target.linux-x86_64.mk index 969b92b04e..be57920033 100644 --- a/mojo/mojo_environment_chromium_impl.target.linux-x86_64.mk +++ b/mojo/mojo_environment_chromium_impl.target.linux-x86_64.mk @@ -222,7 +222,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_examples.gypi b/mojo/mojo_examples.gypi index 590285fd19..4de6fbd755 100644 --- a/mojo/mojo_examples.gypi +++ b/mojo/mojo_examples.gypi @@ -9,9 +9,8 @@ 'type': 'shared_library', 'dependencies': [ # TODO(darin): we should not be linking against these libraries! - '../ui/gfx/gfx.gyp:gfx', + '../ui/events/events.gyp:events', '../ui/gfx/gfx.gyp:gfx_geometry', - '../ui/gl/gl.gyp:gl', 'mojo_bindings', 'mojo_environment_standalone', 'mojo_gles2', @@ -277,47 +276,25 @@ 'includes': [ 'build/package_app.gypi' ], }, { - 'target_name': 'mojo_view_manager_bindings', - 'type': 'static_library', - 'sources': [ - 'examples/view_manager/view_manager.mojom', - ], - 'variables': { - 'mojom_base_output_dir': 'mojo', - }, - 'includes': [ 'public/tools/bindings/mojom_bindings_generator.gypi' ], - 'export_dependent_settings': [ - 'mojo_bindings', - ], - 'dependencies': [ - 'mojo_bindings', - ], - }, - { - 'target_name': 'mojo_view_manager', + 'target_name': 'mojo_sample_view_manager_app', 'type': 'shared_library', 'dependencies': [ '../base/base.gyp:base', + '../ui/gfx/gfx.gyp:gfx', '../ui/gfx/gfx.gyp:gfx_geometry', - 'mojo_common_lib', - 'mojo_environment_chromium', - 'mojo_launcher_bindings', - 'mojo_native_viewport_bindings', - 'mojo_shell_client', - 'mojo_system_impl', + '../ui/gl/gl.gyp:gl', + 'mojo_bindings', + 'mojo_environment_standalone', + 'mojo_gles2', 'mojo_view_manager_bindings', + 'mojo_shell_client', + 'mojo_system', + 'mojo_utility', ], 'sources': [ - 'examples/view_manager/view_manager.cc', + 'examples/sample_view_manager_app/sample_view_manager_app.cc', ], }, - { - 'target_name': 'package_mojo_view_manager', - 'variables': { - 'app_name': 'mojo_view_manager', - }, - 'includes': [ 'build/package_app.gypi' ], - }, ], }], ], diff --git a/mojo/mojo_js_bindings_lib.target.darwin-arm.mk b/mojo/mojo_js_bindings_lib.target.darwin-arm.mk index e6d62904d8..447aa89258 100644 --- a/mojo/mojo_js_bindings_lib.target.darwin-arm.mk +++ b/mojo/mojo_js_bindings_lib.target.darwin-arm.mk @@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \ mojo/bindings/js/core.cc \ mojo/bindings/js/handle.cc \ mojo/bindings/js/support.cc \ + mojo/bindings/js/unicode.cc \ mojo/bindings/js/waiting_callback.cc @@ -231,7 +232,6 @@ LOCAL_LDFLAGS_Debug := \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ -Wl,--icf=safe \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_js_bindings_lib.target.darwin-mips.mk b/mojo/mojo_js_bindings_lib.target.darwin-mips.mk index fbe094e163..41c997a6ff 100644 --- a/mojo/mojo_js_bindings_lib.target.darwin-mips.mk +++ b/mojo/mojo_js_bindings_lib.target.darwin-mips.mk @@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \ mojo/bindings/js/core.cc \ mojo/bindings/js/handle.cc \ mojo/bindings/js/support.cc \ + mojo/bindings/js/unicode.cc \ mojo/bindings/js/waiting_callback.cc @@ -227,7 +228,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_js_bindings_lib.target.darwin-x86.mk b/mojo/mojo_js_bindings_lib.target.darwin-x86.mk index e7af031fa6..d5cf56fe93 100644 --- a/mojo/mojo_js_bindings_lib.target.darwin-x86.mk +++ b/mojo/mojo_js_bindings_lib.target.darwin-x86.mk @@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \ mojo/bindings/js/core.cc \ mojo/bindings/js/handle.cc \ mojo/bindings/js/support.cc \ + mojo/bindings/js/unicode.cc \ mojo/bindings/js/waiting_callback.cc @@ -229,7 +230,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_js_bindings_lib.target.darwin-x86_64.mk b/mojo/mojo_js_bindings_lib.target.darwin-x86_64.mk index 729edf8a01..8252f697f5 100644 --- a/mojo/mojo_js_bindings_lib.target.darwin-x86_64.mk +++ b/mojo/mojo_js_bindings_lib.target.darwin-x86_64.mk @@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \ mojo/bindings/js/core.cc \ mojo/bindings/js/handle.cc \ mojo/bindings/js/support.cc \ + mojo/bindings/js/unicode.cc \ mojo/bindings/js/waiting_callback.cc @@ -229,7 +230,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_js_bindings_lib.target.linux-arm.mk b/mojo/mojo_js_bindings_lib.target.linux-arm.mk index e6d62904d8..447aa89258 100644 --- a/mojo/mojo_js_bindings_lib.target.linux-arm.mk +++ b/mojo/mojo_js_bindings_lib.target.linux-arm.mk @@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \ mojo/bindings/js/core.cc \ mojo/bindings/js/handle.cc \ mojo/bindings/js/support.cc \ + mojo/bindings/js/unicode.cc \ mojo/bindings/js/waiting_callback.cc @@ -231,7 +232,6 @@ LOCAL_LDFLAGS_Debug := \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ -Wl,--icf=safe \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_js_bindings_lib.target.linux-mips.mk b/mojo/mojo_js_bindings_lib.target.linux-mips.mk index fbe094e163..41c997a6ff 100644 --- a/mojo/mojo_js_bindings_lib.target.linux-mips.mk +++ b/mojo/mojo_js_bindings_lib.target.linux-mips.mk @@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \ mojo/bindings/js/core.cc \ mojo/bindings/js/handle.cc \ mojo/bindings/js/support.cc \ + mojo/bindings/js/unicode.cc \ mojo/bindings/js/waiting_callback.cc @@ -227,7 +228,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_js_bindings_lib.target.linux-x86.mk b/mojo/mojo_js_bindings_lib.target.linux-x86.mk index e7af031fa6..d5cf56fe93 100644 --- a/mojo/mojo_js_bindings_lib.target.linux-x86.mk +++ b/mojo/mojo_js_bindings_lib.target.linux-x86.mk @@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \ mojo/bindings/js/core.cc \ mojo/bindings/js/handle.cc \ mojo/bindings/js/support.cc \ + mojo/bindings/js/unicode.cc \ mojo/bindings/js/waiting_callback.cc @@ -229,7 +230,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_js_bindings_lib.target.linux-x86_64.mk b/mojo/mojo_js_bindings_lib.target.linux-x86_64.mk index 729edf8a01..8252f697f5 100644 --- a/mojo/mojo_js_bindings_lib.target.linux-x86_64.mk +++ b/mojo/mojo_js_bindings_lib.target.linux-x86_64.mk @@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \ mojo/bindings/js/core.cc \ mojo/bindings/js/handle.cc \ mojo/bindings/js/support.cc \ + mojo/bindings/js/unicode.cc \ mojo/bindings/js/waiting_callback.cc @@ -229,7 +230,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_public.gypi b/mojo/mojo_public.gypi index 15eccb0c7e..7f9c2f7c16 100644 --- a/mojo/mojo_public.gypi +++ b/mojo/mojo_public.gypi @@ -14,8 +14,18 @@ '..', ], }, + '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/c/system/async_waiter.h', 'public/c/system/core.h', 'public/c/system/macros.h', 'public/c/system/system_export.h', @@ -111,7 +121,7 @@ 'mojo_environment_standalone', 'mojo_public_test_utils', 'mojo_run_all_unittests', - 'mojo_sample_service', + 'mojo_public_test_interfaces', 'mojo_utility', ], 'sources': [ @@ -124,15 +134,7 @@ 'public/cpp/bindings/tests/router_unittest.cc', 'public/cpp/bindings/tests/sample_service_unittest.cc', 'public/cpp/bindings/tests/type_conversion_unittest.cc', - 'public/interfaces/bindings/tests/math_calculator.mojom', - 'public/interfaces/bindings/tests/sample_factory.mojom', - 'public/interfaces/bindings/tests/sample_interfaces.mojom', - 'public/interfaces/bindings/tests/test_structs.mojom', ], - 'variables': { - 'mojom_base_output_dir': 'mojo', - }, - 'includes': [ 'public/tools/bindings/mojom_bindings_generator.gypi' ], }, { 'target_name': 'mojo_public_environment_unittests', @@ -256,12 +258,16 @@ ], }, { - 'target_name': 'mojo_sample_service', + 'target_name': 'mojo_public_test_interfaces', 'type': 'static_library', 'sources': [ - 'public/interfaces/bindings/tests/sample_service.mojom', + 'public/interfaces/bindings/tests/math_calculator.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/test_structs.mojom', ], 'variables': { 'mojom_base_output_dir': 'mojo', @@ -354,4 +360,18 @@ ], }, ], + 'conditions': [ + ['OS == "android"', { + 'targets': [ + { + 'target_name': 'mojo_public_java', + 'type': 'none', + 'variables': { + 'java_in_dir': 'public/java', + }, + 'includes': [ '../build/java.gypi' ], + }, + ], + }], + ], } diff --git a/mojo/mojo_service_manager.target.darwin-arm.mk b/mojo/mojo_service_manager.target.darwin-arm.mk index 29faa1c09f..b90703cdf7 100644 --- a/mojo/mojo_service_manager.target.darwin-arm.mk +++ b/mojo/mojo_service_manager.target.darwin-arm.mk @@ -232,7 +232,6 @@ LOCAL_LDFLAGS_Debug := \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ -Wl,--icf=safe \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_service_manager.target.darwin-mips.mk b/mojo/mojo_service_manager.target.darwin-mips.mk index 705c431d0e..3fe9c8274e 100644 --- a/mojo/mojo_service_manager.target.darwin-mips.mk +++ b/mojo/mojo_service_manager.target.darwin-mips.mk @@ -228,7 +228,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_service_manager.target.darwin-x86.mk b/mojo/mojo_service_manager.target.darwin-x86.mk index bcf69b8672..d953c977f2 100644 --- a/mojo/mojo_service_manager.target.darwin-x86.mk +++ b/mojo/mojo_service_manager.target.darwin-x86.mk @@ -228,7 +228,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_service_manager.target.darwin-x86_64.mk b/mojo/mojo_service_manager.target.darwin-x86_64.mk index 1074db399d..4868f8333d 100644 --- a/mojo/mojo_service_manager.target.darwin-x86_64.mk +++ b/mojo/mojo_service_manager.target.darwin-x86_64.mk @@ -230,7 +230,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_service_manager.target.linux-arm.mk b/mojo/mojo_service_manager.target.linux-arm.mk index 29faa1c09f..b90703cdf7 100644 --- a/mojo/mojo_service_manager.target.linux-arm.mk +++ b/mojo/mojo_service_manager.target.linux-arm.mk @@ -232,7 +232,6 @@ LOCAL_LDFLAGS_Debug := \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ -Wl,--icf=safe \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_service_manager.target.linux-mips.mk b/mojo/mojo_service_manager.target.linux-mips.mk index 705c431d0e..3fe9c8274e 100644 --- a/mojo/mojo_service_manager.target.linux-mips.mk +++ b/mojo/mojo_service_manager.target.linux-mips.mk @@ -228,7 +228,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_service_manager.target.linux-x86.mk b/mojo/mojo_service_manager.target.linux-x86.mk index bcf69b8672..d953c977f2 100644 --- a/mojo/mojo_service_manager.target.linux-x86.mk +++ b/mojo/mojo_service_manager.target.linux-x86.mk @@ -228,7 +228,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_service_manager.target.linux-x86_64.mk b/mojo/mojo_service_manager.target.linux-x86_64.mk index 1074db399d..4868f8333d 100644 --- a/mojo/mojo_service_manager.target.linux-x86_64.mk +++ b/mojo/mojo_service_manager.target.linux-x86_64.mk @@ -230,7 +230,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_services.gypi b/mojo/mojo_services.gypi index 208f14bbca..3911a21856 100644 --- a/mojo/mojo_services.gypi +++ b/mojo/mojo_services.gypi @@ -60,7 +60,8 @@ }, { 'target_name': 'mojo_native_viewport_service', - 'type': 'shared_library', + # This is linked directly into the embedder, so we make it a component. + 'type': '<(component)', 'dependencies': [ '../base/base.gyp:base', '../ui/events/events.gyp:events', @@ -100,5 +101,124 @@ }], ], }, + { + 'target_name': 'mojo_view_manager_lib', + 'type': 'static_library', + 'dependencies': [ + '../base/base.gyp:base', + ], + 'sources': [ + 'services/public/cpp/view_manager/lib/view.cc', + 'services/public/cpp/view_manager/lib/view_manager.cc', + 'services/public/cpp/view_manager/lib/view_tree_host.cc', + 'services/public/cpp/view_manager/lib/view_tree_node.cc', + 'services/public/cpp/view_manager/lib/view_tree_node_observer.cc', + 'services/public/cpp/view_manager/lib/view_tree_node_private.cc', + 'services/public/cpp/view_manager/lib/view_tree_node_private.h', + 'services/public/cpp/view_manager/view.h', + 'services/public/cpp/view_manager/view_manager.h', + 'services/public/cpp/view_manager/view_tree_host.h', + 'services/public/cpp/view_manager/view_tree_node.h', + 'services/public/cpp/view_manager/view_tree_node_observer.h', + ], + }, + { + 'target_name': 'mojo_view_manager_lib_unittests', + 'type': 'executable', + 'dependencies': [ + '../base/base.gyp:base', + '../base/base.gyp:test_support_base', + '../testing/gtest.gyp:gtest', + 'mojo_run_all_unittests', + 'mojo_view_manager_lib', + ], + 'sources': [ + 'services/public/cpp/view_manager/tests/view_unittest.cc', + 'services/public/cpp/view_manager/tests/view_manager_unittest.cc', + 'services/public/cpp/view_manager/tests/view_tree_host_unittest.cc', + 'services/public/cpp/view_manager/tests/view_tree_node_unittest.cc', + ], + }, + ], + 'conditions': [ + ['use_aura==1', { + 'targets': [ + { + 'target_name': 'mojo_view_manager_bindings', + 'type': 'static_library', + 'sources': [ + 'services/public/interfaces/view_manager/view_manager.mojom', + ], + 'variables': { + 'mojom_base_output_dir': 'mojo', + }, + 'includes': [ 'public/tools/bindings/mojom_bindings_generator.gypi' ], + 'export_dependent_settings': [ + 'mojo_bindings', + ], + 'dependencies': [ + 'mojo_bindings', + ], + }, + { + 'target_name': 'mojo_view_manager', + 'type': '<(component)', + 'dependencies': [ + '../base/base.gyp:base', + '../skia/skia.gyp:skia', + '../ui/aura/aura.gyp:aura', + '../ui/gfx/gfx.gyp:gfx_geometry', + 'mojo_common_lib', + 'mojo_environment_chromium', + 'mojo_launcher_bindings', + 'mojo_native_viewport_bindings', + 'mojo_shell_client', + 'mojo_system_impl', + 'mojo_view_manager_bindings', + ], + 'sources': [ + 'services/view_manager/ids.h', + 'services/view_manager/node.cc', + 'services/view_manager/node.h', + 'services/view_manager/node_delegate.h', + 'services/view_manager/root_node_manager.cc', + 'services/view_manager/root_node_manager.h', + 'services/view_manager/view_manager.cc', + 'services/view_manager/view_manager_connection.cc', + 'services/view_manager/view_manager_connection.h', + 'services/view_manager/view_manager_export.h', + ], + 'defines': [ + 'MOJO_VIEW_MANAGER_IMPLEMENTATION', + ], + }, + { + 'target_name': 'mojo_view_manager_unittests', + 'type': 'executable', + 'dependencies': [ + '../base/base.gyp:base', + '../skia/skia.gyp:skia', + '../testing/gtest.gyp:gtest', + '../ui/aura/aura.gyp:aura', + 'mojo_environment_chromium', + 'mojo_run_all_unittests', + 'mojo_shell_client', + 'mojo_system_impl', + 'mojo_view_manager', + 'mojo_view_manager_bindings', + ], + 'sources': [ + 'services/view_manager/view_manager_connection_unittest.cc', + ], + }, + { + 'target_name': 'package_mojo_view_manager', + 'variables': { + 'app_name': 'mojo_view_manager', + }, + 'includes': [ 'build/package_app.gypi' ], + }, + ], + }], ], } diff --git a/mojo/mojo_shell_bindings.target.darwin-arm.mk b/mojo/mojo_shell_bindings.target.darwin-arm.mk index 34e065264d..fd24e3b38b 100644 --- a/mojo/mojo_shell_bindings.target.darwin-arm.mk +++ b/mojo/mojo_shell_bindings.target.darwin-arm.mk @@ -15,12 +15,12 @@ GYP_TARGET_DEPENDENCIES := ### Generated for rule "mojo_mojo_gyp_mojo_shell_bindings_target_Generate_C___source_files_from_mojom_files": -# "{'inputs': ['../mojo/public/tools/bindings/mojom_bindings_generator.py', '../mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl', '../mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/module.js.tmpl', '../mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/mojom_cpp_generator.py', '../mojo/public/tools/bindings/generators/mojom_js_generator.py', '../mojo/public/tools/bindings/pylib/parse/__init__.py', '../mojo/public/tools/bindings/pylib/parse/mojo_lexer.py', '../mojo/public/tools/bindings/pylib/parse/mojo_parser.py', '../mojo/public/tools/bindings/pylib/parse/mojo_translate.py', '../mojo/public/tools/bindings/pylib/generate/__init__.py', '../mojo/public/tools/bindings/pylib/generate/mojom.py', '../mojo/public/tools/bindings/pylib/generate/mojom_data.py', '../mojo/public/tools/bindings/pylib/generate/mojom_generator.py', '../mojo/public/tools/bindings/pylib/generate/mojom_pack.py', '../mojo/public/tools/bindings/pylib/generate/template_expander.py'], 'process_outputs_as_sources': '1', 'extension': 'mojom', 'outputs': ['$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.cc', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.h', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.js', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom-internal.h'], 'variables': {'mojom_bindings_generator': '../mojo/public/tools/bindings/mojom_bindings_generator.py'}, 'rule_name': 'Generate C++ source files from mojom files', 'rule_sources': ['public/interfaces/shell/shell.mojom'], 'action': ['python', '../mojo/public/tools/bindings/mojom_bindings_generator.py', '%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom', '-d', '..', '-o', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s'], 'message': 'Generating Mojo bindings from %(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom'}": +# "{'inputs': ['../mojo/public/tools/bindings/mojom_bindings_generator.py', '../mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl', '../mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/module.js.tmpl', '../mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/mojom_cpp_generator.py', '../mojo/public/tools/bindings/generators/mojom_js_generator.py', '../mojo/public/tools/bindings/pylib/mojom/generate/__init__.py', '../mojo/public/tools/bindings/pylib/mojom/generate/data.py', '../mojo/public/tools/bindings/pylib/mojom/generate/generator.py', '../mojo/public/tools/bindings/pylib/mojom/generate/module.py', '../mojo/public/tools/bindings/pylib/mojom/generate/pack.py', '../mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py', '../mojo/public/tools/bindings/pylib/mojom/parse/__init__.py', '../mojo/public/tools/bindings/pylib/mojom/parse/ast.py', '../mojo/public/tools/bindings/pylib/mojom/parse/lexer.py', '../mojo/public/tools/bindings/pylib/mojom/parse/parser.py', '../mojo/public/tools/bindings/pylib/mojom/parse/translate.py'], 'process_outputs_as_sources': '1', 'extension': 'mojom', 'outputs': ['$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.cc', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.h', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.js', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom-internal.h'], 'variables': {'mojom_bindings_generator': '../mojo/public/tools/bindings/mojom_bindings_generator.py'}, 'rule_name': 'Generate C++ source files from mojom files', 'rule_sources': ['public/interfaces/shell/shell.mojom'], 'action': ['python', '../mojo/public/tools/bindings/mojom_bindings_generator.py', '%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom', '-d', '..', '-o', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s'], 'message': 'Generating Mojo bindings from %(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom'}": $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_local_path := $(LOCAL_PATH) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir)) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir)) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH)) -$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: $(LOCAL_PATH)/mojo/public/interfaces/shell/shell.mojom $(LOCAL_PATH)/mojo/public/tools/bindings/mojom_bindings_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_cpp_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_js_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_lexer.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_parser.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_translate.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_data.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_pack.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/template_expander.py $(GYP_TARGET_DEPENDENCIES) +$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: $(LOCAL_PATH)/mojo/public/interfaces/shell/shell.mojom $(LOCAL_PATH)/mojo/public/tools/bindings/mojom_bindings_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_cpp_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_js_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/data.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/module.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/pack.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/ast.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/lexer.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/parser.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/translate.py $(GYP_TARGET_DEPENDENCIES) mkdir -p $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell; cd $(gyp_local_path)/mojo; python ../mojo/public/tools/bindings/mojom_bindings_generator.py public/interfaces/shell/shell.mojom -d .. -o "$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell" $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.h: $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc ; @@ -244,7 +244,6 @@ LOCAL_LDFLAGS_Debug := \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ -Wl,--icf=safe \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_shell_bindings.target.darwin-mips.mk b/mojo/mojo_shell_bindings.target.darwin-mips.mk index dcb5ada33e..3488379fd6 100644 --- a/mojo/mojo_shell_bindings.target.darwin-mips.mk +++ b/mojo/mojo_shell_bindings.target.darwin-mips.mk @@ -15,12 +15,12 @@ GYP_TARGET_DEPENDENCIES := ### Generated for rule "mojo_mojo_gyp_mojo_shell_bindings_target_Generate_C___source_files_from_mojom_files": -# "{'inputs': ['../mojo/public/tools/bindings/mojom_bindings_generator.py', '../mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl', '../mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/module.js.tmpl', '../mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/mojom_cpp_generator.py', '../mojo/public/tools/bindings/generators/mojom_js_generator.py', '../mojo/public/tools/bindings/pylib/parse/__init__.py', '../mojo/public/tools/bindings/pylib/parse/mojo_lexer.py', '../mojo/public/tools/bindings/pylib/parse/mojo_parser.py', '../mojo/public/tools/bindings/pylib/parse/mojo_translate.py', '../mojo/public/tools/bindings/pylib/generate/__init__.py', '../mojo/public/tools/bindings/pylib/generate/mojom.py', '../mojo/public/tools/bindings/pylib/generate/mojom_data.py', '../mojo/public/tools/bindings/pylib/generate/mojom_generator.py', '../mojo/public/tools/bindings/pylib/generate/mojom_pack.py', '../mojo/public/tools/bindings/pylib/generate/template_expander.py'], 'process_outputs_as_sources': '1', 'extension': 'mojom', 'outputs': ['$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.cc', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.h', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.js', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom-internal.h'], 'variables': {'mojom_bindings_generator': '../mojo/public/tools/bindings/mojom_bindings_generator.py'}, 'rule_name': 'Generate C++ source files from mojom files', 'rule_sources': ['public/interfaces/shell/shell.mojom'], 'action': ['python', '../mojo/public/tools/bindings/mojom_bindings_generator.py', '%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom', '-d', '..', '-o', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s'], 'message': 'Generating Mojo bindings from %(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom'}": +# "{'inputs': ['../mojo/public/tools/bindings/mojom_bindings_generator.py', '../mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl', '../mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/module.js.tmpl', '../mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/mojom_cpp_generator.py', '../mojo/public/tools/bindings/generators/mojom_js_generator.py', '../mojo/public/tools/bindings/pylib/mojom/generate/__init__.py', '../mojo/public/tools/bindings/pylib/mojom/generate/data.py', '../mojo/public/tools/bindings/pylib/mojom/generate/generator.py', '../mojo/public/tools/bindings/pylib/mojom/generate/module.py', '../mojo/public/tools/bindings/pylib/mojom/generate/pack.py', '../mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py', '../mojo/public/tools/bindings/pylib/mojom/parse/__init__.py', '../mojo/public/tools/bindings/pylib/mojom/parse/ast.py', '../mojo/public/tools/bindings/pylib/mojom/parse/lexer.py', '../mojo/public/tools/bindings/pylib/mojom/parse/parser.py', '../mojo/public/tools/bindings/pylib/mojom/parse/translate.py'], 'process_outputs_as_sources': '1', 'extension': 'mojom', 'outputs': ['$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.cc', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.h', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.js', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom-internal.h'], 'variables': {'mojom_bindings_generator': '../mojo/public/tools/bindings/mojom_bindings_generator.py'}, 'rule_name': 'Generate C++ source files from mojom files', 'rule_sources': ['public/interfaces/shell/shell.mojom'], 'action': ['python', '../mojo/public/tools/bindings/mojom_bindings_generator.py', '%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom', '-d', '..', '-o', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s'], 'message': 'Generating Mojo bindings from %(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom'}": $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_local_path := $(LOCAL_PATH) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir)) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir)) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH)) -$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: $(LOCAL_PATH)/mojo/public/interfaces/shell/shell.mojom $(LOCAL_PATH)/mojo/public/tools/bindings/mojom_bindings_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_cpp_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_js_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_lexer.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_parser.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_translate.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_data.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_pack.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/template_expander.py $(GYP_TARGET_DEPENDENCIES) +$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: $(LOCAL_PATH)/mojo/public/interfaces/shell/shell.mojom $(LOCAL_PATH)/mojo/public/tools/bindings/mojom_bindings_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_cpp_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_js_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/data.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/module.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/pack.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/ast.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/lexer.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/parser.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/translate.py $(GYP_TARGET_DEPENDENCIES) mkdir -p $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell; cd $(gyp_local_path)/mojo; python ../mojo/public/tools/bindings/mojom_bindings_generator.py public/interfaces/shell/shell.mojom -d .. -o "$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell" $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.h: $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc ; @@ -240,7 +240,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_shell_bindings.target.darwin-x86.mk b/mojo/mojo_shell_bindings.target.darwin-x86.mk index 154618ab57..7594e6f5c0 100644 --- a/mojo/mojo_shell_bindings.target.darwin-x86.mk +++ b/mojo/mojo_shell_bindings.target.darwin-x86.mk @@ -15,12 +15,12 @@ GYP_TARGET_DEPENDENCIES := ### Generated for rule "mojo_mojo_gyp_mojo_shell_bindings_target_Generate_C___source_files_from_mojom_files": -# "{'inputs': ['../mojo/public/tools/bindings/mojom_bindings_generator.py', '../mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl', '../mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/module.js.tmpl', '../mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/mojom_cpp_generator.py', '../mojo/public/tools/bindings/generators/mojom_js_generator.py', '../mojo/public/tools/bindings/pylib/parse/__init__.py', '../mojo/public/tools/bindings/pylib/parse/mojo_lexer.py', '../mojo/public/tools/bindings/pylib/parse/mojo_parser.py', '../mojo/public/tools/bindings/pylib/parse/mojo_translate.py', '../mojo/public/tools/bindings/pylib/generate/__init__.py', '../mojo/public/tools/bindings/pylib/generate/mojom.py', '../mojo/public/tools/bindings/pylib/generate/mojom_data.py', '../mojo/public/tools/bindings/pylib/generate/mojom_generator.py', '../mojo/public/tools/bindings/pylib/generate/mojom_pack.py', '../mojo/public/tools/bindings/pylib/generate/template_expander.py'], 'process_outputs_as_sources': '1', 'extension': 'mojom', 'outputs': ['$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.cc', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.h', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.js', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom-internal.h'], 'variables': {'mojom_bindings_generator': '../mojo/public/tools/bindings/mojom_bindings_generator.py'}, 'rule_name': 'Generate C++ source files from mojom files', 'rule_sources': ['public/interfaces/shell/shell.mojom'], 'action': ['python', '../mojo/public/tools/bindings/mojom_bindings_generator.py', '%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom', '-d', '..', '-o', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s'], 'message': 'Generating Mojo bindings from %(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom'}": +# "{'inputs': ['../mojo/public/tools/bindings/mojom_bindings_generator.py', '../mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl', '../mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/module.js.tmpl', '../mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/mojom_cpp_generator.py', '../mojo/public/tools/bindings/generators/mojom_js_generator.py', '../mojo/public/tools/bindings/pylib/mojom/generate/__init__.py', '../mojo/public/tools/bindings/pylib/mojom/generate/data.py', '../mojo/public/tools/bindings/pylib/mojom/generate/generator.py', '../mojo/public/tools/bindings/pylib/mojom/generate/module.py', '../mojo/public/tools/bindings/pylib/mojom/generate/pack.py', '../mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py', '../mojo/public/tools/bindings/pylib/mojom/parse/__init__.py', '../mojo/public/tools/bindings/pylib/mojom/parse/ast.py', '../mojo/public/tools/bindings/pylib/mojom/parse/lexer.py', '../mojo/public/tools/bindings/pylib/mojom/parse/parser.py', '../mojo/public/tools/bindings/pylib/mojom/parse/translate.py'], 'process_outputs_as_sources': '1', 'extension': 'mojom', 'outputs': ['$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.cc', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.h', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.js', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom-internal.h'], 'variables': {'mojom_bindings_generator': '../mojo/public/tools/bindings/mojom_bindings_generator.py'}, 'rule_name': 'Generate C++ source files from mojom files', 'rule_sources': ['public/interfaces/shell/shell.mojom'], 'action': ['python', '../mojo/public/tools/bindings/mojom_bindings_generator.py', '%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom', '-d', '..', '-o', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s'], 'message': 'Generating Mojo bindings from %(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom'}": $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_local_path := $(LOCAL_PATH) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir)) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir)) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH)) -$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: $(LOCAL_PATH)/mojo/public/interfaces/shell/shell.mojom $(LOCAL_PATH)/mojo/public/tools/bindings/mojom_bindings_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_cpp_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_js_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_lexer.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_parser.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_translate.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_data.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_pack.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/template_expander.py $(GYP_TARGET_DEPENDENCIES) +$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: $(LOCAL_PATH)/mojo/public/interfaces/shell/shell.mojom $(LOCAL_PATH)/mojo/public/tools/bindings/mojom_bindings_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_cpp_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_js_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/data.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/module.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/pack.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/ast.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/lexer.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/parser.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/translate.py $(GYP_TARGET_DEPENDENCIES) mkdir -p $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell; cd $(gyp_local_path)/mojo; python ../mojo/public/tools/bindings/mojom_bindings_generator.py public/interfaces/shell/shell.mojom -d .. -o "$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell" $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.h: $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc ; @@ -242,7 +242,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_shell_bindings.target.darwin-x86_64.mk b/mojo/mojo_shell_bindings.target.darwin-x86_64.mk index b95ff6b4e5..b2d097e4a2 100644 --- a/mojo/mojo_shell_bindings.target.darwin-x86_64.mk +++ b/mojo/mojo_shell_bindings.target.darwin-x86_64.mk @@ -15,12 +15,12 @@ GYP_TARGET_DEPENDENCIES := ### Generated for rule "mojo_mojo_gyp_mojo_shell_bindings_target_Generate_C___source_files_from_mojom_files": -# "{'inputs': ['../mojo/public/tools/bindings/mojom_bindings_generator.py', '../mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl', '../mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/module.js.tmpl', '../mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/mojom_cpp_generator.py', '../mojo/public/tools/bindings/generators/mojom_js_generator.py', '../mojo/public/tools/bindings/pylib/parse/__init__.py', '../mojo/public/tools/bindings/pylib/parse/mojo_lexer.py', '../mojo/public/tools/bindings/pylib/parse/mojo_parser.py', '../mojo/public/tools/bindings/pylib/parse/mojo_translate.py', '../mojo/public/tools/bindings/pylib/generate/__init__.py', '../mojo/public/tools/bindings/pylib/generate/mojom.py', '../mojo/public/tools/bindings/pylib/generate/mojom_data.py', '../mojo/public/tools/bindings/pylib/generate/mojom_generator.py', '../mojo/public/tools/bindings/pylib/generate/mojom_pack.py', '../mojo/public/tools/bindings/pylib/generate/template_expander.py'], 'process_outputs_as_sources': '1', 'extension': 'mojom', 'outputs': ['$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.cc', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.h', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.js', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom-internal.h'], 'variables': {'mojom_bindings_generator': '../mojo/public/tools/bindings/mojom_bindings_generator.py'}, 'rule_name': 'Generate C++ source files from mojom files', 'rule_sources': ['public/interfaces/shell/shell.mojom'], 'action': ['python', '../mojo/public/tools/bindings/mojom_bindings_generator.py', '%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom', '-d', '..', '-o', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s'], 'message': 'Generating Mojo bindings from %(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom'}": +# "{'inputs': ['../mojo/public/tools/bindings/mojom_bindings_generator.py', '../mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl', '../mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/module.js.tmpl', '../mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/mojom_cpp_generator.py', '../mojo/public/tools/bindings/generators/mojom_js_generator.py', '../mojo/public/tools/bindings/pylib/mojom/generate/__init__.py', '../mojo/public/tools/bindings/pylib/mojom/generate/data.py', '../mojo/public/tools/bindings/pylib/mojom/generate/generator.py', '../mojo/public/tools/bindings/pylib/mojom/generate/module.py', '../mojo/public/tools/bindings/pylib/mojom/generate/pack.py', '../mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py', '../mojo/public/tools/bindings/pylib/mojom/parse/__init__.py', '../mojo/public/tools/bindings/pylib/mojom/parse/ast.py', '../mojo/public/tools/bindings/pylib/mojom/parse/lexer.py', '../mojo/public/tools/bindings/pylib/mojom/parse/parser.py', '../mojo/public/tools/bindings/pylib/mojom/parse/translate.py'], 'process_outputs_as_sources': '1', 'extension': 'mojom', 'outputs': ['$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.cc', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.h', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.js', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom-internal.h'], 'variables': {'mojom_bindings_generator': '../mojo/public/tools/bindings/mojom_bindings_generator.py'}, 'rule_name': 'Generate C++ source files from mojom files', 'rule_sources': ['public/interfaces/shell/shell.mojom'], 'action': ['python', '../mojo/public/tools/bindings/mojom_bindings_generator.py', '%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom', '-d', '..', '-o', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s'], 'message': 'Generating Mojo bindings from %(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom'}": $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_local_path := $(LOCAL_PATH) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir)) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir)) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH)) -$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: $(LOCAL_PATH)/mojo/public/interfaces/shell/shell.mojom $(LOCAL_PATH)/mojo/public/tools/bindings/mojom_bindings_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_cpp_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_js_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_lexer.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_parser.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_translate.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_data.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_pack.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/template_expander.py $(GYP_TARGET_DEPENDENCIES) +$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: $(LOCAL_PATH)/mojo/public/interfaces/shell/shell.mojom $(LOCAL_PATH)/mojo/public/tools/bindings/mojom_bindings_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_cpp_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_js_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/data.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/module.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/pack.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/ast.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/lexer.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/parser.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/translate.py $(GYP_TARGET_DEPENDENCIES) mkdir -p $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell; cd $(gyp_local_path)/mojo; python ../mojo/public/tools/bindings/mojom_bindings_generator.py public/interfaces/shell/shell.mojom -d .. -o "$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell" $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.h: $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc ; @@ -242,7 +242,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_shell_bindings.target.linux-arm.mk b/mojo/mojo_shell_bindings.target.linux-arm.mk index 34e065264d..fd24e3b38b 100644 --- a/mojo/mojo_shell_bindings.target.linux-arm.mk +++ b/mojo/mojo_shell_bindings.target.linux-arm.mk @@ -15,12 +15,12 @@ GYP_TARGET_DEPENDENCIES := ### Generated for rule "mojo_mojo_gyp_mojo_shell_bindings_target_Generate_C___source_files_from_mojom_files": -# "{'inputs': ['../mojo/public/tools/bindings/mojom_bindings_generator.py', '../mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl', '../mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/module.js.tmpl', '../mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/mojom_cpp_generator.py', '../mojo/public/tools/bindings/generators/mojom_js_generator.py', '../mojo/public/tools/bindings/pylib/parse/__init__.py', '../mojo/public/tools/bindings/pylib/parse/mojo_lexer.py', '../mojo/public/tools/bindings/pylib/parse/mojo_parser.py', '../mojo/public/tools/bindings/pylib/parse/mojo_translate.py', '../mojo/public/tools/bindings/pylib/generate/__init__.py', '../mojo/public/tools/bindings/pylib/generate/mojom.py', '../mojo/public/tools/bindings/pylib/generate/mojom_data.py', '../mojo/public/tools/bindings/pylib/generate/mojom_generator.py', '../mojo/public/tools/bindings/pylib/generate/mojom_pack.py', '../mojo/public/tools/bindings/pylib/generate/template_expander.py'], 'process_outputs_as_sources': '1', 'extension': 'mojom', 'outputs': ['$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.cc', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.h', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.js', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom-internal.h'], 'variables': {'mojom_bindings_generator': '../mojo/public/tools/bindings/mojom_bindings_generator.py'}, 'rule_name': 'Generate C++ source files from mojom files', 'rule_sources': ['public/interfaces/shell/shell.mojom'], 'action': ['python', '../mojo/public/tools/bindings/mojom_bindings_generator.py', '%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom', '-d', '..', '-o', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s'], 'message': 'Generating Mojo bindings from %(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom'}": +# "{'inputs': ['../mojo/public/tools/bindings/mojom_bindings_generator.py', '../mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl', '../mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/module.js.tmpl', '../mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/mojom_cpp_generator.py', '../mojo/public/tools/bindings/generators/mojom_js_generator.py', '../mojo/public/tools/bindings/pylib/mojom/generate/__init__.py', '../mojo/public/tools/bindings/pylib/mojom/generate/data.py', '../mojo/public/tools/bindings/pylib/mojom/generate/generator.py', '../mojo/public/tools/bindings/pylib/mojom/generate/module.py', '../mojo/public/tools/bindings/pylib/mojom/generate/pack.py', '../mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py', '../mojo/public/tools/bindings/pylib/mojom/parse/__init__.py', '../mojo/public/tools/bindings/pylib/mojom/parse/ast.py', '../mojo/public/tools/bindings/pylib/mojom/parse/lexer.py', '../mojo/public/tools/bindings/pylib/mojom/parse/parser.py', '../mojo/public/tools/bindings/pylib/mojom/parse/translate.py'], 'process_outputs_as_sources': '1', 'extension': 'mojom', 'outputs': ['$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.cc', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.h', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.js', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom-internal.h'], 'variables': {'mojom_bindings_generator': '../mojo/public/tools/bindings/mojom_bindings_generator.py'}, 'rule_name': 'Generate C++ source files from mojom files', 'rule_sources': ['public/interfaces/shell/shell.mojom'], 'action': ['python', '../mojo/public/tools/bindings/mojom_bindings_generator.py', '%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom', '-d', '..', '-o', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s'], 'message': 'Generating Mojo bindings from %(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom'}": $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_local_path := $(LOCAL_PATH) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir)) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir)) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH)) -$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: $(LOCAL_PATH)/mojo/public/interfaces/shell/shell.mojom $(LOCAL_PATH)/mojo/public/tools/bindings/mojom_bindings_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_cpp_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_js_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_lexer.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_parser.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_translate.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_data.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_pack.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/template_expander.py $(GYP_TARGET_DEPENDENCIES) +$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: $(LOCAL_PATH)/mojo/public/interfaces/shell/shell.mojom $(LOCAL_PATH)/mojo/public/tools/bindings/mojom_bindings_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_cpp_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_js_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/data.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/module.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/pack.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/ast.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/lexer.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/parser.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/translate.py $(GYP_TARGET_DEPENDENCIES) mkdir -p $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell; cd $(gyp_local_path)/mojo; python ../mojo/public/tools/bindings/mojom_bindings_generator.py public/interfaces/shell/shell.mojom -d .. -o "$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell" $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.h: $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc ; @@ -244,7 +244,6 @@ LOCAL_LDFLAGS_Debug := \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ -Wl,--icf=safe \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_shell_bindings.target.linux-mips.mk b/mojo/mojo_shell_bindings.target.linux-mips.mk index dcb5ada33e..3488379fd6 100644 --- a/mojo/mojo_shell_bindings.target.linux-mips.mk +++ b/mojo/mojo_shell_bindings.target.linux-mips.mk @@ -15,12 +15,12 @@ GYP_TARGET_DEPENDENCIES := ### Generated for rule "mojo_mojo_gyp_mojo_shell_bindings_target_Generate_C___source_files_from_mojom_files": -# "{'inputs': ['../mojo/public/tools/bindings/mojom_bindings_generator.py', '../mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl', '../mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/module.js.tmpl', '../mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/mojom_cpp_generator.py', '../mojo/public/tools/bindings/generators/mojom_js_generator.py', '../mojo/public/tools/bindings/pylib/parse/__init__.py', '../mojo/public/tools/bindings/pylib/parse/mojo_lexer.py', '../mojo/public/tools/bindings/pylib/parse/mojo_parser.py', '../mojo/public/tools/bindings/pylib/parse/mojo_translate.py', '../mojo/public/tools/bindings/pylib/generate/__init__.py', '../mojo/public/tools/bindings/pylib/generate/mojom.py', '../mojo/public/tools/bindings/pylib/generate/mojom_data.py', '../mojo/public/tools/bindings/pylib/generate/mojom_generator.py', '../mojo/public/tools/bindings/pylib/generate/mojom_pack.py', '../mojo/public/tools/bindings/pylib/generate/template_expander.py'], 'process_outputs_as_sources': '1', 'extension': 'mojom', 'outputs': ['$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.cc', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.h', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.js', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom-internal.h'], 'variables': {'mojom_bindings_generator': '../mojo/public/tools/bindings/mojom_bindings_generator.py'}, 'rule_name': 'Generate C++ source files from mojom files', 'rule_sources': ['public/interfaces/shell/shell.mojom'], 'action': ['python', '../mojo/public/tools/bindings/mojom_bindings_generator.py', '%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom', '-d', '..', '-o', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s'], 'message': 'Generating Mojo bindings from %(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom'}": +# "{'inputs': ['../mojo/public/tools/bindings/mojom_bindings_generator.py', '../mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl', '../mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/module.js.tmpl', '../mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/mojom_cpp_generator.py', '../mojo/public/tools/bindings/generators/mojom_js_generator.py', '../mojo/public/tools/bindings/pylib/mojom/generate/__init__.py', '../mojo/public/tools/bindings/pylib/mojom/generate/data.py', '../mojo/public/tools/bindings/pylib/mojom/generate/generator.py', '../mojo/public/tools/bindings/pylib/mojom/generate/module.py', '../mojo/public/tools/bindings/pylib/mojom/generate/pack.py', '../mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py', '../mojo/public/tools/bindings/pylib/mojom/parse/__init__.py', '../mojo/public/tools/bindings/pylib/mojom/parse/ast.py', '../mojo/public/tools/bindings/pylib/mojom/parse/lexer.py', '../mojo/public/tools/bindings/pylib/mojom/parse/parser.py', '../mojo/public/tools/bindings/pylib/mojom/parse/translate.py'], 'process_outputs_as_sources': '1', 'extension': 'mojom', 'outputs': ['$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.cc', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.h', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.js', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom-internal.h'], 'variables': {'mojom_bindings_generator': '../mojo/public/tools/bindings/mojom_bindings_generator.py'}, 'rule_name': 'Generate C++ source files from mojom files', 'rule_sources': ['public/interfaces/shell/shell.mojom'], 'action': ['python', '../mojo/public/tools/bindings/mojom_bindings_generator.py', '%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom', '-d', '..', '-o', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s'], 'message': 'Generating Mojo bindings from %(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom'}": $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_local_path := $(LOCAL_PATH) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir)) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir)) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH)) -$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: $(LOCAL_PATH)/mojo/public/interfaces/shell/shell.mojom $(LOCAL_PATH)/mojo/public/tools/bindings/mojom_bindings_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_cpp_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_js_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_lexer.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_parser.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_translate.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_data.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_pack.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/template_expander.py $(GYP_TARGET_DEPENDENCIES) +$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: $(LOCAL_PATH)/mojo/public/interfaces/shell/shell.mojom $(LOCAL_PATH)/mojo/public/tools/bindings/mojom_bindings_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_cpp_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_js_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/data.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/module.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/pack.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/ast.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/lexer.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/parser.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/translate.py $(GYP_TARGET_DEPENDENCIES) mkdir -p $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell; cd $(gyp_local_path)/mojo; python ../mojo/public/tools/bindings/mojom_bindings_generator.py public/interfaces/shell/shell.mojom -d .. -o "$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell" $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.h: $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc ; @@ -240,7 +240,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_shell_bindings.target.linux-x86.mk b/mojo/mojo_shell_bindings.target.linux-x86.mk index 154618ab57..7594e6f5c0 100644 --- a/mojo/mojo_shell_bindings.target.linux-x86.mk +++ b/mojo/mojo_shell_bindings.target.linux-x86.mk @@ -15,12 +15,12 @@ GYP_TARGET_DEPENDENCIES := ### Generated for rule "mojo_mojo_gyp_mojo_shell_bindings_target_Generate_C___source_files_from_mojom_files": -# "{'inputs': ['../mojo/public/tools/bindings/mojom_bindings_generator.py', '../mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl', '../mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/module.js.tmpl', '../mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/mojom_cpp_generator.py', '../mojo/public/tools/bindings/generators/mojom_js_generator.py', '../mojo/public/tools/bindings/pylib/parse/__init__.py', '../mojo/public/tools/bindings/pylib/parse/mojo_lexer.py', '../mojo/public/tools/bindings/pylib/parse/mojo_parser.py', '../mojo/public/tools/bindings/pylib/parse/mojo_translate.py', '../mojo/public/tools/bindings/pylib/generate/__init__.py', '../mojo/public/tools/bindings/pylib/generate/mojom.py', '../mojo/public/tools/bindings/pylib/generate/mojom_data.py', '../mojo/public/tools/bindings/pylib/generate/mojom_generator.py', '../mojo/public/tools/bindings/pylib/generate/mojom_pack.py', '../mojo/public/tools/bindings/pylib/generate/template_expander.py'], 'process_outputs_as_sources': '1', 'extension': 'mojom', 'outputs': ['$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.cc', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.h', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.js', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom-internal.h'], 'variables': {'mojom_bindings_generator': '../mojo/public/tools/bindings/mojom_bindings_generator.py'}, 'rule_name': 'Generate C++ source files from mojom files', 'rule_sources': ['public/interfaces/shell/shell.mojom'], 'action': ['python', '../mojo/public/tools/bindings/mojom_bindings_generator.py', '%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom', '-d', '..', '-o', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s'], 'message': 'Generating Mojo bindings from %(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom'}": +# "{'inputs': ['../mojo/public/tools/bindings/mojom_bindings_generator.py', '../mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl', '../mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/module.js.tmpl', '../mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/mojom_cpp_generator.py', '../mojo/public/tools/bindings/generators/mojom_js_generator.py', '../mojo/public/tools/bindings/pylib/mojom/generate/__init__.py', '../mojo/public/tools/bindings/pylib/mojom/generate/data.py', '../mojo/public/tools/bindings/pylib/mojom/generate/generator.py', '../mojo/public/tools/bindings/pylib/mojom/generate/module.py', '../mojo/public/tools/bindings/pylib/mojom/generate/pack.py', '../mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py', '../mojo/public/tools/bindings/pylib/mojom/parse/__init__.py', '../mojo/public/tools/bindings/pylib/mojom/parse/ast.py', '../mojo/public/tools/bindings/pylib/mojom/parse/lexer.py', '../mojo/public/tools/bindings/pylib/mojom/parse/parser.py', '../mojo/public/tools/bindings/pylib/mojom/parse/translate.py'], 'process_outputs_as_sources': '1', 'extension': 'mojom', 'outputs': ['$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.cc', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.h', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.js', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom-internal.h'], 'variables': {'mojom_bindings_generator': '../mojo/public/tools/bindings/mojom_bindings_generator.py'}, 'rule_name': 'Generate C++ source files from mojom files', 'rule_sources': ['public/interfaces/shell/shell.mojom'], 'action': ['python', '../mojo/public/tools/bindings/mojom_bindings_generator.py', '%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom', '-d', '..', '-o', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s'], 'message': 'Generating Mojo bindings from %(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom'}": $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_local_path := $(LOCAL_PATH) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir)) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir)) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH)) -$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: $(LOCAL_PATH)/mojo/public/interfaces/shell/shell.mojom $(LOCAL_PATH)/mojo/public/tools/bindings/mojom_bindings_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_cpp_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_js_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_lexer.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_parser.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_translate.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_data.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_pack.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/template_expander.py $(GYP_TARGET_DEPENDENCIES) +$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: $(LOCAL_PATH)/mojo/public/interfaces/shell/shell.mojom $(LOCAL_PATH)/mojo/public/tools/bindings/mojom_bindings_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_cpp_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_js_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/data.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/module.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/pack.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/ast.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/lexer.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/parser.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/translate.py $(GYP_TARGET_DEPENDENCIES) mkdir -p $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell; cd $(gyp_local_path)/mojo; python ../mojo/public/tools/bindings/mojom_bindings_generator.py public/interfaces/shell/shell.mojom -d .. -o "$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell" $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.h: $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc ; @@ -242,7 +242,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_shell_bindings.target.linux-x86_64.mk b/mojo/mojo_shell_bindings.target.linux-x86_64.mk index b95ff6b4e5..b2d097e4a2 100644 --- a/mojo/mojo_shell_bindings.target.linux-x86_64.mk +++ b/mojo/mojo_shell_bindings.target.linux-x86_64.mk @@ -15,12 +15,12 @@ GYP_TARGET_DEPENDENCIES := ### Generated for rule "mojo_mojo_gyp_mojo_shell_bindings_target_Generate_C___source_files_from_mojom_files": -# "{'inputs': ['../mojo/public/tools/bindings/mojom_bindings_generator.py', '../mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl', '../mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/module.js.tmpl', '../mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/mojom_cpp_generator.py', '../mojo/public/tools/bindings/generators/mojom_js_generator.py', '../mojo/public/tools/bindings/pylib/parse/__init__.py', '../mojo/public/tools/bindings/pylib/parse/mojo_lexer.py', '../mojo/public/tools/bindings/pylib/parse/mojo_parser.py', '../mojo/public/tools/bindings/pylib/parse/mojo_translate.py', '../mojo/public/tools/bindings/pylib/generate/__init__.py', '../mojo/public/tools/bindings/pylib/generate/mojom.py', '../mojo/public/tools/bindings/pylib/generate/mojom_data.py', '../mojo/public/tools/bindings/pylib/generate/mojom_generator.py', '../mojo/public/tools/bindings/pylib/generate/mojom_pack.py', '../mojo/public/tools/bindings/pylib/generate/template_expander.py'], 'process_outputs_as_sources': '1', 'extension': 'mojom', 'outputs': ['$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.cc', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.h', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.js', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom-internal.h'], 'variables': {'mojom_bindings_generator': '../mojo/public/tools/bindings/mojom_bindings_generator.py'}, 'rule_name': 'Generate C++ source files from mojom files', 'rule_sources': ['public/interfaces/shell/shell.mojom'], 'action': ['python', '../mojo/public/tools/bindings/mojom_bindings_generator.py', '%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom', '-d', '..', '-o', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s'], 'message': 'Generating Mojo bindings from %(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom'}": +# "{'inputs': ['../mojo/public/tools/bindings/mojom_bindings_generator.py', '../mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl', '../mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl', '../mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl', '../mojo/public/tools/bindings/generators/js_templates/module.js.tmpl', '../mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl', '../mojo/public/tools/bindings/generators/mojom_cpp_generator.py', '../mojo/public/tools/bindings/generators/mojom_js_generator.py', '../mojo/public/tools/bindings/pylib/mojom/generate/__init__.py', '../mojo/public/tools/bindings/pylib/mojom/generate/data.py', '../mojo/public/tools/bindings/pylib/mojom/generate/generator.py', '../mojo/public/tools/bindings/pylib/mojom/generate/module.py', '../mojo/public/tools/bindings/pylib/mojom/generate/pack.py', '../mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py', '../mojo/public/tools/bindings/pylib/mojom/parse/__init__.py', '../mojo/public/tools/bindings/pylib/mojom/parse/ast.py', '../mojo/public/tools/bindings/pylib/mojom/parse/lexer.py', '../mojo/public/tools/bindings/pylib/mojom/parse/parser.py', '../mojo/public/tools/bindings/pylib/mojom/parse/translate.py'], 'process_outputs_as_sources': '1', 'extension': 'mojom', 'outputs': ['$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.cc', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.h', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom.js', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom-internal.h'], 'variables': {'mojom_bindings_generator': '../mojo/public/tools/bindings/mojom_bindings_generator.py'}, 'rule_name': 'Generate C++ source files from mojom files', 'rule_sources': ['public/interfaces/shell/shell.mojom'], 'action': ['python', '../mojo/public/tools/bindings/mojom_bindings_generator.py', '%(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom', '-d', '..', '-o', '$(gyp_shared_intermediate_dir)/mojo/%(INPUT_DIRNAME)s'], 'message': 'Generating Mojo bindings from %(INPUT_DIRNAME)s/%(INPUT_ROOT)s.mojom'}": $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_local_path := $(LOCAL_PATH) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir)) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir)) $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH)) -$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: $(LOCAL_PATH)/mojo/public/interfaces/shell/shell.mojom $(LOCAL_PATH)/mojo/public/tools/bindings/mojom_bindings_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_cpp_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_js_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_lexer.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_parser.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/parse/mojo_translate.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_data.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/mojom_pack.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/generate/template_expander.py $(GYP_TARGET_DEPENDENCIES) +$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc: $(LOCAL_PATH)/mojo/public/interfaces/shell/shell.mojom $(LOCAL_PATH)/mojo/public/tools/bindings/mojom_bindings_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_builder_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_destructor.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_cpp_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/generators/mojom_js_generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/data.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/generator.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/module.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/pack.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/__init__.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/ast.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/lexer.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/parser.py $(LOCAL_PATH)/mojo/public/tools/bindings/pylib/mojom/parse/translate.py $(GYP_TARGET_DEPENDENCIES) mkdir -p $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell; cd $(gyp_local_path)/mojo; python ../mojo/public/tools/bindings/mojom_bindings_generator.py public/interfaces/shell/shell.mojom -d .. -o "$(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell" $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.h: $(gyp_shared_intermediate_dir)/mojo/public/interfaces/shell/shell.mojom.cc ; @@ -242,7 +242,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_system_impl.target.darwin-arm.mk b/mojo/mojo_system_impl.target.darwin-arm.mk index 5337403863..cea7e9507c 100644 --- a/mojo/mojo_system_impl.target.darwin-arm.mk +++ b/mojo/mojo_system_impl.target.darwin-arm.mk @@ -256,7 +256,6 @@ LOCAL_LDFLAGS_Debug := \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ -Wl,--icf=safe \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_system_impl.target.darwin-mips.mk b/mojo/mojo_system_impl.target.darwin-mips.mk index 6c230facd6..a1cb2a9d1e 100644 --- a/mojo/mojo_system_impl.target.darwin-mips.mk +++ b/mojo/mojo_system_impl.target.darwin-mips.mk @@ -252,7 +252,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_system_impl.target.darwin-x86.mk b/mojo/mojo_system_impl.target.darwin-x86.mk index 31241a66d4..c78af2fcbf 100644 --- a/mojo/mojo_system_impl.target.darwin-x86.mk +++ b/mojo/mojo_system_impl.target.darwin-x86.mk @@ -254,7 +254,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_system_impl.target.darwin-x86_64.mk b/mojo/mojo_system_impl.target.darwin-x86_64.mk index dd4dc4933c..a9bc33b168 100644 --- a/mojo/mojo_system_impl.target.darwin-x86_64.mk +++ b/mojo/mojo_system_impl.target.darwin-x86_64.mk @@ -254,7 +254,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_system_impl.target.linux-arm.mk b/mojo/mojo_system_impl.target.linux-arm.mk index 5337403863..cea7e9507c 100644 --- a/mojo/mojo_system_impl.target.linux-arm.mk +++ b/mojo/mojo_system_impl.target.linux-arm.mk @@ -256,7 +256,6 @@ LOCAL_LDFLAGS_Debug := \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ -Wl,--icf=safe \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_system_impl.target.linux-mips.mk b/mojo/mojo_system_impl.target.linux-mips.mk index 6c230facd6..a1cb2a9d1e 100644 --- a/mojo/mojo_system_impl.target.linux-mips.mk +++ b/mojo/mojo_system_impl.target.linux-mips.mk @@ -252,7 +252,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_system_impl.target.linux-x86.mk b/mojo/mojo_system_impl.target.linux-x86.mk index 31241a66d4..c78af2fcbf 100644 --- a/mojo/mojo_system_impl.target.linux-x86.mk +++ b/mojo/mojo_system_impl.target.linux-x86.mk @@ -254,7 +254,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/mojo_system_impl.target.linux-x86_64.mk b/mojo/mojo_system_impl.target.linux-x86_64.mk index dd4dc4933c..a9bc33b168 100644 --- a/mojo/mojo_system_impl.target.linux-x86_64.mk +++ b/mojo/mojo_system_impl.target.linux-x86_64.mk @@ -254,7 +254,6 @@ LOCAL_LDFLAGS_Debug := \ -nostdlib \ -Wl,--no-undefined \ -Wl,--exclude-libs=ALL \ - -Wl,--gc-sections \ -Wl,--warn-shared-textrel \ -Wl,-O1 \ -Wl,--as-needed diff --git a/mojo/public/README.md b/mojo/public/README.md index 32fc4b1861..a31a8a8245 100644 --- a/mojo/public/README.md +++ b/mojo/public/README.md @@ -1,62 +1,43 @@ Mojo Public API =============== -The Mojo Public API is a binary stable API to the Mojo system. There are -several components to the API: +The Mojo Public API is a binary stable API to the Mojo system. -Bindings --------- - -This directory contains a static library that clients may link into their -binary. The contents of this directory are not binary stable as each client is -free to use whichever version they prefer. +It consists of support for a number of programming languages (with a directory +for each support language), some "build" tools and build-time requirements, and +interface definitions for Mojo services (specified using an IDL). -This directory also contains a compiler that translates mojom interface -definition files into idiomatic bindings for various languages, including -C++ and JavaScript. Clients are expected to statically link with the generated -code, which reads and writes the binary stable IPC message format. +Note that there are various subdirectories named tests/. These contain tests of +the code in the enclosing directory, and are not meant for use by Mojo +applications. -Environment ------------ +C/CPP/JS +-------- -This directory contains a static library that clients may link into their -binary. The contents of this directory are not binary stable as each client is -free to use whichever version they prefer. +The c/, cpp/, js/ subdirectories define the API for C, C++, and JavaScript, +respectively. -The environment static library represents the shared state that is needed to -support the Bindings and GLES2 libraries. It depends on the Utility library. +The basic principle for these directories is that they consist of the source +files that one needs at build/deployment/run time (as appropriate for the +language), organized in a natural way for the particular language. -GLES2 ------ +Interfaces +---------- -The IPC protocol used to communicate between Mojo client and the GLES2 -service is not binary stable. To insulate themselves from changes in this -protocol, clients are expected to link dynamically against the standard GLES2 -headers from Khronos and the headers in this directory, which provide an -adaptor between the GLES2 C API and the underlying IPC protocol. +The interfaces/ subdirectory contains Mojo IDL (a.k.a. .mojom) descriptions of +standard Mojo services. -System ------- +Platform +-------- -This directory defines the interface between Mojo clients and the Mojo IPC -system. Although the Mojo IPC message format is binary stable, the mechanism -by which these messages are transported is not stable. To insulate themselves -from changes in the underlying transport, clients are expected to link against -these headers dynamically. +The platform/ subdirectory contains any build-time requirements (e.g., static +libraries) that may be needed to produce a Mojo application for certain +platforms, such as a native shared library or as a NaCl binary. -Tests +Tools ----- -This directory contains tests for code contained in the public API. Mojo -clients are expected to ignore this directory. - -Utility -------- - -This directory contains a static library that clients may link into their -binary. The contents of this directory are not binary stable as each client is -free to use whichever version they prefer. - -The Utility static library most notably defines an implementation of a RunLoop -based on the MojoWaitMany that clients may use as the basis for asynchronous -message processing. +The tools/ subdirectory contains tools that are useful/necessary at +build/deployment time. These tools may be needed (as a practical necessity) to +use the API in any given language, e.g., to generate bindings from Mojo IDL +files. diff --git a/mojo/public/c/README.md b/mojo/public/c/README.md new file mode 100644 index 0000000000..8e11545deb --- /dev/null +++ b/mojo/public/c/README.md @@ -0,0 +1,45 @@ +Mojo Public C API +================= + +This directory contains C language bindings for the Mojo Public API. + +Environment +----------- + +The environment/ subdirectory defines some common things that, while not part of +the system API, may be required for GLES2 (for example). These are things that a +Mojo application may be required to provide to the GLES2 (for example) library +in order to use it. (However, the Mojo application may implement these things as +it sees fit.) + +GLES2 +----- + +The gles2/ subdirectory defines the GLES2 C API that's available to Mojo +applications. To use GLES2, Mojo applications must link against a dynamic +library (the exact mechanism being platform-dependent) and use the header files +in this directory as well as the standard Khronos GLES2 header files. + +The reason for this, rather than providing GLES2 using the standard Mojo IPC +mechanism, is performance: The protocol (and transport mechanisms) used to +communicate with the Mojo GLES2 service is not stable nor "public" (mainly for +performance reasons), and using the dynamic library shields the application from +changes to the underlying system. + +System +------ + +The system/ subdirectory provides definitions of the basic low-level API used by +all Mojo applications (whether directly or indirectly). These consist primarily +of the IPC primitives used to communicate with Mojo services. + +Though the message protocol is stable, the implementation of the transport is +not, and access to the IPC mechanisms must be via the primitives defined in this +directory. + +Test Support +------------ + +This directory contains a C API for running tests. This API is only available +under special, specific test conditions. It is not meant for general use by Mojo +applications. diff --git a/mojo/public/c/system/async_waiter.h b/mojo/public/c/environment/async_waiter.h index ab999a3bd5..05689543b5 100644 --- a/mojo/public/c/system/async_waiter.h +++ b/mojo/public/c/environment/async_waiter.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef MOJO_PUBLIC_C_SYSTEM_ASYNC_WAITER_H_ -#define MOJO_PUBLIC_C_SYSTEM_ASYNC_WAITER_H_ +#ifndef MOJO_PUBLIC_C_ENVIRONMENT_ASYNC_WAITER_H_ +#define MOJO_PUBLIC_C_ENVIRONMENT_ASYNC_WAITER_H_ #include "mojo/public/c/system/core.h" @@ -37,4 +37,4 @@ struct MojoAsyncWaiter { } // extern "C" #endif -#endif // MOJO_PUBLIC_C_SYSTEM_ASYNC_WAITER_H_ +#endif // MOJO_PUBLIC_C_ENVIRONMENT_ASYNC_WAITER_H_ diff --git a/mojo/public/c/gles2/DEPS b/mojo/public/c/gles2/DEPS new file mode 100644 index 0000000000..3887457940 --- /dev/null +++ b/mojo/public/c/gles2/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+mojo/public/c/environment", +] diff --git a/mojo/public/c/gles2/gles2.h b/mojo/public/c/gles2/gles2.h index 6b20b9c596..3ee249d5aa 100644 --- a/mojo/public/c/gles2/gles2.h +++ b/mojo/public/c/gles2/gles2.h @@ -10,9 +10,9 @@ #include <stdint.h> #include <GLES2/gl2.h> +#include "mojo/public/c/environment/async_waiter.h" #include "mojo/public/c/gles2/gles2_export.h" #include "mojo/public/c/gles2/gles2_types.h" -#include "mojo/public/c/system/async_waiter.h" #include "mojo/public/c/system/core.h" #ifdef __cplusplus diff --git a/mojo/public/c/system/tests/core_unittest_pure_c.c b/mojo/public/c/system/tests/core_unittest_pure_c.c index 7293ff2d65..a95af50d17 100644 --- a/mojo/public/c/system/tests/core_unittest_pure_c.c +++ b/mojo/public/c/system/tests/core_unittest_pure_c.c @@ -11,8 +11,8 @@ // Include all the header files that are meant to be compilable as C. Start with // core.h, since it's the most important one. +#include "mojo/public/c/environment/async_waiter.h" #include "mojo/public/c/system/core.h" -#include "mojo/public/c/system/async_waiter.h" #include "mojo/public/c/system/macros.h" // The joys of the C preprocessor.... diff --git a/mojo/public/cpp/README.md b/mojo/public/cpp/README.md new file mode 100644 index 0000000000..8f03d984b9 --- /dev/null +++ b/mojo/public/cpp/README.md @@ -0,0 +1,71 @@ +Mojo Public C++ API +=================== + +This directory contains C++ language bindings for the Mojo Public API. + +A number of subdirectories provide wrappers for the lower-level C APIs (in +subdirectories of the same name, under mojo/public/c/). Typically, these +wrappers provide increased convenience and/or type-safety. + +Other subdirectories provide support (static) libraries of various sorts. In +this case, the organization is to have the public interface for the library in +defined in header files in the subdirectory itself and the implementation of the +library at a lower level, under a lib (sub)subdirectory. A developer should be +able to substitute their own implementation of any such support library, and +expect other support libraries, which may depend on that library, to work +properly. + +Bindings +-------- + +The bindings/ subdirectory contains a support (static) library needed by the +code generated by the bindings generator tool (in mojo/public/tools/bindings/), +which translates Mojo IDL (.mojom) files into idiomatic C++ (among other +languages). + +This library depends on the Environment library. + +Environment +----------- + +The environment/ subdirectory contains a support (static) library that +represents shared state needed to support the Bindings and GLES2 libraries. + +This library depends on the Utility library. + + +GLES2 +----- + +The gles2/ subdirectory contains C++ wrappers (and some additional helpers) of +the API defined in mojo/public/c/gles2/ (which provides access to GLES2). + +These wrappers depend on the Environment library. + +Shell +----- + +The shell/ subdirectory contains a support (static) library that aids in writing +Mojo applications and interacting with the Shell service. + +System +------ + +The system/ subdirectory contains C++ wrappers (and some additional helpers) of +the API defined in mojo/public/c/system/, which defines the basic, "core" API, +especially used to communicate with Mojo services. + +Test Support +------------ + +The test_support/ subdirectory contains C++ wrappers of the test-only API +defined in mojo/public/c/test_support/. It is not meant for general use by Mojo +applications. + +Utility +------- + +The utility/ subdirectory contains a support (static) library that provides +various basic functionality. Most notably, it provides an implementation of a +RunLoop based on MojoWaitMany() that applications may use as the basis for +asynchronous message processing. diff --git a/mojo/public/cpp/bindings/array.h b/mojo/public/cpp/bindings/array.h index 72aa56de58..f7ced01aa8 100644 --- a/mojo/public/cpp/bindings/array.h +++ b/mojo/public/cpp/bindings/array.h @@ -20,7 +20,9 @@ namespace mojo { template <typename T> class Array { public: - typedef internal::ArrayTraits<T, internal::TypeTraits<T>::kIsObject> Traits_; + typedef internal::ArrayTraits<T, + internal::TypeTraits<T>::kIsObject, + internal::TypeTraits<T>::kIsHandle> Traits_; typedef typename Traits_::DataType Data; typedef typename Traits_::ConstRef ConstRef; @@ -65,7 +67,7 @@ class Array { typedef typename Traits_::Ref Ref; explicit Builder(size_t num_elements, Buffer* buf = mojo::Buffer::current()) - : data_(Data::New(num_elements, buf)) { + : data_(Data::New(num_elements, buf, Traits_::GetDestructor())) { } size_t size() const { return data_->size(); } diff --git a/mojo/public/cpp/bindings/lib/array_internal.cc b/mojo/public/cpp/bindings/lib/array_internal.cc index efdda8c810..1852ff73ce 100644 --- a/mojo/public/cpp/bindings/lib/array_internal.cc +++ b/mojo/public/cpp/bindings/lib/array_internal.cc @@ -35,7 +35,25 @@ ArrayDataTraits<bool>::BitRef::operator bool() const { } // static -void ArraySerializationHelper<Handle>::EncodePointersAndHandles( +void ArraySerializationHelper<Handle, true>::ClearHandles( + const ArrayHeader* header, + ElementType* elements) { + for (uint32_t i = 0; i < header->num_elements; ++i) + elements[i].set_value(MOJO_HANDLE_INVALID); +} + +// static +void ArraySerializationHelper<Handle, true>::CloseHandles( + const ArrayHeader* header, + ElementType* elements) { + for (uint32_t i = 0; i < header->num_elements; ++i) { + if (elements[i].is_valid()) + CloseRaw(elements[i]); + } +} + +// static +void ArraySerializationHelper<Handle, true>::EncodePointersAndHandles( const ArrayHeader* header, ElementType* elements, std::vector<Handle>* handles) { @@ -44,7 +62,7 @@ void ArraySerializationHelper<Handle>::EncodePointersAndHandles( } // static -bool ArraySerializationHelper<Handle>::DecodePointersAndHandles( +bool ArraySerializationHelper<Handle, true>::DecodePointersAndHandles( const ArrayHeader* header, ElementType* elements, Message* message) { diff --git a/mojo/public/cpp/bindings/lib/array_internal.h b/mojo/public/cpp/bindings/lib/array_internal.h index 978dca36a4..4ecad35591 100644 --- a/mojo/public/cpp/bindings/lib/array_internal.h +++ b/mojo/public/cpp/bindings/lib/array_internal.h @@ -8,10 +8,10 @@ #include <new> #include "mojo/public/cpp/bindings/buffer.h" +#include "mojo/public/cpp/bindings/interface.h" #include "mojo/public/cpp/bindings/lib/bindings_internal.h" #include "mojo/public/cpp/bindings/lib/bindings_serialization.h" #include "mojo/public/cpp/bindings/passable.h" -#include "mojo/public/cpp/system/core.h" namespace mojo { template <typename T> class Array; @@ -97,9 +97,11 @@ struct ArrayDataTraits<bool> { // are two interesting cases: arrays of primitives and arrays of objects. // Arrays of objects are represented as arrays of pointers to objects. +template <typename T, bool kIsHandle> struct ArraySerializationHelper; + template <typename T> -struct ArraySerializationHelper { - typedef T ElementType; +struct ArraySerializationHelper<T, false> { + typedef typename ArrayDataTraits<T>::StorageType ElementType; static size_t ComputeSizeOfElements(const ArrayHeader* header, const ElementType* elements) { @@ -111,6 +113,13 @@ struct ArraySerializationHelper { Buffer* buf) { } + static void ClearHandles(const ArrayHeader* header, ElementType* elements) { + } + + static void CloseHandles(const ArrayHeader* header, + ElementType* elements) { + } + static void EncodePointersAndHandles(const ArrayHeader* header, ElementType* elements, std::vector<Handle>* handles) { @@ -124,8 +133,8 @@ struct ArraySerializationHelper { }; template <> -struct ArraySerializationHelper<Handle> { - typedef Handle ElementType; +struct ArraySerializationHelper<Handle, true> { + typedef ArrayDataTraits<Handle>::StorageType ElementType; static size_t ComputeSizeOfElements(const ArrayHeader* header, const ElementType* elements) { @@ -137,6 +146,10 @@ struct ArraySerializationHelper<Handle> { Buffer* buf) { } + static void ClearHandles(const ArrayHeader* header, ElementType* elements); + + static void CloseHandles(const ArrayHeader* header, ElementType* elements); + static void EncodePointersAndHandles(const ArrayHeader* header, ElementType* elements, std::vector<Handle>* handles); @@ -146,9 +159,46 @@ struct ArraySerializationHelper<Handle> { Message* message); }; +template <typename H> +struct ArraySerializationHelper<H, true> { + typedef typename ArrayDataTraits<H>::StorageType ElementType; + + static size_t ComputeSizeOfElements(const ArrayHeader* header, + const ElementType* elements) { + return 0; + } + + static void CloneElements(const ArrayHeader* header, + ElementType* elements, + Buffer* buf) { + } + + static void ClearHandles(const ArrayHeader* header, ElementType* elements) { + ArraySerializationHelper<Handle, true>::ClearHandles(header, elements); + } + + static void CloseHandles(const ArrayHeader* header, ElementType* elements) { + ArraySerializationHelper<Handle, true>::CloseHandles(header, elements); + } + + static void EncodePointersAndHandles(const ArrayHeader* header, + ElementType* elements, + std::vector<Handle>* handles) { + ArraySerializationHelper<Handle, true>::EncodePointersAndHandles( + header, elements, handles); + } + + static bool DecodePointersAndHandles(const ArrayHeader* header, + ElementType* elements, + Message* message) { + return ArraySerializationHelper<Handle, true>::DecodePointersAndHandles( + header, elements, message); + } +}; + template <typename P> -struct ArraySerializationHelper<P*> { - typedef StructPointer<P> ElementType; +struct ArraySerializationHelper<P*, false> { + typedef typename ArrayDataTraits<P*>::StorageType ElementType; static size_t ComputeSizeOfElements(const ArrayHeader* header, const ElementType* elements) { @@ -169,6 +219,17 @@ struct ArraySerializationHelper<P*> { } } + static void ClearHandles(const ArrayHeader* header, ElementType* elements) { + } + + static void CloseHandles(const ArrayHeader* header, + ElementType* elements) { + for (uint32_t i = 0; i < header->num_elements; ++i) { + if (elements[i].ptr) + elements[i].ptr->CloseHandles(); + } + } + static void EncodePointersAndHandles(const ArrayHeader* header, ElementType* elements, std::vector<Handle>* handles) { @@ -195,12 +256,18 @@ class Array_Data { typedef typename Traits::Wrapper Wrapper; typedef typename Traits::Ref Ref; typedef typename Traits::ConstRef ConstRef; + typedef ArraySerializationHelper<T, TypeTraits<T>::kIsHandle> Helper; - static Array_Data<T>* New(size_t num_elements, Buffer* buf) { + static Array_Data<T>* New(size_t num_elements, Buffer* buf, + Buffer::Destructor dtor = NULL) { size_t num_bytes = sizeof(Array_Data<T>) + Traits::GetStorageSize(num_elements); - return new (buf->Allocate(num_bytes)) Array_Data<T>(num_bytes, - num_elements); + return new (buf->Allocate(num_bytes, dtor)) Array_Data<T>(num_bytes, + num_elements); + } + + static void Destructor(void* address) { + static_cast<Array_Data*>(address)->CloseHandles(); } size_t size() const { return header_.num_elements; } @@ -227,33 +294,32 @@ class Array_Data { size_t ComputeSize() const { return Align(header_.num_bytes) + - ArraySerializationHelper<T>::ComputeSizeOfElements(&header_, storage()); + Helper::ComputeSizeOfElements(&header_, storage()); } - Array_Data<T>* Clone(Buffer* buf) const { + Array_Data<T>* Clone(Buffer* buf) { Array_Data<T>* clone = New(header_.num_elements, buf); memcpy(clone->storage(), storage(), header_.num_bytes - sizeof(Array_Data<T>)); + Helper::CloneElements(&clone->header_, clone->storage(), buf); - ArraySerializationHelper<T>::CloneElements(&clone->header_, - clone->storage(), buf); + // Zero-out handles in the original storage as they have been transferred + // to the clone. + Helper::ClearHandles(&header_, storage()); return clone; } void CloseHandles() { - // TODO(darin): Implement! + Helper::CloseHandles(&header_, storage()); } void EncodePointersAndHandles(std::vector<Handle>* handles) { - ArraySerializationHelper<T>::EncodePointersAndHandles(&header_, storage(), - handles); + Helper::EncodePointersAndHandles(&header_, storage(), handles); } bool DecodePointersAndHandles(Message* message) { - return ArraySerializationHelper<T>::DecodePointersAndHandles(&header_, - storage(), - message); + return Helper::DecodePointersAndHandles(&header_, storage(), message); } private: @@ -272,12 +338,16 @@ MOJO_COMPILE_ASSERT(sizeof(Array_Data<char>) == 8, bad_sizeof_Array_Data); // UTF-8 encoded typedef Array_Data<char> String_Data; -template <typename T, bool kIsObject> struct ArrayTraits {}; +template <typename T, bool kIsObject, bool kIsHandle> struct ArrayTraits {}; -template <typename T> struct ArrayTraits<T, true> { +// When T is an object type: +template <typename T> struct ArrayTraits<T, true, false> { typedef Array_Data<typename T::Data*> DataType; typedef const T& ConstRef; typedef T& Ref; + static Buffer::Destructor GetDestructor() { + return NULL; + } static typename T::Data* ToArrayElement(const T& value) { return Unwrap(value); } @@ -290,10 +360,14 @@ template <typename T> struct ArrayTraits<T, true> { } }; -template <typename T> struct ArrayTraits<T, false> { +// When T is a primitive (non-bool) type: +template <typename T> struct ArrayTraits<T, false, false> { typedef Array_Data<T> DataType; typedef const T& ConstRef; typedef T& Ref; + static Buffer::Destructor GetDestructor() { + return NULL; + } static T ToArrayElement(const T& value) { return value; } @@ -301,10 +375,14 @@ template <typename T> struct ArrayTraits<T, false> { static ConstRef ToConstRef(const T& data) { return data; } }; -template <> struct ArrayTraits<bool, false> { +// When T is a bool type: +template <> struct ArrayTraits<bool, false, false> { typedef Array_Data<bool> DataType; typedef bool ConstRef; typedef ArrayDataTraits<bool>::Ref Ref; + static Buffer::Destructor GetDestructor() { + return NULL; + } static bool ToArrayElement(const bool& value) { return value; } @@ -312,57 +390,20 @@ template <> struct ArrayTraits<bool, false> { static ConstRef ToConstRef(ConstRef data) { return data; } }; -template <> struct ArrayTraits<Handle, false> { - typedef Array_Data<Handle> DataType; - typedef Passable<Handle> ConstRef; - typedef AssignableAndPassable<Handle> Ref; - static Handle ToArrayElement(const Handle& value) { - return value; - } - static Ref ToRef(Handle& data) { return Ref(&data); } - static ConstRef ToConstRef(const Handle& data) { - return ConstRef(const_cast<Handle*>(&data)); - } -}; - -template <> struct ArrayTraits<DataPipeConsumerHandle, false> { - typedef Array_Data<DataPipeConsumerHandle> DataType; - typedef Passable<DataPipeConsumerHandle> ConstRef; - typedef AssignableAndPassable<DataPipeConsumerHandle> Ref; - static DataPipeConsumerHandle ToArrayElement( - const DataPipeConsumerHandle& value) { - return value; - } - static Ref ToRef(DataPipeConsumerHandle& data) { return Ref(&data); } - static ConstRef ToConstRef(const DataPipeConsumerHandle& data) { - return ConstRef(const_cast<DataPipeConsumerHandle*>(&data)); +// When T is a handle type: +template <typename H> struct ArrayTraits<H, false, true> { + typedef Array_Data<H> DataType; + typedef Passable<H> ConstRef; + typedef AssignableAndPassable<H> Ref; + static Buffer::Destructor GetDestructor() { + return &DataType::Destructor; } -}; - -template <> struct ArrayTraits<DataPipeProducerHandle, false> { - typedef Array_Data<DataPipeProducerHandle> DataType; - typedef Passable<DataPipeProducerHandle> ConstRef; - typedef AssignableAndPassable<DataPipeProducerHandle> Ref; - static DataPipeProducerHandle ToArrayElement( - const DataPipeProducerHandle& value) { - return value; - } - static Ref ToRef(DataPipeProducerHandle& data) { return Ref(&data); } - static ConstRef ToConstRef(const DataPipeProducerHandle& data) { - return ConstRef(const_cast<DataPipeProducerHandle*>(&data)); - } -}; - -template <> struct ArrayTraits<MessagePipeHandle, false> { - typedef Array_Data<MessagePipeHandle> DataType; - typedef Passable<MessagePipeHandle> ConstRef; - typedef AssignableAndPassable<MessagePipeHandle> Ref; - static MessagePipeHandle ToArrayElement(const MessagePipeHandle& value) { + static H ToArrayElement(const H& value) { return value; } - static Ref ToRef(MessagePipeHandle& data) { return Ref(&data); } - static ConstRef ToConstRef(const MessagePipeHandle& data) { - return ConstRef(const_cast<MessagePipeHandle*>(&data)); + static Ref ToRef(H& data) { return Ref(&data); } + static ConstRef ToConstRef(const H& data) { + return ConstRef(const_cast<H*>(&data)); } }; diff --git a/mojo/public/cpp/bindings/lib/bindings_internal.h b/mojo/public/cpp/bindings/lib/bindings_internal.h index ef6fc47dc8..4b847e71e3 100644 --- a/mojo/public/cpp/bindings/lib/bindings_internal.h +++ b/mojo/public/cpp/bindings/lib/bindings_internal.h @@ -8,6 +8,8 @@ #include "mojo/public/cpp/system/core.h" namespace mojo { +template <typename S> class InterfaceHandle; + namespace internal { template <typename T> class Array_Data; @@ -82,54 +84,75 @@ inline typename T::Data* Unwrap(const T& object) { } template <typename T> struct TypeTraits { + static const bool kIsHandle = false; static const bool kIsObject = true; }; template <> struct TypeTraits<bool> { + static const bool kIsHandle = false; static const bool kIsObject = false; }; template <> struct TypeTraits<char> { + static const bool kIsHandle = false; static const bool kIsObject = false; }; template <> struct TypeTraits<int8_t> { + static const bool kIsHandle = false; static const bool kIsObject = false; }; template <> struct TypeTraits<int16_t> { + static const bool kIsHandle = false; static const bool kIsObject = false; }; template <> struct TypeTraits<int32_t> { + static const bool kIsHandle = false; static const bool kIsObject = false; }; template <> struct TypeTraits<int64_t> { + static const bool kIsHandle = false; static const bool kIsObject = false; }; template <> struct TypeTraits<uint8_t> { + static const bool kIsHandle = false; static const bool kIsObject = false; }; template <> struct TypeTraits<uint16_t> { + static const bool kIsHandle = false; static const bool kIsObject = false; }; template <> struct TypeTraits<uint32_t> { + static const bool kIsHandle = false; static const bool kIsObject = false; }; template <> struct TypeTraits<uint64_t> { + static const bool kIsHandle = false; static const bool kIsObject = false; }; template <> struct TypeTraits<float> { + static const bool kIsHandle = false; static const bool kIsObject = false; }; template <> struct TypeTraits<double> { + static const bool kIsHandle = false; static const bool kIsObject = false; }; template <> struct TypeTraits<Handle> { + static const bool kIsHandle = true; static const bool kIsObject = false; }; template <> struct TypeTraits<DataPipeConsumerHandle> { + static const bool kIsHandle = true; static const bool kIsObject = false; }; template <> struct TypeTraits<DataPipeProducerHandle> { + static const bool kIsHandle = true; static const bool kIsObject = false; }; template <> struct TypeTraits<MessagePipeHandle> { + static const bool kIsHandle = true; + static const bool kIsObject = false; +}; +template <typename S> struct TypeTraits<InterfaceHandle<S> > { + static const bool kIsHandle = true; static const bool kIsObject = false; }; diff --git a/mojo/public/cpp/bindings/lib/bindings_serialization.cc b/mojo/public/cpp/bindings/lib/bindings_serialization.cc index ff06d95f83..fc574d77e7 100644 --- a/mojo/public/cpp/bindings/lib/bindings_serialization.cc +++ b/mojo/public/cpp/bindings/lib/bindings_serialization.cc @@ -37,7 +37,7 @@ const void* DecodePointerRaw(const uint64_t* offset) { bool ValidatePointer(const void* ptr, const Message& message) { const uint8_t* data = static_cast<const uint8_t*>(ptr); - if (reinterpret_cast<ptrdiff_t>(data) % 8 != 0) + if (reinterpret_cast<uintptr_t>(data) % 8 != 0) return false; const uint8_t* data_start = message.data(); diff --git a/mojo/public/cpp/bindings/lib/shared_data.h b/mojo/public/cpp/bindings/lib/shared_data.h index e396b0d795..bba4710910 100644 --- a/mojo/public/cpp/bindings/lib/shared_data.h +++ b/mojo/public/cpp/bindings/lib/shared_data.h @@ -32,6 +32,7 @@ class SharedData { holder_->Release(); holder_ = other.holder_; holder_->Retain(); + return *this; } void reset() { diff --git a/mojo/public/cpp/bindings/tests/array_unittest.cc b/mojo/public/cpp/bindings/tests/array_unittest.cc index 72033eab29..dccd7167e9 100644 --- a/mojo/public/cpp/bindings/tests/array_unittest.cc +++ b/mojo/public/cpp/bindings/tests/array_unittest.cc @@ -4,9 +4,11 @@ #include "mojo/public/cpp/bindings/allocation_scope.h" #include "mojo/public/cpp/bindings/array.h" +#include "mojo/public/cpp/bindings/interface.h" #include "mojo/public/cpp/bindings/lib/fixed_buffer.h" #include "mojo/public/cpp/bindings/lib/scratch_buffer.h" #include "mojo/public/cpp/environment/environment.h" +#include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h" #include "testing/gtest/include/gtest/gtest.h" namespace mojo { @@ -84,6 +86,86 @@ TEST(ArrayTest, Handle) { EXPECT_FALSE(handles[0].is_valid()); } +// Tests that Array<Handle> supports closing handles. +TEST(ArrayTest, HandlesAreClosed) { + Environment env; + + ScopedMessagePipeHandle msg_pipe0, msg_pipe1; + CreateMessagePipe(&msg_pipe0, &msg_pipe1); + + ScopedHandle pipe0 = ScopedHandle::From(msg_pipe0.Pass()); + ScopedHandle pipe1 = ScopedHandle::From(msg_pipe1.Pass()); + + MojoHandle pipe0_value = pipe0.get().value(); + MojoHandle pipe1_value = pipe1.get().value(); + + { + AllocationScope scope; + + Array<Handle>::Builder handles_builder(2); + handles_builder[0] = pipe0.Pass(); + handles_builder[1].reset(pipe1.release()); + + MOJO_ALLOW_UNUSED Array<Handle> handles = + handles_builder.Finish(); + } + + // We expect the pipes to have been closed. + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe0_value)); + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe1_value)); +} + +// Tests that Array<MessagePipeHandle> supports closing handles. +TEST(ArrayTest, MessagePipeHandlesAreClosed) { + Environment env; + + ScopedMessagePipeHandle pipe0, pipe1; + CreateMessagePipe(&pipe0, &pipe1); + + MojoHandle pipe0_value = pipe0.get().value(); + MojoHandle pipe1_value = pipe1.get().value(); + + { + AllocationScope scope; + + Array<MessagePipeHandle>::Builder handles_builder(2); + handles_builder[0] = pipe0.Pass(); + handles_builder[1].reset(pipe1.release()); + + MOJO_ALLOW_UNUSED Array<MessagePipeHandle> handles = + handles_builder.Finish(); + } + + // We expect the pipes to have been closed. + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe0_value)); + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe1_value)); +} + +// Tests that Array<InterfaceHandle<S>> supports closing handles. +TEST(ArrayTest, InterfaceHandlesAreClosed) { + Environment env; + + InterfacePipe<sample::Port, sample::Port> pipe; + + MojoHandle pipe0_value = pipe.handle_to_self.get().value(); + MojoHandle pipe1_value = pipe.handle_to_peer.get().value(); + + { + AllocationScope scope; + + Array<sample::PortHandle>::Builder handles_builder(2); + handles_builder[0] = pipe.handle_to_self.Pass(); + handles_builder[1].reset(pipe.handle_to_peer.release()); + + MOJO_ALLOW_UNUSED Array<sample::PortHandle> handles = + handles_builder.Finish(); + } + + // We expect the pipes to have been closed. + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe0_value)); + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe1_value)); +} + } // namespace } // namespace test } // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc b/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc index 23d8798462..7df6db6e02 100644 --- a/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc +++ b/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc @@ -231,6 +231,39 @@ TEST_F(HandlePassingTest, DataPipe) { EXPECT_TRUE(factory_client.got_response()); } +TEST_F(HandlePassingTest, PipesAreClosed) { + InterfacePipe<sample::Factory> pipe; + RemotePtr<sample::Factory> factory(pipe.handle_to_self.Pass(), NULL); + + MessagePipe extra_pipe; + + MojoHandle handle0_value = extra_pipe.handle0.get().value(); + MojoHandle handle1_value = extra_pipe.handle1.get().value(); + + { + AllocationScope scope; + + Array<MessagePipeHandle>::Builder pipes(2); + pipes[0] = extra_pipe.handle0.Pass(); + pipes[1] = extra_pipe.handle1.Pass(); + + sample::Request::Builder request_builder; + request_builder.set_more_pipes(pipes.Finish()); + + sample::Request request = request_builder.Finish(); + + factory->DoStuff(request, ScopedMessagePipeHandle()); + + // The handles should have been transferred to the underlying Message. + EXPECT_EQ(MOJO_HANDLE_INVALID, request.more_pipes()[0].get().value()); + EXPECT_EQ(MOJO_HANDLE_INVALID, request.more_pipes()[1].get().value()); + } + + // We expect the pipes to have been closed. + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(handle0_value)); + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(handle1_value)); +} + } // namespace } // namespace test } // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/request_response_unittest.cc b/mojo/public/cpp/bindings/tests/request_response_unittest.cc index 9ca7cd4e89..94ed91ff87 100644 --- a/mojo/public/cpp/bindings/tests/request_response_unittest.cc +++ b/mojo/public/cpp/bindings/tests/request_response_unittest.cc @@ -25,7 +25,10 @@ class ProviderImpl : public sample::Provider { const String& a, const Callback<void(String)>& callback) MOJO_OVERRIDE { AllocationScope scope; - callback.Run(a); + Callback<void(String)> callback_copy; + // Make sure operator= is used. + callback_copy = callback; + callback_copy.Run(a); } virtual void EchoStrings( @@ -43,6 +46,12 @@ class ProviderImpl : public sample::Provider { callback.Run(a.Pass()); } + virtual void EchoEnum(sample::Enum a, + const Callback<void(sample::Enum)>& callback) + MOJO_OVERRIDE { + callback.Run(a); + } + private: RemotePtr<sample::ProviderClient> client_; }; @@ -61,6 +70,17 @@ class StringRecorder { std::string* buf_; }; +class EnumRecorder { + public: + EnumRecorder(sample::Enum* value) : value_(value) { + } + void Run(sample::Enum a) const { + *value_ = a; + } + private: + sample::Enum* value_; +}; + class MessagePipeWriter { public: explicit MessagePipeWriter(const char* text) : text_(text) { @@ -135,6 +155,22 @@ TEST_F(RequestResponseTest, EchoMessagePipeHandle) { EXPECT_EQ(std::string("hello"), value); } +TEST_F(RequestResponseTest, EchoEnum) { + InterfacePipe<sample::Provider> pipe; + ProviderImpl provider_impl(pipe.handle_to_peer.Pass()); + RemotePtr<sample::Provider> provider(pipe.handle_to_self.Pass(), NULL); + + sample::Enum value; + { + AllocationScope scope; + provider->EchoEnum(sample::ENUM_VALUE, EnumRecorder(&value)); + } + + PumpMessages(); + + EXPECT_EQ(sample::ENUM_VALUE, value); +} + } // namespace } // namespace test } // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/sample_service_unittest.cc b/mojo/public/cpp/bindings/tests/sample_service_unittest.cc index 75d0d9b3e2..05eca4486c 100644 --- a/mojo/public/cpp/bindings/tests/sample_service_unittest.cc +++ b/mojo/public/cpp/bindings/tests/sample_service_unittest.cc @@ -75,6 +75,15 @@ Foo MakeFoo() { output_streams[i] = producer.Pass(); } + mojo::Array<mojo::Array<bool> >::Builder array_of_array_of_bools(2); + for (size_t i = 0; i < 2; ++i) { + mojo::Array<bool>::Builder array_of_bools(2); + for (size_t j = 0; j < 2; ++j) { + array_of_bools[j] = j; + } + array_of_array_of_bools[i] = array_of_bools.Finish(); + } + mojo::ScopedMessagePipeHandle pipe0, pipe1; mojo::CreateMessagePipe(&pipe0, &pipe1); @@ -91,6 +100,7 @@ Foo MakeFoo() { foo.set_source(pipe1.Pass()); foo.set_input_streams(input_streams.Finish()); foo.set_output_streams(output_streams.Finish()); + foo.set_array_of_array_of_bools(array_of_array_of_bools.Finish()); return foo.Finish(); } @@ -138,6 +148,14 @@ void CheckFoo(const Foo& foo) { EXPECT_FALSE(foo.output_streams().is_null()); EXPECT_EQ(2u, foo.output_streams().size()); + + EXPECT_EQ(2u, foo.array_of_array_of_bools().size()); + for (size_t i = 0; i < foo.array_of_array_of_bools().size(); ++i) { + EXPECT_EQ(2u, foo.array_of_array_of_bools()[i].size()); + for (size_t j = 0; j < foo.array_of_array_of_bools()[i].size(); ++j) { + EXPECT_EQ(bool(j), foo.array_of_array_of_bools()[i][j]); + } + } } void PrintSpacer(int depth) { @@ -222,6 +240,7 @@ void Print(int depth, const char* name, const Foo& foo) { Print(depth, "source", foo.source().get()); Print(depth, "input_streams", foo.input_streams()); Print(depth, "output_streams", foo.output_streams()); + Print(depth, "array_of_array_of_bools", foo.array_of_array_of_bools()); --depth; } } diff --git a/mojo/public/cpp/environment/DEPS b/mojo/public/cpp/environment/DEPS new file mode 100644 index 0000000000..3887457940 --- /dev/null +++ b/mojo/public/cpp/environment/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+mojo/public/c/environment", +] diff --git a/mojo/public/cpp/environment/default_async_waiter.h b/mojo/public/cpp/environment/default_async_waiter.h index d7f48bf529..6edfaaa0cf 100644 --- a/mojo/public/cpp/environment/default_async_waiter.h +++ b/mojo/public/cpp/environment/default_async_waiter.h @@ -5,7 +5,7 @@ #ifndef MOJO_PUBLIC_CPP_ENVIRONMENT_DEFAULT_ASYNC_WAITER_H_ #define MOJO_PUBLIC_CPP_ENVIRONMENT_DEFAULT_ASYNC_WAITER_H_ -#include "mojo/public/c/system/async_waiter.h" +#include "mojo/public/c/environment/async_waiter.h" namespace mojo { diff --git a/mojo/public/cpp/shell/application.h b/mojo/public/cpp/shell/application.h index 9a2ea67cba..ffca7fe682 100644 --- a/mojo/public/cpp/shell/application.h +++ b/mojo/public/cpp/shell/application.h @@ -14,18 +14,18 @@ namespace mojo { -class Application : public internal::ServiceFactoryBase::Owner { +class Application : public internal::ServiceConnectorBase::Owner { public: explicit Application(ScopedShellHandle shell_handle); explicit Application(MojoHandle shell_handle); virtual ~Application(); - // internal::ServiceFactoryBase::Owner methods. - // Takes ownership of |service_factory|. - virtual void AddServiceFactory(internal::ServiceFactoryBase* service_factory) - MOJO_OVERRIDE; - virtual void RemoveServiceFactory( - internal::ServiceFactoryBase* service_factory) MOJO_OVERRIDE; + // internal::ServiceConnectorBase::Owner methods. + // Takes ownership of |service_connector|. + virtual void AddServiceConnector( + internal::ServiceConnectorBase* service_connector) MOJO_OVERRIDE; + virtual void RemoveServiceConnector( + internal::ServiceConnectorBase* service_connector) MOJO_OVERRIDE; protected: // ShellClient methods. @@ -34,8 +34,8 @@ class Application : public internal::ServiceFactoryBase::Owner { MOJO_OVERRIDE; private: - typedef std::vector<internal::ServiceFactoryBase*> ServiceFactoryList; - ServiceFactoryList service_factories_; + typedef std::vector<internal::ServiceConnectorBase*> ServiceConnectorList; + ServiceConnectorList service_connectors_; }; } // namespace mojo diff --git a/mojo/public/cpp/shell/lib/application.cc b/mojo/public/cpp/shell/lib/application.cc index 4d0b06f63f..3224202873 100644 --- a/mojo/public/cpp/shell/lib/application.cc +++ b/mojo/public/cpp/shell/lib/application.cc @@ -7,48 +7,48 @@ namespace mojo { Application::Application(ScopedShellHandle shell_handle) - : internal::ServiceFactoryBase::Owner(shell_handle.Pass()) { + : internal::ServiceConnectorBase::Owner(shell_handle.Pass()) { } Application::Application(MojoHandle shell_handle) - : internal::ServiceFactoryBase::Owner( + : internal::ServiceConnectorBase::Owner( mojo::MakeScopedHandle(ShellHandle(shell_handle)).Pass()) {} Application::~Application() { - for (ServiceFactoryList::iterator it = service_factories_.begin(); - it != service_factories_.end(); ++it) { + for (ServiceConnectorList::iterator it = service_connectors_.begin(); + it != service_connectors_.end(); ++it) { delete *it; } } -void Application::AddServiceFactory( - internal::ServiceFactoryBase* service_factory) { - service_factories_.push_back(service_factory); - set_service_factory_owner(service_factory, this); +void Application::AddServiceConnector( + internal::ServiceConnectorBase* service_connector) { + service_connectors_.push_back(service_connector); + set_service_connector_owner(service_connector, this); } -void Application::RemoveServiceFactory( - internal::ServiceFactoryBase* service_factory) { - for (ServiceFactoryList::iterator it = service_factories_.begin(); - it != service_factories_.end(); ++it) { - if (*it == service_factory) { - service_factories_.erase(it); - delete service_factory; +void Application::RemoveServiceConnector( + internal::ServiceConnectorBase* service_connector) { + for (ServiceConnectorList::iterator it = service_connectors_.begin(); + it != service_connectors_.end(); ++it) { + if (*it == service_connector) { + service_connectors_.erase(it); + delete service_connector; break; } } - if (service_factories_.empty()) + if (service_connectors_.empty()) shell_.reset(); } void Application::AcceptConnection(const mojo::String& url, ScopedMessagePipeHandle client_handle) { // TODO(davemoore): This method must be overridden by an Application subclass - // to dispatch to the right ServiceFactory. We need to figure out an approach - // to registration to make this better. - assert(1 == service_factories_.size()); - return service_factories_.front()->AcceptConnection(url.To<std::string>(), - client_handle.Pass()); + // to dispatch to the right ServiceConnector. We need to figure out an + // approach to registration to make this better. + assert(1 == service_connectors_.size()); + return service_connectors_.front()->AcceptConnection(url.To<std::string>(), + client_handle.Pass()); } } // namespace mojo diff --git a/mojo/public/cpp/shell/lib/service.cc b/mojo/public/cpp/shell/lib/service.cc index 391a57612c..e408481a35 100644 --- a/mojo/public/cpp/shell/lib/service.cc +++ b/mojo/public/cpp/shell/lib/service.cc @@ -7,13 +7,13 @@ namespace mojo { namespace internal { -ServiceFactoryBase::Owner::Owner(ScopedShellHandle shell_handle) +ServiceConnectorBase::Owner::Owner(ScopedShellHandle shell_handle) : shell_(shell_handle.Pass(), this) { } -ServiceFactoryBase::Owner::~Owner() {} +ServiceConnectorBase::Owner::~Owner() {} -ServiceFactoryBase::~ServiceFactoryBase() {} +ServiceConnectorBase::~ServiceConnectorBase() {} } // namespace internal } // namespace mojo diff --git a/mojo/public/cpp/shell/service.h b/mojo/public/cpp/shell/service.h index 55b4aaea2f..7dd08ffa70 100644 --- a/mojo/public/cpp/shell/service.h +++ b/mojo/public/cpp/shell/service.h @@ -19,41 +19,42 @@ // class FooImpl : public Foo { // public: // FooImpl(); -// void Initialize(ServiceFactory<FooImpl>* service_factory, +// void Initialize(ServiceConnector<FooImpl>* service_connector, // ScopedMessagePipeHandle client_handle // private: -// ServiceFactory<FooImpl>* service_factory_; +// ServiceConnector<FooImpl>* service_connector_; // RemotePtr<FooPeer> client_; // }; // // -// To simplify further FooImpl can use the Service<> template. -// class FooImpl : public Service<Foo, FooImpl> { +// To simplify further FooImpl can use the ServiceConnection<> template. +// class FooImpl : public ServiceConnection<Foo, FooImpl> { // public: // FooImpl(); // ... // <Foo implementation> // }; // -// Instances of FooImpl will be created by a specialized ServiceFactory +// Instances of FooImpl will be created by a specialized ServiceConnector // -// ServiceFactory<FooImpl> +// ServiceConnector<FooImpl> // // Optionally the classes can be specializeed with a shared context -// class ServiceFactory<FooImpl, MyContext> +// class ServiceConnector<FooImpl, MyContext> // and -// class FooImpl : public Service<Foo, FooImpl, MyContext> +// class FooImpl : public ServiceConnection<Foo, FooImpl, MyContext> // -// foo_factory = new ServiceFactory<FooImpl, MyContext>(my_context); +// foo_connector = new ServiceConnector<FooImpl, MyContext>(my_context); // instances of FooImpl can call context() and retrieve the value of my_context. // -// Lastly create an Application instance that collects all the ServiceFactories. +// Lastly create an Application instance that collects all the +// ServiceConnectors. // // Application app(shell_handle); -// app.AddServiceFactory(new ServiceFactory<FooImpl>); +// app.AddServiceConnector(new ServiceConnector<FooImpl>); // // -// Specialization of ServiceFactory. +// Specialization of ServiceConnector. // ServiceImpl: Implementation of Service interface. // Context: Optional type of shared context.v // @@ -61,27 +62,27 @@ namespace mojo { namespace internal { -class ServiceFactoryBase { +class ServiceConnectorBase { public: class Owner : public ShellClient { public: Owner(ScopedShellHandle shell_handle); ~Owner(); Shell* shell() { return shell_.get(); } - virtual void AddServiceFactory( - internal::ServiceFactoryBase* service_factory) = 0; - virtual void RemoveServiceFactory( - internal::ServiceFactoryBase* service_factory) = 0; + virtual void AddServiceConnector( + internal::ServiceConnectorBase* service_connector) = 0; + virtual void RemoveServiceConnector( + internal::ServiceConnectorBase* service_connector) = 0; protected: - void set_service_factory_owner(ServiceFactoryBase* service_factory, - Owner* owner) { - service_factory->owner_ = owner; + void set_service_connector_owner(ServiceConnectorBase* service_connector, + Owner* owner) { + service_connector->owner_ = owner; } RemotePtr<Shell> shell_; }; - ServiceFactoryBase() : owner_(NULL) {} - virtual ~ServiceFactoryBase(); + ServiceConnectorBase() : owner_(NULL) {} + virtual ~ServiceConnectorBase(); Shell* shell() { return owner_->shell(); } virtual void AcceptConnection(const std::string& url, ScopedMessagePipeHandle client_handle) = 0; @@ -92,11 +93,11 @@ class ServiceFactoryBase { } // namespace internal template <class ServiceImpl, typename Context=void> -class ServiceFactory : public internal::ServiceFactoryBase { +class ServiceConnector : public internal::ServiceConnectorBase { public: - ServiceFactory(Context* context = NULL) : context_(context) {} + ServiceConnector(Context* context = NULL) : context_(context) {} - virtual ~ServiceFactory() { + virtual ~ServiceConnector() { for (typename ServiceList::iterator it = services_.begin(); it != services_.end(); ++it) { delete *it; @@ -118,7 +119,7 @@ class ServiceFactory : public internal::ServiceFactoryBase { services_.erase(it); delete service; if (services_.empty()) - owner_->RemoveServiceFactory(this); + owner_->RemoveServiceConnector(this); return; } } @@ -132,21 +133,21 @@ class ServiceFactory : public internal::ServiceFactoryBase { Context* context_; }; -// Specialization of ServiceFactory. +// Specialization of ServiceConnection. // ServiceInterface: Service interface. // ServiceImpl: Implementation of Service interface. // Context: Optional type of shared context. template <class ServiceInterface, class ServiceImpl, typename Context=void> -class Service : public ServiceInterface { +class ServiceConnection : public ServiceInterface { public: - virtual ~Service() {} + virtual ~ServiceConnection() {} protected: - Service() : reaper_(this), service_factory_(NULL) {} + ServiceConnection() : reaper_(this), service_connector_(NULL) {} - void Initialize(ServiceFactory<ServiceImpl, Context>* service_factory, + void Initialize(ServiceConnector<ServiceImpl, Context>* service_connector, ScopedMessagePipeHandle client_handle) { - service_factory_ = service_factory; + service_connector_ = service_connector; client_.reset( MakeScopedHandle( InterfaceHandle<typename ServiceInterface::_Peer>( @@ -155,27 +156,27 @@ class Service : public ServiceInterface { &reaper_); } - Shell* shell() { return service_factory_->shell(); } - Context* context() const { return service_factory_->context(); } + Shell* shell() { return service_connector_->shell(); } + Context* context() const { return service_connector_->context(); } typename ServiceInterface::_Peer* client() { return client_.get(); } private: // The Reaper class allows us to handle errors on the client proxy without - // polluting the name space of the Service<> class. + // polluting the name space of the ServiceConnection<> class. class Reaper : public ErrorHandler { public: - Reaper(Service<ServiceInterface, ServiceImpl, Context>* service) + Reaper(ServiceConnection<ServiceInterface, ServiceImpl, Context>* service) : service_(service) {} virtual void OnError() { - service_->service_factory_->RemoveService( + service_->service_connector_->RemoveService( static_cast<ServiceImpl*>(service_)); } private: - Service<ServiceInterface, ServiceImpl, Context>* service_; + ServiceConnection<ServiceInterface, ServiceImpl, Context>* service_; }; - friend class ServiceFactory<ServiceImpl, Context>; + friend class ServiceConnector<ServiceImpl, Context>; Reaper reaper_; - ServiceFactory<ServiceImpl, Context>* service_factory_; + ServiceConnector<ServiceImpl, Context>* service_connector_; RemotePtr<typename ServiceInterface::_Peer> client_; }; diff --git a/mojo/public/gles2/gles2_private.h b/mojo/public/gles2/gles2_private.h index 591e043592..c92f555ea8 100644 --- a/mojo/public/gles2/gles2_private.h +++ b/mojo/public/gles2/gles2_private.h @@ -7,9 +7,9 @@ #include <stdint.h> +#include "mojo/public/c/environment/async_waiter.h" #include "mojo/public/c/gles2/gles2_export.h" #include "mojo/public/c/gles2/gles2_types.h" -#include "mojo/public/c/system/async_waiter.h" #include "mojo/public/cpp/system/core.h" namespace mojo { diff --git a/mojo/public/interfaces/bindings/tests/sample_factory.mojom b/mojo/public/interfaces/bindings/tests/sample_factory.mojom index 15b771a100..00ab1ef076 100644 --- a/mojo/public/interfaces/bindings/tests/sample_factory.mojom +++ b/mojo/public/interfaces/bindings/tests/sample_factory.mojom @@ -10,6 +10,7 @@ module sample { struct Request { int32 x; handle<message_pipe> pipe; + handle<message_pipe>[] more_pipes; }; struct Response { diff --git a/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom b/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom index 50e2c60df7..7c20b30473 100644 --- a/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom +++ b/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom @@ -4,11 +4,16 @@ module sample { +enum Enum { + ENUM_VALUE +}; + [Peer=ProviderClient] interface Provider { EchoString(string a) => (string a); EchoStrings(string a, string b) => (string a, string b); EchoMessagePipeHandle(handle<message_pipe> a) => (handle<message_pipe> a); + EchoEnum(Enum a) => (Enum a); }; [Peer=Provider] diff --git a/mojo/public/interfaces/bindings/tests/sample_service.mojom b/mojo/public/interfaces/bindings/tests/sample_service.mojom index e9cdbd4fb8..04893a4952 100644 --- a/mojo/public/interfaces/bindings/tests/sample_service.mojom +++ b/mojo/public/interfaces/bindings/tests/sample_service.mojom @@ -34,6 +34,7 @@ struct Foo { handle<message_pipe> source @9; handle<data_pipe_consumer>[] input_streams @10; handle<data_pipe_producer>[] output_streams @11; + bool[][] array_of_array_of_bools @12; }; struct DefaultsTestInner { @@ -51,10 +52,6 @@ struct DefaultsTest { Bar.Type bar_type = Bar.TYPE_BOTH; }; -interface Port { - PostMessage@0(string message_text @0); -}; - [Peer=ServiceClient] interface Service { enum BazOptions { @@ -69,4 +66,10 @@ interface ServiceClient { DidFrobinate@0(int32 result @0); }; +// This interface is referenced above where it is defined. It also refers to +// itself from a method. +interface Port { + PostMessage@0(string message_text @0, Port[] extra_ports@1); +}; + } diff --git a/mojo/public/java/src/org/chromium/mojo/system/Core.java b/mojo/public/java/src/org/chromium/mojo/system/Core.java new file mode 100644 index 0000000000..8d084b32be --- /dev/null +++ b/mojo/public/java/src/org/chromium/mojo/system/Core.java @@ -0,0 +1,178 @@ +// 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. + +package org.chromium.mojo.system; + +import java.util.List; + +/** + * Core mojo interface giving access to the base operations. See |src/mojo/public/c/system/core.h| + * for the underlying api. + */ +public interface Core { + + /** + * Used to indicate an infinite deadline (timeout). + */ + public static final long DEADLINE_INFINITE = -1; + + /** + * Flags for the wait operations on handles. + */ + public static class WaitFlags extends Flags<WaitFlags> { + /** + * Constructor. + * + * @param flags the serialized flags. + */ + private WaitFlags(int flags) { + super(flags); + } + + private static final int FLAG_NONE = 0; + private static final int FLAG_READABLE = 1 << 0; + private static final int FLAG_WRITABLE = 1 << 1; + private static final int FLAG_ALL = ~0; + + /** + * Change the readable bit of this flag. + * + * @param readable the new value of the readable bit. + * @return this. + */ + public WaitFlags setReadable(boolean readable) { + return setFlag(FLAG_READABLE, readable); + } + + /** + * Change the writable bit of this flag. + * + * @param writable the new value of the writable bit. + * @return this. + */ + public WaitFlags setWritable(boolean writable) { + return setFlag(FLAG_WRITABLE, writable); + } + + /** + * @return a flag with no bit set. + */ + public static WaitFlags none() { + return new WaitFlags(FLAG_NONE); + } + + /** + * @return a flag with all bits set. + */ + public static WaitFlags all() { + return new WaitFlags(FLAG_ALL); + } + } + + /** + * @return a platform-dependent monotonically increasing tick count representing "right now." + */ + public long getTimeTicksNow(); + + /** + * Waits on the given |handle| until the state indicated by |flags| is satisfied or until + * |deadline| has passed. + * + * @return |MojoResult.OK| if some flag in |flags| was satisfied (or is already satisfied). + * <p> + * |MojoResult.DEADLINE_EXCEEDED| if the deadline has passed without any of the flags + * begin satisfied. + * <p> + * |MojoResult.CANCELLED| if |handle| is closed concurrently by another thread. + * <p> + * |MojoResult.FAILED_PRECONDITION| if it is or becomes impossible that any flag in + * |flags| will ever be satisfied (for example, if the other endpoint is close). + */ + public int wait(Handle handle, WaitFlags flags, long deadline); + + /** + * Result for the |waitMany| method. + */ + public static class WaitManyResult { + + /** + * See |wait| for the different possible values. + */ + private int mMojoResult; + /** + * If |mojoResult| is |MojoResult.OK|, |handleIndex| is the index of the handle for which + * some flag was satisfied (or is already satisfied). If |mojoResult| is + * |MojoResult.CANCELLED| or |MojoResult.FAILED_PRECONDITION|, |handleIndex| is the index of + * the handle for which the issue occurred. + */ + private int mHandleIndex; + + /** + * @return the mojoResult + */ + public int getMojoResult() { + return mMojoResult; + } + + /** + * @param mojoResult the mojoResult to set + */ + public void setMojoResult(int mojoResult) { + mMojoResult = mojoResult; + } + + /** + * @return the handleIndex + */ + public int getHandleIndex() { + return mHandleIndex; + } + + /** + * @param handleIndex the handleIndex to set + */ + public void setHandleIndex(int handleIndex) { + mHandleIndex = handleIndex; + } + } + + /** + * Waits on handle in |handles| for at least one of them to satisfy the associated |WaitFlags|, + * or until |deadline| has passed. + * + * @returns a |WaitManyResult|. + */ + public WaitManyResult waitMany(List<Pair<Handle, WaitFlags>> handles, long deadline); + + /** + * Creates a message pipe, which is a bidirectional communication channel for framed data (i.e., + * messages). Messages can contain plain data and/or Mojo handles. + * + * @return the set of handles for the two endpoints (ports) of the message pipe. + */ + public Pair<MessagePipeHandle, MessagePipeHandle> createMessagePipe(); + + /** + * Creates a data pipe, which is a unidirectional communication channel for unframed data, with + * the given options. Data is unframed, but must come as (multiples of) discrete elements, of + * the size given in |options|. See |DataPipe.CreateOptions| for a description of the different + * options available for data pipes. |options| may be set to null for a data pipe with the + * default options (which will have an element size of one byte and have some system-dependent + * capacity). + * + * @return the set of handles for the two endpoints of the data pipe. + */ + public Pair<DataPipe.ProducerHandle, DataPipe.ConsumerHandle> createDataPipe( + DataPipe.CreateOptions options); + + /** + * Creates a buffer that can be shared between applications (by duplicating the handle -- see + * |SharedBufferHandle.duplicate()| -- and passing it over a message pipe). To access the + * buffer, one must call |SharedBufferHandle.map|. + * + * @return the new |SharedBufferHandle|. + */ + public SharedBufferHandle createSharedBuffer(SharedBufferHandle.CreateOptions options, + long numBytes); +} diff --git a/mojo/public/java/src/org/chromium/mojo/system/DataPipe.java b/mojo/public/java/src/org/chromium/mojo/system/DataPipe.java new file mode 100644 index 0000000000..175f97b305 --- /dev/null +++ b/mojo/public/java/src/org/chromium/mojo/system/DataPipe.java @@ -0,0 +1,308 @@ +// 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. + +package org.chromium.mojo.system; + +import java.nio.ByteBuffer; + +/** + * Interface for data pipes. A data pipe is a unidirectional communication channel for unframed + * data. Data is unframed, but must come as (multiples of) discrete elements, of the size given at + * creation time. + */ +public interface DataPipe { + + /** + * Flags for the data pipe creation operation. + */ + public static class CreateFlags extends Flags<CreateFlags> { + private static final int FLAG_NONE = 0; + private static final int FLAG_MAY_DISCARD = 1 << 0; + + /** + * Dedicated constructor. + * + * @param flags initial value of the flags. + */ + protected CreateFlags(int flags) { + super(flags); + } + + /** + * Change the may-discard bit of this flag. This indicates that the data pipe may discard + * data for whatever reason; best-effort delivery. In particular, if the capacity is + * reached, old data may be discard to make room for new data. + * + * @param mayDiscard the new value of the may-discard bit. + * @return this. + */ + public CreateFlags setMayDiscard(boolean mayDiscard) { + return setFlag(FLAG_MAY_DISCARD, mayDiscard); + } + + /** + * @return flags with no bit set. + */ + public static CreateFlags none() { + return new CreateFlags(FLAG_NONE); + } + + } + + /** + * Used to specify creation parameters for a data pipe to |Core.createDataPipe()|. + */ + public static class CreateOptions { + + /** + * Used to specify different modes of operation, see |DataPipe.CreateFlags|. + */ + private CreateFlags mFlags = CreateFlags.none(); + /** + * The size of an element, in bytes. All transactions and buffers will consist of an + * integral number of elements. Must be nonzero. + */ + private int mElementNumBytes; + /** + * The capacity of the data pipe, in number of bytes; must be a multiple of + * |element_num_bytes|. The data pipe will always be able to queue AT LEAST this much data. + * Set to zero to opt for a system-dependent automatically-calculated capacity (which will + * always be at least one element). + */ + private int mCapacityNumBytes; + + /** + * @return the flags + */ + public CreateFlags getFlags() { + return mFlags; + } + + /** + * @return the elementNumBytes + */ + public int getElementNumBytes() { + return mElementNumBytes; + } + + /** + * @param elementNumBytes the elementNumBytes to set + */ + public void setElementNumBytes(int elementNumBytes) { + mElementNumBytes = elementNumBytes; + } + + /** + * @return the capacityNumBytes + */ + public int getCapacityNumBytes() { + return mCapacityNumBytes; + } + + /** + * @param capacityNumBytes the capacityNumBytes to set + */ + public void setCapacityNumBytes(int capacityNumBytes) { + mCapacityNumBytes = capacityNumBytes; + } + + } + + /** + * Flags for the write operations on MessagePipeHandle . + */ + public static class WriteFlags extends Flags<WriteFlags> { + private static final int FLAG_NONE = 0; + private static final int FLAG_ALL_OR_NONE = 1 << 0; + + /** + * Dedicated constructor. + * + * @param flags initial value of the flags. + */ + private WriteFlags(int flags) { + super(flags); + } + + /** + * Change the all-or-none bit of those flags. If set, write either all the elements + * requested or none of them. + * + * @param allOrNone the new value of all-or-none bit. + * @return this. + */ + public WriteFlags setAllOrNone(boolean allOrNone) { + return setFlag(FLAG_ALL_OR_NONE, allOrNone); + } + + /** + * @return a flag with no bit set. + */ + public static WriteFlags none() { + return new WriteFlags(FLAG_NONE); + } + } + + /** + * Flags for the read operations on MessagePipeHandle. + */ + public static class ReadFlags extends Flags<ReadFlags> { + private static final int FLAG_NONE = 0; + private static final int FLAG_ALL_OR_NONE = 1 << 0; + private static final int FLAG_QUERY = 1 << 2; + + /** + * Dedicated constructor. + * + * @param flags initial value of the flag. + */ + private ReadFlags(int flags) { + super(flags); + } + + /** + * Change the all-or-none bit of this flag. If set, read (or discard) either the requested + * number of elements or none. + * + * @param allOrNone the new value of the all-or-none bit. + * @return this. + */ + public ReadFlags setAllOrNone(boolean allOrNone) { + return setFlag(FLAG_ALL_OR_NONE, allOrNone); + } + + /** + * Change the query bit of this flag. If set query the number of elements available to read. + * Mutually exclusive with |dicard| and |allOrNone| is ignored if this flag is set. + * + * @param query the new value of the query bit. + * @return this. + */ + public ReadFlags query(boolean query) { + return setFlag(FLAG_QUERY, query); + } + + /** + * @return a flag with no bit set. + */ + public static ReadFlags none() { + return new ReadFlags(FLAG_NONE); + } + + } + + /** + * Handle for the producer part of a data pipe. + */ + public static interface ProducerHandle extends Handle { + + /** + * Writes the given data to the data pipe producer. |elements| points to data; the buffer + * must be a direct ByteBuffer and the limit should be a multiple of the data pipe's element + * size. If |allOrNone| is set in |flags|, either all the data will be written or none is. + * <p> + * On success, returns the amount of data that was actually written. + * <p> + * Note: If the data pipe has the "may discard" option flag (specified on creation), this + * will discard as much data as required to write the given data, starting with the earliest + * written data that has not been consumed. However, even with "may discard", if the buffer + * limit is greater than the data pipe's capacity (and |allOrNone| is not set), this will + * write the maximum amount possible (namely, the data pipe's capacity) and return that + * amount. It will *not* discard data from |elements|. + * + * @return number of written bytes. + */ + public int writeData(ByteBuffer elements, WriteFlags flags); + + /** + * Begins a two-phase write to the data pipe producer . On success, returns a |ByteBuffer| + * to which the caller can write. If flags has |allOrNone| set, then the buffer capacity + * will be at least as large as |numBytes|, which must also be a multiple of the element + * size (if |allOrNone| is not set, |numBytes| is ignored and the caller must check the + * capacity of the buffer). + * <p> + * During a two-phase write, this handle is *not* writable. E.g., if another thread tries to + * write to it, it will throw a |MojoException| with code |MojoResult.BUSY|; that thread can + * then wait for this handle to become writable again. + * <p> + * Once the caller has finished writing data to the buffer, it should call |endWriteData()| + * to specify the amount written and to complete the two-phase write. + * <p> + * Note: If the data pipe has the "may discard" option flag (specified on creation) and + * |flags| has |allOrNone| set, this may discard some data. + * + * @return The buffer to write to. + */ + public ByteBuffer beginWriteData(int numBytes, WriteFlags flags); + + /** + * Ends a two-phase write to the data pipe producer that was begun by a call to + * |beginWriteData()| on the same handle. |numBytesWritten| should indicate the amount of + * data actually written; it must be less than or equal to the capacity of the buffer + * returned by |beginWriteData()| and must be a multiple of the element size. The buffer + * returned from |beginWriteData()| must have been filled with exactly |numBytesWritten| + * bytes of data. + * <p> + * On failure, the two-phase write (if any) is ended (so the handle may become writable + * again, if there's space available) but no data written to the buffer is "put into" the + * data pipe. + */ + public void endWriteData(int numBytesWritten); + } + + /** + * Handle for the consumer part of a data pipe. + */ + public static interface ConsumerHandle extends Handle { + + /** + * Discards data on the data pie consumer. This method discards up to |numBytes| (which + * again be a multiple of the element size) bytes of data, returning the amount actually + * discarded. if |flags| has |allOrNone|, it will either discard exactly |numBytes| bytes of + * data or none. In this case, |query| must not be set. + */ + public int discardData(int numBytes, ReadFlags flags); + + /** + * Reads data from the data pipe consumer. May also be used to query the amount of data + * available. If |flags| has not |query| set, this tries to read up to |elements| capacity + * (which must be a multiple of the data pipe's element size) bytes of data to |elements| + * and returns the amount actually read. |elements| must be a direct ByteBuffer. If flags + * has |allOrNone| set, it will either read exactly |elements| capacity bytes of data or + * none. + * <p> + * If flags has |query| set, it queries the amount of data available, returning the number + * of bytes available. In this case |allOrNone| is ignored, as are |elements|. + */ + public int readData(ByteBuffer elements, ReadFlags flags); + + /** + * Begins a two-phase read from the data pipe consumer. On success, returns a |ByteBuffer| + * from which the caller can read up to its limit bytes of data. If flags has |allOrNone| + * set, then the limit will be at least as large as |numBytes|, which must also be a + * multiple of the element size (if |allOrNone| is not set, |numBytes| is ignored). |flags| + * must not have |query| set. + * <p> + * During a two-phase read, this handle is *not* readable. E.g., if another thread tries to + * read from it, it will throw a |MojoException| with code |MojoResult.BUSY|; that thread + * can then wait for this handle to become readable again. + * <p> + * Once the caller has finished reading data from the buffer, it should call |endReadData()| + * to specify the amount read and to complete the two-phase read. + */ + public ByteBuffer beginReadData(int numBytes, ReadFlags flags); + + /** + * Ends a two-phase read from the data pipe consumer that was begun by a call to + * |beginReadData()| on the same handle. |numBytesRead| should indicate the amount of data + * actually read; it must be less than or equal to the limit of the buffer returned by + * |beginReadData()| and must be a multiple of the element size. + * <p> + * On failure, the two-phase read (if any) is ended (so the handle may become readable + * again) but no data is "removed" from the data pipe. + */ + public void endReadData(int numBytesRead); + } + +} diff --git a/mojo/public/java/src/org/chromium/mojo/system/Flags.java b/mojo/public/java/src/org/chromium/mojo/system/Flags.java new file mode 100644 index 0000000000..bfce6e4712 --- /dev/null +++ b/mojo/public/java/src/org/chromium/mojo/system/Flags.java @@ -0,0 +1,48 @@ +// 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. + +package org.chromium.mojo.system; + +/** + * Base class for bit field used as flags. + * + * @param <F> the type of the flags. + */ +public abstract class Flags<F extends Flags<F>> { + private int mFlags; + + /** + * Dedicated constructor. + * + * @param flags initial value of the flag. + */ + protected Flags(int flags) { + mFlags = flags; + } + + /** + * @return the computed flag. + */ + public int getFlags() { + return mFlags; + } + + /** + * Change the given bit of this flag. + * + * @param value the new value of given bit. + * @return this. + */ + protected F setFlag(int flag, boolean value) { + if (value) { + mFlags |= flag; + } else { + mFlags &= ~flag; + } + @SuppressWarnings("unchecked") + F f = (F) this; + return f; + } + +} diff --git a/mojo/public/java/src/org/chromium/mojo/system/Handle.java b/mojo/public/java/src/org/chromium/mojo/system/Handle.java new file mode 100644 index 0000000000..6f60055d74 --- /dev/null +++ b/mojo/public/java/src/org/chromium/mojo/system/Handle.java @@ -0,0 +1,36 @@ +// 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. + +package org.chromium.mojo.system; + +import java.io.Closeable; + +/** + * A generic mojo handle. + */ +public interface Handle extends Closeable { + + /** + * Closes the given |handle|. + * <p> + * Concurrent operations on |handle| may succeed (or fail as usual) if they happen before the + * close, be cancelled with result |MojoResult.CANCELLED| if they properly overlap (this is + * likely the case with |wait()|, etc.), or fail with |MojoResult.INVALID_ARGUMENT| if they + * happen after. + */ + @Override + public void close(); + + /** + * @see Core#wait(Handle, Core.WaitFlags, long) + */ + public int wait(Core.WaitFlags flags, long deadline); + + /** + * @return whether the handle is valid. A handle is valid until it has been explicitly closed or + * send through a message pipe via |MessagePipeHandle.writeMessage|. + */ + public boolean isValid(); + +} diff --git a/mojo/public/java/src/org/chromium/mojo/system/MessagePipeHandle.java b/mojo/public/java/src/org/chromium/mojo/system/MessagePipeHandle.java new file mode 100644 index 0000000000..c187497d3f --- /dev/null +++ b/mojo/public/java/src/org/chromium/mojo/system/MessagePipeHandle.java @@ -0,0 +1,181 @@ +// 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. + +package org.chromium.mojo.system; + +import java.nio.ByteBuffer; +import java.util.List; + +/** + * Message pipes are bidirectional communication channel for framed data (i.e., messages). Messages + * can contain plain data and/or Mojo handles. + */ +public interface MessagePipeHandle extends Handle { + /** + * Flags for the write operations on MessagePipeHandle . + */ + public static class WriteFlags extends Flags<WriteFlags> { + private static final int FLAG_NONE = 0; + + /** + * Dedicated constructor. + * + * @param flags initial value of the flag. + */ + private WriteFlags(int flags) { + super(flags); + } + + /** + * @return a flag with no bit set. + */ + public static WriteFlags none() { + return new WriteFlags(FLAG_NONE); + } + } + + /** + * Flags for the read operations on MessagePipeHandle. + */ + public static class ReadFlags extends Flags<ReadFlags> { + private static final int FLAG_NONE = 0; + private static final int FLAG_MAY_DISCARD = 1 << 0; + + /** + * Dedicated constructor. + * + * @param flags initial value of the flag. + */ + private ReadFlags(int flags) { + super(flags); + } + + /** + * Change the may-discard bit of this flag. If set, if the message is unable to be read for + * whatever reason (e.g., the caller-supplied buffer is too small), discard the message + * (i.e., simply dequeue it). + * + * @param mayDiscard the new value of the may-discard bit. + * @return this. + */ + public ReadFlags setMayDiscard(boolean mayDiscard) { + return setFlag(FLAG_MAY_DISCARD, mayDiscard); + } + + /** + * @return a flag with no bit set. + */ + public static ReadFlags none() { + return new ReadFlags(FLAG_NONE); + } + + } + + /** + * Writes a message to the message pipe endpoint, with message data specified by |bytes| and + * attached handles specified by |handles|, and options specified by |flags|. If there is no + * message data, |bytes| may be null, otherwise it must be a direct ByteBuffer. If there are no + * attached handles, |handles| may be null. + * <p> + * If handles are attached, on success the handles will no longer be valid (the receiver will + * receive equivalent, but logically different, handles). Handles to be sent should not be in + * simultaneous use (e.g., on another thread). + */ + void writeMessage(ByteBuffer bytes, List<Handle> handles, WriteFlags flags); + + /** + * Result of the |readMessage| method. + */ + public static class ReadMessageResult { + /** + * <code>true</code> if a message was read. + */ + private boolean mWasMessageRead; + /** + * If a message was read, the size in bytes of the message, otherwise the size in bytes of + * the next message. + */ + private int mMessageSize; + /** + * If a message was read, the number of handles contained in the message, otherwise the + * number of handles contained in the next message. + */ + private int mHandlesCount; + /** + * If a message was read, the handles contained in the message, undefined otherwise. + */ + private List<UntypedHandle> mHandles; + + /** + * @return the wasMessageRead + */ + public boolean getWasMessageRead() { + return mWasMessageRead; + } + + /** + * @param wasMessageRead the wasMessageRead to set + */ + public void setWasMessageRead(boolean wasMessageRead) { + mWasMessageRead = wasMessageRead; + } + + /** + * @return the messageSize + */ + public int getMessageSize() { + return mMessageSize; + } + + /** + * @param messageSize the messageSize to set + */ + public void setMessageSize(int messageSize) { + mMessageSize = messageSize; + } + + /** + * @return the handlesCount + */ + public int getHandlesCount() { + return mHandlesCount; + } + + /** + * @param handlesCount the handlesCount to set + */ + public void setHandlesCount(int handlesCount) { + mHandlesCount = handlesCount; + } + + /** + * @return the handles + */ + public List<UntypedHandle> getHandles() { + return mHandles; + } + + /** + * @param handles the handles to set + */ + public void setHandles(List<UntypedHandle> handles) { + mHandles = handles; + } + } + + /** + * Reads a message from the message pipe endpoint; also usable to query the size of the next + * message or discard the next message. |bytes| indicate the buffer/buffer size to receive the + * message data (if any) and |maxNumberOfHandles| indicate the maximum handle count to receive + * the attached handles (if any). |bytes| is optional. If null, |maxNumberOfHandles| must be + * zero, and the return value will indicate the size of the next message. If non-null, it must + * be a direct ByteBuffer and the return value will indicate if the message was read or not. If + * the message was read its content will be in |bytes|, and the attached handles will be in the + * return value. Partial reads are NEVER done. Either a full read is done and |wasMessageRead| + * will be true, or the read is NOT done and |wasMessageRead| will be false (if |mayDiscard| was + * set, the message is also discarded in this case). + */ + ReadMessageResult readMessage(ByteBuffer bytes, int maxNumberOfHandles, + ReadFlags flags); +} diff --git a/mojo/public/java/src/org/chromium/mojo/system/MojoException.java b/mojo/public/java/src/org/chromium/mojo/system/MojoException.java new file mode 100644 index 0000000000..e06f647aeb --- /dev/null +++ b/mojo/public/java/src/org/chromium/mojo/system/MojoException.java @@ -0,0 +1,36 @@ +// 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. + +package org.chromium.mojo.system; + +/** + * Exception for the core mojo API. + */ +public class MojoException extends RuntimeException { + + private final int mCode; + + /** + * Constructor. + */ + public MojoException(int code) { + mCode = code; + } + + /** + * The mojo result code associated with this exception. See {@link MojoResult} for possible + * values. + */ + public int getMojoResult() { + return mCode; + } + + /** + * @see Object#toString() + */ + @Override + public String toString() { + return "MojoResult(" + mCode + "): " + MojoResult.describe(mCode); + } +} diff --git a/mojo/public/java/src/org/chromium/mojo/system/MojoResult.java b/mojo/public/java/src/org/chromium/mojo/system/MojoResult.java new file mode 100644 index 0000000000..a829c8332a --- /dev/null +++ b/mojo/public/java/src/org/chromium/mojo/system/MojoResult.java @@ -0,0 +1,82 @@ +// 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. + +package org.chromium.mojo.system; + +/** + * The different mojo result codes. + */ +public final class MojoResult { + public static final int OK = 0; + public static final int CANCELLED = -1; + public static final int UNKNOWN = -2; + public static final int INVALID_ARGUMENT = -3; + public static final int DEADLINE_EXCEEDED = -4; + public static final int NOT_FOUND = -5; + public static final int ALREADY_EXISTS = -6; + public static final int PERMISSION_DENIED = -7; + public static final int RESOURCE_EXHAUSTED = -8; + public static final int FAILED_PRECONDITION = -9; + public static final int ABORTED = -10; + public static final int OUT_OF_RANGE = -11; + public static final int UNIMPLEMENTED = -12; + public static final int INTERNAL = -13; + public static final int UNAVAILABLE = -14; + public static final int DATA_LOSS = -15; + public static final int BUSY = -16; + public static final int SHOULD_WAIT = -17; + + /** + * never instantiate. + */ + private MojoResult() { + } + + /** + * Describes the given result code. + */ + public static String describe(int mCode) { + switch (mCode) { + case OK: + return "OK"; + case CANCELLED: + return "CANCELLED"; + case UNKNOWN: + return "UNKNOWN"; + case INVALID_ARGUMENT: + return "INVALID_ARGUMENT"; + case DEADLINE_EXCEEDED: + return "DEADLINE_EXCEEDED"; + case NOT_FOUND: + return "NOT_FOUND"; + case ALREADY_EXISTS: + return "ALREADY_EXISTS"; + case PERMISSION_DENIED: + return "PERMISSION_DENIED"; + case RESOURCE_EXHAUSTED: + return "RESOURCE_EXHAUSTED"; + case FAILED_PRECONDITION: + return "FAILED_PRECONDITION"; + case ABORTED: + return "ABORTED"; + case OUT_OF_RANGE: + return "OUT_OF_RANGE"; + case UNIMPLEMENTED: + return "UNIMPLEMENTED"; + case INTERNAL: + return "INTERNAL"; + case UNAVAILABLE: + return "UNAVAILABLE"; + case DATA_LOSS: + return "DATA_LOSS"; + case BUSY: + return "BUSY"; + case SHOULD_WAIT: + return "SHOULD_WAIT"; + default: + return "UNKNOWN"; + } + + } +} diff --git a/mojo/public/java/src/org/chromium/mojo/system/Pair.java b/mojo/public/java/src/org/chromium/mojo/system/Pair.java new file mode 100644 index 0000000000..c302aed680 --- /dev/null +++ b/mojo/public/java/src/org/chromium/mojo/system/Pair.java @@ -0,0 +1,61 @@ +// 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. + +package org.chromium.mojo.system; + +import java.util.Objects; + +/** + * A pair of object. + * + * @param <F> Type of the first element. + * @param <S> Type of the second element. + */ +public class Pair<F, S> { + + public final F first; + public final S second; + + /** + * Dedicated constructor. + * + * @param first the first element of the pair. + * @param second the second element of the pair. + */ + public Pair(F first, S second) { + this.first = first; + this.second = second; + } + + /** + * @see Object#equals(Object) + */ + @Override + public boolean equals(Object o) { + if (!(o instanceof Pair)) { + return false; + } + Pair<?, ?> p = (Pair<?, ?>) o; + return Objects.equals(p.first, first) && Objects.equals(p.second, second); + } + + /** + * @see Object#hashCode() + */ + @Override + public int hashCode() { + return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode()); + } + + /** + * Helper method for creating a pair. + * + * @param a the first element of the pair. + * @param b the second element of the pair. + * @return the pair containing a and b. + */ + public static <A, B, C extends A, D extends B> Pair<A, B> create(C a, D b) { + return new Pair<A, B>(a, b); + } +} diff --git a/mojo/public/java/src/org/chromium/mojo/system/SharedBufferHandle.java b/mojo/public/java/src/org/chromium/mojo/system/SharedBufferHandle.java new file mode 100644 index 0000000000..908db9ef6c --- /dev/null +++ b/mojo/public/java/src/org/chromium/mojo/system/SharedBufferHandle.java @@ -0,0 +1,139 @@ +// 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. + +package org.chromium.mojo.system; + +import java.nio.ByteBuffer; + +/** + * A buffer that can be shared between applications. + */ +public interface SharedBufferHandle extends Handle { + + /** + * Flags for the shared buffer creation operation. + */ + public static class CreateFlags extends Flags<CreateFlags> { + private static final int FLAG_NONE = 0; + + /** + * Dedicated constructor. + * + * @param flags initial value of the flags. + */ + protected CreateFlags(int flags) { + super(flags); + } + + /** + * @return flags with no bit set. + */ + public static CreateFlags none() { + return new CreateFlags(FLAG_NONE); + } + + } + + /** + * Used to specify creation parameters for a shared buffer to |Core#createSharedBuffer()|. + */ + public static class CreateOptions { + private CreateFlags mFlags = CreateFlags.none(); + + /** + * @return the flags + */ + public CreateFlags getFlags() { + return mFlags; + } + + } + + /** + * Flags for the shared buffer duplication operation. + */ + public static class DuplicateFlags extends Flags<DuplicateFlags> { + private static final int FLAG_NONE = 0; + + /** + * Dedicated constructor. + * + * @param flags initial value of the flags. + */ + protected DuplicateFlags(int flags) { + super(flags); + } + + /** + * @return flags with no bit set. + */ + public static DuplicateFlags none() { + return new DuplicateFlags(FLAG_NONE); + } + + } + + /** + * Used to specify parameters in duplicating access to a shared buffer to + * |SharedBufferHandle#duplicate| + */ + public static class DuplicateOptions { + private DuplicateFlags mFlags = DuplicateFlags.none(); + + /** + * @return the flags + */ + public DuplicateFlags getFlags() { + return mFlags; + } + + } + + /** + * TODO(qsr): Insert description here. + */ + public static class MapFlags extends Flags<MapFlags> { + private static final int FLAG_NONE = 0; + + /** + * Dedicated constructor. + * + * @param flags initial value of the flags. + */ + protected MapFlags(int flags) { + super(flags); + } + + /** + * @return flags with no bit set. + */ + public static MapFlags none() { + return new MapFlags(FLAG_NONE); + } + + } + + /** + * Duplicates the handle. This creates another handle (returned on success), which can then be + * sent to another application over a message pipe, while retaining access to this handle (and + * any mappings that it may have). + */ + public SharedBufferHandle duplicate(DuplicateOptions options); + + /** + * Map the part (at offset |offset| of length |numBytes|) of the buffer given by this handle + * into memory. |offset + numBytes| must be less than or equal to the size of the buffer. On + * success, the returned buffer points to memory with the requested part of the buffer. A single + * buffer handle may have multiple active mappings (possibly depending on the buffer type). The + * permissions (e.g., writable or executable) of the returned memory may depend on the + * properties of the buffer and properties attached to the buffer handle as well as |flags|. + */ + public ByteBuffer map(long offset, long numBytes, MapFlags flags); + + /** + * Unmap a buffer pointer that was mapped by |map()|. + */ + public void unmap(ByteBuffer buffer); + +} diff --git a/mojo/public/java/src/org/chromium/mojo/system/UntypedHandle.java b/mojo/public/java/src/org/chromium/mojo/system/UntypedHandle.java new file mode 100644 index 0000000000..63b5f7c322 --- /dev/null +++ b/mojo/public/java/src/org/chromium/mojo/system/UntypedHandle.java @@ -0,0 +1,41 @@ +// 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. + +package org.chromium.mojo.system; + + +/** + * TODO(qsr): Insert description here. + */ +public interface UntypedHandle extends Handle { + + /** + * TODO(qsr): + * + * @return TODO(qsr) + */ + public MessagePipeHandle toMessagePipeHandle(); + + /** + * TODO(qsr): + * + * @return TODO(qsr) + */ + public DataPipe.ConsumerHandle toDataPipeConsumerHandle(); + + /** + * TODO(qsr): + * + * @return TODO(qsr) + */ + public DataPipe.ProducerHandle toDataPipeProducerHandle(); + + /** + * TODO(qsr): + * + * @return TODO(qsr) + */ + public SharedBufferHandle toSharedBufferHandle(); + +} diff --git a/mojo/public/js/bindings/codec.js b/mojo/public/js/bindings/codec.js index f3d4b68ae5..ef2060e516 100644 --- a/mojo/public/js/bindings/codec.js +++ b/mojo/public/js/bindings/codec.js @@ -2,81 +2,111 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -define("mojo/public/js/bindings/codec", function() { +define("mojo/public/js/bindings/codec", [ + "mojo/public/js/bindings/unicode" +], function(unicode) { - // Memory ------------------------------------------------------------------- + var kErrorUnsigned = "Passing negative value to unsigned"; - function store8(memory, pointer, val) { - memory[pointer] = val; - } + // Memory ------------------------------------------------------------------- - function store16(memory, pointer, val) { - memory[pointer + 0] = val >> 0; - memory[pointer + 1] = val >> 8; - } + var kAlignment = 8; + var kHighWordMultiplier = 0x100000000; + var kHostIsLittleEndian = (function () { + var endianArrayBuffer = new ArrayBuffer(2); + var endianUint8Array = new Uint8Array(endianArrayBuffer); + var endianUint16Array = new Uint16Array(endianArrayBuffer); + endianUint16Array[0] = 1; + return endianUint8Array[0] == 1; + })(); - function store32(memory, pointer, val) { - memory[pointer + 0] = val >> 0; - memory[pointer + 1] = val >> 8; - memory[pointer + 2] = val >> 16; - memory[pointer + 3] = val >> 24; + function align(size) { + return size + (kAlignment - (size % kAlignment)) % kAlignment; } - function store64(memory, pointer, val) { - store32(memory, pointer, val); - var high = (val / 0x10000) | 0; - store32(memory, pointer + 4, high); + function getInt64(dataView, byteOffset, value) { + var lo, hi; + if (kHostIsLittleEndian) { + lo = dataView.getUint32(byteOffset, kHostIsLittleEndian); + hi = dataView.getInt32(byteOffset + 4, kHostIsLittleEndian); + } else { + hi = dataView.getInt32(byteOffset, kHostIsLittleEndian); + lo = dataView.getUint32(byteOffset + 4, kHostIsLittleEndian); + } + return lo + hi * kHighWordMultiplier; } - function load8(memory, pointer) { - return memory[pointer]; + function getUint64(dataView, byteOffset, value) { + var lo, hi; + if (kHostIsLittleEndian) { + lo = dataView.getUint32(byteOffset, kHostIsLittleEndian); + hi = dataView.getUint32(byteOffset + 4, kHostIsLittleEndian); + } else { + hi = dataView.getUint32(byteOffset, kHostIsLittleEndian); + lo = dataView.getUint32(byteOffset + 4, kHostIsLittleEndian); + } + return lo + hi * kHighWordMultiplier; } - function load16(memory, pointer) { - return (memory[pointer + 0] << 0) + - (memory[pointer + 1] << 8); + function setInt64(dataView, byteOffset, value) { + var hi = Math.floor(value / kHighWordMultiplier); + if (kHostIsLittleEndian) { + dataView.setInt32(byteOffset, value, kHostIsLittleEndian); + dataView.setInt32(byteOffset + 4, hi, kHostIsLittleEndian); + } else { + dataView.setInt32(byteOffset, hi, kHostIsLittleEndian); + dataView.setInt32(byteOffset + 4, value, kHostIsLittleEndian); + } } - function load32(memory, pointer) { - return (memory[pointer + 0] << 0) + - (memory[pointer + 1] << 8) + - (memory[pointer + 2] << 16) + - (memory[pointer + 3] << 24); + function setUint64(dataView, byteOffset, value) { + var hi = (value / kHighWordMultiplier) | 0; + if (kHostIsLittleEndian) { + dataView.setInt32(byteOffset, value, kHostIsLittleEndian); + dataView.setInt32(byteOffset + 4, hi, kHostIsLittleEndian); + } else { + dataView.setInt32(byteOffset, hi, kHostIsLittleEndian); + dataView.setInt32(byteOffset + 4, value, kHostIsLittleEndian); + } } - var kAlignment = 8; - - function align(size) { - return size + (kAlignment - (size % kAlignment)) % kAlignment; + function copyArrayBuffer(dstArrayBuffer, srcArrayBuffer) { + (new Uint8Array(dstArrayBuffer)).set(new Uint8Array(srcArrayBuffer)); } // Buffer ------------------------------------------------------------------- - function Buffer(size) { - this.memory = new Uint8Array(size); + function Buffer(sizeOrArrayBuffer) { + if (sizeOrArrayBuffer instanceof ArrayBuffer) { + this.arrayBuffer = sizeOrArrayBuffer; + } else { + this.arrayBuffer = new ArrayBuffer(sizeOrArrayBuffer); + }; + + this.dataView = new DataView(this.arrayBuffer); this.next = 0; } Buffer.prototype.alloc = function(size) { var pointer = this.next; this.next += size; - if (this.next > this.memory.length) { - var newSize = (1.5 * (this.memory.length + size)) | 0; + if (this.next > this.arrayBuffer.byteLength) { + var newSize = (1.5 * (this.arrayBuffer.byteLength + size)) | 0; this.grow(newSize); } return pointer; }; Buffer.prototype.grow = function(size) { - var newMemory = new Uint8Array(size); - var oldMemory = this.memory; - for (var i = 0; i < oldMemory.length; ++i) - newMemory[i] = oldMemory[i]; - this.memory = newMemory; + var newArrayBuffer = new ArrayBuffer(size); + copyArrayBuffer(newArrayBuffer, this.arrayBuffer); + this.arrayBuffer = newArrayBuffer; + this.dataView = new DataView(this.arrayBuffer); }; - Buffer.prototype.createViewOfAllocatedMemory = function() { - return new Uint8Array(this.memory.buffer, 0, this.next); + Buffer.prototype.trim = function() { + this.arrayBuffer = this.arrayBuffer.slice(0, this.next); + this.dataView = new DataView(this.arrayBuffer); }; // Constants ---------------------------------------------------------------- @@ -88,50 +118,77 @@ define("mojo/public/js/bindings/codec", function() { // Decoder ------------------------------------------------------------------ - function Decoder(memory, handles, base) { - this.memory = memory; + function Decoder(buffer, handles, base) { + this.buffer = buffer; this.handles = handles; this.base = base; this.next = base; - this.viewU32 = new Uint32Array( - this.memory.buffer, 0, - Math.floor(this.memory.length / Uint32Array.BYTES_PER_ELEMENT)); - this.viewFloat = new Float32Array( - this.memory.buffer, 0, - Math.floor(this.memory.length / Float32Array.BYTES_PER_ELEMENT)); } Decoder.prototype.skip = function(offset) { this.next += offset; }; - Decoder.prototype.read8 = function() { - var result = load8(this.memory, this.next); + Decoder.prototype.readInt8 = function() { + var result = this.buffer.dataView.getInt8(this.next, kHostIsLittleEndian); this.next += 1; return result; }; - Decoder.prototype.read16 = function() { - var result = load16(this.memory, this.next); + Decoder.prototype.readUint8 = function() { + var result = this.buffer.dataView.getUint8(this.next, kHostIsLittleEndian); + this.next += 1; + return result; + }; + + Decoder.prototype.readInt16 = function() { + var result = this.buffer.dataView.getInt16(this.next, kHostIsLittleEndian); this.next += 2; return result; }; - Decoder.prototype.read32 = function() { - var result = this.viewU32[this.next / this.viewU32.BYTES_PER_ELEMENT]; - this.next += this.viewU32.BYTES_PER_ELEMENT; + Decoder.prototype.readUint16 = function() { + var result = this.buffer.dataView.getUint16(this.next, kHostIsLittleEndian); + this.next += 2; return result; }; - Decoder.prototype.read64 = function() { - var low = this.read32(); - var high = this.read32(); - return low + high * 0x100000000; + Decoder.prototype.readInt32 = function() { + var result = this.buffer.dataView.getInt32(this.next, kHostIsLittleEndian); + this.next += 4; + return result; }; - Decoder.prototype.decodeFloat = function() { - var result = this.viewFloat[this.next / this.viewFloat.BYTES_PER_ELEMENT]; - this.next += this.viewFloat.BYTES_PER_ELEMENT; + Decoder.prototype.readUint32 = function() { + var result = this.buffer.dataView.getUint32(this.next, kHostIsLittleEndian); + this.next += 4; + return result; + }; + + Decoder.prototype.readInt64 = function() { + var result = getInt64(this.buffer.dataView, this.next, kHostIsLittleEndian); + this.next += 8; + return result; + }; + + Decoder.prototype.readUint64 = function() { + var result = getUint64( + this.buffer.dataView, this.next, kHostIsLittleEndian); + this.next += 8; + return result; + }; + + Decoder.prototype.readFloat32 = function() { + var result = this.buffer.dataView.readFloat32( + this.next, kHostIsLittleEndian); + this.next += 4; + return result; + }; + + Decoder.prototype.readFloat64 = function() { + var result = this.buffer.dataView.readFloat64( + this.next, kHostIsLittleEndian); + this.next += 8; return result; }; @@ -139,39 +196,32 @@ define("mojo/public/js/bindings/codec", function() { // TODO(abarth): To correctly decode a pointer, we need to know the real // base address of the array buffer. var offsetPointer = this.next; - var offset = this.read64(); + var offset = this.readUint64(); if (!offset) return 0; return offsetPointer + offset; }; Decoder.prototype.decodeAndCreateDecoder = function() { - return new Decoder(this.memory, this.handles, this.decodePointer()); + return new Decoder(this.buffer, this.handles, this.decodePointer()); }; Decoder.prototype.decodeHandle = function() { - return this.handles[this.read32()]; + return this.handles[this.readUint32()]; }; Decoder.prototype.decodeString = function() { - // TODO(abarth): We should really support UTF-8. We might want to - // jump out of the VM to decode the string directly from the array - // buffer using v8::String::NewFromUtf8. - var numberOfBytes = this.read32(); - var numberOfElements = this.read32(); - var val = new Array(numberOfElements); - var memory = this.memory; + var numberOfBytes = this.readUint32(); + var numberOfElements = this.readUint32(); var base = this.next; - for (var i = 0; i < numberOfElements; ++i) { - val[i] = String.fromCharCode(memory[base + i] & 0x7F); - } this.next += numberOfElements; - return val.join(''); + return unicode.decodeUtf8String( + new Uint8Array(this.buffer.arrayBuffer, base, numberOfElements)); }; Decoder.prototype.decodeArray = function(cls) { - var numberOfBytes = this.read32(); - var numberOfElements = this.read32(); + var numberOfBytes = this.readUint32(); + var numberOfElements = this.readUint32(); var val = new Array(numberOfElements); for (var i = 0; i < numberOfElements; ++i) { val[i] = cls.decode(this); @@ -204,41 +254,77 @@ define("mojo/public/js/bindings/codec", function() { this.next += offset; }; - Encoder.prototype.write8 = function(val) { - store8(this.buffer.memory, this.next, val); + Encoder.prototype.writeInt8 = function(val) { + // NOTE: Endianness doesn't come into play for single bytes. + this.buffer.dataView.setInt8(this.next, val); + this.next += 1; + }; + + Encoder.prototype.writeUint8 = function(val) { + if (val < 0) { + throw new Error(kErrorUnsigned); + } + // NOTE: Endianness doesn't come into play for single bytes. + this.buffer.dataView.setUint8(this.next, val); this.next += 1; }; - Encoder.prototype.write16 = function(val) { - store16(this.buffer.memory, this.next, val); + Encoder.prototype.writeInt16 = function(val) { + this.buffer.dataView.setInt16(this.next, val, kHostIsLittleEndian); this.next += 2; }; - Encoder.prototype.write32 = function(val) { - store32(this.buffer.memory, this.next, val); + Encoder.prototype.writeUint16 = function(val) { + if (val < 0) { + throw new Error(kErrorUnsigned); + } + this.buffer.dataView.setUint16(this.next, val, kHostIsLittleEndian); + this.next += 2; + }; + + Encoder.prototype.writeInt32 = function(val) { + this.buffer.dataView.setInt32(this.next, val, kHostIsLittleEndian); this.next += 4; }; - Encoder.prototype.write64 = function(val) { - store64(this.buffer.memory, this.next, val); + Encoder.prototype.writeUint32 = function(val) { + if (val < 0) { + throw new Error(kErrorUnsigned); + } + this.buffer.dataView.setUint32(this.next, val, kHostIsLittleEndian); + this.next += 4; + }; + + Encoder.prototype.writeInt64 = function(val) { + setInt64(this.buffer.dataView, this.next, val); this.next += 8; }; - Encoder.prototype.encodeFloat = function(val) { - var floatBuffer = new Float32Array(1); - floatBuffer[0] = val; - var buffer = new Uint8Array(floatBuffer.buffer, 0); - for (var i = 0; i < buffer.length; ++i) - this.buffer.memory[this.next++] = buffer[i]; + Encoder.prototype.writeUint64 = function(val) { + if (val < 0) { + throw new Error(kErrorUnsigned); + } + setUint64(this.buffer.dataView, this.next, val); + this.next += 8; + }; + + Encoder.prototype.writeFloat32 = function(val) { + this.buffer.dataView.setFloat32(val, kHostIsLittleEndian); + this.next += 4; + }; + + Encoder.prototype.writeFloat64 = function(val) { + this.buffer.dataView.setFloat64(val, kHostIsLittleEndian); + this.next += 8; }; Encoder.prototype.encodePointer = function(pointer) { if (!pointer) - return this.write64(0); + return this.writeUint64(0); // TODO(abarth): To correctly encode a pointer, we need to know the real // base address of the array buffer. var offset = pointer - this.next; - this.write64(offset); + this.writeUint64(offset); }; Encoder.prototype.createAndEncodeEncoder = function(size) { @@ -249,31 +335,24 @@ define("mojo/public/js/bindings/codec", function() { Encoder.prototype.encodeHandle = function(handle) { this.handles.push(handle); - this.write32(this.handles.length - 1); + this.writeUint32(this.handles.length - 1); }; Encoder.prototype.encodeString = function(val) { - var numberOfElements = val.length; + var base = this.next + kArrayHeaderSize; + var numberOfElements = unicode.encodeUtf8String( + val, new Uint8Array(this.buffer.arrayBuffer, base)); var numberOfBytes = kArrayHeaderSize + numberOfElements; - this.write32(numberOfBytes); - this.write32(numberOfElements); - // TODO(abarth): We should really support UTF-8. We might want to - // jump out of the VM to encode the string directly from the array - // buffer using v8::String::WriteUtf8. - var memory = this.buffer.memory; - var base = this.next; - var len = val.length; - for (var i = 0; i < len; ++i) { - memory[base + i] = val.charCodeAt(i) & 0x7F; - } - this.next += len; + this.writeUint32(numberOfBytes); + this.writeUint32(numberOfElements); + this.next += numberOfElements; }; Encoder.prototype.encodeArray = function(cls, val) { var numberOfElements = val.length; var numberOfBytes = kArrayHeaderSize + cls.encodedSize * numberOfElements; - this.write32(numberOfBytes); - this.write32(numberOfElements); + this.writeUint32(numberOfBytes); + this.writeUint32(numberOfElements); for (var i = 0; i < numberOfElements; ++i) { cls.encode(this, val[i]); } @@ -291,8 +370,7 @@ define("mojo/public/js/bindings/codec", function() { }; Encoder.prototype.encodeStringPointer = function(val) { - // TODO(abarth): This won't be right once we support UTF-8. - var encodedSize = kArrayHeaderSize + val.length; + var encodedSize = kArrayHeaderSize + unicode.utf8Length(val); var encoder = this.createAndEncodeEncoder(encodedSize); encoder.encodeString(val); }; @@ -302,19 +380,24 @@ define("mojo/public/js/bindings/codec", function() { var kMessageExpectsResponse = 1 << 0; var kMessageIsResponse = 1 << 1; - function Message(memory, handles) { - this.memory = memory; + // Skip over num_bytes, num_fields, and message_name. + var kFlagsOffset = 4 + 4 + 4; + + // Skip over num_bytes, num_fields, message_name, and flags. + var kRequestIDOffset = 4 + 4 + 4 + 4; + + function Message(buffer, handles) { + this.buffer = buffer; this.handles = handles; } Message.prototype.setRequestID = function(requestID) { // TODO(darin): Verify that space was reserved for this field! - store64(this.memory, 4 + 4 + 4 + 4, requestID); + setUint64(this.buffer.dataView, kRequestIDOffset, requestID); }; Message.prototype.getFlags = function() { - // Skip over num_bytes, num_fields, and message_name. - return load32(this.memory, 4 + 4 + 4); + return this.buffer.dataView.getUint32(kFlagsOffset, kHostIsLittleEndian); }; // MessageBuilder ----------------------------------------------------------- @@ -326,10 +409,10 @@ define("mojo/public/js/bindings/codec", function() { this.buffer = new Buffer(numberOfBytes); this.handles = []; var encoder = this.createEncoder(kMessageHeaderSize); - encoder.write32(kMessageHeaderSize); - encoder.write32(2); // num_fields. - encoder.write32(messageName); - encoder.write32(0); // flags. + encoder.writeUint32(kMessageHeaderSize); + encoder.writeUint32(2); // num_fields. + encoder.writeUint32(messageName); + encoder.writeUint32(0); // flags. } MessageBuilder.prototype.createEncoder = function(size) { @@ -344,8 +427,8 @@ define("mojo/public/js/bindings/codec", function() { MessageBuilder.prototype.finish = function() { // TODO(abarth): Rather than resizing the buffer at the end, we could // compute the size we need ahead of time, like we do in C++. - var memory = this.buffer.createViewOfAllocatedMemory(); - var message = new Message(memory, this.handles); + this.buffer.trim(); + var message = new Message(this.buffer, this.handles); this.buffer = null; this.handles = null; this.encoder = null; @@ -362,29 +445,31 @@ define("mojo/public/js/bindings/codec", function() { this.buffer = new Buffer(numberOfBytes); this.handles = []; var encoder = this.createEncoder(kMessageWithRequestIDHeaderSize); - encoder.write32(kMessageWithRequestIDHeaderSize); - encoder.write32(3); // num_fields. - encoder.write32(messageName); - encoder.write32(flags); - encoder.write64(requestID); + encoder.writeUint32(kMessageWithRequestIDHeaderSize); + encoder.writeUint32(3); // num_fields. + encoder.writeUint32(messageName); + encoder.writeUint32(flags); + encoder.writeUint64(requestID); } MessageWithRequestIDBuilder.prototype = Object.create(MessageBuilder.prototype); + MessageWithRequestIDBuilder.prototype.constructor = MessageWithRequestIDBuilder; // MessageReader ------------------------------------------------------------ function MessageReader(message) { - this.decoder = new Decoder(message.memory, message.handles, 0); - var messageHeaderSize = this.decoder.read32(); - this.payloadSize = message.memory.length - messageHeaderSize; - var numFields = this.decoder.read32(); - this.messageName = this.decoder.read32(); - this.flags = this.decoder.read32(); + this.decoder = new Decoder(message.buffer, message.handles, 0); + var messageHeaderSize = this.decoder.readUint32(); + this.payloadSize = + message.buffer.arrayBuffer.byteLength - messageHeaderSize; + var numFields = this.decoder.readUint32(); + this.messageName = this.decoder.readUint32(); + this.flags = this.decoder.readUint32(); if (numFields >= 3) - this.requestID = this.decoder.read64(); + this.requestID = this.decoder.readUint64(); this.decoder.skip(messageHeaderSize - this.decoder.next); } @@ -394,17 +479,43 @@ define("mojo/public/js/bindings/codec", function() { // Built-in types ----------------------------------------------------------- + function Int8() { + } + + Int8.encodedSize = 1; + + Int8.decode = function(decoder) { + return decoder.readInt8(); + }; + + Uint8.encode = function(encoder, val) { + encoder.writeUint8(val); + }; + function Uint8() { } Uint8.encodedSize = 1; Uint8.decode = function(decoder) { - return decoder.read8(); + return decoder.readUint8(); }; Uint8.encode = function(encoder, val) { - encoder.write8(val); + encoder.writeUint8(val); + }; + + function Int16() { + } + + Int16.encodedSize = 2; + + Int16.decode = function(decoder) { + return decoder.readInt16(); + }; + + Int16.encode = function(encoder, val) { + encoder.writeInt16(val); }; function Uint16() { @@ -413,11 +524,24 @@ define("mojo/public/js/bindings/codec", function() { Uint16.encodedSize = 2; Uint16.decode = function(decoder) { - return decoder.read16(); + return decoder.readUint16(); }; Uint16.encode = function(encoder, val) { - encoder.write16(val); + encoder.writeUint16(val); + }; + + function Int32() { + } + + Int32.encodedSize = 4; + + Int32.decode = function(decoder) { + return decoder.readInt32(); + }; + + Int32.encode = function(encoder, val) { + encoder.writeInt32(val); }; function Uint32() { @@ -426,11 +550,24 @@ define("mojo/public/js/bindings/codec", function() { Uint32.encodedSize = 4; Uint32.decode = function(decoder) { - return decoder.read32(); + return decoder.readUint32(); }; Uint32.encode = function(encoder, val) { - encoder.write32(val); + encoder.writeUint32(val); + }; + + function Int64() { + }; + + Int64.encodedSize = 8; + + Int64.decode = function(decoder) { + return decoder.readInt64(); + }; + + Int64.encode = function(encoder, val) { + encoder.writeInt64(val); }; function Uint64() { @@ -439,11 +576,11 @@ define("mojo/public/js/bindings/codec", function() { Uint64.encodedSize = 8; Uint64.decode = function(decoder) { - return decoder.read64(); + return decoder.readUint64(); }; Uint64.encode = function(encoder, val) { - encoder.write64(val); + encoder.writeUint64(val); }; function PointerTo(cls) { @@ -496,6 +633,7 @@ define("mojo/public/js/bindings/codec", function() { var exports = {}; exports.align = align; + exports.Buffer = Buffer; exports.Message = Message; exports.MessageBuilder = MessageBuilder; exports.MessageWithRequestIDBuilder = MessageWithRequestIDBuilder; @@ -505,9 +643,13 @@ define("mojo/public/js/bindings/codec", function() { exports.kMessageHeaderSize = kMessageHeaderSize; exports.kMessageExpectsResponse = kMessageExpectsResponse; exports.kMessageIsResponse = kMessageIsResponse; + exports.Int8 = Int8; exports.Uint8 = Uint8; + exports.Int16 = Int16; exports.Uint16 = Uint16; + exports.Int32 = Int32; exports.Uint32 = Uint32; + exports.Int64 = Int64; exports.Uint64 = Uint64; exports.PointerTo = PointerTo; exports.ArrayOf = ArrayOf; diff --git a/mojo/public/js/bindings/connector.js b/mojo/public/js/bindings/connector.js index f2ccb04c2e..51fb7fe96b 100644 --- a/mojo/public/js/bindings/connector.js +++ b/mojo/public/js/bindings/connector.js @@ -4,8 +4,8 @@ define("mojo/public/js/bindings/connector", [ "mojo/public/js/bindings/codec", - "mojo/bindings/js/core", - "mojo/bindings/js/support", + "mojo/public/js/bindings/core", + "mojo/public/js/bindings/support", ], function(codec, core, support) { function Connector(handle) { @@ -38,10 +38,9 @@ define("mojo/public/js/bindings/connector", [ return true; var result = core.writeMessage(this.handle_, - message.memory, + new Uint8Array(message.buffer.arrayBuffer), message.handles, core.WRITE_MESSAGE_FLAG_NONE); - switch (result) { case core.RESULT_OK: // The handles were successfully transferred, so we don't own them @@ -96,11 +95,11 @@ define("mojo/public/js/bindings/connector", [ this.errorHandler_.onError(read.result); return; } - // TODO(abarth): Should core.readMessage return a Uint8Array? - var memory = new Uint8Array(read.buffer); - var message = new codec.Message(memory, read.handles); - if (this.incomingReceiver_) - this.incomingReceiver_.accept(message); + var buffer = new codec.Buffer(read.buffer); + var message = new codec.Message(buffer, read.handles); + if (this.incomingReceiver_) { + this.incomingReceiver_.accept(message); + } } }; diff --git a/mojo/public/js/bindings/core.js b/mojo/public/js/bindings/core.js new file mode 100644 index 0000000000..389681af2d --- /dev/null +++ b/mojo/public/js/bindings/core.js @@ -0,0 +1,215 @@ +// 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. + +// Module "mojo/public/js/bindings/core" +// +// Note: This file is for documentation purposes only. The code here is not +// actually executed. The real module is implemented natively in Mojo. +// +// This module provides the JavaScript bindings for mojo/public/c/system/core.h. +// Refer to that file for more detailed documentation for equivalent methods. + +while (1); + +/** + * MojoHandle: An opaque handles to a Mojo object (e.g. a message pipe). + */ +var kInvalidHandle; + +/** + * MojoResult {number}: Result codes for Mojo operations. + * See core.h for more information. + */ +var RESULT_OK; +var RESULT_CANCELLED; +var RESULT_UNKNOWN; +var RESULT_INVALID_ARGUMENT; +var RESULT_DEADLINE_EXCEEDED; +var RESULT_NOT_FOUND; +var RESULT_ALREADY_EXISTS; +var RESULT_PERMISSION_DENIED; +var RESULT_RESOURCE_EXHAUSTED; +var RESULT_FAILED_PRECONDITION; +var RESULT_ABORTED; +var RESULT_OUT_OF_RANGE; +var RESULT_UNIMPLEMENTED; +var RESULT_INTERNAL; +var RESULT_UNAVAILABLE; +var RESULT_DATA_LOSS; +var RESULT_BUSY; +var RESULT_SHOULD_WAIT; + +/** + * MojoDeadline {number}: Used to specify deadlines (timeouts), in microseconds. + * See core.h for more information. + */ +var DEADLINE_INDEFINITE; + +/** + * MojoWaitFlags: Used to specify the state of a handle to wait on (e.g., the + * ability to read or write to it). + * See core.h for more information. + */ +var WAIT_FLAG_NONE; +var WAIT_FLAG_READABLE; +var WAIT_FLAG_WRITABLE; +var WAIT_FLAG_EVERYTHING; + +/* + * MojoWriteMessageFlags: Used to specify different modes to |writeMessage()|. + * See core.h for more information. + */ +var WRITE_MESSAGE_FLAG_NONE; + +/** + * MojoReadMessageFlags: Used to specify different modes to |readMessage()|. + * See core.h for more information. + */ +var READ_MESSAGE_FLAG_NONE; +var READ_MESSAGE_FLAG_MAY_DISCARD; + +/** + * MojoCreateDataPipeOptions: Used to specify creation parameters for a data + * pipe to |createDataPipe()|. + * See core.h for more information. + */ +dictionary MojoCreateDataPipeOptions { + MojoCreateDataPipeOptionsFlags flags; // See below. + int32 elementNumBytes; // The size of an element, in bytes. + int32 capacityNumBytes; // The capacity of the data pipe, in bytes. +}; + +// MojoCreateDataPipeOptionsFlags +var CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; +var CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD; + +/* + * MojoWriteDataFlags: Used to specify different modes to |writeData()|. + * See core.h for more information. + */ +var WRITE_DATA_FLAG_NONE; +var WRITE_DATA_FLAG_ALL_OR_NONE; + +/** + * MojoReadDataFlags: Used to specify different modes to |readData()|. + * See core.h for more information. + */ +var READ_DATA_FLAG_NONE; +var READ_DATA_FLAG_ALL_OR_NONE; +var READ_DATA_FLAG_DISCARD; +var READ_DATA_FLAG_QUERY; + +/** + * Closes the given |handle|. See MojoClose for more info. + * @param {MojoHandle} Handle to close. + * @return {MojoResult} Result code. + */ +function close(handle) { [native code] } + +/** + * Waits on the given handle until the state indicated by |waitFlags| is + * satisfied or until |deadline| is passed. See MojoWait for more information. + * + * @param {MojoHandle} handle Handle to wait on. + * @param {MojoWaitFlags} waitFlags Specifies the condition to wait for. + * @param {MojoDeadline} deadline Stops waiting if this is reached. + * @return {MojoResult} Result code. + */ +function wait(handle, waitFlags, deadline) { [native code] } + +/** + * Waits on |handles[0]|, ..., |handles[handles.length-1]| for at least one of + * them to satisfy the state indicated by |flags[0]|, ..., + * |flags[handles.length-1]|, respectively, or until |deadline| has passed. + * See MojoWaitMany for more information. + * + * @param {Array.MojoHandle} handles Handles to wait on. + * @param {Array.MojoWaitFlags} waitFlags Specifies the condition to wait for, + * for each corresponding handle. Must be the same length as |handles|. + * @param {MojoDeadline} deadline Stops waiting if this is reached. + * @return {MojoResult} Result code. + */ +function waitMany(handles, waitFlags, deadline) { [native code] } + +/** + * Creates a message pipe. This function always succeeds. + * See MojoCreateMessagePipe for more information on message pipes. + * + * @return {MessagePipe} An object of the form { + * handle0, + * handle1, + * } + * where |handle0| and |handle1| are MojoHandles to each end of the channel. + */ +function createMessagePipe() { [native code] } + +/** + * Writes a message to the message pipe endpoint given by |handle|. See + * MojoWriteMessage for more information, including return codes. + * + * @param {MojoHandle} handle The endpoint to write to. + * @param {ArrayBufferView} buffer The message data. May be empty. + * @param {Array.MojoHandle} handlesArray Any handles to attach. Handles are + * transferred on success and will no longer be valid. May be empty. + * @param {MojoWriteMessageFlags} flags Flags. + * @return {MojoResult} Result code. + */ +function writeMessage(handle, buffer, handlesArray, flags) { [native code] } + +/** + * Reads a message from the message pipe endpoint given by |handle|. See + * MojoReadMessage for more information, including return codes. + * + * @param {MojoHandle} handle The endpoint to read from. + * @param {MojoReadMessageFlags} flags Flags. + * @return {object} An object of the form { + * result, // |RESULT_OK| on success, error code otherwise. + * buffer, // An ArrayBufferView of the message data (only on success). + * handles // An array of MojoHandles transferred, if any. + * } + */ +function readMessage(handle, flags) { [native code] } + +/** + * Creates a data pipe, which is a unidirectional communication channel for + * unframed data, with the given options. See MojoCreateDataPipe for more + * more information, including return codes. + * + * @param {MojoCreateDataPipeOptions} optionsDict Options to control the data + * pipe parameters. May be null. + * @return {object} An object of the form { + * result, // |RESULT_OK| on success, error code otherwise. + * producerHandle, // MojoHandle to use with writeData (only on success). + * consumerHandle, // MojoHandle to use with readData (only on success). + * } + */ +function createDataPipe(optionsDict) { [native code] } + +/** + * Writes the given data to the data pipe producer given by |handle|. See + * MojoWriteData for more information, including return codes. + * + * @param {MojoHandle} handle A producerHandle returned by createDataPipe. + * @param {ArrayBufferView} buffer The data to write. + * @param {MojoWriteDataFlags} flags Flags. + * @return {object} An object of the form { + * result, // |RESULT_OK| on success, error code otherwise. + * numBytes, // The number of bytes written. + * } + */ +function writeData(handle, buffer, flags) { [native code] } + +/** + * Reads data from the data pipe consumer given by |handle|. May also + * be used to discard data. See MojoReadData for more information, including + * return codes. + * + * @param {MojoHandle} handle A consumerHandle returned by createDataPipe. + * @param {MojoReadDataFlags} flags Flags. + * @return {object} An object of the form { + * result, // |RESULT_OK| on success, error code otherwise. + * buffer, // An ArrayBufferView of the data read (only on success). + * } + */ +function readData(handle, flags) { [native code] } diff --git a/mojo/public/js/bindings/support.js b/mojo/public/js/bindings/support.js new file mode 100644 index 0000000000..756e7ba70c --- /dev/null +++ b/mojo/public/js/bindings/support.js @@ -0,0 +1,30 @@ +// 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. + +// Module "mojo/public/js/bindings/support" +// +// Note: This file is for documentation purposes only. The code here is not +// actually executed. The real module is implemented natively in Mojo. + +while (1); + +/* + * Waits on the given handle until the state indicated by |waitFlags| is + * satisfied. + * + * @param {MojoHandle} handle The handle to wait on. + * @param {MojoWaitFlags} waitFlags Flags. + * @param {function (mojoResult)} callback Called with the result the wait is + * complete. See MojoWait for possible result codes. + * + * @return {MojoWaitId} A waitId that can be passed to cancelWait to cancel the + * wait. + */ +function asyncWait(handle, waitFlags, callback) { [native code] } + +/* + * Cancels the asyncWait operation specified by the given |waitId|. + * @param {MojoWaitId} waitId The waitId returned by asyncWait. + */ +function cancelWait(waitId) { [native code] } diff --git a/mojo/public/js/bindings/unicode.js b/mojo/public/js/bindings/unicode.js new file mode 100644 index 0000000000..a42c710be4 --- /dev/null +++ b/mojo/public/js/bindings/unicode.js @@ -0,0 +1,33 @@ +// 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. + +// Module "mojo/public/js/bindings/unicode" +// +// Note: This file is for documentation purposes only. The code here is not +// actually executed. The real module is implemented natively in Mojo. + +while (1); + +/** + * Decodes the UTF8 string from the given buffer. + * @param {ArrayBufferView} buffer The buffer containing UTF8 string data. + * @return {string} The corresponding JavaScript string. + */ +function decodeUtf8String(buffer) { [native code] } + +/** + * Encodes the given JavaScript string into UTF8. + * @param {string} str The string to encode. + * @param {ArrayBufferView} outputBuffer The buffer to contain the result. + * Should be pre-allocated to hold enough space. Use |utf8Length| to determine + * how much space is required. + * @return {number} The number of bytes written to |outputBuffer|. + */ +function encodeUtf8String(str, outputBuffer) { [native code] } + +/** + * Returns the number of bytes that a UTF8 encoding of the JavaScript string + * |str| would occupy. + */ +function utf8Length(str) { [native code] } diff --git a/mojo/public/tools/bindings/generators/cpp_templates/enum_traits.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/enum_traits.tmpl new file mode 100644 index 0000000000..3096839321 --- /dev/null +++ b/mojo/public/tools/bindings/generators/cpp_templates/enum_traits.tmpl @@ -0,0 +1,5 @@ +template <> struct TypeTraits<{% for namespace in namespaces_as_array -%} +{{namespace}}::{% endfor %}{{enum.name}}> { + static const bool kIsHandle = false; + static const bool kIsObject = false; +}; diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl index 5b61e173ca..60fbfc52c7 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl @@ -23,12 +23,6 @@ class {{interface.name}} { {#--- Methods #} {%- for method in interface.methods %} - virtual void {{method.name}}({{interface_macros.declare_request_params(method)}}) = 0; + virtual void {{method.name}}({{interface_macros.declare_request_params("", method)}}) = 0; {%- endfor %} }; - -// A typesafe variant of MessagePipeHandle. -typedef mojo::Interface<{{interface.name}}>::Handle {{interface.name}}Handle; - -// A typesafe variant of ScopedMessagePipeHandle. -typedef mojo::Interface<{{interface.name}}>::ScopedHandle Scoped{{interface.name}}Handle; diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl index 906099cd18..4910463d80 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl @@ -97,7 +97,7 @@ bool {{class_name}}_{{method.name}}_ForwardToCallback::Accept( {%- set params_name = "internal::%s_%s_Params_Data"|format(interface.name, method.name) %} void {{proxy_name}}::{{method.name}}( - {{interface_macros.declare_request_params(method)}}) { + {{interface_macros.declare_request_params("in_", method)}}) { {{compute_payload_size(params_name, method.parameters)}} {%- if method.response_parameters != None %} @@ -140,7 +140,7 @@ class {{class_name}}_{{method.name}}_ProxyToResponder responder_(responder) { } - virtual void Run({{interface_macros.declare_params(method.response_parameters)}}) const; + virtual void Run({{interface_macros.declare_params("in_", method.response_parameters)}}) const; private: uint64_t request_id_; @@ -148,7 +148,7 @@ class {{class_name}}_{{method.name}}_ProxyToResponder MOJO_DISALLOW_COPY_AND_ASSIGN({{class_name}}_{{method.name}}_ProxyToResponder); }; void {{class_name}}_{{method.name}}_ProxyToResponder::Run( - {{interface_macros.declare_params(method.response_parameters)}}) const { + {{interface_macros.declare_params("in_", method.response_parameters)}}) const { {{compute_payload_size(params_name, method.response_parameters)}} mojo::internal::ResponseMessageBuilder builder( {{message_name}}, payload_size, request_id_); diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl index 70b6091821..fbefce2d39 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl @@ -1,6 +1,6 @@ -{%- macro declare_params(parameters) %} +{%- macro declare_params(prefix, parameters) %} {%- for param in parameters -%} -{{param.kind|cpp_const_wrapper_type}} in_{{param.name}} +{{param.kind|cpp_const_wrapper_type}} {{prefix}}{{param.name}} {%- if not loop.last %}, {% endif %} {%- endfor %} {%- endmacro %} @@ -14,8 +14,8 @@ mojo::Callback<void( )> {%- endmacro -%} -{%- macro declare_request_params(method) -%} -{{declare_params(method.parameters)}} +{%- macro declare_request_params(prefix, method) -%} +{{declare_params(prefix, method.parameters)}} {%- if method.response_parameters != None -%} {%- if method.parameters %}, {% endif %} const {{declare_callback(method)}}& callback diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl index ff7c327c6d..c4a8bed632 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl @@ -5,7 +5,7 @@ class {{interface.name}}Proxy : public {{interface.name}} { {%- for method in interface.methods %} virtual void {{method.name}}( - {{interface_macros.declare_request_params(method)}} + {{interface_macros.declare_request_params("", method)}} ) MOJO_OVERRIDE; {%- endfor %} diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl index e804fc638d..df545a8810 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl @@ -13,9 +13,9 @@ #include "{{import.module.path}}-internal.h" {%- endfor %} -{%- if namespace %} +{%- for namespace in namespaces_as_array %} namespace {{namespace}} { -{%- endif %} +{%- endfor %} {#--- Wrapper forward declarations #} {% for struct in structs %} @@ -34,8 +34,8 @@ namespace internal { #pragma pack(pop) } // namespace internal -{%- if namespace %} +{%- for namespace in namespaces_as_array|reverse %} } // namespace {{namespace}} -{%- endif %} +{%- endfor %} #endif // {{header_guard}} diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl index d99a3e2424..4e423aa844 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl @@ -12,9 +12,9 @@ #include "mojo/public/cpp/bindings/lib/bindings_serialization.h" #include "mojo/public/cpp/bindings/lib/message_builder.h" -{%- if namespace %} +{%- for namespace in namespaces_as_array %} namespace {{namespace}} { -{%- endif %} +{%- endfor %} namespace internal { namespace { @@ -59,9 +59,9 @@ const uint32_t {{method_name}} = {{method.ordinal}}; {%- for interface in interfaces %} {%- include "interface_definition.tmpl" %} {%- endfor %} -{%- if namespace %} +{%- for namespace in namespaces_as_array|reverse %} } // namespace {{namespace}} -{%- endif %} +{%- endfor %} #if defined(__clang__) #pragma clang diagnostic pop diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl index c2233861c3..4c667aee9d 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl @@ -16,15 +16,24 @@ #include "{{import.module.path}}.h" {%- endfor %} -{%- if namespace %} +{%- for namespace in namespaces_as_array %} namespace {{namespace}} { -{%- endif %} +{%- endfor %} {#--- Enums #} {% for enum in enums %} {% include "enum_declaration.tmpl" %} {%- endfor %} +{#--- Interface Forward Declarations -#} +{% for interface in interfaces %} +class {{interface.name}}; +// A typesafe variant of MessagePipeHandle: +typedef mojo::Interface<{{interface.name}}>::Handle {{interface.name}}Handle; +// A typesafe variant of ScopedMessagePipeHandle: +typedef mojo::Interface<{{interface.name}}>::ScopedHandle Scoped{{interface.name}}Handle; +{% endfor %} + {#--- Structs #} {% for struct in structs %} {% include "wrapper_class_declaration.tmpl" %} @@ -45,8 +54,19 @@ namespace {{namespace}} { {% include "interface_stub_declaration.tmpl" %} {%- endfor %} -{%- if namespace %} +{%- for namespace in namespaces_as_array|reverse %} } // namespace {{namespace}} +{%- endfor %} + +{#--- Enum TypeTraits Specializations #} +{% if enums %} +namespace mojo { +namespace internal { +{% for enum in enums %} +{% include "enum_traits.tmpl" %} +{%- endfor %} +} // namespace internal +} // namespace mojo {%- endif %} #endif // {{header_guard}} diff --git a/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl b/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl index 08c5a9721f..9b3046825c 100644 --- a/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl +++ b/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl @@ -3,7 +3,7 @@ // found in the LICENSE file. define("{{module.path}}", [ - "mojo/bindings/js/core", + "mojo/public/js/bindings/core", "mojo/public/js/bindings/codec", {%- for import in imports %} "{{import.module.path}}", diff --git a/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl b/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl index 1686820a7e..6db102ce8e 100644 --- a/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl +++ b/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl @@ -74,11 +74,11 @@ this.{{packed_field.field.name}} = {{result}}; {{struct.name}}.decode = function(decoder) { var packed; var val = new {{struct.name}}(); - var numberOfBytes = decoder.read32(); - var numberOfFields = decoder.read32(); + var numberOfBytes = decoder.readUint32(); + var numberOfFields = decoder.readUint32(); {%- for byte in struct.bytes %} {%- if byte.packed_fields|length > 1 %} - packed = decoder.read8(); + packed = decoder.readUint8(); {%- for packed_field in byte.packed_fields %} val.{{packed_field.field.name}} = (packed >> {{packed_field.bit}}) & 1 ? true : false; {%- endfor %} @@ -96,8 +96,8 @@ this.{{packed_field.field.name}} = {{result}}; {{struct.name}}.encode = function(encoder, val) { var packed; - encoder.write32({{struct.name}}.encodedSize); - encoder.write32({{struct.packed.packed_fields|length}}); + encoder.writeUint32({{struct.name}}.encodedSize); + encoder.writeUint32({{struct.packed.packed_fields|length}}); {%- for byte in struct.bytes %} {%- if byte.packed_fields|length > 1 %} @@ -105,7 +105,7 @@ this.{{packed_field.field.name}} = {{result}}; {%- for packed_field in byte.packed_fields %} packed |= (val.{{packed_field.field.name}} & 1) << {{packed_field.bit}} {%- endfor %} - encoder.write8(packed); + encoder.writeUint8(packed); {%- else %} {%- for packed_field in byte.packed_fields %} encoder.{{packed_field.field.kind|encode_snippet}}val.{{packed_field.field.name}}); diff --git a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py index a95e711d85..8f48f8e06f 100644 --- a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py +++ b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py @@ -4,11 +4,10 @@ """Generates C++ source files from a mojom.Module.""" -from generate import mojom -from generate import mojom_pack -from generate import mojom_generator - -from generate.template_expander import UseJinja +import mojom.generate.generator as generator +import mojom.generate.module as mojom +import mojom.generate.pack as pack +from mojom.generate.template_expander import UseJinja _kind_to_cpp_type = { @@ -31,10 +30,13 @@ _kind_to_cpp_type = { } +def NamespaceToArray(namespace): + return namespace.split('.') if namespace else [] + def GetNameForKind(kind, internal = False): parts = [] if kind.imported_from: - parts.append(kind.imported_from["namespace"]) + parts.extend(NamespaceToArray(kind.imported_from["namespace"])) if internal: parts.append("internal") if kind.parent_kind: @@ -96,7 +98,7 @@ def GetCppWrapperType(kind): return "mojo::Passable<%sHandle>" % kind.name if kind.spec == 's': return "mojo::String" - if mojom_generator.IsHandleKind(kind): + if generator.IsHandleKind(kind): return "mojo::Passable<%s>" % _kind_to_cpp_type[kind] return _kind_to_cpp_type[kind] @@ -141,7 +143,7 @@ def GetCppFieldType(kind): def IsStructWithHandles(struct): for pf in struct.packed.packed_fields: - if mojom_generator.IsHandleKind(pf.field.kind): + if generator.IsHandleKind(pf.field.kind): return True return False @@ -151,7 +153,7 @@ def TranslateConstants(token, module): # Namespace::Struct::FIELD_NAME name = [] if token.imported_from: - name.append(token.namespace) + name.extend(NamespaceToArray(token.namespace)) if token.parent_kind: name.append(token.parent_kind.name) name.append(token.name[1]) @@ -161,12 +163,12 @@ def TranslateConstants(token, module): def ExpressionToText(value, module): if value[0] != "EXPRESSION": raise Exception("Expected EXPRESSION, got" + value) - return "".join(mojom_generator.ExpressionMapper(value, + return "".join(generator.ExpressionMapper(value, lambda token: TranslateConstants(token, module))) _HEADER_SIZE = 8 -class Generator(mojom_generator.Generator): +class Generator(generator.Generator): cpp_filters = { "cpp_const_wrapper_type": GetCppConstWrapperType, @@ -175,24 +177,25 @@ class Generator(mojom_generator.Generator): "cpp_result_type": GetCppResultWrapperType, "cpp_wrapper_type": GetCppWrapperType, "expression_to_text": ExpressionToText, - "get_pad": mojom_pack.GetPad, - "is_enum_kind": mojom_generator.IsEnumKind, - "is_handle_kind": mojom_generator.IsHandleKind, - "is_object_kind": mojom_generator.IsObjectKind, - "is_string_kind": mojom_generator.IsStringKind, + "get_pad": pack.GetPad, + "is_enum_kind": generator.IsEnumKind, + "is_handle_kind": generator.IsHandleKind, + "is_object_kind": generator.IsObjectKind, + "is_string_kind": generator.IsStringKind, "is_array_kind": lambda kind: isinstance(kind, mojom.Array), "is_struct_with_handles": IsStructWithHandles, "struct_size": lambda ps: ps.GetTotalSize() + _HEADER_SIZE, - "struct_from_method": mojom_generator.GetStructFromMethod, - "response_struct_from_method": mojom_generator.GetResponseStructFromMethod, - "stylize_method": mojom_generator.StudlyCapsToCamel, - "verify_token_type": mojom_generator.VerifyTokenType, + "struct_from_method": generator.GetStructFromMethod, + "response_struct_from_method": generator.GetResponseStructFromMethod, + "stylize_method": generator.StudlyCapsToCamel, + "verify_token_type": generator.VerifyTokenType, } def GetJinjaExports(self): return { "module": self.module, "namespace": self.module.namespace, + "namespaces_as_array": NamespaceToArray(self.module.namespace), "imports": self.module.imports, "kinds": self.module.kinds, "enums": self.module.enums, diff --git a/mojo/public/tools/bindings/generators/mojom_js_generator.py b/mojo/public/tools/bindings/generators/mojom_js_generator.py index b3d572f27c..53672a2677 100644 --- a/mojo/public/tools/bindings/generators/mojom_js_generator.py +++ b/mojo/public/tools/bindings/generators/mojom_js_generator.py @@ -4,11 +4,10 @@ """Generates JavaScript source files from a mojom.Module.""" -from generate import mojom -from generate import mojom_pack -from generate import mojom_generator - -from generate.template_expander import UseJinja +import mojom.generate.generator as generator +import mojom.generate.module as mojom +import mojom.generate.pack as pack +from mojom.generate.template_expander import UseJinja _kind_to_javascript_default_value = { mojom.BOOL: "false", @@ -52,7 +51,7 @@ def JavaScriptPayloadSize(packed): return 0; last_field = packed_fields[-1] offset = last_field.offset + last_field.size - pad = mojom_pack.GetPad(offset, 8) + pad = pack.GetPad(offset, 8) return offset + pad; @@ -92,21 +91,21 @@ def GetJavaScriptType(kind): _kind_to_javascript_decode_snippet = { - mojom.BOOL: "read8() & 1", - mojom.INT8: "read8()", - mojom.UINT8: "read8()", - mojom.INT16: "read16()", - mojom.UINT16: "read16()", - mojom.INT32: "read32()", - mojom.UINT32: "read32()", + mojom.BOOL: "readUint8() & 1", + mojom.INT8: "readInt8()", + mojom.UINT8: "readUint8()", + mojom.INT16: "readInt16()", + mojom.UINT16: "readUint16()", + mojom.INT32: "readInt32()", + mojom.UINT32: "readUint32()", mojom.FLOAT: "decodeFloat()", mojom.HANDLE: "decodeHandle()", mojom.DCPIPE: "decodeHandle()", mojom.DPPIPE: "decodeHandle()", mojom.MSGPIPE: "decodeHandle()", mojom.SHAREDBUFFER: "decodeHandle()", - mojom.INT64: "read64()", - mojom.UINT64: "read64()", + mojom.INT64: "readInt64()", + mojom.UINT64: "readUint64()", mojom.DOUBLE: "decodeDouble()", mojom.STRING: "decodeStringPointer()", } @@ -126,21 +125,21 @@ def JavaScriptDecodeSnippet(kind): _kind_to_javascript_encode_snippet = { - mojom.BOOL: "write8(1 & ", - mojom.INT8: "write8(", - mojom.UINT8: "write8(", - mojom.INT16: "write16(", - mojom.UINT16: "write16(", - mojom.INT32: "write32(", - mojom.UINT32: "write32(", + mojom.BOOL: "writeUint8(1 & ", + mojom.INT8: "writeInt8(", + mojom.UINT8: "writeUint8(", + mojom.INT16: "writeInt16(", + mojom.UINT16: "writeUint16(", + mojom.INT32: "writeInt32(", + mojom.UINT32: "writeUint32(", mojom.FLOAT: "encodeFloat(", mojom.HANDLE: "encodeHandle(", mojom.DCPIPE: "encodeHandle(", mojom.DPPIPE: "encodeHandle(", mojom.MSGPIPE: "encodeHandle(", mojom.SHAREDBUFFER: "encodeHandle(", - mojom.INT64: "write64(", - mojom.UINT64: "write64(", + mojom.INT64: "writeInt64(", + mojom.UINT64: "writeUint64(", mojom.DOUBLE: "encodeDouble(", mojom.STRING: "encodeStringPointer(", } @@ -177,7 +176,7 @@ def TranslateConstants(token, module): def ExpressionToText(value, module): if value[0] != "EXPRESSION": raise Exception("Expected EXPRESSION, got" + value) - return "".join(mojom_generator.ExpressionMapper(value, + return "".join(generator.ExpressionMapper(value, lambda token: TranslateConstants(token, module))) @@ -187,7 +186,7 @@ def JavascriptType(kind): return kind.name -class Generator(mojom_generator.Generator): +class Generator(generator.Generator): js_filters = { "default_value": JavaScriptDefaultValue, @@ -195,12 +194,12 @@ class Generator(mojom_generator.Generator): "decode_snippet": JavaScriptDecodeSnippet, "encode_snippet": JavaScriptEncodeSnippet, "expression_to_text": ExpressionToText, - "is_object_kind": mojom_generator.IsObjectKind, - "is_string_kind": mojom_generator.IsStringKind, + "is_object_kind": generator.IsObjectKind, + "is_string_kind": generator.IsStringKind, "is_array_kind": lambda kind: isinstance(kind, mojom.Array), "js_type": JavascriptType, - "stylize_method": mojom_generator.StudlyCapsToCamel, - "verify_token_type": mojom_generator.VerifyTokenType, + "stylize_method": generator.StudlyCapsToCamel, + "verify_token_type": generator.VerifyTokenType, } @UseJinja("js_templates/module.js.tmpl", filters=js_filters) diff --git a/mojo/public/tools/bindings/generators/run_cpp_generator.py b/mojo/public/tools/bindings/generators/run_cpp_generator.py index 36ef8bc9ed..8a80a46839 100755 --- a/mojo/public/tools/bindings/generators/run_cpp_generator.py +++ b/mojo/public/tools/bindings/generators/run_cpp_generator.py @@ -10,7 +10,7 @@ import sys script_dir = os.path.dirname(os.path.realpath(__file__)) sys.path.insert(0, os.path.join(script_dir, os.pardir, "pylib")) -from generate import mojom_data +from mojom.generate.data import mojom_cpp_generator def ReadDict(file): @@ -20,7 +20,7 @@ def ReadDict(file): return dict dict = ReadDict(sys.argv[1]) -module = mojom_data.ModuleFromData(dict) +module = mojom.generate.data.ModuleFromData(dict) dir = None if len(sys.argv) > 2: dir = sys.argv[2] diff --git a/mojo/public/tools/bindings/mojom_bindings_generator.gypi b/mojo/public/tools/bindings/mojom_bindings_generator.gypi index 5778c9ccc7..de20ce4b24 100644 --- a/mojo/public/tools/bindings/mojom_bindings_generator.gypi +++ b/mojo/public/tools/bindings/mojom_bindings_generator.gypi @@ -39,16 +39,17 @@ '<(DEPTH)/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl', '<(DEPTH)/mojo/public/tools/bindings/generators/mojom_cpp_generator.py', '<(DEPTH)/mojo/public/tools/bindings/generators/mojom_js_generator.py', - '<(DEPTH)/mojo/public/tools/bindings/pylib/parse/__init__.py', - '<(DEPTH)/mojo/public/tools/bindings/pylib/parse/mojo_lexer.py', - '<(DEPTH)/mojo/public/tools/bindings/pylib/parse/mojo_parser.py', - '<(DEPTH)/mojo/public/tools/bindings/pylib/parse/mojo_translate.py', - '<(DEPTH)/mojo/public/tools/bindings/pylib/generate/__init__.py', - '<(DEPTH)/mojo/public/tools/bindings/pylib/generate/mojom.py', - '<(DEPTH)/mojo/public/tools/bindings/pylib/generate/mojom_data.py', - '<(DEPTH)/mojo/public/tools/bindings/pylib/generate/mojom_generator.py', - '<(DEPTH)/mojo/public/tools/bindings/pylib/generate/mojom_pack.py', - '<(DEPTH)/mojo/public/tools/bindings/pylib/generate/template_expander.py', + '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/generate/__init__.py', + '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/generate/data.py', + '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/generate/generator.py', + '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/generate/module.py', + '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/generate/pack.py', + '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py', + '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/parse/__init__.py', + '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/parse/ast.py', + '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/parse/lexer.py', + '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/parse/parser.py', + '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/parse/translate.py', ], 'outputs': [ '<(SHARED_INTERMEDIATE_DIR)/<(mojom_base_output_dir)/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).mojom.cc', diff --git a/mojo/public/tools/bindings/mojom_bindings_generator.py b/mojo/public/tools/bindings/mojom_bindings_generator.py index a9d8b681e6..643f46840a 100755 --- a/mojo/public/tools/bindings/mojom_bindings_generator.py +++ b/mojo/public/tools/bindings/mojom_bindings_generator.py @@ -12,13 +12,13 @@ import os import pprint import sys -script_dir = os.path.dirname(os.path.realpath(__file__)) +script_dir = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, os.path.join(script_dir, "pylib")) -from generate import mojom_data -from parse import mojo_lexer -from parse import mojo_parser -from parse import mojo_translate +from mojom.generate.data import OrderedModuleFromData +from mojom.parse.lexer import LexError +from mojom.parse.parser import Parse, ParseError +from mojom.parse.translate import Translate def LoadGenerators(generators_string): @@ -46,11 +46,13 @@ def LoadGenerators(generators_string): return generators -def _PrintImportStack(imported_filename_stack): - """Prints a chain of imports, given by imported_filename_stack.""" - for i in reversed(xrange(0, len(imported_filename_stack)-1)): - print " %s was imported by %s" % (imported_filename_stack[i+1], - imported_filename_stack[i]) +def MakeImportStackMessage(imported_filename_stack): + """Make a (human-readable) message listing a chain of imports. (Returned + string begins with a newline (if nonempty) and does not end with one.)""" + return ''.join( + reversed(["\n %s was imported by %s" % (a, b) for (a, b) in \ + zip(imported_filename_stack[1:], imported_filename_stack)])) + def ProcessFile(args, generator_modules, filename, processed_files={}, imported_filename_stack=[]): @@ -60,27 +62,26 @@ def ProcessFile(args, generator_modules, filename, processed_files={}, # Ensure we only visit each file once. if filename in imported_filename_stack: - print "%s: Error: Circular dependency" % filename - _PrintImportStack(imported_filename_stack + [filename]) + print "%s: Error: Circular dependency" % filename + \ + MakeImportStackMessage(imported_filename_stack + [filename]) sys.exit(1) try: with open(filename) as f: source = f.read() except IOError as e: - print "%s: Error: %s" % (e.filename, e.strerror) - _PrintImportStack(imported_filename_stack + [filename]) + print "%s: Error: %s" % (e.filename, e.strerror) + \ + MakeImportStackMessage(imported_filename_stack + [filename]) sys.exit(1) try: - tree = mojo_parser.Parse(source, filename) - except (mojo_lexer.LexError, mojo_parser.ParseError) as e: - print e - _PrintImportStack(imported_filename_stack + [filename]) + tree = Parse(source, filename) + except (LexError, ParseError) as e: + print str(e) + MakeImportStackMessage(imported_filename_stack + [filename]) sys.exit(1) dirname, name = os.path.split(filename) - mojom = mojo_translate.Translate(tree, name) + mojom = Translate(tree, name) if args.debug_print_intermediate: pprint.PrettyPrinter().pprint(mojom) @@ -93,7 +94,7 @@ def ProcessFile(args, generator_modules, filename, processed_files={}, processed_files=processed_files, imported_filename_stack=imported_filename_stack + [filename]) - module = mojom_data.OrderedModuleFromData(mojom) + module = OrderedModuleFromData(mojom) # Set the path as relative to the source root. module.path = os.path.relpath(os.path.abspath(filename), diff --git a/mojo/public/tools/bindings/mojom_bindings_generator_unittest.py b/mojo/public/tools/bindings/mojom_bindings_generator_unittest.py new file mode 100644 index 0000000000..de388561cb --- /dev/null +++ b/mojo/public/tools/bindings/mojom_bindings_generator_unittest.py @@ -0,0 +1,23 @@ +# 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 unittest + +from mojom_bindings_generator import MakeImportStackMessage + + +class MojoBindingsGeneratorTest(unittest.TestCase): + """Tests mojo_bindings_generator.""" + + def testMakeImportStackMessage(self): + """Tests MakeImportStackMessage().""" + self.assertEquals(MakeImportStackMessage(["x"]), "") + self.assertEquals(MakeImportStackMessage(["x", "y"]), + "\n y was imported by x") + self.assertEquals(MakeImportStackMessage(["x", "y", "z"]), + "\n z was imported by y\n y was imported by x") + + +if __name__ == "__main__": + unittest.main() diff --git a/mojo/public/tools/bindings/pylib/parse/__init__.py b/mojo/public/tools/bindings/pylib/mojom/__init__.py index e69de29bb2..e69de29bb2 100644 --- a/mojo/public/tools/bindings/pylib/parse/__init__.py +++ b/mojo/public/tools/bindings/pylib/mojom/__init__.py diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/__init__.py b/mojo/public/tools/bindings/pylib/mojom/generate/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/mojo/public/tools/bindings/pylib/mojom/generate/__init__.py diff --git a/mojo/public/tools/bindings/pylib/generate/mojom_data.py b/mojo/public/tools/bindings/pylib/mojom/generate/data.py index ce9bc182ce..ffbffde606 100644 --- a/mojo/public/tools/bindings/pylib/generate/mojom_data.py +++ b/mojo/public/tools/bindings/pylib/mojom/generate/data.py @@ -2,10 +2,13 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import mojom +# TODO(vtl): "data" is a pretty vague name. Rename it? + import copy -# mojom_data provides a mechanism to turn mojom Modules to dictionaries and +import module as mojom + +# This module provides a mechanism to turn mojom Modules to dictionaries and # back again. This can be used to persist a mojom Module created progromatically # or to read a dictionary from code or a file. # Example: @@ -26,7 +29,7 @@ import copy # {'name': 'bar', 'kind': 'a:x:teststruct'}], # 'ordinal': 42}]}] # } -# test_module = mojom_data.ModuleFromData(test_dict) +# test_module = data.ModuleFromData(test_dict) # Used to create a subclass of str that supports sorting by index, to make # pretty printing maintain the order. @@ -133,8 +136,8 @@ def StructFromData(module, data): module.kinds[struct.spec] = struct struct.enums = map(lambda enum: EnumFromData(module, enum, struct), data['enums']) - struct.fields = map(lambda field: - FieldFromData(module, field, struct), data['fields']) + # Stash fields data here temporarily. + struct.fields_data = data['fields'] return struct def FieldToData(field): @@ -231,8 +234,8 @@ def InterfaceFromData(module, data): module.kinds[interface.spec] = interface interface.enums = map(lambda enum: EnumFromData(module, enum, interface), data['enums']) - interface.methods = map(lambda method: - MethodFromData(module, method, interface), data['methods']) + # Stash methods data here temporarily. + interface.methods_data = data['methods'] return interface def EnumFieldFromData(module, enum, data, parent_kind): @@ -286,6 +289,8 @@ def ModuleFromData(data): module.imports = map( lambda import_data: ImportFromData(module, import_data), data['imports']) + + # First pass collects kinds. module.enums = map( lambda enum: EnumFromData(module, enum, None), data['enums']) module.structs = map( @@ -294,6 +299,17 @@ def ModuleFromData(data): lambda interface: InterfaceFromData(module, interface), data['interfaces']) + # Second pass expands fields and methods. This allows fields and parameters + # to refer to kinds defined anywhere in the mojom. + for struct in module.structs: + struct.fields = map(lambda field: + FieldFromData(module, field, struct), struct.fields_data) + del struct.fields_data + for interface in module.interfaces: + interface.methods = map(lambda method: + MethodFromData(module, method, interface), interface.methods_data) + del interface.methods_data + return module def OrderedModuleFromData(data): diff --git a/mojo/public/tools/bindings/pylib/generate/mojom_data_tests.py b/mojo/public/tools/bindings/pylib/mojom/generate/data_tests.py index 7f622e4adf..bca7ed83cc 100644 --- a/mojo/public/tools/bindings/pylib/generate/mojom_data_tests.py +++ b/mojo/public/tools/bindings/pylib/mojom/generate/data_tests.py @@ -2,13 +2,14 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import mojom_data -import mojom_test import sys -EXPECT_EQ = mojom_test.EXPECT_EQ -EXPECT_TRUE = mojom_test.EXPECT_TRUE -RunTest = mojom_test.RunTest +import data +import test_support + +EXPECT_EQ = test_support.EXPECT_EQ +EXPECT_TRUE = test_support.EXPECT_TRUE +RunTest = test_support.RunTest def DeepEquals(d1, d2): @@ -54,22 +55,22 @@ test_dict = { def TestRead(): - module = mojom_data.ModuleFromData(test_dict) - return mojom_test.TestTestModule(module) + module = data.ModuleFromData(test_dict) + return test_support.TestTestModule(module) def TestWrite(): - module = mojom_test.BuildTestModule() - d = mojom_data.ModuleToData(module) + module = test_support.BuildTestModule() + d = data.ModuleToData(module) return EXPECT_TRUE(DeepEquals(test_dict, d)) def TestWriteRead(): - module1 = mojom_test.BuildTestModule() + module1 = test_support.BuildTestModule() - dict1 = mojom_data.ModuleToData(module1) - module2 = mojom_data.ModuleFromData(dict1) - return EXPECT_TRUE(mojom_test.ModulesAreEqual(module1, module2)) + dict1 = data.ModuleToData(module1) + module2 = data.ModuleFromData(dict1) + return EXPECT_TRUE(test_support.ModulesAreEqual(module1, module2)) def Main(args): diff --git a/mojo/public/tools/bindings/pylib/generate/mojom_generator.py b/mojo/public/tools/bindings/pylib/mojom/generate/generator.py index 131c248433..1984204d32 100644 --- a/mojo/public/tools/bindings/pylib/generate/mojom_generator.py +++ b/mojo/public/tools/bindings/pylib/mojom/generate/generator.py @@ -4,11 +4,12 @@ """Code shared by the various language-specific code generators.""" +from functools import partial import os -import mojom -import mojom_pack import re -from functools import partial + +import module as mojom +import pack def GetStructFromMethod(interface, method): """Converts a method's parameters into the fields of a struct.""" @@ -16,7 +17,7 @@ def GetStructFromMethod(interface, method): struct = mojom.Struct(params_class) for param in method.parameters: struct.AddField(param.name, param.kind, param.ordinal) - struct.packed = mojom_pack.PackedStruct(struct) + struct.packed = pack.PackedStruct(struct) return struct def GetResponseStructFromMethod(interface, method): @@ -25,12 +26,12 @@ def GetResponseStructFromMethod(interface, method): struct = mojom.Struct(params_class) for param in method.response_parameters: struct.AddField(param.name, param.kind, param.ordinal) - struct.packed = mojom_pack.PackedStruct(struct) + struct.packed = pack.PackedStruct(struct) return struct def GetStructInfo(exported, struct): - struct.packed = mojom_pack.PackedStruct(struct) - struct.bytes = mojom_pack.GetByteLayout(struct.packed) + struct.packed = pack.PackedStruct(struct) + struct.bytes = pack.GetByteLayout(struct.packed) struct.exported = exported return struct diff --git a/mojo/public/tools/bindings/pylib/generate/mojom.py b/mojo/public/tools/bindings/pylib/mojom/generate/module.py index 4c5e413ebc..d24d36fbc0 100644 --- a/mojo/public/tools/bindings/pylib/generate/mojom.py +++ b/mojo/public/tools/bindings/pylib/mojom/generate/module.py @@ -2,11 +2,12 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# mojom's classes provide an interface to mojo modules. Modules are collections -# of interfaces and structs to be used by mojo ipc clients and servers. +# This module's classes provide an interface to mojo modules. Modules are +# collections of interfaces and structs to be used by mojo ipc clients and +# servers. # # A simple interface would be created this way: -# module = mojom.Module('Foo') +# module = mojom.generate.module.Module('Foo') # interface = module.AddInterface('Bar') # method = interface.AddMethod('Tat', 0) # method.AddParameter('baz', 0, mojom.INT32) diff --git a/mojo/public/tools/bindings/pylib/generate/mojom_tests.py b/mojo/public/tools/bindings/pylib/mojom/generate/module_tests.py index 58ef5fd60e..a887686e1b 100644 --- a/mojo/public/tools/bindings/pylib/generate/mojom_tests.py +++ b/mojo/public/tools/bindings/pylib/mojom/generate/module_tests.py @@ -2,15 +2,16 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import mojom_test import sys -EXPECT_EQ = mojom_test.EXPECT_EQ -EXPECT_TRUE = mojom_test.EXPECT_TRUE -RunTest = mojom_test.RunTest -ModulesAreEqual = mojom_test.ModulesAreEqual -BuildTestModule = mojom_test.BuildTestModule -TestTestModule = mojom_test.TestTestModule +import test_support + +EXPECT_EQ = test_support.EXPECT_EQ +EXPECT_TRUE = test_support.EXPECT_TRUE +RunTest = test_support.RunTest +ModulesAreEqual = test_support.ModulesAreEqual +BuildTestModule = test_support.BuildTestModule +TestTestModule = test_support.TestTestModule def BuildAndTestModule(): diff --git a/mojo/public/tools/bindings/pylib/generate/mojom_pack.py b/mojo/public/tools/bindings/pylib/mojom/generate/pack.py index c737eb651b..84378d7f1e 100644 --- a/mojo/public/tools/bindings/pylib/generate/mojom_pack.py +++ b/mojo/public/tools/bindings/pylib/mojom/generate/pack.py @@ -2,12 +2,12 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import mojom +import module as mojom -# mojom_pack provides a mechanism for determining the packed order and offsets +# This module provides a mechanism for determining the packed order and offsets # of a mojom.Struct. # -# ps = mojom_pack.PackedStruct(struct) +# ps = pack.PackedStruct(struct) # ps.packed_fields will access a list of PackedField objects, each of which # will have an offset, a size and a bit (for mojom.BOOLs). diff --git a/mojo/public/tools/bindings/pylib/generate/mojom_pack_tests.py b/mojo/public/tools/bindings/pylib/mojom/generate/pack_tests.py index 8b72562e39..4e61004e5f 100644 --- a/mojo/public/tools/bindings/pylib/generate/mojom_pack_tests.py +++ b/mojo/public/tools/bindings/pylib/mojom/generate/pack_tests.py @@ -2,14 +2,16 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import mojom -import mojom_pack -import mojom_test import sys -EXPECT_EQ = mojom_test.EXPECT_EQ -EXPECT_TRUE = mojom_test.EXPECT_TRUE -RunTest = mojom_test.RunTest +import module as mojom +import pack +import test_support + + +EXPECT_EQ = test_support.EXPECT_EQ +EXPECT_TRUE = test_support.EXPECT_TRUE +RunTest = test_support.RunTest def TestOrdinalOrder(): @@ -17,7 +19,7 @@ def TestOrdinalOrder(): struct = mojom.Struct('test') struct.AddField('testfield1', mojom.INT32, 2) struct.AddField('testfield2', mojom.INT32, 1) - ps = mojom_pack.PackedStruct(struct) + ps = pack.PackedStruct(struct) errors += EXPECT_EQ(2, len(ps.packed_fields)) errors += EXPECT_EQ('testfield2', ps.packed_fields[0].field.name) @@ -28,7 +30,7 @@ def TestOrdinalOrder(): def TestZeroFields(): errors = 0 struct = mojom.Struct('test') - ps = mojom_pack.PackedStruct(struct) + ps = pack.PackedStruct(struct) errors += EXPECT_EQ(0, len(ps.packed_fields)) return errors @@ -37,7 +39,7 @@ def TestOneField(): errors = 0 struct = mojom.Struct('test') struct.AddField('testfield1', mojom.INT8) - ps = mojom_pack.PackedStruct(struct) + ps = pack.PackedStruct(struct) errors += EXPECT_EQ(1, len(ps.packed_fields)) return errors @@ -54,7 +56,7 @@ def TestSequence(kinds, fields, offsets): for kind in kinds: struct.AddField("%d" % index, kind) index += 1 - ps = mojom_pack.PackedStruct(struct) + ps = pack.PackedStruct(struct) num_fields = len(ps.packed_fields) errors += EXPECT_EQ(len(kinds), num_fields) for i in xrange(num_fields): @@ -105,7 +107,7 @@ def TestPaddingPackedOutOfOrderByOrdinal(): struct.AddField('testfield1', mojom.INT8) struct.AddField('testfield3', mojom.UINT8, 3) struct.AddField('testfield2', mojom.INT32, 2) - ps = mojom_pack.PackedStruct(struct) + ps = pack.PackedStruct(struct) errors += EXPECT_EQ(3, len(ps.packed_fields)) # Second byte should be packed in behind first, altering order. @@ -134,7 +136,7 @@ def TestBools(): struct.AddField('bit6', mojom.BOOL) struct.AddField('bit7', mojom.BOOL) struct.AddField('bit8', mojom.BOOL) - ps = mojom_pack.PackedStruct(struct) + ps = pack.PackedStruct(struct) errors += EXPECT_EQ(10, len(ps.packed_fields)) # First 8 bits packed together. diff --git a/mojo/public/tools/bindings/pylib/generate/run_mojom_tests.py b/mojo/public/tools/bindings/pylib/mojom/generate/run_tests.py index e57ef477e9..41f11a2b71 100755 --- a/mojo/public/tools/bindings/pylib/generate/run_mojom_tests.py +++ b/mojo/public/tools/bindings/pylib/mojom/generate/run_tests.py @@ -22,9 +22,9 @@ def TestMojom(testname, args): def main(args): errors = 0 - errors += TestMojom('mojom_tests.py', ['--test']) - errors += TestMojom('mojom_data_tests.py', ['--test']) - errors += TestMojom('mojom_pack_tests.py', ['--test']) + errors += TestMojom('data_tests.py', ['--test']) + errors += TestMojom('module_tests.py', ['--test']) + errors += TestMojom('pack_tests.py', ['--test']) if errors: print '\nFailed tests.' diff --git a/mojo/public/tools/bindings/pylib/generate/template_expander.py b/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py index 1b3ee7489a..00c388e631 100644 --- a/mojo/public/tools/bindings/pylib/generate/template_expander.py +++ b/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py @@ -9,12 +9,16 @@ import inspect import os import sys -_current_dir = os.path.dirname(os.path.realpath(__file__)) -# jinja2 is in the third_party directory (current directory is -# mojo/public/tools/bindings/pylib/generate). -# Insert at front to override system libraries, and after path[0] == script dir -sys.path.insert(1, os.path.join(_current_dir, os.pardir, os.pardir, os.pardir, - os.pardir, os.pardir, os.pardir, 'third_party')) +# jinja2 is in the third_party directory. +# Insert at front to override system libraries, and after path[0] == script dir. +path = os.path.abspath(__file__) +while True: + path, tail = os.path.split(path) + assert tail + if tail == "mojo": + break +sys.path.insert(1, os.path.join(path, "third_party")) +del path, tail import jinja2 diff --git a/mojo/public/tools/bindings/pylib/generate/mojom_test.py b/mojo/public/tools/bindings/pylib/mojom/generate/test_support.py index a6b30a395a..93c8739cc7 100644 --- a/mojo/public/tools/bindings/pylib/generate/mojom_test.py +++ b/mojo/public/tools/bindings/pylib/mojom/generate/test_support.py @@ -2,10 +2,11 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import mojom import sys import traceback +import module as mojom + # Support for writing mojom test cases. # RunTest(fn) will execute fn, catching any exceptions. fn should return # the number of errors that are encountered. diff --git a/mojo/public/tools/bindings/pylib/mojom/parse/__init__.py b/mojo/public/tools/bindings/pylib/mojom/parse/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/mojo/public/tools/bindings/pylib/mojom/parse/__init__.py diff --git a/mojo/public/tools/bindings/pylib/mojom/parse/ast.py b/mojo/public/tools/bindings/pylib/mojom/parse/ast.py new file mode 100644 index 0000000000..bd398c18ec --- /dev/null +++ b/mojo/public/tools/bindings/pylib/mojom/parse/ast.py @@ -0,0 +1,25 @@ +# 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. + +"""Node objects for the AST for a Mojo IDL file.""" + +# Note: For convenience of testing, you probably want to define __eq__() methods +# for all node types; it's okay to be slightly lax (e.g., not compare filename +# and lineno). + + +class BaseNode(object): + def __init__(self, filename=None, lineno=None): + self.filename = filename + self.lineno = lineno + + +class Ordinal(BaseNode): + """Represents an ordinal value labeling, e.g., a struct field.""" + def __init__(self, value, **kwargs): + BaseNode.__init__(self, **kwargs) + self.value = value + + def __eq__(self, other): + return self.value == other.value diff --git a/mojo/public/tools/bindings/pylib/parse/mojo_lexer.py b/mojo/public/tools/bindings/pylib/mojom/parse/lexer.py index 6704ae1d3f..10abedd451 100644 --- a/mojo/public/tools/bindings/pylib/parse/mojo_lexer.py +++ b/mojo/public/tools/bindings/pylib/mojom/parse/lexer.py @@ -2,9 +2,9 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import os.path import re import sys -import os.path # Try to load the ply module, if not, then assume it is in the third_party # directory. @@ -13,11 +13,16 @@ try: # pylint: disable=F0401 from ply.lex import TOKEN except ImportError: - # This assumes this file is in src/mojo/public/tools/bindings/pylib/parse/. - module_path, module_name = os.path.split(__file__) - third_party = os.path.join(module_path, os.pardir, os.pardir, os.pardir, - os.pardir, os.pardir, os.pardir, 'third_party') - sys.path.append(third_party) + # Work our way up to the directory containing mojo/ (usually src/). (Note: + # Some builds don't check out into a directory called src/.) + path = os.path.abspath(__file__) + while True: + path, tail = os.path.split(path) + assert tail + if tail == "mojo": + break + sys.path.append(os.path.join(path, "third_party")) + del path, tail # pylint: disable=F0401 from ply.lex import TOKEN diff --git a/mojo/public/tools/bindings/pylib/parse/mojo_lexer_unittest.py b/mojo/public/tools/bindings/pylib/mojom/parse/lexer_unittest.py index 18be667bef..a3b0222cbf 100644 --- a/mojo/public/tools/bindings/pylib/parse/mojo_lexer_unittest.py +++ b/mojo/public/tools/bindings/pylib/mojom/parse/lexer_unittest.py @@ -2,7 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import mojo_lexer +import os.path +import sys import unittest # Try to load the ply module, if not, then assume it is in the third_party @@ -12,14 +13,21 @@ try: # pylint: disable=F0401 from ply import lex except ImportError: - # This assumes this file is in src/mojo/public/tools/bindings/pylib/parse/. - module_path, module_name = os.path.split(__file__) - third_party = os.path.join(module_path, os.pardir, os.pardir, os.pardir, - os.pardir, os.pardir, os.pardir, 'third_party') - sys.path.append(third_party) + # Work our way up to the directory containing mojo/ (usually src/). (Note: + # Some builds don't check out into a directory called src/.) + path = os.path.abspath(__file__) + while True: + path, tail = os.path.split(path) + assert tail + if tail == "mojo": + break + sys.path.append(os.path.join(path, "third_party")) + del path, tail # pylint: disable=F0401 from ply import lex +import lexer + # This (monkey-patching LexToken to make comparison value-based) is evil, but # we'll do it anyway. (I'm pretty sure ply's lexer never cares about comparing @@ -43,13 +51,13 @@ def _MakeLexTokenForKeyword(keyword, **kwargs): return _MakeLexToken(keyword.upper(), keyword.lower(), **kwargs) -class MojoLexerTest(unittest.TestCase): - """Tests mojo_lexer (in particular, Lexer).""" +class LexerTest(unittest.TestCase): + """Tests |lexer.Lexer|.""" def __init__(self, *args, **kwargs): unittest.TestCase.__init__(self, *args, **kwargs) # Clone all lexer instances from this one, since making a lexer is slow. - self._zygote_lexer = lex.lex(mojo_lexer.Lexer("my_file.mojom")) + self._zygote_lexer = lex.lex(lexer.Lexer("my_file.mojom")) def testValidSingleKeywords(self): """Tests valid, single keywords.""" diff --git a/mojo/public/tools/bindings/pylib/parse/mojo_parser.py b/mojo/public/tools/bindings/pylib/mojom/parse/parser.py index c3c961ed0d..33af7d90c6 100755 --- a/mojo/public/tools/bindings/pylib/parse/mojo_parser.py +++ b/mojo/public/tools/bindings/pylib/mojom/parse/parser.py @@ -1,13 +1,13 @@ #!/usr/bin/env python -# Copyright 2013 The Chromium Authors. All rights reserved. +# 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. """Generates a syntax tree from a Mojo IDL file.""" -import sys import os.path +import sys # Try to load the ply module, if not, then assume it is in the third_party # directory. @@ -17,16 +17,25 @@ try: from ply import lex from ply import yacc except ImportError: - # This assumes this file is in src/mojo/public/tools/bindings/pylib/parse/. - module_path, module_name = os.path.split(__file__) - third_party = os.path.join(module_path, os.pardir, os.pardir, os.pardir, - os.pardir, os.pardir, os.pardir, 'third_party') - sys.path.append(third_party) + # Work our way up to the directory containing mojo/ (usually src/). (Note: + # Some builds don't check out into a directory called src/.) + path = os.path.abspath(__file__) + while True: + path, tail = os.path.split(path) + assert tail + if tail == "mojo": + break + sys.path.append(os.path.join(path, "third_party")) + del path, tail # pylint: disable=F0401 from ply import lex from ply import yacc -from mojo_lexer import Lexer +import ast +from lexer import Lexer + + +_MAX_ORDINAL_VALUE = 0xffffffff def _ListFromConcat(*items): @@ -45,18 +54,18 @@ def _ListFromConcat(*items): class ParseError(Exception): - def __init__(self, filename, lineno=None, snippet=None, bad_char=None, - eof=False): + def __init__(self, filename, message, lineno=None, snippet=None): self.filename = filename + self.message = message self.lineno = lineno self.snippet = snippet - self.bad_char = bad_char - self.eof = eof def __str__(self): - return "%s: Error: Unexpected end of file" % self.filename if self.eof \ - else "%s:%d: Error: Unexpected %r:\n%s" % ( - self.filename, self.lineno, self.bad_char, self.snippet) + if self.lineno is None: + return "%s: Error: %s" % (self.filename, self.message) + + s = "%s:%d: Error: %s" % (self.filename, self.lineno, self.message) + return s if self.snippet is None else s + "\n" + self.snippet def __repr__(self): return str(self) @@ -76,6 +85,8 @@ class Parser(object): if len(p) > 2: p[0] = _ListFromConcat(p[1], p[2]) else: + # Generator expects a module. If one wasn't specified insert one with an + # empty name. if p[1][0] != 'MODULE': p[0] = [('MODULE', '', p[1])] else: @@ -87,7 +98,7 @@ class Parser(object): p[0] = ('IMPORT', eval(p[2])) def p_module(self, p): - """module : MODULE NAME LBRACE definitions RBRACE""" + """module : MODULE identifier LBRACE definitions RBRACE""" p[0] = ('MODULE', p[2], p[4]) def p_definitions(self, p): @@ -204,14 +215,21 @@ class Parser(object): p[0] = p[1] def p_array(self, p): - """array : basictypename LBRACKET RBRACKET""" + """array : typename LBRACKET RBRACKET""" p[0] = p[1] + "[]" def p_ordinal(self, p): """ordinal : ORDINAL | """ if len(p) > 1: - p[0] = p[1] + value = int(p[1][1:]) + if value > _MAX_ORDINAL_VALUE: + raise ParseError(self.filename, "Ordinal value %d too large:" % value, + lineno=p.lineno(1), + snippet=self._GetSnippet(p.lineno(1))) + p[0] = ast.Ordinal(value, filename=self.filename, lineno=p.lineno(1)) + else: + p[0] = ast.Ordinal(None) def p_enum(self, p): """enum : ENUM NAME LBRACE enum_fields RBRACE SEMI""" @@ -332,11 +350,13 @@ class Parser(object): if e is None: # Unexpected EOF. # TODO(vtl): Can we figure out what's missing? - raise ParseError(self.filename, eof=True) + raise ParseError(self.filename, "Unexpected end of file") + + raise ParseError(self.filename, "Unexpected %r:" % e.value, lineno=e.lineno, + snippet=self._GetSnippet(e.lineno)) - snippet = self.source.split('\n')[e.lineno - 1] - raise ParseError(self.filename, lineno=e.lineno, snippet=snippet, - bad_char=e.value) + def _GetSnippet(self, lineno): + return self.source.split('\n')[lineno - 1] def Parse(source, filename): diff --git a/mojo/public/tools/bindings/pylib/parse/mojo_parser_unittest.py b/mojo/public/tools/bindings/pylib/mojom/parse/parser_unittest.py index cc49c46c3d..fdce26c18f 100644 --- a/mojo/public/tools/bindings/pylib/parse/mojo_parser_unittest.py +++ b/mojo/public/tools/bindings/pylib/mojom/parse/parser_unittest.py @@ -2,13 +2,15 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import mojo_lexer -import mojo_parser import unittest +import ast +import lexer +import parser -class MojoParserTest(unittest.TestCase): - """Tests mojo_parser (in particular, Parse()).""" + +class ParserTest(unittest.TestCase): + """Tests |parser.Parse()|.""" def testTrivialValidSource(self): """Tests a trivial, but valid, .mojom source.""" @@ -18,13 +20,13 @@ class MojoParserTest(unittest.TestCase): module my_module { } """ - self.assertEquals(mojo_parser.Parse(source, "my_file.mojom"), + self.assertEquals(parser.Parse(source, "my_file.mojom"), [("MODULE", "my_module", None)]) def testSourceWithCrLfs(self): """Tests a .mojom source with CR-LFs instead of LFs.""" source = "// This is a comment.\r\n\r\nmodule my_module {\r\n}\r\n"; - self.assertEquals(mojo_parser.Parse(source, "my_file.mojom"), + self.assertEquals(parser.Parse(source, "my_file.mojom"), [("MODULE", "my_module", None)]) def testUnexpectedEOF(self): @@ -35,9 +37,9 @@ module my_module { module my_module { """ with self.assertRaisesRegexp( - mojo_parser.ParseError, + parser.ParseError, r"^my_file\.mojom: Error: Unexpected end of file$"): - mojo_parser.Parse(source, "my_file.mojom") + parser.Parse(source, "my_file.mojom") def testSimpleStruct(self): """Tests a simple .mojom source that just defines a struct.""" @@ -57,9 +59,9 @@ struct MyStruct { [('STRUCT', 'MyStruct', None, - [('FIELD', 'int32', 'a', None, None), - ('FIELD', 'double', 'b', None, None)])])] - self.assertEquals(mojo_parser.Parse(source, "my_file.mojom"), expected) + [('FIELD', 'int32', 'a', ast.Ordinal(None), None), + ('FIELD', 'double', 'b', ast.Ordinal(None), None)])])] + self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) def testSimpleStructWithoutModule(self): """Tests a simple struct without an enclosing module.""" @@ -75,9 +77,9 @@ struct MyStruct { [('STRUCT', 'MyStruct', None, - [('FIELD', 'int32', 'a', None, None), - ('FIELD', 'double', 'b', None, None)])])] - self.assertEquals(mojo_parser.Parse(source, "my_file.mojom"), expected) + [('FIELD', 'int32', 'a', ast.Ordinal(None), None), + ('FIELD', 'double', 'b', ast.Ordinal(None), None)])])] + self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) def testMissingModuleName(self): """Tests an (invalid) .mojom with a missing module name.""" @@ -90,9 +92,9 @@ struct MyStruct { } """ with self.assertRaisesRegexp( - mojo_parser.ParseError, + parser.ParseError, r"^my_file\.mojom:2: Error: Unexpected '{':\nmodule {$"): - mojo_parser.Parse(source1, "my_file.mojom") + parser.Parse(source1, "my_file.mojom") # Another similar case, but make sure that line-number tracking/reporting # is correct. @@ -104,9 +106,9 @@ module } """ with self.assertRaisesRegexp( - mojo_parser.ParseError, + parser.ParseError, r"^my_file\.mojom:4: Error: Unexpected '{':\n{$"): - mojo_parser.Parse(source2, "my_file.mojom") + parser.Parse(source2, "my_file.mojom") def testEnumExpressions(self): """Tests an enum with values calculated using simple expressions.""" @@ -160,7 +162,7 @@ enum MyEnum { ('ENUM_FIELD', 'MY_ENUM_MINUS_1', ('EXPRESSION', ['~', ('EXPRESSION', ['0'])]))])])] - self.assertEquals(mojo_parser.Parse(source, "my_file.mojom"), expected) + self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) def testNoConditionals(self): """Tests that ?: is not allowed.""" @@ -174,9 +176,9 @@ enum MyEnum { } // my_module """ with self.assertRaisesRegexp( - mojo_lexer.LexError, + lexer.LexError, r"^my_file\.mojom:4: Error: Illegal character '\?'$"): - mojo_parser.Parse(source, "my_file.mojom") + parser.Parse(source, "my_file.mojom") def testSimpleOrdinals(self): """Tests that (valid) ordinal values are scanned correctly.""" @@ -204,15 +206,15 @@ struct MyStruct { [('STRUCT', 'MyStruct', None, - [('FIELD', 'int32', 'a0', '@0', None), - ('FIELD', 'int32', 'a1', '@1', None), - ('FIELD', 'int32', 'a2', '@2', None), - ('FIELD', 'int32', 'a9', '@9', None), - ('FIELD', 'int32', 'a10', '@10', None), - ('FIELD', 'int32', 'a11', '@11', None), - ('FIELD', 'int32', 'a29', '@29', None), - ('FIELD', 'int32', 'a1234567890', '@1234567890', None)])])] - self.assertEquals(mojo_parser.Parse(source, "my_file.mojom"), expected) + [('FIELD', 'int32', 'a0', ast.Ordinal(0), None), + ('FIELD', 'int32', 'a1', ast.Ordinal(1), None), + ('FIELD', 'int32', 'a2', ast.Ordinal(2), None), + ('FIELD', 'int32', 'a9', ast.Ordinal(9), None), + ('FIELD', 'int32', 'a10', ast.Ordinal(10), None), + ('FIELD', 'int32', 'a11', ast.Ordinal(11), None), + ('FIELD', 'int32', 'a29', ast.Ordinal(29), None), + ('FIELD', 'int32', 'a1234567890', ast.Ordinal(1234567890), None)])])] + self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) def testInvalidOrdinals(self): """Tests that (lexically) invalid ordinals are correctly detected.""" @@ -226,9 +228,9 @@ struct MyStruct { } // module my_module """ with self.assertRaisesRegexp( - mojo_lexer.LexError, + lexer.LexError, r"^my_file\.mojom:4: Error: Missing ordinal value$"): - mojo_parser.Parse(source1, "my_file.mojom") + parser.Parse(source1, "my_file.mojom") source2 = """\ module my_module { @@ -240,37 +242,69 @@ struct MyStruct { } // module my_module """ with self.assertRaisesRegexp( - mojo_lexer.LexError, + lexer.LexError, r"^my_file\.mojom:4: Error: " r"Octal and hexadecimal ordinal values not allowed$"): - mojo_parser.Parse(source2, "my_file.mojom") + parser.Parse(source2, "my_file.mojom") source3 = """\ module my_module { struct MyStruct { int32 a_invalid_octal @08; }; } """ with self.assertRaisesRegexp( - mojo_lexer.LexError, + lexer.LexError, r"^my_file\.mojom:1: Error: " r"Octal and hexadecimal ordinal values not allowed$"): - mojo_parser.Parse(source3, "my_file.mojom") + parser.Parse(source3, "my_file.mojom") source4 = """\ module my_module { struct MyStruct { int32 a_hex @0x1aB9; }; } """ with self.assertRaisesRegexp( - mojo_lexer.LexError, + lexer.LexError, r"^my_file\.mojom:1: Error: " r"Octal and hexadecimal ordinal values not allowed$"): - mojo_parser.Parse(source4, "my_file.mojom") + parser.Parse(source4, "my_file.mojom") source5 = """\ module my_module { struct MyStruct { int32 a_hex @0X0; }; } """ with self.assertRaisesRegexp( - mojo_lexer.LexError, + lexer.LexError, r"^my_file\.mojom:1: Error: " r"Octal and hexadecimal ordinal values not allowed$"): - mojo_parser.Parse(source5, "my_file.mojom") + parser.Parse(source5, "my_file.mojom") + + source6 = """\ +struct MyStruct { + int32 a_too_big @999999999999; +}; +""" + with self.assertRaisesRegexp( + parser.ParseError, + r"^my_file\.mojom:2: Error: " + r"Ordinal value 999999999999 too large:\n" + r" int32 a_too_big @999999999999;$"): + parser.Parse(source6, "my_file.mojom") + + def testNestedNamespace(self): + """Tests nested namespaces work.""" + source = """\ +module my.mod { + +struct MyStruct { + int32 a; +}; + +} // module my.mod +""" + expected = \ +[('MODULE', + 'my.mod', + [('STRUCT', + 'MyStruct', + None, + [('FIELD', 'int32', 'a', ast.Ordinal(None), None)])])] + self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) if __name__ == "__main__": diff --git a/mojo/public/tools/bindings/pylib/parse/mojo_translate.py b/mojo/public/tools/bindings/pylib/mojom/parse/translate.py index 9906ede8a5..6060c83bf9 100755 --- a/mojo/public/tools/bindings/pylib/parse/mojo_translate.py +++ b/mojo/public/tools/bindings/pylib/mojom/parse/translate.py @@ -1,14 +1,16 @@ #!/usr/bin/env python -# Copyright 2013 The Chromium Authors. All rights reserved. +# 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. -"""Translate parse tree to Mojom IR""" +"""Translates parse tree to Mojom IR.""" -import os +import os.path import sys +import ast + def MapTree(func, tree, name): if not tree: @@ -39,11 +41,6 @@ def MapKind(kind): return map_to_kind[kind] return 'x:' + kind -def MapOrdinal(ordinal): - if ordinal == None: - return None - return int(ordinal[1:]) # Strip leading '@' - def GetAttribute(attributes, name): out = None if attributes: @@ -53,20 +50,23 @@ def GetAttribute(attributes, name): return out def MapField(tree): + assert type(tree[3]) is ast.Ordinal return {'name': tree[2], 'kind': MapKind(tree[1]), - 'ordinal': MapOrdinal(tree[3]), + 'ordinal': tree[3].value, 'default': tree[4]} def MapParameter(tree): + assert type(tree[3]) is ast.Ordinal return {'name': tree[2], 'kind': MapKind(tree[1]), - 'ordinal': MapOrdinal(tree[3])} + 'ordinal': tree[3].value} def MapMethod(tree): + assert type(tree[3]) is ast.Ordinal method = {'name': tree[1], 'parameters': MapTree(MapParameter, tree[2], 'PARAM'), - 'ordinal': MapOrdinal(tree[3])} + 'ordinal': tree[3].value} if tree[4] != None: method['response_parameters'] = MapTree(MapParameter, tree[4], 'PARAM') return method diff --git a/mojo/service_manager/service_manager.cc b/mojo/service_manager/service_manager.cc index f12249ea66..c34e83f55a 100644 --- a/mojo/service_manager/service_manager.cc +++ b/mojo/service_manager/service_manager.cc @@ -9,6 +9,7 @@ #include "base/lazy_instance.h" #include "base/logging.h" #include "base/macros.h" +#include "base/stl_util.h" #include "mojo/public/cpp/bindings/allocation_scope.h" #include "mojo/public/cpp/bindings/error_handler.h" #include "mojo/public/cpp/bindings/remote_ptr.h" @@ -71,16 +72,13 @@ bool ServiceManager::TestAPI::HasFactoryForURL(const GURL& url) const { } ServiceManager::ServiceManager() - : default_loader_(NULL), - interceptor_(NULL) { + : interceptor_(NULL) { } ServiceManager::~ServiceManager() { - for (URLToServiceFactoryMap::iterator it = url_to_service_factory_.begin(); - it != url_to_service_factory_.end(); ++it) { - delete it->second; - } - url_to_service_factory_.clear(); + STLDeleteValues(&url_to_service_factory_); + STLDeleteValues(&url_to_loader_); + STLDeleteValues(&scheme_to_loader_); } // static @@ -110,15 +108,20 @@ void ServiceManager::Connect(const GURL& url, } } -void ServiceManager::SetLoaderForURL(ServiceLoader* loader, const GURL& url) { - DCHECK(url_to_loader_.find(url) == url_to_loader_.end()); - url_to_loader_[url] = loader; +void ServiceManager::SetLoaderForURL(scoped_ptr<ServiceLoader> loader, + const GURL& url) { + URLToLoaderMap::iterator it = url_to_loader_.find(url); + if (it != url_to_loader_.end()) + delete it->second; + url_to_loader_[url] = loader.release(); } -void ServiceManager::SetLoaderForScheme(ServiceLoader* loader, +void ServiceManager::SetLoaderForScheme(scoped_ptr<ServiceLoader> loader, const std::string& scheme) { - DCHECK(scheme_to_loader_.find(scheme) == scheme_to_loader_.end()); - scheme_to_loader_[scheme] = loader; + SchemeToLoaderMap::iterator it = scheme_to_loader_.find(scheme); + if (it != scheme_to_loader_.end()) + delete it->second; + scheme_to_loader_[scheme] = loader.release(); } void ServiceManager::SetInterceptor(Interceptor* interceptor) { @@ -134,7 +137,7 @@ ServiceLoader* ServiceManager::GetLoaderForURL(const GURL& url) { if (scheme_it != scheme_to_loader_.end()) return scheme_it->second; DCHECK(default_loader_); - return default_loader_; + return default_loader_.get(); } void ServiceManager::OnServiceFactoryError(ServiceFactory* service_factory) { diff --git a/mojo/service_manager/service_manager.h b/mojo/service_manager/service_manager.h index 6d9ab5de0d..40cb8cdb1f 100644 --- a/mojo/service_manager/service_manager.h +++ b/mojo/service_manager/service_manager.h @@ -10,7 +10,9 @@ #include "base/basictypes.h" #include "base/callback.h" #include "base/gtest_prod_util.h" +#include "base/memory/scoped_ptr.h" #include "mojo/public/interfaces/shell/shell.mojom.h" +#include "mojo/service_manager/service_loader.h" #include "mojo/service_manager/service_manager_export.h" #include "url/gurl.h" @@ -20,8 +22,6 @@ namespace content { namespace mojo { -class ServiceLoader; - class MOJO_SERVICE_MANAGER_EXPORT ServiceManager { public: // API for testing. @@ -57,16 +57,16 @@ class MOJO_SERVICE_MANAGER_EXPORT ServiceManager { // Loads a service if necessary and establishes a new client connection. void Connect(const GURL& url, ScopedMessagePipeHandle client_handle); - // Sets the default Loader to be used if not overridden by - // SetLoaderForURL() or SetLoaderForScheme(). - // Does not take ownership of |loader|. - void set_default_loader(ServiceLoader* loader) { default_loader_ = loader; } + // Sets the default Loader to be used if not overridden by SetLoaderForURL() + // or SetLoaderForScheme(). + void set_default_loader(scoped_ptr<ServiceLoader> loader) { + default_loader_ = loader.Pass(); + } // Sets a Loader to be used for a specific url. - // Does not take ownership of |loader|. - void SetLoaderForURL(ServiceLoader* loader, const GURL& url); + void SetLoaderForURL(scoped_ptr<ServiceLoader> loader, const GURL& url); // Sets a Loader to be used for a specific url scheme. - // Does not take ownership of |loader|. - void SetLoaderForScheme(ServiceLoader* loader, const std::string& scheme); + void SetLoaderForScheme(scoped_ptr<ServiceLoader> loader, + const std::string& scheme); // Allows to interpose a debugger to service connections. void SetInterceptor(Interceptor* interceptor); @@ -87,7 +87,7 @@ class MOJO_SERVICE_MANAGER_EXPORT ServiceManager { // Loader management. URLToLoaderMap url_to_loader_; SchemeToLoaderMap scheme_to_loader_; - ServiceLoader* default_loader_; + scoped_ptr<ServiceLoader> default_loader_; Interceptor* interceptor_; URLToServiceFactoryMap url_to_service_factory_; diff --git a/mojo/service_manager/service_manager_unittest.cc b/mojo/service_manager/service_manager_unittest.cc index c7b3d2a608..54a6b7d5a6 100644 --- a/mojo/service_manager/service_manager_unittest.cc +++ b/mojo/service_manager/service_manager_unittest.cc @@ -19,18 +19,20 @@ namespace { const char kTestURLString[] = "test:testService"; struct TestContext { - TestContext() : num_impls(0) {} + TestContext() : num_impls(0), num_loader_deletes(0) {} std::string last_test_string; int num_impls; + int num_loader_deletes; }; class TestServiceImpl : - public Service<TestService, TestServiceImpl, TestContext> { + public ServiceConnection<TestService, TestServiceImpl, TestContext> { public: TestServiceImpl() {} virtual ~TestServiceImpl() { - --context()->num_impls; + if (context()) + --context()->num_impls; } virtual void Test(const mojo::String& test_string) OVERRIDE { @@ -38,11 +40,13 @@ class TestServiceImpl : client()->AckTest(); } - void Initialize(ServiceFactory<TestServiceImpl, TestContext>* service_factory, - ScopedMessagePipeHandle client_handle) { - Service<TestService, TestServiceImpl, TestContext>::Initialize( + void Initialize( + ServiceConnector<TestServiceImpl, TestContext>* service_factory, + ScopedMessagePipeHandle client_handle) { + ServiceConnection<TestService, TestServiceImpl, TestContext>::Initialize( service_factory, client_handle.Pass()); - ++context()->num_impls; + if (context()) + ++context()->num_impls; } }; @@ -71,74 +75,51 @@ class TestClientImpl : public TestClient { bool quit_after_ack_; DISALLOW_COPY_AND_ASSIGN(TestClientImpl); }; -} // namespace -class ServiceManagerTest : public testing::Test, public ServiceLoader { +class TestServiceLoader : public ServiceLoader { public: - ServiceManagerTest() {} - - virtual ~ServiceManagerTest() {} - - virtual void SetUp() OVERRIDE { - GURL test_url(kTestURLString); - service_manager_.reset(new ServiceManager); - service_manager_->SetLoaderForURL(this, test_url); - - InterfacePipe<TestService, AnyInterface> pipe; - test_client_.reset(new TestClientImpl(pipe.handle_to_self.Pass())); - service_manager_->Connect(test_url, pipe.handle_to_peer.Pass()); + TestServiceLoader() + : context_(NULL), + num_loads_(0), + quit_after_error_(false) { } - virtual void TearDown() OVERRIDE { - test_client_.reset(NULL); + virtual ~TestServiceLoader() { + if (context_) + ++context_->num_loader_deletes; test_app_.reset(NULL); - service_manager_.reset(NULL); } + void set_context(TestContext* context) { context_ = context; } + void set_quit_after_error(bool quit_after_error) { + quit_after_error_ = quit_after_error; + } + + int num_loads() const { return num_loads_; } + + private: virtual void LoadService(ServiceManager* manager, const GURL& url, ScopedShellHandle shell_handle) OVERRIDE { + ++num_loads_; test_app_.reset(new Application(shell_handle.Pass())); - test_app_->AddServiceFactory( - new ServiceFactory<TestServiceImpl, TestContext>(&context_)); + test_app_->AddServiceConnector( + new ServiceConnector<TestServiceImpl, TestContext>(context_)); } virtual void OnServiceError(ServiceManager* manager, const GURL& url) OVERRIDE { - base::MessageLoop::current()->PostTask(FROM_HERE, - base::MessageLoop::QuitClosure()); + if (quit_after_error_) { + base::MessageLoop::current()->PostTask(FROM_HERE, + base::MessageLoop::QuitClosure()); + } } - bool HasFactoryForTestURL() { - ServiceManager::TestAPI manager_test_api(service_manager_.get()); - return manager_test_api.HasFactoryForURL(GURL(kTestURLString)); - } - protected: - mojo::Environment env_; - base::MessageLoop loop_; - TestContext context_; scoped_ptr<Application> test_app_; - scoped_ptr<TestClientImpl> test_client_; - scoped_ptr<ServiceManager> service_manager_; - DISALLOW_COPY_AND_ASSIGN(ServiceManagerTest); -}; - -class TestServiceLoader : public ServiceLoader { - public: - TestServiceLoader() : num_loads_(0) {} - int num_loads() const { return num_loads_; } - - private: - virtual void LoadService(ServiceManager* manager, - const GURL& url, - ScopedShellHandle service_handle) OVERRIDE { - ++num_loads_; - } - virtual void OnServiceError(ServiceManager* manager, const GURL& url) - OVERRIDE {} - + TestContext* context_; int num_loads_; + bool quit_after_error_; DISALLOW_COPY_AND_ASSIGN(TestServiceLoader); }; @@ -169,6 +150,47 @@ class TestServiceInterceptor : public ServiceManager::Interceptor { DISALLOW_COPY_AND_ASSIGN(TestServiceInterceptor); }; +} // namespace + +class ServiceManagerTest : public testing::Test { + public: + ServiceManagerTest() {} + + virtual ~ServiceManagerTest() {} + + virtual void SetUp() OVERRIDE { + GURL test_url(kTestURLString); + service_manager_.reset(new ServiceManager); + + InterfacePipe<TestService, AnyInterface> pipe; + test_client_.reset(new TestClientImpl(pipe.handle_to_self.Pass())); + TestServiceLoader* default_loader = new TestServiceLoader; + default_loader->set_context(&context_); + default_loader->set_quit_after_error(true); + service_manager_->set_default_loader( + scoped_ptr<ServiceLoader>(default_loader)); + service_manager_->Connect(test_url, pipe.handle_to_peer.Pass()); + } + + virtual void TearDown() OVERRIDE { + test_client_.reset(NULL); + service_manager_.reset(NULL); + } + + bool HasFactoryForTestURL() { + ServiceManager::TestAPI manager_test_api(service_manager_.get()); + return manager_test_api.HasFactoryForURL(GURL(kTestURLString)); + } + + protected: + mojo::Environment env_; + base::MessageLoop loop_; + TestContext context_; + scoped_ptr<TestClientImpl> test_client_; + scoped_ptr<ServiceManager> service_manager_; + DISALLOW_COPY_AND_ASSIGN(ServiceManagerTest); +}; + TEST_F(ServiceManagerTest, Basic) { test_client_->Test("test"); loop_.Run(); @@ -186,43 +208,67 @@ TEST_F(ServiceManagerTest, ClientError) { EXPECT_FALSE(HasFactoryForTestURL()); } +TEST_F(ServiceManagerTest, Deletes) { + { + ServiceManager sm; + TestServiceLoader* default_loader = new TestServiceLoader; + default_loader->set_context(&context_); + TestServiceLoader* url_loader1 = new TestServiceLoader; + TestServiceLoader* url_loader2 = new TestServiceLoader; + url_loader1->set_context(&context_); + url_loader2->set_context(&context_); + TestServiceLoader* scheme_loader1 = new TestServiceLoader; + TestServiceLoader* scheme_loader2 = new TestServiceLoader; + scheme_loader1->set_context(&context_); + scheme_loader2->set_context(&context_); + sm.set_default_loader(scoped_ptr<ServiceLoader>(default_loader)); + sm.SetLoaderForURL(scoped_ptr<ServiceLoader>(url_loader1), + GURL("test:test1")); + sm.SetLoaderForURL(scoped_ptr<ServiceLoader>(url_loader2), + GURL("test:test1")); + sm.SetLoaderForScheme(scoped_ptr<ServiceLoader>(scheme_loader1), "test"); + sm.SetLoaderForScheme(scoped_ptr<ServiceLoader>(scheme_loader2), "test"); + } + EXPECT_EQ(5, context_.num_loader_deletes); +} + // Confirm that both urls and schemes can have their loaders explicitly set. TEST_F(ServiceManagerTest, SetLoaders) { ServiceManager sm; - TestServiceLoader default_loader; - TestServiceLoader url_loader; - TestServiceLoader scheme_loader; - sm.set_default_loader(&default_loader); - sm.SetLoaderForURL(&url_loader, GURL("test:test1")); - sm.SetLoaderForScheme(&scheme_loader, "test"); + TestServiceLoader* default_loader = new TestServiceLoader; + TestServiceLoader* url_loader = new TestServiceLoader; + TestServiceLoader* scheme_loader = new TestServiceLoader; + sm.set_default_loader(scoped_ptr<ServiceLoader>(default_loader)); + sm.SetLoaderForURL(scoped_ptr<ServiceLoader>(url_loader), GURL("test:test1")); + sm.SetLoaderForScheme(scoped_ptr<ServiceLoader>(scheme_loader), "test"); // test::test1 should go to url_loader. InterfacePipe<TestService, AnyInterface> pipe1; sm.Connect(GURL("test:test1"), pipe1.handle_to_peer.Pass()); - EXPECT_EQ(1, url_loader.num_loads()); - EXPECT_EQ(0, scheme_loader.num_loads()); - EXPECT_EQ(0, default_loader.num_loads()); + EXPECT_EQ(1, url_loader->num_loads()); + EXPECT_EQ(0, scheme_loader->num_loads()); + EXPECT_EQ(0, default_loader->num_loads()); // test::test2 should go to scheme loader. InterfacePipe<TestService, AnyInterface> pipe2; sm.Connect(GURL("test:test2"), pipe2.handle_to_peer.Pass()); - EXPECT_EQ(1, url_loader.num_loads()); - EXPECT_EQ(1, scheme_loader.num_loads()); - EXPECT_EQ(0, default_loader.num_loads()); + EXPECT_EQ(1, url_loader->num_loads()); + EXPECT_EQ(1, scheme_loader->num_loads()); + EXPECT_EQ(0, default_loader->num_loads()); // http::test1 should go to default loader. InterfacePipe<TestService, AnyInterface> pipe3; sm.Connect(GURL("http:test1"), pipe3.handle_to_peer.Pass()); - EXPECT_EQ(1, url_loader.num_loads()); - EXPECT_EQ(1, scheme_loader.num_loads()); - EXPECT_EQ(1, default_loader.num_loads()); + EXPECT_EQ(1, url_loader->num_loads()); + EXPECT_EQ(1, scheme_loader->num_loads()); + EXPECT_EQ(1, default_loader->num_loads()); } TEST_F(ServiceManagerTest, Interceptor) { ServiceManager sm; - TestServiceLoader default_loader; TestServiceInterceptor interceptor; - sm.set_default_loader(&default_loader); + TestServiceLoader* default_loader = new TestServiceLoader; + sm.set_default_loader(scoped_ptr<ServiceLoader>(default_loader)); sm.SetInterceptor(&interceptor); std::string url("test:test3"); @@ -230,7 +276,7 @@ TEST_F(ServiceManagerTest, Interceptor) { sm.Connect(GURL(url), pipe1.handle_to_peer.Pass()); EXPECT_EQ(1, interceptor.call_count()); EXPECT_EQ(url, interceptor.url_spec()); - EXPECT_EQ(1, default_loader.num_loads()); + EXPECT_EQ(1, default_loader->num_loads()); } } // namespace mojo diff --git a/mojo/services/native_viewport/native_viewport_android.h b/mojo/services/native_viewport/native_viewport_android.h index 96ecd1f226..c24e38e785 100644 --- a/mojo/services/native_viewport/native_viewport_android.h +++ b/mojo/services/native_viewport/native_viewport_android.h @@ -5,7 +5,7 @@ #ifndef MOJO_SERVICES_NATIVE_VIEWPORT_NATIVE_VIEWPORT_ANDROID_H_ #define MOJO_SERVICES_NATIVE_VIEWPORT_NATIVE_VIEWPORT_ANDROID_H_ -#include "base/android/jni_helper.h" +#include "base/android/jni_weak_ref.h" #include "base/android/scoped_java_ref.h" #include "base/memory/weak_ptr.h" #include "mojo/services/native_viewport/native_viewport.h" diff --git a/mojo/services/native_viewport/native_viewport_export.h b/mojo/services/native_viewport/native_viewport_export.h index 647b6892e3..4870c566f9 100644 --- a/mojo/services/native_viewport/native_viewport_export.h +++ b/mojo/services/native_viewport/native_viewport_export.h @@ -5,6 +5,8 @@ #ifndef MOJO_SERVICES_NATIVE_VIEWPORT_EXPORT_H_ #define MOJO_SERVICES_NATIVE_VIEWPORT_EXPORT_H_ +#if defined(COMPONENT_BUILD) + #if defined(WIN32) #if defined(MOJO_NATIVE_VIEWPORT_IMPLEMENTATION) @@ -23,4 +25,8 @@ #endif // defined(WIN32) +#else // !defined(COMPONENT_BUILD) +#define MOJO_NATIVE_VIEWPORT_EXPORT +#endif + #endif // MOJO_SERVICES_NATIVE_VIEWPORT_EXPORT_H_ diff --git a/mojo/services/native_viewport/native_viewport_service.cc b/mojo/services/native_viewport/native_viewport_service.cc index 024a3bbc56..5625aa1393 100644 --- a/mojo/services/native_viewport/native_viewport_service.cc +++ b/mojo/services/native_viewport/native_viewport_service.cc @@ -28,7 +28,9 @@ bool IsRateLimitedEventType(ui::Event* event) { } class NativeViewportImpl - : public Service<mojo::NativeViewport, NativeViewportImpl, shell::Context>, + : public ServiceConnection<mojo::NativeViewport, + NativeViewportImpl, + shell::Context>, public NativeViewportDelegate { public: NativeViewportImpl() @@ -186,9 +188,9 @@ MOJO_NATIVE_VIEWPORT_EXPORT mojo::Application* CreateNativeViewportService(mojo::shell::Context* context, mojo::ScopedShellHandle shell_handle) { mojo::Application* app = new mojo::Application(shell_handle.Pass()); - app->AddServiceFactory( - new mojo::ServiceFactory<mojo::services::NativeViewportImpl, - mojo::shell::Context>(context)); + app->AddServiceConnector( + new mojo::ServiceConnector<mojo::services::NativeViewportImpl, + mojo::shell::Context>(context)); return app; } diff --git a/mojo/services/public/cpp/view_manager/lib/view.cc b/mojo/services/public/cpp/view_manager/lib/view.cc new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/mojo/services/public/cpp/view_manager/lib/view.cc diff --git a/mojo/services/public/cpp/view_manager/lib/view_manager.cc b/mojo/services/public/cpp/view_manager/lib/view_manager.cc new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/mojo/services/public/cpp/view_manager/lib/view_manager.cc diff --git a/mojo/services/public/cpp/view_manager/lib/view_tree_host.cc b/mojo/services/public/cpp/view_manager/lib/view_tree_host.cc new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/mojo/services/public/cpp/view_manager/lib/view_tree_host.cc diff --git a/mojo/services/public/cpp/view_manager/lib/view_tree_node.cc b/mojo/services/public/cpp/view_manager/lib/view_tree_node.cc new file mode 100644 index 0000000000..9194dc4e3a --- /dev/null +++ b/mojo/services/public/cpp/view_manager/lib/view_tree_node.cc @@ -0,0 +1,144 @@ +// 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/services/public/cpp/view_manager/view_tree_node.h" + +#include "mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h" +#include "mojo/services/public/cpp/view_manager/view_tree_node_observer.h" + +namespace mojo { +namespace services { +namespace view_manager { + +void NotifyViewTreeChangeAtReceiver( + ViewTreeNode* receiver, + const ViewTreeNodeObserver::TreeChangeParams& params) { + ViewTreeNodeObserver::TreeChangeParams local_params = params; + local_params.receiver = receiver; + FOR_EACH_OBSERVER(ViewTreeNodeObserver, + *ViewTreeNodePrivate(receiver).observers(), + OnTreeChange(local_params)); +} + +void NotifyViewTreeChangeUp( + ViewTreeNode* start_at, + const ViewTreeNodeObserver::TreeChangeParams& params) { + for (ViewTreeNode* current = start_at; current; current = current->parent()) + NotifyViewTreeChangeAtReceiver(current, params); +} + +void NotifyViewTreeChangeDown( + ViewTreeNode* start_at, + const ViewTreeNodeObserver::TreeChangeParams& params) { + NotifyViewTreeChangeAtReceiver(start_at, params); + ViewTreeNode::Children::const_iterator it = start_at->children().begin(); + for (; it != start_at->children().end(); ++it) + NotifyViewTreeChangeDown(*it, params); +} + +void NotifyViewTreeChange( + const ViewTreeNodeObserver::TreeChangeParams& params) { + NotifyViewTreeChangeDown(params.target, params); + switch (params.phase) { + case ViewTreeNodeObserver::DISPOSITION_CHANGING: + if (params.old_parent) + NotifyViewTreeChangeUp(params.old_parent, params); + break; + case ViewTreeNodeObserver::DISPOSITION_CHANGED: + if (params.new_parent) + NotifyViewTreeChangeUp(params.new_parent, params); + break; + default: + NOTREACHED(); + break; + } +} + +class ScopedTreeNotifier { + public: + ScopedTreeNotifier(ViewTreeNode* target, + ViewTreeNode* old_parent, + ViewTreeNode* new_parent) { + params_.target = target; + params_.old_parent = old_parent; + params_.new_parent = new_parent; + NotifyViewTreeChange(params_); + } + ~ScopedTreeNotifier() { + params_.phase = ViewTreeNodeObserver::DISPOSITION_CHANGED; + NotifyViewTreeChange(params_); + } + + private: + ViewTreeNodeObserver::TreeChangeParams params_; + + DISALLOW_COPY_AND_ASSIGN(ScopedTreeNotifier); +}; + +void RemoveChildImpl(ViewTreeNode* child, ViewTreeNode::Children* children) { + ViewTreeNode::Children::iterator it = + std::find(children->begin(), children->end(), child); + if (it != children->end()) { + children->erase(it); + ViewTreeNodePrivate(child).ClearParent(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// ViewTreeNode, public: + +ViewTreeNode::ViewTreeNode() : owned_by_parent_(true), parent_(NULL) {} + +ViewTreeNode::~ViewTreeNode() { + while (!children_.empty()) { + ViewTreeNode* child = children_.front(); + if (child->owned_by_parent_) { + delete child; + // Deleting the child also removes it from our child list. + DCHECK(std::find(children_.begin(), children_.end(), child) == + children_.end()); + } else { + RemoveChild(child); + } + } + + if (parent_) + parent_->RemoveChild(this); + +} + +void ViewTreeNode::AddObserver(ViewTreeNodeObserver* observer) { + observers_.AddObserver(observer); +} + +void ViewTreeNode::RemoveObserver(ViewTreeNodeObserver* observer) { + observers_.RemoveObserver(observer); +} + +void ViewTreeNode::AddChild(ViewTreeNode* child) { + ScopedTreeNotifier notifier(child, child->parent(), this); + if (child->parent()) + RemoveChildImpl(child, &child->parent_->children_); + children_.push_back(child); + child->parent_ = this; +} + +void ViewTreeNode::RemoveChild(ViewTreeNode* child) { + DCHECK_EQ(this, child->parent()); + ScopedTreeNotifier(child, this, NULL); + RemoveChildImpl(child, &children_); +} + +bool ViewTreeNode::Contains(ViewTreeNode* child) const { + for (ViewTreeNode* p = child->parent(); p; p = p->parent()) { + if (p == this) + return true; + } + return false; +} + +} // namespace view_manager +} // namespace services +} // namespace mojo + diff --git a/mojo/services/public/cpp/view_manager/lib/view_tree_node_observer.cc b/mojo/services/public/cpp/view_manager/lib/view_tree_node_observer.cc new file mode 100644 index 0000000000..607269c66d --- /dev/null +++ b/mojo/services/public/cpp/view_manager/lib/view_tree_node_observer.cc @@ -0,0 +1,26 @@ +// 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/services/public/cpp/view_manager/view_tree_node_observer.h" + +#include "base/basictypes.h" + +namespace mojo { +namespace services { +namespace view_manager { + +//////////////////////////////////////////////////////////////////////////////// +// ViewTreeNodeObserver, public: + +ViewTreeNodeObserver::TreeChangeParams::TreeChangeParams() + : target(NULL), + old_parent(NULL), + new_parent(NULL), + receiver(NULL), + phase(ViewTreeNodeObserver::DISPOSITION_CHANGING) {} + +} // namespace view_manager +} // namespace services +} // namespace mojo + diff --git a/mojo/services/public/cpp/view_manager/lib/view_tree_node_private.cc b/mojo/services/public/cpp/view_manager/lib/view_tree_node_private.cc new file mode 100644 index 0000000000..a1c3a40ac9 --- /dev/null +++ b/mojo/services/public/cpp/view_manager/lib/view_tree_node_private.cc @@ -0,0 +1,20 @@ +// 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/services/public/cpp/view_manager/lib/view_tree_node_private.h" + +namespace mojo { +namespace services { +namespace view_manager { + +ViewTreeNodePrivate::ViewTreeNodePrivate(ViewTreeNode* node) + : node_(node) { +} + +ViewTreeNodePrivate::~ViewTreeNodePrivate() { +} + +} // namespace view_manager +} // namespace services +} // namespace mojo diff --git a/mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h b/mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h new file mode 100644 index 0000000000..33be9f087d --- /dev/null +++ b/mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h @@ -0,0 +1,37 @@ +// 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_SERVICES_PUBLIC_CPP_VIEW_MANAGER_LIB_VIEW_TREE_NODE_PRIVATE_H_ +#define MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_LIB_VIEW_TREE_NODE_PRIVATE_H_ + +#include <vector> + +#include "base/basictypes.h" + +#include "mojo/services/public/cpp/view_manager/view_tree_node.h" + +namespace mojo { +namespace services { +namespace view_manager { + +class ViewTreeNodePrivate { + public: + explicit ViewTreeNodePrivate(ViewTreeNode* node); + ~ViewTreeNodePrivate(); + + ObserverList<ViewTreeNodeObserver>* observers() { return &node_->observers_; } + + void ClearParent() { node_->parent_ = NULL; } + + private: + ViewTreeNode* node_; + + DISALLOW_COPY_AND_ASSIGN(ViewTreeNodePrivate); +}; + +} // namespace view_manager +} // namespace services +} // namespace mojo + +#endif // MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_LIB_VIEW_TREE_NODE_PRIVATE_H_ diff --git a/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc b/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc diff --git a/mojo/services/public/cpp/view_manager/tests/view_tree_host_unittest.cc b/mojo/services/public/cpp/view_manager/tests/view_tree_host_unittest.cc new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/mojo/services/public/cpp/view_manager/tests/view_tree_host_unittest.cc diff --git a/mojo/services/public/cpp/view_manager/tests/view_tree_node_unittest.cc b/mojo/services/public/cpp/view_manager/tests/view_tree_node_unittest.cc new file mode 100644 index 0000000000..54349eeadd --- /dev/null +++ b/mojo/services/public/cpp/view_manager/tests/view_tree_node_unittest.cc @@ -0,0 +1,330 @@ +// 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/services/public/cpp/view_manager/view_tree_node.h" + +#include "base/logging.h" +#include "mojo/services/public/cpp/view_manager/view_tree_node_observer.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace services { +namespace view_manager { + +// ViewTreeNode ---------------------------------------------------------------- + +typedef testing::Test ViewTreeNodeTest; + +TEST_F(ViewTreeNodeTest, AddChild) { + ViewTreeNode v1; + ViewTreeNode* v11 = new ViewTreeNode; + v1.AddChild(v11); + EXPECT_EQ(1U, v1.children().size()); +} + +TEST_F(ViewTreeNodeTest, RemoveChild) { + ViewTreeNode v1; + ViewTreeNode* v11 = new ViewTreeNode; + v1.AddChild(v11); + EXPECT_EQ(1U, v1.children().size()); + v1.RemoveChild(v11); + EXPECT_EQ(0U, v1.children().size()); +} + +TEST_F(ViewTreeNodeTest, Reparent) { + ViewTreeNode v1; + ViewTreeNode v2; + ViewTreeNode* v11 = new ViewTreeNode; + v1.AddChild(v11); + EXPECT_EQ(1U, v1.children().size()); + v2.AddChild(v11); + EXPECT_EQ(1U, v2.children().size()); + EXPECT_EQ(0U, v1.children().size()); +} + +TEST_F(ViewTreeNodeTest, Contains) { + ViewTreeNode v1; + + // Direct descendant. + ViewTreeNode* v11 = new ViewTreeNode; + v1.AddChild(v11); + EXPECT_TRUE(v1.Contains(v11)); + + // Indirect descendant. + ViewTreeNode* v111 = new ViewTreeNode; + v11->AddChild(v111); + EXPECT_TRUE(v1.Contains(v111)); +} + +// ViewTreeNodeObserver -------------------------------------------------------- + +typedef testing::Test ViewTreeNodeObserverTest; + +bool TreeChangeParamsMatch(const ViewTreeNodeObserver::TreeChangeParams& lhs, + const ViewTreeNodeObserver::TreeChangeParams& rhs) { + return lhs.target == rhs.target && lhs.old_parent == rhs.old_parent && + lhs.new_parent == rhs.new_parent && lhs.receiver == rhs.receiver && + lhs.phase == rhs.phase; +} + +class TreeChangeObserver : public ViewTreeNodeObserver { + public: + explicit TreeChangeObserver(ViewTreeNode* observee) : observee_(observee) { + observee_->AddObserver(this); + } + virtual ~TreeChangeObserver() { + observee_->RemoveObserver(this); + } + + void Reset() { + received_params_.clear(); + } + + const std::vector<TreeChangeParams>& received_params() { + return received_params_; + } + + private: + // Overridden from ViewTreeNodeObserver: + virtual void OnTreeChange(const TreeChangeParams& params) OVERRIDE { + received_params_.push_back(params); + } + + ViewTreeNode* observee_; + std::vector<TreeChangeParams> received_params_; + + DISALLOW_COPY_AND_ASSIGN(TreeChangeObserver); +}; + +// Adds/Removes v11 to v1. +TEST_F(ViewTreeNodeObserverTest, TreeChange_SimpleAddRemove) { + ViewTreeNode v1; + TreeChangeObserver o1(&v1); + EXPECT_TRUE(o1.received_params().empty()); + + ViewTreeNode v11; + v11.set_owned_by_parent(false); + TreeChangeObserver o11(&v11); + EXPECT_TRUE(o11.received_params().empty()); + + // Add. + + v1.AddChild(&v11); + + EXPECT_EQ(1U, o1.received_params().size()); + ViewTreeNodeObserver::TreeChangeParams p1; + p1.target = &v11; + p1.receiver = &v1; + p1.old_parent = NULL; + p1.new_parent = &v1; + p1.phase = ViewTreeNodeObserver::DISPOSITION_CHANGED; + EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back())); + + EXPECT_EQ(2U, o11.received_params().size()); + ViewTreeNodeObserver::TreeChangeParams p11 = p1; + p11.receiver = &v11; + p11.phase = ViewTreeNodeObserver::DISPOSITION_CHANGING; + EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front())); + p11.phase = ViewTreeNodeObserver::DISPOSITION_CHANGED; + EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back())); + + o1.Reset(); + o11.Reset(); + EXPECT_TRUE(o1.received_params().empty()); + EXPECT_TRUE(o11.received_params().empty()); + + // Remove. + + v1.RemoveChild(&v11); + + EXPECT_EQ(1U, o1.received_params().size()); + p1.target = &v11; + p1.receiver = &v1; + p1.old_parent = &v1; + p1.new_parent = NULL; + p1.phase = ViewTreeNodeObserver::DISPOSITION_CHANGING; + EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back())); + + EXPECT_EQ(2U, o11.received_params().size()); + p11 = p1; + p11.receiver = &v11; + EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front())); + p11.phase = ViewTreeNodeObserver::DISPOSITION_CHANGED; + EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back())); +} + +// Creates these two trees: +// v1 +// +- v11 +// v111 +// +- v1111 +// +- v1112 +// Then adds/removes v111 from v11. +TEST_F(ViewTreeNodeObserverTest, TreeChange_NestedAddRemove) { + ViewTreeNode v1, v11, v111, v1111, v1112; + + // Root tree. + v11.set_owned_by_parent(false); + v1.AddChild(&v11); + + // Tree to be attached. + v111.set_owned_by_parent(false); + v1111.set_owned_by_parent(false); + v111.AddChild(&v1111); + v1112.set_owned_by_parent(false); + v111.AddChild(&v1112); + + TreeChangeObserver o1(&v1), o11(&v11), o111(&v111), o1111(&v1111), + o1112(&v1112); + ViewTreeNodeObserver::TreeChangeParams p1, p11, p111, p1111, p1112; + + // Add. + + v11.AddChild(&v111); + + EXPECT_EQ(1U, o1.received_params().size()); + p1.target = &v111; + p1.receiver = &v1; + p1.old_parent = NULL; + p1.new_parent = &v11; + p1.phase = ViewTreeNodeObserver::DISPOSITION_CHANGED; + EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back())); + + EXPECT_EQ(1U, o11.received_params().size()); + p11 = p1; + p11.receiver = &v11; + EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back())); + + EXPECT_EQ(2U, o111.received_params().size()); + p111 = p11; + p111.receiver = &v111; + p111.phase = ViewTreeNodeObserver::DISPOSITION_CHANGING; + EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front())); + p111.phase = ViewTreeNodeObserver::DISPOSITION_CHANGED; + EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back())); + + EXPECT_EQ(2U, o1111.received_params().size()); + p1111 = p111; + p1111.receiver = &v1111; + p1111.phase = ViewTreeNodeObserver::DISPOSITION_CHANGING; + EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().front())); + p1111.phase = ViewTreeNodeObserver::DISPOSITION_CHANGED; + EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().back())); + + EXPECT_EQ(2U, o1112.received_params().size()); + p1112 = p111; + p1112.receiver = &v1112; + p1112.phase = ViewTreeNodeObserver::DISPOSITION_CHANGING; + EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().front())); + p1112.phase = ViewTreeNodeObserver::DISPOSITION_CHANGED; + EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().back())); + + // Remove. + o1.Reset(); + o11.Reset(); + o111.Reset(); + o1111.Reset(); + o1112.Reset(); + EXPECT_TRUE(o1.received_params().empty()); + EXPECT_TRUE(o11.received_params().empty()); + EXPECT_TRUE(o111.received_params().empty()); + EXPECT_TRUE(o1111.received_params().empty()); + EXPECT_TRUE(o1112.received_params().empty()); + + v11.RemoveChild(&v111); + + EXPECT_EQ(1U, o1.received_params().size()); + p1.target = &v111; + p1.receiver = &v1; + p1.old_parent = &v11; + p1.new_parent = NULL; + p1.phase = ViewTreeNodeObserver::DISPOSITION_CHANGING; + EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back())); + + EXPECT_EQ(1U, o11.received_params().size()); + p11 = p1; + p11.receiver = &v11; + EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back())); + + EXPECT_EQ(2U, o111.received_params().size()); + p111 = p11; + p111.receiver = &v111; + p111.phase = ViewTreeNodeObserver::DISPOSITION_CHANGING; + EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front())); + p111.phase = ViewTreeNodeObserver::DISPOSITION_CHANGED; + EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back())); + + EXPECT_EQ(2U, o1111.received_params().size()); + p1111 = p111; + p1111.receiver = &v1111; + p1111.phase = ViewTreeNodeObserver::DISPOSITION_CHANGING; + EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().front())); + p1111.phase = ViewTreeNodeObserver::DISPOSITION_CHANGED; + EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().back())); + + EXPECT_EQ(2U, o1112.received_params().size()); + p1112 = p111; + p1112.receiver = &v1112; + p1112.phase = ViewTreeNodeObserver::DISPOSITION_CHANGING; + EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().front())); + p1112.phase = ViewTreeNodeObserver::DISPOSITION_CHANGED; + EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().back())); +} + +TEST_F(ViewTreeNodeObserverTest, TreeChange_Reparent) { + ViewTreeNode v1, v11, v12, v111; + v11.set_owned_by_parent(false); + v111.set_owned_by_parent(false); + v12.set_owned_by_parent(false); + v1.AddChild(&v11); + v1.AddChild(&v12); + v11.AddChild(&v111); + + TreeChangeObserver o1(&v1), o11(&v11), o12(&v12), o111(&v111); + + // Reparent. + v12.AddChild(&v111); + + // v1 (root) should see both changing and changed notifications. + EXPECT_EQ(2U, o1.received_params().size()); + ViewTreeNodeObserver::TreeChangeParams p1; + p1.target = &v111; + p1.receiver = &v1; + p1.old_parent = &v11; + p1.new_parent = &v12; + p1.phase = ViewTreeNodeObserver::DISPOSITION_CHANGING; + EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front())); + p1.phase = ViewTreeNodeObserver::DISPOSITION_CHANGED; + EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back())); + + // v11 should see changing notifications. + EXPECT_EQ(1U, o11.received_params().size()); + ViewTreeNodeObserver::TreeChangeParams p11; + p11 = p1; + p11.receiver = &v11; + p11.phase = ViewTreeNodeObserver::DISPOSITION_CHANGING; + EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back())); + + // v12 should see changed notifications. + EXPECT_EQ(1U, o12.received_params().size()); + ViewTreeNodeObserver::TreeChangeParams p12; + p12 = p1; + p12.receiver = &v12; + p12.phase = ViewTreeNodeObserver::DISPOSITION_CHANGED; + EXPECT_TRUE(TreeChangeParamsMatch(p12, o12.received_params().back())); + + // v111 should see both changing and changed notifications. + EXPECT_EQ(2U, o111.received_params().size()); + ViewTreeNodeObserver::TreeChangeParams p111; + p111 = p1; + p111.receiver = &v111; + p111.phase = ViewTreeNodeObserver::DISPOSITION_CHANGING; + EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front())); + p111.phase = ViewTreeNodeObserver::DISPOSITION_CHANGED; + EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back())); +} + +} // namespace view_manager +} // namespace services +} // namespace mojo diff --git a/mojo/services/public/cpp/view_manager/tests/view_unittest.cc b/mojo/services/public/cpp/view_manager/tests/view_unittest.cc new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/mojo/services/public/cpp/view_manager/tests/view_unittest.cc diff --git a/mojo/services/public/cpp/view_manager/view.h b/mojo/services/public/cpp/view_manager/view.h new file mode 100644 index 0000000000..a0bba82054 --- /dev/null +++ b/mojo/services/public/cpp/view_manager/view.h @@ -0,0 +1,24 @@ +// 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_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_H_ +#define MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_H_ + +#include "base/basictypes.h" + +namespace mojo { +namespace services { +namespace view_manager { + +class View { + public: + private: + DISALLOW_COPY_AND_ASSIGN(View); +}; + +} // namespace view_manager +} // namespace services +} // namespace mojo + +#endif // MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_H_ diff --git a/mojo/services/public/cpp/view_manager/view_manager.h b/mojo/services/public/cpp/view_manager/view_manager.h new file mode 100644 index 0000000000..45ab0e2f58 --- /dev/null +++ b/mojo/services/public/cpp/view_manager/view_manager.h @@ -0,0 +1,24 @@ +// 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_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_MANAGER_H_ +#define MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_MANAGER_H_ + +#include "base/basictypes.h" + +namespace mojo { +namespace services { +namespace view_manager { + +class ViewManager { + public: + private: + DISALLOW_COPY_AND_ASSIGN(ViewManager); +}; + +} // namespace view_manager +} // namespace services +} // namespace mojo + +#endif // MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_MANAGER_H_ diff --git a/mojo/services/public/cpp/view_manager/view_tree_host.h b/mojo/services/public/cpp/view_manager/view_tree_host.h new file mode 100644 index 0000000000..13fb6dd1f5 --- /dev/null +++ b/mojo/services/public/cpp/view_manager/view_tree_host.h @@ -0,0 +1,24 @@ +// 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_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_TREE_HOST_H_ +#define MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_TREE_HOST_H_ + +#include "base/basictypes.h" + +namespace mojo { +namespace services { +namespace view_manager { + +class ViewTreeHost { + public: + private: + DISALLOW_COPY_AND_ASSIGN(ViewTreeHost); +}; + +} // namespace view_manager +} // namespace services +} // namespace mojo + +#endif // MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_TREE_HOST_H_ diff --git a/mojo/services/public/cpp/view_manager/view_tree_node.h b/mojo/services/public/cpp/view_manager/view_tree_node.h new file mode 100644 index 0000000000..42f27e71f3 --- /dev/null +++ b/mojo/services/public/cpp/view_manager/view_tree_node.h @@ -0,0 +1,61 @@ +// 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_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_TREE_NODE_H_ +#define MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_TREE_NODE_H_ + +#include <vector> + +#include "base/basictypes.h" +#include "base/observer_list.h" + +namespace mojo { +namespace services { +namespace view_manager { + +class ViewTreeNodeObserver; + +class ViewTreeNode { + public: + typedef std::vector<ViewTreeNode*> Children; + + ViewTreeNode(); + ~ViewTreeNode(); + + // Configuration. + void set_owned_by_parent(bool owned_by_parent) { + owned_by_parent_ = owned_by_parent; + } + + // Observation. + void AddObserver(ViewTreeNodeObserver* observer); + void RemoveObserver(ViewTreeNodeObserver* observer); + + // Tree. + ViewTreeNode* parent() { return parent_; } + const ViewTreeNode* parent() const { return parent_; } + const Children& children() const { return children_; } + + void AddChild(ViewTreeNode* child); + void RemoveChild(ViewTreeNode* child); + + bool Contains(ViewTreeNode* child) const; + + private: + friend class ViewTreeNodePrivate; + + bool owned_by_parent_; + ViewTreeNode* parent_; + Children children_; + + ObserverList<ViewTreeNodeObserver> observers_; + + DISALLOW_COPY_AND_ASSIGN(ViewTreeNode); +}; + +} // namespace view_manager +} // namespace services +} // namespace mojo + +#endif // MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_TREE_NODE_H_ diff --git a/mojo/services/public/cpp/view_manager/view_tree_node_observer.h b/mojo/services/public/cpp/view_manager/view_tree_node_observer.h new file mode 100644 index 0000000000..4b4e6e0c17 --- /dev/null +++ b/mojo/services/public/cpp/view_manager/view_tree_node_observer.h @@ -0,0 +1,44 @@ +// 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_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_TREE_NODE_OBSERVER_H_ +#define MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_TREE_NODE_OBSERVER_H_ + +#include <vector> + +#include "base/basictypes.h" + +namespace mojo { +namespace services { +namespace view_manager { + +class ViewTreeNode; + +class ViewTreeNodeObserver { + public: + enum DispositionChangePhase { + DISPOSITION_CHANGING, + DISPOSITION_CHANGED + }; + + struct TreeChangeParams { + TreeChangeParams(); + ViewTreeNode* target; + ViewTreeNode* old_parent; + ViewTreeNode* new_parent; + ViewTreeNode* receiver; + DispositionChangePhase phase; + }; + + virtual void OnTreeChange(const TreeChangeParams& params) {} + + protected: + virtual ~ViewTreeNodeObserver() {} +}; + +} // namespace view_manager +} // namespace services +} // namespace mojo + +#endif // MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_TREE_NODE_OBSERVER_H_ diff --git a/mojo/services/public/interfaces/view_manager/view_manager.mojom b/mojo/services/public/interfaces/view_manager/view_manager.mojom new file mode 100644 index 0000000000..ef5dcf3c34 --- /dev/null +++ b/mojo/services/public/interfaces/view_manager/view_manager.mojom @@ -0,0 +1,54 @@ +// 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. + +module mojo.services.view_manager { + +// Functions that mutate the hierarchy take a |change_id|. |change_id| is an +// arbitrary value assigned by the client originating the change. It may be +// used by the client originating the change to later identify the change in +// an OnNodeHierarchyChanged callback. |change_id| is only passed to the client +// that originated the change; all other clients get a value of 0. +// +// Nodes are identified by a uint32. The upper 16 bits are the connection id, +// and the lower 16 the id assigned by the client. CreateNode() only takes a +// uint16 as the connection id of the originating connection is used. +// +// The root node is identified with a connection id of 0, and value of 1. +[Peer=ViewManagerClient] +interface ViewManager { + // Creates a new node with the specified id. It is up to the client to ensure + // the id is unique to the connection (the id need not be globally unique). + CreateNode(uint16 node_id) => (bool success); + + // Reparents a node. See description above class for details of |change_id|. + AddNode(uint32 parent, uint32 child, int32 change_id) => (bool success); + + // Removes a view from its current parent. See description above class for + // details of |change_id|. + RemoveNodeFromParent(uint32 node_id, int32 change_id) => (bool success); + + // Creates a new view with the specified id. It is up to the client to ensure + // the id is unique to the connection (the id need not be globally unique). + // CreateView(uint16 view_id) => (bool success); + + // Sets the view a node is showing. + // SetView(uint32 node, uint32 view) => (bool success); +}; + +[Peer=ViewManager] +interface ViewManagerClient { + // Invoked once the connection has been established. |connection_id| is the id + // used to uniquely identify the connection. + OnConnectionEstablished(uint16 connection_id); + + // Invoked when a change is done to the hierarchy. A value of 0 is used to + // identify a null node. For example, if the old_parent is NULL, 0 is + // supplied. See description above ViewManager for details on |change_id|. + OnNodeHierarchyChanged(uint32 node, + uint32 new_parent, + uint32 old_parent, + int32 change_id); +}; + +} diff --git a/mojo/examples/view_manager/DEPS b/mojo/services/view_manager/DEPS index 8cb61f5e0a..05af088e23 100644 --- a/mojo/examples/view_manager/DEPS +++ b/mojo/services/view_manager/DEPS @@ -1,4 +1,6 @@ include_rules = [ + "+mojo/services", + "+ui/aura", "+ui/events", "+ui/gfx", ] diff --git a/mojo/services/view_manager/ids.h b/mojo/services/view_manager/ids.h new file mode 100644 index 0000000000..257402bb91 --- /dev/null +++ b/mojo/services/view_manager/ids.h @@ -0,0 +1,71 @@ +// 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_SERVICES_VIEW_MANAGER_IDS_H_ +#define MOJO_SERVICES_VIEW_MANAGER_IDS_H_ + +#include "mojo/services/view_manager/view_manager_export.h" + +namespace mojo { +namespace services { +namespace view_manager { + +// Adds a bit of type safety to node ids. +struct MOJO_VIEW_MANAGER_EXPORT NodeId { + NodeId(uint16_t connection_id, uint16_t node_id) + : connection_id(connection_id), + node_id(node_id) {} + NodeId() : connection_id(0), node_id(0) {} + + bool operator==(const NodeId& other) const { + return other.connection_id == connection_id && + other.node_id == node_id; + } + + uint16_t connection_id; + uint16_t node_id; +}; + +// Adds a bit of type safety to view ids. +struct MOJO_VIEW_MANAGER_EXPORT ViewId { + ViewId(uint16_t connection_id, uint16_t view_id) + : connection_id(connection_id), + view_id(view_id) {} + ViewId() : connection_id(0), view_id(0) {} + + bool operator==(const ViewId& other) const { + return other.connection_id == connection_id && + other.view_id == view_id; + } + + uint16_t connection_id; + uint16_t view_id; +}; + +// Functions for converting to/from structs and transport values. +inline uint16_t FirstIdFromTransportId(uint32_t id) { + return static_cast<uint16_t>((id >> 16) & 0xFFFF); +} + +inline uint16_t SecondIdFromTransportId(uint32_t id) { + return static_cast<uint16_t>(id & 0xFFFF); +} + +inline NodeId NodeIdFromTransportId(uint32_t id) { + return NodeId(FirstIdFromTransportId(id), SecondIdFromTransportId(id)); +} + +inline uint32_t NodeIdToTransportId(const NodeId& id) { + return (id.connection_id << 16) | id.node_id; +} + +inline ViewId ViewIdFromTransportId(uint32_t id) { + return ViewId(FirstIdFromTransportId(id), SecondIdFromTransportId(id)); +} + +} // namespace view_manager +} // namespace services +} // namespace mojo + +#endif // MOJO_SERVICES_VIEW_MANAGER_IDS_H_ diff --git a/mojo/services/view_manager/node.cc b/mojo/services/view_manager/node.cc new file mode 100644 index 0000000000..1457a7ee6b --- /dev/null +++ b/mojo/services/view_manager/node.cc @@ -0,0 +1,60 @@ +// 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/services/view_manager/node.h" + +#include "mojo/services/view_manager/node_delegate.h" +#include "ui/aura/window_property.h" + +DECLARE_WINDOW_PROPERTY_TYPE(mojo::services::view_manager::Node*); + +namespace mojo { +namespace services { +namespace view_manager { + +DEFINE_WINDOW_PROPERTY_KEY(Node*, kNodeKey, NULL); + +Node::Node(NodeDelegate* delegate, const NodeId& id) + : delegate_(delegate), + id_(id), + window_(NULL) { + DCHECK(delegate); // Must provide a delegate. + window_.set_owned_by_parent(false); + window_.AddObserver(this); + window_.SetProperty(kNodeKey, this); +} + +Node::~Node() { +} + +Node* Node::GetParent() { + if (!window_.parent()) + return NULL; + return window_.parent()->GetProperty(kNodeKey); +} + +void Node::Add(Node* child) { + window_.AddChild(&child->window_); +} + +void Node::Remove(Node* child) { + window_.RemoveChild(&child->window_); +} + +void Node::OnWindowHierarchyChanged( + const aura::WindowObserver::HierarchyChangeParams& params) { + if (params.target != &window_ || params.receiver != &window_) + return; + NodeId new_parent_id; + if (params.new_parent) + new_parent_id = params.new_parent->GetProperty(kNodeKey)->id(); + NodeId old_parent_id; + if (params.old_parent) + old_parent_id = params.old_parent->GetProperty(kNodeKey)->id(); + delegate_->OnNodeHierarchyChanged(id_, new_parent_id, old_parent_id); +} + +} // namespace view_manager +} // namespace services +} // namespace mojo diff --git a/mojo/services/view_manager/node.h b/mojo/services/view_manager/node.h new file mode 100644 index 0000000000..5892af058e --- /dev/null +++ b/mojo/services/view_manager/node.h @@ -0,0 +1,53 @@ +// 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_SERVICES_VIEW_MANAGER_NODE_H_ +#define MOJO_SERVICES_VIEW_MANAGER_NODE_H_ + +#include "base/logging.h" +#include "mojo/services/view_manager/ids.h" +#include "mojo/services/view_manager/view_manager_export.h" +#include "ui/aura/window.h" +#include "ui/aura/window_observer.h" + +namespace mojo { +namespace services { +namespace view_manager { + +class NodeDelegate; + +// Represents a node in the graph. Delegate is informed of interesting events. +class MOJO_VIEW_MANAGER_EXPORT Node : public aura::WindowObserver { + public: + Node(NodeDelegate* delegate, const NodeId& id); + virtual ~Node(); + + void set_view_id(const ViewId& view_id) { view_id_ = view_id; } + const ViewId& view_id() const { return view_id_; } + + const NodeId& id() const { return id_; } + + void Add(Node* child); + void Remove(Node* child); + + Node* GetParent(); + + private: + // WindowObserver overrides: + virtual void OnWindowHierarchyChanged( + const aura::WindowObserver::HierarchyChangeParams& params) OVERRIDE; + + NodeDelegate* delegate_; + const NodeId id_; + ViewId view_id_; + aura::Window window_; + + DISALLOW_COPY_AND_ASSIGN(Node); +}; + +} // namespace view_manager +} // namespace services +} // namespace mojo + +#endif // MOJO_SERVICES_VIEW_MANAGER_NODE_H_ diff --git a/mojo/services/view_manager/node_delegate.h b/mojo/services/view_manager/node_delegate.h new file mode 100644 index 0000000000..3e34940ffc --- /dev/null +++ b/mojo/services/view_manager/node_delegate.h @@ -0,0 +1,31 @@ +// 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_SERVICES_VIEW_MANAGER_NODE_DELEGATE_H_ +#define MOJO_SERVICES_VIEW_MANAGER_NODE_DELEGATE_H_ + +#include "mojo/services/view_manager/view_manager_export.h" + +namespace mojo { +namespace services { +namespace view_manager { + +struct NodeId; + +class MOJO_VIEW_MANAGER_EXPORT NodeDelegate { + public: + // Invoked when the hierarchy has changed. + virtual void OnNodeHierarchyChanged(const NodeId& node, + const NodeId& new_parent, + const NodeId& old_parent) = 0; + + protected: + virtual ~NodeDelegate() {} +}; + +} // namespace view_manager +} // namespace services +} // namespace mojo + +#endif // MOJO_SERVICES_VIEW_MANAGER_NODE_DELEGATE_H_ diff --git a/mojo/services/view_manager/root_node_manager.cc b/mojo/services/view_manager/root_node_manager.cc new file mode 100644 index 0000000000..f35df3da29 --- /dev/null +++ b/mojo/services/view_manager/root_node_manager.cc @@ -0,0 +1,106 @@ +// 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/services/view_manager/root_node_manager.h" + +#include "base/logging.h" +#include "mojo/services/view_manager/view_manager_connection.h" + +namespace mojo { +namespace services { +namespace view_manager { +namespace { + +// Id for the root node. +const uint16_t kRootId = 1; + +} // namespace + +RootNodeManager::ScopedChange::ScopedChange(ViewManagerConnection* connection, + RootNodeManager* root, + int32_t change_id) + : root_(root) { + root_->PrepareForChange(connection, change_id); +} + +RootNodeManager::ScopedChange::~ScopedChange() { + root_->FinishChange(); +} + +RootNodeManager::RootNodeManager() + : next_connection_id_(1), + root_(this, NodeId(0, kRootId)) { +} + +RootNodeManager::~RootNodeManager() { +} + +uint16_t RootNodeManager::GetAndAdvanceNextConnectionId() { + const uint16_t id = next_connection_id_++; + DCHECK_LT(id, next_connection_id_); + return id; +} + +void RootNodeManager::AddConnection(ViewManagerConnection* connection) { + DCHECK_EQ(0u, connection_map_.count(connection->id())); + connection_map_[connection->id()] = connection; +} + +void RootNodeManager::RemoveConnection(ViewManagerConnection* connection) { + connection_map_.erase(connection->id()); +} + +Node* RootNodeManager::GetNode(const NodeId& id) { + if (id == root_.id()) + return &root_; + ConnectionMap::iterator i = connection_map_.find(id.connection_id); + return i == connection_map_.end() ? NULL : i->second->GetNode(id); +} + +void RootNodeManager::NotifyNodeHierarchyChanged(const NodeId& node, + const NodeId& new_parent, + const NodeId& old_parent) { + for (ConnectionMap::iterator i = connection_map_.begin(); + i != connection_map_.end(); ++i) { + const int32_t change_id = (change_ && i->first == change_->connection_id) ? + change_->change_id : 0; + i->second->NotifyNodeHierarchyChanged( + node, new_parent, old_parent, change_id); + } +} + +void RootNodeManager::PrepareForChange(ViewManagerConnection* connection, + int32_t change_id) { + DCHECK(!change_.get()); // Should only ever have one change in flight. + change_.reset(new Change(connection->id(), change_id)); +} + +void RootNodeManager::FinishChange() { + DCHECK(change_.get()); // PrepareForChange/FinishChange should be balanced. + change_.reset(); +} + +void RootNodeManager::OnCreated() { +} + +void RootNodeManager::OnDestroyed() { +} + +void RootNodeManager::OnBoundsChanged(const Rect& bounds) { +} + +void RootNodeManager::OnEvent(const Event& event, + const mojo::Callback<void()>& callback) { + callback.Run(); +} + +void RootNodeManager::OnNodeHierarchyChanged(const NodeId& node, + const NodeId& new_parent, + const NodeId& old_parent) { + NotifyNodeHierarchyChanged(node, new_parent, old_parent); +} + +} // namespace view_manager +} // namespace services +} // namespace mojo diff --git a/mojo/services/view_manager/root_node_manager.h b/mojo/services/view_manager/root_node_manager.h new file mode 100644 index 0000000000..aecfa8b738 --- /dev/null +++ b/mojo/services/view_manager/root_node_manager.h @@ -0,0 +1,117 @@ +// 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_SERVICES_VIEW_MANAGER_ROOT_NODE_MANAGER_H_ +#define MOJO_SERVICES_VIEW_MANAGER_ROOT_NODE_MANAGER_H_ + +#include <map> + +#include "base/basictypes.h" +#include "mojo/services/native_viewport/native_viewport.mojom.h" +#include "mojo/services/view_manager/node.h" +#include "mojo/services/view_manager/node_delegate.h" +#include "mojo/services/view_manager/view_manager_export.h" + +namespace mojo { +namespace services { +namespace view_manager { + +class View; +class ViewManagerConnection; + +// RootNodeManager is responsible for managing the set of ViewManagerConnections +// as well as providing the root of the node hierarchy. +class MOJO_VIEW_MANAGER_EXPORT RootNodeManager + : public NativeViewportClient, + public NodeDelegate { + public: + // Create when a ViewManagerConnection is about to make a change. Ensures + // clients are notified of the correct change id. + class ScopedChange { + public: + ScopedChange(ViewManagerConnection* connection, + RootNodeManager* root, + int32_t change_id); + ~ScopedChange(); + + private: + RootNodeManager* root_; + + DISALLOW_COPY_AND_ASSIGN(ScopedChange); + }; + + RootNodeManager(); + virtual ~RootNodeManager(); + + // Returns the id for the next ViewManagerConnection. + uint16_t GetAndAdvanceNextConnectionId(); + + void AddConnection(ViewManagerConnection* connection); + void RemoveConnection(ViewManagerConnection* connection); + + // Returns the Node identified by |id|. + Node* GetNode(const NodeId& id); + + // Notifies all ViewManagerConnections of a hierarchy change. + void NotifyNodeHierarchyChanged(const NodeId& node, + const NodeId& new_parent, + const NodeId& old_parent); + + private: + // Tracks a change. + struct Change { + Change(int32_t connection_id, int32_t change_id) + : connection_id(connection_id), + change_id(change_id) { + } + + int32_t connection_id; + int32_t change_id; + }; + + typedef std::map<uint16_t, ViewManagerConnection*> ConnectionMap; + + // Invoked when a particular connection is about to make a change. Records + // the |change_id| so that it can be supplied to the clients by way of + // OnNodeHierarchyChanged(). + // Changes should never nest, meaning each PrepareForChange() must be + // balanced with a call to FinishChange() with no PrepareForChange() + // in between. + void PrepareForChange(ViewManagerConnection* connection, int32_t change_id); + + // Balances a call to PrepareForChange(). + void FinishChange(); + + // Overridden from NativeViewportClient: + virtual void OnCreated() OVERRIDE; + virtual void OnDestroyed() OVERRIDE; + virtual void OnBoundsChanged(const Rect& bounds) OVERRIDE; + virtual void OnEvent(const Event& event, + const mojo::Callback<void()>& callback) OVERRIDE; + + // Overriden from NodeDelegate: + virtual void OnNodeHierarchyChanged(const NodeId& node, + const NodeId& new_parent, + const NodeId& old_parent) OVERRIDE; + + // ID to use for next ViewManagerConnection. + uint16_t next_connection_id_; + + // Set of ViewManagerConnections. + ConnectionMap connection_map_; + + // Root node. + Node root_; + + // If non-null we're processing a change. + scoped_ptr<Change> change_; + + DISALLOW_COPY_AND_ASSIGN(RootNodeManager); +}; + +} // namespace view_manager +} // namespace services +} // namespace mojo + +#endif // MOJO_SERVICES_VIEW_MANAGER_ROOT_NODE_MANAGER_H_ diff --git a/mojo/services/view_manager/view_manager.cc b/mojo/services/view_manager/view_manager.cc new file mode 100644 index 0000000000..e2e09f5cb2 --- /dev/null +++ b/mojo/services/view_manager/view_manager.cc @@ -0,0 +1,32 @@ +// 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/message_loop/message_loop.h" +#include "mojo/public/cpp/shell/application.h" +#include "mojo/services/view_manager/root_node_manager.h" +#include "mojo/services/view_manager/view_manager_connection.h" + +#if defined(WIN32) +#if !defined(CDECL) +#define CDECL __cdecl) +#endif +#define VIEW_MANAGER_EXPORT __declspec(dllexport) +#else +#define CDECL +#define VIEW_MANAGER_EXPORT __attribute__((visibility("default"))) +#endif + +extern "C" VIEW_MANAGER_EXPORT MojoResult CDECL MojoMain( + MojoHandle shell_handle) { + base::MessageLoop loop; + mojo::Application app(shell_handle); + mojo::services::view_manager::RootNodeManager root_node_manager; + app.AddServiceConnector(new mojo::ServiceConnector + <mojo::services::view_manager::ViewManagerConnection, + mojo::services::view_manager::RootNodeManager>( + &root_node_manager)); + loop.Run(); + + return MOJO_RESULT_OK; +} diff --git a/mojo/services/view_manager/view_manager_connection.cc b/mojo/services/view_manager/view_manager_connection.cc new file mode 100644 index 0000000000..83c061b497 --- /dev/null +++ b/mojo/services/view_manager/view_manager_connection.cc @@ -0,0 +1,101 @@ +// 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/services/view_manager/view_manager_connection.h" + +#include "base/stl_util.h" +#include "mojo/services/view_manager/node.h" +#include "mojo/services/view_manager/root_node_manager.h" + +namespace mojo { +namespace services { +namespace view_manager { + +ViewManagerConnection::ViewManagerConnection() : id_(0) { +} + +ViewManagerConnection::~ViewManagerConnection() { + STLDeleteContainerPairSecondPointers(node_map_.begin(), node_map_.end()); + context()->RemoveConnection(this); +} + +void ViewManagerConnection::Initialize( + ServiceConnector<ViewManagerConnection, RootNodeManager>* service_factory, + ScopedMessagePipeHandle client_handle) { + DCHECK_EQ(0, id_); // Should only get Initialize() once. + ServiceConnection<ViewManager, ViewManagerConnection, RootNodeManager>:: + Initialize(service_factory, client_handle.Pass()); + id_ = context()->GetAndAdvanceNextConnectionId(); + context()->AddConnection(this); + client()->OnConnectionEstablished(id_); +} + +Node* ViewManagerConnection::GetNode(const NodeId& id) { + if (id_ == id.connection_id) { + NodeMap::iterator i = node_map_.find(id.node_id); + return i == node_map_.end() ? NULL : i->second; + } + return context()->GetNode(id); +} + +void ViewManagerConnection::NotifyNodeHierarchyChanged( + const NodeId& node, + const NodeId& new_parent, + const NodeId& old_parent, + int32_t change_id) { + client()->OnNodeHierarchyChanged(NodeIdToTransportId(node), + NodeIdToTransportId(new_parent), + NodeIdToTransportId(old_parent), + change_id); +} + +void ViewManagerConnection::CreateNode( + uint16_t node_id, + const Callback<void(bool)>& callback) { + // Negative values are reserved. + if (node_map_.find(node_id) != node_map_.end()) { + callback.Run(false); + return; + } + node_map_[node_id] = new Node(this, NodeId(id_, node_id)); + callback.Run(true); +} + +void ViewManagerConnection::AddNode( + uint32_t parent_id, + uint32_t child_id, + int32_t change_id, + const Callback<void(bool)>& callback) { + Node* parent = GetNode(NodeIdFromTransportId(parent_id)); + Node* child = GetNode(NodeIdFromTransportId(child_id)); + const bool success = parent && child && parent != child; + if (success) { + RootNodeManager::ScopedChange change(this, context(), change_id); + parent->Add(child); + } + callback.Run(success); +} + +void ViewManagerConnection::RemoveNodeFromParent( + uint32_t node_id, + int32_t change_id, + const Callback<void(bool)>& callback) { + Node* node = GetNode(NodeIdFromTransportId(node_id)); + const bool success = (node && node->GetParent()); + if (success) { + RootNodeManager::ScopedChange change(this, context(), change_id); + node->GetParent()->Remove(node); + } + callback.Run(success); +} + +void ViewManagerConnection::OnNodeHierarchyChanged(const NodeId& node, + const NodeId& new_parent, + const NodeId& old_parent) { + context()->NotifyNodeHierarchyChanged(node, new_parent, old_parent); +} + +} // namespace view_manager +} // namespace services +} // namespace mojo diff --git a/mojo/services/view_manager/view_manager_connection.h b/mojo/services/view_manager/view_manager_connection.h new file mode 100644 index 0000000000..a03ef6ae0b --- /dev/null +++ b/mojo/services/view_manager/view_manager_connection.h @@ -0,0 +1,81 @@ +// 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_SERVICES_VIEW_MANAGER_VIEW_MANAGER_CONNECTION_H_ +#define MOJO_SERVICES_VIEW_MANAGER_VIEW_MANAGER_CONNECTION_H_ + +#include <set> + +#include "base/basictypes.h" +#include "mojo/public/cpp/shell/service.h" +#include "mojo/services/public/interfaces/view_manager/view_manager.mojom.h" +#include "mojo/services/view_manager/node_delegate.h" +#include "mojo/services/view_manager/view_manager_export.h" + +namespace mojo { +namespace services { +namespace view_manager { + +class Node; +class RootNodeManager; + +// Manages a connection from the client. +class MOJO_VIEW_MANAGER_EXPORT ViewManagerConnection + : public ServiceConnection<ViewManager, ViewManagerConnection, + RootNodeManager>, + public NodeDelegate { + public: + ViewManagerConnection(); + virtual ~ViewManagerConnection(); + + uint16_t id() const { return id_; } + + // Invoked from Service when connection is established. + void Initialize( + ServiceConnector<ViewManagerConnection, RootNodeManager>* service_factory, + ScopedMessagePipeHandle client_handle); + + // Returns the Node by id. + Node* GetNode(const NodeId& id); + + // Notifies the client of a hierarchy change. + void NotifyNodeHierarchyChanged(const NodeId& node, + const NodeId& new_parent, + const NodeId& old_parent, + int32_t change_id); + + private: + typedef std::map<uint16_t, Node*> NodeMap; + + // Overridden from ViewManager: + virtual void CreateNode(uint16_t node_id, + const Callback<void(bool)>& callback) OVERRIDE; + virtual void AddNode(uint32_t parent_id, + uint32_t child_id, + int32_t change_id, + const Callback<void(bool)>& callback) OVERRIDE; + virtual void RemoveNodeFromParent( + uint32_t node_id, + int32_t change_id, + const Callback<void(bool)>& callback) OVERRIDE; + + // Overriden from NodeDelegate: + virtual void OnNodeHierarchyChanged(const NodeId& node, + const NodeId& new_parent, + const NodeId& old_parent) OVERRIDE; + + // Id of this connection as assigned by RootNodeManager. Assigned in + // Initialize(). + uint16_t id_; + + NodeMap node_map_; + + DISALLOW_COPY_AND_ASSIGN(ViewManagerConnection); +}; + +} // namespace view_manager +} // namespace services +} // namespace mojo + +#endif // MOJO_SERVICES_VIEW_MANAGER_VIEW_MANAGER_CONNECTION_H_ diff --git a/mojo/services/view_manager/view_manager_connection_unittest.cc b/mojo/services/view_manager/view_manager_connection_unittest.cc new file mode 100644 index 0000000000..88bf323ea3 --- /dev/null +++ b/mojo/services/view_manager/view_manager_connection_unittest.cc @@ -0,0 +1,307 @@ +// 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/services/view_manager/view_manager_connection.h" + +#include <string> +#include <vector> + +#include "base/bind.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/strings/stringprintf.h" +#include "mojo/public/cpp/bindings/allocation_scope.h" +#include "mojo/public/cpp/environment/environment.h" +#include "mojo/services/view_manager/root_node_manager.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace services { +namespace view_manager { + +namespace { + +base::RunLoop* current_run_loop = NULL; + +// Sets |current_run_loop| and runs it. It is expected that someone else quits +// the loop. +void DoRunLoop() { + base::RunLoop run_loop; + current_run_loop = &run_loop; + current_run_loop->Run(); + current_run_loop = NULL; +} + +// Converts |id| into a string. +std::string NodeIdToString(uint32_t id) { + return (id == 0) ? "null" : + base::StringPrintf("%d,%d", FirstIdFromTransportId(id), + SecondIdFromTransportId(id)); +} + +// Boolean callback. Sets |result_cache| to the value of |result| and quits +// the run loop. +void BooleanCallback(bool* result_cache, bool result) { + *result_cache = result; + current_run_loop->Quit(); +} + +// Creates an id used for transport from the specified parameters. +uint32_t CreateNodeId(uint16_t connection_id, uint16_t node_id) { + return NodeIdToTransportId(NodeId(connection_id, node_id)); +} + +// Creates a node with the specified id. Returns true on success. Blocks until +// we get back result from server. +bool CreateNode(ViewManager* view_manager, uint16_t id) { + bool result = false; + view_manager->CreateNode(id, base::Bind(&BooleanCallback, &result)); + DoRunLoop(); + return result; +} + +// Adds a node, blocking until done. +bool AddNode(ViewManager* view_manager, + uint32_t parent, + uint32_t child, + int32_t change_id) { + bool result = false; + view_manager->AddNode(parent, child, change_id, + base::Bind(&BooleanCallback, &result)); + DoRunLoop(); + return result; +} + +// Removes a node, blocking until done. +bool RemoveNodeFromParent(ViewManager* view_manager, + uint32_t node_id, + int32_t change_id) { + bool result = false; + view_manager->RemoveNodeFromParent(node_id, change_id, + base::Bind(&BooleanCallback, &result)); + DoRunLoop(); + return result; +} + +} // namespace + +typedef std::vector<std::string> Changes; + +class ViewManagerClientImpl : public ViewManagerClient { + public: + ViewManagerClientImpl() : id_(0), quit_count_(0) {} + + void set_quit_count(int count) { quit_count_ = count; } + + uint16_t id() const { return id_; } + + Changes GetAndClearChanges() { + Changes changes; + changes.swap(changes_); + return changes; + } + + private: + // ViewManagerClient overrides: + virtual void OnConnectionEstablished(uint16_t connection_id) OVERRIDE { + id_ = connection_id; + current_run_loop->Quit(); + } + virtual void OnNodeHierarchyChanged(uint32_t node, + uint32_t new_parent, + uint32_t old_parent, + int32_t change_id) OVERRIDE { + changes_.push_back( + base::StringPrintf( + "change_id=%d node=%s new_parent=%s old_parent=%s", + change_id, NodeIdToString(node).c_str(), + NodeIdToString(new_parent).c_str(), + NodeIdToString(old_parent).c_str())); + if (quit_count_ > 0) { + if (--quit_count_ == 0) + current_run_loop->Quit(); + } + } + + uint16_t id_; + + // Used to determine when/if to quit the run loop. + int quit_count_; + + Changes changes_; + + DISALLOW_COPY_AND_ASSIGN(ViewManagerClientImpl); +}; + +class ViewManagerConnectionTest : public testing::Test { + public: + ViewManagerConnectionTest() : service_factory_(&root_node_manager_) {} + + virtual void SetUp() OVERRIDE { + InterfacePipe<ViewManagerClient, ViewManager> pipe; + view_manager_.reset(pipe.handle_to_peer.Pass(), &client_); + connection_.Initialize( + &service_factory_, + ScopedMessagePipeHandle::From(pipe.handle_to_self.Pass())); + // Wait for the id. + DoRunLoop(); + } + + protected: + // Creates a second connection to the viewmanager. + void EstablishSecondConnection() { + connection2_.reset(new ViewManagerConnection); + InterfacePipe<ViewManagerClient, ViewManager> pipe; + view_manager2_.reset(pipe.handle_to_peer.Pass(), &client2_); + connection2_->Initialize( + &service_factory_, + ScopedMessagePipeHandle::From(pipe.handle_to_self.Pass())); + // Wait for the id. + DoRunLoop(); + } + + Environment env_; + base::MessageLoop loop_; + RootNodeManager root_node_manager_; + ServiceConnector<ViewManagerConnection, RootNodeManager> service_factory_; + ViewManagerConnection connection_; + ViewManagerClientImpl client_; + RemotePtr<ViewManager> view_manager_; + + ViewManagerClientImpl client2_; + RemotePtr<ViewManager> view_manager2_; + scoped_ptr<ViewManagerConnection> connection2_; + + DISALLOW_COPY_AND_ASSIGN(ViewManagerConnectionTest); +}; + +// Verifies client gets a valid id. +TEST_F(ViewManagerConnectionTest, ValidId) { + EXPECT_NE(0, client_.id()); +} + +// Verifies two clients/connections get different ids. +TEST_F(ViewManagerConnectionTest, TwoClientsGetDifferentConnectionIds) { + EstablishSecondConnection(); + EXPECT_NE(0, client2_.id()); + EXPECT_NE(client_.id(), client2_.id()); +} + +// Verifies client gets a valid id. +TEST_F(ViewManagerConnectionTest, CreateNode) { + ASSERT_TRUE(CreateNode(view_manager_.get(), 1)); + + // Can't create a node with the same id. + ASSERT_FALSE(CreateNode(view_manager_.get(), 1)); +} + +// Verifies hierarchy changes. +TEST_F(ViewManagerConnectionTest, AddRemoveNotify) { + ASSERT_TRUE(CreateNode(view_manager_.get(), 1)); + ASSERT_TRUE(CreateNode(view_manager_.get(), 2)); + + EXPECT_TRUE(client_.GetAndClearChanges().empty()); + + // Make 2 a child of 1. + { + AllocationScope scope; + ASSERT_TRUE(AddNode(view_manager_.get(), + CreateNodeId(client_.id(), 1), + CreateNodeId(client_.id(), 2), + 11)); + Changes changes(client_.GetAndClearChanges()); + ASSERT_EQ(1u, changes.size()); + EXPECT_EQ("change_id=11 node=1,2 new_parent=1,1 old_parent=null", + changes[0]); + } + + // Remove 2 from its parent. + { + AllocationScope scope; + ASSERT_TRUE(RemoveNodeFromParent(view_manager_.get(), + CreateNodeId(client_.id(), 2), + 101)); + Changes changes(client_.GetAndClearChanges()); + ASSERT_EQ(1u, changes.size()); + EXPECT_EQ("change_id=101 node=1,2 new_parent=null old_parent=1,1", + changes[0]); + } +} + +// Verifies hierarchy changes are sent to multiple clients. +TEST_F(ViewManagerConnectionTest, AddRemoveNotifyMultipleConnections) { + EstablishSecondConnection(); + + // Create two nodes in first connection. + ASSERT_TRUE(CreateNode(view_manager_.get(), 1)); + ASSERT_TRUE(CreateNode(view_manager_.get(), 2)); + + EXPECT_TRUE(client_.GetAndClearChanges().empty()); + EXPECT_TRUE(client2_.GetAndClearChanges().empty()); + + // Make 2 a child of 1. + { + AllocationScope scope; + ASSERT_TRUE(AddNode(view_manager_.get(), + CreateNodeId(client_.id(), 1), + CreateNodeId(client_.id(), 2), + 11)); + Changes changes(client_.GetAndClearChanges()); + ASSERT_EQ(1u, changes.size()); + EXPECT_EQ("change_id=11 node=1,2 new_parent=1,1 old_parent=null", + changes[0]); + } + + // Second client should also have received the change. + { + Changes changes(client2_.GetAndClearChanges()); + if (changes.empty()) { + client2_.set_quit_count(1); + DoRunLoop(); + changes = client2_.GetAndClearChanges(); + } + ASSERT_EQ(1u, changes.size()); + EXPECT_EQ("change_id=0 node=1,2 new_parent=1,1 old_parent=null", + changes[0]); + } +} + +// Verifies adding to root sends right notifications. +TEST_F(ViewManagerConnectionTest, AddToRoot) { + ASSERT_TRUE(CreateNode(view_manager_.get(), 21)); + ASSERT_TRUE(CreateNode(view_manager_.get(), 3)); + + EXPECT_TRUE(client_.GetAndClearChanges().empty()); + + // Make 3 a child of 21. + { + AllocationScope scope; + ASSERT_TRUE(AddNode(view_manager_.get(), + CreateNodeId(client_.id(), 21), + CreateNodeId(client_.id(), 3), + 11)); + Changes changes(client_.GetAndClearChanges()); + ASSERT_EQ(1u, changes.size()); + EXPECT_EQ("change_id=11 node=1,3 new_parent=1,21 old_parent=null", + changes[0]); + } + + // Make 21 a child of the root. + { + AllocationScope scope; + ASSERT_TRUE(AddNode(view_manager_.get(), + CreateNodeId(0, 1), + CreateNodeId(client_.id(), 21), + 44)); + Changes changes(client_.GetAndClearChanges()); + ASSERT_EQ(1u, changes.size()); + EXPECT_EQ("change_id=44 node=1,21 new_parent=0,1 old_parent=null", + changes[0]); + } +} + +} // namespace view_manager +} // namespace services +} // namespace mojo diff --git a/mojo/services/view_manager/view_manager_export.h b/mojo/services/view_manager/view_manager_export.h new file mode 100644 index 0000000000..29b0e6219c --- /dev/null +++ b/mojo/services/view_manager/view_manager_export.h @@ -0,0 +1,31 @@ +// 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_SERVICES_VIEW_MANAGER_VIEW_MANAGER_EXPORT_H_ +#define MOJO_SERVICES_VIEW_MANAGER_VIEW_MANAGER_EXPORT_H_ + +#if defined(COMPONENT_BUILD) +#if defined(WIN32) + +#if defined(MOJO_VIEW_MANAGER_IMPLEMENTATION) +#define MOJO_VIEW_MANAGER_EXPORT __declspec(dllexport) +#else +#define MOJO_VIEW_MANAGER_EXPORT __declspec(dllimport) +#endif + +#else // !defined(WIN32) + +#if defined(MOJO_VIEW_MANAGER_IMPLEMENTATION) +#define MOJO_VIEW_MANAGER_EXPORT __attribute__((visibility("default"))) +#else +#define MOJO_VIEW_MANAGER_EXPORT +#endif + +#endif // defined(WIN32) + +#else // defined(COMPONENT_BUILD) +#define MOJO_VIEW_MANAGER_EXPORT +#endif + +#endif // MOJO_SERVICES_VIEW_MANAGER_VIEW_MANAGER_EXPORT_H_ diff --git a/mojo/shell/android/mojo_main.cc b/mojo/shell/android/mojo_main.cc index a9128646e4..9d70c8fecd 100644 --- a/mojo/shell/android/mojo_main.cc +++ b/mojo/shell/android/mojo_main.cc @@ -13,10 +13,10 @@ #include "base/macros.h" #include "base/message_loop/message_loop.h" #include "jni/MojoMain_jni.h" +#include "mojo/public/cpp/environment/environment.h" #include "mojo/public/cpp/shell/application.h" #include "mojo/service_manager/service_loader.h" #include "mojo/service_manager/service_manager.h" -#include "mojo/services/native_viewport/native_viewport_service.h" #include "mojo/shell/context.h" #include "mojo/shell/init.h" #include "mojo/shell/run.h" @@ -34,28 +34,9 @@ LazyInstance<scoped_ptr<base::MessageLoop> > g_java_message_loop = LazyInstance<scoped_ptr<shell::Context> > g_context = LAZY_INSTANCE_INITIALIZER; -class NativeViewportServiceLoader : public ServiceLoader { - public: - NativeViewportServiceLoader() {} - virtual ~NativeViewportServiceLoader() {} - - private: - virtual void LoadService(ServiceManager* manager, - const GURL& url, - ScopedShellHandle service_handle) OVERRIDE { - app_.reset(CreateNativeViewportService(g_context.Get().get(), - service_handle.Pass())); - } - - virtual void OnServiceError(ServiceManager* manager, - const GURL& url) OVERRIDE { - } - scoped_ptr<Application> app_; -}; - -LazyInstance<scoped_ptr<NativeViewportServiceLoader> > - g_viewport_service_loader = LAZY_INSTANCE_INITIALIZER; +LazyInstance<scoped_ptr<mojo::Environment> > g_env = + LAZY_INSTANCE_INITIALIZER; } // namspace @@ -93,15 +74,13 @@ static void Start(JNIEnv* env, jclass clazz, jobject context, jstring jurl) { CommandLine::ForCurrentProcess()->InitFromArgv(argv); } + g_env.Get().reset(new Environment); + base::android::ScopedJavaGlobalRef<jobject> activity; activity.Reset(env, context); shell::Context* shell_context = new shell::Context(); shell_context->set_activity(activity.obj()); - g_viewport_service_loader.Get().reset(new NativeViewportServiceLoader()); - shell_context->service_manager()->SetLoaderForURL( - g_viewport_service_loader.Get().get(), - GURL("mojo:mojo_native_viewport_service")); g_context.Get().reset(shell_context); shell::Run(shell_context); diff --git a/mojo/shell/context.cc b/mojo/shell/context.cc index 2ba4aef4f1..df86d14bfc 100644 --- a/mojo/shell/context.cc +++ b/mojo/shell/context.cc @@ -59,12 +59,12 @@ Context::Context() else runner_factory.reset(new InProcessDynamicServiceRunnerFactory()); - dynamic_service_loader_.reset( - new DynamicServiceLoader(this, runner_factory.Pass())); - service_manager_.set_default_loader(dynamic_service_loader_.get()); - native_viewport_service_loader_.reset(new NativeViewportServiceLoader(this)); - service_manager_.SetLoaderForURL(native_viewport_service_loader_.get(), - GURL("mojo:mojo_native_viewport_service")); + service_manager_.set_default_loader( + scoped_ptr<ServiceLoader>( + new DynamicServiceLoader(this, runner_factory.Pass()))); + service_manager_.SetLoaderForURL( + scoped_ptr<ServiceLoader>(new NativeViewportServiceLoader(this)), + GURL("mojo:mojo_native_viewport_service")); if (cmdline->HasSwitch(switches::kSpy)) { spy_.reset(new mojo::Spy(&service_manager_, @@ -73,7 +73,7 @@ Context::Context() } Context::~Context() { - service_manager_.set_default_loader(NULL); + service_manager_.set_default_loader(scoped_ptr<ServiceLoader>()); } } // namespace shell diff --git a/mojo/shell/context.h b/mojo/shell/context.h index 57ed5d508a..c9acdc4fb1 100644 --- a/mojo/shell/context.h +++ b/mojo/shell/context.h @@ -46,9 +46,7 @@ class Context { Storage storage_; Loader loader_; ServiceManager service_manager_; - scoped_ptr<DynamicServiceLoader> dynamic_service_loader_; scoped_ptr<Spy> spy_; - scoped_ptr<NativeViewportServiceLoader> native_viewport_service_loader_; #if defined(OS_ANDROID) base::android::ScopedJavaGlobalRef<jobject> activity_; #endif // defined(OS_ANDROID) diff --git a/mojo/system/channel.cc b/mojo/system/channel.cc index 770275a1a8..b0b9df93cf 100644 --- a/mojo/system/channel.cc +++ b/mojo/system/channel.cc @@ -4,11 +4,14 @@ #include "mojo/system/channel.h" +#include <algorithm> + #include "base/basictypes.h" #include "base/bind.h" #include "base/compiler_specific.h" #include "base/logging.h" #include "base/strings/stringprintf.h" +#include "build/build_config.h" // TODO(vtl): Remove this. #include "mojo/system/message_pipe_endpoint.h" namespace mojo { @@ -21,12 +24,15 @@ COMPILE_ASSERT(Channel::kBootstrapEndpointId != STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::EndpointId Channel::kBootstrapEndpointId; -Channel::EndpointInfo::EndpointInfo() { +Channel::EndpointInfo::EndpointInfo() + : state(STATE_NORMAL), + port() { } Channel::EndpointInfo::EndpointInfo(scoped_refptr<MessagePipe> message_pipe, unsigned port) - : message_pipe(message_pipe), + : state(STATE_NORMAL), + message_pipe(message_pipe), port(port) { } @@ -34,7 +40,8 @@ Channel::EndpointInfo::~EndpointInfo() { } Channel::Channel() - : next_local_id_(kBootstrapEndpointId) { + : is_running_(false), + next_local_id_(kBootstrapEndpointId) { } bool Channel::Init(scoped_ptr<RawChannel> raw_channel) { @@ -43,7 +50,7 @@ bool Channel::Init(scoped_ptr<RawChannel> raw_channel) { // No need to take |lock_|, since this must be called before this object // becomes thread-safe. - DCHECK(!raw_channel_); + DCHECK(!is_running_no_lock()); raw_channel_ = raw_channel.Pass(); if (!raw_channel_->Init(this)) { @@ -51,34 +58,50 @@ bool Channel::Init(scoped_ptr<RawChannel> raw_channel) { return false; } + is_running_ = true; return true; } void Channel::Shutdown() { DCHECK(creation_thread_checker_.CalledOnValidThread()); - base::AutoLock locker(lock_); - DCHECK(raw_channel_.get()); - raw_channel_->Shutdown(); - raw_channel_.reset(); - - // This should not occur, but it probably mostly results in leaking; - // (Explicitly clearing the |local_id_to_endpoint_info_map_| would likely put - // things in an inconsistent state, which is worse. Note that if the map is - // nonempty, we probably won't be destroyed, since the endpoints have a - // reference to us.) - LOG_IF(ERROR, !local_id_to_endpoint_info_map_.empty()) - << "Channel shutting down with endpoints still attached"; - // TODO(vtl): This currently blows up, but the fix will be nontrivial. - // crbug.com/360081 - //DCHECK(local_id_to_endpoint_info_map_.empty()); + IdToEndpointInfoMap to_destroy; + { + base::AutoLock locker(lock_); + if (!is_running_no_lock()) + return; + + // Note: Don't reset |raw_channel_|, in case we're being called from within + // |OnReadMessage()| or |OnFatalError()|. + raw_channel_->Shutdown(); + is_running_ = false; + + // We need to deal with it outside the lock. + std::swap(to_destroy, local_id_to_endpoint_info_map_); + } + + size_t num_live = 0; + size_t num_zombies = 0; + for (IdToEndpointInfoMap::iterator it = to_destroy.begin(); + it != to_destroy.end(); + ++it) { + if (it->second.state == EndpointInfo::STATE_NORMAL) { + it->second.message_pipe->OnRemove(it->second.port); + num_live++; + } else { + DCHECK(!it->second.message_pipe.get()); + num_zombies++; + } + } + DVLOG(2) << "Shut down Channel with " << num_live << " live endpoints and " + << num_zombies << " zombies"; } MessageInTransit::EndpointId Channel::AttachMessagePipeEndpoint( - scoped_refptr<MessagePipe> message_pipe, unsigned port) { + scoped_refptr<MessagePipe> message_pipe, + unsigned port) { + DCHECK(message_pipe); DCHECK(port == 0 || port == 1); - // Note: This assertion must *not* be done under |lock_|. - DCHECK_EQ(message_pipe->GetType(port), MessagePipeEndpoint::kTypeProxy); MessageInTransit::EndpointId local_id; { @@ -98,8 +121,32 @@ MessageInTransit::EndpointId Channel::AttachMessagePipeEndpoint( local_id_to_endpoint_info_map_[local_id] = EndpointInfo(message_pipe, port); } - message_pipe->Attach(port, scoped_refptr<Channel>(this), local_id); - return local_id; + // This might fail if that port got an |OnPeerClose()| before attaching. + if (message_pipe->Attach(port, scoped_refptr<Channel>(this), local_id)) + return local_id; + + // Note: If it failed, quite possibly the endpoint info was removed from that + // map (there's a race between us adding it to the map above and calling + // |Attach()|). And even if an entry exists for |local_id|, we need to check + // that it's the one we added (and not some other one that was added since). + { + base::AutoLock locker(lock_); + IdToEndpointInfoMap::iterator it = + local_id_to_endpoint_info_map_.find(local_id); + if (it != local_id_to_endpoint_info_map_.end() && + it->second.message_pipe.get() == message_pipe.get() && + it->second.port == port) { + DCHECK_EQ(it->second.state, EndpointInfo::STATE_NORMAL); + // TODO(vtl): FIXME -- This is wrong. We need to specify (to + // |AttachMessagePipeEndpoint()| who's going to be responsible for calling + // |RunMessagePipeEndpoint()| ("us", or the remote by sending us a + // |kSubtypeChannelRunMessagePipeEndpoint|). If the remote is going to + // run, then we'll get messages to an "invalid" local ID (for running, for + // removal). + local_id_to_endpoint_info_map_.erase(it); + } + } + return MessageInTransit::kInvalidEndpointId; } bool Channel::RunMessagePipeEndpoint(MessageInTransit::EndpointId local_id, @@ -115,6 +162,14 @@ bool Channel::RunMessagePipeEndpoint(MessageInTransit::EndpointId local_id, endpoint_info = it->second; } + // Assume that this was in response to |kSubtypeChannelRunMessagePipeEndpoint| + // and ignore it. + if (endpoint_info.state != EndpointInfo::STATE_NORMAL) { + DVLOG(2) << "Ignoring run message pipe endpoint for zombie endpoint " + "(local ID " << local_id << ", remote ID " << remote_id << ")"; + return true; + } + // TODO(vtl): FIXME -- We need to handle the case that message pipe is already // running when we're here due to |kSubtypeChannelRunMessagePipeEndpoint|). endpoint_info.message_pipe->Run(endpoint_info.port, remote_id); @@ -124,27 +179,27 @@ bool Channel::RunMessagePipeEndpoint(MessageInTransit::EndpointId local_id, void Channel::RunRemoteMessagePipeEndpoint( MessageInTransit::EndpointId local_id, MessageInTransit::EndpointId remote_id) { - base::AutoLock locker(lock_); - - DCHECK(local_id_to_endpoint_info_map_.find(local_id) != - local_id_to_endpoint_info_map_.end()); +#if DCHECK_IS_ON + { + base::AutoLock locker(lock_); + DCHECK(local_id_to_endpoint_info_map_.find(local_id) != + local_id_to_endpoint_info_map_.end()); + } +#endif - scoped_ptr<MessageInTransit> message(new MessageInTransit( - MessageInTransit::kTypeChannel, - MessageInTransit::kSubtypeChannelRunMessagePipeEndpoint, - 0, 0, NULL)); - message->set_source_id(local_id); - message->set_destination_id(remote_id); - if (!raw_channel_->WriteMessage(message.Pass())) { - // TODO(vtl): FIXME -- I guess we should report the error back somehow so - // that the dispatcher can be closed? - CHECK(false) << "Not yet handled"; + if (!SendControlMessage( + MessageInTransit::kSubtypeChannelRunMessagePipeEndpoint, + local_id, remote_id)) { + HandleLocalError(base::StringPrintf( + "Failed to send message to run remote message pipe endpoint (local ID " + "%u, remote ID %u)", + static_cast<unsigned>(local_id), static_cast<unsigned>(remote_id))); } } bool Channel::WriteMessage(scoped_ptr<MessageInTransit> message) { base::AutoLock locker(lock_); - if (!raw_channel_.get()) { + if (!is_running_no_lock()) { // TODO(vtl): I think this is probably not an error condition, but I should // think about it (and the shutdown sequence) more carefully. LOG(WARNING) << "WriteMessage() after shutdown"; @@ -156,24 +211,60 @@ bool Channel::WriteMessage(scoped_ptr<MessageInTransit> message) { bool Channel::IsWriteBufferEmpty() { base::AutoLock locker(lock_); - DCHECK(raw_channel_.get()); + if (!is_running_no_lock()) + return true; return raw_channel_->IsWriteBufferEmpty(); } -void Channel::DetachMessagePipeEndpoint(MessageInTransit::EndpointId local_id) { +void Channel::DetachMessagePipeEndpoint( + MessageInTransit::EndpointId local_id, + MessageInTransit::EndpointId remote_id) { DCHECK_NE(local_id, MessageInTransit::kInvalidEndpointId); - base::AutoLock locker_(lock_); - local_id_to_endpoint_info_map_.erase(local_id); + bool should_send_remove_message = false; + { + base::AutoLock locker_(lock_); + if (!is_running_no_lock()) + return; + + IdToEndpointInfoMap::iterator it = + local_id_to_endpoint_info_map_.find(local_id); + DCHECK(it != local_id_to_endpoint_info_map_.end()); + + switch (it->second.state) { + case EndpointInfo::STATE_NORMAL: + it->second.state = EndpointInfo::STATE_WAIT_REMOTE_REMOVE_ACK; + it->second.message_pipe = NULL; + should_send_remove_message = + (remote_id != MessageInTransit::kInvalidEndpointId); + break; + case EndpointInfo::STATE_WAIT_LOCAL_DETACH: + local_id_to_endpoint_info_map_.erase(it); + break; + case EndpointInfo::STATE_WAIT_REMOTE_REMOVE_ACK: + NOTREACHED(); + break; + case EndpointInfo::STATE_WAIT_LOCAL_DETACH_AND_REMOTE_REMOVE_ACK: + it->second.state = EndpointInfo::STATE_WAIT_REMOTE_REMOVE_ACK; + break; + } + } + if (!should_send_remove_message) + return; + + if (!SendControlMessage( + MessageInTransit::kSubtypeChannelRemoveMessagePipeEndpoint, + local_id, remote_id)) { + HandleLocalError(base::StringPrintf( + "Failed to send message to remove remote message pipe endpoint (local " + "ID %u, remote ID %u)", + static_cast<unsigned>(local_id), static_cast<unsigned>(remote_id))); + } } Channel::~Channel() { // The channel should have been shut down first. - DCHECK(!raw_channel_.get()); - - DLOG_IF(WARNING, !local_id_to_endpoint_info_map_.empty()) - << "Destroying Channel with " << local_id_to_endpoint_info_map_.size() - << " endpoints still present"; + DCHECK(!is_running_no_lock()); } void Channel::OnReadMessage(const MessageInTransit::View& message_view) { @@ -198,8 +289,13 @@ void Channel::OnReadMessage(const MessageInTransit::View& message_view) { } void Channel::OnFatalError(FatalError fatal_error) { - // TODO(vtl): IMPORTANT. Notify all our endpoints that they're dead. - NOTIMPLEMENTED(); + LOG(ERROR) << "RawChannel fatal error (type " << fatal_error << ")"; + // TODO(vtl): We have some nested-deletion bugs on Windows, so this crashes. +#if defined(OS_WIN) + LOG(ERROR) << "Not shutting down due Windows-only bug"; +#else + Shutdown(); +#endif } bool Channel::ValidateReadMessage(const MessageInTransit::View& message_view) { @@ -231,7 +327,7 @@ void Channel::OnReadMessageForDownstream( // 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(raw_channel_.get()); + DCHECK(is_running_no_lock()); IdToEndpointInfoMap::const_iterator it = local_id_to_endpoint_info_map_.find(local_id); @@ -249,6 +345,13 @@ void Channel::OnReadMessageForDownstream( endpoint_info = it->second; } + // Ignore messages for zombie endpoints (not an error). + if (endpoint_info.state != EndpointInfo::STATE_NORMAL) { + DVLOG(2) << "Ignoring downstream message for zombie endpoint (local ID = " + << local_id << ", remote ID = " << message_view.source_id() << ")"; + return; + } + // We need to duplicate the message, because |EnqueueMessage()| will take // ownership of it. scoped_ptr<MessageInTransit> message(new MessageInTransit(message_view)); @@ -261,7 +364,7 @@ void Channel::OnReadMessageForDownstream( // error, e.g., if the remote side is sending invalid control messages (to // the message pipe). HandleLocalError(base::StringPrintf( - "Failed to enqueue message to local destination ID %u (result %d)", + "Failed to enqueue message to local ID %u (result %d)", static_cast<unsigned>(local_id), static_cast<int>(result))); return; } @@ -273,14 +376,35 @@ void Channel::OnReadMessageForChannel( switch (message_view.subtype()) { case MessageInTransit::kSubtypeChannelRunMessagePipeEndpoint: - // TODO(vtl): FIXME -- Error handling (also validation of - // source/destination IDs). - DVLOG(2) << "Handling channel message to run message pipe (local ID = " - << message_view.destination_id() << ", remote ID = " + DVLOG(2) << "Handling channel message to run message pipe (local ID " + << message_view.destination_id() << ", remote ID " << message_view.source_id() << ")"; if (!RunMessagePipeEndpoint(message_view.destination_id(), - message_view.source_id())) - HandleRemoteError("Received invalid channel run message pipe message"); + message_view.source_id())) { + HandleRemoteError( + "Received invalid channel message to run message pipe"); + } + break; + case MessageInTransit::kSubtypeChannelRemoveMessagePipeEndpoint: + DVLOG(2) << "Handling channel message to remove message pipe (local ID " + << message_view.destination_id() << ", remote ID " + << message_view.source_id() << ")"; + if (!RemoveMessagePipeEndpoint(message_view.destination_id(), + message_view.source_id())) { + HandleRemoteError( + "Received invalid channel message to remove message pipe"); + } + break; + case MessageInTransit::kSubtypeChannelRemoveMessagePipeEndpointAck: + DVLOG(2) << "Handling channel message to ack remove message pipe (local " + "ID " + << message_view.destination_id() << ", remote ID " + << message_view.source_id() << ")"; + if (!RemoveMessagePipeEndpoint(message_view.destination_id(), + message_view.source_id())) { + HandleRemoteError( + "Received invalid channel message to ack remove message pipe"); + } break; default: HandleRemoteError("Received invalid channel message"); @@ -289,6 +413,62 @@ void Channel::OnReadMessageForChannel( } } +bool Channel::RemoveMessagePipeEndpoint( + MessageInTransit::EndpointId local_id, + MessageInTransit::EndpointId remote_id) { + EndpointInfo endpoint_info; + { + base::AutoLock locker(lock_); + + IdToEndpointInfoMap::iterator it = + local_id_to_endpoint_info_map_.find(local_id); + if (it == local_id_to_endpoint_info_map_.end()) { + DVLOG(2) << "Remove message pipe error: not found"; + return false; + } + + // If it's waiting for the remove ack, just do it and return. + if (it->second.state == EndpointInfo::STATE_WAIT_REMOTE_REMOVE_ACK) { + local_id_to_endpoint_info_map_.erase(it); + return true; + } + + if (it->second.state != EndpointInfo::STATE_NORMAL) { + DVLOG(2) << "Remove message pipe error: wrong state"; + return false; + } + + it->second.state = EndpointInfo::STATE_WAIT_LOCAL_DETACH; + endpoint_info = it->second; + it->second.message_pipe = NULL; + } + + if (!SendControlMessage( + MessageInTransit::kSubtypeChannelRemoveMessagePipeEndpointAck, + local_id, remote_id)) { + HandleLocalError(base::StringPrintf( + "Failed to send message to remove remote message pipe endpoint ack " + "(local ID %u, remote ID %u)", + static_cast<unsigned>(local_id), static_cast<unsigned>(remote_id))); + } + + endpoint_info.message_pipe->OnRemove(endpoint_info.port); + + return true; +} + +bool Channel::SendControlMessage(MessageInTransit::Subtype subtype, + MessageInTransit::EndpointId local_id, + MessageInTransit::EndpointId 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::kTypeChannel, subtype, 0, 0, NULL)); + message->set_source_id(local_id); + message->set_destination_id(remote_id); + return WriteMessage(message.Pass()); +} + void Channel::HandleRemoteError(const base::StringPiece& 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. @@ -297,6 +477,10 @@ void Channel::HandleRemoteError(const base::StringPiece& error_message) { void Channel::HandleLocalError(const base::StringPiece& 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. LOG(WARNING) << error_message; } diff --git a/mojo/system/channel.h b/mojo/system/channel.h index 1e66a8804e..7b30dbb4f3 100644 --- a/mojo/system/channel.h +++ b/mojo/system/channel.h @@ -72,11 +72,12 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel // which it returns. The first message pipe endpoint attached will always have // |kBootstrapEndpointId| as its local ID. (For bootstrapping, this occurs on // both sides, so one should use |kBootstrapEndpointId| for the remote ID for - // the first message pipe across a channel.) - // TODO(vtl): Maybe limit the number of attached message pipes and allow this - // to fail. + // the first message pipe across a channel.) Returns |kInvalidEndpointId| on + // failure. + // TODO(vtl): Maybe limit the number of attached message pipes. MessageInTransit::EndpointId AttachMessagePipeEndpoint( - scoped_refptr<MessagePipe> message_pipe, unsigned port); + scoped_refptr<MessagePipe> message_pipe, + unsigned port); // Runs the message pipe with the given |local_id| (previously attached), with // the given |remote_id| (negotiated using some other means, e.g., over an @@ -103,12 +104,37 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel // |FlushWriteBufferAndShutdown()| or something like that. bool IsWriteBufferEmpty(); - // This removes the message pipe/port's endpoint (with the given local ID, + // This removes the message pipe/port's endpoint (with the given local ID and + // given remote ID, which should be |kInvalidEndpointId| if not yet running), // returned by |AttachMessagePipeEndpoint()| from this channel. After this is // called, |local_id| may be reused for another message pipe. - void DetachMessagePipeEndpoint(MessageInTransit::EndpointId local_id); + void DetachMessagePipeEndpoint(MessageInTransit::EndpointId local_id, + MessageInTransit::EndpointId remote_id); private: + struct EndpointInfo { + enum State { + // Attached, possibly running or not. + STATE_NORMAL, + // "Zombie" states: + // Waiting for |DetachMessagePipeEndpoint()| before removing. + STATE_WAIT_LOCAL_DETACH, + // Waiting for a |kSubtypeChannelRemoveMessagePipeEndpointAck| before + // removing. + STATE_WAIT_REMOTE_REMOVE_ACK, + // Waiting for both of the above conditions before removing. + STATE_WAIT_LOCAL_DETACH_AND_REMOTE_REMOVE_ACK, + }; + + EndpointInfo(); + EndpointInfo(scoped_refptr<MessagePipe> message_pipe, unsigned port); + ~EndpointInfo(); + + State state; + scoped_refptr<MessagePipe> message_pipe; + unsigned port; + }; + friend class base::RefCountedThreadSafe<Channel>; virtual ~Channel(); @@ -122,19 +148,24 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel void OnReadMessageForDownstream(const MessageInTransit::View& message_view); void OnReadMessageForChannel(const MessageInTransit::View& message_view); + // Removes the message pipe endpoint with the given local ID, which must exist + // and be a zombie, and given remote ID. Returns false on failure, in + // particular if no message pipe with |local_id| is attached. + bool RemoveMessagePipeEndpoint(MessageInTransit::EndpointId local_id, + MessageInTransit::EndpointId remote_id); + // Handles errors (e.g., invalid messages) from the remote side. void HandleRemoteError(const base::StringPiece& error_message); // Handles internal errors/failures from the local side. void HandleLocalError(const base::StringPiece& error_message); - struct EndpointInfo { - EndpointInfo(); - EndpointInfo(scoped_refptr<MessagePipe> message_pipe, unsigned port); - ~EndpointInfo(); + // Helper to send channel control messages. Returns true on success. Should be + // called *without* |lock_| held. + bool SendControlMessage(MessageInTransit::Subtype subtype, + MessageInTransit::EndpointId source_id, + MessageInTransit::EndpointId destination_id); - scoped_refptr<MessagePipe> message_pipe; - unsigned port; - }; + bool is_running_no_lock() const { return is_running_; } base::ThreadChecker creation_thread_checker_; @@ -146,6 +177,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel base::Lock lock_; // Protects the members below. scoped_ptr<RawChannel> raw_channel_; + bool is_running_; typedef base::hash_map<MessageInTransit::EndpointId, EndpointInfo> IdToEndpointInfoMap; diff --git a/mojo/system/local_message_pipe_endpoint.cc b/mojo/system/local_message_pipe_endpoint.cc index ece8e03190..b5b6bd0223 100644 --- a/mojo/system/local_message_pipe_endpoint.cc +++ b/mojo/system/local_message_pipe_endpoint.cc @@ -27,13 +27,7 @@ MessagePipeEndpoint::Type LocalMessagePipeEndpoint::GetType() const { return kTypeLocal; } -void LocalMessagePipeEndpoint::Close() { - DCHECK(is_open_); - is_open_ = false; - message_queue_.Clear(); -} - -void LocalMessagePipeEndpoint::OnPeerClose() { +bool LocalMessagePipeEndpoint::OnPeerClose() { DCHECK(is_open_); DCHECK(is_peer_open_); @@ -48,6 +42,8 @@ void LocalMessagePipeEndpoint::OnPeerClose() { waiter_list_.AwakeWaitersForStateChange(new_satisfied_flags, new_satisfiable_flags); } + + return true; } void LocalMessagePipeEndpoint::EnqueueMessage( @@ -63,6 +59,12 @@ void LocalMessagePipeEndpoint::EnqueueMessage( } } +void LocalMessagePipeEndpoint::Close() { + DCHECK(is_open_); + is_open_ = false; + message_queue_.Clear(); +} + void LocalMessagePipeEndpoint::CancelAllWaiters() { DCHECK(is_open_); waiter_list_.CancelAllWaiters(); diff --git a/mojo/system/local_message_pipe_endpoint.h b/mojo/system/local_message_pipe_endpoint.h index 9e200f16f7..963188f1df 100644 --- a/mojo/system/local_message_pipe_endpoint.h +++ b/mojo/system/local_message_pipe_endpoint.h @@ -24,12 +24,12 @@ class MOJO_SYSTEM_IMPL_EXPORT LocalMessagePipeEndpoint // |MessagePipeEndpoint| implementation: virtual Type GetType() const OVERRIDE; - virtual void Close() OVERRIDE; - virtual void OnPeerClose() OVERRIDE; + virtual bool OnPeerClose() OVERRIDE; virtual void EnqueueMessage(scoped_ptr<MessageInTransit> message) OVERRIDE; // There's a dispatcher for |LocalMessagePipeEndpoint|s, so we have to // implement/override these: + virtual void Close() OVERRIDE; virtual void CancelAllWaiters() OVERRIDE; virtual MojoResult ReadMessage( void* bytes, uint32_t* num_bytes, diff --git a/mojo/system/message_in_transit.cc b/mojo/system/message_in_transit.cc index 73cefe38dd..442cd7142d 100644 --- a/mojo/system/message_in_transit.cc +++ b/mojo/system/message_in_transit.cc @@ -49,7 +49,11 @@ STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype MessageInTransit::kSubtypeMessagePipeEndpointData; STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype - MessageInTransit::kSubtypeMessagePipePeerClosed; + MessageInTransit::kSubtypeChannelRunMessagePipeEndpoint; +STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype + MessageInTransit::kSubtypeChannelRemoveMessagePipeEndpoint; +STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype + MessageInTransit::kSubtypeChannelRemoveMessagePipeEndpointAck; STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::EndpointId MessageInTransit::kInvalidEndpointId; STATIC_CONST_MEMBER_DEFINITION const size_t MessageInTransit::kMessageAlignment; diff --git a/mojo/system/message_in_transit.h b/mojo/system/message_in_transit.h index bf8d5cf186..9e578afddf 100644 --- a/mojo/system/message_in_transit.h +++ b/mojo/system/message_in_transit.h @@ -54,9 +54,11 @@ class MOJO_SYSTEM_IMPL_EXPORT MessageInTransit { // Subtypes for type |kTypeMessagePipeEndpoint|: static const Subtype kSubtypeMessagePipeEndpointData = 0; // Subtypes for type |kTypeMessagePipe|: - static const Subtype kSubtypeMessagePipePeerClosed = 0; + // Nothing currently. // Subtypes for type |kTypeChannel|: static const Subtype kSubtypeChannelRunMessagePipeEndpoint = 0; + static const Subtype kSubtypeChannelRemoveMessagePipeEndpoint = 1; + static const Subtype kSubtypeChannelRemoveMessagePipeEndpointAck = 2; typedef uint32_t EndpointId; // Never a valid endpoint ID. diff --git a/mojo/system/message_pipe.cc b/mojo/system/message_pipe.cc index 6f2e5cbb66..975293442a 100644 --- a/mojo/system/message_pipe.cc +++ b/mojo/system/message_pipe.cc @@ -57,8 +57,10 @@ void MessagePipe::Close(unsigned port) { DCHECK(endpoints_[port].get()); endpoints_[port]->Close(); - if (endpoints_[destination_port].get()) - endpoints_[destination_port]->OnPeerClose(); + if (endpoints_[destination_port].get()) { + if (!endpoints_[destination_port]->OnPeerClose()) + endpoints_[destination_port].reset(); + } endpoints_[port].reset(); } @@ -223,7 +225,7 @@ MojoResult MessagePipe::EnqueueMessage( return MOJO_RESULT_OK; } -void MessagePipe::Attach(unsigned port, +bool MessagePipe::Attach(unsigned port, scoped_refptr<Channel> channel, MessageInTransit::EndpointId local_id) { DCHECK(port == 0 || port == 1); @@ -231,9 +233,12 @@ void MessagePipe::Attach(unsigned port, DCHECK_NE(local_id, MessageInTransit::kInvalidEndpointId); base::AutoLock locker(lock_); - DCHECK(endpoints_[port].get()); + if (!endpoints_[port].get()) + return false; + DCHECK_EQ(endpoints_[port]->GetType(), MessagePipeEndpoint::kTypeProxy); endpoints_[port]->Attach(channel, local_id); + return true; } void MessagePipe::Run(unsigned port, MessageInTransit::EndpointId remote_id) { @@ -242,7 +247,24 @@ void MessagePipe::Run(unsigned port, MessageInTransit::EndpointId remote_id) { base::AutoLock locker(lock_); DCHECK(endpoints_[port].get()); - endpoints_[port]->Run(remote_id); + if (!endpoints_[port]->Run(remote_id)) + endpoints_[port].reset(); +} + +void MessagePipe::OnRemove(unsigned port) { + unsigned destination_port = GetPeerPort(port); + + base::AutoLock locker(lock_); + // A |OnPeerClose()| can come in first, before |OnRemove()| gets called. + if (!endpoints_[port].get()) + return; + + endpoints_[port]->OnRemove(); + if (endpoints_[destination_port].get()) { + if (!endpoints_[destination_port]->OnPeerClose()) + endpoints_[destination_port].reset(); + } + endpoints_[port].reset(); } MessagePipe::~MessagePipe() { @@ -254,28 +276,8 @@ MessagePipe::~MessagePipe() { } MojoResult MessagePipe::HandleControlMessage( - unsigned port, + unsigned /*port*/, scoped_ptr<MessageInTransit> message) { - DCHECK(port == 0 || port == 1); - DCHECK(message.get()); - DCHECK_EQ(message->type(), MessageInTransit::kTypeMessagePipe); - - switch (message->subtype()) { - case MessageInTransit::kSubtypeMessagePipePeerClosed: { - unsigned source_port = GetPeerPort(port); - - base::AutoLock locker(lock_); - DCHECK(endpoints_[source_port].get()); - - endpoints_[source_port]->Close(); - if (endpoints_[port].get()) - endpoints_[port]->OnPeerClose(); - - endpoints_[source_port].reset(); - return MOJO_RESULT_OK; - } - } - LOG(WARNING) << "Unrecognized MessagePipe control message subtype " << message->subtype(); return MOJO_RESULT_UNKNOWN; diff --git a/mojo/system/message_pipe.h b/mojo/system/message_pipe.h index 85cce0ae3d..6392ab3530 100644 --- a/mojo/system/message_pipe.h +++ b/mojo/system/message_pipe.h @@ -81,10 +81,11 @@ class MOJO_SYSTEM_IMPL_EXPORT MessagePipe : std::vector<DispatcherTransport>* transports); // These are used by |Channel|. - void Attach(unsigned port, + bool Attach(unsigned port, scoped_refptr<Channel> channel, MessageInTransit::EndpointId local_id); void Run(unsigned port, MessageInTransit::EndpointId remote_id); + void OnRemove(unsigned port); private: friend class base::RefCountedThreadSafe<MessagePipe>; diff --git a/mojo/system/message_pipe_dispatcher.cc b/mojo/system/message_pipe_dispatcher.cc index 364259bd72..fc626efb71 100644 --- a/mojo/system/message_pipe_dispatcher.cc +++ b/mojo/system/message_pipe_dispatcher.cc @@ -73,8 +73,21 @@ scoped_refptr<MessagePipeDispatcher> MessagePipeDispatcher::Deserialize( MessageInTransit::EndpointId remote_id = static_cast<const SerializedMessagePipeDispatcher*>(source)->endpoint_id; + if (remote_id == MessageInTransit::kInvalidEndpointId) { + // This means that the other end was closed, and there were no messages + // enqueued for us. + // TODO(vtl): This is wrong. We should produce a "dead" message pipe + // dispatcher. + NOTIMPLEMENTED(); + return scoped_refptr<MessagePipeDispatcher>(); + } MessageInTransit::EndpointId local_id = channel->AttachMessagePipeEndpoint(remote_message_pipe.second, 1); + if (local_id == MessageInTransit::kInvalidEndpointId) { + LOG(ERROR) << "Failed to deserialize message pipe dispatcher (failed to " + "attach; remote ID = " << remote_id << ")"; + return scoped_refptr<MessagePipeDispatcher>(); + } DVLOG(2) << "Deserializing message pipe dispatcher (remote ID = " << remote_id << ", new local ID = " << local_id << ")"; @@ -199,8 +212,11 @@ bool MessagePipeDispatcher::EndSerializeAndCloseImplNoLock( // Attach the new proxy endpoint to the channel. MessageInTransit::EndpointId endpoint_id = channel->AttachMessagePipeEndpoint(message_pipe_, port_); - DCHECK_NE(endpoint_id, MessageInTransit::kInvalidEndpointId); - + // Note: It's okay to get an endpoint ID of |kInvalidEndpointId|. (It's + // possible that the other endpoint -- the one that we're not sending -- was + // closed in the intervening time.) In that case, we need to deserialize a + // "dead" message pipe dispatcher on the other end. (Note that this is + // different from just producing |MOJO_HANDLE_INVALID|.) DVLOG(2) << "Serializing message pipe dispatcher (local ID = " << endpoint_id << ")"; diff --git a/mojo/system/message_pipe_endpoint.cc b/mojo/system/message_pipe_endpoint.cc index dd186fd89c..a1a7be3a41 100644 --- a/mojo/system/message_pipe_endpoint.cc +++ b/mojo/system/message_pipe_endpoint.cc @@ -10,6 +10,10 @@ namespace mojo { namespace system { +void MessagePipeEndpoint::Close() { + NOTREACHED(); +} + void MessagePipeEndpoint::CancelAllWaiters() { NOTREACHED(); } @@ -39,7 +43,12 @@ void MessagePipeEndpoint::Attach(scoped_refptr<Channel> /*channel*/, NOTREACHED(); } -void MessagePipeEndpoint::Run(MessageInTransit::EndpointId /*remote_id*/) { +bool MessagePipeEndpoint::Run(MessageInTransit::EndpointId /*remote_id*/) { + NOTREACHED(); + return true; +} + +void MessagePipeEndpoint::OnRemove() { NOTREACHED(); } diff --git a/mojo/system/message_pipe_endpoint.h b/mojo/system/message_pipe_endpoint.h index b7b9589450..d14c58a627 100644 --- a/mojo/system/message_pipe_endpoint.h +++ b/mojo/system/message_pipe_endpoint.h @@ -42,8 +42,8 @@ class MOJO_SYSTEM_IMPL_EXPORT MessagePipeEndpoint { virtual Type GetType() const = 0; // All implementations must implement these. - virtual void Close() = 0; - virtual void OnPeerClose() = 0; + // 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 @@ -58,6 +58,7 @@ class MOJO_SYSTEM_IMPL_EXPORT MessagePipeEndpoint { // 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 Close(); virtual void CancelAllWaiters(); virtual MojoResult ReadMessage( void* bytes, uint32_t* num_bytes, @@ -74,7 +75,9 @@ class MOJO_SYSTEM_IMPL_EXPORT MessagePipeEndpoint { // they should never be called. virtual void Attach(scoped_refptr<Channel> channel, MessageInTransit::EndpointId local_id); - virtual void Run(MessageInTransit::EndpointId remote_id); + // Returns false if the endpoint should be closed and destroyed, else true. + virtual bool Run(MessageInTransit::EndpointId remote_id); + virtual void OnRemove(); protected: MessagePipeEndpoint() {} diff --git a/mojo/system/proxy_message_pipe_endpoint.cc b/mojo/system/proxy_message_pipe_endpoint.cc index d5ef6566b2..81adda5450 100644 --- a/mojo/system/proxy_message_pipe_endpoint.cc +++ b/mojo/system/proxy_message_pipe_endpoint.cc @@ -17,7 +17,6 @@ namespace system { ProxyMessagePipeEndpoint::ProxyMessagePipeEndpoint() : local_id_(MessageInTransit::kInvalidEndpointId), remote_id_(MessageInTransit::kInvalidEndpointId), - is_open_(true), is_peer_open_(true) { } @@ -26,7 +25,6 @@ ProxyMessagePipeEndpoint::ProxyMessagePipeEndpoint( bool is_peer_open) : local_id_(MessageInTransit::kInvalidEndpointId), remote_id_(MessageInTransit::kInvalidEndpointId), - is_open_(true), is_peer_open_(is_peer_open), paused_message_queue_(MessageInTransitQueue::PassContents(), local_message_pipe_endpoint->message_queue()) { @@ -44,27 +42,26 @@ MessagePipeEndpoint::Type ProxyMessagePipeEndpoint::GetType() const { return kTypeProxy; } -void ProxyMessagePipeEndpoint::Close() { - DCHECK(is_open_); - is_open_ = false; - - DCHECK(is_attached()); - channel_->DetachMessagePipeEndpoint(local_id_); - channel_ = NULL; - local_id_ = MessageInTransit::kInvalidEndpointId; - remote_id_ = MessageInTransit::kInvalidEndpointId; - paused_message_queue_.Clear(); -} - -void ProxyMessagePipeEndpoint::OnPeerClose() { - DCHECK(is_open_); +bool ProxyMessagePipeEndpoint::OnPeerClose() { DCHECK(is_peer_open_); is_peer_open_ = false; - EnqueueMessage(make_scoped_ptr( - new MessageInTransit(MessageInTransit::kTypeMessagePipe, - MessageInTransit::kSubtypeMessagePipePeerClosed, - 0, 0, NULL))); + + // If our outgoing message queue isn't empty, we shouldn't be destroyed yet. + if (!paused_message_queue_.IsEmpty()) + return true; + + if (is_attached()) { + if (!is_running()) { + // If we're not running yet, we can't be destroyed yet, because we're + // still waiting for the "run" message from the other side. + return true; + } + + Detach(); + } + + return false; } // Note: We may have to enqueue messages even when our (local) peer isn't open @@ -72,8 +69,6 @@ void ProxyMessagePipeEndpoint::OnPeerClose() { // This case is handled in |Run()| (which will call us). void ProxyMessagePipeEndpoint::EnqueueMessage( scoped_ptr<MessageInTransit> message) { - DCHECK(is_open_); - if (is_running()) { message->SerializeAndCloseDispatchers(channel_.get()); @@ -99,7 +94,7 @@ void ProxyMessagePipeEndpoint::Attach(scoped_refptr<Channel> channel, AssertConsistentState(); } -void ProxyMessagePipeEndpoint::Run(MessageInTransit::EndpointId remote_id) { +bool ProxyMessagePipeEndpoint::Run(MessageInTransit::EndpointId remote_id) { // Assertions about arguments: DCHECK_NE(remote_id, MessageInTransit::kInvalidEndpointId); @@ -113,6 +108,29 @@ void ProxyMessagePipeEndpoint::Run(MessageInTransit::EndpointId remote_id) { while (!paused_message_queue_.IsEmpty()) EnqueueMessage(paused_message_queue_.GetMessage()); + + if (is_peer_open_) + return true; // Stay alive. + + // We were just waiting to die. + Detach(); + return false; +} + +void ProxyMessagePipeEndpoint::OnRemove() { + Detach(); +} + +void ProxyMessagePipeEndpoint::Detach() { + DCHECK(is_attached()); + + AssertConsistentState(); + channel_->DetachMessagePipeEndpoint(local_id_, remote_id_); + channel_ = NULL; + local_id_ = MessageInTransit::kInvalidEndpointId; + remote_id_ = MessageInTransit::kInvalidEndpointId; + paused_message_queue_.Clear(); + AssertConsistentState(); } #ifndef NDEBUG diff --git a/mojo/system/proxy_message_pipe_endpoint.h b/mojo/system/proxy_message_pipe_endpoint.h index 7d62b9b79e..28b634d906 100644 --- a/mojo/system/proxy_message_pipe_endpoint.h +++ b/mojo/system/proxy_message_pipe_endpoint.h @@ -53,14 +53,22 @@ class MOJO_SYSTEM_IMPL_EXPORT ProxyMessagePipeEndpoint // |MessagePipeEndpoint| implementation: virtual Type GetType() const OVERRIDE; - virtual void Close() OVERRIDE; - virtual void OnPeerClose() OVERRIDE; + virtual bool OnPeerClose() OVERRIDE; virtual void EnqueueMessage(scoped_ptr<MessageInTransit> message) OVERRIDE; virtual void Attach(scoped_refptr<Channel> channel, MessageInTransit::EndpointId local_id) OVERRIDE; - virtual void Run(MessageInTransit::EndpointId remote_id) OVERRIDE; + virtual bool Run(MessageInTransit::EndpointId remote_id) OVERRIDE; + virtual void OnRemove() OVERRIDE; private: + void Detach(); + +#ifdef NDEBUG + void AssertConsistentState() const {} +#else + void AssertConsistentState() const; +#endif + bool is_attached() const { return !!channel_.get(); } @@ -69,12 +77,6 @@ class MOJO_SYSTEM_IMPL_EXPORT ProxyMessagePipeEndpoint return remote_id_ != MessageInTransit::kInvalidEndpointId; } -#ifdef NDEBUG - void AssertConsistentState() const {} -#else - void AssertConsistentState() const; -#endif - // This should only be set if we're attached. scoped_refptr<Channel> channel_; @@ -88,7 +90,6 @@ class MOJO_SYSTEM_IMPL_EXPORT ProxyMessagePipeEndpoint // we're attached. MessageInTransit::EndpointId remote_id_; - bool is_open_; bool is_peer_open_; // This queue is only used while we're detached, to store messages while we're diff --git a/mojo/system/raw_channel.h b/mojo/system/raw_channel.h index f1ce443e9d..4b60e36d5c 100644 --- a/mojo/system/raw_channel.h +++ b/mojo/system/raw_channel.h @@ -53,17 +53,18 @@ class MOJO_SYSTEM_IMPL_EXPORT RawChannel { FATAL_ERROR_FAILED_WRITE }; - // Called when a message is read. This may call |Shutdown()| on the - // |RawChannel|, but must not destroy it. + // Called when a message is read. This may call |Shutdown()| (on the + // |RawChannel|), but must not destroy it. virtual void OnReadMessage(const MessageInTransit::View& message_view) = 0; // Called when there's a fatal error, which leads to the channel no longer - // being viable. - // For each raw channel, at most one |FATAL_ERROR_FAILED_READ| and one - // |FATAL_ERROR_FAILED_WRITE| notification will be issued. (And it is - // possible to get both.) - // After |OnFatalError(FATAL_ERROR_FAILED_READ)| there won't be further - // |OnReadMessage()| calls. + // being viable. This may call |Shutdown()| (on the |RawChannel()|), but + // must now destroy it. + // + // For each raw channel, at most one |FATAL_ERROR_FAILED_READ| and at most + // one |FATAL_ERROR_FAILED_WRITE| notification will be issued (both may be + // issued). After a |OnFatalError(FATAL_ERROR_FAILED_READ)|, there will be + // no further calls to |OnReadMessage()|. virtual void OnFatalError(FatalError fatal_error) = 0; protected: diff --git a/mojo/system/remote_message_pipe_unittest.cc b/mojo/system/remote_message_pipe_unittest.cc index 4dee5772ab..7deb252ef4 100644 --- a/mojo/system/remote_message_pipe_unittest.cc +++ b/mojo/system/remote_message_pipe_unittest.cc @@ -138,10 +138,13 @@ class RemoteMessagePipeTest : public testing::Test { unsigned port = channel_index ^ 1u; - // Important: If we don't boot CreateAndInitChannel(channel_index); - CHECK_EQ(channels_[channel_index]->AttachMessagePipeEndpoint(mp, port), - Channel::kBootstrapEndpointId); + MessageInTransit::EndpointId endpoint_id = + channels_[channel_index]->AttachMessagePipeEndpoint(mp, port); + if (endpoint_id == MessageInTransit::kInvalidEndpointId) + return; + + CHECK_EQ(endpoint_id, Channel::kBootstrapEndpointId); CHECK(channels_[channel_index]->RunMessagePipeEndpoint( Channel::kBootstrapEndpointId, Channel::kBootstrapEndpointId)); } @@ -561,7 +564,8 @@ TEST_F(RemoteMessagePipeTest, HandlePassing) { TEST_F(RemoteMessagePipeTest, RacingClosesStress) { base::TimeDelta delay = base::TimeDelta::FromMilliseconds(5); - for (unsigned i = 0u; i < 256u; i++) { + for (unsigned i = 0; i < 256; i++) { + DVLOG(2) << "---------------------------------------- " << i; scoped_refptr<MessagePipe> mp0(new MessagePipe( scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint()), scoped_ptr<MessagePipeEndpoint>(new ProxyMessagePipeEndpoint()))); diff --git a/mojo/tools/data/unittests b/mojo/tools/data/unittests index 4ec0b295a5..e209379c7a 100644 --- a/mojo/tools/data/unittests +++ b/mojo/tools/data/unittests @@ -14,3 +14,4 @@ mojo_apps_js_unittests mojo_common_unittests mojo_js_unittests mojo_service_manager_unittests +mojo_view_manager_unittests diff --git a/mojo/tools/mojob.sh b/mojo/tools/mojob.sh index 291012ca23..b870cd1301 100755 --- a/mojo/tools/mojob.sh +++ b/mojo/tools/mojob.sh @@ -61,9 +61,7 @@ do_perftests() { } do_pytests() { - echo "Running Python unit tests under mojo/public/tools/bindings/pylib ..." - python -m unittest \ - discover -s mojo/public/tools/bindings/pylib -p "*_unittest.py" + python mojo/tools/run_mojo_python_tests.py || exit 1 } do_gyp() { diff --git a/mojo/tools/run_mojo_python_tests.py b/mojo/tools/run_mojo_python_tests.py new file mode 100755 index 0000000000..48b723cfd3 --- /dev/null +++ b/mojo/tools/run_mojo_python_tests.py @@ -0,0 +1,40 @@ +#!/bin/python +# 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 optparse +import os +import sys +import unittest + + +# TODO(dpranke): crbug.com/364709 . We should add the ability to return +# JSONified results data for the bots. + + +def main(): + parser = optparse.OptionParser() + parser.add_option('-v', '--verbose', action='count', default=0) + options, args = parser.parse_args() + if args: + parser.usage() + return 1 + + chromium_src_dir = os.path.join(os.path.dirname(__file__), + os.pardir, + os.pardir) + + loader = unittest.loader.TestLoader() + print "Running Python unit tests under mojo/public/tools/bindings/pylib ..." + suite = loader.discover(os.path.join(chromium_src_dir, 'mojo', 'public', + 'tools', 'bindings', 'pylib'), + pattern='*_unittest.py') + + runner = unittest.runner.TextTestRunner(verbosity=(options.verbose+1)) + result = runner.run(suite) + return 0 if result.wasSuccessful() else 1 + + +if __name__ == '__main__': + sys.exit(main()) |