Merging mozilla-central with mozilla-inbound.

This commit is contained in:
Mounir Lamouri 2011-06-17 15:29:14 +02:00
commit 12c71e7bf0
28 changed files with 827 additions and 130 deletions

View File

@ -74,11 +74,11 @@ let AllTabs = {
*/
register: function register(eventName, callback) {
// Either add additional callbacks or create the first entry
let listeners = eventListeners[eventName];
let listeners = eventListeners[events[eventName]];
if (listeners)
listeners.push(callback);
else
eventListeners[eventName] = [callback];
eventListeners[events[eventName]] = [callback];
},
/**
@ -93,7 +93,7 @@ let AllTabs = {
*/
unregister: function unregister(eventName, callback) {
// Nothing to remove for this event
let listeners = eventListeners[eventName];
let listeners = eventListeners[events[eventName]];
if (!listeners)
return;
@ -114,31 +114,50 @@ __defineGetter__("browserWindows", function browserWindows() {
return browserWindows;
});
let events = ["attrModified", "close", "move", "open", "select", "pinned", "unpinned"];
let events = {
attrModified: "TabAttrModified",
close: "TabClose",
move: "TabMove",
open: "TabOpen",
select: "TabSelect",
pinned: "TabPinned",
unpinned: "TabUnpinned"
};
let eventListeners = {};
function registerBrowserWindow(browserWindow) {
events.forEach(function(eventName) {
let tabEvent = "Tab" + eventName[0].toUpperCase() + eventName.slice(1);
browserWindow.addEventListener(tabEvent, function(event) {
// Make sure we've gotten listeners before trying to call
let listeners = eventListeners[eventName];
if (!listeners)
return;
for each (let event in events)
browserWindow.addEventListener(event, tabEventListener, true);
let tab = event.target;
browserWindow.addEventListener("unload", unregisterBrowserWindow, false);
}
// Make a copy of the listeners, so it can't change as we call back
listeners.slice().forEach(function(callback) {
try {
callback(tab, event);
}
// Don't let failing callbacks stop us but report the failure
catch(ex) {
Cu.reportError(ex);
}
});
}, true);
function unregisterBrowserWindow(unloadEvent) {
let browserWindow = unloadEvent.currentTarget;
for each (let event in events)
browserWindow.removeEventListener(event, tabEventListener, true);
browserWindow.removeEventListener("unload", unregisterBrowserWindow, false);
}
function tabEventListener(event) {
// Make sure we've gotten listeners before trying to call
let listeners = eventListeners[event.type];
if (!listeners)
return;
let tab = event.target;
// Make a copy of the listeners, so it can't change as we call back
listeners.slice().forEach(function (callback) {
try {
callback(tab, event);
}
// Don't let failing callbacks stop us but report the failure
catch (ex) {
Cu.reportError(ex);
}
});
}

View File

@ -95,6 +95,13 @@ defaults/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/
defaults/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/install.rdf
defaults/profile/search.rdf
#ifndef SHIP_FEEDBACK
# In the average case, this directory is only used by Test Pilot, and will get
# removed by the updater. In some cases (eg, partner builds), distribution/
# will have other files and/or directories in it. In these cases, the updater
# will print a non-fatal error and continue on, because we're not appending
# '*' to force a recursive removal.
distribution/
distribution/extensions/
distribution/extensions/testpilot@labs.mozilla.com.xpi
#endif
extensions/talkback@mozilla.org/
@ -267,7 +274,6 @@ res/ua.css
res/unixcharset.properties
res/viewsource.css
res/wincharset.properties
searchplugins/
searchplugins/DRAE.gif
searchplugins/DRAE.png
searchplugins/DRAE.src

View File

@ -1904,9 +1904,10 @@ public:
nsInProcessTabChildGlobal* tabChild =
static_cast<nsInProcessTabChildGlobal*>(mFrameLoader->mChildMessageManager.get());
if (tabChild && tabChild->GetInnerManager()) {
tabChild->GetInnerManager()->
ReceiveMessage(static_cast<nsPIDOMEventTarget*>(tabChild), mMessage,
PR_FALSE, mJSON, nsnull, nsnull);
nsFrameScriptCx cx(static_cast<nsPIDOMEventTarget*>(tabChild), tabChild);
nsRefPtr<nsFrameMessageManager> mm = tabChild->GetInnerManager();
mm->ReceiveMessage(static_cast<nsPIDOMEventTarget*>(tabChild), mMessage,
PR_FALSE, mJSON, nsnull, nsnull);
}
return NS_OK;
}

View File

@ -462,6 +462,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
}
}
}
nsRefPtr<nsFrameMessageManager> kungfuDeathGrip = mParentManager;
return mParentManager ? mParentManager->ReceiveMessage(aTarget, aMessage,
aSync, aJSON, aObjectsArray,
aJSONRetVal, mContext) : NS_OK;
@ -601,11 +602,18 @@ nsFrameScriptExecutor::DidCreateCx()
void
nsFrameScriptExecutor::DestroyCx()
{
nsIXPConnect* xpc = nsContentUtils::XPConnect();
if (xpc) {
xpc->ReleaseJSContext(mCx, PR_TRUE);
} else {
JS_DestroyContext(mCx);
if (mCxStackRefCnt) {
mDelayedCxDestroy = PR_TRUE;
return;
}
mDelayedCxDestroy = PR_FALSE;
if (mCx) {
nsIXPConnect* xpc = nsContentUtils::XPConnect();
if (xpc) {
xpc->ReleaseJSContext(mCx, PR_TRUE);
} else {
JS_DestroyContext(mCx);
}
}
mCx = nsnull;
mGlobal = nsnull;

View File

@ -201,7 +201,9 @@ class nsFrameScriptExecutor
public:
static void Shutdown();
protected:
nsFrameScriptExecutor() : mCx(nsnull)
friend class nsFrameScriptCx;
nsFrameScriptExecutor() : mCx(nsnull), mCxStackRefCnt(0),
mDelayedCxDestroy(PR_FALSE)
{ MOZ_COUNT_CTOR(nsFrameScriptExecutor); }
~nsFrameScriptExecutor()
{ MOZ_COUNT_DTOR(nsFrameScriptExecutor); }
@ -213,11 +215,32 @@ protected:
nsCycleCollectionTraversalCallback &cb);
nsCOMPtr<nsIXPConnectJSObjectHolder> mGlobal;
JSContext* mCx;
PRUint32 mCxStackRefCnt;
PRPackedBool mDelayedCxDestroy;
nsCOMPtr<nsIPrincipal> mPrincipal;
static nsDataHashtable<nsStringHashKey, nsFrameScriptExecutorJSObjectHolder*>* sCachedScripts;
static nsRefPtr<nsScriptCacheCleaner> sScriptCacheCleaner;
};
class nsFrameScriptCx
{
public:
nsFrameScriptCx(nsISupports* aOwner, nsFrameScriptExecutor* aExec)
: mOwner(aOwner), mExec(aExec)
{
++(mExec->mCxStackRefCnt);
}
~nsFrameScriptCx()
{
if (--(mExec->mCxStackRefCnt) == 0 &&
mExec->mDelayedCxDestroy) {
mExec->DestroyCx();
}
}
nsCOMPtr<nsISupports> mOwner;
nsFrameScriptExecutor* mExec;
};
class nsScriptCacheCleaner : public nsIObserver
{
NS_DECL_ISUPPORTS

View File

@ -68,8 +68,8 @@ bool SendSyncMessageToParent(void* aCallbackData,
async->Run();
}
if (tabChild->mChromeMessageManager) {
tabChild->mChromeMessageManager->ReceiveMessage(owner, aMessage, PR_TRUE,
aJSON, nsnull, aJSONRetVal);
nsRefPtr<nsFrameMessageManager> mm = tabChild->mChromeMessageManager;
mm->ReceiveMessage(owner, aMessage, PR_TRUE, aJSON, nsnull, aJSONRetVal);
}
return true;
}
@ -85,9 +85,9 @@ public:
{
mTabChild->mASyncMessages.RemoveElement(this);
if (mTabChild->mChromeMessageManager) {
mTabChild->mChromeMessageManager->ReceiveMessage(mTabChild->mOwner, mMessage,
PR_FALSE,
mJSON, nsnull, nsnull);
nsRefPtr<nsFrameMessageManager> mm = mTabChild->mChromeMessageManager;
mm->ReceiveMessage(mTabChild->mOwner, mMessage, PR_FALSE,
mJSON, nsnull, nsnull);
}
return NS_OK;
}

