diff --git a/browser/components/migration/src/Makefile.in b/browser/components/migration/src/Makefile.in index 63bbf784473b..26cdb0a8ffa2 100644 --- a/browser/components/migration/src/Makefile.in +++ b/browser/components/migration/src/Makefile.in @@ -49,16 +49,15 @@ USE_STATIC_LIBS = 1 endif -CPPSRCS = nsBrowserProfileMigratorUtils.cpp \ - $(NULL) - ifeq ($(OS_ARCH)_$(GNU_CXX),WINNT_) CPPSRCS += nsIEProfileMigrator.cpp \ + nsBrowserProfileMigratorUtils.cpp \ $(NULL) endif ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) CPPSRCS += nsSafariProfileMigrator.cpp \ + nsBrowserProfileMigratorUtils.cpp \ $(NULL) endif diff --git a/build/unix/build-toolchain/build-gcc.py b/build/unix/build-toolchain/build-gcc.py index 19fd67d2b8f3..10b98c8a9210 100755 --- a/build/unix/build-toolchain/build-gcc.py +++ b/build/unix/build-toolchain/build-gcc.py @@ -98,7 +98,14 @@ def build_tar_package(tar, name, base, directory): ############################################## -source_dir = os.path.realpath('src') +# The directories end up in the debug info, so the easy way of getting +# a reproducible build is to run it in a know absolute directory. +# We use a directory in /builds/slave because the mozilla infrastructure +# cleans it up automatically. +base_dir = "/builds/slave/moz-toolschain" + +source_dir = base_dir + "/src" +build_dir = base_dir + "/build" def build_source_dir(prefix, version): return source_dir + '/' + prefix + version @@ -133,8 +140,6 @@ mpfr_source_tar = download_uri(mpfr_source_uri) gmp_source_tar = download_uri(gmp_source_uri) gcc_source_tar = download_uri(gcc_source_uri) -build_dir = os.path.realpath('build') - binutils_source_dir = build_source_dir('binutils-', binutils_version) glibc_source_dir = build_source_dir('glibc-', glibc_version) tar_source_dir = build_source_dir('tar-', tar_version) @@ -144,7 +149,7 @@ gmp_source_dir = build_source_dir('gmp-', gmp_version) gcc_source_dir = build_source_dir('gcc-', gcc_version) if not os.path.exists(source_dir): - os.mkdir(source_dir) + os.makedirs(source_dir) extract(binutils_source_tar, source_dir) patch('binutils-deterministic.patch', 1, binutils_source_dir) extract(glibc_source_tar, source_dir) @@ -160,7 +165,7 @@ if not os.path.exists(source_dir): if os.path.exists(build_dir): shutil.rmtree(build_dir) -os.mkdir(build_dir) +os.makedirs(build_dir) tar_inst_dir = build_dir + '/tar_inst' build_tar(build_dir, tar_inst_dir) diff --git a/config/system-headers b/config/system-headers index 6544f6b7ed03..a4c34167f196 100644 --- a/config/system-headers +++ b/config/system-headers @@ -268,6 +268,11 @@ freetype/ftoutln.h freetype/ttnameid.h freetype/tttables.h freetype/t1tables.h +freetype/ftlcdfil.h +freetype/ftsizes.h +freetype/ftadvanc.h +freetype/ftbitmap.h +freetype/ftxf86.h fribidi/fribidi.h FSp_fopen.h fstream diff --git a/configure.in b/configure.in index 0c8c153221bc..3e5d6fe05ae8 100644 --- a/configure.in +++ b/configure.in @@ -8056,7 +8056,7 @@ dnl ======================================================== dnl Graphics checks. dnl ======================================================== -if test "${OS_ARCH}" = "Darwin" -o "${MOZ_WIDGET_TOOLKIT}" = "android"; then +if test "${OS_ARCH}" = "Darwin" -o "${MOZ_WIDGET_TOOLKIT}" = "android" -o "${MOZ_WIDGET_TOOLKIT}" = "gtk2"; then MOZ_ENABLE_SKIA=1 else MOZ_ENABLE_SKIA= diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index 62f80c181441..519e0a72855c 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -2124,13 +2124,6 @@ public: DOUBLE_HI32_EXPMASK | DOUBLE_HI32_MANTMASK}} #endif -#if defined(XP_WIN) -#define DOUBLE_COMPARE(LVAL, OP, RVAL) \ - (!DOUBLE_IS_NaN(LVAL) && !DOUBLE_IS_NaN(RVAL) && (LVAL) OP (RVAL)) -#else -#define DOUBLE_COMPARE(LVAL, OP, RVAL) ((LVAL) OP (RVAL)) -#endif - /* * In the following helper macros we exploit the fact that the result of a * series of additions will not be finite if any one of the operands in the diff --git a/content/base/src/nsImageLoadingContent.cpp b/content/base/src/nsImageLoadingContent.cpp index bc565bee3abc..c7acfb4a11fe 100644 --- a/content/base/src/nsImageLoadingContent.cpp +++ b/content/base/src/nsImageLoadingContent.cpp @@ -60,6 +60,7 @@ #include "nsThreadUtils.h" #include "nsNetUtil.h" #include "nsAsyncDOMEvent.h" +#include "nsGenericHTMLElement.h" #include "nsIPresShell.h" #include "nsEventStates.h" @@ -774,9 +775,9 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI, nsLoadFlags loadFlags = aLoadFlags; PRInt32 corsmode = GetCORSMode(); - if (corsmode == nsImageLoadingContent::CORS_ANONYMOUS) { + if (corsmode == nsGenericHTMLElement::CORS_ANONYMOUS) { loadFlags |= imgILoader::LOAD_CORS_ANONYMOUS; - } else if (corsmode == nsImageLoadingContent::CORS_USE_CREDENTIALS) { + } else if (corsmode == nsGenericHTMLElement::CORS_USE_CREDENTIALS) { loadFlags |= imgILoader::LOAD_CORS_USE_CREDENTIALS; } @@ -1186,8 +1187,8 @@ nsImageLoadingContent::CreateStaticImageClone(nsImageLoadingContent* aDest) cons aDest->mSuppressed = mSuppressed; } -nsImageLoadingContent::CORSMode +nsGenericHTMLElement::CORSMode nsImageLoadingContent::GetCORSMode() { - return CORS_NONE; + return nsGenericHTMLElement::CORS_NONE; } diff --git a/content/base/src/nsImageLoadingContent.h b/content/base/src/nsImageLoadingContent.h index c5aea1966520..415afe9b7a39 100644 --- a/content/base/src/nsImageLoadingContent.h +++ b/content/base/src/nsImageLoadingContent.h @@ -53,6 +53,7 @@ #include "nsContentUtils.h" // NS_CONTENT_DELETE_LIST_MEMBER #include "nsString.h" #include "nsEventStates.h" +#include "nsGenericHTMLElement.h" class nsIURI; class nsIDocument; @@ -70,25 +71,6 @@ public: NS_DECL_IMGIDECODEROBSERVER NS_DECL_NSIIMAGELOADINGCONTENT - enum CORSMode { - /** - * The default of not using CORS to validate cross-origin loads. - */ - CORS_NONE, - - /** - * Validate cross-site loads using CORS, but do not send any credentials - * (cookies, HTTP auth logins, etc) along with the request. - */ - CORS_ANONYMOUS, - - /** - * Validate cross-site loads using CORS, and send credentials such as cookies - * and HTTP auth logins along with the request. - */ - CORS_USE_CREDENTIALS - }; - protected: /** * LoadImage is called by subclasses when the appropriate @@ -201,7 +183,7 @@ protected: * Returns the CORS mode that will be used for all future image loads. The * default implementation returns CORS_NONE unconditionally. */ - virtual CORSMode GetCORSMode(); + virtual nsGenericHTMLElement::CORSMode GetCORSMode(); private: /** diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index 46497671274f..928d022885e4 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -3950,7 +3950,7 @@ WebGLContext::DOMElementToImageSurface(nsIDOMElement *imageOrCanvas, return NS_ERROR_FAILURE; } - // We disallow loading cross-domain images that have not been validated + // We disallow loading cross-domain images and videos that have not been validated // with CORS as WebGL textures. The reason for doing that is that timing // attacks on WebGL shaders are able to retrieve approximations of the // pixel values in WebGL textures; see bug 655987. diff --git a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp index 08fa44aeb7e3..d3f97c0306f8 100644 --- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp @@ -995,7 +995,7 @@ NS_NewCanvasRenderingContext2DAzure(nsIDOMCanvasRenderingContext2D** aResult) !Preferences::GetBool("gfx.canvas.azure.prefer-skia", false)) { return NS_ERROR_NOT_AVAILABLE; } -#elif !defined(XP_MACOSX) && !defined(ANDROID) +#elif !defined(XP_MACOSX) && !defined(ANDROID) && !defined(XP_LINUX) return NS_ERROR_NOT_AVAILABLE; #endif diff --git a/content/canvas/test/crossorigin/Makefile.in b/content/canvas/test/crossorigin/Makefile.in index ce009e1d836b..73df9ac94c50 100644 --- a/content/canvas/test/crossorigin/Makefile.in +++ b/content/canvas/test/crossorigin/Makefile.in @@ -51,6 +51,8 @@ _TEST_FILES = \ image.png \ test_canvas2d_crossorigin.html \ test_webgl_crossorigin_textures.html \ + video.sjs \ + test_video_crossorigin.html \ $(NULL) libs:: $(_TEST_FILES) diff --git a/content/canvas/test/crossorigin/test_video_crossorigin.html b/content/canvas/test/crossorigin/test_video_crossorigin.html new file mode 100644 index 000000000000..287b1a6f993c --- /dev/null +++ b/content/canvas/test/crossorigin/test_video_crossorigin.html @@ -0,0 +1,196 @@ + + + + + Test for Bug 682299 + + + + + +Mozilla Bug 682299 +

