Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(258)

Unified Diff: content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityInjector.java

Issue 1100823004: Remove AccessibilityInjector support. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update Chrome cast shell Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityInjector.java
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityInjector.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityInjector.java
deleted file mode 100644
index d07c4931dfb152ea992b1ae7d7e0052a1d153ba3..0000000000000000000000000000000000000000
--- a/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityInjector.java
+++ /dev/null
@@ -1,457 +0,0 @@
-// Copyright 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 org.chromium.content.browser.accessibility;
-
-import android.accessibilityservice.AccessibilityServiceInfo;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Vibrator;
-import android.speech.tts.TextToSpeech;
-import android.view.View;
-import android.view.accessibility.AccessibilityManager;
-import android.view.accessibility.AccessibilityNodeInfo;
-
-import org.apache.http.NameValuePair;
-import org.apache.http.client.utils.URLEncodedUtils;
-import org.chromium.base.CommandLine;
-import org.chromium.content.browser.ContentViewCore;
-import org.chromium.content.browser.JavascriptInterface;
-import org.chromium.content.common.ContentSwitches;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * Responsible for accessibility injection and management of a {@link ContentViewCore}.
- */
-public class AccessibilityInjector {
- // The ContentView this injector is responsible for managing.
- protected ContentViewCore mContentViewCore;
-
- // The Java objects that are exposed to JavaScript
- private TextToSpeechWrapper mTextToSpeech;
- private VibratorWrapper mVibrator;
- private final boolean mHasVibratePermission;
-
- // Lazily loaded helper objects.
- private AccessibilityManager mAccessibilityManager;
-
- // Whether or not we should be injecting the script.
- protected boolean mInjectedScriptEnabled;
- protected boolean mScriptInjected;
-
- private final String mAccessibilityScreenReaderUrl;
-
- // To support building against the JELLY_BEAN and not JELLY_BEAN_MR1 SDK we need to add this
- // constant here.
- private static final int FEEDBACK_BRAILLE = 0x00000020;
-
- // constants for determining script injection strategy
- private static final int ACCESSIBILITY_SCRIPT_INJECTION_UNDEFINED = -1;
- private static final int ACCESSIBILITY_SCRIPT_INJECTION_OPTED_OUT = 0;
- private static final int ACCESSIBILITY_SCRIPT_INJECTION_PROVIDED = 1;
- private static final String ALIAS_ACCESSIBILITY_JS_INTERFACE = "accessibility";
- private static final String ALIAS_ACCESSIBILITY_JS_INTERFACE_2 = "accessibility2";
-
- // Template for JavaScript that injects a screen-reader.
- private static final String DEFAULT_ACCESSIBILITY_SCREEN_READER_URL =
- "https://ssl.gstatic.com/accessibility/javascript/android/chromeandroidvox.js";
-
- private static final String ACCESSIBILITY_SCREEN_READER_JAVASCRIPT_TEMPLATE =
- "(function() {"
- + " var chooser = document.createElement('script');"
- + " chooser.type = 'text/javascript';"
- + " chooser.src = '%1s';"
- + " document.getElementsByTagName('head')[0].appendChild(chooser);"
- + " })();";
-
- // JavaScript call to turn ChromeVox on or off.
- private static final String TOGGLE_CHROME_VOX_JAVASCRIPT =
- "(function() {"
- + " if (typeof cvox !== 'undefined') {"
- + " cvox.ChromeVox.host.activateOrDeactivateChromeVox(%1s);"
- + " }"
- + " })();";
-
- /**
- * Returns an instance of the {@link AccessibilityInjector} based on the SDK version.
- * @param view The ContentViewCore that this AccessibilityInjector manages.
- * @return An instance of a {@link AccessibilityInjector}.
- */
- public static AccessibilityInjector newInstance(ContentViewCore view) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- return new LollipopAccessibilityInjector(view);
- } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- return new JellyBeanAccessibilityInjector(view);
- } else {
- return new AccessibilityInjector(view);
- }
- }
-
- /**
- * Creates an instance of the IceCreamSandwichAccessibilityInjector.
- * @param view The ContentViewCore that this AccessibilityInjector manages.
- */
- protected AccessibilityInjector(ContentViewCore view) {
- mContentViewCore = view;
-
- mAccessibilityScreenReaderUrl = CommandLine.getInstance().getSwitchValue(
- ContentSwitches.ACCESSIBILITY_JAVASCRIPT_URL,
- DEFAULT_ACCESSIBILITY_SCREEN_READER_URL);
-
- mHasVibratePermission = mContentViewCore.getContext().checkCallingOrSelfPermission(
- android.Manifest.permission.VIBRATE) == PackageManager.PERMISSION_GRANTED;
- }
-
- /**
- * Injects a <script> tag into the current web site that pulls in the ChromeVox script for
- * accessibility support. Only injects if accessibility is turned on by
- * {@link AccessibilityManager#isEnabled()}, accessibility script injection is turned on, and
- * javascript is enabled on this page.
- *
- * @see AccessibilityManager#isEnabled()
- */
- public void injectAccessibilityScriptIntoPage() {
- if (!accessibilityIsAvailable()) return;
-
- int axsParameterValue = getAxsUrlParameterValue();
- if (axsParameterValue != ACCESSIBILITY_SCRIPT_INJECTION_UNDEFINED) {
- return;
- }
-
- String js = getScreenReaderInjectingJs();
- if (mContentViewCore.isDeviceAccessibilityScriptInjectionEnabled()
- && js != null && mContentViewCore.isAlive()) {
- addOrRemoveAccessibilityApisIfNecessary();
- mContentViewCore.getWebContents().evaluateJavaScript(js, null);
- mInjectedScriptEnabled = true;
- mScriptInjected = true;
- }
- }
-
- /**
- * Handles adding or removing accessibility related Java objects ({@link TextToSpeech} and
- * {@link Vibrator}) interfaces from Javascript. This method should be called at a time when it
- * is safe to add or remove these interfaces, specifically when the {@link ContentViewCore} is
- * first initialized or right before the {@link ContentViewCore} is about to navigate to a URL
- * or reload.
- * <p>
- * If this method is called at other times, the interfaces might not be correctly removed,
- * meaning that Javascript can still access these Java objects that may have been already
- * shut down.
- */
- public void addOrRemoveAccessibilityApisIfNecessary() {
- if (accessibilityIsAvailable()) {
- addAccessibilityApis();
- } else {
- removeAccessibilityApis();
- }
- }
-
- /**
- * Checks whether or not touch to explore is enabled on the system.
- */
- public boolean accessibilityIsAvailable() {
- if (!getAccessibilityManager().isEnabled()
- || !mContentViewCore.getContentViewClient().isJavascriptEnabled()) {
- return false;
- }
-
- try {
- // Check that there is actually a service running that requires injecting this script.
- List<AccessibilityServiceInfo> services =
- getAccessibilityManager().getEnabledAccessibilityServiceList(
- FEEDBACK_BRAILLE | AccessibilityServiceInfo.FEEDBACK_SPOKEN);
- return services.size() > 0;
- } catch (NullPointerException e) {
- // getEnabledAccessibilityServiceList() can throw an NPE due to a bad
- // AccessibilityService.
- return false;
- }
- }
-
- /**
- * Sets whether or not the script is enabled. If the script is disabled, we also stop any
- * we output that is occurring. If the script has not yet been injected, injects it.
- * @param enabled Whether or not to enable the script.
- */
- public void setScriptEnabled(boolean enabled) {
- if (enabled && !mScriptInjected) injectAccessibilityScriptIntoPage();
- if (!accessibilityIsAvailable() || mInjectedScriptEnabled == enabled) return;
-
- mInjectedScriptEnabled = enabled;
- if (mContentViewCore.isAlive()) {
- String js = String.format(TOGGLE_CHROME_VOX_JAVASCRIPT, Boolean.toString(
- mInjectedScriptEnabled));
- mContentViewCore.getWebContents().evaluateJavaScript(js, null);
-
- if (!mInjectedScriptEnabled) {
- // Stop any TTS/Vibration right now.
- onPageLostFocus();
- }
- }
- }
-
- /**
- * Notifies this handler that a page load has started, which means we should mark the
- * accessibility script as not being injected. This way we can properly ignore incoming
- * accessibility gesture events.
- */
- public void onPageLoadStarted() {
- mScriptInjected = false;
- }
-
- /**
- * Notifies this handler that a page load has stopped, which means we can now inject the
- * accessibility script.
- */
- public void onPageLoadStopped() {
- injectAccessibilityScriptIntoPage();
- }
-
- /**
- * Stop any notifications that are currently going on (e.g. Text-to-Speech).
- */
- public void onPageLostFocus() {
- if (mContentViewCore.isAlive()) {
- if (mTextToSpeech != null) mTextToSpeech.stop();
- if (mVibrator != null) mVibrator.cancel();
- }
- }
-
- /**
- * Initializes an {@link AccessibilityNodeInfo} with the actions and movement granularity
- * levels supported by this {@link AccessibilityInjector}.
- * <p>
- * If an action identifier is added in this method, this {@link AccessibilityInjector} should
- * also return {@code true} from {@link #supportsAccessibilityAction(int)}.
- * </p>
- *
- * @param info The info to initialize.
- * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
- */
- public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { }
-
- /**
- * Returns {@code true} if this {@link AccessibilityInjector} should handle the specified
- * action.
- *
- * @param action An accessibility action identifier.
- * @return {@code true} if this {@link AccessibilityInjector} should handle the specified
- * action.
- */
- public boolean supportsAccessibilityAction(int action) {
- return false;
- }
-
- /**
- * Performs the specified accessibility action.
- *
- * @param action The identifier of the action to perform.
- * @param arguments The action arguments, or {@code null} if no arguments.
- * @return {@code true} if the action was successful.
- * @see View#performAccessibilityAction(int, Bundle)
- */
- public boolean performAccessibilityAction(int action, Bundle arguments) {
- return false;
- }
-
- protected void addAccessibilityApis() {
- Context context = mContentViewCore.getContext();
- if (context != null) {
- // Enabled, we should try to add if we have to.
- if (mTextToSpeech == null) {
- mTextToSpeech = createTextToSpeechWrapper(mContentViewCore.getContainerView(),
- context);
- mContentViewCore.addJavascriptInterface(mTextToSpeech,
- ALIAS_ACCESSIBILITY_JS_INTERFACE);
- }
-
- if (mVibrator == null && mHasVibratePermission) {
- mVibrator = new VibratorWrapper(context);
- mContentViewCore.addJavascriptInterface(mVibrator,
- ALIAS_ACCESSIBILITY_JS_INTERFACE_2);
- }
- }
- }
-
- protected void removeAccessibilityApis() {
- if (mTextToSpeech != null) {
- mContentViewCore.removeJavascriptInterface(ALIAS_ACCESSIBILITY_JS_INTERFACE);
- mTextToSpeech.stop();
- mTextToSpeech.shutdownInternal();
- mTextToSpeech = null;
- }
-
- if (mVibrator != null) {
- mContentViewCore.removeJavascriptInterface(ALIAS_ACCESSIBILITY_JS_INTERFACE_2);
- mVibrator.cancel();
- mVibrator = null;
- }
- }
-
- private int getAxsUrlParameterValue() {
- if (mContentViewCore.getWebContents().getUrl() == null) {
- return ACCESSIBILITY_SCRIPT_INJECTION_UNDEFINED;
- }
-
- try {
- List<NameValuePair> params = URLEncodedUtils.parse(
- new URI(mContentViewCore.getWebContents().getUrl()), null);
-
- for (NameValuePair param : params) {
- if ("axs".equals(param.getName())) {
- return Integer.parseInt(param.getValue());
- }
- }
- } catch (URISyntaxException ex) {
- // Intentional no-op.
- } catch (NumberFormatException ex) {
- // Intentional no-op.
- } catch (IllegalArgumentException ex) {
- // Intentional no-op.
- }
-
- return ACCESSIBILITY_SCRIPT_INJECTION_UNDEFINED;
- }
-
- private String getScreenReaderInjectingJs() {
- return String.format(ACCESSIBILITY_SCREEN_READER_JAVASCRIPT_TEMPLATE,
- mAccessibilityScreenReaderUrl);
- }
-
- private AccessibilityManager getAccessibilityManager() {
- if (mAccessibilityManager == null) {
- mAccessibilityManager = (AccessibilityManager) mContentViewCore.getContext()
- .getSystemService(Context.ACCESSIBILITY_SERVICE);
- }
-
- return mAccessibilityManager;
- }
-
- /**
- * Used to protect how long JavaScript can vibrate for. This isn't a good comprehensive
- * protection, just used to cover mistakes and protect against long vibrate durations/repeats.
- *
- * Also only exposes methods we *want* to expose, no others for the class.
- */
- private static class VibratorWrapper {
- private static final long MAX_VIBRATE_DURATION_MS = 5000;
-
- private final Vibrator mVibrator;
-
- public VibratorWrapper(Context context) {
- mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
- }
-
- @JavascriptInterface
- @SuppressWarnings("unused")
- public boolean hasVibrator() {
- return mVibrator.hasVibrator();
- }
-
- @JavascriptInterface
- @SuppressWarnings("unused")
- public void vibrate(long milliseconds) {
- milliseconds = Math.min(milliseconds, MAX_VIBRATE_DURATION_MS);
- mVibrator.vibrate(milliseconds);
- }
-
- @JavascriptInterface
- @SuppressWarnings("unused")
- public void vibrate(long[] pattern, int repeat) {
- for (int i = 0; i < pattern.length; ++i) {
- pattern[i] = Math.min(pattern[i], MAX_VIBRATE_DURATION_MS);
- }
-
- repeat = -1;
-
- mVibrator.vibrate(pattern, repeat);
- }
-
- @JavascriptInterface
- @SuppressWarnings("unused")
- public void cancel() {
- mVibrator.cancel();
- }
- }
-
- protected TextToSpeechWrapper createTextToSpeechWrapper(View view, Context context) {
- return new TextToSpeechWrapper(view, context);
- }
-
- /**
- * Used to protect the TextToSpeech class, only exposing the methods we want to expose.
- */
- protected static class TextToSpeechWrapper {
- protected final TextToSpeech mTextToSpeech;
- private final View mView;
-
- protected TextToSpeechWrapper(View view, Context context) {
- mView = view;
- mTextToSpeech = new TextToSpeech(context, null, null);
- }
-
- @JavascriptInterface
- @SuppressWarnings("unused")
- public boolean isSpeaking() {
- return mTextToSpeech.isSpeaking();
- }
-
- @JavascriptInterface
- @SuppressWarnings({"unused", "deprecation"})
- public int speak(String text, int queueMode, String jsonParams) {
- // Try to pull the params from the JSON string.
- HashMap<String, String> params = null;
- try {
- if (jsonParams != null) {
- params = new HashMap<String, String>();
- JSONObject json = new JSONObject(jsonParams);
-
- // Using legacy API here.
- @SuppressWarnings("unchecked")
- Iterator<String> keyIt = json.keys();
-
- while (keyIt.hasNext()) {
- String key = keyIt.next();
- // Only add parameters that are raw data types.
- if (json.optJSONObject(key) == null && json.optJSONArray(key) == null) {
- params.put(key, json.getString(key));
- }
- }
- }
- } catch (JSONException e) {
- params = null;
- }
-
- return mTextToSpeech.speak(text, queueMode, params);
- }
-
- @JavascriptInterface
- @SuppressWarnings("unused")
- public int stop() {
- return mTextToSpeech.stop();
- }
-
- @JavascriptInterface
- @SuppressWarnings("unused")
- public void braille(String jsonString) {
- // This is here because AndroidVox depends on the existence
- // of this method.
- }
-
- @SuppressWarnings("unused")
- protected void shutdownInternal() {
- mTextToSpeech.shutdown();
- }
- }
-}

Powered by Google App Engine
This is Rietveld 408576698