View File

@ -3913,6 +3913,8 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI *aURI,
case NS_ERROR_DOCUMENT_NOT_CACHED:
// Doc failed to load because we are offline and the cache does not
// contain a copy of the document.
case NS_ERROR_OFFLINE:
// Doc failed to load because we are offline
error.AssignLiteral("netOffline");
break;
case NS_ERROR_DOCUMENT_IS_PRINTMODE:
@ -6278,6 +6280,7 @@ nsDocShell::EndPageLoad(nsIWebProgress * aProgress,
aStatus == NS_ERROR_UNKNOWN_SOCKET_TYPE ||
aStatus == NS_ERROR_NET_INTERRUPT ||
aStatus == NS_ERROR_NET_RESET ||
aStatus == NS_ERROR_OFFLINE ||
aStatus == NS_ERROR_MALWARE_URI ||
aStatus == NS_ERROR_PHISHING_URI ||
aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE ||

View File

@ -220,7 +220,7 @@ ContentParent::OnChannelConnected(int32 pid)
nice = atoi(relativeNicenessStr);
}
/* make the GUI thread have higher priority on single-cpu devices */
/* make the GUI thread have higher priority on single-cpu devices */
nsCOMPtr<nsIPropertyBag2> infoService = do_GetService(NS_SYSTEMINFO_CONTRACTID);
if (infoService) {
PRInt32 cpus;

View File

@ -145,6 +145,7 @@ TabChild::Init()
}
NS_INTERFACE_MAP_BEGIN(TabChild)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowserChrome)
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2)
NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow)
@ -754,9 +755,11 @@ TabChild::RecvAsyncMessage(const nsString& aMessage,
const nsString& aJSON)
{
if (mTabChildGlobal) {
static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get())->
ReceiveMessage(static_cast<nsPIDOMEventTarget*>(mTabChildGlobal),
aMessage, PR_FALSE, aJSON, nsnull, nsnull);
nsFrameScriptCx cx(static_cast<nsIWebBrowserChrome*>(this), this);
nsRefPtr<nsFrameMessageManager> mm =
static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
mm->ReceiveMessage(static_cast<nsPIDOMEventTarget*>(mTabChildGlobal),
aMessage, PR_FALSE, aJSON, nsnull, nsnull);
}
return true;
}

View File

@ -587,7 +587,8 @@ TabParent::ReceiveMessage(const nsString& aMessage,
{
nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
if (frameLoader && frameLoader->GetFrameMessageManager()) {
nsFrameMessageManager* manager = frameLoader->GetFrameMessageManager();
nsRefPtr<nsFrameMessageManager> manager =
frameLoader->GetFrameMessageManager();
JSContext* ctx = manager->GetJSContext();
JSAutoRequest ar(ctx);
PRUint32 len = 0; //TODO: obtain a real value in bug 572685

View File

@ -139,7 +139,7 @@ abstract public class GeckoApp
mLibLoadThread.join();
} catch (InterruptedException ie) {}
surfaceView.mSplashStatusMsg =
getResources().getString(R.string.splash_screen_label);
getResources().getString(R.string.splash_screen_loading);
surfaceView.drawSplashScreen();
// unpack files in the components directory
try {
@ -260,10 +260,10 @@ abstract public class GeckoApp
new File(getApplication().getPackageResourcePath()).lastModified()
>= libxulFile.lastModified()))
surfaceView.mSplashStatusMsg =
getResources().getString(R.string.splash_screen_installing);
getResources().getString(R.string.splash_screen_installing_libs);
else
surfaceView.mSplashStatusMsg =
getResources().getString(R.string.splash_screen_label);
getResources().getString(R.string.splash_screen_loading);
mLibLoadThread.start();
}

