Commit f6250339 authored by dtrainor@chromium.org's avatar dtrainor@chromium.org

Start upstreaming accessibility.


BUG=http://crbug.com/138218


Review URL: https://chromiumcodereview.appspot.com/10832104

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@149667 0039d316-1c4b-4281-b951-d872f2087c98
parent cfeb8ee8
...@@ -7,13 +7,18 @@ package org.chromium.content.browser; ...@@ -7,13 +7,18 @@ package org.chromium.content.browser;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.os.Build;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.webkit.DownloadListener; import android.webkit.DownloadListener;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import org.chromium.content.browser.ContentViewCore;
/** /**
* The containing view for {@link ContentViewCore} that exists in the Android UI hierarchy and * The containing view for {@link ContentViewCore} that exists in the Android UI hierarchy and
* exposes the various {@link View} functionality to it. * exposes the various {@link View} functionality to it.
...@@ -94,21 +99,55 @@ public class ContentView extends FrameLayout implements ContentViewCore.Internal ...@@ -94,21 +99,55 @@ public class ContentView extends FrameLayout implements ContentViewCore.Internal
private ContentViewCore mContentViewCore; private ContentViewCore mContentViewCore;
public ContentView(Context context, int nativeWebContents, int personality) { /**
this(context, nativeWebContents, null, android.R.attr.webViewStyle, personality); * Creates an instance of a ContentView.
* @param context The Context the view is running in, through which it can
* access the current theme, resources, etc.
* @param nativeWebContents A pointer to the native web contents.
* @param personality One of {@link #PERSONALITY_CHROME} or {@link #PERSONALITY_VIEW}.
* @return A ContentView instance.
*/
public static ContentView newInstance(Context context, int nativeWebContents, int personality) {
return newInstance(context, nativeWebContents, null, android.R.attr.webViewStyle,
personality);
} }
public ContentView(Context context, int nativeWebContents, AttributeSet attrs) { /**
* Creates an instance of a ContentView.
* @param context The Context the view is running in, through which it can
* access the current theme, resources, etc.
* @param nativeWebContents A pointer to the native web contents.
* @param attrs The attributes of the XML tag that is inflating the view.
* @return A ContentView instance.
*/
public static ContentView newInstance(Context context, int nativeWebContents,
AttributeSet attrs) {
// TODO(klobag): use the WebViewStyle as the default style for now. It enables scrollbar. // TODO(klobag): use the WebViewStyle as the default style for now. It enables scrollbar.
// When ContentView is moved to framework, we can define its own style in the res. // When ContentView is moved to framework, we can define its own style in the res.
this(context, nativeWebContents, attrs, android.R.attr.webViewStyle); return newInstance(context, nativeWebContents, attrs, android.R.attr.webViewStyle);
}
/**
* Creates an instance of a ContentView.
* @param context The Context the view is running in, through which it can
* access the current theme, resources, etc.
* @param nativeWebContents A pointer to the native web contents.
* @param attrs The attributes of the XML tag that is inflating the view.
* @param defStyle The default style to apply to this view.
* @return A ContentView instance.
*/
public static ContentView newInstance(Context context, int nativeWebContents,
AttributeSet attrs, int defStyle) {
return newInstance(context, nativeWebContents, attrs, defStyle, PERSONALITY_VIEW);
} }
public ContentView(Context context, int nativeWebContents, AttributeSet attrs, int defStyle) { private static ContentView newInstance(Context context, int nativeWebContents,
this(context, nativeWebContents, attrs, defStyle, PERSONALITY_VIEW); AttributeSet attrs, int defStyle, int personality) {
// TODO(dtrainor): Upstream JellyBean version of AccessibilityInjector when SDK is 16.
return new ContentView(context, nativeWebContents, attrs, defStyle, personality);
} }
private ContentView(Context context, int nativeWebContents, AttributeSet attrs, int defStyle, protected ContentView(Context context, int nativeWebContents, AttributeSet attrs, int defStyle,
int personality) { int personality) {
super(context, attrs, defStyle); super(context, attrs, defStyle);
...@@ -319,6 +358,34 @@ public class ContentView extends FrameLayout implements ContentViewCore.Internal ...@@ -319,6 +358,34 @@ public class ContentView extends FrameLayout implements ContentViewCore.Internal
mContentViewCore.getContentViewGestureHandler().pinchBy(timeMs, anchorX, anchorY, delta); mContentViewCore.getContentViewGestureHandler().pinchBy(timeMs, anchorX, anchorY, delta);
} }
/**
* This method should be called when the containing activity is paused.
**/
public void onActivityPause() {
mContentViewCore.onActivityPause();
}
/**
* This method should be called when the containing activity is resumed.
**/
public void onActivityResume() {
mContentViewCore.onActivityResume();
}
/**
* To be called when the ContentView is shown.
**/
public void onShow() {
mContentViewCore.onShow();
}
/**
* To be called when the ContentView is hidden.
**/
public void onHide() {
mContentViewCore.onHide();
}
/** /**
* Return the ContentSettings object used to control the settings for this * Return the ContentSettings object used to control the settings for this
* WebView. * WebView.
...@@ -363,6 +430,30 @@ public class ContentView extends FrameLayout implements ContentViewCore.Internal ...@@ -363,6 +430,30 @@ public class ContentView extends FrameLayout implements ContentViewCore.Internal
return super.awakenScrollBars(); return super.awakenScrollBars();
} }
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
mContentViewCore.onInitializeAccessibilityNodeInfo(info);
}
@Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
mContentViewCore.onInitializeAccessibilityEvent(event);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mContentViewCore.onAttachedToWindow();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mContentViewCore.onDetachedFromWindow();
}
void updateMultiTouchZoomSupport() { void updateMultiTouchZoomSupport() {
mContentViewCore.updateMultiTouchZoomSupport(); mContentViewCore.updateMultiTouchZoomSupport();
} }
......
...@@ -7,6 +7,7 @@ package org.chromium.content.browser; ...@@ -7,6 +7,7 @@ package org.chromium.content.browser;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.ActionMode; import android.view.ActionMode;
...@@ -14,6 +15,8 @@ import android.view.KeyEvent; ...@@ -14,6 +15,8 @@ import android.view.KeyEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.webkit.DownloadListener; import android.webkit.DownloadListener;
import org.chromium.base.CalledByNative; import org.chromium.base.CalledByNative;
...@@ -25,6 +28,7 @@ import org.chromium.content.browser.ZoomManager; ...@@ -25,6 +28,7 @@ import org.chromium.content.browser.ZoomManager;
import org.chromium.content.common.CleanupReference; import org.chromium.content.common.CleanupReference;
import org.chromium.content.common.TraceEvent; import org.chromium.content.common.TraceEvent;
import org.chromium.content.browser.accessibility.AccessibilityInjector;
import org.chromium.content.browser.ContentViewGestureHandler.MotionEventDelegate; import org.chromium.content.browser.ContentViewGestureHandler.MotionEventDelegate;
/** /**
...@@ -178,6 +182,9 @@ public class ContentViewCore implements MotionEventDelegate { ...@@ -178,6 +182,9 @@ public class ContentViewCore implements MotionEventDelegate {
// over DownloadListener. // over DownloadListener.
private ContentViewDownloadDelegate mDownloadDelegate; private ContentViewDownloadDelegate mDownloadDelegate;
// The AccessibilityInjector that handles loading Accessibility scripts into the web page.
private final AccessibilityInjector mAccessibilityInjector;
/** /**
* Enable multi-process ContentView. This should be called by the application before * Enable multi-process ContentView. This should be called by the application before
* constructing any ContentView instances. If enabled, ContentView will run renderers in * constructing any ContentView instances. If enabled, ContentView will run renderers in
...@@ -235,6 +242,9 @@ public class ContentViewCore implements MotionEventDelegate { ...@@ -235,6 +242,9 @@ public class ContentViewCore implements MotionEventDelegate {
AndroidBrowserProcess.initContentViewProcess( AndroidBrowserProcess.initContentViewProcess(
context, AndroidBrowserProcess.MAX_RENDERERS_SINGLE_PROCESS); context, AndroidBrowserProcess.MAX_RENDERERS_SINGLE_PROCESS);
mAccessibilityInjector = AccessibilityInjector.newInstance(this);
mAccessibilityInjector.addOrRemoveAccessibilityApisIfNecessary();
initialize(context, nativeWebContents, personality); initialize(context, nativeWebContents, personality);
} }
...@@ -368,6 +378,7 @@ public class ContentViewCore implements MotionEventDelegate { ...@@ -368,6 +378,7 @@ public class ContentViewCore implements MotionEventDelegate {
* omnibox can report suggestions correctly. * omnibox can report suggestions correctly.
*/ */
public void loadUrlWithoutUrlSanitization(String url, int pageTransition) { public void loadUrlWithoutUrlSanitization(String url, int pageTransition) {
mAccessibilityInjector.addOrRemoveAccessibilityApisIfNecessary();
if (mNativeContentViewCore != 0) { if (mNativeContentViewCore != 0) {
if (isPersonalityView()) { if (isPersonalityView()) {
nativeLoadUrlWithoutUrlSanitizationWithUserAgentOverride( nativeLoadUrlWithoutUrlSanitizationWithUserAgentOverride(
...@@ -484,6 +495,7 @@ public class ContentViewCore implements MotionEventDelegate { ...@@ -484,6 +495,7 @@ public class ContentViewCore implements MotionEventDelegate {
* Reload the current page. * Reload the current page.
*/ */
public void reload() { public void reload() {
mAccessibilityInjector.addOrRemoveAccessibilityApisIfNecessary();
if (mNativeContentViewCore != 0) nativeReload(mNativeContentViewCore); if (mNativeContentViewCore != 0) nativeReload(mNativeContentViewCore);
} }
...@@ -605,19 +617,35 @@ public class ContentViewCore implements MotionEventDelegate { ...@@ -605,19 +617,35 @@ public class ContentViewCore implements MotionEventDelegate {
} }
/** /**
* This method should be called when the containing activity is paused * This method should be called when the containing activity is paused.
*/ */
public void onActivityPause() { public void onActivityPause() {
TraceEvent.begin(); TraceEvent.begin();
hidePopupDialog(); hidePopupDialog();
setAccessibilityState(false);
TraceEvent.end(); TraceEvent.end();
} }
/** /**
* Called when the ContentView is hidden. * This method should be called when the containing activity is resumed.
*/
public void onActivityResume() {
setAccessibilityState(true);
}
/**
* To be called when the ContentView is shown.
*/
public void onShow() {
setAccessibilityState(true);
}
/**
* To be called when the ContentView is hidden.
*/ */
public void onHide() { public void onHide() {
hidePopupDialog(); hidePopupDialog();
setAccessibilityState(false);
} }
/** /**
...@@ -645,6 +673,22 @@ public class ContentViewCore implements MotionEventDelegate { ...@@ -645,6 +673,22 @@ public class ContentViewCore implements MotionEventDelegate {
SelectPopupDialog.hide(this); SelectPopupDialog.hide(this);
} }
/**
* @see View#onAttachedToWindow()
*/
@SuppressWarnings("javadoc")
protected void onAttachedToWindow() {
setAccessibilityState(true);
}
/**
* @see View#onDetachedFromWindow()
*/
@SuppressWarnings("javadoc")
protected void onDetachedFromWindow() {
setAccessibilityState(false);
}
// End FrameLayout overrides. // End FrameLayout overrides.
/** /**
...@@ -1012,6 +1056,57 @@ public class ContentViewCore implements MotionEventDelegate { ...@@ -1012,6 +1056,57 @@ public class ContentViewCore implements MotionEventDelegate {
getContentViewClient().onStartContentIntent(getContext(), contentUrl); getContentViewClient().onStartContentIntent(getContext(), contentUrl);
} }
/**
* Determines whether or not this ContentViewCore can handle this accessibility action.
* @param action The action to perform.
* @return Whether or not this action is supported.
*/
public boolean supportsAccessibilityAction(int action) {
return mAccessibilityInjector.supportsAccessibilityAction(action);
}
/**
* Attempts to perform an accessibility action on the web content. If the accessibility action
* cannot be processed, it returns {@code null}, allowing the caller to know to call the
* super {@link View#performAccessibilityAction(int, Bundle)} method and use that return value.
* Otherwise the return value from this method should be used.
* @param action The action to perform.
* @param arguments Optional action arguments.
* @return Whether the action was performed or {@code null} if the call should be delegated to
* the super {@link View} class.
*/
public boolean performAccessibilityAction(int action, Bundle arguments) {
if (mAccessibilityInjector.supportsAccessibilityAction(action)) {
return mAccessibilityInjector.performAccessibilityAction(action, arguments);
}
return false;
}
/**
* @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
*/
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
mAccessibilityInjector.onInitializeAccessibilityNodeInfo(info);
// TODO(dtrainor): Upstream accessibility scrolling event information once that data is
// available in ContentViewCore. Currently internal scrolling variables aren't upstreamed.
}
/**
* @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
*/
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
event.setClassName(this.getClass().getName());
}
/**
* Enable or disable accessibility features.
*/
public void setAccessibilityState(boolean state) {
mAccessibilityInjector.setScriptEnabled(state);
}
// The following methods are implemented at native side. // The following methods are implemented at native side.
/** /**
......
...@@ -56,5 +56,6 @@ ...@@ -56,5 +56,6 @@
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="14" /> <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="14" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.WAKE_LOCK"/>
</manifest> </manifest>
...@@ -99,6 +99,22 @@ public class ContentShellActivity extends Activity { ...@@ -99,6 +99,22 @@ public class ContentShellActivity extends Activity {
} }
} }
@Override
protected void onPause() {
ContentView view = getActiveContentView();
if (view != null) view.onActivityPause();
super.onPause();
}
@Override
protected void onResume() {
super.onResume();
ContentView view = getActiveContentView();
if (view != null) view.onActivityResume();
}
private static String getUrlFromIntent(Intent intent) { private static String getUrlFromIntent(Intent intent) {
return intent != null ? intent.getDataString() : null; return intent != null ? intent.getDataString() : null;
} }
...@@ -118,6 +134,15 @@ public class ContentShellActivity extends Activity { ...@@ -118,6 +134,15 @@ public class ContentShellActivity extends Activity {
return mShellManager != null ? mShellManager.getActiveShell() : null; return mShellManager != null ? mShellManager.getActiveShell() : null;
} }
/**
* @return The {@link ContentView} owned by the currently visible {@link Shell} or null if one
* is not showing.
*/
public ContentView getActiveContentView() {
Shell shell = getActiveShell();
return shell != null ? shell.getContentView() : null;
}
private void initializeContentViewResources() { private void initializeContentViewResources() {
AppResource.DIMENSION_LINK_PREVIEW_OVERLAY_RADIUS = R.dimen.link_preview_overlay_radius; AppResource.DIMENSION_LINK_PREVIEW_OVERLAY_RADIUS = R.dimen.link_preview_overlay_radius;
AppResource.DRAWABLE_LINK_PREVIEW_POPUP_OVERLAY = R.drawable.popup_zoomer_overlay; AppResource.DRAWABLE_LINK_PREVIEW_POPUP_OVERLAY = R.drawable.popup_zoomer_overlay;
......
...@@ -171,7 +171,7 @@ public class Shell extends LinearLayout { ...@@ -171,7 +171,7 @@ public class Shell extends LinearLayout {
@SuppressWarnings("unused") @SuppressWarnings("unused")
@CalledByNative @CalledByNative
private void initFromNativeTabContents(int nativeTabContents) { private void initFromNativeTabContents(int nativeTabContents) {
mContentView = new ContentView( mContentView = ContentView.newInstance(
getContext(), nativeTabContents, ContentView.PERSONALITY_CHROME); getContext(), nativeTabContents, ContentView.PERSONALITY_CHROME);
if (mContentView.getUrl() != null) mUrlTextView.setText(mContentView.getUrl()); if (mContentView.getUrl() != null) mUrlTextView.setText(mContentView.getUrl());
((FrameLayout) findViewById(R.id.contentview_holder)).addView(mContentView, ((FrameLayout) findViewById(R.id.contentview_holder)).addView(mContentView,
......
...@@ -86,9 +86,14 @@ public class ShellManager extends FrameLayout { ...@@ -86,9 +86,14 @@ public class ShellManager extends FrameLayout {
shellView.setSurfaceView(mSurfaceView); shellView.setSurfaceView(mSurfaceView);
removeAllViews(); removeAllViews();
if (mActiveShell != null && mActiveShell.getContentView() != null) {
mActiveShell.getContentView().onHide();
}
addView(shellView, new FrameLayout.LayoutParams( addView(shellView, new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)); FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
mActiveShell = shellView; mActiveShell = shellView;
if (mActiveShell.getContentView() != null) mActiveShell.getContentView().onShow();
return shellView; return shellView;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment