下面列出了android.view.ViewTreeObserver.OnGlobalFocusChangeListener#org.chromium.ui.base.WindowAndroid 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* This is called when the native library are ready.
*/
public void onNativeLibraryReady(
WindowAndroid windowAndroid, TabContentManager tabContentManager) {
assert mLayerTitleCache == null : "Should be called once";
if (DeviceClassManager.enableLayerDecorationCache()) {
mLayerTitleCache = new LayerTitleCache(getContext());
}
mCompositorView.initNativeCompositor(
SysUtils.isLowEndDevice(), windowAndroid, mLayerTitleCache, tabContentManager);
if (mLayerTitleCache != null) {
mLayerTitleCache.setResourceManager(getResourceManager());
}
if (mControlContainer != null) {
mCompositorView.getResourceManager().getDynamicResourceLoader().registerResource(
R.id.control_container, mControlContainer.getToolbarResourceAdapter());
}
}
/**
* Initializes the {@link CompositorView}'s native parts (e.g. the rendering parts).
* @param lowMemDevice If this is a low memory device.
* @param windowAndroid A {@link WindowAndroid} instance.
* @param layerTitleCache A {@link LayerTitleCache} instance.
* @param tabContentManager A {@link TabContentManager} instance.
*/
public void initNativeCompositor(boolean lowMemDevice, WindowAndroid windowAndroid,
LayerTitleCache layerTitleCache, TabContentManager tabContentManager) {
mWindowAndroid = windowAndroid;
mLayerTitleCache = layerTitleCache;
mTabContentManager = tabContentManager;
mNativeCompositorView = nativeInit(lowMemDevice,
windowAndroid.getNativePointer(), layerTitleCache, tabContentManager);
assert !getHolder().getSurface().isValid()
: "Surface created before native library loaded.";
getHolder().addCallback(this);
// Cover the black surface before it has valid content.
setBackgroundColor(Color.WHITE);
setVisibility(View.VISIBLE);
// Grab the Resource Manager
mResourceManager = nativeGetResourceManager(mNativeCompositorView);
}
private static SparseArray<String[]> generatePermissionsMapping(
WindowAndroid windowAndroid, int[] contentSettingsTypes) {
SparseArray<String[]> permissionsToRequest = new SparseArray<>();
for (int i = 0; i < contentSettingsTypes.length; i++) {
String[] permissions = PrefServiceBridge.getAndroidPermissionsForContentSetting(
contentSettingsTypes[i]);
if (permissions == null) continue;
List<String> missingPermissions = new ArrayList<>();
for (int j = 0; j < permissions.length; j++) {
String permission = permissions[j];
if (!windowAndroid.hasPermission(permission)) missingPermissions.add(permission);
}
if (!missingPermissions.isEmpty()) {
permissionsToRequest.append(contentSettingsTypes[i],
missingPermissions.toArray(new String[missingPermissions.size()]));
}
}
return permissionsToRequest;
}
@CalledByNative
private static BluetoothChooserDialog create(WindowAndroid windowAndroid, String origin,
int securityLevel, long nativeBluetoothChooserDialogPtr) {
if (!LocationUtils.getInstance().hasAndroidLocationPermission(
windowAndroid.getActivity().get())
&& !windowAndroid.canRequestPermission(
Manifest.permission.ACCESS_COARSE_LOCATION)) {
// If we can't even ask for enough permission to scan for Bluetooth devices, don't open
// the dialog.
return null;
}
BluetoothChooserDialog dialog = new BluetoothChooserDialog(
windowAndroid, origin, securityLevel, nativeBluetoothChooserDialogPtr);
dialog.show();
return dialog;
}
@Override
public void onIntentCompleted(WindowAndroid window, int resultCode,
ContentResolver contentResolver, Intent data) {
if (resultCode != Activity.RESULT_OK) return;
if (data.getExtras() == null) return;
VoiceResult topResult = mAutocomplete.onVoiceResults(data.getExtras());
if (topResult == null) return;
String topResultQuery = topResult.getMatch();
if (TextUtils.isEmpty(topResultQuery)) return;
if (topResult.getConfidence() < VOICE_SEARCH_CONFIDENCE_NAVIGATE_THRESHOLD) {
setSearchQuery(topResultQuery);
return;
}
String url = AutocompleteController.nativeQualifyPartialURLQuery(topResultQuery);
if (url == null) {
url = TemplateUrlService.getInstance().getUrlForVoiceSearchQuery(
topResultQuery);
}
loadUrl(url, PageTransition.TYPED);
}
/**
* Creates an instance of a {@link Tab} that is fully detached from any activity.
* Also performs general tab initialization as well as detached specifics.
*
* The current application context must allow the creation of a WindowAndroid.
*
* @return The newly created and initialized tab.
*/
public static Tab createDetached(TabDelegateFactory delegateFactory) {
Context context = ContextUtils.getApplicationContext();
WindowAndroid windowAndroid = new WindowAndroid(context);
Tab tab = new Tab(INVALID_TAB_ID, INVALID_TAB_ID, false, context, windowAndroid,
TabLaunchType.FROM_DETACHED, null, null);
tab.initialize(null, null, delegateFactory, true, false);
// Resize the webContent to avoid expensive post load resize when attaching the tab.
Rect bounds = ExternalPrerenderHandler.estimateContentSize((Application) context, false);
int width = bounds.right - bounds.left;
int height = bounds.bottom - bounds.top;
tab.getContentViewCore().onSizeChanged(width, height, 0, 0);
tab.detach(null, null);
return tab;
}
private WindowAndroid.IntentCallback createIntentCallback(final AppData appData) {
return new WindowAndroid.IntentCallback() {
@Override
public void onIntentCompleted(WindowAndroid window, int resultCode,
ContentResolver contentResolver, Intent data) {
boolean isInstalling = resultCode == Activity.RESULT_OK;
if (isInstalling) {
// Start monitoring the install.
PackageManager pm =
getPackageManager(ContextUtils.getApplicationContext());
mInstallTask = new InstallerDelegate(
Looper.getMainLooper(), pm, createInstallerDelegateObserver(),
appData.packageName());
mInstallTask.start();
}
nativeOnInstallIntentReturned(mNativePointer, isInstalling);
}
};
}
private WindowAndroid.IntentCallback createIntentCallback(final AppData appData) {
return new WindowAndroid.IntentCallback() {
@Override
public void onIntentCompleted(WindowAndroid window, int resultCode,
ContentResolver contentResolver, Intent data) {
boolean isInstalling = resultCode == Activity.RESULT_OK;
if (isInstalling) {
// Start monitoring the install.
PackageManager pm =
getPackageManager(ContextUtils.getApplicationContext());
mInstallTask = new InstallerDelegate(
Looper.getMainLooper(), pm, createInstallerDelegateObserver(),
appData.packageName());
mInstallTask.start();
}
nativeOnInstallIntentReturned(mNativePointer, isInstalling);
}
};
}
@Override
public PaymentRequest createImpl() {
if (!ChromeFeatureList.isEnabled(ChromeFeatureList.WEB_PAYMENTS)) {
return new InvalidPaymentRequest();
}
if (mWebContents == null) return new InvalidPaymentRequest();
ContentViewCore contentViewCore = ContentViewCore.fromWebContents(mWebContents);
if (contentViewCore == null) return new InvalidPaymentRequest();
WindowAndroid window = contentViewCore.getWindowAndroid();
if (window == null) return new InvalidPaymentRequest();
Activity context = window.getActivity().get();
if (context == null) return new InvalidPaymentRequest();
return new PaymentRequestImpl(context, mWebContents);
}
public AutofillPopupBridge(View anchorView, long nativeAutofillPopupViewAndroid,
WindowAndroid windowAndroid) {
mNativeAutofillPopup = nativeAutofillPopupViewAndroid;
Activity activity = windowAndroid.getActivity().get();
if (activity == null) {
mAutofillPopup = null;
mContext = null;
// Clean up the native counterpart. This is posted to allow the native counterpart
// to fully finish the construction of this glue object before we attempt to delete it.
new Handler().post(new Runnable() {
@Override
public void run() {
dismissed();
}
});
} else {
mAutofillPopup = new AutofillPopup(activity, anchorView, this);
mContext = activity;
mBrowserAccessibilityManager = ((ChromeActivity) activity)
.getCurrentContentViewCore()
.getBrowserAccessibilityManager();
}
}
@CalledByNative
private static void promptToEnableSystemLocationSetting(
@LocationSettingsDialogContext int promptContext, WebContents webContents,
final long nativeCallback) {
WindowAndroid window = webContents.getTopLevelNativeWindow();
if (window == null) {
nativeOnLocationSettingsDialogOutcome(
nativeCallback, LocationSettingsDialogOutcome.NO_PROMPT);
return;
}
LocationUtils.getInstance().promptToEnableSystemLocationSetting(
promptContext, window, new Callback<Integer>() {
@Override
public void onResult(Integer result) {
nativeOnLocationSettingsDialogOutcome(nativeCallback, result);
}
});
}
@Override
public void onIntentCompleted(WindowAndroid window, int resultCode,
ContentResolver contentResolver, Intent data) {
if (resultCode != Activity.RESULT_OK) return;
if (data.getExtras() == null) return;
VoiceResult topResult = mAutocomplete.onVoiceResults(data.getExtras());
if (topResult == null) return;
String topResultQuery = topResult.getMatch();
if (TextUtils.isEmpty(topResultQuery)) return;
if (topResult.getConfidence() < VOICE_SEARCH_CONFIDENCE_NAVIGATE_THRESHOLD) {
setSearchQuery(topResultQuery);
return;
}
String url = AutocompleteController.nativeQualifyPartialURLQuery(topResultQuery);
if (url == null) {
url = TemplateUrlService.getInstance().getUrlForVoiceSearchQuery(
topResultQuery);
}
loadUrl(url, PageTransition.TYPED);
}
@CalledByNative
private static void reauthenticateChildAccount(
WindowAndroid windowAndroid, String accountName, final long nativeCallback) {
ThreadUtils.assertOnUiThread();
Activity activity = windowAndroid.getActivity().get();
if (activity == null) {
ThreadUtils.postOnUiThread(new Runnable() {
@Override
public void run() {
nativeOnReauthenticationResult(nativeCallback, false);
}
});
return;
}
Account account = AccountManagerHelper.createAccountFromName(accountName);
AccountManagerHelper.get().updateCredentials(account, activity, new Callback<Boolean>() {
@Override
public void onResult(Boolean result) {
nativeOnReauthenticationResult(nativeCallback, result);
}
});
}
@Override
public void onIntentCompleted(WindowAndroid window, int resultCode, Intent data) {
if (resultCode != Activity.RESULT_OK) return;
if (data.getExtras() == null) return;
VoiceResult topResult = mAutocomplete.onVoiceResults(data.getExtras());
if (topResult == null) return;
String topResultQuery = topResult.getMatch();
if (TextUtils.isEmpty(topResultQuery)) return;
if (topResult.getConfidence() < VOICE_SEARCH_CONFIDENCE_NAVIGATE_THRESHOLD) {
setSearchQuery(topResultQuery);
return;
}
String url = AutocompleteController.nativeQualifyPartialURLQuery(topResultQuery);
if (url == null) {
url = TemplateUrlService.getInstance().getUrlForVoiceSearchQuery(
topResultQuery);
}
loadUrl(url, PageTransition.TYPED);
}
/**
* Create a new asynchronous request to select a client certificate.
*
* @param nativePtr The native object responsible for this request.
* @param window A WindowAndroid instance.
* @param keyTypes The list of supported key exchange types.
* @param encodedPrincipals The list of CA DistinguishedNames.
* @param hostName The server host name is available (empty otherwise).
* @param port The server port if available (0 otherwise).
* @return true on success.
* Note that nativeOnSystemRequestComplete will be called iff this method returns true.
*/
@CalledByNative
private static boolean selectClientCertificate(final long nativePtr, final WindowAndroid window,
final String[] keyTypes, byte[][] encodedPrincipals, final String hostName,
final int port) {
ThreadUtils.assertOnUiThread();
final Activity activity = window.getActivity().get();
if (activity == null) {
Log.w(TAG, "Certificate request on GC'd activity.");
return false;
}
// Build the list of principals from encoded versions.
Principal[] principals = null;
if (encodedPrincipals.length > 0) {
principals = new X500Principal[encodedPrincipals.length];
try {
for (int n = 0; n < encodedPrincipals.length; n++) {
principals[n] = new X500Principal(encodedPrincipals[n]);
}
} catch (Exception e) {
Log.w(TAG, "Exception while decoding issuers list: " + e);
return false;
}
}
KeyChainCertSelectionCallback callback =
new KeyChainCertSelectionCallback(activity.getApplicationContext(),
nativePtr);
KeyChainCertSelectionWrapper keyChain = new KeyChainCertSelectionWrapper(activity,
callback, keyTypes, principals, hostName, port, null);
maybeShowCertSelection(keyChain, callback,
new CertSelectionFailureDialog(activity));
// We've taken ownership of the native ssl request object.
return true;
}
@CalledByNative
static void unlockOrientation(@Nullable WindowAndroid window) {
// WindowAndroid may be null if the tab is being reparented.
if (window == null) return;
Activity activity = window.getActivity().get();
// Locking orientation is only supported for web contents that have an associated activity.
// Note that we can't just use the focused activity, as that would lead to bugs where
// unlockOrientation unlocks a different activity to the one that was locked.
if (activity == null) return;
int defaultOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
// Activities opened from a shortcut may have EXTRA_ORIENTATION set. In
// which case, we want to use that as the default orientation.
int orientation = activity.getIntent().getIntExtra(
ScreenOrientationConstants.EXTRA_ORIENTATION,
ScreenOrientationValues.DEFAULT);
defaultOrientation = getOrientationFromWebScreenOrientations(
(byte) orientation, window, activity);
try {
if (defaultOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
ActivityInfo info = activity.getPackageManager().getActivityInfo(
activity.getComponentName(), PackageManager.GET_META_DATA);
defaultOrientation = info.screenOrientation;
}
} catch (PackageManager.NameNotFoundException e) {
// Do nothing, defaultOrientation should be SCREEN_ORIENTATION_UNSPECIFIED.
} finally {
activity.setRequestedOrientation(defaultOrientation);
}
}
@CalledByNative
private static UsbChooserDialog create(WindowAndroid windowAndroid, String origin,
int securityLevel, long nativeUsbChooserDialogPtr) {
Activity activity = windowAndroid.getActivity().get();
if (activity == null) {
return null;
}
UsbChooserDialog dialog = new UsbChooserDialog(nativeUsbChooserDialogPtr);
dialog.show(activity, origin, securityLevel);
return dialog;
}
private static void createCompositorScreenshot(WindowAndroid windowAndroid,
Rect windowRect, final ScreenshotTaskCallback callback) {
SnapshotResultCallback resultCallback = new SnapshotResultCallback() {
@Override
public void onCompleted(byte[] pngBytes) {
callback.onGotBitmap(pngBytes != null
? BitmapFactory.decodeByteArray(pngBytes, 0, pngBytes.length) : null);
}
};
nativeGrabWindowSnapshotAsync(resultCallback, windowAndroid.getNativePointer(),
windowRect.width(), windowRect.height());
}
@CalledByNative
private static AutoSigninFirstRunDialog createAndShowDialog(WindowAndroid windowAndroid,
long nativeAutoSigninFirstRunDialog, String title, String explanation,
int explanationLinkStart, int explanationLinkEnd, String okButtonText,
String turnOffButtonText) {
Activity activity = windowAndroid.getActivity().get();
if (activity == null) return null;
AutoSigninFirstRunDialog dialog = new AutoSigninFirstRunDialog(activity,
nativeAutoSigninFirstRunDialog, title, explanation, explanationLinkStart,
explanationLinkEnd, okButtonText, turnOffButtonText);
dialog.show();
return dialog;
}
private static void createCompositorScreenshot(WindowAndroid windowAndroid,
Rect windowRect, final ScreenshotTaskCallback callback) {
SnapshotResultCallback resultCallback = new SnapshotResultCallback() {
@Override
public void onCompleted(byte[] pngBytes) {
callback.onGotBitmap(pngBytes != null
? BitmapFactory.decodeByteArray(pngBytes, 0, pngBytes.length) : null);
}
};
nativeGrabWindowSnapshotAsync(resultCallback, windowAndroid.getNativePointer(),
windowRect.width(), windowRect.height());
}
@CalledByNative
private void showDialog(WindowAndroid windowAndroid) {
if (windowAndroid == null) {
cancel();
}
Activity activity = windowAndroid.getActivity().get();
if (activity == null) {
cancel();
}
LoginPrompt authDialog = new LoginPrompt(activity, this);
setAutofillObserver(authDialog);
authDialog.show();
}
public ChromeTabCreator(ChromeActivity activity, WindowAndroid nativeWindow,
TabModelOrderController orderController, TabPersistentStore tabSaver,
boolean incognito) {
mActivity = activity;
mNativeWindow = nativeWindow;
mOrderController = orderController;
mTabSaver = tabSaver;
mIncognito = incognito;
}
@Nullable
private static Activity activityFromWebContents(@Nullable WebContents webContents) {
if (webContents == null) return null;
WindowAndroid window = webContents.getTopLevelNativeWindow();
if (window == null) return null;
return window.getActivity().get();
}
/**
* Creates a new tab to be loaded lazily. This can be used for tabs opened in the background
* that should be loaded when switched to. initialize() needs to be called afterwards to
* complete the second level initialization.
*/
public static Tab createTabForLazyLoad(ChromeActivity activity, boolean incognito,
WindowAndroid nativeWindow, TabLaunchType type, int parentId,
LoadUrlParams loadUrlParams) {
Tab tab = new Tab(
INVALID_TAB_ID, parentId, incognito, activity, nativeWindow, type,
TabCreationState.FROZEN_FOR_LAZY_LOAD, null);
tab.setPendingLoadParams(loadUrlParams);
return tab;
}
/**
* Initialization that requires native libraries should be done here.
* Native code should add/remove the layers to be rendered through the ContentViewLayerRenderer.
* @param rootWindow The {@link WindowAndroid} this render view should be linked to.
*/
public void onNativeLibraryLoaded(WindowAndroid rootWindow) {
assert !mSurfaceView.getHolder().getSurface().isValid() :
"Surface created before native library loaded.";
assert rootWindow != null;
mNativeContentViewRenderView = nativeInit(rootWindow.getNativePointer());
assert mNativeContentViewRenderView != 0;
mSurfaceCallback = new SurfaceHolder.Callback() {
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
assert mNativeContentViewRenderView != 0;
nativeSurfaceChanged(mNativeContentViewRenderView,
format, width, height, holder.getSurface());
if (mContentViewCore != null) {
nativeOnPhysicalBackingSizeChanged(mNativeContentViewRenderView,
mContentViewCore.getWebContents(), width, height);
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
assert mNativeContentViewRenderView != 0;
nativeSurfaceCreated(mNativeContentViewRenderView);
onReadyToRender();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
assert mNativeContentViewRenderView != 0;
nativeSurfaceDestroyed(mNativeContentViewRenderView);
}
};
mSurfaceView.getHolder().addCallback(mSurfaceCallback);
mSurfaceView.setVisibility(VISIBLE);
}
/**
* For certain download types(OMA for example), android DownloadManager should
* handle them. Call this function to intercept those downloads.
*
* @param url URL to be downloaded.
* @return whether the DownloadManager should intercept the download.
*/
public boolean shouldInterceptContextMenuDownload(String url) {
Uri uri = Uri.parse(url);
String scheme = uri.normalizeScheme().getScheme();
if (!"http".equals(scheme) && !"https".equals(scheme)) return false;
String path = uri.getPath();
// OMA downloads have extension "dm" or "dd". For the latter, it
// can be handled when native download completes.
if (path != null && (path.endsWith(".dm"))) {
if (mTab == null) return true;
String fileName = URLUtil.guessFileName(
url, null, OMADownloadHandler.OMA_DRM_MESSAGE_MIME);
final DownloadInfo downloadInfo =
new DownloadInfo.Builder().setUrl(url).setFileName(fileName).build();
WindowAndroid window = mTab.getWindowAndroid();
if (window.hasPermission(permission.WRITE_EXTERNAL_STORAGE)) {
onDownloadStartNoStream(downloadInfo);
} else if (window.canRequestPermission(permission.WRITE_EXTERNAL_STORAGE)) {
PermissionCallback permissionCallback = new PermissionCallback() {
@Override
public void onRequestPermissionsResult(
String[] permissions, int[] grantResults) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
onDownloadStartNoStream(downloadInfo);
}
}
};
window.requestPermissions(
new String[] {permission.WRITE_EXTERNAL_STORAGE}, permissionCallback);
}
return true;
}
return false;
}
/**
* For certain download types(OMA for example), android DownloadManager should
* handle them. Call this function to intercept those downloads.
*
* @param url URL to be downloaded.
* @return whether the DownloadManager should intercept the download.
*/
public boolean shouldInterceptContextMenuDownload(String url) {
Uri uri = Uri.parse(url);
String scheme = uri.normalizeScheme().getScheme();
if (!UrlConstants.HTTP_SCHEME.equals(scheme) && !UrlConstants.HTTPS_SCHEME.equals(scheme)) {
return false;
}
String path = uri.getPath();
if (!OMADownloadHandler.isOMAFile(path)) return false;
if (mTab == null) return true;
String fileName = URLUtil.guessFileName(
url, null, OMADownloadHandler.OMA_DRM_MESSAGE_MIME);
final DownloadInfo downloadInfo =
new DownloadInfo.Builder().setUrl(url).setFileName(fileName).build();
WindowAndroid window = mTab.getWindowAndroid();
if (window.hasPermission(permission.WRITE_EXTERNAL_STORAGE)) {
onDownloadStartNoStream(downloadInfo);
} else if (window.canRequestPermission(permission.WRITE_EXTERNAL_STORAGE)) {
PermissionCallback permissionCallback = new PermissionCallback() {
@Override
public void onRequestPermissionsResult(
String[] permissions, int[] grantResults) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
onDownloadStartNoStream(downloadInfo);
}
}
};
window.requestPermissions(
new String[] {permission.WRITE_EXTERNAL_STORAGE}, permissionCallback);
}
return true;
}
@Override
public void onDIPScaleChanged(float dipScale) {
WindowAndroid windowAndroid = getWindowAndroid();
if (windowAndroid == null || mNativeContentViewCore == 0) return;
mRenderCoordinates.setDeviceScaleFactor(dipScale, getWindowAndroid().getContext());
nativeSetDIPScale(mNativeContentViewCore, dipScale);
}
private void notifyPermissionResult() {
boolean hasAllPermissions = true;
WindowAndroid windowAndroid = mContentViewCore.getWindowAndroid();
if (windowAndroid == null) {
hasAllPermissions = false;
} else {
for (int i = 0; i < mAndroidPermisisons.length; i++) {
hasAllPermissions &= windowAndroid.hasPermission(mAndroidPermisisons[i]);
}
}
if (mNativePtr != 0) nativeOnPermissionResult(mNativePtr, hasAllPermissions);
}
/**
* Creates a new tab to be loaded lazily. This can be used for tabs opened in the background
* that should be loaded when switched to. initialize() needs to be called afterwards to
* complete the second level initialization.
*/
public static Tab createTabForLazyLoad(ChromeActivity activity, boolean incognito,
WindowAndroid nativeWindow, TabLaunchType type, int parentId,
LoadUrlParams loadUrlParams) {
Tab tab = new Tab(
INVALID_TAB_ID, parentId, incognito, activity, nativeWindow, type,
TabCreationState.FROZEN_FOR_LAZY_LOAD, null);
tab.setPendingLoadParams(loadUrlParams);
return tab;
}