View File

@ -273,7 +273,7 @@ public class GeckoInputConnection
// 2. Make a guess about what the text actually is
if (mComposing && extract.selectionEnd > extract.text.length())
extract.text = extract.text.subSequence(0, mCompositionStart) + mComposingText;
extract.text = extract.text.subSequence(0, Math.min(extract.text.length(), mCompositionStart)) + mComposingText;
// 3. If all else fails, make sure our selection indexes make sense
extract.selectionStart = Math.min(extract.selectionStart, extract.text.length());

View File

@ -132,6 +132,40 @@ class GeckoSurfaceView
* Called on main thread
*/
public void draw(SurfaceHolder holder, ByteBuffer buffer) {
if (buffer == null || buffer.capacity() != (mWidth * mHeight * 2))
return;
synchronized (mSoftwareBuffer) {
if (buffer != mSoftwareBuffer || mSoftwareBufferCopy == null)
return;
Canvas c = holder.lockCanvas();
if (c == null)
return;
mSoftwareBufferCopy.copyPixelsFromBuffer(buffer);
c.drawBitmap(mSoftwareBufferCopy, 0, 0, null);
holder.unlockCanvasAndPost(c);
}
}
public void draw(SurfaceHolder holder, Bitmap bitmap) {
if (bitmap == null ||
bitmap.getWidth() != mWidth || bitmap.getHeight() != mHeight)
return;
synchronized (mSoftwareBitmap) {
if (bitmap != mSoftwareBitmap)
return;
Canvas c = holder.lockCanvas();
if (c == null)
return;
c.drawBitmap(bitmap, 0, 0, null);
holder.unlockCanvasAndPost(c);
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (mShowingSplashScreen)
drawSplashScreen(holder, width, height);
@ -142,14 +176,15 @@ class GeckoSurfaceView
Log.w("GeckoAppJava", "surfaceChanged while mInDrawing is true!");
}
if (width == 0 || height == 0)
if (width == 0 || height == 0) {
mSoftwareBitmap = null;
mSoftwareBuffer = null;
else if (mSoftwareBuffer == null ||
mSoftwareBuffer.capacity() < (width * height * 2) ||
mWidth != width || mHeight != height)
mSoftwareBuffer = ByteBuffer.allocateDirect(width * height * 2);
boolean doSyncDraw = mDrawMode == DRAW_2D &&
mSoftwareBuffer != null &&
mSoftwareBufferCopy = null;
}
boolean doSyncDraw =
mDrawMode == DRAW_2D &&
(mSoftwareBitmap != null || mSoftwareBuffer != null) &&
GeckoApp.checkLaunchState(GeckoApp.LaunchState.GeckoRunning);
mSyncDraw = doSyncDraw;
@ -167,7 +202,7 @@ class GeckoSurfaceView
metrics.widthPixels, metrics.heightPixels);
GeckoAppShell.sendEventToGecko(e);
if (mSoftwareBuffer != null)
if (mSoftwareBitmap != null || mSoftwareBuffer != null)
GeckoAppShell.scheduleRedraw();
if (!doSyncDraw) {
@ -182,18 +217,17 @@ class GeckoSurfaceView
mSurfaceLock.unlock();
}
ByteBuffer bb = null;
Object syncDrawObject = null;
try {
bb = mSyncBuf.take();
Object syncObject = mSyncDraws.take();
} catch (InterruptedException ie) {
Log.e("GeckoAppJava", "Threw exception while getting sync buf: ", ie);
Log.e("GeckoAppJava", "Threw exception while getting sync draw bitmap/buffer: ", ie);
}
if (bb != null && bb.capacity() == (width * height * 2)) {
mSoftwareBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.RGB_565);
mSoftwareBitmap.copyPixelsFromBuffer(bb);
Canvas c = holder.lockCanvas();
c.drawBitmap(mSoftwareBitmap, 0, 0, null);
holder.unlockCanvasAndPost(c);
if (syncDrawObject != null) {
if (syncDrawObject instanceof Bitmap)
draw(holder, (Bitmap)syncDrawObject);
else
draw(holder, (ByteBuffer)syncDrawObject);
}
}
@ -209,11 +243,37 @@ class GeckoSurfaceView
Log.i("GeckoAppJava", "surface destroyed");
mSurfaceValid = false;
mSoftwareBuffer = null;
mSoftwareBufferCopy = null;
mSoftwareBitmap = null;
GeckoEvent e = new GeckoEvent(GeckoEvent.SURFACE_DESTROYED);
GeckoAppShell.sendEventToGecko(e);
}
public Bitmap getSoftwareDrawBitmap() {
if (mSoftwareBitmap == null ||
mSoftwareBitmap.getHeight() != mHeight ||
mSoftwareBitmap.getWidth() != mWidth) {
mSoftwareBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.RGB_565);
}
mDrawMode = DRAW_2D;
return mSoftwareBitmap;
}
public ByteBuffer getSoftwareDrawBuffer() {
// We store pixels in 565 format, so two bytes per pixel (explaining
// the * 2 in the following check/allocation)
if (mSoftwareBuffer == null ||
mSoftwareBuffer.capacity() != (mWidth * mHeight * 2)) {
mSoftwareBuffer = ByteBuffer.allocateDirect(mWidth * mHeight * 2);
}
if (mSoftwareBufferCopy == null ||
mSoftwareBufferCopy.getHeight() != mHeight ||
mSoftwareBufferCopy.getWidth() != mWidth) {
mSoftwareBufferCopy = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.RGB_565);
}
mDrawMode = DRAW_2D;
return mSoftwareBuffer;
}
@ -290,19 +350,19 @@ class GeckoSurfaceView
* unless you're in SurfaceChanged, in which case the canvas was already
* locked. Surface lock -> Canvas lock will lead to AB-BA deadlocks.
*/
public void draw2D(ByteBuffer buffer, int stride) {
// mSurfaceLock ensures that we get mSyncDraw/mSoftwareBuffer/etc.
public void draw2D(Bitmap bitmap, int width, int height) {
// mSurfaceLock ensures that we get mSyncDraw/mSoftwareBitmap/etc.
// set correctly before determining whether we should do a sync draw
mSurfaceLock.lock();
try {
if (mSyncDraw) {
if (buffer != mSoftwareBuffer || stride != (mWidth * 2))
if (bitmap != mSoftwareBitmap || width != mWidth || height != mHeight)
return;
mSyncDraw = false;
try {
mSyncBuf.put(buffer);
mSyncDraws.put(bitmap);
} catch (InterruptedException ie) {
Log.e("GeckoAppJava", "Threw exception while getting sync buf: ", ie);
Log.e("GeckoAppJava", "Threw exception while getting sync draws queue: ", ie);
}
return;
}
@ -310,29 +370,28 @@ class GeckoSurfaceView
mSurfaceLock.unlock();
}
if (buffer != mSoftwareBuffer || stride != (mWidth * 2))
return;
Canvas c = getHolder().lockCanvas();
if (c == null)
return;
if (buffer != mSoftwareBuffer || stride != (mWidth * 2)) {
/* We're screwed. Fill it with white and hope it isn't too noticable
* This could potentially happen if this function is called
* right before mSurfaceLock is locked in SurfaceChanged.
* However, I've never actually seen this code get hit.
*/
c.drawARGB(255, 255, 255, 255);
getHolder().unlockCanvasAndPost(c);
return;
draw(getHolder(), bitmap);
}
public void draw2D(ByteBuffer buffer, int stride) {
mSurfaceLock.lock();
try {
if (mSyncDraw) {
if (buffer != mSoftwareBuffer || stride != (mWidth * 2))
return;
mSyncDraw = false;
try {
mSyncDraws.put(buffer);
} catch (InterruptedException ie) {
Log.e("GeckoAppJava", "Threw exception while getting sync bitmaps queue: ", ie);
}
return;
}
} finally {
mSurfaceLock.unlock();
}
if (mSoftwareBitmap == null ||
mSoftwareBitmap.getHeight() != mHeight ||
mSoftwareBitmap.getWidth() != mWidth) {
mSoftwareBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.RGB_565);
}
mSoftwareBitmap.copyPixelsFromBuffer(mSoftwareBuffer);
c.drawBitmap(mSoftwareBitmap, 0, 0, null);
getHolder().unlockCanvasAndPost(c);
draw(getHolder(), buffer);
}
@Override
@ -631,12 +690,13 @@ class GeckoSurfaceView
boolean mIMELandscapeFS;
// Software rendering
ByteBuffer mSoftwareBuffer;
Bitmap mSoftwareBitmap;
ByteBuffer mSoftwareBuffer;
Bitmap mSoftwareBufferCopy;
Geocoder mGeocoder;
Address mLastGeoAddress;
final SynchronousQueue<ByteBuffer> mSyncBuf = new SynchronousQueue<ByteBuffer>();
final SynchronousQueue<Object> mSyncDraws = new SynchronousQueue<Object>();
}

