// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.media;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.webkit.MimeTypeMap;
import org.chromium.base.BuildInfo;
import org.chromium.base.IntentUtils;
import org.chromium.base.Log;
import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
import java.util.Locale;
/**
* The MediaLauncherActivity handles media-viewing Intents from other apps. It takes the given
* content:// URI from the Intent and properly routes it to a media-viewing CustomTabActivity.
*/
public class MediaLauncherActivity extends Activity {
private static final String TAG = "MediaLauncher";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent input = IntentUtils.sanitizeIntent(getIntent());
Uri contentUri = input.getData();
String mimeType = getMIMEType(contentUri);
if (!MediaViewerUtils.isMediaMIMEType(mimeType)) {
// With our intent-filter, we should only receive implicit intents with media MIME
// types. If we receive a non-media MIME type, it is likely a malicious explicit intent,
// so we should not proceed.
finish();
return;
}
boolean allowShareAction = !BuildInfo.getInstance().isAutomotive;
// TODO(crbug.com/40557611): Determine file:// URI when possible.
Intent intent =
MediaViewerUtils.getMediaViewerIntent(
contentUri,
contentUri,
mimeType,
/* allowExternalAppHandlers= */ false,
allowShareAction,
this);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra(
CustomTabIntentDataProvider.EXTRA_BROWSER_LAUNCH_SOURCE,
CustomTabIntentDataProvider.LaunchSourceType.MEDIA_LAUNCHER_ACTIVITY);
try {
startActivity(intent);
} catch (SecurityException e) {
Log.w(TAG, "Cannot open content URI: " + contentUri.toString(), e);
}
finish();
}
private String getMIMEType(Uri uri) {
// With a content URI, we can just query the ContentResolver.
if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
return getContentResolver().getType(uri);
}
// Otherwise, use the file extension.
String filteredUri = filterURI(uri);
String fileExtension = MimeTypeMap.getFileExtensionFromUrl(filteredUri);
return MimeTypeMap.getSingleton()
.getMimeTypeFromExtension(fileExtension.toLowerCase(Locale.ROOT));
}
// MimeTypeMap.getFileExtensionFromUrl fails when the file name includes certain special
// characters, so we filter those out of the URI when determining the MIME type.
protected static String filterURI(Uri uri) {
String uriString = uri.toString();
int filterIndex = uriString.length();
int fragmentIndex = uriString.lastIndexOf('#', filterIndex);
if (fragmentIndex >= 0) filterIndex = fragmentIndex;
int queryIndex = uriString.lastIndexOf('?', filterIndex);
if (queryIndex >= 0) filterIndex = queryIndex;
int extensionIndex = uriString.lastIndexOf('.', filterIndex);
if (extensionIndex >= 0) filterIndex = extensionIndex;
return uriString.substring(0, filterIndex).replaceAll("['$!]", "")
+ uriString.substring(filterIndex);
}
}