removing visibleRect event and tracking rectangles instead.
diff --git a/WebCore/plugins/android/PluginViewAndroid.cpp b/WebCore/plugins/android/PluginViewAndroid.cpp
index 230a389..668c419 100644
--- a/WebCore/plugins/android/PluginViewAndroid.cpp
+++ b/WebCore/plugins/android/PluginViewAndroid.cpp
@@ -402,8 +402,7 @@
         setCallingPlugin(false);
     }
 
-    m_window->setWindow(m_npWindow.x, m_npWindow.y, width, height,
-                        m_isTransparent);
+    m_window->setWindow(&m_npWindow, m_isTransparent);
 }
 
 void PluginView::stop()
diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp
index d304e79..f9dfa61 100644
--- a/WebKit/android/jni/WebViewCore.cpp
+++ b/WebKit/android/jni/WebViewCore.cpp
@@ -897,8 +897,8 @@
                 m_scrollOffsetY);
         m_mainFrame->eventHandler()->sendScrollEvent();
 
-        // update the currently visible window
-        sendVisibleRectBounds();
+        // update the currently visible screen
+        sendPluginVisibleScreen();
     }
     gCursorBoundsMutex.lock();
     bool hasCursorBounds = m_hasCursorBounds;
@@ -974,20 +974,8 @@
         }
     }
 
-    // update the currently visible window
-    sendVisibleRectBounds();
-}
-
-void WebViewCore::sendVisibleRectBounds()
-{
-    ANPEvent event;
-    SkANP::InitEvent(&event, kVisibleRect_ANPEventType);
-    event.data.visibleRect.rect.left = m_scrollOffsetX;
-    event.data.visibleRect.rect.top = m_scrollOffsetY;
-    event.data.visibleRect.rect.right = m_scrollOffsetX + m_screenWidth;
-    event.data.visibleRect.rect.bottom = m_scrollOffsetY + m_screenHeight;
-    event.data.visibleRect.zoomScale = m_scale;
-    sendPluginEvent(event, kVisibleRect_ANPEventFlag);
+    // update the currently visible screen
+    sendPluginVisibleScreen();
 }
 
 void WebViewCore::dumpDomTree(bool useFile)
@@ -1179,6 +1167,21 @@
     }
 }
 
+void WebViewCore::sendPluginVisibleScreen()
+{
+    ANPRectI visibleRect;
+    visibleRect.left = m_scrollOffsetX;
+    visibleRect.top = m_scrollOffsetY;
+    visibleRect.right = m_scrollOffsetX + m_screenWidth;
+    visibleRect.bottom = m_scrollOffsetY + m_screenHeight;
+
+    PluginWidgetAndroid** iter = m_plugins.begin();
+    PluginWidgetAndroid** stop = m_plugins.end();
+    for (; iter < stop; ++iter) {
+        (*iter)->setVisibleScreen(visibleRect, m_scale);
+    }
+}
+
 void WebViewCore::sendPluginEvent(const ANPEvent& evt, ANPEventFlag flag)
 {
     PluginWidgetAndroid** iter = m_plugins.begin();
diff --git a/WebKit/android/jni/WebViewCore.h b/WebKit/android/jni/WebViewCore.h
index 62189bd..66ef470 100644
--- a/WebKit/android/jni/WebViewCore.h
+++ b/WebKit/android/jni/WebViewCore.h
@@ -296,6 +296,9 @@
         void invalPlugin(PluginWidgetAndroid*);
         void drawPlugins();
 
+        // send the current screen size/zoom to all of the plugins in our list
+        void sendPluginVisibleScreen();
+
         // send this event to all of the plugins in our list
         void sendPluginEvent(const ANPEvent&);
 
@@ -430,7 +433,6 @@
         SkPicture* rebuildPicture(const SkIRect& inval);
         void rebuildPictureSet(PictureSet* );
         void sendNotifyProgressFinished();
-        void sendVisibleRectBounds();
         bool handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* nodePtr);
 #if DEBUG_NAV_UI
         uint32_t m_now;
diff --git a/WebKit/android/plugins/ANPWindowInterface.cpp b/WebKit/android/plugins/ANPWindowInterface.cpp
index 7773e6e..41e00e9 100644
--- a/WebKit/android/plugins/ANPWindowInterface.cpp
+++ b/WebKit/android/plugins/ANPWindowInterface.cpp
@@ -26,9 +26,9 @@
 // must include config.h first for webkit to fiddle with new/delete
 #include "config.h"
 #include "SkANP.h"
-#include "ScrollView.h"
 #include "WebViewCore.h"
 #include "PluginView.h"
+#include "PluginWidgetAndroid.h"
 
 static bool anp_lockRect(void* window, const ANPRectI* inval,
                          ANPBitmap* bitmap) {
@@ -57,10 +57,14 @@
     return PluginView::currentPluginView();
 }
 