View File

@ -1,6 +1,8 @@
<!ENTITY splash_screen_label "loading">
<!ENTITY splash_screen_installing "installing libraries\u2026">
<!ENTITY splash_screen_loading "Loading">
<!ENTITY splash_screen_installing_libs "Installing libraries\u2026">
<!ENTITY splash_firstrun "Setting up &brandShortName;\u2026">
<!ENTITY no_space_to_start_error "There is not enough space available for &brandShortName; to start.">
<!ENTITY error_loading_file "An error occurred when trying to load files required to run &brandShortName;">

View File

@ -5,8 +5,8 @@
#includesubst @STRINGSPATH@
]>
<resources>
<string name="splash_screen_label">&splash_screen_label;</string>
<string name="splash_screen_installing">&splash_screen_installing;</string>
<string name="splash_screen_loading">&splash_screen_loading;</string>
<string name="splash_screen_installing_libs">&splash_screen_installing_libs;</string>
<string name="splash_firstrun">&splash_firstrun;</string>
<string name="no_space_to_start_error">&no_space_to_start_error;</string>
<string name="error_loading_file">&error_loading_file;</string>

View File

@ -297,6 +297,7 @@ EXPORTS_NAMESPACES += mozilla
EXPORTS_mozilla = \
RangedPtr.h \
RefPtr.h \
Types.h \
Util.h \
$(NULL)

View File

