blob: e6f39ff97ce3391dd6224419be4bcc348ebfa7a6 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.mojo.shell;
import android.app.Activity;
import android.content.Intent;
import android.os.Parcel;
import org.chromium.base.ApplicationStatus;
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* Java helper class for services/android/intent_receiver.mojom. This class creates intents for
* privileged mojo applications and routes received intents back to the mojo application. The
* implementation of the IntentReceiverManager service is in C++, but calls back to this class to
* access the android framework.
*/
@JNINamespace("shell")
public class IntentReceiverRegistry {
private static class LazyHolder {
private static final IntentReceiverRegistry INSTANCE = new IntentReceiverRegistry();
}
/**
* Returns the instance.
*/
public static IntentReceiverRegistry getInstance() {
return LazyHolder.INSTANCE;
}
private final Map<String, Long> mReceiversByUuid = new HashMap<>();
private final Map<Long, String> mUuidsByReceiver = new HashMap<>();
private int mLastRequestCode = 0;
private IntentReceiverRegistry() {}
public void onIntentReceived(Intent intent) {
String uuid = intent.getAction();
if (uuid == null) return;
Long ptr = mReceiversByUuid.get(uuid);
if (ptr == null) return;
nativeOnIntentReceived(ptr, true, intentToBuffer(intent));
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
String uuid = Integer.toString(requestCode);
if (uuid == null) return;
Long ptr = mReceiversByUuid.get(uuid);
if (ptr == null) return;
if (resultCode == Activity.RESULT_OK) {
nativeOnIntentReceived(ptr, true, intentToBuffer(data));
} else {
nativeOnIntentReceived(ptr, false, null);
}
}
private static ByteBuffer intentToBuffer(Intent intent) {
Parcel p = Parcel.obtain();
intent.writeToParcel(p, 0);
p.setDataPosition(0);
byte[] b = p.marshall();
ByteBuffer result = ByteBuffer.allocateDirect(b.length);
result.put(b);
result.flip();
return result;
}
private static Intent bufferToIntent(ByteBuffer buffer) {
Parcel p = Parcel.obtain();
byte[] bytes;
if (buffer.hasArray()) {
bytes = buffer.array();
} else {
bytes = new byte[buffer.limit()];
buffer.get(bytes, 0, buffer.limit());
}
p.unmarshall(bytes, 0, bytes.length);
p.setDataPosition(0);
Intent result = Intent.CREATOR.createFromParcel(p);
p.recycle();
return result;
}
@CalledByNative
private static ByteBuffer registerIntentReceiver(long intentDispatcher) {
IntentReceiverRegistry registry = getInstance();
String uuid = UUID.randomUUID().toString();
Intent intent = new Intent(
uuid, null, ApplicationStatus.getApplicationContext(), IntentReceiverService.class);
registry.mReceiversByUuid.put(uuid, intentDispatcher);
registry.mUuidsByReceiver.put(intentDispatcher, uuid);
return intentToBuffer(intent);
}
@CalledByNative
private static ByteBuffer registerActivityResultReceiver(long intentDispatcher) {
IntentReceiverRegistry registry = getInstance();
String uuid;
// Handle unlikely overflows.
do {
++registry.mLastRequestCode;
if (registry.mLastRequestCode < 1) {
registry.mLastRequestCode = 1;
}
uuid = Integer.toString(registry.mLastRequestCode);
} while (registry.mReceiversByUuid.keySet().contains(uuid));
registry.mReceiversByUuid.put(uuid, intentDispatcher);
registry.mUuidsByReceiver.put(intentDispatcher, uuid);
Intent intent = new Intent(
uuid, null, ApplicationStatus.getApplicationContext(), IntentReceiverService.class);
intent.addCategory(IntentReceiverService.CATEGORY_START_ACTIVITY_FOR_RESULT);
return intentToBuffer(intent);
}
@CalledByNative
private static void unregisterReceiver(long intentDispatcher) {
IntentReceiverRegistry registry = getInstance();
String uuid = registry.mUuidsByReceiver.get(intentDispatcher);
if (uuid != null) {
registry.mUuidsByReceiver.remove(intentDispatcher);
registry.mReceiversByUuid.remove(uuid);
}
}
private static native void nativeOnIntentReceived(
long intentDispatcher, boolean accepted, ByteBuffer intent);
}