This commit is contained in:
Richard Newman 2011-12-14 01:58:41 -08:00
Родитель f7008445e8 83561ee1fd
Коммит 089dbf05e1
33 изменённых файлов: 426 добавлений и 238 удалений

Просмотреть файл

@ -174,8 +174,9 @@ NS_IMETHODIMP nsBMPEncoder::StartImageEncode(PRUint32 aWidth,
return NS_OK; return NS_OK;
} }
// Returns the image buffer size // Returns the number of bytes in the image buffer used.
NS_IMETHODIMP nsBMPEncoder::GetImageBufferSize(PRUint32 *aOutputSize) // For a BMP file, this is all bytes in the buffer.
NS_IMETHODIMP nsBMPEncoder::GetImageBufferUsed(PRUint32 *aOutputSize)
{ {
NS_ENSURE_ARG_POINTER(aOutputSize); NS_ENSURE_ARG_POINTER(aOutputSize);
*aOutputSize = mImageBufferSize; *aOutputSize = mImageBufferSize;

Просмотреть файл

@ -111,9 +111,10 @@ NS_IMETHODIMP nsICOEncoder::InitFromData(const PRUint8* aData,
return rv; return rv;
} }
// Returns the image buffer size // Returns the number of bytes in the image buffer used
// For an ICO file, this is all bytes in the buffer.
NS_IMETHODIMP NS_IMETHODIMP
nsICOEncoder::GetImageBufferSize(PRUint32 *aOutputSize) nsICOEncoder::GetImageBufferUsed(PRUint32 *aOutputSize)
{ {
NS_ENSURE_ARG_POINTER(aOutputSize); NS_ENSURE_ARG_POINTER(aOutputSize);
*aOutputSize = mImageBufferSize; *aOutputSize = mImageBufferSize;
@ -147,16 +148,16 @@ nsICOEncoder::AddImageFrame(const PRUint8* aData,
aStride, aInputFormat, noParams); aStride, aInputFormat, noParams);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
PRUint32 imageBufferSize; PRUint32 PNGImageBufferSize;
mContainedEncoder->GetImageBufferSize(&imageBufferSize); mContainedEncoder->GetImageBufferUsed(&PNGImageBufferSize);
mImageBufferSize = ICONFILEHEADERSIZE + ICODIRENTRYSIZE + mImageBufferSize = ICONFILEHEADERSIZE + ICODIRENTRYSIZE +
imageBufferSize; PNGImageBufferSize;
mImageBufferStart = static_cast<PRUint8*>(moz_malloc(mImageBufferSize)); mImageBufferStart = static_cast<PRUint8*>(moz_malloc(mImageBufferSize));
if (!mImageBufferStart) { if (!mImageBufferStart) {
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
mImageBufferCurr = mImageBufferStart; mImageBufferCurr = mImageBufferStart;
mICODirEntry.mBytesInRes = imageBufferSize; mICODirEntry.mBytesInRes = PNGImageBufferSize;
EncodeFileHeader(); EncodeFileHeader();
EncodeInfoHeader(); EncodeInfoHeader();
@ -164,8 +165,8 @@ nsICOEncoder::AddImageFrame(const PRUint8* aData,
char *imageBuffer; char *imageBuffer;
rv = mContainedEncoder->GetImageBuffer(&imageBuffer); rv = mContainedEncoder->GetImageBuffer(&imageBuffer);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
memcpy(mImageBufferCurr, imageBuffer, imageBufferSize); memcpy(mImageBufferCurr, imageBuffer, PNGImageBufferSize);
mImageBufferCurr += imageBufferSize; mImageBufferCurr += PNGImageBufferSize;
} else { } else {
mContainedEncoder = new nsBMPEncoder(); mContainedEncoder = new nsBMPEncoder();
nsresult rv; nsresult rv;
@ -181,10 +182,10 @@ nsICOEncoder::AddImageFrame(const PRUint8* aData,
PRUint32 andMaskSize = ((GetRealWidth() + 31) / 32) * 4 * // row AND mask PRUint32 andMaskSize = ((GetRealWidth() + 31) / 32) * 4 * // row AND mask
GetRealHeight(); // num rows GetRealHeight(); // num rows
PRUint32 imageBufferSize; PRUint32 BMPImageBufferSize;
mContainedEncoder->GetImageBufferSize(&imageBufferSize); mContainedEncoder->GetImageBufferUsed(&BMPImageBufferSize);
mImageBufferSize = ICONFILEHEADERSIZE + ICODIRENTRYSIZE + mImageBufferSize = ICONFILEHEADERSIZE + ICODIRENTRYSIZE +
imageBufferSize + andMaskSize; BMPImageBufferSize + andMaskSize;
mImageBufferStart = static_cast<PRUint8*>(moz_malloc(mImageBufferSize)); mImageBufferStart = static_cast<PRUint8*>(moz_malloc(mImageBufferSize));
if (!mImageBufferStart) { if (!mImageBufferStart) {
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
@ -192,7 +193,7 @@ nsICOEncoder::AddImageFrame(const PRUint8* aData,
mImageBufferCurr = mImageBufferStart; mImageBufferCurr = mImageBufferStart;
// The icon buffer does not include the BFH at all. // The icon buffer does not include the BFH at all.
mICODirEntry.mBytesInRes = imageBufferSize - BFH_LENGTH + andMaskSize; mICODirEntry.mBytesInRes = BMPImageBufferSize - BFH_LENGTH + andMaskSize;
// Encode the icon headers // Encode the icon headers
EncodeFileHeader(); EncodeFileHeader();
@ -202,13 +203,13 @@ nsICOEncoder::AddImageFrame(const PRUint8* aData,
rv = mContainedEncoder->GetImageBuffer(&imageBuffer); rv = mContainedEncoder->GetImageBuffer(&imageBuffer);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
memcpy(mImageBufferCurr, imageBuffer + BFH_LENGTH, memcpy(mImageBufferCurr, imageBuffer + BFH_LENGTH,
imageBufferSize - BFH_LENGTH); BMPImageBufferSize - BFH_LENGTH);
// We need to fix the BMP height to be *2 for the AND mask // We need to fix the BMP height to be *2 for the AND mask
PRUint32 fixedHeight = GetRealHeight() * 2; PRUint32 fixedHeight = GetRealHeight() * 2;
fixedHeight = NATIVE32_TO_LITTLE(fixedHeight); fixedHeight = NATIVE32_TO_LITTLE(fixedHeight);
// The height is stored at an offset of 8 from the DIB header // The height is stored at an offset of 8 from the DIB header
memcpy(mImageBufferCurr + 8, &fixedHeight, sizeof(fixedHeight)); memcpy(mImageBufferCurr + 8, &fixedHeight, sizeof(fixedHeight));
mImageBufferCurr += imageBufferSize - BFH_LENGTH; mImageBufferCurr += BMPImageBufferSize - BFH_LENGTH;
// Calculate rowsize in DWORD's // Calculate rowsize in DWORD's
PRUint32 rowSize = ((GetRealWidth() + 31) / 32) * 4; // + 31 to round up PRUint32 rowSize = ((GetRealWidth() + 31) / 32) * 4; // + 31 to round up

Просмотреть файл

@ -221,11 +221,11 @@ NS_IMETHODIMP nsJPEGEncoder::StartImageEncode(PRUint32 aWidth,
return NS_ERROR_NOT_IMPLEMENTED; return NS_ERROR_NOT_IMPLEMENTED;
} }
// Returns the image buffer size // Returns the number of bytes in the image buffer used.
NS_IMETHODIMP nsJPEGEncoder::GetImageBufferSize(PRUint32 *aOutputSize) NS_IMETHODIMP nsJPEGEncoder::GetImageBufferUsed(PRUint32 *aOutputSize)
{ {
NS_ENSURE_ARG_POINTER(aOutputSize); NS_ENSURE_ARG_POINTER(aOutputSize);
*aOutputSize = mImageBufferSize; *aOutputSize = mImageBufferUsed;
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -206,11 +206,11 @@ NS_IMETHODIMP nsPNGEncoder::StartImageEncode(PRUint32 aWidth,
return NS_OK; return NS_OK;
} }
// Returns the image buffer size // Returns the number of bytes in the image buffer used.
NS_IMETHODIMP nsPNGEncoder::GetImageBufferSize(PRUint32 *aOutputSize) NS_IMETHODIMP nsPNGEncoder::GetImageBufferUsed(PRUint32 *aOutputSize)
{ {
NS_ENSURE_ARG_POINTER(aOutputSize); NS_ENSURE_ARG_POINTER(aOutputSize);
*aOutputSize = mImageBufferSize; *aOutputSize = mImageBufferUsed;
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -44,7 +44,7 @@
/** /**
* imgIEncoder interface * imgIEncoder interface
*/ */
[scriptable, uuid(d02e2d95-072d-4b91-8b8f-1300e45fcb2b)] [scriptable, uuid(4baa2d6e-fee7-42df-ae3f-5fbebc0c267c)]
interface imgIEncoder : nsIAsyncInputStream interface imgIEncoder : nsIAsyncInputStream
{ {
// Possible values for outputOptions. Multiple values are semicolon-separated. // Possible values for outputOptions. Multiple values are semicolon-separated.
@ -159,8 +159,9 @@ interface imgIEncoder : nsIAsyncInputStream
/* /*
* Sometimes an encoder can contain another encoder and direct access * Sometimes an encoder can contain another encoder and direct access
* to its buffer is necessary. * to its buffer is necessary. It is only safe to assume that the buffer
* returned from getImageBuffer() is of size equal to getImageBufferUsed().
*/ */
[noscript] unsigned long getImageBufferSize(); [noscript] unsigned long getImageBufferUsed();
[noscript] charPtr getImageBuffer(); [noscript] charPtr getImageBuffer();
}; };

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* *
* ***** BEGIN LICENSE BLOCK ***** * ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
@ -102,8 +102,7 @@ js_InitArrayClass(JSContext *cx, JSObject *obj);
extern bool extern bool
js_InitContextBusyArrayTable(JSContext *cx); js_InitContextBusyArrayTable(JSContext *cx);
namespace js namespace js {
{
/* Create a dense array with no capacity allocated, length set to 0. */ /* Create a dense array with no capacity allocated, length set to 0. */
extern JSObject * JS_FASTCALL extern JSObject * JS_FASTCALL
@ -136,7 +135,7 @@ NewDenseCopiedArray(JSContext *cx, uint32 length, const Value *vp, JSObject *pro
extern JSObject * extern JSObject *
NewSlowEmptyArray(JSContext *cx); NewSlowEmptyArray(JSContext *cx);
} } /* namespace js */
extern JSBool extern JSBool
js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp); js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp);
@ -162,10 +161,7 @@ array_deleteElement(JSContext *cx, JSObject *obj, uint32 index, Value *rval, JSB
extern bool extern bool
GetElements(JSContext *cx, JSObject *aobj, jsuint length, js::Value *vp); GetElements(JSContext *cx, JSObject *aobj, jsuint length, js::Value *vp);
}
/* Natives exposed for optimization by the interpreter and JITs. */ /* Natives exposed for optimization by the interpreter and JITs. */
namespace js {
extern JSBool extern JSBool
array_sort(JSContext *cx, uintN argc, js::Value *vp); array_sort(JSContext *cx, uintN argc, js::Value *vp);
@ -213,7 +209,4 @@ js_GetDenseArrayElementValue(JSContext *cx, JSObject *obj, jsid id,
JSBool JSBool
js_Array(JSContext *cx, uintN argc, js::Value *vp); js_Array(JSContext *cx, uintN argc, js::Value *vp);
extern JSBool JS_FASTCALL
js_EnsureDenseArrayCapacity(JSContext *cx, JSObject *obj, jsint i);
#endif /* jsarray_h___ */ #endif /* jsarray_h___ */

Просмотреть файл

@ -697,15 +697,6 @@ CreateEvalCallObject(JSContext *cx, StackFrame *fp)
} // namespace js } // namespace js
JSObject * JS_FASTCALL
js_CreateCallObjectOnTrace(JSContext *cx, JSFunction *fun, JSObject *callee, JSObject *scopeChain)
{
JS_ASSERT(!js_IsNamedLambda(fun));
JS_ASSERT(scopeChain);
JS_ASSERT(callee);
return CallObject::create(cx, fun->script(), *scopeChain, callee);
}
void void
js_PutCallObject(StackFrame *fp) js_PutCallObject(StackFrame *fp)
{ {

Просмотреть файл

@ -312,9 +312,6 @@ js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
uintN flags, JSObject *parent, JSAtom *atom, uintN flags, JSObject *parent, JSAtom *atom,
js::gc::AllocKind kind = JSFunction::FinalizeKind); js::gc::AllocKind kind = JSFunction::FinalizeKind);
extern void
js_FinalizeFunction(JSContext *cx, JSFunction *fun);
extern JSFunction * JS_FASTCALL extern JSFunction * JS_FASTCALL
js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent, JSObject *proto, js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent, JSObject *proto,
js::gc::AllocKind kind = JSFunction::FinalizeKind); js::gc::AllocKind kind = JSFunction::FinalizeKind);
@ -345,16 +342,9 @@ js_ValueToCallableObject(JSContext *cx, js::Value *vp, uintN flags);
extern void extern void
js_ReportIsNotFunction(JSContext *cx, const js::Value *vp, uintN flags); js_ReportIsNotFunction(JSContext *cx, const js::Value *vp, uintN flags);
extern JSObject * JS_FASTCALL
js_CreateCallObjectOnTrace(JSContext *cx, JSFunction *fun, JSObject *callee, JSObject *scopeChain);
extern void extern void
js_PutCallObject(js::StackFrame *fp); js_PutCallObject(js::StackFrame *fp);
extern JSBool JS_FASTCALL
js_PutCallObjectOnTrace(JSObject *scopeChain, uint32 nargs, js::Value *argv,
uint32 nvars, js::Value *slots);
namespace js { namespace js {
CallObject * CallObject *

Просмотреть файл

@ -236,7 +236,11 @@ public class AboutHomeContent extends ScrollView {
return is; return is;
File applicationPackage = new File(activity.getApplication().getPackageResourcePath()); File applicationPackage = new File(activity.getApplication().getPackageResourcePath());
ZipFile zip = new ZipFile(applicationPackage); ZipFile zip = new ZipFile(applicationPackage);
if (zip == null)
return null;
ZipEntry fileEntry = zip.getEntry("recommended-addons.json"); ZipEntry fileEntry = zip.getEntry("recommended-addons.json");
if (fileEntry == null)
return null;
return zip.getInputStream(fileEntry); return zip.getInputStream(fileEntry);
} }
@ -246,6 +250,8 @@ public class AboutHomeContent extends ScrollView {
try { try {
byte[] buf = new byte[32768]; byte[] buf = new byte[32768];
InputStream fileStream = getRecommendedAddonsStream(activity); InputStream fileStream = getRecommendedAddonsStream(activity);
if (fileStream == null)
return;
StringBuffer jsonString = new StringBuffer(); StringBuffer jsonString = new StringBuffer();
int read = 0; int read = 0;
while ((read = fileStream.read(buf, 0, 32768)) != -1) { while ((read = fileStream.read(buf, 0, 32768)) != -1) {

Просмотреть файл

@ -234,7 +234,7 @@ public class AwesomeBar extends Activity implements GeckoEventListener {
// If a space is found before any dot or colon, we assume this is a search query // If a space is found before any dot or colon, we assume this is a search query
boolean spacedOut = space > -1 && (space < colon || space < dot); boolean spacedOut = space > -1 && (space < colon || space < dot);
return spacedOut || (dot == -1); return spacedOut || (dot == -1 && colon == -1);
} }
private void updateGoButton(String text) { private void updateGoButton(String text) {

Просмотреть файл

@ -456,11 +456,13 @@ abstract public class GeckoApp
MenuItem forward = aMenu.findItem(R.id.forward); MenuItem forward = aMenu.findItem(R.id.forward);
MenuItem share = aMenu.findItem(R.id.share); MenuItem share = aMenu.findItem(R.id.share);
MenuItem agentMode = aMenu.findItem(R.id.agent_mode); MenuItem agentMode = aMenu.findItem(R.id.agent_mode);
MenuItem saveAsPDF = aMenu.findItem(R.id.save_as_pdf);
if (tab == null) { if (tab == null) {
bookmark.setEnabled(false); bookmark.setEnabled(false);
forward.setEnabled(false); forward.setEnabled(false);
share.setEnabled(false); share.setEnabled(false);
saveAsPDF.setEnabled(false);
return true; return true;
} }
@ -481,7 +483,11 @@ abstract public class GeckoApp
// Don't share about:, chrome: and file: URIs // Don't share about:, chrome: and file: URIs
String scheme = Uri.parse(tab.getURL()).getScheme(); String scheme = Uri.parse(tab.getURL()).getScheme();
share.setEnabled(!scheme.equals("about") && !scheme.equals("chrome") && !scheme.equals("file")); share.setEnabled(!(scheme.equals("about") || scheme.equals("chrome") || scheme.equals("file")));
// Disable save as PDF for about:home and xul pages
saveAsPDF.setEnabled(!(tab.getURL().equals("about:home") ||
tab.getContentType().equals("application/vnd.mozilla.xul+xml")));
return true; return true;
} }
@ -667,7 +673,8 @@ abstract public class GeckoApp
tab.setFaviconLoadId(id); tab.setFaviconLoadId(id);
} }
void handleLocationChange(final int tabId, final String uri) { void handleLocationChange(final int tabId, final String uri,
final String documentURI, final String contentType) {
final Tab tab = Tabs.getInstance().getTab(tabId); final Tab tab = Tabs.getInstance().getTab(tabId);
if (tab == null) if (tab == null)
return; return;
@ -681,6 +688,8 @@ abstract public class GeckoApp
String oldBaseURI = tab.getURL(); String oldBaseURI = tab.getURL();
tab.updateURL(uri); tab.updateURL(uri);
tab.setDocumentURI(documentURI);
tab.setContentType(contentType);
String baseURI = uri; String baseURI = uri;
if (baseURI.indexOf('#') != -1) if (baseURI.indexOf('#') != -1)
@ -848,8 +857,10 @@ abstract public class GeckoApp
} else if (event.equals("Content:LocationChange")) { } else if (event.equals("Content:LocationChange")) {
final int tabId = message.getInt("tabID"); final int tabId = message.getInt("tabID");
final String uri = message.getString("uri"); final String uri = message.getString("uri");
final String documentURI = message.getString("documentURI");
final String contentType = message.getString("contentType");
Log.i(LOGTAG, "URI - " + uri); Log.i(LOGTAG, "URI - " + uri);
handleLocationChange(tabId, uri); handleLocationChange(tabId, uri, documentURI, contentType);
} else if (event.equals("Content:SecurityChange")) { } else if (event.equals("Content:SecurityChange")) {
final int tabId = message.getInt("tabID"); final int tabId = message.getInt("tabID");
final String mode = message.getString("mode"); final String mode = message.getString("mode");
@ -902,7 +913,11 @@ abstract public class GeckoApp
setLaunchState(GeckoApp.LaunchState.GeckoRunning); setLaunchState(GeckoApp.LaunchState.GeckoRunning);
GeckoAppShell.sendPendingEventsToGecko(); GeckoAppShell.sendPendingEventsToGecko();
connectGeckoLayerClient(); connectGeckoLayerClient();
GeckoAppShell.getHandler().post(new Runnable() {
public void run() {
Looper.myQueue().addIdleHandler(new UpdateIdleHandler()); Looper.myQueue().addIdleHandler(new UpdateIdleHandler());
}
});
} else if (event.equals("ToggleChrome:Hide")) { } else if (event.equals("ToggleChrome:Hide")) {
mMainHandler.post(new Runnable() { mMainHandler.post(new Runnable() {
public void run() { public void run() {

Просмотреть файл

@ -38,6 +38,7 @@
package org.mozilla.gecko; package org.mozilla.gecko;
import java.lang.CharSequence;
import java.util.ArrayList; import java.util.ArrayList;
import android.os.Build; import android.os.Build;
@ -131,8 +132,12 @@ public class GeckoPreferences
public boolean onPreferenceChange(Preference preference, Object newValue) { public boolean onPreferenceChange(Preference preference, Object newValue) {
String prefName = preference.getKey(); String prefName = preference.getKey();
setPreference(prefName, newValue); setPreference(prefName, newValue);
if (preference instanceof ListPreference) if (preference instanceof ListPreference) {
((ListPreference)preference).setSummary((String)newValue); // We need to find the entry for the new value
int newIndex = ((ListPreference)preference).findIndexOfValue((String) newValue);
CharSequence newEntry = ((ListPreference)preference).getEntries()[newIndex];
((ListPreference)preference).setSummary(newEntry);
}
if (preference instanceof LinkPreference) if (preference instanceof LinkPreference)
finish(); finish();
return true; return true;
@ -177,6 +182,9 @@ public class GeckoPreferences
GeckoAppShell.getMainHandler().post(new Runnable() { GeckoAppShell.getMainHandler().post(new Runnable() {
public void run() { public void run() {
((ListPreference)pref).setValue(value); ((ListPreference)pref).setValue(value);
// Set the summary string to the current entry
CharSequence selectedEntry = ((ListPreference)pref).getEntry();
((ListPreference)pref).setSummary(selectedEntry);
} }
}); });
} }

Просмотреть файл

@ -206,6 +206,7 @@ RES_LAYOUT_V11 = \
RES_VALUES = \ RES_VALUES = \
res/values/defaults.xml \ res/values/defaults.xml \
res/values/arrays.xml \
res/values/colors.xml \ res/values/colors.xml \
res/values/styles.xml \ res/values/styles.xml \
res/values/themes.xml \ res/values/themes.xml \
@ -453,6 +454,7 @@ $(RES_VALUES): \
$(srcdir)/resources/values/colors.xml \ $(srcdir)/resources/values/colors.xml \
$(srcdir)/resources/values/styles.xml \ $(srcdir)/resources/values/styles.xml \
$(srcdir)/resources/values/themes.xml \ $(srcdir)/resources/values/themes.xml \
$(srcdir)/resources/values/arrays.xml \
$(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/res/values/defaults.xml $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/res/values/defaults.xml
$(NSINSTALL) -D res/values $(NSINSTALL) -D res/values
$(NSINSTALL) $^ res/values $(NSINSTALL) $^ res/values

Просмотреть файл

@ -75,6 +75,8 @@ public class Tab {
private HashMap<String, DoorHanger> mDoorHangers; private HashMap<String, DoorHanger> mDoorHangers;
private long mFaviconLoadId; private long mFaviconLoadId;
private AgentMode mAgentMode = AgentMode.MOBILE; private AgentMode mAgentMode = AgentMode.MOBILE;
private String mDocumentURI;
private String mContentType;
static class HistoryEntry { static class HistoryEntry {
public final String mUri; // must never be null public final String mUri; // must never be null
@ -103,6 +105,8 @@ public class Tab {
mBookmark = false; mBookmark = false;
mDoorHangers = new HashMap<String, DoorHanger>(); mDoorHangers = new HashMap<String, DoorHanger>();
mFaviconLoadId = 0; mFaviconLoadId = 0;
mDocumentURI = "";
mContentType = "";
} }
public int getId() { public int getId() {
@ -182,6 +186,22 @@ public class Tab {
} }
} }
public void setDocumentURI(String documentURI) {
mDocumentURI = documentURI;
}
public String getDocumentURI() {
return mDocumentURI;
}
public void setContentType(String contentType) {
mContentType = contentType;
}
public String getContentType() {
return mContentType;
}
public void updateTitle(String title) { public void updateTitle(String title) {
mTitle = (title == null ? "" : title); mTitle = (title == null ? "" : title);

Просмотреть файл

@ -37,6 +37,7 @@
package org.mozilla.gecko.gfx; package org.mozilla.gecko.gfx;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.gfx.CairoImage; import org.mozilla.gecko.gfx.CairoImage;
import org.mozilla.gecko.gfx.CairoUtils; import org.mozilla.gecko.gfx.CairoUtils;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@ -46,6 +47,7 @@ import java.nio.ByteBuffer;
public class BufferedCairoImage extends CairoImage { public class BufferedCairoImage extends CairoImage {
private ByteBuffer mBuffer; private ByteBuffer mBuffer;
private int mWidth, mHeight, mFormat; private int mWidth, mHeight, mFormat;
private boolean mNeedToFreeBuffer = false;
/** Creates a buffered Cairo image from a byte buffer. */ /** Creates a buffered Cairo image from a byte buffer. */
public BufferedCairoImage(ByteBuffer inBuffer, int inWidth, int inHeight, int inFormat) { public BufferedCairoImage(ByteBuffer inBuffer, int inWidth, int inHeight, int inFormat) {
@ -57,10 +59,22 @@ public class BufferedCairoImage extends CairoImage {
mFormat = CairoUtils.bitmapConfigToCairoFormat(bitmap.getConfig()); mFormat = CairoUtils.bitmapConfigToCairoFormat(bitmap.getConfig());
mWidth = bitmap.getWidth(); mWidth = bitmap.getWidth();
mHeight = bitmap.getHeight(); mHeight = bitmap.getHeight();
mBuffer = ByteBuffer.allocateDirect(mWidth * mHeight * 4); mNeedToFreeBuffer = true;
mBuffer = GeckoAppShell.allocateDirectBuffer(mWidth * mHeight * 4);
bitmap.copyPixelsToBuffer(mBuffer.asIntBuffer()); bitmap.copyPixelsToBuffer(mBuffer.asIntBuffer());
} }
protected void finalize() throws Throwable {
try {
if (mNeedToFreeBuffer && mBuffer != null)
GeckoAppShell.freeDirectBuffer(mBuffer);
mNeedToFreeBuffer = false;
mBuffer = null;
} finally {
super.finalize();
}
}
@Override @Override
public ByteBuffer getBuffer() { return mBuffer; } public ByteBuffer getBuffer() { return mBuffer; }
@Override @Override

Просмотреть файл

@ -103,7 +103,7 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
mScreenSize = new IntSize(1, 1); mScreenSize = new IntSize(1, 1);
mBuffer = ByteBuffer.allocateDirect(mWidth * mHeight * 2); mBuffer = GeckoAppShell.allocateDirectBuffer(mWidth * mHeight * 2);
mCairoImage = new CairoImage() { mCairoImage = new CairoImage() {
@Override @Override
@ -119,6 +119,17 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
mTileLayer = new SingleTileLayer(mCairoImage); mTileLayer = new SingleTileLayer(mCairoImage);
} }
protected void finalize() throws Throwable {
try {
if (mBuffer != null)
GeckoAppShell.freeDirectBuffer(mBuffer);
mBuffer = null;
} finally {
super.finalize();
}
}
/** Attaches the root layer to the layer controller so that Gecko appears. */ /** Attaches the root layer to the layer controller so that Gecko appears. */
@Override @Override
public void setLayerController(LayerController layerController) { public void setLayerController(LayerController layerController) {
@ -151,29 +162,23 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
mGeckoViewport = new ViewportMetrics(viewportObject); mGeckoViewport = new ViewportMetrics(viewportObject);
mGeckoViewport.setSize(viewportSize); mGeckoViewport.setSize(viewportSize);
mTileLayer.setOrigin(PointUtils.round(mGeckoViewport.getDisplayportOrigin())); LayerController controller = getLayerController();
synchronized (controller) {
PointF displayportOrigin = mGeckoViewport.getDisplayportOrigin();
mTileLayer.setOrigin(PointUtils.round(displayportOrigin));
mTileLayer.setResolution(mGeckoViewport.getZoomFactor()); mTileLayer.setResolution(mGeckoViewport.getZoomFactor());
// Make sure LayerController metrics changes only happen in the
// UI thread.
final LayerController controller = getLayerController();
if (controller != null) {
controller.post(new Runnable() {
@Override
public void run() {
if (onlyUpdatePageSize) { if (onlyUpdatePageSize) {
// Don't adjust page size when zooming unless zoom levels are // Don't adjust page size when zooming unless zoom levels are
// approximately equal. // approximately equal.
if (FloatUtils.fuzzyEquals(controller.getZoomFactor(), mGeckoViewport.getZoomFactor())) if (FloatUtils.fuzzyEquals(controller.getZoomFactor(),
mGeckoViewport.getZoomFactor()))
controller.setPageSize(mGeckoViewport.getPageSize()); controller.setPageSize(mGeckoViewport.getPageSize());
} else { } else {
controller.setViewportMetrics(mGeckoViewport); controller.setViewportMetrics(mGeckoViewport);
controller.notifyPanZoomControllerOfGeometryChange(true); controller.notifyPanZoomControllerOfGeometryChange(true);
} }
} }
});
}
} catch (JSONException e) { } catch (JSONException e) {
Log.e(LOGTAG, "Bad viewport description: " + viewportDescription); Log.e(LOGTAG, "Bad viewport description: " + viewportDescription);
throw new RuntimeException(e); throw new RuntimeException(e);
@ -209,7 +214,7 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
b.copyPixelsFromBuffer(mBuffer.asIntBuffer()); b.copyPixelsFromBuffer(mBuffer.asIntBuffer());
return b; return b;
} catch (OutOfMemoryError oom) { } catch (OutOfMemoryError oom) {
Log.e(LOGTAG, "Unable to create bitmap", oom); Log.w(LOGTAG, "Unable to create bitmap", oom);
return null; return null;
} }
} }

Просмотреть файл

@ -58,12 +58,13 @@ import android.view.GestureDetector;
import android.view.ScaleGestureDetector; import android.view.ScaleGestureDetector;
import android.view.View.OnTouchListener; import android.view.View.OnTouchListener;
import java.lang.Math; import java.lang.Math;
import java.util.ArrayList;
/** /**
* The layer controller manages a tile that represents the visible page. It does panning and * The layer controller manages a tile that represents the visible page. It does panning and
* zooming natively by delegating to a panning/zooming controller. Touch events can be dispatched * zooming natively by delegating to a panning/zooming controller. Touch events can be dispatched
* to a higher-level view. * to a higher-level view.
*
* Many methods require that the monitor be held, with a synchronized (controller) { ... } block.
*/ */
public class LayerController { public class LayerController {
private static final String LOGTAG = "GeckoLayerController"; private static final String LOGTAG = "GeckoLayerController";
@ -155,7 +156,8 @@ public class LayerController {
} }
/** /**
* The view calls this to indicate that the viewport changed size. * The view calls this function to indicate that the viewport changed size. It must hold the
* monitor while calling it.
* *
* TODO: Refactor this to use an interface. Expose that interface only to the view and not * TODO: Refactor this to use an interface. Expose that interface only to the view and not
* to the layer client. That way, the layer client won't be tempted to call this, which might * to the layer client. That way, the layer client won't be tempted to call this, which might
@ -173,6 +175,7 @@ public class LayerController {
mView.requestRender(); mView.requestRender();
} }
/** Scrolls the viewport to the given point. You must hold the monitor while calling this. */
public void scrollTo(PointF point) { public void scrollTo(PointF point) {
mViewportMetrics.setOrigin(point); mViewportMetrics.setOrigin(point);
notifyLayerClientOfGeometryChange(); notifyLayerClientOfGeometryChange();
@ -181,6 +184,7 @@ public class LayerController {
mView.requestRender(); mView.requestRender();
} }
/** Scrolls the viewport by the given offset. You must hold the monitor while calling this. */
public void scrollBy(PointF point) { public void scrollBy(PointF point) {
PointF origin = mViewportMetrics.getOrigin(); PointF origin = mViewportMetrics.getOrigin();
origin.offset(point.x, point.y); origin.offset(point.x, point.y);
@ -192,6 +196,7 @@ public class LayerController {
mView.requestRender(); mView.requestRender();
} }
/** Sets the current viewport. You must hold the monitor while calling this. */
public void setViewport(RectF viewport) { public void setViewport(RectF viewport) {
mViewportMetrics.setViewport(viewport); mViewportMetrics.setViewport(viewport);
notifyLayerClientOfGeometryChange(); notifyLayerClientOfGeometryChange();
@ -200,6 +205,7 @@ public class LayerController {
mView.requestRender(); mView.requestRender();
} }
/** Sets the current page size. You must hold the monitor while calling this. */
public void setPageSize(FloatSize size) { public void setPageSize(FloatSize size) {
if (mViewportMetrics.getPageSize().fuzzyEquals(size)) if (mViewportMetrics.getPageSize().fuzzyEquals(size))
return; return;
@ -215,7 +221,8 @@ public class LayerController {
/** /**
* Sets the entire viewport metrics at once. This function does not notify the layer client or * Sets the entire viewport metrics at once. This function does not notify the layer client or
* the pan/zoom controller, so you will need to call notifyLayerClientOfGeometryChange() or * the pan/zoom controller, so you will need to call notifyLayerClientOfGeometryChange() or
* notifyPanZoomControllerOfGeometryChange() after calling this. * notifyPanZoomControllerOfGeometryChange() after calling this. You must hold the monitor
* while calling this.
*/ */
public void setViewportMetrics(ViewportMetrics viewport) { public void setViewportMetrics(ViewportMetrics viewport) {
mViewportMetrics = new ViewportMetrics(viewport); mViewportMetrics = new ViewportMetrics(viewport);
@ -223,10 +230,15 @@ public class LayerController {
mView.requestRender(); mView.requestRender();
} }
/** Scales the viewport. You must hold the monitor while calling this. */
public void scaleTo(float zoomFactor) { public void scaleTo(float zoomFactor) {
scaleWithFocus(zoomFactor, new PointF(0,0)); scaleWithFocus(zoomFactor, new PointF(0,0));
} }
/**
* Scales the viewport, keeping the given focus point in the same place before and after the
* scale operation. You must hold the monitor while calling this.
*/
public void scaleWithFocus(float zoomFactor, PointF focus) { public void scaleWithFocus(float zoomFactor, PointF focus) {
mViewportMetrics.scaleTo(zoomFactor, focus); mViewportMetrics.scaleTo(zoomFactor, focus);
@ -237,6 +249,10 @@ public class LayerController {
mView.requestRender(); mView.requestRender();
} }
/**
* Sets the viewport origin and scales in one operation. You must hold the monitor while
* calling this.
*/
public void scaleWithOrigin(float zoomFactor, PointF origin) { public void scaleWithOrigin(float zoomFactor, PointF origin) {
mViewportMetrics.setOrigin(origin); mViewportMetrics.setOrigin(origin);
scaleTo(zoomFactor); scaleTo(zoomFactor);

Просмотреть файл

@ -132,9 +132,6 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
/** /**
* Called whenever a new frame is about to be drawn. * Called whenever a new frame is about to be drawn.
*
* FIXME: This is racy. Layers and page sizes can be modified by the pan/zoom controller while
* this is going on.
*/ */
public void onDrawFrame(GL10 gl) { public void onDrawFrame(GL10 gl) {
long frameStartTime = SystemClock.uptimeMillis(); long frameStartTime = SystemClock.uptimeMillis();
@ -142,8 +139,11 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
TextureReaper.get().reap(gl); TextureReaper.get().reap(gl);
LayerController controller = mView.getController(); LayerController controller = mView.getController();
RenderContext screenContext = createScreenContext();
synchronized (controller) {
Layer rootLayer = controller.getRoot(); Layer rootLayer = controller.getRoot();
RenderContext screenContext = createScreenContext(), pageContext = createPageContext(); RenderContext pageContext = createPageContext();
if (!pageContext.fuzzyEquals(mLastPageContext)) { if (!pageContext.fuzzyEquals(mLastPageContext)) {
// the viewport or page changed, so show the scrollbars again // the viewport or page changed, so show the scrollbars again
@ -173,7 +173,8 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
/* Draw the drop shadow, if we need to. */ /* Draw the drop shadow, if we need to. */
Rect pageRect = getPageRect(); Rect pageRect = getPageRect();
RectF untransformedPageRect = new RectF(0.0f, 0.0f, pageRect.width(), pageRect.height()); RectF untransformedPageRect = new RectF(0.0f, 0.0f, pageRect.width(),
pageRect.height());
if (!untransformedPageRect.contains(controller.getViewport())) if (!untransformedPageRect.contains(controller.getViewport()))
mShadowLayer.draw(pageContext); mShadowLayer.draw(pageContext);
@ -199,6 +200,7 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
/* Draw the horizontal scrollbar. */ /* Draw the horizontal scrollbar. */
if (pageRect.width() > screenSize.width) if (pageRect.width() > screenSize.width)
mHorizScrollLayer.draw(pageContext); mHorizScrollLayer.draw(pageContext);
}
/* Draw the FPS. */ /* Draw the FPS. */
if (mShowFrameRate) { if (mShowFrameRate) {

Просмотреть файл

@ -51,6 +51,7 @@ import android.util.Log;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.opengles.GL10;
import org.mozilla.gecko.FloatUtils; import org.mozilla.gecko.FloatUtils;
import org.mozilla.gecko.GeckoAppShell;
/** /**
* Draws a small rect. This is scaled to become a scrollbar. * Draws a small rect. This is scaled to become a scrollbar.
@ -74,6 +75,7 @@ public class ScrollbarLayer extends TileLayer {
private final Bitmap mBitmap; private final Bitmap mBitmap;
private final Canvas mCanvas; private final Canvas mCanvas;
private float mOpacity; private float mOpacity;
private boolean mFinalized = false;
private ScrollbarLayer(CairoImage image, boolean vertical, ByteBuffer buffer) { private ScrollbarLayer(CairoImage image, boolean vertical, ByteBuffer buffer) {
super(false, image); super(false, image);
@ -84,11 +86,22 @@ public class ScrollbarLayer extends TileLayer {
mCanvas = new Canvas(mBitmap); mCanvas = new Canvas(mBitmap);
} }
protected void finalize() throws Throwable {
try {
if (!mFinalized && mBuffer != null)
GeckoAppShell.freeDirectBuffer(mBuffer);
mFinalized = true;
} finally {
super.finalize();
}
}
public static ScrollbarLayer create(boolean vertical) { public static ScrollbarLayer create(boolean vertical) {
// just create an empty image for now, it will get drawn // just create an empty image for now, it will get drawn
// on demand anyway // on demand anyway
int imageSize = nextPowerOfTwo(BAR_SIZE); int imageSize = nextPowerOfTwo(BAR_SIZE);
ByteBuffer buffer = ByteBuffer.allocateDirect(imageSize * imageSize * 4); ByteBuffer buffer = GeckoAppShell.allocateDirectBuffer(imageSize * imageSize * 4);
CairoImage image = new BufferedCairoImage(buffer, imageSize, imageSize, CairoImage.FORMAT_ARGB32); CairoImage image = new BufferedCairoImage(buffer, imageSize, imageSize, CairoImage.FORMAT_ARGB32);
return new ScrollbarLayer(image, vertical, buffer); return new ScrollbarLayer(image, vertical, buffer);
} }

Просмотреть файл

@ -37,6 +37,7 @@
package org.mozilla.gecko.gfx; package org.mozilla.gecko.gfx;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.gfx.BufferedCairoImage; import org.mozilla.gecko.gfx.BufferedCairoImage;
import org.mozilla.gecko.gfx.CairoImage; import org.mozilla.gecko.gfx.CairoImage;
import org.mozilla.gecko.gfx.IntSize; import org.mozilla.gecko.gfx.IntSize;
@ -56,6 +57,7 @@ import java.nio.IntBuffer;
public class TextLayer extends SingleTileLayer { public class TextLayer extends SingleTileLayer {
private final ByteBuffer mBuffer; private final ByteBuffer mBuffer;
private final IntSize mSize; private final IntSize mSize;
private boolean mFinalized = false;
/* /*
* This awkward pattern is necessary due to Java's restrictions on when one can call superclass * This awkward pattern is necessary due to Java's restrictions on when one can call superclass
@ -68,8 +70,18 @@ public class TextLayer extends SingleTileLayer {
renderText(text); renderText(text);
} }
protected void finalize() throws Throwable {
try {
if (!mFinalized && mBuffer != null)
GeckoAppShell.freeDirectBuffer(mBuffer);
mFinalized = true;
} finally {
super.finalize();
}
}
public static TextLayer create(IntSize size, String text) { public static TextLayer create(IntSize size, String text) {
ByteBuffer buffer = ByteBuffer.allocateDirect(size.width * size.height * 4); ByteBuffer buffer = GeckoAppShell.allocateDirectBuffer(size.width * size.height * 4);
BufferedCairoImage image = new BufferedCairoImage(buffer, size.width, size.height, BufferedCairoImage image = new BufferedCairoImage(buffer, size.width, size.height,
CairoImage.FORMAT_ARGB32); CairoImage.FORMAT_ARGB32);
return new TextLayer(buffer, image, size, text); return new TextLayer(buffer, image, size, text);

Просмотреть файл

@ -168,15 +168,5 @@ public abstract class TileLayer extends Layer {
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, repeatMode); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, repeatMode);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, repeatMode); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, repeatMode);
} }
protected static FloatBuffer createBuffer(float[] values) {
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(values.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();
floatBuffer.put(values);
floatBuffer.position(0);
return floatBuffer;
}
} }

Просмотреть файл

@ -62,6 +62,10 @@
<!ENTITY pref_clear_history_confirm "Browsing history will be deleted"> <!ENTITY pref_clear_history_confirm "Browsing history will be deleted">
<!ENTITY pref_clear_private_data "Clear private data"> <!ENTITY pref_clear_private_data "Clear private data">
<!ENTITY pref_clear_private_data_confirm "Browsing settings, including passwords and cookies, will be deleted"> <!ENTITY pref_clear_private_data_confirm "Browsing settings, including passwords and cookies, will be deleted">
<!ENTITY pref_enable_flash "Enable Flash">
<!ENTITY pref_enable_flash_yes "Yes">
<!ENTITY pref_enable_flash_tap_to_play "Tap To Play">
<!ENTITY pref_enable_flash_no "No">
<!ENTITY quit "Quit"> <!ENTITY quit "Quit">

Просмотреть файл

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="pref_enable_flash_entries">
<item>@string/pref_enable_flash_yes</item>
<item>@string/pref_enable_flash_tap_to_play</item>
<item>@string/pref_enable_flash_no</item>
</string-array>
<string-array name="pref_enable_flash_values">
<item>1</item>
<item>2</item>
<item>0</item>
</string-array>
</resources>

Просмотреть файл

@ -19,6 +19,12 @@
android:title="@string/pref_char_encoding" android:title="@string/pref_char_encoding"
android:persistent="false" /> android:persistent="false" />
<ListPreference android:key="plugin.enable"
android:title="@string/pref_enable_flash"
android:entries="@array/pref_enable_flash_entries"
android:entryValues="@array/pref_enable_flash_values"
android:persistent="false" />
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory android:title="@string/pref_category_privacy"> <PreferenceCategory android:title="@string/pref_category_privacy">

Просмотреть файл

@ -68,6 +68,10 @@
<string name="pref_clear_history_confirm">&pref_clear_history_confirm;</string> <string name="pref_clear_history_confirm">&pref_clear_history_confirm;</string>
<string name="pref_clear_private_data">&pref_clear_private_data;</string> <string name="pref_clear_private_data">&pref_clear_private_data;</string>
<string name="pref_clear_private_data_confirm">&pref_clear_private_data_confirm;</string> <string name="pref_clear_private_data_confirm">&pref_clear_private_data_confirm;</string>
<string name="pref_enable_flash">&pref_enable_flash;</string>
<string name="pref_enable_flash_yes">&pref_enable_flash_yes;</string>
<string name="pref_enable_flash_tap_to_play">&pref_enable_flash_tap_to_play;</string>
<string name="pref_enable_flash_no">&pref_enable_flash_no;</string>
<string name="reload">&reload;</string> <string name="reload">&reload;</string>
<string name="forward">&forward;</string> <string name="forward">&forward;</string>

Просмотреть файл

@ -560,8 +560,10 @@ public class PanZoomController
GeckoAppShell.sendEventToGecko(e); GeckoAppShell.sendEventToGecko(e);
mOverrideScrollAck = false; mOverrideScrollAck = false;
} else { } else {
synchronized (mController) {
mController.scrollBy(new PointF(mX.displacement, mY.displacement)); mController.scrollBy(new PointF(mX.displacement, mY.displacement));
} }
}
mX.displacement = mY.displacement = 0; mX.displacement = mY.displacement = 0;
} }
@ -592,20 +594,24 @@ public class PanZoomController
/* Performs one frame of a bounce animation. */ /* Performs one frame of a bounce animation. */
private void advanceBounce() { private void advanceBounce() {
synchronized (mController) {
float t = EASE_OUT_ANIMATION_FRAMES[mBounceFrame]; float t = EASE_OUT_ANIMATION_FRAMES[mBounceFrame];
ViewportMetrics newMetrics = mBounceStartMetrics.interpolate(mBounceEndMetrics, t); ViewportMetrics newMetrics = mBounceStartMetrics.interpolate(mBounceEndMetrics, t);
mController.setViewportMetrics(newMetrics); mController.setViewportMetrics(newMetrics);
mController.notifyLayerClientOfGeometryChange(); mController.notifyLayerClientOfGeometryChange();
mBounceFrame++; mBounceFrame++;
} }
}
/* Concludes a bounce animation and snaps the viewport into place. */ /* Concludes a bounce animation and snaps the viewport into place. */
private void finishBounce() { private void finishBounce() {
synchronized (mController) {
mController.setViewportMetrics(mBounceEndMetrics); mController.setViewportMetrics(mBounceEndMetrics);
mController.notifyLayerClientOfGeometryChange(); mController.notifyLayerClientOfGeometryChange();
mBounceFrame = -1; mBounceFrame = -1;
} }
} }
}
// The callback that performs the fling animation. // The callback that performs the fling animation.
private class FlingRunnable implements Runnable { private class FlingRunnable implements Runnable {
@ -881,11 +887,14 @@ public class PanZoomController
else else
spanRatio = 1.0f - (1.0f - spanRatio) * resistance; spanRatio = 1.0f - (1.0f - spanRatio) * resistance;
synchronized (mController) {
float newZoomFactor = mController.getZoomFactor() * spanRatio; float newZoomFactor = mController.getZoomFactor() * spanRatio;
mController.scrollBy(new PointF(mLastZoomFocus.x - detector.getFocusX(), mController.scrollBy(new PointF(mLastZoomFocus.x - detector.getFocusX(),
mLastZoomFocus.y - detector.getFocusY())); mLastZoomFocus.y - detector.getFocusY()));
mController.scaleWithFocus(newZoomFactor, new PointF(detector.getFocusX(), detector.getFocusY())); PointF focus = new PointF(detector.getFocusX(), detector.getFocusY());
mController.scaleWithFocus(newZoomFactor, focus);
}
mLastZoomFocus.set(detector.getFocusX(), detector.getFocusY()); mLastZoomFocus.set(detector.getFocusX(), detector.getFocusY());

Просмотреть файл

@ -205,6 +205,7 @@ var BrowserApp = {
IndexedDB.init(); IndexedDB.init();
XPInstallObserver.init(); XPInstallObserver.init();
ConsoleAPI.init(); ConsoleAPI.init();
ClipboardHelper.init();
// Init LoginManager // Init LoginManager
Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager); Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
@ -435,6 +436,16 @@ var BrowserApp = {
name: prefName name: prefName
}; };
// The plugin pref is actually two separate prefs, so
// we need to handle it differently
if (prefName == "plugin.enable") {
// Use a string type for java's ListPreference
pref.type = "string";
pref.value = PluginHelper.getPluginPreference();
prefs.push(pref);
continue;
}
try { try {
switch (Services.prefs.getPrefType(prefName)) { switch (Services.prefs.getPrefType(prefName)) {
case Ci.nsIPrefBranch.PREF_BOOL: case Ci.nsIPrefBranch.PREF_BOOL:
@ -490,6 +501,13 @@ var BrowserApp = {
setPreferences: function setPreferences(aPref) { setPreferences: function setPreferences(aPref) {
let json = JSON.parse(aPref); let json = JSON.parse(aPref);
// The plugin pref is actually two separate prefs, so
// we need to handle it differently
if (json.name == "plugin.enable") {
PluginHelper.setPluginPreference(json.value);
return;
}
// when sending to java, we normalized special preferences that use // when sending to java, we normalized special preferences that use
// integers and strings to represent booleans. here, we convert them back // integers and strings to represent booleans. here, we convert them back
// to their actual types so we can store them. // to their actual types so we can store them.
@ -753,12 +771,6 @@ var NativeWindow = {
BrowserApp.addTab(url, { selected: false }); BrowserApp.addTab(url, { selected: false });
}); });
this.add(Strings.browser.GetStringFromName("contextmenu.changeInputMethod"),
this.textContext,
function(aTarget) {
Cc["@mozilla.org/imepicker;1"].getService(Ci.nsIIMEPicker).show();
});
this.add(Strings.browser.GetStringFromName("contextmenu.fullScreen"), this.add(Strings.browser.GetStringFromName("contextmenu.fullScreen"),
this.SelectorContext("video:not(:-moz-full-screen)"), this.SelectorContext("video:not(:-moz-full-screen)"),
function(aTarget) { function(aTarget) {
@ -1381,12 +1393,16 @@ Tab.prototype = {
let browser = BrowserApp.getBrowserForWindow(contentWin); let browser = BrowserApp.getBrowserForWindow(contentWin);
let uri = browser.currentURI.spec; let uri = browser.currentURI.spec;
let documentURI = browser.contentDocument.documentURIObject.spec;
let contentType = browser.contentDocument.contentType;
let message = { let message = {
gecko: { gecko: {
type: "Content:LocationChange", type: "Content:LocationChange",
tabID: this.id, tabID: this.id,
uri: uri uri: uri,
documentURI: documentURI,
contentType: contentType
} }
}; };
@ -2898,6 +2914,83 @@ var ConsoleAPI = {
} }
}; };
var ClipboardHelper = {
init: function() {
NativeWindow.contextmenus.add(Strings.browser.GetStringFromName("contextmenu.copy"), ClipboardHelper.getCopyContext(false), ClipboardHelper.copy.bind(ClipboardHelper));
NativeWindow.contextmenus.add(Strings.browser.GetStringFromName("contextmenu.copyAll"), ClipboardHelper.getCopyContext(true), ClipboardHelper.copy.bind(ClipboardHelper));
NativeWindow.contextmenus.add(Strings.browser.GetStringFromName("contextmenu.selectAll"), NativeWindow.contextmenus.textContext, ClipboardHelper.select.bind(ClipboardHelper));
NativeWindow.contextmenus.add(Strings.browser.GetStringFromName("contextmenu.paste"), ClipboardHelper.pasteContext, ClipboardHelper.paste.bind(ClipboardHelper));
NativeWindow.contextmenus.add(Strings.browser.GetStringFromName("contextmenu.changeInputMethod"), NativeWindow.contextmenus.textContext, ClipboardHelper.inputMethod.bind(ClipboardHelper));
},
get clipboardHelper() {
delete this.clipboardHelper;
return this.clipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
},
get clipboard() {
delete this.clipboard;
return this.clipboard = Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard);
},
copy: function(aElement) {
let selectionStart = aElement.selectionStart;
let selectionEnd = aElement.selectionEnd;
if (selectionStart != selectionEnd) {
string = aElement.value.slice(selectionStart, selectionEnd);
this.clipboardHelper.copyString(string);
} else {
this.clipboardHelper.copyString(aElement.value);
}
},
select: function(aElement) {
if (!aElement || !(aElement instanceof Ci.nsIDOMNSEditableElement))
return;
let target = aElement.QueryInterface(Ci.nsIDOMNSEditableElement);
target.editor.selectAll();
target.focus();
},
paste: function(aElement) {
if (!aElement || !(aElement instanceof Ci.nsIDOMNSEditableElement))
return;
let target = aElement.QueryInterface(Ci.nsIDOMNSEditableElement);
target.editor.paste(Ci.nsIClipboard.kGlobalClipboard);
target.focus();
},
inputMethod: function(aElement) {
Cc["@mozilla.org/imepicker;1"].getService(Ci.nsIIMEPicker).show();
},
getCopyContext: function(isCopyAll) {
return {
matches: function(aElement) {
if (NativeWindow.contextmenus.textContext.matches(aElement)) {
let selectionStart = aElement.selectionStart;
let selectionEnd = aElement.selectionEnd;
if (selectionStart != selectionEnd)
return true;
else if (isCopyAll)
return true;
}
return false;
}
}
},
pasteContext: {
matches: function(aElement) {
if (NativeWindow.contextmenus.textContext.matches(aElement)) {
let flavors = ["text/unicode"];
return ClipboardHelper.clipboard.hasDataMatchingFlavors(flavors, flavors.length, Ci.nsIClipboard.kGlobalClipboard);
}
return false;
}
}
}
var PluginHelper = { var PluginHelper = {
showDoorHanger: function(aTab) { showDoorHanger: function(aTab) {
let message = Strings.browser.GetStringFromName("clickToPlayFlash.message"); let message = Strings.browser.GetStringFromName("clickToPlayFlash.message");
@ -2926,6 +3019,32 @@ var PluginHelper = {
} }
}, },
getPluginPreference: function getPluginPreference() {
let pluginDisable = Services.prefs.getBoolPref("plugin.disable");
if (pluginDisable)
return "0";
let clickToPlay = Services.prefs.getBoolPref("plugins.click_to_play");
return clickToPlay ? "2" : "1";
},
setPluginPreference: function setPluginPreference(aValue) {
switch (aValue) {
case "0": // Enable Plugins = No
Services.prefs.setBoolPref("plugin.disable", true);
Services.prefs.clearUserPref("plugins.click_to_play");
break;
case "1": // Enable Plugins = Yes
Services.prefs.clearUserPref("plugin.disable");
Services.prefs.setBoolPref("plugins.click_to_play", false);
break;
case "2": // Enable Plugins = Tap to Play (default)
Services.prefs.clearUserPref("plugin.disable");
Services.prefs.clearUserPref("plugins.click_to_play");
break;
}
},
// Mostly copied from /browser/base/content/browser.js // Mostly copied from /browser/base/content/browser.js
addPluginClickCallback: function (plugin, callbackName /*callbackArgs...*/) { addPluginClickCallback: function (plugin, callbackName /*callbackArgs...*/) {
// XXX just doing (callback)(arg) was giving a same-origin error. bug? // XXX just doing (callback)(arg) was giving a same-origin error. bug?

Просмотреть файл

@ -11,18 +11,6 @@
<!ENTITY newtab.label "New Tab"> <!ENTITY newtab.label "New Tab">
<!ENTITY closetab.label "Close Tab"> <!ENTITY closetab.label "Close Tab">
<!ENTITY cut.label "Cut">
<!ENTITY copy.label "Copy">
<!ENTITY copyAll.label "Copy All">
<!ENTITY copylink.label "Copy Link Location">
<!ENTITY paste.label "Paste">
<!ENTITY pasteAndGo.label "Paste &amp; Go">
<!ENTITY delete.label "Delete">
<!ENTITY selectAll.label "Select All">
<!ENTITY noSuggestions.label "(No suggestions)">
<!ENTITY addToDictionary.label "Add to Dictionary">
<!ENTITY inputMethod.label "Select Input Method">
<!ENTITY allPagesHeader.label "All Pages"> <!ENTITY allPagesHeader.label "All Pages">
<!ENTITY bookmarksHeader.label "Bookmarks"> <!ENTITY bookmarksHeader.label "Bookmarks">
<!ENTITY historyHeader.label "History"> <!ENTITY historyHeader.label "History">

Просмотреть файл

@ -256,6 +256,11 @@ contextmenu.openInNewTab=Open Link in New Tab
contextmenu.changeInputMethod=Select Input Method contextmenu.changeInputMethod=Select Input Method
contextmenu.fullScreen=Full Screen contextmenu.fullScreen=Full Screen
contextmenu.copy=Copy
contextmenu.copyAll=Copy All
contextmenu.selectAll=Select All
contextmenu.paste=Paste
# Select UI # Select UI
selectHelper.closeMultipleSelectDialog=Done selectHelper.closeMultipleSelectDialog=Done

Просмотреть файл

@ -359,8 +359,6 @@ FormHistory.prototype = {
}, },
get dbConnection() { get dbConnection() {
let connection;
// Make sure dbConnection can't be called from now to prevent infinite loops. // Make sure dbConnection can't be called from now to prevent infinite loops.
delete FormHistory.prototype.dbConnection; delete FormHistory.prototype.dbConnection;

Просмотреть файл

@ -58,7 +58,7 @@
<xul:spacer flex="1"/> <xul:spacer flex="1"/>
<xul:box class="icon"/> <xul:box class="icon"/>
<html:div class="msg msgUnsupported">&missingPlugin;</html:div> <html:div class="msg msgUnsupported">&missingPlugin;</html:div>
<html:div class="msg msgClickToPlay"><html:a class="clickToPlayLink" href="">&clickToPlayPlugin;</html:a></html:div> <html:div class="msg msgClickToPlay">&clickToPlayPlugin;</html:div>
<html:div class="msg msgDisabled">&disabledPlugin;</html:div> <html:div class="msg msgDisabled">&disabledPlugin;</html:div>
<html:div class="msg msgBlocked">&blockedPlugin.label;</html:div> <html:div class="msg msgBlocked">&blockedPlugin.label;</html:div>
<html:div class="msg msgCrashed"><!-- set at runtime --></html:div> <html:div class="msg msgCrashed"><!-- set at runtime --></html:div>

Просмотреть файл

@ -1049,11 +1049,11 @@ class nsRefPtr
return get(); return get();
} }
nsCOMPtr_base::nsDerivedSafe<T>* T*
operator->() const operator->() const
{ {
NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsRefPtr with operator->()."); NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsRefPtr with operator->().");
return reinterpret_cast<nsCOMPtr_base::nsDerivedSafe<T>*> (get()); return get();
} }
// This operator is needed for gcc <= 4.0.* and for Sun Studio; it // This operator is needed for gcc <= 4.0.* and for Sun Studio; it

Просмотреть файл

@ -429,45 +429,6 @@ nsCOMPtr_base
{ {
public: public:
template <class T>
class
NS_STACK_CLASS
nsDerivedSafe : public T
/*
No client should ever see or have to type the name of this class. It is the
artifact that makes it a compile-time error to call |AddRef| and |Release|
on a |nsCOMPtr|. DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE.
See |nsCOMPtr::operator->| and |nsRefPtr::operator->|.
*/
{
private:
NS_METHOD_(nsrefcnt) AddRef();
NS_METHOD_(nsrefcnt) Release();
//using T::AddRef;
//using T::Release;
/*
We could use |using| above, except that gcc 4.2 on Mac has a bug
which causes |using| be unable to make the function private in
templated derived classes (see bug 689397).
*/
~nsDerivedSafe(); // NOT TO BE IMPLEMENTED
/*
This dtor is added to make this class compatible with GCC 4.6.
If the destructor for T is private, nsDerivedSafe's unimplemented destructor
will be implicitly-declared by the compiler as deleted.
Therefore this explicit dtor exists to avoid that deletion. See bug 689301.
*/
protected:
nsDerivedSafe(); // NOT TO BE IMPLEMENTED
/*
This ctor exists to avoid compile errors and warnings about nsDerivedSafe using the
default ctor but inheriting classes without an empty ctor. See bug 209667.
*/
};
nsCOMPtr_base( nsISupports* rawPtr = 0 ) nsCOMPtr_base( nsISupports* rawPtr = 0 )
: mRawPtr(rawPtr) : mRawPtr(rawPtr)
{ {
@ -840,11 +801,11 @@ class nsCOMPtr MOZ_FINAL
return get(); return get();
} }
nsCOMPtr_base::nsDerivedSafe<T>* T*
operator->() const operator->() const
{ {
NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->()."); NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
return reinterpret_cast<nsCOMPtr_base::nsDerivedSafe<T>*> (get()); return get();
} }
nsCOMPtr<T>* nsCOMPtr<T>*
@ -1147,11 +1108,11 @@ class nsCOMPtr<nsISupports>
return get(); return get();
} }
nsDerivedSafe<nsISupports>* nsISupports*
operator->() const operator->() const
{ {
NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->()."); NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
return reinterpret_cast<nsCOMPtr_base::nsDerivedSafe<nsISupports>*> (get()); return get();
} }
nsCOMPtr<nsISupports>* nsCOMPtr<nsISupports>*