@ -1762,6 +1762,10 @@ DocumentViewerImpl::SetDocumentInternal(nsIDocument* aDocument,
aDocument->SetContainer(container);
if (mDocument != aDocument) {
if (mDocument->IsStaticDocument()) {
mDocument->SetScriptGlobalObject(nsnull);
mDocument->Destroy();
}
// Replace the old document with the new one. Do this only when
// the new document really is a new document.
mDocument = aDocument;

View File

@ -3322,10 +3322,14 @@ nsTextPaintStyle::GetURLSecondaryColor(nscolor* aForeColor)
{
NS_ASSERTION(aForeColor, "aForeColor is null");
nsILookAndFeel* look = mPresContext->LookAndFeel();
nscolor foreColor;
look->GetColor(nsILookAndFeel::eColor_graytext, foreColor);
*aForeColor = foreColor;
nscolor textColor = GetTextColor();
textColor = NS_RGBA(NS_GET_R(textColor),
NS_GET_G(textColor),
NS_GET_B(textColor),
(PRUint8)(255 * 0.5f));
// Don't use true alpha color for readability.
InitCommonColors();
*aForeColor = NS_ComposeColors(mFrameBackgroundColor, textColor);
}
void

View File

@ -74,7 +74,7 @@ nsPrintData::nsPrintData(ePrintDataType aType) :
mShrinkRatio(1.0), mOrigDCScale(1.0), mPPEventListeners(NULL),
mBrandName(nsnull)
{
MOZ_COUNT_CTOR(nsPrintData);
nsCOMPtr<nsIStringBundle> brandBundle;
nsCOMPtr<nsIStringBundleService> svc =
mozilla::services::GetStringBundleService();
@ -93,6 +93,7 @@ nsPrintData::nsPrintData(ePrintDataType aType) :
nsPrintData::~nsPrintData()
{
MOZ_COUNT_DTOR(nsPrintData);
// remove the event listeners
if (mPPEventListeners) {
mPPEventListeners->RemoveListeners();

View File

@ -55,11 +55,13 @@ nsPrintObject::nsPrintObject() :
mSharedPresShell(PR_FALSE), mInvisible(PR_FALSE), mDidCreateDocShell(PR_FALSE),
mShrinkRatio(1.0), mZoomRatio(1.0)
{
MOZ_COUNT_CTOR(nsPrintObject);
}
nsPrintObject::~nsPrintObject()
{
MOZ_COUNT_DTOR(nsPrintObject);
for (PRUint32 i=0;i<mKids.Length();i++) {
nsPrintObject* po = mKids[i];
delete po;

413
mfbt/RefPtr.h Normal file
View File

@ -0,0 +1,413 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Chris Jones <jones.chris.g@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_RefPtr_h_
#define mozilla_RefPtr_h_
#include "mozilla/Util.h"
/**
* Helpers for defining and using refcounted objects.
*/
namespace mozilla {
template<typename T> class RefCounted;
template<typename T> class RefPtr;
template<typename T> class TemporaryRef;
template<typename T> class OutParamRef;
template<typename T> OutParamRef<T> byRef(RefPtr<T>&);
/**
* RefCounted<T> is a sort of a "mixin" for a class T. RefCounted
* manages, well, refcounting for T, and because RefCounted is
* parameterized on T, RefCounted<T> can call T's destructor directly.
* This means T doesn't need to have a virtual dtor and so doesn't
* need a vtable.
*
* RefCounted<T> is created with refcount == 0. Newly-allocated
* RefCounted<T> must immediately be assigned to a RefPtr to make the
* refcount > 0. It's an error to allocate and free a bare
* RefCounted<T>, i.e. outside of the RefPtr machinery. Attempts to
* do so will abort DEBUG builds.
*
* Live RefCounted<T> have refcount > 0. The lifetime (refcounts) of
* live RefCounted<T> are controlled by RefPtr<T> and
* RefPtr<super/subclass of T>. Upon a transition from refcounted==1
* to 0, the RefCounted<T> "dies" and is destroyed. The "destroyed"
* state is represented in DEBUG builds by refcount==-0xdead. This
* state distinguishes use-before-ref (refcount==0) from
* use-after-destroy (refcount==-0xdead).
*/
template<typename T>
class RefCounted
{
friend class RefPtr<T>;
public:
RefCounted() : refCnt(0) { }
~RefCounted() { MOZ_ASSERT(refCnt == -0xdead); }
// Compatibility with nsRefPtr.
void AddRef() {
MOZ_ASSERT(refCnt >= 0);
++refCnt;
}
void Release() {
MOZ_ASSERT(refCnt > 0);
if (0 == --refCnt) {
#ifdef DEBUG
refCnt = -0xdead;
#endif
delete static_cast<T*>(this);
}
}
// Compatibility with wtf::RefPtr.
void ref() { AddRef(); }
void deref() { Release(); }
int refCount() const { return refCnt; }
bool hasOneRef() const {
MOZ_ASSERT(refCnt > 0);
return refCnt == 1;
}
private:
int refCnt;
};
/**
* RefPtr points to a refcounted thing that has AddRef and Release
* methods to increase/decrease the refcount, respectively. After a
* RefPtr<T> is assigned a T*, the T* can be used through the RefPtr
* as if it were a T*.
*
* A RefPtr can forget its underlying T*, which results in the T*
* being wrapped in a temporary object until the T* is either
* re-adopted from or released by the temporary.
*/
template<typename T>
class RefPtr
{
// To allow them to use unref()
friend class TemporaryRef<T>;
friend class OutParamRef<T>;
public:
RefPtr() : ptr(0) { }
RefPtr(const RefPtr& o) : ptr(ref(o.ptr)) {}
RefPtr(const TemporaryRef<T>& o) : ptr(o.drop()) {}
RefPtr(T* t) : ptr(ref(t)) {}
template<typename U>
RefPtr(const RefPtr<U>& o) : ptr(ref(o.get())) {}
~RefPtr() { unref(ptr); }
RefPtr& operator=(const RefPtr& o) {
assign(ref(o.ptr));
return *this;
}
RefPtr& operator=(const TemporaryRef<T>& o) {
assign(o.drop());
return *this;
}
RefPtr& operator=(T* t) {
assign(ref(t));
return *this;
}
template<typename U>
RefPtr& operator=(const RefPtr<U>& o) {
assign(ref(o.get()));
return *this;
}
TemporaryRef<T> forget() {
T* tmp = ptr;
ptr = 0;
return TemporaryRef<T>(tmp);
}
T* get() const { return ptr; }
operator T*() const { return ptr; }
T* operator->() const { return ptr; }
T& operator*() const { return *ptr; }
private:
void assign(T* t) {
unref(ptr);
ptr = t;
}
T* ptr;
static MOZ_ALWAYS_INLINE T* ref(T* t) {
if (t) {
t->AddRef();
}
return t;
}
static MOZ_ALWAYS_INLINE void unref(T* t) {
if (t) {
t->Release();
}
}
};
/**
* TemporaryRef<T> represents an object that holds a temporary
* reference to a T. TemporaryRef objects can't be manually ref'd or
* unref'd (being temporaries, not lvalues), so can only relinquish
* references to other objects, or unref on destruction.
*/
template<typename T>
class TemporaryRef
{
// To allow it to construct TemporaryRef from a bare T*
friend class RefPtr<T>;
public:
TemporaryRef(const TemporaryRef& o) : ptr(o.drop()) {}
template<typename U>
TemporaryRef(const TemporaryRef<U>& o) : ptr(o.drop()) {}
~TemporaryRef() { RefPtr<T>::unref(ptr); }
T* drop() const {
T* tmp = ptr;
ptr = 0;
return tmp;
}
private:
TemporaryRef(T* t) : ptr(t) {}
mutable T* ptr;
TemporaryRef();
TemporaryRef& operator=(const TemporaryRef&);
};
/**
* OutParamRef is a wrapper that tracks a refcounted pointer passed as
* an outparam argument to a function. If OutParamRef holds a ref to
* an object that's reassigned during a function call in which the
* OutParamRef is an outparam, then the old object is unref'd and the
* new object is ref'd.
*
* Prefer returning TemporaryRef<T> from functions over creating T**
* outparams and passing OutParamRef<T> to T**. Prefer RefPtr<T>*
* outparams over T** outparams.
*/
template<typename T>
class OutParamRef
{
friend OutParamRef byRef<T>(RefPtr<T>&);
public:
~OutParamRef() { refPtr = tmp; }
operator T**() { return &tmp; }
private:
OutParamRef(RefPtr<T>& p) : refPtr(p), tmp(p.get()) {}
RefPtr<T>& refPtr;
T* tmp;
OutParamRef();
OutParamRef& operator=(const OutParamRef&);
};
template<typename T>
OutParamRef<T>
byRef(RefPtr<T>& ptr)
{
return OutParamRef<T>(ptr);
}
} // namespace mozilla
#endif // mozilla_RefPtr_h_
#if 0
// Command line that builds these tests
//
// cp RefPtr.h test.cc && g++ -g -Wall -pedantic -DDEBUG -o test test.cc && ./test
using namespace mozilla;
struct Foo : public RefCounted<Foo>
{
Foo() : dead(false) { }
~Foo() {
MOZ_ASSERT(!dead);
dead = true;
numDestroyed++;
}
bool dead;
static int numDestroyed;
};
int Foo::numDestroyed;
struct Bar : public Foo { };
TemporaryRef<Foo>
NewFoo()
{
RefPtr<Foo> f = new Foo();
return f.forget();
}
TemporaryRef<Foo>
NewBar()
{
RefPtr<Bar> b = new Bar();
return b.forget();
}
void
GetNewFoo(Foo** f)
{
*f = new Bar();
}
void
GetPassedFoo(Foo** f)
{}
void
GetNewFoo(RefPtr<Foo>* f)
{
*f = new Bar();
}
void
GetPassedFoo(RefPtr<Foo>* f)
{}
int
main(int argc, char** argv)
{
// This should blow up
// Foo* f = new Foo(); delete f;
MOZ_ASSERT(0 == Foo::numDestroyed);
{
RefPtr<Foo> f = new Foo();
MOZ_ASSERT(f->refCount() == 1);
}
MOZ_ASSERT(1 == Foo::numDestroyed);
{
RefPtr<Foo> f1 = NewFoo();
RefPtr<Foo> f2(NewFoo());
MOZ_ASSERT(1 == Foo::numDestroyed);
}
MOZ_ASSERT(3 == Foo::numDestroyed);
{
RefPtr<Foo> b = NewBar();
MOZ_ASSERT(3 == Foo::numDestroyed);
}
MOZ_ASSERT(4 == Foo::numDestroyed);
{
RefPtr<Foo> f1;
{
f1 = new Foo();
RefPtr<Foo> f2(f1);
RefPtr<Foo> f3 = f2;
MOZ_ASSERT(4 == Foo::numDestroyed);
}
MOZ_ASSERT(4 == Foo::numDestroyed);
}
MOZ_ASSERT(5 == Foo::numDestroyed);
{
RefPtr<Foo> f = new Foo();
f.forget();
MOZ_ASSERT(6 == Foo::numDestroyed);
}
{
RefPtr<Foo> f = new Foo();
GetNewFoo(byRef(f));
MOZ_ASSERT(7 == Foo::numDestroyed);
}
MOZ_ASSERT(8 == Foo::numDestroyed);
{
RefPtr<Foo> f = new Foo();
GetPassedFoo(byRef(f));
MOZ_ASSERT(8 == Foo::numDestroyed);
}
MOZ_ASSERT(9 == Foo::numDestroyed);
{
RefPtr<Foo> f = new Foo();
GetNewFoo(&f);
MOZ_ASSERT(10 == Foo::numDestroyed);
}
MOZ_ASSERT(11 == Foo::numDestroyed);
{
RefPtr<Foo> f = new Foo();
GetPassedFoo(&f);
MOZ_ASSERT(11 == Foo::numDestroyed);
}
MOZ_ASSERT(12 == Foo::numDestroyed);
{
RefPtr<Foo> f1 = new Bar();
}
MOZ_ASSERT(13 == Foo::numDestroyed);
return 0;
}
#endif

View File

@ -1979,8 +1979,7 @@ nsOfflineCacheDevice::AddNamespace(const nsCString &clientID,
NS_ENSURE_SUCCESS(rv, rv);
LOG(("nsOfflineCacheDevice::AddNamespace [cid=%s, ns=%s, data=%s, type=%d]",
PromiseFlatCString(clientID).get(),
namespaceSpec.get(), data.get(), itemType));
clientID.get(), namespaceSpec.get(), data.get(), itemType));
AutoResetStatement statement(mStatement_InsertNamespaceEntry);

View File

@ -306,8 +306,7 @@ bool
HttpChannelParent::RecvSetCacheTokenCachedCharset(const nsCString& charset)
{
if (mCacheDescriptor)
mCacheDescriptor->SetMetaDataElement("charset",
PromiseFlatCString(charset).get());
mCacheDescriptor->SetMetaDataElement("charset", charset.get());
return true;
}

View File

@ -36,6 +36,7 @@
* ***** END LICENSE BLOCK ***** */
#include <android/log.h>
#include <dlfcn.h>
#include "nsXULAppAPI.h"
#include <pthread.h>
@ -104,6 +105,8 @@ AndroidBridge::Init(JNIEnv *jEnv,
mJNIEnv = nsnull;
mThread = nsnull;
mOpenedBitmapLibrary = false;
mHasNativeBitmapAccess = false;
mGeckoAppShellClass = (jclass) jEnv->NewGlobalRef(jGeckoAppShellClass);
@ -858,3 +861,84 @@ AndroidBridge::ScanMedia(const nsAString& aFile, const nsACString& aMimeType)
mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jScanMedia, jstrFile, jstrMimeTypes);
}
bool
AndroidBridge::HasNativeBitmapAccess()
{
if (!mOpenedBitmapLibrary) {
// Try to dlopen libjnigraphics.so for direct bitmap access on
// Android 2.2+ (API level 8)
mOpenedBitmapLibrary = true;
void *handle = dlopen("/system/lib/libjnigraphics.so", RTLD_LAZY | RTLD_LOCAL);
if (handle == nsnull)
return false;
AndroidBitmap_getInfo = (int (*)(JNIEnv *, jobject, void *))dlsym(handle, "AndroidBitmap_getInfo");
if (AndroidBitmap_getInfo == nsnull)
return false;
AndroidBitmap_lockPixels = (int (*)(JNIEnv *, jobject, void **))dlsym(handle, "AndroidBitmap_lockPixels");
if (AndroidBitmap_lockPixels == nsnull)
return false;
AndroidBitmap_unlockPixels = (int (*)(JNIEnv *, jobject))dlsym(handle, "AndroidBitmap_unlockPixels");
if (AndroidBitmap_unlockPixels == nsnull)
return false;
ALOG_BRIDGE("Successfully opened libjnigraphics.so");
mHasNativeBitmapAccess = true;
}
return mHasNativeBitmapAccess;
}
bool
AndroidBridge::ValidateBitmap(jobject bitmap, int width, int height)
{
// This structure is defined in Android API level 8's <android/bitmap.h>
// Because we can't depend on this, we get the function pointers via dlsym
// and define this struct ourselves.
struct BitmapInfo {
uint32_t width;
uint32_t height;
uint32_t stride;
uint32_t format;
uint32_t flags;
};
int err;
struct BitmapInfo info = { 0, };
if ((err = AndroidBitmap_getInfo(JNI(), bitmap, &info)) != 0) {
ALOG_BRIDGE("AndroidBitmap_getInfo failed! (error %d)", err);
return false;
}
if (info.width != width || info.height != height)
return false;
return true;
}
void *
AndroidBridge::LockBitmap(jobject bitmap)
{
int err;
void *buf;
if ((err = AndroidBitmap_lockPixels(JNI(), bitmap, &buf)) != 0) {
ALOG_BRIDGE("AndroidBitmap_lockPixels failed! (error %d)", err);
buf = nsnull;
}
return buf;
}
void
AndroidBridge::UnlockBitmap(jobject bitmap)
{
int err;
if ((err = AndroidBitmap_unlockPixels(JNI(), bitmap)) != 0)
ALOG_BRIDGE("AndroidBitmap_unlockPixels failed! (error %d)", err);
}

View File

@ -245,6 +245,15 @@ public:
void ScanMedia(const nsAString& aFile, const nsACString& aMimeType);
// These next four functions are for native Bitmap access in Android 2.2+
bool HasNativeBitmapAccess();
bool ValidateBitmap(jobject bitmap, int width, int height);
void *LockBitmap(jobject bitmap);
void UnlockBitmap(jobject bitmap);
protected:
static AndroidBridge *sBridge;
@ -266,6 +275,9 @@ protected:
void EnsureJNIThread();
bool mOpenedBitmapLibrary;
bool mHasNativeBitmapAccess;
// other things
jmethodID jNotifyIME;
jmethodID jNotifyIMEEnabled;
@ -309,6 +321,11 @@ protected:
jclass jEGLDisplayImplClass;
jclass jEGLContextClass;
jclass jEGL10Class;
// calls we've dlopened from libjnigraphics.so
int (* AndroidBitmap_getInfo)(JNIEnv *env, jobject bitmap, void *info);
int (* AndroidBitmap_lockPixels)(JNIEnv *env, jobject bitmap, void **buffer);
int (* AndroidBitmap_unlockPixels)(JNIEnv *env, jobject bitmap);
};
}

View File

@ -102,7 +102,9 @@ jmethodID AndroidAddress::jGetThoroughfareMethod;
jclass AndroidGeckoSurfaceView::jGeckoSurfaceViewClass = 0;
jmethodID AndroidGeckoSurfaceView::jBeginDrawingMethod = 0;
jmethodID AndroidGeckoSurfaceView::jEndDrawingMethod = 0;
jmethodID AndroidGeckoSurfaceView::jDraw2DMethod = 0;
jmethodID AndroidGeckoSurfaceView::jDraw2DBitmapMethod = 0;
jmethodID AndroidGeckoSurfaceView::jDraw2DBufferMethod = 0;
jmethodID AndroidGeckoSurfaceView::jGetSoftwareDrawBitmapMethod = 0;
jmethodID AndroidGeckoSurfaceView::jGetSoftwareDrawBufferMethod = 0;
jmethodID AndroidGeckoSurfaceView::jGetHolderMethod = 0;
@ -170,9 +172,11 @@ AndroidGeckoSurfaceView::InitGeckoSurfaceViewClass(JNIEnv *jEnv)
jGeckoSurfaceViewClass = getClassGlobalRef("org/mozilla/gecko/GeckoSurfaceView");
jBeginDrawingMethod = getMethod("beginDrawing", "()I");
jGetSoftwareDrawBitmapMethod = getMethod("getSoftwareDrawBitmap", "()Landroid/graphics/Bitmap;");
jGetSoftwareDrawBufferMethod = getMethod("getSoftwareDrawBuffer", "()Ljava/nio/ByteBuffer;");
jEndDrawingMethod = getMethod("endDrawing", "()V");
jDraw2DMethod = getMethod("draw2D", "(Ljava/nio/ByteBuffer;I)V");
jDraw2DBitmapMethod = getMethod("draw2D", "(Landroid/graphics/Bitmap;II)V");
jDraw2DBufferMethod = getMethod("draw2D", "(Ljava/nio/ByteBuffer;I)V");
jGetHolderMethod = getMethod("getHolder", "()Landroid/view/SurfaceHolder;");
}
@ -463,10 +467,22 @@ AndroidGeckoSurfaceView::EndDrawing()
JNI()->CallVoidMethod(wrapped_obj, jEndDrawingMethod);
}
void
AndroidGeckoSurfaceView::Draw2D(jobject bitmap, int width, int height)
{
JNI()->CallVoidMethod(wrapped_obj, jDraw2DBitmapMethod, bitmap, width, height);
}
void
AndroidGeckoSurfaceView::Draw2D(jobject buffer, int stride)
{
JNI()->CallVoidMethod(wrapped_obj, jDraw2DMethod, buffer, stride);
JNI()->CallVoidMethod(wrapped_obj, jDraw2DBufferMethod, buffer, stride);
}
jobject
AndroidGeckoSurfaceView::GetSoftwareDrawBitmap()
{
return JNI()->CallObjectMethod(wrapped_obj, jGetSoftwareDrawBitmapMethod);
}
jobject

View File

@ -167,8 +167,10 @@ public:
};
int BeginDrawing();
jobject GetSoftwareDrawBitmap();
jobject GetSoftwareDrawBuffer();
void EndDrawing();
void Draw2D(jobject bitmap, int width, int height);
void Draw2D(jobject buffer, int stride);
// must have a JNI local frame when calling this,
@ -179,7 +181,9 @@ protected:
static jclass jGeckoSurfaceViewClass;
static jmethodID jBeginDrawingMethod;
static jmethodID jEndDrawingMethod;
static jmethodID jDraw2DMethod;
static jmethodID jDraw2DBitmapMethod;
static jmethodID jDraw2DBufferMethod;
static jmethodID jGetSoftwareDrawBitmapMethod;
static jmethodID jGetSoftwareDrawBufferMethod;
static jmethodID jGetHolderMethod;
};

