Chromium Code Reviews| Index: chrome/android/java/src/org/chromium/chrome/browser/UsbChooserDialog.java |
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/UsbChooserDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/UsbChooserDialog.java |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..6946b0a6dcadb65ca5a4fe3c26ba22dff4364680 |
| --- /dev/null |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/UsbChooserDialog.java |
| @@ -0,0 +1,180 @@ |
| +// Copyright 2016 The Chromium 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.chrome.browser; |
| + |
| +import android.content.Context; |
| +import android.graphics.Color; |
| +import android.text.SpannableString; |
| +import android.text.TextPaint; |
| +import android.text.TextUtils; |
| +import android.text.style.ClickableSpan; |
| +import android.view.View; |
| + |
| +import org.chromium.base.annotations.CalledByNative; |
| +import org.chromium.chrome.R; |
| +import org.chromium.chrome.browser.omnibox.OmniboxUrlEmphasizer; |
| +import org.chromium.chrome.browser.profiles.Profile; |
| +import org.chromium.ui.base.WindowAndroid; |
| +import org.chromium.ui.text.SpanApplier; |
| +import org.chromium.ui.text.SpanApplier.SpanInfo; |
| + |
| +import java.util.ArrayList; |
| +import java.util.List; |
| + |
| +/** |
| + * A dialog for showing available USB devices. This dialog is shown when a website requests to |
| + * connect to a USB device (e.g. through a usb.requestDevice Javascript call). |
| + */ |
| +public class UsbChooserDialog |
| + implements ItemChooserDialog.ItemSelectedCallback, WindowAndroid.PermissionCallback { |
| + // Values passed to nativeOnDialogFinished:eventType, and only used in the native function. |
| + private static final int DIALOG_FINISHED_CANCELLED = 0; |
| + private static final int DIALOG_FINISHED_SELECTED = 1; |
| + |
| + // The window that owns this dialog. |
| + final WindowAndroid mWindowAndroid; |
| + |
| + // Always equal to mWindowAndroid.getActivity().get(), but stored separately to make sure it's |
| + // not GC'ed. |
|
Yaron
2016/03/07 21:51:49
This seems like the exact reason to *not* do this.
juncai
2016/03/09 01:26:50
Done.
|
| + final Context mContext; |
| + |
| + // The dialog to show to let the user pick a device. |
| + ItemChooserDialog mItemChooserDialog; |
| + |
| + // The origin for the site wanting to connect to the USB device. |
| + String mOrigin; |
|
Yaron
2016/03/07 21:51:49
I don't see why mOrigin and mSecurityLevel are mem
juncai
2016/03/09 01:26:50
Done.
|
| + |
| + // The security level of the connection to the site wanting to connect to the |
| + // USB device. For valid values see SecurityStateModel::SecurityLevel. |
| + int mSecurityLevel; |
| + |
| + // A pointer back to the native part of the implementation for this dialog. |
| + long mNativeUsbChooserDialogPtr; |
| + |
| + /** |
| + * Creates the UsbChooserDialog and displays it (and starts waiting for data). |
| + * |
| + * @param context Context which is used for launching a dialog. |
| + */ |
| + private UsbChooserDialog(WindowAndroid windowAndroid, String origin, int securityLevel, |
| + long nativeUsbChooserDialogPtr) { |
| + mWindowAndroid = windowAndroid; |
| + mContext = windowAndroid.getActivity().get(); |
| + assert mContext != null; |
| + mOrigin = origin; |
| + mSecurityLevel = securityLevel; |
| + mNativeUsbChooserDialogPtr = nativeUsbChooserDialogPtr; |
| + } |
| + |
| + /** |
| + * Show the UsbChooserDialog. |
| + */ |
| + private void show() { |
| + // Emphasize the origin. |
| + Profile profile = Profile.getLastUsedProfile(); |
| + SpannableString origin = new SpannableString(mOrigin); |
| + OmniboxUrlEmphasizer.emphasizeUrl(origin, mContext.getResources(), profile, mSecurityLevel, |
| + false /* isInternalPage */, true /* useDarkColors */, |
| + true /* emphasizeHttpsScheme */); |
| + // Construct a full string and replace the origin text with emphasized version. |
| + SpannableString title = new SpannableString( |
| + mContext.getString(R.string.usb_chooser_dialog_prompt, mOrigin)); |
| + int start = title.toString().indexOf(mOrigin); |
| + TextUtils.copySpansFrom(origin, 0, origin.length(), Object.class, title, start); |
| + |
| + SpannableString searching = new SpannableString(new String("")); |
| + SpannableString noneFound = new SpannableString( |
| + mContext.getString(R.string.usb_chooser_dialog_no_devices_found_prompt)); |
| + SpannableString statusActive = SpanApplier.applySpans( |
| + mContext.getString(R.string.usb_chooser_dialog_footnote_text), |
| + new SpanInfo("<link>", "</link>", new NoUnderlineClickableSpan())); |
| + SpannableString statusIdleNoneFound = statusActive; |
| + SpannableString statusIdleSomeFound = statusActive; |
| + String positiveButton = mContext.getString(R.string.usb_chooser_dialog_connect_button_text); |
| + |
| + ItemChooserDialog.ItemChooserLabels labels = |
| + new ItemChooserDialog.ItemChooserLabels(title, searching, noneFound, statusActive, |
| + statusIdleNoneFound, statusIdleSomeFound, positiveButton); |
| + mItemChooserDialog = new ItemChooserDialog(mContext, this, labels); |
| + } |
| + |
| + @Override |
| + public void onItemSelected(String id) { |
| + if (mNativeUsbChooserDialogPtr != 0) { |
| + if (id.isEmpty()) { |
| + nativeOnDialogFinished(mNativeUsbChooserDialogPtr, DIALOG_FINISHED_CANCELLED, ""); |
| + } else { |
| + nativeOnDialogFinished(mNativeUsbChooserDialogPtr, DIALOG_FINISHED_SELECTED, id); |
| + } |
| + } |
| + } |
| + |
| + @Override |
| + public void onRequestPermissionsResult(String[] permissions, int[] grantResults) {} |
|
Yaron
2016/03/07 21:51:49
Remove this and the the corresponding interface de
Finnur
2016/03/08 10:26:20
Is there no special permission that is needed for
juncai
2016/03/09 01:26:50
Done.
juncai
2016/03/09 01:26:50
I think for Bluetooth on Android, Chromium needs t
Finnur
2016/03/09 13:47:02
Then yeah, removing this is the right thing to do.
|
| + |
| + /** |
| + * A helper class to show a clickable link with underlines turned off. |
|
Yaron
2016/03/07 21:51:49
I'm not a UI-guy (+newt - should probably look at
Finnur
2016/03/08 10:26:20
It is not a huge amount of savings, but we should
juncai
2016/03/09 01:26:50
Done.
juncai
2016/03/09 01:26:50
Added a class NoUnderlineClickableSpan that both B
|
| + */ |
| + private class NoUnderlineClickableSpan extends ClickableSpan { |
| + NoUnderlineClickableSpan() {} |
| + |
| + @Override |
| + public void onClick(View view) { |
| + if (mNativeUsbChooserDialogPtr == 0) { |
| + return; |
| + } |
| + |
| + nativeShowUsbOverviewLink(mNativeUsbChooserDialogPtr); |
| + |
| + // Get rid of the highlight background on selection. |
| + view.invalidate(); |
| + } |
| + |
| + @Override |
| + public void updateDrawState(TextPaint textPaint) { |
| + super.updateDrawState(textPaint); |
| + textPaint.bgColor = Color.TRANSPARENT; |
| + textPaint.setUnderlineText(false); |
| + } |
| + } |
| + |
| + @CalledByNative |
| + private static UsbChooserDialog create(WindowAndroid windowAndroid, String origin, |
| + int securityLevel, long nativeUsbChooserDialogPtr) { |
| + UsbChooserDialog dialog = new UsbChooserDialog( |
| + windowAndroid, origin, securityLevel, nativeUsbChooserDialogPtr); |
| + dialog.show(); |
| + return dialog; |
| + } |
| + |
| + @CalledByNative |
| + private void updateOptions(String[] deviceId, String[] deviceName) { |
|
Finnur
2016/03/08 10:26:20
Nit: seems to me like addDevices is a better descr
juncai
2016/03/09 01:26:50
Done.
|
| + if (deviceName == null) return; |
|
Yaron
2016/03/07 21:51:49
Do this on the native side
juncai
2016/03/09 01:26:50
Done.
|
| + mItemChooserDialog.clear(); |
|
Finnur
2016/03/08 10:26:20
Are you guaranteeing that you won't receive more c
juncai
2016/03/09 01:26:50
Receiving more calls to add devices can be handled
Finnur
2016/03/09 13:47:02
Hmmm... Let me rephrase the question.
Bluetooth
juncai
2016/03/10 01:22:22
ah, I see, the USB and Bluetooth dialog implementa
Finnur
2016/03/10 12:12:56
I see.
Yeah, the Bluetooth devices could drop in
juncai
2016/03/11 23:32:33
Thanks for the comments. I added addItemToList and
|
| + List<ItemChooserDialog.ItemChooserRow> devices = |
|
Yaron
2016/03/07 21:51:49
move allocation after early-return
juncai
2016/03/09 01:26:50
Done.
|
| + new ArrayList<ItemChooserDialog.ItemChooserRow>(); |
| + int len = deviceId.length; |
| + if (len == 0) { |
| + mItemChooserDialog.setIdleState(); |
| + return; |
| + } |
| + |
| + for (int i = 0; i < len; ++i) { |
| + devices.add(new ItemChooserDialog.ItemChooserRow(deviceId[i], deviceName[i])); |
| + } |
| + mItemChooserDialog.addItemsToList(devices); |
| + } |
| + |
| + @CalledByNative |
| + private void closeDialog() { |
| + mNativeUsbChooserDialogPtr = 0; |
| + mItemChooserDialog.dismiss(); |
| + } |
| + |
| + private native void nativeOnDialogFinished( |
| + long nativeUsbChooserAndroid, int eventType, String deviceId); |
| + // Help links. |
|
Finnur
2016/03/08 10:26:20
nit: Singular (link).
juncai
2016/03/09 01:26:50
Done.
|
| + private native void nativeShowUsbOverviewLink(long nativeUsbChooserAndroid); |
| +} |