diff --git a/ipc/chromium/src/base/message_loop.cc b/ipc/chromium/src/base/message_loop.cc index c19f9137ee63..38edbd594a36 100644 --- a/ipc/chromium/src/base/message_loop.cc +++ b/ipc/chromium/src/base/message_loop.cc @@ -256,14 +256,6 @@ void MessageLoop::PostNonNestableDelayedTask( PostTask_Helper(from_here, task, delay_ms, false); } -void MessageLoop::PostIdleTask( - const tracked_objects::Location& from_here, Task* task) { - DCHECK(current() == this); - task->SetBirthPlace(from_here); - PendingTask pending_task(task, false); - deferred_non_nestable_work_queue_.push(pending_task); -} - // Possibly called on a background thread! void MessageLoop::PostTask_Helper( const tracked_objects::Location& from_here, Task* task, int delay_ms, diff --git a/ipc/chromium/src/base/message_loop.h b/ipc/chromium/src/base/message_loop.h index e3de53f7bd2d..dd4a814984a1 100644 --- a/ipc/chromium/src/base/message_loop.h +++ b/ipc/chromium/src/base/message_loop.h @@ -121,10 +121,6 @@ public: void PostNonNestableDelayedTask( const tracked_objects::Location& from_here, Task* task, int delay_ms); - // PostIdleTask is not thread safe and should be called on this thread - void PostIdleTask( - const tracked_objects::Location& from_here, Task* task); - // A variant on PostTask that deletes the given object. This is useful // if the object needs to live until the next run of the MessageLoop (for // example, deleting a RenderProcessHost from within an IPC callback is not diff --git a/js/public/HashTable.h b/js/public/HashTable.h index 9e2caab51375..ae5cc21aac8f 100644 --- a/js/public/HashTable.h +++ b/js/public/HashTable.h @@ -142,23 +142,21 @@ class HashTable : private AllocPolicy protected: friend class HashTable; - Range(Entry *c, Entry *e) : cur(c), end(e), validEntry(true) { + Range(Entry *c, Entry *e) : cur(c), end(e) { while (cur < end && !cur->isLive()) ++cur; } Entry *cur, *end; - DebugOnly validEntry; public: - Range() : cur(NULL), end(NULL), validEntry(false) {} + Range() : cur(NULL), end(NULL) {} bool empty() const { return cur == end; } T &front() const { - JS_ASSERT(validEntry); JS_ASSERT(!empty()); return cur->t; } @@ -167,7 +165,6 @@ class HashTable : private AllocPolicy JS_ASSERT(!empty()); while (++cur < end && !cur->isLive()) continue; - validEntry = true; } }; @@ -208,7 +205,6 @@ class HashTable : private AllocPolicy void removeFront() { table.remove(*this->cur); removed = true; - this->validEntry = false; } /* @@ -225,7 +221,6 @@ class HashTable : private AllocPolicy table.remove(*this->cur); table.add(l, e); added = true; - this->validEntry = false; } void rekeyFront(const Key &k) { diff --git a/js/src/jsweakmap.h b/js/src/jsweakmap.h index 7680151b37b9..a4d05d29e910 100644 --- a/js/src/jsweakmap.h +++ b/js/src/jsweakmap.h @@ -187,6 +187,7 @@ class WeakMap : public HashMap, publ markedAny = true; e.rekeyFront(k); } + JS_ASSERT_IF(keyIsMarked, gc::IsMarked(&e.front().value)); } return markedAny; } diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index 9a2119d6b0a6..48a7917c7554 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -688,7 +688,7 @@ abstract public class GeckoApp int dw = tab.getThumbnailWidth(); int dh = tab.getThumbnailHeight(); - GeckoAppShell.sendEventToGecko(GeckoEvent.createScreenshotEvent(tab.getId(), 0, 0, 0, 0, 0, 0, dw, dh, dw, dh, GeckoAppShell.SCREENSHOT_THUMBNAIL, tab.getThumbnailBuffer())); + GeckoAppShell.sendEventToGecko(GeckoEvent.createScreenshotEvent(tab.getId(), 0, 0, 0, 0, 0, 0, dw, dh, GeckoAppShell.SCREENSHOT_THUMBNAIL)); } } diff --git a/mobile/android/base/GeckoAppShell.java b/mobile/android/base/GeckoAppShell.java index ed64a5c2409b..2a9a0d1ebdb4 100644 --- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -15,7 +15,6 @@ import org.mozilla.gecko.gfx.ScreenshotLayer; import org.mozilla.gecko.FloatUtils; import org.mozilla.gecko.gfx.ImmutableViewportMetrics; import org.mozilla.gecko.gfx.ViewportMetrics; -import org.mozilla.gecko.gfx.RectUtils; import java.io.*; import java.lang.reflect.*; @@ -84,7 +83,8 @@ public class GeckoAppShell public static final String SHORTCUT_TYPE_BOOKMARK = "bookmark"; static public final int SCREENSHOT_THUMBNAIL = 0; - static public final int SCREENSHOT_CHECKERBOARD = 1; + static public final int SCREENSHOT_WHOLE_PAGE = 1; + static public final int SCREENSHOT_UPDATE = 2; static public final int RESTORE_NONE = 0; static public final int RESTORE_OOM = 1; @@ -98,6 +98,11 @@ public class GeckoAppShell private static Boolean sNSSLibsLoaded = false; private static Boolean sLibsSetup = false; private static File sGREDir = null; + private static RectF sCheckerboardPageRect; + private static float sLastCheckerboardWidthRatio, sLastCheckerboardHeightRatio; + private static RepaintRunnable sRepaintRunnable = new RepaintRunnable(); + static private int sMaxTextureSize = 0; + private static Map> mEventListeners = new HashMap>(); @@ -123,6 +128,8 @@ public class GeckoAppShell private static Handler sGeckoHandler; + private static boolean sDisableScreenshot = false; + /* The Android-side API: API methods that Android calls */ // Initialization methods @@ -528,7 +535,42 @@ public class GeckoAppShell // Called by AndroidBridge using JNI public static void notifyScreenShot(final ByteBuffer data, final int tabId, final int x, final int y, final int width, final int height, final int token) { - ScreenshotHandler.notifyScreenShot(data, tabId, x, y, width, height, token); + getHandler().post(new Runnable() { + public void run() { + try { + final Tab tab = Tabs.getInstance().getTab(tabId); + if (tab == null) + return; + + if (!Tabs.getInstance().isSelectedTab(tab) && SCREENSHOT_THUMBNAIL != token) + return; + + Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); + b.copyPixelsFromBuffer(data); + switch (token) { + case SCREENSHOT_WHOLE_PAGE: + GeckoApp.mAppContext.getLayerController() + .getView().getRenderer() + .setCheckerboardBitmap(b, sCheckerboardPageRect); + break; + case SCREENSHOT_UPDATE: + GeckoApp.mAppContext.getLayerController().getView().getRenderer(). + updateCheckerboardBitmap( + b, sLastCheckerboardWidthRatio * x, + sLastCheckerboardHeightRatio * y, + sLastCheckerboardWidthRatio * width, + sLastCheckerboardHeightRatio * height, + sCheckerboardPageRect); + break; + case SCREENSHOT_THUMBNAIL: + GeckoApp.mAppContext.processThumbnail(tab, b, null); + break; + } + } finally { + freeDirectBuffer(data); + } + } + }); } private static CountDownLatch sGeckoPendingAcks = null; @@ -2094,26 +2136,6 @@ public class GeckoAppShell if (!GeckoApp.mAppContext.showFilePicker(aMimeType, new AsyncResultHandler(id))) GeckoAppShell.notifyFilePickerResult("", id); } - public static void screenshotWholePage(Tab tab) { - ScreenshotHandler.screenshotWholePage(tab); - } - - // Called by AndroidBridge using JNI - public static void notifyPaintedRect(float top, float left, float bottom, float right) { - ScreenshotHandler.notifyPaintedRect(top, left, bottom, right); - } -} - -class ScreenshotHandler { - private static Queue sPendingScreenshots = new ArrayDeque(); - private static RectF sCheckerboardPageRect; - private static float sLastCheckerboardWidthRatio, sLastCheckerboardHeightRatio; - private static RepaintRunnable sRepaintRunnable = new RepaintRunnable(); - private static int sMaxTextureSize = 0; - private static final String LOGTAG = "GeckoScreenshot"; - private static boolean sDisableScreenshot = false; - private static ByteBuffer sWholePageScreenshotBuffer; - private static int sCheckerboardBufferWidth, sCheckerboardBufferHeight; static class RepaintRunnable implements Runnable { private boolean mIsRepaintRunnablePosted = false; @@ -2136,40 +2158,25 @@ class ScreenshotHandler { mIsRepaintRunnablePosted = false; } - Tab tab = Tabs.getInstance().getSelectedTab(); - ImmutableViewportMetrics viewport = GeckoApp.mAppContext.getLayerController().getViewportMetrics(); - - if (RectUtils.fuzzyEquals(sCheckerboardPageRect, viewport.getCssPageRect())) { - float width = right - left; - float height = bottom - top; - scheduleCheckerboardScreenshotEvent(tab.getId(), - (int)left, (int)top, (int)width, (int)height, - (int)(sLastCheckerboardWidthRatio * left), - (int)(sLastCheckerboardHeightRatio * top), - (int)(sLastCheckerboardWidthRatio * width), - (int)(sLastCheckerboardHeightRatio * height), - sCheckerboardBufferWidth, sCheckerboardBufferHeight); - } else { - GeckoAppShell.screenshotWholePage(tab); - } + GeckoAppShell.screenshotWholePage(tab); } void addRectToRepaint(float top, float left, float bottom, float right) { synchronized(this) { - ImmutableViewportMetrics viewport = GeckoApp.mAppContext.getLayerController().getViewportMetrics(); - mDirtyTop = Math.max(sCheckerboardPageRect.top, Math.min(top, mDirtyTop)); - mDirtyLeft = Math.max(sCheckerboardPageRect.left, Math.min(left, mDirtyLeft)); - mDirtyBottom = Math.min(sCheckerboardPageRect.bottom, Math.max(bottom, mDirtyBottom)); - mDirtyRight = Math.min(sCheckerboardPageRect.right, Math.max(right, mDirtyRight)); + mDirtyTop = Math.min(top, mDirtyTop); + mDirtyLeft = Math.min(left, mDirtyLeft); + mDirtyBottom = Math.max(bottom, mDirtyBottom); + mDirtyRight = Math.max(right, mDirtyRight); if (!mIsRepaintRunnablePosted) { - GeckoAppShell.getHandler().postDelayed(this, 5000); + getHandler().postDelayed(this, 5000); mIsRepaintRunnablePosted = true; } } } } + // Called by AndroidBridge using JNI public static void notifyPaintedRect(float top, float left, float bottom, float right) { sRepaintRunnable.addRectToRepaint(top, left, bottom, right); } @@ -2196,9 +2203,7 @@ class ScreenshotHandler { sMaxTextureSize = maxTextureSize[0]; if (sMaxTextureSize == 0) return; - sWholePageScreenshotBuffer = GeckoAppShell.allocateDirectBuffer(ScreenshotLayer.getMaxNumPixels() * 2 /* 16 bpp */); } - ImmutableViewportMetrics viewport = GeckoApp.mAppContext.getLayerController().getViewportMetrics(); Log.i(LOGTAG, "Taking whole-screen screenshot, viewport: " + viewport); // source width and height to screenshot @@ -2219,96 +2224,14 @@ class ScreenshotHandler { int dy = 0; int dw = clamp(minTextureSize, idealDstWidth, sMaxTextureSize); int dh = maxPixels / dw; - sCheckerboardBufferWidth = dw; - sCheckerboardBufferHeight = dh; sLastCheckerboardWidthRatio = dw / sw; sLastCheckerboardHeightRatio = dh / sh; sCheckerboardPageRect = viewport.getCssPageRect(); - scheduleCheckerboardScreenshotEvent(tab.getId(), (int)sx, (int)sy, (int)sw, (int)sh, dx, dy, dw, dh, dw, dh); - } - static void scheduleCheckerboardScreenshotEvent(int tabId, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int bw, int bh) { - float totalSize = sw * sh; - int numSlices = (int) Math.ceil(totalSize / 100000); - int srcSliceSize = (int) Math.ceil(sh / numSlices); - int dstSliceSize = (int) Math.ceil(dh / numSlices); - for (int i = 0; i < numSlices; i++) { - GeckoEvent event = - GeckoEvent.createScreenshotEvent(tabId, - sx, sy + srcSliceSize * i, sw, srcSliceSize, - dx, dy + dstSliceSize * i, dw, dstSliceSize, bw, bh, - GeckoAppShell.SCREENSHOT_CHECKERBOARD, - sWholePageScreenshotBuffer); - synchronized(sPendingScreenshots) { - sPendingScreenshots.add(new PendingScreenshot(tabId, event)); - if (sPendingScreenshots.size() == 1) - sendNextEventToGecko(); - } - } - } - - static void sendNextEventToGecko() { - synchronized(sPendingScreenshots) { - if (sPendingScreenshots.isEmpty()) - return; - GeckoAppShell.sendEventToGecko(sPendingScreenshots.element().getEvent()); - } - } - - static class PendingScreenshot { - private final GeckoEvent mEvent; - private final int mTabId; - - PendingScreenshot(int tabId, GeckoEvent event) { - mTabId = tabId; - mEvent = event; - } - - GeckoEvent getEvent() { - return mEvent; - } - - } - - public static void notifyScreenShot(final ByteBuffer data, final int tabId, final int x, final int y, - final int width, final int height, final int token) { - - GeckoAppShell.getHandler().post(new Runnable() { - public void run() { - final Tab tab = Tabs.getInstance().getTab(tabId); - if (tab == null) { - if (token == GeckoAppShell.SCREENSHOT_CHECKERBOARD) { - synchronized(sPendingScreenshots) { - sPendingScreenshots.remove(); - sendNextEventToGecko(); - } - } - return; - } - switch (token) { - case GeckoAppShell.SCREENSHOT_CHECKERBOARD: - { - GeckoApp.mAppContext.getLayerController() - .getView().getRenderer() - .setCheckerboardBitmap(data, width, height, sCheckerboardPageRect); - synchronized(sPendingScreenshots) { - sPendingScreenshots.remove(); - sendNextEventToGecko(); - } - break; - } - case GeckoAppShell.SCREENSHOT_THUMBNAIL: - { - if (Tabs.getInstance().isSelectedTab(tab)) { - Bitmap b = tab.getThumbnailBitmap(); - b.copyPixelsFromBuffer(data); - GeckoApp.mAppContext.processThumbnail(tab, b, null); - } - break; - } - } - } - }); + GeckoAppShell.sendEventToGecko(GeckoEvent.createScreenshotEvent(tab.getId(), + (int)FloatMath.ceil(sx), (int)FloatMath.ceil(sy), + (int)FloatMath.floor(sw), (int)FloatMath.floor(sh), + dx, dy, dw, dh, GeckoAppShell.SCREENSHOT_WHOLE_PAGE)); } } diff --git a/mobile/android/base/GeckoEvent.java b/mobile/android/base/GeckoEvent.java index 1b01bd7fcd01..f9682507715c 100644 --- a/mobile/android/base/GeckoEvent.java +++ b/mobile/android/base/GeckoEvent.java @@ -23,7 +23,6 @@ import android.text.format.Time; import android.os.SystemClock; import java.lang.Math; import java.lang.System; -import java.nio.ByteBuffer; import android.util.Log; @@ -117,8 +116,6 @@ public class GeckoEvent { public short mScreenOrientation; - public ByteBuffer mBuffer; - private GeckoEvent(int evType) { mType = evType; } @@ -459,17 +456,15 @@ public class GeckoEvent { return event; } - public static GeckoEvent createScreenshotEvent(int tabId, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int bw, int bh, int token, ByteBuffer buffer) { + public static GeckoEvent createScreenshotEvent(int tabId, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int token) { GeckoEvent event = new GeckoEvent(SCREENSHOT); - event.mPoints = new Point[5]; + event.mPoints = new Point[4]; event.mPoints[0] = new Point(sx, sy); event.mPoints[1] = new Point(sw, sh); event.mPoints[2] = new Point(dx, dy); event.mPoints[3] = new Point(dw, dh); - event.mPoints[4] = new Point(bw, bh); event.mMetaState = tabId; event.mFlags = token; - event.mBuffer = buffer; return event; } diff --git a/mobile/android/base/Tab.java b/mobile/android/base/Tab.java index 2812984fffb1..eae1f70a04a2 100644 --- a/mobile/android/base/Tab.java +++ b/mobile/android/base/Tab.java @@ -21,7 +21,6 @@ import org.json.JSONObject; import org.mozilla.gecko.db.BrowserDB; import org.mozilla.gecko.gfx.Layer; -import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -65,8 +64,6 @@ public final class Tab { private ContentObserver mContentObserver; private int mCheckerboardColor = Color.WHITE; private int mState; - private ByteBuffer mThumbnailBuffer; - private Bitmap mThumbnailBitmap; public static final int STATE_DELAYED = 0; public static final int STATE_LOADING = 1; @@ -141,31 +138,6 @@ public final class Tab { return mThumbnail; } - synchronized public ByteBuffer getThumbnailBuffer() { - int capacity = getThumbnailWidth() * getThumbnailHeight() * 2 /* 16 bpp */; - if (mThumbnailBuffer != null && mThumbnailBuffer.capacity() == capacity) - return mThumbnailBuffer; - if (mThumbnailBuffer != null) - GeckoAppShell.freeDirectBuffer(mThumbnailBuffer); // not calling freeBuffer() because it would deadlock - return mThumbnailBuffer = GeckoAppShell.allocateDirectBuffer(capacity); - } - - public Bitmap getThumbnailBitmap() { - if (mThumbnailBitmap != null) - return mThumbnailBitmap; - return mThumbnailBitmap = Bitmap.createBitmap(getThumbnailWidth(), getThumbnailHeight(), Bitmap.Config.RGB_565); - } - - public void finalize() { - freeBuffer(); - } - - synchronized void freeBuffer() { - if (mThumbnailBuffer != null) - GeckoAppShell.freeDirectBuffer(mThumbnailBuffer); - mThumbnailBuffer = null; - } - float getDensity() { if (sDensity == 0.0f) { sDensity = GeckoApp.mAppContext.getDisplayMetrics().density; @@ -187,10 +159,13 @@ public final class Tab { public void run() { if (b != null) { try { - if (mState == Tab.STATE_SUCCESS) - saveThumbnailToDB(new BitmapDrawable(b)); + Bitmap bitmap = Bitmap.createScaledBitmap(b, getThumbnailWidth(), getThumbnailHeight(), false); - mThumbnail = new BitmapDrawable(b); + if (mState == Tab.STATE_SUCCESS) + saveThumbnailToDB(new BitmapDrawable(bitmap)); + + mThumbnail = new BitmapDrawable(bitmap); + b.recycle(); } catch (OutOfMemoryError oom) { Log.e(LOGTAG, "Unable to create/scale bitmap", oom); mThumbnail = null; diff --git a/mobile/android/base/Tabs.java b/mobile/android/base/Tabs.java index e8123d513320..c688a76d7be9 100644 --- a/mobile/android/base/Tabs.java +++ b/mobile/android/base/Tabs.java @@ -76,10 +76,8 @@ public class Tabs implements GeckoEventListener { public void removeTab(int id) { if (tabs.containsKey(id)) { - Tab tab = getTab(id); - order.remove(tab); + order.remove(getTab(id)); tabs.remove(id); - tab.freeBuffer(); Log.i(LOGTAG, "Removed a tab with id: " + id); } } diff --git a/mobile/android/base/gfx/IntSize.java b/mobile/android/base/gfx/IntSize.java index dfc594885330..8560ca23e915 100644 --- a/mobile/android/base/gfx/IntSize.java +++ b/mobile/android/base/gfx/IntSize.java @@ -71,11 +71,5 @@ public class IntSize { public IntSize nextPowerOfTwo() { return new IntSize(nextPowerOfTwo(width), nextPowerOfTwo(height)); } - - public static boolean isPowerOfTwo(int value) { - if (value == 0) - return false; - return (value & (value - 1)) == 0; - } } diff --git a/mobile/android/base/gfx/LayerRenderer.java b/mobile/android/base/gfx/LayerRenderer.java index 4ba17da27dc1..fccda1843d23 100644 --- a/mobile/android/base/gfx/LayerRenderer.java +++ b/mobile/android/base/gfx/LayerRenderer.java @@ -134,8 +134,8 @@ public class LayerRenderer implements GLSurfaceView.Renderer { " gl_FragColor = texture2D(sTexture, vTexCoord);\n" + "}\n"; - public void setCheckerboardBitmap(ByteBuffer data, int width, int height, RectF pageRect) { - mCheckerboardLayer.setBitmap(data, width, height); + public void setCheckerboardBitmap(Bitmap bitmap, RectF pageRect) { + mCheckerboardLayer.setBitmap(bitmap); mCheckerboardLayer.beginTransaction(); try { mCheckerboardLayer.setPosition(RectUtils.round(pageRect)); diff --git a/mobile/android/base/gfx/ScreenshotLayer.java b/mobile/android/base/gfx/ScreenshotLayer.java index 1a3ed9fc7b68..355cea785607 100644 --- a/mobile/android/base/gfx/ScreenshotLayer.java +++ b/mobile/android/base/gfx/ScreenshotLayer.java @@ -35,7 +35,6 @@ public class ScreenshotLayer extends SingleTileLayer { private IntSize mImageSize; // Whether we have an up-to-date image to draw private boolean mHasImage; - private static String LOGTAG = "GeckoScreenshot"; public static int getMaxNumPixels() { return SCREENSHOT_SIZE_LIMIT; @@ -45,19 +44,6 @@ public class ScreenshotLayer extends SingleTileLayer { mHasImage = false; } - void setBitmap(ByteBuffer data, int width, int height) { - mImageSize = new IntSize(width, height); - if (IntSize.isPowerOfTwo(width) && IntSize.isPowerOfTwo(height)) { - mBufferSize = mImageSize; - mHasImage = true; - mImage.setBitmap(data, width, height, CairoImage.FORMAT_RGB16_565); - } else { - Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); - b.copyPixelsFromBuffer(data); - setBitmap(b); - } - } - void setBitmap(Bitmap bitmap) { mImageSize = new IntSize(bitmap.getWidth(), bitmap.getHeight()); int width = IntSize.nextPowerOfTwo(bitmap.getWidth()); @@ -130,17 +116,7 @@ public class ScreenshotLayer extends SingleTileLayer { } } - void copyBuffer(ByteBuffer src, ByteBuffer dst, int size) { - dst.asIntBuffer().put(src.asIntBuffer()); - } - - synchronized void setBitmap(ByteBuffer data, int width, int height, int format) { - mSize = new IntSize(width, height); - mFormat = format; - copyBuffer(data, mBuffer, width * height * 2); - } - - synchronized void setBitmap(Bitmap bitmap, int width, int height, int format) { + void setBitmap(Bitmap bitmap, int width, int height, int format) { Bitmap tmp; mSize = new IntSize(width, height); mFormat = format; @@ -162,10 +138,10 @@ public class ScreenshotLayer extends SingleTileLayer { } @Override - synchronized public ByteBuffer getBuffer() { return mBuffer; } + public ByteBuffer getBuffer() { return mBuffer; } @Override - synchronized public IntSize getSize() { return mSize; } + public IntSize getSize() { return mSize; } @Override - synchronized public int getFormat() { return mFormat; } + public int getFormat() { return mFormat; } } } diff --git a/widget/android/AndroidBridge.cpp b/widget/android/AndroidBridge.cpp index d13a14d5da88..fa875d105816 100644 --- a/widget/android/AndroidBridge.cpp +++ b/widget/android/AndroidBridge.cpp @@ -29,8 +29,6 @@ #include "nsIDocShell.h" #include "nsPIDOMWindow.h" #include "mozilla/dom/ScreenOrientation.h" -#include "nsIDOMWindowUtils.h" -#include "nsIDOMClientRect.h" #ifdef DEBUG #define ALOG_BRIDGE(args...) ALOG(args) @@ -2350,33 +2348,36 @@ jobject JNICALL Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer(JNIEnv *env, jclass, jlong size); -nsresult AndroidBridge::TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt32 srcY, PRInt32 srcW, PRInt32 srcH, PRInt32 dstX, PRInt32 dstY, PRInt32 dstW, PRInt32 dstH, PRInt32 bufW, PRInt32 bufH, PRInt32 tabId, PRInt32 token, jobject buffer) +nsresult AndroidBridge::TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt32 srcY, PRInt32 srcW, PRInt32 srcH, PRInt32 dstW, PRInt32 dstH, PRInt32 tabId, float scale, PRInt32 token) { nsresult rv; - float scale = 1.0; - - if (!buffer) - return NS_OK; // take a screenshot, as wide as possible, proportional to the destination size if (!srcW && !srcH) { - nsCOMPtr utils = do_GetInterface(window); - if (!utils) - return NS_ERROR_FAILURE; - - nsCOMPtr rect; - rv = utils->GetRootBounds(getter_AddRefs(rect)); + nsCOMPtr doc; + rv = window->GetDocument(getter_AddRefs(doc)); NS_ENSURE_SUCCESS(rv, rv); - if (!rect) + if (!doc) return NS_ERROR_FAILURE; - float left, top, width, height; - rect->GetLeft(&left); - rect->GetTop(&top); - rect->GetWidth(&width); - rect->GetHeight(&height); + nsCOMPtr docElement; + rv = doc->GetDocumentElement(getter_AddRefs(docElement)); + NS_ENSURE_SUCCESS(rv, rv); + if (!docElement) + return NS_ERROR_FAILURE; - if (width == 0 || height == 0) + PRInt32 viewportHeight; + PRInt32 pageWidth; + PRInt32 pageHeight; + window->GetInnerHeight(&viewportHeight); + docElement->GetScrollWidth(&pageWidth); + docElement->GetScrollHeight(&pageHeight); + + // use the page or viewport dimensions, whichever is larger + PRInt32 width = pageWidth; + PRInt32 height = viewportHeight > pageHeight ? viewportHeight : pageHeight; + + if (!width || !height) return NS_ERROR_FAILURE; float aspectRatio = ((float) dstW) / dstH; @@ -2387,9 +2388,6 @@ nsresult AndroidBridge::TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt srcW = height * aspectRatio; srcH = height; } - - srcX = left; - srcY = top; } JNIEnv* env = GetJNIEnv(); @@ -2417,17 +2415,21 @@ nsresult AndroidBridge::TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt nsPresContext::CSSPixelsToAppUnits(srcW / scale), nsPresContext::CSSPixelsToAppUnits(srcH / scale)); - PRUint32 stride = bufW * 2 /* 16 bpp */; + PRUint32 stride = dstW * 2; + PRUint32 bufferSize = dstH * stride; + + jobject buffer = Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer(env, NULL, bufferSize); + if (!buffer) + return NS_OK; void* data = env->GetDirectBufferAddress(buffer); - nsRefPtr surf = new gfxImageSurface(static_cast(data), nsIntSize(bufW, bufH), stride, gfxASurface::ImageFormatRGB16_565); + memset(data, 0, bufferSize); + nsRefPtr surf = new gfxImageSurface(static_cast(data), nsIntSize(dstW, dstH), stride, gfxASurface::ImageFormatRGB16_565); nsRefPtr context = new gfxContext(surf); - gfxPoint pt(dstX, dstY); - context->Translate(pt); context->Scale(scale * dstW / srcW, scale * dstH / srcH); rv = presShell->RenderDocument(r, renderDocFlags, bgColor, context); NS_ENSURE_SUCCESS(rv, rv); - env->CallStaticVoidMethod(AndroidBridge::Bridge()->mGeckoAppShellClass, AndroidBridge::Bridge()->jNotifyScreenShot, buffer, tabId, srcX * dstW / srcW , srcY * dstH / srcH, bufW, bufH, token); + env->CallStaticVoidMethod(AndroidBridge::Bridge()->mGeckoAppShellClass, AndroidBridge::Bridge()->jNotifyScreenShot, buffer, tabId, srcX * dstW / srcW , srcY * dstH / srcH, dstW, dstH, token); return NS_OK; } diff --git a/widget/android/AndroidBridge.h b/widget/android/AndroidBridge.h index 6917cb7300a0..5f3f383bfb02 100644 --- a/widget/android/AndroidBridge.h +++ b/widget/android/AndroidBridge.h @@ -155,7 +155,7 @@ public: SCREENSHOT_UPDATE = 2 }; - nsresult TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt32 srcY, PRInt32 srcW, PRInt32 srcH, PRInt32 dstY, PRInt32 dstX, PRInt32 dstW, PRInt32 dstH, PRInt32 bufW, PRInt32 bufH, PRInt32 tabId, PRInt32 token, jobject buffer); + nsresult TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt32 srcY, PRInt32 srcW, PRInt32 srcH, PRInt32 dstW, PRInt32 dstH, PRInt32 tabId, float scale, PRInt32 token); static void NotifyPaintedRect(float top, float left, float bottom, float right); diff --git a/widget/android/AndroidJavaWrappers.cpp b/widget/android/AndroidJavaWrappers.cpp index 698de5f41272..923352676201 100644 --- a/widget/android/AndroidJavaWrappers.cpp +++ b/widget/android/AndroidJavaWrappers.cpp @@ -42,7 +42,6 @@ jfieldID AndroidGeckoEvent::jLocationField = 0; jfieldID AndroidGeckoEvent::jBandwidthField = 0; jfieldID AndroidGeckoEvent::jCanBeMeteredField = 0; jfieldID AndroidGeckoEvent::jScreenOrientationField = 0; -jfieldID AndroidGeckoEvent::jByteBufferField = 0; jclass AndroidPoint::jPointClass = 0; jfieldID AndroidPoint::jXField = 0; @@ -104,12 +103,6 @@ jmethodID AndroidGeckoSurfaceView::jGetHolderMethod = 0; #define getMethod(fname, ftype) \ ((jmethodID) jEnv->GetMethodID(jClass, fname, ftype)) -RefCountedJavaObject::~RefCountedJavaObject() { - if (mObject) - GetJNIForThread()->DeleteGlobalRef(mObject); - mObject = NULL; -} - void mozilla::InitAndroidJavaWrappers(JNIEnv *jEnv) { @@ -161,7 +154,6 @@ AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv) jBandwidthField = getField("mBandwidth", "D"); jCanBeMeteredField = getField("mCanBeMetered", "Z"); jScreenOrientationField = getField("mScreenOrientation", "S"); - jByteBufferField = getField("mBuffer", "Ljava/nio/ByteBuffer;"); } void @@ -506,8 +498,7 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj) case SCREENSHOT: { mMetaState = jenv->GetIntField(jobj, jMetaStateField); mFlags = jenv->GetIntField(jobj, jFlagsField); - ReadPointArray(mPoints, jenv, jPoints, 5); - mByteBuffer = new RefCountedJavaObject(jenv, jenv->GetObjectField(jobj, jByteBufferField)); + ReadPointArray(mPoints, jenv, jPoints, 4); break; } diff --git a/widget/android/AndroidJavaWrappers.h b/widget/android/AndroidJavaWrappers.h index 9efa1049e315..a152adad420f 100644 --- a/widget/android/AndroidJavaWrappers.h +++ b/widget/android/AndroidJavaWrappers.h @@ -41,27 +41,6 @@ void InitAndroidJavaWrappers(JNIEnv *jEnv); * handle it. */ -class RefCountedJavaObject { -public: - RefCountedJavaObject(JNIEnv* env, jobject obj) : mObject(env->NewGlobalRef(obj)) {} - - ~RefCountedJavaObject(); - - PRInt32 AddRef() { return ++mRefCnt; } - - PRInt32 Release() { - PRInt32 refcnt = --mRefCnt; - if (refcnt == 0) - delete this; - return refcnt; - } - - jobject GetObject() { return mObject; } -private: - PRInt32 mRefCnt; - jobject mObject; -}; - class WrappedJavaObject { public: WrappedJavaObject() : @@ -597,7 +576,6 @@ public: double Bandwidth() { return mBandwidth; } bool CanBeMetered() { return mCanBeMetered; } short ScreenOrientation() { return mScreenOrientation; } - RefCountedJavaObject* ByteBuffer() { return mByteBuffer; } protected: int mAction; @@ -622,7 +600,6 @@ protected: double mBandwidth; bool mCanBeMetered; short mScreenOrientation; - nsRefPtr mByteBuffer; void ReadIntArray(nsTArray &aVals, JNIEnv *jenv, @@ -676,7 +653,6 @@ protected: static jfieldID jCanBeMeteredField; static jfieldID jScreenOrientationField; - static jfieldID jByteBufferField; public: enum { diff --git a/widget/android/nsAppShell.cpp b/widget/android/nsAppShell.cpp index ef7a5f5cff4e..8c9f82210108 100644 --- a/widget/android/nsAppShell.cpp +++ b/widget/android/nsAppShell.cpp @@ -6,8 +6,6 @@ // Make sure the order of included headers #include "base/basictypes.h" #include "nspr/prtypes.h" -#include "base/message_loop.h" -#include "base/task.h" #include "mozilla/Hal.h" #include "nsAppShell.h" @@ -65,34 +63,6 @@ nsAppShell *nsAppShell::gAppShell = nsnull; NS_IMPL_ISUPPORTS_INHERITED1(nsAppShell, nsBaseAppShell, nsIObserver) -class ScreenshotRunnable : public nsRunnable { -public: - ScreenshotRunnable(nsIAndroidBrowserApp* aBrowserApp, int aTabId, nsTArray& aPoints, int aToken, RefCountedJavaObject* aBuffer): - mBrowserApp(aBrowserApp), mTabId(aTabId), mPoints(aPoints), mToken(aToken), mBuffer(aBuffer) {} - - virtual nsresult Run() { - nsCOMPtr domWindow; - nsCOMPtr tab; - mBrowserApp->GetBrowserTab(mTabId, getter_AddRefs(tab)); - if (!tab) - return NS_OK; - - tab->GetWindow(getter_AddRefs(domWindow)); - if (!domWindow) - return NS_OK; - - NS_ASSERTION(mPoints.Length() == 5, "Screenshot event does not have enough coordinates"); - - AndroidBridge::Bridge()->TakeScreenshot(domWindow, mPoints[0].x, mPoints[0].y, mPoints[1].x, mPoints[1].y, mPoints[2].x, mPoints[2].y, mPoints[3].x, mPoints[3].y, mPoints[4].x, mPoints[4].y, mTabId, mToken, mBuffer->GetObject()); - return NS_OK; - } -private: - nsCOMPtr mBrowserApp; - nsTArray mPoints; - int mTabId, mToken; - nsRefPtr mBuffer; -}; - class AfterPaintListener : public nsIDOMEventListener { public: NS_DECL_ISUPPORTS @@ -119,15 +89,23 @@ class AfterPaintListener : public nsIDOMEventListener { if (!paintEvent) return NS_OK; - nsCOMPtr rect; - paintEvent->GetBoundingClientRect(getter_AddRefs(rect)); - float top, left, bottom, right; - rect->GetTop(&top); - rect->GetLeft(&left); - rect->GetRight(&right); - rect->GetBottom(&bottom); - __android_log_print(ANDROID_LOG_INFO, "GeckoScreenshot", "rect: %f, %f, %f, %f", top, left, right, bottom); - AndroidBridge::NotifyPaintedRect(top, left, bottom, right); + nsCOMPtr rects; + paintEvent->GetClientRects(getter_AddRefs(rects)); + if (!rects) + return NS_OK; + PRUint32 length; + rects->GetLength(&length); + for (PRUint32 i = 0; i < length; ++i) { + float top, left, bottom, right; + nsCOMPtr rect = rects->GetItemAt(i); + if (!rect) + continue; + rect->GetTop(&top); + rect->GetLeft(&left); + rect->GetRight(&right); + rect->GetBottom(&bottom); + AndroidBridge::NotifyPaintedRect(top, left, bottom, right); + } return NS_OK; } @@ -447,13 +425,21 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait) break; PRInt32 token = curEvent->Flags(); - PRInt32 tabId = curEvent->MetaState(); + + nsCOMPtr domWindow; + nsCOMPtr tab; + mBrowserApp->GetBrowserTab(curEvent->MetaState(), getter_AddRefs(tab)); + if (!tab) + break; + + tab->GetWindow(getter_AddRefs(domWindow)); + if (!domWindow) + break; + + float scale = 1.0; nsTArray points = curEvent->Points(); - RefCountedJavaObject* buffer = curEvent->ByteBuffer(); - nsCOMPtr sr = - new ScreenshotRunnable(mBrowserApp, tabId, points, token, buffer); - MessageLoop::current()->PostIdleTask( - FROM_HERE, NewRunnableMethod(sr.get(), &ScreenshotRunnable::Run)); + NS_ASSERTION(points.Length() == 4, "Screenshot event does not have enough coordinates"); + bridge->TakeScreenshot(domWindow, points[0].x, points[0].y, points[1].x, points[1].y, points[3].x, points[3].y, curEvent->MetaState(), scale, curEvent->Flags()); break; }