-static void anp_scrollTo(NPP instance, int32_t x, int32_t y) {
-    ScrollView* scrollView = pluginViewForInstance(instance)->parent();
-    android::WebViewCore* core = android::WebViewCore::getWebViewCore(scrollView);
-    core->scrollTo(x,y,true);
+static void anp_setVisibleRects(NPP instance, const ANPRectI rects[], int32_t count) {
+    PluginView* pluginView = pluginViewForInstance(instance);
+    PluginWidgetAndroid* pluginWidget = pluginView->platformPluginWidget();
+    pluginWidget->setVisibleRects(rects, count);
+}
+
+static void anp_clearVisibleRects(NPP instance) {
+    anp_setVisibleRects(instance, NULL, 0);
 }
 
 static void anp_showKeyboard(NPP instance, bool value) {
@@ -78,7 +82,8 @@
 
     ASSIGN(i, lockRect);
     ASSIGN(i, lockRegion);
-    ASSIGN(i, scrollTo);
+    ASSIGN(i, setVisibleRects);
+    ASSIGN(i, clearVisibleRects);
     ASSIGN(i, showKeyboard);
     ASSIGN(i, unlock);
 }
diff --git a/WebKit/android/plugins/PluginWidgetAndroid.cpp b/WebKit/android/plugins/PluginWidgetAndroid.cpp
index bf9b1bf..7b24e5e 100644
--- a/WebKit/android/plugins/PluginWidgetAndroid.cpp
+++ b/WebKit/android/plugins/PluginWidgetAndroid.cpp
@@ -32,6 +32,7 @@
 #include "PluginSurface.h"
 #include "PluginView.h"
 #include "PluginWidgetAndroid.h"
+#include "ScrollView.h"
 #include "SkANP.h"
 #include "SkFlipPixelRef.h"
 #include "WebViewCore.h"
@@ -42,7 +43,10 @@
     m_core = NULL;
     m_drawingModel = kBitmap_ANPDrawingModel;
     m_eventFlags = 0;
-    m_x = m_y = 0;
+    m_pluginWindow = NULL;
+    m_requestedVisibleRectCount = 0;
+    m_requestedFrameRect.setEmpty();
+    m_visibleDocRect.setEmpty();
 }
 
 PluginWidgetAndroid::~PluginWidgetAndroid() {
@@ -62,19 +66,17 @@
                          : SkBitmap::kRGB_565_Config;
 }
 
-void PluginWidgetAndroid::setWindow(int x, int y, int width, int height,
-                                    bool isTransparent) {
-    m_x = x;
-    m_y = y;
+void PluginWidgetAndroid::setWindow(NPWindow* window, bool isTransparent) {
+    m_pluginWindow = window;
 
     if (m_drawingModel == kSurface_ANPDrawingModel) {
         if (m_surface) {
-            m_surface->attach(x, y, width, height);
+            m_surface->attach(window->x, window->y, window->width, window->height);
         }
     } else {
         m_flipPixelRef->safeUnref();
         m_flipPixelRef = new SkFlipPixelRef(computeConfig(isTransparent),
-                                            width, height);
+                                            window->width, window->height);
     }
 }
 
@@ -84,7 +86,8 @@
 }
 
 void PluginWidgetAndroid::localToPageCoords(SkIRect* rect) const {
-    rect->offset(m_x, m_y);
+    if (m_pluginWindow)
+        rect->offset(m_pluginWindow->x, m_pluginWindow->y);
 }
 
 bool PluginWidgetAndroid::isDirty(SkIRect* rect) const {
@@ -143,11 +146,11 @@
                                  bitmap) &&
                     pkg->pluginFuncs()->event(instance, &event)) {
 
-                if (canvas) {
+                if (canvas && m_pluginWindow) {
                     SkBitmap bm(bitmap);
                     bm.setPixelRef(m_flipPixelRef);
-                    canvas->drawBitmap(bm, SkIntToScalar(m_x),
-                                           SkIntToScalar(m_y), NULL);
+                    canvas->drawBitmap(bm, SkIntToScalar(m_pluginWindow->x),
+                                           SkIntToScalar(m_pluginWindow->y), NULL);
                 }
             }
             break;
@@ -202,3 +205,107 @@
     surface->type = ignored;
     return surface;
 }