View File

@ -987,27 +987,54 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
AndroidBridge::Bridge()->HideProgressDialogOnce();
if (GetLayerManager(nsnull)->GetBackendType() == LayerManager::LAYERS_BASIC) {
jobject bytebuf = sview.GetSoftwareDrawBuffer();
if (!bytebuf) {
ALOG("no buffer to draw into - skipping draw");
return;
if (AndroidBridge::Bridge()->HasNativeBitmapAccess()) {
jobject bitmap = sview.GetSoftwareDrawBitmap();
if (!bitmap) {
ALOG("no bitmap to draw into - skipping draw");
return;
}
if (!AndroidBridge::Bridge()->ValidateBitmap(bitmap, mBounds.width, mBounds.height))
return;
void *buf = AndroidBridge::Bridge()->LockBitmap(bitmap);
if (buf == nsnull) {
ALOG("### Software drawing, but failed to lock bitmap.");
return;
}
nsRefPtr<gfxImageSurface> targetSurface =
new gfxImageSurface((unsigned char *)buf,
gfxIntSize(mBounds.width, mBounds.height),
mBounds.width * 2,
gfxASurface::ImageFormatRGB16_565);
DrawTo(targetSurface);
AndroidBridge::Bridge()->UnlockBitmap(bitmap);
sview.Draw2D(bitmap, mBounds.width, mBounds.height);
} else {
jobject bytebuf = sview.GetSoftwareDrawBuffer();
if (!bytebuf) {
ALOG("no buffer to draw into - skipping draw");
return;
}
void *buf = AndroidBridge::JNI()->GetDirectBufferAddress(bytebuf);
int cap = AndroidBridge::JNI()->GetDirectBufferCapacity(bytebuf);
if (!buf || cap != (mBounds.width * mBounds.height * 2)) {
ALOG("### Software drawing, but unexpected buffer size %d expected %d (or no buffer %p)!", cap, mBounds.width * mBounds.height * 2, buf);
return;
}
nsRefPtr<gfxImageSurface> targetSurface =
new gfxImageSurface((unsigned char *)buf,
gfxIntSize(mBounds.width, mBounds.height),
mBounds.width * 2,
gfxASurface::ImageFormatRGB16_565);
DrawTo(targetSurface);
sview.Draw2D(bytebuf, mBounds.width * 2);
}
void *buf = AndroidBridge::JNI()->GetDirectBufferAddress(bytebuf);
int cap = AndroidBridge::JNI()->GetDirectBufferCapacity(bytebuf);
if (!buf || cap != (mBounds.width * mBounds.height * 2)) {
ALOG("### Software drawing, but unexpected buffer size %d expected %d (or no buffer %p)!", cap, mBounds.width * mBounds.height * 2, buf);
return;
}
nsRefPtr<gfxImageSurface> targetSurface =
new gfxImageSurface((unsigned char *)buf,
gfxIntSize(mBounds.width, mBounds.height),
mBounds.width * 2,
gfxASurface::ImageFormatRGB16_565);
DrawTo(targetSurface);
sview.Draw2D(bytebuf, mBounds.width * 2);
} else {
int drawType = sview.BeginDrawing();