+ +
+
+
+ + diff --git a/content/canvas/test/crossorigin/video.sjs b/content/canvas/test/crossorigin/video.sjs new file mode 100644 index 000000000000..5b154d0e69b6 --- /dev/null +++ b/content/canvas/test/crossorigin/video.sjs @@ -0,0 +1,43 @@ +function parseQuery(request, key) { + var params = request.queryString.split('&'); + for (var j = 0; j < params.length; ++j) { + var p = params[j]; + if (p == key) + return true; + if (p.indexOf(key + "=") == 0) + return p.substring(key.length + 1); + if (p.indexOf("=") < 0 && key == "") + return p; + } + return false; +} + +function handleRequest(request, response) { + var name = parseQuery(request, "name"); + var type = parseQuery(request, "type"); + var cors = parseQuery(request, "cors"); + var file = Components.classes["@mozilla.org/file/directory_service;1"]. + getService(Components.interfaces.nsIProperties). + get("CurWorkD", Components.interfaces.nsILocalFile); + var fis = Components.classes['@mozilla.org/network/file-input-stream;1']. + createInstance(Components.interfaces.nsIFileInputStream); + var bis = Components.classes["@mozilla.org/binaryinputstream;1"]. + createInstance(Components.interfaces.nsIBinaryInputStream); + var split = name.split("/"); + for(var i = 0; i < split.length; ++i) { + file.append(split[i]); + } + fis.init(file, -1, -1, false); + bis.setInputStream(fis); + var bytes = bis.readBytes(bis.available()); + response.setHeader("Content-Length", ""+bytes.length, false); + response.setHeader("Content-Type", type, false); + if (cors == "anonymous") { + response.setHeader("Access-Control-Allow-Origin", "*", false); + } else if (cors == "use-credentials") { + response.setHeader("Access-Control-Allow-Origin", "http://mochi.test:8888", false); + response.setHeader("Access-Control-Allow-Credentials", "true", false); + } + response.write(bytes, bytes.length); + bis.close(); +} diff --git a/content/html/content/public/nsHTMLMediaElement.h b/content/html/content/public/nsHTMLMediaElement.h index 7b859c93e7e6..a6b531207b49 100644 --- a/content/html/content/public/nsHTMLMediaElement.h +++ b/content/html/content/public/nsHTMLMediaElement.h @@ -73,6 +73,10 @@ public: CANPLAY_YES }; + CORSMode GetCORSMode() { + return mCORSMode; + } + nsHTMLMediaElement(already_AddRefed aNodeInfo); virtual ~nsHTMLMediaElement(); @@ -233,8 +237,7 @@ public: // autoplay pref enabled, etc), it should start playing back. void NotifyAutoplayDataReady(); - // Gets the pref media.enforce_same_site_origin, which determines - // if we should check Access Controls, or allow cross domain loads. + // Check if the media element had crossorigin set when loading started bool ShouldCheckAllowOrigin(); // Is the media element potentially playing as defined by the HTML 5 specification. @@ -761,6 +764,9 @@ protected: // True if a same-origin check has been done for the media element and resource. bool mMediaSecurityVerified; + + // The CORS mode when loading the media element + CORSMode mCORSMode; }; #endif diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index 41ef30cf0b08..7897ffd19fc6 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -2884,6 +2884,14 @@ nsGenericHTMLFormElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor) return nsGenericHTMLElement::PreHandleEvent(aVisitor); } +const nsAttrValue::EnumTable nsGenericHTMLElement::kCORSAttributeTable[] = { + // Order matters here + // See ParseAttribute in nsHTMLImageElement or nsHTMLMediaElement + { "anonymous", nsGenericHTMLElement::CORS_ANONYMOUS }, + { "use-credentials", nsGenericHTMLElement::CORS_USE_CREDENTIALS }, + { 0 } +}; + /* virtual */ bool nsGenericHTMLFormElement::IsDisabled() const diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index f79ba6ef1eab..f23c8ea76a09 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -542,6 +542,32 @@ public: return HasAttr(kNameSpaceID_None, nsGkAtoms::hidden); } + /** + * Shared cross-origin resource sharing attributes so they don't get + * duplicated on every CORS-enabled element + */ + + enum CORSMode { + /** + * The default of not using CORS to validate cross-origin loads. + */ + CORS_NONE, + + /** + * Validate cross-site loads using CORS, but do not send any credentials + * (cookies, HTTP auth logins, etc) along with the request. + */ + CORS_ANONYMOUS, + + /** + * Validate cross-site loads using CORS, and send credentials such as cookies + * and HTTP auth logins along with the request. + */ + CORS_USE_CREDENTIALS + }; + + const static nsAttrValue::EnumTable kCORSAttributeTable[]; + protected: /** * Add/remove this element to the documents name cache diff --git a/content/html/content/src/nsHTMLImageElement.cpp b/content/html/content/src/nsHTMLImageElement.cpp index 0cd7d940a3ae..521c613b8379 100644 --- a/content/html/content/src/nsHTMLImageElement.cpp +++ b/content/html/content/src/nsHTMLImageElement.cpp @@ -126,7 +126,7 @@ public: NS_DECL_NSIDOMHTMLIMAGEELEMENT // override from nsImageLoadingContent - nsImageLoadingContent::CORSMode GetCORSMode(); + CORSMode GetCORSMode(); // nsIJSNativeInitializer NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* aContext, @@ -245,13 +245,6 @@ NS_IMPL_URI_ATTR(nsHTMLImageElement, Src, src) NS_IMPL_STRING_ATTR(nsHTMLImageElement, UseMap, usemap) NS_IMPL_INT_ATTR(nsHTMLImageElement, Vspace, vspace) -static const nsAttrValue::EnumTable kCrossOriginTable[] = { - // Order matters here; see ParseAttribute - { "anonymous", nsImageLoadingContent::CORS_ANONYMOUS }, - { "use-credentials", nsImageLoadingContent::CORS_USE_CREDENTIALS }, - { 0 } -}; - // crossorigin is not "limited to only known values" per spec, so it's // just a string attr purposes of the DOM crossOrigin property. NS_IMPL_STRING_ATTR(nsHTMLImageElement, CrossOrigin, crossorigin) @@ -370,10 +363,10 @@ nsHTMLImageElement::ParseAttribute(PRInt32 aNamespaceID, return ParseAlignValue(aValue, aResult); } if (aAttribute == nsGkAtoms::crossorigin) { - return aResult.ParseEnumValue(aValue, kCrossOriginTable, false, + return aResult.ParseEnumValue(aValue, nsGenericHTMLElement::kCORSAttributeTable, false, // default value is anonymous if aValue is // not a value we understand - &kCrossOriginTable[0]); + &nsGenericHTMLElement::kCORSAttributeTable[0]); } if (ParseImageAttribute(aAttribute, aValue, aResult)) { return true; @@ -669,16 +662,16 @@ nsHTMLImageElement::CopyInnerTo(nsGenericElement* aDest) const return nsGenericHTMLElement::CopyInnerTo(aDest); } -nsImageLoadingContent::CORSMode +nsGenericHTMLElement::CORSMode nsHTMLImageElement::GetCORSMode() { - nsImageLoadingContent::CORSMode ret = nsImageLoadingContent::CORS_NONE; + nsGenericHTMLElement::CORSMode ret = nsGenericHTMLElement::CORS_NONE; const nsAttrValue* value = GetParsedAttr(nsGkAtoms::crossorigin); if (value) { NS_ASSERTION(value->Type() == nsAttrValue::eEnum, "Why is this not an enum value?"); - ret = nsImageLoadingContent::CORSMode(value->GetEnumValue()); + ret = nsGenericHTMLElement::CORSMode(value->GetEnumValue()); } return ret; diff --git a/content/html/content/src/nsHTMLMediaElement.cpp b/content/html/content/src/nsHTMLMediaElement.cpp index 5cf17b0ac3c6..b08e178cf4df 100644 --- a/content/html/content/src/nsHTMLMediaElement.cpp +++ b/content/html/content/src/nsHTMLMediaElement.cpp @@ -940,6 +940,16 @@ nsresult nsHTMLMediaElement::LoadResource() mChannel = nsnull; } + // Set the media element's CORS mode only when loading a resource + // By default, it's CORS_NONE + mCORSMode = CORS_NONE; + const nsAttrValue* value = GetParsedAttr(nsGkAtoms::crossorigin); + if (value) { + NS_ASSERTION(value->Type() == nsAttrValue::eEnum, + "Why is this not an enum value?"); + mCORSMode = CORSMode(value->GetEnumValue()); + } + nsHTMLMediaElement* other = LookupMediaElementURITable(mLoadingSrc); if (other) { // Clone it. @@ -1002,7 +1012,7 @@ nsresult nsHTMLMediaElement::LoadResource() new nsCORSListenerProxy(loadListener, NodePrincipal(), channel, - false, + GetCORSMode() == CORS_USE_CREDENTIALS, &rv); } else { rv = nsContentUtils::GetSecurityManager()-> @@ -1392,11 +1402,10 @@ nsHTMLMediaElement::LookupMediaElementURITable(nsIURI* aURI) for (PRUint32 i = 0; i < entry->mElements.Length(); ++i) { nsHTMLMediaElement* elem = entry->mElements[i]; bool equal; - // Look for elements that have the same principal. - // XXX when we implement crossorigin for video, we'll also need to check - // for the same crossorigin mode here. Ditto for anything else that could - // cause us to send different headers. - if (NS_SUCCEEDED(elem->NodePrincipal()->Equals(NodePrincipal(), &equal)) && equal) { + // Look for elements that have the same principal and CORS mode. + // Ditto for anything else that could cause us to send different headers. + if (NS_SUCCEEDED(elem->NodePrincipal()->Equals(NodePrincipal(), &equal)) && equal && + elem->mCORSMode == mCORSMode) { NS_ASSERTION(elem->mDecoder && elem->mDecoder->GetStream(), "Decoder gone"); return elem; } @@ -1438,7 +1447,8 @@ nsHTMLMediaElement::nsHTMLMediaElement(already_AddRefed aNodeInfo) mHasSelfReference(false), mShuttingDown(false), mLoadIsSuspended(false), - mMediaSecurityVerified(false) + mMediaSecurityVerified(false), + mCORSMode(CORS_NONE) { #ifdef PR_LOGGING if (!gMediaElementLog) { @@ -1559,6 +1569,8 @@ NS_IMETHODIMP nsHTMLMediaElement::Play() return NS_OK; } +NS_IMPL_STRING_ATTR(nsHTMLMediaElement, Crossorigin, crossorigin) + bool nsHTMLMediaElement::ParseAttribute(PRInt32 aNamespaceID, nsIAtom* aAttribute, const nsAString& aValue, @@ -1577,6 +1589,12 @@ bool nsHTMLMediaElement::ParseAttribute(PRInt32 aNamespaceID, if (ParseImageAttribute(aAttribute, aValue, aResult)) { return true; } + if (aAttribute == nsGkAtoms::crossorigin) { + return aResult.ParseEnumValue(aValue, kCORSAttributeTable, false, + // default value is anonymous if aValue is + // not a value we understand + &kCORSAttributeTable[0]); + } if (aAttribute == nsGkAtoms::preload) { return aResult.ParseEnumValue(aValue, kPreloadTable, false); } @@ -2101,8 +2119,8 @@ nsresult nsHTMLMediaElement::FinishDecoderSetup(nsMediaDecoder* aDecoder) } if (NS_FAILED(rv)) { - RemoveMediaElementFromURITable(); - mDecoder->Shutdown(); + RemoveMediaElementFromURITable(); + mDecoder->Shutdown(); mDecoder = nsnull; } @@ -2330,7 +2348,7 @@ void nsHTMLMediaElement::DownloadStalled() bool nsHTMLMediaElement::ShouldCheckAllowOrigin() { - return Preferences::GetBool("media.enforce_same_site_origin", true); + return mCORSMode != CORS_NONE; } void nsHTMLMediaElement::UpdateReadyStateForData(NextFrameStatus aNextFrame) diff --git a/content/media/test/file_access_controls.html b/content/media/test/file_access_controls.html index d732e6c8e1f4..65fbb82b94a5 100644 --- a/content/media/test/file_access_controls.html +++ b/content/media/test/file_access_controls.html @@ -76,7 +76,6 @@ var gTests = [ var gTestNum = 0; var gVideo = null; var gTestedRemoved = false; -var gOldPref; function eventHandler(event) { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); @@ -93,6 +92,7 @@ function createVideo() { var v = document.createElement('video'); v.addEventListener('loadeddata', eventHandler, false); v.addEventListener('error', eventHandler, false); + v.crossorigin = 'anonymous'; return v; } @@ -101,16 +101,7 @@ function load() { opener.is(window.location.href, "http://example.org/tests/content/media/test/file_access_controls.html", "We must be on a example.org:80"); - - // Ensure access control check pref is on. - // media.enforce_same_site_origin - var prefService = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefService); - opener.ok(prefService!=null, "Get pref service"); - var branch = prefService.getBranch("media."); - opener.ok(branch!=null, "Get media pref branch"); - gOldPref = branch.getBoolPref("enforce_same_site_origin"); - branch.setBoolPref("enforce_same_site_origin", true); + nextTest(); } @@ -159,11 +150,6 @@ function nextTest() { function done() { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); - // Undo change to access control check pref. - var prefService = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefService); - var branch = prefService.getBranch("media."); - branch.setBoolPref("enforce_same_site_origin", gOldPref); mediaTestCleanup(); opener.done(); } diff --git a/content/xslt/src/xpath/txRelationalExpr.cpp b/content/xslt/src/xpath/txRelationalExpr.cpp index 20f89f1afe2e..17517cd56b94 100644 --- a/content/xslt/src/xpath/txRelationalExpr.cpp +++ b/content/xslt/src/xpath/txRelationalExpr.cpp @@ -119,7 +119,7 @@ RelationalExpr::compareResults(txIEvalContext* aContext, txAExprResult* aLeft, rtype == txAExprResult::NUMBER) { double lval = aLeft->numberValue(); double rval = aRight->numberValue(); - result = DOUBLE_COMPARE(lval, ==, rval); + result = (lval == rval); } // Otherwise compare as strings. Try to use the stringobject in @@ -154,19 +154,19 @@ RelationalExpr::compareResults(txIEvalContext* aContext, txAExprResult* aLeft, switch (mOp) { case LESS_THAN: { - return DOUBLE_COMPARE(leftDbl, <, rightDbl); + return (leftDbl < rightDbl); } case LESS_OR_EQUAL: { - return DOUBLE_COMPARE(leftDbl, <=, rightDbl); + return (leftDbl <= rightDbl); } case GREATER_THAN: { - return DOUBLE_COMPARE(leftDbl, >, rightDbl); + return (leftDbl > rightDbl); } case GREATER_OR_EQUAL: { - return DOUBLE_COMPARE(leftDbl, >=, rightDbl); + return (leftDbl >= rightDbl); } default: { diff --git a/dom/interfaces/html/nsIDOMHTMLAudioElement.idl b/dom/interfaces/html/nsIDOMHTMLAudioElement.idl index e0193c7c690b..7e0f8e6ceb00 100644 --- a/dom/interfaces/html/nsIDOMHTMLAudioElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLAudioElement.idl @@ -52,7 +52,7 @@ * @status UNDER_DEVELOPMENT */ -[scriptable, uuid(c74b835f-bb68-4ab3-a02c-08152cbb09fa)] +[scriptable, uuid(390c059a-0a26-4a44-96b6-3f8817bf92e9)] interface nsIDOMHTMLAudioElement : nsIDOMHTMLMediaElement { // Setup the audio stream for writing diff --git a/dom/interfaces/html/nsIDOMHTMLMediaElement.idl b/dom/interfaces/html/nsIDOMHTMLMediaElement.idl index d8b2ac2fb53b..648a07205842 100644 --- a/dom/interfaces/html/nsIDOMHTMLMediaElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLMediaElement.idl @@ -57,7 +57,7 @@ #endif %} -[scriptable, uuid(1f312b70-c1e1-40ca-94d4-5f70cac773da)] +[scriptable, uuid(6733a409-fab3-45e1-af23-9af8c361bdfd)] interface nsIDOMHTMLMediaElement : nsIDOMHTMLElement { // error state @@ -66,6 +66,7 @@ interface nsIDOMHTMLMediaElement : nsIDOMHTMLElement // network state attribute DOMString src; readonly attribute DOMString currentSrc; + attribute DOMString crossorigin; const unsigned short NETWORK_EMPTY = 0; const unsigned short NETWORK_IDLE = 1; const unsigned short NETWORK_LOADING = 2; diff --git a/dom/interfaces/html/nsIDOMHTMLVideoElement.idl b/dom/interfaces/html/nsIDOMHTMLVideoElement.idl index 6f9c3f26373e..248c23eaff98 100644 --- a/dom/interfaces/html/nsIDOMHTMLVideoElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLVideoElement.idl @@ -48,7 +48,7 @@ * @status UNDER_DEVELOPMENT */ -[scriptable, uuid(8e6d81a9-a6e1-44af-95be-cbe86de36ede)] +[scriptable, uuid(2274055b-8b3a-4a5a-8d72-5d5aea07021a)] interface nsIDOMHTMLVideoElement : nsIDOMHTMLMediaElement { attribute long width; diff --git a/gfx/layers/opengl/ContainerLayerOGL.cpp b/gfx/layers/opengl/ContainerLayerOGL.cpp index 97905ed833a8..1db510645a93 100644 --- a/gfx/layers/opengl/ContainerLayerOGL.cpp +++ b/gfx/layers/opengl/ContainerLayerOGL.cpp @@ -214,6 +214,7 @@ ContainerRender(Container* aContainer, framebufferRect -= childOffset; aManager->CreateFBOWithTexture(framebufferRect, mode, + aPreviousFrameBuffer, &frameBuffer, &containerSurface); childOffset.x = visibleRect.x; diff --git a/gfx/layers/opengl/LayerManagerOGL.cpp b/gfx/layers/opengl/LayerManagerOGL.cpp index f1b14169fd7d..ece7126019dd 100644 --- a/gfx/layers/opengl/LayerManagerOGL.cpp +++ b/gfx/layers/opengl/LayerManagerOGL.cpp @@ -1132,8 +1132,33 @@ LayerManagerOGL::SetLayerProgramProjectionMatrix(const gfx3DMatrix& aMatrix) } FOR_EACH_LAYER_PROGRAM_END } +static GLenum +GetFrameBufferInternalFormat(GLContext* gl, + GLuint aCurrentFrameBuffer, + nsIWidget* aWidget) +{ + if (aCurrentFrameBuffer == 0) { // default framebuffer + return aWidget->GetGLFrameBufferFormat(); + } + return LOCAL_GL_RGBA; +} + +static bool +AreFormatsCompatibleForCopyTexImage2D(GLenum aF1, GLenum aF2) +{ + // GL requires that the implementation has to handle copies between + // different formats, so all are "compatible". GLES does not + // require that. +#ifdef USE_GLES2 + return (aF1 == aF2); +#else + return true; +#endif +} + void LayerManagerOGL::CreateFBOWithTexture(const nsIntRect& aRect, InitMode aInit, + GLuint aCurrentFrameBuffer, GLuint *aFBO, GLuint *aTexture) { GLuint tex, fbo; @@ -1142,12 +1167,40 @@ LayerManagerOGL::CreateFBOWithTexture(const nsIntRect& aRect, InitMode aInit, mGLContext->fGenTextures(1, &tex); mGLContext->fBindTexture(mFBOTextureTarget, tex); if (aInit == InitModeCopy) { - mGLContext->fCopyTexImage2D(mFBOTextureTarget, - 0, - LOCAL_GL_RGBA, - aRect.x, aRect.y, - aRect.width, aRect.height, - 0); + // We're going to create an RGBA temporary fbo. But to + // CopyTexImage() from the current framebuffer, the framebuffer's + // format has to be compatible with the new texture's. So we + // check the format of the framebuffer here and take a slow path + // if it's incompatible. + GLenum format = + GetFrameBufferInternalFormat(gl(), aCurrentFrameBuffer, mWidget); + if (AreFormatsCompatibleForCopyTexImage2D(format, LOCAL_GL_RGBA)) { + mGLContext->fCopyTexImage2D(mFBOTextureTarget, + 0, + LOCAL_GL_RGBA, + aRect.x, aRect.y, + aRect.width, aRect.height, + 0); + } else { + // Curses, incompatible formats. Take a slow path. + // + // XXX Technically CopyTexSubImage2D also has the requirement of + // matching formats, but it doesn't seem to affect us in the + // real world. + mGLContext->fTexImage2D(mFBOTextureTarget, + 0, + LOCAL_GL_RGBA, + aRect.width, aRect.height, + 0, + LOCAL_GL_RGBA, + LOCAL_GL_UNSIGNED_BYTE, + NULL); + mGLContext->fCopyTexSubImage2D(mFBOTextureTarget, + 0, // level + 0, 0, // offset + aRect.x, aRect.y, + aRect.width, aRect.height); + } } else { mGLContext->fTexImage2D(mFBOTextureTarget, 0, diff --git a/gfx/layers/opengl/LayerManagerOGL.h b/gfx/layers/opengl/LayerManagerOGL.h index 92fd8fcb31b8..d5b6a7d33915 100644 --- a/gfx/layers/opengl/LayerManagerOGL.h +++ b/gfx/layers/opengl/LayerManagerOGL.h @@ -308,6 +308,7 @@ public: * texture types. */ void CreateFBOWithTexture(const nsIntRect& aRect, InitMode aInit, + GLuint aCurrentFrameBuffer, GLuint *aFBO, GLuint *aTexture); GLuint QuadVBO() { return mQuadVBO; } diff --git a/gfx/skia/Makefile.in b/gfx/skia/Makefile.in index 2ac443fb529e..7dbe4d22728d 100644 --- a/gfx/skia/Makefile.in +++ b/gfx/skia/Makefile.in @@ -68,6 +68,7 @@ VPATH += \ $(srcdir)/src/ports \ $(srcdir)/src/opts \ $(srcdir)/src/effects \ + $(srcdir)/src/utils \ $(NULL) EXPORTS_skia = \ @@ -317,6 +318,19 @@ DEFINES += -DSK_BUILD_FOR_ANDROID_NDK OS_CXXFLAGS += $(CAIRO_FT_CFLAGS) endif +ifeq (gtk2,$(MOZ_WIDGET_TOOLKIT)) +CPPSRCS += \ + SkFontHost_FreeType.cpp \ + SkFontHost_linux.cpp \ + SkFontHost_gamma.cpp \ + SkTime_Unix.cpp \ + SkMMapStream.cpp \ + SkOSFile.cpp \ + $(NULL) + +OS_CXXFLAGS += $(MOZ_PANGO_CFLAGS) +endif + ifeq (windows,$(MOZ_WIDGET_TOOLKIT)) EXPORTS_skia += \ include/config/sk_stdint.h \ diff --git a/gfx/thebes/gfxPlatformGtk.cpp b/gfx/thebes/gfxPlatformGtk.cpp index 94e5ab27e8e0..c3614d8ccbe4 100644 --- a/gfx/thebes/gfxPlatformGtk.cpp +++ b/gfx/thebes/gfxPlatformGtk.cpp @@ -56,6 +56,8 @@ #include "gfxFT2Fonts.h" #endif +#include "mozilla/gfx/2D.h" + #include "cairo.h" #include @@ -83,6 +85,9 @@ #include FT_FREETYPE_H #endif +using namespace mozilla; +using namespace mozilla::gfx; + gfxFontconfigUtils *gfxPlatformGtk::sFontconfigUtils = nsnull; #ifndef MOZ_PANGO @@ -761,3 +766,23 @@ gfxPlatformGtk::GetGdkDrawable(gfxASurface *target) return NULL; } + +RefPtr +gfxPlatformGtk::GetScaledFontForFont(gfxFont *aFont) +{ + NativeFont nativeFont; + nativeFont.mType = NATIVE_FONT_SKIA_FONT_FACE; + nativeFont.mFont = aFont; + RefPtr scaledFont = + Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize()); + + return scaledFont; +} + +bool +gfxPlatformGtk::SupportsAzure(BackendType& aBackend) +{ + aBackend = BACKEND_SKIA; + return true; +} + diff --git a/gfx/thebes/gfxPlatformGtk.h b/gfx/thebes/gfxPlatformGtk.h index b383f30d7afd..2ec617c19c1f 100644 --- a/gfx/thebes/gfxPlatformGtk.h +++ b/gfx/thebes/gfxPlatformGtk.h @@ -66,6 +66,11 @@ public: already_AddRefed CreateOffscreenSurface(const gfxIntSize& size, gfxASurface::gfxContentType contentType); + mozilla::RefPtr + GetScaledFontForFont(gfxFont *aFont); + + virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend); + nsresult GetFontList(nsIAtom *aLangGroup, const nsACString& aGenericFamily, nsTArray& aListOfFonts); diff --git a/ipc/glue/IPCMessageUtils.h b/ipc/glue/IPCMessageUtils.h index a74ce36147f2..4b82576e9cb9 100644 --- a/ipc/glue/IPCMessageUtils.h +++ b/ipc/glue/IPCMessageUtils.h @@ -484,10 +484,8 @@ struct ParamTraits WriteParam(msg, int32(param)); return; - default: - NS_RUNTIMEABORT("not reached"); - return; } + NS_RUNTIMEABORT("not reached"); } static bool Read(const Message* msg, void** iter, paramType* result) diff --git a/js/src/assembler/assembler/AbstractMacroAssembler.h b/js/src/assembler/assembler/AbstractMacroAssembler.h index 4c5af67ab8b1..42276896a11e 100644 --- a/js/src/assembler/assembler/AbstractMacroAssembler.h +++ b/js/src/assembler/assembler/AbstractMacroAssembler.h @@ -33,7 +33,6 @@ #include "assembler/wtf/Platform.h" #include "assembler/assembler/MacroAssemblerCodeRef.h" #include "assembler/assembler/CodeLocation.h" -#include "jsstdint.h" #if ENABLE_ASSEMBLER diff --git a/js/src/assembler/assembler/AssemblerBuffer.h b/js/src/assembler/assembler/AssemblerBuffer.h index 7107e935559a..daeec22823d5 100644 --- a/js/src/assembler/assembler/AssemblerBuffer.h +++ b/js/src/assembler/assembler/AssemblerBuffer.h @@ -37,7 +37,6 @@ #include #include "assembler/jit/ExecutableAllocator.h" #include "assembler/wtf/Assertions.h" -#include "jsstdint.h" namespace JSC { diff --git a/js/src/assembler/assembler/X86Assembler.h b/js/src/assembler/assembler/X86Assembler.h index 8babaa160fc3..1ed088e06336 100644 --- a/js/src/assembler/assembler/X86Assembler.h +++ b/js/src/assembler/assembler/X86Assembler.h @@ -35,7 +35,6 @@ #if ENABLE_ASSEMBLER && (WTF_CPU_X86 || WTF_CPU_X86_64) #include "AssemblerBuffer.h" -#include "jsstdint.h" #include "assembler/wtf/Assertions.h" #include "js/Vector.h" diff --git a/js/src/config/system-headers b/js/src/config/system-headers index 6544f6b7ed03..a4c34167f196 100644 --- a/js/src/config/system-headers +++ b/js/src/config/system-headers @@ -268,6 +268,11 @@ freetype/ftoutln.h freetype/ttnameid.h freetype/tttables.h freetype/t1tables.h +freetype/ftlcdfil.h +freetype/ftsizes.h +freetype/ftadvanc.h +freetype/ftbitmap.h +freetype/ftxf86.h fribidi/fribidi.h FSp_fopen.h fstream diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index ad4ec237c3be..7b6f7400687f 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -48,7 +48,6 @@ #include #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jsprf.h" #include "jsapi.h" diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index f6dcee8522a3..f93a67d6e53c 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -57,7 +57,6 @@ #include #include #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jsapi.h" #include "jsarray.h" diff --git a/js/src/frontend/TokenStream.cpp b/js/src/frontend/TokenStream.cpp index 299b977008fc..d9dae0a43fdb 100644 --- a/js/src/frontend/TokenStream.cpp +++ b/js/src/frontend/TokenStream.cpp @@ -53,7 +53,6 @@ #include #include #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jsprf.h" #include "jsapi.h" diff --git a/js/src/jit-test/tests/basic/regress-bug720680.js b/js/src/jit-test/tests/basic/regress-bug720680.js new file mode 100644 index 000000000000..ebb794fb5452 --- /dev/null +++ b/js/src/jit-test/tests/basic/regress-bug720680.js @@ -0,0 +1,15 @@ +// |jit-test| error: InternalError +version(0); +eval("\ +function TimeFromYear( y ) {}\ +addTestCase( -2208988800000 );\ +function addTestCase( t ) {\ + var start = TimeFromYear((addTestCase(addTestCase << t, 0)));\ + new TestCase( \ + SECTION,\ + '(new Date('+d+')).getUTCDay()',\ + WeekDay((d)),\ + (new Date(let ({ stop } = 'properties.length' )('/ab[c\\\n]/'))).getUTCDay() \ + );\ +}\ +"); diff --git a/js/src/jit-test/tests/basic/testTypedArraySetConversion.js b/js/src/jit-test/tests/basic/testTypedArraySetConversion.js new file mode 100644 index 000000000000..c50cf236dcf0 --- /dev/null +++ b/js/src/jit-test/tests/basic/testTypedArraySetConversion.js @@ -0,0 +1,15 @@ +var n = 16; +var a = new Int32Array(n); +for (var i = 0; i < n; ++i) { + a[i] = i; +} +var b = new Int32Array(n); +for (var i = 0; i < n; ++i) { + b[i] = i * 2; +} + +a.set(b, 0.99); + +for (var i = 0; i < n; ++i) { + assertEq(a[i], b[i]); +} diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 874cff974d37..b2f79975ad26 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -47,7 +47,6 @@ #include #include #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jsclist.h" #include "jsdhash.h" diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 0a8df11989b5..b87d44014bb1 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -103,7 +103,6 @@ #include "mozilla/RangedPtr.h" #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jsapi.h" diff --git a/js/src/jsatom.cpp b/js/src/jsatom.cpp index 5cc64d3cb06c..ada194371f28 100644 --- a/js/src/jsatom.cpp +++ b/js/src/jsatom.cpp @@ -47,7 +47,6 @@ #include "mozilla/Util.h" #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jshash.h" #include "jsprf.h" diff --git a/js/src/jsbool.cpp b/js/src/jsbool.cpp index 2341667c9537..c1fdd201ea03 100644 --- a/js/src/jsbool.cpp +++ b/js/src/jsbool.cpp @@ -41,7 +41,6 @@ * JS boolean implementation. */ #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jsapi.h" #include "jsatom.h" diff --git a/js/src/jsclone.h b/js/src/jsclone.h index cb9a15f5dcd7..7d202eaab937 100644 --- a/js/src/jsclone.h +++ b/js/src/jsclone.h @@ -41,7 +41,6 @@ #include "jsapi.h" #include "jscntxt.h" -#include "jsstdint.h" #include "js/HashTable.h" #include "js/Vector.h" diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index e781da8f3a3f..27682ef2c9a1 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -54,8 +54,6 @@ # include #endif // ANDROID -#include "jsstdint.h" - #include "jstypes.h" #include "jsutil.h" #include "jsclist.h" diff --git a/js/src/jsdate.cpp b/js/src/jsdate.cpp index bc8d5be93941..8d00b9952a05 100644 --- a/js/src/jsdate.cpp +++ b/js/src/jsdate.cpp @@ -60,7 +60,6 @@ #include "mozilla/Util.h" #include "jstypes.h" -#include "jsstdint.h" #include "jsprf.h" #include "prmjtime.h" #include "jsutil.h" diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 48e8d81fbce0..0b40558282b8 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -46,7 +46,6 @@ #include #include "jsprvtd.h" #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jsclist.h" #include "jsapi.h" diff --git a/js/src/jsdhash.cpp b/js/src/jsdhash.cpp index f25c602cbc44..71b6ab215d89 100644 --- a/js/src/jsdhash.cpp +++ b/js/src/jsdhash.cpp @@ -46,7 +46,6 @@ #include #include #include -#include "jsstdint.h" #include "jsdhash.h" #include "jsutil.h" diff --git a/js/src/jsdtoa.cpp b/js/src/jsdtoa.cpp index c1f74f73f317..fb7295c8ebf2 100644 --- a/js/src/jsdtoa.cpp +++ b/js/src/jsdtoa.cpp @@ -41,7 +41,6 @@ * Portable double to alphanumeric string and back converters. */ #include "jstypes.h" -#include "jsstdint.h" #include "jsdtoa.h" #include "jsprf.h" #include "jsapi.h" diff --git a/js/src/jsexn.cpp b/js/src/jsexn.cpp index e9d318caf9fd..876913de8100 100644 --- a/js/src/jsexn.cpp +++ b/js/src/jsexn.cpp @@ -47,7 +47,6 @@ #include "mozilla/Util.h" #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jsprf.h" #include "jsapi.h" diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index d897fc8851ed..884b788ea9e5 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -46,7 +46,6 @@ #include "mozilla/Util.h" #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jsapi.h" #include "jsarray.h" diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 08a1b7feeb32..983ae8784fcb 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -55,7 +55,6 @@ #include /* for memset used when DEBUG */ #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jshash.h" #include "jsclist.h" diff --git a/js/src/jsgcchunk.cpp b/js/src/jsgcchunk.cpp index 740d010e90d4..207a68ae8cd6 100644 --- a/js/src/jsgcchunk.cpp +++ b/js/src/jsgcchunk.cpp @@ -33,7 +33,6 @@ #include #include "jstypes.h" -#include "jsstdint.h" #include "jsgcchunk.h" #ifdef XP_WIN diff --git a/js/src/jshash.cpp b/js/src/jshash.cpp index 3e8ecb740870..ff18dbde785c 100644 --- a/js/src/jshash.cpp +++ b/js/src/jshash.cpp @@ -43,7 +43,6 @@ #include #include #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jshash.h" diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index d34c896fed10..38f2c711a33e 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -45,7 +45,6 @@ #include #include #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jsprf.h" #include "jsapi.h" @@ -824,7 +823,7 @@ js::LooselyEqual(JSContext *cx, const Value &lval, const Value &rval, bool *resu if (lval.isDouble()) { double l = lval.toDouble(), r = rval.toDouble(); - *result = JSDOUBLE_COMPARE(l, ==, r, false); + *result = (l == r); return true; } @@ -875,7 +874,7 @@ js::LooselyEqual(JSContext *cx, const Value &lval, const Value &rval, bool *resu double l, r; if (!ToNumber(cx, lvalue, &l) || !ToNumber(cx, rvalue, &r)) return false; - *result = JSDOUBLE_COMPARE(l, ==, r, false); + *result = (l == r); return true; } @@ -887,7 +886,7 @@ js::StrictlyEqual(JSContext *cx, const Value &lref, const Value &rref, bool *equ if (lval.isString()) return EqualStrings(cx, lval.toString(), rval.toString(), equal); if (lval.isDouble()) { - *equal = JSDOUBLE_COMPARE(lval.toDouble(), ==, rval.toDouble(), JS_FALSE); + *equal = (lval.toDouble() == rval.toDouble()); return true; } if (lval.isObject()) { @@ -905,13 +904,13 @@ js::StrictlyEqual(JSContext *cx, const Value &lref, const Value &rref, bool *equ if (lval.isDouble() && rval.isInt32()) { double ld = lval.toDouble(); double rd = rval.toInt32(); - *equal = JSDOUBLE_COMPARE(ld, ==, rd, JS_FALSE); + *equal = (ld == rd); return true; } if (lval.isInt32() && rval.isDouble()) { double ld = lval.toInt32(); double rd = rval.toDouble(); - *equal = JSDOUBLE_COMPARE(ld, ==, rd, JS_FALSE); + *equal = (ld == rd); return true; } @@ -2325,7 +2324,7 @@ END_CASE(JSOP_CASE) double l, r; \ if (!ToNumber(cx, lval, &l) || !ToNumber(cx, rval, &r)) \ goto error; \ - cond = JSDOUBLE_COMPARE(l, OP, r, false); \ + cond = (l OP r); \ } \ } \ TRY_BRANCH_AFTER_COND(cond, 2); \ diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 7c37ea03da0b..bf8f0b0dbc66 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -44,7 +44,6 @@ #include "mozilla/Util.h" #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jsapi.h" #include "jsarray.h" diff --git a/js/src/jsmath.cpp b/js/src/jsmath.cpp index 991baa270f8b..49bc33cee418 100644 --- a/js/src/jsmath.cpp +++ b/js/src/jsmath.cpp @@ -42,7 +42,6 @@ */ #include #include "jstypes.h" -#include "jsstdint.h" #include "prmjtime.h" #include "jsapi.h" #include "jsatom.h" diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp index b7457a164165..dce29d06b55b 100644 --- a/js/src/jsnum.cpp +++ b/js/src/jsnum.cpp @@ -55,7 +55,6 @@ #include "mozilla/RangedPtr.h" #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jsapi.h" #include "jsatom.h" diff --git a/js/src/jsnum.h b/js/src/jsnum.h index b53627dd4ffa..12f7cefe328a 100644 --- a/js/src/jsnum.h +++ b/js/src/jsnum.h @@ -42,7 +42,6 @@ #include -#include "jsstdint.h" #include "jsobj.h" /* @@ -129,15 +128,6 @@ JS_HASH_DOUBLE(jsdouble d) return u.s.lo ^ u.s.hi; } -#if defined(XP_WIN) -#define JSDOUBLE_COMPARE(LVAL, OP, RVAL, IFNAN) \ - ((JSDOUBLE_IS_NaN(LVAL) || JSDOUBLE_IS_NaN(RVAL)) \ - ? (IFNAN) \ - : (LVAL) OP (RVAL)) -#else -#define JSDOUBLE_COMPARE(LVAL, OP, RVAL, IFNAN) ((LVAL) OP (RVAL)) -#endif - extern jsdouble js_NaN; extern jsdouble js_PositiveInfinity; extern jsdouble js_NegativeInfinity; diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 350d1d874316..483640f73361 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -47,7 +47,6 @@ #include "mozilla/Util.h" #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jshash.h" #include "jsdhash.h" @@ -72,7 +71,6 @@ #include "jsproxy.h" #include "jsscope.h" #include "jsscript.h" -#include "jsstdint.h" #include "jsstr.h" #include "jsdbgapi.h" #include "json.h" diff --git a/js/src/json.cpp b/js/src/json.cpp index eef69cc97cf1..4f930addd591 100644 --- a/js/src/json.cpp +++ b/js/src/json.cpp @@ -55,7 +55,6 @@ #include "jsprf.h" #include "jsstr.h" #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jsxml.h" diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index 7c66df437b22..43c6f08611d3 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -52,7 +52,6 @@ #include "mozilla/Util.h" #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jsprf.h" #include "jsapi.h" @@ -856,8 +855,7 @@ Sprinter::put(const char *s, size_t len) s = stringAt(s - oldBase); /* this is where it lives now */ memmove(bp, s, len); } else { - JS_ASSERT(s < base || s >= base + size); - memcpy(bp, s, len); + js_memcpy(bp, s, len); } bp[len] = 0; @@ -2060,7 +2058,7 @@ DecompileDestructuringLHS(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc, JS * the nb parameter. */ ptrdiff_t todo = ss->sprinter.getOffset(); - ss->sprinter.setOffset(todo + PAREN_SLOP); + ss->sprinter.reserve(PAREN_SLOP); pc = Decompile(ss, pc, -((intN)ss->top)); if (!pc) return NULL; diff --git a/js/src/jsprf.cpp b/js/src/jsprf.cpp index 743b515a01c1..5a058dccc18b 100644 --- a/js/src/jsprf.cpp +++ b/js/src/jsprf.cpp @@ -46,7 +46,6 @@ #include #include #include "jsprf.h" -#include "jsstdint.h" #include "jsutil.h" #include "jspubtd.h" #include "jsstr.h" diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index a272cc6a1519..d4ca4446d402 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -45,7 +45,6 @@ #include #include #include "jstypes.h" -#include "jsstdint.h" #include "jsclist.h" #include "jsdhash.h" #include "jsutil.h" diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index 9a45a7153622..7b8c884ed9b1 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -42,9 +42,9 @@ /* * JS script operations. */ + #include #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jscrashreport.h" #include "jsprf.h" diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 4e6cbb025f49..cf458c55e9ee 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -54,7 +54,6 @@ #include #include #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jshash.h" #include "jsprf.h" diff --git a/js/src/jstypedarray.cpp b/js/src/jstypedarray.cpp index b0e9f46aad3c..cae989951e83 100644 --- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -42,7 +42,6 @@ #include "mozilla/Util.h" #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jshash.h" #include "jsprf.h" @@ -1544,7 +1543,7 @@ class TypedArrayTemplate int32_t length = -1; if (argc > 1) { - if (!NonstandardToInt32(cx, argv[1], &byteOffset)) + if (!ToInt32(cx, argv[1], &byteOffset)) return NULL; if (byteOffset < 0) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, @@ -1553,7 +1552,7 @@ class TypedArrayTemplate } if (argc > 2) { - if (!NonstandardToInt32(cx, argv[2], &length)) + if (!ToInt32(cx, argv[2], &length)) return NULL; if (length < 0) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, @@ -1625,7 +1624,7 @@ class TypedArrayTemplate int32_t off = 0; if (args.length() > 1) { - if (!NonstandardToInt32(cx, args[1], &off)) + if (!ToInt32(cx, args[1], &off)) return false; if (off < 0 || uint32_t(off) > getLength(tarray)) { diff --git a/js/src/jsutil.cpp b/js/src/jsutil.cpp index abe991530b7b..42578441dfb6 100644 --- a/js/src/jsutil.cpp +++ b/js/src/jsutil.cpp @@ -45,7 +45,6 @@ #include #include #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #ifdef WIN32 diff --git a/js/src/jsxdrapi.cpp b/js/src/jsxdrapi.cpp index 2de22a56d02a..58663515d241 100644 --- a/js/src/jsxdrapi.cpp +++ b/js/src/jsxdrapi.cpp @@ -45,7 +45,6 @@ #include #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jsdhash.h" #include "jsprf.h" diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index 36bcd6f452bc..cdfe38ab2bba 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -48,7 +48,6 @@ #include "mozilla/Util.h" #include "jstypes.h" -#include "jsstdint.h" #include "jsprf.h" #include "jsutil.h" #include "jsapi.h" @@ -5315,7 +5314,7 @@ js_TestXMLEquality(JSContext *cx, const Value &v1, const Value &v2, JSBool *bp) if (ok) { d2 = JSVAL_IS_INT(v) ? JSVAL_TO_INT(v) : JSVAL_TO_DOUBLE(v); - *bp = JSDOUBLE_COMPARE(d, ==, d2, JS_FALSE); + *bp = (d == d2); } } } else { diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index 5ad8c85e55b5..c2b71e14450b 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -525,7 +525,7 @@ template void JS_FASTCALL stubs::DefFun(VMFrame &f, JSFunction *fun); double l, r; \ if (!ToNumber(cx, lval, &l) || !ToNumber(cx, rval, &r)) \ THROWV(JS_FALSE); \ - cond = JSDOUBLE_COMPARE(l, OP, r, false); \ + cond = (l OP r); \ } \ regs.sp[-2].setBoolean(cond); \ return cond; \ @@ -568,7 +568,7 @@ stubs::Not(VMFrame &f) f.regs.sp[-1].setBoolean(b); } -template +template static inline bool StubEqualityOp(VMFrame &f) { @@ -606,9 +606,9 @@ StubEqualityOp(VMFrame &f) double l = lval.toDouble(); double r = rval.toDouble(); if (EQ) - cond = JSDOUBLE_COMPARE(l, ==, r, IFNAN); + cond = (l == r); else - cond = JSDOUBLE_COMPARE(l, !=, r, IFNAN); + cond = (l != r); } else if (lval.isObject()) { JSObject *l = &lval.toObject(), *r = &rval.toObject(); if (JSEqualityOp eq = l->getClass()->ext.equality) { @@ -652,9 +652,9 @@ StubEqualityOp(VMFrame &f) return false; if (EQ) - cond = JSDOUBLE_COMPARE(l, ==, r, false); + cond = (l == r); else - cond = JSDOUBLE_COMPARE(l, !=, r, true); + cond = (l != r); } } } @@ -666,7 +666,7 @@ StubEqualityOp(VMFrame &f) JSBool JS_FASTCALL stubs::Equal(VMFrame &f) { - if (!StubEqualityOp(f)) + if (!StubEqualityOp(f)) THROWV(JS_FALSE); return f.regs.sp[-2].toBoolean(); } @@ -674,7 +674,7 @@ stubs::Equal(VMFrame &f) JSBool JS_FASTCALL stubs::NotEqual(VMFrame &f) { - if (!StubEqualityOp(f)) + if (!StubEqualityOp(f)) THROWV(JS_FALSE); return f.regs.sp[-2].toBoolean(); } diff --git a/js/src/prmjtime.cpp b/js/src/prmjtime.cpp index d4bc3ab42e7d..cded6dac5e14 100644 --- a/js/src/prmjtime.cpp +++ b/js/src/prmjtime.cpp @@ -46,7 +46,6 @@ #include #include -#include "jsstdint.h" #include "jstypes.h" #include "jsutil.h" diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 894e57456897..e805a4fdb4be 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -52,7 +52,6 @@ #include "mozilla/Util.h" #include "jstypes.h" -#include "jsstdint.h" #include "jsutil.h" #include "jsprf.h" #include "jswrapper.h" diff --git a/js/src/shell/jsworkers.cpp b/js/src/shell/jsworkers.cpp index b309e9783ed1..c0b9d87a2191 100644 --- a/js/src/shell/jsworkers.cpp +++ b/js/src/shell/jsworkers.cpp @@ -49,7 +49,6 @@ #include "jsapi.h" #include "jscntxt.h" #include "jsdbgapi.h" -#include "jsstdint.h" #include "jslock.h" #include "jsworkers.h" diff --git a/js/src/yarr/PageBlock.h b/js/src/yarr/PageBlock.h index 33751315e049..34ff55096f4b 100644 --- a/js/src/yarr/PageBlock.h +++ b/js/src/yarr/PageBlock.h @@ -30,8 +30,9 @@ #ifndef PageBlock_h #define PageBlock_h +#include "mozilla/StdInt.h" + #include -#include "jsstdint.h" #include "assembler/wtf/Platform.h" namespace WTF { diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 6469acc71746..392a5a555595 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -90,6 +90,7 @@ #ifdef MOZ_MEDIA #include "nsHTMLVideoElement.h" #endif +#include "nsGenericHTMLElement.h" #include "imgIRequest.h" #include "imgIContainer.h" #include "nsIImageLoadingContent.h" @@ -4151,6 +4152,7 @@ nsLayoutUtils::SurfaceFromElement(dom::Element* aElement, surf = imgSurf; } + result.mCORSUsed = video->GetCORSMode() != nsGenericHTMLElement::CORS_NONE; result.mSurface = surf; result.mSize = size; result.mPrincipal = principal.forget(); diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index d7d05aed5a73..af97e0e2b0ed 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -6582,10 +6582,10 @@ nsRuleNode::ComputeColumnData(void* aStartStruct, // column-fill: enum SetDiscrete(*aRuleData->ValueForColumnFill(), - column->mColumnFill, canStoreInRuleTree, - SETDSC_ENUMERATED, parent->mColumnFill, - NS_STYLE_COLUMN_FILL_BALANCE, - 0, 0, 0, 0); + column->mColumnFill, canStoreInRuleTree, + SETDSC_ENUMERATED, parent->mColumnFill, + NS_STYLE_COLUMN_FILL_BALANCE, + 0, 0, 0, 0); COMPUTE_END_RESET(Column, column) } diff --git a/layout/svg/base/src/Makefile.in b/layout/svg/base/src/Makefile.in index dcb6ae37f4d4..7fd1dc6913bb 100644 --- a/layout/svg/base/src/Makefile.in +++ b/layout/svg/base/src/Makefile.in @@ -106,6 +106,7 @@ LOCAL_INCLUDES = \ -I$(srcdir)/../../../xul/base/src \ -I$(srcdir)/../../../../content/svg/content/src \ -I$(srcdir)/../../../../content/base/src \ + -I$(srcdir)/../../../../content/html/content/src \ $(NULL) libs:: diff --git a/mobile/android/base/AndroidManifest.xml.in b/mobile/android/base/AndroidManifest.xml.in index 852e52468616..d54f87018d66 100644 --- a/mobile/android/base/AndroidManifest.xml.in +++ b/mobile/android/base/AndroidManifest.xml.in @@ -61,6 +61,10 @@ + + + + @@ -112,6 +116,7 @@ android:excludeFromRecents="true"> + diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index abb528a084ca..9571e629f1ca 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -105,6 +105,7 @@ abstract public class GeckoApp public static final String ACTION_DEBUG = "org.mozilla.gecko.DEBUG"; public static final String ACTION_BOOKMARK = "org.mozilla.gecko.BOOKMARK"; public static final String ACTION_LOAD = "org.mozilla.gecko.LOAD"; + public static final String ACTION_UPDATE = "org.mozilla.gecko.UPDATE"; public static final String SAVED_STATE_URI = "uri"; public static final String SAVED_STATE_TITLE = "title"; public static final String SAVED_STATE_VIEWPORT = "viewport"; @@ -593,11 +594,10 @@ abstract public class GeckoApp } } - void getAndProcessThumbnailForTab(Tab tab) { - Bitmap bitmap = null; - if (Tabs.getInstance().isSelectedTab(tab)) - bitmap = mSoftwareLayerClient.getBitmap(); - + void getAndProcessThumbnailForTab(final Tab tab) { + final Bitmap bitmap = Tabs.getInstance().isSelectedTab(tab) ? + mSoftwareLayerClient.getBitmap() : null; + if (bitmap != null) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 0, bos); @@ -1052,6 +1052,8 @@ abstract public class GeckoApp } }); } + } else if (event.equals("Update:Restart")) { + doRestart("org.mozilla.gecko.restart_update"); } } catch (Exception e) { Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e); @@ -1458,6 +1460,11 @@ abstract public class GeckoApp } } + if (ACTION_UPDATE.equals(intent.getAction()) || args != null && args.contains("-alert update-app")) { + Log.i(LOGTAG,"onCreate: Update request"); + checkAndLaunchUpdate(); + } + String uri = intent.getDataString(); String title = uri; if (uri != null && uri.length() > 0) { @@ -1606,6 +1613,7 @@ abstract public class GeckoApp GeckoAppShell.registerGeckoEventListener("Downloads:Done", GeckoApp.mAppContext); GeckoAppShell.registerGeckoEventListener("CharEncoding:Data", GeckoApp.mAppContext); GeckoAppShell.registerGeckoEventListener("CharEncoding:State", GeckoApp.mAppContext); + GeckoAppShell.registerGeckoEventListener("Update:Restart", GeckoApp.mAppContext); mConnectivityFilter = new IntentFilter(); mConnectivityFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); @@ -1641,10 +1649,6 @@ abstract public class GeckoApp return; } - // it would be good only to do this if MOZ_UPDATER was defined - long startTime = SystemClock.uptimeMillis(); - checkAndLaunchUpdate(); - Log.w(LOGTAG, "checking for an update took " + (SystemClock.uptimeMillis() - startTime) + "ms"); checkMigrateProfile(); } }, 50); @@ -2012,8 +2016,12 @@ abstract public class GeckoApp } public void doRestart() { + doRestart("org.mozilla.gecko.restart"); + } + + public void doRestart(String action) { + Log.i(LOGTAG, "doRestart(\"" + action + "\")"); try { - String action = "org.mozilla.gecko.restart"; Intent intent = new Intent(action); intent.setClassName(getPackageName(), getPackageName() + ".Restarter"); @@ -2108,12 +2116,19 @@ abstract public class GeckoApp private void checkMigrateProfile() { File profileDir = getProfileDir(); if (profileDir != null) { + long currentTime = SystemClock.uptimeMillis(); Log.i(LOGTAG, "checking profile migration in: " + profileDir.getAbsolutePath()); final GeckoApp app = GeckoApp.mAppContext; + final SetupScreen setupScreen = new SetupScreen(app); + // don't show unless we take a while + setupScreen.showDelayed(mMainHandler); GeckoAppShell.ensureSQLiteLibsLoaded(app.getApplication().getPackageResourcePath()); ProfileMigrator profileMigrator = new ProfileMigrator(app.getContentResolver(), profileDir); - profileMigrator.launchBackground(); + profileMigrator.launch(); + setupScreen.dismiss(); + long timeDiff = SystemClock.uptimeMillis() - currentTime; + Log.i(LOGTAG, "Profile migration took " + timeDiff + " ms"); } } @@ -2363,7 +2378,7 @@ abstract public class GeckoApp while (tabsIter.hasNext()) { Tab tab = tabsIter.next(); if (url.equals(tab.getURL())) { - GeckoAppShell.sendEventToGecko(new GeckoEvent("Tab:Select", String.valueOf(tab.getId()))); + Tabs.getInstance().selectTab(tab.getId()); return; } } diff --git a/mobile/android/base/GeckoInputConnection.java b/mobile/android/base/GeckoInputConnection.java index 421dfe65f23a..54ed53ae508d 100644 --- a/mobile/android/base/GeckoInputConnection.java +++ b/mobile/android/base/GeckoInputConnection.java @@ -435,6 +435,7 @@ public class GeckoInputConnection public void reset() { mComposing = false; + mCompositionStart = -1; mBatchMode = false; mUpdateRequest = null; } @@ -442,11 +443,17 @@ public class GeckoInputConnection // TextWatcher public void onTextChanged(CharSequence s, int start, int before, int count) { + if (mComposing && mCompositionStart != start) { + // Changed range is different from the composition, need to reset the composition + endComposition(); + } + if (!mComposing) { if (DEBUG) Log.d(LOGTAG, ". . . onTextChanged: IME_COMPOSITION_BEGIN"); GeckoAppShell.sendEventToGecko( new GeckoEvent(GeckoEvent.IME_COMPOSITION_BEGIN, 0, 0)); mComposing = true; + mCompositionStart = start; if (DEBUG) Log.d(LOGTAG, ". . . onTextChanged: IME_SET_SELECTION, start=" + start + ", len=" + before); GeckoAppShell.sendEventToGecko( @@ -474,6 +481,7 @@ public class GeckoInputConnection GeckoAppShell.sendEventToGecko( new GeckoEvent(GeckoEvent.IME_COMPOSITION_END, 0, 0)); mComposing = false; + mCompositionStart = -1; } private void sendTextToGecko(CharSequence text, int caretPos) { @@ -888,7 +896,8 @@ public class GeckoInputConnection } // Is a composition active? - boolean mComposing; + private boolean mComposing; + private int mCompositionStart = -1; // IME stuff public static final int IME_STATE_DISABLED = 0; diff --git a/mobile/android/base/Makefile.in b/mobile/android/base/Makefile.in index c0b5e86d5097..860687bfd0fd 100644 --- a/mobile/android/base/Makefile.in +++ b/mobile/android/base/Makefile.in @@ -68,6 +68,7 @@ FENNEC_JAVA_FILES = \ AwesomeBarTabs.java \ BrowserToolbar.java \ ConfirmPreference.java \ + SyncPreference.java \ db/AndroidBrowserDB.java \ db/BrowserDB.java \ db/LocalBrowserDB.java \ @@ -95,6 +96,7 @@ FENNEC_JAVA_FILES = \ sqlite/ByteBufferInputStream.java \ sqlite/SQLiteBridge.java \ sqlite/SQLiteBridgeException.java \ + SetupScreen.java \ SurfaceLockInfo.java \ Tab.java \ Tabs.java \ @@ -231,6 +233,7 @@ RES_LAYOUT = \ res/layout/notification_progress.xml \ res/layout/notification_progress_text.xml \ res/layout/site_setting_title.xml \ + res/layout/setup_screen.xml \ res/layout/tabs_row.xml \ res/layout/tabs_tray.xml \ res/layout/list_item_header.xml \ @@ -277,6 +280,7 @@ RES_DRAWABLE_NODPI = \ $(NULL) RES_DRAWABLE_MDPI_V8 = \ + res/drawable-mdpi-v8/favicon.png \ res/drawable-mdpi-v8/abouthome_icon.png \ res/drawable-mdpi-v8/abouthome_logo.png \ res/drawable-mdpi-v8/abouthome_separator.9.png \ @@ -319,6 +323,7 @@ RES_DRAWABLE_MDPI_V8 = \ $(NULL) RES_DRAWABLE_HDPI_V8 = \ + res/drawable-hdpi-v8/favicon.png \ res/drawable-hdpi-v8/home_bg.png \ res/drawable-hdpi-v8/home_star.png \ res/drawable-hdpi-v8/abouthome_icon.png \ @@ -383,6 +388,7 @@ RES_DRAWABLE_HDPI_V11 = \ $(NULL) RES_DRAWABLE_XHDPI_V11 = \ + res/drawable-xhdpi-v11/favicon.png \ res/drawable-xhdpi-v11/abouthome_icon.png \ res/drawable-xhdpi-v11/abouthome_logo.png \ res/drawable-xhdpi-v11/abouthome_separator.9.png \ @@ -496,7 +502,6 @@ MOZ_ANDROID_DRAWABLES += \ mobile/android/base/resources/drawable/awesomebar_tab_unselected.xml \ mobile/android/base/resources/drawable/background.png \ mobile/android/base/resources/drawable/desktop_notification.png \ - mobile/android/base/resources/drawable/favicon.png \ mobile/android/base/resources/drawable/gecko_actionbar_bg.xml \ mobile/android/base/resources/drawable/progress_spinner.xml \ mobile/android/base/resources/drawable/progress_spinner_1.png \ diff --git a/mobile/android/base/ProfileMigrator.java b/mobile/android/base/ProfileMigrator.java index e007357d481c..b3b769de2cd6 100644 --- a/mobile/android/base/ProfileMigrator.java +++ b/mobile/android/base/ProfileMigrator.java @@ -69,12 +69,6 @@ public class ProfileMigrator { private File mProfileDir; private ContentResolver mCr; - /* - Amount of Android history entries we will remember - to prevent moving their last access date backwards. - */ - private static final int MAX_HISTORY_TO_CHECK = 1000; - /* These queries are derived from the low-level Places schema https://developer.mozilla.org/en/The_Places_database @@ -88,41 +82,48 @@ public class ProfileMigrator { private final String bookmarkUrl = "a_url"; private final String bookmarkTitle = "a_title"; + /* + The sort criterion here corresponds to the one used for the + Awesomebar results. It's an simplification of Frecency. + We must divide date by 1000 due to the micro (Places) + vs milli (Android) distiction. + */ private final String historyQuery = - "SELECT places.url AS a_url, places.title AS a_title, " - + "history.visit_date AS a_date FROM " - + "(moz_historyvisits AS history JOIN moz_places AS places ON " - + "places.id = history.place_id) WHERE places.hidden <> 1 " - + "ORDER BY history.visit_date DESC"; - private final String historyUrl = "a_url"; - private final String historyTitle = "a_title"; - private final String historyDate = "a_date"; - - private final String faviconQuery = - "SELECT places.url AS a_url, favicon.data AS a_data, " - + "favicon.mime_type AS a_mime FROM (moz_places AS places JOIN " - + "moz_favicons AS favicon ON places.favicon_id = favicon.id)"; - private final String faviconUrl = "a_url"; - private final String faviconData = "a_data"; - private final String faviconMime = "a_mime"; + "SELECT places.url AS a_url, places.title AS a_title," + + "MAX(history.visit_date) AS a_date, COUNT(*) AS a_visits, " + // see BrowserDB.filterAllSites for this formula + + "MAX(1, (((MAX(history.visit_date)/1000) - ?) / 86400000 + 120)) AS a_recent, " + + "favicon.data AS a_favicon_data, favicon.mime_type AS a_favicon_mime " + + "FROM (moz_historyvisits AS history JOIN moz_places AS places " + + "ON places.id = history.place_id " + // Add favicon data if a favicon is present for this URL. + + "LEFT OUTER JOIN moz_favicons AS favicon " + + "ON places.favicon_id = favicon.id) " + + "WHERE places.hidden <> 1 " + + "GROUP BY a_url ORDER BY a_visits * a_recent DESC LIMIT ?"; + private final String historyUrl = "a_url"; + private final String historyTitle = "a_title"; + private final String historyDate = "a_date"; + private final String historyVisits = "a_visits"; + private final String faviconData = "a_favicon_data"; + private final String faviconMime = "a_favicon_mime"; public ProfileMigrator(ContentResolver cr, File profileDir) { mProfileDir = profileDir; mCr = cr; } - public void launchBackground() { - // Work around http://code.google.com/p/android/issues/detail?id=11291 - // WebIconDatabase needs to be initialized within a looper thread. - GeckoAppShell.getHandler().post(new PlacesTask()); + public void launch() { + new PlacesTask().run(); } private class PlacesTask implements Runnable { // Get a list of the last times an URL was accessed - protected Map gatherAndroidHistory() { + protected Map gatherBrowserDBHistory() { Map history = new HashMap(); - Cursor cursor = BrowserDB.getRecentHistory(mCr, MAX_HISTORY_TO_CHECK); + Cursor cursor = + BrowserDB.getRecentHistory(mCr, BrowserDB.getMaxHistoryCount()); final int urlCol = cursor.getColumnIndexOrThrow(BrowserDB.URLColumns.URL); final int dateCol = @@ -144,48 +145,71 @@ public class ProfileMigrator { return history; } - protected void addHistory(Map androidHistory, - String url, String title, long date) { + protected void addHistory(Map browserDBHistory, + String url, String title, long date, int visits) { boolean allowUpdate = false; - if (!androidHistory.containsKey(url)) { - // Android doesn't know the URL, allow it to be - // inserted with places date + if (!browserDBHistory.containsKey(url)) { + // BrowserDB doesn't know the URL, allow it to be + // inserted with places date. allowUpdate = true; } else { - long androidDate = androidHistory.get(url); + long androidDate = browserDBHistory.get(url); if (androidDate < date) { - // Places URL hit is newer than Android, - // allow it to be updated with places date + // Places URL hit is newer than BrowserDB, + // allow it to be updated with places date. allowUpdate = true; } } if (allowUpdate) { BrowserDB.updateVisitedHistory(mCr, url); - BrowserDB.updateHistoryDate(mCr, url, date); - if (title != null) { - BrowserDB.updateHistoryTitle(mCr, url, title); - } + // The above records one visit. Subtract that one visit here. + BrowserDB.updateHistoryEntry(mCr, url, title, date, visits - 1); } } protected void migrateHistory(SQLiteBridge db) { - Map androidHistory = gatherAndroidHistory(); + Map browserDBHistory = gatherBrowserDBHistory(); final ArrayList placesHistory = new ArrayList(); try { - ArrayList queryResult = db.query(historyQuery); + final String[] queryParams = new String[] { + /* current time */ + Long.toString(System.currentTimeMillis()), + /* + History entries to return. No point + in retrieving more than we can store. + */ + Integer.toString(BrowserDB.getMaxHistoryCount()) + }; + ArrayList queryResult = + db.query(historyQuery, queryParams); final int urlCol = db.getColumnIndex(historyUrl); final int titleCol = db.getColumnIndex(historyTitle); final int dateCol = db.getColumnIndex(historyDate); + final int visitsCol = db.getColumnIndex(historyVisits); + final int faviconMimeCol = db.getColumnIndex(faviconMime); + final int faviconDataCol = db.getColumnIndex(faviconData); for (Object[] resultRow: queryResult) { String url = (String)resultRow[urlCol]; String title = (String)resultRow[titleCol]; long date = Long.parseLong((String)(resultRow[dateCol])) / (long)1000; - addHistory(androidHistory, url, title, date); + int visits = Integer.parseInt((String)(resultRow[visitsCol])); + addHistory(browserDBHistory, url, title, date, visits); placesHistory.add(url); + + String mime = (String)resultRow[faviconMimeCol]; + if (mime != null) { + // Some GIFs can cause us to lock up completely + // without exceptions or anything. Not cool. + if (mime.compareTo("image/gif") != 0) { + ByteBuffer dataBuff = + (ByteBuffer)resultRow[faviconDataCol]; + addFavicon(url, mime, dataBuff); + } + } } } catch (SQLiteBridgeException e) { Log.i(LOGTAG, "Failed to get bookmarks: " + e.getMessage()); @@ -241,25 +265,6 @@ public class ProfileMigrator { } } - protected void migrateFavicons(SQLiteBridge db) { - try { - ArrayList queryResult = db.query(faviconQuery); - final int urlCol = db.getColumnIndex(faviconUrl); - final int mimeCol = db.getColumnIndex(faviconMime); - final int dataCol = db.getColumnIndex(faviconData); - - for (Object[] resultRow: queryResult) { - String url = (String)resultRow[urlCol]; - String mime = (String)resultRow[mimeCol]; - ByteBuffer dataBuff = (ByteBuffer)resultRow[dataCol]; - addFavicon(url, mime, dataBuff); - } - } catch (SQLiteBridgeException e) { - Log.i(LOGTAG, "Failed to get favicons: " + e.getMessage()); - return; - } - } - protected void migratePlaces(File aFile) { String dbPath = aFile.getPath() + "/places.sqlite"; String dbPathWal = aFile.getPath() + "/places.sqlite-wal"; @@ -279,7 +284,6 @@ public class ProfileMigrator { db = new SQLiteBridge(dbPath); migrateBookmarks(db); migrateHistory(db); - migrateFavicons(db); db.close(); // Clean up diff --git a/mobile/android/base/Restarter.java.in b/mobile/android/base/Restarter.java.in index 52386e787f2b..8728c8599671 100644 --- a/mobile/android/base/Restarter.java.in +++ b/mobile/android/base/Restarter.java.in @@ -75,7 +75,9 @@ public class Restarter extends Activity { Log.i(LOGTAG, e.toString()); } try { - String action = "android.intent.action.MAIN"; + String action = "org.mozilla.gecko.restart_update".equals(getIntent().getAction()) ? + App.ACTION_UPDATE : Intent.ACTION_MAIN; + Intent intent = new Intent(action); intent.setClassName("@ANDROID_PACKAGE_NAME@", "@ANDROID_PACKAGE_NAME@.App"); diff --git a/mobile/android/base/SetupScreen.java b/mobile/android/base/SetupScreen.java new file mode 100644 index 000000000000..2443e72a5b4c --- /dev/null +++ b/mobile/android/base/SetupScreen.java @@ -0,0 +1,148 @@ +/* -*- Mode: Java; tab-width: 20; indent-tabs-mode: nil; -*- + * ***** 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 Android code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Gian-Carlo Pascutto + * + * 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 ***** */ + +package org.mozilla.gecko; + +import android.app.Dialog; +import android.content.Context; +import android.graphics.drawable.AnimationDrawable; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.os.Handler; +import android.util.Log; +import android.widget.ImageView; +import java.util.Timer; +import java.util.TimerTask; + +import org.mozilla.gecko.R; + +public class SetupScreen extends Dialog +{ + private static final String LOGTAG = "SetupScreen"; + // Default delay before showing dialog, in milliseconds + private static final int DEFAULT_DELAY = 100; + private AnimationDrawable mProgressSpinner; + private Context mContext; + private Timer mTimer; + private TimerTask mShowTask; + + public class ShowTask extends TimerTask { + private Handler mHandler; + + public ShowTask(Handler aHandler) { + mHandler = aHandler; + } + + @Override + public void run() { + mHandler.post(new Runnable() { + public void run() { + SetupScreen.this.show(); + } + }); + + } + + @Override + public boolean cancel() { + boolean stillInQueue = super.cancel(); + if (!stillInQueue) { + mHandler.post(new Runnable() { + public void run() { + // SetupScreen.dismiss calls us, + // we need to call the real Dialog.dismiss. + SetupScreen.super.dismiss(); + } + }); + } + return stillInQueue; + } + } + + public SetupScreen(Context aContext) { + super(aContext, android.R.style.Theme_NoTitleBar_Fullscreen); + mContext = aContext; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.setup_screen); + setCancelable(false); + + setTitle(R.string.splash_firstrun); + + ImageView spinnerImage = (ImageView)findViewById(R.id.spinner_image); + mProgressSpinner = (AnimationDrawable)spinnerImage.getBackground(); + spinnerImage.setImageDrawable(mProgressSpinner); + } + + @Override + public void onWindowFocusChanged (boolean hasFocus) { + mProgressSpinner.start(); + } + + public void showDelayed(Handler aHandler) { + showDelayed(aHandler, DEFAULT_DELAY); + } + + // Delay showing the dialog until at least aDelay ms have + // passed. We need to know the handler to (eventually) post the UI + // actions on. + public void showDelayed(Handler aHandler, int aDelay) { + mTimer = new Timer("SetupScreen"); + mShowTask = new ShowTask(aHandler); + mTimer.schedule(mShowTask, aDelay); + } + + @Override + public void dismiss() { + // Cancel the timers/tasks if we were using showDelayed, + // and post to the correct handler. + if (mShowTask != null) { + mShowTask.cancel(); + mShowTask = null; + } else { + // If not using showDelayed, just dismiss here. + super.dismiss(); + } + if (mTimer != null) { + mTimer.cancel(); + mTimer = null; + } + } +} diff --git a/mobile/android/base/SyncPreference.java b/mobile/android/base/SyncPreference.java new file mode 100644 index 000000000000..92cab8f42dbb --- /dev/null +++ b/mobile/android/base/SyncPreference.java @@ -0,0 +1,73 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- + * ***** 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 Android code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2009-2012 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Brian Nicholson + * + * 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 ***** */ + +package org.mozilla.gecko; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.preference.Preference; +import android.util.AttributeSet; +import android.util.Log; + +import org.mozilla.gecko.sync.setup.activities.SetupSyncActivity; + +class SyncPreference extends Preference { + private static final String FENNEC_ACCOUNT_TYPE = "org.mozilla.firefox_sync"; + private static final String SYNC_SETTINGS = "android.settings.SYNC_SETTINGS"; + + private Context mContext; + + public SyncPreference(Context context, AttributeSet attrs) { + super(context, attrs); + mContext = context; + } + + @Override + protected void onClick() { + // show sync setup if no accounts exist; otherwise, show account settings + Account[] accounts = AccountManager.get(mContext).getAccountsByType(FENNEC_ACCOUNT_TYPE); + Intent intent; + if (accounts.length > 0) + intent = new Intent(SYNC_SETTINGS); + else + intent = new Intent(mContext, SetupSyncActivity.class); + mContext.startActivity(intent); + } +} diff --git a/mobile/android/base/Tab.java b/mobile/android/base/Tab.java index 97d7db68c2ad..fd580d27beb3 100644 --- a/mobile/android/base/Tab.java +++ b/mobile/android/base/Tab.java @@ -55,11 +55,13 @@ import java.util.List; public final class Tab { private static final String LOGTAG = "GeckoTab"; - private static final int kThumbnailWidth = 120; - private static final int kThumbnailHeight = 80; + private static final int kThumbnailWidth = 136; + private static final int kThumbnailHeight = 77; - private static int sMinDim = 0; + private static float sMinDim = 0; private static float sDensity = 1; + private static int sMinScreenshotWidth = 0; + private static int sMinScreenshotHeight = 0; private int mId; private String mUrl; private String mTitle; @@ -145,24 +147,73 @@ public final class Tab { return mThumbnail; } + void initMetrics() { + DisplayMetrics metrics = new DisplayMetrics(); + GeckoApp.mAppContext.getWindowManager().getDefaultDisplay().getMetrics(metrics); + sMinDim = Math.min(metrics.widthPixels / kThumbnailWidth, metrics.heightPixels / kThumbnailHeight); + sDensity = metrics.density; + } + + float getMinDim() { + if (sMinDim == 0) + initMetrics(); + return sMinDim; + } + + float getDensity() { + if (sDensity == 0.0f) + initMetrics(); + return sDensity; + } + + int getMinScreenshotWidth() { + if (sMinScreenshotWidth != 0) + return sMinScreenshotWidth; + return sMinScreenshotWidth = (int)(getMinDim() * kThumbnailWidth); + } + + int getMinScreenshotHeight() { + if (sMinScreenshotHeight != 0) + return sMinScreenshotHeight; + return sMinScreenshotHeight = (int)(getMinDim() * kThumbnailHeight); + } + + int getThumbnailWidth() { + return (int)(kThumbnailWidth * getDensity()); + } + + int getThumbnailHeight() { + return (int)(kThumbnailHeight * getDensity()); + } + public void updateThumbnail(final Bitmap b) { final Tab tab = this; GeckoAppShell.getHandler().post(new Runnable() { public void run() { - if (sMinDim == 0) { - DisplayMetrics metrics = new DisplayMetrics(); - GeckoApp.mAppContext.getWindowManager().getDefaultDisplay().getMetrics(metrics); - sMinDim = Math.min(metrics.widthPixels / 3, metrics.heightPixels / 2); - sDensity = metrics.density; - } if (b != null) { try { - Bitmap cropped = Bitmap.createBitmap(b, 0, 0, sMinDim * 3, sMinDim * 2); - Bitmap bitmap = Bitmap.createScaledBitmap(cropped, (int) (kThumbnailWidth * sDensity), (int) (kThumbnailHeight * sDensity), false); - saveThumbnailToDB(new BitmapDrawable(bitmap)); - b.recycle(); + Bitmap cropped = null; + /* Crop to screen width if the bitmap is larger than the screen width or height. If smaller and the + * the aspect ratio is correct, just use the bitmap as is. Otherwise, fit the smaller + * smaller dimension, then crop the larger dimention. + */ + if (getMinScreenshotWidth() < b.getWidth() && getMinScreenshotHeight() < b.getHeight()) + cropped = Bitmap.createBitmap(b, 0, 0, getMinScreenshotWidth(), getMinScreenshotHeight()); + else if (b.getWidth() * getMinScreenshotHeight() == b.getHeight() * getMinScreenshotWidth()) + cropped = b; + else if (b.getWidth() * getMinScreenshotHeight() < b.getHeight() * getMinScreenshotWidth()) + cropped = Bitmap.createBitmap(b, 0, 0, b.getWidth(), + b.getWidth() * getMinScreenshotHeight() / getMinScreenshotWidth()); + else + cropped = Bitmap.createBitmap(b, 0, 0, + b.getHeight() * getMinScreenshotWidth() / getMinScreenshotHeight(), + b.getHeight()); - bitmap = Bitmap.createBitmap(cropped, 0, 0, (int) (138 * sDensity), (int) (78 * sDensity)); + Bitmap bitmap = Bitmap.createScaledBitmap(cropped, getThumbnailWidth(), getThumbnailHeight(), false); + saveThumbnailToDB(new BitmapDrawable(bitmap)); + + if (!cropped.equals(b)) + b.recycle(); mThumbnail = new BitmapDrawable(bitmap); cropped.recycle(); } catch (OutOfMemoryError oom) { diff --git a/mobile/android/base/Tabs.java b/mobile/android/base/Tabs.java index f1511e385b77..4ccf6eb70d92 100644 --- a/mobile/android/base/Tabs.java +++ b/mobile/android/base/Tabs.java @@ -288,8 +288,12 @@ public class Tabs implements GeckoEventListener { } public void refreshThumbnails() { - Iterator iterator = tabs.values().iterator(); - while (iterator.hasNext()) - GeckoApp.mAppContext.getAndProcessThumbnailForTab(iterator.next()); + GeckoAppShell.getHandler().post(new Runnable() { + public void run() { + Iterator iterator = tabs.values().iterator(); + while (iterator.hasNext()) + GeckoApp.mAppContext.getAndProcessThumbnailForTab(iterator.next()); + } + }); } } diff --git a/mobile/android/base/TabsTray.java b/mobile/android/base/TabsTray.java index a67e2fc7276e..e69761f2e904 100644 --- a/mobile/android/base/TabsTray.java +++ b/mobile/android/base/TabsTray.java @@ -91,8 +91,8 @@ public class TabsTray extends Activity implements GeckoApp.OnTabsChangedListener } }); - Tabs.getInstance().refreshThumbnails(); GeckoApp.registerOnTabsChangedListener(this); + Tabs.getInstance().refreshThumbnails(); onTabsChanged(null); } @@ -140,6 +140,7 @@ public class TabsTray extends Activity implements GeckoApp.OnTabsChangedListener void finishActivity() { finish(); overridePendingTransition(0, R.anim.shrink_fade_out); + GeckoAppShell.sendEventToGecko(new GeckoEvent("Tab:Screenshot:Cancel","")); } // Adapter to bind tabs into a list diff --git a/mobile/android/base/db/AndroidBrowserDB.java b/mobile/android/base/db/AndroidBrowserDB.java index 05d628628be9..41161e87d909 100644 --- a/mobile/android/base/db/AndroidBrowserDB.java +++ b/mobile/android/base/db/AndroidBrowserDB.java @@ -118,9 +118,31 @@ public class AndroidBrowserDB implements BrowserDB.BrowserDBIface { new String[] { uri }); } - public void updateHistoryDate(ContentResolver cr, String uri, long date) { + public void updateHistoryEntry(ContentResolver cr, String uri, String title, + long date, int visits) { + int oldVisits = 0; + Cursor cursor = null; + try { + cursor = cr.query(Browser.BOOKMARKS_URI, + new String[] { Browser.BookmarkColumns.VISITS }, + Browser.BookmarkColumns.URL + " = ?", + new String[] { uri }, + null); + + if (cursor.moveToFirst()) { + oldVisits = cursor.getInt(0); + } + } finally { + if (cursor != null) + cursor.close(); + } + ContentValues values = new ContentValues(); values.put(Browser.BookmarkColumns.DATE, date); + values.put(Browser.BookmarkColumns.VISITS, oldVisits + visits); + if (title != null) { + values.put(Browser.BookmarkColumns.TITLE, title); + } cr.update(Browser.BOOKMARKS_URI, values, @@ -145,7 +167,8 @@ public class AndroidBrowserDB implements BrowserDB.BrowserDBIface { BookmarkColumns.URL, BookmarkColumns.TITLE, BookmarkColumns.FAVICON, - BookmarkColumns.DATE }, + BookmarkColumns.DATE, + BookmarkColumns.VISITS }, // Bookmarks that have not been visited have a date value // of 0, so don't pick them up in the history view. Browser.BookmarkColumns.DATE + " > 0", @@ -155,6 +178,11 @@ public class AndroidBrowserDB implements BrowserDB.BrowserDBIface { return new AndroidDBCursor(c); } + public int getMaxHistoryCount() { + // Valid for Android versions up to 4.0. + return 250; + } + public void clearHistory(ContentResolver cr) { Browser.clearHistory(cr); } @@ -357,6 +385,8 @@ public class AndroidBrowserDB implements BrowserDB.BrowserDBIface { columnName = URL_COLUMN_THUMBNAIL; } else if (columnName.equals(BrowserDB.URLColumns.DATE_LAST_VISITED)) { columnName = Browser.BookmarkColumns.DATE; + } else if (columnName.equals(BrowserDB.URLColumns.VISITS)) { + columnName = Browser.BookmarkColumns.VISITS; } return columnName; diff --git a/mobile/android/base/db/BrowserDB.java b/mobile/android/base/db/BrowserDB.java index e32329510228..25db4c084840 100644 --- a/mobile/android/base/db/BrowserDB.java +++ b/mobile/android/base/db/BrowserDB.java @@ -50,6 +50,7 @@ public class BrowserDB { public static String FAVICON = "favicon"; public static String THUMBNAIL = "thumbnail"; public static String DATE_LAST_VISITED = "date-last-visited"; + public static String VISITS = "visits"; } private static BrowserDBIface sDb; @@ -63,12 +64,15 @@ public class BrowserDB { public void updateHistoryTitle(ContentResolver cr, String uri, String title); - public void updateHistoryDate(ContentResolver cr, String uri, long date); + public void updateHistoryEntry(ContentResolver cr, String uri, String title, + long date, int visits); public Cursor getAllVisitedHistory(ContentResolver cr); public Cursor getRecentHistory(ContentResolver cr, int limit); + public int getMaxHistoryCount(); + public void clearHistory(ContentResolver cr); public Cursor getAllBookmarks(ContentResolver cr); @@ -107,8 +111,9 @@ public class BrowserDB { sDb.updateHistoryTitle(cr, uri, title); } - public static void updateHistoryDate(ContentResolver cr, String uri, long date) { - sDb.updateHistoryDate(cr, uri, date); + public static void updateHistoryEntry(ContentResolver cr, String uri, String title, + long date, int visits) { + sDb.updateHistoryEntry(cr, uri, title, date, visits); } public static Cursor getAllVisitedHistory(ContentResolver cr) { @@ -119,6 +124,10 @@ public class BrowserDB { return sDb.getRecentHistory(cr, limit); } + public static int getMaxHistoryCount() { + return sDb.getMaxHistoryCount(); + } + public static void clearHistory(ContentResolver cr) { sDb.clearHistory(cr); } diff --git a/mobile/android/base/db/LocalBrowserDB.java b/mobile/android/base/db/LocalBrowserDB.java index b11463c27479..5ba99165f4ed 100644 --- a/mobile/android/base/db/LocalBrowserDB.java +++ b/mobile/android/base/db/LocalBrowserDB.java @@ -200,9 +200,31 @@ public class LocalBrowserDB implements BrowserDB.BrowserDBIface { new String[] { uri }); } - public void updateHistoryDate(ContentResolver cr, String uri, long date) { + public void updateHistoryEntry(ContentResolver cr, String uri, String title, + long date, int visits) { + int oldVisits = 0; + Cursor cursor = null; + try { + cursor = cr.query(appendProfile(History.CONTENT_URI), + new String[] { History.VISITS }, + History.URL + " = ?", + new String[] { uri }, + null); + + if (cursor.moveToFirst()) { + oldVisits = cursor.getInt(0); + } + } finally { + if (cursor != null) + cursor.close(); + } + ContentValues values = new ContentValues(); values.put(History.DATE_LAST_VISITED, date); + values.put(History.VISITS, oldVisits + visits); + if (title != null) { + values.put(History.TITLE, title); + } cr.update(appendProfile(History.CONTENT_URI), values, @@ -226,7 +248,8 @@ public class LocalBrowserDB implements BrowserDB.BrowserDBIface { History.URL, History.TITLE, History.FAVICON, - History.DATE_LAST_VISITED }, + History.DATE_LAST_VISITED, + History.VISITS }, History.DATE_LAST_VISITED + " > 0", null, History.DATE_LAST_VISITED + " DESC"); @@ -234,6 +257,10 @@ public class LocalBrowserDB implements BrowserDB.BrowserDBIface { return new LocalDBCursor(c); } + public int getMaxHistoryCount() { + return MAX_HISTORY_COUNT; + } + public void clearHistory(ContentResolver cr) { cr.delete(appendProfile(History.CONTENT_URI), null, null); } @@ -401,6 +428,8 @@ public class LocalBrowserDB implements BrowserDB.BrowserDBIface { columnName = ImageColumns.THUMBNAIL; } else if (columnName.equals(BrowserDB.URLColumns.DATE_LAST_VISITED)) { columnName = History.DATE_LAST_VISITED; + } else if (columnName.equals(BrowserDB.URLColumns.VISITS)) { + columnName = History.VISITS; } return columnName; diff --git a/mobile/android/base/gfx/GeckoSoftwareLayerClient.java b/mobile/android/base/gfx/GeckoSoftwareLayerClient.java index 97ce42fee27f..00346f73bd7e 100644 --- a/mobile/android/base/gfx/GeckoSoftwareLayerClient.java +++ b/mobile/android/base/gfx/GeckoSoftwareLayerClient.java @@ -162,7 +162,7 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL GeckoAppShell.registerGeckoEventListener("Viewport:UpdateAndDraw", this); GeckoAppShell.registerGeckoEventListener("Viewport:UpdateLater", this); GeckoAppShell.registerGeckoEventListener("Document:Shown", this); - GeckoAppShell.registerGeckoEventListener("Tab:Selected", this); + GeckoAppShell.registerGeckoEventListener("Tab:Selected:Done", this); sendResizeEventIfNecessary(); } @@ -519,7 +519,7 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL } else if ("Viewport:UpdateLater".equals(event)) { mUpdateViewportOnEndDraw = true; } else if (("Document:Shown".equals(event) || - "Tab:Selected".equals(event)) && + "Tab:Selected:Done".equals(event)) && (mTileLayer instanceof MultiTileLayer)) { beginTransaction(mTileLayer); try { diff --git a/mobile/android/base/gfx/LayerController.java b/mobile/android/base/gfx/LayerController.java index 7b13c3881024..06332b4e795d 100644 --- a/mobile/android/base/gfx/LayerController.java +++ b/mobile/android/base/gfx/LayerController.java @@ -189,10 +189,24 @@ public class LayerController { public void setViewportSize(FloatSize size) { // Resize the viewport, and modify its zoom factor so that the page retains proportionally // zoomed relative to the screen. + float oldHeight = mViewportMetrics.getSize().height; float oldWidth = mViewportMetrics.getSize().width; float oldZoomFactor = mViewportMetrics.getZoomFactor(); mViewportMetrics.setSize(size); + // if the viewport got larger (presumably because the vkb went away), and the page + // is smaller than the new viewport size, increase the page size so that the panzoomcontroller + // doesn't zoom in to make it fit (bug 718270). this page size change is in anticipation of + // gecko increasing the page size to match the new viewport size, which will happen the next + // time we get a draw update. + if (size.width >= oldWidth && size.height >= oldHeight) { + FloatSize pageSize = mViewportMetrics.getPageSize(); + if (pageSize.width < size.width || pageSize.height < size.height) { + mViewportMetrics.setPageSize(new FloatSize(Math.max(pageSize.width, size.width), + Math.max(pageSize.height, size.height))); + } + } + PointF newFocus = new PointF(size.width / 2.0f, size.height / 2.0f); float newZoomFactor = size.width * oldZoomFactor / oldWidth; mViewportMetrics.scaleTo(newZoomFactor, newFocus); diff --git a/mobile/android/base/locales/en-US/android_strings.dtd b/mobile/android/base/locales/en-US/android_strings.dtd index 2803aed3c9e3..c03b21807278 100644 --- a/mobile/android/base/locales/en-US/android_strings.dtd +++ b/mobile/android/base/locales/en-US/android_strings.dtd @@ -69,6 +69,7 @@ + diff --git a/mobile/android/base/resources/drawable-hdpi-v8/favicon.png b/mobile/android/base/resources/drawable-hdpi-v8/favicon.png new file mode 100644 index 000000000000..b74375ec8aef Binary files /dev/null and b/mobile/android/base/resources/drawable-hdpi-v8/favicon.png differ diff --git a/mobile/android/base/resources/drawable-mdpi-v8/favicon.png b/mobile/android/base/resources/drawable-mdpi-v8/favicon.png new file mode 100644 index 000000000000..e8be73ed522e Binary files /dev/null and b/mobile/android/base/resources/drawable-mdpi-v8/favicon.png differ diff --git a/mobile/android/base/resources/drawable-xhdpi-v11/favicon.png b/mobile/android/base/resources/drawable-xhdpi-v11/favicon.png new file mode 100644 index 000000000000..ae307d3dd9a3 Binary files /dev/null and b/mobile/android/base/resources/drawable-xhdpi-v11/favicon.png differ diff --git a/mobile/android/base/resources/drawable/favicon.png b/mobile/android/base/resources/drawable/favicon.png deleted file mode 100644 index 8e66e5ae57e0..000000000000 Binary files a/mobile/android/base/resources/drawable/favicon.png and /dev/null differ diff --git a/mobile/android/base/resources/layout/abouthome_topsite_item.xml b/mobile/android/base/resources/layout/abouthome_topsite_item.xml index 714fa3b70b82..3e598e232cbe 100644 --- a/mobile/android/base/resources/layout/abouthome_topsite_item.xml +++ b/mobile/android/base/resources/layout/abouthome_topsite_item.xml @@ -8,15 +8,15 @@ android:layout_height="fill_parent"> + android:paddingBottom="2dip"> diff --git a/mobile/android/base/resources/layout/setup_screen.xml b/mobile/android/base/resources/layout/setup_screen.xml new file mode 100644 index 000000000000..269be1d04aac --- /dev/null +++ b/mobile/android/base/resources/layout/setup_screen.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + diff --git a/mobile/android/base/resources/layout/tabs_row.xml b/mobile/android/base/resources/layout/tabs_row.xml index b5bc55370efc..b32076c171e6 100644 --- a/mobile/android/base/resources/layout/tabs_row.xml +++ b/mobile/android/base/resources/layout/tabs_row.xml @@ -7,8 +7,8 @@ android:background="@drawable/tabs_tray_list_selector"> - - - + diff --git a/mobile/android/base/strings.xml.in b/mobile/android/base/strings.xml.in index 45b232a3e695..d1c1ed01df7c 100644 --- a/mobile/android/base/strings.xml.in +++ b/mobile/android/base/strings.xml.in @@ -74,6 +74,7 @@ &pref_font_size_medium; &pref_font_size_large; &pref_font_size_xlarge; + &pref_sync; &reload; &forward; diff --git a/mobile/android/branding/aurora/android-resources.mn b/mobile/android/branding/aurora/android-resources.mn index 6a19940fa868..c537ec5155ae 100644 --- a/mobile/android/branding/aurora/android-resources.mn +++ b/mobile/android/branding/aurora/android-resources.mn @@ -1,6 +1,4 @@ mobile/android/app/android/drawable/alertaddons.png mobile/android/app/android/drawable/alertdownloads.png -mobile/android/branding/aurora/content/splash.png -mobile/android/branding/aurora/content/splash_v9.9.png -mobile/android/branding/aurora/content/splash_v8.9.png +mobile/android/branding/aurora/content/logo.png mobile/android/branding/aurora/content/favicon32.png diff --git a/mobile/android/branding/beta/android-resources.mn b/mobile/android/branding/beta/android-resources.mn index 58951349996e..b764cddaef0a 100644 --- a/mobile/android/branding/beta/android-resources.mn +++ b/mobile/android/branding/beta/android-resources.mn @@ -1,6 +1,4 @@ mobile/android/app/android/drawable/alertaddons.png mobile/android/app/android/drawable/alertdownloads.png -mobile/android/branding/beta/content/splash.png -mobile/android/branding/beta/content/splash_v9.9.png -mobile/android/branding/beta/content/splash_v8.9.png +mobile/android/branding/beta/content/logo.png mobile/android/branding/beta/content/favicon32.png diff --git a/mobile/android/branding/nightly/android-resources.mn b/mobile/android/branding/nightly/android-resources.mn index 869bf89f9fc2..d7a908d6414f 100644 --- a/mobile/android/branding/nightly/android-resources.mn +++ b/mobile/android/branding/nightly/android-resources.mn @@ -1,6 +1,4 @@ mobile/android/app/android/drawable/alertaddons.png mobile/android/app/android/drawable/alertdownloads.png -mobile/android/branding/nightly/content/splash.png -mobile/android/branding/nightly/content/splash_v9.9.png -mobile/android/branding/nightly/content/splash_v8.9.png +mobile/android/branding/nightly/content/logo.png mobile/android/branding/nightly/content/favicon32.png diff --git a/mobile/android/branding/official/android-resources.mn b/mobile/android/branding/official/android-resources.mn index 9fd41a2b2c5d..c97ba90024fc 100644 --- a/mobile/android/branding/official/android-resources.mn +++ b/mobile/android/branding/official/android-resources.mn @@ -1,6 +1,4 @@ mobile/android/app/android/drawable/alertaddons.png mobile/android/app/android/drawable/alertdownloads.png -mobile/android/branding/official/content/splash.png -mobile/android/branding/official/content/splash_v9.9.png -mobile/android/branding/official/content/splash_v8.9.png +mobile/android/branding/official/content/logo.png mobile/android/branding/official/content/favicon32.png diff --git a/mobile/android/branding/unofficial/android-resources.mn b/mobile/android/branding/unofficial/android-resources.mn index 5013dc4032c9..9f5a2c5903a6 100644 --- a/mobile/android/branding/unofficial/android-resources.mn +++ b/mobile/android/branding/unofficial/android-resources.mn @@ -1,6 +1,4 @@ mobile/android/app/android/drawable/alertaddons.png mobile/android/app/android/drawable/alertdownloads.png -mobile/android/branding/unofficial/content/splash.png -mobile/android/branding/unofficial/content/splash_v9.9.png -mobile/android/branding/unofficial/content/splash_v8.9.png mobile/android/branding/unofficial/content/favicon32.png +mobile/android/branding/unofficial/content/logo.png diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 72da2b555c7f..2d55ee9a7e02 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -504,7 +504,31 @@ var BrowserApp = { this._tabs.splice(this._tabs.indexOf(aTab), 1); }, + screenshotQueue: null, + screenshotTab: function screenshotTab(aData) { + if (this.screenshotQueue == null) { + this.screenShotQueue = []; + this.doScreenshotTab(aData); + } else { + this.screenshotQueue.push(aData); + } + }, + + doNextScreenshot: function() { + if (this.screenshotQueue == null || this.screenshotQueue.length == 0) { + this.screenshotQueue = null; + return; + } + let data = this.screenshotQueue.pop(); + if (data == null) { + this.screenshotQueue = null; + return; + } + this.doScreenshotTab(data); + }, + + doScreenshotTab: function doScreenshotTab(aData) { let json = JSON.parse(aData); let tab = this.getTabForId(parseInt(json.tabID)); let width = parseInt(json.width); @@ -539,6 +563,14 @@ var BrowserApp = { let evt = document.createEvent("UIEvents"); evt.initUIEvent("TabSelect", true, false, window, null); aTab.browser.dispatchEvent(evt); + + let message = { + gecko: { + type: "Tab:Selected:Done", + tabID: aTab.id + } + }; + sendMessageToJava(message); }, quit: function quit() { @@ -891,6 +923,8 @@ var BrowserApp = { this._handleTabClosed(this.getTabForId(parseInt(aData))); } else if (aTopic == "Tab:Screenshot") { this.screenshotTab(aData); + } else if (aTopic == "Tab:Screenshot:Cancel") { + this.screenshotQueue = null; } else if (aTopic == "Browser:Quit") { this.quit(); } else if (aTopic == "SaveAs:PDF") { @@ -1549,6 +1583,9 @@ Tab.prototype = { } }; sendMessageToJava(message); + Services.tm.mainThread.dispatch(function() { + BrowserApp.doNextScreenshot() + }, Ci.nsIThread.DISPATCH_NORMAL); }, updateTransform: function() { diff --git a/mobile/android/components/UpdatePrompt.js b/mobile/android/components/UpdatePrompt.js index 262744bcb4e9..c85c25bd7ab8 100644 --- a/mobile/android/components/UpdatePrompt.js +++ b/mobile/android/components/UpdatePrompt.js @@ -75,6 +75,11 @@ function getPref(func, preference, defaultValue) { return defaultValue; } +function sendMessageToJava(aMsg) { + let data = Cc["@mozilla.org/android/bridge;1"].getService(Ci.nsIAndroidBridge).handleGeckoMessage(JSON.stringify(aMsg)); + return JSON.parse(data); +} + // ----------------------------------------------------------------------- // Update Prompt // ----------------------------------------------------------------------- @@ -138,8 +143,11 @@ UpdatePrompt.prototype = { // If nothing aborted, restart the app if (cancelQuit.data == false) { - let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"].getService(Ci.nsIAppStartup); - appStartup.quit(Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit); + sendMessageToJava({ + gecko: { + type: "Update:Restart" + } + }); } } }, diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 80c3c499a0e2..8462f3822b92 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -170,10 +170,6 @@ pref("browser.chrome.image_icons.max_size", 1024); pref("browser.triple_click_selects_paragraph", true); -// When loading