+
+void PluginWidgetAndroid::setVisibleScreen(const ANPRectI& visibleDocRect, float zoom) {
+
+    //TODO send an event to the plugin that communicates the zoom
+
+    int oldScreenW = m_visibleDocRect.width();
+    int oldScreenH = m_visibleDocRect.height();
+
+    m_visibleDocRect.set(visibleDocRect.left, visibleDocRect.top,
+                         visibleDocRect.right, visibleDocRect.bottom);
+
+    int newScreenW = m_visibleDocRect.width();
+    int newScreenH = m_visibleDocRect.height();
+
+    if (oldScreenW != newScreenW || oldScreenH != newScreenH)
+        computeVisibleFrameRect();
+}
+
+void PluginWidgetAndroid::setVisibleRects(const ANPRectI rects[], int32_t count) {
+
+    // ensure the count does not exceed our allocated space
+    if (count > MAX_REQUESTED_RECTS)
+        count = MAX_REQUESTED_RECTS;
+
+    // store the values in member variables
+    m_requestedVisibleRectCount = count;
+    memcpy(m_requestedVisibleRect, rects, count * sizeof(rects[0]));
+
+    computeVisibleFrameRect();
+}
+
+void PluginWidgetAndroid::computeVisibleFrameRect() {
+
+    // ensure the visibleDocRect has been set (i.e. not equal to zero)
+    if (m_visibleDocRect.isEmpty())
+        return;
+
+    // create a rect that represents the plugin's bounds
+    SkIRect pluginBounds;
+    pluginBounds.set(m_pluginWindow->x, m_pluginWindow->y,
+                     m_pluginWindow->x + m_pluginWindow->width,
+                     m_pluginWindow->y + m_pluginWindow->height);
+
+    // create a rect that will contain as many of the rects that will fit on screen
+    SkIRect visibleRect;
+    visibleRect.setEmpty();
+
+    for (int counter = 0; counter < m_requestedVisibleRectCount; counter++) {
+
+        ANPRectI* rect = &m_requestedVisibleRect[counter];
+
+        // create skia rect for easier manipulation and convert it to frame coordinates
+        SkIRect pluginRect;
+        pluginRect.set(rect->left, rect->top, rect->right, rect->bottom);
+        pluginRect.offset(m_pluginWindow->x, m_pluginWindow->y);
+
+        // ensure the rect falls within the plugin's bounds
+        if (!pluginBounds.contains(pluginRect))
+          continue;
+
+        // combine this new rect with the higher priority rects
+        pluginRect.join(visibleRect);
+
+        // check to see if the new rect fits within the screen bounds. If this
+        // is the highest priority rect then attempt to center even if it doesn't
+        // fit on the screen.
+        if (counter > 0 && (m_visibleDocRect.width() < pluginRect.width() ||
+                               m_visibleDocRect.height() < pluginRect.height()))
+          break;
+
+        // set the new visible rect
+        visibleRect = pluginRect;
+    }
+
+    m_requestedFrameRect = visibleRect;
+    scrollToVisibleFrameRect();
+}
+
+void PluginWidgetAndroid::scrollToVisibleFrameRect() {
+
+    if (m_requestedFrameRect.isEmpty() || m_visibleDocRect.isEmpty())
+        return;
+
+    // TODO if the entire rect is already visible then we don't need to scroll,
+    // this requires converting the m_requestedFrameRect from frame to doc coordinates
+
+    // find the center of the visibleRect in document coordinates
+    ScrollView* scrollView = m_pluginView->parent();
+    IntPoint pluginFramePoint = IntPoint(m_requestedFrameRect.fLeft, m_requestedFrameRect.fTop);
+    IntPoint pluginDocPoint = scrollView->convertToContainingWindow(pluginFramePoint);
+    int rectCenterX = pluginDocPoint.x() + m_requestedFrameRect.width()/2;
+    int rectCenterY = pluginDocPoint.y() + m_requestedFrameRect.height()/2;
+
+    // find document coordinates for center of the visible screen
+    int screenCenterX = m_visibleDocRect.fLeft + m_visibleDocRect.width()/2;
+    int screenCenterY = m_visibleDocRect.fTop + m_visibleDocRect.height()/2;
+
+    //compute the delta of the two points
+    int deltaX = rectCenterX - screenCenterX;
+    int deltaY = rectCenterY - screenCenterY;
+
+    android::WebViewCore* core = android::WebViewCore::getWebViewCore(scrollView);
+    core->scrollBy(deltaX, deltaY, true);
+}
diff --git a/WebKit/android/plugins/PluginWidgetAndroid.h b/WebKit/android/plugins/PluginWidgetAndroid.h
index 84ac729..1da618f 100644
--- a/WebKit/android/plugins/PluginWidgetAndroid.h
+++ b/WebKit/android/plugins/PluginWidgetAndroid.h
@@ -27,6 +27,7 @@
 #define PluginWidgetAndroid_H
 
 #include "android_npapi.h"
+#include "SkRect.h"
 
 #include <wtf/OwnPtr.h>
 
@@ -64,7 +65,8 @@
     void init(android::WebViewCore*);
     /*  Called each time the PluginView gets a new size or position.
      */
