10f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
20f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
30f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// found in the LICENSE file.
40f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
50f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)package org.chromium.android_webview;
60f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
70f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)import android.os.Handler;
80f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)import android.os.Message;
90f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)import android.view.View;
100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)import android.view.accessibility.AccessibilityEvent;
110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)/**
130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) * Helper used to post the VIEW_SCROLLED accessibility event.
140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) *
150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) * TODO(mkosiba): Investigate whether this is behavior we want to share with the chrome/ layer.
160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) * TODO(mkosiba): We currently don't handle JS-initiated scrolling for layers other than the root
170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) * layer.
180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) */
190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)class ScrollAccessibilityHelper {
200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    // This is copied straight out of android.view.ViewConfiguration.
210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    private static final long SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS = 100;
220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    private class HandlerCallback implements Handler.Callback {
240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        public static final int MSG_VIEW_SCROLLED = 1;
250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        private View mEventSender;
270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        public HandlerCallback(View eventSender) {
290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)            mEventSender = eventSender;
300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        }
310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        @Override
330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        public boolean handleMessage(Message msg) {
340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)            switch(msg.what) {
350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                case MSG_VIEW_SCROLLED:
360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                    mMsgViewScrolledQueued = false;
370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                    mEventSender.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                    break;
390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                default:
400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                    throw new IllegalStateException(
410f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                            "AccessibilityInjector: unhandled message: " + msg.what);
420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)            }
430f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)            return true;
440f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        }
450f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    }
460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
470f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    private Handler mHandler;
480f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    private boolean mMsgViewScrolledQueued;
490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
500f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    public ScrollAccessibilityHelper(View eventSender) {
510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        mHandler = new Handler(new HandlerCallback(eventSender));
520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    }
530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    /**
550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)     * This event is sent at most once every
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)     * {@link android.view.ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)     */
590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    public void postViewScrolledAccessibilityEventCallback() {
600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        if (mMsgViewScrolledQueued)
610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)            return;
620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        mMsgViewScrolledQueued = true;
630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        Message msg = mHandler.obtainMessage(HandlerCallback.MSG_VIEW_SCROLLED);
650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        mHandler.sendMessageDelayed(msg, SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS);
660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    }
670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    public void removePostedViewScrolledAccessibilityEventCallback() {
690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        if (!mMsgViewScrolledQueued)
700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)            return;
710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        mMsgViewScrolledQueued = false;
720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
730f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        mHandler.removeMessages(HandlerCallback.MSG_VIEW_SCROLLED);
740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    }
750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    public void removePostedCallbacks() {
770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        removePostedViewScrolledAccessibilityEventCallback();
780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    }
790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
80