-    void setWindow(int x, int y, int width, int height, bool isTransparent);
+    void setWindow(NPWindow* window, bool isTransparent);
+
     /*  Called whenever the plugin itself requests a new drawing model. If the
         hardware does not support the requested model then false is returned,
         otherwise true is returned.
@@ -113,15 +115,45 @@
      */
     ANPSurface* createSurface(ANPSurfaceType type);
 
+    /*  Notify the plugin of the currently visible screen coordinates (document
+        space) and the current zoom level.
+     */
+    void setVisibleScreen(const ANPRectI& visibleScreenRect, float zoom);
+
+    /** Registers a set of rectangles that the plugin would like to keep on
+        screen. The rectangles are listed in order of priority with the highest
+        priority rectangle in location rects[0].  The browser will attempt to keep
+        as many of the rectangles on screen as possible and will scroll them into
+        view in response to the invocation of this method and other various events.
+        The count specifies how many rectangles are in the array. If the count is
+        zero it signals the plugin that any existing rectangles should be cleared
+        and no rectangles will be tracked.
+     */
+    void setVisibleRects(const ANPRectI rects[], int32_t count);
+
 private:
+    void computeVisibleFrameRect();
+    void scrollToVisibleFrameRect();
+
     WebCore::PluginView*    m_pluginView;
     android::WebViewCore*   m_core;
     SkFlipPixelRef*         m_flipPixelRef;
     ANPDrawingModel         m_drawingModel;
     ANPEventFlags           m_eventFlags;
-    int                     m_x;
-    int                     m_y;
+    NPWindow*               m_pluginWindow;
+    SkIRect                 m_visibleDocRect;
+    SkIRect                 m_requestedFrameRect;
     OwnPtr<android::PluginSurface> m_surface;
+
+    /* We limit the number of rectangles to minimize storage and ensure adequate
+       speed.
+    */
+    enum {
+        MAX_REQUESTED_RECTS = 5,
+    };
+
+    ANPRectI                m_requestedVisibleRect[MAX_REQUESTED_RECTS];
+    int32_t                 m_requestedVisibleRectCount;
 };
 
 #endif
diff --git a/WebKit/android/plugins/android_npapi.h b/WebKit/android/plugins/android_npapi.h
index cfea681..e50f031 100644
--- a/WebKit/android/plugins/android_npapi.h
+++ b/WebKit/android/plugins/android_npapi.h
@@ -164,7 +164,6 @@
 enum ANPEventFlag {
     kKey_ANPEventFlag           = 0x01,
     kTouch_ANPEventFlag         = 0x02,
-    kVisibleRect_ANPEventFlag   = 0x04,
 };
 typedef uint32_t ANPEventFlags;
 
@@ -615,11 +614,20 @@
         results. If lock returned false, unlock should not be called.
      */
     void    (*unlock)(void* window);
-    /** Given (x,y) coordinates in the document space the currently visible
-        window will be shifted so that window's upper left corner will be as
-        closely aligned to the coordinates as possible.
+    /** Registers a set of rectangles that the plugin would like to keep on
+        screen. The rectangles are listed in order of priority with the highest
+        priority rectangle in location rects[0].  The browser will attempt to keep
+        as many of the rectangles on screen as possible and will scroll them into
+        view in response to the invocation of this method and other various events.
+        The count specifies how many rectangles are in the array. If the count is
+        zero it signals the browser that any existing rectangles should be cleared
+        and no rectangles will be tracked.
      */
-    void    (*scrollTo)(NPP instance, int32_t x, int32_t y);
+    void (*setVisibleRects)(NPP instance, const ANPRectI rects[], int32_t count);
+    /** Clears any rectangles that are being tracked as a result of a call to
+        setVisibleRects. This call is equivalent to setVisibleRect(inst, NULL, 0).
+     */
+    void    (*clearVisibleRects)(NPP instance);
     /** Given a boolean value of true the device will be requested to provide
         a keyboard. A value of false will result in a request to hide the
         keyboard. Further, the on-screen keyboard will not be displayed if a
@@ -716,8 +724,7 @@
     kTouch_ANPEventType         = 3,
     kDraw_ANPEventType          = 4,
     kLifecycle_ANPEventType     = 5,
-    kVisibleRect_ANPEventType   = 6,
-    kSurface_ANPEventType       = 7,
+    kSurface_ANPEventType       = 6,
 };
 typedef int32_t ANPEventType;
 
@@ -815,10 +822,6 @@
             } data;
         } draw;
         struct {
-            ANPRectI    rect;       // in global document coordinates
-            float       zoomScale;  // 1.0 means no zoom scale
-        } visibleRect;
-        struct {
             ANPSurfaceAction action;
             /** This union is based on the value of action and contains data
                 specific to the given action.