From ceb0b935579bd5970384c87e15dfe92675b6fd05 Mon Sep 17 00:00:00 2001 From: Bas Schouten Date: Thu, 16 Feb 2012 04:08:08 +0100 Subject: [PATCH 01/93] Bug 726951: Correctly use height to normalize mask v-texture coordinate. r=jrmuizel --- gfx/2d/DrawTargetD2D.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gfx/2d/DrawTargetD2D.cpp b/gfx/2d/DrawTargetD2D.cpp index 13771aee7645..f3cb54db98df 100644 --- a/gfx/2d/DrawTargetD2D.cpp +++ b/gfx/2d/DrawTargetD2D.cpp @@ -633,7 +633,7 @@ DrawTargetD2D::DrawSurfaceWithShadow(SourceSurface *aSurface, if (mPushedClips.size()) { mPrivateData->mEffect->GetVariableByName("mask")->AsShaderResource()->SetResource(maskSRView); mPrivateData->mEffect->GetVariableByName("MaskTexCoords")->AsVector()-> - SetFloatVector(ShaderConstantRectD3D10(shadowDest.x / mSize.width, shadowDest.y / mSize.width, + SetFloatVector(ShaderConstantRectD3D10(shadowDest.x / mSize.width, shadowDest.y / mSize.height, Float(aSurface->GetSize().width) / mSize.width, Float(aSurface->GetSize().height) / mSize.height)); mPrivateData->mEffect->GetTechniqueByName("SampleTextureWithShadow")-> @@ -658,7 +658,7 @@ DrawTargetD2D::DrawSurfaceWithShadow(SourceSurface *aSurface, if (mPushedClips.size()) { mPrivateData->mEffect->GetVariableByName("MaskTexCoords")->AsVector()-> - SetFloatVector(ShaderConstantRectD3D10(aDest.x / mSize.width, aDest.y / mSize.width, + SetFloatVector(ShaderConstantRectD3D10(aDest.x / mSize.width, aDest.y / mSize.height, Float(aSurface->GetSize().width) / mSize.width, Float(aSurface->GetSize().height) / mSize.height)); mPrivateData->mEffect->GetTechniqueByName("SampleMaskedTexture")-> From ac9c902d7e87d8870109b8fc45fd6473db351bef Mon Sep 17 00:00:00 2001 From: Bas Schouten Date: Thu, 16 Feb 2012 04:08:12 +0100 Subject: [PATCH 02/93] Bug 726951 - Reftest: Test for shadow clips working correctly in non-rectangular canvases. r=jrmuizel --- .../canvas/726951-shadow-clips-ref.html | 18 ++++++++++++++++++ .../reftests/canvas/726951-shadow-clips.html | 18 ++++++++++++++++++ layout/reftests/canvas/reftest.list | 2 ++ 3 files changed, 38 insertions(+) create mode 100644 layout/reftests/canvas/726951-shadow-clips-ref.html create mode 100644 layout/reftests/canvas/726951-shadow-clips.html diff --git a/layout/reftests/canvas/726951-shadow-clips-ref.html b/layout/reftests/canvas/726951-shadow-clips-ref.html new file mode 100644 index 000000000000..b7be1ec0c7cb --- /dev/null +++ b/layout/reftests/canvas/726951-shadow-clips-ref.html @@ -0,0 +1,18 @@ + + + + + + + diff --git a/layout/reftests/canvas/726951-shadow-clips.html b/layout/reftests/canvas/726951-shadow-clips.html new file mode 100644 index 000000000000..b14e0c307d86 --- /dev/null +++ b/layout/reftests/canvas/726951-shadow-clips.html @@ -0,0 +1,18 @@ + + + + + + + diff --git a/layout/reftests/canvas/reftest.list b/layout/reftests/canvas/reftest.list index 375880f3e968..cb8a38777b98 100644 --- a/layout/reftests/canvas/reftest.list +++ b/layout/reftests/canvas/reftest.list @@ -75,4 +75,6 @@ fails-if(/Mac\x20OS\x20X\x2010\.[56]/.test(http.oscpu)) == 672646-alpha-radial-g != 693610-1.html 693610-1-notref.html # bug 693610: multiple glyph runs should not be overprinted +== 726951-shadow-clips.html 726951-shadow-clips-ref.html + == transformed-clip.html transformed-clip-ref.html From 97b4dcee77c8626b51c3daa2a44f0d94d08ed97f Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Wed, 15 Feb 2012 22:05:51 -0800 Subject: [PATCH 03/93] Bug 726045 - Match Fennec history limit. --- .../base/sync/stage/AndroidBrowserHistoryServerSyncStage.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mobile/android/base/sync/stage/AndroidBrowserHistoryServerSyncStage.java b/mobile/android/base/sync/stage/AndroidBrowserHistoryServerSyncStage.java index d745591df1b5..769921264c61 100644 --- a/mobile/android/base/sync/stage/AndroidBrowserHistoryServerSyncStage.java +++ b/mobile/android/base/sync/stage/AndroidBrowserHistoryServerSyncStage.java @@ -50,7 +50,7 @@ public class AndroidBrowserHistoryServerSyncStage extends ServerSyncStage { // Eventually this kind of sync stage will be data-driven, // and all this hard-coding can go away. private static final String HISTORY_SORT = "index"; - private static final long HISTORY_REQUEST_LIMIT = 500; + private static final long HISTORY_REQUEST_LIMIT = 250; @Override public void execute(org.mozilla.gecko.sync.GlobalSession session) throws NoSuchStageException { @@ -85,4 +85,4 @@ public class AndroidBrowserHistoryServerSyncStage extends ServerSyncStage { protected RecordFactory getRecordFactory() { return new HistoryRecordFactory(); } -} \ No newline at end of file +} From 390b9bd7efebd50cbeb74ca1ecf5e93b3184d4e8 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Wed, 15 Feb 2012 22:05:51 -0800 Subject: [PATCH 04/93] Bug 722524. r=rnewman --- .../jpake/Gx3OrGx4IsZeroOrOneException.java | 42 +++++++++++++++++++ .../android/base/sync/jpake/JPakeClient.java | 36 +++++++++------- .../android/base/sync/jpake/JPakeCrypto.java | 11 ++--- mobile/android/sync/java-sources.mn | 2 +- 4 files changed, 71 insertions(+), 20 deletions(-) create mode 100644 mobile/android/base/sync/jpake/Gx3OrGx4IsZeroOrOneException.java diff --git a/mobile/android/base/sync/jpake/Gx3OrGx4IsZeroOrOneException.java b/mobile/android/base/sync/jpake/Gx3OrGx4IsZeroOrOneException.java new file mode 100644 index 000000000000..1a791b2bf413 --- /dev/null +++ b/mobile/android/base/sync/jpake/Gx3OrGx4IsZeroOrOneException.java @@ -0,0 +1,42 @@ +/* ***** 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 Android Sync Client. + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chenxia Liu + * + * 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.sync.jpake; + +public class Gx3OrGx4IsZeroOrOneException extends Exception { + private static final long serialVersionUID = 7347530447460039679L; +} diff --git a/mobile/android/base/sync/jpake/JPakeClient.java b/mobile/android/base/sync/jpake/JPakeClient.java index ed2296cb8915..aefadebff41c 100644 --- a/mobile/android/base/sync/jpake/JPakeClient.java +++ b/mobile/android/base/sync/jpake/JPakeClient.java @@ -387,12 +387,14 @@ public class JPakeClient implements JPakeRequestDelegate { // Jpake round 2 try { JPakeCrypto.round2(secret, jParty, numGen); - } catch (Gx4IsOneException e) { - Log.e(LOG_TAG, "gx4 cannot equal 1."); + } catch (Gx3OrGx4IsZeroOrOneException e) { + Log.e(LOG_TAG, "gx3 and gx4 cannot equal 0 or 1."); abort(Constants.JPAKE_ERROR_INTERNAL); + return; } catch (IncorrectZkpException e) { Log.e(LOG_TAG, "ZKP mismatch"); abort(Constants.JPAKE_ERROR_WRONGMESSAGE); + return; } // Make outgoing payload. @@ -491,7 +493,20 @@ public class JPakeClient implements JPakeRequestDelegate { this.state = State.VERIFY_PAIRING; scheduleGetRequest(jpakePollInterval); } else { // Prepare and send verification of keys. - jOutgoing = computeKeyVerification(myKeyBundle); + try { + jOutgoing = computeKeyVerification(myKeyBundle); + } catch (UnsupportedEncodingException e) { + Log.e(LOG_TAG, "Failed to encrypt key verification value.", e); + abort(Constants.JPAKE_ERROR_INTERNAL); + e.printStackTrace(); + return; + } catch (CryptoException e) { + Log.e(LOG_TAG, "Failed to encrypt key verification value.", e); + abort(Constants.JPAKE_ERROR_INTERNAL); + e.printStackTrace(); + return; + } + stateContext = State.VERIFY_KEY; this.state = State.PUT; putStep(); @@ -502,19 +517,12 @@ public class JPakeClient implements JPakeRequestDelegate { * (Receiver Only) Helper method to compute verification message from JPake * key bundle, to be sent to other device for verification. */ - public ExtendedJSONObject computeKeyVerification(KeyBundle keyBundle) { + public ExtendedJSONObject computeKeyVerification(KeyBundle keyBundle) + throws UnsupportedEncodingException, CryptoException + { Log.d(LOG_TAG, "Encrypting key verification value."); // KeyBundle not null - ExtendedJSONObject jPayload = null; - try { - jPayload = encryptPayload(JPAKE_VERIFY_VALUE, keyBundle); - } catch (UnsupportedEncodingException e) { - Log.e(LOG_TAG, "Failed to encrypt key verification value.", e); - abort(Constants.JPAKE_ERROR_INTERNAL); - } catch (CryptoException e) { - Log.e(LOG_TAG, "Failed to encrypt key verification value.", e); - abort(Constants.JPAKE_ERROR_INTERNAL); - } + ExtendedJSONObject jPayload = encryptPayload(JPAKE_VERIFY_VALUE, keyBundle); Log.d( LOG_TAG, "enc key64: " diff --git a/mobile/android/base/sync/jpake/JPakeCrypto.java b/mobile/android/base/sync/jpake/JPakeCrypto.java index ea37a57a2cd4..5b4215b17a56 100644 --- a/mobile/android/base/sync/jpake/JPakeCrypto.java +++ b/mobile/android/base/sync/jpake/JPakeCrypto.java @@ -131,16 +131,17 @@ public class JPakeCrypto { * @param gx4 * @param zkp3 * @param zkp4 - * @throws Gx4IsOneException * @throws IncorrectZkpException */ public static void round2(String secret, JPakeParty jp, - JPakeNumGenerator gen) throws Gx4IsOneException, IncorrectZkpException { + JPakeNumGenerator gen) throws IncorrectZkpException, Gx3OrGx4IsZeroOrOneException { Log.d(LOG_TAG, "round2 started."); - if (BigInteger.ONE.compareTo(jp.gx4) == 0) { - throw new Gx4IsOneException(); + // checkZkp does some additional checks, but we can throw a more informative exception here. + if (BigInteger.ZERO.compareTo(jp.gx3) == 0 || BigInteger.ONE.compareTo(jp.gx3) == 0 || + BigInteger.ZERO.compareTo(jp.gx4) == 0 || BigInteger.ONE.compareTo(jp.gx4) == 0) { + throw new Gx3OrGx4IsZeroOrOneException(); } // Check ZKP. @@ -243,7 +244,7 @@ public class JPakeCrypto { // Check parameters of zkp, and compare to computed hash. These shouldn't // fail. - if (gx.compareTo(BigInteger.ZERO) < 1) {// g^x > 1 + if (gx.compareTo(BigInteger.ONE) < 1) { // g^x > 1. Log.e(LOG_TAG, "g^x > 1 fails."); throw new IncorrectZkpException(); } diff --git a/mobile/android/sync/java-sources.mn b/mobile/android/sync/java-sources.mn index 0511919e52a2..64b4efee8499 100644 --- a/mobile/android/sync/java-sources.mn +++ b/mobile/android/sync/java-sources.mn @@ -1 +1 @@ -sync/AlreadySyncingException.java sync/CollectionKeys.java sync/CredentialsSource.java sync/crypto/CryptoException.java sync/crypto/Cryptographer.java sync/crypto/CryptoInfo.java sync/crypto/HKDF.java sync/crypto/HMACVerificationException.java sync/crypto/KeyBundle.java sync/crypto/MissingCryptoInputException.java sync/crypto/NoKeyBundleException.java sync/cryptographer/CryptoStatusBundle.java sync/cryptographer/SyncCryptographer.java sync/CryptoRecord.java sync/DelayedWorkTracker.java sync/delegates/FreshStartDelegate.java sync/delegates/GlobalSessionCallback.java sync/delegates/InfoCollectionsDelegate.java sync/delegates/KeyUploadDelegate.java sync/delegates/MetaGlobalDelegate.java sync/delegates/WipeServerDelegate.java sync/ExtendedJSONObject.java sync/GlobalSession.java sync/HTTPFailureException.java sync/InfoCollections.java sync/jpake/BigIntegerHelper.java sync/jpake/Gx4IsOneException.java sync/jpake/IncorrectZkpException.java sync/jpake/JPakeClient.java sync/jpake/JPakeCrypto.java sync/jpake/JPakeNoActivePairingException.java sync/jpake/JPakeNumGenerator.java sync/jpake/JPakeNumGeneratorRandom.java sync/jpake/JPakeParty.java sync/jpake/JPakeRequest.java sync/jpake/JPakeRequestDelegate.java sync/jpake/JPakeResponse.java sync/jpake/JPakeUtils.java sync/jpake/Zkp.java sync/MetaGlobal.java sync/MetaGlobalException.java sync/MetaGlobalMissingEnginesException.java sync/MetaGlobalNotSetException.java sync/middleware/Crypto5MiddlewareRepository.java sync/middleware/Crypto5MiddlewareRepositorySession.java sync/middleware/MiddlewareRepository.java sync/net/BaseResource.java sync/net/CompletedEntity.java sync/net/HandleProgressException.java sync/net/Resource.java sync/net/ResourceDelegate.java sync/net/SyncResourceDelegate.java sync/net/SyncResponse.java sync/net/SyncStorageCollectionRequest.java sync/net/SyncStorageCollectionRequestDelegate.java sync/net/SyncStorageRecordRequest.java sync/net/SyncStorageRequest.java sync/net/SyncStorageRequestDelegate.java sync/net/SyncStorageRequestIncrementalDelegate.java sync/net/SyncStorageResponse.java sync/net/TLSSocketFactory.java sync/net/WBOCollectionRequestDelegate.java sync/NoCollectionKeysSetException.java sync/NonArrayJSONException.java sync/NonObjectJSONException.java sync/PrefsSource.java sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java sync/repositories/android/AndroidBrowserBookmarksRepository.java sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java sync/repositories/android/AndroidBrowserHistoryDataAccessor.java sync/repositories/android/AndroidBrowserHistoryDataExtender.java sync/repositories/android/AndroidBrowserHistoryRepository.java sync/repositories/android/AndroidBrowserHistoryRepositorySession.java sync/repositories/android/AndroidBrowserPasswordsDataAccessor.java sync/repositories/android/AndroidBrowserPasswordsRepository.java sync/repositories/android/AndroidBrowserPasswordsRepositorySession.java sync/repositories/android/AndroidBrowserRepository.java sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java sync/repositories/android/AndroidBrowserRepositorySession.java sync/repositories/android/BrowserContract.java sync/repositories/android/PasswordColumns.java sync/repositories/android/RepoUtils.java sync/repositories/BookmarkNeedsReparentingException.java sync/repositories/BookmarksRepository.java sync/repositories/ConstrainedServer11Repository.java sync/repositories/delegates/DeferrableRepositorySessionCreationDelegate.java sync/repositories/delegates/DeferredRepositorySessionBeginDelegate.java sync/repositories/delegates/DeferredRepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/DeferredRepositorySessionFinishDelegate.java sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionBeginDelegate.java sync/repositories/delegates/RepositorySessionCleanDelegate.java sync/repositories/delegates/RepositorySessionCreationDelegate.java sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/RepositorySessionFinishDelegate.java sync/repositories/delegates/RepositorySessionGuidsSinceDelegate.java sync/repositories/delegates/RepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionWipeDelegate.java sync/repositories/domain/BookmarkRecord.java sync/repositories/domain/BookmarkRecordFactory.java sync/repositories/domain/HistoryRecord.java sync/repositories/domain/HistoryRecordFactory.java sync/repositories/domain/PasswordRecord.java sync/repositories/domain/Record.java sync/repositories/HashSetStoreTracker.java sync/repositories/HistoryRepository.java sync/repositories/IdentityRecordFactory.java sync/repositories/InactiveSessionException.java sync/repositories/InvalidBookmarkTypeException.java sync/repositories/InvalidRequestException.java sync/repositories/InvalidSessionTransitionException.java sync/repositories/MultipleRecordsForGuidException.java sync/repositories/NoGuidForIdException.java sync/repositories/NoStoreDelegateException.java sync/repositories/NullCursorException.java sync/repositories/ParentNotFoundException.java sync/repositories/ProfileDatabaseException.java sync/repositories/RecordFactory.java sync/repositories/RecordFilter.java sync/repositories/Repository.java sync/repositories/RepositorySession.java sync/repositories/RepositorySessionBundle.java sync/repositories/Server11Repository.java sync/repositories/Server11RepositorySession.java sync/repositories/StoreTracker.java sync/repositories/StoreTrackingRepositorySession.java sync/setup/activities/AccountActivity.java sync/setup/activities/SetupFailureActivity.java sync/setup/activities/SetupSuccessActivity.java sync/setup/activities/SetupSyncActivity.java sync/setup/Constants.java sync/setup/SyncAuthenticatorService.java sync/stage/AndroidBrowserBookmarksServerSyncStage.java sync/stage/AndroidBrowserHistoryServerSyncStage.java sync/stage/CheckPreconditionsStage.java sync/stage/CompletedStage.java sync/stage/EnsureClusterURLStage.java sync/stage/EnsureKeysStage.java sync/stage/FetchInfoCollectionsStage.java sync/stage/FetchMetaGlobalStage.java sync/stage/GlobalSyncStage.java sync/stage/NoSuchStageException.java sync/stage/NoSyncIDException.java sync/stage/ServerSyncStage.java sync/StubActivity.java sync/syncadapter/SyncAdapter.java sync/syncadapter/SyncService.java sync/SyncConfiguration.java sync/SyncConfigurationException.java sync/SyncException.java sync/synchronizer/ConcurrentRecordConsumer.java sync/synchronizer/RecordConsumer.java sync/synchronizer/RecordsChannel.java sync/synchronizer/RecordsChannelDelegate.java sync/synchronizer/RecordsConsumerDelegate.java sync/synchronizer/SerialRecordConsumer.java sync/synchronizer/SessionNotBegunException.java sync/synchronizer/Synchronizer.java sync/synchronizer/SynchronizerDelegate.java sync/synchronizer/SynchronizerSession.java sync/synchronizer/SynchronizerSessionDelegate.java sync/synchronizer/UnbundleError.java sync/synchronizer/UnexpectedSessionException.java sync/SynchronizerConfiguration.java sync/SynchronizerConfigurations.java sync/ThreadPool.java sync/UnexpectedJSONException.java sync/UnknownSynchronizerConfigurationVersionException.java sync/Utils.java +sync/AlreadySyncingException.java sync/CollectionKeys.java sync/CredentialsSource.java sync/crypto/CryptoException.java sync/crypto/Cryptographer.java sync/crypto/CryptoInfo.java sync/crypto/HKDF.java sync/crypto/HMACVerificationException.java sync/crypto/KeyBundle.java sync/crypto/MissingCryptoInputException.java sync/crypto/NoKeyBundleException.java sync/cryptographer/CryptoStatusBundle.java sync/cryptographer/SyncCryptographer.java sync/CryptoRecord.java sync/DelayedWorkTracker.java sync/delegates/FreshStartDelegate.java sync/delegates/GlobalSessionCallback.java sync/delegates/InfoCollectionsDelegate.java sync/delegates/KeyUploadDelegate.java sync/delegates/MetaGlobalDelegate.java sync/delegates/WipeServerDelegate.java sync/ExtendedJSONObject.java sync/GlobalSession.java sync/HTTPFailureException.java sync/InfoCollections.java sync/jpake/BigIntegerHelper.java sync/jpake/Gx3OrGx4IsZeroOrOneException.java sync/jpake/IncorrectZkpException.java sync/jpake/JPakeClient.java sync/jpake/JPakeCrypto.java sync/jpake/JPakeNoActivePairingException.java sync/jpake/JPakeNumGenerator.java sync/jpake/JPakeNumGeneratorRandom.java sync/jpake/JPakeParty.java sync/jpake/JPakeRequest.java sync/jpake/JPakeRequestDelegate.java sync/jpake/JPakeResponse.java sync/jpake/JPakeUtils.java sync/jpake/Zkp.java sync/MetaGlobal.java sync/MetaGlobalException.java sync/MetaGlobalMissingEnginesException.java sync/MetaGlobalNotSetException.java sync/middleware/Crypto5MiddlewareRepository.java sync/middleware/Crypto5MiddlewareRepositorySession.java sync/middleware/MiddlewareRepository.java sync/net/BaseResource.java sync/net/CompletedEntity.java sync/net/HandleProgressException.java sync/net/Resource.java sync/net/ResourceDelegate.java sync/net/SyncResourceDelegate.java sync/net/SyncResponse.java sync/net/SyncStorageCollectionRequest.java sync/net/SyncStorageCollectionRequestDelegate.java sync/net/SyncStorageRecordRequest.java sync/net/SyncStorageRequest.java sync/net/SyncStorageRequestDelegate.java sync/net/SyncStorageRequestIncrementalDelegate.java sync/net/SyncStorageResponse.java sync/net/TLSSocketFactory.java sync/net/WBOCollectionRequestDelegate.java sync/NoCollectionKeysSetException.java sync/NonArrayJSONException.java sync/NonObjectJSONException.java sync/PrefsSource.java sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java sync/repositories/android/AndroidBrowserBookmarksRepository.java sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java sync/repositories/android/AndroidBrowserHistoryDataAccessor.java sync/repositories/android/AndroidBrowserHistoryDataExtender.java sync/repositories/android/AndroidBrowserHistoryRepository.java sync/repositories/android/AndroidBrowserHistoryRepositorySession.java sync/repositories/android/AndroidBrowserPasswordsDataAccessor.java sync/repositories/android/AndroidBrowserPasswordsRepository.java sync/repositories/android/AndroidBrowserPasswordsRepositorySession.java sync/repositories/android/AndroidBrowserRepository.java sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java sync/repositories/android/AndroidBrowserRepositorySession.java sync/repositories/android/BrowserContract.java sync/repositories/android/PasswordColumns.java sync/repositories/android/RepoUtils.java sync/repositories/BookmarkNeedsReparentingException.java sync/repositories/BookmarksRepository.java sync/repositories/ConstrainedServer11Repository.java sync/repositories/delegates/DeferrableRepositorySessionCreationDelegate.java sync/repositories/delegates/DeferredRepositorySessionBeginDelegate.java sync/repositories/delegates/DeferredRepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/DeferredRepositorySessionFinishDelegate.java sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionBeginDelegate.java sync/repositories/delegates/RepositorySessionCleanDelegate.java sync/repositories/delegates/RepositorySessionCreationDelegate.java sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/RepositorySessionFinishDelegate.java sync/repositories/delegates/RepositorySessionGuidsSinceDelegate.java sync/repositories/delegates/RepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionWipeDelegate.java sync/repositories/domain/BookmarkRecord.java sync/repositories/domain/BookmarkRecordFactory.java sync/repositories/domain/HistoryRecord.java sync/repositories/domain/HistoryRecordFactory.java sync/repositories/domain/PasswordRecord.java sync/repositories/domain/Record.java sync/repositories/HashSetStoreTracker.java sync/repositories/HistoryRepository.java sync/repositories/IdentityRecordFactory.java sync/repositories/InactiveSessionException.java sync/repositories/InvalidBookmarkTypeException.java sync/repositories/InvalidRequestException.java sync/repositories/InvalidSessionTransitionException.java sync/repositories/MultipleRecordsForGuidException.java sync/repositories/NoGuidForIdException.java sync/repositories/NoStoreDelegateException.java sync/repositories/NullCursorException.java sync/repositories/ParentNotFoundException.java sync/repositories/ProfileDatabaseException.java sync/repositories/RecordFactory.java sync/repositories/RecordFilter.java sync/repositories/Repository.java sync/repositories/RepositorySession.java sync/repositories/RepositorySessionBundle.java sync/repositories/Server11Repository.java sync/repositories/Server11RepositorySession.java sync/repositories/StoreTracker.java sync/repositories/StoreTrackingRepositorySession.java sync/setup/activities/AccountActivity.java sync/setup/activities/SetupFailureActivity.java sync/setup/activities/SetupSuccessActivity.java sync/setup/activities/SetupSyncActivity.java sync/setup/Constants.java sync/setup/SyncAuthenticatorService.java sync/stage/AndroidBrowserBookmarksServerSyncStage.java sync/stage/AndroidBrowserHistoryServerSyncStage.java sync/stage/CheckPreconditionsStage.java sync/stage/CompletedStage.java sync/stage/EnsureClusterURLStage.java sync/stage/EnsureKeysStage.java sync/stage/FetchInfoCollectionsStage.java sync/stage/FetchMetaGlobalStage.java sync/stage/GlobalSyncStage.java sync/stage/NoSuchStageException.java sync/stage/NoSyncIDException.java sync/stage/ServerSyncStage.java sync/StubActivity.java sync/syncadapter/SyncAdapter.java sync/syncadapter/SyncService.java sync/SyncConfiguration.java sync/SyncConfigurationException.java sync/SyncException.java sync/synchronizer/ConcurrentRecordConsumer.java sync/synchronizer/RecordConsumer.java sync/synchronizer/RecordsChannel.java sync/synchronizer/RecordsChannelDelegate.java sync/synchronizer/RecordsConsumerDelegate.java sync/synchronizer/SerialRecordConsumer.java sync/synchronizer/SessionNotBegunException.java sync/synchronizer/Synchronizer.java sync/synchronizer/SynchronizerDelegate.java sync/synchronizer/SynchronizerSession.java sync/synchronizer/SynchronizerSessionDelegate.java sync/synchronizer/UnbundleError.java sync/synchronizer/UnexpectedSessionException.java sync/SynchronizerConfiguration.java sync/SynchronizerConfigurations.java sync/ThreadPool.java sync/UnexpectedJSONException.java sync/UnknownSynchronizerConfigurationVersionException.java sync/Utils.java From 2d70349b3cacd17b2d71dcb625f8f28fc8023825 Mon Sep 17 00:00:00 2001 From: Marina Samuel Date: Wed, 15 Feb 2012 22:05:52 -0800 Subject: [PATCH 05/93] Bug 724200 - SyncStorageRequest.delete() results in NullPointerException. r=rnewman --- mobile/android/base/sync/net/SyncStorageRequest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mobile/android/base/sync/net/SyncStorageRequest.java b/mobile/android/base/sync/net/SyncStorageRequest.java index 7c9f626bcbdd..4025e3d6b0f0 100644 --- a/mobile/android/base/sync/net/SyncStorageRequest.java +++ b/mobile/android/base/sync/net/SyncStorageRequest.java @@ -170,6 +170,9 @@ public class SyncStorageRequest implements Resource { if (ifUnmodifiedSince != null) { request.setHeader("x-weave-if-unmodified-since", ifUnmodifiedSince); } + if (request.getMethod().equalsIgnoreCase("DELETE")) { + request.addHeader("x-confirm-delete", "1"); + } } } @@ -192,7 +195,6 @@ public class SyncStorageRequest implements Resource { } public void delete() { - this.resource.request.addHeader("x-confirm-delete", "1"); this.resource.delete(); } From 69a2795004f5c7668400eee6f51b33d7abfb3f4e Mon Sep 17 00:00:00 2001 From: Nick Alexander Date: Wed, 15 Feb 2012 22:05:52 -0800 Subject: [PATCH 06/93] Bug 722496, Bug 722579, Bug 722482, Bug 722541. r=rnewman --- mobile/android/base/sync/Utils.java | 33 ++- .../android/base/sync/jpake/JPakeClient.java | 255 ++++++++++-------- .../android/base/sync/jpake/JPakeCrypto.java | 64 ++--- .../sync/jpake/JPakeNumGeneratorRandom.java | 13 +- .../base/sync/syncadapter/SyncAdapter.java | 1 + mobile/android/sync/java-sources.mn | 2 +- 6 files changed, 197 insertions(+), 171 deletions(-) diff --git a/mobile/android/base/sync/Utils.java b/mobile/android/base/sync/Utils.java index 0f5be6122bf5..002e46a6fe39 100644 --- a/mobile/android/base/sync/Utils.java +++ b/mobile/android/base/sync/Utils.java @@ -40,9 +40,10 @@ package org.mozilla.gecko.sync; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; +import java.math.BigInteger; import java.security.NoSuchAlgorithmException; import java.util.HashMap; -import java.util.Random; +import java.security.SecureRandom; import org.mozilla.apache.commons.codec.binary.Base32; import org.mozilla.apache.commons.codec.binary.Base64; @@ -56,6 +57,8 @@ public class Utils { private static final String LOG_TAG = "Utils"; + private static SecureRandom sharedSecureRandom = new SecureRandom(); + // See public static final int SHARED_PREFERENCES_MODE = 0; @@ -104,13 +107,35 @@ public class Utils { return new String(encodedBytes).replace("+", "-").replace("/", "_"); } - private static byte[] generateRandomBytes(int length) { + /* + * Helper to generate secure random bytes. + * + * @param length Number of bytes to generate. + */ + public static byte[] generateRandomBytes(int length) { byte[] bytes = new byte[length]; - Random random = new Random(System.nanoTime()); - random.nextBytes(bytes); + sharedSecureRandom.nextBytes(bytes); return bytes; } + /* + * Helper to generate a random integer in a specified range. + * + * @param r Generate an integer between 0 and r-1 inclusive. + */ + public static BigInteger generateBigIntegerLessThan(BigInteger r) { + int maxBytes = (int) Math.ceil(((double) r.bitLength()) / 8); + BigInteger randInt = new BigInteger(generateRandomBytes(maxBytes)); + return randInt.mod(r); + } + + /* + * Helper to reseed the shared secure random number generator. + */ + public static void reseedSharedRandom() { + sharedSecureRandom.setSeed(sharedSecureRandom.generateSeed(8)); + } + /* * Helper to convert Byte Array to a Hex String * Input: byte[] array diff --git a/mobile/android/base/sync/jpake/JPakeClient.java b/mobile/android/base/sync/jpake/JPakeClient.java index aefadebff41c..fdfa1e96567b 100644 --- a/mobile/android/base/sync/jpake/JPakeClient.java +++ b/mobile/android/base/sync/jpake/JPakeClient.java @@ -245,7 +245,7 @@ public class JPakeClient implements JPakeRequestDelegate { channelRequest = new JPakeRequest(jpakeServer + "new_channel", makeRequestResourceDelegate()); } catch (URISyntaxException e) { - e.printStackTrace(); + Log.e(LOG_TAG, "URISyntaxException", e); abort(Constants.JPAKE_ERROR_CHANNEL); return; } @@ -266,7 +266,7 @@ public class JPakeClient implements JPakeRequestDelegate { putRequest = new JPakeRequest(channelUrl, makeRequestResourceDelegate()); } catch (URISyntaxException e) { - e.printStackTrace(); + Log.e(LOG_TAG, "URISyntaxException", e); abort(Constants.JPAKE_ERROR_CHANNEL); return; } @@ -283,7 +283,7 @@ public class JPakeClient implements JPakeRequestDelegate { /* * Step One of J-PAKE protocol. */ - private void computeStepOne() { + private void computeStepOne() throws NoSuchAlgorithmException, UnsupportedEncodingException { Log.d(LOG_TAG, "Computing round 1."); JPakeCrypto.round1(jParty, numGen); @@ -321,7 +321,7 @@ public class JPakeClient implements JPakeRequestDelegate { * Verifies message computed by other party in their Step One. Creates Step * Two message to be sent. */ - private void computeStepTwo() { + private void computeStepTwo() throws NonObjectJSONException { Log.d(LOG_TAG, "Computing round 2."); // Check incoming message sender. @@ -332,61 +332,47 @@ public class JPakeClient implements JPakeRequestDelegate { } // Check incoming message fields. - ExtendedJSONObject iPayload = null; - try { - iPayload = jIncoming.getObject(Constants.JSON_KEY_PAYLOAD); - if (iPayload == null - || iPayload.getObject(Constants.ZKP_KEY_ZKP_X1) == null - || !theirSignerId.equals(iPayload.getObject(Constants.ZKP_KEY_ZKP_X1) - .get(Constants.ZKP_KEY_ID)) - || iPayload.getObject(Constants.ZKP_KEY_ZKP_X2) == null - || !theirSignerId.equals(iPayload.getObject(Constants.ZKP_KEY_ZKP_X2) - .get(Constants.ZKP_KEY_ID))) { - Log.e(LOG_TAG, "Invalid round 1 message: " + jIncoming.toJSONString()); - abort(Constants.JPAKE_ERROR_WRONGMESSAGE); - return; - } - } catch (NonObjectJSONException e) { - e.printStackTrace(); + ExtendedJSONObject iPayload = jIncoming.getObject(Constants.JSON_KEY_PAYLOAD); + if (iPayload == null) { + Log.e(LOG_TAG, "Invalid round 1 message: " + jIncoming.toJSONString()); + abort(Constants.JPAKE_ERROR_WRONGMESSAGE); + return; + } + + ExtendedJSONObject zkpPayload3 = iPayload.getObject(Constants.ZKP_KEY_ZKP_X1); + ExtendedJSONObject zkpPayload4 = iPayload.getObject(Constants.ZKP_KEY_ZKP_X2); + if (zkpPayload3 == null || zkpPayload4 == null) { + Log.e(LOG_TAG, "Invalid round 1 zkpPayload message"); + abort(Constants.JPAKE_ERROR_WRONGMESSAGE); + return; + } + + if (!theirSignerId.equals(zkpPayload3.get(Constants.ZKP_KEY_ID)) || + !theirSignerId.equals(zkpPayload4.get(Constants.ZKP_KEY_ID))) { + Log.e(LOG_TAG, "Invalid round 1 zkpPayload message"); + abort(Constants.JPAKE_ERROR_WRONGMESSAGE); + return; } // Extract message fields. - jParty.gx3 = new BigInteger((String) iPayload.get(Constants.ZKP_KEY_GX1), - 16); - jParty.gx4 = new BigInteger((String) iPayload.get(Constants.ZKP_KEY_GX2), - 16); - - ExtendedJSONObject zkpPayload3 = null; - ExtendedJSONObject zkpPayload4 = null; - try { - zkpPayload3 = iPayload.getObject(Constants.ZKP_KEY_ZKP_X1); - zkpPayload4 = iPayload.getObject(Constants.ZKP_KEY_ZKP_X2); - if (zkpPayload3 == null || zkpPayload4 == null) { - Log.e(LOG_TAG, "Invalid round 1 zkpPayload message"); - abort(Constants.JPAKE_ERROR_WRONGMESSAGE); - return; - } - } catch (NonObjectJSONException e) { - e.printStackTrace(); - } + jParty.gx3 = new BigInteger((String) iPayload.get(Constants.ZKP_KEY_GX1), 16); + jParty.gx4 = new BigInteger((String) iPayload.get(Constants.ZKP_KEY_GX2), 16); // Extract ZKPs. String zkp3_gr = (String) zkpPayload3.get(Constants.ZKP_KEY_GR); - String zkp3_b = (String) zkpPayload3.get(Constants.ZKP_KEY_B); + String zkp3_b = (String) zkpPayload3.get(Constants.ZKP_KEY_B); String zkp3_id = (String) zkpPayload3.get(Constants.ZKP_KEY_ID); String zkp4_gr = (String) zkpPayload4.get(Constants.ZKP_KEY_GR); - String zkp4_b = (String) zkpPayload4.get(Constants.ZKP_KEY_B); + String zkp4_b = (String) zkpPayload4.get(Constants.ZKP_KEY_B); String zkp4_id = (String) zkpPayload4.get(Constants.ZKP_KEY_ID); - jParty.zkp3 = new Zkp(new BigInteger(zkp3_gr, 16), new BigInteger(zkp3_b, - 16), zkp3_id); - jParty.zkp4 = new Zkp(new BigInteger(zkp4_gr, 16), new BigInteger(zkp4_b, - 16), zkp4_id); + jParty.zkp3 = new Zkp(new BigInteger(zkp3_gr, 16), new BigInteger(zkp3_b, 16), zkp3_id); + jParty.zkp4 = new Zkp(new BigInteger(zkp4_gr, 16), new BigInteger(zkp4_b, 16), zkp4_id); - // Jpake round 2 + // J-PAKE round 2. try { - JPakeCrypto.round2(secret, jParty, numGen); + JPakeCrypto.round2(JPakeClient.secretAsBigInteger(secret), jParty, numGen); } catch (Gx3OrGx4IsZeroOrOneException e) { Log.e(LOG_TAG, "gx3 and gx4 cannot equal 0 or 1."); abort(Constants.JPAKE_ERROR_INTERNAL); @@ -395,14 +381,21 @@ public class JPakeClient implements JPakeRequestDelegate { Log.e(LOG_TAG, "ZKP mismatch"); abort(Constants.JPAKE_ERROR_WRONGMESSAGE); return; + } catch (NoSuchAlgorithmException e) { + Log.e(LOG_TAG, "NoSuchAlgorithmException", e); + abort(Constants.JPAKE_ERROR_INTERNAL); + return; + } catch (UnsupportedEncodingException e) { + Log.e(LOG_TAG, "UnsupportedEncodingException", e); + abort(Constants.JPAKE_ERROR_INTERNAL); + return; } // Make outgoing payload. Zkp zkpA = jParty.thisZkpA; ExtendedJSONObject oPayload = new ExtendedJSONObject(); ExtendedJSONObject jZkpA = makeJZkp(zkpA.gr, zkpA.b, zkpA.id); - oPayload.put(Constants.ZKP_KEY_A, - BigIntegerHelper.toEvenLengthHex(jParty.thisA)); + oPayload.put(Constants.ZKP_KEY_A, BigIntegerHelper.toEvenLengthHex(jParty.thisA)); oPayload.put(Constants.ZKP_KEY_ZKP_A, jZkpA); // Make outgoing message. @@ -429,7 +422,7 @@ public class JPakeClient implements JPakeRequestDelegate { * Verifies message computed by other party in Step Two. Creates or fetches * encrypted message for verification of successful key exchange. */ - private void computeFinal() { + private void computeFinal() throws NonObjectJSONException { Log.d(LOG_TAG, "Computing final round."); // Check incoming message type. if (!jIncoming.get(Constants.JSON_KEY_TYPE).equals(theirSignerId + "2")) { @@ -439,53 +432,49 @@ public class JPakeClient implements JPakeRequestDelegate { } // Check incoming message fields. - ExtendedJSONObject iPayload = null; - try { - iPayload = jIncoming.getObject(Constants.JSON_KEY_PAYLOAD); - if (iPayload == null - || iPayload.getObject(Constants.ZKP_KEY_ZKP_A) == null - || !theirSignerId.equals(iPayload.getObject(Constants.ZKP_KEY_ZKP_A) - .get(Constants.ZKP_KEY_ID))) { - Log.e(LOG_TAG, "Invalid round 2 message: " + jIncoming.toJSONString()); - abort(Constants.JPAKE_ERROR_WRONGMESSAGE); - return; - } - } catch (NonObjectJSONException e) { - e.printStackTrace(); + ExtendedJSONObject iPayload = jIncoming.getObject(Constants.JSON_KEY_PAYLOAD); + if (iPayload == null || + iPayload.getObject(Constants.ZKP_KEY_ZKP_A) == null) { + Log.e(LOG_TAG, "Invalid round 2 message: " + jIncoming.toJSONString()); + abort(Constants.JPAKE_ERROR_WRONGMESSAGE); + return; + } + ExtendedJSONObject zkpPayload = iPayload.getObject(Constants.ZKP_KEY_ZKP_A); + if (!theirSignerId.equals(zkpPayload.get(Constants.ZKP_KEY_ID))) { + Log.e(LOG_TAG, "Invalid round 2 message: " + jIncoming.toJSONString()); + abort(Constants.JPAKE_ERROR_WRONGMESSAGE); + return; } - // Extract fields. - jParty.otherA = new BigInteger((String) iPayload.get(Constants.ZKP_KEY_A), - 16); - ExtendedJSONObject zkpPayload = null; - try { - zkpPayload = iPayload.getObject(Constants.ZKP_KEY_ZKP_A); - } catch (NonObjectJSONException e) { - e.printStackTrace(); - } + // Extract fields. + jParty.otherA = new BigInteger((String) iPayload.get(Constants.ZKP_KEY_A), 16); + // Extract ZKP. String gr = (String) zkpPayload.get(Constants.ZKP_KEY_GR); - String b = (String) zkpPayload.get(Constants.ZKP_KEY_B); + String b = (String) zkpPayload.get(Constants.ZKP_KEY_B); String id = (String) zkpPayload.get(Constants.ZKP_KEY_ID); - jParty.otherZkpA = new Zkp(new BigInteger(gr, 16), new BigInteger(b, 16), - id); + jParty.otherZkpA = new Zkp(new BigInteger(gr, 16), new BigInteger(b, 16), id); myKeyBundle = null; try { - myKeyBundle = JPakeCrypto.finalRound(secret, jParty); + myKeyBundle = JPakeCrypto.finalRound(JPakeClient.secretAsBigInteger(secret), jParty); } catch (IncorrectZkpException e) { Log.e(LOG_TAG, "ZKP mismatch"); abort(Constants.JPAKE_ERROR_WRONGMESSAGE); - e.printStackTrace(); + return; } catch (NoSuchAlgorithmException e) { Log.e(LOG_TAG, "NoSuchAlgorithmException", e); abort(Constants.JPAKE_ERROR_INTERNAL); - e.printStackTrace(); + return; } catch (InvalidKeyException e) { Log.e(LOG_TAG, "InvalidKeyException", e); abort(Constants.JPAKE_ERROR_INTERNAL); - e.printStackTrace(); + return; + } catch (UnsupportedEncodingException e) { + Log.e(LOG_TAG, "UnsupportedEncodingException", e); + abort(Constants.JPAKE_ERROR_INTERNAL); + return; } if (pairWithPin) { // Wait for other device to send verification of keys. @@ -498,12 +487,10 @@ public class JPakeClient implements JPakeRequestDelegate { } catch (UnsupportedEncodingException e) { Log.e(LOG_TAG, "Failed to encrypt key verification value.", e); abort(Constants.JPAKE_ERROR_INTERNAL); - e.printStackTrace(); return; } catch (CryptoException e) { Log.e(LOG_TAG, "Failed to encrypt key verification value.", e); abort(Constants.JPAKE_ERROR_INTERNAL); - e.printStackTrace(); return; } @@ -523,13 +510,6 @@ public class JPakeClient implements JPakeRequestDelegate { Log.d(LOG_TAG, "Encrypting key verification value."); // KeyBundle not null ExtendedJSONObject jPayload = encryptPayload(JPAKE_VERIFY_VALUE, keyBundle); - Log.d( - LOG_TAG, - "enc key64: " - + new String(Base64.encodeBase64(keyBundle.getEncryptionKey()))); - Log.e(LOG_TAG, - "hmac64: " + new String(Base64.encodeBase64(keyBundle.getHMACKey()))); - ExtendedJSONObject result = new ExtendedJSONObject(); result.put(Constants.JSON_KEY_TYPE, mySignerId + "3"); result.put(Constants.JSON_KEY_VERSION, KEYEXCHANGE_VERSION); @@ -546,8 +526,7 @@ public class JPakeClient implements JPakeRequestDelegate { NonObjectJSONException { if (!verificationObject.get(Constants.JSON_KEY_TYPE).equals( theirSignerId + "3")) { - Log.e(LOG_TAG, - "Invalid round 3 message: " + verificationObject.toJSONString()); + Log.e(LOG_TAG, "Invalid round 3 message: " + verificationObject.toJSONString()); abort(Constants.JPAKE_ERROR_WRONGMESSAGE); return false; } @@ -609,9 +588,11 @@ public class JPakeClient implements JPakeRequestDelegate { } catch (UnsupportedEncodingException e) { Log.e(LOG_TAG, "Failed to encrypt data.", e); abort(Constants.JPAKE_ERROR_INTERNAL); + return; } catch (CryptoException e) { Log.e(LOG_TAG, "Failed to encrypt data.", e); abort(Constants.JPAKE_ERROR_INTERNAL); + return; } jOutgoing = new ExtendedJSONObject(); jOutgoing.put(Constants.JSON_KEY_TYPE, mySignerId + "3"); @@ -636,6 +617,7 @@ public class JPakeClient implements JPakeRequestDelegate { e.printStackTrace(); } abort(Constants.JPAKE_ERROR_WRONGMESSAGE); + return; } // Decrypt payload and verify HMAC. @@ -645,6 +627,7 @@ public class JPakeClient implements JPakeRequestDelegate { } catch (NonObjectJSONException e1) { Log.e(LOG_TAG, "Invalid round 3 data.", e1); abort(Constants.JPAKE_ERROR_WRONGMESSAGE); + return; } Log.d(LOG_TAG, "Decrypting data."); String cleartext = null; @@ -653,9 +636,11 @@ public class JPakeClient implements JPakeRequestDelegate { } catch (UnsupportedEncodingException e1) { Log.e(LOG_TAG, "Failed to decrypt data.", e1); abort(Constants.JPAKE_ERROR_INTERNAL); + return; } catch (CryptoException e1) { Log.e(LOG_TAG, "Failed to decrypt data.", e1); abort(Constants.JPAKE_ERROR_KEYMISMATCH); + return; } JSONObject jCreds = null; try { @@ -679,7 +664,7 @@ public class JPakeClient implements JPakeRequestDelegate { ssActivity.onComplete(jCreds); } - /* JpakeRequestDelegate methods */ + // JPakeRequestDelegate methods. @Override public void onRequestFailure(HttpResponse res) { JPakeResponse response = new JPakeResponse(res); @@ -718,16 +703,14 @@ public class JPakeClient implements JPakeRequestDelegate { onRequestSuccess(res); break; default: - Log.e(LOG_TAG, "Could not retrieve data. Server responded with HTTP " - + statusCode); + Log.e(LOG_TAG, "Could not retrieve data. Server responded with HTTP " + statusCode); abort(Constants.JPAKE_ERROR_SERVER); return; } pollTries = 0; break; case PUT: - Log.e(LOG_TAG, "Could not upload data. Server responded with HTTP " - + response.getStatusCode()); + Log.e(LOG_TAG, "Could not upload data. Server responded with HTTP " + response.getStatusCode()); abort(Constants.JPAKE_ERROR_SERVER); break; case ABORT: @@ -777,7 +760,17 @@ public class JPakeClient implements JPakeRequestDelegate { // Set up next step. this.state = State.RCVR_STEP_ONE; - computeStepOne(); + try { + computeStepOne(); + } catch (NoSuchAlgorithmException e) { + Log.e(LOG_TAG, "NoSuchAlgorithmException", e); + abort(Constants.JPAKE_ERROR_INTERNAL); + return; + } catch (UnsupportedEncodingException e) { + Log.e(LOG_TAG, "UnsupportedEncodingException", e); + abort(Constants.JPAKE_ERROR_INTERNAL); + return; + } break; // Results from GET request. Continue flow depending on case. @@ -794,8 +787,7 @@ public class JPakeClient implements JPakeRequestDelegate { etagHeaders = response.httpResponse().getHeaders("etag"); if (etagHeaders == null) { try { - Log.e(LOG_TAG, - "Server did not supply ETag for message: " + response.body()); + Log.e(LOG_TAG, "Server did not supply ETag for message: " + response.body()); abort(Constants.JPAKE_ERROR_SERVER); } catch (IllegalStateException e) { e.printStackTrace(); @@ -822,16 +814,37 @@ public class JPakeClient implements JPakeRequestDelegate { Log.d(LOG_TAG, "incoming message: " + jIncoming.toJSONString()); if (this.state == State.SNDR_STEP_ZERO) { - computeStepOne(); + try { + computeStepOne(); + } catch (NoSuchAlgorithmException e) { + Log.e(LOG_TAG, "NoSuchAlgorithmException", e); + abort(Constants.JPAKE_ERROR_INTERNAL); + return; + } catch (UnsupportedEncodingException e) { + Log.e(LOG_TAG, "UnsupportedEncodingException", e); + abort(Constants.JPAKE_ERROR_INTERNAL); + return; + } } else if (this.state == State.RCVR_STEP_ONE || this.state == State.SNDR_STEP_ONE) { - computeStepTwo(); + try { + computeStepTwo(); + } catch (NonObjectJSONException e) { + Log.e(LOG_TAG, "NonObjectJSONException", e); + abort(Constants.JPAKE_ERROR_INVALID); + return; + } } else if (this.state == State.SNDR_STEP_TWO) { stateContext = state; state = State.PUT; putStep(); } else if (this.state == State.RCVR_STEP_TWO) { - computeFinal(); + try { + computeFinal(); + } catch (NonObjectJSONException e) { + abort(Constants.JPAKE_ERROR_INVALID); + return; + } } else if (this.state == State.VERIFY_KEY) { decryptData(myKeyBundle); } else if (this.state == State.VERIFY_PAIRING) { @@ -864,11 +877,23 @@ public class JPakeClient implements JPakeRequestDelegate { ssActivity.onPaired(); } if (state == State.SNDR_STEP_ONE) { - computeStepTwo(); + try { + computeStepTwo(); + } catch (NonObjectJSONException e) { + Log.e(LOG_TAG, "NonObjectJSONException", e); + abort(Constants.JPAKE_ERROR_INVALID); + return; + } return; // No need to wait for response from PUT request. } if (state == State.SNDR_STEP_TWO) { - computeFinal(); + try { + computeFinal(); + } catch (NonObjectJSONException e) { + Log.e(LOG_TAG, "NonObjectJSONException", e); + abort(Constants.JPAKE_ERROR_INVALID); + return; + } return; // No need to wait for response from PUT request. } @@ -892,20 +917,20 @@ public class JPakeClient implements JPakeRequestDelegate { /* ResourceDelegate that handles Resource responses */ public ResourceDelegate makeRequestResourceDelegate() { - return new JpakeRequestResourceDelegate(this); + return new JPakeRequestResourceDelegate(this); } - public class JpakeRequestResourceDelegate implements ResourceDelegate { + public class JPakeRequestResourceDelegate implements ResourceDelegate { private JPakeRequestDelegate requestDelegate; - public JpakeRequestResourceDelegate(JPakeRequestDelegate delegate) { + public JPakeRequestResourceDelegate(JPakeRequestDelegate delegate) { this.requestDelegate = delegate; } @Override public String getCredentials() { - // Jpake setup has no credentials + // J-PAKE setup has no credentials return null; } @@ -1063,7 +1088,7 @@ public class JPakeClient implements JPakeRequestDelegate { * Generates and sets a clientId for communications with JPAKE setup server. */ private void setClientId() { - byte[] rBytes = generateRandomBytes(JPAKE_LENGTH_CLIENTID / 2); + byte[] rBytes = Utils.generateRandomBytes(JPAKE_LENGTH_CLIENTID / 2); StringBuilder id = new StringBuilder(); for (byte b : rBytes) { @@ -1085,7 +1110,7 @@ public class JPakeClient implements JPakeRequestDelegate { String key = "23456789abcdefghijkmnpqrstuvwxyz"; int keylen = key.length(); - byte[] rBytes = generateRandomBytes(JPAKE_LENGTH_SECRET); + byte[] rBytes = Utils.generateRandomBytes(JPAKE_LENGTH_SECRET); StringBuilder secret = new StringBuilder(); for (byte b : rBytes) { secret.append(key.charAt(Math.abs(b) * keylen / 256)); @@ -1133,7 +1158,7 @@ public class JPakeClient implements JPakeRequestDelegate { try { getRequest = new JPakeRequest(channelUrl, makeRequestResourceDelegate()); } catch (URISyntaxException e) { - e.printStackTrace(); + Log.e(LOG_TAG, "URISyntaxException", e); abort(Constants.JPAKE_ERROR_CHANNEL); return; } @@ -1156,17 +1181,13 @@ public class JPakeClient implements JPakeRequestDelegate { } /* - * Helper to generate random bytes - * - * @param length Number of bytes to generate + * Helper for turning a string secret into a numeric secret. */ - private static byte[] generateRandomBytes(int length) { - byte[] bytes = new byte[length]; - Random random = new Random(System.nanoTime()); - random.nextBytes(bytes); - return bytes; + public static BigInteger secretAsBigInteger(String secretString) throws UnsupportedEncodingException { + return new BigInteger(secretString.getBytes("UTF-8")); } + /* * Helper function to generate a JSON encoded ZKP. */ diff --git a/mobile/android/base/sync/jpake/JPakeCrypto.java b/mobile/android/base/sync/jpake/JPakeCrypto.java index 5b4215b17a56..d3f5104b71eb 100644 --- a/mobile/android/base/sync/jpake/JPakeCrypto.java +++ b/mobile/android/base/sync/jpake/JPakeCrypto.java @@ -101,8 +101,9 @@ public class JPakeCrypto { * * @param mySignerId * @param valuesOut + * @throws NoSuchAlgorithmException */ - public static void round1(JPakeParty jp, JPakeNumGenerator gen) { + public static void round1(JPakeParty jp, JPakeNumGenerator gen) throws NoSuchAlgorithmException, UnsupportedEncodingException { // Randomly select x1 from [0,q), x2 from [1,q). BigInteger x1 = gen.generateFromRange(Q); // [0, q) BigInteger x2 = jp.x2 = BigInteger.ONE.add(gen.generateFromRange(Q @@ -132,9 +133,11 @@ public class JPakeCrypto { * @param zkp3 * @param zkp4 * @throws IncorrectZkpException + * @throws NoSuchAlgorithmException */ - public static void round2(String secret, JPakeParty jp, - JPakeNumGenerator gen) throws IncorrectZkpException, Gx3OrGx4IsZeroOrOneException { + public static void round2(BigInteger secretValue, JPakeParty jp, JPakeNumGenerator gen) + throws IncorrectZkpException, NoSuchAlgorithmException, + Gx3OrGx4IsZeroOrOneException, UnsupportedEncodingException { Log.d(LOG_TAG, "round2 started."); @@ -150,13 +153,7 @@ public class JPakeCrypto { // Compute a = g^[(x1+x3+x4)*(x2*secret)]. BigInteger y1 = jp.gx3.multiply(jp.gx4).mod(P).multiply(jp.gx1).mod(P); - BigInteger y2 = null; - try { - y2 = jp.x2.multiply(new BigInteger(secret.getBytes("US-ASCII"))).mod(P); - } catch (UnsupportedEncodingException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + BigInteger y2 = jp.x2.multiply(secretValue).mod(P); BigInteger a = y1.modPow(y2, P); jp.thisZkpA = createZkp(y1, y2, a, jp.signerId, gen); @@ -175,8 +172,8 @@ public class JPakeCrypto { * @return KeyBundle * @throws IncorrectZkpException */ - public static KeyBundle finalRound(String secret, JPakeParty jp) - throws IncorrectZkpException, NoSuchAlgorithmException, InvalidKeyException { + public static KeyBundle finalRound(BigInteger secretValue, JPakeParty jp) + throws IncorrectZkpException, NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException { Log.d(LOG_TAG, "Final round started."); BigInteger gb = jp.gx1.multiply(jp.gx2).mod(P).multiply(jp.gx3) .mod(P); @@ -184,7 +181,7 @@ public class JPakeCrypto { // Calculate shared key g^(x1+x3)*x2*x4*secret, which is equivalent to // (B/g^(x2*x4*s))^x2 = (B*(g^x4)^x2^s^-1)^2. - BigInteger k = jp.gx4.modPow(jp.x2.multiply(new BigInteger(secret.getBytes())).negate().mod(Q), P).multiply(jp.otherA) + BigInteger k = jp.gx4.modPow(jp.x2.multiply(secretValue).negate().mod(Q), P).multiply(jp.otherA) .modPow(jp.x2, P); byte[] enc = new byte[32]; @@ -217,7 +214,7 @@ public class JPakeCrypto { * pass in gx to save on an exponentiation of g^x) */ private static Zkp createZkp(BigInteger g, BigInteger x, BigInteger gx, - String id, JPakeNumGenerator gen) { + String id, JPakeNumGenerator gen) throws NoSuchAlgorithmException, UnsupportedEncodingException { // Generate random r for exponent. BigInteger r = gen.generateFromRange(Q); @@ -238,7 +235,7 @@ public class JPakeCrypto { * Verify ZKP. */ private static void checkZkp(BigInteger g, BigInteger gx, Zkp zkp) - throws IncorrectZkpException { + throws IncorrectZkpException, NoSuchAlgorithmException, UnsupportedEncodingException { BigInteger h = computeBHash(g, zkp.gr, gx, zkp.id); @@ -278,33 +275,22 @@ public class JPakeCrypto { * form hash. */ private static BigInteger computeBHash(BigInteger g, BigInteger gr, BigInteger gx, - String id) { - MessageDigest sha = null; - try { - sha = MessageDigest.getInstance("SHA-256"); - sha.reset(); + String id) throws NoSuchAlgorithmException, UnsupportedEncodingException { + MessageDigest sha = MessageDigest.getInstance("SHA-256"); + sha.reset(); - /* - * Note: you should ensure the items in H(...) have clear boundaries. It - * is simple if the other party knows sizes of g, gr, gx and signerID and - * hence the boundary is unambiguous. If not, you'd better prepend each - * item with its byte length, but I've omitted that here. - */ + /* + * Note: you should ensure the items in H(...) have clear boundaries. It + * is simple if the other party knows sizes of g, gr, gx and signerID and + * hence the boundary is unambiguous. If not, you'd better prepend each + * item with its byte length, but I've omitted that here. + */ - hashByteArrayWithLength(sha, - BigIntegerHelper.BigIntegerToByteArrayWithoutSign(g)); - hashByteArrayWithLength(sha, - BigIntegerHelper.BigIntegerToByteArrayWithoutSign(gr)); - hashByteArrayWithLength(sha, - BigIntegerHelper.BigIntegerToByteArrayWithoutSign(gx)); - hashByteArrayWithLength(sha, id.getBytes("US-ASCII")); + hashByteArrayWithLength(sha, BigIntegerHelper.BigIntegerToByteArrayWithoutSign(g)); + hashByteArrayWithLength(sha, BigIntegerHelper.BigIntegerToByteArrayWithoutSign(gr)); + hashByteArrayWithLength(sha, BigIntegerHelper.BigIntegerToByteArrayWithoutSign(gx)); + hashByteArrayWithLength(sha, id.getBytes("UTF-8")); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } catch (UnsupportedEncodingException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } byte[] hash = sha.digest(); return BigIntegerHelper.ByteArrayToBigIntegerWithoutSign(hash); diff --git a/mobile/android/base/sync/jpake/JPakeNumGeneratorRandom.java b/mobile/android/base/sync/jpake/JPakeNumGeneratorRandom.java index 6e47df798b08..c2077f75819c 100644 --- a/mobile/android/base/sync/jpake/JPakeNumGeneratorRandom.java +++ b/mobile/android/base/sync/jpake/JPakeNumGeneratorRandom.java @@ -38,7 +38,8 @@ package org.mozilla.gecko.sync.jpake; import java.math.BigInteger; -import java.security.SecureRandom; + +import org.mozilla.gecko.sync.Utils; /** * Helper Function to generate a uniformly random value in [0, r). @@ -47,14 +48,6 @@ public class JPakeNumGeneratorRandom implements JPakeNumGenerator { @Override public BigInteger generateFromRange(BigInteger r) { - int maxBytes = (int) Math.ceil(((double) r.bitLength()) / 8); - - byte[] bytes = new byte[maxBytes]; - new SecureRandom().nextBytes(bytes); - BigInteger randInt = new BigInteger(bytes); - // TODO: is this going to be very slow? - // bit shifting/masking to decrease mod computation - return randInt.mod(r); + return Utils.generateBigIntegerLessThan(r); } - } diff --git a/mobile/android/base/sync/syncadapter/SyncAdapter.java b/mobile/android/base/sync/syncadapter/SyncAdapter.java index 023039ff4ecc..9b7c393e3ecd 100644 --- a/mobile/android/base/sync/syncadapter/SyncAdapter.java +++ b/mobile/android/base/sync/syncadapter/SyncAdapter.java @@ -222,6 +222,7 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter implements GlobalSe final String authority, final ContentProviderClient provider, final SyncResult syncResult) { + Utils.reseedSharedRandom(); // Make sure we don't work with the same random seed for too long. long delay = delayMilliseconds(); if (delay > 0) { diff --git a/mobile/android/sync/java-sources.mn b/mobile/android/sync/java-sources.mn index 64b4efee8499..a8934571c2d0 100644 --- a/mobile/android/sync/java-sources.mn +++ b/mobile/android/sync/java-sources.mn @@ -1 +1 @@ -sync/AlreadySyncingException.java sync/CollectionKeys.java sync/CredentialsSource.java sync/crypto/CryptoException.java sync/crypto/Cryptographer.java sync/crypto/CryptoInfo.java sync/crypto/HKDF.java sync/crypto/HMACVerificationException.java sync/crypto/KeyBundle.java sync/crypto/MissingCryptoInputException.java sync/crypto/NoKeyBundleException.java sync/cryptographer/CryptoStatusBundle.java sync/cryptographer/SyncCryptographer.java sync/CryptoRecord.java sync/DelayedWorkTracker.java sync/delegates/FreshStartDelegate.java sync/delegates/GlobalSessionCallback.java sync/delegates/InfoCollectionsDelegate.java sync/delegates/KeyUploadDelegate.java sync/delegates/MetaGlobalDelegate.java sync/delegates/WipeServerDelegate.java sync/ExtendedJSONObject.java sync/GlobalSession.java sync/HTTPFailureException.java sync/InfoCollections.java sync/jpake/BigIntegerHelper.java sync/jpake/Gx3OrGx4IsZeroOrOneException.java sync/jpake/IncorrectZkpException.java sync/jpake/JPakeClient.java sync/jpake/JPakeCrypto.java sync/jpake/JPakeNoActivePairingException.java sync/jpake/JPakeNumGenerator.java sync/jpake/JPakeNumGeneratorRandom.java sync/jpake/JPakeParty.java sync/jpake/JPakeRequest.java sync/jpake/JPakeRequestDelegate.java sync/jpake/JPakeResponse.java sync/jpake/JPakeUtils.java sync/jpake/Zkp.java sync/MetaGlobal.java sync/MetaGlobalException.java sync/MetaGlobalMissingEnginesException.java sync/MetaGlobalNotSetException.java sync/middleware/Crypto5MiddlewareRepository.java sync/middleware/Crypto5MiddlewareRepositorySession.java sync/middleware/MiddlewareRepository.java sync/net/BaseResource.java sync/net/CompletedEntity.java sync/net/HandleProgressException.java sync/net/Resource.java sync/net/ResourceDelegate.java sync/net/SyncResourceDelegate.java sync/net/SyncResponse.java sync/net/SyncStorageCollectionRequest.java sync/net/SyncStorageCollectionRequestDelegate.java sync/net/SyncStorageRecordRequest.java sync/net/SyncStorageRequest.java sync/net/SyncStorageRequestDelegate.java sync/net/SyncStorageRequestIncrementalDelegate.java sync/net/SyncStorageResponse.java sync/net/TLSSocketFactory.java sync/net/WBOCollectionRequestDelegate.java sync/NoCollectionKeysSetException.java sync/NonArrayJSONException.java sync/NonObjectJSONException.java sync/PrefsSource.java sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java sync/repositories/android/AndroidBrowserBookmarksRepository.java sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java sync/repositories/android/AndroidBrowserHistoryDataAccessor.java sync/repositories/android/AndroidBrowserHistoryDataExtender.java sync/repositories/android/AndroidBrowserHistoryRepository.java sync/repositories/android/AndroidBrowserHistoryRepositorySession.java sync/repositories/android/AndroidBrowserPasswordsDataAccessor.java sync/repositories/android/AndroidBrowserPasswordsRepository.java sync/repositories/android/AndroidBrowserPasswordsRepositorySession.java sync/repositories/android/AndroidBrowserRepository.java sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java sync/repositories/android/AndroidBrowserRepositorySession.java sync/repositories/android/BrowserContract.java sync/repositories/android/PasswordColumns.java sync/repositories/android/RepoUtils.java sync/repositories/BookmarkNeedsReparentingException.java sync/repositories/BookmarksRepository.java sync/repositories/ConstrainedServer11Repository.java sync/repositories/delegates/DeferrableRepositorySessionCreationDelegate.java sync/repositories/delegates/DeferredRepositorySessionBeginDelegate.java sync/repositories/delegates/DeferredRepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/DeferredRepositorySessionFinishDelegate.java sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionBeginDelegate.java sync/repositories/delegates/RepositorySessionCleanDelegate.java sync/repositories/delegates/RepositorySessionCreationDelegate.java sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/RepositorySessionFinishDelegate.java sync/repositories/delegates/RepositorySessionGuidsSinceDelegate.java sync/repositories/delegates/RepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionWipeDelegate.java sync/repositories/domain/BookmarkRecord.java sync/repositories/domain/BookmarkRecordFactory.java sync/repositories/domain/HistoryRecord.java sync/repositories/domain/HistoryRecordFactory.java sync/repositories/domain/PasswordRecord.java sync/repositories/domain/Record.java sync/repositories/HashSetStoreTracker.java sync/repositories/HistoryRepository.java sync/repositories/IdentityRecordFactory.java sync/repositories/InactiveSessionException.java sync/repositories/InvalidBookmarkTypeException.java sync/repositories/InvalidRequestException.java sync/repositories/InvalidSessionTransitionException.java sync/repositories/MultipleRecordsForGuidException.java sync/repositories/NoGuidForIdException.java sync/repositories/NoStoreDelegateException.java sync/repositories/NullCursorException.java sync/repositories/ParentNotFoundException.java sync/repositories/ProfileDatabaseException.java sync/repositories/RecordFactory.java sync/repositories/RecordFilter.java sync/repositories/Repository.java sync/repositories/RepositorySession.java sync/repositories/RepositorySessionBundle.java sync/repositories/Server11Repository.java sync/repositories/Server11RepositorySession.java sync/repositories/StoreTracker.java sync/repositories/StoreTrackingRepositorySession.java sync/setup/activities/AccountActivity.java sync/setup/activities/SetupFailureActivity.java sync/setup/activities/SetupSuccessActivity.java sync/setup/activities/SetupSyncActivity.java sync/setup/Constants.java sync/setup/SyncAuthenticatorService.java sync/stage/AndroidBrowserBookmarksServerSyncStage.java sync/stage/AndroidBrowserHistoryServerSyncStage.java sync/stage/CheckPreconditionsStage.java sync/stage/CompletedStage.java sync/stage/EnsureClusterURLStage.java sync/stage/EnsureKeysStage.java sync/stage/FetchInfoCollectionsStage.java sync/stage/FetchMetaGlobalStage.java sync/stage/GlobalSyncStage.java sync/stage/NoSuchStageException.java sync/stage/NoSyncIDException.java sync/stage/ServerSyncStage.java sync/StubActivity.java sync/syncadapter/SyncAdapter.java sync/syncadapter/SyncService.java sync/SyncConfiguration.java sync/SyncConfigurationException.java sync/SyncException.java sync/synchronizer/ConcurrentRecordConsumer.java sync/synchronizer/RecordConsumer.java sync/synchronizer/RecordsChannel.java sync/synchronizer/RecordsChannelDelegate.java sync/synchronizer/RecordsConsumerDelegate.java sync/synchronizer/SerialRecordConsumer.java sync/synchronizer/SessionNotBegunException.java sync/synchronizer/Synchronizer.java sync/synchronizer/SynchronizerDelegate.java sync/synchronizer/SynchronizerSession.java sync/synchronizer/SynchronizerSessionDelegate.java sync/synchronizer/UnbundleError.java sync/synchronizer/UnexpectedSessionException.java sync/SynchronizerConfiguration.java sync/SynchronizerConfigurations.java sync/ThreadPool.java sync/UnexpectedJSONException.java sync/UnknownSynchronizerConfigurationVersionException.java sync/Utils.java +sync/AlreadySyncingException.java sync/CollectionKeys.java sync/CredentialsSource.java sync/crypto/CryptoException.java sync/crypto/Cryptographer.java sync/crypto/CryptoInfo.java sync/crypto/HKDF.java sync/crypto/HMACVerificationException.java sync/crypto/KeyBundle.java sync/crypto/MissingCryptoInputException.java sync/crypto/NoKeyBundleException.java sync/cryptographer/CryptoStatusBundle.java sync/cryptographer/SyncCryptographer.java sync/CryptoRecord.java sync/DelayedWorkTracker.java sync/delegates/FreshStartDelegate.java sync/delegates/GlobalSessionCallback.java sync/delegates/InfoCollectionsDelegate.java sync/delegates/KeyUploadDelegate.java sync/delegates/MetaGlobalDelegate.java sync/delegates/WipeServerDelegate.java sync/ExtendedJSONObject.java sync/GlobalSession.java sync/HTTPFailureException.java sync/InfoCollections.java sync/jpake/BigIntegerHelper.java sync/jpake/Gx3OrGx4IsZeroOrOneException.java sync/jpake/IncorrectZkpException.java sync/jpake/JPakeClient.java sync/jpake/JPakeCrypto.java sync/jpake/JPakeNoActivePairingException.java sync/jpake/JPakeNumGenerator.java sync/jpake/JPakeNumGeneratorRandom.java sync/jpake/JPakeParty.java sync/jpake/JPakeRequest.java sync/jpake/JPakeRequestDelegate.java sync/jpake/JPakeResponse.java sync/jpake/Zkp.java sync/MetaGlobal.java sync/MetaGlobalException.java sync/MetaGlobalMissingEnginesException.java sync/MetaGlobalNotSetException.java sync/middleware/Crypto5MiddlewareRepository.java sync/middleware/Crypto5MiddlewareRepositorySession.java sync/middleware/MiddlewareRepository.java sync/net/BaseResource.java sync/net/CompletedEntity.java sync/net/HandleProgressException.java sync/net/Resource.java sync/net/ResourceDelegate.java sync/net/SyncResourceDelegate.java sync/net/SyncResponse.java sync/net/SyncStorageCollectionRequest.java sync/net/SyncStorageCollectionRequestDelegate.java sync/net/SyncStorageRecordRequest.java sync/net/SyncStorageRequest.java sync/net/SyncStorageRequestDelegate.java sync/net/SyncStorageRequestIncrementalDelegate.java sync/net/SyncStorageResponse.java sync/net/TLSSocketFactory.java sync/net/WBOCollectionRequestDelegate.java sync/NoCollectionKeysSetException.java sync/NonArrayJSONException.java sync/NonObjectJSONException.java sync/PrefsSource.java sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java sync/repositories/android/AndroidBrowserBookmarksRepository.java sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java sync/repositories/android/AndroidBrowserHistoryDataAccessor.java sync/repositories/android/AndroidBrowserHistoryDataExtender.java sync/repositories/android/AndroidBrowserHistoryRepository.java sync/repositories/android/AndroidBrowserHistoryRepositorySession.java sync/repositories/android/AndroidBrowserPasswordsDataAccessor.java sync/repositories/android/AndroidBrowserPasswordsRepository.java sync/repositories/android/AndroidBrowserPasswordsRepositorySession.java sync/repositories/android/AndroidBrowserRepository.java sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java sync/repositories/android/AndroidBrowserRepositorySession.java sync/repositories/android/BrowserContract.java sync/repositories/android/PasswordColumns.java sync/repositories/android/RepoUtils.java sync/repositories/BookmarkNeedsReparentingException.java sync/repositories/BookmarksRepository.java sync/repositories/ConstrainedServer11Repository.java sync/repositories/delegates/DeferrableRepositorySessionCreationDelegate.java sync/repositories/delegates/DeferredRepositorySessionBeginDelegate.java sync/repositories/delegates/DeferredRepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/DeferredRepositorySessionFinishDelegate.java sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionBeginDelegate.java sync/repositories/delegates/RepositorySessionCleanDelegate.java sync/repositories/delegates/RepositorySessionCreationDelegate.java sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/RepositorySessionFinishDelegate.java sync/repositories/delegates/RepositorySessionGuidsSinceDelegate.java sync/repositories/delegates/RepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionWipeDelegate.java sync/repositories/domain/BookmarkRecord.java sync/repositories/domain/BookmarkRecordFactory.java sync/repositories/domain/HistoryRecord.java sync/repositories/domain/HistoryRecordFactory.java sync/repositories/domain/PasswordRecord.java sync/repositories/domain/Record.java sync/repositories/HashSetStoreTracker.java sync/repositories/HistoryRepository.java sync/repositories/IdentityRecordFactory.java sync/repositories/InactiveSessionException.java sync/repositories/InvalidBookmarkTypeException.java sync/repositories/InvalidRequestException.java sync/repositories/InvalidSessionTransitionException.java sync/repositories/MultipleRecordsForGuidException.java sync/repositories/NoGuidForIdException.java sync/repositories/NoStoreDelegateException.java sync/repositories/NullCursorException.java sync/repositories/ParentNotFoundException.java sync/repositories/ProfileDatabaseException.java sync/repositories/RecordFactory.java sync/repositories/RecordFilter.java sync/repositories/Repository.java sync/repositories/RepositorySession.java sync/repositories/RepositorySessionBundle.java sync/repositories/Server11Repository.java sync/repositories/Server11RepositorySession.java sync/repositories/StoreTracker.java sync/repositories/StoreTrackingRepositorySession.java sync/setup/activities/AccountActivity.java sync/setup/activities/SetupFailureActivity.java sync/setup/activities/SetupSuccessActivity.java sync/setup/activities/SetupSyncActivity.java sync/setup/Constants.java sync/setup/SyncAuthenticatorService.java sync/stage/AndroidBrowserBookmarksServerSyncStage.java sync/stage/AndroidBrowserHistoryServerSyncStage.java sync/stage/CheckPreconditionsStage.java sync/stage/CompletedStage.java sync/stage/EnsureClusterURLStage.java sync/stage/EnsureKeysStage.java sync/stage/FetchInfoCollectionsStage.java sync/stage/FetchMetaGlobalStage.java sync/stage/GlobalSyncStage.java sync/stage/NoSuchStageException.java sync/stage/NoSyncIDException.java sync/stage/ServerSyncStage.java sync/StubActivity.java sync/syncadapter/SyncAdapter.java sync/syncadapter/SyncService.java sync/SyncConfiguration.java sync/SyncConfigurationException.java sync/SyncException.java sync/synchronizer/ConcurrentRecordConsumer.java sync/synchronizer/RecordConsumer.java sync/synchronizer/RecordsChannel.java sync/synchronizer/RecordsChannelDelegate.java sync/synchronizer/RecordsConsumerDelegate.java sync/synchronizer/SerialRecordConsumer.java sync/synchronizer/SessionNotBegunException.java sync/synchronizer/Synchronizer.java sync/synchronizer/SynchronizerDelegate.java sync/synchronizer/SynchronizerSession.java sync/synchronizer/SynchronizerSessionDelegate.java sync/synchronizer/UnbundleError.java sync/synchronizer/UnexpectedSessionException.java sync/SynchronizerConfiguration.java sync/SynchronizerConfigurations.java sync/ThreadPool.java sync/UnexpectedJSONException.java sync/UnknownSynchronizerConfigurationVersionException.java sync/Utils.java From d5e355632da7ad6ace5b804770dd0a98e896bfa7 Mon Sep 17 00:00:00 2001 From: Marina Samuel Date: Wed, 15 Feb 2012 22:05:52 -0800 Subject: [PATCH 07/93] Bug 722520. r=rnewman --- .../android/AndroidBrowserHistoryDataExtender.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/mobile/android/base/sync/repositories/android/AndroidBrowserHistoryDataExtender.java b/mobile/android/base/sync/repositories/android/AndroidBrowserHistoryDataExtender.java index 9c6d9df86d94..82359a3ef968 100644 --- a/mobile/android/base/sync/repositories/android/AndroidBrowserHistoryDataExtender.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserHistoryDataExtender.java @@ -145,12 +145,15 @@ public class AndroidBrowserHistoryDataExtender extends SQLiteOpenHelper { } public Cursor fetch(String guid) throws NullCursorException { + String where = COL_GUID + " = ?"; + String[] args = new String[] { guid }; + SQLiteDatabase db = this.getCachedReadableDatabase(); long queryStart = System.currentTimeMillis(); Cursor cur = db.query(TBL_HISTORY_EXT, new String[] { COL_GUID, COL_VISITS }, - COL_GUID + " = '" + guid + "'", - null, null, null, null); + where, args, + null, null, null); RepoUtils.queryTimeLogger("AndroidBrowserHistoryDataExtender.fetch(guid)", queryStart, System.currentTimeMillis()); if (cur == null) { Log.e(TAG, "Got a null cursor while doing fetch for guid " + guid + " on history extension table"); @@ -160,7 +163,10 @@ public class AndroidBrowserHistoryDataExtender extends SQLiteOpenHelper { } public void delete(String guid) { + String where = COL_GUID + " = ?"; + String[] args = new String[] { guid }; + SQLiteDatabase db = this.getCachedWritableDatabase(); - db.delete(TBL_HISTORY_EXT, COL_GUID + " = '" + guid + "'", null); + db.delete(TBL_HISTORY_EXT, where, args); } } From 4de51660dba9fbf932a965c29d7d5b9b02301ffe Mon Sep 17 00:00:00 2001 From: Nick Alexander Date: Wed, 15 Feb 2012 22:05:52 -0800 Subject: [PATCH 08/93] Bug 722561 - remove isSecure override; default from SSLSocketFactory. r=rnewman --- mobile/android/base/sync/net/TLSSocketFactory.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/mobile/android/base/sync/net/TLSSocketFactory.java b/mobile/android/base/sync/net/TLSSocketFactory.java index 30339cbf715f..5ddfdbfbcb39 100644 --- a/mobile/android/base/sync/net/TLSSocketFactory.java +++ b/mobile/android/base/sync/net/TLSSocketFactory.java @@ -98,9 +98,4 @@ public class TLSSocketFactory extends SSLSocketFactory { setEnabledCipherSuites(socket); return socket; } - - @Override - public boolean isSecure(Socket sock) throws IllegalArgumentException { - return true; - } } \ No newline at end of file From 5b01ccf58b5f085f466ad12b058aa16df3a3f027 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Wed, 15 Feb 2012 22:05:52 -0800 Subject: [PATCH 09/93] Bug 725525 - Part 1: simplify and remove excess logging in Sync. --- .../android/base/sync/DelayedWorkTracker.java | 12 +- mobile/android/base/sync/Logger.java | 83 +++++++++++ .../base/sync/SynchronizerConfiguration.java | 2 +- mobile/android/base/sync/Utils.java | 141 ++++++------------ .../android/base/sync/jpake/JPakeClient.java | 57 +++---- .../sync/repositories/RepositorySession.java | 6 +- .../Server11RepositorySession.java | 2 +- .../StoreTrackingRepositorySession.java | 4 +- .../AndroidBrowserBookmarksDataAccessor.java | 2 +- ...roidBrowserBookmarksRepositorySession.java | 76 ++++++---- .../AndroidBrowserRepositoryDataAccessor.java | 2 +- .../AndroidBrowserRepositorySession.java | 69 +++++---- .../sync/repositories/android/RepoUtils.java | 56 ++++--- .../repositories/domain/BookmarkRecord.java | 3 +- .../repositories/domain/HistoryRecord.java | 10 +- .../sync/setup/SyncAuthenticatorService.java | 2 +- .../sync/stage/FetchInfoCollectionsStage.java | 2 +- .../ConcurrentRecordConsumer.java | 12 +- .../sync/synchronizer/RecordsChannel.java | 44 ++---- .../base/sync/synchronizer/Synchronizer.java | 2 +- mobile/android/sync/java-sources.mn | 2 +- 21 files changed, 316 insertions(+), 273 deletions(-) create mode 100644 mobile/android/base/sync/Logger.java diff --git a/mobile/android/base/sync/DelayedWorkTracker.java b/mobile/android/base/sync/DelayedWorkTracker.java index ec45b91c9e16..aef33f8a1aa8 100644 --- a/mobile/android/base/sync/DelayedWorkTracker.java +++ b/mobile/android/base/sync/DelayedWorkTracker.java @@ -37,8 +37,6 @@ package org.mozilla.gecko.sync; -import android.util.Log; - /** * A little class to allow us to maintain a count of extant * things (in our case, callbacks that need to fire), and @@ -53,13 +51,13 @@ public class DelayedWorkTracker { protected int outstandingCount = 0; public int incrementOutstanding() { - Log.d(LOG_TAG, "Incrementing outstanding."); + Logger.trace(LOG_TAG, "Incrementing outstanding."); synchronized(this) { return ++outstandingCount; } } public int decrementOutstanding() { - Log.d(LOG_TAG, "Decrementing outstanding."); + Logger.trace(LOG_TAG, "Decrementing outstanding."); Runnable job = null; int count; synchronized(this) { @@ -81,10 +79,10 @@ public class DelayedWorkTracker { } } public void delayWorkItem(Runnable item) { - Log.d(LOG_TAG, "delayWorkItem."); + Logger.trace(LOG_TAG, "delayWorkItem."); boolean runnableNow = false; synchronized(this) { - Log.d(LOG_TAG, "outstandingCount: " + outstandingCount); + Logger.trace(LOG_TAG, "outstandingCount: " + outstandingCount); if (outstandingCount == 0) { runnableNow = true; } else { @@ -95,7 +93,7 @@ public class DelayedWorkTracker { } } if (runnableNow) { - Log.d(LOG_TAG, "Running item now."); + Logger.trace(LOG_TAG, "Running item now."); item.run(); } } diff --git a/mobile/android/base/sync/Logger.java b/mobile/android/base/sync/Logger.java new file mode 100644 index 000000000000..ca3ee09e84e6 --- /dev/null +++ b/mobile/android/base/sync/Logger.java @@ -0,0 +1,83 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.sync; + +import android.util.Log; + +public class Logger { + + // For extra debugging. + public static boolean LOG_PERSONAL_INFORMATION = false; + + // If true, log to System.out as well as using Android's Log.* calls. + public static boolean LOG_TO_STDOUT = false; + + public static void logToStdout(String... s) { + if (LOG_TO_STDOUT) { + for (String string : s) { + System.out.print(string); + } + System.out.println(""); + } + } + + public static void error(String logTag, String message) { + Logger.error(logTag, message, null); + } + + public static void error(String logTag, String message, Throwable error) { + logToStdout(logTag, " :: ERROR: ", message); + if (!Log.isLoggable(logTag, Log.ERROR)) { + return; + } + Log.e(logTag, message, error); + } + + public static void warn(String logTag, String message) { + Logger.warn(logTag, message, null); + } + + public static void warn(String logTag, String message, Throwable error) { + logToStdout(logTag, " :: WARN: ", message); + if (!Log.isLoggable(logTag, Log.WARN)) { + return; + } + Log.w(logTag, message, error); + } + + public static void info(String logTag, String message) { + logToStdout(logTag, " :: INFO: ", message); + if (!Log.isLoggable(logTag, Log.INFO)) { + return; + } + Log.i(logTag, message); + } + + public static void debug(String logTag, String message) { + Logger.debug(logTag, message, null); + } + + public static void debug(String logTag, String message, Throwable error) { + logToStdout(logTag, " :: DEBUG: ", message); + if (!Log.isLoggable(logTag, Log.DEBUG)) { + return; + } + Log.d(logTag, message, error); + } + + public static void trace(String logTag, String message) { + logToStdout(logTag, " :: TRACE: ", message); + if (!Log.isLoggable(logTag, Log.VERBOSE)) { + return; + } + Log.v(logTag, message); + } + + public static void pii(String logTag, String message) { + if (LOG_PERSONAL_INFORMATION) { + Logger.debug(logTag, "$$PII$$: " + message); + } + } +} diff --git a/mobile/android/base/sync/SynchronizerConfiguration.java b/mobile/android/base/sync/SynchronizerConfiguration.java index fcc06d89d351..7ba744aa16e6 100644 --- a/mobile/android/base/sync/SynchronizerConfiguration.java +++ b/mobile/android/base/sync/SynchronizerConfiguration.java @@ -47,7 +47,7 @@ import android.content.SharedPreferences.Editor; import android.util.Log; public class SynchronizerConfiguration { - private static final String LOG_TAG = "SynchronizerConfiguration"; + private static final String LOG_TAG = "SynczrConfiguration"; public String syncID; public RepositorySessionBundle remoteBundle; diff --git a/mobile/android/base/sync/Utils.java b/mobile/android/base/sync/Utils.java index 002e46a6fe39..445c6e5c05b7 100644 --- a/mobile/android/base/sync/Utils.java +++ b/mobile/android/base/sync/Utils.java @@ -42,8 +42,8 @@ import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.math.BigInteger; import java.security.NoSuchAlgorithmException; -import java.util.HashMap; import java.security.SecureRandom; +import java.util.HashMap; import org.mozilla.apache.commons.codec.binary.Base32; import org.mozilla.apache.commons.codec.binary.Base64; @@ -51,7 +51,6 @@ import org.mozilla.gecko.sync.crypto.Cryptographer; import android.content.Context; import android.content.SharedPreferences; -import android.util.Log; public class Utils { @@ -62,46 +61,6 @@ public class Utils { // See public static final int SHARED_PREFERENCES_MODE = 0; - - // We don't really have a trace logger, so use this to toggle - // some debug logging. - // This is awful. I'm so sorry. - public static boolean ENABLE_TRACE_LOGGING = true; - - // If true, log to System.out as well as using Android's Log.* calls. - public static boolean LOG_TO_STDOUT = false; - public static void logToStdout(String... s) { - if (LOG_TO_STDOUT) { - for (String string : s) { - System.out.print(string); - } - System.out.println(""); - } - } - - public static void error(String logTag, String message) { - logToStdout(logTag, " :: ERROR: ", message); - Log.i(logTag, message); - } - - public static void info(String logTag, String message) { - logToStdout(logTag, " :: INFO: ", message); - Log.i(logTag, message); - } - - public static void debug(String logTag, String message) { - logToStdout(logTag, " :: DEBUG: ", message); - Log.d(logTag, message); - } - - public static void trace(String logTag, String message) { - if (!ENABLE_TRACE_LOGGING) { - return; - } - logToStdout(logTag, " :: TRACE: ", message); - Log.d(logTag, message); - } - public static String generateGuid() { byte[] encodedBytes = Base64.encodeBase64(generateRandomBytes(9), false); return new String(encodedBytes).replace("+", "-").replace("/", "_"); @@ -142,26 +101,25 @@ public class Utils { * Output: Hex string */ public static String byte2hex(byte[] b) { - - // String Buffer can be used instead - String hs = ""; - String stmp = ""; - - for (int n = 0; n < b.length; n++) { - stmp = (java.lang.Integer.toHexString(b[n] & 0XFF)); - - if (stmp.length() == 1) { - hs = hs + "0" + stmp; - } else { - hs = hs + stmp; - } - - if (n < b.length - 1) { - hs = hs + ""; - } + // StringBuffer should be used instead. + String hs = ""; + String stmp; + + for (int n = 0; n < b.length; n++) { + stmp = java.lang.Integer.toHexString(b[n] & 0XFF); + + if (stmp.length() == 1) { + hs = hs + "0" + stmp; + } else { + hs = hs + stmp; } - - return hs; + + if (n < b.length - 1) { + hs = hs + ""; + } + } + + return hs; } /* @@ -170,21 +128,21 @@ public class Utils { * Output: A concatenated version of them */ public static byte[] concatAll(byte[] first, byte[]... rest) { - int totalLength = first.length; - for (byte[] array : rest) { - totalLength += array.length; - } - - byte[] result = new byte[totalLength]; - int offset = first.length; + int totalLength = first.length; + for (byte[] array : rest) { + totalLength += array.length; + } - System.arraycopy(first, 0, result, 0, offset); - - for (byte[] array : rest) { - System.arraycopy(array, 0, result, offset, array.length); - offset += array.length; - } - return result; + byte[] result = new byte[totalLength]; + int offset = first.length; + + System.arraycopy(first, 0, result, 0, offset); + + for (byte[] array : rest) { + System.arraycopy(array, 0, result, offset, array.length); + offset += array.length; + } + return result; } /** @@ -199,16 +157,16 @@ public class Utils { * Should not occur. */ public static byte[] decodeBase64(String base64) throws UnsupportedEncodingException { - return Base64.decodeBase64(base64.getBytes("UTF-8")); + return Base64.decodeBase64(base64.getBytes("UTF-8")); } /* * Decode a friendly base32 string. */ public static byte[] decodeFriendlyBase32(String base32) { - Base32 converter = new Base32(); - return converter.decode(base32.replace('8', 'l').replace('9', 'o') - .toUpperCase()); + Base32 converter = new Base32(); + final String translated = base32.replace('8', 'l').replace('9', 'o'); + return converter.decode(translated.toUpperCase()); } /* @@ -216,19 +174,16 @@ public class Utils { * Input: Hex string * Output: byte[] version of hex string */ - public static byte[] hex2Byte(String str) - { - if (str.length() % 2 == 1) { - str = "0" + str; - } - - byte[] bytes = new byte[str.length() / 2]; - for (int i = 0; i < bytes.length; i++) - { - bytes[i] = (byte) Integer - .parseInt(str.substring(2 * i, 2 * i + 2), 16); - } - return bytes; + public static byte[] hex2Byte(String str) { + if (str.length() % 2 == 1) { + str = "0" + str; + } + + byte[] bytes = new byte[str.length() / 2]; + for (int i = 0; i < bytes.length; i++) { + bytes[i] = (byte) Integer.parseInt(str.substring(2 * i, 2 * i + 2), 16); + } + return bytes; } public static String millisecondsToDecimalSecondsString(long ms) { @@ -264,7 +219,7 @@ public class Utils { public static SharedPreferences getSharedPreferences(Context context, String username, String serverURL) throws NoSuchAlgorithmException, UnsupportedEncodingException { String prefsPath = getPrefsPath(username, serverURL); - Log.d(LOG_TAG, "Shared preferences: " + prefsPath); + Logger.debug(LOG_TAG, "Shared preferences: " + prefsPath); return context.getSharedPreferences(prefsPath, SHARED_PREFERENCES_MODE); } diff --git a/mobile/android/base/sync/jpake/JPakeClient.java b/mobile/android/base/sync/jpake/JPakeClient.java index fdfa1e96567b..9659c16846ca 100644 --- a/mobile/android/base/sync/jpake/JPakeClient.java +++ b/mobile/android/base/sync/jpake/JPakeClient.java @@ -53,6 +53,7 @@ import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import org.mozilla.apache.commons.codec.binary.Base64; import org.mozilla.gecko.sync.ExtendedJSONObject; +import org.mozilla.gecko.sync.Logger; import org.mozilla.gecko.sync.NonObjectJSONException; import org.mozilla.gecko.sync.ThreadPool; import org.mozilla.gecko.sync.Utils; @@ -236,20 +237,26 @@ public class JPakeClient implements JPakeRequestDelegate { * (Receiver Only) Request channel for J-PAKE from server. */ private void getChannel() { - Log.d(LOG_TAG, "Getting channel."); - if (finished) + Logger.debug(LOG_TAG, "Getting channel."); + if (finished) { + Logger.debug(LOG_TAG, "Finished; returning."); return; + } - JPakeRequest channelRequest = null; try { - channelRequest = new JPakeRequest(jpakeServer + "new_channel", - makeRequestResourceDelegate()); + final String uri = jpakeServer + "new_channel"; + Logger.debug(LOG_TAG, "Fetching " + uri); + JPakeRequest channelRequest = new JPakeRequest(uri, makeRequestResourceDelegate()); + channelRequest.get(); } catch (URISyntaxException e) { Log.e(LOG_TAG, "URISyntaxException", e); abort(Constants.JPAKE_ERROR_CHANNEL); return; + } catch (Exception e) { + Log.e(LOG_TAG, "Unexpected exception in getChannel().", e); + abort(Constants.JPAKE_ERROR_CHANNEL); + return; } - channelRequest.get(); } /* @@ -257,7 +264,7 @@ public class JPakeClient implements JPakeRequestDelegate { * jOutgoing JSONObject. */ private void putStep() { - Log.d(LOG_TAG, "Uploading message."); + Logger.debug(LOG_TAG, "Uploading message."); runOnThread(new Runnable() { @Override public void run() { @@ -275,7 +282,7 @@ public class JPakeClient implements JPakeRequestDelegate { } catch (UnsupportedEncodingException e) { e.printStackTrace(); } - Log.d(LOG_TAG, "outgoing: " + jOutgoing.toJSONString()); + Logger.debug(LOG_TAG, "outgoing: " + jOutgoing.toJSONString()); } }); } @@ -284,7 +291,7 @@ public class JPakeClient implements JPakeRequestDelegate { * Step One of J-PAKE protocol. */ private void computeStepOne() throws NoSuchAlgorithmException, UnsupportedEncodingException { - Log.d(LOG_TAG, "Computing round 1."); + Logger.debug(LOG_TAG, "Computing round 1."); JPakeCrypto.round1(jParty, numGen); @@ -307,7 +314,7 @@ public class JPakeClient implements JPakeRequestDelegate { jOutgoing.put(Constants.JSON_KEY_TYPE, mySignerId + "1"); jOutgoing.put(Constants.JSON_KEY_PAYLOAD, jOne); jOutgoing.put(Constants.JSON_KEY_VERSION, KEYEXCHANGE_VERSION); - Log.d(LOG_TAG, "Sending: " + jOutgoing.toJSONString()); + Logger.debug(LOG_TAG, "Sending: " + jOutgoing.toJSONString()); // Store context to determine next step after PUT request. stateContext = pairWithPin ? State.SNDR_STEP_ONE : State.RCVR_STEP_ONE; @@ -322,7 +329,7 @@ public class JPakeClient implements JPakeRequestDelegate { * Two message to be sent. */ private void computeStepTwo() throws NonObjectJSONException { - Log.d(LOG_TAG, "Computing round 2."); + Logger.debug(LOG_TAG, "Computing round 2."); // Check incoming message sender. if (!jIncoming.get(Constants.JSON_KEY_TYPE).equals(theirSignerId + "1")) { @@ -423,7 +430,7 @@ public class JPakeClient implements JPakeRequestDelegate { * encrypted message for verification of successful key exchange. */ private void computeFinal() throws NonObjectJSONException { - Log.d(LOG_TAG, "Computing final round."); + Logger.debug(LOG_TAG, "Computing final round."); // Check incoming message type. if (!jIncoming.get(Constants.JSON_KEY_TYPE).equals(theirSignerId + "2")) { Log.e(LOG_TAG, "Invalid round 2 message: " + jIncoming.toJSONString()); @@ -478,7 +485,7 @@ public class JPakeClient implements JPakeRequestDelegate { } if (pairWithPin) { // Wait for other device to send verification of keys. - Log.d(LOG_TAG, "get: verifyPairing"); + Logger.debug(LOG_TAG, "get: verifyPairing"); this.state = State.VERIFY_PAIRING; scheduleGetRequest(jpakePollInterval); } else { // Prepare and send verification of keys. @@ -507,7 +514,7 @@ public class JPakeClient implements JPakeRequestDelegate { public ExtendedJSONObject computeKeyVerification(KeyBundle keyBundle) throws UnsupportedEncodingException, CryptoException { - Log.d(LOG_TAG, "Encrypting key verification value."); + Logger.debug(LOG_TAG, "Encrypting key verification value."); // KeyBundle not null ExtendedJSONObject jPayload = encryptPayload(JPAKE_VERIFY_VALUE, keyBundle); ExtendedJSONObject result = new ExtendedJSONObject(); @@ -581,7 +588,7 @@ public class JPakeClient implements JPakeRequestDelegate { * @param payload Credentials data to be encrypted. */ private void encryptData(KeyBundle keyBundle, String payload) { - Log.d(LOG_TAG, "Encrypting data."); + Logger.debug(LOG_TAG, "Encrypting data."); ExtendedJSONObject jPayload = null; try { jPayload = encryptPayload(payload, keyBundle); @@ -608,7 +615,7 @@ public class JPakeClient implements JPakeRequestDelegate { * @param keyBundle */ private void decryptData(KeyBundle keyBundle) { - Log.d(LOG_TAG, "Verifying their key"); + Logger.debug(LOG_TAG, "Verifying their key"); if (!(theirSignerId + "3").equals((String) jIncoming .get(Constants.JSON_KEY_TYPE))) { try { @@ -629,7 +636,7 @@ public class JPakeClient implements JPakeRequestDelegate { abort(Constants.JPAKE_ERROR_WRONGMESSAGE); return; } - Log.d(LOG_TAG, "Decrypting data."); + Logger.debug(LOG_TAG, "Decrypting data."); String cleartext = null; try { cleartext = new String(decryptPayload(iPayload, keyBundle), "UTF-8"); @@ -659,7 +666,7 @@ public class JPakeClient implements JPakeRequestDelegate { * @param jCreds Credentials to be stored by controller. May be null if device is sender. */ private void complete(JSONObject jCreds) { - Log.d(LOG_TAG, "Exchange complete."); + Logger.debug(LOG_TAG, "Exchange complete."); finished = true; ssActivity.onComplete(jCreds); } @@ -683,7 +690,7 @@ public class JPakeClient implements JPakeRequestDelegate { int statusCode = response.getStatusCode(); switch (statusCode) { case 304: - Log.d(LOG_TAG, "Channel hasn't been updated yet. Will try again later"); + Logger.debug(LOG_TAG, "Channel hasn't been updated yet. Will try again later"); if (pollTries >= jpakeMaxTries) { Log.e(LOG_TAG, "Tried for " + pollTries + " times, maxTries " + jpakeMaxTries + ", aborting"); abort(Constants.JPAKE_ERROR_TIMEOUT); @@ -699,7 +706,7 @@ public class JPakeClient implements JPakeRequestDelegate { abort(Constants.JPAKE_ERROR_NODATA); break; case 412: // "Precondition failed" - Log.d(LOG_TAG, "Message already replaced on server by other party."); + Logger.debug(LOG_TAG, "Message already replaced on server by other party."); onRequestSuccess(res); break; default: @@ -754,7 +761,7 @@ public class JPakeClient implements JPakeRequestDelegate { return; } channelUrl = jpakeServer + channel; - Log.d(LOG_TAG, "using channel " + channel); + Logger.debug(LOG_TAG, "using channel " + channel); ssActivity.displayPin(secret + channel); @@ -811,7 +818,7 @@ public class JPakeClient implements JPakeRequestDelegate { abort(Constants.JPAKE_ERROR_INVALID); return; } - Log.d(LOG_TAG, "incoming message: " + jIncoming.toJSONString()); + Logger.debug(LOG_TAG, "incoming message: " + jIncoming.toJSONString()); if (this.state == State.SNDR_STEP_ZERO) { try { @@ -1040,13 +1047,13 @@ public class JPakeClient implements JPakeRequestDelegate { * Defaults to user abort */ public void abort(String error) { - Log.d(LOG_TAG, "aborting..."); + Logger.debug(LOG_TAG, "aborting..."); finished = true; if (error == null) { error = Constants.JPAKE_ERROR_USERABORT; } - Log.d(LOG_TAG, error); + Logger.debug(LOG_TAG, error); if (Constants.JPAKE_ERROR_CHANNEL.equals(error) || Constants.JPAKE_ERROR_NETWORK.equals(error) @@ -1062,7 +1069,7 @@ public class JPakeClient implements JPakeRequestDelegate { * Make a /report post to to server */ private void reportFailure(String error) { - Log.d(LOG_TAG, "reporting error to server"); + Logger.debug(LOG_TAG, "reporting error to server"); this.error = error; runOnThread(new Runnable() { @Override diff --git a/mobile/android/base/sync/repositories/RepositorySession.java b/mobile/android/base/sync/repositories/RepositorySession.java index d2626c084dba..88f1b969e5a1 100644 --- a/mobile/android/base/sync/repositories/RepositorySession.java +++ b/mobile/android/base/sync/repositories/RepositorySession.java @@ -41,7 +41,7 @@ package org.mozilla.gecko.sync.repositories; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import org.mozilla.gecko.sync.Utils; +import org.mozilla.gecko.sync.Logger; import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionBeginDelegate; import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionFetchRecordsDelegate; import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionFinishDelegate; @@ -77,11 +77,11 @@ public abstract class RepositorySession { private static final String LOG_TAG = "RepositorySession"; private static void error(String message) { - Utils.error(LOG_TAG, message); + Logger.error(LOG_TAG, message); } protected static void trace(String message) { - Utils.trace(LOG_TAG, message); + Logger.trace(LOG_TAG, message); } protected SessionStatus status = SessionStatus.UNSTARTED; diff --git a/mobile/android/base/sync/repositories/Server11RepositorySession.java b/mobile/android/base/sync/repositories/Server11RepositorySession.java index e92a354bb477..644ff37cb666 100644 --- a/mobile/android/base/sync/repositories/Server11RepositorySession.java +++ b/mobile/android/base/sync/repositories/Server11RepositorySession.java @@ -82,7 +82,7 @@ public class Server11RepositorySession extends RepositorySession { } } - public static final String LOG_TAG = "Server11RepositorySession"; + public static final String LOG_TAG = "Server11Session"; private static final int UPLOAD_BYTE_THRESHOLD = 1024 * 1024; // 1MB. private static final int UPLOAD_ITEM_THRESHOLD = 50; diff --git a/mobile/android/base/sync/repositories/StoreTrackingRepositorySession.java b/mobile/android/base/sync/repositories/StoreTrackingRepositorySession.java index 9574652062d4..cded12065afa 100644 --- a/mobile/android/base/sync/repositories/StoreTrackingRepositorySession.java +++ b/mobile/android/base/sync/repositories/StoreTrackingRepositorySession.java @@ -11,7 +11,7 @@ import org.mozilla.gecko.sync.repositories.domain.Record; import android.util.Log; public abstract class StoreTrackingRepositorySession extends RepositorySession { - private static final String LOG_TAG = "StoreTrackingRepositorySession"; + private static final String LOG_TAG = "StoreTrackSession"; protected StoreTracker storeTracker; protected static StoreTracker createStoreTracker() { @@ -59,4 +59,4 @@ public abstract class StoreTrackingRepositorySession extends RepositorySession { this.storeTracker = null; super.finish(delegate); } -} \ No newline at end of file +} diff --git a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java index d788617be4e6..652861a29799 100644 --- a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java @@ -53,7 +53,7 @@ import android.util.Log; public class AndroidBrowserBookmarksDataAccessor extends AndroidBrowserRepositoryDataAccessor { - private static final String LOG_TAG = "AndroidBrowserBookmarksDataAccessor"; + private static final String LOG_TAG = "BookmarksDataAccessor"; /* * Fragments of SQL to make our lives easier. diff --git a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java index 1e0d525c4d05..1750c2dcf00f 100644 --- a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java @@ -41,6 +41,7 @@ import java.util.ArrayList; import java.util.HashMap; import org.json.simple.JSONArray; +import org.mozilla.gecko.sync.Logger; import org.mozilla.gecko.sync.Utils; import org.mozilla.gecko.sync.repositories.BookmarkNeedsReparentingException; import org.mozilla.gecko.sync.repositories.NoGuidForIdException; @@ -122,7 +123,7 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo parentName = RepoUtils.getStringFromCursor(name, BrowserContract.Bookmarks.TITLE); } else { - Log.e(LOG_TAG, "Couldn't find record with guid '" + parentGUID + "' when looking for parent name."); + Logger.error(LOG_TAG, "Couldn't find record with guid '" + parentGUID + "' when looking for parent name."); throw new ParentNotFoundException(null); } } finally { @@ -157,13 +158,13 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo int childPosition = (int) RepoUtils.getLongFromCursor(children, BrowserContract.Bookmarks.POSITION); trace(" Child position: " + childPosition); if (childPosition >= count) { - Log.w(LOG_TAG, "Child position " + childPosition + " greater than expected children " + count); + Logger.warn(LOG_TAG, "Child position " + childPosition + " greater than expected children " + count); broken.put(childGuid, 0L); } else { String existing = kids[childPosition]; if (existing != null) { - Log.w(LOG_TAG, "Child position " + childPosition + " already occupied! (" + - childGuid + ", " + existing + ")"); + Logger.warn(LOG_TAG, "Child position " + childPosition + " already occupied! (" + + childGuid + ", " + existing + ")"); broken.put(childGuid, 0L); } else { kids[childPosition] = childGuid; @@ -175,7 +176,7 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo try { Utils.fillArraySpaces(kids, broken); } catch (Exception e) { - Log.e(LOG_TAG, "Unable to reposition children to yield a valid sequence. Data loss may result.", e); + Logger.error(LOG_TAG, "Unable to reposition children to yield a valid sequence. Data loss may result.", e); } // TODO: now use 'broken' to edit the records on disk. @@ -187,8 +188,9 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo } childArray.add(kid); } - if (Utils.ENABLE_TRACE_LOGGING) { - Log.d(LOG_TAG, "Output child array: " + childArray.toJSONString()); + if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) { + // Don't JSON-encode unless we're logging. + Logger.trace(LOG_TAG, "Output child array: " + childArray.toJSONString()); } } finally { children.close(); @@ -199,10 +201,10 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo @Override protected Record recordFromMirrorCursor(Cursor cur) throws NoGuidForIdException, NullCursorException, ParentNotFoundException { String recordGUID = getGUID(cur); - Log.d(LOG_TAG, "Record from mirror cursor: " + recordGUID); + Logger.trace(LOG_TAG, "Record from mirror cursor: " + recordGUID); if (forbiddenGUID(recordGUID)) { - Log.d(LOG_TAG, "Ignoring " + recordGUID + " record in recordFromMirrorCursor."); + Logger.debug(LOG_TAG, "Ignoring " + recordGUID + " record in recordFromMirrorCursor."); return null; } @@ -210,10 +212,10 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo String androidParentGUID = getGUIDForID(androidParentID); if (androidParentGUID == null) { - Log.d(LOG_TAG, "No parent GUID for record " + recordGUID + " with parent " + androidParentID); + Logger.debug(LOG_TAG, "No parent GUID for record " + recordGUID + " with parent " + androidParentID); // If the parent has been stored and somehow has a null GUID, throw an error. if (idToGuid.containsKey(androidParentID)) { - Log.e(LOG_TAG, "Have the parent android ID for the record but the parent's GUID wasn't found."); + Logger.error(LOG_TAG, "Have the parent android ID for the record but the parent's GUID wasn't found."); throw new NoGuidForIdException(null); } } @@ -227,13 +229,13 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo protected JSONArray getChildArrayForCursor(Cursor cur, String recordGUID) throws NullCursorException { JSONArray childArray = null; boolean isFolder = rowIsFolder(cur); - Log.d(LOG_TAG, "Record " + recordGUID + " is a " + (isFolder ? "folder." : "bookmark.")); + Logger.debug(LOG_TAG, "Record " + recordGUID + " is a " + (isFolder ? "folder." : "bookmark.")); if (isFolder) { long androidID = guidToID.get(recordGUID); childArray = getChildren(androidID); } if (childArray != null) { - Log.d(LOG_TAG, "Fetched " + childArray.size() + " children for " + recordGUID); + Logger.debug(LOG_TAG, "Fetched " + childArray.size() + " children for " + recordGUID); } return childArray; } @@ -245,7 +247,7 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo bmk.type.equalsIgnoreCase(AndroidBrowserBookmarksDataAccessor.TYPE_FOLDER)) { return true; } - Log.i(LOG_TAG, "Ignoring record with guid: " + record.guid + " and type: " + ((BookmarkRecord)record).type); + Logger.info(LOG_TAG, "Ignoring record with guid: " + record.guid + " and type: " + ((BookmarkRecord)record).type); return false; } @@ -255,12 +257,12 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo // and insert them if they don't exist. Cursor cur; try { - Log.d(LOG_TAG, "Check and build special GUIDs."); + Logger.debug(LOG_TAG, "Check and build special GUIDs."); dataAccessor.checkAndBuildSpecialGuids(); cur = dataAccessor.getGuidsIDsForFolders(); - Log.d(LOG_TAG, "Got GUIDs for folders."); + Logger.debug(LOG_TAG, "Got GUIDs for folders."); } catch (android.database.sqlite.SQLiteConstraintException e) { - Log.e(LOG_TAG, "Got sqlite constraint exception working with Fennec bookmark DB.", e); + Logger.error(LOG_TAG, "Got sqlite constraint exception working with Fennec bookmark DB.", e); delegate.onBeginFailed(e); return; } catch (NullCursorException e) { @@ -274,7 +276,7 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo // To deal with parent mapping of bookmarks we have to do some // hairy stuff. Here's the setup for it. - Log.d(LOG_TAG, "Preparing folder ID mappings."); + Logger.debug(LOG_TAG, "Preparing folder ID mappings."); idToGuid.put(0L, "places"); // Fake our root. try { cur.moveToFirst(); @@ -283,13 +285,13 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo long id = RepoUtils.getLongFromCursor(cur, BrowserContract.Bookmarks._ID); guidToID.put(guid, id); idToGuid.put(id, guid); - Log.d(LOG_TAG, "GUID " + guid + " maps to " + id); + Logger.debug(LOG_TAG, "GUID " + guid + " maps to " + id); cur.moveToNext(); } } finally { cur.close(); } - Log.d(LOG_TAG, "Done with initial setup of bookmarks session."); + Logger.debug(LOG_TAG, "Done with initial setup of bookmarks session."); super.begin(delegate); } @@ -298,8 +300,8 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo // Override finish to do this check; make sure all records // needing re-parenting have been re-parented. if (needsReparenting != 0) { - Log.e(LOG_TAG, "Finish called but " + needsReparenting + - " bookmark(s) have been placed in unsorted bookmarks and not been reparented."); + Logger.error(LOG_TAG, "Finish called but " + needsReparenting + + " bookmark(s) have been placed in unsorted bookmarks and not been reparented."); // TODO: handling of failed reparenting. // E.g., delegate.onFinishFailed(new BookmarkNeedsReparentingException(null)); @@ -337,16 +339,28 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo missingParentToChildren.put(bmk.parentID, children); } - if (bmk.isFolder()) { - Log.d(LOG_TAG, "Inserting folder " + bmk.guid + ", " + bmk.title + - " with parent " + bmk.androidParentID + - " (" + bmk.parentID + ", " + bmk.parentName + - ", " + bmk.pos + ")"); + if (Logger.LOG_PERSONAL_INFORMATION) { + if (bmk.isFolder()) { + Logger.pii(LOG_TAG, "Inserting folder " + bmk.guid + ", " + bmk.title + + " with parent " + bmk.androidParentID + + " (" + bmk.parentID + ", " + bmk.parentName + + ", " + bmk.pos + ")"); + } else { + Logger.pii(LOG_TAG, "Inserting bookmark " + bmk.guid + ", " + bmk.title + ", " + + bmk.bookmarkURI + " with parent " + bmk.androidParentID + + " (" + bmk.parentID + ", " + bmk.parentName + + ", " + bmk.pos + ")"); + } } else { - Log.d(LOG_TAG, "Inserting bookmark " + bmk.guid + ", " + bmk.title + ", " + - bmk.bookmarkURI + " with parent " + bmk.androidParentID + - " (" + bmk.parentID + ", " + bmk.parentName + - ", " + bmk.pos + ")"); + if (bmk.isFolder()) { + Logger.debug(LOG_TAG, "Inserting folder " + bmk.guid + ", parent " + + bmk.androidParentID + + " (" + bmk.parentID + ", " + bmk.pos + ")"); + } else { + Logger.debug(LOG_TAG, "Inserting bookmark " + bmk.guid + " with parent " + + bmk.androidParentID + + " (" + bmk.parentID + ", " + ", " + bmk.pos + ")"); + } } return bmk; } diff --git a/mobile/android/base/sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java b/mobile/android/base/sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java index 25f85fa99b2a..2459f91e9a61 100644 --- a/mobile/android/base/sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java @@ -51,7 +51,7 @@ public abstract class AndroidBrowserRepositoryDataAccessor { private static final String[] GUID_COLUMNS = new String[] { BrowserContract.SyncColumns.GUID }; protected Context context; - protected String LOG_TAG = "AndroidBrowserRepositoryDataAccessor"; + protected static String LOG_TAG = "BrowserDataAccessor"; private final RepoUtils.QueryHelper queryHelper; public AndroidBrowserRepositoryDataAccessor(Context context) { diff --git a/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java b/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java index 3ac08dfcb8a5..928c255b8f7c 100644 --- a/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java @@ -41,7 +41,7 @@ package org.mozilla.gecko.sync.repositories.android; import java.util.ArrayList; import java.util.HashMap; -import org.mozilla.gecko.sync.Utils; +import org.mozilla.gecko.sync.Logger; import org.mozilla.gecko.sync.repositories.InactiveSessionException; import org.mozilla.gecko.sync.repositories.InvalidRequestException; import org.mozilla.gecko.sync.repositories.InvalidSessionTransitionException; @@ -62,7 +62,6 @@ import org.mozilla.gecko.sync.repositories.domain.Record; import android.database.Cursor; import android.net.Uri; -import android.util.Log; /** * You'll notice that all delegate calls *either*: @@ -89,7 +88,7 @@ import android.util.Log; public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepositorySession { protected AndroidBrowserRepositoryDataAccessor dbHelper; - public static final String LOG_TAG = "AndroidBrowserRepositorySession"; + public static final String LOG_TAG = "BrowserRepoSession"; private HashMap recordToGuid; public AndroidBrowserRepositorySession(Repository repository) { @@ -142,7 +141,7 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos // is no way of knowing which call would be hit first. checkDatabase(); } catch (ProfileDatabaseException e) { - Log.e(LOG_TAG, "ProfileDatabaseException from begin. Fennec must be launched once until this error is fixed"); + Logger.error(LOG_TAG, "ProfileDatabaseException from begin. Fennec must be launched once until this error is fixed"); deferredDelegate.onBeginFailed(e); return; } catch (NullCursorException e) { @@ -159,10 +158,10 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos protected abstract String buildRecordString(Record record); protected void checkDatabase() throws ProfileDatabaseException, NullCursorException { - Utils.info(LOG_TAG, "BEGIN: checking database."); + Logger.info(LOG_TAG, "BEGIN: checking database."); try { dbHelper.fetch(new String[] { "none" }).close(); - Utils.info(LOG_TAG, "END: checking database."); + Logger.info(LOG_TAG, "END: checking database."); } catch (NullPointerException e) { throw new ProfileDatabaseException(e); } @@ -215,7 +214,7 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos cur.moveToNext(); } } finally { - Log.d(LOG_TAG, "Closing cursor after guidsSince."); + Logger.debug(LOG_TAG, "Closing cursor after guidsSince."); cur.close(); } @@ -240,7 +239,7 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos } protected void fetchFromCursor(Cursor cursor, RecordFilter filter, long end) { - Log.d(LOG_TAG, "Fetch from cursor:"); + Logger.debug(LOG_TAG, "Fetch from cursor:"); try { try { if (!cursor.moveToFirst()) { @@ -248,28 +247,28 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos return; } while (!cursor.isAfterLast()) { - Log.d(LOG_TAG, "... one more record."); Record r = recordFromMirrorCursor(cursor); if (r != null) { if (filter == null || !filter.excludeRecord(r)) { + Logger.trace(LOG_TAG, "Processing record " + r.guid); delegate.onFetchedRecord(transformRecord(r)); } else { - Log.d(LOG_TAG, "Filter says to skip record."); + Logger.debug(LOG_TAG, "Skipping filtered record " + r.guid); } } cursor.moveToNext(); } delegate.onFetchCompleted(end); } catch (NoGuidForIdException e) { - Log.w(LOG_TAG, "No GUID for ID.", e); + Logger.warn(LOG_TAG, "No GUID for ID.", e); delegate.onFetchFailed(e, null); } catch (Exception e) { - Log.w(LOG_TAG, "Exception in fetchFromCursor.", e); + Logger.warn(LOG_TAG, "Exception in fetchFromCursor.", e); delegate.onFetchFailed(e, null); return; } } finally { - Log.d(LOG_TAG, "Closing cursor after fetch."); + Logger.trace(LOG_TAG, "Closing cursor after fetch."); cursor.close(); } } @@ -298,7 +297,7 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos } if (guids == null || guids.length < 1) { - Log.e(LOG_TAG, "No guids sent to fetch"); + Logger.error(LOG_TAG, "No guids sent to fetch"); delegate.onFetchFailed(new InvalidRequestException(null), null); return; } @@ -319,7 +318,7 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos throw new IllegalStateException("Store tracker not yet initialized!"); } - Log.i(LOG_TAG, "Running fetchSince(" + timestamp + ")."); + Logger.info(LOG_TAG, "Running fetchSince(" + timestamp + ")."); FetchSinceRunnable command = new FetchSinceRunnable(timestamp, now(), this.storeTracker.getFilter(), delegate); delegateQueue.execute(command); } @@ -367,7 +366,7 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos throw new NoStoreDelegateException(); } if (record == null) { - Log.e(LOG_TAG, "Record sent to store was null"); + Logger.error(LOG_TAG, "Record sent to store was null"); throw new IllegalArgumentException("Null record passed to AndroidBrowserRepositorySession.store()."); } @@ -388,7 +387,7 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos // See Bug 708149. This might be resolved by Fennec changing its database // schema, or by Sync storing non-applied records in its own private database. if (!checkRecordType(record)) { - Log.d(LOG_TAG, "Ignoring record " + record.guid + " due to unknown record type."); + Logger.debug(LOG_TAG, "Ignoring record " + record.guid + " due to unknown record type."); // Don't throw: we don't want to abort the entire sync when we get a livemark! // delegate.onRecordStoreFailed(new InvalidBookmarkTypeException(null)); @@ -445,7 +444,7 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos trace("Remote is older, local is not deleted. Ignoring."); if (!locallyModified) { - Log.w(LOG_TAG, "Inconsistency: old remote record is deleted, but local record not modified!"); + Logger.warn(LOG_TAG, "Inconsistency: old remote record is deleted, but local record not modified!"); // Ensure that this is tracked for upload. } return; @@ -475,35 +474,35 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos Record toStore = reconcileRecords(record, existingRecord, lastRemoteRetrieval, lastLocalRetrieval); if (toStore == null) { - Log.d(LOG_TAG, "Reconciling returned null. Not inserting a record."); + Logger.debug(LOG_TAG, "Reconciling returned null. Not inserting a record."); return; } // TODO: pass in timestamps? - Log.d(LOG_TAG, "Replacing " + existingRecord.guid + " with record " + toStore.guid); + Logger.debug(LOG_TAG, "Replacing " + existingRecord.guid + " with record " + toStore.guid); Record replaced = replace(toStore, existingRecord); // Note that we don't track records here; deciding that is the job // of reconcileRecords. - Log.d(LOG_TAG, "Calling delegate callback with guid " + replaced.guid + - "(" + replaced.androidID + ")"); + Logger.debug(LOG_TAG, "Calling delegate callback with guid " + replaced.guid + + "(" + replaced.androidID + ")"); delegate.onRecordStoreSucceeded(replaced); return; } catch (MultipleRecordsForGuidException e) { - Log.e(LOG_TAG, "Multiple records returned for given guid: " + record.guid); + Logger.error(LOG_TAG, "Multiple records returned for given guid: " + record.guid); delegate.onRecordStoreFailed(e); return; } catch (NoGuidForIdException e) { - Log.e(LOG_TAG, "Store failed for " + record.guid, e); + Logger.error(LOG_TAG, "Store failed for " + record.guid, e); delegate.onRecordStoreFailed(e); return; } catch (NullCursorException e) { - Log.e(LOG_TAG, "Store failed for " + record.guid, e); + Logger.error(LOG_TAG, "Store failed for " + record.guid, e); delegate.onRecordStoreFailed(e); return; } catch (Exception e) { - Log.e(LOG_TAG, "Store failed for " + record.guid, e); + Logger.error(LOG_TAG, "Store failed for " + record.guid, e); delegate.onRecordStoreFailed(e); return; } @@ -523,11 +522,11 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos Record toStore = prepareRecord(record); Uri recordURI = dbHelper.insert(toStore); long id = RepoUtils.getAndroidIdFromUri(recordURI); - Log.d(LOG_TAG, "Inserted as " + id); + Logger.debug(LOG_TAG, "Inserted as " + id); toStore.androidID = id; updateBookkeeping(toStore); - Log.d(LOG_TAG, "insert() returning record " + toStore.guid); + Logger.debug(LOG_TAG, "insert() returning record " + toStore.guid); return toStore; } @@ -537,7 +536,7 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos // newRecord should already have suitable androidID and guid. dbHelper.update(existingRecord.guid, toStore); updateBookkeeping(toStore); - Log.d(LOG_TAG, "replace() returning record " + toStore.guid); + Logger.debug(LOG_TAG, "replace() returning record " + toStore.guid); return toStore; } @@ -583,15 +582,15 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos protected Record findExistingRecord(Record record) throws MultipleRecordsForGuidException, NoGuidForIdException, NullCursorException, ParentNotFoundException { - Log.d(LOG_TAG, "Finding existing record for incoming record with GUID " + record.guid); + Logger.debug(LOG_TAG, "Finding existing record for incoming record with GUID " + record.guid); String recordString = buildRecordString(record); - Log.d(LOG_TAG, "Searching with record string " + recordString); + Logger.debug(LOG_TAG, "Searching with record string " + recordString); String guid = getRecordToGuidMap().get(recordString); if (guid != null) { - Log.d(LOG_TAG, "Found one. Returning computed record."); + Logger.debug(LOG_TAG, "Found one. Returning computed record."); return recordForGUID(guid); } - Log.d(LOG_TAG, "findExistingRecord failed to find one for " + record.guid); + Logger.debug(LOG_TAG, "findExistingRecord failed to find one for " + record.guid); return null; } @@ -603,7 +602,7 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos } private void createRecordToGuidMap() throws NoGuidForIdException, NullCursorException, ParentNotFoundException { - Utils.info(LOG_TAG, "BEGIN: creating record -> GUID map."); + Logger.info(LOG_TAG, "BEGIN: creating record -> GUID map."); recordToGuid = new HashMap(); Cursor cur = dbHelper.fetchAll(); try { @@ -620,7 +619,7 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos } finally { cur.close(); } - Utils.info(LOG_TAG, "END: creating record -> GUID map."); + Logger.info(LOG_TAG, "END: creating record -> GUID map."); } public void putRecordToGuidMap(String recordString, String guid) throws NoGuidForIdException, NullCursorException, ParentNotFoundException { diff --git a/mobile/android/base/sync/repositories/android/RepoUtils.java b/mobile/android/base/sync/repositories/android/RepoUtils.java index ce96c801db2f..4bb6f7440d14 100644 --- a/mobile/android/base/sync/repositories/android/RepoUtils.java +++ b/mobile/android/base/sync/repositories/android/RepoUtils.java @@ -46,6 +46,7 @@ import org.json.simple.JSONArray; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import org.mozilla.gecko.R; +import org.mozilla.gecko.sync.Logger; import org.mozilla.gecko.sync.repositories.NullCursorException; import org.mozilla.gecko.sync.repositories.domain.BookmarkRecord; import org.mozilla.gecko.sync.repositories.domain.HistoryRecord; @@ -54,7 +55,6 @@ import org.mozilla.gecko.sync.repositories.domain.PasswordRecord; import android.content.Context; import android.database.Cursor; import android.net.Uri; -import android.util.Log; public class RepoUtils { @@ -177,7 +177,7 @@ public class RepoUtils { public Cursor safeQuery(String label, String[] projection, String selection, String[] selectionArgs, String sortOrder) throws NullCursorException { Cursor c = this.query(label, projection, selection, selectionArgs, sortOrder); if (c == null) { - Log.e(tag, "Got null cursor exception in " + tag + ((label == null) ? "" : label)); + Logger.error(tag, "Got null cursor exception in " + tag + ((label == null) ? "" : label)); throw new NullCursorException(null); } return c; @@ -206,7 +206,7 @@ public class RepoUtils { try { return (JSONArray) new JSONParser().parse(getStringFromCursor(cur, colId)); } catch (ParseException e) { - Log.e(LOG_TAG, "JSON parsing error for " + colId, e); + Logger.error(LOG_TAG, "JSON parsing error for " + colId, e); return null; } } @@ -223,7 +223,7 @@ public class RepoUtils { final String guid = rec.guid; if (guid == null) { // Oh dear. - Log.e(LOG_TAG, "No guid in computeParentFields!"); + Logger.error(LOG_TAG, "No guid in computeParentFields!"); return null; } @@ -232,13 +232,13 @@ public class RepoUtils { // No magic parent. Use whatever the caller suggests. realParent = suggestedParentID; } else { - Log.d(LOG_TAG, "Ignoring suggested parent ID " + suggestedParentID + - " for " + guid + "; using " + realParent); + Logger.debug(LOG_TAG, "Ignoring suggested parent ID " + suggestedParentID + + " for " + guid + "; using " + realParent); } if (realParent == null) { // Oh dear. - Log.e(LOG_TAG, "No parent for record " + guid); + Logger.error(LOG_TAG, "No parent for record " + guid); return null; } @@ -283,18 +283,24 @@ public class RepoUtils { private static BookmarkRecord logBookmark(BookmarkRecord rec) { try { - Log.d(LOG_TAG, "Returning bookmark record " + rec.guid + " (" + rec.androidID + - ", " + rec.parentName + ":" + rec.parentID + ")"); - Log.d(LOG_TAG, "> Title: " + rec.title); - Log.d(LOG_TAG, "> Type: " + rec.type); - Log.d(LOG_TAG, "> URI: " + rec.bookmarkURI); - Log.d(LOG_TAG, "> Android position: " + rec.androidPosition); - Log.d(LOG_TAG, "> Position: " + rec.pos); - if (rec.isFolder()) { - Log.d(LOG_TAG, "FOLDER: Children are " + (rec.children == null ? "null" : rec.children.toJSONString())); + Logger.debug(LOG_TAG, "Returning bookmark record " + rec.guid + " (" + rec.androidID + + ", parent " + rec.parentID + ")"); + if (Logger.LOG_PERSONAL_INFORMATION) { + Logger.pii(LOG_TAG, "> Parent name: " + rec.parentName); + Logger.pii(LOG_TAG, "> Title: " + rec.title); + Logger.pii(LOG_TAG, "> Type: " + rec.type); + Logger.pii(LOG_TAG, "> URI: " + rec.bookmarkURI); + Logger.pii(LOG_TAG, "> Android position: " + rec.androidPosition); + Logger.pii(LOG_TAG, "> Position: " + rec.pos); + if (rec.isFolder()) { + Logger.pii(LOG_TAG, "FOLDER: Children are " + + (rec.children == null ? + "null" : + rec.children.toJSONString())); + } } } catch (Exception e) { - Log.d(LOG_TAG, "Exception logging bookmark record " + rec, e); + Logger.debug(LOG_TAG, "Exception logging bookmark record " + rec, e); } return rec; } @@ -319,13 +325,15 @@ public class RepoUtils { private static HistoryRecord logHistory(HistoryRecord rec) { try { - Log.d(LOG_TAG, "Returning history record " + rec.guid + " (" + rec.androidID + ")"); - Log.d(LOG_TAG, "> Title: " + rec.title); - Log.d(LOG_TAG, "> URI: " + rec.histURI); - Log.d(LOG_TAG, "> Visited: " + rec.fennecDateVisited); - Log.d(LOG_TAG, "> Visits: " + rec.fennecVisitCount); + Logger.debug(LOG_TAG, "Returning history record " + rec.guid + " (" + rec.androidID + ")"); + Logger.debug(LOG_TAG, "> Visited: " + rec.fennecDateVisited); + Logger.debug(LOG_TAG, "> Visits: " + rec.fennecVisitCount); + if (Logger.LOG_PERSONAL_INFORMATION) { + Logger.pii(LOG_TAG, "> Title: " + rec.title); + Logger.pii(LOG_TAG, "> URI: " + rec.histURI); + } } catch (Exception e) { - Log.d(LOG_TAG, "Exception logging bookmark record " + rec, e); + Logger.debug(LOG_TAG, "Exception logging bookmark record " + rec, e); } return rec; } @@ -356,7 +364,7 @@ public class RepoUtils { public static void queryTimeLogger(String methodCallingQuery, long queryStart, long queryEnd) { long elapsedTime = queryEnd - queryStart; - Log.i(LOG_TAG, "Query timer: " + methodCallingQuery + " took " + elapsedTime + "ms."); + Logger.debug(LOG_TAG, "Query timer: " + methodCallingQuery + " took " + elapsedTime + "ms."); } public static boolean stringsEqual(String a, String b) { diff --git a/mobile/android/base/sync/repositories/domain/BookmarkRecord.java b/mobile/android/base/sync/repositories/domain/BookmarkRecord.java index 00d3fa4233c6..3b2409994ab3 100644 --- a/mobile/android/base/sync/repositories/domain/BookmarkRecord.java +++ b/mobile/android/base/sync/repositories/domain/BookmarkRecord.java @@ -41,6 +41,7 @@ package org.mozilla.gecko.sync.repositories.domain; import org.json.simple.JSONArray; import org.mozilla.gecko.sync.CryptoRecord; import org.mozilla.gecko.sync.ExtendedJSONObject; +import org.mozilla.gecko.sync.Logger; import org.mozilla.gecko.sync.NonArrayJSONException; import org.mozilla.gecko.sync.Utils; import org.mozilla.gecko.sync.repositories.android.RepoUtils; @@ -224,7 +225,7 @@ public class BookmarkRecord extends Record { } private void trace(String s) { - Utils.trace(LOG_TAG, s); + Logger.trace(LOG_TAG, s); } @Override diff --git a/mobile/android/base/sync/repositories/domain/HistoryRecord.java b/mobile/android/base/sync/repositories/domain/HistoryRecord.java index 4cd32fcc86bb..e7e1bb6f2ae2 100644 --- a/mobile/android/base/sync/repositories/domain/HistoryRecord.java +++ b/mobile/android/base/sync/repositories/domain/HistoryRecord.java @@ -43,6 +43,7 @@ import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.mozilla.gecko.sync.CryptoRecord; import org.mozilla.gecko.sync.ExtendedJSONObject; +import org.mozilla.gecko.sync.Logger; import org.mozilla.gecko.sync.NonArrayJSONException; import org.mozilla.gecko.sync.Utils; import org.mozilla.gecko.sync.repositories.android.RepoUtils; @@ -191,10 +192,11 @@ public class HistoryRecord extends Record { } private boolean checkVisitsEquals(HistoryRecord other) { - Log.d(LOG_TAG, "Checking visits."); - if (Utils.ENABLE_TRACE_LOGGING) { - Log.d(LOG_TAG, ">> Mine: " + ((this.visits == null) ? "null" : this.visits.toJSONString())); - Log.d(LOG_TAG, ">> Theirs: " + ((other.visits == null) ? "null" : other.visits.toJSONString())); + Logger.debug(LOG_TAG, "Checking visits."); + if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) { + // Don't JSON-encode unless we're logging. + Logger.trace(LOG_TAG, ">> Mine: " + ((this.visits == null) ? "null" : this.visits.toJSONString())); + Logger.trace(LOG_TAG, ">> Theirs: " + ((other.visits == null) ? "null" : other.visits.toJSONString())); } // Handle nulls. diff --git a/mobile/android/base/sync/setup/SyncAuthenticatorService.java b/mobile/android/base/sync/setup/SyncAuthenticatorService.java index 635c27050034..4055634d4c44 100644 --- a/mobile/android/base/sync/setup/SyncAuthenticatorService.java +++ b/mobile/android/base/sync/setup/SyncAuthenticatorService.java @@ -57,7 +57,7 @@ import android.os.IBinder; import android.util.Log; public class SyncAuthenticatorService extends Service { - private static final String LOG_TAG = "SyncAuthenticatorService"; + private static final String LOG_TAG = "SyncAuthService"; private SyncAccountAuthenticator sAccountAuthenticator = null; @Override diff --git a/mobile/android/base/sync/stage/FetchInfoCollectionsStage.java b/mobile/android/base/sync/stage/FetchInfoCollectionsStage.java index e6688c10cdd6..97e786384249 100644 --- a/mobile/android/base/sync/stage/FetchInfoCollectionsStage.java +++ b/mobile/android/base/sync/stage/FetchInfoCollectionsStage.java @@ -47,7 +47,7 @@ import org.mozilla.gecko.sync.net.SyncStorageResponse; import android.util.Log; public class FetchInfoCollectionsStage implements GlobalSyncStage { - private static final String LOG_TAG = "FetchInfoCollectionsStage"; + private static final String LOG_TAG = "FetchInfoCollStage"; public class StageInfoCollectionsDelegate implements InfoCollectionsDelegate { diff --git a/mobile/android/base/sync/synchronizer/ConcurrentRecordConsumer.java b/mobile/android/base/sync/synchronizer/ConcurrentRecordConsumer.java index 0bc02316f94c..00399348c1c0 100644 --- a/mobile/android/base/sync/synchronizer/ConcurrentRecordConsumer.java +++ b/mobile/android/base/sync/synchronizer/ConcurrentRecordConsumer.java @@ -37,7 +37,7 @@ package org.mozilla.gecko.sync.synchronizer; -import org.mozilla.gecko.sync.Utils; +import org.mozilla.gecko.sync.Logger; import org.mozilla.gecko.sync.repositories.domain.Record; import android.util.Log; @@ -51,7 +51,7 @@ import android.util.Log; * */ class ConcurrentRecordConsumer extends RecordConsumer { - private static final String LOG_TAG = "ConcurrentRecordConsumer"; + private static final String LOG_TAG = "CRecordConsumer"; /** * When this is true and all records have been processed, the consumer @@ -65,15 +65,15 @@ class ConcurrentRecordConsumer extends RecordConsumer { } private static void info(String message) { - Utils.info(LOG_TAG, message); + Logger.info(LOG_TAG, message); } private static void debug(String message) { - Utils.debug(LOG_TAG, message); + Logger.debug(LOG_TAG, message); } private static void trace(String message) { - Utils.trace(LOG_TAG, message); + Logger.trace(LOG_TAG, message); } private Object monitor = new Object(); @@ -104,7 +104,7 @@ class ConcurrentRecordConsumer extends RecordConsumer { private Object countMonitor = new Object(); @Override public void stored() { - debug("Record stored. Notifying."); + trace("Record stored. Notifying."); synchronized (countMonitor) { counter++; } diff --git a/mobile/android/base/sync/synchronizer/RecordsChannel.java b/mobile/android/base/sync/synchronizer/RecordsChannel.java index d93bda2dd9ce..d86bbf773d0b 100644 --- a/mobile/android/base/sync/synchronizer/RecordsChannel.java +++ b/mobile/android/base/sync/synchronizer/RecordsChannel.java @@ -40,8 +40,8 @@ package org.mozilla.gecko.sync.synchronizer; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutorService; +import org.mozilla.gecko.sync.Logger; import org.mozilla.gecko.sync.ThreadPool; -import org.mozilla.gecko.sync.Utils; import org.mozilla.gecko.sync.repositories.NoStoreDelegateException; import org.mozilla.gecko.sync.repositories.RepositorySession; import org.mozilla.gecko.sync.repositories.delegates.DeferredRepositorySessionBeginDelegate; @@ -135,30 +135,6 @@ class RecordsChannel implements return source.isActive() && sink.isActive(); } - - private static void info(String message) { - Utils.logToStdout(LOG_TAG, "::INFO: ", message); - Log.i(LOG_TAG, message); - } - - private static void trace(String message) { - if (!Utils.ENABLE_TRACE_LOGGING) { - return; - } - Utils.logToStdout(LOG_TAG, "::TRACE: ", message); - Log.d(LOG_TAG, message); - } - - private static void error(String message, Exception e) { - Utils.logToStdout(LOG_TAG, "::ERROR: ", message); - Log.e(LOG_TAG, message, e); - } - - private static void warn(String message, Exception e) { - Utils.logToStdout(LOG_TAG, "::WARN: ", message); - Log.w(LOG_TAG, message, e); - } - /** * Attempt to abort an outstanding fetch. Finish both sessions. */ @@ -194,7 +170,7 @@ class RecordsChannel implements * Begin both sessions, invoking flow() when done. */ public void beginAndFlow() { - info("Beginning source."); + Logger.info(LOG_TAG, "Beginning source."); source.begin(this); } @@ -203,7 +179,7 @@ class RecordsChannel implements try { sink.store(record); } catch (NoStoreDelegateException e) { - error("Got NoStoreDelegateException in RecordsChannel.store(). This should not occur. Aborting.", e); + Logger.error(LOG_TAG, "Got NoStoreDelegateException in RecordsChannel.store(). This should not occur. Aborting.", e); delegate.onFlowStoreFailed(this, e); this.abort(); } @@ -211,7 +187,7 @@ class RecordsChannel implements @Override public void onFetchFailed(Exception ex, Record record) { - warn("onFetchFailed. Calling for immediate stop.", ex); + Logger.warn(LOG_TAG, "onFetchFailed. Calling for immediate stop.", ex); this.consumer.halt(); } @@ -232,8 +208,8 @@ class RecordsChannel implements @Override public void onFetchCompleted(long end) { - info("onFetchCompleted. Stopping consumer once stores are done."); - info("Fetch timestamp is " + end); + Logger.info(LOG_TAG, "onFetchCompleted. Stopping consumer once stores are done."); + Logger.info(LOG_TAG, "Fetch timestamp is " + end); this.end = end; this.consumer.queueFilled(); } @@ -253,7 +229,7 @@ class RecordsChannel implements @Override public void consumerIsDone(boolean allRecordsQueued) { - trace("Consumer is done. Are we waiting for it? " + waitingForQueueDone); + Logger.trace(LOG_TAG, "Consumer is done. Are we waiting for it? " + waitingForQueueDone); if (waitingForQueueDone) { waitingForQueueDone = false; this.sink.storeDone(); // Now we'll be waiting for onStoreCompleted. @@ -262,7 +238,7 @@ class RecordsChannel implements @Override public void onStoreCompleted() { - info("onStoreCompleted. Notifying delegate of onFlowCompleted. End is " + end); + Logger.info(LOG_TAG, "onStoreCompleted. Notifying delegate of onFlowCompleted. End is " + end); // TODO: synchronize on consumer callback? delegate.onFlowCompleted(this, end); } @@ -275,11 +251,11 @@ class RecordsChannel implements @Override public void onBeginSucceeded(RepositorySession session) { if (session == source) { - info("Source session began. Beginning sink session."); + Logger.info(LOG_TAG, "Source session began. Beginning sink session."); sink.begin(this); } if (session == sink) { - info("Sink session began. Beginning flow."); + Logger.info(LOG_TAG, "Sink session began. Beginning flow."); this.flow(); return; } diff --git a/mobile/android/base/sync/synchronizer/Synchronizer.java b/mobile/android/base/sync/synchronizer/Synchronizer.java index c41ab288bc40..4baaf7a4de64 100644 --- a/mobile/android/base/sync/synchronizer/Synchronizer.java +++ b/mobile/android/base/sync/synchronizer/Synchronizer.java @@ -63,7 +63,7 @@ public class Synchronizer { public class SynchronizerDelegateSessionDelegate implements SynchronizerSessionDelegate { - private static final String LOG_TAG = "SynchronizerDelegateSessionDelegate"; + private static final String LOG_TAG = "SyncDelSDelegate"; private SynchronizerDelegate synchronizerDelegate; private SynchronizerSession session; diff --git a/mobile/android/sync/java-sources.mn b/mobile/android/sync/java-sources.mn index a8934571c2d0..94563c79ff6d 100644 --- a/mobile/android/sync/java-sources.mn +++ b/mobile/android/sync/java-sources.mn @@ -1 +1 @@ -sync/AlreadySyncingException.java sync/CollectionKeys.java sync/CredentialsSource.java sync/crypto/CryptoException.java sync/crypto/Cryptographer.java sync/crypto/CryptoInfo.java sync/crypto/HKDF.java sync/crypto/HMACVerificationException.java sync/crypto/KeyBundle.java sync/crypto/MissingCryptoInputException.java sync/crypto/NoKeyBundleException.java sync/cryptographer/CryptoStatusBundle.java sync/cryptographer/SyncCryptographer.java sync/CryptoRecord.java sync/DelayedWorkTracker.java sync/delegates/FreshStartDelegate.java sync/delegates/GlobalSessionCallback.java sync/delegates/InfoCollectionsDelegate.java sync/delegates/KeyUploadDelegate.java sync/delegates/MetaGlobalDelegate.java sync/delegates/WipeServerDelegate.java sync/ExtendedJSONObject.java sync/GlobalSession.java sync/HTTPFailureException.java sync/InfoCollections.java sync/jpake/BigIntegerHelper.java sync/jpake/Gx3OrGx4IsZeroOrOneException.java sync/jpake/IncorrectZkpException.java sync/jpake/JPakeClient.java sync/jpake/JPakeCrypto.java sync/jpake/JPakeNoActivePairingException.java sync/jpake/JPakeNumGenerator.java sync/jpake/JPakeNumGeneratorRandom.java sync/jpake/JPakeParty.java sync/jpake/JPakeRequest.java sync/jpake/JPakeRequestDelegate.java sync/jpake/JPakeResponse.java sync/jpake/Zkp.java sync/MetaGlobal.java sync/MetaGlobalException.java sync/MetaGlobalMissingEnginesException.java sync/MetaGlobalNotSetException.java sync/middleware/Crypto5MiddlewareRepository.java sync/middleware/Crypto5MiddlewareRepositorySession.java sync/middleware/MiddlewareRepository.java sync/net/BaseResource.java sync/net/CompletedEntity.java sync/net/HandleProgressException.java sync/net/Resource.java sync/net/ResourceDelegate.java sync/net/SyncResourceDelegate.java sync/net/SyncResponse.java sync/net/SyncStorageCollectionRequest.java sync/net/SyncStorageCollectionRequestDelegate.java sync/net/SyncStorageRecordRequest.java sync/net/SyncStorageRequest.java sync/net/SyncStorageRequestDelegate.java sync/net/SyncStorageRequestIncrementalDelegate.java sync/net/SyncStorageResponse.java sync/net/TLSSocketFactory.java sync/net/WBOCollectionRequestDelegate.java sync/NoCollectionKeysSetException.java sync/NonArrayJSONException.java sync/NonObjectJSONException.java sync/PrefsSource.java sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java sync/repositories/android/AndroidBrowserBookmarksRepository.java sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java sync/repositories/android/AndroidBrowserHistoryDataAccessor.java sync/repositories/android/AndroidBrowserHistoryDataExtender.java sync/repositories/android/AndroidBrowserHistoryRepository.java sync/repositories/android/AndroidBrowserHistoryRepositorySession.java sync/repositories/android/AndroidBrowserPasswordsDataAccessor.java sync/repositories/android/AndroidBrowserPasswordsRepository.java sync/repositories/android/AndroidBrowserPasswordsRepositorySession.java sync/repositories/android/AndroidBrowserRepository.java sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java sync/repositories/android/AndroidBrowserRepositorySession.java sync/repositories/android/BrowserContract.java sync/repositories/android/PasswordColumns.java sync/repositories/android/RepoUtils.java sync/repositories/BookmarkNeedsReparentingException.java sync/repositories/BookmarksRepository.java sync/repositories/ConstrainedServer11Repository.java sync/repositories/delegates/DeferrableRepositorySessionCreationDelegate.java sync/repositories/delegates/DeferredRepositorySessionBeginDelegate.java sync/repositories/delegates/DeferredRepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/DeferredRepositorySessionFinishDelegate.java sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionBeginDelegate.java sync/repositories/delegates/RepositorySessionCleanDelegate.java sync/repositories/delegates/RepositorySessionCreationDelegate.java sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/RepositorySessionFinishDelegate.java sync/repositories/delegates/RepositorySessionGuidsSinceDelegate.java sync/repositories/delegates/RepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionWipeDelegate.java sync/repositories/domain/BookmarkRecord.java sync/repositories/domain/BookmarkRecordFactory.java sync/repositories/domain/HistoryRecord.java sync/repositories/domain/HistoryRecordFactory.java sync/repositories/domain/PasswordRecord.java sync/repositories/domain/Record.java sync/repositories/HashSetStoreTracker.java sync/repositories/HistoryRepository.java sync/repositories/IdentityRecordFactory.java sync/repositories/InactiveSessionException.java sync/repositories/InvalidBookmarkTypeException.java sync/repositories/InvalidRequestException.java sync/repositories/InvalidSessionTransitionException.java sync/repositories/MultipleRecordsForGuidException.java sync/repositories/NoGuidForIdException.java sync/repositories/NoStoreDelegateException.java sync/repositories/NullCursorException.java sync/repositories/ParentNotFoundException.java sync/repositories/ProfileDatabaseException.java sync/repositories/RecordFactory.java sync/repositories/RecordFilter.java sync/repositories/Repository.java sync/repositories/RepositorySession.java sync/repositories/RepositorySessionBundle.java sync/repositories/Server11Repository.java sync/repositories/Server11RepositorySession.java sync/repositories/StoreTracker.java sync/repositories/StoreTrackingRepositorySession.java sync/setup/activities/AccountActivity.java sync/setup/activities/SetupFailureActivity.java sync/setup/activities/SetupSuccessActivity.java sync/setup/activities/SetupSyncActivity.java sync/setup/Constants.java sync/setup/SyncAuthenticatorService.java sync/stage/AndroidBrowserBookmarksServerSyncStage.java sync/stage/AndroidBrowserHistoryServerSyncStage.java sync/stage/CheckPreconditionsStage.java sync/stage/CompletedStage.java sync/stage/EnsureClusterURLStage.java sync/stage/EnsureKeysStage.java sync/stage/FetchInfoCollectionsStage.java sync/stage/FetchMetaGlobalStage.java sync/stage/GlobalSyncStage.java sync/stage/NoSuchStageException.java sync/stage/NoSyncIDException.java sync/stage/ServerSyncStage.java sync/StubActivity.java sync/syncadapter/SyncAdapter.java sync/syncadapter/SyncService.java sync/SyncConfiguration.java sync/SyncConfigurationException.java sync/SyncException.java sync/synchronizer/ConcurrentRecordConsumer.java sync/synchronizer/RecordConsumer.java sync/synchronizer/RecordsChannel.java sync/synchronizer/RecordsChannelDelegate.java sync/synchronizer/RecordsConsumerDelegate.java sync/synchronizer/SerialRecordConsumer.java sync/synchronizer/SessionNotBegunException.java sync/synchronizer/Synchronizer.java sync/synchronizer/SynchronizerDelegate.java sync/synchronizer/SynchronizerSession.java sync/synchronizer/SynchronizerSessionDelegate.java sync/synchronizer/UnbundleError.java sync/synchronizer/UnexpectedSessionException.java sync/SynchronizerConfiguration.java sync/SynchronizerConfigurations.java sync/ThreadPool.java sync/UnexpectedJSONException.java sync/UnknownSynchronizerConfigurationVersionException.java sync/Utils.java +sync/AlreadySyncingException.java sync/CollectionKeys.java sync/CredentialsSource.java sync/crypto/CryptoException.java sync/crypto/Cryptographer.java sync/crypto/CryptoInfo.java sync/crypto/HKDF.java sync/crypto/HMACVerificationException.java sync/crypto/KeyBundle.java sync/crypto/MissingCryptoInputException.java sync/crypto/NoKeyBundleException.java sync/cryptographer/CryptoStatusBundle.java sync/cryptographer/SyncCryptographer.java sync/CryptoRecord.java sync/DelayedWorkTracker.java sync/delegates/FreshStartDelegate.java sync/delegates/GlobalSessionCallback.java sync/delegates/InfoCollectionsDelegate.java sync/delegates/KeyUploadDelegate.java sync/delegates/MetaGlobalDelegate.java sync/delegates/WipeServerDelegate.java sync/ExtendedJSONObject.java sync/GlobalSession.java sync/HTTPFailureException.java sync/InfoCollections.java sync/jpake/BigIntegerHelper.java sync/jpake/Gx3OrGx4IsZeroOrOneException.java sync/jpake/IncorrectZkpException.java sync/jpake/JPakeClient.java sync/jpake/JPakeCrypto.java sync/jpake/JPakeNoActivePairingException.java sync/jpake/JPakeNumGenerator.java sync/jpake/JPakeNumGeneratorRandom.java sync/jpake/JPakeParty.java sync/jpake/JPakeRequest.java sync/jpake/JPakeRequestDelegate.java sync/jpake/JPakeResponse.java sync/jpake/Zkp.java sync/Logger.java sync/MetaGlobal.java sync/MetaGlobalException.java sync/MetaGlobalMissingEnginesException.java sync/MetaGlobalNotSetException.java sync/middleware/Crypto5MiddlewareRepository.java sync/middleware/Crypto5MiddlewareRepositorySession.java sync/middleware/MiddlewareRepository.java sync/net/BaseResource.java sync/net/CompletedEntity.java sync/net/HandleProgressException.java sync/net/Resource.java sync/net/ResourceDelegate.java sync/net/SyncResourceDelegate.java sync/net/SyncResponse.java sync/net/SyncStorageCollectionRequest.java sync/net/SyncStorageCollectionRequestDelegate.java sync/net/SyncStorageRecordRequest.java sync/net/SyncStorageRequest.java sync/net/SyncStorageRequestDelegate.java sync/net/SyncStorageRequestIncrementalDelegate.java sync/net/SyncStorageResponse.java sync/net/TLSSocketFactory.java sync/net/WBOCollectionRequestDelegate.java sync/NoCollectionKeysSetException.java sync/NonArrayJSONException.java sync/NonObjectJSONException.java sync/PrefsSource.java sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java sync/repositories/android/AndroidBrowserBookmarksRepository.java sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java sync/repositories/android/AndroidBrowserHistoryDataAccessor.java sync/repositories/android/AndroidBrowserHistoryDataExtender.java sync/repositories/android/AndroidBrowserHistoryRepository.java sync/repositories/android/AndroidBrowserHistoryRepositorySession.java sync/repositories/android/AndroidBrowserPasswordsDataAccessor.java sync/repositories/android/AndroidBrowserPasswordsRepository.java sync/repositories/android/AndroidBrowserPasswordsRepositorySession.java sync/repositories/android/AndroidBrowserRepository.java sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java sync/repositories/android/AndroidBrowserRepositorySession.java sync/repositories/android/BrowserContract.java sync/repositories/android/PasswordColumns.java sync/repositories/android/RepoUtils.java sync/repositories/BookmarkNeedsReparentingException.java sync/repositories/BookmarksRepository.java sync/repositories/ConstrainedServer11Repository.java sync/repositories/delegates/DeferrableRepositorySessionCreationDelegate.java sync/repositories/delegates/DeferredRepositorySessionBeginDelegate.java sync/repositories/delegates/DeferredRepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/DeferredRepositorySessionFinishDelegate.java sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionBeginDelegate.java sync/repositories/delegates/RepositorySessionCleanDelegate.java sync/repositories/delegates/RepositorySessionCreationDelegate.java sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/RepositorySessionFinishDelegate.java sync/repositories/delegates/RepositorySessionGuidsSinceDelegate.java sync/repositories/delegates/RepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionWipeDelegate.java sync/repositories/domain/BookmarkRecord.java sync/repositories/domain/BookmarkRecordFactory.java sync/repositories/domain/HistoryRecord.java sync/repositories/domain/HistoryRecordFactory.java sync/repositories/domain/PasswordRecord.java sync/repositories/domain/Record.java sync/repositories/HashSetStoreTracker.java sync/repositories/HistoryRepository.java sync/repositories/IdentityRecordFactory.java sync/repositories/InactiveSessionException.java sync/repositories/InvalidBookmarkTypeException.java sync/repositories/InvalidRequestException.java sync/repositories/InvalidSessionTransitionException.java sync/repositories/MultipleRecordsForGuidException.java sync/repositories/NoGuidForIdException.java sync/repositories/NoStoreDelegateException.java sync/repositories/NullCursorException.java sync/repositories/ParentNotFoundException.java sync/repositories/ProfileDatabaseException.java sync/repositories/RecordFactory.java sync/repositories/RecordFilter.java sync/repositories/Repository.java sync/repositories/RepositorySession.java sync/repositories/RepositorySessionBundle.java sync/repositories/Server11Repository.java sync/repositories/Server11RepositorySession.java sync/repositories/StoreTracker.java sync/repositories/StoreTrackingRepositorySession.java sync/setup/activities/AccountActivity.java sync/setup/activities/SetupFailureActivity.java sync/setup/activities/SetupSuccessActivity.java sync/setup/activities/SetupSyncActivity.java sync/setup/Constants.java sync/setup/SyncAuthenticatorService.java sync/stage/AndroidBrowserBookmarksServerSyncStage.java sync/stage/AndroidBrowserHistoryServerSyncStage.java sync/stage/CheckPreconditionsStage.java sync/stage/CompletedStage.java sync/stage/EnsureClusterURLStage.java sync/stage/EnsureKeysStage.java sync/stage/FetchInfoCollectionsStage.java sync/stage/FetchMetaGlobalStage.java sync/stage/GlobalSyncStage.java sync/stage/NoSuchStageException.java sync/stage/NoSyncIDException.java sync/stage/ServerSyncStage.java sync/StubActivity.java sync/syncadapter/SyncAdapter.java sync/syncadapter/SyncService.java sync/SyncConfiguration.java sync/SyncConfigurationException.java sync/SyncException.java sync/synchronizer/ConcurrentRecordConsumer.java sync/synchronizer/RecordConsumer.java sync/synchronizer/RecordsChannel.java sync/synchronizer/RecordsChannelDelegate.java sync/synchronizer/RecordsConsumerDelegate.java sync/synchronizer/SerialRecordConsumer.java sync/synchronizer/SessionNotBegunException.java sync/synchronizer/Synchronizer.java sync/synchronizer/SynchronizerDelegate.java sync/synchronizer/SynchronizerSession.java sync/synchronizer/SynchronizerSessionDelegate.java sync/synchronizer/UnbundleError.java sync/synchronizer/UnexpectedSessionException.java sync/SynchronizerConfiguration.java sync/SynchronizerConfigurations.java sync/ThreadPool.java sync/UnexpectedJSONException.java sync/UnknownSynchronizerConfigurationVersionException.java sync/Utils.java From 62f01e3d4942f1c348e7b5c62dd0a8f88fe51913 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Wed, 15 Feb 2012 22:05:52 -0800 Subject: [PATCH 10/93] Bug 724328 - misc Sync cleaning. --- mobile/android/base/sync/GlobalSession.java | 4 +--- .../base/sync/SynchronizerConfigurations.java | 2 -- mobile/android/base/sync/Utils.java | 14 ++++++++++++-- mobile/android/base/sync/crypto/Cryptographer.java | 14 +------------- mobile/android/base/sync/crypto/KeyBundle.java | 2 +- mobile/android/base/sync/jpake/JPakeClient.java | 6 +++--- .../AndroidBrowserBookmarksRepositorySession.java | 1 - .../sync/setup/activities/AccountActivity.java | 1 + .../setup/activities/SetupSuccessActivity.java | 1 + .../android/base/sync/syncadapter/SyncAdapter.java | 2 -- 10 files changed, 20 insertions(+), 27 deletions(-) diff --git a/mobile/android/base/sync/GlobalSession.java b/mobile/android/base/sync/GlobalSession.java index c9ea8028aaff..84b3ba43ebd2 100644 --- a/mobile/android/base/sync/GlobalSession.java +++ b/mobile/android/base/sync/GlobalSession.java @@ -58,7 +58,6 @@ import org.mozilla.gecko.sync.net.SyncStorageRecordRequest; import org.mozilla.gecko.sync.net.SyncStorageRequest; import org.mozilla.gecko.sync.net.SyncStorageRequestDelegate; import org.mozilla.gecko.sync.net.SyncStorageResponse; -import org.mozilla.gecko.sync.repositories.RepositorySessionBundle; import org.mozilla.gecko.sync.stage.AndroidBrowserBookmarksServerSyncStage; import org.mozilla.gecko.sync.stage.AndroidBrowserHistoryServerSyncStage; import org.mozilla.gecko.sync.stage.CheckPreconditionsStage; @@ -71,12 +70,11 @@ import org.mozilla.gecko.sync.stage.GlobalSyncStage; import org.mozilla.gecko.sync.stage.GlobalSyncStage.Stage; import org.mozilla.gecko.sync.stage.NoSuchStageException; -import ch.boye.httpclientandroidlib.HttpResponse; - import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; import android.util.Log; +import ch.boye.httpclientandroidlib.HttpResponse; public class GlobalSession implements CredentialsSource, PrefsSource { private static final String LOG_TAG = "GlobalSession"; diff --git a/mobile/android/base/sync/SynchronizerConfigurations.java b/mobile/android/base/sync/SynchronizerConfigurations.java index d571fd1e5cd8..f7ccc9114eb5 100644 --- a/mobile/android/base/sync/SynchronizerConfigurations.java +++ b/mobile/android/base/sync/SynchronizerConfigurations.java @@ -39,7 +39,6 @@ package org.mozilla.gecko.sync; import java.io.IOException; import java.util.HashMap; -import java.util.Map.Entry; import java.util.Set; import org.json.simple.parser.ParseException; @@ -48,7 +47,6 @@ import org.mozilla.gecko.sync.repositories.RepositorySessionBundle; import android.os.Bundle; public class SynchronizerConfigurations { - private static final int CONFIGURATION_VERSION = 1; private HashMap engines; protected HashMap enginesMapFromBundleV1(Bundle engineBundle) throws IOException, ParseException, NonObjectJSONException { diff --git a/mobile/android/base/sync/Utils.java b/mobile/android/base/sync/Utils.java index 445c6e5c05b7..a12ea17e168f 100644 --- a/mobile/android/base/sync/Utils.java +++ b/mobile/android/base/sync/Utils.java @@ -41,13 +41,13 @@ package org.mozilla.gecko.sync; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.math.BigInteger; +import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.HashMap; import org.mozilla.apache.commons.codec.binary.Base32; import org.mozilla.apache.commons.codec.binary.Base64; -import org.mozilla.gecko.sync.crypto.Cryptographer; import android.content.Context; import android.content.SharedPreferences; @@ -211,10 +211,20 @@ public class Utils { return (long)(decimal * 1000); } + public static byte[] sha1(String utf8) + throws NoSuchAlgorithmException, UnsupportedEncodingException { + MessageDigest sha1 = MessageDigest.getInstance("SHA-1"); + return sha1.digest(utf8.getBytes("UTF-8")); + } + + public static String sha1Base32(String utf8) + throws NoSuchAlgorithmException, UnsupportedEncodingException { + return new Base32().encodeAsString(sha1(utf8)).toLowerCase(); + } public static String getPrefsPath(String username, String serverURL) throws NoSuchAlgorithmException, UnsupportedEncodingException { - return "sync.prefs." + Cryptographer.sha1Base32(serverURL + ":" + username); + return "sync.prefs." + sha1Base32(serverURL + ":" + username); } public static SharedPreferences getSharedPreferences(Context context, String username, String serverURL) throws NoSuchAlgorithmException, UnsupportedEncodingException { diff --git a/mobile/android/base/sync/crypto/Cryptographer.java b/mobile/android/base/sync/crypto/Cryptographer.java index 1594a8abfc11..f63fae9939ba 100644 --- a/mobile/android/base/sync/crypto/Cryptographer.java +++ b/mobile/android/base/sync/crypto/Cryptographer.java @@ -38,9 +38,8 @@ package org.mozilla.gecko.sync.crypto; -import java.io.UnsupportedEncodingException; import java.security.GeneralSecurityException; -import java.security.MessageDigest; +import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.Arrays; @@ -53,10 +52,8 @@ import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; -import org.mozilla.apache.commons.codec.binary.Base32; import org.mozilla.apache.commons.codec.binary.Base64; import org.mozilla.gecko.sync.Utils; -import java.security.InvalidKeyException; /* * Implements the basic required cryptography options. @@ -222,13 +219,4 @@ public class Cryptographer { Mac hmacHasher = HKDF.makeHMACHasher(bundle.getKeys().getHMACKey()); return hmacHasher.doFinal(Base64.encodeBase64(bundle.getMessage())); } - - public static byte[] sha1(String utf8) throws NoSuchAlgorithmException, UnsupportedEncodingException { - MessageDigest sha1 = MessageDigest.getInstance("SHA-1"); - return sha1.digest(utf8.getBytes("UTF-8")); - } - - public static String sha1Base32(String utf8) throws NoSuchAlgorithmException, UnsupportedEncodingException { - return new Base32().encodeAsString(sha1(utf8)).toLowerCase(); - } } diff --git a/mobile/android/base/sync/crypto/KeyBundle.java b/mobile/android/base/sync/crypto/KeyBundle.java index ded6372bf300..6ad7b492f9ae 100644 --- a/mobile/android/base/sync/crypto/KeyBundle.java +++ b/mobile/android/base/sync/crypto/KeyBundle.java @@ -75,7 +75,7 @@ public class KeyBundle { if (account.matches("^[A-Za-z0-9._-]+$")) { return account; } - return Cryptographer.sha1Base32(account); + return Utils.sha1Base32(account); } // If we encounter characters not allowed by the API (as found for diff --git a/mobile/android/base/sync/jpake/JPakeClient.java b/mobile/android/base/sync/jpake/JPakeClient.java index 9659c16846ca..62c75d05aa16 100644 --- a/mobile/android/base/sync/jpake/JPakeClient.java +++ b/mobile/android/base/sync/jpake/JPakeClient.java @@ -44,7 +44,8 @@ import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.net.URISyntaxException; import java.security.GeneralSecurityException; -import java.util.Random; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; import java.util.Timer; import java.util.TimerTask; @@ -75,8 +76,6 @@ import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase; import ch.boye.httpclientandroidlib.entity.StringEntity; import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient; import ch.boye.httpclientandroidlib.message.BasicHeader; -import java.security.NoSuchAlgorithmException; -import java.security.InvalidKeyException; public class JPakeClient implements JPakeRequestDelegate { private static String LOG_TAG = "JPakeClient"; @@ -107,6 +106,7 @@ public class JPakeClient implements JPakeRequestDelegate { private String myEtag; private String mySignerId; + @SuppressWarnings("unused") private String theirEtag; private String theirSignerId; private String jpakeServer; diff --git a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java index 1750c2dcf00f..f82aa8652cfa 100644 --- a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java @@ -43,7 +43,6 @@ import java.util.HashMap; import org.json.simple.JSONArray; import org.mozilla.gecko.sync.Logger; import org.mozilla.gecko.sync.Utils; -import org.mozilla.gecko.sync.repositories.BookmarkNeedsReparentingException; import org.mozilla.gecko.sync.repositories.NoGuidForIdException; import org.mozilla.gecko.sync.repositories.NullCursorException; import org.mozilla.gecko.sync.repositories.ParentNotFoundException; diff --git a/mobile/android/base/sync/setup/activities/AccountActivity.java b/mobile/android/base/sync/setup/activities/AccountActivity.java index 54a02c70db68..4effd15bd060 100644 --- a/mobile/android/base/sync/setup/activities/AccountActivity.java +++ b/mobile/android/base/sync/setup/activities/AccountActivity.java @@ -274,6 +274,7 @@ public class AccountActivity extends AccountAuthenticatorActivity { return intent; } + @SuppressWarnings("unused") private void authFailure() { enableCredEntry(true); Intent intent = new Intent(mContext, SetupFailureActivity.class); diff --git a/mobile/android/base/sync/setup/activities/SetupSuccessActivity.java b/mobile/android/base/sync/setup/activities/SetupSuccessActivity.java index 74505c42fefb..b4802ad3e8a2 100644 --- a/mobile/android/base/sync/setup/activities/SetupSuccessActivity.java +++ b/mobile/android/base/sync/setup/activities/SetupSuccessActivity.java @@ -49,6 +49,7 @@ import android.view.View; import android.widget.TextView; public class SetupSuccessActivity extends Activity { + @SuppressWarnings("unused") private final static String LOG_TAG = "SetupSuccessActivity"; private TextView setupSubtitle; private Context mContext; diff --git a/mobile/android/base/sync/syncadapter/SyncAdapter.java b/mobile/android/base/sync/syncadapter/SyncAdapter.java index 9b7c393e3ecd..69843293457c 100644 --- a/mobile/android/base/sync/syncadapter/SyncAdapter.java +++ b/mobile/android/base/sync/syncadapter/SyncAdapter.java @@ -39,7 +39,6 @@ package org.mozilla.gecko.sync.syncadapter; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.security.NoSuchAlgorithmException; import java.util.concurrent.TimeUnit; @@ -51,7 +50,6 @@ import org.mozilla.gecko.sync.SyncConfiguration; import org.mozilla.gecko.sync.SyncConfigurationException; import org.mozilla.gecko.sync.SyncException; import org.mozilla.gecko.sync.Utils; -import org.mozilla.gecko.sync.crypto.Cryptographer; import org.mozilla.gecko.sync.crypto.KeyBundle; import org.mozilla.gecko.sync.delegates.GlobalSessionCallback; import org.mozilla.gecko.sync.setup.Constants; From 51cd0898b20a5142d82dcffc217c9ba134f4e351 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Wed, 15 Feb 2012 22:05:52 -0800 Subject: [PATCH 11/93] Bug 725525 - Part 2: make Logger cache log levels. --- mobile/android/base/sync/Logger.java | 127 +++++++++++++++--- ...roidBrowserBookmarksRepositorySession.java | 3 +- .../repositories/domain/HistoryRecord.java | 12 +- 3 files changed, 112 insertions(+), 30 deletions(-) diff --git a/mobile/android/base/sync/Logger.java b/mobile/android/base/sync/Logger.java index ca3ee09e84e6..d46542cfedc7 100644 --- a/mobile/android/base/sync/Logger.java +++ b/mobile/android/base/sync/Logger.java @@ -4,8 +4,20 @@ package org.mozilla.gecko.sync; +import java.util.IdentityHashMap; +import java.util.Map; + import android.util.Log; +/** + * Logging helper class. Serializes all log operations (by synchronizing), + * and caches log level settings. + * + * Ultimately this will also be a hook point for our own logging system. + * + * @author rnewman + * + */ public class Logger { // For extra debugging. @@ -14,7 +26,85 @@ public class Logger { // If true, log to System.out as well as using Android's Log.* calls. public static boolean LOG_TO_STDOUT = false; - public static void logToStdout(String... s) { + // I can't believe we have to implement this ourselves. + // These aren't synchronized (and neither are the setters) because + // the logging calls themselves are synchronized. + private static Map isErrorLoggable = new IdentityHashMap(); + private static Map isWarnLoggable = new IdentityHashMap(); + private static Map isInfoLoggable = new IdentityHashMap(); + private static Map isDebugLoggable = new IdentityHashMap(); + private static Map isVerboseLoggable = new IdentityHashMap(); + + /** + * Empty the caches of log levels. + */ + public synchronized void refreshLogLevels() { + isErrorLoggable = new IdentityHashMap(); + isWarnLoggable = new IdentityHashMap(); + isInfoLoggable = new IdentityHashMap(); + isDebugLoggable = new IdentityHashMap(); + isVerboseLoggable = new IdentityHashMap(); + } + + private static boolean shouldLogError(String logTag) { + Boolean out = isErrorLoggable.get(logTag); + if (out != null) { + return out.booleanValue(); + } + out = Log.isLoggable(logTag, Log.ERROR); + isErrorLoggable.put(logTag, out); + return out; + } + + private static boolean shouldLogWarn(String logTag) { + Boolean out = isWarnLoggable.get(logTag); + if (out != null) { + return out.booleanValue(); + } + out = Log.isLoggable(logTag, Log.WARN); + isWarnLoggable.put(logTag, out); + return out; + } + + private static boolean shouldLogInfo(String logTag) { + Boolean out = isInfoLoggable.get(logTag); + if (out != null) { + return out.booleanValue(); + } + Log.d("XXX", "Calling out to isLoggable for INFO!"); + out = Log.isLoggable(logTag, Log.INFO); + isInfoLoggable.put(logTag, out); + return out; + } + + private static boolean shouldLogDebug(String logTag) { + Boolean out = isDebugLoggable.get(logTag); + if (out != null) { + return out.booleanValue(); + } + Log.d("XXX", "Calling out to isLoggable for DEBUG!"); + out = Log.isLoggable(logTag, Log.DEBUG); + isDebugLoggable.put(logTag, out); + return out; + } + + private static boolean shouldLogVerbose(String logTag) { + Boolean out = isVerboseLoggable.get(logTag); + if (out != null) { + return out.booleanValue(); + } + Log.d("XXX", "Calling out to isLoggable for VERBOSE!"); + out = Log.isLoggable(logTag, Log.VERBOSE); + isVerboseLoggable.put(logTag, out); + return out; + } + + // Synchronized version for other classes to use. + public static synchronized boolean logVerbose(String logTag) { + return shouldLogVerbose(logTag); + } + + private static void logToStdout(String... s) { if (LOG_TO_STDOUT) { for (String string : s) { System.out.print(string); @@ -27,52 +117,47 @@ public class Logger { Logger.error(logTag, message, null); } - public static void error(String logTag, String message, Throwable error) { + public static synchronized void error(String logTag, String message, Throwable error) { logToStdout(logTag, " :: ERROR: ", message); - if (!Log.isLoggable(logTag, Log.ERROR)) { - return; + if (shouldLogError(logTag)) { + Log.e(logTag, message, error); } - Log.e(logTag, message, error); } public static void warn(String logTag, String message) { Logger.warn(logTag, message, null); } - public static void warn(String logTag, String message, Throwable error) { + public static synchronized void warn(String logTag, String message, Throwable error) { logToStdout(logTag, " :: WARN: ", message); - if (!Log.isLoggable(logTag, Log.WARN)) { - return; + if (shouldLogWarn(logTag)) { + Log.w(logTag, message, error); } - Log.w(logTag, message, error); } - public static void info(String logTag, String message) { + public static synchronized void info(String logTag, String message) { logToStdout(logTag, " :: INFO: ", message); - if (!Log.isLoggable(logTag, Log.INFO)) { - return; + if (shouldLogInfo(logTag)) { + Log.i(logTag, message); } - Log.i(logTag, message); } public static void debug(String logTag, String message) { Logger.debug(logTag, message, null); } - public static void debug(String logTag, String message, Throwable error) { + public static synchronized void debug(String logTag, String message, Throwable error) { logToStdout(logTag, " :: DEBUG: ", message); - if (!Log.isLoggable(logTag, Log.DEBUG)) { - return; + if (shouldLogDebug(logTag)) { + Log.d(logTag, message, error); } - Log.d(logTag, message, error); } - public static void trace(String logTag, String message) { + public static synchronized void trace(String logTag, String message) { logToStdout(logTag, " :: TRACE: ", message); - if (!Log.isLoggable(logTag, Log.VERBOSE)) { - return; + if (shouldLogVerbose(logTag)) { + Log.v(logTag, message); } - Log.v(logTag, message); } public static void pii(String logTag, String message) { diff --git a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java index f82aa8652cfa..7df6cee5f6fb 100644 --- a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java @@ -54,7 +54,6 @@ import org.mozilla.gecko.sync.repositories.domain.Record; import android.content.Context; import android.database.Cursor; -import android.util.Log; public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepositorySession { @@ -187,7 +186,7 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo } childArray.add(kid); } - if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) { + if (Logger.logVerbose(LOG_TAG)) { // Don't JSON-encode unless we're logging. Logger.trace(LOG_TAG, "Output child array: " + childArray.toJSONString()); } diff --git a/mobile/android/base/sync/repositories/domain/HistoryRecord.java b/mobile/android/base/sync/repositories/domain/HistoryRecord.java index e7e1bb6f2ae2..07a1b04f942c 100644 --- a/mobile/android/base/sync/repositories/domain/HistoryRecord.java +++ b/mobile/android/base/sync/repositories/domain/HistoryRecord.java @@ -48,8 +48,6 @@ import org.mozilla.gecko.sync.NonArrayJSONException; import org.mozilla.gecko.sync.Utils; import org.mozilla.gecko.sync.repositories.android.RepoUtils; -import android.util.Log; - /** * Visits are in microsecond precision. * @@ -125,7 +123,7 @@ public class HistoryRecord extends Record { try { this.visits = p.getArray("visits"); } catch (NonArrayJSONException e) { - Log.e(LOG_TAG, "Got non-array visits in history record " + this.guid, e); + Logger.error(LOG_TAG, "Got non-array visits in history record " + this.guid, e); this.visits = new JSONArray(); } } @@ -134,7 +132,7 @@ public class HistoryRecord extends Record { public CryptoRecord getPayload() { CryptoRecord rec = new CryptoRecord(this); rec.payload = new ExtendedJSONObject(); - Log.d(LOG_TAG, "Getting payload for history record " + this.guid + " (" + this.guid.length() + ")."); + Logger.debug(LOG_TAG, "Getting payload for history record " + this.guid + " (" + this.guid.length() + ")."); rec.payload.put("id", this.guid); rec.payload.put("title", this.title); rec.payload.put("histUri", this.histURI); // TODO: encoding? @@ -163,12 +161,12 @@ public class HistoryRecord extends Record { @Override public boolean equalPayloads(Object o) { if (o == null || !(o instanceof HistoryRecord)) { - Log.d(LOG_TAG, "Not a HistoryRecord: " + o); + Logger.debug(LOG_TAG, "Not a HistoryRecord: " + o); return false; } HistoryRecord other = (HistoryRecord) o; if (!super.equalPayloads(other)) { - Log.d(LOG_TAG, "super.equalPayloads returned false."); + Logger.debug(LOG_TAG, "super.equalPayloads returned false."); return false; } return RepoUtils.stringsEqual(this.title, other.title) && @@ -193,7 +191,7 @@ public class HistoryRecord extends Record { private boolean checkVisitsEquals(HistoryRecord other) { Logger.debug(LOG_TAG, "Checking visits."); - if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) { + if (Logger.logVerbose(LOG_TAG)) { // Don't JSON-encode unless we're logging. Logger.trace(LOG_TAG, ">> Mine: " + ((this.visits == null) ? "null" : this.visits.toJSONString())); Logger.trace(LOG_TAG, ">> Theirs: " + ((other.visits == null) ? "null" : other.visits.toJSONString())); From 6380ff09799778626adfd988c497462b49298558 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Wed, 15 Feb 2012 22:05:53 -0800 Subject: [PATCH 12/93] Bug 725913 - Don't log credentials during setup. --- .../sync/setup/SyncAuthenticatorService.java | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/mobile/android/base/sync/setup/SyncAuthenticatorService.java b/mobile/android/base/sync/setup/SyncAuthenticatorService.java index 4055634d4c44..6a47e279a631 100644 --- a/mobile/android/base/sync/setup/SyncAuthenticatorService.java +++ b/mobile/android/base/sync/setup/SyncAuthenticatorService.java @@ -41,6 +41,7 @@ package org.mozilla.gecko.sync.setup; import java.io.UnsupportedEncodingException; import java.security.NoSuchAlgorithmException; +import org.mozilla.gecko.sync.Logger; import org.mozilla.gecko.sync.crypto.KeyBundle; import org.mozilla.gecko.sync.setup.activities.SetupSyncActivity; @@ -54,7 +55,6 @@ import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.IBinder; -import android.util.Log; public class SyncAuthenticatorService extends Service { private static final String LOG_TAG = "SyncAuthService"; @@ -62,17 +62,16 @@ public class SyncAuthenticatorService extends Service { @Override public void onCreate() { - Log.d(LOG_TAG, "onCreate"); + Logger.debug(LOG_TAG, "onCreate"); sAccountAuthenticator = getAuthenticator(); } @Override public IBinder onBind(Intent intent) { - IBinder ret = null; - if (intent.getAction().equals( - android.accounts.AccountManager.ACTION_AUTHENTICATOR_INTENT)) - ret = getAuthenticator().getIBinder(); - return ret; + if (intent.getAction().equals(android.accounts.AccountManager.ACTION_AUTHENTICATOR_INTENT)) { + return getAuthenticator().getIBinder(); + } + return null; } private SyncAccountAuthenticator getAuthenticator() { @@ -82,8 +81,7 @@ public class SyncAuthenticatorService extends Service { return sAccountAuthenticator; } - private static class SyncAccountAuthenticator extends - AbstractAccountAuthenticator { + private static class SyncAccountAuthenticator extends AbstractAccountAuthenticator { private Context mContext; public SyncAccountAuthenticator(Context context) { super(context); @@ -94,10 +92,10 @@ public class SyncAuthenticatorService extends Service { public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException { - Log.d(LOG_TAG, "addAccount()"); + Logger.debug(LOG_TAG, "addAccount()"); final Intent intent = new Intent(mContext, SetupSyncActivity.class); intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, - response); + response); intent.putExtra("accountType", Constants.ACCOUNTTYPE_SYNC); intent.putExtra(Constants.INTENT_EXTRA_IS_SETUP, true); @@ -109,15 +107,16 @@ public class SyncAuthenticatorService extends Service { @Override public Bundle confirmCredentials(AccountAuthenticatorResponse response, - Account account, Bundle options) throws NetworkErrorException { - Log.d(LOG_TAG, "confirmCredentials()"); + Account account, + Bundle options) throws NetworkErrorException { + Logger.debug(LOG_TAG, "confirmCredentials()"); return null; } @Override public Bundle editProperties(AccountAuthenticatorResponse response, - String accountType) { - Log.d(LOG_TAG, "editProperties"); + String accountType) { + Logger.debug(LOG_TAG, "editProperties"); return null; } @@ -125,7 +124,7 @@ public class SyncAuthenticatorService extends Service { public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException { - Log.d(LOG_TAG, "getAuthToken()"); + Logger.debug(LOG_TAG, "getAuthToken()"); if (!authTokenType.equals(Constants.AUTHTOKEN_TYPE_PLAIN)) { final Bundle result = new Bundle(); result.putString(AccountManager.KEY_ERROR_MESSAGE, @@ -135,7 +134,7 @@ public class SyncAuthenticatorService extends Service { // Extract the username and password from the Account Manager, and ask // the server for an appropriate AuthToken. - Log.d(LOG_TAG, "AccountManager.get(" + mContext + ")"); + Logger.info(LOG_TAG, "AccountManager.get(" + mContext + ")"); final AccountManager am = AccountManager.get(mContext); final String password = am.getPassword(account); if (password != null) { @@ -154,7 +153,8 @@ public class SyncAuthenticatorService extends Service { // Username after hashing. try { String username = KeyBundle.usernameFromAccount(account.name); - Log.i("rnewman", "Account " + account.name + " hashes to " + username); + Logger.pii(LOG_TAG, "Account " + account.name + " hashes to " + username); + Logger.info(LOG_TAG, "Setting username. Null?" + (username == null)); result.putString(Constants.OPTION_USERNAME, username); } catch (NoSuchAlgorithmException e) { // Do nothing. Calling code must check for missing value. @@ -164,27 +164,27 @@ public class SyncAuthenticatorService extends Service { // Sync key. final String syncKey = am.getUserData(account, Constants.OPTION_SYNCKEY); - Log.i("rnewman", "Setting Sync Key to " + syncKey); + Logger.info(LOG_TAG, "Setting Sync Key. Null? " + (syncKey == null)); result.putString(Constants.OPTION_SYNCKEY, syncKey); // Password. result.putString(AccountManager.KEY_AUTHTOKEN, password); return result; } - Log.w(LOG_TAG, "Returning null bundle for getAuthToken."); + Logger.warn(LOG_TAG, "Returning null bundle for getAuthToken."); return null; } @Override public String getAuthTokenLabel(String authTokenType) { - Log.d(LOG_TAG, "getAuthTokenLabel()"); + Logger.debug(LOG_TAG, "getAuthTokenLabel()"); return null; } @Override public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException { - Log.d(LOG_TAG, "hasFeatures()"); + Logger.debug(LOG_TAG, "hasFeatures()"); return null; } @@ -192,7 +192,7 @@ public class SyncAuthenticatorService extends Service { public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException { - Log.d(LOG_TAG, "updateCredentials()"); + Logger.debug(LOG_TAG, "updateCredentials()"); return null; } } From 2480460fdebd186e13ae41176b6133e1e635ea3f Mon Sep 17 00:00:00 2001 From: Nick Alexander Date: Wed, 15 Feb 2012 22:05:53 -0800 Subject: [PATCH 13/93] Bug 709408 - Part 1: Remove SyncCryptographer. r=rnewman --- mobile/android/base/sync/Logger.java | 2 +- .../cryptographer/CryptoStatusBundle.java | 75 ---- .../sync/cryptographer/SyncCryptographer.java | 370 ------------------ .../base/sync/jpake/Gx4IsOneException.java | 42 -- .../android/base/sync/jpake/JPakeUtils.java | 50 --- .../AndroidBrowserHistoryServerSyncStage.java | 2 +- mobile/android/sync/java-sources.mn | 2 +- 7 files changed, 3 insertions(+), 540 deletions(-) delete mode 100644 mobile/android/base/sync/cryptographer/CryptoStatusBundle.java delete mode 100644 mobile/android/base/sync/cryptographer/SyncCryptographer.java delete mode 100644 mobile/android/base/sync/jpake/Gx4IsOneException.java delete mode 100644 mobile/android/base/sync/jpake/JPakeUtils.java diff --git a/mobile/android/base/sync/Logger.java b/mobile/android/base/sync/Logger.java index d46542cfedc7..a41fd220dce0 100644 --- a/mobile/android/base/sync/Logger.java +++ b/mobile/android/base/sync/Logger.java @@ -43,7 +43,7 @@ public class Logger { isWarnLoggable = new IdentityHashMap(); isInfoLoggable = new IdentityHashMap(); isDebugLoggable = new IdentityHashMap(); - isVerboseLoggable = new IdentityHashMap(); + isVerboseLoggable = new IdentityHashMap(); } private static boolean shouldLogError(String logTag) { diff --git a/mobile/android/base/sync/cryptographer/CryptoStatusBundle.java b/mobile/android/base/sync/cryptographer/CryptoStatusBundle.java deleted file mode 100644 index d06cb257f9cd..000000000000 --- a/mobile/android/base/sync/cryptographer/CryptoStatusBundle.java +++ /dev/null @@ -1,75 +0,0 @@ -/* ***** 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 Android Sync Client. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Jason Voll - * - * 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.sync.cryptographer; - -public class CryptoStatusBundle { - - public enum CryptoStatus { - OK, - MISSING_KEYS, - HMAC_VERIFY_FAIL, - INVALID_JSON, - INVALID_KEYS_BUNDLE, - MISSING_SYNCKEY_OR_USER - } - - private CryptoStatus status; - private String json; - - public CryptoStatusBundle (CryptoStatus status, String json) { - this.setStatus(status); - this.setJson(json); - } - - public CryptoStatus getStatus() { - return status; - } - - public void setStatus(CryptoStatus status) { - this.status = status; - } - - public String getJson() { - return json; - } - - public void setJson(String json) { - this.json = json; - } - -} diff --git a/mobile/android/base/sync/cryptographer/SyncCryptographer.java b/mobile/android/base/sync/cryptographer/SyncCryptographer.java deleted file mode 100644 index b9530549ae84..000000000000 --- a/mobile/android/base/sync/cryptographer/SyncCryptographer.java +++ /dev/null @@ -1,370 +0,0 @@ -/* ***** 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 Android Sync Client. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Jason Voll - * Richard Newman - * - * 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.sync.cryptographer; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringReader; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; - -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.mozilla.apache.commons.codec.binary.Base64; -import org.mozilla.gecko.sync.ExtendedJSONObject; -import org.mozilla.gecko.sync.Utils; -import org.mozilla.gecko.sync.crypto.CryptoException; -import org.mozilla.gecko.sync.crypto.CryptoInfo; -import org.mozilla.gecko.sync.crypto.Cryptographer; -import org.mozilla.gecko.sync.crypto.KeyBundle; -import org.mozilla.gecko.sync.cryptographer.CryptoStatusBundle.CryptoStatus; -import java.security.GeneralSecurityException; - -/* - * This class acts as a wrapper for the Cryptographer class. - * The goal here is to take care of all JSON parsing and BaseXX - * encoding/decoding so that the Cryptographer class doesn't need - * to know anything about the format of the original data. It also - * enables classes to get crypto services based on a WBO, rather than - * having to parse JSON themselves. - * - * This class decouples the Cryptographer from the Sync client. - */ -public class SyncCryptographer { - - // JSON related constants. - private static final String KEY_CIPHER_TEXT = "ciphertext"; - private static final String KEY_HMAC = "hmac"; - private static final String KEY_IV = "IV"; - private static final String KEY_PAYLOAD = "payload"; - private static final String KEY_ID = "id"; - private static final String KEY_COLLECTION = "collection"; - private static final String KEY_COLLECTIONS = "collections"; - private static final String KEY_DEFAULT_COLLECTION = "default"; - - private static final String ID_CRYPTO_KEYS = "keys"; - private static final String CRYPTO_KEYS_COLLECTION = "crypto"; - - public String syncKey; - private String username; - private KeyBundle keys; - - /* - * Constructors. - */ - public SyncCryptographer(String username) throws UnsupportedEncodingException { - this(username, "", "", ""); - } - - public SyncCryptographer(String username, String friendlyBase32SyncKey) throws UnsupportedEncodingException { - this(username, friendlyBase32SyncKey, "", ""); - } - - public SyncCryptographer(String username, String friendlyBase32SyncKey, - String base64EncryptionKey, String base64HmacKey) throws UnsupportedEncodingException { - this.setUsername(username); - this.syncKey = friendlyBase32SyncKey; - this.setKeys(base64EncryptionKey, base64HmacKey); - } - - /* - * Same as above...but for JSONArray - */ - @SuppressWarnings("unchecked") - private static final ArrayList asAList(JSONArray j) { - return j; - } - - /* - * Input: A string representation of a WBO (JSON) payload to be encrypted. - * Output: CryptoStatusBundle with a JSON payload containing - * crypto information (ciphertext, IV, HMAC). - */ - public CryptoStatusBundle encryptWBO(String jsonString) throws CryptoException { - // Verify that encryption keys are set. - if (keys == null) { - return new CryptoStatusBundle(CryptoStatus.MISSING_KEYS, jsonString); - } - return encrypt(jsonString, keys); - } - - /* - * Input: A string representation of the WBO (JSON). - * Output: the decrypted payload and status. - */ - public CryptoStatusBundle decryptWBO(String jsonString) throws CryptoException, UnsupportedEncodingException { - // Get JSON from string. - JSONObject json = null; - JSONObject payload = null; - try { - json = getJSONObject(jsonString); - payload = getJSONObject(json, KEY_PAYLOAD); - - } catch (Exception e) { - return new CryptoStatusBundle(CryptoStatus.INVALID_JSON, jsonString); - } - - // Check that payload contains all pieces for crypto. - if (!payload.containsKey(KEY_CIPHER_TEXT) || - !payload.containsKey(KEY_IV) || - !payload.containsKey(KEY_HMAC)) { - return new CryptoStatusBundle(CryptoStatus.INVALID_JSON, jsonString); - } - - String id = (String) json.get(KEY_ID); - if (id.equalsIgnoreCase(ID_CRYPTO_KEYS)) { - // If this is a crypto keys bundle, handle it separately. - return decryptKeysWBO(payload); - } else if (keys == null) { - // Otherwise, make sure we have crypto keys before continuing. - return new CryptoStatusBundle(CryptoStatus.MISSING_KEYS, jsonString); - } - - byte[] clearText = decryptPayload(payload, this.keys); - return new CryptoStatusBundle(CryptoStatus.OK, new String(clearText)); - } - - /* - * Handles the case where we are decrypting the crypto/keys bundle. - * Uses the sync key and username to get keys for decrypting this - * bundle. Once bundle is decrypted the keys are saved to this - * object for future use and the decrypted payload is returned. - * - * Input: JSONObject payload containing crypto/keys JSON. - * Output: Decrypted crypto/keys String. - */ - private CryptoStatusBundle decryptKeysWBO(JSONObject payload) throws CryptoException, UnsupportedEncodingException { - // Get the keys to decrypt the crypto keys bundle. - KeyBundle cryptoKeysBundleKeys; - try { - cryptoKeysBundleKeys = getCryptoKeysBundleKeys(); - } catch (Exception e) { - return new CryptoStatusBundle(CryptoStatus.MISSING_SYNCKEY_OR_USER, payload.toString()); - } - - byte[] cryptoKeysBundle = decryptPayload(payload, cryptoKeysBundleKeys); - - // Extract decrypted keys. - InputStream stream = new ByteArrayInputStream(cryptoKeysBundle); - Reader in = new InputStreamReader(stream); - JSONObject json = null; - try { - json = (JSONObject) new JSONParser().parse(in); - } catch (Exception e) { - e.printStackTrace(); - } - - if (json == null) { - throw new CryptoException(new GeneralSecurityException("Could not decrypt JSON payload")); - } - - // Verify that this is indeed the crypto/keys bundle and that - // decryption worked. - String id = (String) json.get(KEY_ID); - String collection = (String) json.get(KEY_COLLECTION); - - if (id.equalsIgnoreCase(ID_CRYPTO_KEYS) && - collection.equalsIgnoreCase(CRYPTO_KEYS_COLLECTION) && - json.containsKey(KEY_DEFAULT_COLLECTION)) { - - // Extract the keys and add them to this. - Object jsonKeysObj = json.get(KEY_DEFAULT_COLLECTION); - if (jsonKeysObj.getClass() != JSONArray.class) { - return new CryptoStatusBundle(CryptoStatus.INVALID_KEYS_BUNDLE, - json.toString()); - } - - JSONArray jsonKeys = (JSONArray) jsonKeysObj; - this.setKeys((String) jsonKeys.get(0), (String) jsonKeys.get(1)); - - // Return the string containing the decrypted payload. - return new CryptoStatusBundle(CryptoStatus.OK, - new String(cryptoKeysBundle)); - } else { - return new CryptoStatusBundle(CryptoStatus.INVALID_KEYS_BUNDLE, - json.toString()); - } - } - - /** - * Generates new encryption keys and creates the crypto/keys - * payload, encrypted using Sync Key. - * - * @return The crypto/keys payload encrypted for sending to - * the server. - * @throws CryptoException - * @throws UnsupportedEncodingException - */ - public CryptoStatusBundle generateCryptoKeysWBOPayload() throws CryptoException, UnsupportedEncodingException { - - // Generate the keys and save for later use. - KeyBundle cryptoKeys = Cryptographer.generateKeys(); - setKeys(new String(Base64.encodeBase64(cryptoKeys.getEncryptionKey())), - new String(Base64.encodeBase64(cryptoKeys.getHMACKey()))); - - // Generate JSON. - JSONArray keysArray = new JSONArray(); - asAList(keysArray).add(new String(Base64.encodeBase64(cryptoKeys.getEncryptionKey()))); - asAList(keysArray).add(new String(Base64.encodeBase64(cryptoKeys.getHMACKey()))); - ExtendedJSONObject json = new ExtendedJSONObject(); - json.put(KEY_ID, ID_CRYPTO_KEYS); - json.put(KEY_COLLECTION, CRYPTO_KEYS_COLLECTION); - json.put(KEY_COLLECTIONS, "{}"); - json.put(KEY_DEFAULT_COLLECTION, keysArray); - - // Get the keys to encrypt the crypto/keys bundle. - KeyBundle cryptoKeysBundleKeys; - try { - cryptoKeysBundleKeys = getCryptoKeysBundleKeys(); - } catch (Exception e) { - return new CryptoStatusBundle(CryptoStatus.MISSING_SYNCKEY_OR_USER, ""); - } - - return encrypt(json.toString(), cryptoKeysBundleKeys); - } - - /////////////////////// HELPERS ///////////////////////////// - - /* - * Helper method for doing actual encryption. - * - * Input: Message to encrypt, Keys for encryption/hmac - * Output: CryptoStatusBundle with a JSON payload containing - * crypto information (ciphertext, iv, hmac). - */ - private CryptoStatusBundle encrypt(String message, KeyBundle keys) throws CryptoException { - CryptoInfo encrypted = Cryptographer.encrypt(new CryptoInfo(message.getBytes(), keys)); - String payload = createJSONBundle(encrypted); - return new CryptoStatusBundle(CryptoStatus.OK, payload); - } - - /** - * Helper method for doing actual decryption. - * - * Input: JSONObject containing a valid payload (cipherText, IV, HMAC), - * KeyBundle with keys for decryption. - * Output: byte[] clearText - * @throws CryptoException - * @throws UnsupportedEncodingException - */ - private byte[] decryptPayload(JSONObject payload, KeyBundle keybundle) throws CryptoException, UnsupportedEncodingException { - byte[] clearText = Cryptographer.decrypt( - new CryptoInfo ( - Base64.decodeBase64(((String) payload.get(KEY_CIPHER_TEXT)).getBytes("UTF-8")), - Base64.decodeBase64(((String) payload.get(KEY_IV)).getBytes("UTF-8")), - Utils.hex2Byte( (String) payload.get(KEY_HMAC) ), - keybundle - ) - ); - - return clearText; - } - - /** - * Helper method to get a JSONObject from a String. - * Input: String containing JSON. - * Output: Extracted JSONObject. - * Throws: Exception if JSON is invalid. - */ - private JSONObject getJSONObject(String jsonString) throws Exception { - Reader in = new StringReader(jsonString); - try { - return (JSONObject) new JSONParser().parse(in); - } catch (Exception e) { - throw e; - } - } - - /** - * Helper method for extracting a JSONObject - * from within another JSONObject. - * - * Input: JSONObject and key. - * Output: JSONObject extracted. - * Throws: Exception if JSON is invalid. - */ - private JSONObject getJSONObject(JSONObject json, String key) throws Exception { - try { - return getJSONObject((String) json.get(key)); - } catch (Exception e) { - throw e; - } - } - - /* - * Helper to create JSON bundle for encrypted objects. - */ - private String createJSONBundle(CryptoInfo info) { - ExtendedJSONObject json = new ExtendedJSONObject(); - json.put(KEY_CIPHER_TEXT, new String(Base64.encodeBase64(info.getMessage()))); - json.put(KEY_IV, new String(Base64.encodeBase64(info.getIV()))); - json.put(KEY_HMAC, Utils.byte2hex(info.getHMAC())); - return json.toString(); - } - - /* - * Get the keys needed to encrypt the crypto/keys bundle. - */ - public KeyBundle getCryptoKeysBundleKeys() throws CryptoException { - return new KeyBundle(username, syncKey); - } - - public KeyBundle getKeys() { - return keys; - } - - /* - * Input: Base64 encoded encryption and HMAC keys. - */ - public void setKeys(String base64EncryptionKey, String base64HmacKey) throws UnsupportedEncodingException { - this.keys = new KeyBundle(Base64.decodeBase64(base64EncryptionKey.getBytes("UTF-8")), - Base64.decodeBase64(base64HmacKey.getBytes("UTF-8"))); - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } -} diff --git a/mobile/android/base/sync/jpake/Gx4IsOneException.java b/mobile/android/base/sync/jpake/Gx4IsOneException.java deleted file mode 100644 index e23ab7efc3cf..000000000000 --- a/mobile/android/base/sync/jpake/Gx4IsOneException.java +++ /dev/null @@ -1,42 +0,0 @@ -/* ***** 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 Android Sync Client. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Chenxia Liu - * - * 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.sync.jpake; - -public class Gx4IsOneException extends Exception { - private static final long serialVersionUID = 815366241052296473L; -} diff --git a/mobile/android/base/sync/jpake/JPakeUtils.java b/mobile/android/base/sync/jpake/JPakeUtils.java deleted file mode 100644 index 2b862eb7e6f2..000000000000 --- a/mobile/android/base/sync/jpake/JPakeUtils.java +++ /dev/null @@ -1,50 +0,0 @@ -/* ***** 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 Android Sync Client. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Chenxia Liu - * - * 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.sync.jpake; - -import java.util.Random; - -public class JPakeUtils { - - public static byte[] generateRandomBytes(int length) { - byte[] bytes = new byte[length]; - Random random = new Random(System.nanoTime()); - random.nextBytes(bytes); - return bytes; - } -} diff --git a/mobile/android/base/sync/stage/AndroidBrowserHistoryServerSyncStage.java b/mobile/android/base/sync/stage/AndroidBrowserHistoryServerSyncStage.java index 769921264c61..ab52ff13060a 100644 --- a/mobile/android/base/sync/stage/AndroidBrowserHistoryServerSyncStage.java +++ b/mobile/android/base/sync/stage/AndroidBrowserHistoryServerSyncStage.java @@ -85,4 +85,4 @@ public class AndroidBrowserHistoryServerSyncStage extends ServerSyncStage { protected RecordFactory getRecordFactory() { return new HistoryRecordFactory(); } -} +} \ No newline at end of file diff --git a/mobile/android/sync/java-sources.mn b/mobile/android/sync/java-sources.mn index 94563c79ff6d..a967fd434308 100644 --- a/mobile/android/sync/java-sources.mn +++ b/mobile/android/sync/java-sources.mn @@ -1 +1 @@ -sync/AlreadySyncingException.java sync/CollectionKeys.java sync/CredentialsSource.java sync/crypto/CryptoException.java sync/crypto/Cryptographer.java sync/crypto/CryptoInfo.java sync/crypto/HKDF.java sync/crypto/HMACVerificationException.java sync/crypto/KeyBundle.java sync/crypto/MissingCryptoInputException.java sync/crypto/NoKeyBundleException.java sync/cryptographer/CryptoStatusBundle.java sync/cryptographer/SyncCryptographer.java sync/CryptoRecord.java sync/DelayedWorkTracker.java sync/delegates/FreshStartDelegate.java sync/delegates/GlobalSessionCallback.java sync/delegates/InfoCollectionsDelegate.java sync/delegates/KeyUploadDelegate.java sync/delegates/MetaGlobalDelegate.java sync/delegates/WipeServerDelegate.java sync/ExtendedJSONObject.java sync/GlobalSession.java sync/HTTPFailureException.java sync/InfoCollections.java sync/jpake/BigIntegerHelper.java sync/jpake/Gx3OrGx4IsZeroOrOneException.java sync/jpake/IncorrectZkpException.java sync/jpake/JPakeClient.java sync/jpake/JPakeCrypto.java sync/jpake/JPakeNoActivePairingException.java sync/jpake/JPakeNumGenerator.java sync/jpake/JPakeNumGeneratorRandom.java sync/jpake/JPakeParty.java sync/jpake/JPakeRequest.java sync/jpake/JPakeRequestDelegate.java sync/jpake/JPakeResponse.java sync/jpake/Zkp.java sync/Logger.java sync/MetaGlobal.java sync/MetaGlobalException.java sync/MetaGlobalMissingEnginesException.java sync/MetaGlobalNotSetException.java sync/middleware/Crypto5MiddlewareRepository.java sync/middleware/Crypto5MiddlewareRepositorySession.java sync/middleware/MiddlewareRepository.java sync/net/BaseResource.java sync/net/CompletedEntity.java sync/net/HandleProgressException.java sync/net/Resource.java sync/net/ResourceDelegate.java sync/net/SyncResourceDelegate.java sync/net/SyncResponse.java sync/net/SyncStorageCollectionRequest.java sync/net/SyncStorageCollectionRequestDelegate.java sync/net/SyncStorageRecordRequest.java sync/net/SyncStorageRequest.java sync/net/SyncStorageRequestDelegate.java sync/net/SyncStorageRequestIncrementalDelegate.java sync/net/SyncStorageResponse.java sync/net/TLSSocketFactory.java sync/net/WBOCollectionRequestDelegate.java sync/NoCollectionKeysSetException.java sync/NonArrayJSONException.java sync/NonObjectJSONException.java sync/PrefsSource.java sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java sync/repositories/android/AndroidBrowserBookmarksRepository.java sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java sync/repositories/android/AndroidBrowserHistoryDataAccessor.java sync/repositories/android/AndroidBrowserHistoryDataExtender.java sync/repositories/android/AndroidBrowserHistoryRepository.java sync/repositories/android/AndroidBrowserHistoryRepositorySession.java sync/repositories/android/AndroidBrowserPasswordsDataAccessor.java sync/repositories/android/AndroidBrowserPasswordsRepository.java sync/repositories/android/AndroidBrowserPasswordsRepositorySession.java sync/repositories/android/AndroidBrowserRepository.java sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java sync/repositories/android/AndroidBrowserRepositorySession.java sync/repositories/android/BrowserContract.java sync/repositories/android/PasswordColumns.java sync/repositories/android/RepoUtils.java sync/repositories/BookmarkNeedsReparentingException.java sync/repositories/BookmarksRepository.java sync/repositories/ConstrainedServer11Repository.java sync/repositories/delegates/DeferrableRepositorySessionCreationDelegate.java sync/repositories/delegates/DeferredRepositorySessionBeginDelegate.java sync/repositories/delegates/DeferredRepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/DeferredRepositorySessionFinishDelegate.java sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionBeginDelegate.java sync/repositories/delegates/RepositorySessionCleanDelegate.java sync/repositories/delegates/RepositorySessionCreationDelegate.java sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/RepositorySessionFinishDelegate.java sync/repositories/delegates/RepositorySessionGuidsSinceDelegate.java sync/repositories/delegates/RepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionWipeDelegate.java sync/repositories/domain/BookmarkRecord.java sync/repositories/domain/BookmarkRecordFactory.java sync/repositories/domain/HistoryRecord.java sync/repositories/domain/HistoryRecordFactory.java sync/repositories/domain/PasswordRecord.java sync/repositories/domain/Record.java sync/repositories/HashSetStoreTracker.java sync/repositories/HistoryRepository.java sync/repositories/IdentityRecordFactory.java sync/repositories/InactiveSessionException.java sync/repositories/InvalidBookmarkTypeException.java sync/repositories/InvalidRequestException.java sync/repositories/InvalidSessionTransitionException.java sync/repositories/MultipleRecordsForGuidException.java sync/repositories/NoGuidForIdException.java sync/repositories/NoStoreDelegateException.java sync/repositories/NullCursorException.java sync/repositories/ParentNotFoundException.java sync/repositories/ProfileDatabaseException.java sync/repositories/RecordFactory.java sync/repositories/RecordFilter.java sync/repositories/Repository.java sync/repositories/RepositorySession.java sync/repositories/RepositorySessionBundle.java sync/repositories/Server11Repository.java sync/repositories/Server11RepositorySession.java sync/repositories/StoreTracker.java sync/repositories/StoreTrackingRepositorySession.java sync/setup/activities/AccountActivity.java sync/setup/activities/SetupFailureActivity.java sync/setup/activities/SetupSuccessActivity.java sync/setup/activities/SetupSyncActivity.java sync/setup/Constants.java sync/setup/SyncAuthenticatorService.java sync/stage/AndroidBrowserBookmarksServerSyncStage.java sync/stage/AndroidBrowserHistoryServerSyncStage.java sync/stage/CheckPreconditionsStage.java sync/stage/CompletedStage.java sync/stage/EnsureClusterURLStage.java sync/stage/EnsureKeysStage.java sync/stage/FetchInfoCollectionsStage.java sync/stage/FetchMetaGlobalStage.java sync/stage/GlobalSyncStage.java sync/stage/NoSuchStageException.java sync/stage/NoSyncIDException.java sync/stage/ServerSyncStage.java sync/StubActivity.java sync/syncadapter/SyncAdapter.java sync/syncadapter/SyncService.java sync/SyncConfiguration.java sync/SyncConfigurationException.java sync/SyncException.java sync/synchronizer/ConcurrentRecordConsumer.java sync/synchronizer/RecordConsumer.java sync/synchronizer/RecordsChannel.java sync/synchronizer/RecordsChannelDelegate.java sync/synchronizer/RecordsConsumerDelegate.java sync/synchronizer/SerialRecordConsumer.java sync/synchronizer/SessionNotBegunException.java sync/synchronizer/Synchronizer.java sync/synchronizer/SynchronizerDelegate.java sync/synchronizer/SynchronizerSession.java sync/synchronizer/SynchronizerSessionDelegate.java sync/synchronizer/UnbundleError.java sync/synchronizer/UnexpectedSessionException.java sync/SynchronizerConfiguration.java sync/SynchronizerConfigurations.java sync/ThreadPool.java sync/UnexpectedJSONException.java sync/UnknownSynchronizerConfigurationVersionException.java sync/Utils.java +sync/AlreadySyncingException.java sync/CollectionKeys.java sync/CredentialsSource.java sync/crypto/CryptoException.java sync/crypto/Cryptographer.java sync/crypto/CryptoInfo.java sync/crypto/HKDF.java sync/crypto/HMACVerificationException.java sync/crypto/KeyBundle.java sync/crypto/MissingCryptoInputException.java sync/crypto/NoKeyBundleException.java sync/CryptoRecord.java sync/DelayedWorkTracker.java sync/delegates/FreshStartDelegate.java sync/delegates/GlobalSessionCallback.java sync/delegates/InfoCollectionsDelegate.java sync/delegates/KeyUploadDelegate.java sync/delegates/MetaGlobalDelegate.java sync/delegates/WipeServerDelegate.java sync/ExtendedJSONObject.java sync/GlobalSession.java sync/HTTPFailureException.java sync/InfoCollections.java sync/jpake/BigIntegerHelper.java sync/jpake/Gx3OrGx4IsZeroOrOneException.java sync/jpake/IncorrectZkpException.java sync/jpake/JPakeClient.java sync/jpake/JPakeCrypto.java sync/jpake/JPakeNoActivePairingException.java sync/jpake/JPakeNumGenerator.java sync/jpake/JPakeNumGeneratorRandom.java sync/jpake/JPakeParty.java sync/jpake/JPakeRequest.java sync/jpake/JPakeRequestDelegate.java sync/jpake/JPakeResponse.java sync/jpake/Zkp.java sync/Logger.java sync/MetaGlobal.java sync/MetaGlobalException.java sync/MetaGlobalMissingEnginesException.java sync/MetaGlobalNotSetException.java sync/middleware/Crypto5MiddlewareRepository.java sync/middleware/Crypto5MiddlewareRepositorySession.java sync/middleware/MiddlewareRepository.java sync/net/BaseResource.java sync/net/CompletedEntity.java sync/net/HandleProgressException.java sync/net/Resource.java sync/net/ResourceDelegate.java sync/net/SyncResourceDelegate.java sync/net/SyncResponse.java sync/net/SyncStorageCollectionRequest.java sync/net/SyncStorageCollectionRequestDelegate.java sync/net/SyncStorageRecordRequest.java sync/net/SyncStorageRequest.java sync/net/SyncStorageRequestDelegate.java sync/net/SyncStorageRequestIncrementalDelegate.java sync/net/SyncStorageResponse.java sync/net/TLSSocketFactory.java sync/net/WBOCollectionRequestDelegate.java sync/NoCollectionKeysSetException.java sync/NonArrayJSONException.java sync/NonObjectJSONException.java sync/PrefsSource.java sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java sync/repositories/android/AndroidBrowserBookmarksRepository.java sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java sync/repositories/android/AndroidBrowserHistoryDataAccessor.java sync/repositories/android/AndroidBrowserHistoryDataExtender.java sync/repositories/android/AndroidBrowserHistoryRepository.java sync/repositories/android/AndroidBrowserHistoryRepositorySession.java sync/repositories/android/AndroidBrowserPasswordsDataAccessor.java sync/repositories/android/AndroidBrowserPasswordsRepository.java sync/repositories/android/AndroidBrowserPasswordsRepositorySession.java sync/repositories/android/AndroidBrowserRepository.java sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java sync/repositories/android/AndroidBrowserRepositorySession.java sync/repositories/android/BrowserContract.java sync/repositories/android/PasswordColumns.java sync/repositories/android/RepoUtils.java sync/repositories/BookmarkNeedsReparentingException.java sync/repositories/BookmarksRepository.java sync/repositories/ConstrainedServer11Repository.java sync/repositories/delegates/DeferrableRepositorySessionCreationDelegate.java sync/repositories/delegates/DeferredRepositorySessionBeginDelegate.java sync/repositories/delegates/DeferredRepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/DeferredRepositorySessionFinishDelegate.java sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionBeginDelegate.java sync/repositories/delegates/RepositorySessionCleanDelegate.java sync/repositories/delegates/RepositorySessionCreationDelegate.java sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/RepositorySessionFinishDelegate.java sync/repositories/delegates/RepositorySessionGuidsSinceDelegate.java sync/repositories/delegates/RepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionWipeDelegate.java sync/repositories/domain/BookmarkRecord.java sync/repositories/domain/BookmarkRecordFactory.java sync/repositories/domain/HistoryRecord.java sync/repositories/domain/HistoryRecordFactory.java sync/repositories/domain/PasswordRecord.java sync/repositories/domain/Record.java sync/repositories/HashSetStoreTracker.java sync/repositories/HistoryRepository.java sync/repositories/IdentityRecordFactory.java sync/repositories/InactiveSessionException.java sync/repositories/InvalidBookmarkTypeException.java sync/repositories/InvalidRequestException.java sync/repositories/InvalidSessionTransitionException.java sync/repositories/MultipleRecordsForGuidException.java sync/repositories/NoGuidForIdException.java sync/repositories/NoStoreDelegateException.java sync/repositories/NullCursorException.java sync/repositories/ParentNotFoundException.java sync/repositories/ProfileDatabaseException.java sync/repositories/RecordFactory.java sync/repositories/RecordFilter.java sync/repositories/Repository.java sync/repositories/RepositorySession.java sync/repositories/RepositorySessionBundle.java sync/repositories/Server11Repository.java sync/repositories/Server11RepositorySession.java sync/repositories/StoreTracker.java sync/repositories/StoreTrackingRepositorySession.java sync/setup/activities/AccountActivity.java sync/setup/activities/SetupFailureActivity.java sync/setup/activities/SetupSuccessActivity.java sync/setup/activities/SetupSyncActivity.java sync/setup/Constants.java sync/setup/SyncAuthenticatorService.java sync/stage/AndroidBrowserBookmarksServerSyncStage.java sync/stage/AndroidBrowserHistoryServerSyncStage.java sync/stage/CheckPreconditionsStage.java sync/stage/CompletedStage.java sync/stage/EnsureClusterURLStage.java sync/stage/EnsureKeysStage.java sync/stage/FetchInfoCollectionsStage.java sync/stage/FetchMetaGlobalStage.java sync/stage/GlobalSyncStage.java sync/stage/NoSuchStageException.java sync/stage/NoSyncIDException.java sync/stage/ServerSyncStage.java sync/StubActivity.java sync/syncadapter/SyncAdapter.java sync/syncadapter/SyncService.java sync/SyncConfiguration.java sync/SyncConfigurationException.java sync/SyncException.java sync/synchronizer/ConcurrentRecordConsumer.java sync/synchronizer/RecordConsumer.java sync/synchronizer/RecordsChannel.java sync/synchronizer/RecordsChannelDelegate.java sync/synchronizer/RecordsConsumerDelegate.java sync/synchronizer/SerialRecordConsumer.java sync/synchronizer/SessionNotBegunException.java sync/synchronizer/Synchronizer.java sync/synchronizer/SynchronizerDelegate.java sync/synchronizer/SynchronizerSession.java sync/synchronizer/SynchronizerSessionDelegate.java sync/synchronizer/UnbundleError.java sync/synchronizer/UnexpectedSessionException.java sync/SynchronizerConfiguration.java sync/SynchronizerConfigurations.java sync/ThreadPool.java sync/UnexpectedJSONException.java sync/UnknownSynchronizerConfigurationVersionException.java sync/Utils.java From 4e1755a73982c65d9c7619823cb6b4fb903b65a5 Mon Sep 17 00:00:00 2001 From: Nick Alexander Date: Wed, 15 Feb 2012 22:05:53 -0800 Subject: [PATCH 14/93] Bug 709408 - Part 2: Remove Cryptographer. r=rnewman --- mobile/android/base/sync/CollectionKeys.java | 25 +- mobile/android/base/sync/CryptoRecord.java | 9 +- .../android/base/sync/crypto/CryptoInfo.java | 175 ++++++++++++++ .../base/sync/crypto/Cryptographer.java | 222 ------------------ .../android/base/sync/crypto/KeyBundle.java | 38 ++- .../android/base/sync/jpake/JPakeClient.java | 15 +- mobile/android/sync/java-sources.mn | 2 +- 7 files changed, 228 insertions(+), 258 deletions(-) delete mode 100644 mobile/android/base/sync/crypto/Cryptographer.java diff --git a/mobile/android/base/sync/CollectionKeys.java b/mobile/android/base/sync/CollectionKeys.java index dfd12275560b..8a8f0903c9fc 100644 --- a/mobile/android/base/sync/CollectionKeys.java +++ b/mobile/android/base/sync/CollectionKeys.java @@ -42,12 +42,11 @@ import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.Map.Entry; -import org.mozilla.apache.commons.codec.binary.Base64; import org.json.JSONException; import org.json.simple.JSONArray; import org.json.simple.parser.ParseException; +import org.mozilla.apache.commons.codec.binary.Base64; import org.mozilla.gecko.sync.crypto.CryptoException; -import org.mozilla.gecko.sync.crypto.Cryptographer; import org.mozilla.gecko.sync.crypto.KeyBundle; import android.util.Log; @@ -68,9 +67,16 @@ public class CollectionKeys { } } + /** + * Randomly generate a basic CollectionKeys object. + * @throws CryptoException + */ public static CollectionKeys generateCollectionKeys() throws CryptoException { CollectionKeys ck = new CollectionKeys(); - ck.populate(); + ck.clear(); + ck.defaultKeyBundle = KeyBundle.withRandomKeys(); + // TODO: eventually we would like to keep per-collection keys, just generate + // new ones as appropriate. return ck; } @@ -104,7 +110,7 @@ public class CollectionKeys { private static KeyBundle arrayToKeyBundle(JSONArray array) throws UnsupportedEncodingException { String encKeyStr = (String) array.get(0); String hmacKeyStr = (String) array.get(1); - return KeyBundle.decodeKeyStrings(encKeyStr, hmacKeyStr); + return KeyBundle.fromBase64EncodedKeys(encKeyStr, hmacKeyStr); } @SuppressWarnings("unchecked") @@ -204,15 +210,4 @@ public class CollectionKeys { this.defaultKeyBundle = null; this.collectionKeyBundles = new HashMap(); } - - /** - * Randomly generate a basic CollectionKeys object. - * @throws CryptoException - */ - public void populate() throws CryptoException { - this.clear(); - this.defaultKeyBundle = Cryptographer.generateKeys(); - // TODO: eventually we would like to keep per-collection keys, just generate - // new ones as appropriate. - } } diff --git a/mobile/android/base/sync/CryptoRecord.java b/mobile/android/base/sync/CryptoRecord.java index 912fb77417ff..e5dc6e6c841f 100644 --- a/mobile/android/base/sync/CryptoRecord.java +++ b/mobile/android/base/sync/CryptoRecord.java @@ -46,7 +46,6 @@ import org.json.simple.parser.ParseException; import org.mozilla.apache.commons.codec.binary.Base64; import org.mozilla.gecko.sync.crypto.CryptoException; import org.mozilla.gecko.sync.crypto.CryptoInfo; -import org.mozilla.gecko.sync.crypto.Cryptographer; import org.mozilla.gecko.sync.crypto.KeyBundle; import org.mozilla.gecko.sync.crypto.MissingCryptoInputException; import org.mozilla.gecko.sync.crypto.NoKeyBundleException; @@ -65,6 +64,8 @@ import org.mozilla.gecko.sync.repositories.domain.Record; * Until there's some benefit to the abstraction, we're simply going to * call this CryptoRecord. * + * CryptoRecord uses CryptoInfo to do the actual encryption and decryption. + * * @author rnewman * */ @@ -92,7 +93,8 @@ public class CryptoRecord extends Record { byte[] ciphertext = Base64.decodeBase64(((String) payload.get(KEY_CIPHERTEXT)).getBytes("UTF-8")); byte[] iv = Base64.decodeBase64(((String) payload.get(KEY_IV)).getBytes("UTF-8")); byte[] hmac = Utils.hex2Byte((String) payload.get(KEY_HMAC)); - return Cryptographer.decrypt(new CryptoInfo(ciphertext, iv, hmac, keybundle)); + + return CryptoInfo.decrypt(ciphertext, iv, hmac, keybundle).getMessage(); } // The encrypted JSON body object. @@ -221,8 +223,7 @@ public class CryptoRecord extends Record { } String cleartext = payload.toJSONString(); byte[] cleartextBytes = cleartext.getBytes("UTF-8"); - CryptoInfo info = new CryptoInfo(cleartextBytes, keyBundle); - Cryptographer.encrypt(info); + CryptoInfo info = CryptoInfo.encrypt(cleartextBytes, keyBundle); String message = new String(Base64.encodeBase64(info.getMessage())); String iv = new String(Base64.encodeBase64(info.getIV())); String hmac = Utils.byte2hex(info.getHMAC()); diff --git a/mobile/android/base/sync/crypto/CryptoInfo.java b/mobile/android/base/sync/crypto/CryptoInfo.java index eb38568dcb59..c3d17ff5316c 100644 --- a/mobile/android/base/sync/crypto/CryptoInfo.java +++ b/mobile/android/base/sync/crypto/CryptoInfo.java @@ -4,16 +4,61 @@ package org.mozilla.gecko.sync.crypto; +import java.security.GeneralSecurityException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.HashMap; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.Mac; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import org.mozilla.apache.commons.codec.binary.Base64; + /* * All info in these objects should be decoded (i.e. not BaseXX encoded). */ public class CryptoInfo { + private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding"; + private static final String KEY_ALGORITHM_SPEC = "AES"; private byte[] message; private byte[] iv; private byte[] hmac; private KeyBundle keys; + /** + * Return a CryptoInfo with given plaintext encrypted using given keys. + */ + public static CryptoInfo encrypt(byte[] plaintextBytes, KeyBundle keys) throws CryptoException { + CryptoInfo info = new CryptoInfo(plaintextBytes, keys); + info.encrypt(); + return info; + } + + /** + * Return a CryptoInfo with given plaintext encrypted using given keys and initial vector. + */ + public static CryptoInfo encrypt(byte[] plaintextBytes, byte[] iv, KeyBundle keys) throws CryptoException { + CryptoInfo info = new CryptoInfo(plaintextBytes, iv, null, keys); + info.encrypt(); + return info; + } + + /** + * Return a CryptoInfo with given ciphertext decrypted using given keys and initial vector, verifying that given HMAC validates. + */ + public static CryptoInfo decrypt(byte[] ciphertext, byte[] iv, byte[] hmac, KeyBundle keys) throws CryptoException { + CryptoInfo info = new CryptoInfo(ciphertext, iv, hmac, keys); + info.decrypt(); + return info; + } + /* * Constructor typically used when encrypting. */ @@ -63,4 +108,134 @@ public class CryptoInfo { public void setKeys(KeyBundle keys) { this.keys = keys; } + + /* + * Generate HMAC for given cipher text. + */ + public static byte[] generatedHMACFor(byte[] message, KeyBundle keys) throws NoSuchAlgorithmException, InvalidKeyException { + Mac hmacHasher = HKDF.makeHMACHasher(keys.getHMACKey()); + return hmacHasher.doFinal(Base64.encodeBase64(message)); + } + + /* + * Return true if generated HMAC is the same as the specified HMAC. + */ + public boolean generatedHMACIsHMAC() throws NoSuchAlgorithmException, InvalidKeyException { + byte[] generatedHMAC = generatedHMACFor(getMessage(), getKeys()); + byte[] expectedHMAC = getHMAC(); + return Arrays.equals(generatedHMAC, expectedHMAC); + } + + /** + * Performs functionality common to both encryption and decryption. + * + * @param cipher + * @param inputMessage non-BaseXX-encoded message + * @return encrypted/decrypted message + * @throws CryptoException + */ + private static byte[] commonCrypto(Cipher cipher, byte[] inputMessage) + throws CryptoException { + byte[] outputMessage = null; + try { + outputMessage = cipher.doFinal(inputMessage); + } catch (IllegalBlockSizeException e) { + throw new CryptoException(e); + } catch (BadPaddingException e) { + throw new CryptoException(e); + } + return outputMessage; + } + + /** + * Encrypt a CryptoInfo in-place. + * + * @throws CryptoException + */ + public void encrypt() throws CryptoException { + + Cipher cipher = CryptoInfo.getCipher(TRANSFORMATION); + try { + byte[] encryptionKey = getKeys().getEncryptionKey(); + SecretKeySpec spec = new SecretKeySpec(encryptionKey, KEY_ALGORITHM_SPEC); + + // If no IV is provided, we allow the cipher to provide one. + if (getIV() == null || getIV().length == 0) { + cipher.init(Cipher.ENCRYPT_MODE, spec); + } else { + cipher.init(Cipher.ENCRYPT_MODE, spec, new IvParameterSpec(getIV())); + } + } catch (GeneralSecurityException ex) { + throw new CryptoException(ex); + } + + // Encrypt. + byte[] encryptedBytes = commonCrypto(cipher, getMessage()); + byte[] iv = cipher.getIV(); + + byte[] hmac; + // Generate HMAC. + try { + hmac = generatedHMACFor(encryptedBytes, keys); + } catch (NoSuchAlgorithmException e) { + throw new CryptoException(e); + } catch (InvalidKeyException e) { + throw new CryptoException(e); + } + + // Update in place. keys is already set. + this.setHMAC(hmac); + this.setIV(iv); + this.setMessage(encryptedBytes); + } + + /** + * Decrypt a CryptoInfo in-place. + * + * @throws CryptoException + */ + public void decrypt() throws CryptoException { + + // Check HMAC. + try { + if (!generatedHMACIsHMAC()) { + throw new HMACVerificationException(); + } + } catch (NoSuchAlgorithmException e) { + throw new CryptoException(e); + } catch (InvalidKeyException e) { + throw new CryptoException(e); + } + + Cipher cipher = CryptoInfo.getCipher(TRANSFORMATION); + try { + byte[] encryptionKey = getKeys().getEncryptionKey(); + SecretKeySpec spec = new SecretKeySpec(encryptionKey, KEY_ALGORITHM_SPEC); + cipher.init(Cipher.DECRYPT_MODE, spec, new IvParameterSpec(getIV())); + } catch (GeneralSecurityException ex) { + throw new CryptoException(ex); + } + byte[] decryptedBytes = commonCrypto(cipher, getMessage()); + byte[] iv = cipher.getIV(); + + // Update in place. keys is already set. + this.setHMAC(null); + this.setIV(iv); + this.setMessage(decryptedBytes); + } + + /** + * Helper to get a Cipher object. + * + * @param transformation The type of Cipher to get. + */ + private static Cipher getCipher(String transformation) throws CryptoException { + try { + return Cipher.getInstance(transformation); + } catch (NoSuchAlgorithmException e) { + throw new CryptoException(e); + } catch (NoSuchPaddingException e) { + throw new CryptoException(e); + } + } } diff --git a/mobile/android/base/sync/crypto/Cryptographer.java b/mobile/android/base/sync/crypto/Cryptographer.java deleted file mode 100644 index f63fae9939ba..000000000000 --- a/mobile/android/base/sync/crypto/Cryptographer.java +++ /dev/null @@ -1,222 +0,0 @@ -/* ***** 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 Android Sync Client. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Jason Voll - * Richard Newman - * - * 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.sync.crypto; - -import java.security.GeneralSecurityException; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; - -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.KeyGenerator; -import javax.crypto.Mac; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; - -import org.mozilla.apache.commons.codec.binary.Base64; -import org.mozilla.gecko.sync.Utils; - -/* - * Implements the basic required cryptography options. - */ -public class Cryptographer { - - private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding"; - private static final String KEY_ALGORITHM_SPEC = "AES"; - private static final int KEY_SIZE = 256; - - public static CryptoInfo encrypt(CryptoInfo info) throws CryptoException { - - Cipher cipher = getCipher(); - try { - byte[] encryptionKey = info.getKeys().getEncryptionKey(); - SecretKeySpec spec = new SecretKeySpec(encryptionKey, KEY_ALGORITHM_SPEC); - - // If no IV is provided, we allow the cipher to provide one. - if (info.getIV() == null || - info.getIV().length == 0) { - cipher.init(Cipher.ENCRYPT_MODE, spec); - } else { - System.out.println("IV is " + info.getIV().length); - cipher.init(Cipher.ENCRYPT_MODE, spec, new IvParameterSpec(info.getIV())); - } - } catch (GeneralSecurityException ex) { - throw new CryptoException(ex); - } - - // Encrypt. - byte[] encryptedBytes = commonCrypto(cipher, info.getMessage()); - info.setMessage(encryptedBytes); - - // Save IV. - info.setIV(cipher.getIV()); - - // Generate HMAC. - try { - info.setHMAC(generateHMAC(info)); - } catch (NoSuchAlgorithmException e) { - throw new CryptoException(e); - } catch (InvalidKeyException e) { - throw new CryptoException(e); - } - - return info; - - } - - /* - * Perform a decryption. - * - * @argument info info bundle for decryption - * - * @return decrypted byte[] - * - * @throws CryptoException - */ - public static byte[] decrypt(CryptoInfo info) throws CryptoException { - - // Check HMAC. - try { - if (!verifyHMAC(info)) { - throw new HMACVerificationException(); - } - } catch (NoSuchAlgorithmException e) { - throw new CryptoException(e); - } catch (InvalidKeyException e) { - throw new CryptoException(e); - } - - Cipher cipher = getCipher(); - try { - byte[] encryptionKey = info.getKeys().getEncryptionKey(); - SecretKeySpec spec = new SecretKeySpec(encryptionKey, KEY_ALGORITHM_SPEC); - cipher.init(Cipher.DECRYPT_MODE, spec, new IvParameterSpec(info.getIV())); - } catch (GeneralSecurityException ex) { - ex.printStackTrace(); - throw new CryptoException(ex); - } - return commonCrypto(cipher, info.getMessage()); - } - - /* - * Make 2 random 256 bit keys (encryption and HMAC). - */ - public static KeyBundle generateKeys() throws CryptoException { - KeyGenerator keygen; - try { - keygen = KeyGenerator.getInstance(KEY_ALGORITHM_SPEC); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - throw new CryptoException(e); - } - - keygen.init(KEY_SIZE); - byte[] encryptionKey = keygen.generateKey().getEncoded(); - byte[] hmacKey = keygen.generateKey().getEncoded(); - return new KeyBundle(encryptionKey, hmacKey); - } - - /* - * Performs functionality common to both the encryption and decryption - * operations. - * - * Input: Cipher object, non-BaseXX-encoded byte[] input Output: - * encrypted/decrypted byte[] - */ - private static byte[] commonCrypto(Cipher cipher, byte[] inputMessage) - throws CryptoException { - byte[] outputMessage = null; - try { - outputMessage = cipher.doFinal(inputMessage); - } catch (IllegalBlockSizeException e) { - e.printStackTrace(); - throw new CryptoException(e); - } catch (BadPaddingException e) { - e.printStackTrace(); - throw new CryptoException(e); - } - return outputMessage; - } - - /* - * Helper to get a Cipher object. - * Input: None. - * Output: Cipher object. - */ - private static Cipher getCipher() throws CryptoException { - Cipher cipher = null; - try { - cipher = Cipher.getInstance(TRANSFORMATION); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - throw new CryptoException(e); - } catch (NoSuchPaddingException e) { - e.printStackTrace(); - throw new CryptoException(e); - } - return cipher; - } - - /* - * Helper to verify HMAC Input: CryptoInfo Output: true if HMAC is correct - */ - private static boolean verifyHMAC(CryptoInfo bundle) throws NoSuchAlgorithmException, InvalidKeyException { - byte[] generatedHMAC = generateHMAC(bundle); - byte[] expectedHMAC = bundle.getHMAC(); - boolean eq = Arrays.equals(generatedHMAC, expectedHMAC); - if (!eq) { - System.err.println("Failed HMAC verification."); - System.err.println("Expecting: " + Utils.byte2hex(generatedHMAC)); - System.err.println("Got: " + Utils.byte2hex(expectedHMAC)); - } - return eq; - } - - /* - * Helper to generate HMAC Input: CryptoInfo Output: a generated HMAC for - * given cipher text - */ - private static byte[] generateHMAC(CryptoInfo bundle) throws NoSuchAlgorithmException, InvalidKeyException { - Mac hmacHasher = HKDF.makeHMACHasher(bundle.getKeys().getHMACKey()); - return hmacHasher.doFinal(Base64.encodeBase64(bundle.getMessage())); - } -} diff --git a/mobile/android/base/sync/crypto/KeyBundle.java b/mobile/android/base/sync/crypto/KeyBundle.java index 6ad7b492f9ae..06a3256980ad 100644 --- a/mobile/android/base/sync/crypto/KeyBundle.java +++ b/mobile/android/base/sync/crypto/KeyBundle.java @@ -41,6 +41,7 @@ package org.mozilla.gecko.sync.crypto; import java.io.UnsupportedEncodingException; import java.security.NoSuchAlgorithmException; +import javax.crypto.KeyGenerator; import javax.crypto.Mac; import org.mozilla.apache.commons.codec.binary.Base64; @@ -49,6 +50,8 @@ import org.mozilla.gecko.sync.crypto.CryptoException; import java.security.InvalidKeyException; public class KeyBundle { + private static final String KEY_ALGORITHM_SPEC = "AES"; + private static final int KEY_SIZE = 256; private byte[] encryptionKey; private byte[] hmacKey; @@ -130,6 +133,36 @@ public class KeyBundle { this.setHMACKey(hmacKey); } + /** + * Make a KeyBundle with the specified base64-encoded keys. + * + * @return A KeyBundle with the specified keys. + */ + public static KeyBundle fromBase64EncodedKeys(String base64EncryptionKey, String base64HmacKey) throws UnsupportedEncodingException { + return new KeyBundle(Base64.decodeBase64(base64EncryptionKey.getBytes("UTF-8")), + Base64.decodeBase64(base64HmacKey.getBytes("UTF-8"))); + } + + /** + * Make a KeyBundle with two random 256 bit keys (encryption and HMAC). + * + * @return A KeyBundle with random keys. + */ + public static KeyBundle withRandomKeys() throws CryptoException { + KeyGenerator keygen; + try { + keygen = KeyGenerator.getInstance(KEY_ALGORITHM_SPEC); + } catch (NoSuchAlgorithmException e) { + throw new CryptoException(e); + } + + keygen.init(KEY_SIZE); + byte[] encryptionKey = keygen.generateKey().getEncoded(); + byte[] hmacKey = keygen.generateKey().getEncoded(); + + return new KeyBundle(encryptionKey, hmacKey); + } + public byte[] getEncryptionKey() { return encryptionKey; } @@ -145,9 +178,4 @@ public class KeyBundle { public void setHMACKey(byte[] hmacKey) { this.hmacKey = hmacKey; } - - public static KeyBundle decodeKeyStrings(String base64EncryptionKey, String base64HmacKey) throws UnsupportedEncodingException { - return new KeyBundle(Base64.decodeBase64(base64EncryptionKey.getBytes("UTF-8")), - Base64.decodeBase64(base64HmacKey.getBytes("UTF-8"))); - } } diff --git a/mobile/android/base/sync/jpake/JPakeClient.java b/mobile/android/base/sync/jpake/JPakeClient.java index 62c75d05aa16..5f7d766e6525 100644 --- a/mobile/android/base/sync/jpake/JPakeClient.java +++ b/mobile/android/base/sync/jpake/JPakeClient.java @@ -60,7 +60,6 @@ import org.mozilla.gecko.sync.ThreadPool; import org.mozilla.gecko.sync.Utils; import org.mozilla.gecko.sync.crypto.CryptoException; import org.mozilla.gecko.sync.crypto.CryptoInfo; -import org.mozilla.gecko.sync.crypto.Cryptographer; import org.mozilla.gecko.sync.crypto.KeyBundle; import org.mozilla.gecko.sync.crypto.NoKeyBundleException; import org.mozilla.gecko.sync.net.ResourceDelegate; @@ -553,11 +552,8 @@ public class JPakeClient implements JPakeRequestDelegate { public boolean verifyCiphertext(String theirCiphertext, String iv, KeyBundle keyBundle) throws UnsupportedEncodingException, CryptoException { byte[] cleartextBytes = JPAKE_VERIFY_VALUE.getBytes("UTF-8"); - CryptoInfo info = new CryptoInfo(cleartextBytes, keyBundle); - info.setIV(Base64.decodeBase64(iv)); - - Cryptographer.encrypt(info); - String myCiphertext = new String(Base64.encodeBase64(info.getMessage())); + CryptoInfo encrypted = CryptoInfo.encrypt(cleartextBytes, Base64.decodeBase64(iv), keyBundle); + String myCiphertext = new String(Base64.encodeBase64(encrypted.getMessage())); return myCiphertext.equals(theirCiphertext); } @@ -1221,9 +1217,7 @@ public class JPakeClient implements JPakeRequestDelegate { .get(Constants.JSON_KEY_CIPHERTEXT)); byte[] iv = Utils.decodeBase64((String) payload.get(Constants.JSON_KEY_IV)); byte[] hmac = Utils.hex2Byte((String) payload.get(Constants.JSON_KEY_HMAC)); - byte[] plainbytes = Cryptographer.decrypt(new CryptoInfo(ciphertext, iv, - hmac, keybundle)); - return plainbytes; + return CryptoInfo.decrypt(ciphertext, iv, hmac, keybundle).getMessage(); } /** @@ -1242,8 +1236,7 @@ public class JPakeClient implements JPakeRequestDelegate { throw new NoKeyBundleException(); } byte[] cleartextBytes = data.getBytes("UTF-8"); - CryptoInfo info = new CryptoInfo(cleartextBytes, keyBundle); - Cryptographer.encrypt(info); + CryptoInfo info = CryptoInfo.encrypt(cleartextBytes, keyBundle); String message = new String(Base64.encodeBase64(info.getMessage())); String iv = new String(Base64.encodeBase64(info.getIV())); diff --git a/mobile/android/sync/java-sources.mn b/mobile/android/sync/java-sources.mn index a967fd434308..a66c67344660 100644 --- a/mobile/android/sync/java-sources.mn +++ b/mobile/android/sync/java-sources.mn @@ -1 +1 @@ -sync/AlreadySyncingException.java sync/CollectionKeys.java sync/CredentialsSource.java sync/crypto/CryptoException.java sync/crypto/Cryptographer.java sync/crypto/CryptoInfo.java sync/crypto/HKDF.java sync/crypto/HMACVerificationException.java sync/crypto/KeyBundle.java sync/crypto/MissingCryptoInputException.java sync/crypto/NoKeyBundleException.java sync/CryptoRecord.java sync/DelayedWorkTracker.java sync/delegates/FreshStartDelegate.java sync/delegates/GlobalSessionCallback.java sync/delegates/InfoCollectionsDelegate.java sync/delegates/KeyUploadDelegate.java sync/delegates/MetaGlobalDelegate.java sync/delegates/WipeServerDelegate.java sync/ExtendedJSONObject.java sync/GlobalSession.java sync/HTTPFailureException.java sync/InfoCollections.java sync/jpake/BigIntegerHelper.java sync/jpake/Gx3OrGx4IsZeroOrOneException.java sync/jpake/IncorrectZkpException.java sync/jpake/JPakeClient.java sync/jpake/JPakeCrypto.java sync/jpake/JPakeNoActivePairingException.java sync/jpake/JPakeNumGenerator.java sync/jpake/JPakeNumGeneratorRandom.java sync/jpake/JPakeParty.java sync/jpake/JPakeRequest.java sync/jpake/JPakeRequestDelegate.java sync/jpake/JPakeResponse.java sync/jpake/Zkp.java sync/Logger.java sync/MetaGlobal.java sync/MetaGlobalException.java sync/MetaGlobalMissingEnginesException.java sync/MetaGlobalNotSetException.java sync/middleware/Crypto5MiddlewareRepository.java sync/middleware/Crypto5MiddlewareRepositorySession.java sync/middleware/MiddlewareRepository.java sync/net/BaseResource.java sync/net/CompletedEntity.java sync/net/HandleProgressException.java sync/net/Resource.java sync/net/ResourceDelegate.java sync/net/SyncResourceDelegate.java sync/net/SyncResponse.java sync/net/SyncStorageCollectionRequest.java sync/net/SyncStorageCollectionRequestDelegate.java sync/net/SyncStorageRecordRequest.java sync/net/SyncStorageRequest.java sync/net/SyncStorageRequestDelegate.java sync/net/SyncStorageRequestIncrementalDelegate.java sync/net/SyncStorageResponse.java sync/net/TLSSocketFactory.java sync/net/WBOCollectionRequestDelegate.java sync/NoCollectionKeysSetException.java sync/NonArrayJSONException.java sync/NonObjectJSONException.java sync/PrefsSource.java sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java sync/repositories/android/AndroidBrowserBookmarksRepository.java sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java sync/repositories/android/AndroidBrowserHistoryDataAccessor.java sync/repositories/android/AndroidBrowserHistoryDataExtender.java sync/repositories/android/AndroidBrowserHistoryRepository.java sync/repositories/android/AndroidBrowserHistoryRepositorySession.java sync/repositories/android/AndroidBrowserPasswordsDataAccessor.java sync/repositories/android/AndroidBrowserPasswordsRepository.java sync/repositories/android/AndroidBrowserPasswordsRepositorySession.java sync/repositories/android/AndroidBrowserRepository.java sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java sync/repositories/android/AndroidBrowserRepositorySession.java sync/repositories/android/BrowserContract.java sync/repositories/android/PasswordColumns.java sync/repositories/android/RepoUtils.java sync/repositories/BookmarkNeedsReparentingException.java sync/repositories/BookmarksRepository.java sync/repositories/ConstrainedServer11Repository.java sync/repositories/delegates/DeferrableRepositorySessionCreationDelegate.java sync/repositories/delegates/DeferredRepositorySessionBeginDelegate.java sync/repositories/delegates/DeferredRepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/DeferredRepositorySessionFinishDelegate.java sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionBeginDelegate.java sync/repositories/delegates/RepositorySessionCleanDelegate.java sync/repositories/delegates/RepositorySessionCreationDelegate.java sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/RepositorySessionFinishDelegate.java sync/repositories/delegates/RepositorySessionGuidsSinceDelegate.java sync/repositories/delegates/RepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionWipeDelegate.java sync/repositories/domain/BookmarkRecord.java sync/repositories/domain/BookmarkRecordFactory.java sync/repositories/domain/HistoryRecord.java sync/repositories/domain/HistoryRecordFactory.java sync/repositories/domain/PasswordRecord.java sync/repositories/domain/Record.java sync/repositories/HashSetStoreTracker.java sync/repositories/HistoryRepository.java sync/repositories/IdentityRecordFactory.java sync/repositories/InactiveSessionException.java sync/repositories/InvalidBookmarkTypeException.java sync/repositories/InvalidRequestException.java sync/repositories/InvalidSessionTransitionException.java sync/repositories/MultipleRecordsForGuidException.java sync/repositories/NoGuidForIdException.java sync/repositories/NoStoreDelegateException.java sync/repositories/NullCursorException.java sync/repositories/ParentNotFoundException.java sync/repositories/ProfileDatabaseException.java sync/repositories/RecordFactory.java sync/repositories/RecordFilter.java sync/repositories/Repository.java sync/repositories/RepositorySession.java sync/repositories/RepositorySessionBundle.java sync/repositories/Server11Repository.java sync/repositories/Server11RepositorySession.java sync/repositories/StoreTracker.java sync/repositories/StoreTrackingRepositorySession.java sync/setup/activities/AccountActivity.java sync/setup/activities/SetupFailureActivity.java sync/setup/activities/SetupSuccessActivity.java sync/setup/activities/SetupSyncActivity.java sync/setup/Constants.java sync/setup/SyncAuthenticatorService.java sync/stage/AndroidBrowserBookmarksServerSyncStage.java sync/stage/AndroidBrowserHistoryServerSyncStage.java sync/stage/CheckPreconditionsStage.java sync/stage/CompletedStage.java sync/stage/EnsureClusterURLStage.java sync/stage/EnsureKeysStage.java sync/stage/FetchInfoCollectionsStage.java sync/stage/FetchMetaGlobalStage.java sync/stage/GlobalSyncStage.java sync/stage/NoSuchStageException.java sync/stage/NoSyncIDException.java sync/stage/ServerSyncStage.java sync/StubActivity.java sync/syncadapter/SyncAdapter.java sync/syncadapter/SyncService.java sync/SyncConfiguration.java sync/SyncConfigurationException.java sync/SyncException.java sync/synchronizer/ConcurrentRecordConsumer.java sync/synchronizer/RecordConsumer.java sync/synchronizer/RecordsChannel.java sync/synchronizer/RecordsChannelDelegate.java sync/synchronizer/RecordsConsumerDelegate.java sync/synchronizer/SerialRecordConsumer.java sync/synchronizer/SessionNotBegunException.java sync/synchronizer/Synchronizer.java sync/synchronizer/SynchronizerDelegate.java sync/synchronizer/SynchronizerSession.java sync/synchronizer/SynchronizerSessionDelegate.java sync/synchronizer/UnbundleError.java sync/synchronizer/UnexpectedSessionException.java sync/SynchronizerConfiguration.java sync/SynchronizerConfigurations.java sync/ThreadPool.java sync/UnexpectedJSONException.java sync/UnknownSynchronizerConfigurationVersionException.java sync/Utils.java +sync/AlreadySyncingException.java sync/CollectionKeys.java sync/CredentialsSource.java sync/crypto/CryptoException.java sync/crypto/CryptoInfo.java sync/crypto/HKDF.java sync/crypto/HMACVerificationException.java sync/crypto/KeyBundle.java sync/crypto/MissingCryptoInputException.java sync/crypto/NoKeyBundleException.java sync/CryptoRecord.java sync/DelayedWorkTracker.java sync/delegates/FreshStartDelegate.java sync/delegates/GlobalSessionCallback.java sync/delegates/InfoCollectionsDelegate.java sync/delegates/KeyUploadDelegate.java sync/delegates/MetaGlobalDelegate.java sync/delegates/WipeServerDelegate.java sync/ExtendedJSONObject.java sync/GlobalSession.java sync/HTTPFailureException.java sync/InfoCollections.java sync/jpake/BigIntegerHelper.java sync/jpake/Gx3OrGx4IsZeroOrOneException.java sync/jpake/IncorrectZkpException.java sync/jpake/JPakeClient.java sync/jpake/JPakeCrypto.java sync/jpake/JPakeNoActivePairingException.java sync/jpake/JPakeNumGenerator.java sync/jpake/JPakeNumGeneratorRandom.java sync/jpake/JPakeParty.java sync/jpake/JPakeRequest.java sync/jpake/JPakeRequestDelegate.java sync/jpake/JPakeResponse.java sync/jpake/Zkp.java sync/Logger.java sync/MetaGlobal.java sync/MetaGlobalException.java sync/MetaGlobalMissingEnginesException.java sync/MetaGlobalNotSetException.java sync/middleware/Crypto5MiddlewareRepository.java sync/middleware/Crypto5MiddlewareRepositorySession.java sync/middleware/MiddlewareRepository.java sync/net/BaseResource.java sync/net/CompletedEntity.java sync/net/HandleProgressException.java sync/net/Resource.java sync/net/ResourceDelegate.java sync/net/SyncResourceDelegate.java sync/net/SyncResponse.java sync/net/SyncStorageCollectionRequest.java sync/net/SyncStorageCollectionRequestDelegate.java sync/net/SyncStorageRecordRequest.java sync/net/SyncStorageRequest.java sync/net/SyncStorageRequestDelegate.java sync/net/SyncStorageRequestIncrementalDelegate.java sync/net/SyncStorageResponse.java sync/net/TLSSocketFactory.java sync/net/WBOCollectionRequestDelegate.java sync/NoCollectionKeysSetException.java sync/NonArrayJSONException.java sync/NonObjectJSONException.java sync/PrefsSource.java sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java sync/repositories/android/AndroidBrowserBookmarksRepository.java sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java sync/repositories/android/AndroidBrowserHistoryDataAccessor.java sync/repositories/android/AndroidBrowserHistoryDataExtender.java sync/repositories/android/AndroidBrowserHistoryRepository.java sync/repositories/android/AndroidBrowserHistoryRepositorySession.java sync/repositories/android/AndroidBrowserPasswordsDataAccessor.java sync/repositories/android/AndroidBrowserPasswordsRepository.java sync/repositories/android/AndroidBrowserPasswordsRepositorySession.java sync/repositories/android/AndroidBrowserRepository.java sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java sync/repositories/android/AndroidBrowserRepositorySession.java sync/repositories/android/BrowserContract.java sync/repositories/android/PasswordColumns.java sync/repositories/android/RepoUtils.java sync/repositories/BookmarkNeedsReparentingException.java sync/repositories/BookmarksRepository.java sync/repositories/ConstrainedServer11Repository.java sync/repositories/delegates/DeferrableRepositorySessionCreationDelegate.java sync/repositories/delegates/DeferredRepositorySessionBeginDelegate.java sync/repositories/delegates/DeferredRepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/DeferredRepositorySessionFinishDelegate.java sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionBeginDelegate.java sync/repositories/delegates/RepositorySessionCleanDelegate.java sync/repositories/delegates/RepositorySessionCreationDelegate.java sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/RepositorySessionFinishDelegate.java sync/repositories/delegates/RepositorySessionGuidsSinceDelegate.java sync/repositories/delegates/RepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionWipeDelegate.java sync/repositories/domain/BookmarkRecord.java sync/repositories/domain/BookmarkRecordFactory.java sync/repositories/domain/HistoryRecord.java sync/repositories/domain/HistoryRecordFactory.java sync/repositories/domain/PasswordRecord.java sync/repositories/domain/Record.java sync/repositories/HashSetStoreTracker.java sync/repositories/HistoryRepository.java sync/repositories/IdentityRecordFactory.java sync/repositories/InactiveSessionException.java sync/repositories/InvalidBookmarkTypeException.java sync/repositories/InvalidRequestException.java sync/repositories/InvalidSessionTransitionException.java sync/repositories/MultipleRecordsForGuidException.java sync/repositories/NoGuidForIdException.java sync/repositories/NoStoreDelegateException.java sync/repositories/NullCursorException.java sync/repositories/ParentNotFoundException.java sync/repositories/ProfileDatabaseException.java sync/repositories/RecordFactory.java sync/repositories/RecordFilter.java sync/repositories/Repository.java sync/repositories/RepositorySession.java sync/repositories/RepositorySessionBundle.java sync/repositories/Server11Repository.java sync/repositories/Server11RepositorySession.java sync/repositories/StoreTracker.java sync/repositories/StoreTrackingRepositorySession.java sync/setup/activities/AccountActivity.java sync/setup/activities/SetupFailureActivity.java sync/setup/activities/SetupSuccessActivity.java sync/setup/activities/SetupSyncActivity.java sync/setup/Constants.java sync/setup/SyncAuthenticatorService.java sync/stage/AndroidBrowserBookmarksServerSyncStage.java sync/stage/AndroidBrowserHistoryServerSyncStage.java sync/stage/CheckPreconditionsStage.java sync/stage/CompletedStage.java sync/stage/EnsureClusterURLStage.java sync/stage/EnsureKeysStage.java sync/stage/FetchInfoCollectionsStage.java sync/stage/FetchMetaGlobalStage.java sync/stage/GlobalSyncStage.java sync/stage/NoSuchStageException.java sync/stage/NoSyncIDException.java sync/stage/ServerSyncStage.java sync/StubActivity.java sync/syncadapter/SyncAdapter.java sync/syncadapter/SyncService.java sync/SyncConfiguration.java sync/SyncConfigurationException.java sync/SyncException.java sync/synchronizer/ConcurrentRecordConsumer.java sync/synchronizer/RecordConsumer.java sync/synchronizer/RecordsChannel.java sync/synchronizer/RecordsChannelDelegate.java sync/synchronizer/RecordsConsumerDelegate.java sync/synchronizer/SerialRecordConsumer.java sync/synchronizer/SessionNotBegunException.java sync/synchronizer/Synchronizer.java sync/synchronizer/SynchronizerDelegate.java sync/synchronizer/SynchronizerSession.java sync/synchronizer/SynchronizerSessionDelegate.java sync/synchronizer/UnbundleError.java sync/synchronizer/UnexpectedSessionException.java sync/SynchronizerConfiguration.java sync/SynchronizerConfigurations.java sync/ThreadPool.java sync/UnexpectedJSONException.java sync/UnknownSynchronizerConfigurationVersionException.java sync/Utils.java From 6f225ae687190d6725502835d87fa89f3d953929 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Wed, 15 Feb 2012 22:05:53 -0800 Subject: [PATCH 15/93] Bug 726054 - Desktop parity: track last sync time from final upload, not final fetch. r=nalexander --- .../Crypto5MiddlewareRepositorySession.java | 13 +++++--- .../sync/repositories/RepositorySession.java | 9 +++++- .../repositories/RepositorySessionBundle.java | 6 +++- .../Server11RepositorySession.java | 21 +++++++++++- ...RepositorySessionFetchRecordsDelegate.java | 10 +++--- ...eferredRepositorySessionStoreDelegate.java | 6 ++-- ...RepositorySessionFetchRecordsDelegate.java | 4 +-- .../RepositorySessionStoreDelegate.java | 2 +- .../sync/synchronizer/RecordsChannel.java | 21 ++++++------ .../synchronizer/RecordsChannelDelegate.java | 2 +- .../synchronizer/SynchronizerSession.java | 32 +++++++++++++------ 11 files changed, 86 insertions(+), 40 deletions(-) diff --git a/mobile/android/base/sync/middleware/Crypto5MiddlewareRepositorySession.java b/mobile/android/base/sync/middleware/Crypto5MiddlewareRepositorySession.java index b6977be428fa..03c0c0a06136 100644 --- a/mobile/android/base/sync/middleware/Crypto5MiddlewareRepositorySession.java +++ b/mobile/android/base/sync/middleware/Crypto5MiddlewareRepositorySession.java @@ -146,7 +146,7 @@ public class Crypto5MiddlewareRepositorySession extends RepositorySession { } @Override - public void onFetchSucceeded(Record[] records, long end) { + public void onFetchSucceeded(Record[] records, long fetchEnd) { for (Record record : records) { try { this.onFetchedRecord(record); @@ -154,12 +154,12 @@ public class Crypto5MiddlewareRepositorySession extends RepositorySession { this.onFetchFailed(e, record); } } - this.onFetchCompleted(end); + this.onFetchCompleted(fetchEnd); } @Override - public void onFetchCompleted(long end) { - next.onFetchCompleted(end); + public void onFetchCompleted(final long fetchEnd) { + next.onFetchCompleted(fetchEnd); } @Override @@ -237,4 +237,9 @@ public class Crypto5MiddlewareRepositorySession extends RepositorySession { public void storeDone() { inner.storeDone(); } + + @Override + public void storeDone(long end) { + inner.storeDone(end); + } } diff --git a/mobile/android/base/sync/repositories/RepositorySession.java b/mobile/android/base/sync/repositories/RepositorySession.java index 88f1b969e5a1..cd2e85e46504 100644 --- a/mobile/android/base/sync/repositories/RepositorySession.java +++ b/mobile/android/base/sync/repositories/RepositorySession.java @@ -147,11 +147,18 @@ public abstract class RepositorySession { public abstract void store(Record record) throws NoStoreDelegateException; public void storeDone() { + // Our default behavior will be to assume that the Runnable is + // executed as soon as all the stores synchronously finish, so + // our end timestamp can just be… now. + storeDone(now()); + } + + public void storeDone(final long end) { Log.d(LOG_TAG, "Scheduling onStoreCompleted for after storing is done."); Runnable command = new Runnable() { @Override public void run() { - delegate.onStoreCompleted(); + delegate.onStoreCompleted(end); } }; storeWorkQueue.execute(command); diff --git a/mobile/android/base/sync/repositories/RepositorySessionBundle.java b/mobile/android/base/sync/repositories/RepositorySessionBundle.java index 3645e47a1a90..84630846e930 100644 --- a/mobile/android/base/sync/repositories/RepositorySessionBundle.java +++ b/mobile/android/base/sync/repositories/RepositorySessionBundle.java @@ -41,6 +41,7 @@ import java.io.IOException; import org.json.simple.parser.ParseException; import org.mozilla.gecko.sync.ExtendedJSONObject; +import org.mozilla.gecko.sync.Logger; import org.mozilla.gecko.sync.NonObjectJSONException; import android.util.Log; @@ -75,8 +76,11 @@ public class RepositorySessionBundle extends ExtendedJSONObject { } public void bumpTimestamp(long timestamp) { - if (timestamp > this.getTimestamp()) { + long existing = this.getTimestamp(); + if (timestamp > existing) { this.setTimestamp(timestamp); + } else { + Logger.debug(LOG_TAG, "Timestamp " + timestamp + " not greater than " + existing + "; not bumping."); } } } diff --git a/mobile/android/base/sync/repositories/Server11RepositorySession.java b/mobile/android/base/sync/repositories/Server11RepositorySession.java index 644ff37cb666..28afc59bebb7 100644 --- a/mobile/android/base/sync/repositories/Server11RepositorySession.java +++ b/mobile/android/base/sync/repositories/Server11RepositorySession.java @@ -44,6 +44,7 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Date; +import java.util.concurrent.atomic.AtomicLong; import org.json.simple.JSONArray; import org.mozilla.gecko.sync.CryptoRecord; @@ -186,6 +187,20 @@ public class Server11RepositorySession extends RepositorySession { Server11Repository serverRepository; + AtomicLong uploadTimestamp = new AtomicLong(0); + + private void bumpUploadTimestamp(long ts) { + while (true) { + long existing = uploadTimestamp.get(); + if (existing > ts) { + return; + } + if (uploadTimestamp.compareAndSet(existing, ts)) { + return; + } + } + } + public Server11RepositorySession(Repository repository) { super(repository); serverRepository = (Server11Repository) repository; @@ -320,7 +335,7 @@ public class Server11RepositorySession extends RepositorySession { public void storeDone() { synchronized (recordsBufferMonitor) { flush(); - super.storeDone(); + storeDone(uploadTimestamp.get()); } } @@ -379,6 +394,10 @@ public class Server11RepositorySession extends RepositorySession { (success.size() > 0)) { Log.d(LOG_TAG, "Successful records: " + success.toString()); // TODO: how do we notify without the whole record? + + long ts = response.normalizedWeaveTimestamp(); + Log.d(LOG_TAG, "Passing back upload X-Weave-Timestamp: " + ts); + bumpUploadTimestamp(ts); } if ((failed != null) && (failed.object.size() > 0)) { diff --git a/mobile/android/base/sync/repositories/delegates/DeferredRepositorySessionFetchRecordsDelegate.java b/mobile/android/base/sync/repositories/delegates/DeferredRepositorySessionFetchRecordsDelegate.java index 3815e276ea98..b733d9d8d661 100644 --- a/mobile/android/base/sync/repositories/delegates/DeferredRepositorySessionFetchRecordsDelegate.java +++ b/mobile/android/base/sync/repositories/delegates/DeferredRepositorySessionFetchRecordsDelegate.java @@ -61,11 +61,11 @@ public class DeferredRepositorySessionFetchRecordsDelegate implements Repository } @Override - public void onFetchSucceeded(final Record[] records, final long end) { + public void onFetchSucceeded(final Record[] records, final long fetchEnd) { executor.execute(new Runnable() { @Override public void run() { - inner.onFetchSucceeded(records, end); + inner.onFetchSucceeded(records, fetchEnd); } }); } @@ -81,11 +81,11 @@ public class DeferredRepositorySessionFetchRecordsDelegate implements Repository } @Override - public void onFetchCompleted(final long end) { + public void onFetchCompleted(final long fetchEnd) { executor.execute(new Runnable() { @Override public void run() { - inner.onFetchCompleted(end); + inner.onFetchCompleted(fetchEnd); } }); } @@ -97,4 +97,4 @@ public class DeferredRepositorySessionFetchRecordsDelegate implements Repository } throw new IllegalArgumentException("Can't re-defer this delegate."); } -} \ No newline at end of file +} diff --git a/mobile/android/base/sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java b/mobile/android/base/sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java index 62291272f05f..7e98ef1d6f05 100644 --- a/mobile/android/base/sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java +++ b/mobile/android/base/sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java @@ -81,12 +81,12 @@ public class DeferredRepositorySessionStoreDelegate implements } @Override - public void onStoreCompleted() { + public void onStoreCompleted(final long storeEnd) { executor.execute(new Runnable() { @Override public void run() { - inner.onStoreCompleted(); + inner.onStoreCompleted(storeEnd); } }); } -} \ No newline at end of file +} diff --git a/mobile/android/base/sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java b/mobile/android/base/sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java index 729c65191a11..5983f13d2794 100644 --- a/mobile/android/base/sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java +++ b/mobile/android/base/sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java @@ -55,11 +55,11 @@ public interface RepositorySessionFetchRecordsDelegate { * which the request was received. * E.g., the (normalized) value of the X-Weave-Timestamp header. */ - public void onFetchCompleted(long end); + public void onFetchCompleted(final long fetchEnd); // Shorthand for calling onFetchedRecord for each record in turn, then // calling onFetchCompleted. - public void onFetchSucceeded(Record[] records, long end); + public void onFetchSucceeded(Record[] records, final long fetchEnd); public RepositorySessionFetchRecordsDelegate deferredFetchDelegate(ExecutorService executor); } diff --git a/mobile/android/base/sync/repositories/delegates/RepositorySessionStoreDelegate.java b/mobile/android/base/sync/repositories/delegates/RepositorySessionStoreDelegate.java index 80c91519f2d0..d7c501bad2fa 100644 --- a/mobile/android/base/sync/repositories/delegates/RepositorySessionStoreDelegate.java +++ b/mobile/android/base/sync/repositories/delegates/RepositorySessionStoreDelegate.java @@ -51,6 +51,6 @@ import org.mozilla.gecko.sync.repositories.domain.Record; public interface RepositorySessionStoreDelegate { public void onRecordStoreFailed(Exception ex); public void onRecordStoreSucceeded(Record record); - public void onStoreCompleted(); + public void onStoreCompleted(long storeEnd); public RepositorySessionStoreDelegate deferredStoreDelegate(ExecutorService executor); } diff --git a/mobile/android/base/sync/synchronizer/RecordsChannel.java b/mobile/android/base/sync/synchronizer/RecordsChannel.java index d86bbf773d0b..ff936364c12f 100644 --- a/mobile/android/base/sync/synchronizer/RecordsChannel.java +++ b/mobile/android/base/sync/synchronizer/RecordsChannel.java @@ -51,8 +51,6 @@ import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionFetchRecor import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionStoreDelegate; import org.mozilla.gecko.sync.repositories.domain.Record; -import android.util.Log; - /** * Pulls records from `source`, applying them to `sink`. * Notifies its delegate of errors and completion. @@ -104,7 +102,7 @@ class RecordsChannel implements public RepositorySession sink; private RecordsChannelDelegate delegate; private long timestamp; - private long end = -1; // Oo er, missus. + private long fetchEnd = -1; public RecordsChannel(RepositorySession source, RepositorySession sink, RecordsChannelDelegate delegate) { this.source = source; @@ -198,19 +196,19 @@ class RecordsChannel implements } @Override - public void onFetchSucceeded(Record[] records, long end) { + public void onFetchSucceeded(Record[] records, final long fetchEnd) { for (Record record : records) { this.toProcess.add(record); } this.consumer.doNotify(); - this.onFetchCompleted(end); + this.onFetchCompleted(fetchEnd); } @Override - public void onFetchCompleted(long end) { + public void onFetchCompleted(final long fetchEnd) { Logger.info(LOG_TAG, "onFetchCompleted. Stopping consumer once stores are done."); - Logger.info(LOG_TAG, "Fetch timestamp is " + end); - this.end = end; + Logger.info(LOG_TAG, "Fetch timestamp is " + fetchEnd); + this.fetchEnd = fetchEnd; this.consumer.queueFilled(); } @@ -237,10 +235,11 @@ class RecordsChannel implements } @Override - public void onStoreCompleted() { - Logger.info(LOG_TAG, "onStoreCompleted. Notifying delegate of onFlowCompleted. End is " + end); + public void onStoreCompleted(long storeEnd) { + Logger.info(LOG_TAG, "onStoreCompleted. Notifying delegate of onFlowCompleted. " + + "Fetch end is " + fetchEnd + ", store end is " + storeEnd); // TODO: synchronize on consumer callback? - delegate.onFlowCompleted(this, end); + delegate.onFlowCompleted(this, fetchEnd, storeEnd); } @Override diff --git a/mobile/android/base/sync/synchronizer/RecordsChannelDelegate.java b/mobile/android/base/sync/synchronizer/RecordsChannelDelegate.java index 13566f8e2dd9..273f655ff07a 100644 --- a/mobile/android/base/sync/synchronizer/RecordsChannelDelegate.java +++ b/mobile/android/base/sync/synchronizer/RecordsChannelDelegate.java @@ -38,7 +38,7 @@ package org.mozilla.gecko.sync.synchronizer; public interface RecordsChannelDelegate { - public void onFlowCompleted(RecordsChannel recordsChannel, long end); + public void onFlowCompleted(RecordsChannel recordsChannel, long fetchEnd, long storeEnd); public void onFlowBeginFailed(RecordsChannel recordsChannel, Exception ex); public void onFlowStoreFailed(RecordsChannel recordsChannel, Exception ex); public void onFlowFinishFailed(RecordsChannel recordsChannel, Exception ex); diff --git a/mobile/android/base/sync/synchronizer/SynchronizerSession.java b/mobile/android/base/sync/synchronizer/SynchronizerSession.java index a06d9304f995..4f124d8bfa9b 100644 --- a/mobile/android/base/sync/synchronizer/SynchronizerSession.java +++ b/mobile/android/base/sync/synchronizer/SynchronizerSession.java @@ -66,8 +66,15 @@ implements RecordsChannelDelegate, private RepositorySession sessionB; private RepositorySessionBundle bundleA; private RepositorySessionBundle bundleB; + + // Bug 726054: just like desktop, we track our last interaction with the server, + // not the last record timestamp that we fetched. This ensures that we don't re- + // download the records we just uploaded, at the cost of skipping any records + // that a concurrently syncing client has uploaded. private long pendingATimestamp = -1; private long pendingBTimestamp = -1; + private long storeEndATimestamp = -1; + private long storeEndBTimestamp = -1; private boolean flowAToBCompleted = false; private boolean flowBToACompleted = false; @@ -133,9 +140,11 @@ implements RecordsChannelDelegate, // TODO: failed record handling. final RecordsChannel channelBToA = new RecordsChannel(this.sessionB, this.sessionA, this); RecordsChannelDelegate channelDelegate = new RecordsChannelDelegate() { - public void onFlowCompleted(RecordsChannel recordsChannel, long end) { - info("First RecordsChannel flow completed. End is " + end + ". Starting next."); - pendingATimestamp = end; + public void onFlowCompleted(RecordsChannel recordsChannel, long fetchEnd, long storeEnd) { + info("First RecordsChannel flow completed. Fetch end is " + fetchEnd + + ". Store end is " + storeEnd + ". Starting next."); + pendingATimestamp = fetchEnd; + storeEndBTimestamp = storeEnd; flowAToBCompleted = true; channelBToA.flow(); } @@ -165,9 +174,12 @@ implements RecordsChannelDelegate, } @Override - public void onFlowCompleted(RecordsChannel channel, long end) { - info("Second RecordsChannel flow completed. End is " + end + ". Finishing."); - pendingBTimestamp = end; + public void onFlowCompleted(RecordsChannel channel, long fetchEnd, long storeEnd) { + info("Second RecordsChannel flow completed. Fetch end is " + fetchEnd + + ". Store end is " + storeEnd + ". Finishing."); + + pendingBTimestamp = fetchEnd; + storeEndATimestamp = storeEnd; flowBToACompleted = true; // Finish the two sessions. @@ -278,8 +290,8 @@ implements RecordsChannelDelegate, if (session == sessionA) { if (flowAToBCompleted) { - info("onFinishSucceeded: bumping session A's timestamp to " + pendingATimestamp); - bundle.bumpTimestamp(pendingATimestamp); + info("onFinishSucceeded: bumping session A's timestamp to " + pendingATimestamp + " or " + storeEndATimestamp); + bundle.bumpTimestamp(Math.max(pendingATimestamp, storeEndATimestamp)); this.synchronizer.bundleA = bundle; } if (this.sessionB != null) { @@ -289,8 +301,8 @@ implements RecordsChannelDelegate, } } else if (session == sessionB) { if (flowBToACompleted) { - info("onFinishSucceeded: bumping session B's timestamp to " + pendingBTimestamp); - bundle.bumpTimestamp(pendingBTimestamp); + info("onFinishSucceeded: bumping session B's timestamp to " + pendingBTimestamp + " or " + storeEndBTimestamp); + bundle.bumpTimestamp(Math.max(pendingBTimestamp, storeEndBTimestamp)); this.synchronizer.bundleB = bundle; info("Notifying delegate.onSynchronized."); this.delegate.onSynchronized(this); From 138558ffb43db83f509302b66fd3e34a58977fbe Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Wed, 15 Feb 2012 22:05:53 -0800 Subject: [PATCH 16/93] Bug 724328 - Bump Android Sync version to 0.5. r=rnewman --- mobile/android/base/sync/net/SyncStorageRequest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/android/base/sync/net/SyncStorageRequest.java b/mobile/android/base/sync/net/SyncStorageRequest.java index 4025e3d6b0f0..a9258382bdf7 100644 --- a/mobile/android/base/sync/net/SyncStorageRequest.java +++ b/mobile/android/base/sync/net/SyncStorageRequest.java @@ -176,7 +176,7 @@ public class SyncStorageRequest implements Resource { } } - public static String USER_AGENT = "Firefox AndroidSync 0.4"; + public static String USER_AGENT = "Firefox AndroidSync 0.5"; protected SyncResourceDelegate resourceDelegate; public SyncStorageRequestDelegate delegate; protected BaseResource resource; From 4e017cf537f4340d9e540f4be4ab02928ef9e909 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Wed, 15 Feb 2012 23:11:48 -0800 Subject: [PATCH 17/93] Bug 727686: Remove unused variable 'sTestDeque' from TestDeque.cpp. r=cpearce --- xpcom/tests/TestDeque.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/xpcom/tests/TestDeque.cpp b/xpcom/tests/TestDeque.cpp index e0fd85a0e208..36d465c3c789 100644 --- a/xpcom/tests/TestDeque.cpp +++ b/xpcom/tests/TestDeque.cpp @@ -52,7 +52,6 @@ private: int AssignFlaw(); int TestRemove(); }; -static _TestDeque sTestDeque; class _Dealloc: public nsDequeFunctor { virtual void* operator()(void* aObject) { From 0119d534ac46677e51552955467cb35cef38b55c Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 16 Feb 2012 09:00:53 +0100 Subject: [PATCH 18/93] Bug 720704 - Avoid setting an alternative stack for signals if there is already one. r=ted --- .../client/linux/handler/exception_handler.cc | 16 ++++++++++------ .../src/client/linux/handler/exception_handler.h | 1 - 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.cc b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.cc index 54a529a2923e..5946256c20d7 100644 --- a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.cc +++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.cc @@ -190,14 +190,18 @@ bool ExceptionHandler::InstallHandlers() { // such a small stack. static const unsigned kSigStackSize = 8192; - signal_stack = malloc(kSigStackSize); stack_t stack; - memset(&stack, 0, sizeof(stack)); - stack.ss_sp = signal_stack; - stack.ss_size = kSigStackSize; + // Only set an alternative stack if there isn't already one, or if the current + // one is too small. + if (sys_sigaltstack(NULL, &stack) == -1 || !stack.ss_sp || + stack.ss_size < kSigStackSize) { + memset(&stack, 0, sizeof(stack)); + stack.ss_sp = malloc(kSigStackSize); + stack.ss_size = kSigStackSize; - if (sys_sigaltstack(&stack, NULL) == -1) - return false; + if (sys_sigaltstack(&stack, NULL) == -1) + return false; + } struct sigaction sa; memset(&sa, 0, sizeof(sa)); diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h index 355e8a63a930..60e69ef2c629 100644 --- a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h +++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h @@ -259,7 +259,6 @@ class ExceptionHandler { const char* next_minidump_id_c_; const bool handler_installed_; - void* signal_stack; // the handler stack. HandlerCallback crash_handler_; // The global exception handler stack. This is need becuase there may exist From 3b90cf62ea9f8d83fd0a2e33387cd9ddcd10199d Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 16 Feb 2012 09:01:31 +0100 Subject: [PATCH 19/93] Bug 721737 - Add toolkit l10n Makefiles to browser/makefiles.sh. r=khuey --- browser/makefiles.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/browser/makefiles.sh b/browser/makefiles.sh index e5bc351d0baf..d76045f8cfa0 100644 --- a/browser/makefiles.sh +++ b/browser/makefiles.sh @@ -88,6 +88,12 @@ browser/themes/Makefile $MOZ_BRANDING_DIRECTORY/Makefile $MOZ_BRANDING_DIRECTORY/content/Makefile $MOZ_BRANDING_DIRECTORY/locales/Makefile +toolkit/locales/Makefile +extensions/spellcheck/locales/Makefile +intl/locales/Makefile +netwerk/locales/Makefile +dom/locales/Makefile +security/manager/locales/Makefile " if [ "$MOZ_SAFE_BROWSING" ]; then From f4d721b1f06ab33cecbabdb7585a725636cb44e7 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 16 Feb 2012 09:02:25 +0100 Subject: [PATCH 20/93] Bug 727202 - Wrap malloc and free to use jemalloc in GeckoAppShell.{allocate,free}DirectBuffer. r=blassey --- mozglue/android/nsGeckoUtils.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mozglue/android/nsGeckoUtils.cpp b/mozglue/android/nsGeckoUtils.cpp index 59487842c7d6..2dfa0dca9e1c 100644 --- a/mozglue/android/nsGeckoUtils.cpp +++ b/mozglue/android/nsGeckoUtils.cpp @@ -36,6 +36,9 @@ * ***** END LICENSE BLOCK ***** */ #include +// Wrap malloc and free to use jemalloc +#define malloc __wrap_malloc +#define free __wrap_free #include extern "C" From 9ceeaad4db1c3576f84947d01aa3f191cbcf45be Mon Sep 17 00:00:00 2001 From: Jared Wein Date: Thu, 16 Feb 2012 11:20:26 +0100 Subject: [PATCH 21/93] Bug 722681 - Show the tab close button immediately when opening a second tab. r=dao --- browser/base/content/tabbrowser.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index 97a2564216bf..f6cb890668e0 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -1265,6 +1265,12 @@ else { t._animStartTime = Date.now(); t.setAttribute("fadein", "true"); + + // This call to adjustTabstrip is redundant but needed so that + // when opening a second tab, the first tab's close buttons + // appears immediately rather than when the transition ends. + if (tabContainer.childNodes.length == 2) + tabContainer.adjustTabstrip(); } }, 0, this.tabContainer); } From ff16c1a5f26752d6abc3f2e3c6c533960e2443f4 Mon Sep 17 00:00:00 2001 From: Aryeh Gregor Date: Tue, 14 Feb 2012 15:33:06 -0500 Subject: [PATCH 22/93] Bug 722463 - Transforms should not work on non-replaced inline elements. r=roc --- layout/generic/nsInlineFrame.cpp | 14 ++++++++++++++ layout/generic/nsInlineFrame.h | 7 +++++++ layout/reftests/transform/descendant-1.html | 6 +++--- layout/reftests/transform/inline-1-ref.html | 2 ++ layout/reftests/transform/inline-1a.html | 3 +++ layout/reftests/transform/reftest.list | 2 ++ 6 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 layout/reftests/transform/inline-1-ref.html create mode 100644 layout/reftests/transform/inline-1a.html diff --git a/layout/generic/nsInlineFrame.cpp b/layout/generic/nsInlineFrame.cpp index 17121a8c2436..eddff255c25b 100644 --- a/layout/generic/nsInlineFrame.cpp +++ b/layout/generic/nsInlineFrame.cpp @@ -71,6 +71,20 @@ NS_NewInlineFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) return new (aPresShell) nsInlineFrame(aContext); } +NS_IMETHODIMP +nsInlineFrame::Init(nsIContent* aContent, + nsIFrame* aParent, + nsIFrame* aPrevInFlow) +{ + // Let the base class do its processing + nsresult rv = nsContainerFrame::Init(aContent, aParent, aPrevInFlow); + + // Transforms do not affect regular inline elements (bug 722463) + mState &= ~NS_FRAME_MAY_BE_TRANSFORMED; + + return rv; +} + NS_IMPL_FRAMEARENA_HELPERS(nsInlineFrame) NS_QUERYFRAME_HEAD(nsInlineFrame) diff --git a/layout/generic/nsInlineFrame.h b/layout/generic/nsInlineFrame.h index 924c3561c8c5..94faa93074ba 100644 --- a/layout/generic/nsInlineFrame.h +++ b/layout/generic/nsInlineFrame.h @@ -69,6 +69,13 @@ public: friend nsIFrame* NS_NewInlineFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); + /** sets defaults for inline-specific style. + * @see nsIFrame::Init + */ + NS_IMETHOD Init(nsIContent* aContent, + nsIFrame* aParent, + nsIFrame* aPrevInFlow); + // nsIFrame overrides NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, diff --git a/layout/reftests/transform/descendant-1.html b/layout/reftests/transform/descendant-1.html index 090084af2b9f..6de49fc5f087 100644 --- a/layout/reftests/transform/descendant-1.html +++ b/layout/reftests/transform/descendant-1.html @@ -9,14 +9,14 @@ span { background: yellow; } - #div1 span {-moz-transform: translate(20px, 150px); - -moz-transform-origin: 0% 0%; + #div1 div {-moz-transform: translate(20px, 150px); + -moz-transform-origin: 0% 0%; }
- span 1 +
span 1
span 2 diff --git a/layout/reftests/transform/inline-1-ref.html b/layout/reftests/transform/inline-1-ref.html new file mode 100644 index 000000000000..84a2f6dd4a80 --- /dev/null +++ b/layout/reftests/transform/inline-1-ref.html @@ -0,0 +1,2 @@ + +This is some text
that is not transformed diff --git a/layout/reftests/transform/inline-1a.html b/layout/reftests/transform/inline-1a.html new file mode 100644 index 000000000000..fab499d72c1f --- /dev/null +++ b/layout/reftests/transform/inline-1a.html @@ -0,0 +1,3 @@ + +This is some text
+that is
not transformed diff --git a/layout/reftests/transform/reftest.list b/layout/reftests/transform/reftest.list index b57672abf0ae..a8a70d98f8b7 100644 --- a/layout/reftests/transform/reftest.list +++ b/layout/reftests/transform/reftest.list @@ -118,3 +118,5 @@ fails-if(Android) == stresstest-1.html stresstest-1-ref.html == table-1c.html table-1-ref.html == table-2a.html table-2-ref.html == table-2b.html table-2-ref.html +# Bug 722463 +== inline-1a.html inline-1-ref.html From 5e505cd07f51b1e91597e77c2c096edc7508dfd7 Mon Sep 17 00:00:00 2001 From: Matthew Schranz Date: Thu, 16 Feb 2012 11:22:25 +0100 Subject: [PATCH 23/93] Bug 725289 - Removed moz prefix in Blob.mozSlice. r=sicking --HG-- rename : dom/workers/test/fileReadMozSlice_worker.js => dom/workers/test/fileReadSlice_worker.js rename : dom/workers/test/fileMozSlice_worker.js => dom/workers/test/fileSlice_worker.js rename : dom/workers/test/test_fileReadMozSlice.xul => dom/workers/test/test_fileReadSlice.xul rename : dom/workers/test/test_fileMozSlice.xul => dom/workers/test/test_fileSlice.xul --- content/base/crashtests/700512-worker.js | 2 +- content/base/public/nsIDOMFile.idl | 6 ++-- content/base/src/nsDOMBlobBuilder.cpp | 10 +++---- content/base/src/nsDOMFile.cpp | 6 ++-- content/base/test/fileutils.js | 28 +++++++++---------- content/base/test/test_blobbuilder.html | 2 +- content/base/test/test_fileapi_slice.html | 8 +++--- dom/workers/File.cpp | 14 +++++----- dom/workers/test/Makefile.in | 8 +++--- ...lice_worker.js => fileReadSlice_worker.js} | 2 +- ...MozSlice_worker.js => fileSlice_worker.js} | 6 ++-- dom/workers/test/test_fileBlobPosting.xul | 2 +- dom/workers/test/test_fileBlobSubWorker.xul | 2 +- ...eadMozSlice.xul => test_fileReadSlice.xul} | 14 +++++----- ...st_fileMozSlice.xul => test_fileSlice.xul} | 22 +++++++-------- 15 files changed, 66 insertions(+), 66 deletions(-) rename dom/workers/test/{fileReadMozSlice_worker.js => fileReadSlice_worker.js} (89%) rename dom/workers/test/{fileMozSlice_worker.js => fileSlice_worker.js} (81%) rename dom/workers/test/{test_fileReadMozSlice.xul => test_fileReadSlice.xul} (85%) rename dom/workers/test/{test_fileMozSlice.xul => test_fileSlice.xul} (80%) diff --git a/content/base/crashtests/700512-worker.js b/content/base/crashtests/700512-worker.js index 83b732ab570d..fcb558fcf459 100644 --- a/content/base/crashtests/700512-worker.js +++ b/content/base/crashtests/700512-worker.js @@ -1,7 +1,7 @@ onmessage = function(event) { var blob = event.data; - blob.mozSlice(1, 5); + blob.slice(1, 5); postMessage("done"); } diff --git a/content/base/public/nsIDOMFile.idl b/content/base/public/nsIDOMFile.idl index 6d47a5fc5b88..7c9913fe2038 100644 --- a/content/base/public/nsIDOMFile.idl +++ b/content/base/public/nsIDOMFile.idl @@ -71,9 +71,9 @@ interface nsIDOMBlob : nsISupports // blob: protocol handler [noscript] DOMString getInternalUrl(in nsIPrincipal principal); - [optional_argc] nsIDOMBlob mozSlice([optional] in long long start, - [optional] in long long end, - [optional] in DOMString contentType); + [optional_argc] nsIDOMBlob slice([optional] in long long start, + [optional] in long long end, + [optional] in DOMString contentType); // Get internal id of stored file. Returns -1 if it is not a stored file. // Intended only for testing. It can be called on any thread. diff --git a/content/base/src/nsDOMBlobBuilder.cpp b/content/base/src/nsDOMBlobBuilder.cpp index b1dab01e18fb..402edddd103a 100644 --- a/content/base/src/nsDOMBlobBuilder.cpp +++ b/content/base/src/nsDOMBlobBuilder.cpp @@ -122,9 +122,9 @@ nsDOMMultipartFile::CreateSlice(PRUint64 aStart, PRUint64 aLength, PRUint64 upperBound = NS_MIN(l - skipStart, length); nsCOMPtr firstBlob; - rv = blob->MozSlice(skipStart, skipStart + upperBound, - aContentType, 3, - getter_AddRefs(firstBlob)); + rv = blob->Slice(skipStart, skipStart + upperBound, + aContentType, 3, + getter_AddRefs(firstBlob)); NS_ENSURE_SUCCESS(rv, nsnull); // Avoid wrapping a single blob inside an nsDOMMultipartFile @@ -150,8 +150,8 @@ nsDOMMultipartFile::CreateSlice(PRUint64 aStart, PRUint64 aLength, if (length < l) { nsCOMPtr lastBlob; - rv = blob->MozSlice(0, length, aContentType, 3, - getter_AddRefs(lastBlob)); + rv = blob->Slice(0, length, aContentType, 3, + getter_AddRefs(lastBlob)); NS_ENSURE_SUCCESS(rv, nsnull); blobs.AppendElement(lastBlob); diff --git a/content/base/src/nsDOMFile.cpp b/content/base/src/nsDOMFile.cpp index 9c1d56d08d68..1df7d3863e0e 100644 --- a/content/base/src/nsDOMFile.cpp +++ b/content/base/src/nsDOMFile.cpp @@ -238,9 +238,9 @@ ParseSize(PRInt64 aSize, PRInt64& aStart, PRInt64& aEnd) } NS_IMETHODIMP -nsDOMFileBase::MozSlice(PRInt64 aStart, PRInt64 aEnd, - const nsAString& aContentType, PRUint8 optional_argc, - nsIDOMBlob **aBlob) +nsDOMFileBase::Slice(PRInt64 aStart, PRInt64 aEnd, + const nsAString& aContentType, PRUint8 optional_argc, + nsIDOMBlob **aBlob) { *aBlob = nsnull; diff --git a/content/base/test/fileutils.js b/content/base/test/fileutils.js index fbe6cbaa1c39..5693be02f3cb 100644 --- a/content/base/test/fileutils.js +++ b/content/base/test/fileutils.js @@ -201,24 +201,24 @@ function testSlice(file, size, type, contents, fileType) { ok(file instanceof File, fileType + " file is a File"); ok(file instanceof Blob, fileType + " file is also a Blob"); - var slice = file.mozSlice(0, size); + var slice = file.slice(0, size); ok(slice instanceof Blob, fileType + " fullsize slice is a Blob"); ok(!(slice instanceof File), fileType + " fullsize slice is not a File"); - slice = file.mozSlice(0, 1234); + slice = file.slice(0, 1234); ok(slice instanceof Blob, fileType + " sized slice is a Blob"); ok(!(slice instanceof File), fileType + " sized slice is not a File"); - slice = file.mozSlice(0, size, "foo/bar"); + slice = file.slice(0, size, "foo/bar"); is(slice.type, "foo/bar", fileType + " fullsize slice foo/bar type"); - slice = file.mozSlice(0, 5432, "foo/bar"); + slice = file.slice(0, 5432, "foo/bar"); is(slice.type, "foo/bar", fileType + " sized slice foo/bar type"); - is(slice.mozSlice(0, 10).type, "", fileType + " slice-slice type"); - is(slice.mozSlice(0, 10).size, 10, fileType + " slice-slice size"); - is(slice.mozSlice(0, 10, "hello/world").type, "hello/world", fileType + " slice-slice hello/world type"); - is(slice.mozSlice(0, 10, "hello/world").size, 10, fileType + " slice-slice hello/world size"); + is(slice.slice(0, 10).type, "", fileType + " slice-slice type"); + is(slice.slice(0, 10).size, 10, fileType + " slice-slice size"); + is(slice.slice(0, 10, "hello/world").type, "hello/world", fileType + " slice-slice hello/world type"); + is(slice.slice(0, 10, "hello/world").size, 10, fileType + " slice-slice hello/world size"); // Start, end, expected size var indexes = [[0, size, size], @@ -247,17 +247,17 @@ function testSlice(file, size, type, contents, fileType) { var sliceContents; var testName; if (indexes[i][0] == undefined) { - slice = file.mozSlice(); + slice = file.slice(); sliceContents = contents.slice(); testName = fileType + " slice()"; } else if (indexes[i][1] == undefined) { - slice = file.mozSlice(indexes[i][0]); + slice = file.slice(indexes[i][0]); sliceContents = contents.slice(indexes[i][0]); testName = fileType + " slice(" + indexes[i][0] + ")"; } else { - slice = file.mozSlice(indexes[i][0], indexes[i][1]); + slice = file.slice(indexes[i][0], indexes[i][1]); sliceContents = contents.slice(indexes[i][0], indexes[i][1]); testName = fileType + " slice(" + indexes[i][0] + ", " + indexes[i][1] + ")"; } @@ -268,11 +268,11 @@ function testSlice(file, size, type, contents, fileType) { } // Slice of slice - var slice = file.mozSlice(0, 40000); - testFile(slice.mozSlice(5000, 42000), contents.slice(5000, 40000), "file slice slice"); + var slice = file.slice(0, 40000); + testFile(slice.slice(5000, 42000), contents.slice(5000, 40000), "file slice slice"); // ...of slice of slice - slice = slice.mozSlice(5000, 42000).mozSlice(400, 700); + slice = slice.slice(5000, 42000).mozSlice(400, 700); SpecialPowers.gc(); testFile(slice, contents.slice(5400, 5700), "file slice slice slice"); } diff --git a/content/base/test/test_blobbuilder.html b/content/base/test/test_blobbuilder.html index 7b767c782450..6addb2f75f5b 100644 --- a/content/base/test/test_blobbuilder.html +++ b/content/base/test/test_blobbuilder.html @@ -151,7 +151,7 @@ function doTest(data) { ok(blob instanceof Blob, "Test " + testCounter + " blob is a Blob"); ok(!(blob instanceof File), "Test " + testCounter + " blob is not a File"); - let slice = blob.mozSlice(test.start, test.start + test.length); + let slice = blob.slice(test.start, test.start + test.length); ok(slice, "Test " + testCounter + " got slice"); ok(slice instanceof Blob, "Test " + testCounter + " slice is a Blob"); ok(!(slice instanceof File), "Test " + testCounter + " slice is not a File"); diff --git a/content/base/test/test_fileapi_slice.html b/content/base/test/test_fileapi_slice.html index 2b5594ce93e1..9bfc6e0315cb 100644 --- a/content/base/test/test_fileapi_slice.html +++ b/content/base/test/test_fileapi_slice.html @@ -104,7 +104,7 @@ function imageLoadHandler(event) { var imgfile = createFileWithData(testBinaryData + fileData + testBinaryData); is(imgfile.size, size + testBinaryData.length * 2, "correct file size (middle)"); var img = new Image; -img.src = URL.createObjectURL(imgfile.mozSlice(testBinaryData.length, testBinaryData.length + size)); +img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, testBinaryData.length + size)); img.onload = imageLoadHandler; expectedTestCount++; @@ -112,7 +112,7 @@ expectedTestCount++; var imgfile = createFileWithData(fileData + testBinaryData); is(imgfile.size, size + testBinaryData.length, "correct file size (start)"); var img = new Image; -img.src = URL.createObjectURL(imgfile.mozSlice(0, size)); +img.src = URL.createObjectURL(imgfile.slice(0, size)); img.onload = imageLoadHandler; expectedTestCount++; @@ -120,7 +120,7 @@ expectedTestCount++; var imgfile = createFileWithData(testBinaryData + fileData); is(imgfile.size, size + testBinaryData.length, "correct file size (end)"); var img = new Image; -img.src = URL.createObjectURL(imgfile.mozSlice(testBinaryData.length, testBinaryData.length + size)); +img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, testBinaryData.length + size)); img.onload = imageLoadHandler; expectedTestCount++; @@ -128,7 +128,7 @@ expectedTestCount++; var imgfile = createFileWithData(testBinaryData + fileData); is(imgfile.size, size + testBinaryData.length, "correct file size (past end)"); var img = new Image; -img.src = URL.createObjectURL(imgfile.mozSlice(testBinaryData.length, testBinaryData.length + size + 1000)); +img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, testBinaryData.length + size + 1000)); img.onload = imageLoadHandler; expectedTestCount++; diff --git a/dom/workers/File.cpp b/dom/workers/File.cpp index 29975086f702..109ea97b258d 100644 --- a/dom/workers/File.cpp +++ b/dom/workers/File.cpp @@ -171,14 +171,14 @@ private: } static JSBool - MozSlice(JSContext* aCx, uintN aArgc, jsval* aVp) + Slice(JSContext* aCx, uintN aArgc, jsval* aVp) { JSObject* obj = JS_THIS_OBJECT(aCx, aVp); if (!obj) { return false; } - nsIDOMBlob* blob = GetInstancePrivate(aCx, obj, "mozSlice"); + nsIDOMBlob* blob = GetInstancePrivate(aCx, obj, "slice"); if (!blob) { return false; } @@ -197,10 +197,10 @@ private: PRUint8 optionalArgc = aArgc; nsCOMPtr rtnBlob; - if (NS_FAILED(blob->MozSlice(static_cast(start), - static_cast(end), - contentType, optionalArgc, - getter_AddRefs(rtnBlob)))) { + if (NS_FAILED(blob->Slice(static_cast(start), + static_cast(end), + contentType, optionalArgc, + getter_AddRefs(rtnBlob)))) { ThrowFileExceptionForCode(aCx, FILE_NOT_READABLE_ERR); return false; } @@ -230,7 +230,7 @@ JSPropertySpec Blob::sProperties[] = { }; JSFunctionSpec Blob::sFunctions[] = { - JS_FN("mozSlice", MozSlice, 1, JSPROP_ENUMERATE), + JS_FN("slice", Slice, 1, JSPROP_ENUMERATE), JS_FS_END }; diff --git a/dom/workers/test/Makefile.in b/dom/workers/test/Makefile.in index e3c610caa700..27a7138b0451 100644 --- a/dom/workers/test/Makefile.in +++ b/dom/workers/test/Makefile.in @@ -136,21 +136,21 @@ _CHROME_TEST_FILES = \ test_extension.xul \ test_extensionBootstrap.xul \ test_file.xul \ - test_fileMozSlice.xul \ + test_fileSlice.xul \ test_fileBlobPosting.xul \ test_filePosting.xul \ test_fileReaderSync.xul \ test_fileReaderSyncErrors.xul \ - test_fileReadMozSlice.xul \ + test_fileReadSlice.xul \ test_fileSubWorker.xul \ test_fileBlobSubWorker.xul \ file_worker.js \ fileBlob_worker.js \ - fileMozSlice_worker.js \ + fileSlice_worker.js \ filePosting_worker.js \ fileReaderSync_worker.js \ fileReaderSyncErrors_worker.js \ - fileReadMozSlice_worker.js \ + fileReadSlice_worker.js \ fileSubWorker_worker.js \ fileBlobSubWorker_worker.js \ WorkerTest.jsm \ diff --git a/dom/workers/test/fileReadMozSlice_worker.js b/dom/workers/test/fileReadSlice_worker.js similarity index 89% rename from dom/workers/test/fileReadMozSlice_worker.js rename to dom/workers/test/fileReadSlice_worker.js index 659eb1eca282..2c10b7d7633e 100644 --- a/dom/workers/test/fileReadMozSlice_worker.js +++ b/dom/workers/test/fileReadSlice_worker.js @@ -7,7 +7,7 @@ onmessage = function(event) { var start = event.data.start; var end = event.data.end; - var slicedBlob = blob.mozSlice(start, end); + var slicedBlob = blob.slice(start, end); var fileReader = new FileReaderSync(); var text = fileReader.readAsText(slicedBlob); diff --git a/dom/workers/test/fileMozSlice_worker.js b/dom/workers/test/fileSlice_worker.js similarity index 81% rename from dom/workers/test/fileMozSlice_worker.js rename to dom/workers/test/fileSlice_worker.js index edeb82def54d..d0c6364e2e24 100644 --- a/dom/workers/test/fileMozSlice_worker.js +++ b/dom/workers/test/fileSlice_worker.js @@ -11,11 +11,11 @@ onmessage = function(event) { var slicedBlob; if (contentType == undefined && end == undefined) { - slicedBlob = blob.mozSlice(start); + slicedBlob = blob.slice(start); } else if (contentType == undefined) { - slicedBlob = blob.mozSlice(start, end); + slicedBlob = blob.slice(start, end); } else { - slicedBlob = blob.mozSlice(start, end, contentType); + slicedBlob = blob.slice(start, end, contentType); } var rtnObj = new Object(); diff --git a/dom/workers/test/test_fileBlobPosting.xul b/dom/workers/test/test_fileBlobPosting.xul index c849f0261597..7537e9332a4f 100644 --- a/dom/workers/test/test_fileBlobPosting.xul +++ b/dom/workers/test/test_fileBlobPosting.xul @@ -70,7 +70,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=664783 finish(); }; - var blob = file.mozSlice(); + var blob = file.slice(); worker.postMessage(blob); waitForWorkerFinish(); } diff --git a/dom/workers/test/test_fileBlobSubWorker.xul b/dom/workers/test/test_fileBlobSubWorker.xul index d2cf4e113e5f..eda8daac8cf6 100644 --- a/dom/workers/test/test_fileBlobSubWorker.xul +++ b/dom/workers/test/test_fileBlobSubWorker.xul @@ -72,7 +72,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=664783 finish(); }; - var blob = file.mozSlice(); + var blob = file.slice(); worker.postMessage(blob); waitForWorkerFinish(); } diff --git a/dom/workers/test/test_fileReadMozSlice.xul b/dom/workers/test/test_fileReadSlice.xul similarity index 85% rename from dom/workers/test/test_fileReadMozSlice.xul rename to dom/workers/test/test_fileReadSlice.xul index c701585179f6..6249613a9439 100644 --- a/dom/workers/test/test_fileReadMozSlice.xul +++ b/dom/workers/test/test_fileReadSlice.xul @@ -36,7 +36,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=664783 var testFile = Components.classes["@mozilla.org/file/directory_service;1"] .getService(Components.interfaces.nsIProperties) .get("ProfD", Components.interfaces.nsIFile); - testFile.append("workerReadMozSlice" + fileNum++); + testFile.append("workerReadSlice" + fileNum++); var outStream = Components.classes["@mozilla.org/network/file-output-stream;1"] .createInstance(Components.interfaces.nsIFileOutputStream); @@ -55,8 +55,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=664783 * Creates a worker which slices a blob to the given start and end offset and * reads the content as text. */ - function readMozSlice(blob, start, end, expectedText) { - var worker = new Worker("fileReadMozSlice_worker.js"); + function readSlice(blob, start, end, expectedText) { + var worker = new Worker("fileReadSlice_worker.js"); worker.onerror = function(event) { ok(false, "Worker had an error: " + event.data); @@ -74,16 +74,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=664783 } // Empty file. - readMozSlice(createFileWithData(""), 0, 0, ""); + readSlice(createFileWithData(""), 0, 0, ""); // Typical use case. - readMozSlice(createFileWithData("HelloBye"), 5, 8, "Bye"); + readSlice(createFileWithData("HelloBye"), 5, 8, "Bye"); // End offset too large. - readMozSlice(createFileWithData("HelloBye"), 5, 9, "Bye"); + readSlice(createFileWithData("HelloBye"), 5, 9, "Bye"); // Start of file. - readMozSlice(createFileWithData("HelloBye"), 0, 5, "Hello"); + readSlice(createFileWithData("HelloBye"), 0, 5, "Hello"); ]]> diff --git a/dom/workers/test/test_fileMozSlice.xul b/dom/workers/test/test_fileSlice.xul similarity index 80% rename from dom/workers/test/test_fileMozSlice.xul rename to dom/workers/test/test_fileSlice.xul index 05240b03d83a..7756acd87b60 100644 --- a/dom/workers/test/test_fileMozSlice.xul +++ b/dom/workers/test/test_fileSlice.xul @@ -37,7 +37,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=664783 .getService(Components.interfaces.nsIProperties) .get("ProfD", Components.interfaces.nsIFile); var fileExtension = (extension == undefined) ? "" : "." + extension; - testFile.append("workerMozSlice" + fileNum++ + fileExtension); + testFile.append("workerSlice" + fileNum++ + fileExtension); var outStream = Components.classes["@mozilla.org/network/file-output-stream;1"] .createInstance(Components.interfaces.nsIFileOutputStream); @@ -56,8 +56,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=664783 * Starts a worker which slices the blob to the given start offset and optional end offset and * content type. It then verifies that the size and type of the sliced blob is correct. */ - function createMozSlice(blob, start, expectedLength, /** optional */ end, /** optional */ contentType) { - var worker = new Worker("fileMozSlice_worker.js"); + function createSlice(blob, start, expectedLength, /** optional */ end, /** optional */ contentType) { + var worker = new Worker("fileSlice_worker.js"); worker.onerror = function(event) { ok(false, "Worker had an error: " + event.data); @@ -76,30 +76,30 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=664783 } // Empty file. - createMozSlice(createFileWithData(""), 0, 0, 0); + createSlice(createFileWithData(""), 0, 0, 0); // Typical use case. - createMozSlice(createFileWithData("Hello"), 1, 1, 2); + createSlice(createFileWithData("Hello"), 1, 1, 2); // Longish file. var text = ""; for (var i = 0; i < 10000; ++i) { text += "long"; } - createMozSlice(createFileWithData(text), 2000, 2000, 4000); + createSlice(createFileWithData(text), 2000, 2000, 4000); // Slice to different type. - createMozSlice(createFileWithData("text", "txt"), 0, 2, 2, "image/png"); + createSlice(createFileWithData("text", "txt"), 0, 2, 2, "image/png"); // Length longer than blob. - createMozSlice(createFileWithData("text"), 0, 4, 20); + createSlice(createFileWithData("text"), 0, 4, 20); // Start longer than blob. - createMozSlice(createFileWithData("text"), 20, 0, 4); + createSlice(createFileWithData("text"), 20, 0, 4); // No optional arguments - createMozSlice(createFileWithData("text"), 0, 4); - createMozSlice(createFileWithData("text"), 2, 2); + createSlice(createFileWithData("text"), 0, 4); + createSlice(createFileWithData("text"), 2, 2); ]]> From 0253ae147230697ffcdfdf0be9abdc49eedfd066 Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Thu, 16 Feb 2012 11:23:34 +0100 Subject: [PATCH 24/93] Bug 721498 - Use remote timestamp when available for focus requests. r=karlt --- toolkit/components/remote/nsGTKRemoteService.cpp | 9 +++++---- widget/gtk2/nsWindow.cpp | 14 +++++++++++++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/toolkit/components/remote/nsGTKRemoteService.cpp b/toolkit/components/remote/nsGTKRemoteService.cpp index 4c8c3c3026ea..9da8f057a867 100644 --- a/toolkit/components/remote/nsGTKRemoteService.cpp +++ b/toolkit/components/remote/nsGTKRemoteService.cpp @@ -164,19 +164,20 @@ nsGTKRemoteService::Shutdown() // Set desktop startup ID to the passed ID, if there is one, so that any created // windows get created with the right window manager metadata, and any windows // that get new tabs and are activated also get the right WM metadata. -// If there is no desktop startup ID, then use the X event's timestamp -// for _NET_ACTIVE_WINDOW when the window gets focused or shown. +// The timestamp will be used if there is no desktop startup ID, or if we're +// raising an existing window rather than showing a new window for the first time. void nsGTKRemoteService::SetDesktopStartupIDOrTimestamp(const nsACString& aDesktopStartupID, PRUint32 aTimestamp) { nsGTKToolkit* toolkit = nsGTKToolkit::GetToolkit(); if (!toolkit) return; + if (!aDesktopStartupID.IsEmpty()) { toolkit->SetDesktopStartupID(aDesktopStartupID); - } else { - toolkit->SetFocusTimestamp(aTimestamp); } + + toolkit->SetFocusTimestamp(aTimestamp); } diff --git a/widget/gtk2/nsWindow.cpp b/widget/gtk2/nsWindow.cpp index 6ef9829e12e2..9d77d274a883 100644 --- a/widget/gtk2/nsWindow.cpp +++ b/widget/gtk2/nsWindow.cpp @@ -1438,6 +1438,9 @@ SetUserTimeAndStartupIDForActivatedWindow(GtkWidget* aWindow) sn_display_unref(snd); #endif + // If we used the startup ID, that already contains the focus timestamp; + // we don't want to reuse the timestamp next time we raise the window + GTKToolkit->SetFocusTimestamp(0); GTKToolkit->SetDesktopStartupID(EmptyCString()); } @@ -1501,11 +1504,20 @@ nsWindow::SetFocus(bool aRaise) if (gRaiseWindows && owningWindow->mIsShown && owningWindow->mShell && !gtk_window_is_active(GTK_WINDOW(owningWindow->mShell))) { + PRUint32 timestamp = GDK_CURRENT_TIME; + + nsGTKToolkit* GTKToolkit = nsGTKToolkit::GetToolkit(); + if (GTKToolkit) + timestamp = GTKToolkit->GetFocusTimestamp(); + LOGFOCUS((" requesting toplevel activation [%p]\n", (void *)this)); NS_ASSERTION(owningWindow->mWindowType != eWindowType_popup || mParent, "Presenting an override-redirect window"); - gtk_window_present(GTK_WINDOW(owningWindow->mShell)); + gtk_window_present_with_time(GTK_WINDOW(owningWindow->mShell), timestamp); + + if (GTKToolkit) + GTKToolkit->SetFocusTimestamp(0); } return NS_OK; From 3ddbeef61e6c488cb9053680b4933ba71a2e406c Mon Sep 17 00:00:00 2001 From: David Rajchenbach-Teller Date: Thu, 16 Feb 2012 01:17:02 +0100 Subject: [PATCH 25/93] Bug 727435 - Implementing MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT. r=Waldo --HG-- extra : rebase_source : 4fcf555106b06b0080d2986102f6d84d3ae8fd4d --- mfbt/GuardObjects.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mfbt/GuardObjects.h b/mfbt/GuardObjects.h index 2e50405b062d..68d5eb35d068 100644 --- a/mfbt/GuardObjects.h +++ b/mfbt/GuardObjects.h @@ -163,6 +163,8 @@ class MOZ_EXPORT_API(GuardObjectNotificationReceiver) , const mozilla::detail::GuardObjectNotifier& _notifier # define MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT \ , _notifier +# define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT \ + _notifier # define MOZ_GUARD_OBJECT_NOTIFIER_INIT \ do { _mCheckNotUsedAsTemporary.init(_notifier); } while (0) #else @@ -170,6 +172,7 @@ class MOZ_EXPORT_API(GuardObjectNotificationReceiver) # define MOZ_GUARD_OBJECT_NOTIFIER_PARAM # define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM # define MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL +# define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT # define MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT # define MOZ_GUARD_OBJECT_NOTIFIER_INIT do { } while (0) #endif From 410d2e06871a65f77e2495d177563b4b6e9006f8 Mon Sep 17 00:00:00 2001 From: Aryeh Gregor Date: Wed, 15 Feb 2012 16:31:40 -0500 Subject: [PATCH 26/93] Bug 655478 - CSSStyleDeclaration.setProperty shouldn't require the third parameter to be set; r=bzbarsky --HG-- extra : rebase_source : 131b879a0190c1979ee563cc102b5a548bf6986d --- dom/interfaces/css/nsIDOMCSSStyleDeclaration.idl | 2 +- layout/style/test/test_priority_preservation.html | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/dom/interfaces/css/nsIDOMCSSStyleDeclaration.idl b/dom/interfaces/css/nsIDOMCSSStyleDeclaration.idl index d50ddf86a499..83959e9f6ba4 100644 --- a/dom/interfaces/css/nsIDOMCSSStyleDeclaration.idl +++ b/dom/interfaces/css/nsIDOMCSSStyleDeclaration.idl @@ -60,7 +60,7 @@ interface nsIDOMCSSStyleDeclaration : nsISupports DOMString getPropertyPriority(in DOMString propertyName); void setProperty(in DOMString propertyName, in DOMString value, - in DOMString priority) + [optional] in DOMString priority) raises(DOMException); readonly attribute unsigned long length; DOMString item(in unsigned long index); diff --git a/layout/style/test/test_priority_preservation.html b/layout/style/test/test_priority_preservation.html index 24f808320d4e..346f4390da6c 100644 --- a/layout/style/test/test_priority_preservation.html +++ b/layout/style/test/test_priority_preservation.html @@ -88,7 +88,8 @@ is(s.getPropertyPriority("z-index"), "", "z-index priority still stored"); // and overriding one element of that shorthand with some longhand -s.setProperty("font-style", "normal", ""); + // test omitting the third argument to setProperty too (bug 655478) +s.setProperty("font-style", "normal"); is(s.getPropertyValue("font-style"), "normal", "font-style overridden"); is(s.getPropertyPriority("font-style"), "", "font-style priority overridden"); From b3d16fbbbdb8a04c4abf1a54b855afd71505402e Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Fri, 20 Jan 2012 13:56:48 -0800 Subject: [PATCH 27/93] Bug 715927 - addon telemetry, C++ side; r=taras --HG-- extra : rebase_source : 21fc9e5dd98e4aa2ed09023a512df9e42bd1c4c9 --- toolkit/components/telemetry/Telemetry.cpp | 193 ++++++++++++++++++ toolkit/components/telemetry/nsITelemetry.idl | 58 +++++- 2 files changed, 248 insertions(+), 3 deletions(-) diff --git a/toolkit/components/telemetry/Telemetry.cpp b/toolkit/components/telemetry/Telemetry.cpp index e67bd740f391..6a2d3fadeaf0 100644 --- a/toolkit/components/telemetry/Telemetry.cpp +++ b/toolkit/components/telemetry/Telemetry.cpp @@ -146,6 +146,27 @@ private: bool ShouldReflectHistogram(Histogram *h); void IdentifyCorruptHistograms(StatisticsRecorder::Histograms &hs); typedef StatisticsRecorder::Histograms::iterator HistogramIterator; + + struct AddonHistogramInfo { + PRUint32 min; + PRUint32 max; + PRUint32 bucketCount; + PRUint32 histogramType; + Histogram *h; + }; + typedef nsBaseHashtableET AddonHistogramEntryType; + typedef AutoHashtable AddonHistogramMapType; + typedef nsBaseHashtableET AddonEntryType; + typedef AutoHashtable AddonMapType; + struct AddonEnumeratorArgs { + JSContext *cx; + JSObject *obj; + }; + static bool AddonHistogramReflector(AddonHistogramEntryType *entry, + JSContext *cx, JSObject *obj); + static bool AddonReflector(AddonEntryType *entry, JSContext *cx, JSObject *obj); + AddonMapType mAddonMap; + // This is used for speedy string->Telemetry::ID conversions typedef nsBaseHashtableET CharPtrEntryType; typedef AutoHashtable HistogramMapType; @@ -612,6 +633,111 @@ TelemetryImpl::ShouldReflectHistogram(Histogram *h) } } +// Compute the name to pass into Histogram for the addon histogram +// 'name' from the addon 'id'. We can't use 'name' directly because it +// might conflict with other histograms in other addons or even with our +// own. +void +AddonHistogramName(const nsACString &id, const nsACString &name, + nsACString &ret) +{ + ret.Append(id); + ret.Append(NS_LITERAL_CSTRING(":")); + ret.Append(name); +} + +NS_IMETHODIMP +TelemetryImpl::RegisterAddonHistogram(const nsACString &id, + const nsACString &name, + PRUint32 min, PRUint32 max, + PRUint32 bucketCount, + PRUint32 histogramType) +{ + AddonEntryType *addonEntry = mAddonMap.GetEntry(id); + if (!addonEntry) { + addonEntry = mAddonMap.PutEntry(id); + if (NS_UNLIKELY(!addonEntry)) { + return NS_ERROR_OUT_OF_MEMORY; + } + addonEntry->mData = new AddonHistogramMapType(); + } + + AddonHistogramMapType *histogramMap = addonEntry->mData; + AddonHistogramEntryType *histogramEntry = histogramMap->GetEntry(name); + // Can't re-register the same histogram. + if (histogramEntry) { + return NS_ERROR_FAILURE; + } + + histogramEntry = histogramMap->PutEntry(name); + if (NS_UNLIKELY(!histogramEntry)) { + return NS_ERROR_OUT_OF_MEMORY; + } + + AddonHistogramInfo &info = histogramEntry->mData; + info.min = min; + info.max = max; + info.bucketCount = bucketCount; + info.histogramType = histogramType; + + return NS_OK; +} + +NS_IMETHODIMP +TelemetryImpl::GetAddonHistogram(const nsACString &id, const nsACString &name, + JSContext *cx, jsval *ret) +{ + AddonEntryType *addonEntry = mAddonMap.GetEntry(id); + // The given id has not been registered. + if (!addonEntry) { + return NS_ERROR_INVALID_ARG; + } + + AddonHistogramMapType *histogramMap = addonEntry->mData; + AddonHistogramEntryType *histogramEntry = histogramMap->GetEntry(name); + // The given histogram name has not been registered. + if (!histogramEntry) { + return NS_ERROR_INVALID_ARG; + } + + AddonHistogramInfo &info = histogramEntry->mData; + Histogram *h; + if (info.h) { + h = info.h; + } else { + nsCAutoString actualName; + AddonHistogramName(id, name, actualName); + nsresult rv = HistogramGet(PromiseFlatCString(actualName).get(), + info.min, info.max, info.bucketCount, + info.histogramType, &h); + if (NS_FAILED(rv)) { + return rv; + } + // Don't let this histogram be reported via the normal means + // (e.g. Telemetry.registeredHistograms); we'll make it available in + // other ways. + h->ClearFlags(Histogram::kUmaTargetedHistogramFlag); + info.h = h; + } + return WrapAndReturnHistogram(h, cx, ret); +} + +NS_IMETHODIMP +TelemetryImpl::UnregisterAddonHistograms(const nsACString &id) +{ + AddonEntryType *addonEntry = mAddonMap.GetEntry(id); + if (addonEntry) { + // Histogram's destructor is private, so this is the best we can do. + // The histograms the addon created *will* stick around, but they + // will be deleted if and when the addon registers histograms with + // the same names. + delete addonEntry->mData; + mAddonMap.RemoveEntry(id); + } + + return NS_OK; +} + NS_IMETHODIMP TelemetryImpl::GetHistogramSnapshots(JSContext *cx, jsval *ret) { @@ -660,6 +786,73 @@ TelemetryImpl::GetHistogramSnapshots(JSContext *cx, jsval *ret) return NS_OK; } +bool +TelemetryImpl::AddonHistogramReflector(AddonHistogramEntryType *entry, + JSContext *cx, JSObject *obj) +{ + // Never even accessed the histogram. + if (!entry->mData.h) { + return true; + } + + JSObject *snapshot = JS_NewObject(cx, NULL, NULL, NULL); + js::AutoObjectRooter r(cx, snapshot); + switch (ReflectHistogramSnapshot(cx, snapshot, entry->mData.h)) { + case REFLECT_FAILURE: + case REFLECT_CORRUPT: + return false; + case REFLECT_OK: + const nsACString &histogramName = entry->GetKey(); + if (!JS_DefineProperty(cx, obj, + PromiseFlatCString(histogramName).get(), + OBJECT_TO_JSVAL(snapshot), NULL, NULL, + JSPROP_ENUMERATE)) { + return false; + } + break; + } + return true; +} + +bool +TelemetryImpl::AddonReflector(AddonEntryType *entry, + JSContext *cx, JSObject *obj) +{ + const nsACString &addonId = entry->GetKey(); + JSObject *subobj = JS_NewObject(cx, NULL, NULL, NULL); + if (!subobj) { + return false; + } + js::AutoObjectRooter r(cx, subobj); + + AddonHistogramMapType *map = entry->mData; + if (!(map->ReflectHashtable(AddonHistogramReflector, cx, subobj) + && JS_DefineProperty(cx, obj, + PromiseFlatCString(addonId).get(), + OBJECT_TO_JSVAL(subobj), NULL, NULL, + JSPROP_ENUMERATE))) { + return false; + } + return true; +} + +NS_IMETHODIMP +TelemetryImpl::GetAddonHistogramSnapshots(JSContext *cx, jsval *ret) +{ + *ret = JSVAL_VOID; + JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL); + if (!obj) { + return NS_ERROR_FAILURE; + } + js::AutoObjectRooter r(cx, obj); + + if (!mAddonMap.ReflectHashtable(AddonReflector, cx, obj)) { + return NS_ERROR_FAILURE; + } + *ret = OBJECT_TO_JSVAL(obj); + return NS_OK; +} + NS_IMETHODIMP TelemetryImpl::GetSlowSQL(JSContext *cx, jsval *ret) { diff --git a/toolkit/components/telemetry/nsITelemetry.idl b/toolkit/components/telemetry/nsITelemetry.idl index c86a07c2932f..0c0288eeed8b 100644 --- a/toolkit/components/telemetry/nsITelemetry.idl +++ b/toolkit/components/telemetry/nsITelemetry.idl @@ -58,7 +58,7 @@ interface nsITelemetry : nsISupports * where data is consists of the following properties: * min - Minimal bucket size * max - Maximum bucket size - * histogram_type - HISTOGRAM_EXPONENTIAL or HISTOGRAM_LINEAR + * histogram_type - HISTOGRAM_EXPONENTIAL, HISTOGRAM_LINEAR, or HISTOGRAM_BOOLEAN * counts - array representing contents of the buckets in the histogram * ranges - an array with calculated bucket sizes * sum - sum of the bucket contents @@ -94,13 +94,13 @@ interface nsITelemetry : nsISupports readonly attribute jsval registeredHistograms; /** - * Create and return a histogram where bucket sizes increase exponentially. Parameters: + * Create and return a histogram. Parameters: * * @param name Unique histogram name * @param min - Minimal bucket size * @param max - Maximum bucket size * @param bucket_count - number of buckets in the histogram. - * @param type - HISTOGRAM_EXPONENTIAL or HISTOGRAM_LINEAR + * @param type - HISTOGRAM_EXPONENTIAL, HISTOGRAM_LINEAR or HISTOGRAM_BOOLEAN * The returned object has the following functions: * add(int) - Adds an int value to the appropriate bucket * snapshot() - Returns a snapshot of the histogram with the same data fields as in histogramSnapshots() @@ -136,4 +136,56 @@ interface nsITelemetry : nsISupports * A flag indicating whether Telemetry can submit official results. */ readonly attribute boolean canSend; + + /** Addon telemetry hooks */ + + /** + * Register a histogram for an addon. Throws an error if the + * histogram name has been registered previously. + * + * @param addon_id - Unique ID of the addon + * @param name - Unique histogram name + * @param min - Minimal bucket size + * @param max - Maximum bucket size + * @param bucket_count - number of buckets in the histogram + * @param histogram_type - HISTOGRAM_EXPONENTIAL, HISTOGRAM_LINEAR, or + * HISTOGRAM_BOOLEAN + */ + void registerAddonHistogram(in ACString addon_id, in ACString name, + in PRUint32 min, in PRUint32 max, + in PRUint32 bucket_count, + in unsigned long histogram_type); + + /** + * Return a histogram previously registered via + * registerAddonHistogram. Throws an error if the id/name combo has + * not been registered via registerAddonHistogram. + * + * @param addon_id - Unique ID of the addon + * @param name - Registered histogram name + * + * The returned object has the same functions as a histogram returned + * from newHistogram. + */ + [implicit_jscontext] + jsval getAddonHistogram(in ACString addon_id, in ACString name); + + /** + * Delete all histograms associated with the given addon id. + * + * @param addon_id - Unique ID of the addon + */ + void unregisterAddonHistograms(in ACString addon_id); + + /** + * An object containing a snapshot from all of the currently + * registered addon histograms. + * { addon-id1 : data1, ... } + * + * where data is an object whose properties are the names of the + * addon's histograms and whose corresponding values are as in + * histogramSnapshots. + */ + [implicit_jscontext] + readonly attribute jsval addonHistogramSnapshots; }; From 174bc8b56557ee9c75c9e1833db57f74362452cc Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Fri, 20 Jan 2012 13:57:02 -0800 Subject: [PATCH 28/93] Bug 715927 - tests for addon telemetry; r=taras --HG-- extra : rebase_source : ad13ed4da8c50db5f94485177cd53cceb37b1555 --- .../telemetry/tests/unit/test_nsITelemetry.js | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/toolkit/components/telemetry/tests/unit/test_nsITelemetry.js b/toolkit/components/telemetry/tests/unit/test_nsITelemetry.js index e0711d7cedda..e7eca13bf57c 100644 --- a/toolkit/components/telemetry/tests/unit/test_nsITelemetry.js +++ b/toolkit/components/telemetry/tests/unit/test_nsITelemetry.js @@ -52,6 +52,17 @@ function expect_fail(f) { do_check_true(failed); } +function expect_success(f) { + let succeeded = false; + try { + f(); + succeeded = true; + } catch (e) { + succeeded = false; + } + do_check_true(succeeded); +} + function test_boolean_histogram() { var h = Telemetry.newHistogram("test::boolean histogram", 99,1,4, Telemetry.HISTOGRAM_BOOLEAN); @@ -93,6 +104,78 @@ function test_getSlowSQL() { do_check_true(("mainThread" in slow) && ("otherThreads" in slow)); } +function test_addons() { + var addon_id = "testing-addon"; + var fake_addon_id = "fake-addon"; + var name1 = "testing-histogram1"; + var register = Telemetry.registerAddonHistogram; + expect_success(function () + register(addon_id, name1, 1, 5, 6, Telemetry.HISTOGRAM_LINEAR)); + // Can't register the same histogram multiple times. + expect_fail(function () + register(addon_id, name1, 1, 5, 6, Telemetry.HISTOGRAM_LINEAR)); + // Make sure we can't get at it with another name. + expect_fail(function () Telemetry.getAddonHistogram(fake_addon_id, name1)); + + // Check for reflection capabilities. + var h1 = Telemetry.getAddonHistogram(addon_id, name1); + h1.add(1); + h1.add(3); + var s1 = h1.snapshot(); + do_check_eq(s1.histogram_type, Telemetry.HISTOGRAM_LINEAR); + do_check_eq(s1.min, 1); + do_check_eq(s1.max, 5); + do_check_eq(s1.counts[1], 1); + do_check_eq(s1.counts[3], 1); + + var name2 = "testing-histogram2"; + expect_success(function () + register(addon_id, name2, 2, 4, 4, Telemetry.HISTOGRAM_LINEAR)); + + var h2 = Telemetry.getAddonHistogram(addon_id, name2); + h2.add(2); + h2.add(3); + var s2 = h2.snapshot(); + do_check_eq(s2.histogram_type, Telemetry.HISTOGRAM_LINEAR); + do_check_eq(s2.min, 2); + do_check_eq(s2.max, 4); + do_check_eq(s2.counts[1], 1); + do_check_eq(s2.counts[2], 1); + + // Check that we can register histograms for a different addon with + // identical names. + var extra_addon = "testing-extra-addon"; + expect_success(function () + register(extra_addon, name1, 0, 1, 2, Telemetry.HISTOGRAM_BOOLEAN)); + + // Check that we reflect registered addons and histograms. + snapshots = Telemetry.addonHistogramSnapshots; + do_check_true(addon_id in snapshots) + do_check_true(extra_addon in snapshots); + + // Check that we have data for our created histograms. + do_check_true(name1 in snapshots[addon_id]); + do_check_true(name2 in snapshots[addon_id]); + var s1_alt = snapshots[addon_id][name1]; + var s2_alt = snapshots[addon_id][name2]; + do_check_eq(s1_alt.min, s1.min); + do_check_eq(s1_alt.max, s1.max); + do_check_eq(s1_alt.histogram_type, s1.histogram_type); + do_check_eq(s2_alt.min, s2.min); + do_check_eq(s2_alt.max, s2.max); + do_check_eq(s2_alt.histogram_type, s2.histogram_type); + + // Even though we've registered it, it shouldn't show up until data is added to it. + do_check_false(name1 in snapshots[extra_addon]); + + // Check that we can remove addon histograms. + Telemetry.unregisterAddonHistograms(addon_id); + snapshots = Telemetry.addonHistogramSnapshots; + do_check_false(addon_id in snapshots); + // Make sure other addons are unaffected. + do_check_true(extra_addon in snapshots); +} + // Check that telemetry doesn't record in private mode function test_privateMode() { var h = Telemetry.newHistogram("test::private_mode_boolean", 1,2,3, Telemetry.HISTOGRAM_BOOLEAN); @@ -121,4 +204,5 @@ function run_test() test_getHistogramById(); test_getSlowSQL(); test_privateMode(); + test_addons(); } From 92df66d69daf95c11a9bba358e449b10d1974735 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Wed, 25 Jan 2012 09:23:38 -0800 Subject: [PATCH 29/93] Bug 715927 - separate packHistogram into its own function; r=taras --HG-- extra : rebase_source : d00ea49793c4d2e5ffb37649ee55f71394276ed6 --- toolkit/components/telemetry/TelemetryPing.js | 91 ++++++++++--------- 1 file changed, 50 insertions(+), 41 deletions(-) diff --git a/toolkit/components/telemetry/TelemetryPing.js b/toolkit/components/telemetry/TelemetryPing.js index 405a15b96882..86763856bbda 100644 --- a/toolkit/components/telemetry/TelemetryPing.js +++ b/toolkit/components/telemetry/TelemetryPing.js @@ -187,57 +187,66 @@ TelemetryPing.prototype = { _slowSQLStartup: {}, /** - * Returns a set of histograms that can be converted into JSON - * @return a snapshot of the histograms of form: - * { histogram_name: {range:[minvalue,maxvalue], bucket_count:, - * histogram_type: <0 for exponential, 1 for linear>, bucketX:countX, ....} ...} - * where bucket[XY], count[XY] are positive integers. + * When reflecting a histogram into JS, Telemetry hands us an object + * with the following properties: + * + * - min, max, histogram_type, sum: simple integers; + * - counts: array of counts for histogram buckets; + * - ranges: array of calculated bucket sizes. + * + * This format is not straightforward to read and potentially bulky + * with lots of zeros in the counts array. Packing histograms makes + * raw histograms easier to read and compresses the data a little bit. + * + * Returns an object: + * { range: [min, max], bucket_count: , + * histogram_type: , sum: + * values: { bucket1: count1, bucket2: count2, ... } } */ + packHistogram: function packHistogram(hgram) { + let r = hgram.ranges;; + let c = hgram.counts; + let retgram = { + range: [r[1], r[r.length - 1]], + bucket_count: r.length, + histogram_type: hgram.histogram_type, + values: {}, + sum: hgram.sum + }; + let first = true; + let last = 0; + + for (let i = 0; i < c.length; i++) { + let value = c[i]; + if (!value) + continue; + + // add a lower bound + if (i && first) { + retgram.values[r[i - 1]] = 0; + } + first = false; + last = i + 1; + retgram.values[r[i]] = value; + } + + // add an upper bound + if (last && last < c.length) + retgram.values[r[last]] = 0; + return retgram; + }, + getHistograms: function getHistograms() { let hls = Telemetry.histogramSnapshots; let info = Telemetry.registeredHistograms; let ret = {}; - function processHistogram(name, hgram) { - let r = hgram.ranges;; - let c = hgram.counts; - let retgram = { - range: [r[1], r[r.length - 1]], - bucket_count: r.length, - histogram_type: hgram.histogram_type, - values: {}, - sum: hgram.sum - }; - let first = true; - let last = 0; - - for (let i = 0; i < c.length; i++) { - let value = c[i]; - if (!value) - continue; - - // add a lower bound - if (i && first) { - first = false; - retgram.values[r[i - 1]] = 0; - } - first = false; - last = i + 1; - retgram.values[r[i]] = value; - } - - // add an upper bound - if (last && last < c.length) - retgram.values[r[last]] = 0; - ret[name] = retgram; - }; - for (let name in hls) { if (info[name]) { - processHistogram(name, hls[name]); + ret[name] = this.packHistogram(hls[name]); let startup_name = "STARTUP_" + name; if (hls[startup_name]) - processHistogram(startup_name, hls[startup_name]); + ret[startup_name] = this.packHistogram(hls[startup_name]); } } From 45f5b5e9d604c448fb7602b5ae7840d10e7d45e5 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Wed, 25 Jan 2012 09:24:08 -0800 Subject: [PATCH 30/93] Bug 715927 - report addon histograms in telemetry pings; r=taras --HG-- extra : rebase_source : fba9951ede4da2e114d72ff6fd4ea564825eceeb --- toolkit/components/telemetry/TelemetryPing.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/toolkit/components/telemetry/TelemetryPing.js b/toolkit/components/telemetry/TelemetryPing.js index 86763856bbda..4673b3011b38 100644 --- a/toolkit/components/telemetry/TelemetryPing.js +++ b/toolkit/components/telemetry/TelemetryPing.js @@ -1,3 +1,4 @@ +/* -*- indent-tabs-mode: nil -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -253,6 +254,17 @@ TelemetryPing.prototype = { return ret; }, + getAddonHistograms: function getAddonHistograms() { + let ahs = Telemetry.addonHistogramSnapshots; + let ret = {}; + + for (let name in ahs) { + ret[name] = this.convertHistogram(ahs[name]); + } + + return ret; + }, + addValue: function addValue(name, id, val) { let h = this._histograms[name]; if (!h) { @@ -425,7 +437,8 @@ TelemetryPing.prototype = { info: this.getMetadata(reason), simpleMeasurements: getSimpleMeasurements(), histograms: this.getHistograms(), - slowSQL: Telemetry.slowSQL + slowSQL: Telemetry.slowSQL, + addonHistograms: this.getAddonHistograms() }; if (Object.keys(this._slowSQLStartup.mainThread).length || Object.keys(this._slowSQLStartup.otherThreads).length) { From 635a192024222c3e47cafcd7c042be1ebdab111f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A3o=20Gottwald?= Date: Thu, 16 Feb 2012 12:43:08 +0100 Subject: [PATCH 31/93] Bug 725289 followup, replace remaining mozSlize with slice --- content/base/test/fileutils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/base/test/fileutils.js b/content/base/test/fileutils.js index 5693be02f3cb..67ba18989b4c 100644 --- a/content/base/test/fileutils.js +++ b/content/base/test/fileutils.js @@ -272,7 +272,7 @@ function testSlice(file, size, type, contents, fileType) { testFile(slice.slice(5000, 42000), contents.slice(5000, 40000), "file slice slice"); // ...of slice of slice - slice = slice.slice(5000, 42000).mozSlice(400, 700); + slice = slice.slice(5000, 42000).slice(400, 700); SpecialPowers.gc(); testFile(slice, contents.slice(5400, 5700), "file slice slice slice"); } From 8f4c1c22db0253c49896a7821a61c51146ad0fdf Mon Sep 17 00:00:00 2001 From: Igor Bukanov Date: Fri, 10 Feb 2012 13:40:34 +0100 Subject: [PATCH 32/93] bug 725595 - drop native object checks from JS_(Get|Set)ReservedSlot. r=Waldo --- js/src/jsapi.cpp | 11 ++--------- js/src/jsobj.cpp | 6 +++--- js/src/jsproxy.cpp | 7 +++++-- js/src/jsproxy.h | 10 ---------- 4 files changed, 10 insertions(+), 24 deletions(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index a214c1f67581..8e1bb1769ee1 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4415,20 +4415,13 @@ JS_ElementIteratorStub(JSContext *cx, JSObject *obj, JSBool keysonly) JS_PUBLIC_API(jsval) JS_GetReservedSlot(JSObject *obj, uint32_t index) { - if (!obj->isNative()) - return UndefinedValue(); - - return GetReservedSlot(obj, index); + return obj->getReservedSlot(index); } JS_PUBLIC_API(void) JS_SetReservedSlot(JSObject *obj, uint32_t index, jsval v) { - if (!obj->isNative()) - return; - - SetReservedSlot(obj, index, v); - GCPoke(obj->compartment()->rt, NullValue()); + obj->setReservedSlot(index, v); } JS_PUBLIC_API(JSObject *) diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 5fd9286f900d..8f921b8f9ad0 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -3595,7 +3595,7 @@ DefineStandardSlot(JSContext *cx, JSObject *obj, JSProtoKey key, JSAtom *atom, const Shape *shape = obj->nativeLookup(cx, id); if (!shape) { uint32_t slot = 2 * JSProto_LIMIT + key; - SetReservedSlot(obj, slot, v); + obj->setReservedSlot(slot, v); if (!obj->addProperty(cx, id, JS_PropertyStub, JS_StrictPropertyStub, slot, attrs, 0, 0)) return false; AddTypePropertyId(cx, obj, id, v); @@ -3618,8 +3618,8 @@ SetClassObject(JSObject *obj, JSProtoKey key, JSObject *cobj, JSObject *proto) if (!obj->isGlobal()) return; - SetReservedSlot(obj, key, ObjectOrNullValue(cobj)); - SetReservedSlot(obj, JSProto_LIMIT + key, ObjectOrNullValue(proto)); + obj->setReservedSlot(key, ObjectOrNullValue(cobj)); + obj->setReservedSlot(JSProto_LIMIT + key, ObjectOrNullValue(proto)); } static void diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index 599c125ded60..77bb3afc61cb 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -92,6 +92,9 @@ OperationInProgress(JSContext *cx, JSObject *proxy) return false; } +static bool +FixProxy(JSContext *cx, JSObject *proxy, JSBool *bp); + ProxyHandler::ProxyHandler(void *family) : mFamily(family) { } @@ -1735,8 +1738,8 @@ Class js::CallableObjectClass = { callable_Construct, }; -JS_FRIEND_API(JSBool) -js::FixProxy(JSContext *cx, JSObject *proxy, JSBool *bp) +static bool +FixProxy(JSContext *cx, JSObject *proxy, JSBool *bp) { if (OperationInProgress(cx, proxy)) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_PROXY_FIX); diff --git a/js/src/jsproxy.h b/js/src/jsproxy.h index baf5a4e86cbc..4a37f634543f 100644 --- a/js/src/jsproxy.h +++ b/js/src/jsproxy.h @@ -183,13 +183,6 @@ GetProxyPrivate(const JSObject *obj) return GetReservedSlot(obj, JSSLOT_PROXY_PRIVATE); } -inline void -SetProxyPrivate(JSObject *obj, const Value &priv) -{ - JS_ASSERT(IsProxy(obj)); - SetReservedSlot(obj, JSSLOT_PROXY_PRIVATE, priv); -} - inline const Value & GetProxyExtra(const JSObject *obj, size_t n) { @@ -210,9 +203,6 @@ NewProxyObject(JSContext *cx, ProxyHandler *handler, const Value &priv, JSObject *proto, JSObject *parent, JSObject *call = NULL, JSObject *construct = NULL); -JS_FRIEND_API(JSBool) -FixProxy(JSContext *cx, JSObject *proxy, JSBool *bp); - } /* namespace js */ JS_BEGIN_EXTERN_C From f738baa87be47bc4b6af9827896660e8b0ff5bc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Thu, 16 Feb 2012 07:03:53 -0500 Subject: [PATCH 33/93] Bug 721603 - We should spin the loop after calling asyncClose in Database.cpp. r=mak. --HG-- extra : rebase_source : 3defc8d4da90de3f1c4738ec7e56faff6afec521 --- toolkit/components/places/Database.cpp | 48 ++++++++++++++++++++++++-- toolkit/components/places/Helpers.cpp | 10 +----- toolkit/components/places/Helpers.h | 2 -- 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/toolkit/components/places/Database.cpp b/toolkit/components/places/Database.cpp index afbac50a248e..4071e18b993a 100644 --- a/toolkit/components/places/Database.cpp +++ b/toolkit/components/places/Database.cpp @@ -251,6 +251,49 @@ SetJournalMode(nsCOMPtr& aDBConn, return JOURNAL_DELETE; } +class BlockingConnectionCloseCallback : public mozIStorageCompletionCallback { + bool mDone; + +public: + NS_DECL_ISUPPORTS + NS_DECL_MOZISTORAGECOMPLETIONCALLBACK + BlockingConnectionCloseCallback(); + void Spin(); +}; + +NS_IMETHODIMP +BlockingConnectionCloseCallback::Complete() +{ + mDone = true; + nsCOMPtr os = mozilla::services::GetObserverService(); + MOZ_ASSERT(os); + if (!os) + return NS_OK; + DebugOnly rv = os->NotifyObservers(nsnull, + TOPIC_PLACES_CONNECTION_CLOSED, + nsnull); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + return NS_OK; +} + +BlockingConnectionCloseCallback::BlockingConnectionCloseCallback() + : mDone(false) +{ + MOZ_ASSERT(NS_IsMainThread()); +} + +void BlockingConnectionCloseCallback::Spin() { + nsCOMPtr thread = do_GetCurrentThread(); + while (!mDone) { + NS_ProcessNextEvent(thread); + } +} + +NS_IMPL_THREADSAFE_ISUPPORTS1( + BlockingConnectionCloseCallback +, mozIStorageCompletionCallback +) + nsresult CreateRoot(nsCOMPtr& aDBConn, const nsCString& aRootName, @@ -1672,9 +1715,10 @@ Database::Shutdown() ); DispatchToAsyncThread(event); - nsRefPtr closeListener = - new PlacesEvent(TOPIC_PLACES_CONNECTION_CLOSED); + nsRefPtr closeListener = + new BlockingConnectionCloseCallback(); (void)mMainConn->AsyncClose(closeListener); + closeListener->Spin(); // Don't set this earlier, otherwise some internal helper used on shutdown // may bail out. diff --git a/toolkit/components/places/Helpers.cpp b/toolkit/components/places/Helpers.cpp index 6e70f2dcfd0d..0f6f7499dce7 100644 --- a/toolkit/components/places/Helpers.cpp +++ b/toolkit/components/places/Helpers.cpp @@ -400,13 +400,6 @@ PlacesEvent::Run() return NS_OK; } -NS_IMETHODIMP -PlacesEvent::Complete() -{ - Notify(); - return NS_OK; -} - void PlacesEvent::Notify() { @@ -417,9 +410,8 @@ PlacesEvent::Notify() } } -NS_IMPL_THREADSAFE_ISUPPORTS2( +NS_IMPL_THREADSAFE_ISUPPORTS1( PlacesEvent -, mozIStorageCompletionCallback , nsIRunnable ) diff --git a/toolkit/components/places/Helpers.h b/toolkit/components/places/Helpers.h index a8d00f26f3e0..ebfeb5e4ba8f 100644 --- a/toolkit/components/places/Helpers.h +++ b/toolkit/components/places/Helpers.h @@ -247,12 +247,10 @@ bool GetHiddenState(bool aIsRedirect, * Notifies a specified topic via the observer service. */ class PlacesEvent : public nsRunnable - , public mozIStorageCompletionCallback { public: NS_DECL_ISUPPORTS NS_DECL_NSIRUNNABLE - NS_DECL_MOZISTORAGECOMPLETIONCALLBACK PlacesEvent(const char* aTopic); protected: From 3dcaefdb54ad3bc803f3ad67830a2d2e03f94ea4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Thu, 16 Feb 2012 07:23:41 -0500 Subject: [PATCH 34/93] Bug 683975 - Need infra for developer contributed compilers. r=rail. downgrade glibc to 2.11.1. --- build/unix/build-toolchain/build-gcc.py | 49 ++++++++++++++++--------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/build/unix/build-toolchain/build-gcc.py b/build/unix/build-toolchain/build-gcc.py index 3b46b6742e30..84635a64b631 100755 --- a/build/unix/build-toolchain/build-gcc.py +++ b/build/unix/build-toolchain/build-gcc.py @@ -1,5 +1,18 @@ #!/usr/bin/python +# 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" +aux_inst_dir = build_dir + '/aux_inst' +old_make = aux_inst_dir + '/bin/make' + +############################################## + import urllib import os import os.path @@ -33,17 +46,21 @@ def patch(patch, plevel, srcdir): check_run(['patch', '-d', srcdir, '-p%s' % plevel, '-i', patch, '--fuzz=0', '-s']) -def build_package(package_source_dir, package_build_dir, configure_args): +def build_package(package_source_dir, package_build_dir, configure_args, + make = old_make): os.mkdir(package_build_dir) run_in(package_build_dir, ["%s/configure" % package_source_dir] + configure_args) - run_in(package_build_dir, ["make", "-j8"]) - run_in(package_build_dir, ["make", "install"]) + run_in(package_build_dir, [make, "-j8"]) + run_in(package_build_dir, [make, "install"]) -def build_tar(base_dir, tar_inst_dir): +def build_aux_tools(base_dir): + make_build_dir = base_dir + '/make_build' + build_package(make_source_dir, make_build_dir, + ["--prefix=%s" % aux_inst_dir], "make") tar_build_dir = base_dir + '/tar_build' build_package(tar_source_dir, tar_build_dir, - ["--prefix=%s" % tar_inst_dir]) + ["--prefix=%s" % aux_inst_dir]) def with_env(env, f): old_env = os.environ.copy() @@ -133,21 +150,13 @@ def build_tar_package(tar, name, base, directory): ############################################## -# 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 binutils_version = "2.21.1" -glibc_version = "2.12.2" #FIXME: should probably use 2.5.1 +glibc_version = "2.11.1" #FIXME: should probably use 2.5.1 tar_version = "1.26" +make_version = "3.81" gcc_version = "4.5.2" mpfr_version = "2.4.2" gmp_version = "5.0.1" @@ -159,6 +168,8 @@ glibc_source_uri = "http://ftp.gnu.org/gnu/glibc/glibc-%s.tar.bz2" % \ glibc_version tar_source_uri = "http://ftp.gnu.org/gnu/tar/tar-%s.tar.bz2" % \ tar_version +make_source_uri = "http://ftp.gnu.org/gnu/make/make-%s.tar.bz2" % \ + make_version gcc_source_uri = "http://ftp.gnu.org/gnu/gcc/gcc-%s/gcc-%s.tar.bz2" % \ (gcc_version, gcc_version) mpfr_source_uri = "http://www.mpfr.org/mpfr-%s/mpfr-%s.tar.bz2" % \ @@ -170,6 +181,7 @@ mpc_source_uri = "http://www.multiprecision.org/mpc/download/mpc-%s.tar.gz" % \ binutils_source_tar = download_uri(binutils_source_uri) glibc_source_tar = download_uri(glibc_source_uri) tar_source_tar = download_uri(tar_source_uri) +make_source_tar = download_uri(make_source_uri) mpc_source_tar = download_uri(mpc_source_uri) mpfr_source_tar = download_uri(mpfr_source_uri) gmp_source_tar = download_uri(gmp_source_uri) @@ -178,6 +190,7 @@ gcc_source_tar = download_uri(gcc_source_uri) 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) +make_source_dir = build_source_dir('make-', make_version) mpc_source_dir = build_source_dir('mpc-', mpc_version) mpfr_source_dir = build_source_dir('mpfr-', mpfr_version) gmp_source_dir = build_source_dir('gmp-', gmp_version) @@ -191,6 +204,7 @@ if not os.path.exists(source_dir): patch('glibc-deterministic.patch', 1, glibc_source_dir) run_in(glibc_source_dir, ["autoconf"]) extract(tar_source_tar, source_dir) + extract(make_source_tar, source_dir) extract(mpc_source_tar, source_dir) extract(mpfr_source_tar, source_dir) extract(gmp_source_tar, source_dir) @@ -203,8 +217,7 @@ if os.path.exists(build_dir): shutil.rmtree(build_dir) os.makedirs(build_dir) -tar_inst_dir = build_dir + '/tar_inst' -build_tar(build_dir, tar_inst_dir) +build_aux_tools(build_dir) stage1_dir = build_dir + '/stage1' build_one_stage({"CC": "gcc", "CXX" : "g++"}, stage1_dir, True) @@ -217,5 +230,5 @@ build_one_stage({"CC" : stage1_tool_inst_dir + "/bin/gcc", "RANLIB" : "true" }, stage2_dir, False) -build_tar_package(tar_inst_dir + "/bin/tar", +build_tar_package(aux_inst_dir + "/bin/tar", "toolchain.tar", stage2_dir, "inst") From 1bf8b5c3a9fe6c042dd4710a21abd82cb0c0415b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Thu, 16 Feb 2012 08:20:51 -0500 Subject: [PATCH 35/93] Bug 727220 - Fix _CGLContextObject's forward declaration. r=jrmuizel. --- gfx/thebes/nsIOSurface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx/thebes/nsIOSurface.h b/gfx/thebes/nsIOSurface.h index 621e0b1eda4e..f71a75d534a0 100644 --- a/gfx/thebes/nsIOSurface.h +++ b/gfx/thebes/nsIOSurface.h @@ -44,7 +44,7 @@ #import class gfxASurface; -class _CGLContextObject; +struct _CGLContextObject; typedef _CGLContextObject* CGLContextObj; typedef uint32_t IOSurfaceID; From ff6085b93f0a11185b3fd4ee48773b986b8d086c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Thu, 16 Feb 2012 08:24:18 -0500 Subject: [PATCH 36/93] Bug 727226 - mark some classes in content/canvas/src final. r=:jrmuizel. --- content/canvas/src/WebGLContext.h | 18 +++++++++--------- .../canvas/src/nsCanvasRenderingContext2D.cpp | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/content/canvas/src/WebGLContext.h b/content/canvas/src/WebGLContext.h index 5a709d0c1ea3..1b99c250bf56 100644 --- a/content/canvas/src/WebGLContext.h +++ b/content/canvas/src/WebGLContext.h @@ -1024,7 +1024,7 @@ struct WebGLVertexAttribData { } }; -class WebGLBuffer +class WebGLBuffer MOZ_FINAL : public nsIWebGLBuffer , public WebGLRefCountedObject , public WebGLContextBoundObject @@ -1158,7 +1158,7 @@ protected: void* mData; // in the case of an Element Array Buffer, we keep a copy. }; -class WebGLTexture +class WebGLTexture MOZ_FINAL : public nsIWebGLTexture , public WebGLRefCountedObject , public WebGLContextBoundObject @@ -1608,7 +1608,7 @@ public: } }; -class WebGLShader +class WebGLShader MOZ_FINAL : public nsIWebGLShader , public WebGLRefCountedObject , public WebGLContextBoundObject @@ -1673,7 +1673,7 @@ protected: WebGLMonotonicHandle mMonotonicHandle; }; -class WebGLProgram +class WebGLProgram MOZ_FINAL : public nsIWebGLProgram , public WebGLRefCountedObject , public WebGLContextBoundObject @@ -1795,7 +1795,7 @@ protected: WebGLMonotonicHandle mMonotonicHandle; }; -class WebGLRenderbuffer +class WebGLRenderbuffer MOZ_FINAL : public nsIWebGLRenderbuffer , public WebGLRefCountedObject , public WebGLRectangleObject @@ -2001,7 +2001,7 @@ public: } }; -class WebGLFramebuffer +class WebGLFramebuffer MOZ_FINAL : public nsIWebGLFramebuffer , public WebGLRefCountedObject , public WebGLContextBoundObject @@ -2296,7 +2296,7 @@ public: WebGLMonotonicHandle mMonotonicHandle; }; -class WebGLUniformLocation +class WebGLUniformLocation MOZ_FINAL : public nsIWebGLUniformLocation , public WebGLContextBoundObject , public WebGLRefCountedObject @@ -2337,7 +2337,7 @@ protected: friend class WebGLProgram; }; -class WebGLActiveInfo +class WebGLActiveInfo MOZ_FINAL : public nsIWebGLActiveInfo { public: @@ -2356,7 +2356,7 @@ protected: nsString mName; }; -class WebGLShaderPrecisionFormat +class WebGLShaderPrecisionFormat MOZ_FINAL : public nsIWebGLShaderPrecisionFormat { public: diff --git a/content/canvas/src/nsCanvasRenderingContext2D.cpp b/content/canvas/src/nsCanvasRenderingContext2D.cpp index b159d7efbf78..7b4fa8b7f3a6 100644 --- a/content/canvas/src/nsCanvasRenderingContext2D.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp @@ -180,7 +180,7 @@ CopyContext(gfxContext* dest, gfxContext* src) **/ #define NS_CANVASGRADIENT_PRIVATE_IID \ { 0x491d39d8, 0x4058, 0x42bd, { 0xac, 0x76, 0x70, 0xd5, 0x62, 0x7f, 0x02, 0x10 } } -class nsCanvasGradient : public nsIDOMCanvasGradient +class nsCanvasGradient MOZ_FINAL : public nsIDOMCanvasGradient { public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_CANVASGRADIENT_PRIVATE_IID) @@ -238,7 +238,7 @@ NS_INTERFACE_MAP_END **/ #define NS_CANVASPATTERN_PRIVATE_IID \ { 0xb85c6c8a, 0x0624, 0x4530, { 0xb8, 0xee, 0xff, 0xdf, 0x42, 0xe8, 0x21, 0x6d } } -class nsCanvasPattern : public nsIDOMCanvasPattern +class nsCanvasPattern MOZ_FINAL : public nsIDOMCanvasPattern { public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_CANVASPATTERN_PRIVATE_IID) From b4a0973d6845c16744490678a3a40f176da33fad Mon Sep 17 00:00:00 2001 From: Gian-Carlo Pascutto Date: Mon, 13 Feb 2012 17:09:16 +0100 Subject: [PATCH 37/93] Bug 726002 - More OOM handling in UrlClassifier. r=dcamp --- .../components/url-classifier/LookupCache.cpp | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/toolkit/components/url-classifier/LookupCache.cpp b/toolkit/components/url-classifier/LookupCache.cpp index 9702385b68ab..6763af41452f 100644 --- a/toolkit/components/url-classifier/LookupCache.cpp +++ b/toolkit/components/url-classifier/LookupCache.cpp @@ -174,6 +174,9 @@ nsresult LookupCache::Build(const AddPrefixArray& aAddPrefixes, const AddCompleteArray& aAddCompletes) { + Telemetry::Accumulate(Telemetry::URLCLASSIFIER_LC_COMPLETIONS, + static_cast(aAddCompletes.Length())); + mCompletions.Clear(); mCompletions.SetCapacity(aAddCompletes.Length()); for (uint32 i = 0; i < aAddCompletes.Length(); i++) { @@ -181,16 +184,13 @@ LookupCache::Build(const AddPrefixArray& aAddPrefixes, } mCompletions.Sort(); - Telemetry::Accumulate(Telemetry::URLCLASSIFIER_LC_COMPLETIONS, - static_cast(mCompletions.Length())); + Telemetry::Accumulate(Telemetry::URLCLASSIFIER_LC_PREFIXES, + static_cast(aAddPrefixes.Length())); nsresult rv = ConstructPrefixSet(aAddPrefixes); NS_ENSURE_SUCCESS(rv, rv); mPrimed = true; - Telemetry::Accumulate(Telemetry::URLCLASSIFIER_LC_PREFIXES, - static_cast(aAddPrefixes.Length())); - return NS_OK; } @@ -683,8 +683,12 @@ LookupCache::ConstructPrefixSet(const AddPrefixArray& aAddPrefixes) { Telemetry::AutoTimer timer; - nsTArray array; - array.SetCapacity(aAddPrefixes.Length()); + FallibleTArray array; + nsresult rv; + if (!array.SetCapacity(aAddPrefixes.Length())) { + rv = NS_ERROR_OUT_OF_MEMORY; + goto error_bailout; + } for (uint32 i = 0; i < aAddPrefixes.Length(); i++) { array.AppendElement(aAddPrefixes[i].PrefixHash().ToUint32()); @@ -699,7 +703,7 @@ LookupCache::ConstructPrefixSet(const AddPrefixArray& aAddPrefixes) array.Sort(); // construct new one, replace old entries - nsresult rv = mPrefixSet->SetPrefixes(array.Elements(), array.Length()); + rv = mPrefixSet->SetPrefixes(array.Elements(), array.Length()); if (NS_FAILED(rv)) { goto error_bailout; } From a6a2f1971c259ae0adad4255c32d26343befc48e Mon Sep 17 00:00:00 2001 From: Gian-Carlo Pascutto Date: Mon, 13 Feb 2012 17:10:22 +0100 Subject: [PATCH 38/93] Bug 726002 - Clear some big nsTArrays as early as possible in updates. r=dcamp --- toolkit/components/url-classifier/Classifier.cpp | 1 + toolkit/components/url-classifier/HashStore.h | 8 ++++---- toolkit/components/url-classifier/LookupCache.cpp | 9 +++++---- toolkit/components/url-classifier/LookupCache.h | 10 ++++++---- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/toolkit/components/url-classifier/Classifier.cpp b/toolkit/components/url-classifier/Classifier.cpp index 51231f16288a..d0afcd7b3c79 100644 --- a/toolkit/components/url-classifier/Classifier.cpp +++ b/toolkit/components/url-classifier/Classifier.cpp @@ -531,6 +531,7 @@ Classifier::ApplyTableUpdates(nsTArray* aUpdates, NS_ENSURE_SUCCESS(rv, rv); rv = store->AugmentAdds(AddPrefixHashes); NS_ENSURE_SUCCESS(rv, rv); + AddPrefixHashes.Clear(); uint32 applied = 0; bool updateFreshness = false; diff --git a/toolkit/components/url-classifier/HashStore.h b/toolkit/components/url-classifier/HashStore.h index fca2d2aa27ce..e832cb9e35ba 100644 --- a/toolkit/components/url-classifier/HashStore.h +++ b/toolkit/components/url-classifier/HashStore.h @@ -120,10 +120,10 @@ public: ChunkSet& AddChunks() { return mAddChunks; } ChunkSet& SubChunks() { return mSubChunks; } - const AddPrefixArray& AddPrefixes() const { return mAddPrefixes; } - const AddCompleteArray& AddCompletes() const { return mAddCompletes; } - const SubPrefixArray& SubPrefixes() const { return mSubPrefixes; } - const SubCompleteArray& SubCompletes() const { return mSubCompletes; } + AddPrefixArray& AddPrefixes() { return mAddPrefixes; } + AddCompleteArray& AddCompletes() { return mAddCompletes; } + SubPrefixArray& SubPrefixes() { return mSubPrefixes; } + SubCompleteArray& SubCompletes() { return mSubCompletes; } // ======= // Updates diff --git a/toolkit/components/url-classifier/LookupCache.cpp b/toolkit/components/url-classifier/LookupCache.cpp index 6763af41452f..ef70f7b568e2 100644 --- a/toolkit/components/url-classifier/LookupCache.cpp +++ b/toolkit/components/url-classifier/LookupCache.cpp @@ -171,8 +171,8 @@ LookupCache::Reset() nsresult -LookupCache::Build(const AddPrefixArray& aAddPrefixes, - const AddCompleteArray& aAddCompletes) +LookupCache::Build(AddPrefixArray& aAddPrefixes, + AddCompleteArray& aAddCompletes) { Telemetry::Accumulate(Telemetry::URLCLASSIFIER_LC_COMPLETIONS, static_cast(aAddCompletes.Length())); @@ -182,6 +182,7 @@ LookupCache::Build(const AddPrefixArray& aAddPrefixes, for (uint32 i = 0; i < aAddCompletes.Length(); i++) { mCompletions.AppendElement(aAddCompletes[i].CompleteHash()); } + aAddCompletes.Clear(); mCompletions.Sort(); Telemetry::Accumulate(Telemetry::URLCLASSIFIER_LC_PREFIXES, @@ -679,7 +680,7 @@ bool LookupCache::IsPrimed() } nsresult -LookupCache::ConstructPrefixSet(const AddPrefixArray& aAddPrefixes) +LookupCache::ConstructPrefixSet(AddPrefixArray& aAddPrefixes) { Telemetry::AutoTimer timer; @@ -693,8 +694,8 @@ LookupCache::ConstructPrefixSet(const AddPrefixArray& aAddPrefixes) for (uint32 i = 0; i < aAddPrefixes.Length(); i++) { array.AppendElement(aAddPrefixes[i].PrefixHash().ToUint32()); } + aAddPrefixes.Clear(); - // clear old tree if (array.IsEmpty()) { // DB is empty, but put a sentinel to show that we looked array.AppendElement(0); diff --git a/toolkit/components/url-classifier/LookupCache.h b/toolkit/components/url-classifier/LookupCache.h index 5ba07d5fe099..ba50701b1a9a 100644 --- a/toolkit/components/url-classifier/LookupCache.h +++ b/toolkit/components/url-classifier/LookupCache.h @@ -137,8 +137,9 @@ public: nsresult Init(); nsresult Open(); - nsresult Build(const AddPrefixArray& aAddPrefixes, - const AddCompleteArray& aAddCompletes); + // This will Clear() the passed arrays when done. + nsresult Build(AddPrefixArray& aAddPrefixes, + AddCompleteArray& aAddCompletes); nsresult GetPrefixes(nsTArray* aAddPrefixes); #if DEBUG && defined(PR_LOGGING) @@ -160,9 +161,10 @@ private: nsresult ReadHeader(); nsresult EnsureSizeConsistent(); nsresult ReadCompletions(); - // Construct a Prefix Set with known prefixes nsresult LoadPrefixSet(); - nsresult ConstructPrefixSet(const AddPrefixArray& aAddPrefixes); + // Construct a Prefix Set with known prefixes. + // This will Clear() aAddPrefixes when done. + nsresult ConstructPrefixSet(AddPrefixArray& aAddPrefixes); struct Header { uint32 magic; From 5a53e8d92ef008bd3c6488c43f87793a9ea6d7da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A3o=20Gottwald?= Date: Thu, 16 Feb 2012 14:26:14 +0100 Subject: [PATCH 39/93] Bug 727793 - Status panel tracks the mouse position on the wrong side when using a RTL locale. r=mak --HG-- extra : rebase_source : 67e64830d3ea3789bbd2fc2663867470855067f7 --- browser/base/content/tabbrowser.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index 01982adfbf8f..1148f8a5e741 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -4060,7 +4060,7 @@ let alignRight = false; if (getComputedStyle(document.documentElement).direction == "rtl") - alighRight = !alignRight; + alignRight = !alignRight; let rect = this.getBoundingClientRect(); this._mouseTargetRect = { From 4f7befc144efa0fccca108f25abe73a8ef367698 Mon Sep 17 00:00:00 2001 From: Daniel Levin Date: Thu, 16 Feb 2012 14:29:05 +0100 Subject: [PATCH 40/93] Bug 710973 - Validate aYResolution in PresShell::SetResolution, don't validate aXResolution twice. r=tn --HG-- extra : rebase_source : 995ad8ddd8edac814bc2bfb8dd3891430b8704cb --- layout/base/nsPresShell.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 606c92add155..ffe4bc85d19b 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -5214,7 +5214,7 @@ void PresShell::SetDisplayPort(const nsRect& aDisplayPort) nsresult PresShell::SetResolution(float aXResolution, float aYResolution) { - if (!(aXResolution > 0.0 && aXResolution > 0.0)) { + if (!(aXResolution > 0.0 && aYResolution > 0.0)) { return NS_ERROR_ILLEGAL_VALUE; } if (aXResolution == mXResolution && aYResolution == mYResolution) { From ca639d81bb791605a6b123d32af7741f7459d8ff Mon Sep 17 00:00:00 2001 From: Aryeh Gregor Date: Thu, 16 Feb 2012 14:30:34 +0100 Subject: [PATCH 41/93] Bug 724750 - 3D transform backface-visibility has no effect when applied to an element with display:table. r=roc --HG-- rename : layout/reftests/transform-3d/backface-visibility-1b.html => layout/reftests/transform-3d/backface-visibility-1c.html extra : rebase_source : 8e878d9729f49b3adc0107b6760f618b8025f390 --- layout/reftests/transform-3d/backface-visibility-1c.html | 9 +++++++++ layout/reftests/transform-3d/reftest.list | 1 + layout/style/ua.css | 2 ++ 3 files changed, 12 insertions(+) create mode 100644 layout/reftests/transform-3d/backface-visibility-1c.html diff --git a/layout/reftests/transform-3d/backface-visibility-1c.html b/layout/reftests/transform-3d/backface-visibility-1c.html new file mode 100644 index 000000000000..6129b443e027 --- /dev/null +++ b/layout/reftests/transform-3d/backface-visibility-1c.html @@ -0,0 +1,9 @@ + + + + +
+ Test Text +
+ + diff --git a/layout/reftests/transform-3d/reftest.list b/layout/reftests/transform-3d/reftest.list index 31e4e7070704..be2b27f1f4a8 100644 --- a/layout/reftests/transform-3d/reftest.list +++ b/layout/reftests/transform-3d/reftest.list @@ -31,6 +31,7 @@ fails-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == preserve3d-1a.html preser == rotate3d-2a.html rotatey-1-ref.html != backface-visibility-1a.html about:blank == backface-visibility-1b.html about:blank +== backface-visibility-1c.html about:blank != perspective-origin-1a.html rotatex-perspective-1a.html == perspective-origin-1b.html perspective-origin-1a.html == perspective-origin-2a.html perspective-origin-2-ref.html diff --git a/layout/style/ua.css b/layout/style/ua.css index edfb8582d35a..de336a9a1e7f 100644 --- a/layout/style/ua.css +++ b/layout/style/ua.css @@ -77,6 +77,8 @@ /* Bug 722777 */ -moz-transform: inherit; -moz-transform-origin: inherit; + /* Bug 724750 */ + -moz-backface-visibility: inherit; } *|*::-moz-table-row { From 3e0d245944d37bf904c058e639cfbe36999699e6 Mon Sep 17 00:00:00 2001 From: "Brian R. Bondy" Date: Thu, 16 Feb 2012 08:49:24 -0500 Subject: [PATCH 42/93] Bug 726481 - Reduce calls to nsLocalFileWin's IsDirectory by not calling it when enumerating directories. r=neil --- xpcom/io/nsLocalFileWin.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/xpcom/io/nsLocalFileWin.cpp b/xpcom/io/nsLocalFileWin.cpp index e41573ea46be..2ab691c43c8b 100644 --- a/xpcom/io/nsLocalFileWin.cpp +++ b/xpcom/io/nsLocalFileWin.cpp @@ -261,6 +261,9 @@ static nsresult ConvertWinError(DWORD winErr) case ERROR_FILENAME_EXCED_RANGE: rv = NS_ERROR_FILE_NAME_TOO_LONG; break; + case ERROR_DIRECTORY: + rv = NS_ERROR_FILE_NOT_DIRECTORY; + break; case 0: rv = NS_OK; break; @@ -490,10 +493,12 @@ OpenDir(const nsAFlatString &name, nsDir * *dir) filename.ReplaceChar(L'/', L'\\'); + // FindFirstFileW Will have a last error of ERROR_DIRECTORY if + // \* is passed in. If \* is passed in then + // ERROR_PATH_NOT_FOUND will be the last error. d->handle = ::FindFirstFileW(filename.get(), &(d->data) ); - if ( d->handle == INVALID_HANDLE_VALUE ) - { + if (d->handle == INVALID_HANDLE_VALUE) { PR_Free(d); return ConvertWinError(GetLastError()); } @@ -589,6 +594,8 @@ class nsDirEnumerator : public nsISimpleEnumerator, return NS_ERROR_UNEXPECTED; } + // IsDirectory is not needed here because OpenDir will return + // NS_ERROR_FILE_NOT_DIRECTORY if the passed in path is a file. nsresult rv = OpenDir(filepath, &mDir); if (NS_FAILED(rv)) return rv; @@ -2736,13 +2743,6 @@ nsLocalFile::GetDirectoryEntries(nsISimpleEnumerator * *entries) return NS_OK; } - bool isDir; - rv = IsDirectory(&isDir); - if (NS_FAILED(rv)) - return rv; - if (!isDir) - return NS_ERROR_FILE_NOT_DIRECTORY; - nsDirEnumerator* dirEnum = new nsDirEnumerator(); if (dirEnum == nsnull) return NS_ERROR_OUT_OF_MEMORY; From b2c6eef529aa7c767c7624bcab442691a69bd924 Mon Sep 17 00:00:00 2001 From: "Brian R. Bondy" Date: Thu, 16 Feb 2012 08:55:19 -0500 Subject: [PATCH 43/93] Bug 726503 - FILE_FLAG_SEQUENTIAL_SCAN always being passed for all file IO. r=taras --- xpcom/io/nsLocalFileWin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xpcom/io/nsLocalFileWin.cpp b/xpcom/io/nsLocalFileWin.cpp index 2ab691c43c8b..67823c4af307 100644 --- a/xpcom/io/nsLocalFileWin.cpp +++ b/xpcom/io/nsLocalFileWin.cpp @@ -380,7 +380,7 @@ OpenFile(const nsAFlatString &name, PRIntn osflags, PRIntn mode, flag6 |= FILE_FLAG_DELETE_ON_CLOSE; } - if (osflags && nsILocalFile::OS_READAHEAD) { + if (osflags & nsILocalFile::OS_READAHEAD) { flag6 |= FILE_FLAG_SEQUENTIAL_SCAN; } From 5b0c52860f77721bda9ea50a3541626841e17d7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Thu, 16 Feb 2012 09:39:57 -0500 Subject: [PATCH 44/93] Bug 727221 - mark LastDictionary and nsElementDeletionObserver final. r=ehsan. --- editor/composer/src/nsEditorSpellCheck.cpp | 2 +- editor/libeditor/html/nsHTMLAnonymousUtils.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/editor/composer/src/nsEditorSpellCheck.cpp b/editor/composer/src/nsEditorSpellCheck.cpp index 3778f8f0a31a..5eed950c5e40 100644 --- a/editor/composer/src/nsEditorSpellCheck.cpp +++ b/editor/composer/src/nsEditorSpellCheck.cpp @@ -83,7 +83,7 @@ class UpdateDictionnaryHolder { #define CPS_PREF_NAME NS_LITERAL_STRING("spellcheck.lang") -class LastDictionary { +class LastDictionary MOZ_FINAL { public: /** * Store current dictionary for editor document url. Use content pref diff --git a/editor/libeditor/html/nsHTMLAnonymousUtils.cpp b/editor/libeditor/html/nsHTMLAnonymousUtils.cpp index b84725db8810..923bfbd2fe91 100644 --- a/editor/libeditor/html/nsHTMLAnonymousUtils.cpp +++ b/editor/libeditor/html/nsHTMLAnonymousUtils.cpp @@ -102,7 +102,7 @@ static PRInt32 GetCSSFloatValue(nsIDOMCSSStyleDeclaration * aDecl, return (PRInt32) f; } -class nsElementDeletionObserver : public nsIMutationObserver +class nsElementDeletionObserver MOZ_FINAL : public nsIMutationObserver { public: nsElementDeletionObserver(nsINode* aNativeAnonNode, nsINode* aObservedNode) From b028fa644656e660c825912a555edc5e9df8fe0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Thu, 16 Feb 2012 09:53:08 -0500 Subject: [PATCH 45/93] Bug 727145 - Pass -Wno-return-type-c-linkage to clang. r=glandium. --- aclocal.m4 | 1 + build/autoconf/compiler-opts.m4 | 13 +++++++++++++ configure.in | 1 + js/src/aclocal.m4 | 1 + js/src/build/autoconf/compiler-opts.m4 | 13 +++++++++++++ js/src/configure.in | 1 + 6 files changed, 30 insertions(+) create mode 100644 build/autoconf/compiler-opts.m4 create mode 100644 js/src/build/autoconf/compiler-opts.m4 diff --git a/aclocal.m4 b/aclocal.m4 index fc58446c9dcf..77f9452fb6c7 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -17,6 +17,7 @@ builtin(include, build/autoconf/acwinpaths.m4)dnl builtin(include, build/autoconf/lto.m4)dnl builtin(include, build/autoconf/gcc-pr49911.m4)dnl builtin(include, build/autoconf/frameptr.m4)dnl +builtin(include, build/autoconf/compiler-opts.m4)dnl MOZ_PROG_CHECKMSYS() diff --git a/build/autoconf/compiler-opts.m4 b/build/autoconf/compiler-opts.m4 new file mode 100644 index 000000000000..0c2fd2a0b1a4 --- /dev/null +++ b/build/autoconf/compiler-opts.m4 @@ -0,0 +1,13 @@ +dnl Add compiler specific options + +AC_DEFUN([MOZ_COMPILER_OPTS], +[ +if test "$CLANG_CXX"; then + ## We disable return-type-c-linkage because jsval is defined as a C++ type but is + ## returned by C functions. This is possible because we use knowledge about the ABI + ## to typedef it to a C type with the same layout when the headers are included + ## from C. + _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-return-type-c-linkage" +fi +]) + diff --git a/configure.in b/configure.in index 4d9a187c4614..889068270eec 100644 --- a/configure.in +++ b/configure.in @@ -3343,6 +3343,7 @@ AC_SUBST(WRAP_SYSTEM_INCLUDES) AC_SUBST(VISIBILITY_FLAGS) MOZ_GCC_PR49911 +MOZ_COMPILER_OPTS dnl Check for __force_align_arg_pointer__ for SSE2 on gcc dnl ======================================================== diff --git a/js/src/aclocal.m4 b/js/src/aclocal.m4 index b826fcbe4715..cd5b6727cfa6 100644 --- a/js/src/aclocal.m4 +++ b/js/src/aclocal.m4 @@ -14,5 +14,6 @@ builtin(include, build/autoconf/acwinpaths.m4)dnl builtin(include, build/autoconf/lto.m4)dnl builtin(include, build/autoconf/gcc-pr49911.m4)dnl builtin(include, build/autoconf/frameptr.m4)dnl +builtin(include, build/autoconf/compiler-opts.m4)dnl MOZ_PROG_CHECKMSYS() diff --git a/js/src/build/autoconf/compiler-opts.m4 b/js/src/build/autoconf/compiler-opts.m4 new file mode 100644 index 000000000000..0c2fd2a0b1a4 --- /dev/null +++ b/js/src/build/autoconf/compiler-opts.m4 @@ -0,0 +1,13 @@ +dnl Add compiler specific options + +AC_DEFUN([MOZ_COMPILER_OPTS], +[ +if test "$CLANG_CXX"; then + ## We disable return-type-c-linkage because jsval is defined as a C++ type but is + ## returned by C functions. This is possible because we use knowledge about the ABI + ## to typedef it to a C type with the same layout when the headers are included + ## from C. + _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-return-type-c-linkage" +fi +]) + diff --git a/js/src/configure.in b/js/src/configure.in index d663c46d8461..adde2e68dd0c 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -3133,6 +3133,7 @@ AC_SUBST(WRAP_SYSTEM_INCLUDES) AC_SUBST(VISIBILITY_FLAGS) MOZ_GCC_PR49911 +MOZ_COMPILER_OPTS dnl Check for __force_align_arg_pointer__ for SSE2 on gcc dnl ======================================================== From 5244ac7e302372e431e1d3e57b221ce28e58cb52 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Sat, 11 Feb 2012 03:34:00 -0500 Subject: [PATCH 46/93] Bug 698519 - Update libjpeg-turbo to version 1.2.0. r=jlebar --- config/autoconf.mk.in | 1 + configure.in | 29 +- media/libjpeg/MOZCHANGES | 36 +- media/libjpeg/Makefile.in | 27 +- media/libjpeg/README | 19 +- media/libjpeg/README-turbo.txt | 181 ++- media/libjpeg/cderror.h | 134 -- media/libjpeg/cdjpeg.h | 187 --- media/libjpeg/config.h | 6 + media/libjpeg/jaricom.c | 1 + media/libjpeg/jccolext.c | 114 ++ media/libjpeg/jccolor.c | 324 ++-- media/libjpeg/jcdctmgr.c | 2 +- media/libjpeg/jchuff.c | 338 +++-- media/libjpeg/jcmainct.c | 90 +- media/libjpeg/jcmaster.c | 2 + media/libjpeg/jconfig.h | 29 +- media/libjpeg/jconfig.h.in | 60 - media/libjpeg/jcparam.c | 6 +- media/libjpeg/jctrans.c | 399 +++++ media/libjpeg/jdcolext.c | 104 ++ media/libjpeg/jdcolor.c | 233 ++- media/libjpeg/jdhuff.c | 339 +++-- media/libjpeg/jdhuff.h | 51 +- media/libjpeg/jdmainct.c | 124 +- media/libjpeg/jdmarker.c | 6 +- media/libjpeg/jdmaster.c | 12 +- media/libjpeg/jdmerge.c | 276 ++-- media/libjpeg/jdmrgext.c | 156 ++ media/libjpeg/jdtrans.c | 5 + media/libjpeg/jerror.h | 19 + media/libjpeg/jmemmgr.c | 15 +- media/libjpeg/jmorecfg.h | 54 +- media/libjpeg/jpegint.h | 2 +- media/libjpeg/jpeglib.h | 18 +- media/libjpeg/jsimd.h | 8 + media/libjpeg/jsimd_none.c | 15 +- media/libjpeg/jutils.c | 4 +- media/libjpeg/jversion.h | 16 +- media/libjpeg/mozilla.diff | 70 + media/libjpeg/simd/jcclrmmx.asm | 2 - media/libjpeg/simd/jcclrss2-64.asm | 2 - media/libjpeg/simd/jcclrss2.asm | 2 - media/libjpeg/simd/jccolmmx.asm | 51 +- media/libjpeg/simd/jccolss2-64.asm | 51 +- media/libjpeg/simd/jccolss2.asm | 51 +- media/libjpeg/simd/jcgrammx.asm | 116 ++ media/libjpeg/simd/jcgrass2-64.asm | 113 ++ media/libjpeg/simd/jcgrass2.asm | 113 ++ media/libjpeg/simd/jcgrymmx.asm | 357 +++++ media/libjpeg/simd/jcgryss2-64.asm | 364 +++++ media/libjpeg/simd/jcgryss2.asm | 383 +++++ media/libjpeg/simd/jdclrmmx.asm | 2 - media/libjpeg/simd/jdclrss2-64.asm | 55 +- media/libjpeg/simd/jdclrss2.asm | 55 +- media/libjpeg/simd/jdcolmmx.asm | 51 +- media/libjpeg/simd/jdcolss2-64.asm | 51 +- media/libjpeg/simd/jdcolss2.asm | 51 +- media/libjpeg/simd/jdmermmx.asm | 51 +- media/libjpeg/simd/jdmerss2-64.asm | 51 +- media/libjpeg/simd/jdmerss2.asm | 51 +- media/libjpeg/simd/jdmrgmmx.asm | 2 - media/libjpeg/simd/jdmrgss2-64.asm | 55 +- media/libjpeg/simd/jdmrgss2.asm | 55 +- media/libjpeg/simd/jsimd.h | 172 ++- media/libjpeg/simd/jsimd_arm.c | 670 +++++++++ media/libjpeg/simd/jsimd_arm_neon.S | 2159 +++++++++++++++++++++++++++ media/libjpeg/simd/jsimd_i386.c | 95 +- media/libjpeg/simd/jsimd_x86_64.c | 74 +- media/libjpeg/simd/jsimdcfg.inc | 25 + media/libjpeg/simd/jsimdcfg.inc.h | 168 --- media/libjpeg/simd/jsimdext.inc | 18 +- media/libjpeg/transupp.h | 210 --- 73 files changed, 7448 insertions(+), 1790 deletions(-) delete mode 100644 media/libjpeg/cderror.h delete mode 100644 media/libjpeg/cdjpeg.h create mode 100644 media/libjpeg/config.h create mode 100644 media/libjpeg/jccolext.c delete mode 100644 media/libjpeg/jconfig.h.in create mode 100644 media/libjpeg/jctrans.c create mode 100644 media/libjpeg/jdcolext.c create mode 100644 media/libjpeg/jdmrgext.c create mode 100644 media/libjpeg/mozilla.diff create mode 100644 media/libjpeg/simd/jcgrammx.asm create mode 100644 media/libjpeg/simd/jcgrass2-64.asm create mode 100644 media/libjpeg/simd/jcgrass2.asm create mode 100644 media/libjpeg/simd/jcgrymmx.asm create mode 100644 media/libjpeg/simd/jcgryss2-64.asm create mode 100644 media/libjpeg/simd/jcgryss2.asm create mode 100644 media/libjpeg/simd/jsimd_arm.c create mode 100644 media/libjpeg/simd/jsimd_arm_neon.S delete mode 100644 media/libjpeg/simd/jsimdcfg.inc.h delete mode 100644 media/libjpeg/transupp.h diff --git a/config/autoconf.mk.in b/config/autoconf.mk.in index b8d954ccc17e..debabccf6794 100644 --- a/config/autoconf.mk.in +++ b/config/autoconf.mk.in @@ -181,6 +181,7 @@ LIBJPEG_TURBO_AS = @LIBJPEG_TURBO_AS@ LIBJPEG_TURBO_ASFLAGS = @LIBJPEG_TURBO_ASFLAGS@ LIBJPEG_TURBO_X86_ASM = @LIBJPEG_TURBO_X86_ASM@ LIBJPEG_TURBO_X64_ASM = @LIBJPEG_TURBO_X64_ASM@ +LIBJPEG_TURBO_ARM_ASM = @LIBJPEG_TURBO_ARM_ASM@ NS_PRINTING = @NS_PRINTING@ MOZ_PDF_PRINTING = @MOZ_PDF_PRINTING@ MOZ_CRASHREPORTER = @MOZ_CRASHREPORTER@ diff --git a/configure.in b/configure.in index 889068270eec..2b8b976e981a 100644 --- a/configure.in +++ b/configure.in @@ -4613,6 +4613,7 @@ LIBJPEG_TURBO_AS= LIBJPEG_TURBO_ASFLAGS= LIBJPEG_TURBO_X86_ASM= LIBJPEG_TURBO_X64_ASM= +LIBJPEG_TURBO_ARM_ASM= MOZ_PANGO=1 MOZ_PERMISSIONS=1 MOZ_PLACES=1 @@ -6172,38 +6173,51 @@ if test -n "$MOZ_LIBJPEG_TURBO"; then LIBJPEG_TURBO_ASFLAGS="-f win64 -rnasm -pnasm -D__x86_64__ -DPIC -DWIN64 -DMSVC" LIBJPEG_TURBO_X64_ASM=1 ;; + *:arm*) + LIBJPEG_TURBO_ASFLAGS="-march=armv7-a -mfpu=neon" + LIBJPEG_TURBO_ARM_ASM=1 + ;; esac fi -dnl If we're on a system which supports libjpeg-turbo's asm routines and -dnl --disable-libjpeg-turbo wasn't passed, check for yasm, and error out if it -dnl doesn't exist or we have too old of a version. +dnl If we're on an x86 or x64 system which supports libjpeg-turbo's asm routines +dnl and --disable-libjpeg-turbo wasn't passed, check for Yasm, and error out if +dnl it doesn't exist or we have too old of a version. if test -n "$LIBJPEG_TURBO_X86_ASM" -o -n "$LIBJPEG_TURBO_X64_ASM" ; then - AC_MSG_CHECKING([for YASM assembler]) + AC_MSG_CHECKING([for Yasm assembler]) AC_CHECK_PROGS(LIBJPEG_TURBO_AS, yasm, "") if test -z "$LIBJPEG_TURBO_AS" ; then - AC_MSG_ERROR([yasm is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you do not appear to have yasm installed. Either install it or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder. See https://developer.mozilla.org/en/YASM for more details.]) + AC_MSG_ERROR([Yasm is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you do not appear to have Yasm installed. Either install it or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder. See https://developer.mozilla.org/en/YASM for more details.]) fi dnl Check that we have the right yasm version. We require 1.0.1 or newer dnl on Linux and 1.1 or newer everywhere else. if test "$OS_ARCH" = "Linux" ; then if test "$_YASM_MAJOR_VERSION" -lt "1" -o \( "$_YASM_MAJOR_VERSION" -eq "1" -a "$_YASM_MINOR_VERSION" -eq "0" -a "$_YASM_RELEASE" -lt "1" \) ; then - AC_MSG_ERROR([yasm 1.0.1 or greater is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you appear to have version $_YASM_MAJOR_VERSION.$_YASM_MINOR_VERSION.$_YASM_RELEASE. Upgrade to the newest version or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder. See https://developer.mozilla.org/en/YASM for more details.]) + AC_MSG_ERROR([Yasm 1.0.1 or greater is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you appear to have version $_YASM_MAJOR_VERSION.$_YASM_MINOR_VERSION.$_YASM_RELEASE. Upgrade to the newest version or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder. See https://developer.mozilla.org/en/YASM for more details.]) fi else if test "$_YASM_MAJOR_VERSION" -lt "1" -o \( "$_YASM_MAJOR_VERSION" -eq "1" -a "$_YASM_MINOR_VERSION" -lt "1" \) ; then - AC_MSG_ERROR([yasm 1.1 or greater is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you appear to have version $_YASM_MAJOR_VERSION.$_YASM_MINOR_VERSION. Upgrade to the newest version or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder. See https://developer.mozilla.org/en/YASM for more details.]) + AC_MSG_ERROR([Yasm 1.1 or greater is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you appear to have version $_YASM_MAJOR_VERSION.$_YASM_MINOR_VERSION. Upgrade to the newest version or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder. See https://developer.mozilla.org/en/YASM for more details.]) fi fi fi +dnl If we're on an ARM system which supports libjpeg-turbo's asm routines and +dnl --disable-libjpeg-turbo wasn't passed, use the C compiler as the assembler. +if test -n "$LIBJPEG_TURBO_ARM_ASM" ; then + echo "Using $AS as the assembler for ARM code." + LIBJPEG_TURBO_AS=$AS +fi + if test -n "$LIBJPEG_TURBO_X86_ASM"; then AC_DEFINE(LIBJPEG_TURBO_X86_ASM) elif test -n "$LIBJPEG_TURBO_X64_ASM"; then AC_DEFINE(LIBJPEG_TURBO_X64_ASM) +elif test -n "$LIBJPEG_TURBO_ARM_ASM"; then + AC_DEFINE(LIBJPEG_TURBO_ARM_ASM) elif test -n "$MOZ_LIBJPEG_TURBO"; then dnl Warn if we're not building the optimized routines, even though the user dnl didn't specify --disable-libjpeg-turbo. @@ -8757,6 +8771,7 @@ AC_SUBST(LIBJPEG_TURBO_AS) AC_SUBST(LIBJPEG_TURBO_ASFLAGS) AC_SUBST(LIBJPEG_TURBO_X86_ASM) AC_SUBST(LIBJPEG_TURBO_X64_ASM) +AC_SUBST(LIBJPEG_TURBO_ARM_ASM) AC_MSG_CHECKING([for posix_fallocate]) AC_TRY_LINK([#define _XOPEN_SOURCE 600 diff --git a/media/libjpeg/MOZCHANGES b/media/libjpeg/MOZCHANGES index 78c2752a1b2a..17267e5a5de0 100644 --- a/media/libjpeg/MOZCHANGES +++ b/media/libjpeg/MOZCHANGES @@ -6,9 +6,15 @@ To upgrade to a new revision of libjpeg-turbo, do the following: * In a clean clone of mozilla-central, run the following commands - $ rm -rf jpeg - $ svn export --ignore-externals /path/to/libjpeg-turbo jpeg - $ cd jpeg + $ rm -rf media/libjpeg + $ svn export --ignore-externals /path/to/libjpeg-turbo media/libjpeg + $ cd media/libjpeg + +* Copy win/jsimdcfg.inc to simd/. + +* Since libjpeg-turbo normally creates config.h and jconfig.h at build time and + we use pre-generated versions, changes to jconfig.h.in and win/config.h.in + should be looked for and noted for later inclusion. * Now look through the new files and rm any which are npotb. When I upgraded to libjpeg-turbo 1.1.0, the only files I kept which didn't match @@ -32,13 +38,19 @@ To upgrade to a new revision of libjpeg-turbo, do the following: diff <(ls *.c | sort) <(grep -o '\w*\.c' Makefile.in | sort) - of course, libjpeg-turbo might have added some new source files, so you'll + Of course, libjpeg-turbo might have added some new source files, so you'll have to look though and figure out which of these files to keep. * Restore files modified in the Mozilla repository. - $ hg revert --no-backup Makefile.in jconfig.h jmorecfg.h simd/Makefile.in \ - simd/jsimdcfg.inc jchuff.c jdhuff.c jdhuff.h MOZCHANGES + $ hg revert --no-backup config.h jconfig.h Makefile.in MOZCHANGES \ + mozilla.diff simd/Makefile.in + +* Update config.h and jconfig.h as noted previously. + +* Apply Mozilla-specific changes to upstream files. + + $ patch -p0 -i mozilla.diff * Update Makefile.in to build any new files. @@ -47,6 +59,18 @@ To upgrade to a new revision of libjpeg-turbo, do the following: $ hg addremove +== February 10, 2012 (libjpeg-turbo v1.2.0 r807 2012-02-10) == + +* Imported jchuff.c, jdhuff.c, jdhuff.h under new licensing. + +* Created mozilla.diff for the required jmorecfg.h changes and to allow for any + future changes made by Mozilla to upstream files. + +* Removed the following files which are unused by the Mozilla build: + + cderror.h, cdjpeg.h, jconfig.h.in, transupp.h, simd/jsimdcfg.inc.h + + == March 28, 2011 (initial commit, libjpeg-turbo v1.1.0 r469 2011-02-27) == * Modified jmorecfg.h to define UINT8, UINT16, INT16, and INT32 in terms of diff --git a/media/libjpeg/Makefile.in b/media/libjpeg/Makefile.in index 1d82ea257908..f7507755bb70 100644 --- a/media/libjpeg/Makefile.in +++ b/media/libjpeg/Makefile.in @@ -103,6 +103,7 @@ CSRCS += \ jcphuff.c \ jcprepct.c \ jcsample.c \ + jctrans.c \ $(NULL) AS=$(LIBJPEG_TURBO_AS) @@ -115,14 +116,20 @@ ifeq ($(AS),yasm) endif # No SIMD support? -ifeq (,$(LIBJPEG_TURBO_X86_ASM)$(LIBJPEG_TURBO_X64_ASM)) +ifeq (,$(LIBJPEG_TURBO_X86_ASM)$(LIBJPEG_TURBO_X64_ASM)$(LIBJPEG_TURBO_ARM_ASM)) CSRCS += jsimd_none.c endif +ifeq (1,$(LIBJPEG_TURBO_ARM_ASM)) + CSRCS += simd/jsimd_arm.c + SSRCS += simd/jsimd_arm_neon.S +endif + ifeq (1,$(LIBJPEG_TURBO_X64_ASM)) CSRCS += simd/jsimd_x86_64.c ASFILES += \ simd/jccolss2-64.asm \ + simd/jcgrass2-64.asm \ simd/jcqnts2f-64.asm \ simd/jcqnts2i-64.asm \ simd/jcsamss2-64.asm \ @@ -144,6 +151,8 @@ ifeq (1,$(LIBJPEG_TURBO_X86_ASM)) ASFILES += \ simd/jccolmmx.asm \ simd/jccolss2.asm \ + simd/jcgrammx.asm \ + simd/jcgrass2.asm \ simd/jcqnt3dn.asm \ simd/jcqntmmx.asm \ simd/jcqnts2f.asm \ @@ -176,14 +185,14 @@ ifeq (1,$(LIBJPEG_TURBO_X86_ASM)) $(NULL) endif -EXPORTS = \ - jconfig.h \ - jerror.h \ - jinclude.h \ - jmorecfg.h \ - jpegint.h \ - jpeglib.h \ - $(NULL) +EXPORTS = \ + jconfig.h \ + jerror.h \ + jinclude.h \ + jmorecfg.h \ + jpegint.h \ + jpeglib.h \ + $(NULL) # need static lib for some of the libimg componentry to link properly FORCE_STATIC_LIB = 1 diff --git a/media/libjpeg/README b/media/libjpeg/README index 2ead09e64a46..0e9b4295e5bf 100644 --- a/media/libjpeg/README +++ b/media/libjpeg/README @@ -1,7 +1,8 @@ -libjpeg-turbo note: This file is mostly taken from the libjpeg v8b README -file, and it is included only for reference. Some parts of it may not apply to -libjpeg-turbo. Please see README-turbo.txt for information specific to the -turbo version. +libjpeg-turbo note: This file contains portions of the libjpeg v6b and v8 +README files, with additional wordsmithing by The libjpeg-turbo Project. +It is included only for reference, as some parts of it may not apply to +libjpeg-turbo. Please see README-turbo.txt for information specific to +libjpeg-turbo. The Independent JPEG Group's JPEG software @@ -62,7 +63,7 @@ OVERVIEW This package contains C software to implement JPEG image encoding, decoding, and transcoding. JPEG (pronounced "jay-peg") is a standardized compression method for full-color and gray-scale images. JPEG's strong suit is compressing -photographic images or other types of images which have smooth color and +photographic images or other types of images that have smooth color and brightness transitions between neighboring pixels. Images with sharp lines or other abrupt features may not compress well with JPEG, and a higher JPEG quality may have to be used to avoid visible compression artifacts with such @@ -256,8 +257,8 @@ ARCHIVE LOCATIONS The "official" archive site for this software is www.ijg.org. The most recent released version can always be found there in directory "files". This particular version will be archived as -http://www.ijg.org/files/jpegsrc.v8b.tar.gz, and in Windows-compatible -"zip" archive format as http://www.ijg.org/files/jpegsr8b.zip. +http://www.ijg.org/files/jpegsrc.v8d.tar.gz, and in Windows-compatible +"zip" archive format as http://www.ijg.org/files/jpegsr8d.zip. The JPEG FAQ (Frequently Asked Questions) article is a source of some general information about JPEG. @@ -274,7 +275,7 @@ FILE FORMAT WARS ================ The ISO JPEG standards committee actually promotes different formats like -"JPEG 2000" or "JPEG XR" which are incompatible with original DCT-based +"JPEG 2000" or "JPEG XR", which are incompatible with original DCT-based JPEG. IJG therefore does not support these formats (see REFERENCES). Indeed, one of the original reasons for developing this free software was to help force convergence on common, interoperable format standards for JPEG files. @@ -286,4 +287,4 @@ image files indefinitely.) TO DO ===== -Please send bug reports, offers of help, etc. to jpeg-info@uc.ag. +Please send bug reports, offers of help, etc. to jpeg-info@jpegclub.org. diff --git a/media/libjpeg/README-turbo.txt b/media/libjpeg/README-turbo.txt index fec34e0cdabb..899a36819877 100644 --- a/media/libjpeg/README-turbo.txt +++ b/media/libjpeg/README-turbo.txt @@ -2,51 +2,80 @@ ** Background ******************************************************************************* -libjpeg-turbo is a derivative of libjpeg which uses SIMD instructions (MMX, -SSE2, etc.) to accelerate baseline JPEG compression and decompression on x86 -and x86-64 systems. On such systems, libjpeg-turbo is generally 2-4x as fast -as the unmodified version of libjpeg, all else being equal. +libjpeg-turbo is a derivative of libjpeg that uses SIMD instructions (MMX, +SSE2, NEON) to accelerate baseline JPEG compression and decompression on x86, +x86-64, and ARM systems. On such systems, libjpeg-turbo is generally 2-4x as +fast as the unmodified version of libjpeg, all else being equal. libjpeg-turbo was originally based on libjpeg/SIMD by Miyasaka Masaru, but the TigerVNC and VirtualGL projects made numerous enhancements to the codec in 2009, including improved support for Mac OS X, 64-bit support, support for -32-bit and big endian pixel formats (RGBX, XBGR, etc.), accelerated Huffman -encoding/decoding, and various bug fixes. The goal was to produce a fully open -source codec that could replace the partially closed source TurboJPEG/IPP codec -used by VirtualGL and TurboVNC. libjpeg-turbo generally performs in the range -of 80-120% of TurboJPEG/IPP. It is faster in some areas but slower in others. +32-bit and big-endian pixel formats (RGBX, XBGR, etc.), accelerated Huffman +encoding/decoding, and various bug fixes. The goal was to produce a fully +open-source codec that could replace the partially closed-source TurboJPEG/IPP +codec used by VirtualGL and TurboVNC. libjpeg-turbo generally achieves 80-120% +of the performance of TurboJPEG/IPP. It is faster in some areas but slower in +others. In early 2010, libjpeg-turbo spun off into its own independent project, with the goal of making high-speed JPEG compression/decompression technology -available to a broader range of users and developers. The libjpeg-turbo shared -libraries can be used as drop-in replacements for libjpeg on most systems. +available to a broader range of users and developers. ******************************************************************************* ** License ******************************************************************************* -The TurboJPEG/OSS wrapper, as well as some of the optimizations to the Huffman -encoder (jchuff.c) and decoder (jdhuff.c), were borrowed from VirtualGL, and -thus any distribution of libjpeg-turbo which includes those files must, as a -whole, be subject to the terms of the wxWindows Library Licence, Version 3.1. -A copy of this license can be found in this directory under LICENSE.txt. The -wxWindows Library License is based on the LGPL but includes provisions which -allow the Library to be statically linked into proprietary libraries and -applications without requiring the resulting binaries to be distributed under -the terms of the LGPL. +Most of libjpeg-turbo inherits the non-restrictive, BSD-style license used by +libjpeg (see README.) The TurboJPEG/OSS wrapper (both C and Java versions) and +associated test programs bear a similar license, which is reproduced below: -The rest of the source code, apart from TurboJPEG/OSS and the Huffman codec -optimizations, falls under a less restrictive, BSD-style license (see README.) -You can choose to distribute libjpeg-turbo, as a whole, under this BSD-style -license by simply removing TurboJPEG/OSS and replacing the optimized jchuff.c -and jdhuff.c with their unoptimized counterparts from the libjpeg v6b source. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +- Neither the name of the libjpeg-turbo Project nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. ******************************************************************************* ** Using libjpeg-turbo ******************************************************************************* +libjpeg-turbo includes two APIs that can be used to compress and decompress +JPEG images: + + TurboJPEG API: This API provides an easy-to-use interface for compressing + and decompressing JPEG images in memory. It also provides some functionality + that would not be straightforward to achieve using the underlying libjpeg + API, such as generating planar YUV images and performing multiple + simultaneous lossless transforms on an image. The Java interface for + libjpeg-turbo is written on top of the TurboJPEG API. + + libjpeg API: This is the de facto industry-standard API for compressing and + decompressing JPEG images. It is more difficult to use than the TurboJPEG + API but also more powerful. libjpeg-turbo is both API/ABI-compatible and + mathematically compatible with libjpeg v6b. It can also optionally be + configured to be API/ABI-compatible with libjpeg v7 and v8 (see below.) + + ============================= Replacing libjpeg at Run Time ============================= @@ -72,13 +101,13 @@ NOTE: {lib} can be lib, lib32, lib64, or lib/64, depending on the O/S and architecture. System administrators can also replace the libjpeg sym links in /usr/{lib} with -links to the libjpeg dynamic library located in /opt/libjpeg-turbo/{lib}. This -will effectively accelerate every dynamically linked libjpeg application on the -system. +links to the libjpeg-turbo dynamic library located in /opt/libjpeg-turbo/{lib}. +This will effectively accelerate every application that uses the libjpeg +dynamic library on the system. The libjpeg-turbo SDK for Visual C++ installs the libjpeg-turbo DLL -(jpeg62.dll, jpeg7.dll, or jpeg8.dll, depending on whether libjpeg v6b, v7, or -v8 emulation is enabled) into c:\libjpeg-turbo[64]\bin, and the PATH +(jpeg62.dll, jpeg7.dll, or jpeg8.dll, depending on whether it was built with +libjpeg v6b, v7, or v8 emulation) into c:\libjpeg-turbo[64]\bin, and the PATH environment variable can be modified such that this directory is searched before any others that might contain a libjpeg DLL. However, if a libjpeg DLL exists in an application's install directory, then Windows will load this @@ -88,16 +117,16 @@ version of this DLL and copy c:\libjpeg-turbo[64]\bin\jpeg*.dll into the application's install directory to accelerate it. The version of the libjpeg-turbo DLL distributed in the libjpeg-turbo SDK for -Visual C++ requires the Visual C++ 2008 C run time DLL (msvcr90.dll). +Visual C++ requires the Visual C++ 2008 C run-time DLL (msvcr90.dll). msvcr90.dll ships with more recent versions of Windows, but users of older Windows releases can obtain it from the Visual C++ 2008 Redistributable Package, which is available as a free download from Microsoft's web site. -NOTE: Features of libjpeg which require passing a C run time structure, such +NOTE: Features of libjpeg that require passing a C run-time structure, such as a file handle, from an application to libjpeg will probably not work with the version of the libjpeg-turbo DLL distributed in the libjpeg-turbo SDK for Visual C++, unless the application is also built to use the Visual C++ 2008 C -run time DLL. In particular, this affects jpeg_stdio_dest() and +run-time DLL. In particular, this affects jpeg_stdio_dest() and jpeg_stdio_src(). Mac applications typically embed their own copies of the libjpeg dylib inside @@ -117,7 +146,7 @@ Replacing TurboJPEG/IPP libjpeg-turbo is a drop-in replacement for the TurboJPEG/IPP SDK used by VirtualGL 2.1.x and TurboVNC 0.6 (and prior.) libjpeg-turbo contains a wrapper library (TurboJPEG/OSS) that emulates the TurboJPEG API using libjpeg-turbo -instead of the closed source Intel Performance Primitives. You can replace the +instead of the closed-source Intel Performance Primitives. You can replace the TurboJPEG/IPP package on Linux systems with the libjpeg-turbo package in order to make existing releases of VirtualGL 2.1.x and TurboVNC 0.x use the new codec at run time. Note that the 64-bit libjpeg-turbo packages contain only 64-bit @@ -128,7 +157,7 @@ both the 64-bit and 32-bit versions of libjpeg-turbo. You can also build the VirtualGL 2.1.x and TurboVNC 0.6 source code with the libjpeg-turbo SDK instead of TurboJPEG/IPP. It should work identically. libjpeg-turbo also includes static library versions of TurboJPEG/OSS, which -are used to build TurboVNC 1.0 and later. +are used to build VirtualGL 2.2 and TurboVNC 1.0 and later. ======================================== Using libjpeg-turbo in Your Own Programs @@ -179,9 +208,9 @@ libjpeg-turbo) or jpeg-static.lib (to use the static version of libjpeg-turbo.) Colorspace Extensions ===================== -libjpeg-turbo includes extensions which allow JPEG images to be compressed -directly from (and decompressed directly to) buffers which use BGR, BGRX, -RGBX, XBGR, and XRGB pixel ordering. This is implemented with six new +libjpeg-turbo includes extensions that allow JPEG images to be compressed +directly from (and decompressed directly to) buffers that use BGR, BGRX, +RGBX, XBGR, and XRGB pixel ordering. This is implemented with ten new colorspace constants: JCS_EXT_RGB /* red/green/blue */ @@ -190,11 +219,15 @@ colorspace constants: JCS_EXT_BGRX /* blue/green/red/x */ JCS_EXT_XBGR /* x/blue/green/red */ JCS_EXT_XRGB /* x/red/green/blue */ + JCS_EXT_RGBA /* red/green/blue/alpha */ + JCS_EXT_BGRA /* blue/green/red/alpha */ + JCS_EXT_ABGR /* alpha/blue/green/red */ + JCS_EXT_ARGB /* alpha/red/green/blue */ Setting cinfo.in_color_space (compression) or cinfo.out_color_space (decompression) to one of these values will cause libjpeg-turbo to read the red, green, and blue values from (or write them to) the appropriate position in -the pixel when YUV conversion is performed. +the pixel when compressing from/decompressing to an RGB buffer. Your application can check for the existence of these extensions at compile time with: @@ -204,33 +237,41 @@ time with: At run time, attempting to use these extensions with a version of libjpeg that doesn't support them will result in a "Bogus input colorspace" error. +When using the RGBX, BGRX, XBGR, and XRGB colorspaces during decompression, the +X byte is undefined, and in order to ensure the best performance, libjpeg-turbo +can set that byte to whatever value it wishes. If an application expects the X +byte to be used as an alpha channel, then it should specify JCS_EXT_RGBA, +JCS_EXT_BGRA, JCS_EXT_ABGR, or JCS_EXT_ARGB. When these colorspace constants +are used, the X byte is guaranteed to be 0xFF, which is interpreted as opaque. + +Your application can check for the existence of the alpha channel colorspace +extensions at compile time with: + + #ifdef JCS_ALPHA_EXTENSIONS + +jcstest.c, located in the libjpeg-turbo source tree, demonstrates how to check +for the existence of the colorspace extensions at compile time and run time. + ================================= libjpeg v7 and v8 API/ABI support ================================= -libjpeg v7 and v8 added new features to the API/ABI, and, unfortunately, the -compression and decompression structures were extended in a backward- -incompatible manner to accommodate these features. Thus, programs which are +With libjpeg v7 and v8, new features were added that necessitated extending the +compression and decompression structures. Unfortunately, due to the exposed +nature of those structures, extending them also necessitated breaking backward +ABI compatibility with previous libjpeg releases. Thus, programs that are built to use libjpeg v7 or v8 did not work with libjpeg-turbo, since it is based on the libjpeg v6b code base. Although libjpeg v7 and v8 are still not as widely used as v6b, enough programs (including a few Linux distros) have made the switch that it was desirable to provide support for the libjpeg v7/v8 -API/ABI in libjpeg-turbo. - -Some of the libjpeg v7 and v8 features -- DCT scaling, to name one -- involve -deep modifications to the code which cannot be accommodated by libjpeg-turbo -without either breaking compatibility with libjpeg v6b or producing an -unsupportable mess. In order to fully support libjpeg v8 with all of its -features, we would have to essentially port the SIMD extensions to the libjpeg -v8 code base and maintain two separate code trees. We are hesitant to do this -until/unless the newer libjpeg code bases garner more community support and -involvement and until/unless we have some notion of whether future libjpeg -releases will also be backward-incompatible. +API/ABI in libjpeg-turbo. Although libjpeg-turbo can now be configured as a +drop-in replacement for libjpeg v7 or v8, it should be noted that not all of +the features in libjpeg v7 and v8 are supported (see below.) By passing an argument of --with-jpeg7 or --with-jpeg8 to configure, or an argument of -DWITH_JPEG7=1 or -DWITH_JPEG8=1 to cmake, you can build a version -of libjpeg-turbo which emulates the libjpeg v7 or v8 API/ABI, so that programs -which are built against libjpeg v7 or v8 can be run with libjpeg-turbo. The +of libjpeg-turbo that emulates the libjpeg v7 or v8 API/ABI, so that programs +that are built against libjpeg v7 or v8 can be run with libjpeg-turbo. The following section describes which libjpeg v7+ features are supported and which aren't. @@ -264,6 +305,16 @@ Not supported: -- libjpeg: DCT scaling in compressor cinfo.scale_num and cinfo.scale_denom are silently ignored. + There is no technical reason why DCT scaling cannot be supported, but + without the SmartScale extension (see below), it would only be able to + down-scale using ratios of 1/2, 8/15, 4/7, 8/13, 2/3, 8/11, 4/5, and 8/9, + which is of limited usefulness. + +-- libjpeg: SmartScale + cinfo.block_size is silently ignored. + SmartScale is an extension to the JPEG format that allows for DCT block + sizes other than 8x8. It would be difficult to support this feature while + retaining backward compatibility with libjpeg v6b. -- libjpeg: IDCT scaling extensions in decompressor libjpeg-turbo still supports IDCT scaling with scaling factors of 1/2, 1/4, @@ -271,9 +322,14 @@ Not supported: -- libjpeg: Fancy downsampling in compressor cinfo.do_fancy_downsampling is silently ignored. + This requires the DCT scaling feature, which is not supported. -- jpegtran: Scaling - Seems to depend on the DCT scaling feature, which isn't supported. + This requires both the DCT scaling and SmartScale features, which are not + supported. + +-- Lossless RGB JPEG files + This requires the SmartScale feature, which is not supported. ******************************************************************************* @@ -285,12 +341,13 @@ Restart Markers =============== The optimized Huffman decoder in libjpeg-turbo does not handle restart markers -in a way that makes libjpeg happy, so it is necessary to use the slow Huffman -decoder when decompressing a JPEG image that has restart markers. This can -cause the decompression performance to drop by as much as 20%, but the -performance will still be much much greater than that of libjpeg v6b. Many -consumer packages, such as PhotoShop, use restart markers when generating JPEG -images, so images generated by those programs will experience this issue. +in a way that makes the rest of the libjpeg infrastructure happy, so it is +necessary to use the slow Huffman decoder when decompressing a JPEG image that +has restart markers. This can cause the decompression performance to drop by +as much as 20%, but the performance will still be much greater than that of +libjpeg. Many consumer packages, such as PhotoShop, use restart markers when +generating JPEG images, so images generated by those programs will experience +this issue. =============================================== Fast Integer Forward DCT at High Quality Levels diff --git a/media/libjpeg/cderror.h b/media/libjpeg/cderror.h deleted file mode 100644 index e19c475c5c5c..000000000000 --- a/media/libjpeg/cderror.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * cderror.h - * - * Copyright (C) 1994-1997, Thomas G. Lane. - * Modified 2009 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file defines the error and message codes for the cjpeg/djpeg - * applications. These strings are not needed as part of the JPEG library - * proper. - * Edit this file to add new codes, or to translate the message strings to - * some other language. - */ - -/* - * To define the enum list of message codes, include this file without - * defining macro JMESSAGE. To create a message string table, include it - * again with a suitable JMESSAGE definition (see jerror.c for an example). - */ -#ifndef JMESSAGE -#ifndef CDERROR_H -#define CDERROR_H -/* First time through, define the enum list */ -#define JMAKE_ENUM_LIST -#else -/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ -#define JMESSAGE(code,string) -#endif /* CDERROR_H */ -#endif /* JMESSAGE */ - -#ifdef JMAKE_ENUM_LIST - -typedef enum { - -#define JMESSAGE(code,string) code , - -#endif /* JMAKE_ENUM_LIST */ - -JMESSAGE(JMSG_FIRSTADDONCODE=1000, NULL) /* Must be first entry! */ - -#ifdef BMP_SUPPORTED -JMESSAGE(JERR_BMP_BADCMAP, "Unsupported BMP colormap format") -JMESSAGE(JERR_BMP_BADDEPTH, "Only 8- and 24-bit BMP files are supported") -JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length") -JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1") -JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB") -JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported") -JMESSAGE(JERR_BMP_EMPTY, "Empty BMP image") -JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM") -JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image") -JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image") -JMESSAGE(JTRC_BMP_OS2, "%ux%u 24-bit OS2 BMP image") -JMESSAGE(JTRC_BMP_OS2_MAPPED, "%ux%u 8-bit colormapped OS2 BMP image") -#endif /* BMP_SUPPORTED */ - -#ifdef GIF_SUPPORTED -JMESSAGE(JERR_GIF_BUG, "GIF output got confused") -JMESSAGE(JERR_GIF_CODESIZE, "Bogus GIF codesize %d") -JMESSAGE(JERR_GIF_COLORSPACE, "GIF output must be grayscale or RGB") -JMESSAGE(JERR_GIF_IMAGENOTFOUND, "Too few images in GIF file") -JMESSAGE(JERR_GIF_NOT, "Not a GIF file") -JMESSAGE(JTRC_GIF, "%ux%ux%d GIF image") -JMESSAGE(JTRC_GIF_BADVERSION, - "Warning: unexpected GIF version number '%c%c%c'") -JMESSAGE(JTRC_GIF_EXTENSION, "Ignoring GIF extension block of type 0x%02x") -JMESSAGE(JTRC_GIF_NONSQUARE, "Caution: nonsquare pixels in input") -JMESSAGE(JWRN_GIF_BADDATA, "Corrupt data in GIF file") -JMESSAGE(JWRN_GIF_CHAR, "Bogus char 0x%02x in GIF file, ignoring") -JMESSAGE(JWRN_GIF_ENDCODE, "Premature end of GIF image") -JMESSAGE(JWRN_GIF_NOMOREDATA, "Ran out of GIF bits") -#endif /* GIF_SUPPORTED */ - -#ifdef PPM_SUPPORTED -JMESSAGE(JERR_PPM_COLORSPACE, "PPM output must be grayscale or RGB") -JMESSAGE(JERR_PPM_NONNUMERIC, "Nonnumeric data in PPM file") -JMESSAGE(JERR_PPM_NOT, "Not a PPM/PGM file") -JMESSAGE(JTRC_PGM, "%ux%u PGM image") -JMESSAGE(JTRC_PGM_TEXT, "%ux%u text PGM image") -JMESSAGE(JTRC_PPM, "%ux%u PPM image") -JMESSAGE(JTRC_PPM_TEXT, "%ux%u text PPM image") -#endif /* PPM_SUPPORTED */ - -#ifdef RLE_SUPPORTED -JMESSAGE(JERR_RLE_BADERROR, "Bogus error code from RLE library") -JMESSAGE(JERR_RLE_COLORSPACE, "RLE output must be grayscale or RGB") -JMESSAGE(JERR_RLE_DIMENSIONS, "Image dimensions (%ux%u) too large for RLE") -JMESSAGE(JERR_RLE_EMPTY, "Empty RLE file") -JMESSAGE(JERR_RLE_EOF, "Premature EOF in RLE header") -JMESSAGE(JERR_RLE_MEM, "Insufficient memory for RLE header") -JMESSAGE(JERR_RLE_NOT, "Not an RLE file") -JMESSAGE(JERR_RLE_TOOMANYCHANNELS, "Cannot handle %d output channels for RLE") -JMESSAGE(JERR_RLE_UNSUPPORTED, "Cannot handle this RLE setup") -JMESSAGE(JTRC_RLE, "%ux%u full-color RLE file") -JMESSAGE(JTRC_RLE_FULLMAP, "%ux%u full-color RLE file with map of length %d") -JMESSAGE(JTRC_RLE_GRAY, "%ux%u grayscale RLE file") -JMESSAGE(JTRC_RLE_MAPGRAY, "%ux%u grayscale RLE file with map of length %d") -JMESSAGE(JTRC_RLE_MAPPED, "%ux%u colormapped RLE file with map of length %d") -#endif /* RLE_SUPPORTED */ - -#ifdef TARGA_SUPPORTED -JMESSAGE(JERR_TGA_BADCMAP, "Unsupported Targa colormap format") -JMESSAGE(JERR_TGA_BADPARMS, "Invalid or unsupported Targa file") -JMESSAGE(JERR_TGA_COLORSPACE, "Targa output must be grayscale or RGB") -JMESSAGE(JTRC_TGA, "%ux%u RGB Targa image") -JMESSAGE(JTRC_TGA_GRAY, "%ux%u grayscale Targa image") -JMESSAGE(JTRC_TGA_MAPPED, "%ux%u colormapped Targa image") -#else -JMESSAGE(JERR_TGA_NOTCOMP, "Targa support was not compiled") -#endif /* TARGA_SUPPORTED */ - -JMESSAGE(JERR_BAD_CMAP_FILE, - "Color map file is invalid or of unsupported format") -JMESSAGE(JERR_TOO_MANY_COLORS, - "Output file format cannot handle %d colormap entries") -JMESSAGE(JERR_UNGETC_FAILED, "ungetc failed") -#ifdef TARGA_SUPPORTED -JMESSAGE(JERR_UNKNOWN_FORMAT, - "Unrecognized input file format --- perhaps you need -targa") -#else -JMESSAGE(JERR_UNKNOWN_FORMAT, "Unrecognized input file format") -#endif -JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format") - -#ifdef JMAKE_ENUM_LIST - - JMSG_LASTADDONCODE -} ADDON_MESSAGE_CODE; - -#undef JMAKE_ENUM_LIST -#endif /* JMAKE_ENUM_LIST */ - -/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ -#undef JMESSAGE diff --git a/media/libjpeg/cdjpeg.h b/media/libjpeg/cdjpeg.h deleted file mode 100644 index ed024ac3ae85..000000000000 --- a/media/libjpeg/cdjpeg.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * cdjpeg.h - * - * Copyright (C) 1994-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains common declarations for the sample applications - * cjpeg and djpeg. It is NOT used by the core JPEG library. - */ - -#define JPEG_CJPEG_DJPEG /* define proper options in jconfig.h */ -#define JPEG_INTERNAL_OPTIONS /* cjpeg.c,djpeg.c need to see xxx_SUPPORTED */ -#include "jinclude.h" -#include "jpeglib.h" -#include "jerror.h" /* get library error codes too */ -#include "cderror.h" /* get application-specific error codes */ - - -/* - * Object interface for cjpeg's source file decoding modules - */ - -typedef struct cjpeg_source_struct * cjpeg_source_ptr; - -struct cjpeg_source_struct { - JMETHOD(void, start_input, (j_compress_ptr cinfo, - cjpeg_source_ptr sinfo)); - JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo, - cjpeg_source_ptr sinfo)); - JMETHOD(void, finish_input, (j_compress_ptr cinfo, - cjpeg_source_ptr sinfo)); - - FILE *input_file; - - JSAMPARRAY buffer; - JDIMENSION buffer_height; -}; - - -/* - * Object interface for djpeg's output file encoding modules - */ - -typedef struct djpeg_dest_struct * djpeg_dest_ptr; - -struct djpeg_dest_struct { - /* start_output is called after jpeg_start_decompress finishes. - * The color map will be ready at this time, if one is needed. - */ - JMETHOD(void, start_output, (j_decompress_ptr cinfo, - djpeg_dest_ptr dinfo)); - /* Emit the specified number of pixel rows from the buffer. */ - JMETHOD(void, put_pixel_rows, (j_decompress_ptr cinfo, - djpeg_dest_ptr dinfo, - JDIMENSION rows_supplied)); - /* Finish up at the end of the image. */ - JMETHOD(void, finish_output, (j_decompress_ptr cinfo, - djpeg_dest_ptr dinfo)); - - /* Target file spec; filled in by djpeg.c after object is created. */ - FILE * output_file; - - /* Output pixel-row buffer. Created by module init or start_output. - * Width is cinfo->output_width * cinfo->output_components; - * height is buffer_height. - */ - JSAMPARRAY buffer; - JDIMENSION buffer_height; -}; - - -/* - * cjpeg/djpeg may need to perform extra passes to convert to or from - * the source/destination file format. The JPEG library does not know - * about these passes, but we'd like them to be counted by the progress - * monitor. We use an expanded progress monitor object to hold the - * additional pass count. - */ - -struct cdjpeg_progress_mgr { - struct jpeg_progress_mgr pub; /* fields known to JPEG library */ - int completed_extra_passes; /* extra passes completed */ - int total_extra_passes; /* total extra */ - /* last printed percentage stored here to avoid multiple printouts */ - int percent_done; -}; - -typedef struct cdjpeg_progress_mgr * cd_progress_ptr; - - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jinit_read_bmp jIRdBMP -#define jinit_write_bmp jIWrBMP -#define jinit_read_gif jIRdGIF -#define jinit_write_gif jIWrGIF -#define jinit_read_ppm jIRdPPM -#define jinit_write_ppm jIWrPPM -#define jinit_read_rle jIRdRLE -#define jinit_write_rle jIWrRLE -#define jinit_read_targa jIRdTarga -#define jinit_write_targa jIWrTarga -#define read_quant_tables RdQTables -#define read_scan_script RdScnScript -#define set_quality_ratings SetQRates -#define set_quant_slots SetQSlots -#define set_sample_factors SetSFacts -#define read_color_map RdCMap -#define enable_signal_catcher EnSigCatcher -#define start_progress_monitor StProgMon -#define end_progress_monitor EnProgMon -#define read_stdin RdStdin -#define write_stdout WrStdout -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - -/* Module selection routines for I/O modules. */ - -EXTERN(cjpeg_source_ptr) jinit_read_bmp JPP((j_compress_ptr cinfo)); -EXTERN(djpeg_dest_ptr) jinit_write_bmp JPP((j_decompress_ptr cinfo, - boolean is_os2)); -EXTERN(cjpeg_source_ptr) jinit_read_gif JPP((j_compress_ptr cinfo)); -EXTERN(djpeg_dest_ptr) jinit_write_gif JPP((j_decompress_ptr cinfo)); -EXTERN(cjpeg_source_ptr) jinit_read_ppm JPP((j_compress_ptr cinfo)); -EXTERN(djpeg_dest_ptr) jinit_write_ppm JPP((j_decompress_ptr cinfo)); -EXTERN(cjpeg_source_ptr) jinit_read_rle JPP((j_compress_ptr cinfo)); -EXTERN(djpeg_dest_ptr) jinit_write_rle JPP((j_decompress_ptr cinfo)); -EXTERN(cjpeg_source_ptr) jinit_read_targa JPP((j_compress_ptr cinfo)); -EXTERN(djpeg_dest_ptr) jinit_write_targa JPP((j_decompress_ptr cinfo)); - -/* cjpeg support routines (in rdswitch.c) */ - -EXTERN(boolean) read_quant_tables JPP((j_compress_ptr cinfo, char * filename, - boolean force_baseline)); -EXTERN(boolean) read_scan_script JPP((j_compress_ptr cinfo, char * filename)); -EXTERN(boolean) set_quality_ratings JPP((j_compress_ptr cinfo, char *arg, - boolean force_baseline)); -EXTERN(boolean) set_quant_slots JPP((j_compress_ptr cinfo, char *arg)); -EXTERN(boolean) set_sample_factors JPP((j_compress_ptr cinfo, char *arg)); - -/* djpeg support routines (in rdcolmap.c) */ - -EXTERN(void) read_color_map JPP((j_decompress_ptr cinfo, FILE * infile)); - -/* common support routines (in cdjpeg.c) */ - -EXTERN(void) enable_signal_catcher JPP((j_common_ptr cinfo)); -EXTERN(void) start_progress_monitor JPP((j_common_ptr cinfo, - cd_progress_ptr progress)); -EXTERN(void) end_progress_monitor JPP((j_common_ptr cinfo)); -EXTERN(boolean) keymatch JPP((char * arg, const char * keyword, int minchars)); -EXTERN(FILE *) read_stdin JPP((void)); -EXTERN(FILE *) write_stdout JPP((void)); - -/* miscellaneous useful macros */ - -#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ -#define READ_BINARY "r" -#define WRITE_BINARY "w" -#else -#ifdef VMS /* VMS is very nonstandard */ -#define READ_BINARY "rb", "ctx=stm" -#define WRITE_BINARY "wb", "ctx=stm" -#else /* standard ANSI-compliant case */ -#define READ_BINARY "rb" -#define WRITE_BINARY "wb" -#endif -#endif - -#ifndef EXIT_FAILURE /* define exit() codes if not provided */ -#define EXIT_FAILURE 1 -#endif -#ifndef EXIT_SUCCESS -#ifdef VMS -#define EXIT_SUCCESS 1 /* VMS is very nonstandard */ -#else -#define EXIT_SUCCESS 0 -#endif -#endif -#ifndef EXIT_WARNING -#ifdef VMS -#define EXIT_WARNING 1 /* VMS is very nonstandard */ -#else -#define EXIT_WARNING 2 -#endif -#endif diff --git a/media/libjpeg/config.h b/media/libjpeg/config.h new file mode 100644 index 000000000000..a0c568127531 --- /dev/null +++ b/media/libjpeg/config.h @@ -0,0 +1,6 @@ +#define VERSION "1.2.0" +#define BUILD "2012-02-10" +#define PACKAGE_NAME "libjpeg-turbo" + +/* Need to use Mozilla-specific function inlining. */ +#define INLINE NS_ALWAYS_INLINE diff --git a/media/libjpeg/jaricom.c b/media/libjpeg/jaricom.c index 2195a9733153..f43e2ea7face 100644 --- a/media/libjpeg/jaricom.c +++ b/media/libjpeg/jaricom.c @@ -150,3 +150,4 @@ const INT32 jpeg_aritab[113+1] = { * as recommended in Section 10.3 Table 5 of ITU-T Rec. T.851. */ V( 113, 0x5a1d, 113, 113, 0 ) +}; diff --git a/media/libjpeg/jccolext.c b/media/libjpeg/jccolext.c new file mode 100644 index 000000000000..acbfa2352391 --- /dev/null +++ b/media/libjpeg/jccolext.c @@ -0,0 +1,114 @@ +/* + * jccolext.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * Copyright (C) 2009-2011, D. R. Commander. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains input colorspace conversion routines. + */ + + +/* This file is included by jccolor.c */ + + +/* + * Convert some rows of samples to the JPEG colorspace. + * + * Note that we change from the application's interleaved-pixel format + * to our internal noninterleaved, one-plane-per-component format. + * The input buffer is therefore three times as wide as the output buffer. + * + * A starting row offset is provided only for the output buffer. The caller + * can easily adjust the passed input_buf value to accommodate any row + * offset required on that side. + */ + +INLINE +LOCAL(void) +rgb_ycc_convert_internal (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr0, outptr1, outptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr0 = output_buf[0][output_row]; + outptr1 = output_buf[1][output_row]; + outptr2 = output_buf[2][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr[RGB_RED]); + g = GETJSAMPLE(inptr[RGB_GREEN]); + b = GETJSAMPLE(inptr[RGB_BLUE]); + inptr += RGB_PIXELSIZE; + /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations + * must be too; we do not need an explicit range-limiting operation. + * Hence the value being shifted is never negative, and we don't + * need the general RIGHT_SHIFT macro. + */ + /* Y */ + outptr0[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + /* Cb */ + outptr1[col] = (JSAMPLE) + ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) + >> SCALEBITS); + /* Cr */ + outptr2[col] = (JSAMPLE) + ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) + >> SCALEBITS); + } + } +} + + +/**************** Cases other than RGB -> YCbCr **************/ + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles RGB->grayscale conversion, which is the same + * as the RGB->Y portion of RGB->YCbCr. + * We assume rgb_ycc_start has been called (we only use the Y tables). + */ + +INLINE +LOCAL(void) +rgb_gray_convert_internal (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr = output_buf[0][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr[RGB_RED]); + g = GETJSAMPLE(inptr[RGB_GREEN]); + b = GETJSAMPLE(inptr[RGB_BLUE]); + inptr += RGB_PIXELSIZE; + /* Y */ + outptr[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + } + } +} diff --git a/media/libjpeg/jccolor.c b/media/libjpeg/jccolor.c index 73969901dcd8..973055574249 100644 --- a/media/libjpeg/jccolor.c +++ b/media/libjpeg/jccolor.c @@ -3,7 +3,7 @@ * * Copyright (C) 1991-1996, Thomas G. Lane. * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright 2009 D. R. Commander + * Copyright (C) 2009-2011, D. R. Commander. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -14,6 +14,7 @@ #include "jinclude.h" #include "jpeglib.h" #include "jsimd.h" +#include "config.h" /* Private subobject */ @@ -81,72 +82,97 @@ typedef my_color_converter * my_cconvert_ptr; #define TABLE_SIZE (8*(MAXJSAMPLE+1)) -#if BITS_IN_JSAMPLE == 8 +/* Include inline routines for colorspace extensions */ -static const unsigned char red_lut[256] = { - 0 , 0 , 1 , 1 , 1 , 1 , 2 , 2 , 2 , 3 , 3 , 3 , 4 , 4 , 4 , 4 , - 5 , 5 , 5 , 6 , 6 , 6 , 7 , 7 , 7 , 7 , 8 , 8 , 8 , 9 , 9 , 9 , - 10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, - 14, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, - 19, 19, 20, 20, 20, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 24, - 24, 24, 25, 25, 25, 25, 26, 26, 26, 27, 27, 27, 28, 28, 28, 28, - 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 32, 32, 32, 33, 33, 33, - 33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 36, 37, 37, 37, 38, 38, - 38, 39, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, 42, 43, - 43, 43, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 47, 47, 47, 48, - 48, 48, 48, 49, 49, 49, 50, 50, 50, 51, 51, 51, 51, 52, 52, 52, - 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 56, 56, 56, 57, 57, 57, - 57, 58, 58, 58, 59, 59, 59, 60, 60, 60, 60, 61, 61, 61, 62, 62, - 62, 62, 63, 63, 63, 64, 64, 64, 65, 65, 65, 65, 66, 66, 66, 67, - 67, 67, 68, 68, 68, 68, 69, 69, 69, 70, 70, 70, 71, 71, 71, 71, - 72, 72, 72, 73, 73, 73, 74, 74, 74, 74, 75, 75, 75, 76, 76, 76 -}; +#include "jccolext.c" +#undef RGB_RED +#undef RGB_GREEN +#undef RGB_BLUE +#undef RGB_PIXELSIZE -static const unsigned char green_lut[256] = { - 0 , 1 , 1 , 2 , 2 , 3 , 4 , 4 , 5 , 5 , 6 , 6 , - 7 , 8 , 8 , 9 , 9 , 10 , 11 , 11 , 12 , 12 , 13 , 14 , - 14 , 15 , 15 , 16 , 16 , 17 , 18 , 18 , 19 , 19 , 20 , 21 , - 21 , 22 , 22 , 23 , 23 , 24 , 25 , 25 , 26 , 26 , 27 , 28 , - 28 , 29 , 29 , 30 , 31 , 31 , 32 , 32 , 33 , 33 , 34 , 35 , - 35 , 36 , 36 , 37 , 38 , 38 , 39 , 39 , 40 , 41 , 41 , 42 , - 42 , 43 , 43 , 44 , 45 , 45 , 46 , 46 , 47 , 48 , 48 , 49 , - 49 , 50 , 50 , 51 , 52 , 52 , 53 , 53 , 54 , 55 , 55 , 56 , - 56 , 57 , 58 , 58 , 59 , 59 , 60 , 60 , 61 , 62 , 62 , 63 , - 63 , 64 , 65 , 65 , 66 , 66 , 67 , 68 , 68 , 69 , 69 , 70 , - 70 , 71 , 72 , 72 , 73 , 73 , 74 , 75 , 75 , 76 , 76 , 77 , - 77 , 78 , 79 , 79 , 80 , 80 , 81 , 82 , 82 , 83 , 83 , 84 , - 85 , 85 , 86 , 86 , 87 , 87 , 88 , 89 , 89 , 90 , 90 , 91 , - 92 , 92 , 93 , 93 , 94 , 95 , 95 , 96 , 96 , 97 , 97 , 98 , - 99 , 99 , 100, 100, 101, 102, 102, 103, 103, 104, 104, 105, - 106, 106, 107, 107, 108, 109, 109, 110, 110, 111, 112, 112, - 113, 113, 114, 114, 115, 116, 116, 117, 117, 118, 119, 119, - 120, 120, 121, 122, 122, 123, 123, 124, 124, 125, 126, 126, - 127, 127, 128, 129, 129, 130, 130, 131, 131, 132, 133, 133, - 134, 134, 135, 136, 136, 137, 137, 138, 139, 139, 140, 140, - 141, 141, 142, 143, 143, 144, 144, 145, 146, 146, 147, 147, - 148, 149, 149, 150 -}; +#define RGB_RED EXT_RGB_RED +#define RGB_GREEN EXT_RGB_GREEN +#define RGB_BLUE EXT_RGB_BLUE +#define RGB_PIXELSIZE EXT_RGB_PIXELSIZE +#define rgb_ycc_convert_internal extrgb_ycc_convert_internal +#define rgb_gray_convert_internal extrgb_gray_convert_internal +#include "jccolext.c" +#undef RGB_RED +#undef RGB_GREEN +#undef RGB_BLUE +#undef RGB_PIXELSIZE +#undef rgb_ycc_convert_internal +#undef rgb_gray_convert_internal -static const unsigned char blue_lut[256] = { - 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 2 , 2 , - 2 , 2 , 2 , 2 , 2 , 2 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 4 , - 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , - 5 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 7 , 7 , 7 , 7 , 7 , 7 , - 7 , 7 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 9 , 9 , 9 , 9 , 9 , - 9 , 9 , 9 , 9 , 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, - 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, - 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, - 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29 -}; +#define RGB_RED EXT_RGBX_RED +#define RGB_GREEN EXT_RGBX_GREEN +#define RGB_BLUE EXT_RGBX_BLUE +#define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE +#define rgb_ycc_convert_internal extrgbx_ycc_convert_internal +#define rgb_gray_convert_internal extrgbx_gray_convert_internal +#include "jccolext.c" +#undef RGB_RED +#undef RGB_GREEN +#undef RGB_BLUE +#undef RGB_PIXELSIZE +#undef rgb_ycc_convert_internal +#undef rgb_gray_convert_internal -#endif +#define RGB_RED EXT_BGR_RED +#define RGB_GREEN EXT_BGR_GREEN +#define RGB_BLUE EXT_BGR_BLUE +#define RGB_PIXELSIZE EXT_BGR_PIXELSIZE +#define rgb_ycc_convert_internal extbgr_ycc_convert_internal +#define rgb_gray_convert_internal extbgr_gray_convert_internal +#include "jccolext.c" +#undef RGB_RED +#undef RGB_GREEN +#undef RGB_BLUE +#undef RGB_PIXELSIZE +#undef rgb_ycc_convert_internal +#undef rgb_gray_convert_internal + +#define RGB_RED EXT_BGRX_RED +#define RGB_GREEN EXT_BGRX_GREEN +#define RGB_BLUE EXT_BGRX_BLUE +#define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE +#define rgb_ycc_convert_internal extbgrx_ycc_convert_internal +#define rgb_gray_convert_internal extbgrx_gray_convert_internal +#include "jccolext.c" +#undef RGB_RED +#undef RGB_GREEN +#undef RGB_BLUE +#undef RGB_PIXELSIZE +#undef rgb_ycc_convert_internal +#undef rgb_gray_convert_internal + +#define RGB_RED EXT_XBGR_RED +#define RGB_GREEN EXT_XBGR_GREEN +#define RGB_BLUE EXT_XBGR_BLUE +#define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE +#define rgb_ycc_convert_internal extxbgr_ycc_convert_internal +#define rgb_gray_convert_internal extxbgr_gray_convert_internal +#include "jccolext.c" +#undef RGB_RED +#undef RGB_GREEN +#undef RGB_BLUE +#undef RGB_PIXELSIZE +#undef rgb_ycc_convert_internal +#undef rgb_gray_convert_internal + +#define RGB_RED EXT_XRGB_RED +#define RGB_GREEN EXT_XRGB_GREEN +#define RGB_BLUE EXT_XRGB_BLUE +#define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE +#define rgb_ycc_convert_internal extxrgb_ycc_convert_internal +#define rgb_gray_convert_internal extxrgb_gray_convert_internal +#include "jccolext.c" +#undef RGB_RED +#undef RGB_GREEN +#undef RGB_BLUE +#undef RGB_PIXELSIZE +#undef rgb_ycc_convert_internal +#undef rgb_gray_convert_internal /* @@ -187,14 +213,6 @@ rgb_ycc_start (j_compress_ptr cinfo) /* * Convert some rows of samples to the JPEG colorspace. - * - * Note that we change from the application's interleaved-pixel format - * to our internal noninterleaved, one-plane-per-component format. - * The input buffer is therefore three times as wide as the output buffer. - * - * A starting row offset is provided only for the output buffer. The caller - * can easily adjust the passed input_buf value to accommodate any row - * offset required on that side. */ METHODDEF(void) @@ -202,43 +220,39 @@ rgb_ycc_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - register int r, g, b; - register INT32 * ctab = cconvert->rgb_ycc_tab; - register JSAMPROW inptr; - register JSAMPROW outptr0, outptr1, outptr2; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->image_width; - - while (--num_rows >= 0) { - inptr = *input_buf++; - outptr0 = output_buf[0][output_row]; - outptr1 = output_buf[1][output_row]; - outptr2 = output_buf[2][output_row]; - output_row++; - for (col = 0; col < num_cols; col++) { - r = GETJSAMPLE(inptr[rgb_red[cinfo->in_color_space]]); - g = GETJSAMPLE(inptr[rgb_green[cinfo->in_color_space]]); - b = GETJSAMPLE(inptr[rgb_blue[cinfo->in_color_space]]); - inptr += rgb_pixelsize[cinfo->in_color_space]; - /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations - * must be too; we do not need an explicit range-limiting operation. - * Hence the value being shifted is never negative, and we don't - * need the general RIGHT_SHIFT macro. - */ - /* Y */ - outptr0[col] = (JSAMPLE) - ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) - >> SCALEBITS); - /* Cb */ - outptr1[col] = (JSAMPLE) - ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) - >> SCALEBITS); - /* Cr */ - outptr2[col] = (JSAMPLE) - ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) - >> SCALEBITS); - } + switch (cinfo->in_color_space) { + case JCS_EXT_RGB: + extrgb_ycc_convert_internal(cinfo, input_buf, output_buf, output_row, + num_rows); + break; + case JCS_EXT_RGBX: + case JCS_EXT_RGBA: + extrgbx_ycc_convert_internal(cinfo, input_buf, output_buf, output_row, + num_rows); + break; + case JCS_EXT_BGR: + extbgr_ycc_convert_internal(cinfo, input_buf, output_buf, output_row, + num_rows); + break; + case JCS_EXT_BGRX: + case JCS_EXT_BGRA: + extbgrx_ycc_convert_internal(cinfo, input_buf, output_buf, output_row, + num_rows); + break; + case JCS_EXT_XBGR: + case JCS_EXT_ABGR: + extxbgr_ycc_convert_internal(cinfo, input_buf, output_buf, output_row, + num_rows); + break; + case JCS_EXT_XRGB: + case JCS_EXT_ARGB: + extxrgb_ycc_convert_internal(cinfo, input_buf, output_buf, output_row, + num_rows); + break; + default: + rgb_ycc_convert_internal(cinfo, input_buf, output_buf, output_row, + num_rows); + break; } } @@ -248,9 +262,6 @@ rgb_ycc_convert (j_compress_ptr cinfo, /* * Convert some rows of samples to the JPEG colorspace. - * This version handles RGB->grayscale conversion, which is the same - * as the RGB->Y portion of RGB->YCbCr. - * We assume rgb_ycc_start has been called (we only use the Y tables). */ METHODDEF(void) @@ -258,36 +269,39 @@ rgb_gray_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { - #if BITS_IN_JSAMPLE != 8 - register INT32 * ctab = cconvert->rgb_ycc_tab; - #endif - register JSAMPROW inptr; - register JSAMPROW outptr; - JSAMPLE *maxoutptr; - JDIMENSION num_cols = cinfo->image_width; - int rindex = rgb_red[cinfo->in_color_space]; - int gindex = rgb_green[cinfo->in_color_space]; - int bindex = rgb_blue[cinfo->in_color_space]; - int rgbstride = rgb_pixelsize[cinfo->in_color_space]; - - while (--num_rows >= 0) { - inptr = *input_buf++; - outptr = output_buf[0][output_row]; - maxoutptr = &outptr[num_cols]; - output_row++; - for (; outptr < maxoutptr; outptr++, inptr += rgbstride) { - /* Y */ - #if BITS_IN_JSAMPLE == 8 - *outptr = red_lut[inptr[rindex]] + green_lut[inptr[gindex]] - + blue_lut[inptr[bindex]]; - #else - *outptr = (JSAMPLE) - ((ctab[GETJSAMPLE(inptr[rindex])+R_Y_OFF] - + ctab[GETJSAMPLE(inptr[gindex])+G_Y_OFF] - + ctab[GETJSAMPLE(inptr[bindex])+B_Y_OFF]) - >> SCALEBITS); - #endif - } + switch (cinfo->in_color_space) { + case JCS_EXT_RGB: + extrgb_gray_convert_internal(cinfo, input_buf, output_buf, output_row, + num_rows); + break; + case JCS_EXT_RGBX: + case JCS_EXT_RGBA: + extrgbx_gray_convert_internal(cinfo, input_buf, output_buf, output_row, + num_rows); + break; + case JCS_EXT_BGR: + extbgr_gray_convert_internal(cinfo, input_buf, output_buf, output_row, + num_rows); + break; + case JCS_EXT_BGRX: + case JCS_EXT_BGRA: + extbgrx_gray_convert_internal(cinfo, input_buf, output_buf, output_row, + num_rows); + break; + case JCS_EXT_XBGR: + case JCS_EXT_ABGR: + extxbgr_gray_convert_internal(cinfo, input_buf, output_buf, output_row, + num_rows); + break; + case JCS_EXT_XRGB: + case JCS_EXT_ARGB: + extxrgb_gray_convert_internal(cinfo, input_buf, output_buf, output_row, + num_rows); + break; + default: + rgb_gray_convert_internal(cinfo, input_buf, output_buf, output_row, + num_rows); + break; } } @@ -453,6 +467,10 @@ jinit_color_converter (j_compress_ptr cinfo) case JCS_EXT_BGRX: case JCS_EXT_XBGR: case JCS_EXT_XRGB: + case JCS_EXT_RGBA: + case JCS_EXT_BGRA: + case JCS_EXT_ABGR: + case JCS_EXT_ARGB: if (cinfo->input_components != rgb_pixelsize[cinfo->in_color_space]) ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); break; @@ -487,9 +505,17 @@ jinit_color_converter (j_compress_ptr cinfo) cinfo->in_color_space == JCS_EXT_BGR || cinfo->in_color_space == JCS_EXT_BGRX || cinfo->in_color_space == JCS_EXT_XBGR || - cinfo->in_color_space == JCS_EXT_XRGB) { - cconvert->pub.start_pass = rgb_ycc_start; - cconvert->pub.color_convert = rgb_gray_convert; + cinfo->in_color_space == JCS_EXT_XRGB || + cinfo->in_color_space == JCS_EXT_RGBA || + cinfo->in_color_space == JCS_EXT_BGRA || + cinfo->in_color_space == JCS_EXT_ABGR || + cinfo->in_color_space == JCS_EXT_ARGB) { + if (jsimd_can_rgb_gray()) + cconvert->pub.color_convert = jsimd_rgb_gray_convert; + else { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = rgb_gray_convert; + } } else if (cinfo->in_color_space == JCS_YCbCr) cconvert->pub.color_convert = grayscale_convert; else @@ -503,6 +529,10 @@ jinit_color_converter (j_compress_ptr cinfo) case JCS_EXT_BGRX: case JCS_EXT_XBGR: case JCS_EXT_XRGB: + case JCS_EXT_RGBA: + case JCS_EXT_BGRA: + case JCS_EXT_ABGR: + case JCS_EXT_ARGB: if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); if (cinfo->in_color_space == cinfo->jpeg_color_space && @@ -521,7 +551,11 @@ jinit_color_converter (j_compress_ptr cinfo) cinfo->in_color_space == JCS_EXT_BGR || cinfo->in_color_space == JCS_EXT_BGRX || cinfo->in_color_space == JCS_EXT_XBGR || - cinfo->in_color_space == JCS_EXT_XRGB) { + cinfo->in_color_space == JCS_EXT_XRGB || + cinfo->in_color_space == JCS_EXT_RGBA || + cinfo->in_color_space == JCS_EXT_BGRA || + cinfo->in_color_space == JCS_EXT_ABGR || + cinfo->in_color_space == JCS_EXT_ARGB) { if (jsimd_can_rgb_ycc()) cconvert->pub.color_convert = jsimd_rgb_ycc_convert; else { diff --git a/media/libjpeg/jcdctmgr.c b/media/libjpeg/jcdctmgr.c index 711f9dab6290..12f88725ddfd 100644 --- a/media/libjpeg/jcdctmgr.c +++ b/media/libjpeg/jcdctmgr.c @@ -182,7 +182,7 @@ compute_reciprocal (UINT16 divisor, DCTELEM * dtbl) /* fq will be one bit too large to fit in DCTELEM, so adjust */ fq >>= 1; r--; - } else if (fr <= (divisor / 2)) { /* fractional part is < 0.5 */ + } else if (fr <= (divisor / 2U)) { /* fractional part is < 0.5 */ c++; } else { /* fractional part is > 0.5 */ fq++; diff --git a/media/libjpeg/jchuff.c b/media/libjpeg/jchuff.c index f9fba90b6d42..fd4fa46ca531 100644 --- a/media/libjpeg/jchuff.c +++ b/media/libjpeg/jchuff.c @@ -2,6 +2,7 @@ * jchuff.c * * Copyright (C) 1991-1997, Thomas G. Lane. + * Copyright (C) 2009-2011, D. R. Commander. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -18,6 +19,15 @@ #include "jinclude.h" #include "jpeglib.h" #include "jchuff.h" /* Declarations shared with jcphuff.c */ +#include + +static unsigned char jpeg_nbits_table[65536]; +static int jpeg_nbits_table_init = 0; + +#ifndef min + #define min(a,b) ((a)<(b)?(a):(b)) +#endif + /* Expanded entropy encoder object for Huffman encoding. * @@ -26,7 +36,7 @@ */ typedef struct { - INT32 put_buffer; /* current bit-accumulation buffer */ + size_t put_buffer; /* current bit-accumulation buffer */ int put_bits; /* # of bits now in it */ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ } savable_state; @@ -260,6 +270,15 @@ jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, dtbl->ehufco[i] = huffcode[p]; dtbl->ehufsi[i] = huffsize[p]; } + + if(!jpeg_nbits_table_init) { + for(i = 0; i < 65536; i++) { + int nbits = 0, temp = i; + while (temp) {temp >>= 1; nbits++;} + jpeg_nbits_table[i] = nbits; + } + jpeg_nbits_table_init = 1; + } } @@ -279,6 +298,8 @@ dump_buffer (working_state * state) { struct jpeg_destination_mgr * dest = state->cinfo->dest; + dest->free_in_buffer = state->free_in_buffer; + if (! (*dest->empty_output_buffer) (state->cinfo)) return FALSE; /* After a successful buffer dump, must reset buffer pointers */ @@ -290,58 +311,138 @@ dump_buffer (working_state * state) /* Outputting bits to the file */ -/* Only the right 24 bits of put_buffer are used; the valid bits are - * left-justified in this part. At most 16 bits can be passed to emit_bits - * in one call, and we never retain more than 7 bits in put_buffer - * between calls, so 24 bits are sufficient. +/* These macros perform the same task as the emit_bits() function in the + * original libjpeg code. In addition to reducing overhead by explicitly + * inlining the code, additional performance is achieved by taking into + * account the size of the bit buffer and waiting until it is almost full + * before emptying it. This mostly benefits 64-bit platforms, since 6 + * bytes can be stored in a 64-bit bit buffer before it has to be emptied. */ -INLINE -LOCAL(boolean) -emit_bits (working_state * state, unsigned int code, int size) -/* Emit some bits; return TRUE if successful, FALSE if must suspend */ -{ - /* This routine is heavily used, so it's worth coding tightly. */ - register INT32 put_buffer = (INT32) code; - register int put_bits = state->cur.put_bits; +#define EMIT_BYTE() { \ + JOCTET c; \ + put_bits -= 8; \ + c = (JOCTET)GETJOCTET(put_buffer >> put_bits); \ + *buffer++ = c; \ + if (c == 0xFF) /* need to stuff a zero byte? */ \ + *buffer++ = 0; \ + } - /* if size is 0, caller used an invalid Huffman table entry */ - if (size == 0) - ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); - - put_buffer &= (((INT32) 1)<cur.put_buffer; /* and merge with old buffer contents */ - - while (put_bits >= 8) { - int c = (int) ((put_buffer >> 16) & 0xFF); - - emit_byte(state, c, return FALSE); - if (c == 0xFF) { /* need to stuff a zero byte? */ - emit_byte(state, 0, return FALSE); - } - put_buffer <<= 8; - put_bits -= 8; - } - - state->cur.put_buffer = put_buffer; /* update state variables */ - state->cur.put_bits = put_bits; - - return TRUE; +#define PUT_BITS(code, size) { \ + put_bits += size; \ + put_buffer = (put_buffer << size) | code; \ } +#define CHECKBUF15() { \ + if (put_bits > 15) { \ + EMIT_BYTE() \ + EMIT_BYTE() \ + } \ +} + +#define CHECKBUF31() { \ + if (put_bits > 31) { \ + EMIT_BYTE() \ + EMIT_BYTE() \ + EMIT_BYTE() \ + EMIT_BYTE() \ + } \ +} + +#define CHECKBUF47() { \ + if (put_bits > 47) { \ + EMIT_BYTE() \ + EMIT_BYTE() \ + EMIT_BYTE() \ + EMIT_BYTE() \ + EMIT_BYTE() \ + EMIT_BYTE() \ + } \ +} + +#if __WORDSIZE==64 || defined(_WIN64) + +#define EMIT_BITS(code, size) { \ + CHECKBUF47() \ + PUT_BITS(code, size) \ +} + +#define EMIT_CODE(code, size) { \ + temp2 &= (((INT32) 1)<free_in_buffer < BUFSIZE) { \ + localbuf = 1; \ + buffer = _buffer; \ + } \ + else buffer = state->next_output_byte; \ + } + +#define STORE_BUFFER() { \ + if (localbuf) { \ + bytes = buffer - _buffer; \ + buffer = _buffer; \ + while (bytes > 0) { \ + bytestocopy = min(bytes, state->free_in_buffer); \ + MEMCOPY(state->next_output_byte, buffer, bytestocopy); \ + state->next_output_byte += bytestocopy; \ + buffer += bytestocopy; \ + state->free_in_buffer -= bytestocopy; \ + if (state->free_in_buffer == 0) \ + if (! dump_buffer(state)) return FALSE; \ + bytes -= bytestocopy; \ + } \ + } \ + else { \ + state->free_in_buffer -= (buffer - state->next_output_byte); \ + state->next_output_byte = buffer; \ + } \ + } + LOCAL(boolean) flush_bits (working_state * state) { - if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ - return FALSE; + JOCTET _buffer[BUFSIZE], *buffer; + size_t put_buffer; int put_bits; + size_t bytes, bytestocopy; int localbuf = 0; + + put_buffer = state->cur.put_buffer; + put_bits = state->cur.put_bits; + LOAD_BUFFER() + + /* fill any partial byte with ones */ + PUT_BITS(0x7F, 7) + while (put_bits >= 8) EMIT_BYTE() + state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ state->cur.put_bits = 0; + STORE_BUFFER() + return TRUE; } @@ -352,91 +453,108 @@ LOCAL(boolean) encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, c_derived_tbl *dctbl, c_derived_tbl *actbl) { - register int temp, temp2; - register int nbits; - register int k, r, i; - + int temp, temp2, temp3; + int nbits; + int r, code, size; + JOCTET _buffer[BUFSIZE], *buffer; + size_t put_buffer; int put_bits; + int code_0xf0 = actbl->ehufco[0xf0], size_0xf0 = actbl->ehufsi[0xf0]; + size_t bytes, bytestocopy; int localbuf = 0; + + put_buffer = state->cur.put_buffer; + put_bits = state->cur.put_bits; + LOAD_BUFFER() + /* Encode the DC coefficient difference per section F.1.2.1 */ temp = temp2 = block[0] - last_dc_val; - if (temp < 0) { - temp = -temp; /* temp is abs value of input */ - /* For a negative input, want temp2 = bitwise complement of abs(input) */ - /* This code assumes we are on a two's complement machine */ - temp2--; - } - + /* This is a well-known technique for obtaining the absolute value without a + * branch. It is derived from an assembly language technique presented in + * "How to Optimize for the Pentium Processors", Copyright (c) 1996, 1997 by + * Agner Fog. + */ + temp3 = temp >> (CHAR_BIT * sizeof(int) - 1); + temp ^= temp3; + temp -= temp3; + + /* For a negative input, want temp2 = bitwise complement of abs(input) */ + /* This code assumes we are on a two's complement machine */ + temp2 += temp3; + /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 0; - while (temp) { - nbits++; - temp >>= 1; - } - /* Check for out-of-range coefficient values. - * Since we're encoding a difference, the range limit is twice as much. - */ - if (nbits > MAX_COEF_BITS+1) - ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); - + nbits = jpeg_nbits_table[temp]; + /* Emit the Huffman-coded symbol for the number of bits */ - if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) - return FALSE; + code = dctbl->ehufco[nbits]; + size = dctbl->ehufsi[nbits]; + PUT_BITS(code, size) + CHECKBUF15() + + /* Mask off any extra bits in code */ + temp2 &= (((INT32) 1)< 15, must emit special run-length-16 codes (0xF0) */ - while (r > 15) { - if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) - return FALSE; - r -= 16; - } - temp2 = temp; - if (temp < 0) { - temp = -temp; /* temp is abs value of input */ - /* This code assumes we are on a two's complement machine */ - temp2--; - } - - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 1; /* there must be at least one 1 bit */ - while ((temp >>= 1)) - nbits++; - /* Check for out-of-range coefficient values */ - if (nbits > MAX_COEF_BITS) - ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); - - /* Emit Huffman symbol for run length / number of bits */ - i = (r << 4) + nbits; - if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i])) - return FALSE; +/* Manually unroll the k loop to eliminate the counter variable. This + * improves performance greatly on systems with a limited number of + * registers (such as x86.) + */ +#define kloop(jpeg_natural_order_of_k) { \ + if ((temp = block[jpeg_natural_order_of_k]) == 0) { \ + r++; \ + } else { \ + temp2 = temp; \ + /* Branch-less absolute value, bitwise complement, etc., same as above */ \ + temp3 = temp >> (CHAR_BIT * sizeof(int) - 1); \ + temp ^= temp3; \ + temp -= temp3; \ + temp2 += temp3; \ + nbits = jpeg_nbits_table[temp]; \ + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ \ + while (r > 15) { \ + EMIT_BITS(code_0xf0, size_0xf0) \ + r -= 16; \ + } \ + /* Emit Huffman symbol for run length / number of bits */ \ + temp3 = (r << 4) + nbits; \ + code = actbl->ehufco[temp3]; \ + size = actbl->ehufsi[temp3]; \ + EMIT_CODE(code, size) \ + r = 0; \ + } \ +} - /* Emit that number of bits of the value, if positive, */ - /* or the complement of its magnitude, if negative. */ - if (! emit_bits(state, (unsigned int) temp2, nbits)) - return FALSE; - - r = 0; - } - } + /* One iteration for each value in jpeg_natural_order[] */ + kloop(1); kloop(8); kloop(16); kloop(9); kloop(2); kloop(3); + kloop(10); kloop(17); kloop(24); kloop(32); kloop(25); kloop(18); + kloop(11); kloop(4); kloop(5); kloop(12); kloop(19); kloop(26); + kloop(33); kloop(40); kloop(48); kloop(41); kloop(34); kloop(27); + kloop(20); kloop(13); kloop(6); kloop(7); kloop(14); kloop(21); + kloop(28); kloop(35); kloop(42); kloop(49); kloop(56); kloop(57); + kloop(50); kloop(43); kloop(36); kloop(29); kloop(22); kloop(15); + kloop(23); kloop(30); kloop(37); kloop(44); kloop(51); kloop(58); + kloop(59); kloop(52); kloop(45); kloop(38); kloop(31); kloop(39); + kloop(46); kloop(53); kloop(60); kloop(61); kloop(54); kloop(47); + kloop(55); kloop(62); kloop(63); /* If the last coef(s) were zero, emit an end-of-block code */ - if (r > 0) - if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0])) - return FALSE; + if (r > 0) { + code = actbl->ehufco[0]; + size = actbl->ehufsi[0]; + EMIT_BITS(code, size) + } + + state->cur.put_buffer = put_buffer; + state->cur.put_bits = put_bits; + STORE_BUFFER() return TRUE; } diff --git a/media/libjpeg/jcmainct.c b/media/libjpeg/jcmainct.c index e0279a7e017a..bd0051af8522 100644 --- a/media/libjpeg/jcmainct.c +++ b/media/libjpeg/jcmainct.c @@ -68,32 +68,32 @@ METHODDEF(void) process_data_buffer_main METHODDEF(void) start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode) { - my_main_ptr main = (my_main_ptr) cinfo->main; + my_main_ptr main_ptr = (my_main_ptr) cinfo->main; /* Do nothing in raw-data mode. */ if (cinfo->raw_data_in) return; - main->cur_iMCU_row = 0; /* initialize counters */ - main->rowgroup_ctr = 0; - main->suspended = FALSE; - main->pass_mode = pass_mode; /* save mode for use by process_data */ + main_ptr->cur_iMCU_row = 0; /* initialize counters */ + main_ptr->rowgroup_ctr = 0; + main_ptr->suspended = FALSE; + main_ptr->pass_mode = pass_mode; /* save mode for use by process_data */ switch (pass_mode) { case JBUF_PASS_THRU: #ifdef FULL_MAIN_BUFFER_SUPPORTED - if (main->whole_image[0] != NULL) + if (main_ptr->whole_image[0] != NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif - main->pub.process_data = process_data_simple_main; + main_ptr->pub.process_data = process_data_simple_main; break; #ifdef FULL_MAIN_BUFFER_SUPPORTED case JBUF_SAVE_SOURCE: case JBUF_CRANK_DEST: case JBUF_SAVE_AND_PASS: - if (main->whole_image[0] == NULL) + if (main_ptr->whole_image[0] == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - main->pub.process_data = process_data_buffer_main; + main_ptr->pub.process_data = process_data_buffer_main; break; #endif default: @@ -114,46 +114,46 @@ process_data_simple_main (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail) { - my_main_ptr main = (my_main_ptr) cinfo->main; + my_main_ptr main_ptr = (my_main_ptr) cinfo->main; - while (main->cur_iMCU_row < cinfo->total_iMCU_rows) { + while (main_ptr->cur_iMCU_row < cinfo->total_iMCU_rows) { /* Read input data if we haven't filled the main buffer yet */ - if (main->rowgroup_ctr < DCTSIZE) + if (main_ptr->rowgroup_ctr < DCTSIZE) (*cinfo->prep->pre_process_data) (cinfo, input_buf, in_row_ctr, in_rows_avail, - main->buffer, &main->rowgroup_ctr, + main_ptr->buffer, &main_ptr->rowgroup_ctr, (JDIMENSION) DCTSIZE); /* If we don't have a full iMCU row buffered, return to application for * more data. Note that preprocessor will always pad to fill the iMCU row * at the bottom of the image. */ - if (main->rowgroup_ctr != DCTSIZE) + if (main_ptr->rowgroup_ctr != DCTSIZE) return; /* Send the completed row to the compressor */ - if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) { + if (! (*cinfo->coef->compress_data) (cinfo, main_ptr->buffer)) { /* If compressor did not consume the whole row, then we must need to * suspend processing and return to the application. In this situation * we pretend we didn't yet consume the last input row; otherwise, if * it happened to be the last row of the image, the application would * think we were done. */ - if (! main->suspended) { + if (! main_ptr->suspended) { (*in_row_ctr)--; - main->suspended = TRUE; + main_ptr->suspended = TRUE; } return; } /* We did finish the row. Undo our little suspension hack if a previous * call suspended; then mark the main buffer empty. */ - if (main->suspended) { + if (main_ptr->suspended) { (*in_row_ctr)++; - main->suspended = FALSE; + main_ptr->suspended = FALSE; } - main->rowgroup_ctr = 0; - main->cur_iMCU_row++; + main_ptr->rowgroup_ctr = 0; + main_ptr->cur_iMCU_row++; } } @@ -173,22 +173,22 @@ process_data_buffer_main (j_compress_ptr cinfo, my_main_ptr main = (my_main_ptr) cinfo->main; int ci; jpeg_component_info *compptr; - boolean writing = (main->pass_mode != JBUF_CRANK_DEST); + boolean writing = (main_ptr->pass_mode != JBUF_CRANK_DEST); - while (main->cur_iMCU_row < cinfo->total_iMCU_rows) { + while (main_ptr->cur_iMCU_row < cinfo->total_iMCU_rows) { /* Realign the virtual buffers if at the start of an iMCU row. */ - if (main->rowgroup_ctr == 0) { + if (main_ptr->rowgroup_ctr == 0) { for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - main->buffer[ci] = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, main->whole_image[ci], - main->cur_iMCU_row * (compptr->v_samp_factor * DCTSIZE), + main_ptr->buffer[ci] = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, main_ptr->whole_image[ci], + main_ptr->cur_iMCU_row * (compptr->v_samp_factor * DCTSIZE), (JDIMENSION) (compptr->v_samp_factor * DCTSIZE), writing); } /* In a read pass, pretend we just read some source data. */ if (! writing) { *in_row_ctr += cinfo->max_v_samp_factor * DCTSIZE; - main->rowgroup_ctr = DCTSIZE; + main_ptr->rowgroup_ctr = DCTSIZE; } } @@ -197,40 +197,40 @@ process_data_buffer_main (j_compress_ptr cinfo, if (writing) { (*cinfo->prep->pre_process_data) (cinfo, input_buf, in_row_ctr, in_rows_avail, - main->buffer, &main->rowgroup_ctr, + main_ptr->buffer, &main_ptr->rowgroup_ctr, (JDIMENSION) DCTSIZE); /* Return to application if we need more data to fill the iMCU row. */ - if (main->rowgroup_ctr < DCTSIZE) + if (main_ptr->rowgroup_ctr < DCTSIZE) return; } /* Emit data, unless this is a sink-only pass. */ - if (main->pass_mode != JBUF_SAVE_SOURCE) { - if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) { + if (main_ptr->pass_mode != JBUF_SAVE_SOURCE) { + if (! (*cinfo->coef->compress_data) (cinfo, main_ptr->buffer)) { /* If compressor did not consume the whole row, then we must need to * suspend processing and return to the application. In this situation * we pretend we didn't yet consume the last input row; otherwise, if * it happened to be the last row of the image, the application would * think we were done. */ - if (! main->suspended) { + if (! main_ptr->suspended) { (*in_row_ctr)--; - main->suspended = TRUE; + main_ptr->suspended = TRUE; } return; } /* We did finish the row. Undo our little suspension hack if a previous * call suspended; then mark the main buffer empty. */ - if (main->suspended) { + if (main_ptr->suspended) { (*in_row_ctr)++; - main->suspended = FALSE; + main_ptr->suspended = FALSE; } } /* If get here, we are done with this iMCU row. Mark buffer empty. */ - main->rowgroup_ctr = 0; - main->cur_iMCU_row++; + main_ptr->rowgroup_ctr = 0; + main_ptr->cur_iMCU_row++; } } @@ -244,15 +244,15 @@ process_data_buffer_main (j_compress_ptr cinfo, GLOBAL(void) jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) { - my_main_ptr main; + my_main_ptr main_ptr; int ci; jpeg_component_info *compptr; - main = (my_main_ptr) + main_ptr = (my_main_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_main_controller)); - cinfo->main = (struct jpeg_c_main_controller *) main; - main->pub.start_pass = start_pass_main; + cinfo->main = (struct jpeg_c_main_controller *) main_ptr; + main_ptr->pub.start_pass = start_pass_main; /* We don't need to create a buffer in raw-data mode. */ if (cinfo->raw_data_in) @@ -267,7 +267,7 @@ jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) /* Note we pad the bottom to a multiple of the iMCU height */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - main->whole_image[ci] = (*cinfo->mem->request_virt_sarray) + main_ptr->whole_image[ci] = (*cinfo->mem->request_virt_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, compptr->width_in_blocks * DCTSIZE, (JDIMENSION) jround_up((long) compptr->height_in_blocks, @@ -279,12 +279,12 @@ jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) #endif } else { #ifdef FULL_MAIN_BUFFER_SUPPORTED - main->whole_image[0] = NULL; /* flag for no virtual arrays */ + main_ptr->whole_image[0] = NULL; /* flag for no virtual arrays */ #endif /* Allocate a strip buffer for each component */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - main->buffer[ci] = (*cinfo->mem->alloc_sarray) + main_ptr->buffer[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, compptr->width_in_blocks * DCTSIZE, (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); diff --git a/media/libjpeg/jcmaster.c b/media/libjpeg/jcmaster.c index 74df5556ce2d..3ca346ca80d9 100644 --- a/media/libjpeg/jcmaster.c +++ b/media/libjpeg/jcmaster.c @@ -75,7 +75,9 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only) JDIMENSION jd_samplesperrow; #if JPEG_LIB_VERSION >= 70 +#if JPEG_LIB_VERSION >= 80 if (!transcode_only) +#endif jpeg_calc_jpeg_dimensions(cinfo); #endif diff --git a/media/libjpeg/jconfig.h b/media/libjpeg/jconfig.h index 4d3c49d37c93..f25cbc4d2513 100644 --- a/media/libjpeg/jconfig.h +++ b/media/libjpeg/jconfig.h @@ -4,7 +4,10 @@ /* Export libjpeg v6.2's ABI. */ #define JPEG_LIB_VERSION 62 -/* Define if your compiler supports prototypes */ +/* libjpeg-turbo version */ +#define LIBJPEG_TURBO_VERSION 1.2.0 + +/* Compiler supports function prototypes. */ #define HAVE_PROTOTYPES 1 /* Define to 1 if you have the header file. */ @@ -13,25 +16,25 @@ /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 -/* Define to 1 if the system has the type `unsigned char'. */ +/* Compiler supports 'unsigned char'. */ #define HAVE_UNSIGNED_CHAR 1 -/* Define to 1 if the system has the type `unsigned short'. */ +/* Compiler supports 'unsigned short'. */ #define HAVE_UNSIGNED_SHORT 1 -/* Define if you want use complete types */ +/* Compiler does not support pointers to unspecified structures. */ /* #define INCOMPLETE_TYPES_BROKEN 1 */ -/* Define if you have BSD-like bzero and bcopy */ +/* Compiler has rather than standard . */ /* #undef NEED_BSD_STRINGS */ -/* Define if you need short function names */ +/* Linker requires that global names be unique in first 15 characters. */ /* #undef NEED_SHORT_EXTERNAL_NAMES */ -/* Define if you have sys/types.h */ +/* Need to include in order to obtain size_t. */ #define NEED_SYS_TYPES_H 1 -/* Define if shift is unsigned */ +/* Broken compiler shifts signed values as an unsigned shift. */ /* #undef RIGHT_SHIFT_IS_UNSIGNED */ /* Use accelerated SIMD routines. */ @@ -45,15 +48,5 @@ /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - /* Define to `unsigned int' if does not define. */ /* #undef size_t */ - -/* MOZILLA CHANGE: libjpeg-turbo doesn't define INLINE in its config file, so - * we define it here. */ -#define INLINE NS_ALWAYS_INLINE diff --git a/media/libjpeg/jconfig.h.in b/media/libjpeg/jconfig.h.in deleted file mode 100644 index 670afab53e43..000000000000 --- a/media/libjpeg/jconfig.h.in +++ /dev/null @@ -1,60 +0,0 @@ -/* Version ID for the JPEG library. - * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". - */ -#define JPEG_LIB_VERSION 62 /* Version 6b */ - -/* Support arithmetic encoding */ -#undef C_ARITH_CODING_SUPPORTED - -/* Support arithmetic decoding */ -#undef D_ARITH_CODING_SUPPORTED - -/* Define if your compiler supports prototypes */ -#undef HAVE_PROTOTYPES - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDDEF_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDLIB_H - -/* Define to 1 if the system has the type `unsigned char'. */ -#undef HAVE_UNSIGNED_CHAR - -/* Define to 1 if the system has the type `unsigned short'. */ -#undef HAVE_UNSIGNED_SHORT - -/* Define if you want use complete types */ -#undef INCOMPLETE_TYPES_BROKEN - -/* Define if you have BSD-like bzero and bcopy */ -#undef NEED_BSD_STRINGS - -/* Define if you need short function names */ -#undef NEED_SHORT_EXTERNAL_NAMES - -/* Define if you have sys/types.h */ -#undef NEED_SYS_TYPES_H - -/* Define if shift is unsigned */ -#undef RIGHT_SHIFT_IS_UNSIGNED - -/* Use accelerated SIMD routines. */ -#undef WITH_SIMD - -/* Define to 1 if type `char' is unsigned and you are not using gcc. */ -#ifndef __CHAR_UNSIGNED__ -# undef __CHAR_UNSIGNED__ -#endif - -/* Define to empty if `const' does not conform to ANSI C. */ -#undef const - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -#undef inline -#endif - -/* Define to `unsigned int' if does not define. */ -#undef size_t diff --git a/media/libjpeg/jcparam.c b/media/libjpeg/jcparam.c index 27b5a035b308..557fdc9f67b4 100644 --- a/media/libjpeg/jcparam.c +++ b/media/libjpeg/jcparam.c @@ -3,7 +3,7 @@ * * Copyright (C) 1991-1998, Thomas G. Lane. * Modified 2003-2008 by Guido Vollbeding. - * Copyright (C) 2009-2010, D. R. Commander. + * Copyright (C) 2009-2011, D. R. Commander. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -398,6 +398,10 @@ jpeg_default_colorspace (j_compress_ptr cinfo) case JCS_EXT_BGRX: case JCS_EXT_XBGR: case JCS_EXT_XRGB: + case JCS_EXT_RGBA: + case JCS_EXT_BGRA: + case JCS_EXT_ABGR: + case JCS_EXT_ARGB: jpeg_set_colorspace(cinfo, JCS_YCbCr); break; case JCS_YCbCr: diff --git a/media/libjpeg/jctrans.c b/media/libjpeg/jctrans.c new file mode 100644 index 000000000000..916e872faf06 --- /dev/null +++ b/media/libjpeg/jctrans.c @@ -0,0 +1,399 @@ +/* + * jctrans.c + * + * Copyright (C) 1995-1998, Thomas G. Lane. + * Modified 2000-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains library routines for transcoding compression, + * that is, writing raw DCT coefficient arrays to an output JPEG file. + * The routines in jcapimin.c will also be needed by a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Forward declarations */ +LOCAL(void) transencode_master_selection + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); +LOCAL(void) transencode_coef_controller + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); + + +/* + * Compression initialization for writing raw-coefficient data. + * Before calling this, all parameters and a data destination must be set up. + * Call jpeg_finish_compress() to actually write the data. + * + * The number of passed virtual arrays must match cinfo->num_components. + * Note that the virtual arrays need not be filled or even realized at + * the time write_coefficients is called; indeed, if the virtual arrays + * were requested from this compression object's memory manager, they + * typically will be realized during this routine and filled afterwards. + */ + +GLOBAL(void) +jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Mark all tables to be written */ + jpeg_suppress_tables(cinfo, FALSE); + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Perform master selection of active modules */ + transencode_master_selection(cinfo, coef_arrays); + /* Wait for jpeg_finish_compress() call */ + cinfo->next_scanline = 0; /* so jpeg_write_marker works */ + cinfo->global_state = CSTATE_WRCOEFS; +} + + +/* + * Initialize the compression object with default parameters, + * then copy from the source object all parameters needed for lossless + * transcoding. Parameters that can be varied without loss (such as + * scan script and Huffman optimization) are left in their default states. + */ + +GLOBAL(void) +jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, + j_compress_ptr dstinfo) +{ + JQUANT_TBL ** qtblptr; + jpeg_component_info *incomp, *outcomp; + JQUANT_TBL *c_quant, *slot_quant; + int tblno, ci, coefi; + + /* Safety check to ensure start_compress not called yet. */ + if (dstinfo->global_state != CSTATE_START) + ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state); + /* Copy fundamental image dimensions */ + dstinfo->image_width = srcinfo->image_width; + dstinfo->image_height = srcinfo->image_height; + dstinfo->input_components = srcinfo->num_components; + dstinfo->in_color_space = srcinfo->jpeg_color_space; +#if JPEG_LIB_VERSION >= 70 + dstinfo->jpeg_width = srcinfo->output_width; + dstinfo->jpeg_height = srcinfo->output_height; + dstinfo->min_DCT_h_scaled_size = srcinfo->min_DCT_h_scaled_size; + dstinfo->min_DCT_v_scaled_size = srcinfo->min_DCT_v_scaled_size; +#endif + /* Initialize all parameters to default values */ + jpeg_set_defaults(dstinfo); + /* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB. + * Fix it to get the right header markers for the image colorspace. + */ + jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space); + dstinfo->data_precision = srcinfo->data_precision; + dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling; + /* Copy the source's quantization tables. */ + for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { + if (srcinfo->quant_tbl_ptrs[tblno] != NULL) { + qtblptr = & dstinfo->quant_tbl_ptrs[tblno]; + if (*qtblptr == NULL) + *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo); + MEMCOPY((*qtblptr)->quantval, + srcinfo->quant_tbl_ptrs[tblno]->quantval, + SIZEOF((*qtblptr)->quantval)); + (*qtblptr)->sent_table = FALSE; + } + } + /* Copy the source's per-component info. + * Note we assume jpeg_set_defaults has allocated the dest comp_info array. + */ + dstinfo->num_components = srcinfo->num_components; + if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS) + ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components, + MAX_COMPONENTS); + for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info; + ci < dstinfo->num_components; ci++, incomp++, outcomp++) { + outcomp->component_id = incomp->component_id; + outcomp->h_samp_factor = incomp->h_samp_factor; + outcomp->v_samp_factor = incomp->v_samp_factor; + outcomp->quant_tbl_no = incomp->quant_tbl_no; + /* Make sure saved quantization table for component matches the qtable + * slot. If not, the input file re-used this qtable slot. + * IJG encoder currently cannot duplicate this. + */ + tblno = outcomp->quant_tbl_no; + if (tblno < 0 || tblno >= NUM_QUANT_TBLS || + srcinfo->quant_tbl_ptrs[tblno] == NULL) + ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno); + slot_quant = srcinfo->quant_tbl_ptrs[tblno]; + c_quant = incomp->quant_table; + if (c_quant != NULL) { + for (coefi = 0; coefi < DCTSIZE2; coefi++) { + if (c_quant->quantval[coefi] != slot_quant->quantval[coefi]) + ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno); + } + } + /* Note: we do not copy the source's Huffman table assignments; + * instead we rely on jpeg_set_colorspace to have made a suitable choice. + */ + } + /* Also copy JFIF version and resolution information, if available. + * Strictly speaking this isn't "critical" info, but it's nearly + * always appropriate to copy it if available. In particular, + * if the application chooses to copy JFIF 1.02 extension markers from + * the source file, we need to copy the version to make sure we don't + * emit a file that has 1.02 extensions but a claimed version of 1.01. + * We will *not*, however, copy version info from mislabeled "2.01" files. + */ + if (srcinfo->saw_JFIF_marker) { + if (srcinfo->JFIF_major_version == 1) { + dstinfo->JFIF_major_version = srcinfo->JFIF_major_version; + dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version; + } + dstinfo->density_unit = srcinfo->density_unit; + dstinfo->X_density = srcinfo->X_density; + dstinfo->Y_density = srcinfo->Y_density; + } +} + + +/* + * Master selection of compression modules for transcoding. + * This substitutes for jcinit.c's initialization of the full compressor. + */ + +LOCAL(void) +transencode_master_selection (j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays) +{ + /* Although we don't actually use input_components for transcoding, + * jcmaster.c's initial_setup will complain if input_components is 0. + */ + cinfo->input_components = 1; + /* Initialize master control (includes parameter checking/processing) */ + jinit_c_master_control(cinfo, TRUE /* transcode only */); + + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { +#ifdef C_ARITH_CODING_SUPPORTED + jinit_arith_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +#endif + } else { + if (cinfo->progressive_mode) { +#ifdef C_PROGRESSIVE_SUPPORTED + jinit_phuff_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_huff_encoder(cinfo); + } + + /* We need a special coefficient buffer controller. */ + transencode_coef_controller(cinfo, coef_arrays); + + jinit_marker_writer(cinfo); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Write the datastream header (SOI, JFIF) immediately. + * Frame and scan headers are postponed till later. + * This lets application insert special markers after the SOI. + */ + (*cinfo->marker->write_file_header) (cinfo); +} + + +/* + * The rest of this file is a special implementation of the coefficient + * buffer controller. This is similar to jccoefct.c, but it handles only + * output from presupplied virtual arrays. Furthermore, we generate any + * dummy padding blocks on-the-fly rather than expecting them to be present + * in the arrays. + */ + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_coef_controller pub; /* public fields */ + + JDIMENSION iMCU_row_num; /* iMCU row # within image */ + JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* Virtual block array for each component. */ + jvirt_barray_ptr * whole_image; + + /* Workspace for constructing dummy blocks at right/bottom edges. */ + JBLOCKROW dummy_buffer[C_MAX_BLOCKS_IN_MCU]; +} my_coef_controller; + +typedef my_coef_controller * my_coef_ptr; + + +LOCAL(void) +start_iMCU_row (j_compress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row */ +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->mcu_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + if (pass_mode != JBUF_CRANK_DEST) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + coef->iMCU_row_num = 0; + start_iMCU_row(cinfo); +} + + +/* + * Process some data. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the scan. + * The data is obtained from the virtual arrays and fed to the entropy coder. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf is ignored; it is likely to be a NULL pointer. + */ + +METHODDEF(boolean) +compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, ci, xindex, yindex, yoffset, blockcnt; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + coef->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * compptr->MCU_width; + blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (coef->iMCU_row_num < last_iMCU_row || + yindex+yoffset < compptr->last_row_height) { + /* Fill in pointers to real blocks in this row */ + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < blockcnt; xindex++) + MCU_buffer[blkn++] = buffer_ptr++; + } else { + /* At bottom of image, need a whole row of dummy blocks */ + xindex = 0; + } + /* Fill in any dummy blocks needed in this row. + * Dummy blocks are filled in the same way as in jccoefct.c: + * all zeroes in the AC entries, DC entries equal to previous + * block's DC value. The init routine has already zeroed the + * AC entries, so we need only set the DC entries correctly. + */ + for (; xindex < compptr->MCU_width; xindex++) { + MCU_buffer[blkn] = coef->dummy_buffer[blkn]; + MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0]; + blkn++; + } + } + } + /* Try to write the MCU. */ + if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + + +/* + * Initialize coefficient buffer controller. + * + * Each passed coefficient array must be the right size for that + * coefficient: width_in_blocks wide and height_in_blocks high, + * with unitheight at least v_samp_factor. + */ + +LOCAL(void) +transencode_coef_controller (j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays) +{ + my_coef_ptr coef; + JBLOCKROW buffer; + int i; + + coef = (my_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_coef_controller)); + cinfo->coef = (struct jpeg_c_coef_controller *) coef; + coef->pub.start_pass = start_pass_coef; + coef->pub.compress_data = compress_output; + + /* Save pointer to virtual arrays */ + coef->whole_image = coef_arrays; + + /* Allocate and pre-zero space for dummy DCT blocks. */ + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + jzero_far((void FAR *) buffer, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { + coef->dummy_buffer[i] = buffer + i; + } +} diff --git a/media/libjpeg/jdcolext.c b/media/libjpeg/jdcolext.c new file mode 100644 index 000000000000..07da949fae02 --- /dev/null +++ b/media/libjpeg/jdcolext.c @@ -0,0 +1,104 @@ +/* + * jdcolext.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * Copyright (C) 2009, 2011, D. R. Commander. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains output colorspace conversion routines. + */ + + +/* This file is included by jdcolor.c */ + + +/* + * Convert some rows of samples to the output colorspace. + * + * Note that we change from noninterleaved, one-plane-per-component format + * to interleaved-pixel format. The output buffer is therefore three times + * as wide as the input buffer. + * A starting row offset is provided only for the input buffer. The caller + * can easily adjust the passed output_buf value to accommodate any row + * offset required on that side. + */ + +INLINE +LOCAL(void) +ycc_rgb_convert_internal (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int y, cb, cr; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + register int * Crrtab = cconvert->Cr_r_tab; + register int * Cbbtab = cconvert->Cb_b_tab; + register INT32 * Crgtab = cconvert->Cr_g_tab; + register INT32 * Cbgtab = cconvert->Cb_g_tab; + SHIFT_TEMPS + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + y = GETJSAMPLE(inptr0[col]); + cb = GETJSAMPLE(inptr1[col]); + cr = GETJSAMPLE(inptr2[col]); + /* Range-limiting is essential due to noise introduced by DCT losses. */ + outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; + outptr[RGB_GREEN] = range_limit[y + + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], + SCALEBITS))]; + outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; + /* Set unused byte to 0xFF so it can be interpreted as an opaque */ + /* alpha channel value */ +#ifdef RGB_ALPHA + outptr[RGB_ALPHA] = 0xFF; +#endif + outptr += RGB_PIXELSIZE; + } + } +} + + +/* + * Convert grayscale to RGB: just duplicate the graylevel three times. + * This is provided to support applications that don't want to cope + * with grayscale as a separate case. + */ + +INLINE +LOCAL(void) +gray_rgb_convert_internal (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + register JSAMPROW inptr, outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + + while (--num_rows >= 0) { + inptr = input_buf[0][input_row++]; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + /* We can dispense with GETJSAMPLE() here */ + outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; + /* Set unused byte to 0xFF so it can be interpreted as an opaque */ + /* alpha channel value */ +#ifdef RGB_ALPHA + outptr[RGB_ALPHA] = 0xFF; +#endif + outptr += RGB_PIXELSIZE; + } + } +} diff --git a/media/libjpeg/jdcolor.c b/media/libjpeg/jdcolor.c index bc73b3f4621e..d9268dbb5224 100644 --- a/media/libjpeg/jdcolor.c +++ b/media/libjpeg/jdcolor.c @@ -3,7 +3,7 @@ * * Copyright (C) 1991-1997, Thomas G. Lane. * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2009, D. R. Commander. + * Copyright (C) 2009, 2011, D. R. Commander. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -14,6 +14,7 @@ #include "jinclude.h" #include "jpeglib.h" #include "jsimd.h" +#include "config.h" /* Private subobject */ @@ -65,6 +66,107 @@ typedef my_color_deconverter * my_cconvert_ptr; #define FIX(x) ((INT32) ((x) * (1L<RGB colorspace conversion. */ @@ -110,13 +212,6 @@ build_ycc_rgb_table (j_decompress_ptr cinfo) /* * Convert some rows of samples to the output colorspace. - * - * Note that we change from noninterleaved, one-plane-per-component format - * to interleaved-pixel format. The output buffer is therefore three times - * as wide as the input buffer. - * A starting row offset is provided only for the input buffer. The caller - * can easily adjust the passed output_buf value to accommodate any row - * offset required on that side. */ METHODDEF(void) @@ -124,38 +219,39 @@ ycc_rgb_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - register int y, cb, cr; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->output_width; - /* copy these pointers into registers if possible */ - register JSAMPLE * range_limit = cinfo->sample_range_limit; - register int * Crrtab = cconvert->Cr_r_tab; - register int * Cbbtab = cconvert->Cb_b_tab; - register INT32 * Crgtab = cconvert->Cr_g_tab; - register INT32 * Cbgtab = cconvert->Cb_g_tab; - SHIFT_TEMPS - - while (--num_rows >= 0) { - inptr0 = input_buf[0][input_row]; - inptr1 = input_buf[1][input_row]; - inptr2 = input_buf[2][input_row]; - input_row++; - outptr = *output_buf++; - for (col = 0; col < num_cols; col++) { - y = GETJSAMPLE(inptr0[col]); - cb = GETJSAMPLE(inptr1[col]); - cr = GETJSAMPLE(inptr2[col]); - /* Range-limiting is essential due to noise introduced by DCT losses. */ - outptr[rgb_red[cinfo->out_color_space]] = range_limit[y + Crrtab[cr]]; - outptr[rgb_green[cinfo->out_color_space]] = range_limit[y + - ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], - SCALEBITS))]; - outptr[rgb_blue[cinfo->out_color_space]] = range_limit[y + Cbbtab[cb]]; - outptr += rgb_pixelsize[cinfo->out_color_space]; - } + switch (cinfo->out_color_space) { + case JCS_EXT_RGB: + ycc_extrgb_convert_internal(cinfo, input_buf, input_row, output_buf, + num_rows); + break; + case JCS_EXT_RGBX: + case JCS_EXT_RGBA: + ycc_extrgbx_convert_internal(cinfo, input_buf, input_row, output_buf, + num_rows); + break; + case JCS_EXT_BGR: + ycc_extbgr_convert_internal(cinfo, input_buf, input_row, output_buf, + num_rows); + break; + case JCS_EXT_BGRX: + case JCS_EXT_BGRA: + ycc_extbgrx_convert_internal(cinfo, input_buf, input_row, output_buf, + num_rows); + break; + case JCS_EXT_XBGR: + case JCS_EXT_ABGR: + ycc_extxbgr_convert_internal(cinfo, input_buf, input_row, output_buf, + num_rows); + break; + case JCS_EXT_XRGB: + case JCS_EXT_ARGB: + ycc_extxrgb_convert_internal(cinfo, input_buf, input_row, output_buf, + num_rows); + break; + default: + ycc_rgb_convert_internal(cinfo, input_buf, input_row, output_buf, + num_rows); + break; } } @@ -211,9 +307,7 @@ grayscale_convert (j_decompress_ptr cinfo, /* - * Convert grayscale to RGB: just duplicate the graylevel three times. - * This is provided to support applications that don't want to cope - * with grayscale as a separate case. + * Convert grayscale to RGB */ METHODDEF(void) @@ -221,22 +315,39 @@ gray_rgb_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { - register JSAMPROW inptr, outptr; - JSAMPLE *maxinptr; - JDIMENSION num_cols = cinfo->output_width; - int rindex = rgb_red[cinfo->out_color_space]; - int gindex = rgb_green[cinfo->out_color_space]; - int bindex = rgb_blue[cinfo->out_color_space]; - int rgbstride = rgb_pixelsize[cinfo->out_color_space]; - - while (--num_rows >= 0) { - inptr = input_buf[0][input_row++]; - maxinptr = &inptr[num_cols]; - outptr = *output_buf++; - for (; inptr < maxinptr; inptr++, outptr += rgbstride) { - /* We can dispense with GETJSAMPLE() here */ - outptr[rindex] = outptr[gindex] = outptr[bindex] = *inptr; - } + switch (cinfo->out_color_space) { + case JCS_EXT_RGB: + gray_extrgb_convert_internal(cinfo, input_buf, input_row, output_buf, + num_rows); + break; + case JCS_EXT_RGBX: + case JCS_EXT_RGBA: + gray_extrgbx_convert_internal(cinfo, input_buf, input_row, output_buf, + num_rows); + break; + case JCS_EXT_BGR: + gray_extbgr_convert_internal(cinfo, input_buf, input_row, output_buf, + num_rows); + break; + case JCS_EXT_BGRX: + case JCS_EXT_BGRA: + gray_extbgrx_convert_internal(cinfo, input_buf, input_row, output_buf, + num_rows); + break; + case JCS_EXT_XBGR: + case JCS_EXT_ABGR: + gray_extxbgr_convert_internal(cinfo, input_buf, input_row, output_buf, + num_rows); + break; + case JCS_EXT_XRGB: + case JCS_EXT_ARGB: + gray_extxrgb_convert_internal(cinfo, input_buf, input_row, output_buf, + num_rows); + break; + default: + gray_rgb_convert_internal(cinfo, input_buf, input_row, output_buf, + num_rows); + break; } } @@ -369,6 +480,10 @@ jinit_color_deconverter (j_decompress_ptr cinfo) case JCS_EXT_BGRX: case JCS_EXT_XBGR: case JCS_EXT_XRGB: + case JCS_EXT_RGBA: + case JCS_EXT_BGRA: + case JCS_EXT_ABGR: + case JCS_EXT_ARGB: cinfo->out_color_components = rgb_pixelsize[cinfo->out_color_space]; if (cinfo->jpeg_color_space == JCS_YCbCr) { if (jsimd_can_ycc_rgb()) diff --git a/media/libjpeg/jdhuff.c b/media/libjpeg/jdhuff.c index b5ba39f736a7..f822dba86045 100644 --- a/media/libjpeg/jdhuff.c +++ b/media/libjpeg/jdhuff.c @@ -2,6 +2,7 @@ * jdhuff.c * * Copyright (C) 1991-1997, Thomas G. Lane. + * Copyright (C) 2009-2011, D. R. Commander. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -18,6 +19,7 @@ #include "jinclude.h" #include "jpeglib.h" #include "jdhuff.h" /* Declarations shared with jdphuff.c */ +#include "jpegcomp.h" /* @@ -122,7 +124,7 @@ start_pass_huff_decoder (j_decompress_ptr cinfo) if (compptr->component_needed) { entropy->dc_needed[blkn] = TRUE; /* we don't need the ACs if producing a 1/8th-size image */ - entropy->ac_needed[blkn] = (compptr->DCT_scaled_size > 1); + entropy->ac_needed[blkn] = (compptr->_DCT_scaled_size > 1); } else { entropy->dc_needed[blkn] = entropy->ac_needed[blkn] = FALSE; } @@ -225,6 +227,7 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, dtbl->maxcode[l] = -1; /* -1 if no codes of this length */ } } + dtbl->valoffset[17] = 0; dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */ /* Compute lookahead tables to speed up decoding. @@ -234,7 +237,8 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, * with that code. */ - MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits)); + for (i = 0; i < (1 << HUFF_LOOKAHEAD); i++) + dtbl->lookup[i] = (HUFF_LOOKAHEAD + 1) << HUFF_LOOKAHEAD; p = 0; for (l = 1; l <= HUFF_LOOKAHEAD; l++) { @@ -243,8 +247,7 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, /* Generate left-justified code followed by all possible bit sequences */ lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l); for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) { - dtbl->look_nbits[lookbits] = l; - dtbl->look_sym[lookbits] = htbl->huffval[p]; + dtbl->lookup[lookbits] = (l << HUFF_LOOKAHEAD) | htbl->huffval[p]; lookbits++; } } @@ -389,6 +392,50 @@ jpeg_fill_bit_buffer (bitread_working_state * state, } +/* Macro version of the above, which performs much better but does not + handle markers. We have to hand off any blocks with markers to the + slower routines. */ + +#define GET_BYTE \ +{ \ + register int c0, c1; \ + c0 = GETJOCTET(*buffer++); \ + c1 = GETJOCTET(*buffer); \ + /* Pre-execute most common case */ \ + get_buffer = (get_buffer << 8) | c0; \ + bits_left += 8; \ + if (c0 == 0xFF) { \ + /* Pre-execute case of FF/00, which represents an FF data byte */ \ + buffer++; \ + if (c1 != 0) { \ + /* Oops, it's actually a marker indicating end of compressed data. */ \ + cinfo->unread_marker = c1; \ + /* Back out pre-execution and fill the buffer with zero bits */ \ + buffer -= 2; \ + get_buffer &= ~0xFF; \ + } \ + } \ +} + +#if __WORDSIZE == 64 || defined(_WIN64) + +/* Pre-fetch 48 bytes, because the holding register is 64-bit */ +#define FILL_BIT_BUFFER_FAST \ + if (bits_left < 16) { \ + GET_BYTE GET_BYTE GET_BYTE GET_BYTE GET_BYTE GET_BYTE \ + } + +#else + +/* Pre-fetch 16 bytes, because the holding register is 32-bit */ +#define FILL_BIT_BUFFER_FAST \ + if (bits_left < 16) { \ + GET_BYTE GET_BYTE \ + } + +#endif + + /* * Out-of-line code for Huffman code decoding. * See jdhuff.h for info about usage. @@ -438,9 +485,10 @@ jpeg_huff_decode (bitread_working_state * state, * On some machines, a shift and add will be faster than a table lookup. */ +#define AVOID_TABLES #ifdef AVOID_TABLES -#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) +#define HUFF_EXTEND(x,s) ((x) + ((((x) - (1<<((s)-1))) >> 31) & (((-1)<<(s)) + 1))) #else @@ -498,6 +546,187 @@ process_restart (j_decompress_ptr cinfo) } +LOCAL(boolean) +decode_mcu_slow (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + BITREAD_STATE_VARS; + int blkn; + savable_state state; + /* Outer loop handles each block in the MCU */ + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + JBLOCKROW block = MCU_data[blkn]; + d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn]; + d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn]; + register int s, k, r; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + HUFF_DECODE(s, br_state, dctbl, return FALSE, label1); + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + + if (entropy->dc_needed[blkn]) { + /* Convert DC difference to actual value, update last_dc_val */ + int ci = cinfo->MCU_membership[blkn]; + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */ + (*block)[0] = (JCOEF) s; + } + + if (entropy->ac_needed[blkn]) { + + /* Section F.2.2.2: decode the AC coefficients */ + /* Since zeroes are skipped, output area must be cleared beforehand */ + for (k = 1; k < DCTSIZE2; k++) { + HUFF_DECODE(s, br_state, actbl, return FALSE, label2); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Output coefficient in natural (dezigzagged) order. + * Note: the extra entries in jpeg_natural_order[] will save us + * if k >= DCTSIZE2, which could happen if the data is corrupted. + */ + (*block)[jpeg_natural_order[k]] = (JCOEF) s; + } else { + if (r != 15) + break; + k += 15; + } + } + + } else { + + /* Section F.2.2.2: decode the AC coefficients */ + /* In this path we just discard the values */ + for (k = 1; k < DCTSIZE2; k++) { + HUFF_DECODE(s, br_state, actbl, return FALSE, label3); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } else { + if (r != 15) + break; + k += 15; + } + } + } + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + return TRUE; +} + + +LOCAL(boolean) +decode_mcu_fast (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + BITREAD_STATE_VARS; + JOCTET *buffer; + int blkn; + savable_state state; + /* Outer loop handles each block in the MCU */ + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + buffer = (JOCTET *) br_state.next_input_byte; + ASSIGN_STATE(state, entropy->saved); + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + JBLOCKROW block = MCU_data[blkn]; + d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn]; + d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn]; + register int s, k, r, l; + + HUFF_DECODE_FAST(s, l, dctbl); + if (s) { + FILL_BIT_BUFFER_FAST + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + + if (entropy->dc_needed[blkn]) { + int ci = cinfo->MCU_membership[blkn]; + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + (*block)[0] = (JCOEF) s; + } + + if (entropy->ac_needed[blkn]) { + + for (k = 1; k < DCTSIZE2; k++) { + HUFF_DECODE_FAST(s, l, actbl); + r = s >> 4; + s &= 15; + + if (s) { + k += r; + FILL_BIT_BUFFER_FAST + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + (*block)[jpeg_natural_order[k]] = (JCOEF) s; + } else { + if (r != 15) break; + k += 15; + } + } + + } else { + + for (k = 1; k < DCTSIZE2; k++) { + HUFF_DECODE_FAST(s, l, actbl); + r = s >> 4; + s &= 15; + + if (s) { + k += r; + FILL_BIT_BUFFER_FAST + DROP_BITS(s); + } else { + if (r != 15) break; + k += 15; + } + } + } + } + + if (cinfo->unread_marker != 0) { + cinfo->unread_marker = 0; + return FALSE; + } + + br_state.bytes_in_buffer -= (buffer - br_state.next_input_byte); + br_state.next_input_byte = buffer; + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + return TRUE; +} + + /* * Decode and return one MCU's worth of Huffman-compressed coefficients. * The coefficients are reordered from zigzag order into natural array order, @@ -513,111 +742,39 @@ process_restart (j_decompress_ptr cinfo) * this module, since we'll just re-assign them on the next call.) */ +#define BUFSIZE (DCTSIZE2 * 2) + METHODDEF(boolean) decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int blkn; - BITREAD_STATE_VARS; - savable_state state; + int usefast = 1; /* Process restart marker if needed; may have to suspend */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! process_restart(cinfo)) return FALSE; + usefast = 0; } + if (cinfo->src->bytes_in_buffer < BUFSIZE * (size_t)cinfo->blocks_in_MCU + || cinfo->unread_marker != 0) + usefast = 0; + /* If we've run out of data, just leave the MCU set to zeroes. * This way, we return uniform gray for the remainder of the segment. */ if (! entropy->pub.insufficient_data) { - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(state, entropy->saved); - - /* Outer loop handles each block in the MCU */ - - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - JBLOCKROW block = MCU_data[blkn]; - d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn]; - d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn]; - register int s, k, r; - - /* Decode a single block's worth of coefficients */ - - /* Section F.2.2.1: decode the DC coefficient difference */ - HUFF_DECODE(s, br_state, dctbl, return FALSE, label1); - if (s) { - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - } - - if (entropy->dc_needed[blkn]) { - /* Convert DC difference to actual value, update last_dc_val */ - int ci = cinfo->MCU_membership[blkn]; - s += state.last_dc_val[ci]; - state.last_dc_val[ci] = s; - /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */ - (*block)[0] = (JCOEF) s; - } - - if (entropy->ac_needed[blkn]) { - - /* Section F.2.2.2: decode the AC coefficients */ - /* Since zeroes are skipped, output area must be cleared beforehand */ - for (k = 1; k < DCTSIZE2; k++) { - HUFF_DECODE(s, br_state, actbl, return FALSE, label2); - - r = s >> 4; - s &= 15; - - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - /* Output coefficient in natural (dezigzagged) order. - * Note: the extra entries in jpeg_natural_order[] will save us - * if k >= DCTSIZE2, which could happen if the data is corrupted. - */ - (*block)[jpeg_natural_order[k]] = (JCOEF) s; - } else { - if (r != 15) - break; - k += 15; - } - } - - } else { - - /* Section F.2.2.2: decode the AC coefficients */ - /* In this path we just discard the values */ - for (k = 1; k < DCTSIZE2; k++) { - HUFF_DECODE(s, br_state, actbl, return FALSE, label3); - - r = s >> 4; - s &= 15; - - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - DROP_BITS(s); - } else { - if (r != 15) - break; - k += 15; - } - } - - } + if (usefast) { + if (!decode_mcu_fast(cinfo, MCU_data)) goto use_slow; + } + else { + use_slow: + if (!decode_mcu_slow(cinfo, MCU_data)) return FALSE; } - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(entropy->saved, state); } /* Account for restart interval (no-op if not using restarts) */ diff --git a/media/libjpeg/jdhuff.h b/media/libjpeg/jdhuff.h index ae19b6cafd7e..96f2dabf11c6 100644 --- a/media/libjpeg/jdhuff.h +++ b/media/libjpeg/jdhuff.h @@ -2,6 +2,7 @@ * jdhuff.h * * Copyright (C) 1991-1997, Thomas G. Lane. + * Copyright (C) 2010-2011, D. R. Commander. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -27,7 +28,7 @@ typedef struct { /* Basic tables: (element [0] of each array is unused) */ INT32 maxcode[18]; /* largest code of length k (-1 if none) */ /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */ - INT32 valoffset[17]; /* huffval[] offset for codes of length k */ + INT32 valoffset[18]; /* huffval[] offset for codes of length k */ /* valoffset[k] = huffval[] index of 1st symbol of code length k, less * the smallest code of length k; so given a code of length k, the * corresponding symbol is huffval[code + valoffset[k]] @@ -36,13 +37,17 @@ typedef struct { /* Link to public Huffman table (needed only in jpeg_huff_decode) */ JHUFF_TBL *pub; - /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of + /* Lookahead table: indexed by the next HUFF_LOOKAHEAD bits of * the input data stream. If the next Huffman code is no more * than HUFF_LOOKAHEAD bits long, we can obtain its length and - * the corresponding symbol directly from these tables. + * the corresponding symbol directly from this tables. + * + * The lower 8 bits of each table entry contain the number of + * bits in the corresponding Huffman code, or HUFF_LOOKAHEAD + 1 + * if too long. The next 8 bits of each entry contain the + * symbol. */ - int look_nbits[1< 32 bits on your machine, and shifting/masking longs is * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE @@ -183,11 +197,10 @@ EXTERN(boolean) jpeg_fill_bit_buffer } \ } \ look = PEEK_BITS(HUFF_LOOKAHEAD); \ - if ((nb = htbl->look_nbits[look]) != 0) { \ + if ((nb = (htbl->lookup[look] >> HUFF_LOOKAHEAD)) <= HUFF_LOOKAHEAD) { \ DROP_BITS(nb); \ - result = htbl->look_sym[look]; \ + result = htbl->lookup[look] & ((1 << HUFF_LOOKAHEAD) - 1); \ } else { \ - nb = HUFF_LOOKAHEAD+1; \ slowlabel: \ if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ { failaction; } \ @@ -195,6 +208,26 @@ slowlabel: \ } \ } +#define HUFF_DECODE_FAST(s,nb,htbl) \ + FILL_BIT_BUFFER_FAST; \ + s = PEEK_BITS(HUFF_LOOKAHEAD); \ + s = htbl->lookup[s]; \ + nb = s >> HUFF_LOOKAHEAD; \ + /* Pre-execute the common case of nb <= HUFF_LOOKAHEAD */ \ + DROP_BITS(nb); \ + s = s & ((1 << HUFF_LOOKAHEAD) - 1); \ + if (nb > HUFF_LOOKAHEAD) { \ + /* Equivalent of jpeg_huff_decode() */ \ + /* Don't use GET_BITS() here because we don't want to modify bits_left */ \ + s = (get_buffer >> bits_left) & ((1 << (nb)) - 1); \ + while (s > htbl->maxcode[nb]) { \ + s <<= 1; \ + s |= GET_BITS(1); \ + nb++; \ + } \ + s = htbl->pub->huffval[ (int) (s + htbl->valoffset[nb]) & 0xFF ]; \ + } + /* Out-of-line case for Huffman code fetching */ EXTERN(int) jpeg_huff_decode JPP((bitread_working_state * state, register bit_buf_type get_buffer, diff --git a/media/libjpeg/jdmainct.c b/media/libjpeg/jdmainct.c index 67f62153e672..eb32cae0941e 100644 --- a/media/libjpeg/jdmainct.c +++ b/media/libjpeg/jdmainct.c @@ -161,7 +161,7 @@ alloc_funny_pointers (j_decompress_ptr cinfo) * This is done only once, not once per pass. */ { - my_main_ptr main = (my_main_ptr) cinfo->main; + my_main_ptr main_ptr = (my_main_ptr) cinfo->main; int ci, rgroup; int M = cinfo->_min_DCT_scaled_size; jpeg_component_info *compptr; @@ -170,10 +170,10 @@ alloc_funny_pointers (j_decompress_ptr cinfo) /* Get top-level space for component array pointers. * We alloc both arrays with one call to save a few cycles. */ - main->xbuffer[0] = (JSAMPIMAGE) + main_ptr->xbuffer[0] = (JSAMPIMAGE) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->num_components * 2 * SIZEOF(JSAMPARRAY)); - main->xbuffer[1] = main->xbuffer[0] + cinfo->num_components; + main_ptr->xbuffer[1] = main_ptr->xbuffer[0] + cinfo->num_components; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { @@ -186,9 +186,9 @@ alloc_funny_pointers (j_decompress_ptr cinfo) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW)); xbuf += rgroup; /* want one row group at negative offsets */ - main->xbuffer[0][ci] = xbuf; + main_ptr->xbuffer[0][ci] = xbuf; xbuf += rgroup * (M + 4); - main->xbuffer[1][ci] = xbuf; + main_ptr->xbuffer[1][ci] = xbuf; } } @@ -196,13 +196,13 @@ alloc_funny_pointers (j_decompress_ptr cinfo) LOCAL(void) make_funny_pointers (j_decompress_ptr cinfo) /* Create the funny pointer lists discussed in the comments above. - * The actual workspace is already allocated (in main->buffer), + * The actual workspace is already allocated (in main_ptr->buffer), * and the space for the pointer lists is allocated too. * This routine just fills in the curiously ordered lists. * This will be repeated at the beginning of each pass. */ { - my_main_ptr main = (my_main_ptr) cinfo->main; + my_main_ptr main_ptr = (my_main_ptr) cinfo->main; int ci, i, rgroup; int M = cinfo->_min_DCT_scaled_size; jpeg_component_info *compptr; @@ -212,10 +212,10 @@ make_funny_pointers (j_decompress_ptr cinfo) ci++, compptr++) { rgroup = (compptr->v_samp_factor * compptr->_DCT_scaled_size) / cinfo->_min_DCT_scaled_size; /* height of a row group of component */ - xbuf0 = main->xbuffer[0][ci]; - xbuf1 = main->xbuffer[1][ci]; + xbuf0 = main_ptr->xbuffer[0][ci]; + xbuf1 = main_ptr->xbuffer[1][ci]; /* First copy the workspace pointers as-is */ - buf = main->buffer[ci]; + buf = main_ptr->buffer[ci]; for (i = 0; i < rgroup * (M + 2); i++) { xbuf0[i] = xbuf1[i] = buf[i]; } @@ -242,7 +242,7 @@ set_wraparound_pointers (j_decompress_ptr cinfo) * This changes the pointer list state from top-of-image to the normal state. */ { - my_main_ptr main = (my_main_ptr) cinfo->main; + my_main_ptr main_ptr = (my_main_ptr) cinfo->main; int ci, i, rgroup; int M = cinfo->_min_DCT_scaled_size; jpeg_component_info *compptr; @@ -252,8 +252,8 @@ set_wraparound_pointers (j_decompress_ptr cinfo) ci++, compptr++) { rgroup = (compptr->v_samp_factor * compptr->_DCT_scaled_size) / cinfo->_min_DCT_scaled_size; /* height of a row group of component */ - xbuf0 = main->xbuffer[0][ci]; - xbuf1 = main->xbuffer[1][ci]; + xbuf0 = main_ptr->xbuffer[0][ci]; + xbuf1 = main_ptr->xbuffer[1][ci]; for (i = 0; i < rgroup; i++) { xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i]; xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i]; @@ -271,7 +271,7 @@ set_bottom_pointers (j_decompress_ptr cinfo) * Also sets rowgroups_avail to indicate number of nondummy row groups in row. */ { - my_main_ptr main = (my_main_ptr) cinfo->main; + my_main_ptr main_ptr = (my_main_ptr) cinfo->main; int ci, i, rgroup, iMCUheight, rows_left; jpeg_component_info *compptr; JSAMPARRAY xbuf; @@ -288,12 +288,12 @@ set_bottom_pointers (j_decompress_ptr cinfo) * so we need only do it once. */ if (ci == 0) { - main->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1); + main_ptr->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1); } /* Duplicate the last real sample row rgroup*2 times; this pads out the * last partial rowgroup and ensures at least one full rowgroup of context. */ - xbuf = main->xbuffer[main->whichptr][ci]; + xbuf = main_ptr->xbuffer[main_ptr->whichptr][ci]; for (i = 0; i < rgroup * 2; i++) { xbuf[rows_left + i] = xbuf[rows_left-1]; } @@ -308,27 +308,27 @@ set_bottom_pointers (j_decompress_ptr cinfo) METHODDEF(void) start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) { - my_main_ptr main = (my_main_ptr) cinfo->main; + my_main_ptr main_ptr = (my_main_ptr) cinfo->main; switch (pass_mode) { case JBUF_PASS_THRU: if (cinfo->upsample->need_context_rows) { - main->pub.process_data = process_data_context_main; + main_ptr->pub.process_data = process_data_context_main; make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ - main->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ - main->context_state = CTX_PREPARE_FOR_IMCU; - main->iMCU_row_ctr = 0; + main_ptr->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ + main_ptr->context_state = CTX_PREPARE_FOR_IMCU; + main_ptr->iMCU_row_ctr = 0; } else { /* Simple case with no context needed */ - main->pub.process_data = process_data_simple_main; + main_ptr->pub.process_data = process_data_simple_main; } - main->buffer_full = FALSE; /* Mark buffer empty */ - main->rowgroup_ctr = 0; + main_ptr->buffer_full = FALSE; /* Mark buffer empty */ + main_ptr->rowgroup_ctr = 0; break; #ifdef QUANT_2PASS_SUPPORTED case JBUF_CRANK_DEST: /* For last pass of 2-pass quantization, just crank the postprocessor */ - main->pub.process_data = process_data_crank_post; + main_ptr->pub.process_data = process_data_crank_post; break; #endif default: @@ -348,14 +348,14 @@ process_data_simple_main (j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { - my_main_ptr main = (my_main_ptr) cinfo->main; + my_main_ptr main_ptr = (my_main_ptr) cinfo->main; JDIMENSION rowgroups_avail; /* Read input data if we haven't filled the main buffer yet */ - if (! main->buffer_full) { - if (! (*cinfo->coef->decompress_data) (cinfo, main->buffer)) + if (! main_ptr->buffer_full) { + if (! (*cinfo->coef->decompress_data) (cinfo, main_ptr->buffer)) return; /* suspension forced, can do nothing more */ - main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + main_ptr->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ } /* There are always min_DCT_scaled_size row groups in an iMCU row. */ @@ -366,14 +366,14 @@ process_data_simple_main (j_decompress_ptr cinfo, */ /* Feed the postprocessor */ - (*cinfo->post->post_process_data) (cinfo, main->buffer, - &main->rowgroup_ctr, rowgroups_avail, + (*cinfo->post->post_process_data) (cinfo, main_ptr->buffer, + &main_ptr->rowgroup_ctr, rowgroups_avail, output_buf, out_row_ctr, out_rows_avail); /* Has postprocessor consumed all the data yet? If so, mark buffer empty */ - if (main->rowgroup_ctr >= rowgroups_avail) { - main->buffer_full = FALSE; - main->rowgroup_ctr = 0; + if (main_ptr->rowgroup_ctr >= rowgroups_avail) { + main_ptr->buffer_full = FALSE; + main_ptr->rowgroup_ctr = 0; } } @@ -388,15 +388,15 @@ process_data_context_main (j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { - my_main_ptr main = (my_main_ptr) cinfo->main; + my_main_ptr main_ptr = (my_main_ptr) cinfo->main; /* Read input data if we haven't filled the main buffer yet */ - if (! main->buffer_full) { + if (! main_ptr->buffer_full) { if (! (*cinfo->coef->decompress_data) (cinfo, - main->xbuffer[main->whichptr])) + main_ptr->xbuffer[main_ptr->whichptr])) return; /* suspension forced, can do nothing more */ - main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ - main->iMCU_row_ctr++; /* count rows received */ + main_ptr->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + main_ptr->iMCU_row_ctr++; /* count rows received */ } /* Postprocessor typically will not swallow all the input data it is handed @@ -404,47 +404,47 @@ process_data_context_main (j_decompress_ptr cinfo, * to exit and restart. This switch lets us keep track of how far we got. * Note that each case falls through to the next on successful completion. */ - switch (main->context_state) { + switch (main_ptr->context_state) { case CTX_POSTPONED_ROW: /* Call postprocessor using previously set pointers for postponed row */ - (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr], - &main->rowgroup_ctr, main->rowgroups_avail, + (*cinfo->post->post_process_data) (cinfo, main_ptr->xbuffer[main_ptr->whichptr], + &main_ptr->rowgroup_ctr, main_ptr->rowgroups_avail, output_buf, out_row_ctr, out_rows_avail); - if (main->rowgroup_ctr < main->rowgroups_avail) + if (main_ptr->rowgroup_ctr < main_ptr->rowgroups_avail) return; /* Need to suspend */ - main->context_state = CTX_PREPARE_FOR_IMCU; + main_ptr->context_state = CTX_PREPARE_FOR_IMCU; if (*out_row_ctr >= out_rows_avail) return; /* Postprocessor exactly filled output buf */ /*FALLTHROUGH*/ case CTX_PREPARE_FOR_IMCU: /* Prepare to process first M-1 row groups of this iMCU row */ - main->rowgroup_ctr = 0; - main->rowgroups_avail = (JDIMENSION) (cinfo->_min_DCT_scaled_size - 1); + main_ptr->rowgroup_ctr = 0; + main_ptr->rowgroups_avail = (JDIMENSION) (cinfo->_min_DCT_scaled_size - 1); /* Check for bottom of image: if so, tweak pointers to "duplicate" * the last sample row, and adjust rowgroups_avail to ignore padding rows. */ - if (main->iMCU_row_ctr == cinfo->total_iMCU_rows) + if (main_ptr->iMCU_row_ctr == cinfo->total_iMCU_rows) set_bottom_pointers(cinfo); - main->context_state = CTX_PROCESS_IMCU; + main_ptr->context_state = CTX_PROCESS_IMCU; /*FALLTHROUGH*/ case CTX_PROCESS_IMCU: /* Call postprocessor using previously set pointers */ - (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr], - &main->rowgroup_ctr, main->rowgroups_avail, + (*cinfo->post->post_process_data) (cinfo, main_ptr->xbuffer[main_ptr->whichptr], + &main_ptr->rowgroup_ctr, main_ptr->rowgroups_avail, output_buf, out_row_ctr, out_rows_avail); - if (main->rowgroup_ctr < main->rowgroups_avail) + if (main_ptr->rowgroup_ctr < main_ptr->rowgroups_avail) return; /* Need to suspend */ /* After the first iMCU, change wraparound pointers to normal state */ - if (main->iMCU_row_ctr == 1) + if (main_ptr->iMCU_row_ctr == 1) set_wraparound_pointers(cinfo); /* Prepare to load new iMCU row using other xbuffer list */ - main->whichptr ^= 1; /* 0=>1 or 1=>0 */ - main->buffer_full = FALSE; + main_ptr->whichptr ^= 1; /* 0=>1 or 1=>0 */ + main_ptr->buffer_full = FALSE; /* Still need to process last row group of this iMCU row, */ /* which is saved at index M+1 of the other xbuffer */ - main->rowgroup_ctr = (JDIMENSION) (cinfo->_min_DCT_scaled_size + 1); - main->rowgroups_avail = (JDIMENSION) (cinfo->_min_DCT_scaled_size + 2); - main->context_state = CTX_POSTPONED_ROW; + main_ptr->rowgroup_ctr = (JDIMENSION) (cinfo->_min_DCT_scaled_size + 1); + main_ptr->rowgroups_avail = (JDIMENSION) (cinfo->_min_DCT_scaled_size + 2); + main_ptr->context_state = CTX_POSTPONED_ROW; } } @@ -477,15 +477,15 @@ process_data_crank_post (j_decompress_ptr cinfo, GLOBAL(void) jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) { - my_main_ptr main; + my_main_ptr main_ptr; int ci, rgroup, ngroups; jpeg_component_info *compptr; - main = (my_main_ptr) + main_ptr = (my_main_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_main_controller)); - cinfo->main = (struct jpeg_d_main_controller *) main; - main->pub.start_pass = start_pass_main; + cinfo->main = (struct jpeg_d_main_controller *) main_ptr; + main_ptr->pub.start_pass = start_pass_main; if (need_full_buffer) /* shouldn't happen */ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); @@ -506,7 +506,7 @@ jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) ci++, compptr++) { rgroup = (compptr->v_samp_factor * compptr->_DCT_scaled_size) / cinfo->_min_DCT_scaled_size; /* height of a row group of component */ - main->buffer[ci] = (*cinfo->mem->alloc_sarray) + main_ptr->buffer[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, compptr->width_in_blocks * compptr->_DCT_scaled_size, (JDIMENSION) (rgroup * ngroups)); diff --git a/media/libjpeg/jdmarker.c b/media/libjpeg/jdmarker.c index f4cca8cc835c..d8dcba98fa06 100644 --- a/media/libjpeg/jdmarker.c +++ b/media/libjpeg/jdmarker.c @@ -2,6 +2,7 @@ * jdmarker.c * * Copyright (C) 1991-1998, Thomas G. Lane. + * Copyright (C) 2012, D. R. Commander. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -322,13 +323,16 @@ get_sos (j_decompress_ptr cinfo) /* Collect the component-spec parameters */ + for (i = 0; i < cinfo->num_components; i++) + cinfo->cur_comp_info[i] = NULL; + for (i = 0; i < n; i++) { INPUT_BYTE(cinfo, cc, return FALSE); INPUT_BYTE(cinfo, c, return FALSE); for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - if (cc == compptr->component_id) + if (cc == compptr->component_id && !cinfo->cur_comp_info[ci]) goto id_found; } diff --git a/media/libjpeg/jdmaster.c b/media/libjpeg/jdmaster.c index 14520da884c7..c73ec0271789 100644 --- a/media/libjpeg/jdmaster.c +++ b/media/libjpeg/jdmaster.c @@ -2,7 +2,7 @@ * jdmaster.c * * Copyright (C) 1991-1997, Thomas G. Lane. - * Copyright (C) 2009-2010, D. R. Commander. + * Copyright (C) 2009-2011, D. R. Commander. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -57,7 +57,11 @@ use_merged_upsample (j_decompress_ptr cinfo) cinfo->out_color_space != JCS_EXT_BGR && cinfo->out_color_space != JCS_EXT_BGRX && cinfo->out_color_space != JCS_EXT_XBGR && - cinfo->out_color_space != JCS_EXT_XRGB) || + cinfo->out_color_space != JCS_EXT_XRGB && + cinfo->out_color_space != JCS_EXT_RGBA && + cinfo->out_color_space != JCS_EXT_BGRA && + cinfo->out_color_space != JCS_EXT_ABGR && + cinfo->out_color_space != JCS_EXT_ARGB) || cinfo->out_color_components != rgb_pixelsize[cinfo->out_color_space]) return FALSE; /* and it only handles 2h1v or 2h2v sampling ratios */ @@ -209,6 +213,10 @@ jpeg_calc_output_dimensions (j_decompress_ptr cinfo) case JCS_EXT_BGRX: case JCS_EXT_XBGR: case JCS_EXT_XRGB: + case JCS_EXT_RGBA: + case JCS_EXT_BGRA: + case JCS_EXT_ABGR: + case JCS_EXT_ARGB: cinfo->out_color_components = rgb_pixelsize[cinfo->out_color_space]; break; case JCS_YCbCr: diff --git a/media/libjpeg/jdmerge.c b/media/libjpeg/jdmerge.c index edf061a737b1..cfa3bb921d38 100644 --- a/media/libjpeg/jdmerge.c +++ b/media/libjpeg/jdmerge.c @@ -3,7 +3,7 @@ * * Copyright (C) 1994-1996, Thomas G. Lane. * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2009, D. R. Commander. + * Copyright (C) 2009, 2011, D. R. Commander. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -38,6 +38,7 @@ #include "jinclude.h" #include "jpeglib.h" #include "jsimd.h" +#include "config.h" #ifdef UPSAMPLE_MERGING_SUPPORTED @@ -77,6 +78,99 @@ typedef my_upsampler * my_upsample_ptr; #define FIX(x) ((INT32) ((x) * (1L<RGB colorspace conversion. * This is taken directly from jdcolor.c; see that file for more info. @@ -230,55 +324,39 @@ h2v1_merged_upsample (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) { - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - register int y, cred, cgreen, cblue; - int cb, cr; - register JSAMPROW outptr; - JSAMPROW inptr0, inptr1, inptr2; - JDIMENSION col; - /* copy these pointers into registers if possible */ - register JSAMPLE * range_limit = cinfo->sample_range_limit; - int * Crrtab = upsample->Cr_r_tab; - int * Cbbtab = upsample->Cb_b_tab; - INT32 * Crgtab = upsample->Cr_g_tab; - INT32 * Cbgtab = upsample->Cb_g_tab; - SHIFT_TEMPS - - inptr0 = input_buf[0][in_row_group_ctr]; - inptr1 = input_buf[1][in_row_group_ctr]; - inptr2 = input_buf[2][in_row_group_ctr]; - outptr = output_buf[0]; - /* Loop for each pair of output pixels */ - for (col = cinfo->output_width >> 1; col > 0; col--) { - /* Do the chroma part of the calculation */ - cb = GETJSAMPLE(*inptr1++); - cr = GETJSAMPLE(*inptr2++); - cred = Crrtab[cr]; - cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; - /* Fetch 2 Y values and emit 2 pixels */ - y = GETJSAMPLE(*inptr0++); - outptr[rgb_red[cinfo->out_color_space]] = range_limit[y + cred]; - outptr[rgb_green[cinfo->out_color_space]] = range_limit[y + cgreen]; - outptr[rgb_blue[cinfo->out_color_space]] = range_limit[y + cblue]; - outptr += rgb_pixelsize[cinfo->out_color_space]; - y = GETJSAMPLE(*inptr0++); - outptr[rgb_red[cinfo->out_color_space]] = range_limit[y + cred]; - outptr[rgb_green[cinfo->out_color_space]] = range_limit[y + cgreen]; - outptr[rgb_blue[cinfo->out_color_space]] = range_limit[y + cblue]; - outptr += rgb_pixelsize[cinfo->out_color_space]; - } - /* If image width is odd, do the last output column separately */ - if (cinfo->output_width & 1) { - cb = GETJSAMPLE(*inptr1); - cr = GETJSAMPLE(*inptr2); - cred = Crrtab[cr]; - cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; - y = GETJSAMPLE(*inptr0); - outptr[rgb_red[cinfo->out_color_space]] = range_limit[y + cred]; - outptr[rgb_green[cinfo->out_color_space]] = range_limit[y + cgreen]; - outptr[rgb_blue[cinfo->out_color_space]] = range_limit[y + cblue]; + switch (cinfo->out_color_space) { + case JCS_EXT_RGB: + extrgb_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, + output_buf); + break; + case JCS_EXT_RGBX: + case JCS_EXT_RGBA: + extrgbx_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, + output_buf); + break; + case JCS_EXT_BGR: + extbgr_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, + output_buf); + break; + case JCS_EXT_BGRX: + case JCS_EXT_BGRA: + extbgrx_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, + output_buf); + break; + case JCS_EXT_XBGR: + case JCS_EXT_ABGR: + extxbgr_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, + output_buf); + break; + case JCS_EXT_XRGB: + case JCS_EXT_ARGB: + extxrgb_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, + output_buf); + break; + default: + h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, + output_buf); + break; } } @@ -292,71 +370,39 @@ h2v2_merged_upsample (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) { - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - register int y, cred, cgreen, cblue; - int cb, cr; - register JSAMPROW outptr0, outptr1; - JSAMPROW inptr00, inptr01, inptr1, inptr2; - JDIMENSION col; - /* copy these pointers into registers if possible */ - register JSAMPLE * range_limit = cinfo->sample_range_limit; - int * Crrtab = upsample->Cr_r_tab; - int * Cbbtab = upsample->Cb_b_tab; - INT32 * Crgtab = upsample->Cr_g_tab; - INT32 * Cbgtab = upsample->Cb_g_tab; - SHIFT_TEMPS - - inptr00 = input_buf[0][in_row_group_ctr*2]; - inptr01 = input_buf[0][in_row_group_ctr*2 + 1]; - inptr1 = input_buf[1][in_row_group_ctr]; - inptr2 = input_buf[2][in_row_group_ctr]; - outptr0 = output_buf[0]; - outptr1 = output_buf[1]; - /* Loop for each group of output pixels */ - for (col = cinfo->output_width >> 1; col > 0; col--) { - /* Do the chroma part of the calculation */ - cb = GETJSAMPLE(*inptr1++); - cr = GETJSAMPLE(*inptr2++); - cred = Crrtab[cr]; - cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; - /* Fetch 4 Y values and emit 4 pixels */ - y = GETJSAMPLE(*inptr00++); - outptr0[rgb_red[cinfo->out_color_space]] = range_limit[y + cred]; - outptr0[rgb_green[cinfo->out_color_space]] = range_limit[y + cgreen]; - outptr0[rgb_blue[cinfo->out_color_space]] = range_limit[y + cblue]; - outptr0 += RGB_PIXELSIZE; - y = GETJSAMPLE(*inptr00++); - outptr0[rgb_red[cinfo->out_color_space]] = range_limit[y + cred]; - outptr0[rgb_green[cinfo->out_color_space]] = range_limit[y + cgreen]; - outptr0[rgb_blue[cinfo->out_color_space]] = range_limit[y + cblue]; - outptr0 += RGB_PIXELSIZE; - y = GETJSAMPLE(*inptr01++); - outptr1[rgb_red[cinfo->out_color_space]] = range_limit[y + cred]; - outptr1[rgb_green[cinfo->out_color_space]] = range_limit[y + cgreen]; - outptr1[rgb_blue[cinfo->out_color_space]] = range_limit[y + cblue]; - outptr1 += RGB_PIXELSIZE; - y = GETJSAMPLE(*inptr01++); - outptr1[rgb_red[cinfo->out_color_space]] = range_limit[y + cred]; - outptr1[rgb_green[cinfo->out_color_space]] = range_limit[y + cgreen]; - outptr1[rgb_blue[cinfo->out_color_space]] = range_limit[y + cblue]; - outptr1 += RGB_PIXELSIZE; - } - /* If image width is odd, do the last output column separately */ - if (cinfo->output_width & 1) { - cb = GETJSAMPLE(*inptr1); - cr = GETJSAMPLE(*inptr2); - cred = Crrtab[cr]; - cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; - y = GETJSAMPLE(*inptr00); - outptr0[rgb_red[cinfo->out_color_space]] = range_limit[y + cred]; - outptr0[rgb_green[cinfo->out_color_space]] = range_limit[y + cgreen]; - outptr0[rgb_blue[cinfo->out_color_space]] = range_limit[y + cblue]; - y = GETJSAMPLE(*inptr01); - outptr1[rgb_red[cinfo->out_color_space]] = range_limit[y + cred]; - outptr1[rgb_green[cinfo->out_color_space]] = range_limit[y + cgreen]; - outptr1[rgb_blue[cinfo->out_color_space]] = range_limit[y + cblue]; + switch (cinfo->out_color_space) { + case JCS_EXT_RGB: + extrgb_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, + output_buf); + break; + case JCS_EXT_RGBX: + case JCS_EXT_RGBA: + extrgbx_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, + output_buf); + break; + case JCS_EXT_BGR: + extbgr_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, + output_buf); + break; + case JCS_EXT_BGRX: + case JCS_EXT_BGRA: + extbgrx_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, + output_buf); + break; + case JCS_EXT_XBGR: + case JCS_EXT_ABGR: + extxbgr_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, + output_buf); + break; + case JCS_EXT_XRGB: + case JCS_EXT_ARGB: + extxrgb_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, + output_buf); + break; + default: + h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, + output_buf); + break; } } diff --git a/media/libjpeg/jdmrgext.c b/media/libjpeg/jdmrgext.c new file mode 100644 index 000000000000..95ddd556230f --- /dev/null +++ b/media/libjpeg/jdmrgext.c @@ -0,0 +1,156 @@ +/* + * jdmrgext.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains code for merged upsampling/color conversion. + */ + + +/* This file is included by jdmerge.c */ + + +/* + * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. + */ + +INLINE +LOCAL(void) +h2v1_merged_upsample_internal (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + register int y, cred, cgreen, cblue; + int cb, cr; + register JSAMPROW outptr; + JSAMPROW inptr0, inptr1, inptr2; + JDIMENSION col; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + int * Crrtab = upsample->Cr_r_tab; + int * Cbbtab = upsample->Cb_b_tab; + INT32 * Crgtab = upsample->Cr_g_tab; + INT32 * Cbgtab = upsample->Cb_g_tab; + SHIFT_TEMPS + + inptr0 = input_buf[0][in_row_group_ctr]; + inptr1 = input_buf[1][in_row_group_ctr]; + inptr2 = input_buf[2][in_row_group_ctr]; + outptr = output_buf[0]; + /* Loop for each pair of output pixels */ + for (col = cinfo->output_width >> 1; col > 0; col--) { + /* Do the chroma part of the calculation */ + cb = GETJSAMPLE(*inptr1++); + cr = GETJSAMPLE(*inptr2++); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + /* Fetch 2 Y values and emit 2 pixels */ + y = GETJSAMPLE(*inptr0++); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr0++); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr += RGB_PIXELSIZE; + } + /* If image width is odd, do the last output column separately */ + if (cinfo->output_width & 1) { + cb = GETJSAMPLE(*inptr1); + cr = GETJSAMPLE(*inptr2); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + y = GETJSAMPLE(*inptr0); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + } +} + + +/* + * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical. + */ + +INLINE +LOCAL(void) +h2v2_merged_upsample_internal (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + register int y, cred, cgreen, cblue; + int cb, cr; + register JSAMPROW outptr0, outptr1; + JSAMPROW inptr00, inptr01, inptr1, inptr2; + JDIMENSION col; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + int * Crrtab = upsample->Cr_r_tab; + int * Cbbtab = upsample->Cb_b_tab; + INT32 * Crgtab = upsample->Cr_g_tab; + INT32 * Cbgtab = upsample->Cb_g_tab; + SHIFT_TEMPS + + inptr00 = input_buf[0][in_row_group_ctr*2]; + inptr01 = input_buf[0][in_row_group_ctr*2 + 1]; + inptr1 = input_buf[1][in_row_group_ctr]; + inptr2 = input_buf[2][in_row_group_ctr]; + outptr0 = output_buf[0]; + outptr1 = output_buf[1]; + /* Loop for each group of output pixels */ + for (col = cinfo->output_width >> 1; col > 0; col--) { + /* Do the chroma part of the calculation */ + cb = GETJSAMPLE(*inptr1++); + cr = GETJSAMPLE(*inptr2++); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + /* Fetch 4 Y values and emit 4 pixels */ + y = GETJSAMPLE(*inptr00++); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr00++); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr01++); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr01++); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1 += RGB_PIXELSIZE; + } + /* If image width is odd, do the last output column separately */ + if (cinfo->output_width & 1) { + cb = GETJSAMPLE(*inptr1); + cr = GETJSAMPLE(*inptr2); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + y = GETJSAMPLE(*inptr00); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + y = GETJSAMPLE(*inptr01); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + } +} diff --git a/media/libjpeg/jdtrans.c b/media/libjpeg/jdtrans.c index 9d9c1b1d5e0d..f0cd0aef95f8 100644 --- a/media/libjpeg/jdtrans.c +++ b/media/libjpeg/jdtrans.c @@ -99,6 +99,11 @@ transdecode_master_selection (j_decompress_ptr cinfo) /* This is effectively a buffered-image operation. */ cinfo->buffered_image = TRUE; +#if JPEG_LIB_VERSION >= 80 + /* Compute output image dimensions and related values. */ + jpeg_core_output_dimensions(cinfo); +#endif + /* Entropy decoding: either Huffman or arithmetic coding. */ if (cinfo->arith_code) { #ifdef D_ARITH_CODING_SUPPORTED diff --git a/media/libjpeg/jerror.h b/media/libjpeg/jerror.h index 88f019e8f945..275086e675e9 100644 --- a/media/libjpeg/jerror.h +++ b/media/libjpeg/jerror.h @@ -40,15 +40,23 @@ typedef enum { JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ /* For maintenance convenience, list is alphabetical by message code name */ +#if JPEG_LIB_VERSION < 70 JMESSAGE(JERR_ARITH_NOTIMPL, "Sorry, arithmetic coding is not implemented") +#endif JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") +#if JPEG_LIB_VERSION >= 70 JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") +#endif JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") +#if JPEG_LIB_VERSION >= 70 +JMESSAGE(JERR_BAD_DROP_SAMPLING, + "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") +#endif JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") @@ -95,7 +103,9 @@ JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") JMESSAGE(JERR_NOTIMPL, "Not implemented yet") JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +#if JPEG_LIB_VERSION >= 70 JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") +#endif JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") @@ -173,7 +183,9 @@ JMESSAGE(JTRC_UNKNOWN_IDS, JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +#if JPEG_LIB_VERSION >= 70 JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") +#endif JMESSAGE(JWRN_BOGUS_PROGRESSION, "Inconsistent progression sequence for component %d coefficient %d") JMESSAGE(JWRN_EXTRANEOUS_DATA, @@ -186,6 +198,13 @@ JMESSAGE(JWRN_MUST_RESYNC, "Corrupt JPEG data: found marker 0x%02x instead of RST%d") JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") +#if JPEG_LIB_VERSION < 70 +JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") +#if defined(C_ARITH_CODING_SUPPORTED) || defined(D_ARITH_CODING_SUPPORTED) +JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") +JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") +#endif +#endif #ifdef JMAKE_ENUM_LIST diff --git a/media/libjpeg/jmemmgr.c b/media/libjpeg/jmemmgr.c index 54589521a625..cf32524ea705 100644 --- a/media/libjpeg/jmemmgr.c +++ b/media/libjpeg/jmemmgr.c @@ -37,6 +37,15 @@ extern char * getenv JPP((const char * name)); #endif +LOCAL(size_t) +round_up_pow2 (size_t a, size_t b) +/* a rounded up to the next multiple of b, i.e. ceil(a/b)*b */ +/* Assumes a >= 0, b > 0, and b is a power of 2 */ +{ + return ((a + b - 1) & (~(b - 1))); +} + + /* * Some important notes: * The allocation routines provided here must never return NULL. @@ -265,7 +274,7 @@ alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject) * and so that algorithms can straddle outside the proper area up * to the next alignment. */ - sizeofobject = jround_up(sizeofobject, ALIGN_SIZE); + sizeofobject = round_up_pow2(sizeofobject, ALIGN_SIZE); /* Check for unsatisfiable request (do now to ensure no overflow below) */ if ((SIZEOF(small_pool_hdr) + sizeofobject + ALIGN_SIZE - 1) > MAX_ALLOC_CHUNK) @@ -354,7 +363,7 @@ alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject) * algorithms can straddle outside the proper area up to the next * alignment. */ - sizeofobject = jround_up(sizeofobject, ALIGN_SIZE); + sizeofobject = round_up_pow2(sizeofobject, ALIGN_SIZE); /* Check for unsatisfiable request (do now to ensure no overflow below) */ if ((SIZEOF(large_pool_hdr) + sizeofobject + ALIGN_SIZE - 1) > MAX_ALLOC_CHUNK) @@ -420,7 +429,7 @@ alloc_sarray (j_common_ptr cinfo, int pool_id, /* Make sure each row is properly aligned */ if ((ALIGN_SIZE % SIZEOF(JSAMPLE)) != 0) out_of_memory(cinfo, 5); /* safety check */ - samplesperrow = (JDIMENSION)jround_up(samplesperrow, (2 * ALIGN_SIZE) / SIZEOF(JSAMPLE)); + samplesperrow = (JDIMENSION)round_up_pow2(samplesperrow, (2 * ALIGN_SIZE) / SIZEOF(JSAMPLE)); /* Calculate max # of rows allowed in one allocation chunk */ ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / diff --git a/media/libjpeg/jmorecfg.h b/media/libjpeg/jmorecfg.h index c91399732dd3..6c28c606d875 100644 --- a/media/libjpeg/jmorecfg.h +++ b/media/libjpeg/jmorecfg.h @@ -2,7 +2,7 @@ * jmorecfg.h * * Copyright (C) 1991-1997, Thomas G. Lane. - * Copyright (C) 2009, D. R. Commander. + * Copyright (C) 2009, 2011, D. R. Commander. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -242,8 +242,6 @@ typedef int boolean; * (You may HAVE to do that if your compiler doesn't like null source files.) */ -/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ - /* Capability options common to encoder and decoder: */ #define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ @@ -252,7 +250,6 @@ typedef int boolean; /* Encoder capability options: */ -#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ #define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ #define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ @@ -268,7 +265,6 @@ typedef int boolean; /* Decoder capability options: */ -#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ #define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ #define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ @@ -302,22 +298,60 @@ typedef int boolean; #define RGB_BLUE 2 /* Offset of Blue */ #define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ -#define JPEG_NUMCS 12 +#define JPEG_NUMCS 16 + +#define EXT_RGB_RED 0 +#define EXT_RGB_GREEN 1 +#define EXT_RGB_BLUE 2 +#define EXT_RGB_PIXELSIZE 3 + +#define EXT_RGBX_RED 0 +#define EXT_RGBX_GREEN 1 +#define EXT_RGBX_BLUE 2 +#define EXT_RGBX_PIXELSIZE 4 + +#define EXT_BGR_RED 2 +#define EXT_BGR_GREEN 1 +#define EXT_BGR_BLUE 0 +#define EXT_BGR_PIXELSIZE 3 + +#define EXT_BGRX_RED 2 +#define EXT_BGRX_GREEN 1 +#define EXT_BGRX_BLUE 0 +#define EXT_BGRX_PIXELSIZE 4 + +#define EXT_XBGR_RED 3 +#define EXT_XBGR_GREEN 2 +#define EXT_XBGR_BLUE 1 +#define EXT_XBGR_PIXELSIZE 4 + +#define EXT_XRGB_RED 1 +#define EXT_XRGB_GREEN 2 +#define EXT_XRGB_BLUE 3 +#define EXT_XRGB_PIXELSIZE 4 static const int rgb_red[JPEG_NUMCS] = { - -1, -1, RGB_RED, -1, -1, -1, 0, 0, 2, 2, 3, 1 + -1, -1, RGB_RED, -1, -1, -1, EXT_RGB_RED, EXT_RGBX_RED, + EXT_BGR_RED, EXT_BGRX_RED, EXT_XBGR_RED, EXT_XRGB_RED, + EXT_RGBX_RED, EXT_BGRX_RED, EXT_XBGR_RED, EXT_XRGB_RED }; static const int rgb_green[JPEG_NUMCS] = { - -1, -1, RGB_GREEN, -1, -1, -1, 1, 1, 1, 1, 2, 2 + -1, -1, RGB_GREEN, -1, -1, -1, EXT_RGB_GREEN, EXT_RGBX_GREEN, + EXT_BGR_GREEN, EXT_BGRX_GREEN, EXT_XBGR_GREEN, EXT_XRGB_GREEN, + EXT_RGBX_GREEN, EXT_BGRX_GREEN, EXT_XBGR_GREEN, EXT_XRGB_GREEN }; static const int rgb_blue[JPEG_NUMCS] = { - -1, -1, RGB_BLUE, -1, -1, -1, 2, 2, 0, 0, 1, 3 + -1, -1, RGB_BLUE, -1, -1, -1, EXT_RGB_BLUE, EXT_RGBX_BLUE, + EXT_BGR_BLUE, EXT_BGRX_BLUE, EXT_XBGR_BLUE, EXT_XRGB_BLUE, + EXT_RGBX_BLUE, EXT_BGRX_BLUE, EXT_XBGR_BLUE, EXT_XRGB_BLUE }; static const int rgb_pixelsize[JPEG_NUMCS] = { - -1, -1, RGB_PIXELSIZE, -1, -1, -1, 3, 4, 3, 4, 4, 4 + -1, -1, RGB_PIXELSIZE, -1, -1, -1, EXT_RGB_PIXELSIZE, EXT_RGBX_PIXELSIZE, + EXT_BGR_PIXELSIZE, EXT_BGRX_PIXELSIZE, EXT_XBGR_PIXELSIZE, EXT_XRGB_PIXELSIZE, + EXT_RGBX_PIXELSIZE, EXT_BGRX_PIXELSIZE, EXT_XBGR_PIXELSIZE, EXT_XRGB_PIXELSIZE }; /* Definitions for speed-related optimizations. */ diff --git a/media/libjpeg/jpegint.h b/media/libjpeg/jpegint.h index 3ba7be0827fd..78717482ebf1 100644 --- a/media/libjpeg/jpegint.h +++ b/media/libjpeg/jpegint.h @@ -375,7 +375,7 @@ EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo)); /* Utility routines in jutils.c */ EXTERN(long) jdiv_round_up JPP((long a, long b)); -EXTERN(size_t) jround_up JPP((size_t a, size_t b)); +EXTERN(long) jround_up JPP((long a, long b)); EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, JSAMPARRAY output_array, int dest_row, int num_rows, JDIMENSION num_cols)); diff --git a/media/libjpeg/jpeglib.h b/media/libjpeg/jpeglib.h index cb3acaf910a9..d19a3ef2e589 100644 --- a/media/libjpeg/jpeglib.h +++ b/media/libjpeg/jpeglib.h @@ -3,7 +3,7 @@ * * Copyright (C) 1991-1998, Thomas G. Lane. * Modified 2002-2009 by Guido Vollbeding. - * Copyright (C) 2009-2010, D. R. Commander. + * Copyright (C) 2009-2011, D. R. Commander. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -211,12 +211,13 @@ struct jpeg_marker_struct { /* Known color spaces. */ #define JCS_EXTENSIONS 1 +#define JCS_ALPHA_EXTENSIONS 1 typedef enum { JCS_UNKNOWN, /* error/unspecified */ JCS_GRAYSCALE, /* monochrome */ JCS_RGB, /* red/green/blue as specified by the RGB_RED, RGB_GREEN, - RGB_BLUE, and RGB_PIXELSIZE macros */ + RGB_BLUE, and RGB_PIXELSIZE macros */ JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ JCS_CMYK, /* C/M/Y/K */ JCS_YCCK, /* Y/Cb/Cr/K */ @@ -225,7 +226,18 @@ typedef enum { JCS_EXT_BGR, /* blue/green/red */ JCS_EXT_BGRX, /* blue/green/red/x */ JCS_EXT_XBGR, /* x/blue/green/red */ - JCS_EXT_XRGB /* x/red/green/blue */ + JCS_EXT_XRGB, /* x/red/green/blue */ + /* When out_color_space it set to JCS_EXT_RGBX, JCS_EXT_BGRX, + JCS_EXT_XBGR, or JCS_EXT_XRGB during decompression, the X byte is + undefined, and in order to ensure the best performance, + libjpeg-turbo can set that byte to whatever value it wishes. Use + the following colorspace constants to ensure that the X byte is set + to 0xFF, so that it can be interpreted as an opaque alpha + channel. */ + JCS_EXT_RGBA, /* red/green/blue/alpha */ + JCS_EXT_BGRA, /* blue/green/red/alpha */ + JCS_EXT_ABGR, /* alpha/blue/green/red */ + JCS_EXT_ARGB /* alpha/red/green/blue */ } J_COLOR_SPACE; /* DCT/IDCT algorithm options. */ diff --git a/media/libjpeg/jsimd.h b/media/libjpeg/jsimd.h index b6637915372f..3fa2c43271ce 100644 --- a/media/libjpeg/jsimd.h +++ b/media/libjpeg/jsimd.h @@ -2,6 +2,7 @@ * jsimd.h * * Copyright 2009 Pierre Ossman for Cendio AB + * Copyright 2011 D. R. Commander * * Based on the x86 SIMD extension for IJG JPEG library, * Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -13,8 +14,10 @@ #ifdef NEED_SHORT_EXTERNAL_NAMES #define jsimd_can_rgb_ycc jSCanRgbYcc +#define jsimd_can_rgb_gray jSCanRgbGry #define jsimd_can_ycc_rgb jSCanYccRgb #define jsimd_rgb_ycc_convert jSRgbYccConv +#define jsimd_rgb_gray_convert jSRgbGryConv #define jsimd_ycc_rgb_convert jSYccRgbConv #define jsimd_can_h2v2_downsample jSCanH2V2Down #define jsimd_can_h2v1_downsample jSCanH2V1Down @@ -35,12 +38,17 @@ #endif /* NEED_SHORT_EXTERNAL_NAMES */ EXTERN(int) jsimd_can_rgb_ycc JPP((void)); +EXTERN(int) jsimd_can_rgb_gray JPP((void)); EXTERN(int) jsimd_can_ycc_rgb JPP((void)); EXTERN(void) jsimd_rgb_ycc_convert JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)); +EXTERN(void) jsimd_rgb_gray_convert + JPP((j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); EXTERN(void) jsimd_ycc_rgb_convert JPP((j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, diff --git a/media/libjpeg/jsimd_none.c b/media/libjpeg/jsimd_none.c index 7ff30742cc99..9787902a8bdb 100644 --- a/media/libjpeg/jsimd_none.c +++ b/media/libjpeg/jsimd_none.c @@ -2,7 +2,7 @@ * jsimd_none.c * * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright 2009 D. R. Commander + * Copyright 2009-2011 D. R. Commander * * Based on the x86 SIMD extension for IJG JPEG library, * Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -24,6 +24,12 @@ jsimd_can_rgb_ycc (void) return 0; } +GLOBAL(int) +jsimd_can_rgb_gray (void) +{ + return 0; +} + GLOBAL(int) jsimd_can_ycc_rgb (void) { @@ -37,6 +43,13 @@ jsimd_rgb_ycc_convert (j_compress_ptr cinfo, { } +GLOBAL(void) +jsimd_rgb_gray_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ +} + GLOBAL(void) jsimd_ycc_rgb_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, diff --git a/media/libjpeg/jutils.c b/media/libjpeg/jutils.c index 98b54f5f107a..d18a9555621b 100644 --- a/media/libjpeg/jutils.c +++ b/media/libjpeg/jutils.c @@ -77,8 +77,8 @@ jdiv_round_up (long a, long b) } -GLOBAL(size_t) -jround_up (size_t a, size_t b) +GLOBAL(long) +jround_up (long a, long b) /* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */ /* Assumes a >= 0, b > 0 */ { diff --git a/media/libjpeg/jversion.h b/media/libjpeg/jversion.h index 119c481c3f26..71d7b91319c1 100644 --- a/media/libjpeg/jversion.h +++ b/media/libjpeg/jversion.h @@ -2,7 +2,7 @@ * jversion.h * * Copyright (C) 1991-2010, Thomas G. Lane, Guido Vollbeding. - * Copyright (C) 2010, D. R. Commander. + * Copyright (C) 2010, 2012, D. R. Commander. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -14,24 +14,18 @@ #define JVERSION "8b 16-May-2010" -#define JCOPYRIGHT "Copyright (C) 2010, Thomas G. Lane, Guido Vollbeding" - #elif JPEG_LIB_VERSION >= 70 #define JVERSION "7 27-Jun-2009" -#define JCOPYRIGHT "Copyright (C) 2009, Thomas G. Lane, Guido Vollbeding" - #else #define JVERSION "6b 27-Mar-1998" -#define JCOPYRIGHT "Copyright (C) 1998, Thomas G. Lane" - #endif -#define LJTCOPYRIGHT "Copyright (C) 1999-2006 MIYASAKA Masaru\n" \ - "Copyright (C) 2004 Landmark Graphics Corporation\n" \ - "Copyright (C) 2005-2007 Sun Microsystems, Inc.\n" \ +#define JCOPYRIGHT "Copyright (C) 1991-2010 Thomas G. Lane, Guido Vollbeding\n" \ + "Copyright (C) 1999-2006 MIYASAKA Masaru\n" \ "Copyright (C) 2009 Pierre Ossman for Cendio AB\n" \ - "Copyright (C) 2009-2011 D. R. Commander" + "Copyright (C) 2009-2012 D. R. Commander\n" \ + "Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies)" diff --git a/media/libjpeg/mozilla.diff b/media/libjpeg/mozilla.diff new file mode 100644 index 000000000000..83b340f357b7 --- /dev/null +++ b/media/libjpeg/mozilla.diff @@ -0,0 +1,70 @@ +--- jmorecfg.h 2012-01-27 00:46:32 -0500 ++++ jmorecfg.h 2012-02-10 23:08:03 -0500 +@@ -6,16 +6,17 @@ + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + ++#include "prtypes.h" + + /* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 12 for 12-bit sample values + * Only 8 and 12 are legal data precisions for lossy JPEG according to the + * JPEG standard, and the IJG code does not support anything else! + * We do not support run-time selection of data precision, sorry. +@@ -127,45 +128,29 @@ typedef char JOCTET; + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + + /* UINT8 must hold at least the values 0..255. */ + +-#ifdef HAVE_UNSIGNED_CHAR +-typedef unsigned char UINT8; +-#else /* not HAVE_UNSIGNED_CHAR */ +-#ifdef __CHAR_UNSIGNED__ +-typedef char UINT8; +-#else /* not __CHAR_UNSIGNED__ */ +-typedef short UINT8; +-#endif /* __CHAR_UNSIGNED__ */ +-#endif /* HAVE_UNSIGNED_CHAR */ ++typedef PRUint8 UINT8; + + /* UINT16 must hold at least the values 0..65535. */ + +-#ifdef HAVE_UNSIGNED_SHORT +-typedef unsigned short UINT16; +-#else /* not HAVE_UNSIGNED_SHORT */ +-typedef unsigned int UINT16; +-#endif /* HAVE_UNSIGNED_SHORT */ ++typedef PRUint16 UINT16; + + /* INT16 must hold at least the values -32768..32767. */ + +-#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +-typedef short INT16; +-#endif ++typedef PRInt16 INT16; + + /* INT32 must hold at least signed 32-bit values. */ + +-#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ +-typedef long INT32; +-#endif ++typedef PRInt32 INT32; + + /* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. + */ + diff --git a/media/libjpeg/simd/jcclrmmx.asm b/media/libjpeg/simd/jcclrmmx.asm index b6b89121b5fe..e09525310e87 100644 --- a/media/libjpeg/simd/jcclrmmx.asm +++ b/media/libjpeg/simd/jcclrmmx.asm @@ -19,8 +19,6 @@ %include "jcolsamp.inc" ; -------------------------------------------------------------------------- - SECTION SEG_TEXT - BITS 32 ; ; Convert some rows of samples to the output colorspace. ; diff --git a/media/libjpeg/simd/jcclrss2-64.asm b/media/libjpeg/simd/jcclrss2-64.asm index 8ca47aa06cfe..f5d6bed955ce 100644 --- a/media/libjpeg/simd/jcclrss2-64.asm +++ b/media/libjpeg/simd/jcclrss2-64.asm @@ -17,8 +17,6 @@ %include "jcolsamp.inc" ; -------------------------------------------------------------------------- - SECTION SEG_TEXT - BITS 64 ; ; Convert some rows of samples to the output colorspace. ; diff --git a/media/libjpeg/simd/jcclrss2.asm b/media/libjpeg/simd/jcclrss2.asm index 8def718cb172..517b7056388a 100644 --- a/media/libjpeg/simd/jcclrss2.asm +++ b/media/libjpeg/simd/jcclrss2.asm @@ -16,8 +16,6 @@ %include "jcolsamp.inc" ; -------------------------------------------------------------------------- - SECTION SEG_TEXT - BITS 32 ; ; Convert some rows of samples to the output colorspace. ; diff --git a/media/libjpeg/simd/jccolmmx.asm b/media/libjpeg/simd/jccolmmx.asm index 5e7f3be994ee..9650e47d475e 100644 --- a/media/libjpeg/simd/jccolmmx.asm +++ b/media/libjpeg/simd/jccolmmx.asm @@ -51,16 +51,19 @@ PD_ONEHALF times 2 dd (1 << (SCALEBITS-1)) alignz 16 ; -------------------------------------------------------------------------- + SECTION SEG_TEXT + BITS 32 + %include "jcclrmmx.asm" %undef RGB_RED %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 0 -%define RGB_GREEN 1 -%define RGB_BLUE 2 -%define RGB_PIXELSIZE 3 +%define RGB_RED EXT_RGB_RED +%define RGB_GREEN EXT_RGB_GREEN +%define RGB_BLUE EXT_RGB_BLUE +%define RGB_PIXELSIZE EXT_RGB_PIXELSIZE %define jsimd_rgb_ycc_convert_mmx jsimd_extrgb_ycc_convert_mmx %include "jcclrmmx.asm" @@ -68,10 +71,10 @@ PD_ONEHALF times 2 dd (1 << (SCALEBITS-1)) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 0 -%define RGB_GREEN 1 -%define RGB_BLUE 2 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_RGBX_RED +%define RGB_GREEN EXT_RGBX_GREEN +%define RGB_BLUE EXT_RGBX_BLUE +%define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE %define jsimd_rgb_ycc_convert_mmx jsimd_extrgbx_ycc_convert_mmx %include "jcclrmmx.asm" @@ -79,10 +82,10 @@ PD_ONEHALF times 2 dd (1 << (SCALEBITS-1)) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 2 -%define RGB_GREEN 1 -%define RGB_BLUE 0 -%define RGB_PIXELSIZE 3 +%define RGB_RED EXT_BGR_RED +%define RGB_GREEN EXT_BGR_GREEN +%define RGB_BLUE EXT_BGR_BLUE +%define RGB_PIXELSIZE EXT_BGR_PIXELSIZE %define jsimd_rgb_ycc_convert_mmx jsimd_extbgr_ycc_convert_mmx %include "jcclrmmx.asm" @@ -90,10 +93,10 @@ PD_ONEHALF times 2 dd (1 << (SCALEBITS-1)) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 2 -%define RGB_GREEN 1 -%define RGB_BLUE 0 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_BGRX_RED +%define RGB_GREEN EXT_BGRX_GREEN +%define RGB_BLUE EXT_BGRX_BLUE +%define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE %define jsimd_rgb_ycc_convert_mmx jsimd_extbgrx_ycc_convert_mmx %include "jcclrmmx.asm" @@ -101,10 +104,10 @@ PD_ONEHALF times 2 dd (1 << (SCALEBITS-1)) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 3 -%define RGB_GREEN 2 -%define RGB_BLUE 1 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_XBGR_RED +%define RGB_GREEN EXT_XBGR_GREEN +%define RGB_BLUE EXT_XBGR_BLUE +%define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE %define jsimd_rgb_ycc_convert_mmx jsimd_extxbgr_ycc_convert_mmx %include "jcclrmmx.asm" @@ -112,9 +115,9 @@ PD_ONEHALF times 2 dd (1 << (SCALEBITS-1)) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 1 -%define RGB_GREEN 2 -%define RGB_BLUE 3 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_XRGB_RED +%define RGB_GREEN EXT_XRGB_GREEN +%define RGB_BLUE EXT_XRGB_BLUE +%define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE %define jsimd_rgb_ycc_convert_mmx jsimd_extxrgb_ycc_convert_mmx %include "jcclrmmx.asm" diff --git a/media/libjpeg/simd/jccolss2-64.asm b/media/libjpeg/simd/jccolss2-64.asm index 64ee0ba85d51..ae6014885ed2 100644 --- a/media/libjpeg/simd/jccolss2-64.asm +++ b/media/libjpeg/simd/jccolss2-64.asm @@ -48,16 +48,19 @@ PD_ONEHALF times 4 dd (1 << (SCALEBITS-1)) alignz 16 ; -------------------------------------------------------------------------- + SECTION SEG_TEXT + BITS 64 + %include "jcclrss2-64.asm" %undef RGB_RED %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 0 -%define RGB_GREEN 1 -%define RGB_BLUE 2 -%define RGB_PIXELSIZE 3 +%define RGB_RED EXT_RGB_RED +%define RGB_GREEN EXT_RGB_GREEN +%define RGB_BLUE EXT_RGB_BLUE +%define RGB_PIXELSIZE EXT_RGB_PIXELSIZE %define jsimd_rgb_ycc_convert_sse2 jsimd_extrgb_ycc_convert_sse2 %include "jcclrss2-64.asm" @@ -65,10 +68,10 @@ PD_ONEHALF times 4 dd (1 << (SCALEBITS-1)) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 0 -%define RGB_GREEN 1 -%define RGB_BLUE 2 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_RGBX_RED +%define RGB_GREEN EXT_RGBX_GREEN +%define RGB_BLUE EXT_RGBX_BLUE +%define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE %define jsimd_rgb_ycc_convert_sse2 jsimd_extrgbx_ycc_convert_sse2 %include "jcclrss2-64.asm" @@ -76,10 +79,10 @@ PD_ONEHALF times 4 dd (1 << (SCALEBITS-1)) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 2 -%define RGB_GREEN 1 -%define RGB_BLUE 0 -%define RGB_PIXELSIZE 3 +%define RGB_RED EXT_BGR_RED +%define RGB_GREEN EXT_BGR_GREEN +%define RGB_BLUE EXT_BGR_BLUE +%define RGB_PIXELSIZE EXT_BGR_PIXELSIZE %define jsimd_rgb_ycc_convert_sse2 jsimd_extbgr_ycc_convert_sse2 %include "jcclrss2-64.asm" @@ -87,10 +90,10 @@ PD_ONEHALF times 4 dd (1 << (SCALEBITS-1)) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 2 -%define RGB_GREEN 1 -%define RGB_BLUE 0 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_BGRX_RED +%define RGB_GREEN EXT_BGRX_GREEN +%define RGB_BLUE EXT_BGRX_BLUE +%define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE %define jsimd_rgb_ycc_convert_sse2 jsimd_extbgrx_ycc_convert_sse2 %include "jcclrss2-64.asm" @@ -98,10 +101,10 @@ PD_ONEHALF times 4 dd (1 << (SCALEBITS-1)) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 3 -%define RGB_GREEN 2 -%define RGB_BLUE 1 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_XBGR_RED +%define RGB_GREEN EXT_XBGR_GREEN +%define RGB_BLUE EXT_XBGR_BLUE +%define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE %define jsimd_rgb_ycc_convert_sse2 jsimd_extxbgr_ycc_convert_sse2 %include "jcclrss2-64.asm" @@ -109,9 +112,9 @@ PD_ONEHALF times 4 dd (1 << (SCALEBITS-1)) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 1 -%define RGB_GREEN 2 -%define RGB_BLUE 3 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_XRGB_RED +%define RGB_GREEN EXT_XRGB_GREEN +%define RGB_BLUE EXT_XRGB_BLUE +%define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE %define jsimd_rgb_ycc_convert_sse2 jsimd_extxrgb_ycc_convert_sse2 %include "jcclrss2-64.asm" diff --git a/media/libjpeg/simd/jccolss2.asm b/media/libjpeg/simd/jccolss2.asm index 8d1f73406e8a..ac001d186182 100644 --- a/media/libjpeg/simd/jccolss2.asm +++ b/media/libjpeg/simd/jccolss2.asm @@ -48,16 +48,19 @@ PD_ONEHALF times 4 dd (1 << (SCALEBITS-1)) alignz 16 ; -------------------------------------------------------------------------- + SECTION SEG_TEXT + BITS 32 + %include "jcclrss2.asm" %undef RGB_RED %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 0 -%define RGB_GREEN 1 -%define RGB_BLUE 2 -%define RGB_PIXELSIZE 3 +%define RGB_RED EXT_RGB_RED +%define RGB_GREEN EXT_RGB_GREEN +%define RGB_BLUE EXT_RGB_BLUE +%define RGB_PIXELSIZE EXT_RGB_PIXELSIZE %define jsimd_rgb_ycc_convert_sse2 jsimd_extrgb_ycc_convert_sse2 %include "jcclrss2.asm" @@ -65,10 +68,10 @@ PD_ONEHALF times 4 dd (1 << (SCALEBITS-1)) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 0 -%define RGB_GREEN 1 -%define RGB_BLUE 2 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_RGBX_RED +%define RGB_GREEN EXT_RGBX_GREEN +%define RGB_BLUE EXT_RGBX_BLUE +%define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE %define jsimd_rgb_ycc_convert_sse2 jsimd_extrgbx_ycc_convert_sse2 %include "jcclrss2.asm" @@ -76,10 +79,10 @@ PD_ONEHALF times 4 dd (1 << (SCALEBITS-1)) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 2 -%define RGB_GREEN 1 -%define RGB_BLUE 0 -%define RGB_PIXELSIZE 3 +%define RGB_RED EXT_BGR_RED +%define RGB_GREEN EXT_BGR_GREEN +%define RGB_BLUE EXT_BGR_BLUE +%define RGB_PIXELSIZE EXT_BGR_PIXELSIZE %define jsimd_rgb_ycc_convert_sse2 jsimd_extbgr_ycc_convert_sse2 %include "jcclrss2.asm" @@ -87,10 +90,10 @@ PD_ONEHALF times 4 dd (1 << (SCALEBITS-1)) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 2 -%define RGB_GREEN 1 -%define RGB_BLUE 0 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_BGRX_RED +%define RGB_GREEN EXT_BGRX_GREEN +%define RGB_BLUE EXT_BGRX_BLUE +%define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE %define jsimd_rgb_ycc_convert_sse2 jsimd_extbgrx_ycc_convert_sse2 %include "jcclrss2.asm" @@ -98,10 +101,10 @@ PD_ONEHALF times 4 dd (1 << (SCALEBITS-1)) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 3 -%define RGB_GREEN 2 -%define RGB_BLUE 1 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_XBGR_RED +%define RGB_GREEN EXT_XBGR_GREEN +%define RGB_BLUE EXT_XBGR_BLUE +%define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE %define jsimd_rgb_ycc_convert_sse2 jsimd_extxbgr_ycc_convert_sse2 %include "jcclrss2.asm" @@ -109,9 +112,9 @@ PD_ONEHALF times 4 dd (1 << (SCALEBITS-1)) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 1 -%define RGB_GREEN 2 -%define RGB_BLUE 3 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_XRGB_RED +%define RGB_GREEN EXT_XRGB_GREEN +%define RGB_BLUE EXT_XRGB_BLUE +%define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE %define jsimd_rgb_ycc_convert_sse2 jsimd_extxrgb_ycc_convert_sse2 %include "jcclrss2.asm" diff --git a/media/libjpeg/simd/jcgrammx.asm b/media/libjpeg/simd/jcgrammx.asm new file mode 100644 index 000000000000..b8b8dd3ad541 --- /dev/null +++ b/media/libjpeg/simd/jcgrammx.asm @@ -0,0 +1,116 @@ +; +; jcgrammx.asm - grayscale colorspace conversion (MMX) +; +; Copyright 2009 Pierre Ossman for Cendio AB +; Copyright 2011 D. R. Commander +; +; Based on +; x86 SIMD extension for IJG JPEG library +; Copyright (C) 1999-2006, MIYASAKA Masaru. +; For conditions of distribution and use, see copyright notice in jsimdext.inc +; +; This file should be assembled with NASM (Netwide Assembler), +; can *not* be assembled with Microsoft's MASM or any compatible +; assembler (including Borland's Turbo Assembler). +; NASM is available from http://nasm.sourceforge.net/ or +; http://sourceforge.net/project/showfiles.php?group_id=6208 +; +; [TAB8] + +%include "jsimdext.inc" + +; -------------------------------------------------------------------------- + +%define SCALEBITS 16 + +F_0_114 equ 7471 ; FIX(0.11400) +F_0_250 equ 16384 ; FIX(0.25000) +F_0_299 equ 19595 ; FIX(0.29900) +F_0_587 equ 38470 ; FIX(0.58700) +F_0_337 equ (F_0_587 - F_0_250) ; FIX(0.58700) - FIX(0.25000) + +; -------------------------------------------------------------------------- + SECTION SEG_CONST + + alignz 16 + global EXTN(jconst_rgb_gray_convert_mmx) + +EXTN(jconst_rgb_gray_convert_mmx): + +PW_F0299_F0337 times 2 dw F_0_299, F_0_337 +PW_F0114_F0250 times 2 dw F_0_114, F_0_250 +PD_ONEHALF times 2 dd (1 << (SCALEBITS-1)) + + alignz 16 + +; -------------------------------------------------------------------------- + SECTION SEG_TEXT + BITS 32 + +%include "jcgrymmx.asm" + +%undef RGB_RED +%undef RGB_GREEN +%undef RGB_BLUE +%undef RGB_PIXELSIZE +%define RGB_RED EXT_RGB_RED +%define RGB_GREEN EXT_RGB_GREEN +%define RGB_BLUE EXT_RGB_BLUE +%define RGB_PIXELSIZE EXT_RGB_PIXELSIZE +%define jsimd_rgb_gray_convert_mmx jsimd_extrgb_gray_convert_mmx +%include "jcgrymmx.asm" + +%undef RGB_RED +%undef RGB_GREEN +%undef RGB_BLUE +%undef RGB_PIXELSIZE +%define RGB_RED EXT_RGBX_RED +%define RGB_GREEN EXT_RGBX_GREEN +%define RGB_BLUE EXT_RGBX_BLUE +%define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE +%define jsimd_rgb_gray_convert_mmx jsimd_extrgbx_gray_convert_mmx +%include "jcgrymmx.asm" + +%undef RGB_RED +%undef RGB_GREEN +%undef RGB_BLUE +%undef RGB_PIXELSIZE +%define RGB_RED EXT_BGR_RED +%define RGB_GREEN EXT_BGR_GREEN +%define RGB_BLUE EXT_BGR_BLUE +%define RGB_PIXELSIZE EXT_BGR_PIXELSIZE +%define jsimd_rgb_gray_convert_mmx jsimd_extbgr_gray_convert_mmx +%include "jcgrymmx.asm" + +%undef RGB_RED +%undef RGB_GREEN +%undef RGB_BLUE +%undef RGB_PIXELSIZE +%define RGB_RED EXT_BGRX_RED +%define RGB_GREEN EXT_BGRX_GREEN +%define RGB_BLUE EXT_BGRX_BLUE +%define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE +%define jsimd_rgb_gray_convert_mmx jsimd_extbgrx_gray_convert_mmx +%include "jcgrymmx.asm" + +%undef RGB_RED +%undef RGB_GREEN +%undef RGB_BLUE +%undef RGB_PIXELSIZE +%define RGB_RED EXT_XBGR_RED +%define RGB_GREEN EXT_XBGR_GREEN +%define RGB_BLUE EXT_XBGR_BLUE +%define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE +%define jsimd_rgb_gray_convert_mmx jsimd_extxbgr_gray_convert_mmx +%include "jcgrymmx.asm" + +%undef RGB_RED +%undef RGB_GREEN +%undef RGB_BLUE +%undef RGB_PIXELSIZE +%define RGB_RED EXT_XRGB_RED +%define RGB_GREEN EXT_XRGB_GREEN +%define RGB_BLUE EXT_XRGB_BLUE +%define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE +%define jsimd_rgb_gray_convert_mmx jsimd_extxrgb_gray_convert_mmx +%include "jcgrymmx.asm" diff --git a/media/libjpeg/simd/jcgrass2-64.asm b/media/libjpeg/simd/jcgrass2-64.asm new file mode 100644 index 000000000000..ba28cc31dbd3 --- /dev/null +++ b/media/libjpeg/simd/jcgrass2-64.asm @@ -0,0 +1,113 @@ +; +; jcgrass2-64.asm - grayscale colorspace conversion (64-bit SSE2) +; +; x86 SIMD extension for IJG JPEG library +; Copyright (C) 1999-2006, MIYASAKA Masaru. +; Copyright (C) 2011, D. R. Commander. +; For conditions of distribution and use, see copyright notice in jsimdext.inc +; +; This file should be assembled with NASM (Netwide Assembler), +; can *not* be assembled with Microsoft's MASM or any compatible +; assembler (including Borland's Turbo Assembler). +; NASM is available from http://nasm.sourceforge.net/ or +; http://sourceforge.net/project/showfiles.php?group_id=6208 +; +; [TAB8] + +%include "jsimdext.inc" + +; -------------------------------------------------------------------------- + +%define SCALEBITS 16 + +F_0_114 equ 7471 ; FIX(0.11400) +F_0_250 equ 16384 ; FIX(0.25000) +F_0_299 equ 19595 ; FIX(0.29900) +F_0_587 equ 38470 ; FIX(0.58700) +F_0_337 equ (F_0_587 - F_0_250) ; FIX(0.58700) - FIX(0.25000) + +; -------------------------------------------------------------------------- + SECTION SEG_CONST + + alignz 16 + global EXTN(jconst_rgb_gray_convert_sse2) + +EXTN(jconst_rgb_gray_convert_sse2): + +PW_F0299_F0337 times 4 dw F_0_299, F_0_337 +PW_F0114_F0250 times 4 dw F_0_114, F_0_250 +PD_ONEHALF times 4 dd (1 << (SCALEBITS-1)) + + alignz 16 + +; -------------------------------------------------------------------------- + SECTION SEG_TEXT + BITS 64 + +%include "jcgryss2-64.asm" + +%undef RGB_RED +%undef RGB_GREEN +%undef RGB_BLUE +%undef RGB_PIXELSIZE +%define RGB_RED EXT_RGB_RED +%define RGB_GREEN EXT_RGB_GREEN +%define RGB_BLUE EXT_RGB_BLUE +%define RGB_PIXELSIZE EXT_RGB_PIXELSIZE +%define jsimd_rgb_gray_convert_sse2 jsimd_extrgb_gray_convert_sse2 +%include "jcgryss2-64.asm" + +%undef RGB_RED +%undef RGB_GREEN +%undef RGB_BLUE +%undef RGB_PIXELSIZE +%define RGB_RED EXT_RGBX_RED +%define RGB_GREEN EXT_RGBX_GREEN +%define RGB_BLUE EXT_RGBX_BLUE +%define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE +%define jsimd_rgb_gray_convert_sse2 jsimd_extrgbx_gray_convert_sse2 +%include "jcgryss2-64.asm" + +%undef RGB_RED +%undef RGB_GREEN +%undef RGB_BLUE +%undef RGB_PIXELSIZE +%define RGB_RED EXT_BGR_RED +%define RGB_GREEN EXT_BGR_GREEN +%define RGB_BLUE EXT_BGR_BLUE +%define RGB_PIXELSIZE EXT_BGR_PIXELSIZE +%define jsimd_rgb_gray_convert_sse2 jsimd_extbgr_gray_convert_sse2 +%include "jcgryss2-64.asm" + +%undef RGB_RED +%undef RGB_GREEN +%undef RGB_BLUE +%undef RGB_PIXELSIZE +%define RGB_RED EXT_BGRX_RED +%define RGB_GREEN EXT_BGRX_GREEN +%define RGB_BLUE EXT_BGRX_BLUE +%define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE +%define jsimd_rgb_gray_convert_sse2 jsimd_extbgrx_gray_convert_sse2 +%include "jcgryss2-64.asm" + +%undef RGB_RED +%undef RGB_GREEN +%undef RGB_BLUE +%undef RGB_PIXELSIZE +%define RGB_RED EXT_XBGR_RED +%define RGB_GREEN EXT_XBGR_GREEN +%define RGB_BLUE EXT_XBGR_BLUE +%define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE +%define jsimd_rgb_gray_convert_sse2 jsimd_extxbgr_gray_convert_sse2 +%include "jcgryss2-64.asm" + +%undef RGB_RED +%undef RGB_GREEN +%undef RGB_BLUE +%undef RGB_PIXELSIZE +%define RGB_RED EXT_XRGB_RED +%define RGB_GREEN EXT_XRGB_GREEN +%define RGB_BLUE EXT_XRGB_BLUE +%define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE +%define jsimd_rgb_gray_convert_sse2 jsimd_extxrgb_gray_convert_sse2 +%include "jcgryss2-64.asm" diff --git a/media/libjpeg/simd/jcgrass2.asm b/media/libjpeg/simd/jcgrass2.asm new file mode 100644 index 000000000000..998968e7635f --- /dev/null +++ b/media/libjpeg/simd/jcgrass2.asm @@ -0,0 +1,113 @@ +; +; jcgrass2.asm - grayscale colorspace conversion (SSE2) +; +; x86 SIMD extension for IJG JPEG library +; Copyright (C) 1999-2006, MIYASAKA Masaru. +; Copyright (C) 2011, D. R. Commander. +; For conditions of distribution and use, see copyright notice in jsimdext.inc +; +; This file should be assembled with NASM (Netwide Assembler), +; can *not* be assembled with Microsoft's MASM or any compatible +; assembler (including Borland's Turbo Assembler). +; NASM is available from http://nasm.sourceforge.net/ or +; http://sourceforge.net/project/showfiles.php?group_id=6208 +; +; [TAB8] + +%include "jsimdext.inc" + +; -------------------------------------------------------------------------- + +%define SCALEBITS 16 + +F_0_114 equ 7471 ; FIX(0.11400) +F_0_250 equ 16384 ; FIX(0.25000) +F_0_299 equ 19595 ; FIX(0.29900) +F_0_587 equ 38470 ; FIX(0.58700) +F_0_337 equ (F_0_587 - F_0_250) ; FIX(0.58700) - FIX(0.25000) + +; -------------------------------------------------------------------------- + SECTION SEG_CONST + + alignz 16 + global EXTN(jconst_rgb_gray_convert_sse2) + +EXTN(jconst_rgb_gray_convert_sse2): + +PW_F0299_F0337 times 4 dw F_0_299, F_0_337 +PW_F0114_F0250 times 4 dw F_0_114, F_0_250 +PD_ONEHALF times 4 dd (1 << (SCALEBITS-1)) + + alignz 16 + +; -------------------------------------------------------------------------- + SECTION SEG_TEXT + BITS 32 + +%include "jcgryss2.asm" + +%undef RGB_RED +%undef RGB_GREEN +%undef RGB_BLUE +%undef RGB_PIXELSIZE +%define RGB_RED EXT_RGB_RED +%define RGB_GREEN EXT_RGB_GREEN +%define RGB_BLUE EXT_RGB_BLUE +%define RGB_PIXELSIZE EXT_RGB_PIXELSIZE +%define jsimd_rgb_gray_convert_sse2 jsimd_extrgb_gray_convert_sse2 +%include "jcgryss2.asm" + +%undef RGB_RED +%undef RGB_GREEN +%undef RGB_BLUE +%undef RGB_PIXELSIZE +%define RGB_RED EXT_RGBX_RED +%define RGB_GREEN EXT_RGBX_GREEN +%define RGB_BLUE EXT_RGBX_BLUE +%define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE +%define jsimd_rgb_gray_convert_sse2 jsimd_extrgbx_gray_convert_sse2 +%include "jcgryss2.asm" + +%undef RGB_RED +%undef RGB_GREEN +%undef RGB_BLUE +%undef RGB_PIXELSIZE +%define RGB_RED EXT_BGR_RED +%define RGB_GREEN EXT_BGR_GREEN +%define RGB_BLUE EXT_BGR_BLUE +%define RGB_PIXELSIZE EXT_BGR_PIXELSIZE +%define jsimd_rgb_gray_convert_sse2 jsimd_extbgr_gray_convert_sse2 +%include "jcgryss2.asm" + +%undef RGB_RED +%undef RGB_GREEN +%undef RGB_BLUE +%undef RGB_PIXELSIZE +%define RGB_RED EXT_BGRX_RED +%define RGB_GREEN EXT_BGRX_GREEN +%define RGB_BLUE EXT_BGRX_BLUE +%define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE +%define jsimd_rgb_gray_convert_sse2 jsimd_extbgrx_gray_convert_sse2 +%include "jcgryss2.asm" + +%undef RGB_RED +%undef RGB_GREEN +%undef RGB_BLUE +%undef RGB_PIXELSIZE +%define RGB_RED EXT_XBGR_RED +%define RGB_GREEN EXT_XBGR_GREEN +%define RGB_BLUE EXT_XBGR_BLUE +%define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE +%define jsimd_rgb_gray_convert_sse2 jsimd_extxbgr_gray_convert_sse2 +%include "jcgryss2.asm" + +%undef RGB_RED +%undef RGB_GREEN +%undef RGB_BLUE +%undef RGB_PIXELSIZE +%define RGB_RED EXT_XRGB_RED +%define RGB_GREEN EXT_XRGB_GREEN +%define RGB_BLUE EXT_XRGB_BLUE +%define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE +%define jsimd_rgb_gray_convert_sse2 jsimd_extxrgb_gray_convert_sse2 +%include "jcgryss2.asm" diff --git a/media/libjpeg/simd/jcgrymmx.asm b/media/libjpeg/simd/jcgrymmx.asm new file mode 100644 index 000000000000..bbeea09bec96 --- /dev/null +++ b/media/libjpeg/simd/jcgrymmx.asm @@ -0,0 +1,357 @@ +; +; jcgrymmx.asm - grayscale colorspace conversion (MMX) +; +; Copyright 2009 Pierre Ossman for Cendio AB +; Copyright 2011 D. R. Commander +; +; Based on +; x86 SIMD extension for IJG JPEG library +; Copyright (C) 1999-2006, MIYASAKA Masaru. +; For conditions of distribution and use, see copyright notice in jsimdext.inc +; +; This file should be assembled with NASM (Netwide Assembler), +; can *not* be assembled with Microsoft's MASM or any compatible +; assembler (including Borland's Turbo Assembler). +; NASM is available from http://nasm.sourceforge.net/ or +; http://sourceforge.net/project/showfiles.php?group_id=6208 +; +; [TAB8] + +%include "jcolsamp.inc" + +; -------------------------------------------------------------------------- +; +; Convert some rows of samples to the output colorspace. +; +; GLOBAL(void) +; jsimd_rgb_gray_convert_mmx (JDIMENSION img_width, +; JSAMPARRAY input_buf, JSAMPIMAGE output_buf, +; JDIMENSION output_row, int num_rows); +; + +%define img_width(b) (b)+8 ; JDIMENSION img_width +%define input_buf(b) (b)+12 ; JSAMPARRAY input_buf +%define output_buf(b) (b)+16 ; JSAMPIMAGE output_buf +%define output_row(b) (b)+20 ; JDIMENSION output_row +%define num_rows(b) (b)+24 ; int num_rows + +%define original_ebp ebp+0 +%define wk(i) ebp-(WK_NUM-(i))*SIZEOF_MMWORD ; mmword wk[WK_NUM] +%define WK_NUM 2 +%define gotptr wk(0)-SIZEOF_POINTER ; void * gotptr + + align 16 + global EXTN(jsimd_rgb_gray_convert_mmx) + +EXTN(jsimd_rgb_gray_convert_mmx): + push ebp + mov eax,esp ; eax = original ebp + sub esp, byte 4 + and esp, byte (-SIZEOF_MMWORD) ; align to 64 bits + mov [esp],eax + mov ebp,esp ; ebp = aligned ebp + lea esp, [wk(0)] + pushpic eax ; make a room for GOT address + push ebx +; push ecx ; need not be preserved +; push edx ; need not be preserved + push esi + push edi + + get_GOT ebx ; get GOT address + movpic POINTER [gotptr], ebx ; save GOT address + + mov ecx, JDIMENSION [img_width(eax)] ; num_cols + test ecx,ecx + jz near .return + + push ecx + + mov esi, JSAMPIMAGE [output_buf(eax)] + mov ecx, JDIMENSION [output_row(eax)] + mov edi, JSAMPARRAY [esi+0*SIZEOF_JSAMPARRAY] + lea edi, [edi+ecx*SIZEOF_JSAMPROW] + + pop ecx + + mov esi, JSAMPARRAY [input_buf(eax)] + mov eax, INT [num_rows(eax)] + test eax,eax + jle near .return + alignx 16,7 +.rowloop: + pushpic eax + push edi + push esi + push ecx ; col + + mov esi, JSAMPROW [esi] ; inptr + mov edi, JSAMPROW [edi] ; outptr0 + movpic eax, POINTER [gotptr] ; load GOT address (eax) + + cmp ecx, byte SIZEOF_MMWORD + jae short .columnloop + alignx 16,7 + +%if RGB_PIXELSIZE == 3 ; --------------- + +.column_ld1: + push eax + push edx + lea ecx,[ecx+ecx*2] ; imul ecx,RGB_PIXELSIZE + test cl, SIZEOF_BYTE + jz short .column_ld2 + sub ecx, byte SIZEOF_BYTE + xor eax,eax + mov al, BYTE [esi+ecx] +.column_ld2: + test cl, SIZEOF_WORD + jz short .column_ld4 + sub ecx, byte SIZEOF_WORD + xor edx,edx + mov dx, WORD [esi+ecx] + shl eax, WORD_BIT + or eax,edx +.column_ld4: + movd mmA,eax + pop edx + pop eax + test cl, SIZEOF_DWORD + jz short .column_ld8 + sub ecx, byte SIZEOF_DWORD + movd mmG, DWORD [esi+ecx] + psllq mmA, DWORD_BIT + por mmA,mmG +.column_ld8: + test cl, SIZEOF_MMWORD + jz short .column_ld16 + movq mmG,mmA + movq mmA, MMWORD [esi+0*SIZEOF_MMWORD] + mov ecx, SIZEOF_MMWORD + jmp short .rgb_gray_cnv +.column_ld16: + test cl, 2*SIZEOF_MMWORD + mov ecx, SIZEOF_MMWORD + jz short .rgb_gray_cnv + movq mmF,mmA + movq mmA, MMWORD [esi+0*SIZEOF_MMWORD] + movq mmG, MMWORD [esi+1*SIZEOF_MMWORD] + jmp short .rgb_gray_cnv + alignx 16,7 + +.columnloop: + movq mmA, MMWORD [esi+0*SIZEOF_MMWORD] + movq mmG, MMWORD [esi+1*SIZEOF_MMWORD] + movq mmF, MMWORD [esi+2*SIZEOF_MMWORD] + +.rgb_gray_cnv: + ; mmA=(00 10 20 01 11 21 02 12) + ; mmG=(22 03 13 23 04 14 24 05) + ; mmF=(15 25 06 16 26 07 17 27) + + movq mmD,mmA + psllq mmA,4*BYTE_BIT ; mmA=(-- -- -- -- 00 10 20 01) + psrlq mmD,4*BYTE_BIT ; mmD=(11 21 02 12 -- -- -- --) + + punpckhbw mmA,mmG ; mmA=(00 04 10 14 20 24 01 05) + psllq mmG,4*BYTE_BIT ; mmG=(-- -- -- -- 22 03 13 23) + + punpcklbw mmD,mmF ; mmD=(11 15 21 25 02 06 12 16) + punpckhbw mmG,mmF ; mmG=(22 26 03 07 13 17 23 27) + + movq mmE,mmA + psllq mmA,4*BYTE_BIT ; mmA=(-- -- -- -- 00 04 10 14) + psrlq mmE,4*BYTE_BIT ; mmE=(20 24 01 05 -- -- -- --) + + punpckhbw mmA,mmD ; mmA=(00 02 04 06 10 12 14 16) + psllq mmD,4*BYTE_BIT ; mmD=(-- -- -- -- 11 15 21 25) + + punpcklbw mmE,mmG ; mmE=(20 22 24 26 01 03 05 07) + punpckhbw mmD,mmG ; mmD=(11 13 15 17 21 23 25 27) + + pxor mmH,mmH + + movq mmC,mmA + punpcklbw mmA,mmH ; mmA=(00 02 04 06) + punpckhbw mmC,mmH ; mmC=(10 12 14 16) + + movq mmB,mmE + punpcklbw mmE,mmH ; mmE=(20 22 24 26) + punpckhbw mmB,mmH ; mmB=(01 03 05 07) + + movq mmF,mmD + punpcklbw mmD,mmH ; mmD=(11 13 15 17) + punpckhbw mmF,mmH ; mmF=(21 23 25 27) + +%else ; RGB_PIXELSIZE == 4 ; ----------- + +.column_ld1: + test cl, SIZEOF_MMWORD/8 + jz short .column_ld2 + sub ecx, byte SIZEOF_MMWORD/8 + movd mmA, DWORD [esi+ecx*RGB_PIXELSIZE] +.column_ld2: + test cl, SIZEOF_MMWORD/4 + jz short .column_ld4 + sub ecx, byte SIZEOF_MMWORD/4 + movq mmF,mmA + movq mmA, MMWORD [esi+ecx*RGB_PIXELSIZE] +.column_ld4: + test cl, SIZEOF_MMWORD/2 + mov ecx, SIZEOF_MMWORD + jz short .rgb_gray_cnv + movq mmD,mmA + movq mmC,mmF + movq mmA, MMWORD [esi+0*SIZEOF_MMWORD] + movq mmF, MMWORD [esi+1*SIZEOF_MMWORD] + jmp short .rgb_gray_cnv + alignx 16,7 + +.columnloop: + movq mmA, MMWORD [esi+0*SIZEOF_MMWORD] + movq mmF, MMWORD [esi+1*SIZEOF_MMWORD] + movq mmD, MMWORD [esi+2*SIZEOF_MMWORD] + movq mmC, MMWORD [esi+3*SIZEOF_MMWORD] + +.rgb_gray_cnv: + ; mmA=(00 10 20 30 01 11 21 31) + ; mmF=(02 12 22 32 03 13 23 33) + ; mmD=(04 14 24 34 05 15 25 35) + ; mmC=(06 16 26 36 07 17 27 37) + + movq mmB,mmA + punpcklbw mmA,mmF ; mmA=(00 02 10 12 20 22 30 32) + punpckhbw mmB,mmF ; mmB=(01 03 11 13 21 23 31 33) + + movq mmG,mmD + punpcklbw mmD,mmC ; mmD=(04 06 14 16 24 26 34 36) + punpckhbw mmG,mmC ; mmG=(05 07 15 17 25 27 35 37) + + movq mmE,mmA + punpcklwd mmA,mmD ; mmA=(00 02 04 06 10 12 14 16) + punpckhwd mmE,mmD ; mmE=(20 22 24 26 30 32 34 36) + + movq mmH,mmB + punpcklwd mmB,mmG ; mmB=(01 03 05 07 11 13 15 17) + punpckhwd mmH,mmG ; mmH=(21 23 25 27 31 33 35 37) + + pxor mmF,mmF + + movq mmC,mmA + punpcklbw mmA,mmF ; mmA=(00 02 04 06) + punpckhbw mmC,mmF ; mmC=(10 12 14 16) + + movq mmD,mmB + punpcklbw mmB,mmF ; mmB=(01 03 05 07) + punpckhbw mmD,mmF ; mmD=(11 13 15 17) + + movq mmG,mmE + punpcklbw mmE,mmF ; mmE=(20 22 24 26) + punpckhbw mmG,mmF ; mmG=(30 32 34 36) + + punpcklbw mmF,mmH + punpckhbw mmH,mmH + psrlw mmF,BYTE_BIT ; mmF=(21 23 25 27) + psrlw mmH,BYTE_BIT ; mmH=(31 33 35 37) + +%endif ; RGB_PIXELSIZE ; --------------- + + ; mm0=(R0 R2 R4 R6)=RE, mm2=(G0 G2 G4 G6)=GE, mm4=(B0 B2 B4 B6)=BE + ; mm1=(R1 R3 R5 R7)=RO, mm3=(G1 G3 G5 G7)=GO, mm5=(B1 B3 B5 B7)=BO + + ; (Original) + ; Y = 0.29900 * R + 0.58700 * G + 0.11400 * B + ; + ; (This implementation) + ; Y = 0.29900 * R + 0.33700 * G + 0.11400 * B + 0.25000 * G + + movq mm6,mm1 + punpcklwd mm1,mm3 + punpckhwd mm6,mm3 + pmaddwd mm1,[GOTOFF(eax,PW_F0299_F0337)] ; mm1=ROL*FIX(0.299)+GOL*FIX(0.337) + pmaddwd mm6,[GOTOFF(eax,PW_F0299_F0337)] ; mm6=ROH*FIX(0.299)+GOH*FIX(0.337) + + movq mm7, mm6 ; mm7=ROH*FIX(0.299)+GOH*FIX(0.337) + + movq mm6,mm0 + punpcklwd mm0,mm2 + punpckhwd mm6,mm2 + pmaddwd mm0,[GOTOFF(eax,PW_F0299_F0337)] ; mm0=REL*FIX(0.299)+GEL*FIX(0.337) + pmaddwd mm6,[GOTOFF(eax,PW_F0299_F0337)] ; mm6=REH*FIX(0.299)+GEH*FIX(0.337) + + movq MMWORD [wk(0)], mm0 ; wk(0)=REL*FIX(0.299)+GEL*FIX(0.337) + movq MMWORD [wk(1)], mm6 ; wk(1)=REH*FIX(0.299)+GEH*FIX(0.337) + + movq mm0, mm5 ; mm0=BO + movq mm6, mm4 ; mm6=BE + + movq mm4,mm0 + punpcklwd mm0,mm3 + punpckhwd mm4,mm3 + pmaddwd mm0,[GOTOFF(eax,PW_F0114_F0250)] ; mm0=BOL*FIX(0.114)+GOL*FIX(0.250) + pmaddwd mm4,[GOTOFF(eax,PW_F0114_F0250)] ; mm4=BOH*FIX(0.114)+GOH*FIX(0.250) + + movq mm3,[GOTOFF(eax,PD_ONEHALF)] ; mm3=[PD_ONEHALF] + + paddd mm0, mm1 + paddd mm4, mm7 + paddd mm0,mm3 + paddd mm4,mm3 + psrld mm0,SCALEBITS ; mm0=YOL + psrld mm4,SCALEBITS ; mm4=YOH + packssdw mm0,mm4 ; mm0=YO + + movq mm4,mm6 + punpcklwd mm6,mm2 + punpckhwd mm4,mm2 + pmaddwd mm6,[GOTOFF(eax,PW_F0114_F0250)] ; mm6=BEL*FIX(0.114)+GEL*FIX(0.250) + pmaddwd mm4,[GOTOFF(eax,PW_F0114_F0250)] ; mm4=BEH*FIX(0.114)+GEH*FIX(0.250) + + movq mm2,[GOTOFF(eax,PD_ONEHALF)] ; mm2=[PD_ONEHALF] + + paddd mm6, MMWORD [wk(0)] + paddd mm4, MMWORD [wk(1)] + paddd mm6,mm2 + paddd mm4,mm2 + psrld mm6,SCALEBITS ; mm6=YEL + psrld mm4,SCALEBITS ; mm4=YEH + packssdw mm6,mm4 ; mm6=YE + + psllw mm0,BYTE_BIT + por mm6,mm0 ; mm6=Y + movq MMWORD [edi], mm6 ; Save Y + + sub ecx, byte SIZEOF_MMWORD + add esi, byte RGB_PIXELSIZE*SIZEOF_MMWORD ; inptr + add edi, byte SIZEOF_MMWORD ; outptr0 + cmp ecx, byte SIZEOF_MMWORD + jae near .columnloop + test ecx,ecx + jnz near .column_ld1 + + pop ecx ; col + pop esi + pop edi + poppic eax + + add esi, byte SIZEOF_JSAMPROW ; input_buf + add edi, byte SIZEOF_JSAMPROW + dec eax ; num_rows + jg near .rowloop + + emms ; empty MMX state + +.return: + pop edi + pop esi +; pop edx ; need not be preserved +; pop ecx ; need not be preserved + pop ebx + mov esp,ebp ; esp <- aligned ebp + pop esp ; esp <- original ebp + pop ebp + ret + +; For some reason, the OS X linker does not honor the request to align the +; segment unless we do this. + align 16 diff --git a/media/libjpeg/simd/jcgryss2-64.asm b/media/libjpeg/simd/jcgryss2-64.asm new file mode 100644 index 000000000000..23ae8afb1531 --- /dev/null +++ b/media/libjpeg/simd/jcgryss2-64.asm @@ -0,0 +1,364 @@ +; +; jcgryss2-64.asm - grayscale colorspace conversion (64-bit SSE2) +; +; x86 SIMD extension for IJG JPEG library +; Copyright (C) 1999-2006, MIYASAKA Masaru. +; Copyright (C) 2011, D. R. Commander. +; For conditions of distribution and use, see copyright notice in jsimdext.inc +; +; This file should be assembled with NASM (Netwide Assembler), +; can *not* be assembled with Microsoft's MASM or any compatible +; assembler (including Borland's Turbo Assembler). +; NASM is available from http://nasm.sourceforge.net/ or +; http://sourceforge.net/project/showfiles.php?group_id=6208 +; +; [TAB8] + +%include "jcolsamp.inc" + +; -------------------------------------------------------------------------- +; +; Convert some rows of samples to the output colorspace. +; +; GLOBAL(void) +; jsimd_rgb_gray_convert_sse2 (JDIMENSION img_width, +; JSAMPARRAY input_buf, JSAMPIMAGE output_buf, +; JDIMENSION output_row, int num_rows); +; + +; r10 = JDIMENSION img_width +; r11 = JSAMPARRAY input_buf +; r12 = JSAMPIMAGE output_buf +; r13 = JDIMENSION output_row +; r14 = int num_rows + +%define wk(i) rbp-(WK_NUM-(i))*SIZEOF_XMMWORD ; xmmword wk[WK_NUM] +%define WK_NUM 2 + + align 16 + + global EXTN(jsimd_rgb_gray_convert_sse2) + +EXTN(jsimd_rgb_gray_convert_sse2): + push rbp + mov rax,rsp ; rax = original rbp + sub rsp, byte 4 + and rsp, byte (-SIZEOF_XMMWORD) ; align to 128 bits + mov [rsp],rax + mov rbp,rsp ; rbp = aligned rbp + lea rsp, [wk(0)] + collect_args + push rbx + + mov rcx, r10 + test rcx,rcx + jz near .return + + push rcx + + mov rsi, r12 + mov rcx, r13 + mov rdi, JSAMPARRAY [rsi+0*SIZEOF_JSAMPARRAY] + lea rdi, [rdi+rcx*SIZEOF_JSAMPROW] + + pop rcx + + mov rsi, r11 + mov eax, r14d + test rax,rax + jle near .return +.rowloop: + push rdi + push rsi + push rcx ; col + + mov rsi, JSAMPROW [rsi] ; inptr + mov rdi, JSAMPROW [rdi] ; outptr0 + + cmp rcx, byte SIZEOF_XMMWORD + jae near .columnloop + +%if RGB_PIXELSIZE == 3 ; --------------- + +.column_ld1: + push rax + push rdx + lea rcx,[rcx+rcx*2] ; imul ecx,RGB_PIXELSIZE + test cl, SIZEOF_BYTE + jz short .column_ld2 + sub rcx, byte SIZEOF_BYTE + movzx rax, BYTE [rsi+rcx] +.column_ld2: + test cl, SIZEOF_WORD + jz short .column_ld4 + sub rcx, byte SIZEOF_WORD + movzx rdx, WORD [rsi+rcx] + shl rax, WORD_BIT + or rax,rdx +.column_ld4: + movd xmmA,eax + pop rdx + pop rax + test cl, SIZEOF_DWORD + jz short .column_ld8 + sub rcx, byte SIZEOF_DWORD + movd xmmF, XMM_DWORD [rsi+rcx] + pslldq xmmA, SIZEOF_DWORD + por xmmA,xmmF +.column_ld8: + test cl, SIZEOF_MMWORD + jz short .column_ld16 + sub rcx, byte SIZEOF_MMWORD + movq xmmB, XMM_MMWORD [rsi+rcx] + pslldq xmmA, SIZEOF_MMWORD + por xmmA,xmmB +.column_ld16: + test cl, SIZEOF_XMMWORD + jz short .column_ld32 + movdqa xmmF,xmmA + movdqu xmmA, XMMWORD [rsi+0*SIZEOF_XMMWORD] + mov rcx, SIZEOF_XMMWORD + jmp short .rgb_gray_cnv +.column_ld32: + test cl, 2*SIZEOF_XMMWORD + mov rcx, SIZEOF_XMMWORD + jz short .rgb_gray_cnv + movdqa xmmB,xmmA + movdqu xmmA, XMMWORD [rsi+0*SIZEOF_XMMWORD] + movdqu xmmF, XMMWORD [rsi+1*SIZEOF_XMMWORD] + jmp short .rgb_gray_cnv + +.columnloop: + movdqu xmmA, XMMWORD [rsi+0*SIZEOF_XMMWORD] + movdqu xmmF, XMMWORD [rsi+1*SIZEOF_XMMWORD] + movdqu xmmB, XMMWORD [rsi+2*SIZEOF_XMMWORD] + +.rgb_gray_cnv: + ; xmmA=(00 10 20 01 11 21 02 12 22 03 13 23 04 14 24 05) + ; xmmF=(15 25 06 16 26 07 17 27 08 18 28 09 19 29 0A 1A) + ; xmmB=(2A 0B 1B 2B 0C 1C 2C 0D 1D 2D 0E 1E 2E 0F 1F 2F) + + movdqa xmmG,xmmA + pslldq xmmA,8 ; xmmA=(-- -- -- -- -- -- -- -- 00 10 20 01 11 21 02 12) + psrldq xmmG,8 ; xmmG=(22 03 13 23 04 14 24 05 -- -- -- -- -- -- -- --) + + punpckhbw xmmA,xmmF ; xmmA=(00 08 10 18 20 28 01 09 11 19 21 29 02 0A 12 1A) + pslldq xmmF,8 ; xmmF=(-- -- -- -- -- -- -- -- 15 25 06 16 26 07 17 27) + + punpcklbw xmmG,xmmB ; xmmG=(22 2A 03 0B 13 1B 23 2B 04 0C 14 1C 24 2C 05 0D) + punpckhbw xmmF,xmmB ; xmmF=(15 1D 25 2D 06 0E 16 1E 26 2E 07 0F 17 1F 27 2F) + + movdqa xmmD,xmmA + pslldq xmmA,8 ; xmmA=(-- -- -- -- -- -- -- -- 00 08 10 18 20 28 01 09) + psrldq xmmD,8 ; xmmD=(11 19 21 29 02 0A 12 1A -- -- -- -- -- -- -- --) + + punpckhbw xmmA,xmmG ; xmmA=(00 04 08 0C 10 14 18 1C 20 24 28 2C 01 05 09 0D) + pslldq xmmG,8 ; xmmG=(-- -- -- -- -- -- -- -- 22 2A 03 0B 13 1B 23 2B) + + punpcklbw xmmD,xmmF ; xmmD=(11 15 19 1D 21 25 29 2D 02 06 0A 0E 12 16 1A 1E) + punpckhbw xmmG,xmmF ; xmmG=(22 26 2A 2E 03 07 0B 0F 13 17 1B 1F 23 27 2B 2F) + + movdqa xmmE,xmmA + pslldq xmmA,8 ; xmmA=(-- -- -- -- -- -- -- -- 00 04 08 0C 10 14 18 1C) + psrldq xmmE,8 ; xmmE=(20 24 28 2C 01 05 09 0D -- -- -- -- -- -- -- --) + + punpckhbw xmmA,xmmD ; xmmA=(00 02 04 06 08 0A 0C 0E 10 12 14 16 18 1A 1C 1E) + pslldq xmmD,8 ; xmmD=(-- -- -- -- -- -- -- -- 11 15 19 1D 21 25 29 2D) + + punpcklbw xmmE,xmmG ; xmmE=(20 22 24 26 28 2A 2C 2E 01 03 05 07 09 0B 0D 0F) + punpckhbw xmmD,xmmG ; xmmD=(11 13 15 17 19 1B 1D 1F 21 23 25 27 29 2B 2D 2F) + + pxor xmmH,xmmH + + movdqa xmmC,xmmA + punpcklbw xmmA,xmmH ; xmmA=(00 02 04 06 08 0A 0C 0E) + punpckhbw xmmC,xmmH ; xmmC=(10 12 14 16 18 1A 1C 1E) + + movdqa xmmB,xmmE + punpcklbw xmmE,xmmH ; xmmE=(20 22 24 26 28 2A 2C 2E) + punpckhbw xmmB,xmmH ; xmmB=(01 03 05 07 09 0B 0D 0F) + + movdqa xmmF,xmmD + punpcklbw xmmD,xmmH ; xmmD=(11 13 15 17 19 1B 1D 1F) + punpckhbw xmmF,xmmH ; xmmF=(21 23 25 27 29 2B 2D 2F) + +%else ; RGB_PIXELSIZE == 4 ; ----------- + +.column_ld1: + test cl, SIZEOF_XMMWORD/16 + jz short .column_ld2 + sub rcx, byte SIZEOF_XMMWORD/16 + movd xmmA, XMM_DWORD [rsi+rcx*RGB_PIXELSIZE] +.column_ld2: + test cl, SIZEOF_XMMWORD/8 + jz short .column_ld4 + sub rcx, byte SIZEOF_XMMWORD/8 + movq xmmE, XMM_MMWORD [rsi+rcx*RGB_PIXELSIZE] + pslldq xmmA, SIZEOF_MMWORD + por xmmA,xmmE +.column_ld4: + test cl, SIZEOF_XMMWORD/4 + jz short .column_ld8 + sub rcx, byte SIZEOF_XMMWORD/4 + movdqa xmmE,xmmA + movdqu xmmA, XMMWORD [rsi+rcx*RGB_PIXELSIZE] +.column_ld8: + test cl, SIZEOF_XMMWORD/2 + mov rcx, SIZEOF_XMMWORD + jz short .rgb_gray_cnv + movdqa xmmF,xmmA + movdqa xmmH,xmmE + movdqu xmmA, XMMWORD [rsi+0*SIZEOF_XMMWORD] + movdqu xmmE, XMMWORD [rsi+1*SIZEOF_XMMWORD] + jmp short .rgb_gray_cnv + +.columnloop: + movdqu xmmA, XMMWORD [rsi+0*SIZEOF_XMMWORD] + movdqu xmmE, XMMWORD [rsi+1*SIZEOF_XMMWORD] + movdqu xmmF, XMMWORD [rsi+2*SIZEOF_XMMWORD] + movdqu xmmH, XMMWORD [rsi+3*SIZEOF_XMMWORD] + +.rgb_gray_cnv: + ; xmmA=(00 10 20 30 01 11 21 31 02 12 22 32 03 13 23 33) + ; xmmE=(04 14 24 34 05 15 25 35 06 16 26 36 07 17 27 37) + ; xmmF=(08 18 28 38 09 19 29 39 0A 1A 2A 3A 0B 1B 2B 3B) + ; xmmH=(0C 1C 2C 3C 0D 1D 2D 3D 0E 1E 2E 3E 0F 1F 2F 3F) + + movdqa xmmD,xmmA + punpcklbw xmmA,xmmE ; xmmA=(00 04 10 14 20 24 30 34 01 05 11 15 21 25 31 35) + punpckhbw xmmD,xmmE ; xmmD=(02 06 12 16 22 26 32 36 03 07 13 17 23 27 33 37) + + movdqa xmmC,xmmF + punpcklbw xmmF,xmmH ; xmmF=(08 0C 18 1C 28 2C 38 3C 09 0D 19 1D 29 2D 39 3D) + punpckhbw xmmC,xmmH ; xmmC=(0A 0E 1A 1E 2A 2E 3A 3E 0B 0F 1B 1F 2B 2F 3B 3F) + + movdqa xmmB,xmmA + punpcklwd xmmA,xmmF ; xmmA=(00 04 08 0C 10 14 18 1C 20 24 28 2C 30 34 38 3C) + punpckhwd xmmB,xmmF ; xmmB=(01 05 09 0D 11 15 19 1D 21 25 29 2D 31 35 39 3D) + + movdqa xmmG,xmmD + punpcklwd xmmD,xmmC ; xmmD=(02 06 0A 0E 12 16 1A 1E 22 26 2A 2E 32 36 3A 3E) + punpckhwd xmmG,xmmC ; xmmG=(03 07 0B 0F 13 17 1B 1F 23 27 2B 2F 33 37 3B 3F) + + movdqa xmmE,xmmA + punpcklbw xmmA,xmmD ; xmmA=(00 02 04 06 08 0A 0C 0E 10 12 14 16 18 1A 1C 1E) + punpckhbw xmmE,xmmD ; xmmE=(20 22 24 26 28 2A 2C 2E 30 32 34 36 38 3A 3C 3E) + + movdqa xmmH,xmmB + punpcklbw xmmB,xmmG ; xmmB=(01 03 05 07 09 0B 0D 0F 11 13 15 17 19 1B 1D 1F) + punpckhbw xmmH,xmmG ; xmmH=(21 23 25 27 29 2B 2D 2F 31 33 35 37 39 3B 3D 3F) + + pxor xmmF,xmmF + + movdqa xmmC,xmmA + punpcklbw xmmA,xmmF ; xmmA=(00 02 04 06 08 0A 0C 0E) + punpckhbw xmmC,xmmF ; xmmC=(10 12 14 16 18 1A 1C 1E) + + movdqa xmmD,xmmB + punpcklbw xmmB,xmmF ; xmmB=(01 03 05 07 09 0B 0D 0F) + punpckhbw xmmD,xmmF ; xmmD=(11 13 15 17 19 1B 1D 1F) + + movdqa xmmG,xmmE + punpcklbw xmmE,xmmF ; xmmE=(20 22 24 26 28 2A 2C 2E) + punpckhbw xmmG,xmmF ; xmmG=(30 32 34 36 38 3A 3C 3E) + + punpcklbw xmmF,xmmH + punpckhbw xmmH,xmmH + psrlw xmmF,BYTE_BIT ; xmmF=(21 23 25 27 29 2B 2D 2F) + psrlw xmmH,BYTE_BIT ; xmmH=(31 33 35 37 39 3B 3D 3F) + +%endif ; RGB_PIXELSIZE ; --------------- + + ; xmm0=R(02468ACE)=RE, xmm2=G(02468ACE)=GE, xmm4=B(02468ACE)=BE + ; xmm1=R(13579BDF)=RO, xmm3=G(13579BDF)=GO, xmm5=B(13579BDF)=BO + + ; (Original) + ; Y = 0.29900 * R + 0.58700 * G + 0.11400 * B + ; + ; (This implementation) + ; Y = 0.29900 * R + 0.33700 * G + 0.11400 * B + 0.25000 * G + + movdqa xmm6,xmm1 + punpcklwd xmm1,xmm3 + punpckhwd xmm6,xmm3 + pmaddwd xmm1,[rel PW_F0299_F0337] ; xmm1=ROL*FIX(0.299)+GOL*FIX(0.337) + pmaddwd xmm6,[rel PW_F0299_F0337] ; xmm6=ROH*FIX(0.299)+GOH*FIX(0.337) + + movdqa xmm7, xmm6 ; xmm7=ROH*FIX(0.299)+GOH*FIX(0.337) + + movdqa xmm6,xmm0 + punpcklwd xmm0,xmm2 + punpckhwd xmm6,xmm2 + pmaddwd xmm0,[rel PW_F0299_F0337] ; xmm0=REL*FIX(0.299)+GEL*FIX(0.337) + pmaddwd xmm6,[rel PW_F0299_F0337] ; xmm6=REH*FIX(0.299)+GEH*FIX(0.337) + + movdqa XMMWORD [wk(0)], xmm0 ; wk(0)=REL*FIX(0.299)+GEL*FIX(0.337) + movdqa XMMWORD [wk(1)], xmm6 ; wk(1)=REH*FIX(0.299)+GEH*FIX(0.337) + + movdqa xmm0, xmm5 ; xmm0=BO + movdqa xmm6, xmm4 ; xmm6=BE + + movdqa xmm4,xmm0 + punpcklwd xmm0,xmm3 + punpckhwd xmm4,xmm3 + pmaddwd xmm0,[rel PW_F0114_F0250] ; xmm0=BOL*FIX(0.114)+GOL*FIX(0.250) + pmaddwd xmm4,[rel PW_F0114_F0250] ; xmm4=BOH*FIX(0.114)+GOH*FIX(0.250) + + movdqa xmm3,[rel PD_ONEHALF] ; xmm3=[PD_ONEHALF] + + paddd xmm0, xmm1 + paddd xmm4, xmm7 + paddd xmm0,xmm3 + paddd xmm4,xmm3 + psrld xmm0,SCALEBITS ; xmm0=YOL + psrld xmm4,SCALEBITS ; xmm4=YOH + packssdw xmm0,xmm4 ; xmm0=YO + + movdqa xmm4,xmm6 + punpcklwd xmm6,xmm2 + punpckhwd xmm4,xmm2 + pmaddwd xmm6,[rel PW_F0114_F0250] ; xmm6=BEL*FIX(0.114)+GEL*FIX(0.250) + pmaddwd xmm4,[rel PW_F0114_F0250] ; xmm4=BEH*FIX(0.114)+GEH*FIX(0.250) + + movdqa xmm2,[rel PD_ONEHALF] ; xmm2=[PD_ONEHALF] + + paddd xmm6, XMMWORD [wk(0)] + paddd xmm4, XMMWORD [wk(1)] + paddd xmm6,xmm2 + paddd xmm4,xmm2 + psrld xmm6,SCALEBITS ; xmm6=YEL + psrld xmm4,SCALEBITS ; xmm4=YEH + packssdw xmm6,xmm4 ; xmm6=YE + + psllw xmm0,BYTE_BIT + por xmm6,xmm0 ; xmm6=Y + movdqa XMMWORD [rdi], xmm6 ; Save Y + + sub rcx, byte SIZEOF_XMMWORD + add rsi, byte RGB_PIXELSIZE*SIZEOF_XMMWORD ; inptr + add rdi, byte SIZEOF_XMMWORD ; outptr0 + cmp rcx, byte SIZEOF_XMMWORD + jae near .columnloop + test rcx,rcx + jnz near .column_ld1 + + pop rcx ; col + pop rsi + pop rdi + + add rsi, byte SIZEOF_JSAMPROW ; input_buf + add rdi, byte SIZEOF_JSAMPROW + dec rax ; num_rows + jg near .rowloop + +.return: + pop rbx + uncollect_args + mov rsp,rbp ; rsp <- aligned rbp + pop rsp ; rsp <- original rbp + pop rbp + ret + +; For some reason, the OS X linker does not honor the request to align the +; segment unless we do this. + align 16 diff --git a/media/libjpeg/simd/jcgryss2.asm b/media/libjpeg/simd/jcgryss2.asm new file mode 100644 index 000000000000..c294287939e7 --- /dev/null +++ b/media/libjpeg/simd/jcgryss2.asm @@ -0,0 +1,383 @@ +; +; jcgryss2.asm - grayscale colorspace conversion (SSE2) +; +; x86 SIMD extension for IJG JPEG library +; Copyright (C) 1999-2006, MIYASAKA Masaru. +; Copyright (C) 2011, D. R. Commander. +; For conditions of distribution and use, see copyright notice in jsimdext.inc +; +; This file should be assembled with NASM (Netwide Assembler), +; can *not* be assembled with Microsoft's MASM or any compatible +; assembler (including Borland's Turbo Assembler). +; NASM is available from http://nasm.sourceforge.net/ or +; http://sourceforge.net/project/showfiles.php?group_id=6208 +; +; [TAB8] + +%include "jcolsamp.inc" + +; -------------------------------------------------------------------------- +; +; Convert some rows of samples to the output colorspace. +; +; GLOBAL(void) +; jsimd_rgb_gray_convert_sse2 (JDIMENSION img_width, +; JSAMPARRAY input_buf, JSAMPIMAGE output_buf, +; JDIMENSION output_row, int num_rows); +; + +%define img_width(b) (b)+8 ; JDIMENSION img_width +%define input_buf(b) (b)+12 ; JSAMPARRAY input_buf +%define output_buf(b) (b)+16 ; JSAMPIMAGE output_buf +%define output_row(b) (b)+20 ; JDIMENSION output_row +%define num_rows(b) (b)+24 ; int num_rows + +%define original_ebp ebp+0 +%define wk(i) ebp-(WK_NUM-(i))*SIZEOF_XMMWORD ; xmmword wk[WK_NUM] +%define WK_NUM 2 +%define gotptr wk(0)-SIZEOF_POINTER ; void * gotptr + + align 16 + + global EXTN(jsimd_rgb_gray_convert_sse2) + +EXTN(jsimd_rgb_gray_convert_sse2): + push ebp + mov eax,esp ; eax = original ebp + sub esp, byte 4 + and esp, byte (-SIZEOF_XMMWORD) ; align to 128 bits + mov [esp],eax + mov ebp,esp ; ebp = aligned ebp + lea esp, [wk(0)] + pushpic eax ; make a room for GOT address + push ebx +; push ecx ; need not be preserved +; push edx ; need not be preserved + push esi + push edi + + get_GOT ebx ; get GOT address + movpic POINTER [gotptr], ebx ; save GOT address + + mov ecx, JDIMENSION [img_width(eax)] + test ecx,ecx + jz near .return + + push ecx + + mov esi, JSAMPIMAGE [output_buf(eax)] + mov ecx, JDIMENSION [output_row(eax)] + mov edi, JSAMPARRAY [esi+0*SIZEOF_JSAMPARRAY] + lea edi, [edi+ecx*SIZEOF_JSAMPROW] + + pop ecx + + mov esi, JSAMPARRAY [input_buf(eax)] + mov eax, INT [num_rows(eax)] + test eax,eax + jle near .return + alignx 16,7 +.rowloop: + pushpic eax + push edi + push esi + push ecx ; col + + mov esi, JSAMPROW [esi] ; inptr + mov edi, JSAMPROW [edi] ; outptr0 + movpic eax, POINTER [gotptr] ; load GOT address (eax) + + cmp ecx, byte SIZEOF_XMMWORD + jae near .columnloop + alignx 16,7 + +%if RGB_PIXELSIZE == 3 ; --------------- + +.column_ld1: + push eax + push edx + lea ecx,[ecx+ecx*2] ; imul ecx,RGB_PIXELSIZE + test cl, SIZEOF_BYTE + jz short .column_ld2 + sub ecx, byte SIZEOF_BYTE + movzx eax, BYTE [esi+ecx] +.column_ld2: + test cl, SIZEOF_WORD + jz short .column_ld4 + sub ecx, byte SIZEOF_WORD + movzx edx, WORD [esi+ecx] + shl eax, WORD_BIT + or eax,edx +.column_ld4: + movd xmmA,eax + pop edx + pop eax + test cl, SIZEOF_DWORD + jz short .column_ld8 + sub ecx, byte SIZEOF_DWORD + movd xmmF, XMM_DWORD [esi+ecx] + pslldq xmmA, SIZEOF_DWORD + por xmmA,xmmF +.column_ld8: + test cl, SIZEOF_MMWORD + jz short .column_ld16 + sub ecx, byte SIZEOF_MMWORD + movq xmmB, XMM_MMWORD [esi+ecx] + pslldq xmmA, SIZEOF_MMWORD + por xmmA,xmmB +.column_ld16: + test cl, SIZEOF_XMMWORD + jz short .column_ld32 + movdqa xmmF,xmmA + movdqu xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD] + mov ecx, SIZEOF_XMMWORD + jmp short .rgb_gray_cnv +.column_ld32: + test cl, 2*SIZEOF_XMMWORD + mov ecx, SIZEOF_XMMWORD + jz short .rgb_gray_cnv + movdqa xmmB,xmmA + movdqu xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD] + movdqu xmmF, XMMWORD [esi+1*SIZEOF_XMMWORD] + jmp short .rgb_gray_cnv + alignx 16,7 + +.columnloop: + movdqu xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD] + movdqu xmmF, XMMWORD [esi+1*SIZEOF_XMMWORD] + movdqu xmmB, XMMWORD [esi+2*SIZEOF_XMMWORD] + +.rgb_gray_cnv: + ; xmmA=(00 10 20 01 11 21 02 12 22 03 13 23 04 14 24 05) + ; xmmF=(15 25 06 16 26 07 17 27 08 18 28 09 19 29 0A 1A) + ; xmmB=(2A 0B 1B 2B 0C 1C 2C 0D 1D 2D 0E 1E 2E 0F 1F 2F) + + movdqa xmmG,xmmA + pslldq xmmA,8 ; xmmA=(-- -- -- -- -- -- -- -- 00 10 20 01 11 21 02 12) + psrldq xmmG,8 ; xmmG=(22 03 13 23 04 14 24 05 -- -- -- -- -- -- -- --) + + punpckhbw xmmA,xmmF ; xmmA=(00 08 10 18 20 28 01 09 11 19 21 29 02 0A 12 1A) + pslldq xmmF,8 ; xmmF=(-- -- -- -- -- -- -- -- 15 25 06 16 26 07 17 27) + + punpcklbw xmmG,xmmB ; xmmG=(22 2A 03 0B 13 1B 23 2B 04 0C 14 1C 24 2C 05 0D) + punpckhbw xmmF,xmmB ; xmmF=(15 1D 25 2D 06 0E 16 1E 26 2E 07 0F 17 1F 27 2F) + + movdqa xmmD,xmmA + pslldq xmmA,8 ; xmmA=(-- -- -- -- -- -- -- -- 00 08 10 18 20 28 01 09) + psrldq xmmD,8 ; xmmD=(11 19 21 29 02 0A 12 1A -- -- -- -- -- -- -- --) + + punpckhbw xmmA,xmmG ; xmmA=(00 04 08 0C 10 14 18 1C 20 24 28 2C 01 05 09 0D) + pslldq xmmG,8 ; xmmG=(-- -- -- -- -- -- -- -- 22 2A 03 0B 13 1B 23 2B) + + punpcklbw xmmD,xmmF ; xmmD=(11 15 19 1D 21 25 29 2D 02 06 0A 0E 12 16 1A 1E) + punpckhbw xmmG,xmmF ; xmmG=(22 26 2A 2E 03 07 0B 0F 13 17 1B 1F 23 27 2B 2F) + + movdqa xmmE,xmmA + pslldq xmmA,8 ; xmmA=(-- -- -- -- -- -- -- -- 00 04 08 0C 10 14 18 1C) + psrldq xmmE,8 ; xmmE=(20 24 28 2C 01 05 09 0D -- -- -- -- -- -- -- --) + + punpckhbw xmmA,xmmD ; xmmA=(00 02 04 06 08 0A 0C 0E 10 12 14 16 18 1A 1C 1E) + pslldq xmmD,8 ; xmmD=(-- -- -- -- -- -- -- -- 11 15 19 1D 21 25 29 2D) + + punpcklbw xmmE,xmmG ; xmmE=(20 22 24 26 28 2A 2C 2E 01 03 05 07 09 0B 0D 0F) + punpckhbw xmmD,xmmG ; xmmD=(11 13 15 17 19 1B 1D 1F 21 23 25 27 29 2B 2D 2F) + + pxor xmmH,xmmH + + movdqa xmmC,xmmA + punpcklbw xmmA,xmmH ; xmmA=(00 02 04 06 08 0A 0C 0E) + punpckhbw xmmC,xmmH ; xmmC=(10 12 14 16 18 1A 1C 1E) + + movdqa xmmB,xmmE + punpcklbw xmmE,xmmH ; xmmE=(20 22 24 26 28 2A 2C 2E) + punpckhbw xmmB,xmmH ; xmmB=(01 03 05 07 09 0B 0D 0F) + + movdqa xmmF,xmmD + punpcklbw xmmD,xmmH ; xmmD=(11 13 15 17 19 1B 1D 1F) + punpckhbw xmmF,xmmH ; xmmF=(21 23 25 27 29 2B 2D 2F) + +%else ; RGB_PIXELSIZE == 4 ; ----------- + +.column_ld1: + test cl, SIZEOF_XMMWORD/16 + jz short .column_ld2 + sub ecx, byte SIZEOF_XMMWORD/16 + movd xmmA, XMM_DWORD [esi+ecx*RGB_PIXELSIZE] +.column_ld2: + test cl, SIZEOF_XMMWORD/8 + jz short .column_ld4 + sub ecx, byte SIZEOF_XMMWORD/8 + movq xmmE, XMM_MMWORD [esi+ecx*RGB_PIXELSIZE] + pslldq xmmA, SIZEOF_MMWORD + por xmmA,xmmE +.column_ld4: + test cl, SIZEOF_XMMWORD/4 + jz short .column_ld8 + sub ecx, byte SIZEOF_XMMWORD/4 + movdqa xmmE,xmmA + movdqu xmmA, XMMWORD [esi+ecx*RGB_PIXELSIZE] +.column_ld8: + test cl, SIZEOF_XMMWORD/2 + mov ecx, SIZEOF_XMMWORD + jz short .rgb_gray_cnv + movdqa xmmF,xmmA + movdqa xmmH,xmmE + movdqu xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD] + movdqu xmmE, XMMWORD [esi+1*SIZEOF_XMMWORD] + jmp short .rgb_gray_cnv + alignx 16,7 + +.columnloop: + movdqu xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD] + movdqu xmmE, XMMWORD [esi+1*SIZEOF_XMMWORD] + movdqu xmmF, XMMWORD [esi+2*SIZEOF_XMMWORD] + movdqu xmmH, XMMWORD [esi+3*SIZEOF_XMMWORD] + +.rgb_gray_cnv: + ; xmmA=(00 10 20 30 01 11 21 31 02 12 22 32 03 13 23 33) + ; xmmE=(04 14 24 34 05 15 25 35 06 16 26 36 07 17 27 37) + ; xmmF=(08 18 28 38 09 19 29 39 0A 1A 2A 3A 0B 1B 2B 3B) + ; xmmH=(0C 1C 2C 3C 0D 1D 2D 3D 0E 1E 2E 3E 0F 1F 2F 3F) + + movdqa xmmD,xmmA + punpcklbw xmmA,xmmE ; xmmA=(00 04 10 14 20 24 30 34 01 05 11 15 21 25 31 35) + punpckhbw xmmD,xmmE ; xmmD=(02 06 12 16 22 26 32 36 03 07 13 17 23 27 33 37) + + movdqa xmmC,xmmF + punpcklbw xmmF,xmmH ; xmmF=(08 0C 18 1C 28 2C 38 3C 09 0D 19 1D 29 2D 39 3D) + punpckhbw xmmC,xmmH ; xmmC=(0A 0E 1A 1E 2A 2E 3A 3E 0B 0F 1B 1F 2B 2F 3B 3F) + + movdqa xmmB,xmmA + punpcklwd xmmA,xmmF ; xmmA=(00 04 08 0C 10 14 18 1C 20 24 28 2C 30 34 38 3C) + punpckhwd xmmB,xmmF ; xmmB=(01 05 09 0D 11 15 19 1D 21 25 29 2D 31 35 39 3D) + + movdqa xmmG,xmmD + punpcklwd xmmD,xmmC ; xmmD=(02 06 0A 0E 12 16 1A 1E 22 26 2A 2E 32 36 3A 3E) + punpckhwd xmmG,xmmC ; xmmG=(03 07 0B 0F 13 17 1B 1F 23 27 2B 2F 33 37 3B 3F) + + movdqa xmmE,xmmA + punpcklbw xmmA,xmmD ; xmmA=(00 02 04 06 08 0A 0C 0E 10 12 14 16 18 1A 1C 1E) + punpckhbw xmmE,xmmD ; xmmE=(20 22 24 26 28 2A 2C 2E 30 32 34 36 38 3A 3C 3E) + + movdqa xmmH,xmmB + punpcklbw xmmB,xmmG ; xmmB=(01 03 05 07 09 0B 0D 0F 11 13 15 17 19 1B 1D 1F) + punpckhbw xmmH,xmmG ; xmmH=(21 23 25 27 29 2B 2D 2F 31 33 35 37 39 3B 3D 3F) + + pxor xmmF,xmmF + + movdqa xmmC,xmmA + punpcklbw xmmA,xmmF ; xmmA=(00 02 04 06 08 0A 0C 0E) + punpckhbw xmmC,xmmF ; xmmC=(10 12 14 16 18 1A 1C 1E) + + movdqa xmmD,xmmB + punpcklbw xmmB,xmmF ; xmmB=(01 03 05 07 09 0B 0D 0F) + punpckhbw xmmD,xmmF ; xmmD=(11 13 15 17 19 1B 1D 1F) + + movdqa xmmG,xmmE + punpcklbw xmmE,xmmF ; xmmE=(20 22 24 26 28 2A 2C 2E) + punpckhbw xmmG,xmmF ; xmmG=(30 32 34 36 38 3A 3C 3E) + + punpcklbw xmmF,xmmH + punpckhbw xmmH,xmmH + psrlw xmmF,BYTE_BIT ; xmmF=(21 23 25 27 29 2B 2D 2F) + psrlw xmmH,BYTE_BIT ; xmmH=(31 33 35 37 39 3B 3D 3F) + +%endif ; RGB_PIXELSIZE ; --------------- + + ; xmm0=R(02468ACE)=RE, xmm2=G(02468ACE)=GE, xmm4=B(02468ACE)=BE + ; xmm1=R(13579BDF)=RO, xmm3=G(13579BDF)=GO, xmm5=B(13579BDF)=BO + + ; (Original) + ; Y = 0.29900 * R + 0.58700 * G + 0.11400 * B + ; + ; (This implementation) + ; Y = 0.29900 * R + 0.33700 * G + 0.11400 * B + 0.25000 * G + + movdqa xmm6,xmm1 + punpcklwd xmm1,xmm3 + punpckhwd xmm6,xmm3 + pmaddwd xmm1,[GOTOFF(eax,PW_F0299_F0337)] ; xmm1=ROL*FIX(0.299)+GOL*FIX(0.337) + pmaddwd xmm6,[GOTOFF(eax,PW_F0299_F0337)] ; xmm6=ROH*FIX(0.299)+GOH*FIX(0.337) + + movdqa xmm7, xmm6 ; xmm7=ROH*FIX(0.299)+GOH*FIX(0.337) + + movdqa xmm6,xmm0 + punpcklwd xmm0,xmm2 + punpckhwd xmm6,xmm2 + pmaddwd xmm0,[GOTOFF(eax,PW_F0299_F0337)] ; xmm0=REL*FIX(0.299)+GEL*FIX(0.337) + pmaddwd xmm6,[GOTOFF(eax,PW_F0299_F0337)] ; xmm6=REH*FIX(0.299)+GEH*FIX(0.337) + + movdqa XMMWORD [wk(0)], xmm0 ; wk(0)=REL*FIX(0.299)+GEL*FIX(0.337) + movdqa XMMWORD [wk(1)], xmm6 ; wk(1)=REH*FIX(0.299)+GEH*FIX(0.337) + + movdqa xmm0, xmm5 ; xmm0=BO + movdqa xmm6, xmm4 ; xmm6=BE + + movdqa xmm4,xmm0 + punpcklwd xmm0,xmm3 + punpckhwd xmm4,xmm3 + pmaddwd xmm0,[GOTOFF(eax,PW_F0114_F0250)] ; xmm0=BOL*FIX(0.114)+GOL*FIX(0.250) + pmaddwd xmm4,[GOTOFF(eax,PW_F0114_F0250)] ; xmm4=BOH*FIX(0.114)+GOH*FIX(0.250) + + movdqa xmm3,[GOTOFF(eax,PD_ONEHALF)] ; xmm3=[PD_ONEHALF] + + paddd xmm0, xmm1 + paddd xmm4, xmm7 + paddd xmm0,xmm3 + paddd xmm4,xmm3 + psrld xmm0,SCALEBITS ; xmm0=YOL + psrld xmm4,SCALEBITS ; xmm4=YOH + packssdw xmm0,xmm4 ; xmm0=YO + + movdqa xmm4,xmm6 + punpcklwd xmm6,xmm2 + punpckhwd xmm4,xmm2 + pmaddwd xmm6,[GOTOFF(eax,PW_F0114_F0250)] ; xmm6=BEL*FIX(0.114)+GEL*FIX(0.250) + pmaddwd xmm4,[GOTOFF(eax,PW_F0114_F0250)] ; xmm4=BEH*FIX(0.114)+GEH*FIX(0.250) + + movdqa xmm2,[GOTOFF(eax,PD_ONEHALF)] ; xmm2=[PD_ONEHALF] + + paddd xmm6, XMMWORD [wk(0)] + paddd xmm4, XMMWORD [wk(1)] + paddd xmm6,xmm2 + paddd xmm4,xmm2 + psrld xmm6,SCALEBITS ; xmm6=YEL + psrld xmm4,SCALEBITS ; xmm4=YEH + packssdw xmm6,xmm4 ; xmm6=YE + + psllw xmm0,BYTE_BIT + por xmm6,xmm0 ; xmm6=Y + movdqa XMMWORD [edi], xmm6 ; Save Y + + sub ecx, byte SIZEOF_XMMWORD + add esi, byte RGB_PIXELSIZE*SIZEOF_XMMWORD ; inptr + add edi, byte SIZEOF_XMMWORD ; outptr0 + cmp ecx, byte SIZEOF_XMMWORD + jae near .columnloop + test ecx,ecx + jnz near .column_ld1 + + pop ecx ; col + pop esi + pop edi + poppic eax + + add esi, byte SIZEOF_JSAMPROW ; input_buf + add edi, byte SIZEOF_JSAMPROW + dec eax ; num_rows + jg near .rowloop + +.return: + pop edi + pop esi +; pop edx ; need not be preserved +; pop ecx ; need not be preserved + pop ebx + mov esp,ebp ; esp <- aligned ebp + pop esp ; esp <- original ebp + pop ebp + ret + +; For some reason, the OS X linker does not honor the request to align the +; segment unless we do this. + align 16 diff --git a/media/libjpeg/simd/jdclrmmx.asm b/media/libjpeg/simd/jdclrmmx.asm index 79772e0c2726..1c255e802d40 100644 --- a/media/libjpeg/simd/jdclrmmx.asm +++ b/media/libjpeg/simd/jdclrmmx.asm @@ -19,8 +19,6 @@ %include "jcolsamp.inc" ; -------------------------------------------------------------------------- - SECTION SEG_TEXT - BITS 32 ; ; Convert some rows of samples to the output colorspace. ; diff --git a/media/libjpeg/simd/jdclrss2-64.asm b/media/libjpeg/simd/jdclrss2-64.asm index 4282bd269f33..696a383bddf6 100644 --- a/media/libjpeg/simd/jdclrss2-64.asm +++ b/media/libjpeg/simd/jdclrss2-64.asm @@ -20,8 +20,6 @@ %include "jcolsamp.inc" ; -------------------------------------------------------------------------- - SECTION SEG_TEXT - BITS 64 ; ; Convert some rows of samples to the output colorspace. ; @@ -292,6 +290,41 @@ EXTN(jsimd_ycc_rgb_convert_sse2): movdqa xmmA,xmmD sub rcx, byte SIZEOF_XMMWORD .column_st15: +%ifdef STRICT_MEMORY_ACCESS + ; Store the lower 8 bytes of xmmA to the output when it has enough + ; space. + cmp rcx, byte SIZEOF_MMWORD + jb short .column_st7 + movq MMWORD [rdi], xmmA + add rdi, byte SIZEOF_MMWORD + sub rcx, byte SIZEOF_MMWORD + psrldq xmmA, SIZEOF_MMWORD +.column_st7: + ; Store the lower 4 bytes of xmmA to the output when it has enough + ; space. + cmp rcx, byte SIZEOF_DWORD + jb short .column_st3 + movd DWORD [rdi], xmmA + add rdi, byte SIZEOF_DWORD + sub rcx, byte SIZEOF_DWORD + psrldq xmmA, SIZEOF_DWORD +.column_st3: + ; Store the lower 2 bytes of rax to the output when it has enough + ; space. + movd eax, xmmA + cmp rcx, byte SIZEOF_WORD + jb short .column_st1 + mov WORD [rdi], ax + add rdi, byte SIZEOF_WORD + sub rcx, byte SIZEOF_WORD + shr rax, 16 +.column_st1: + ; Store the lower 1 byte of rax to the output when it has enough + ; space. + test rcx, rcx + jz short .nextrow + mov BYTE [rdi], al +%else mov rax,rcx xor rcx, byte 0x0F shl rcx, 2 @@ -331,6 +364,7 @@ EXTN(jsimd_ycc_rgb_convert_sse2): por xmmE,xmmC .adj0: ; ---------------- maskmovdqu xmmA,xmmE ; movntdqu XMMWORD [rdi], xmmA +%endif ; STRICT_MEMORY_ACCESS ; --------------- %else ; RGB_PIXELSIZE == 4 ; ----------- @@ -415,6 +449,22 @@ EXTN(jsimd_ycc_rgb_convert_sse2): movdqa xmmA,xmmD sub rcx, byte SIZEOF_XMMWORD/4 .column_st15: +%ifdef STRICT_MEMORY_ACCESS + ; Store two pixels (8 bytes) of xmmA to the output when it has enough + ; space. + cmp rcx, byte SIZEOF_XMMWORD/8 + jb short .column_st7 + movq MMWORD [rdi], xmmA + add rdi, byte SIZEOF_XMMWORD/8*4 + sub rcx, byte SIZEOF_XMMWORD/8 + psrldq xmmA, SIZEOF_XMMWORD/8*4 +.column_st7: + ; Store one pixel (4 bytes) of xmmA to the output when it has enough + ; space. + test rcx, rcx + jz short .nextrow + movd DWORD [rdi], xmmA +%else cmp rcx, byte SIZEOF_XMMWORD/16 jb near .nextrow mov rax,rcx @@ -454,6 +504,7 @@ EXTN(jsimd_ycc_rgb_convert_sse2): por xmmE,xmmG .adj0: ; ---------------- maskmovdqu xmmA,xmmE ; movntdqu XMMWORD [rdi], xmmA +%endif ; STRICT_MEMORY_ACCESS ; --------------- %endif ; RGB_PIXELSIZE ; --------------- diff --git a/media/libjpeg/simd/jdclrss2.asm b/media/libjpeg/simd/jdclrss2.asm index 865fa8245d38..7f519e6ff302 100644 --- a/media/libjpeg/simd/jdclrss2.asm +++ b/media/libjpeg/simd/jdclrss2.asm @@ -19,8 +19,6 @@ %include "jcolsamp.inc" ; -------------------------------------------------------------------------- - SECTION SEG_TEXT - BITS 32 ; ; Convert some rows of samples to the output colorspace. ; @@ -304,6 +302,41 @@ EXTN(jsimd_ycc_rgb_convert_sse2): movdqa xmmA,xmmD sub ecx, byte SIZEOF_XMMWORD .column_st15: +%ifdef STRICT_MEMORY_ACCESS + ; Store the lower 8 bytes of xmmA to the output when it has enough + ; space. + cmp ecx, byte SIZEOF_MMWORD + jb short .column_st7 + movq MMWORD [edi], xmmA + add edi, byte SIZEOF_MMWORD + sub ecx, byte SIZEOF_MMWORD + psrldq xmmA, SIZEOF_MMWORD +.column_st7: + ; Store the lower 4 bytes of xmmA to the output when it has enough + ; space. + cmp ecx, byte SIZEOF_DWORD + jb short .column_st3 + movd DWORD [edi], xmmA + add edi, byte SIZEOF_DWORD + sub ecx, byte SIZEOF_DWORD + psrldq xmmA, SIZEOF_DWORD +.column_st3: + ; Store the lower 2 bytes of eax to the output when it has enough + ; space. + movd eax, xmmA + cmp ecx, byte SIZEOF_WORD + jb short .column_st1 + mov WORD [edi], ax + add edi, byte SIZEOF_WORD + sub ecx, byte SIZEOF_WORD + shr eax, 16 +.column_st1: + ; Store the lower 1 byte of eax to the output when it has enough + ; space. + test ecx, ecx + jz short .nextrow + mov BYTE [edi], al +%else mov eax,ecx xor ecx, byte 0x0F shl ecx, 2 @@ -343,6 +376,7 @@ EXTN(jsimd_ycc_rgb_convert_sse2): por xmmE,xmmC .adj0: ; ---------------- maskmovdqu xmmA,xmmE ; movntdqu XMMWORD [edi], xmmA +%endif ; STRICT_MEMORY_ACCESS ; --------------- %else ; RGB_PIXELSIZE == 4 ; ----------- @@ -428,6 +462,22 @@ EXTN(jsimd_ycc_rgb_convert_sse2): movdqa xmmA,xmmD sub ecx, byte SIZEOF_XMMWORD/4 .column_st15: +%ifdef STRICT_MEMORY_ACCESS + ; Store two pixels (8 bytes) of xmmA to the output when it has enough + ; space. + cmp ecx, byte SIZEOF_XMMWORD/8 + jb short .column_st7 + movq MMWORD [edi], xmmA + add edi, byte SIZEOF_XMMWORD/8*4 + sub ecx, byte SIZEOF_XMMWORD/8 + psrldq xmmA, SIZEOF_XMMWORD/8*4 +.column_st7: + ; Store one pixel (4 bytes) of xmmA to the output when it has enough + ; space. + test ecx, ecx + jz short .nextrow + movd DWORD [edi], xmmA +%else cmp ecx, byte SIZEOF_XMMWORD/16 jb short .nextrow mov eax,ecx @@ -467,6 +517,7 @@ EXTN(jsimd_ycc_rgb_convert_sse2): por xmmE,xmmG .adj0: ; ---------------- maskmovdqu xmmA,xmmE ; movntdqu XMMWORD [edi], xmmA +%endif ; STRICT_MEMORY_ACCESS ; --------------- %endif ; RGB_PIXELSIZE ; --------------- diff --git a/media/libjpeg/simd/jdcolmmx.asm b/media/libjpeg/simd/jdcolmmx.asm index 58775e8547dc..5e4e47d425ad 100644 --- a/media/libjpeg/simd/jdcolmmx.asm +++ b/media/libjpeg/simd/jdcolmmx.asm @@ -48,16 +48,19 @@ PD_ONEHALF times 2 dd 1 << (SCALEBITS-1) alignz 16 ; -------------------------------------------------------------------------- + SECTION SEG_TEXT + BITS 32 + %include "jdclrmmx.asm" %undef RGB_RED %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 0 -%define RGB_GREEN 1 -%define RGB_BLUE 2 -%define RGB_PIXELSIZE 3 +%define RGB_RED EXT_RGB_RED +%define RGB_GREEN EXT_RGB_GREEN +%define RGB_BLUE EXT_RGB_BLUE +%define RGB_PIXELSIZE EXT_RGB_PIXELSIZE %define jsimd_ycc_rgb_convert_mmx jsimd_ycc_extrgb_convert_mmx %include "jdclrmmx.asm" @@ -65,10 +68,10 @@ PD_ONEHALF times 2 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 0 -%define RGB_GREEN 1 -%define RGB_BLUE 2 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_RGBX_RED +%define RGB_GREEN EXT_RGBX_GREEN +%define RGB_BLUE EXT_RGBX_BLUE +%define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE %define jsimd_ycc_rgb_convert_mmx jsimd_ycc_extrgbx_convert_mmx %include "jdclrmmx.asm" @@ -76,10 +79,10 @@ PD_ONEHALF times 2 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 2 -%define RGB_GREEN 1 -%define RGB_BLUE 0 -%define RGB_PIXELSIZE 3 +%define RGB_RED EXT_BGR_RED +%define RGB_GREEN EXT_BGR_GREEN +%define RGB_BLUE EXT_BGR_BLUE +%define RGB_PIXELSIZE EXT_BGR_PIXELSIZE %define jsimd_ycc_rgb_convert_mmx jsimd_ycc_extbgr_convert_mmx %include "jdclrmmx.asm" @@ -87,10 +90,10 @@ PD_ONEHALF times 2 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 2 -%define RGB_GREEN 1 -%define RGB_BLUE 0 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_BGRX_RED +%define RGB_GREEN EXT_BGRX_GREEN +%define RGB_BLUE EXT_BGRX_BLUE +%define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE %define jsimd_ycc_rgb_convert_mmx jsimd_ycc_extbgrx_convert_mmx %include "jdclrmmx.asm" @@ -98,10 +101,10 @@ PD_ONEHALF times 2 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 3 -%define RGB_GREEN 2 -%define RGB_BLUE 1 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_XBGR_RED +%define RGB_GREEN EXT_XBGR_GREEN +%define RGB_BLUE EXT_XBGR_BLUE +%define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE %define jsimd_ycc_rgb_convert_mmx jsimd_ycc_extxbgr_convert_mmx %include "jdclrmmx.asm" @@ -109,9 +112,9 @@ PD_ONEHALF times 2 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 1 -%define RGB_GREEN 2 -%define RGB_BLUE 3 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_XRGB_RED +%define RGB_GREEN EXT_XRGB_GREEN +%define RGB_BLUE EXT_XRGB_BLUE +%define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE %define jsimd_ycc_rgb_convert_mmx jsimd_ycc_extxrgb_convert_mmx %include "jdclrmmx.asm" diff --git a/media/libjpeg/simd/jdcolss2-64.asm b/media/libjpeg/simd/jdcolss2-64.asm index 2e97d5930838..01b3dce6933f 100644 --- a/media/libjpeg/simd/jdcolss2-64.asm +++ b/media/libjpeg/simd/jdcolss2-64.asm @@ -48,16 +48,19 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) alignz 16 ; -------------------------------------------------------------------------- + SECTION SEG_TEXT + BITS 64 + %include "jdclrss2-64.asm" %undef RGB_RED %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 0 -%define RGB_GREEN 1 -%define RGB_BLUE 2 -%define RGB_PIXELSIZE 3 +%define RGB_RED EXT_RGB_RED +%define RGB_GREEN EXT_RGB_GREEN +%define RGB_BLUE EXT_RGB_BLUE +%define RGB_PIXELSIZE EXT_RGB_PIXELSIZE %define jsimd_ycc_rgb_convert_sse2 jsimd_ycc_extrgb_convert_sse2 %include "jdclrss2-64.asm" @@ -65,10 +68,10 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 0 -%define RGB_GREEN 1 -%define RGB_BLUE 2 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_RGBX_RED +%define RGB_GREEN EXT_RGBX_GREEN +%define RGB_BLUE EXT_RGBX_BLUE +%define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE %define jsimd_ycc_rgb_convert_sse2 jsimd_ycc_extrgbx_convert_sse2 %include "jdclrss2-64.asm" @@ -76,10 +79,10 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 2 -%define RGB_GREEN 1 -%define RGB_BLUE 0 -%define RGB_PIXELSIZE 3 +%define RGB_RED EXT_BGR_RED +%define RGB_GREEN EXT_BGR_GREEN +%define RGB_BLUE EXT_BGR_BLUE +%define RGB_PIXELSIZE EXT_BGR_PIXELSIZE %define jsimd_ycc_rgb_convert_sse2 jsimd_ycc_extbgr_convert_sse2 %include "jdclrss2-64.asm" @@ -87,10 +90,10 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 2 -%define RGB_GREEN 1 -%define RGB_BLUE 0 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_BGRX_RED +%define RGB_GREEN EXT_BGRX_GREEN +%define RGB_BLUE EXT_BGRX_BLUE +%define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE %define jsimd_ycc_rgb_convert_sse2 jsimd_ycc_extbgrx_convert_sse2 %include "jdclrss2-64.asm" @@ -98,10 +101,10 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 3 -%define RGB_GREEN 2 -%define RGB_BLUE 1 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_XBGR_RED +%define RGB_GREEN EXT_XBGR_GREEN +%define RGB_BLUE EXT_XBGR_BLUE +%define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE %define jsimd_ycc_rgb_convert_sse2 jsimd_ycc_extxbgr_convert_sse2 %include "jdclrss2-64.asm" @@ -109,9 +112,9 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 1 -%define RGB_GREEN 2 -%define RGB_BLUE 3 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_XRGB_RED +%define RGB_GREEN EXT_XRGB_GREEN +%define RGB_BLUE EXT_XRGB_BLUE +%define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE %define jsimd_ycc_rgb_convert_sse2 jsimd_ycc_extxrgb_convert_sse2 %include "jdclrss2-64.asm" diff --git a/media/libjpeg/simd/jdcolss2.asm b/media/libjpeg/simd/jdcolss2.asm index 7ae985d6a9af..1912d92e4ff0 100644 --- a/media/libjpeg/simd/jdcolss2.asm +++ b/media/libjpeg/simd/jdcolss2.asm @@ -48,16 +48,19 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) alignz 16 ; -------------------------------------------------------------------------- + SECTION SEG_TEXT + BITS 32 + %include "jdclrss2.asm" %undef RGB_RED %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 0 -%define RGB_GREEN 1 -%define RGB_BLUE 2 -%define RGB_PIXELSIZE 3 +%define RGB_RED EXT_RGB_RED +%define RGB_GREEN EXT_RGB_GREEN +%define RGB_BLUE EXT_RGB_BLUE +%define RGB_PIXELSIZE EXT_RGB_PIXELSIZE %define jsimd_ycc_rgb_convert_sse2 jsimd_ycc_extrgb_convert_sse2 %include "jdclrss2.asm" @@ -65,10 +68,10 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 0 -%define RGB_GREEN 1 -%define RGB_BLUE 2 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_RGBX_RED +%define RGB_GREEN EXT_RGBX_GREEN +%define RGB_BLUE EXT_RGBX_BLUE +%define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE %define jsimd_ycc_rgb_convert_sse2 jsimd_ycc_extrgbx_convert_sse2 %include "jdclrss2.asm" @@ -76,10 +79,10 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 2 -%define RGB_GREEN 1 -%define RGB_BLUE 0 -%define RGB_PIXELSIZE 3 +%define RGB_RED EXT_BGR_RED +%define RGB_GREEN EXT_BGR_GREEN +%define RGB_BLUE EXT_BGR_BLUE +%define RGB_PIXELSIZE EXT_BGR_PIXELSIZE %define jsimd_ycc_rgb_convert_sse2 jsimd_ycc_extbgr_convert_sse2 %include "jdclrss2.asm" @@ -87,10 +90,10 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 2 -%define RGB_GREEN 1 -%define RGB_BLUE 0 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_BGRX_RED +%define RGB_GREEN EXT_BGRX_GREEN +%define RGB_BLUE EXT_BGRX_BLUE +%define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE %define jsimd_ycc_rgb_convert_sse2 jsimd_ycc_extbgrx_convert_sse2 %include "jdclrss2.asm" @@ -98,10 +101,10 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 3 -%define RGB_GREEN 2 -%define RGB_BLUE 1 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_XBGR_RED +%define RGB_GREEN EXT_XBGR_GREEN +%define RGB_BLUE EXT_XBGR_BLUE +%define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE %define jsimd_ycc_rgb_convert_sse2 jsimd_ycc_extxbgr_convert_sse2 %include "jdclrss2.asm" @@ -109,9 +112,9 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 1 -%define RGB_GREEN 2 -%define RGB_BLUE 3 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_XRGB_RED +%define RGB_GREEN EXT_XRGB_GREEN +%define RGB_BLUE EXT_XRGB_BLUE +%define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE %define jsimd_ycc_rgb_convert_sse2 jsimd_ycc_extxrgb_convert_sse2 %include "jdclrss2.asm" diff --git a/media/libjpeg/simd/jdmermmx.asm b/media/libjpeg/simd/jdmermmx.asm index fd587fbc1247..7b86c7493add 100644 --- a/media/libjpeg/simd/jdmermmx.asm +++ b/media/libjpeg/simd/jdmermmx.asm @@ -48,16 +48,19 @@ PD_ONEHALF times 2 dd 1 << (SCALEBITS-1) alignz 16 ; -------------------------------------------------------------------------- + SECTION SEG_TEXT + BITS 32 + %include "jdmrgmmx.asm" %undef RGB_RED %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 0 -%define RGB_GREEN 1 -%define RGB_BLUE 2 -%define RGB_PIXELSIZE 3 +%define RGB_RED EXT_RGB_RED +%define RGB_GREEN EXT_RGB_GREEN +%define RGB_BLUE EXT_RGB_BLUE +%define RGB_PIXELSIZE EXT_RGB_PIXELSIZE %define jsimd_h2v1_merged_upsample_mmx jsimd_h2v1_extrgb_merged_upsample_mmx %define jsimd_h2v2_merged_upsample_mmx jsimd_h2v2_extrgb_merged_upsample_mmx %include "jdmrgmmx.asm" @@ -66,10 +69,10 @@ PD_ONEHALF times 2 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 0 -%define RGB_GREEN 1 -%define RGB_BLUE 2 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_RGBX_RED +%define RGB_GREEN EXT_RGBX_GREEN +%define RGB_BLUE EXT_RGBX_BLUE +%define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE %define jsimd_h2v1_merged_upsample_mmx jsimd_h2v1_extrgbx_merged_upsample_mmx %define jsimd_h2v2_merged_upsample_mmx jsimd_h2v2_extrgbx_merged_upsample_mmx %include "jdmrgmmx.asm" @@ -78,10 +81,10 @@ PD_ONEHALF times 2 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 2 -%define RGB_GREEN 1 -%define RGB_BLUE 0 -%define RGB_PIXELSIZE 3 +%define RGB_RED EXT_BGR_RED +%define RGB_GREEN EXT_BGR_GREEN +%define RGB_BLUE EXT_BGR_BLUE +%define RGB_PIXELSIZE EXT_BGR_PIXELSIZE %define jsimd_h2v1_merged_upsample_mmx jsimd_h2v1_extbgr_merged_upsample_mmx %define jsimd_h2v2_merged_upsample_mmx jsimd_h2v2_extbgr_merged_upsample_mmx %include "jdmrgmmx.asm" @@ -90,10 +93,10 @@ PD_ONEHALF times 2 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 2 -%define RGB_GREEN 1 -%define RGB_BLUE 0 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_BGRX_RED +%define RGB_GREEN EXT_BGRX_GREEN +%define RGB_BLUE EXT_BGRX_BLUE +%define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE %define jsimd_h2v1_merged_upsample_mmx jsimd_h2v1_extbgrx_merged_upsample_mmx %define jsimd_h2v2_merged_upsample_mmx jsimd_h2v2_extbgrx_merged_upsample_mmx %include "jdmrgmmx.asm" @@ -102,10 +105,10 @@ PD_ONEHALF times 2 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 3 -%define RGB_GREEN 2 -%define RGB_BLUE 1 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_XBGR_RED +%define RGB_GREEN EXT_XBGR_GREEN +%define RGB_BLUE EXT_XBGR_BLUE +%define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE %define jsimd_h2v1_merged_upsample_mmx jsimd_h2v1_extxbgr_merged_upsample_mmx %define jsimd_h2v2_merged_upsample_mmx jsimd_h2v2_extxbgr_merged_upsample_mmx %include "jdmrgmmx.asm" @@ -114,10 +117,10 @@ PD_ONEHALF times 2 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 1 -%define RGB_GREEN 2 -%define RGB_BLUE 3 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_XRGB_RED +%define RGB_GREEN EXT_XRGB_GREEN +%define RGB_BLUE EXT_XRGB_BLUE +%define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE %define jsimd_h2v1_merged_upsample_mmx jsimd_h2v1_extxrgb_merged_upsample_mmx %define jsimd_h2v2_merged_upsample_mmx jsimd_h2v2_extxrgb_merged_upsample_mmx %include "jdmrgmmx.asm" diff --git a/media/libjpeg/simd/jdmerss2-64.asm b/media/libjpeg/simd/jdmerss2-64.asm index 1f0b10faac8d..a184ea69b5ec 100644 --- a/media/libjpeg/simd/jdmerss2-64.asm +++ b/media/libjpeg/simd/jdmerss2-64.asm @@ -48,16 +48,19 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) alignz 16 ; -------------------------------------------------------------------------- + SECTION SEG_TEXT + BITS 64 + %include "jdmrgss2-64.asm" %undef RGB_RED %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 0 -%define RGB_GREEN 1 -%define RGB_BLUE 2 -%define RGB_PIXELSIZE 3 +%define RGB_RED EXT_RGB_RED +%define RGB_GREEN EXT_RGB_GREEN +%define RGB_BLUE EXT_RGB_BLUE +%define RGB_PIXELSIZE EXT_RGB_PIXELSIZE %define jsimd_h2v1_merged_upsample_sse2 jsimd_h2v1_extrgb_merged_upsample_sse2 %define jsimd_h2v2_merged_upsample_sse2 jsimd_h2v2_extrgb_merged_upsample_sse2 %include "jdmrgss2-64.asm" @@ -66,10 +69,10 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 0 -%define RGB_GREEN 1 -%define RGB_BLUE 2 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_RGBX_RED +%define RGB_GREEN EXT_RGBX_GREEN +%define RGB_BLUE EXT_RGBX_BLUE +%define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE %define jsimd_h2v1_merged_upsample_sse2 jsimd_h2v1_extrgbx_merged_upsample_sse2 %define jsimd_h2v2_merged_upsample_sse2 jsimd_h2v2_extrgbx_merged_upsample_sse2 %include "jdmrgss2-64.asm" @@ -78,10 +81,10 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 2 -%define RGB_GREEN 1 -%define RGB_BLUE 0 -%define RGB_PIXELSIZE 3 +%define RGB_RED EXT_BGR_RED +%define RGB_GREEN EXT_BGR_GREEN +%define RGB_BLUE EXT_BGR_BLUE +%define RGB_PIXELSIZE EXT_BGR_PIXELSIZE %define jsimd_h2v1_merged_upsample_sse2 jsimd_h2v1_extbgr_merged_upsample_sse2 %define jsimd_h2v2_merged_upsample_sse2 jsimd_h2v2_extbgr_merged_upsample_sse2 %include "jdmrgss2-64.asm" @@ -90,10 +93,10 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 2 -%define RGB_GREEN 1 -%define RGB_BLUE 0 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_BGRX_RED +%define RGB_GREEN EXT_BGRX_GREEN +%define RGB_BLUE EXT_BGRX_BLUE +%define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE %define jsimd_h2v1_merged_upsample_sse2 jsimd_h2v1_extbgrx_merged_upsample_sse2 %define jsimd_h2v2_merged_upsample_sse2 jsimd_h2v2_extbgrx_merged_upsample_sse2 %include "jdmrgss2-64.asm" @@ -102,10 +105,10 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 3 -%define RGB_GREEN 2 -%define RGB_BLUE 1 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_XBGR_RED +%define RGB_GREEN EXT_XBGR_GREEN +%define RGB_BLUE EXT_XBGR_BLUE +%define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE %define jsimd_h2v1_merged_upsample_sse2 jsimd_h2v1_extxbgr_merged_upsample_sse2 %define jsimd_h2v2_merged_upsample_sse2 jsimd_h2v2_extxbgr_merged_upsample_sse2 %include "jdmrgss2-64.asm" @@ -114,10 +117,10 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 1 -%define RGB_GREEN 2 -%define RGB_BLUE 3 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_XRGB_RED +%define RGB_GREEN EXT_XRGB_GREEN +%define RGB_BLUE EXT_XRGB_BLUE +%define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE %define jsimd_h2v1_merged_upsample_sse2 jsimd_h2v1_extxrgb_merged_upsample_sse2 %define jsimd_h2v2_merged_upsample_sse2 jsimd_h2v2_extxrgb_merged_upsample_sse2 %include "jdmrgss2-64.asm" diff --git a/media/libjpeg/simd/jdmerss2.asm b/media/libjpeg/simd/jdmerss2.asm index 2294e0d3ef31..e536c802ea87 100644 --- a/media/libjpeg/simd/jdmerss2.asm +++ b/media/libjpeg/simd/jdmerss2.asm @@ -48,16 +48,19 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) alignz 16 ; -------------------------------------------------------------------------- + SECTION SEG_TEXT + BITS 32 + %include "jdmrgss2.asm" %undef RGB_RED %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 0 -%define RGB_GREEN 1 -%define RGB_BLUE 2 -%define RGB_PIXELSIZE 3 +%define RGB_RED EXT_RGB_RED +%define RGB_GREEN EXT_RGB_GREEN +%define RGB_BLUE EXT_RGB_BLUE +%define RGB_PIXELSIZE EXT_RGB_PIXELSIZE %define jsimd_h2v1_merged_upsample_sse2 jsimd_h2v1_extrgb_merged_upsample_sse2 %define jsimd_h2v2_merged_upsample_sse2 jsimd_h2v2_extrgb_merged_upsample_sse2 %include "jdmrgss2.asm" @@ -66,10 +69,10 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 0 -%define RGB_GREEN 1 -%define RGB_BLUE 2 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_RGBX_RED +%define RGB_GREEN EXT_RGBX_GREEN +%define RGB_BLUE EXT_RGBX_BLUE +%define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE %define jsimd_h2v1_merged_upsample_sse2 jsimd_h2v1_extrgbx_merged_upsample_sse2 %define jsimd_h2v2_merged_upsample_sse2 jsimd_h2v2_extrgbx_merged_upsample_sse2 %include "jdmrgss2.asm" @@ -78,10 +81,10 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 2 -%define RGB_GREEN 1 -%define RGB_BLUE 0 -%define RGB_PIXELSIZE 3 +%define RGB_RED EXT_BGR_RED +%define RGB_GREEN EXT_BGR_GREEN +%define RGB_BLUE EXT_BGR_BLUE +%define RGB_PIXELSIZE EXT_BGR_PIXELSIZE %define jsimd_h2v1_merged_upsample_sse2 jsimd_h2v1_extbgr_merged_upsample_sse2 %define jsimd_h2v2_merged_upsample_sse2 jsimd_h2v2_extbgr_merged_upsample_sse2 %include "jdmrgss2.asm" @@ -90,10 +93,10 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 2 -%define RGB_GREEN 1 -%define RGB_BLUE 0 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_BGRX_RED +%define RGB_GREEN EXT_BGRX_GREEN +%define RGB_BLUE EXT_BGRX_BLUE +%define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE %define jsimd_h2v1_merged_upsample_sse2 jsimd_h2v1_extbgrx_merged_upsample_sse2 %define jsimd_h2v2_merged_upsample_sse2 jsimd_h2v2_extbgrx_merged_upsample_sse2 %include "jdmrgss2.asm" @@ -102,10 +105,10 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 3 -%define RGB_GREEN 2 -%define RGB_BLUE 1 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_XBGR_RED +%define RGB_GREEN EXT_XBGR_GREEN +%define RGB_BLUE EXT_XBGR_BLUE +%define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE %define jsimd_h2v1_merged_upsample_sse2 jsimd_h2v1_extxbgr_merged_upsample_sse2 %define jsimd_h2v2_merged_upsample_sse2 jsimd_h2v2_extxbgr_merged_upsample_sse2 %include "jdmrgss2.asm" @@ -114,10 +117,10 @@ PD_ONEHALF times 4 dd 1 << (SCALEBITS-1) %undef RGB_GREEN %undef RGB_BLUE %undef RGB_PIXELSIZE -%define RGB_RED 1 -%define RGB_GREEN 2 -%define RGB_BLUE 3 -%define RGB_PIXELSIZE 4 +%define RGB_RED EXT_XRGB_RED +%define RGB_GREEN EXT_XRGB_GREEN +%define RGB_BLUE EXT_XRGB_BLUE +%define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE %define jsimd_h2v1_merged_upsample_sse2 jsimd_h2v1_extxrgb_merged_upsample_sse2 %define jsimd_h2v2_merged_upsample_sse2 jsimd_h2v2_extxrgb_merged_upsample_sse2 %include "jdmrgss2.asm" diff --git a/media/libjpeg/simd/jdmrgmmx.asm b/media/libjpeg/simd/jdmrgmmx.asm index b5777a3e165a..d0800a737d74 100644 --- a/media/libjpeg/simd/jdmrgmmx.asm +++ b/media/libjpeg/simd/jdmrgmmx.asm @@ -19,8 +19,6 @@ %include "jcolsamp.inc" ; -------------------------------------------------------------------------- - SECTION SEG_TEXT - BITS 32 ; ; Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. ; diff --git a/media/libjpeg/simd/jdmrgss2-64.asm b/media/libjpeg/simd/jdmrgss2-64.asm index 121bb82bc55a..a64a6b33fcdf 100644 --- a/media/libjpeg/simd/jdmrgss2-64.asm +++ b/media/libjpeg/simd/jdmrgss2-64.asm @@ -20,8 +20,6 @@ %include "jcolsamp.inc" ; -------------------------------------------------------------------------- - SECTION SEG_TEXT - BITS 64 ; ; Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. ; @@ -296,6 +294,41 @@ EXTN(jsimd_h2v1_merged_upsample_sse2): movdqa xmmA,xmmD sub rcx, byte SIZEOF_XMMWORD .column_st15: +%ifdef STRICT_MEMORY_ACCESS + ; Store the lower 8 bytes of xmmA to the output when it has enough + ; space. + cmp rcx, byte SIZEOF_MMWORD + jb short .column_st7 + movq MMWORD [rdi], xmmA + add rdi, byte SIZEOF_MMWORD + sub rcx, byte SIZEOF_MMWORD + psrldq xmmA, SIZEOF_MMWORD +.column_st7: + ; Store the lower 4 bytes of xmmA to the output when it has enough + ; space. + cmp rcx, byte SIZEOF_DWORD + jb short .column_st3 + movd DWORD [rdi], xmmA + add rdi, byte SIZEOF_DWORD + sub rcx, byte SIZEOF_DWORD + psrldq xmmA, SIZEOF_DWORD +.column_st3: + ; Store the lower 2 bytes of rax to the output when it has enough + ; space. + movd eax, xmmA + cmp rcx, byte SIZEOF_WORD + jb short .column_st1 + mov WORD [rdi], ax + add rdi, byte SIZEOF_WORD + sub rcx, byte SIZEOF_WORD + shr rax, 16 +.column_st1: + ; Store the lower 1 byte of rax to the output when it has enough + ; space. + test rcx, rcx + jz short .endcolumn + mov BYTE [rdi], al +%else mov rax,rcx xor rcx, byte 0x0F shl rcx, 2 @@ -335,6 +368,7 @@ EXTN(jsimd_h2v1_merged_upsample_sse2): por xmmE,xmmC .adj0: ; ---------------- maskmovdqu xmmA,xmmE ; movntdqu XMMWORD [edi], xmmA +%endif ; STRICT_MEMORY_ACCESS ; --------------- %else ; RGB_PIXELSIZE == 4 ; ----------- @@ -422,6 +456,22 @@ EXTN(jsimd_h2v1_merged_upsample_sse2): movdqa xmmA,xmmD sub rcx, byte SIZEOF_XMMWORD/4 .column_st15: +%ifdef STRICT_MEMORY_ACCESS + ; Store two pixels (8 bytes) of xmmA to the output when it has enough + ; space. + cmp rcx, byte SIZEOF_XMMWORD/8 + jb short .column_st7 + movq MMWORD [rdi], xmmA + add rdi, byte SIZEOF_XMMWORD/8*4 + sub rcx, byte SIZEOF_XMMWORD/8 + psrldq xmmA, SIZEOF_XMMWORD/8*4 +.column_st7: + ; Store one pixel (4 bytes) of xmmA to the output when it has enough + ; space. + test rcx, rcx + jz short .endcolumn + movd DWORD [rdi], xmmA +%else cmp rcx, byte SIZEOF_XMMWORD/16 jb near .endcolumn mov rax,rcx @@ -461,6 +511,7 @@ EXTN(jsimd_h2v1_merged_upsample_sse2): por xmmE,xmmG .adj0: ; ---------------- maskmovdqu xmmA,xmmE ; movntdqu XMMWORD [edi], xmmA +%endif ; STRICT_MEMORY_ACCESS ; --------------- %endif ; RGB_PIXELSIZE ; --------------- diff --git a/media/libjpeg/simd/jdmrgss2.asm b/media/libjpeg/simd/jdmrgss2.asm index 99b7eb9f0f34..04089aa3c674 100644 --- a/media/libjpeg/simd/jdmrgss2.asm +++ b/media/libjpeg/simd/jdmrgss2.asm @@ -19,8 +19,6 @@ %include "jcolsamp.inc" ; -------------------------------------------------------------------------- - SECTION SEG_TEXT - BITS 32 ; ; Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. ; @@ -309,6 +307,41 @@ EXTN(jsimd_h2v1_merged_upsample_sse2): movdqa xmmA,xmmD sub ecx, byte SIZEOF_XMMWORD .column_st15: +%ifdef STRICT_MEMORY_ACCESS + ; Store the lower 8 bytes of xmmA to the output when it has enough + ; space. + cmp ecx, byte SIZEOF_MMWORD + jb short .column_st7 + movq MMWORD [edi], xmmA + add edi, byte SIZEOF_MMWORD + sub ecx, byte SIZEOF_MMWORD + psrldq xmmA, SIZEOF_MMWORD +.column_st7: + ; Store the lower 4 bytes of xmmA to the output when it has enough + ; space. + cmp ecx, byte SIZEOF_DWORD + jb short .column_st3 + movd DWORD [edi], xmmA + add edi, byte SIZEOF_DWORD + sub ecx, byte SIZEOF_DWORD + psrldq xmmA, SIZEOF_DWORD +.column_st3: + ; Store the lower 2 bytes of eax to the output when it has enough + ; space. + movd eax, xmmA + cmp ecx, byte SIZEOF_WORD + jb short .column_st1 + mov WORD [edi], ax + add edi, byte SIZEOF_WORD + sub ecx, byte SIZEOF_WORD + shr eax, 16 +.column_st1: + ; Store the lower 1 byte of eax to the output when it has enough + ; space. + test ecx, ecx + jz short .endcolumn + mov BYTE [edi], al +%else mov eax,ecx xor ecx, byte 0x0F shl ecx, 2 @@ -348,6 +381,7 @@ EXTN(jsimd_h2v1_merged_upsample_sse2): por xmmE,xmmC .adj0: ; ---------------- maskmovdqu xmmA,xmmE ; movntdqu XMMWORD [edi], xmmA +%endif ; STRICT_MEMORY_ACCESS ; --------------- %else ; RGB_PIXELSIZE == 4 ; ----------- @@ -436,6 +470,22 @@ EXTN(jsimd_h2v1_merged_upsample_sse2): movdqa xmmA,xmmD sub ecx, byte SIZEOF_XMMWORD/4 .column_st15: +%ifdef STRICT_MEMORY_ACCESS + ; Store two pixels (8 bytes) of xmmA to the output when it has enough + ; space. + cmp ecx, byte SIZEOF_XMMWORD/8 + jb short .column_st7 + movq MMWORD [edi], xmmA + add edi, byte SIZEOF_XMMWORD/2 + sub ecx, byte SIZEOF_XMMWORD/8 + psrldq xmmA, 64 +.column_st7: + ; Store one pixel (4 bytes) of xmmA to the output when it has enough + ; space. + test ecx, ecx + jz short .endcolumn + movd DWORD [edi], xmmA +%else cmp ecx, byte SIZEOF_XMMWORD/16 jb short .endcolumn mov eax,ecx @@ -475,6 +525,7 @@ EXTN(jsimd_h2v1_merged_upsample_sse2): por xmmE,xmmG .adj0: ; ---------------- maskmovdqu xmmA,xmmE ; movntdqu XMMWORD [edi], xmmA +%endif ; STRICT_MEMORY_ACCESS ; --------------- %endif ; RGB_PIXELSIZE ; --------------- diff --git a/media/libjpeg/simd/jsimd.h b/media/libjpeg/simd/jsimd.h index 89ac1b75ebfb..6ee99cc6587b 100644 --- a/media/libjpeg/simd/jsimd.h +++ b/media/libjpeg/simd/jsimd.h @@ -2,6 +2,7 @@ * simd/jsimd.h * * Copyright 2009 Pierre Ossman for Cendio AB + * Copyright 2011 D. R. Commander * * Based on the x86 SIMD extension for IJG JPEG library, * Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -11,11 +12,12 @@ /* Bitmask for supported acceleration methods */ -#define JSIMD_NONE 0x00 -#define JSIMD_MMX 0x01 -#define JSIMD_3DNOW 0x02 -#define JSIMD_SSE 0x04 -#define JSIMD_SSE2 0x08 +#define JSIMD_NONE 0x00 +#define JSIMD_MMX 0x01 +#define JSIMD_3DNOW 0x02 +#define JSIMD_SSE 0x04 +#define JSIMD_SSE2 0x08 +#define JSIMD_ARM_NEON 0x10 /* Short forms of external names for systems with brain-damaged linkers. */ @@ -28,6 +30,13 @@ #define jsimd_extbgrx_ycc_convert_mmx jSEXTBGRXYCCM #define jsimd_extxbgr_ycc_convert_mmx jSEXTXBGRYCCM #define jsimd_extxrgb_ycc_convert_mmx jSEXTXRGBYCCM +#define jsimd_rgb_gray_convert_mmx jSRGBGRYM +#define jsimd_extrgb_gray_convert_mmx jSEXTRGBGRYM +#define jsimd_extrgbx_gray_convert_mmx jSEXTRGBXGRYM +#define jsimd_extbgr_gray_convert_mmx jSEXTBGRGRYM +#define jsimd_extbgrx_gray_convert_mmx jSEXTBGRXGRYM +#define jsimd_extxbgr_gray_convert_mmx jSEXTXBGRGRYM +#define jsimd_extxrgb_gray_convert_mmx jSEXTXRGBGRYM #define jsimd_ycc_rgb_convert_mmx jSYCCRGBM #define jsimd_ycc_extrgb_convert_mmx jSYCCEXTRGBM #define jsimd_ycc_extrgbx_convert_mmx jSYCCEXTRGBXM @@ -43,6 +52,14 @@ #define jsimd_extbgrx_ycc_convert_sse2 jSEXTBGRXYCCS2 #define jsimd_extxbgr_ycc_convert_sse2 jSEXTXBGRYCCS2 #define jsimd_extxrgb_ycc_convert_sse2 jSEXTXRGBYCCS2 +#define jconst_rgb_gray_convert_sse2 jSCRGBGRYS2 +#define jsimd_rgb_gray_convert_sse2 jSRGBGRYS2 +#define jsimd_extrgb_gray_convert_sse2 jSEXTRGBGRYS2 +#define jsimd_extrgbx_gray_convert_sse2 jSEXTRGBXGRYS2 +#define jsimd_extbgr_gray_convert_sse2 jSEXTBGRGRYS2 +#define jsimd_extbgrx_gray_convert_sse2 jSEXTBGRXGRYS2 +#define jsimd_extxbgr_gray_convert_sse2 jSEXTXBGRGRYS2 +#define jsimd_extxrgb_gray_convert_sse2 jSEXTXRGBGRYS2 #define jconst_ycc_rgb_convert_sse2 jSCYCCRGBS2 #define jsimd_ycc_rgb_convert_sse2 jSYCCRGBS2 #define jsimd_ycc_extrgb_convert_sse2 jSYCCEXTRGBS2 @@ -163,6 +180,35 @@ EXTERN(void) jsimd_extxrgb_ycc_convert_mmx JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)); +EXTERN(void) jsimd_rgb_gray_convert_mmx + JPP((JDIMENSION img_width, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +EXTERN(void) jsimd_extrgb_gray_convert_mmx + JPP((JDIMENSION img_width, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +EXTERN(void) jsimd_extrgbx_gray_convert_mmx + JPP((JDIMENSION img_width, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +EXTERN(void) jsimd_extbgr_gray_convert_mmx + JPP((JDIMENSION img_width, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +EXTERN(void) jsimd_extbgrx_gray_convert_mmx + JPP((JDIMENSION img_width, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +EXTERN(void) jsimd_extxbgr_gray_convert_mmx + JPP((JDIMENSION img_width, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +EXTERN(void) jsimd_extxrgb_gray_convert_mmx + JPP((JDIMENSION img_width, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); + EXTERN(void) jsimd_ycc_rgb_convert_mmx JPP((JDIMENSION out_width, JSAMPIMAGE input_buf, JDIMENSION input_row, @@ -222,6 +268,36 @@ EXTERN(void) jsimd_extxrgb_ycc_convert_sse2 JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)); +extern const int jconst_rgb_gray_convert_sse2[]; +EXTERN(void) jsimd_rgb_gray_convert_sse2 + JPP((JDIMENSION img_width, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +EXTERN(void) jsimd_extrgb_gray_convert_sse2 + JPP((JDIMENSION img_width, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +EXTERN(void) jsimd_extrgbx_gray_convert_sse2 + JPP((JDIMENSION img_width, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +EXTERN(void) jsimd_extbgr_gray_convert_sse2 + JPP((JDIMENSION img_width, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +EXTERN(void) jsimd_extbgrx_gray_convert_sse2 + JPP((JDIMENSION img_width, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +EXTERN(void) jsimd_extxbgr_gray_convert_sse2 + JPP((JDIMENSION img_width, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +EXTERN(void) jsimd_extxrgb_gray_convert_sse2 + JPP((JDIMENSION img_width, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); + extern const int jconst_ycc_rgb_convert_sse2[]; EXTERN(void) jsimd_ycc_rgb_convert_sse2 JPP((JDIMENSION out_width, @@ -252,6 +328,64 @@ EXTERN(void) jsimd_ycc_extxrgb_convert_sse2 JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)); +EXTERN(void) jsimd_rgb_ycc_convert_neon + JPP((JDIMENSION img_width, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +EXTERN(void) jsimd_extrgb_ycc_convert_neon + JPP((JDIMENSION img_width, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +EXTERN(void) jsimd_extrgbx_ycc_convert_neon + JPP((JDIMENSION img_width, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +EXTERN(void) jsimd_extbgr_ycc_convert_neon + JPP((JDIMENSION img_width, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +EXTERN(void) jsimd_extbgrx_ycc_convert_neon + JPP((JDIMENSION img_width, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +EXTERN(void) jsimd_extxbgr_ycc_convert_neon + JPP((JDIMENSION img_width, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +EXTERN(void) jsimd_extxrgb_ycc_convert_neon + JPP((JDIMENSION img_width, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); + +EXTERN(void) jsimd_ycc_rgb_convert_neon + JPP((JDIMENSION out_width, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows)); +EXTERN(void) jsimd_ycc_extrgb_convert_neon + JPP((JDIMENSION out_width, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows)); +EXTERN(void) jsimd_ycc_extrgbx_convert_neon + JPP((JDIMENSION out_width, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows)); +EXTERN(void) jsimd_ycc_extbgr_convert_neon + JPP((JDIMENSION out_width, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows)); +EXTERN(void) jsimd_ycc_extbgrx_convert_neon + JPP((JDIMENSION out_width, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows)); +EXTERN(void) jsimd_ycc_extxbgr_convert_neon + JPP((JDIMENSION out_width, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows)); +EXTERN(void) jsimd_ycc_extxrgb_convert_neon + JPP((JDIMENSION out_width, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows)); + /* SIMD Downsample */ EXTERN(void) jsimd_h2v2_downsample_mmx JPP((JDIMENSION image_width, int max_v_samp_factor, @@ -397,6 +531,10 @@ EXTERN(void) jsimd_convsamp_sse2 JPP((JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM * workspace)); +EXTERN(void) jsimd_convsamp_neon JPP((JSAMPARRAY sample_data, + JDIMENSION start_col, + DCTELEM * workspace)); + EXTERN(void) jsimd_convsamp_float_3dnow JPP((JSAMPARRAY sample_data, JDIMENSION start_col, FAST_FLOAT * workspace)); @@ -418,6 +556,8 @@ EXTERN(void) jsimd_fdct_islow_sse2 JPP((DCTELEM * data)); extern const int jconst_fdct_islow_sse2[]; EXTERN(void) jsimd_fdct_ifast_sse2 JPP((DCTELEM * data)); +EXTERN(void) jsimd_fdct_ifast_neon JPP((DCTELEM * data)); + EXTERN(void) jsimd_fdct_float_3dnow JPP((FAST_FLOAT * data)); extern const int jconst_fdct_float_sse[]; @@ -432,6 +572,10 @@ EXTERN(void) jsimd_quantize_sse2 JPP((JCOEFPTR coef_block, DCTELEM * divisors, DCTELEM * workspace)); +EXTERN(void) jsimd_quantize_neon JPP((JCOEFPTR coef_block, + DCTELEM * divisors, + DCTELEM * workspace)); + EXTERN(void) jsimd_quantize_float_3dnow JPP((JCOEFPTR coef_block, FAST_FLOAT * divisors, FAST_FLOAT * workspace)); @@ -464,6 +608,15 @@ EXTERN(void) jsimd_idct_4x4_sse2 JPP((void * dct_table, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jsimd_idct_2x2_neon JPP((void * dct_table, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, + JDIMENSION output_col)); +EXTERN(void) jsimd_idct_4x4_neon JPP((void * dct_table, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, + JDIMENSION output_col)); + /* SIMD Inverse DCT */ EXTERN(void) jsimd_idct_islow_mmx JPP((void * dct_table, JCOEFPTR coef_block, @@ -485,6 +638,15 @@ EXTERN(void) jsimd_idct_ifast_sse2 JPP((void * dct_table, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jsimd_idct_islow_neon JPP((void * dct_table, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, + JDIMENSION output_col)); +EXTERN(void) jsimd_idct_ifast_neon JPP((void * dct_table, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, + JDIMENSION output_col)); + EXTERN(void) jsimd_idct_float_3dnow JPP((void * dct_table, JCOEFPTR coef_block, JSAMPARRAY output_buf, diff --git a/media/libjpeg/simd/jsimd_arm.c b/media/libjpeg/simd/jsimd_arm.c new file mode 100644 index 000000000000..af0c2c8afb78 --- /dev/null +++ b/media/libjpeg/simd/jsimd_arm.c @@ -0,0 +1,670 @@ +/* + * jsimd_arm.c + * + * Copyright 2009 Pierre Ossman for Cendio AB + * Copyright 2009-2011 D. R. Commander + * + * Based on the x86 SIMD extension for IJG JPEG library, + * Copyright (C) 1999-2006, MIYASAKA Masaru. + * For conditions of distribution and use, see copyright notice in jsimdext.inc + * + * This file contains the interface between the "normal" portions + * of the library and the SIMD implementations when running on + * ARM architecture. + * + * Based on the stubs from 'jsimd_none.c' + */ + +#define JPEG_INTERNALS +#include "../jinclude.h" +#include "../jpeglib.h" +#include "../jsimd.h" +#include "../jdct.h" +#include "../jsimddct.h" +#include "jsimd.h" + +#include +#include +#include + +static unsigned int simd_support = ~0; + +#if defined(__linux__) || defined(ANDROID) || defined(__ANDROID__) + +#define SOMEWHAT_SANE_PROC_CPUINFO_SIZE_LIMIT (1024 * 1024) + +LOCAL(int) +check_feature (char *buffer, char *feature) +{ + char *p; + if (*feature == 0) + return 0; + if (strncmp(buffer, "Features", 8) != 0) + return 0; + buffer += 8; + while (isspace(*buffer)) + buffer++; + + /* Check if 'feature' is present in the buffer as a separate word */ + while ((p = strstr(buffer, feature))) { + if (p > buffer && !isspace(*(p - 1))) { + buffer++; + continue; + } + p += strlen(feature); + if (*p != 0 && !isspace(*p)) { + buffer++; + continue; + } + return 1; + } + return 0; +} + +LOCAL(int) +parse_proc_cpuinfo (int bufsize) +{ + char *buffer = (char *)malloc(bufsize); + FILE *fd; + simd_support = 0; + + if (!buffer) + return 0; + + fd = fopen("/proc/cpuinfo", "r"); + if (fd) { + while (fgets(buffer, bufsize, fd)) { + if (!strchr(buffer, '\n') && !feof(fd)) { + /* "impossible" happened - insufficient size of the buffer! */ + fclose(fd); + free(buffer); + return 0; + } + if (check_feature(buffer, "neon")) + simd_support |= JSIMD_ARM_NEON; + } + fclose(fd); + } + free(buffer); + return 1; +} + +#endif + +/* + * Check what SIMD accelerations are supported. + * + * FIXME: This code is racy under a multi-threaded environment. + */ +LOCAL(void) +init_simd (void) +{ + char *env = NULL; +#if !defined(__ARM_NEON__) && defined(__linux__) || defined(ANDROID) || defined(__ANDROID__) + int bufsize = 1024; /* an initial guess for the line buffer size limit */ +#endif + + if (simd_support != ~0U) + return; + + simd_support = 0; + +#if defined(__ARM_NEON__) + simd_support |= JSIMD_ARM_NEON; +#elif defined(__linux__) || defined(ANDROID) || defined(__ANDROID__) + /* We still have a chance to use NEON regardless of globally used + * -mcpu/-mfpu options passed to gcc by performing runtime detection via + * /proc/cpuinfo parsing on linux/android */ + while (!parse_proc_cpuinfo(bufsize)) { + bufsize *= 2; + if (bufsize > SOMEWHAT_SANE_PROC_CPUINFO_SIZE_LIMIT) + break; + } +#endif + + /* Force different settings through environment variables */ + env = getenv("JSIMD_FORCE_ARM_NEON"); + if ((env != NULL) && (strcmp(env, "1") == 0)) + simd_support &= JSIMD_ARM_NEON; + env = getenv("JSIMD_FORCE_NO_SIMD"); + if ((env != NULL) && (strcmp(env, "1") == 0)) + simd_support = 0; +} + +GLOBAL(int) +jsimd_can_rgb_ycc (void) +{ + init_simd(); + + /* The code is optimised for these values only */ + if (BITS_IN_JSAMPLE != 8) + return 0; + if (sizeof(JDIMENSION) != 4) + return 0; + if ((RGB_PIXELSIZE != 3) && (RGB_PIXELSIZE != 4)) + return 0; + + if (simd_support & JSIMD_ARM_NEON) + return 1; + + return 0; +} + +GLOBAL(int) +jsimd_can_rgb_gray (void) +{ + init_simd(); + + return 0; +} + +GLOBAL(int) +jsimd_can_ycc_rgb (void) +{ + init_simd(); + + /* The code is optimised for these values only */ + if (BITS_IN_JSAMPLE != 8) + return 0; + if (sizeof(JDIMENSION) != 4) + return 0; + if ((RGB_PIXELSIZE != 3) && (RGB_PIXELSIZE != 4)) + return 0; + if (simd_support & JSIMD_ARM_NEON) + return 1; + + return 0; +} + +GLOBAL(void) +jsimd_rgb_ycc_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + void (*neonfct)(JDIMENSION, JSAMPARRAY, JSAMPIMAGE, JDIMENSION, int); + + switch(cinfo->in_color_space) + { + case JCS_EXT_RGB: + neonfct=jsimd_extrgb_ycc_convert_neon; + break; + case JCS_EXT_RGBX: + case JCS_EXT_RGBA: + neonfct=jsimd_extrgbx_ycc_convert_neon; + break; + case JCS_EXT_BGR: + neonfct=jsimd_extbgr_ycc_convert_neon; + break; + case JCS_EXT_BGRX: + case JCS_EXT_BGRA: + neonfct=jsimd_extbgrx_ycc_convert_neon; + break; + case JCS_EXT_XBGR: + case JCS_EXT_ABGR: + neonfct=jsimd_extxbgr_ycc_convert_neon; + break; + case JCS_EXT_XRGB: + case JCS_EXT_ARGB: + neonfct=jsimd_extxrgb_ycc_convert_neon; + break; + default: + neonfct=jsimd_extrgb_ycc_convert_neon; + break; + } + + if (simd_support & JSIMD_ARM_NEON) + neonfct(cinfo->image_width, input_buf, + output_buf, output_row, num_rows); +} + +GLOBAL(void) +jsimd_rgb_gray_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ +} + +GLOBAL(void) +jsimd_ycc_rgb_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + void (*neonfct)(JDIMENSION, JSAMPIMAGE, JDIMENSION, JSAMPARRAY, int); + + switch(cinfo->out_color_space) + { + case JCS_EXT_RGB: + neonfct=jsimd_ycc_extrgb_convert_neon; + break; + case JCS_EXT_RGBX: + case JCS_EXT_RGBA: + neonfct=jsimd_ycc_extrgbx_convert_neon; + break; + case JCS_EXT_BGR: + neonfct=jsimd_ycc_extbgr_convert_neon; + break; + case JCS_EXT_BGRX: + case JCS_EXT_BGRA: + neonfct=jsimd_ycc_extbgrx_convert_neon; + break; + case JCS_EXT_XBGR: + case JCS_EXT_ABGR: + neonfct=jsimd_ycc_extxbgr_convert_neon; + break; + case JCS_EXT_XRGB: + case JCS_EXT_ARGB: + neonfct=jsimd_ycc_extxrgb_convert_neon; + break; + default: + neonfct=jsimd_ycc_extrgb_convert_neon; + break; + } + + if (simd_support & JSIMD_ARM_NEON) + neonfct(cinfo->output_width, input_buf, + input_row, output_buf, num_rows); +} + +GLOBAL(int) +jsimd_can_h2v2_downsample (void) +{ + init_simd(); + + return 0; +} + +GLOBAL(int) +jsimd_can_h2v1_downsample (void) +{ + init_simd(); + + return 0; +} + +GLOBAL(void) +jsimd_h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ +} + +GLOBAL(void) +jsimd_h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ +} + +GLOBAL(int) +jsimd_can_h2v2_upsample (void) +{ + init_simd(); + + return 0; +} + +GLOBAL(int) +jsimd_can_h2v1_upsample (void) +{ + init_simd(); + + return 0; +} + +GLOBAL(void) +jsimd_h2v2_upsample (j_decompress_ptr cinfo, + jpeg_component_info * compptr, + JSAMPARRAY input_data, + JSAMPARRAY * output_data_ptr) +{ +} + +GLOBAL(void) +jsimd_h2v1_upsample (j_decompress_ptr cinfo, + jpeg_component_info * compptr, + JSAMPARRAY input_data, + JSAMPARRAY * output_data_ptr) +{ +} + +GLOBAL(int) +jsimd_can_h2v2_fancy_upsample (void) +{ + init_simd(); + + return 0; +} + +GLOBAL(int) +jsimd_can_h2v1_fancy_upsample (void) +{ + init_simd(); + + return 0; +} + +GLOBAL(void) +jsimd_h2v2_fancy_upsample (j_decompress_ptr cinfo, + jpeg_component_info * compptr, + JSAMPARRAY input_data, + JSAMPARRAY * output_data_ptr) +{ +} + +GLOBAL(void) +jsimd_h2v1_fancy_upsample (j_decompress_ptr cinfo, + jpeg_component_info * compptr, + JSAMPARRAY input_data, + JSAMPARRAY * output_data_ptr) +{ +} + +GLOBAL(int) +jsimd_can_h2v2_merged_upsample (void) +{ + init_simd(); + + return 0; +} + +GLOBAL(int) +jsimd_can_h2v1_merged_upsample (void) +{ + init_simd(); + + return 0; +} + +GLOBAL(void) +jsimd_h2v2_merged_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) +{ +} + +GLOBAL(void) +jsimd_h2v1_merged_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) +{ +} + +GLOBAL(int) +jsimd_can_convsamp (void) +{ + init_simd(); + + /* The code is optimised for these values only */ + if (DCTSIZE != 8) + return 0; + if (BITS_IN_JSAMPLE != 8) + return 0; + if (sizeof(JDIMENSION) != 4) + return 0; + if (sizeof(DCTELEM) != 2) + return 0; + + if (simd_support & JSIMD_ARM_NEON) + return 1; + + return 0; +} + +GLOBAL(int) +jsimd_can_convsamp_float (void) +{ + init_simd(); + + return 0; +} + +GLOBAL(void) +jsimd_convsamp (JSAMPARRAY sample_data, JDIMENSION start_col, + DCTELEM * workspace) +{ + if (simd_support & JSIMD_ARM_NEON) + jsimd_convsamp_neon(sample_data, start_col, workspace); +} + +GLOBAL(void) +jsimd_convsamp_float (JSAMPARRAY sample_data, JDIMENSION start_col, + FAST_FLOAT * workspace) +{ +} + +GLOBAL(int) +jsimd_can_fdct_islow (void) +{ + init_simd(); + + return 0; +} + +GLOBAL(int) +jsimd_can_fdct_ifast (void) +{ + init_simd(); + + /* The code is optimised for these values only */ + if (DCTSIZE != 8) + return 0; + if (sizeof(DCTELEM) != 2) + return 0; + + if (simd_support & JSIMD_ARM_NEON) + return 1; + + return 0; +} + +GLOBAL(int) +jsimd_can_fdct_float (void) +{ + init_simd(); + + return 0; +} + +GLOBAL(void) +jsimd_fdct_islow (DCTELEM * data) +{ +} + +GLOBAL(void) +jsimd_fdct_ifast (DCTELEM * data) +{ + if (simd_support & JSIMD_ARM_NEON) + jsimd_fdct_ifast_neon(data); +} + +GLOBAL(void) +jsimd_fdct_float (FAST_FLOAT * data) +{ +} + +GLOBAL(int) +jsimd_can_quantize (void) +{ + init_simd(); + + /* The code is optimised for these values only */ + if (DCTSIZE != 8) + return 0; + if (sizeof(JCOEF) != 2) + return 0; + if (sizeof(DCTELEM) != 2) + return 0; + + if (simd_support & JSIMD_ARM_NEON) + return 1; + + return 0; +} + +GLOBAL(int) +jsimd_can_quantize_float (void) +{ + init_simd(); + + return 0; +} + +GLOBAL(void) +jsimd_quantize (JCOEFPTR coef_block, DCTELEM * divisors, + DCTELEM * workspace) +{ + if (simd_support & JSIMD_ARM_NEON) + jsimd_quantize_neon(coef_block, divisors, workspace); +} + +GLOBAL(void) +jsimd_quantize_float (JCOEFPTR coef_block, FAST_FLOAT * divisors, + FAST_FLOAT * workspace) +{ +} + +GLOBAL(int) +jsimd_can_idct_2x2 (void) +{ + init_simd(); + + /* The code is optimised for these values only */ + if (DCTSIZE != 8) + return 0; + if (sizeof(JCOEF) != 2) + return 0; + if (BITS_IN_JSAMPLE != 8) + return 0; + if (sizeof(JDIMENSION) != 4) + return 0; + if (sizeof(ISLOW_MULT_TYPE) != 2) + return 0; + + if ((simd_support & JSIMD_ARM_NEON)) + return 1; + + return 0; +} + +GLOBAL(int) +jsimd_can_idct_4x4 (void) +{ + init_simd(); + + /* The code is optimised for these values only */ + if (DCTSIZE != 8) + return 0; + if (sizeof(JCOEF) != 2) + return 0; + if (BITS_IN_JSAMPLE != 8) + return 0; + if (sizeof(JDIMENSION) != 4) + return 0; + if (sizeof(ISLOW_MULT_TYPE) != 2) + return 0; + + if ((simd_support & JSIMD_ARM_NEON)) + return 1; + + return 0; +} + +GLOBAL(void) +jsimd_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, + JDIMENSION output_col) +{ + if ((simd_support & JSIMD_ARM_NEON)) + jsimd_idct_2x2_neon(compptr->dct_table, coef_block, output_buf, output_col); +} + +GLOBAL(void) +jsimd_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, + JDIMENSION output_col) +{ + if ((simd_support & JSIMD_ARM_NEON)) + jsimd_idct_4x4_neon(compptr->dct_table, coef_block, output_buf, output_col); +} + +GLOBAL(int) +jsimd_can_idct_islow (void) +{ + init_simd(); + + /* The code is optimised for these values only */ + if (DCTSIZE != 8) + return 0; + if (sizeof(JCOEF) != 2) + return 0; + if (BITS_IN_JSAMPLE != 8) + return 0; + if (sizeof(JDIMENSION) != 4) + return 0; + if (sizeof(ISLOW_MULT_TYPE) != 2) + return 0; + + if (simd_support & JSIMD_ARM_NEON) + return 1; + + return 0; +} + +GLOBAL(int) +jsimd_can_idct_ifast (void) +{ + init_simd(); + + /* The code is optimised for these values only */ + if (DCTSIZE != 8) + return 0; + if (sizeof(JCOEF) != 2) + return 0; + if (BITS_IN_JSAMPLE != 8) + return 0; + if (sizeof(JDIMENSION) != 4) + return 0; + if (sizeof(IFAST_MULT_TYPE) != 2) + return 0; + if (IFAST_SCALE_BITS != 2) + return 0; + + if ((simd_support & JSIMD_ARM_NEON)) + return 1; + + return 0; +} + +GLOBAL(int) +jsimd_can_idct_float (void) +{ + init_simd(); + + return 0; +} + +GLOBAL(void) +jsimd_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, + JDIMENSION output_col) +{ + if ((simd_support & JSIMD_ARM_NEON)) + jsimd_idct_islow_neon(compptr->dct_table, coef_block, output_buf, output_col); +} + +GLOBAL(void) +jsimd_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, + JDIMENSION output_col) +{ + if ((simd_support & JSIMD_ARM_NEON)) + jsimd_idct_ifast_neon(compptr->dct_table, coef_block, output_buf, output_col); +} + +GLOBAL(void) +jsimd_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, + JDIMENSION output_col) +{ +} + diff --git a/media/libjpeg/simd/jsimd_arm_neon.S b/media/libjpeg/simd/jsimd_arm_neon.S new file mode 100644 index 000000000000..b2f9c2ae8299 --- /dev/null +++ b/media/libjpeg/simd/jsimd_arm_neon.S @@ -0,0 +1,2159 @@ +/* + * ARM NEON optimizations for libjpeg-turbo + * + * Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). + * All rights reserved. + * Author: Siarhei Siamashka + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits /* mark stack as non-executable */ +#endif + +.text +.fpu neon +.arch armv7a +.object_arch armv4 +.arm + + +#define RESPECT_STRICT_ALIGNMENT 1 + +/*****************************************************************************/ + +/* Supplementary macro for setting function attributes */ +.macro asm_function fname +#ifdef __APPLE__ + .func _\fname + .globl _\fname +_\fname: +#else + .func \fname + .global \fname +#ifdef __ELF__ + .hidden \fname + .type \fname, %function +#endif +\fname: +#endif +.endm + +/* Transpose a block of 4x4 coefficients in four 64-bit registers */ +.macro transpose_4x4 x0, x1, x2, x3 + vtrn.16 \x0, \x1 + vtrn.16 \x2, \x3 + vtrn.32 \x0, \x2 + vtrn.32 \x1, \x3 +.endm + +#define CENTERJSAMPLE 128 + +/*****************************************************************************/ + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + * + * GLOBAL(void) + * jsimd_idct_islow_neon (void * dct_table, JCOEFPTR coef_block, + * JSAMPARRAY output_buf, JDIMENSION output_col) + */ + +#define FIX_0_298631336 (2446) +#define FIX_0_390180644 (3196) +#define FIX_0_541196100 (4433) +#define FIX_0_765366865 (6270) +#define FIX_0_899976223 (7373) +#define FIX_1_175875602 (9633) +#define FIX_1_501321110 (12299) +#define FIX_1_847759065 (15137) +#define FIX_1_961570560 (16069) +#define FIX_2_053119869 (16819) +#define FIX_2_562915447 (20995) +#define FIX_3_072711026 (25172) + +#define FIX_1_175875602_MINUS_1_961570560 (FIX_1_175875602 - FIX_1_961570560) +#define FIX_1_175875602_MINUS_0_390180644 (FIX_1_175875602 - FIX_0_390180644) +#define FIX_0_541196100_MINUS_1_847759065 (FIX_0_541196100 - FIX_1_847759065) +#define FIX_3_072711026_MINUS_2_562915447 (FIX_3_072711026 - FIX_2_562915447) +#define FIX_0_298631336_MINUS_0_899976223 (FIX_0_298631336 - FIX_0_899976223) +#define FIX_1_501321110_MINUS_0_899976223 (FIX_1_501321110 - FIX_0_899976223) +#define FIX_2_053119869_MINUS_2_562915447 (FIX_2_053119869 - FIX_2_562915447) +#define FIX_0_541196100_PLUS_0_765366865 (FIX_0_541196100 + FIX_0_765366865) + +/* + * Reference SIMD-friendly 1-D ISLOW iDCT C implementation. + * Uses some ideas from the comments in 'simd/jiss2int-64.asm' + */ +#define REF_1D_IDCT(xrow0, xrow1, xrow2, xrow3, xrow4, xrow5, xrow6, xrow7) \ +{ \ + DCTELEM row0, row1, row2, row3, row4, row5, row6, row7; \ + INT32 q1, q2, q3, q4, q5, q6, q7; \ + INT32 tmp11_plus_tmp2, tmp11_minus_tmp2; \ + \ + /* 1-D iDCT input data */ \ + row0 = xrow0; \ + row1 = xrow1; \ + row2 = xrow2; \ + row3 = xrow3; \ + row4 = xrow4; \ + row5 = xrow5; \ + row6 = xrow6; \ + row7 = xrow7; \ + \ + q5 = row7 + row3; \ + q4 = row5 + row1; \ + q6 = MULTIPLY(q5, FIX_1_175875602_MINUS_1_961570560) + \ + MULTIPLY(q4, FIX_1_175875602); \ + q7 = MULTIPLY(q5, FIX_1_175875602) + \ + MULTIPLY(q4, FIX_1_175875602_MINUS_0_390180644); \ + q2 = MULTIPLY(row2, FIX_0_541196100) + \ + MULTIPLY(row6, FIX_0_541196100_MINUS_1_847759065); \ + q4 = q6; \ + q3 = ((INT32) row0 - (INT32) row4) << 13; \ + q6 += MULTIPLY(row5, -FIX_2_562915447) + \ + MULTIPLY(row3, FIX_3_072711026_MINUS_2_562915447); \ + /* now we can use q1 (reloadable constants have been used up) */ \ + q1 = q3 + q2; \ + q4 += MULTIPLY(row7, FIX_0_298631336_MINUS_0_899976223) + \ + MULTIPLY(row1, -FIX_0_899976223); \ + q5 = q7; \ + q1 = q1 + q6; \ + q7 += MULTIPLY(row7, -FIX_0_899976223) + \ + MULTIPLY(row1, FIX_1_501321110_MINUS_0_899976223); \ + \ + /* (tmp11 + tmp2) has been calculated (out_row1 before descale) */ \ + tmp11_plus_tmp2 = q1; \ + row1 = 0; \ + \ + q1 = q1 - q6; \ + q5 += MULTIPLY(row5, FIX_2_053119869_MINUS_2_562915447) + \ + MULTIPLY(row3, -FIX_2_562915447); \ + q1 = q1 - q6; \ + q6 = MULTIPLY(row2, FIX_0_541196100_PLUS_0_765366865) + \ + MULTIPLY(row6, FIX_0_541196100); \ + q3 = q3 - q2; \ + \ + /* (tmp11 - tmp2) has been calculated (out_row6 before descale) */ \ + tmp11_minus_tmp2 = q1; \ + \ + q1 = ((INT32) row0 + (INT32) row4) << 13; \ + q2 = q1 + q6; \ + q1 = q1 - q6; \ + \ + /* pick up the results */ \ + tmp0 = q4; \ + tmp1 = q5; \ + tmp2 = (tmp11_plus_tmp2 - tmp11_minus_tmp2) / 2; \ + tmp3 = q7; \ + tmp10 = q2; \ + tmp11 = (tmp11_plus_tmp2 + tmp11_minus_tmp2) / 2; \ + tmp12 = q3; \ + tmp13 = q1; \ +} + +#define XFIX_0_899976223 d0[0] +#define XFIX_0_541196100 d0[1] +#define XFIX_2_562915447 d0[2] +#define XFIX_0_298631336_MINUS_0_899976223 d0[3] +#define XFIX_1_501321110_MINUS_0_899976223 d1[0] +#define XFIX_2_053119869_MINUS_2_562915447 d1[1] +#define XFIX_0_541196100_PLUS_0_765366865 d1[2] +#define XFIX_1_175875602 d1[3] +#define XFIX_1_175875602_MINUS_0_390180644 d2[0] +#define XFIX_0_541196100_MINUS_1_847759065 d2[1] +#define XFIX_3_072711026_MINUS_2_562915447 d2[2] +#define XFIX_1_175875602_MINUS_1_961570560 d2[3] + +.balign 16 +jsimd_idct_islow_neon_consts: + .short FIX_0_899976223 /* d0[0] */ + .short FIX_0_541196100 /* d0[1] */ + .short FIX_2_562915447 /* d0[2] */ + .short FIX_0_298631336_MINUS_0_899976223 /* d0[3] */ + .short FIX_1_501321110_MINUS_0_899976223 /* d1[0] */ + .short FIX_2_053119869_MINUS_2_562915447 /* d1[1] */ + .short FIX_0_541196100_PLUS_0_765366865 /* d1[2] */ + .short FIX_1_175875602 /* d1[3] */ + /* reloadable constants */ + .short FIX_1_175875602_MINUS_0_390180644 /* d2[0] */ + .short FIX_0_541196100_MINUS_1_847759065 /* d2[1] */ + .short FIX_3_072711026_MINUS_2_562915447 /* d2[2] */ + .short FIX_1_175875602_MINUS_1_961570560 /* d2[3] */ + +asm_function jsimd_idct_islow_neon + + DCT_TABLE .req r0 + COEF_BLOCK .req r1 + OUTPUT_BUF .req r2 + OUTPUT_COL .req r3 + TMP1 .req r0 + TMP2 .req r1 + TMP3 .req r2 + TMP4 .req ip + + ROW0L .req d16 + ROW0R .req d17 + ROW1L .req d18 + ROW1R .req d19 + ROW2L .req d20 + ROW2R .req d21 + ROW3L .req d22 + ROW3R .req d23 + ROW4L .req d24 + ROW4R .req d25 + ROW5L .req d26 + ROW5R .req d27 + ROW6L .req d28 + ROW6R .req d29 + ROW7L .req d30 + ROW7R .req d31 + + /* Load and dequantize coefficients into NEON registers + * with the following allocation: + * 0 1 2 3 | 4 5 6 7 + * ---------+-------- + * 0 | d16 | d17 ( q8 ) + * 1 | d18 | d19 ( q9 ) + * 2 | d20 | d21 ( q10 ) + * 3 | d22 | d23 ( q11 ) + * 4 | d24 | d25 ( q12 ) + * 5 | d26 | d27 ( q13 ) + * 6 | d28 | d29 ( q14 ) + * 7 | d30 | d31 ( q15 ) + */ + adr ip, jsimd_idct_islow_neon_consts + vld1.16 {d16, d17, d18, d19}, [COEF_BLOCK, :128]! + vld1.16 {d0, d1, d2, d3}, [DCT_TABLE, :128]! + vld1.16 {d20, d21, d22, d23}, [COEF_BLOCK, :128]! + vmul.s16 q8, q8, q0 + vld1.16 {d4, d5, d6, d7}, [DCT_TABLE, :128]! + vmul.s16 q9, q9, q1 + vld1.16 {d24, d25, d26, d27}, [COEF_BLOCK, :128]! + vmul.s16 q10, q10, q2 + vld1.16 {d0, d1, d2, d3}, [DCT_TABLE, :128]! + vmul.s16 q11, q11, q3 + vld1.16 {d28, d29, d30, d31}, [COEF_BLOCK, :128] + vmul.s16 q12, q12, q0 + vld1.16 {d4, d5, d6, d7}, [DCT_TABLE, :128]! + vmul.s16 q14, q14, q2 + vmul.s16 q13, q13, q1 + vld1.16 {d0, d1, d2, d3}, [ip, :128] /* load constants */ + add ip, ip, #16 + vmul.s16 q15, q15, q3 + vpush {d8-d15} /* save NEON registers */ + /* 1-D IDCT, pass 1, left 4x8 half */ + vadd.s16 d4, ROW7L, ROW3L + vadd.s16 d5, ROW5L, ROW1L + vmull.s16 q6, d4, XFIX_1_175875602_MINUS_1_961570560 + vmlal.s16 q6, d5, XFIX_1_175875602 + vmull.s16 q7, d4, XFIX_1_175875602 + /* Check for the zero coefficients in the right 4x8 half */ + push {r4, r5} + vmlal.s16 q7, d5, XFIX_1_175875602_MINUS_0_390180644 + vsubl.s16 q3, ROW0L, ROW4L + ldrd r4, [COEF_BLOCK, #(-96 + 2 * (4 + 1 * 8))] + vmull.s16 q2, ROW2L, XFIX_0_541196100 + vmlal.s16 q2, ROW6L, XFIX_0_541196100_MINUS_1_847759065 + orr r0, r4, r5 + vmov q4, q6 + vmlsl.s16 q6, ROW5L, XFIX_2_562915447 + ldrd r4, [COEF_BLOCK, #(-96 + 2 * (4 + 2 * 8))] + vmlal.s16 q6, ROW3L, XFIX_3_072711026_MINUS_2_562915447 + vshl.s32 q3, q3, #13 + orr r0, r0, r4 + vmlsl.s16 q4, ROW1L, XFIX_0_899976223 + orr r0, r0, r5 + vadd.s32 q1, q3, q2 + ldrd r4, [COEF_BLOCK, #(-96 + 2 * (4 + 3 * 8))] + vmov q5, q7 + vadd.s32 q1, q1, q6 + orr r0, r0, r4 + vmlsl.s16 q7, ROW7L, XFIX_0_899976223 + orr r0, r0, r5 + vmlal.s16 q7, ROW1L, XFIX_1_501321110_MINUS_0_899976223 + vrshrn.s32 ROW1L, q1, #11 + ldrd r4, [COEF_BLOCK, #(-96 + 2 * (4 + 4 * 8))] + vsub.s32 q1, q1, q6 + vmlal.s16 q5, ROW5L, XFIX_2_053119869_MINUS_2_562915447 + orr r0, r0, r4 + vmlsl.s16 q5, ROW3L, XFIX_2_562915447 + orr r0, r0, r5 + vsub.s32 q1, q1, q6 + vmull.s16 q6, ROW2L, XFIX_0_541196100_PLUS_0_765366865 + ldrd r4, [COEF_BLOCK, #(-96 + 2 * (4 + 5 * 8))] + vmlal.s16 q6, ROW6L, XFIX_0_541196100 + vsub.s32 q3, q3, q2 + orr r0, r0, r4 + vrshrn.s32 ROW6L, q1, #11 + orr r0, r0, r5 + vadd.s32 q1, q3, q5 + ldrd r4, [COEF_BLOCK, #(-96 + 2 * (4 + 6 * 8))] + vsub.s32 q3, q3, q5 + vaddl.s16 q5, ROW0L, ROW4L + orr r0, r0, r4 + vrshrn.s32 ROW2L, q1, #11 + orr r0, r0, r5 + vrshrn.s32 ROW5L, q3, #11 + ldrd r4, [COEF_BLOCK, #(-96 + 2 * (4 + 7 * 8))] + vshl.s32 q5, q5, #13 + vmlal.s16 q4, ROW7L, XFIX_0_298631336_MINUS_0_899976223 + orr r0, r0, r4 + vadd.s32 q2, q5, q6 + orrs r0, r0, r5 + vsub.s32 q1, q5, q6 + vadd.s32 q6, q2, q7 + ldrd r4, [COEF_BLOCK, #(-96 + 2 * (4 + 0 * 8))] + vsub.s32 q2, q2, q7 + vadd.s32 q5, q1, q4 + orr r0, r4, r5 + vsub.s32 q3, q1, q4 + pop {r4, r5} + vrshrn.s32 ROW7L, q2, #11 + vrshrn.s32 ROW3L, q5, #11 + vrshrn.s32 ROW0L, q6, #11 + vrshrn.s32 ROW4L, q3, #11 + + beq 3f /* Go to do some special handling for the sparse right 4x8 half */ + + /* 1-D IDCT, pass 1, right 4x8 half */ + vld1.s16 {d2}, [ip, :64] /* reload constants */ + vadd.s16 d10, ROW7R, ROW3R + vadd.s16 d8, ROW5R, ROW1R + /* Transpose left 4x8 half */ + vtrn.16 ROW6L, ROW7L + vmull.s16 q6, d10, XFIX_1_175875602_MINUS_1_961570560 + vmlal.s16 q6, d8, XFIX_1_175875602 + vtrn.16 ROW2L, ROW3L + vmull.s16 q7, d10, XFIX_1_175875602 + vmlal.s16 q7, d8, XFIX_1_175875602_MINUS_0_390180644 + vtrn.16 ROW0L, ROW1L + vsubl.s16 q3, ROW0R, ROW4R + vmull.s16 q2, ROW2R, XFIX_0_541196100 + vmlal.s16 q2, ROW6R, XFIX_0_541196100_MINUS_1_847759065 + vtrn.16 ROW4L, ROW5L + vmov q4, q6 + vmlsl.s16 q6, ROW5R, XFIX_2_562915447 + vmlal.s16 q6, ROW3R, XFIX_3_072711026_MINUS_2_562915447 + vtrn.32 ROW1L, ROW3L + vshl.s32 q3, q3, #13 + vmlsl.s16 q4, ROW1R, XFIX_0_899976223 + vtrn.32 ROW4L, ROW6L + vadd.s32 q1, q3, q2 + vmov q5, q7 + vadd.s32 q1, q1, q6 + vtrn.32 ROW0L, ROW2L + vmlsl.s16 q7, ROW7R, XFIX_0_899976223 + vmlal.s16 q7, ROW1R, XFIX_1_501321110_MINUS_0_899976223 + vrshrn.s32 ROW1R, q1, #11 + vtrn.32 ROW5L, ROW7L + vsub.s32 q1, q1, q6 + vmlal.s16 q5, ROW5R, XFIX_2_053119869_MINUS_2_562915447 + vmlsl.s16 q5, ROW3R, XFIX_2_562915447 + vsub.s32 q1, q1, q6 + vmull.s16 q6, ROW2R, XFIX_0_541196100_PLUS_0_765366865 + vmlal.s16 q6, ROW6R, XFIX_0_541196100 + vsub.s32 q3, q3, q2 + vrshrn.s32 ROW6R, q1, #11 + vadd.s32 q1, q3, q5 + vsub.s32 q3, q3, q5 + vaddl.s16 q5, ROW0R, ROW4R + vrshrn.s32 ROW2R, q1, #11 + vrshrn.s32 ROW5R, q3, #11 + vshl.s32 q5, q5, #13 + vmlal.s16 q4, ROW7R, XFIX_0_298631336_MINUS_0_899976223 + vadd.s32 q2, q5, q6 + vsub.s32 q1, q5, q6 + vadd.s32 q6, q2, q7 + vsub.s32 q2, q2, q7 + vadd.s32 q5, q1, q4 + vsub.s32 q3, q1, q4 + vrshrn.s32 ROW7R, q2, #11 + vrshrn.s32 ROW3R, q5, #11 + vrshrn.s32 ROW0R, q6, #11 + vrshrn.s32 ROW4R, q3, #11 + /* Transpose right 4x8 half */ + vtrn.16 ROW6R, ROW7R + vtrn.16 ROW2R, ROW3R + vtrn.16 ROW0R, ROW1R + vtrn.16 ROW4R, ROW5R + vtrn.32 ROW1R, ROW3R + vtrn.32 ROW4R, ROW6R + vtrn.32 ROW0R, ROW2R + vtrn.32 ROW5R, ROW7R + +1: /* 1-D IDCT, pass 2 (normal variant), left 4x8 half */ + vld1.s16 {d2}, [ip, :64] /* reload constants */ + vmull.s16 q6, ROW1R, XFIX_1_175875602 /* ROW5L <-> ROW1R */ + vmlal.s16 q6, ROW1L, XFIX_1_175875602 + vmlal.s16 q6, ROW3R, XFIX_1_175875602_MINUS_1_961570560 /* ROW7L <-> ROW3R */ + vmlal.s16 q6, ROW3L, XFIX_1_175875602_MINUS_1_961570560 + vmull.s16 q7, ROW3R, XFIX_1_175875602 /* ROW7L <-> ROW3R */ + vmlal.s16 q7, ROW3L, XFIX_1_175875602 + vmlal.s16 q7, ROW1R, XFIX_1_175875602_MINUS_0_390180644 /* ROW5L <-> ROW1R */ + vmlal.s16 q7, ROW1L, XFIX_1_175875602_MINUS_0_390180644 + vsubl.s16 q3, ROW0L, ROW0R /* ROW4L <-> ROW0R */ + vmull.s16 q2, ROW2L, XFIX_0_541196100 + vmlal.s16 q2, ROW2R, XFIX_0_541196100_MINUS_1_847759065 /* ROW6L <-> ROW2R */ + vmov q4, q6 + vmlsl.s16 q6, ROW1R, XFIX_2_562915447 /* ROW5L <-> ROW1R */ + vmlal.s16 q6, ROW3L, XFIX_3_072711026_MINUS_2_562915447 + vshl.s32 q3, q3, #13 + vmlsl.s16 q4, ROW1L, XFIX_0_899976223 + vadd.s32 q1, q3, q2 + vmov q5, q7 + vadd.s32 q1, q1, q6 + vmlsl.s16 q7, ROW3R, XFIX_0_899976223 /* ROW7L <-> ROW3R */ + vmlal.s16 q7, ROW1L, XFIX_1_501321110_MINUS_0_899976223 + vshrn.s32 ROW1L, q1, #16 + vsub.s32 q1, q1, q6 + vmlal.s16 q5, ROW1R, XFIX_2_053119869_MINUS_2_562915447 /* ROW5L <-> ROW1R */ + vmlsl.s16 q5, ROW3L, XFIX_2_562915447 + vsub.s32 q1, q1, q6 + vmull.s16 q6, ROW2L, XFIX_0_541196100_PLUS_0_765366865 + vmlal.s16 q6, ROW2R, XFIX_0_541196100 /* ROW6L <-> ROW2R */ + vsub.s32 q3, q3, q2 + vshrn.s32 ROW2R, q1, #16 /* ROW6L <-> ROW2R */ + vadd.s32 q1, q3, q5 + vsub.s32 q3, q3, q5 + vaddl.s16 q5, ROW0L, ROW0R /* ROW4L <-> ROW0R */ + vshrn.s32 ROW2L, q1, #16 + vshrn.s32 ROW1R, q3, #16 /* ROW5L <-> ROW1R */ + vshl.s32 q5, q5, #13 + vmlal.s16 q4, ROW3R, XFIX_0_298631336_MINUS_0_899976223 /* ROW7L <-> ROW3R */ + vadd.s32 q2, q5, q6 + vsub.s32 q1, q5, q6 + vadd.s32 q6, q2, q7 + vsub.s32 q2, q2, q7 + vadd.s32 q5, q1, q4 + vsub.s32 q3, q1, q4 + vshrn.s32 ROW3R, q2, #16 /* ROW7L <-> ROW3R */ + vshrn.s32 ROW3L, q5, #16 + vshrn.s32 ROW0L, q6, #16 + vshrn.s32 ROW0R, q3, #16 /* ROW4L <-> ROW0R */ + /* 1-D IDCT, pass 2, right 4x8 half */ + vld1.s16 {d2}, [ip, :64] /* reload constants */ + vmull.s16 q6, ROW5R, XFIX_1_175875602 + vmlal.s16 q6, ROW5L, XFIX_1_175875602 /* ROW5L <-> ROW1R */ + vmlal.s16 q6, ROW7R, XFIX_1_175875602_MINUS_1_961570560 + vmlal.s16 q6, ROW7L, XFIX_1_175875602_MINUS_1_961570560 /* ROW7L <-> ROW3R */ + vmull.s16 q7, ROW7R, XFIX_1_175875602 + vmlal.s16 q7, ROW7L, XFIX_1_175875602 /* ROW7L <-> ROW3R */ + vmlal.s16 q7, ROW5R, XFIX_1_175875602_MINUS_0_390180644 + vmlal.s16 q7, ROW5L, XFIX_1_175875602_MINUS_0_390180644 /* ROW5L <-> ROW1R */ + vsubl.s16 q3, ROW4L, ROW4R /* ROW4L <-> ROW0R */ + vmull.s16 q2, ROW6L, XFIX_0_541196100 /* ROW6L <-> ROW2R */ + vmlal.s16 q2, ROW6R, XFIX_0_541196100_MINUS_1_847759065 + vmov q4, q6 + vmlsl.s16 q6, ROW5R, XFIX_2_562915447 + vmlal.s16 q6, ROW7L, XFIX_3_072711026_MINUS_2_562915447 /* ROW7L <-> ROW3R */ + vshl.s32 q3, q3, #13 + vmlsl.s16 q4, ROW5L, XFIX_0_899976223 /* ROW5L <-> ROW1R */ + vadd.s32 q1, q3, q2 + vmov q5, q7 + vadd.s32 q1, q1, q6 + vmlsl.s16 q7, ROW7R, XFIX_0_899976223 + vmlal.s16 q7, ROW5L, XFIX_1_501321110_MINUS_0_899976223 /* ROW5L <-> ROW1R */ + vshrn.s32 ROW5L, q1, #16 /* ROW5L <-> ROW1R */ + vsub.s32 q1, q1, q6 + vmlal.s16 q5, ROW5R, XFIX_2_053119869_MINUS_2_562915447 + vmlsl.s16 q5, ROW7L, XFIX_2_562915447 /* ROW7L <-> ROW3R */ + vsub.s32 q1, q1, q6 + vmull.s16 q6, ROW6L, XFIX_0_541196100_PLUS_0_765366865 /* ROW6L <-> ROW2R */ + vmlal.s16 q6, ROW6R, XFIX_0_541196100 + vsub.s32 q3, q3, q2 + vshrn.s32 ROW6R, q1, #16 + vadd.s32 q1, q3, q5 + vsub.s32 q3, q3, q5 + vaddl.s16 q5, ROW4L, ROW4R /* ROW4L <-> ROW0R */ + vshrn.s32 ROW6L, q1, #16 /* ROW6L <-> ROW2R */ + vshrn.s32 ROW5R, q3, #16 + vshl.s32 q5, q5, #13 + vmlal.s16 q4, ROW7R, XFIX_0_298631336_MINUS_0_899976223 + vadd.s32 q2, q5, q6 + vsub.s32 q1, q5, q6 + vadd.s32 q6, q2, q7 + vsub.s32 q2, q2, q7 + vadd.s32 q5, q1, q4 + vsub.s32 q3, q1, q4 + vshrn.s32 ROW7R, q2, #16 + vshrn.s32 ROW7L, q5, #16 /* ROW7L <-> ROW3R */ + vshrn.s32 ROW4L, q6, #16 /* ROW4L <-> ROW0R */ + vshrn.s32 ROW4R, q3, #16 + +2: /* Descale to 8-bit and range limit */ + vqrshrn.s16 d16, q8, #2 + vqrshrn.s16 d17, q9, #2 + vqrshrn.s16 d18, q10, #2 + vqrshrn.s16 d19, q11, #2 + vpop {d8-d15} /* restore NEON registers */ + vqrshrn.s16 d20, q12, #2 + /* Transpose the final 8-bit samples and do signed->unsigned conversion */ + vtrn.16 q8, q9 + vqrshrn.s16 d21, q13, #2 + vqrshrn.s16 d22, q14, #2 + vmov.u8 q0, #(CENTERJSAMPLE) + vqrshrn.s16 d23, q15, #2 + vtrn.8 d16, d17 + vtrn.8 d18, d19 + vadd.u8 q8, q8, q0 + vadd.u8 q9, q9, q0 + vtrn.16 q10, q11 + /* Store results to the output buffer */ + ldmia OUTPUT_BUF!, {TMP1, TMP2} + add TMP1, TMP1, OUTPUT_COL + add TMP2, TMP2, OUTPUT_COL + vst1.8 {d16}, [TMP1] + vtrn.8 d20, d21 + vst1.8 {d17}, [TMP2] + ldmia OUTPUT_BUF!, {TMP1, TMP2} + add TMP1, TMP1, OUTPUT_COL + add TMP2, TMP2, OUTPUT_COL + vst1.8 {d18}, [TMP1] + vadd.u8 q10, q10, q0 + vst1.8 {d19}, [TMP2] + ldmia OUTPUT_BUF, {TMP1, TMP2, TMP3, TMP4} + add TMP1, TMP1, OUTPUT_COL + add TMP2, TMP2, OUTPUT_COL + add TMP3, TMP3, OUTPUT_COL + add TMP4, TMP4, OUTPUT_COL + vtrn.8 d22, d23 + vst1.8 {d20}, [TMP1] + vadd.u8 q11, q11, q0 + vst1.8 {d21}, [TMP2] + vst1.8 {d22}, [TMP3] + vst1.8 {d23}, [TMP4] + bx lr + +3: /* Left 4x8 half is done, right 4x8 half contains mostly zeros */ + + /* Transpose left 4x8 half */ + vtrn.16 ROW6L, ROW7L + vtrn.16 ROW2L, ROW3L + vtrn.16 ROW0L, ROW1L + vtrn.16 ROW4L, ROW5L + vshl.s16 ROW0R, ROW0R, #2 /* PASS1_BITS */ + vtrn.32 ROW1L, ROW3L + vtrn.32 ROW4L, ROW6L + vtrn.32 ROW0L, ROW2L + vtrn.32 ROW5L, ROW7L + + cmp r0, #0 + beq 4f /* Right 4x8 half has all zeros, go to 'sparse' second pass */ + + /* Only row 0 is non-zero for the right 4x8 half */ + vdup.s16 ROW1R, ROW0R[1] + vdup.s16 ROW2R, ROW0R[2] + vdup.s16 ROW3R, ROW0R[3] + vdup.s16 ROW4R, ROW0R[0] + vdup.s16 ROW5R, ROW0R[1] + vdup.s16 ROW6R, ROW0R[2] + vdup.s16 ROW7R, ROW0R[3] + vdup.s16 ROW0R, ROW0R[0] + b 1b /* Go to 'normal' second pass */ + +4: /* 1-D IDCT, pass 2 (sparse variant with zero rows 4-7), left 4x8 half */ + vld1.s16 {d2}, [ip, :64] /* reload constants */ + vmull.s16 q6, ROW1L, XFIX_1_175875602 + vmlal.s16 q6, ROW3L, XFIX_1_175875602_MINUS_1_961570560 + vmull.s16 q7, ROW3L, XFIX_1_175875602 + vmlal.s16 q7, ROW1L, XFIX_1_175875602_MINUS_0_390180644 + vmull.s16 q2, ROW2L, XFIX_0_541196100 + vshll.s16 q3, ROW0L, #13 + vmov q4, q6 + vmlal.s16 q6, ROW3L, XFIX_3_072711026_MINUS_2_562915447 + vmlsl.s16 q4, ROW1L, XFIX_0_899976223 + vadd.s32 q1, q3, q2 + vmov q5, q7 + vmlal.s16 q7, ROW1L, XFIX_1_501321110_MINUS_0_899976223 + vadd.s32 q1, q1, q6 + vadd.s32 q6, q6, q6 + vmlsl.s16 q5, ROW3L, XFIX_2_562915447 + vshrn.s32 ROW1L, q1, #16 + vsub.s32 q1, q1, q6 + vmull.s16 q6, ROW2L, XFIX_0_541196100_PLUS_0_765366865 + vsub.s32 q3, q3, q2 + vshrn.s32 ROW2R, q1, #16 /* ROW6L <-> ROW2R */ + vadd.s32 q1, q3, q5 + vsub.s32 q3, q3, q5 + vshll.s16 q5, ROW0L, #13 + vshrn.s32 ROW2L, q1, #16 + vshrn.s32 ROW1R, q3, #16 /* ROW5L <-> ROW1R */ + vadd.s32 q2, q5, q6 + vsub.s32 q1, q5, q6 + vadd.s32 q6, q2, q7 + vsub.s32 q2, q2, q7 + vadd.s32 q5, q1, q4 + vsub.s32 q3, q1, q4 + vshrn.s32 ROW3R, q2, #16 /* ROW7L <-> ROW3R */ + vshrn.s32 ROW3L, q5, #16 + vshrn.s32 ROW0L, q6, #16 + vshrn.s32 ROW0R, q3, #16 /* ROW4L <-> ROW0R */ + /* 1-D IDCT, pass 2 (sparse variant with zero rows 4-7), right 4x8 half */ + vld1.s16 {d2}, [ip, :64] /* reload constants */ + vmull.s16 q6, ROW5L, XFIX_1_175875602 + vmlal.s16 q6, ROW7L, XFIX_1_175875602_MINUS_1_961570560 + vmull.s16 q7, ROW7L, XFIX_1_175875602 + vmlal.s16 q7, ROW5L, XFIX_1_175875602_MINUS_0_390180644 + vmull.s16 q2, ROW6L, XFIX_0_541196100 + vshll.s16 q3, ROW4L, #13 + vmov q4, q6 + vmlal.s16 q6, ROW7L, XFIX_3_072711026_MINUS_2_562915447 + vmlsl.s16 q4, ROW5L, XFIX_0_899976223 + vadd.s32 q1, q3, q2 + vmov q5, q7 + vmlal.s16 q7, ROW5L, XFIX_1_501321110_MINUS_0_899976223 + vadd.s32 q1, q1, q6 + vadd.s32 q6, q6, q6 + vmlsl.s16 q5, ROW7L, XFIX_2_562915447 + vshrn.s32 ROW5L, q1, #16 /* ROW5L <-> ROW1R */ + vsub.s32 q1, q1, q6 + vmull.s16 q6, ROW6L, XFIX_0_541196100_PLUS_0_765366865 + vsub.s32 q3, q3, q2 + vshrn.s32 ROW6R, q1, #16 + vadd.s32 q1, q3, q5 + vsub.s32 q3, q3, q5 + vshll.s16 q5, ROW4L, #13 + vshrn.s32 ROW6L, q1, #16 /* ROW6L <-> ROW2R */ + vshrn.s32 ROW5R, q3, #16 + vadd.s32 q2, q5, q6 + vsub.s32 q1, q5, q6 + vadd.s32 q6, q2, q7 + vsub.s32 q2, q2, q7 + vadd.s32 q5, q1, q4 + vsub.s32 q3, q1, q4 + vshrn.s32 ROW7R, q2, #16 + vshrn.s32 ROW7L, q5, #16 /* ROW7L <-> ROW3R */ + vshrn.s32 ROW4L, q6, #16 /* ROW4L <-> ROW0R */ + vshrn.s32 ROW4R, q3, #16 + b 2b /* Go to epilogue */ + + .unreq DCT_TABLE + .unreq COEF_BLOCK + .unreq OUTPUT_BUF + .unreq OUTPUT_COL + .unreq TMP1 + .unreq TMP2 + .unreq TMP3 + .unreq TMP4 + + .unreq ROW0L + .unreq ROW0R + .unreq ROW1L + .unreq ROW1R + .unreq ROW2L + .unreq ROW2R + .unreq ROW3L + .unreq ROW3R + .unreq ROW4L + .unreq ROW4R + .unreq ROW5L + .unreq ROW5R + .unreq ROW6L + .unreq ROW6R + .unreq ROW7L + .unreq ROW7R +.endfunc + +/*****************************************************************************/ + +/* + * jsimd_idct_ifast_neon + * + * This function contains a fast, not so accurate integer implementation of + * the inverse DCT (Discrete Cosine Transform). It uses the same calculations + * and produces exactly the same output as IJG's original 'jpeg_idct_ifast' + * function from jidctfst.c + * + * Normally 1-D AAN DCT needs 5 multiplications and 29 additions. + * But in ARM NEON case some extra additions are required because VQDMULH + * instruction can't handle the constants larger than 1. So the expressions + * like "x * 1.082392200" have to be converted to "x * 0.082392200 + x", + * which introduces an extra addition. Overall, there are 6 extra additions + * per 1-D IDCT pass, totalling to 5 VQDMULH and 35 VADD/VSUB instructions. + */ + +#define XFIX_1_082392200 d0[0] +#define XFIX_1_414213562 d0[1] +#define XFIX_1_847759065 d0[2] +#define XFIX_2_613125930 d0[3] + +.balign 16 +jsimd_idct_ifast_neon_consts: + .short (277 * 128 - 256 * 128) /* XFIX_1_082392200 */ + .short (362 * 128 - 256 * 128) /* XFIX_1_414213562 */ + .short (473 * 128 - 256 * 128) /* XFIX_1_847759065 */ + .short (669 * 128 - 512 * 128) /* XFIX_2_613125930 */ + +asm_function jsimd_idct_ifast_neon + + DCT_TABLE .req r0 + COEF_BLOCK .req r1 + OUTPUT_BUF .req r2 + OUTPUT_COL .req r3 + TMP1 .req r0 + TMP2 .req r1 + TMP3 .req r2 + TMP4 .req ip + + /* Load and dequantize coefficients into NEON registers + * with the following allocation: + * 0 1 2 3 | 4 5 6 7 + * ---------+-------- + * 0 | d16 | d17 ( q8 ) + * 1 | d18 | d19 ( q9 ) + * 2 | d20 | d21 ( q10 ) + * 3 | d22 | d23 ( q11 ) + * 4 | d24 | d25 ( q12 ) + * 5 | d26 | d27 ( q13 ) + * 6 | d28 | d29 ( q14 ) + * 7 | d30 | d31 ( q15 ) + */ + adr ip, jsimd_idct_ifast_neon_consts + vld1.16 {d16, d17, d18, d19}, [COEF_BLOCK, :128]! + vld1.16 {d0, d1, d2, d3}, [DCT_TABLE, :128]! + vld1.16 {d20, d21, d22, d23}, [COEF_BLOCK, :128]! + vmul.s16 q8, q8, q0 + vld1.16 {d4, d5, d6, d7}, [DCT_TABLE, :128]! + vmul.s16 q9, q9, q1 + vld1.16 {d24, d25, d26, d27}, [COEF_BLOCK, :128]! + vmul.s16 q10, q10, q2 + vld1.16 {d0, d1, d2, d3}, [DCT_TABLE, :128]! + vmul.s16 q11, q11, q3 + vld1.16 {d28, d29, d30, d31}, [COEF_BLOCK, :128] + vmul.s16 q12, q12, q0 + vld1.16 {d4, d5, d6, d7}, [DCT_TABLE, :128]! + vmul.s16 q14, q14, q2 + vmul.s16 q13, q13, q1 + vld1.16 {d0}, [ip, :64] /* load constants */ + vmul.s16 q15, q15, q3 + vpush {d8-d13} /* save NEON registers */ + /* 1-D IDCT, pass 1 */ + vsub.s16 q2, q10, q14 + vadd.s16 q14, q10, q14 + vsub.s16 q1, q11, q13 + vadd.s16 q13, q11, q13 + vsub.s16 q5, q9, q15 + vadd.s16 q15, q9, q15 + vqdmulh.s16 q4, q2, XFIX_1_414213562 + vqdmulh.s16 q6, q1, XFIX_2_613125930 + vadd.s16 q3, q1, q1 + vsub.s16 q1, q5, q1 + vadd.s16 q10, q2, q4 + vqdmulh.s16 q4, q1, XFIX_1_847759065 + vsub.s16 q2, q15, q13 + vadd.s16 q3, q3, q6 + vqdmulh.s16 q6, q2, XFIX_1_414213562 + vadd.s16 q1, q1, q4 + vqdmulh.s16 q4, q5, XFIX_1_082392200 + vsub.s16 q10, q10, q14 + vadd.s16 q2, q2, q6 + vsub.s16 q6, q8, q12 + vadd.s16 q12, q8, q12 + vadd.s16 q9, q5, q4 + vadd.s16 q5, q6, q10 + vsub.s16 q10, q6, q10 + vadd.s16 q6, q15, q13 + vadd.s16 q8, q12, q14 + vsub.s16 q3, q6, q3 + vsub.s16 q12, q12, q14 + vsub.s16 q3, q3, q1 + vsub.s16 q1, q9, q1 + vadd.s16 q2, q3, q2 + vsub.s16 q15, q8, q6 + vadd.s16 q1, q1, q2 + vadd.s16 q8, q8, q6 + vadd.s16 q14, q5, q3 + vsub.s16 q9, q5, q3 + vsub.s16 q13, q10, q2 + vadd.s16 q10, q10, q2 + /* Transpose */ + vtrn.16 q8, q9 + vsub.s16 q11, q12, q1 + vtrn.16 q14, q15 + vadd.s16 q12, q12, q1 + vtrn.16 q10, q11 + vtrn.16 q12, q13 + vtrn.32 q9, q11 + vtrn.32 q12, q14 + vtrn.32 q8, q10 + vtrn.32 q13, q15 + vswp d28, d21 + vswp d26, d19 + /* 1-D IDCT, pass 2 */ + vsub.s16 q2, q10, q14 + vswp d30, d23 + vadd.s16 q14, q10, q14 + vswp d24, d17 + vsub.s16 q1, q11, q13 + vadd.s16 q13, q11, q13 + vsub.s16 q5, q9, q15 + vadd.s16 q15, q9, q15 + vqdmulh.s16 q4, q2, XFIX_1_414213562 + vqdmulh.s16 q6, q1, XFIX_2_613125930 + vadd.s16 q3, q1, q1 + vsub.s16 q1, q5, q1 + vadd.s16 q10, q2, q4 + vqdmulh.s16 q4, q1, XFIX_1_847759065 + vsub.s16 q2, q15, q13 + vadd.s16 q3, q3, q6 + vqdmulh.s16 q6, q2, XFIX_1_414213562 + vadd.s16 q1, q1, q4 + vqdmulh.s16 q4, q5, XFIX_1_082392200 + vsub.s16 q10, q10, q14 + vadd.s16 q2, q2, q6 + vsub.s16 q6, q8, q12 + vadd.s16 q12, q8, q12 + vadd.s16 q9, q5, q4 + vadd.s16 q5, q6, q10 + vsub.s16 q10, q6, q10 + vadd.s16 q6, q15, q13 + vadd.s16 q8, q12, q14 + vsub.s16 q3, q6, q3 + vsub.s16 q12, q12, q14 + vsub.s16 q3, q3, q1 + vsub.s16 q1, q9, q1 + vadd.s16 q2, q3, q2 + vsub.s16 q15, q8, q6 + vadd.s16 q1, q1, q2 + vadd.s16 q8, q8, q6 + vadd.s16 q14, q5, q3 + vsub.s16 q9, q5, q3 + vsub.s16 q13, q10, q2 + vpop {d8-d13} /* restore NEON registers */ + vadd.s16 q10, q10, q2 + vsub.s16 q11, q12, q1 + vadd.s16 q12, q12, q1 + /* Descale to 8-bit and range limit */ + vmov.u8 q0, #0x80 + vqshrn.s16 d16, q8, #5 + vqshrn.s16 d17, q9, #5 + vqshrn.s16 d18, q10, #5 + vqshrn.s16 d19, q11, #5 + vqshrn.s16 d20, q12, #5 + vqshrn.s16 d21, q13, #5 + vqshrn.s16 d22, q14, #5 + vqshrn.s16 d23, q15, #5 + vadd.u8 q8, q8, q0 + vadd.u8 q9, q9, q0 + vadd.u8 q10, q10, q0 + vadd.u8 q11, q11, q0 + /* Transpose the final 8-bit samples */ + vtrn.16 q8, q9 + vtrn.16 q10, q11 + vtrn.32 q8, q10 + vtrn.32 q9, q11 + vtrn.8 d16, d17 + vtrn.8 d18, d19 + /* Store results to the output buffer */ + ldmia OUTPUT_BUF!, {TMP1, TMP2} + add TMP1, TMP1, OUTPUT_COL + add TMP2, TMP2, OUTPUT_COL + vst1.8 {d16}, [TMP1] + vst1.8 {d17}, [TMP2] + ldmia OUTPUT_BUF!, {TMP1, TMP2} + add TMP1, TMP1, OUTPUT_COL + add TMP2, TMP2, OUTPUT_COL + vst1.8 {d18}, [TMP1] + vtrn.8 d20, d21 + vst1.8 {d19}, [TMP2] + ldmia OUTPUT_BUF, {TMP1, TMP2, TMP3, TMP4} + add TMP1, TMP1, OUTPUT_COL + add TMP2, TMP2, OUTPUT_COL + add TMP3, TMP3, OUTPUT_COL + add TMP4, TMP4, OUTPUT_COL + vst1.8 {d20}, [TMP1] + vtrn.8 d22, d23 + vst1.8 {d21}, [TMP2] + vst1.8 {d22}, [TMP3] + vst1.8 {d23}, [TMP4] + bx lr + + .unreq DCT_TABLE + .unreq COEF_BLOCK + .unreq OUTPUT_BUF + .unreq OUTPUT_COL + .unreq TMP1 + .unreq TMP2 + .unreq TMP3 + .unreq TMP4 +.endfunc + +/*****************************************************************************/ + +/* + * jsimd_idct_4x4_neon + * + * This function contains inverse-DCT code for getting reduced-size + * 4x4 pixels output from an 8x8 DCT block. It uses the same calculations + * and produces exactly the same output as IJG's original 'jpeg_idct_4x4' + * function from jpeg-6b (jidctred.c). + * + * NOTE: jpeg-8 has an improved implementation of 4x4 inverse-DCT, which + * requires much less arithmetic operations and hence should be faster. + * The primary purpose of this particular NEON optimized function is + * bit exact compatibility with jpeg-6b. + * + * TODO: a bit better instructions scheduling can be achieved by expanding + * idct_helper/transpose_4x4 macros and reordering instructions, + * but readability will suffer somewhat. + */ + +#define CONST_BITS 13 + +#define FIX_0_211164243 (1730) /* FIX(0.211164243) */ +#define FIX_0_509795579 (4176) /* FIX(0.509795579) */ +#define FIX_0_601344887 (4926) /* FIX(0.601344887) */ +#define FIX_0_720959822 (5906) /* FIX(0.720959822) */ +#define FIX_0_765366865 (6270) /* FIX(0.765366865) */ +#define FIX_0_850430095 (6967) /* FIX(0.850430095) */ +#define FIX_0_899976223 (7373) /* FIX(0.899976223) */ +#define FIX_1_061594337 (8697) /* FIX(1.061594337) */ +#define FIX_1_272758580 (10426) /* FIX(1.272758580) */ +#define FIX_1_451774981 (11893) /* FIX(1.451774981) */ +#define FIX_1_847759065 (15137) /* FIX(1.847759065) */ +#define FIX_2_172734803 (17799) /* FIX(2.172734803) */ +#define FIX_2_562915447 (20995) /* FIX(2.562915447) */ +#define FIX_3_624509785 (29692) /* FIX(3.624509785) */ + +.balign 16 +jsimd_idct_4x4_neon_consts: + .short FIX_1_847759065 /* d0[0] */ + .short -FIX_0_765366865 /* d0[1] */ + .short -FIX_0_211164243 /* d0[2] */ + .short FIX_1_451774981 /* d0[3] */ + .short -FIX_2_172734803 /* d1[0] */ + .short FIX_1_061594337 /* d1[1] */ + .short -FIX_0_509795579 /* d1[2] */ + .short -FIX_0_601344887 /* d1[3] */ + .short FIX_0_899976223 /* d2[0] */ + .short FIX_2_562915447 /* d2[1] */ + .short 1 << (CONST_BITS+1) /* d2[2] */ + .short 0 /* d2[3] */ + +.macro idct_helper x4, x6, x8, x10, x12, x14, x16, shift, y26, y27, y28, y29 + vmull.s16 q14, \x4, d2[2] + vmlal.s16 q14, \x8, d0[0] + vmlal.s16 q14, \x14, d0[1] + + vmull.s16 q13, \x16, d1[2] + vmlal.s16 q13, \x12, d1[3] + vmlal.s16 q13, \x10, d2[0] + vmlal.s16 q13, \x6, d2[1] + + vmull.s16 q15, \x4, d2[2] + vmlsl.s16 q15, \x8, d0[0] + vmlsl.s16 q15, \x14, d0[1] + + vmull.s16 q12, \x16, d0[2] + vmlal.s16 q12, \x12, d0[3] + vmlal.s16 q12, \x10, d1[0] + vmlal.s16 q12, \x6, d1[1] + + vadd.s32 q10, q14, q13 + vsub.s32 q14, q14, q13 + +.if \shift > 16 + vrshr.s32 q10, q10, #\shift + vrshr.s32 q14, q14, #\shift + vmovn.s32 \y26, q10 + vmovn.s32 \y29, q14 +.else + vrshrn.s32 \y26, q10, #\shift + vrshrn.s32 \y29, q14, #\shift +.endif + + vadd.s32 q10, q15, q12 + vsub.s32 q15, q15, q12 + +.if \shift > 16 + vrshr.s32 q10, q10, #\shift + vrshr.s32 q15, q15, #\shift + vmovn.s32 \y27, q10 + vmovn.s32 \y28, q15 +.else + vrshrn.s32 \y27, q10, #\shift + vrshrn.s32 \y28, q15, #\shift +.endif + +.endm + +asm_function jsimd_idct_4x4_neon + + DCT_TABLE .req r0 + COEF_BLOCK .req r1 + OUTPUT_BUF .req r2 + OUTPUT_COL .req r3 + TMP1 .req r0 + TMP2 .req r1 + TMP3 .req r2 + TMP4 .req ip + + vpush {d8-d15} + + /* Load constants (d3 is just used for padding) */ + adr TMP4, jsimd_idct_4x4_neon_consts + vld1.16 {d0, d1, d2, d3}, [TMP4, :128] + + /* Load all COEF_BLOCK into NEON registers with the following allocation: + * 0 1 2 3 | 4 5 6 7 + * ---------+-------- + * 0 | d4 | d5 + * 1 | d6 | d7 + * 2 | d8 | d9 + * 3 | d10 | d11 + * 4 | - | - + * 5 | d12 | d13 + * 6 | d14 | d15 + * 7 | d16 | d17 + */ + vld1.16 {d4, d5, d6, d7}, [COEF_BLOCK, :128]! + vld1.16 {d8, d9, d10, d11}, [COEF_BLOCK, :128]! + add COEF_BLOCK, COEF_BLOCK, #16 + vld1.16 {d12, d13, d14, d15}, [COEF_BLOCK, :128]! + vld1.16 {d16, d17}, [COEF_BLOCK, :128]! + /* dequantize */ + vld1.16 {d18, d19, d20, d21}, [DCT_TABLE, :128]! + vmul.s16 q2, q2, q9 + vld1.16 {d22, d23, d24, d25}, [DCT_TABLE, :128]! + vmul.s16 q3, q3, q10 + vmul.s16 q4, q4, q11 + add DCT_TABLE, DCT_TABLE, #16 + vld1.16 {d26, d27, d28, d29}, [DCT_TABLE, :128]! + vmul.s16 q5, q5, q12 + vmul.s16 q6, q6, q13 + vld1.16 {d30, d31}, [DCT_TABLE, :128]! + vmul.s16 q7, q7, q14 + vmul.s16 q8, q8, q15 + + /* Pass 1 */ + idct_helper d4, d6, d8, d10, d12, d14, d16, 12, d4, d6, d8, d10 + transpose_4x4 d4, d6, d8, d10 + idct_helper d5, d7, d9, d11, d13, d15, d17, 12, d5, d7, d9, d11 + transpose_4x4 d5, d7, d9, d11 + + /* Pass 2 */ + idct_helper d4, d6, d8, d10, d7, d9, d11, 19, d26, d27, d28, d29 + transpose_4x4 d26, d27, d28, d29 + + /* Range limit */ + vmov.u16 q15, #0x80 + vadd.s16 q13, q13, q15 + vadd.s16 q14, q14, q15 + vqmovun.s16 d26, q13 + vqmovun.s16 d27, q14 + + /* Store results to the output buffer */ + ldmia OUTPUT_BUF, {TMP1, TMP2, TMP3, TMP4} + add TMP1, TMP1, OUTPUT_COL + add TMP2, TMP2, OUTPUT_COL + add TMP3, TMP3, OUTPUT_COL + add TMP4, TMP4, OUTPUT_COL + +#if defined(__ARMEL__) && !RESPECT_STRICT_ALIGNMENT + /* We can use much less instructions on little endian systems if the + * OS kernel is not configured to trap unaligned memory accesses + */ + vst1.32 {d26[0]}, [TMP1]! + vst1.32 {d27[0]}, [TMP3]! + vst1.32 {d26[1]}, [TMP2]! + vst1.32 {d27[1]}, [TMP4]! +#else + vst1.8 {d26[0]}, [TMP1]! + vst1.8 {d27[0]}, [TMP3]! + vst1.8 {d26[1]}, [TMP1]! + vst1.8 {d27[1]}, [TMP3]! + vst1.8 {d26[2]}, [TMP1]! + vst1.8 {d27[2]}, [TMP3]! + vst1.8 {d26[3]}, [TMP1]! + vst1.8 {d27[3]}, [TMP3]! + + vst1.8 {d26[4]}, [TMP2]! + vst1.8 {d27[4]}, [TMP4]! + vst1.8 {d26[5]}, [TMP2]! + vst1.8 {d27[5]}, [TMP4]! + vst1.8 {d26[6]}, [TMP2]! + vst1.8 {d27[6]}, [TMP4]! + vst1.8 {d26[7]}, [TMP2]! + vst1.8 {d27[7]}, [TMP4]! +#endif + + vpop {d8-d15} + bx lr + + .unreq DCT_TABLE + .unreq COEF_BLOCK + .unreq OUTPUT_BUF + .unreq OUTPUT_COL + .unreq TMP1 + .unreq TMP2 + .unreq TMP3 + .unreq TMP4 +.endfunc + +.purgem idct_helper + +/*****************************************************************************/ + +/* + * jsimd_idct_2x2_neon + * + * This function contains inverse-DCT code for getting reduced-size + * 2x2 pixels output from an 8x8 DCT block. It uses the same calculations + * and produces exactly the same output as IJG's original 'jpeg_idct_2x2' + * function from jpeg-6b (jidctred.c). + * + * NOTE: jpeg-8 has an improved implementation of 2x2 inverse-DCT, which + * requires much less arithmetic operations and hence should be faster. + * The primary purpose of this particular NEON optimized function is + * bit exact compatibility with jpeg-6b. + */ + +.balign 8 +jsimd_idct_2x2_neon_consts: + .short -FIX_0_720959822 /* d0[0] */ + .short FIX_0_850430095 /* d0[1] */ + .short -FIX_1_272758580 /* d0[2] */ + .short FIX_3_624509785 /* d0[3] */ + +.macro idct_helper x4, x6, x10, x12, x16, shift, y26, y27 + vshll.s16 q14, \x4, #15 + vmull.s16 q13, \x6, d0[3] + vmlal.s16 q13, \x10, d0[2] + vmlal.s16 q13, \x12, d0[1] + vmlal.s16 q13, \x16, d0[0] + + vadd.s32 q10, q14, q13 + vsub.s32 q14, q14, q13 + +.if \shift > 16 + vrshr.s32 q10, q10, #\shift + vrshr.s32 q14, q14, #\shift + vmovn.s32 \y26, q10 + vmovn.s32 \y27, q14 +.else + vrshrn.s32 \y26, q10, #\shift + vrshrn.s32 \y27, q14, #\shift +.endif + +.endm + +asm_function jsimd_idct_2x2_neon + + DCT_TABLE .req r0 + COEF_BLOCK .req r1 + OUTPUT_BUF .req r2 + OUTPUT_COL .req r3 + TMP1 .req r0 + TMP2 .req ip + + vpush {d8-d15} + + /* Load constants */ + adr TMP2, jsimd_idct_2x2_neon_consts + vld1.16 {d0}, [TMP2, :64] + + /* Load all COEF_BLOCK into NEON registers with the following allocation: + * 0 1 2 3 | 4 5 6 7 + * ---------+-------- + * 0 | d4 | d5 + * 1 | d6 | d7 + * 2 | - | - + * 3 | d10 | d11 + * 4 | - | - + * 5 | d12 | d13 + * 6 | - | - + * 7 | d16 | d17 + */ + vld1.16 {d4, d5, d6, d7}, [COEF_BLOCK, :128]! + add COEF_BLOCK, COEF_BLOCK, #16 + vld1.16 {d10, d11}, [COEF_BLOCK, :128]! + add COEF_BLOCK, COEF_BLOCK, #16 + vld1.16 {d12, d13}, [COEF_BLOCK, :128]! + add COEF_BLOCK, COEF_BLOCK, #16 + vld1.16 {d16, d17}, [COEF_BLOCK, :128]! + /* Dequantize */ + vld1.16 {d18, d19, d20, d21}, [DCT_TABLE, :128]! + vmul.s16 q2, q2, q9 + vmul.s16 q3, q3, q10 + add DCT_TABLE, DCT_TABLE, #16 + vld1.16 {d24, d25}, [DCT_TABLE, :128]! + vmul.s16 q5, q5, q12 + add DCT_TABLE, DCT_TABLE, #16 + vld1.16 {d26, d27}, [DCT_TABLE, :128]! + vmul.s16 q6, q6, q13 + add DCT_TABLE, DCT_TABLE, #16 + vld1.16 {d30, d31}, [DCT_TABLE, :128]! + vmul.s16 q8, q8, q15 + + /* Pass 1 */ +#if 0 + idct_helper d4, d6, d10, d12, d16, 13, d4, d6 + transpose_4x4 d4, d6, d8, d10 + idct_helper d5, d7, d11, d13, d17, 13, d5, d7 + transpose_4x4 d5, d7, d9, d11 +#else + vmull.s16 q13, d6, d0[3] + vmlal.s16 q13, d10, d0[2] + vmlal.s16 q13, d12, d0[1] + vmlal.s16 q13, d16, d0[0] + vmull.s16 q12, d7, d0[3] + vmlal.s16 q12, d11, d0[2] + vmlal.s16 q12, d13, d0[1] + vmlal.s16 q12, d17, d0[0] + vshll.s16 q14, d4, #15 + vshll.s16 q15, d5, #15 + vadd.s32 q10, q14, q13 + vsub.s32 q14, q14, q13 + vrshrn.s32 d4, q10, #13 + vrshrn.s32 d6, q14, #13 + vadd.s32 q10, q15, q12 + vsub.s32 q14, q15, q12 + vrshrn.s32 d5, q10, #13 + vrshrn.s32 d7, q14, #13 + vtrn.16 q2, q3 + vtrn.32 q3, q5 +#endif + + /* Pass 2 */ + idct_helper d4, d6, d10, d7, d11, 20, d26, d27 + + /* Range limit */ + vmov.u16 q15, #0x80 + vadd.s16 q13, q13, q15 + vqmovun.s16 d26, q13 + vqmovun.s16 d27, q13 + + /* Store results to the output buffer */ + ldmia OUTPUT_BUF, {TMP1, TMP2} + add TMP1, TMP1, OUTPUT_COL + add TMP2, TMP2, OUTPUT_COL + + vst1.8 {d26[0]}, [TMP1]! + vst1.8 {d27[4]}, [TMP1]! + vst1.8 {d26[1]}, [TMP2]! + vst1.8 {d27[5]}, [TMP2]! + + vpop {d8-d15} + bx lr + + .unreq DCT_TABLE + .unreq COEF_BLOCK + .unreq OUTPUT_BUF + .unreq OUTPUT_COL + .unreq TMP1 + .unreq TMP2 +.endfunc + +.purgem idct_helper + +/*****************************************************************************/ + +/* + * jsimd_ycc_extrgb_convert_neon + * jsimd_ycc_extbgr_convert_neon + * jsimd_ycc_extrgbx_convert_neon + * jsimd_ycc_extbgrx_convert_neon + * jsimd_ycc_extxbgr_convert_neon + * jsimd_ycc_extxrgb_convert_neon + * + * Colorspace conversion YCbCr -> RGB + */ + + +.macro do_load size + .if \size == 8 + vld1.8 {d4}, [U, :64]! + vld1.8 {d5}, [V, :64]! + vld1.8 {d0}, [Y, :64]! + pld [U, #64] + pld [V, #64] + pld [Y, #64] + .elseif \size == 4 + vld1.8 {d4[0]}, [U]! + vld1.8 {d4[1]}, [U]! + vld1.8 {d4[2]}, [U]! + vld1.8 {d4[3]}, [U]! + vld1.8 {d5[0]}, [V]! + vld1.8 {d5[1]}, [V]! + vld1.8 {d5[2]}, [V]! + vld1.8 {d5[3]}, [V]! + vld1.8 {d0[0]}, [Y]! + vld1.8 {d0[1]}, [Y]! + vld1.8 {d0[2]}, [Y]! + vld1.8 {d0[3]}, [Y]! + .elseif \size == 2 + vld1.8 {d4[4]}, [U]! + vld1.8 {d4[5]}, [U]! + vld1.8 {d5[4]}, [V]! + vld1.8 {d5[5]}, [V]! + vld1.8 {d0[4]}, [Y]! + vld1.8 {d0[5]}, [Y]! + .elseif \size == 1 + vld1.8 {d4[6]}, [U]! + vld1.8 {d5[6]}, [V]! + vld1.8 {d0[6]}, [Y]! + .else + .error unsupported macroblock size + .endif +.endm + +.macro do_store bpp, size + .if \bpp == 24 + .if \size == 8 + vst3.8 {d10, d11, d12}, [RGB]! + .elseif \size == 4 + vst3.8 {d10[0], d11[0], d12[0]}, [RGB]! + vst3.8 {d10[1], d11[1], d12[1]}, [RGB]! + vst3.8 {d10[2], d11[2], d12[2]}, [RGB]! + vst3.8 {d10[3], d11[3], d12[3]}, [RGB]! + .elseif \size == 2 + vst3.8 {d10[4], d11[4], d12[4]}, [RGB]! + vst3.8 {d10[5], d11[5], d12[5]}, [RGB]! + .elseif \size == 1 + vst3.8 {d10[6], d11[6], d12[6]}, [RGB]! + .else + .error unsupported macroblock size + .endif + .elseif \bpp == 32 + .if \size == 8 + vst4.8 {d10, d11, d12, d13}, [RGB]! + .elseif \size == 4 + vst4.8 {d10[0], d11[0], d12[0], d13[0]}, [RGB]! + vst4.8 {d10[1], d11[1], d12[1], d13[1]}, [RGB]! + vst4.8 {d10[2], d11[2], d12[2], d13[2]}, [RGB]! + vst4.8 {d10[3], d11[3], d12[3], d13[3]}, [RGB]! + .elseif \size == 2 + vst4.8 {d10[4], d11[4], d12[4], d13[4]}, [RGB]! + vst4.8 {d10[5], d11[5], d12[5], d13[5]}, [RGB]! + .elseif \size == 1 + vst4.8 {d10[6], d11[6], d12[6], d13[6]}, [RGB]! + .else + .error unsupported macroblock size + .endif + .else + .error unsupported bpp + .endif +.endm + +.macro generate_jsimd_ycc_rgb_convert_neon colorid, bpp, r_offs, g_offs, b_offs + +/* + * 2 stage pipelined YCbCr->RGB conversion + */ + +.macro do_yuv_to_rgb_stage1 + vaddw.u8 q3, q1, d4 /* q3 = u - 128 */ + vaddw.u8 q4, q1, d5 /* q2 = v - 128 */ + vmull.s16 q10, d6, d1[1] /* multiply by -11277 */ + vmlal.s16 q10, d8, d1[2] /* multiply by -23401 */ + vmull.s16 q11, d7, d1[1] /* multiply by -11277 */ + vmlal.s16 q11, d9, d1[2] /* multiply by -23401 */ + vmull.s16 q12, d8, d1[0] /* multiply by 22971 */ + vmull.s16 q13, d9, d1[0] /* multiply by 22971 */ + vmull.s16 q14, d6, d1[3] /* multiply by 29033 */ + vmull.s16 q15, d7, d1[3] /* multiply by 29033 */ +.endm + +.macro do_yuv_to_rgb_stage2 + vrshrn.s32 d20, q10, #15 + vrshrn.s32 d21, q11, #15 + vrshrn.s32 d24, q12, #14 + vrshrn.s32 d25, q13, #14 + vrshrn.s32 d28, q14, #14 + vrshrn.s32 d29, q15, #14 + vaddw.u8 q10, q10, d0 + vaddw.u8 q12, q12, d0 + vaddw.u8 q14, q14, d0 + vqmovun.s16 d1\g_offs, q10 + vqmovun.s16 d1\r_offs, q12 + vqmovun.s16 d1\b_offs, q14 +.endm + +.macro do_yuv_to_rgb_stage2_store_load_stage1 + vld1.8 {d4}, [U, :64]! + vrshrn.s32 d20, q10, #15 + vrshrn.s32 d21, q11, #15 + vrshrn.s32 d24, q12, #14 + vrshrn.s32 d25, q13, #14 + vrshrn.s32 d28, q14, #14 + vld1.8 {d5}, [V, :64]! + vrshrn.s32 d29, q15, #14 + vaddw.u8 q10, q10, d0 + vaddw.u8 q12, q12, d0 + vaddw.u8 q14, q14, d0 + vqmovun.s16 d1\g_offs, q10 + vld1.8 {d0}, [Y, :64]! + vqmovun.s16 d1\r_offs, q12 + pld [U, #64] + pld [V, #64] + pld [Y, #64] + vqmovun.s16 d1\b_offs, q14 + vaddw.u8 q3, q1, d4 /* q3 = u - 128 */ + vaddw.u8 q4, q1, d5 /* q2 = v - 128 */ + do_store \bpp, 8 + vmull.s16 q10, d6, d1[1] /* multiply by -11277 */ + vmlal.s16 q10, d8, d1[2] /* multiply by -23401 */ + vmull.s16 q11, d7, d1[1] /* multiply by -11277 */ + vmlal.s16 q11, d9, d1[2] /* multiply by -23401 */ + vmull.s16 q12, d8, d1[0] /* multiply by 22971 */ + vmull.s16 q13, d9, d1[0] /* multiply by 22971 */ + vmull.s16 q14, d6, d1[3] /* multiply by 29033 */ + vmull.s16 q15, d7, d1[3] /* multiply by 29033 */ +.endm + +.macro do_yuv_to_rgb + do_yuv_to_rgb_stage1 + do_yuv_to_rgb_stage2 +.endm + +/* Apple gas crashes on adrl, work around that by using adr. + * But this requires a copy of these constants for each function. + */ + +.balign 16 +jsimd_ycc_\colorid\()_neon_consts: + .short 0, 0, 0, 0 + .short 22971, -11277, -23401, 29033 + .short -128, -128, -128, -128 + .short -128, -128, -128, -128 + +asm_function jsimd_ycc_\colorid\()_convert_neon + OUTPUT_WIDTH .req r0 + INPUT_BUF .req r1 + INPUT_ROW .req r2 + OUTPUT_BUF .req r3 + NUM_ROWS .req r4 + + INPUT_BUF0 .req r5 + INPUT_BUF1 .req r6 + INPUT_BUF2 .req INPUT_BUF + + RGB .req r7 + Y .req r8 + U .req r9 + V .req r10 + N .req ip + + /* Load constants to d1, d2, d3 (d0 is just used for padding) */ + adr ip, jsimd_ycc_\colorid\()_neon_consts + vld1.16 {d0, d1, d2, d3}, [ip, :128] + + /* Save ARM registers and handle input arguments */ + push {r4, r5, r6, r7, r8, r9, r10, lr} + ldr NUM_ROWS, [sp, #(4 * 8)] + ldr INPUT_BUF0, [INPUT_BUF] + ldr INPUT_BUF1, [INPUT_BUF, #4] + ldr INPUT_BUF2, [INPUT_BUF, #8] + .unreq INPUT_BUF + + /* Save NEON registers */ + vpush {d8-d15} + + /* Initially set d10, d11, d12, d13 to 0xFF */ + vmov.u8 q5, #255 + vmov.u8 q6, #255 + + /* Outer loop over scanlines */ + cmp NUM_ROWS, #1 + blt 9f +0: + ldr Y, [INPUT_BUF0, INPUT_ROW, lsl #2] + ldr U, [INPUT_BUF1, INPUT_ROW, lsl #2] + mov N, OUTPUT_WIDTH + ldr V, [INPUT_BUF2, INPUT_ROW, lsl #2] + add INPUT_ROW, INPUT_ROW, #1 + ldr RGB, [OUTPUT_BUF], #4 + + /* Inner loop over pixels */ + subs N, N, #8 + blt 3f + do_load 8 + do_yuv_to_rgb_stage1 + subs N, N, #8 + blt 2f +1: + do_yuv_to_rgb_stage2_store_load_stage1 + subs N, N, #8 + bge 1b +2: + do_yuv_to_rgb_stage2 + do_store \bpp, 8 + tst N, #7 + beq 8f +3: + tst N, #4 + beq 3f + do_load 4 +3: + tst N, #2 + beq 4f + do_load 2 +4: + tst N, #1 + beq 5f + do_load 1 +5: + do_yuv_to_rgb + tst N, #4 + beq 6f + do_store \bpp, 4 +6: + tst N, #2 + beq 7f + do_store \bpp, 2 +7: + tst N, #1 + beq 8f + do_store \bpp, 1 +8: + subs NUM_ROWS, NUM_ROWS, #1 + bgt 0b +9: + /* Restore all registers and return */ + vpop {d8-d15} + pop {r4, r5, r6, r7, r8, r9, r10, pc} + + .unreq OUTPUT_WIDTH + .unreq INPUT_ROW + .unreq OUTPUT_BUF + .unreq NUM_ROWS + .unreq INPUT_BUF0 + .unreq INPUT_BUF1 + .unreq INPUT_BUF2 + .unreq RGB + .unreq Y + .unreq U + .unreq V + .unreq N +.endfunc + +.purgem do_yuv_to_rgb +.purgem do_yuv_to_rgb_stage1 +.purgem do_yuv_to_rgb_stage2 +.purgem do_yuv_to_rgb_stage2_store_load_stage1 + +.endm + +/*--------------------------------- id ----- bpp R G B */ +generate_jsimd_ycc_rgb_convert_neon extrgb, 24, 0, 1, 2 +generate_jsimd_ycc_rgb_convert_neon extbgr, 24, 2, 1, 0 +generate_jsimd_ycc_rgb_convert_neon extrgbx, 32, 0, 1, 2 +generate_jsimd_ycc_rgb_convert_neon extbgrx, 32, 2, 1, 0 +generate_jsimd_ycc_rgb_convert_neon extxbgr, 32, 3, 2, 1 +generate_jsimd_ycc_rgb_convert_neon extxrgb, 32, 1, 2, 3 + +.purgem do_load +.purgem do_store + +/*****************************************************************************/ + +/* + * jsimd_extrgb_ycc_convert_neon + * jsimd_extbgr_ycc_convert_neon + * jsimd_extrgbx_ycc_convert_neon + * jsimd_extbgrx_ycc_convert_neon + * jsimd_extxbgr_ycc_convert_neon + * jsimd_extxrgb_ycc_convert_neon + * + * Colorspace conversion RGB -> YCbCr + */ + +.macro do_store size + .if \size == 8 + vst1.8 {d20}, [Y]! + vst1.8 {d21}, [U]! + vst1.8 {d22}, [V]! + .elseif \size == 4 + vst1.8 {d20[0]}, [Y]! + vst1.8 {d20[1]}, [Y]! + vst1.8 {d20[2]}, [Y]! + vst1.8 {d20[3]}, [Y]! + vst1.8 {d21[0]}, [U]! + vst1.8 {d21[1]}, [U]! + vst1.8 {d21[2]}, [U]! + vst1.8 {d21[3]}, [U]! + vst1.8 {d22[0]}, [V]! + vst1.8 {d22[1]}, [V]! + vst1.8 {d22[2]}, [V]! + vst1.8 {d22[3]}, [V]! + .elseif \size == 2 + vst1.8 {d20[4]}, [Y]! + vst1.8 {d20[5]}, [Y]! + vst1.8 {d21[4]}, [U]! + vst1.8 {d21[5]}, [U]! + vst1.8 {d22[4]}, [V]! + vst1.8 {d22[5]}, [V]! + .elseif \size == 1 + vst1.8 {d20[6]}, [Y]! + vst1.8 {d21[6]}, [U]! + vst1.8 {d22[6]}, [V]! + .else + .error unsupported macroblock size + .endif +.endm + +.macro do_load bpp, size + .if \bpp == 24 + .if \size == 8 + vld3.8 {d10, d11, d12}, [RGB]! + pld [RGB, #128] + .elseif \size == 4 + vld3.8 {d10[0], d11[0], d12[0]}, [RGB]! + vld3.8 {d10[1], d11[1], d12[1]}, [RGB]! + vld3.8 {d10[2], d11[2], d12[2]}, [RGB]! + vld3.8 {d10[3], d11[3], d12[3]}, [RGB]! + .elseif \size == 2 + vld3.8 {d10[4], d11[4], d12[4]}, [RGB]! + vld3.8 {d10[5], d11[5], d12[5]}, [RGB]! + .elseif \size == 1 + vld3.8 {d10[6], d11[6], d12[6]}, [RGB]! + .else + .error unsupported macroblock size + .endif + .elseif \bpp == 32 + .if \size == 8 + vld4.8 {d10, d11, d12, d13}, [RGB]! + pld [RGB, #128] + .elseif \size == 4 + vld4.8 {d10[0], d11[0], d12[0], d13[0]}, [RGB]! + vld4.8 {d10[1], d11[1], d12[1], d13[1]}, [RGB]! + vld4.8 {d10[2], d11[2], d12[2], d13[2]}, [RGB]! + vld4.8 {d10[3], d11[3], d12[3], d13[3]}, [RGB]! + .elseif \size == 2 + vld4.8 {d10[4], d11[4], d12[4], d13[4]}, [RGB]! + vld4.8 {d10[5], d11[5], d12[5], d13[5]}, [RGB]! + .elseif \size == 1 + vld4.8 {d10[6], d11[6], d12[6], d13[6]}, [RGB]! + .else + .error unsupported macroblock size + .endif + .else + .error unsupported bpp + .endif +.endm + +.macro generate_jsimd_rgb_ycc_convert_neon colorid, bpp, r_offs, g_offs, b_offs + +/* + * 2 stage pipelined RGB->YCbCr conversion + */ + +.macro do_rgb_to_yuv_stage1 + vmovl.u8 q2, d1\r_offs /* r = { d4, d5 } */ + vmovl.u8 q3, d1\g_offs /* g = { d6, d7 } */ + vmovl.u8 q4, d1\b_offs /* b = { d8, d9 } */ + vmull.u16 q7, d4, d0[0] + vmlal.u16 q7, d6, d0[1] + vmlal.u16 q7, d8, d0[2] + vmull.u16 q8, d5, d0[0] + vmlal.u16 q8, d7, d0[1] + vmlal.u16 q8, d9, d0[2] + vrev64.32 q9, q1 + vrev64.32 q13, q1 + vmlsl.u16 q9, d4, d0[3] + vmlsl.u16 q9, d6, d1[0] + vmlal.u16 q9, d8, d1[1] + vmlsl.u16 q13, d5, d0[3] + vmlsl.u16 q13, d7, d1[0] + vmlal.u16 q13, d9, d1[1] + vrev64.32 q14, q1 + vrev64.32 q15, q1 + vmlal.u16 q14, d4, d1[1] + vmlsl.u16 q14, d6, d1[2] + vmlsl.u16 q14, d8, d1[3] + vmlal.u16 q15, d5, d1[1] + vmlsl.u16 q15, d7, d1[2] + vmlsl.u16 q15, d9, d1[3] +.endm + +.macro do_rgb_to_yuv_stage2 + vrshrn.u32 d20, q7, #16 + vrshrn.u32 d21, q8, #16 + vshrn.u32 d22, q9, #16 + vshrn.u32 d23, q13, #16 + vshrn.u32 d24, q14, #16 + vshrn.u32 d25, q15, #16 + vmovn.u16 d20, q10 /* d20 = y */ + vmovn.u16 d21, q11 /* d21 = u */ + vmovn.u16 d22, q12 /* d22 = v */ +.endm + +.macro do_rgb_to_yuv + do_rgb_to_yuv_stage1 + do_rgb_to_yuv_stage2 +.endm + +.macro do_rgb_to_yuv_stage2_store_load_stage1 + vrshrn.u32 d20, q7, #16 + vrshrn.u32 d21, q8, #16 + vshrn.u32 d22, q9, #16 + vrev64.32 q9, q1 + vshrn.u32 d23, q13, #16 + vrev64.32 q13, q1 + vshrn.u32 d24, q14, #16 + vshrn.u32 d25, q15, #16 + do_load \bpp, 8 + vmovn.u16 d20, q10 /* d20 = y */ + vmovl.u8 q2, d1\r_offs /* r = { d4, d5 } */ + vmovn.u16 d21, q11 /* d21 = u */ + vmovl.u8 q3, d1\g_offs /* g = { d6, d7 } */ + vmovn.u16 d22, q12 /* d22 = v */ + vmovl.u8 q4, d1\b_offs /* b = { d8, d9 } */ + vmull.u16 q7, d4, d0[0] + vmlal.u16 q7, d6, d0[1] + vmlal.u16 q7, d8, d0[2] + vst1.8 {d20}, [Y]! + vmull.u16 q8, d5, d0[0] + vmlal.u16 q8, d7, d0[1] + vmlal.u16 q8, d9, d0[2] + vmlsl.u16 q9, d4, d0[3] + vmlsl.u16 q9, d6, d1[0] + vmlal.u16 q9, d8, d1[1] + vst1.8 {d21}, [U]! + vmlsl.u16 q13, d5, d0[3] + vmlsl.u16 q13, d7, d1[0] + vmlal.u16 q13, d9, d1[1] + vrev64.32 q14, q1 + vrev64.32 q15, q1 + vmlal.u16 q14, d4, d1[1] + vmlsl.u16 q14, d6, d1[2] + vmlsl.u16 q14, d8, d1[3] + vst1.8 {d22}, [V]! + vmlal.u16 q15, d5, d1[1] + vmlsl.u16 q15, d7, d1[2] + vmlsl.u16 q15, d9, d1[3] +.endm + +.balign 16 +jsimd_\colorid\()_ycc_neon_consts: + .short 19595, 38470, 7471, 11059 + .short 21709, 32768, 27439, 5329 + .short 32767, 128, 32767, 128 + .short 32767, 128, 32767, 128 + +asm_function jsimd_\colorid\()_ycc_convert_neon + OUTPUT_WIDTH .req r0 + INPUT_BUF .req r1 + OUTPUT_BUF .req r2 + OUTPUT_ROW .req r3 + NUM_ROWS .req r4 + + OUTPUT_BUF0 .req r5 + OUTPUT_BUF1 .req r6 + OUTPUT_BUF2 .req OUTPUT_BUF + + RGB .req r7 + Y .req r8 + U .req r9 + V .req r10 + N .req ip + + /* Load constants to d0, d1, d2, d3 */ + adr ip, jsimd_\colorid\()_ycc_neon_consts + vld1.16 {d0, d1, d2, d3}, [ip, :128] + + /* Save ARM registers and handle input arguments */ + push {r4, r5, r6, r7, r8, r9, r10, lr} + ldr NUM_ROWS, [sp, #(4 * 8)] + ldr OUTPUT_BUF0, [OUTPUT_BUF] + ldr OUTPUT_BUF1, [OUTPUT_BUF, #4] + ldr OUTPUT_BUF2, [OUTPUT_BUF, #8] + .unreq OUTPUT_BUF + + /* Save NEON registers */ + vpush {d8-d15} + + /* Outer loop over scanlines */ + cmp NUM_ROWS, #1 + blt 9f +0: + ldr Y, [OUTPUT_BUF0, OUTPUT_ROW, lsl #2] + ldr U, [OUTPUT_BUF1, OUTPUT_ROW, lsl #2] + mov N, OUTPUT_WIDTH + ldr V, [OUTPUT_BUF2, OUTPUT_ROW, lsl #2] + add OUTPUT_ROW, OUTPUT_ROW, #1 + ldr RGB, [INPUT_BUF], #4 + + /* Inner loop over pixels */ + subs N, N, #8 + blt 3f + do_load \bpp, 8 + do_rgb_to_yuv_stage1 + subs N, N, #8 + blt 2f +1: + do_rgb_to_yuv_stage2_store_load_stage1 + subs N, N, #8 + bge 1b +2: + do_rgb_to_yuv_stage2 + do_store 8 + tst N, #7 + beq 8f +3: + tst N, #4 + beq 3f + do_load \bpp, 4 +3: + tst N, #2 + beq 4f + do_load \bpp, 2 +4: + tst N, #1 + beq 5f + do_load \bpp, 1 +5: + do_rgb_to_yuv + tst N, #4 + beq 6f + do_store 4 +6: + tst N, #2 + beq 7f + do_store 2 +7: + tst N, #1 + beq 8f + do_store 1 +8: + subs NUM_ROWS, NUM_ROWS, #1 + bgt 0b +9: + /* Restore all registers and return */ + vpop {d8-d15} + pop {r4, r5, r6, r7, r8, r9, r10, pc} + + .unreq OUTPUT_WIDTH + .unreq OUTPUT_ROW + .unreq INPUT_BUF + .unreq NUM_ROWS + .unreq OUTPUT_BUF0 + .unreq OUTPUT_BUF1 + .unreq OUTPUT_BUF2 + .unreq RGB + .unreq Y + .unreq U + .unreq V + .unreq N +.endfunc + +.purgem do_rgb_to_yuv +.purgem do_rgb_to_yuv_stage1 +.purgem do_rgb_to_yuv_stage2 +.purgem do_rgb_to_yuv_stage2_store_load_stage1 + +.endm + +/*--------------------------------- id ----- bpp R G B */ +generate_jsimd_rgb_ycc_convert_neon extrgb, 24, 0, 1, 2 +generate_jsimd_rgb_ycc_convert_neon extbgr, 24, 2, 1, 0 +generate_jsimd_rgb_ycc_convert_neon extrgbx, 32, 0, 1, 2 +generate_jsimd_rgb_ycc_convert_neon extbgrx, 32, 2, 1, 0 +generate_jsimd_rgb_ycc_convert_neon extxbgr, 32, 3, 2, 1 +generate_jsimd_rgb_ycc_convert_neon extxrgb, 32, 1, 2, 3 + +.purgem do_load +.purgem do_store + +/*****************************************************************************/ + +/* + * Load data into workspace, applying unsigned->signed conversion + * + * TODO: can be combined with 'jsimd_fdct_ifast_neon' to get + * rid of VST1.16 instructions + */ + +asm_function jsimd_convsamp_neon + SAMPLE_DATA .req r0 + START_COL .req r1 + WORKSPACE .req r2 + TMP1 .req r3 + TMP2 .req r4 + TMP3 .req r5 + TMP4 .req ip + + push {r4, r5} + vmov.u8 d0, #128 + + ldmia SAMPLE_DATA!, {TMP1, TMP2, TMP3, TMP4} + add TMP1, TMP1, START_COL + add TMP2, TMP2, START_COL + add TMP3, TMP3, START_COL + add TMP4, TMP4, START_COL + vld1.8 {d16}, [TMP1] + vsubl.u8 q8, d16, d0 + vld1.8 {d18}, [TMP2] + vsubl.u8 q9, d18, d0 + vld1.8 {d20}, [TMP3] + vsubl.u8 q10, d20, d0 + vld1.8 {d22}, [TMP4] + ldmia SAMPLE_DATA!, {TMP1, TMP2, TMP3, TMP4} + vsubl.u8 q11, d22, d0 + vst1.16 {d16, d17, d18, d19}, [WORKSPACE, :128]! + add TMP1, TMP1, START_COL + add TMP2, TMP2, START_COL + vst1.16 {d20, d21, d22, d23}, [WORKSPACE, :128]! + add TMP3, TMP3, START_COL + add TMP4, TMP4, START_COL + vld1.8 {d24}, [TMP1] + vsubl.u8 q12, d24, d0 + vld1.8 {d26}, [TMP2] + vsubl.u8 q13, d26, d0 + vld1.8 {d28}, [TMP3] + vsubl.u8 q14, d28, d0 + vld1.8 {d30}, [TMP4] + vsubl.u8 q15, d30, d0 + vst1.16 {d24, d25, d26, d27}, [WORKSPACE, :128]! + vst1.16 {d28, d29, d30, d31}, [WORKSPACE, :128]! + pop {r4, r5} + bx lr + + .unreq SAMPLE_DATA + .unreq START_COL + .unreq WORKSPACE + .unreq TMP1 + .unreq TMP2 + .unreq TMP3 + .unreq TMP4 +.endfunc + +/*****************************************************************************/ + +/* + * jsimd_fdct_ifast_neon + * + * This function contains a fast, not so accurate integer implementation of + * the forward DCT (Discrete Cosine Transform). It uses the same calculations + * and produces exactly the same output as IJG's original 'jpeg_fdct_ifast' + * function from jfdctfst.c + * + * TODO: can be combined with 'jsimd_convsamp_neon' to get + * rid of a bunch of VLD1.16 instructions + */ + +#define XFIX_0_382683433 d0[0] +#define XFIX_0_541196100 d0[1] +#define XFIX_0_707106781 d0[2] +#define XFIX_1_306562965 d0[3] + +.balign 16 +jsimd_fdct_ifast_neon_consts: + .short (98 * 128) /* XFIX_0_382683433 */ + .short (139 * 128) /* XFIX_0_541196100 */ + .short (181 * 128) /* XFIX_0_707106781 */ + .short (334 * 128 - 256 * 128) /* XFIX_1_306562965 */ + +asm_function jsimd_fdct_ifast_neon + + DATA .req r0 + TMP .req ip + + vpush {d8-d15} + + /* Load constants */ + adr TMP, jsimd_fdct_ifast_neon_consts + vld1.16 {d0}, [TMP, :64] + + /* Load all DATA into NEON registers with the following allocation: + * 0 1 2 3 | 4 5 6 7 + * ---------+-------- + * 0 | d16 | d17 | q8 + * 1 | d18 | d19 | q9 + * 2 | d20 | d21 | q10 + * 3 | d22 | d23 | q11 + * 4 | d24 | d25 | q12 + * 5 | d26 | d27 | q13 + * 6 | d28 | d29 | q14 + * 7 | d30 | d31 | q15 + */ + + vld1.16 {d16, d17, d18, d19}, [DATA, :128]! + vld1.16 {d20, d21, d22, d23}, [DATA, :128]! + vld1.16 {d24, d25, d26, d27}, [DATA, :128]! + vld1.16 {d28, d29, d30, d31}, [DATA, :128] + sub DATA, DATA, #(128 - 32) + + mov TMP, #2 +1: + /* Transpose */ + vtrn.16 q12, q13 + vtrn.16 q10, q11 + vtrn.16 q8, q9 + vtrn.16 q14, q15 + vtrn.32 q9, q11 + vtrn.32 q13, q15 + vtrn.32 q8, q10 + vtrn.32 q12, q14 + vswp d30, d23 + vswp d24, d17 + vswp d26, d19 + /* 1-D FDCT */ + vadd.s16 q2, q11, q12 + vswp d28, d21 + vsub.s16 q12, q11, q12 + vsub.s16 q6, q10, q13 + vadd.s16 q10, q10, q13 + vsub.s16 q7, q9, q14 + vadd.s16 q9, q9, q14 + vsub.s16 q1, q8, q15 + vadd.s16 q8, q8, q15 + vsub.s16 q4, q9, q10 + vsub.s16 q5, q8, q2 + vadd.s16 q3, q9, q10 + vadd.s16 q4, q4, q5 + vadd.s16 q2, q8, q2 + vqdmulh.s16 q4, q4, XFIX_0_707106781 + vadd.s16 q11, q12, q6 + vadd.s16 q8, q2, q3 + vsub.s16 q12, q2, q3 + vadd.s16 q3, q6, q7 + vadd.s16 q7, q7, q1 + vqdmulh.s16 q3, q3, XFIX_0_707106781 + vsub.s16 q6, q11, q7 + vadd.s16 q10, q5, q4 + vqdmulh.s16 q6, q6, XFIX_0_382683433 + vsub.s16 q14, q5, q4 + vqdmulh.s16 q11, q11, XFIX_0_541196100 + vqdmulh.s16 q5, q7, XFIX_1_306562965 + vadd.s16 q4, q1, q3 + vsub.s16 q3, q1, q3 + vadd.s16 q7, q7, q6 + vadd.s16 q11, q11, q6 + vadd.s16 q7, q7, q5 + vadd.s16 q13, q3, q11 + vsub.s16 q11, q3, q11 + vadd.s16 q9, q4, q7 + vsub.s16 q15, q4, q7 + subs TMP, TMP, #1 + bne 1b + + /* store results */ + vst1.16 {d16, d17, d18, d19}, [DATA, :128]! + vst1.16 {d20, d21, d22, d23}, [DATA, :128]! + vst1.16 {d24, d25, d26, d27}, [DATA, :128]! + vst1.16 {d28, d29, d30, d31}, [DATA, :128] + + vpop {d8-d15} + bx lr + + .unreq DATA + .unreq TMP +.endfunc + +/*****************************************************************************/ + +/* + * GLOBAL(void) + * jsimd_quantize_neon (JCOEFPTR coef_block, DCTELEM * divisors, + * DCTELEM * workspace); + * + * Note: the code uses 2 stage pipelining in order to improve instructions + * scheduling and eliminate stalls (this provides ~15% better + * performance for this function on both ARM Cortex-A8 and + * ARM Cortex-A9 when compared to the non-pipelined variant). + * The instructions which belong to the second stage use different + * indentation for better readiability. + */ +asm_function jsimd_quantize_neon + + COEF_BLOCK .req r0 + DIVISORS .req r1 + WORKSPACE .req r2 + + RECIPROCAL .req DIVISORS + CORRECTION .req r3 + SHIFT .req ip + LOOP_COUNT .req r4 + + vld1.16 {d0, d1, d2, d3}, [WORKSPACE, :128]! + vabs.s16 q12, q0 + add CORRECTION, DIVISORS, #(64 * 2) + add SHIFT, DIVISORS, #(64 * 6) + vld1.16 {d20, d21, d22, d23}, [CORRECTION, :128]! + vabs.s16 q13, q1 + vld1.16 {d16, d17, d18, d19}, [RECIPROCAL, :128]! + vadd.u16 q12, q12, q10 /* add correction */ + vadd.u16 q13, q13, q11 + vmull.u16 q10, d24, d16 /* multiply by reciprocal */ + vmull.u16 q11, d25, d17 + vmull.u16 q8, d26, d18 + vmull.u16 q9, d27, d19 + vld1.16 {d24, d25, d26, d27}, [SHIFT, :128]! + vshrn.u32 d20, q10, #16 + vshrn.u32 d21, q11, #16 + vshrn.u32 d22, q8, #16 + vshrn.u32 d23, q9, #16 + vneg.s16 q12, q12 + vneg.s16 q13, q13 + vshr.s16 q2, q0, #15 /* extract sign */ + vshr.s16 q3, q1, #15 + vshl.u16 q14, q10, q12 /* shift */ + vshl.u16 q15, q11, q13 + + push {r4, r5} + mov LOOP_COUNT, #3 +1: + vld1.16 {d0, d1, d2, d3}, [WORKSPACE, :128]! + veor.u16 q14, q14, q2 /* restore sign */ + vabs.s16 q12, q0 + vld1.16 {d20, d21, d22, d23}, [CORRECTION, :128]! + vabs.s16 q13, q1 + veor.u16 q15, q15, q3 + vld1.16 {d16, d17, d18, d19}, [RECIPROCAL, :128]! + vadd.u16 q12, q12, q10 /* add correction */ + vadd.u16 q13, q13, q11 + vmull.u16 q10, d24, d16 /* multiply by reciprocal */ + vmull.u16 q11, d25, d17 + vmull.u16 q8, d26, d18 + vmull.u16 q9, d27, d19 + vsub.u16 q14, q14, q2 + vld1.16 {d24, d25, d26, d27}, [SHIFT, :128]! + vsub.u16 q15, q15, q3 + vshrn.u32 d20, q10, #16 + vshrn.u32 d21, q11, #16 + vst1.16 {d28, d29, d30, d31}, [COEF_BLOCK, :128]! + vshrn.u32 d22, q8, #16 + vshrn.u32 d23, q9, #16 + vneg.s16 q12, q12 + vneg.s16 q13, q13 + vshr.s16 q2, q0, #15 /* extract sign */ + vshr.s16 q3, q1, #15 + vshl.u16 q14, q10, q12 /* shift */ + vshl.u16 q15, q11, q13 + subs LOOP_COUNT, LOOP_COUNT, #1 + bne 1b + pop {r4, r5} + + veor.u16 q14, q14, q2 /* restore sign */ + veor.u16 q15, q15, q3 + vsub.u16 q14, q14, q2 + vsub.u16 q15, q15, q3 + vst1.16 {d28, d29, d30, d31}, [COEF_BLOCK, :128]! + + bx lr /* return */ + + .unreq COEF_BLOCK + .unreq DIVISORS + .unreq WORKSPACE + .unreq RECIPROCAL + .unreq CORRECTION + .unreq SHIFT + .unreq LOOP_COUNT +.endfunc diff --git a/media/libjpeg/simd/jsimd_i386.c b/media/libjpeg/simd/jsimd_i386.c index d9bb774352a5..e96f5b8d79cd 100644 --- a/media/libjpeg/simd/jsimd_i386.c +++ b/media/libjpeg/simd/jsimd_i386.c @@ -2,7 +2,7 @@ * jsimd_i386.c * * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright 2009 D. R. Commander + * Copyright 2009-2011 D. R. Commander * * Based on the x86 SIMD extension for IJG JPEG library, * Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -41,7 +41,7 @@ init_simd (void) { char *env = NULL; - if (simd_support != ~0) + if (simd_support != ~0U) return; simd_support = jpeg_simd_cpu_support(); @@ -83,6 +83,28 @@ jsimd_can_rgb_ycc (void) return 0; } +GLOBAL(int) +jsimd_can_rgb_gray (void) +{ + init_simd(); + + /* The code is optimised for these values only */ + if (BITS_IN_JSAMPLE != 8) + return 0; + if (sizeof(JDIMENSION) != 4) + return 0; + if ((RGB_PIXELSIZE != 3) && (RGB_PIXELSIZE != 4)) + return 0; + + if ((simd_support & JSIMD_SSE2) && + IS_ALIGNED_SSE(jconst_rgb_gray_convert_sse2)) + return 1; + if (simd_support & JSIMD_MMX) + return 1; + + return 0; +} + GLOBAL(int) jsimd_can_ycc_rgb (void) { @@ -120,6 +142,7 @@ jsimd_rgb_ycc_convert (j_compress_ptr cinfo, mmxfct=jsimd_extrgb_ycc_convert_mmx; break; case JCS_EXT_RGBX: + case JCS_EXT_RGBA: sse2fct=jsimd_extrgbx_ycc_convert_sse2; mmxfct=jsimd_extrgbx_ycc_convert_mmx; break; @@ -128,14 +151,17 @@ jsimd_rgb_ycc_convert (j_compress_ptr cinfo, mmxfct=jsimd_extbgr_ycc_convert_mmx; break; case JCS_EXT_BGRX: + case JCS_EXT_BGRA: sse2fct=jsimd_extbgrx_ycc_convert_sse2; mmxfct=jsimd_extbgrx_ycc_convert_mmx; break; case JCS_EXT_XBGR: + case JCS_EXT_ABGR: sse2fct=jsimd_extxbgr_ycc_convert_sse2; mmxfct=jsimd_extxbgr_ycc_convert_mmx; break; case JCS_EXT_XRGB: + case JCS_EXT_ARGB: sse2fct=jsimd_extxrgb_ycc_convert_sse2; mmxfct=jsimd_extxrgb_ycc_convert_mmx; break; @@ -154,6 +180,59 @@ jsimd_rgb_ycc_convert (j_compress_ptr cinfo, output_buf, output_row, num_rows); } +GLOBAL(void) +jsimd_rgb_gray_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + void (*sse2fct)(JDIMENSION, JSAMPARRAY, JSAMPIMAGE, JDIMENSION, int); + void (*mmxfct)(JDIMENSION, JSAMPARRAY, JSAMPIMAGE, JDIMENSION, int); + + switch(cinfo->in_color_space) + { + case JCS_EXT_RGB: + sse2fct=jsimd_extrgb_gray_convert_sse2; + mmxfct=jsimd_extrgb_gray_convert_mmx; + break; + case JCS_EXT_RGBX: + case JCS_EXT_RGBA: + sse2fct=jsimd_extrgbx_gray_convert_sse2; + mmxfct=jsimd_extrgbx_gray_convert_mmx; + break; + case JCS_EXT_BGR: + sse2fct=jsimd_extbgr_gray_convert_sse2; + mmxfct=jsimd_extbgr_gray_convert_mmx; + break; + case JCS_EXT_BGRX: + case JCS_EXT_BGRA: + sse2fct=jsimd_extbgrx_gray_convert_sse2; + mmxfct=jsimd_extbgrx_gray_convert_mmx; + break; + case JCS_EXT_XBGR: + case JCS_EXT_ABGR: + sse2fct=jsimd_extxbgr_gray_convert_sse2; + mmxfct=jsimd_extxbgr_gray_convert_mmx; + break; + case JCS_EXT_XRGB: + case JCS_EXT_ARGB: + sse2fct=jsimd_extxrgb_gray_convert_sse2; + mmxfct=jsimd_extxrgb_gray_convert_mmx; + break; + default: + sse2fct=jsimd_rgb_gray_convert_sse2; + mmxfct=jsimd_rgb_gray_convert_mmx; + break; + } + + if ((simd_support & JSIMD_SSE2) && + IS_ALIGNED_SSE(jconst_rgb_gray_convert_sse2)) + sse2fct(cinfo->image_width, input_buf, + output_buf, output_row, num_rows); + else if (simd_support & JSIMD_MMX) + mmxfct(cinfo->image_width, input_buf, + output_buf, output_row, num_rows); +} + GLOBAL(void) jsimd_ycc_rgb_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, @@ -169,6 +248,7 @@ jsimd_ycc_rgb_convert (j_decompress_ptr cinfo, mmxfct=jsimd_ycc_extrgb_convert_mmx; break; case JCS_EXT_RGBX: + case JCS_EXT_RGBA: sse2fct=jsimd_ycc_extrgbx_convert_sse2; mmxfct=jsimd_ycc_extrgbx_convert_mmx; break; @@ -177,14 +257,17 @@ jsimd_ycc_rgb_convert (j_decompress_ptr cinfo, mmxfct=jsimd_ycc_extbgr_convert_mmx; break; case JCS_EXT_BGRX: + case JCS_EXT_BGRA: sse2fct=jsimd_ycc_extbgrx_convert_sse2; mmxfct=jsimd_ycc_extbgrx_convert_mmx; break; case JCS_EXT_XBGR: + case JCS_EXT_ABGR: sse2fct=jsimd_ycc_extxbgr_convert_sse2; mmxfct=jsimd_ycc_extxbgr_convert_mmx; break; case JCS_EXT_XRGB: + case JCS_EXT_ARGB: sse2fct=jsimd_ycc_extxrgb_convert_sse2; mmxfct=jsimd_ycc_extxrgb_convert_mmx; break; @@ -461,6 +544,7 @@ jsimd_h2v2_merged_upsample (j_decompress_ptr cinfo, mmxfct=jsimd_h2v2_extrgb_merged_upsample_mmx; break; case JCS_EXT_RGBX: + case JCS_EXT_RGBA: sse2fct=jsimd_h2v2_extrgbx_merged_upsample_sse2; mmxfct=jsimd_h2v2_extrgbx_merged_upsample_mmx; break; @@ -469,14 +553,17 @@ jsimd_h2v2_merged_upsample (j_decompress_ptr cinfo, mmxfct=jsimd_h2v2_extbgr_merged_upsample_mmx; break; case JCS_EXT_BGRX: + case JCS_EXT_BGRA: sse2fct=jsimd_h2v2_extbgrx_merged_upsample_sse2; mmxfct=jsimd_h2v2_extbgrx_merged_upsample_mmx; break; case JCS_EXT_XBGR: + case JCS_EXT_ABGR: sse2fct=jsimd_h2v2_extxbgr_merged_upsample_sse2; mmxfct=jsimd_h2v2_extxbgr_merged_upsample_mmx; break; case JCS_EXT_XRGB: + case JCS_EXT_ARGB: sse2fct=jsimd_h2v2_extxrgb_merged_upsample_sse2; mmxfct=jsimd_h2v2_extxrgb_merged_upsample_mmx; break; @@ -511,6 +598,7 @@ jsimd_h2v1_merged_upsample (j_decompress_ptr cinfo, mmxfct=jsimd_h2v1_extrgb_merged_upsample_mmx; break; case JCS_EXT_RGBX: + case JCS_EXT_RGBA: sse2fct=jsimd_h2v1_extrgbx_merged_upsample_sse2; mmxfct=jsimd_h2v1_extrgbx_merged_upsample_mmx; break; @@ -519,14 +607,17 @@ jsimd_h2v1_merged_upsample (j_decompress_ptr cinfo, mmxfct=jsimd_h2v1_extbgr_merged_upsample_mmx; break; case JCS_EXT_BGRX: + case JCS_EXT_BGRA: sse2fct=jsimd_h2v1_extbgrx_merged_upsample_sse2; mmxfct=jsimd_h2v1_extbgrx_merged_upsample_mmx; break; case JCS_EXT_XBGR: + case JCS_EXT_ABGR: sse2fct=jsimd_h2v1_extxbgr_merged_upsample_sse2; mmxfct=jsimd_h2v1_extxbgr_merged_upsample_mmx; break; case JCS_EXT_XRGB: + case JCS_EXT_ARGB: sse2fct=jsimd_h2v1_extxrgb_merged_upsample_sse2; mmxfct=jsimd_h2v1_extxrgb_merged_upsample_mmx; break; diff --git a/media/libjpeg/simd/jsimd_x86_64.c b/media/libjpeg/simd/jsimd_x86_64.c index 7659249e14c0..8d17db30967d 100644 --- a/media/libjpeg/simd/jsimd_x86_64.c +++ b/media/libjpeg/simd/jsimd_x86_64.c @@ -2,7 +2,7 @@ * jsimd_x86_64.c * * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright 2009 D. R. Commander + * Copyright 2009-2011 D. R. Commander * * Based on the x86 SIMD extension for IJG JPEG library, * Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -46,6 +46,23 @@ jsimd_can_rgb_ycc (void) return 1; } +GLOBAL(int) +jsimd_can_rgb_gray (void) +{ + /* The code is optimised for these values only */ + if (BITS_IN_JSAMPLE != 8) + return 0; + if (sizeof(JDIMENSION) != 4) + return 0; + if ((RGB_PIXELSIZE != 3) && (RGB_PIXELSIZE != 4)) + return 0; + + if (!IS_ALIGNED_SSE(jconst_rgb_gray_convert_sse2)) + return 0; + + return 1; +} + GLOBAL(int) jsimd_can_ycc_rgb (void) { @@ -76,18 +93,22 @@ jsimd_rgb_ycc_convert (j_compress_ptr cinfo, sse2fct=jsimd_extrgb_ycc_convert_sse2; break; case JCS_EXT_RGBX: + case JCS_EXT_RGBA: sse2fct=jsimd_extrgbx_ycc_convert_sse2; break; case JCS_EXT_BGR: sse2fct=jsimd_extbgr_ycc_convert_sse2; break; case JCS_EXT_BGRX: + case JCS_EXT_BGRA: sse2fct=jsimd_extbgrx_ycc_convert_sse2; break; case JCS_EXT_XBGR: + case JCS_EXT_ABGR: sse2fct=jsimd_extxbgr_ycc_convert_sse2; break; case JCS_EXT_XRGB: + case JCS_EXT_ARGB: sse2fct=jsimd_extxrgb_ycc_convert_sse2; break; default: @@ -98,6 +119,45 @@ jsimd_rgb_ycc_convert (j_compress_ptr cinfo, sse2fct(cinfo->image_width, input_buf, output_buf, output_row, num_rows); } +GLOBAL(void) +jsimd_rgb_gray_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + void (*sse2fct)(JDIMENSION, JSAMPARRAY, JSAMPIMAGE, JDIMENSION, int); + + switch(cinfo->in_color_space) + { + case JCS_EXT_RGB: + sse2fct=jsimd_extrgb_gray_convert_sse2; + break; + case JCS_EXT_RGBX: + case JCS_EXT_RGBA: + sse2fct=jsimd_extrgbx_gray_convert_sse2; + break; + case JCS_EXT_BGR: + sse2fct=jsimd_extbgr_gray_convert_sse2; + break; + case JCS_EXT_BGRX: + case JCS_EXT_BGRA: + sse2fct=jsimd_extbgrx_gray_convert_sse2; + break; + case JCS_EXT_XBGR: + case JCS_EXT_ABGR: + sse2fct=jsimd_extxbgr_gray_convert_sse2; + break; + case JCS_EXT_XRGB: + case JCS_EXT_ARGB: + sse2fct=jsimd_extxrgb_gray_convert_sse2; + break; + default: + sse2fct=jsimd_rgb_gray_convert_sse2; + break; + } + + sse2fct(cinfo->image_width, input_buf, output_buf, output_row, num_rows); +} + GLOBAL(void) jsimd_ycc_rgb_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, @@ -111,18 +171,22 @@ jsimd_ycc_rgb_convert (j_decompress_ptr cinfo, sse2fct=jsimd_ycc_extrgb_convert_sse2; break; case JCS_EXT_RGBX: + case JCS_EXT_RGBA: sse2fct=jsimd_ycc_extrgbx_convert_sse2; break; case JCS_EXT_BGR: sse2fct=jsimd_ycc_extbgr_convert_sse2; break; case JCS_EXT_BGRX: + case JCS_EXT_BGRA: sse2fct=jsimd_ycc_extbgrx_convert_sse2; break; case JCS_EXT_XBGR: + case JCS_EXT_ABGR: sse2fct=jsimd_ycc_extxbgr_convert_sse2; break; case JCS_EXT_XRGB: + case JCS_EXT_ARGB: sse2fct=jsimd_ycc_extxrgb_convert_sse2; break; default: @@ -321,18 +385,22 @@ jsimd_h2v2_merged_upsample (j_decompress_ptr cinfo, sse2fct=jsimd_h2v2_extrgb_merged_upsample_sse2; break; case JCS_EXT_RGBX: + case JCS_EXT_RGBA: sse2fct=jsimd_h2v2_extrgbx_merged_upsample_sse2; break; case JCS_EXT_BGR: sse2fct=jsimd_h2v2_extbgr_merged_upsample_sse2; break; case JCS_EXT_BGRX: + case JCS_EXT_BGRA: sse2fct=jsimd_h2v2_extbgrx_merged_upsample_sse2; break; case JCS_EXT_XBGR: + case JCS_EXT_ABGR: sse2fct=jsimd_h2v2_extxbgr_merged_upsample_sse2; break; case JCS_EXT_XRGB: + case JCS_EXT_ARGB: sse2fct=jsimd_h2v2_extxrgb_merged_upsample_sse2; break; default: @@ -357,18 +425,22 @@ jsimd_h2v1_merged_upsample (j_decompress_ptr cinfo, sse2fct=jsimd_h2v1_extrgb_merged_upsample_sse2; break; case JCS_EXT_RGBX: + case JCS_EXT_RGBA: sse2fct=jsimd_h2v1_extrgbx_merged_upsample_sse2; break; case JCS_EXT_BGR: sse2fct=jsimd_h2v1_extbgr_merged_upsample_sse2; break; case JCS_EXT_BGRX: + case JCS_EXT_BGRA: sse2fct=jsimd_h2v1_extbgrx_merged_upsample_sse2; break; case JCS_EXT_XBGR: + case JCS_EXT_ABGR: sse2fct=jsimd_h2v1_extxbgr_merged_upsample_sse2; break; case JCS_EXT_XRGB: + case JCS_EXT_ARGB: sse2fct=jsimd_h2v1_extxrgb_merged_upsample_sse2; break; default: diff --git a/media/libjpeg/simd/jsimdcfg.inc b/media/libjpeg/simd/jsimdcfg.inc index 68e22e8691f1..9d4aedec9e36 100644 --- a/media/libjpeg/simd/jsimdcfg.inc +++ b/media/libjpeg/simd/jsimdcfg.inc @@ -13,6 +13,31 @@ %define RGB_GREEN 1 %define RGB_BLUE 2 %define RGB_PIXELSIZE 3 +%define EXT_RGB_RED 0 +%define EXT_RGB_GREEN 1 +%define EXT_RGB_BLUE 2 +%define EXT_RGB_PIXELSIZE 3 +%define EXT_RGBX_RED 0 +%define EXT_RGBX_GREEN 1 +%define EXT_RGBX_BLUE 2 +%define EXT_RGBX_PIXELSIZE 4 +%define EXT_BGR_RED 2 +%define EXT_BGR_GREEN 1 +%define EXT_BGR_BLUE 0 +%define EXT_BGR_PIXELSIZE 3 +%define EXT_BGRX_RED 2 +%define EXT_BGRX_GREEN 1 +%define EXT_BGRX_BLUE 0 +%define EXT_BGRX_PIXELSIZE 4 +%define EXT_XBGR_RED 3 +%define EXT_XBGR_GREEN 2 +%define EXT_XBGR_BLUE 1 +%define EXT_XBGR_PIXELSIZE 4 +%define EXT_XRGB_RED 1 +%define EXT_XRGB_GREEN 2 +%define EXT_XRGB_BLUE 3 +%define EXT_XRGB_PIXELSIZE 4 +%define RGBX_FILLER_0XFF 1 ; Representation of a single sample (pixel element value). ; On this SIMD implementation, this must be 'unsigned char'. ; diff --git a/media/libjpeg/simd/jsimdcfg.inc.h b/media/libjpeg/simd/jsimdcfg.inc.h deleted file mode 100644 index 4876038bc8c5..000000000000 --- a/media/libjpeg/simd/jsimdcfg.inc.h +++ /dev/null @@ -1,168 +0,0 @@ -// This file generates the include file for the assembly -// implementations by abusing the C preprocessor. -// -// Note: Some things are manually defined as they need to -// be mapped to NASM types. - -; -; Automatically generated include file from jsimdcfg.inc.h -; - -#define JPEG_INTERNALS - -#include "../jpeglib.h" -#include "../jconfig.h" -#include "../jmorecfg.h" -#include "jsimd.h" - -#define define(var) %define _cpp_protection_##var -#define definev(var) %define _cpp_protection_##var var - -; -; -- jpeglib.h -; - -definev(DCTSIZE) -definev(DCTSIZE2) - -; -; -- jmorecfg.h -; - -definev(RGB_RED) -definev(RGB_GREEN) -definev(RGB_BLUE) - -definev(RGB_PIXELSIZE) - -; Representation of a single sample (pixel element value). -; On this SIMD implementation, this must be 'unsigned char'. -; - -%define JSAMPLE byte ; unsigned char -%define SIZEOF_JSAMPLE SIZEOF_BYTE ; sizeof(JSAMPLE) - -definev(CENTERJSAMPLE) - -; Representation of a DCT frequency coefficient. -; On this SIMD implementation, this must be 'short'. -; -%define JCOEF word ; short -%define SIZEOF_JCOEF SIZEOF_WORD ; sizeof(JCOEF) - -; Datatype used for image dimensions. -; On this SIMD implementation, this must be 'unsigned int'. -; -%define JDIMENSION dword ; unsigned int -%define SIZEOF_JDIMENSION SIZEOF_DWORD ; sizeof(JDIMENSION) - -%define JSAMPROW POINTER ; JSAMPLE FAR * (jpeglib.h) -%define JSAMPARRAY POINTER ; JSAMPROW * (jpeglib.h) -%define JSAMPIMAGE POINTER ; JSAMPARRAY * (jpeglib.h) -%define JCOEFPTR POINTER ; JCOEF FAR * (jpeglib.h) -%define SIZEOF_JSAMPROW SIZEOF_POINTER ; sizeof(JSAMPROW) -%define SIZEOF_JSAMPARRAY SIZEOF_POINTER ; sizeof(JSAMPARRAY) -%define SIZEOF_JSAMPIMAGE SIZEOF_POINTER ; sizeof(JSAMPIMAGE) -%define SIZEOF_JCOEFPTR SIZEOF_POINTER ; sizeof(JCOEFPTR) - -; -; -- jdct.h -; - -; A forward DCT routine is given a pointer to a work area of type DCTELEM[]; -; the DCT is to be performed in-place in that buffer. -; To maximize parallelism, Type DCTELEM is changed to short (originally, int). -; -%define DCTELEM word ; short -%define SIZEOF_DCTELEM SIZEOF_WORD ; sizeof(DCTELEM) - -%define FAST_FLOAT FP32 ; float -%define SIZEOF_FAST_FLOAT SIZEOF_FP32 ; sizeof(FAST_FLOAT) - -; To maximize parallelism, Type MULTIPLIER is changed to short. -; -%define ISLOW_MULT_TYPE word ; must be short -%define SIZEOF_ISLOW_MULT_TYPE SIZEOF_WORD ; sizeof(ISLOW_MULT_TYPE) - -%define IFAST_MULT_TYPE word ; must be short -%define SIZEOF_IFAST_MULT_TYPE SIZEOF_WORD ; sizeof(IFAST_MULT_TYPE) -%define IFAST_SCALE_BITS 2 ; fractional bits in scale factors - -%define FLOAT_MULT_TYPE FP32 ; must be float -%define SIZEOF_FLOAT_MULT_TYPE SIZEOF_FP32 ; sizeof(FLOAT_MULT_TYPE) - -; -; -- jsimd.h -; - -definev(JSIMD_NONE) -definev(JSIMD_MMX) -definev(JSIMD_3DNOW) -definev(JSIMD_SSE) -definev(JSIMD_SSE2) - -; Short forms of external names for systems with brain-damaged linkers. -; -#ifdef NEED_SHORT_EXTERNAL_NAMES -definev(jpeg_simd_cpu_support) -definev(jsimd_rgb_ycc_convert_mmx) -definev(jsimd_ycc_rgb_convert_mmx) -definev(jconst_rgb_ycc_convert_sse2) -definev(jsimd_rgb_ycc_convert_sse2) -definev(jconst_ycc_rgb_convert_sse2) -definev(jsimd_ycc_rgb_convert_sse2) -definev(jsimd_h2v2_downsample_mmx) -definev(jsimd_h2v1_downsample_mmx) -definev(jsimd_h2v2_downsample_sse2) -definev(jsimd_h2v1_downsample_sse2) -definev(jsimd_h2v2_upsample_mmx) -definev(jsimd_h2v1_upsample_mmx) -definev(jsimd_h2v1_fancy_upsample_mmx) -definev(jsimd_h2v2_fancy_upsample_mmx) -definev(jsimd_h2v1_merged_upsample_mmx) -definev(jsimd_h2v2_merged_upsample_mmx) -definev(jsimd_h2v2_upsample_sse2) -definev(jsimd_h2v1_upsample_sse2) -definev(jconst_fancy_upsample_sse2) -definev(jsimd_h2v1_fancy_upsample_sse2) -definev(jsimd_h2v2_fancy_upsample_sse2) -definev(jconst_merged_upsample_sse2) -definev(jsimd_h2v1_merged_upsample_sse2) -definev(jsimd_h2v2_merged_upsample_sse2) -definev(jsimd_convsamp_mmx) -definev(jsimd_convsamp_sse2) -definev(jsimd_convsamp_float_3dnow) -definev(jsimd_convsamp_float_sse) -definev(jsimd_convsamp_float_sse2) -definev(jsimd_fdct_islow_mmx) -definev(jsimd_fdct_ifast_mmx) -definev(jconst_fdct_islow_sse2) -definev(jsimd_fdct_islow_sse2) -definev(jconst_fdct_ifast_sse2) -definev(jsimd_fdct_ifast_sse2) -definev(jsimd_fdct_float_3dnow) -definev(jconst_fdct_float_sse) -definev(jsimd_fdct_float_sse) -definev(jsimd_quantize_mmx) -definev(jsimd_quantize_sse2) -definev(jsimd_quantize_float_3dnow) -definev(jsimd_quantize_float_sse) -definev(jsimd_quantize_float_sse2) -definev(jsimd_idct_2x2_mmx) -definev(jsimd_idct_4x4_mmx) -definev(jconst_idct_red_sse2) -definev(jsimd_idct_2x2_sse2) -definev(jsimd_idct_4x4_sse2) -definev(jsimd_idct_islow_mmx) -definev(jsimd_idct_ifast_mmx) -definev(jconst_idct_islow_sse2) -definev(jsimd_idct_islow_sse2) -definev(jconst_idct_ifast_sse2) -definev(jsimd_idct_ifast_sse2) -definev(jsimd_idct_float_3dnow) -definev(jconst_idct_float_sse) -definev(jsimd_idct_float_sse) -definev(jconst_idct_float_sse2) -definev(jsimd_idct_float_sse2) -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - diff --git a/media/libjpeg/simd/jsimdext.inc b/media/libjpeg/simd/jsimdext.inc index 4ea3d17c577a..4ab9bc0facd9 100644 --- a/media/libjpeg/simd/jsimdext.inc +++ b/media/libjpeg/simd/jsimdext.inc @@ -38,19 +38,27 @@ ; -- segment definition -- ; +%ifdef __YASM_VER__ +%define SEG_TEXT .text align=16 +%define SEG_CONST .rdata align=16 +%else %define SEG_TEXT .text align=16 public use32 class=CODE %define SEG_CONST .rdata align=16 public use32 class=CONST +%endif %elifdef WIN64 ; ----(nasm -fwin64 -DWIN64 ...)-------- ; * Microsoft Visual C++ ; -- segment definition -- ; +%ifdef __YASM_VER__ +%define SEG_TEXT .text align=16 +%define SEG_CONST .rdata align=16 +%else %define SEG_TEXT .text align=16 public use64 class=CODE %define SEG_CONST .rdata align=16 public use64 class=CONST -%ifdef MSVC -%define EXTN(name) name ; foo() -> foo %endif +%define EXTN(name) name ; foo() -> foo %elifdef OBJ32 ; ----(nasm -fobj -DOBJ32 ...)---------- ; * Borland C++ (Win32) @@ -78,6 +86,8 @@ section .note.GNU-stack noalloc noexec nowrite progbits %define SEG_CONST .rodata progbits alloc noexec nowrite align=16 %endif +%define STRICT_MEMORY_ACCESS 1 + ; To make the code position-independent, append -DPIC to the commandline ; %define GOT_SYMBOL _GLOBAL_OFFSET_TABLE_ ; ELF supports PIC @@ -299,8 +309,6 @@ const_base: %ifdef WIN64 %imacro collect_args 0 - push r10 - push r11 push r12 push r13 push r14 @@ -330,8 +338,6 @@ const_base: pop r14 pop r13 pop r12 - pop r11 - pop r10 %endmacro %else diff --git a/media/libjpeg/transupp.h b/media/libjpeg/transupp.h deleted file mode 100644 index 7c16c19c440d..000000000000 --- a/media/libjpeg/transupp.h +++ /dev/null @@ -1,210 +0,0 @@ -/* - * transupp.h - * - * Copyright (C) 1997-2009, Thomas G. Lane, Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains declarations for image transformation routines and - * other utility code used by the jpegtran sample application. These are - * NOT part of the core JPEG library. But we keep these routines separate - * from jpegtran.c to ease the task of maintaining jpegtran-like programs - * that have other user interfaces. - * - * NOTE: all the routines declared here have very specific requirements - * about when they are to be executed during the reading and writing of the - * source and destination files. See the comments in transupp.c, or see - * jpegtran.c for an example of correct usage. - */ - -/* If you happen not to want the image transform support, disable it here */ -#ifndef TRANSFORMS_SUPPORTED -#define TRANSFORMS_SUPPORTED 1 /* 0 disables transform code */ -#endif - -/* - * Although rotating and flipping data expressed as DCT coefficients is not - * hard, there is an asymmetry in the JPEG format specification for images - * whose dimensions aren't multiples of the iMCU size. The right and bottom - * image edges are padded out to the next iMCU boundary with junk data; but - * no padding is possible at the top and left edges. If we were to flip - * the whole image including the pad data, then pad garbage would become - * visible at the top and/or left, and real pixels would disappear into the - * pad margins --- perhaps permanently, since encoders & decoders may not - * bother to preserve DCT blocks that appear to be completely outside the - * nominal image area. So, we have to exclude any partial iMCUs from the - * basic transformation. - * - * Transpose is the only transformation that can handle partial iMCUs at the - * right and bottom edges completely cleanly. flip_h can flip partial iMCUs - * at the bottom, but leaves any partial iMCUs at the right edge untouched. - * Similarly flip_v leaves any partial iMCUs at the bottom edge untouched. - * The other transforms are defined as combinations of these basic transforms - * and process edge blocks in a way that preserves the equivalence. - * - * The "trim" option causes untransformable partial iMCUs to be dropped; - * this is not strictly lossless, but it usually gives the best-looking - * result for odd-size images. Note that when this option is active, - * the expected mathematical equivalences between the transforms may not hold. - * (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim - * followed by -rot 180 -trim trims both edges.) - * - * We also offer a lossless-crop option, which discards data outside a given - * image region but losslessly preserves what is inside. Like the rotate and - * flip transforms, lossless crop is restricted by the JPEG format: the upper - * left corner of the selected region must fall on an iMCU boundary. If this - * does not hold for the given crop parameters, we silently move the upper left - * corner up and/or left to make it so, simultaneously increasing the region - * dimensions to keep the lower right crop corner unchanged. (Thus, the - * output image covers at least the requested region, but may cover more.) - * - * We also provide a lossless-resize option, which is kind of a lossless-crop - * operation in the DCT coefficient block domain - it discards higher-order - * coefficients and losslessly preserves lower-order coefficients of a - * sub-block. - * - * Rotate/flip transform, resize, and crop can be requested together in a - * single invocation. The crop is applied last --- that is, the crop region - * is specified in terms of the destination image after transform/resize. - * - * We also offer a "force to grayscale" option, which simply discards the - * chrominance channels of a YCbCr image. This is lossless in the sense that - * the luminance channel is preserved exactly. It's not the same kind of - * thing as the rotate/flip transformations, but it's convenient to handle it - * as part of this package, mainly because the transformation routines have to - * be aware of the option to know how many components to work on. - */ - - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jtransform_parse_crop_spec jTrParCrop -#define jtransform_request_workspace jTrRequest -#define jtransform_adjust_parameters jTrAdjust -#define jtransform_execute_transform jTrExec -#define jtransform_perfect_transform jTrPerfect -#define jcopy_markers_setup jCMrkSetup -#define jcopy_markers_execute jCMrkExec -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* - * Codes for supported types of image transformations. - */ - -typedef enum { - JXFORM_NONE, /* no transformation */ - JXFORM_FLIP_H, /* horizontal flip */ - JXFORM_FLIP_V, /* vertical flip */ - JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */ - JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */ - JXFORM_ROT_90, /* 90-degree clockwise rotation */ - JXFORM_ROT_180, /* 180-degree rotation */ - JXFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) */ -} JXFORM_CODE; - -/* - * Codes for crop parameters, which can individually be unspecified, - * positive, or negative. (Negative width or height makes no sense, though.) - */ - -typedef enum { - JCROP_UNSET, - JCROP_POS, - JCROP_NEG -} JCROP_CODE; - -/* - * Transform parameters struct. - * NB: application must not change any elements of this struct after - * calling jtransform_request_workspace. - */ - -typedef struct { - /* Options: set by caller */ - JXFORM_CODE transform; /* image transform operator */ - boolean perfect; /* if TRUE, fail if partial MCUs are requested */ - boolean trim; /* if TRUE, trim partial MCUs as needed */ - boolean force_grayscale; /* if TRUE, convert color image to grayscale */ - boolean crop; /* if TRUE, crop source image */ - - /* Crop parameters: application need not set these unless crop is TRUE. - * These can be filled in by jtransform_parse_crop_spec(). - */ - JDIMENSION crop_width; /* Width of selected region */ - JCROP_CODE crop_width_set; - JDIMENSION crop_height; /* Height of selected region */ - JCROP_CODE crop_height_set; - JDIMENSION crop_xoffset; /* X offset of selected region */ - JCROP_CODE crop_xoffset_set; /* (negative measures from right edge) */ - JDIMENSION crop_yoffset; /* Y offset of selected region */ - JCROP_CODE crop_yoffset_set; /* (negative measures from bottom edge) */ - - /* Internal workspace: caller should not touch these */ - int num_components; /* # of components in workspace */ - jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */ - JDIMENSION output_width; /* cropped destination dimensions */ - JDIMENSION output_height; - JDIMENSION x_crop_offset; /* destination crop offsets measured in iMCUs */ - JDIMENSION y_crop_offset; - int iMCU_sample_width; /* destination iMCU size */ - int iMCU_sample_height; -} jpeg_transform_info; - - -#if TRANSFORMS_SUPPORTED - -/* Parse a crop specification (written in X11 geometry style) */ -EXTERN(boolean) jtransform_parse_crop_spec - JPP((jpeg_transform_info *info, const char *spec)); -/* Request any required workspace */ -EXTERN(boolean) jtransform_request_workspace - JPP((j_decompress_ptr srcinfo, jpeg_transform_info *info)); -/* Adjust output image parameters */ -EXTERN(jvirt_barray_ptr *) jtransform_adjust_parameters - JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, - jvirt_barray_ptr *src_coef_arrays, - jpeg_transform_info *info)); -/* Execute the actual transformation, if any */ -EXTERN(void) jtransform_execute_transform - JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, - jvirt_barray_ptr *src_coef_arrays, - jpeg_transform_info *info)); -/* Determine whether lossless transformation is perfectly - * possible for a specified image and transformation. - */ -EXTERN(boolean) jtransform_perfect_transform - JPP((JDIMENSION image_width, JDIMENSION image_height, - int MCU_width, int MCU_height, - JXFORM_CODE transform)); - -/* jtransform_execute_transform used to be called - * jtransform_execute_transformation, but some compilers complain about - * routine names that long. This macro is here to avoid breaking any - * old source code that uses the original name... - */ -#define jtransform_execute_transformation jtransform_execute_transform - -#endif /* TRANSFORMS_SUPPORTED */ - - -/* - * Support for copying optional markers from source to destination file. - */ - -typedef enum { - JCOPYOPT_NONE, /* copy no optional markers */ - JCOPYOPT_COMMENTS, /* copy only comment (COM) markers */ - JCOPYOPT_ALL /* copy all optional markers */ -} JCOPY_OPTION; - -#define JCOPYOPT_DEFAULT JCOPYOPT_COMMENTS /* recommended default */ - -/* Setup decompression object to save desired markers in memory */ -EXTERN(void) jcopy_markers_setup - JPP((j_decompress_ptr srcinfo, JCOPY_OPTION option)); -/* Copy markers saved in the given source object to the destination object */ -EXTERN(void) jcopy_markers_execute - JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, - JCOPY_OPTION option)); From 6363384c43d1bc6a1f695cfac01466b11879c28a Mon Sep 17 00:00:00 2001 From: Justin Lebar Date: Wed, 15 Feb 2012 13:56:00 -0500 Subject: [PATCH 47/93] Bug 727381 - On Android Fennec, send haptic feedback while a vibration is playing, so as not to clobber it. r=blassey --- mobile/android/base/GeckoAppShell.java | 36 ++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/mobile/android/base/GeckoAppShell.java b/mobile/android/base/GeckoAppShell.java index fff9fac50e3f..ee6445f7a8d0 100644 --- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -116,6 +116,14 @@ public class GeckoAppShell private static HashMap> mEventListeners; + /* Is the value in sVibrationEndTime valid? */ + private static boolean sVibrationMaybePlaying = false; + + /* Time (in System.nanoTime() units) when the currently-playing vibration + * is scheduled to end. This value is valid only when + * sVibrationMaybePlaying is true. */ + private static long sVibrationEndTime = 0; + /* The Android-side API: API methods that Android calls */ // Initialization methods @@ -1125,11 +1133,15 @@ public class GeckoAppShell } public static void performHapticFeedback(boolean aIsLongPress) { - LayerController layerController = GeckoApp.mAppContext.getLayerController(); - LayerView layerView = layerController.getView(); - layerView.performHapticFeedback(aIsLongPress ? - HapticFeedbackConstants.LONG_PRESS : - HapticFeedbackConstants.VIRTUAL_KEY); + // Don't perform haptic feedback if a vibration is currently playing, + // because the haptic feedback will nuke the vibration. + if (!sVibrationMaybePlaying || System.nanoTime() >= sVibrationEndTime) { + LayerController layerController = GeckoApp.mAppContext.getLayerController(); + LayerView layerView = layerController.getView(); + layerView.performHapticFeedback(aIsLongPress ? + HapticFeedbackConstants.LONG_PRESS : + HapticFeedbackConstants.VIRTUAL_KEY); + } } private static Vibrator vibrator() { @@ -1140,14 +1152,28 @@ public class GeckoAppShell } public static void vibrate(long milliseconds) { + sVibrationEndTime = System.nanoTime() + milliseconds * 1000000; + sVibrationMaybePlaying = true; vibrator().vibrate(milliseconds); } public static void vibrate(long[] pattern, int repeat) { + // If pattern.length is even, the last element in the pattern is a + // meaningless delay, so don't include it in vibrationDuration. + long vibrationDuration = 0; + int iterLen = pattern.length - (pattern.length % 2 == 0 ? 1 : 0); + for (int i = 0; i < iterLen; i++) { + vibrationDuration += pattern[i]; + } + + sVibrationEndTime = System.nanoTime() + vibrationDuration * 1000000; + sVibrationMaybePlaying = true; vibrator().vibrate(pattern, repeat); } public static void cancelVibrate() { + sVibrationMaybePlaying = false; + sVibrationEndTime = 0; vibrator().cancel(); } From 2f190b75f44a28d71ddd8ce876329f6cdc6498b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Thu, 16 Feb 2012 11:33:26 -0500 Subject: [PATCH 48/93] Bug 683975 - Need infra for developer contributed compilers. r=rail. Downgrade glibc to 2.10.1. --- build/unix/build-toolchain/build-gcc.py | 2 +- .../build-toolchain/glibc-deterministic.patch | 21 ++++++++++++++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/build/unix/build-toolchain/build-gcc.py b/build/unix/build-toolchain/build-gcc.py index 84635a64b631..c47a32616c40 100755 --- a/build/unix/build-toolchain/build-gcc.py +++ b/build/unix/build-toolchain/build-gcc.py @@ -154,7 +154,7 @@ def build_source_dir(prefix, version): return source_dir + '/' + prefix + version binutils_version = "2.21.1" -glibc_version = "2.11.1" #FIXME: should probably use 2.5.1 +glibc_version = "2.10.1" #FIXME: should probably use 2.5.1 tar_version = "1.26" make_version = "3.81" gcc_version = "4.5.2" diff --git a/build/unix/build-toolchain/glibc-deterministic.patch b/build/unix/build-toolchain/glibc-deterministic.patch index 016fbf1ea726..4310af5de263 100644 --- a/build/unix/build-toolchain/glibc-deterministic.patch +++ b/build/unix/build-toolchain/glibc-deterministic.patch @@ -1,7 +1,22 @@ diff -ru a/configure.in b/configure.in --- a/configure.in 2011-01-17 23:34:07.000000000 -0500 +++ b/configure.in 2012-01-25 20:40:27.919485606 -0500 -@@ -2230,6 +2230,7 @@ +@@ -894,14 +894,6 @@ + LIBC_PROG_BINUTILS + AC_SUBST(MIG)dnl Needed by sysdeps/mach/configure.in + +-# Accept binutils 2.13 or newer. +-AC_CHECK_PROG_VER(AS, $AS, --version, +- [GNU assembler.* \([0-9]*\.[0-9.]*\)], +- [2.1[3-9]*], AS=: critic_missing="$critic_missing as") +-AC_CHECK_PROG_VER(LD, $LD, --version, +- [GNU ld.* \([0-9][0-9]*\.[0-9.]*\)], +- [2.1[3-9]*], LD=: critic_missing="$critic_missing ld") +- + # We need the physical current working directory. We cannot use the + # "pwd -P" shell builtin since that's not portable. Instead we try to + # find a pwd binary. Note that assigning to the PWD environment +@@ -2251,6 +2243,7 @@ fi AC_SUBST(old_glibc_headers) @@ -12,7 +27,7 @@ diff -ru a/configure.in b/configure.in diff -ru a/csu/Makefile b/csu/Makefile --- a/csu/Makefile 2011-01-17 23:34:07.000000000 -0500 +++ b/csu/Makefile 2012-01-23 13:58:28.957792633 -0500 -@@ -234,8 +234,7 @@ +@@ -223,8 +223,7 @@ if [ -z "$$os" ]; then \ os=Linux; \ fi; \ @@ -25,7 +40,7 @@ diff -ru a/csu/Makefile b/csu/Makefile diff -ru a/Makerules b/Makerules --- a/Makerules 2011-01-17 23:34:07.000000000 -0500 +++ b/Makerules 2012-01-30 08:47:56.565068903 -0500 -@@ -992,9 +992,9 @@ +@@ -977,9 +977,9 @@ echo ' Use the shared library, but some functions are only in';\ echo ' the static library, so try that secondarily. */';\ cat $<; \ From dcb1ed46ad57256a39ce27bbd2e1636d436f6f05 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Thu, 16 Feb 2012 08:45:19 -0800 Subject: [PATCH 49/93] Bug 727625 - remove childless nsDOMCSSAttributeDeclaration from the purple buffer. r=smaug --- layout/style/nsDOMCSSAttrDeclaration.cpp | 19 +++++++++++++++++++ layout/style/nsDOMCSSAttrDeclaration.h | 4 ++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/layout/style/nsDOMCSSAttrDeclaration.cpp b/layout/style/nsDOMCSSAttrDeclaration.cpp index ac9a50ee8511..fd5bda8d2116 100644 --- a/layout/style/nsDOMCSSAttrDeclaration.cpp +++ b/layout/style/nsDOMCSSAttrDeclaration.cpp @@ -49,6 +49,7 @@ #include "nsIPrincipal.h" #include "nsIURI.h" #include "nsNodeUtils.h" +#include "nsGenericElement.h" namespace css = mozilla::css; namespace dom = mozilla::dom; @@ -68,8 +69,26 @@ nsDOMCSSAttributeDeclaration::~nsDOMCSSAttributeDeclaration() MOZ_COUNT_DTOR(nsDOMCSSAttributeDeclaration); } +// If nsDOMCSSAttributeDeclaration is changed so that any additional +// fields are traversed by the cycle collector (for instance, if +// wrapper cache handling is changed) then CAN_SKIP must be updated. NS_IMPL_CYCLE_COLLECTION_1(nsDOMCSSAttributeDeclaration, mElement) +// nsDOMCSSAttributeDeclaration has only one cycle collected field, so +// if mElement is going to be skipped, the attribute declaration can't +// be part of a garbage cycle. +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsDOMCSSAttributeDeclaration) + return !tmp->mElement || nsGenericElement::CanSkip(tmp->mElement, true); +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END + +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsDOMCSSAttributeDeclaration) + return !tmp->mElement || nsGenericElement::CanSkipInCC(tmp->mElement); +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END + +// CanSkipThis returns false to avoid problems with incomplete unlinking. +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsDOMCSSAttributeDeclaration) +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END + NS_INTERFACE_MAP_BEGIN(nsDOMCSSAttributeDeclaration) NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsDOMCSSAttributeDeclaration) diff --git a/layout/style/nsDOMCSSAttrDeclaration.h b/layout/style/nsDOMCSSAttrDeclaration.h index fbe96390ad97..b5d0b9119867 100644 --- a/layout/style/nsDOMCSSAttrDeclaration.h +++ b/layout/style/nsDOMCSSAttrDeclaration.h @@ -66,8 +66,8 @@ public: ~nsDOMCSSAttributeDeclaration(); NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDOMCSSAttributeDeclaration, - nsICSSDeclaration) + NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS_AMBIGUOUS(nsDOMCSSAttributeDeclaration, + nsICSSDeclaration) // If GetCSSDeclaration returns non-null, then the decl it returns // is owned by our current style rule. From 99b4415d302f0d86ee4a4f11a7e9799d48475c7f Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Thu, 16 Feb 2012 08:45:19 -0800 Subject: [PATCH 50/93] Bug 727572 - remove childless nsChildContentList from the purple buffer. r=smaug --- content/base/src/nsGenericElement.cpp | 50 ++++++++++++++++++--------- content/base/src/nsGenericElement.h | 2 +- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index 7c7f74107b21..e26bf228eaee 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -1700,9 +1700,29 @@ nsINode::SetExplicitBaseURI(nsIURI* aURI) //---------------------------------------------------------------------- +static JSObject* +GetJSObjectChild(nsWrapperCache* aCache) +{ + if (aCache->PreservingWrapper()) { + return aCache->GetWrapperPreserveColor(); + } + return aCache->GetExpandoObjectPreserveColor(); +} + +static bool +NeedsScriptTraverse(nsWrapperCache* aCache) +{ + JSObject* o = GetJSObjectChild(aCache); + return o && xpc_IsGrayGCThing(o); +} + +//---------------------------------------------------------------------- + NS_IMPL_CYCLE_COLLECTING_ADDREF(nsChildContentList) NS_IMPL_CYCLE_COLLECTING_RELEASE(nsChildContentList) +// If nsChildContentList is changed so that any additional fields are +// traversed by the cycle collector, then CAN_SKIP must be updated. NS_IMPL_CYCLE_COLLECTION_CLASS(nsChildContentList) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsChildContentList) NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER @@ -1714,6 +1734,20 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsChildContentList) NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER NS_IMPL_CYCLE_COLLECTION_TRACE_END +// nsChildContentList only ever has a single child, its wrapper, so if +// the wrapper is black, the list can't be part of a garbage cycle. +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsChildContentList) + return !NeedsScriptTraverse(tmp); +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END + +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsChildContentList) + return !NeedsScriptTraverse(tmp); +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END + +// CanSkipThis returns false to avoid problems with incomplete unlinking. +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsChildContentList) +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END + NS_INTERFACE_TABLE_HEAD(nsChildContentList) NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY NS_NODELIST_OFFSET_AND_INTERFACE_TABLE_BEGIN(nsChildContentList) @@ -4405,22 +4439,6 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGenericElement) nsINode::Trace(tmp, aCallback, aClosure); NS_IMPL_CYCLE_COLLECTION_TRACE_END -static JSObject* -GetJSObjectChild(nsINode* aNode) -{ - if (aNode->PreservingWrapper()) { - return aNode->GetWrapperPreserveColor(); - } - return aNode->GetExpandoObjectPreserveColor(); -} - -static bool -NeedsScriptTraverse(nsINode* aNode) -{ - JSObject* o = GetJSObjectChild(aNode); - return o && xpc_IsGrayGCThing(o); -} - void nsGenericElement::MarkUserData(void* aObject, nsIAtom* aKey, void* aChild, void* aData) diff --git a/content/base/src/nsGenericElement.h b/content/base/src/nsGenericElement.h index bfe8869d236f..1417a46ce64b 100644 --- a/content/base/src/nsGenericElement.h +++ b/content/base/src/nsGenericElement.h @@ -102,7 +102,7 @@ public: } NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsChildContentList) + NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(nsChildContentList) // nsWrapperCache virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope, From 11eb5678022384ebda9e52366ac086c55df36115 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Thu, 16 Feb 2012 13:09:33 -0500 Subject: [PATCH 51/93] Bug 683975 - Need infra for developer contributed compilers. r=rail. Downgrade glibc to 2.9. --- build/unix/build-toolchain/build-gcc.py | 2 +- .../build-toolchain/glibc-deterministic.patch | 34 +++++++++++++++++-- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/build/unix/build-toolchain/build-gcc.py b/build/unix/build-toolchain/build-gcc.py index c47a32616c40..62cca0e16a53 100755 --- a/build/unix/build-toolchain/build-gcc.py +++ b/build/unix/build-toolchain/build-gcc.py @@ -154,7 +154,7 @@ def build_source_dir(prefix, version): return source_dir + '/' + prefix + version binutils_version = "2.21.1" -glibc_version = "2.10.1" #FIXME: should probably use 2.5.1 +glibc_version = "2.9" #FIXME: should probably use 2.5.1 tar_version = "1.26" make_version = "3.81" gcc_version = "4.5.2" diff --git a/build/unix/build-toolchain/glibc-deterministic.patch b/build/unix/build-toolchain/glibc-deterministic.patch index 4310af5de263..0029831dbd66 100644 --- a/build/unix/build-toolchain/glibc-deterministic.patch +++ b/build/unix/build-toolchain/glibc-deterministic.patch @@ -1,7 +1,7 @@ diff -ru a/configure.in b/configure.in --- a/configure.in 2011-01-17 23:34:07.000000000 -0500 +++ b/configure.in 2012-01-25 20:40:27.919485606 -0500 -@@ -894,14 +894,6 @@ +@@ -841,14 +841,6 @@ LIBC_PROG_BINUTILS AC_SUBST(MIG)dnl Needed by sysdeps/mach/configure.in @@ -16,7 +16,7 @@ diff -ru a/configure.in b/configure.in # We need the physical current working directory. We cannot use the # "pwd -P" shell builtin since that's not portable. Instead we try to # find a pwd binary. Note that assigning to the PWD environment -@@ -2251,6 +2243,7 @@ +@@ -2175,6 +2167,7 @@ fi AC_SUBST(old_glibc_headers) @@ -37,6 +37,36 @@ diff -ru a/csu/Makefile b/csu/Makefile *) ;; \ esac; \ files="$(all-Banner-files)"; \ +diff -ru a/elf/Makefile b/elf/Makefile +--- a/elf/Makefile 2008-10-31 16:35:11.000000000 -0400 ++++ b/elf/Makefile 2012-02-16 12:20:00.038593752 -0500 +@@ -1,4 +1,4 @@ +-# Copyright (C) 1995-2007, 2008 Free Software Foundation, Inc. ++# Copyright (C) 1995-2007, 2008, 2009 Free Software Foundation, Inc. + # This file is part of the GNU C Library. + + # The GNU C Library is free software; you can redistribute it and/or +@@ -299,18 +299,11 @@ + z-now-yes = -Wl,-z,now + + $(objpfx)ld.so: $(objpfx)librtld.os $(ld-map) +- @rm -f $@.lds +- $(LINK.o) -nostdlib -nostartfiles -shared $(z-now-$(bind-now)) \ +- $(LDFLAGS-rtld) -Wl,-z,defs -Wl,--verbose 2>&1 | \ +- LC_ALL=C \ +- sed -e '/^=========/,/^=========/!d;/^=========/d' \ +- -e 's/\. = 0 + SIZEOF_HEADERS;/& _begin = . - SIZEOF_HEADERS;/' \ +- > $@.lds + $(LINK.o) -nostdlib -nostartfiles -shared -o $@ \ + $(LDFLAGS-rtld) -Wl,-z,defs $(z-now-$(bind-now)) \ + $(filter-out $(map-file),$^) $(load-map-file) \ +- -Wl,-soname=$(rtld-installed-name) -T $@.lds +- rm -f $@.lds ++ -Wl,-soname=$(rtld-installed-name) \ ++ -Wl,-defsym=_begin=0 + readelf -s $@ \ + | $(AWK) '($$7 ~ /^UND(|EF)$$/ && $$1 != "0:" && $$4 != "REGISTER") { print; p=1 } END { exit p != 0 }' + diff -ru a/Makerules b/Makerules --- a/Makerules 2011-01-17 23:34:07.000000000 -0500 +++ b/Makerules 2012-01-30 08:47:56.565068903 -0500 From b13ee2e4ef038b4cdea5a9e59b539d311d6d3c4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabrice=20Desr=C3=A9?= Date: Thu, 16 Feb 2012 10:20:23 -0800 Subject: [PATCH 52/93] Bug 727728 - Support volume change [r=vingtetun,cjones] --- b2g/app/b2g.js | 2 ++ b2g/chrome/content/shell.js | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index eadcb278ee6e..ae6aaed83d62 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -430,3 +430,5 @@ pref("layout.frame_rate.precise", true); pref("power.screen.timeout", 60); pref("full-screen-api.enabled", true); + +pref("media.volume.steps", 10); diff --git a/b2g/chrome/content/shell.js b/b2g/chrome/content/shell.js index 4facc01217b9..ba9ef0a4cc19 100644 --- a/b2g/chrome/content/shell.js +++ b/b2g/chrome/content/shell.js @@ -186,6 +186,24 @@ var shell = { Services.prefs.setBoolPref("nglayout.debug.paint_flashing", false); } }, + + changeVolume: function shell_changeVolume(aDelta) { + let audioManager = Cc["@mozilla.org/telephony/audiomanager;1"].getService(Ci.nsIAudioManager); + + let steps = 10; + try { + steps = Services.prefs.getIntPref("media.volume.steps"); + if (steps <= 0) + steps = 1; + } catch(e) {} + + let volume = audioManager.masterVolume + aDelta / steps; + if (volume > 1) + volume = 1; + if (volume < 0) + volume = 0; + audioManager.masterVolume = volume; + }, handleEvent: function shell_handleEvent(evt) { switch (evt.type) { @@ -217,6 +235,12 @@ var shell = { case 'Search': this.toggleDebug(); break; + case 'VolumeUp': + this.changeVolume(1); + break; + case 'VolumeDown': + this.changeVolume(-1); + break; } break; case 'load': From 336cae00adb2ec61139e22e43936623c5d18d137 Mon Sep 17 00:00:00 2001 From: Benjamin Smedberg Date: Thu, 16 Feb 2012 13:40:03 -0500 Subject: [PATCH 53/93] Test for bug 410904 and bug 724465 - Is the Referer header present and correct when plugins request streams? --- dom/plugins/test/mochitest/Makefile.in | 2 + .../test/mochitest/plugin-stream-referer.sjs | 10 +++++ .../mochitest/test_pluginstream_referer.html | 42 +++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 dom/plugins/test/mochitest/plugin-stream-referer.sjs create mode 100644 dom/plugins/test/mochitest/test_pluginstream_referer.html diff --git a/dom/plugins/test/mochitest/Makefile.in b/dom/plugins/test/mochitest/Makefile.in index ca7423294abd..c19a56748c71 100644 --- a/dom/plugins/test/mochitest/Makefile.in +++ b/dom/plugins/test/mochitest/Makefile.in @@ -109,6 +109,8 @@ _MOCHITEST_FILES = \ test_instance_unparent1.html \ test_instance_unparent2.html \ test_instance_unparent3.html \ + test_pluginstream_referer.html \ + plugin-stream-referer.sjs \ $(NULL) # test_plugin_scroll_painting.html \ bug 596491 diff --git a/dom/plugins/test/mochitest/plugin-stream-referer.sjs b/dom/plugins/test/mochitest/plugin-stream-referer.sjs new file mode 100644 index 000000000000..cca3e14dee96 --- /dev/null +++ b/dom/plugins/test/mochitest/plugin-stream-referer.sjs @@ -0,0 +1,10 @@ +function handleRequest(request, response) +{ + response.setHeader('Content-Type', 'text/plain', false); + if (request.hasHeader('Referer')) { + response.write('Referer found: ' + request.getHeader('Referer')); + } + else { + response.write('No Referer found'); + } +} diff --git a/dom/plugins/test/mochitest/test_pluginstream_referer.html b/dom/plugins/test/mochitest/test_pluginstream_referer.html new file mode 100644 index 000000000000..d96aac76c619 --- /dev/null +++ b/dom/plugins/test/mochitest/test_pluginstream_referer.html @@ -0,0 +1,42 @@ + + Do plugin stream requests send the Referer header correctly? + + + + +

+ + + + + From 063997e0210cbc9174446e46fda80c46f3342b4f Mon Sep 17 00:00:00 2001 From: Benjamin Smedberg Date: Thu, 16 Feb 2012 13:14:29 -0500 Subject: [PATCH 54/93] Bug 724465 - Only inlude the Referer header in GET requests from plugins, not POST requests, because IIS throws malformed request exceptions, r=josh --- dom/plugins/base/nsPluginHost.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/dom/plugins/base/nsPluginHost.cpp b/dom/plugins/base/nsPluginHost.cpp index fa9cecdb5c85..bf0caf76302d 100644 --- a/dom/plugins/base/nsPluginHost.cpp +++ b/dom/plugins/base/nsPluginHost.cpp @@ -3115,8 +3115,13 @@ nsresult nsPluginHost::NewPluginURLStream(const nsString& aURL, // deal with headers and post data nsCOMPtr httpChannel(do_QueryInterface(channel)); if (httpChannel) { - rv = httpChannel->SetReferrer(doc->GetDocumentURI()); - NS_ENSURE_SUCCESS(rv,rv); + if (!aPostStream) { + // Only set the Referer header for GET requests because IIS throws + // errors about malformed requests if we include it in POSTs. See + // bug 724465. + rv = httpChannel->SetReferrer(doc->GetDocumentURI()); + NS_ENSURE_SUCCESS(rv,rv); + } if (aPostStream) { // XXX it's a bit of a hack to rewind the postdata stream From ba12f349e58afdcd5ee926eca24676407b19bacc Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Wed, 15 Feb 2012 17:16:53 -0800 Subject: [PATCH 55/93] Bug 726845 - Make Value marking interfaces indirect; r=billm This will eventually allow the GC to update Values that reference an Object, when moving an object. --- js/src/builtin/MapObject.cpp | 15 ++++++++--- js/src/gc/Barrier-inl.h | 7 +++-- js/src/gc/Barrier.h | 1 + js/src/jscntxt.cpp | 20 ++++++++++++++ js/src/jscntxt.h | 8 +++--- js/src/jscompartment.cpp | 7 +++-- js/src/jsexn.cpp | 5 ++-- js/src/jsfun.cpp | 2 +- js/src/jsgc.cpp | 36 ++++++------------------- js/src/jsgcmark.cpp | 49 +++++++++++++++++----------------- js/src/jsgcmark.h | 18 ++++++------- js/src/jsproxy.cpp | 18 ++++++------- js/src/jsscript.cpp | 2 +- js/src/jstypedarray.cpp | 2 +- js/src/jsweakmap.h | 12 ++++----- js/src/jswrapper.cpp | 4 +-- js/src/methodjit/StubCalls.cpp | 4 +-- js/src/vm/Stack.cpp | 4 +-- js/src/vm/Stack.h | 2 +- 19 files changed, 115 insertions(+), 101 deletions(-) diff --git a/js/src/builtin/MapObject.cpp b/js/src/builtin/MapObject.cpp index c7cdd46e3b89..bf7f5f3778e7 100644 --- a/js/src/builtin/MapObject.cpp +++ b/js/src/builtin/MapObject.cpp @@ -185,8 +185,11 @@ MapObject::mark(JSTracer *trc, JSObject *obj) MapObject *mapobj = static_cast(obj); if (ValueMap *map = mapobj->getData()) { for (ValueMap::Range r = map->all(); !r.empty(); r.popFront()) { - gc::MarkValue(trc, r.front().key, "key"); - gc::MarkValue(trc, r.front().value, "value"); + const HeapValue &key = r.front().key; + HeapValue tmp(key); + gc::MarkValue(trc, &tmp, "key"); + JS_ASSERT(tmp.get() == key.get()); + gc::MarkValue(trc, &r.front().value, "value"); } } } @@ -331,8 +334,12 @@ SetObject::mark(JSTracer *trc, JSObject *obj) { SetObject *setobj = static_cast(obj); if (ValueSet *set = setobj->getData()) { - for (ValueSet::Range r = set->all(); !r.empty(); r.popFront()) - gc::MarkValue(trc, r.front(), "key"); + for (ValueSet::Range r = set->all(); !r.empty(); r.popFront()) { + const HeapValue &key = r.front(); + HeapValue tmp(key); + gc::MarkValue(trc, &tmp, "key"); + JS_ASSERT(tmp.get() == key.get()); + } } } diff --git a/js/src/gc/Barrier-inl.h b/js/src/gc/Barrier-inl.h index b73101374946..5fdcad67baf1 100644 --- a/js/src/gc/Barrier-inl.h +++ b/js/src/gc/Barrier-inl.h @@ -134,8 +134,11 @@ inline void HeapValue::writeBarrierPre(JSCompartment *comp, const Value &value) { #ifdef JSGC_INCREMENTAL - if (comp->needsBarrier()) - js::gc::MarkValueUnbarriered(comp->barrierTracer(), value, "write barrier"); + if (comp->needsBarrier()) { + Value tmp(value); + js::gc::MarkValueUnbarriered(comp->barrierTracer(), &tmp, "write barrier"); + JS_ASSERT(tmp == value); + } #endif } diff --git a/js/src/gc/Barrier.h b/js/src/gc/Barrier.h index 78d5fa03f560..1f96b29d0908 100644 --- a/js/src/gc/Barrier.h +++ b/js/src/gc/Barrier.h @@ -319,6 +319,7 @@ class HeapValue inline void set(JSCompartment *comp, const Value &v); const Value &get() const { return value; } + Value *unsafeGet() { return &value; } operator const Value &() const { return value; } bool isUndefined() const { return value.isUndefined(); } diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index e9a0b8d60d8c..663b604a8d00 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -1270,6 +1270,26 @@ JSContext::sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const return mallocSizeOf(this) + busyArrays.sizeOfExcludingThis(mallocSizeOf); } +void +JSContext::mark(JSTracer *trc) +{ + /* Stack frames and slots are traced by StackSpace::mark. */ + + /* Mark other roots-by-definition in the JSContext. */ + if (globalObject && !hasRunOption(JSOPTION_UNROOTED_GLOBAL)) + MarkObjectRoot(trc, globalObject, "global object"); + if (isExceptionPending()) + MarkValueRoot(trc, &exception, "exception"); + + if (autoGCRooters) + autoGCRooters->traceAll(trc); + + if (sharpObjectMap.depth > 0) + js_TraceSharpMap(trc, &sharpObjectMap); + + MarkValueRoot(trc, &iterValue, "iterValue"); +} + namespace JS { #if defined JS_THREADSAFE && defined DEBUG diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 8e6cd4fe7d29..c6f54d95b2d3 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -1121,6 +1121,8 @@ struct JSContext : js::ContextFriendFields return reinterpret_cast(uintptr_t(link) - offsetof(JSContext, link)); } + void mark(JSTracer *trc); + private: /* * The allocation code calls the function to indicate either OOM failure @@ -1558,18 +1560,18 @@ class AutoShapeVector : public AutoVectorRooter class AutoValueArray : public AutoGCRooter { - const js::Value *start_; + js::Value *start_; unsigned length_; public: - AutoValueArray(JSContext *cx, const js::Value *start, unsigned length + AutoValueArray(JSContext *cx, js::Value *start, unsigned length JS_GUARD_OBJECT_NOTIFIER_PARAM) : AutoGCRooter(cx, VALARRAY), start_(start), length_(length) { JS_GUARD_OBJECT_NOTIFIER_INIT; } - const Value *start() const { return start_; } + Value *start() { return start_; } unsigned length() const { return length_; } JS_DECL_USE_GUARD_OBJECT_NOTIFIER diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index b87b948697b8..99a17e66177f 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -416,8 +416,11 @@ JSCompartment::markCrossCompartmentWrappers(JSTracer *trc) { JS_ASSERT(trc->runtime->gcCurrentCompartment); - for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) - MarkValueRoot(trc, e.front().key, "cross-compartment wrapper"); + for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) { + Value tmp = e.front().key; + MarkValueRoot(trc, &tmp, "cross-compartment wrapper"); + JS_ASSERT(tmp == e.front().key); + } } void diff --git a/js/src/jsexn.cpp b/js/src/jsexn.cpp index 5ee3aaf47a93..ebde6e30574e 100644 --- a/js/src/jsexn.cpp +++ b/js/src/jsexn.cpp @@ -432,9 +432,8 @@ exn_trace(JSTracer *trc, JSObject *obj) vcount += elem->argc; } vp = GetStackTraceValueBuffer(priv); - for (i = 0; i != vcount; ++i, ++vp) { - MarkValue(trc, *vp, "stack trace argument"); - } + for (i = 0; i != vcount; ++i, ++vp) + MarkValue(trc, vp, "stack trace argument"); } } diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 1c57cb9b42ad..0a01408b113c 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -530,7 +530,7 @@ args_trace(JSTracer *trc, JSObject *obj) { ArgumentsObject &argsobj = obj->asArguments(); ArgumentsData *data = argsobj.data(); - MarkValue(trc, data->callee, js_callee_str); + MarkValue(trc, &data->callee, js_callee_str); MarkValueRange(trc, argsobj.initialLength(), data->slots, js_arguments_str); /* diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index f92f1e5bfc67..8a5b8835b34b 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -1855,7 +1855,7 @@ gc_root_traversal(JSTracer *trc, const RootEntry &entry) if (entry.value.type == JS_GC_ROOT_GCTHING_PTR) MarkGCThingRoot(trc, *reinterpret_cast(entry.key), name); else - MarkValueRoot(trc, *reinterpret_cast(entry.key), name); + MarkValueRoot(trc, reinterpret_cast(entry.key), name); } static void @@ -1883,7 +1883,7 @@ AutoGCRooter::trace(JSTracer *trc) { switch (tag) { case JSVAL: - MarkValueRoot(trc, static_cast(this)->val, "JS::AutoValueRooter.val"); + MarkValueRoot(trc, &static_cast(this)->val, "JS::AutoValueRooter.val"); return; case PARSER: @@ -1905,10 +1905,10 @@ AutoGCRooter::trace(JSTracer *trc) static_cast(this)->descriptors; for (size_t i = 0, len = descriptors.length(); i < len; i++) { PropDesc &desc = descriptors[i]; - MarkValueRoot(trc, desc.pd, "PropDesc::pd"); - MarkValueRoot(trc, desc.value, "PropDesc::value"); - MarkValueRoot(trc, desc.get, "PropDesc::get"); - MarkValueRoot(trc, desc.set, "PropDesc::set"); + MarkValueRoot(trc, &desc.pd, "PropDesc::pd"); + MarkValueRoot(trc, &desc.value, "PropDesc::value"); + MarkValueRoot(trc, &desc.get, "PropDesc::get"); + MarkValueRoot(trc, &desc.set, "PropDesc::set"); } return; } @@ -1917,7 +1917,7 @@ AutoGCRooter::trace(JSTracer *trc) PropertyDescriptor &desc = *static_cast(this); if (desc.obj) MarkObjectRoot(trc, desc.obj, "Descriptor::obj"); - MarkValueRoot(trc, desc.value, "Descriptor::value"); + MarkValueRoot(trc, &desc.value, "Descriptor::value"); if ((desc.attrs & JSPROP_GETTER) && desc.getter) MarkObjectRoot(trc, CastAsObject(desc.getter), "Descriptor::get"); if (desc.attrs & JSPROP_SETTER && desc.setter) @@ -1996,26 +1996,6 @@ AutoGCRooter::traceAll(JSTracer *trc) namespace js { -JS_FRIEND_API(void) -MarkContext(JSTracer *trc, JSContext *acx) -{ - /* Stack frames and slots are traced by StackSpace::mark. */ - - /* Mark other roots-by-definition in acx. */ - if (acx->globalObject && !acx->hasRunOption(JSOPTION_UNROOTED_GLOBAL)) - MarkObjectRoot(trc, acx->globalObject, "global object"); - if (acx->isExceptionPending()) - MarkValueRoot(trc, acx->getPendingException(), "exception"); - - if (acx->autoGCRooters) - acx->autoGCRooters->traceAll(trc); - - if (acx->sharpObjectMap.depth > 0) - js_TraceSharpMap(trc, &acx->sharpObjectMap); - - MarkValueRoot(trc, acx->iterValue, "iterValue"); -} - void MarkWeakReferences(GCMarker *gcmarker) { @@ -2053,7 +2033,7 @@ MarkRuntime(JSTracer *trc) JSContext *iter = NULL; while (JSContext *acx = js_ContextIterator(rt, JS_TRUE, &iter)) - MarkContext(trc, acx); + acx->mark(trc); for (GCCompartmentsIter c(rt); !c.done(); c.next()) { if (c->activeAnalysis) diff --git a/js/src/jsgcmark.cpp b/js/src/jsgcmark.cpp index 6b359195d297..b287d4715c9d 100644 --- a/js/src/jsgcmark.cpp +++ b/js/src/jsgcmark.cpp @@ -45,9 +45,6 @@ * scanning functions, but they don't push onto an explicit stack. */ -using namespace js; -using namespace js::gc; - namespace js { namespace gc { @@ -299,43 +296,43 @@ MarkIdRootRange(JSTracer *trc, size_t len, jsid *vec, const char *name) /*** Value Marking ***/ static inline void -MarkValueInternal(JSTracer *trc, const Value &v) +MarkValueInternal(JSTracer *trc, Value *v) { - if (v.isMarkable()) { - JS_ASSERT(v.toGCThing()); - return MarkKind(trc, v.toGCThing(), v.gcKind()); + if (v->isMarkable()) { + JS_ASSERT(v->toGCThing()); + return MarkKind(trc, v->toGCThing(), v->gcKind()); } } void -MarkValue(JSTracer *trc, const js::HeapValue &v, const char *name) +MarkValue(JSTracer *trc, HeapValue *v, const char *name) +{ + JS_SET_TRACING_NAME(trc, name); + MarkValueInternal(trc, v->unsafeGet()); +} + +void +MarkValueRoot(JSTracer *trc, Value *v, const char *name) { JS_SET_TRACING_NAME(trc, name); MarkValueInternal(trc, v); } void -MarkValueRoot(JSTracer *trc, const Value &v, const char *name) -{ - JS_SET_TRACING_NAME(trc, name); - MarkValueInternal(trc, v); -} - -void -MarkValueRange(JSTracer *trc, size_t len, const HeapValue *vec, const char *name) +MarkValueRange(JSTracer *trc, size_t len, HeapValue *vec, const char *name) { for (size_t i = 0; i < len; ++i) { JS_SET_TRACING_INDEX(trc, name, i); - MarkValueInternal(trc, vec[i]); + MarkValueInternal(trc, vec[i].unsafeGet()); } } void -MarkValueRootRange(JSTracer *trc, size_t len, const Value *vec, const char *name) +MarkValueRootRange(JSTracer *trc, size_t len, Value *vec, const char *name) { for (size_t i = 0; i < len; ++i) { JS_SET_TRACING_INDEX(trc, name, i); - MarkValueInternal(trc, vec[i]); + MarkValueInternal(trc, &vec[i]); } } @@ -360,17 +357,17 @@ MarkShape(JSTracer *trc, const HeapPtr &thing, const char *name) } void -MarkValueUnbarriered(JSTracer *trc, const js::Value &v, const char *name) +MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name) { JS_SET_TRACING_NAME(trc, name); MarkValueInternal(trc, v); } void -MarkCrossCompartmentValue(JSTracer *trc, const js::HeapValue &v, const char *name) +MarkCrossCompartmentValue(JSTracer *trc, HeapValue *v, const char *name) { - if (v.isMarkable()) { - js::gc::Cell *cell = (js::gc::Cell *)v.toGCThing(); + if (v->isMarkable()) { + Cell *cell = (Cell *)v->toGCThing(); JSRuntime *rt = trc->runtime; if (rt->gcCurrentCompartment && cell->compartment() != rt->gcCurrentCompartment) return; @@ -643,7 +640,7 @@ MarkChildren(JSTracer *trc, JSObject *obj) uint32_t nslots = obj->slotSpan(); for (uint32_t i = 0; i < nslots; i++) { JS_SET_TRACING_DETAILS(trc, js_PrintObjectSlotName, obj, i); - MarkValueInternal(trc, obj->nativeGetSlot(i)); + MarkValueInternal(trc, obj->nativeGetSlotRef(i).unsafeGet()); } } } @@ -851,6 +848,8 @@ MarkChildren(JSTracer *trc, JSXML *xml) } /* namespace gc */ +using namespace js::gc; + inline void GCMarker::processMarkStackTop() { @@ -916,7 +915,7 @@ GCMarker::processMarkStackTop() types::TypeObject *type = obj->typeFromGC(); PushMarkStack(this, type); - js::Shape *shape = obj->lastProperty(); + Shape *shape = obj->lastProperty(); PushMarkStack(this, shape); /* Call the trace hook if necessary. */ diff --git a/js/src/jsgcmark.h b/js/src/jsgcmark.h index 57099af8218d..d587225e0c77 100644 --- a/js/src/jsgcmark.h +++ b/js/src/jsgcmark.h @@ -97,19 +97,19 @@ MarkIdRootRange(JSTracer *trc, size_t len, jsid *vec, const char *name); /*** Value Marking ***/ void -MarkValue(JSTracer *trc, const js::HeapValue &v, const char *name); +MarkValue(JSTracer *trc, HeapValue *v, const char *name); void -MarkValueRange(JSTracer *trc, size_t len, const HeapValue *vec, const char *name); +MarkValueRange(JSTracer *trc, size_t len, HeapValue *vec, const char *name); void -MarkValueRoot(JSTracer *trc, const Value &v, const char *name); +MarkValueRoot(JSTracer *trc, Value *v, const char *name); void -MarkValueRootRange(JSTracer *trc, size_t len, const Value *vec, const char *name); +MarkValueRootRange(JSTracer *trc, size_t len, Value *vec, const char *name); inline void -MarkValueRootRange(JSTracer *trc, const Value *begin, const Value *end, const char *name) +MarkValueRootRange(JSTracer *trc, Value *begin, Value *end, const char *name) { MarkValueRootRange(trc, end - begin, begin, name); } @@ -122,14 +122,14 @@ MarkShape(JSTracer *trc, const HeapPtr &thing, const char *name); /* Direct value access used by the write barriers and the methodjit */ void -MarkValueUnbarriered(JSTracer *trc, const js::Value &v, const char *name); +MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name); /* * Mark a value that may be in a different compartment from the compartment * being GC'd. (Although it won't be marked if it's in the wrong compartment.) */ void -MarkCrossCompartmentValue(JSTracer *trc, const js::HeapValue &v, const char *name); +MarkCrossCompartmentValue(JSTracer *trc, HeapValue *v, const char *name); /* * MarkChildren is exposed solely for preWriteBarrier on @@ -153,7 +153,7 @@ MarkCycleCollectorChildren(JSTracer *trc, const Shape *shape); */ inline void -Mark(JSTracer *trc, const js::HeapValue &v, const char *name) +Mark(JSTracer *trc, HeapValue *v, const char *name) { MarkValue(trc, v, name); } @@ -171,7 +171,7 @@ Mark(JSTracer *trc, const HeapPtr &xml, const char *name) } inline bool -IsMarked(const js::Value &v) +IsMarked(const Value &v) { if (v.isMarkable()) return !IsAboutToBeFinalized(v); diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index 77bb3afc61cb..3ea285e4388f 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -57,7 +57,7 @@ using namespace js; using namespace js::gc; -static inline const HeapValue & +static inline HeapValue & GetCall(JSObject *proxy) { JS_ASSERT(IsFunctionProxy(proxy)); @@ -72,7 +72,7 @@ GetConstruct(JSObject *proxy) return proxy->getSlot(JSSLOT_PROXY_CONSTRUCT); } -static inline const HeapValue & +static inline HeapValue & GetFunctionProxyConstruct(JSObject *proxy) { JS_ASSERT(IsFunctionProxy(proxy)); @@ -1246,12 +1246,12 @@ static void proxy_TraceObject(JSTracer *trc, JSObject *obj) { GetProxyHandler(obj)->trace(trc, obj); - MarkCrossCompartmentValue(trc, obj->getReservedSlotRef(JSSLOT_PROXY_PRIVATE), "private"); - MarkCrossCompartmentValue(trc, obj->getReservedSlotRef(JSSLOT_PROXY_EXTRA + 0), "extra0"); - MarkCrossCompartmentValue(trc, obj->getReservedSlotRef(JSSLOT_PROXY_EXTRA + 1), "extra1"); + MarkCrossCompartmentValue(trc, &obj->getReservedSlotRef(JSSLOT_PROXY_PRIVATE), "private"); + MarkCrossCompartmentValue(trc, &obj->getReservedSlotRef(JSSLOT_PROXY_EXTRA + 0), "extra0"); + MarkCrossCompartmentValue(trc, &obj->getReservedSlotRef(JSSLOT_PROXY_EXTRA + 1), "extra1"); if (IsFunctionProxy(obj)) { - MarkCrossCompartmentValue(trc, GetCall(obj), "call"); - MarkCrossCompartmentValue(trc, GetFunctionProxyConstruct(obj), "construct"); + MarkCrossCompartmentValue(trc, &GetCall(obj), "call"); + MarkCrossCompartmentValue(trc, &GetFunctionProxyConstruct(obj), "construct"); } } @@ -1259,8 +1259,8 @@ static void proxy_TraceFunction(JSTracer *trc, JSObject *obj) { proxy_TraceObject(trc, obj); - MarkCrossCompartmentValue(trc, GetCall(obj), "call"); - MarkCrossCompartmentValue(trc, GetFunctionProxyConstruct(obj), "construct"); + MarkCrossCompartmentValue(trc, &GetCall(obj), "call"); + MarkCrossCompartmentValue(trc, &GetFunctionProxyConstruct(obj), "construct"); } static JSBool diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index a7b8ca0e8714..d995d5af0d56 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -1903,6 +1903,6 @@ JSScript::markTrapClosures(JSTracer *trc) for (unsigned i = 0; i < length; i++) { BreakpointSite *site = debug->breakpoints[i]; if (site && site->trapHandler) - MarkValue(trc, site->trapClosure, "trap closure"); + MarkValue(trc, &site->trapClosure, "trap closure"); } } diff --git a/js/src/jstypedarray.cpp b/js/src/jstypedarray.cpp index f3ac1049072a..1fa5bc56732f 100644 --- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -1097,7 +1097,7 @@ class TypedArrayTemplate static void obj_trace(JSTracer *trc, JSObject *obj) { - MarkValue(trc, obj->getFixedSlotRef(FIELD_BUFFER), "typedarray.buffer"); + MarkValue(trc, &obj->getFixedSlotRef(FIELD_BUFFER), "typedarray.buffer"); } static JSBool diff --git a/js/src/jsweakmap.h b/js/src/jsweakmap.h index 9494686eee48..12f0b75a3852 100644 --- a/js/src/jsweakmap.h +++ b/js/src/jsweakmap.h @@ -91,7 +91,7 @@ namespace js { // bool isMarked(const Type &x) // Return true if x has been marked as live by the garbage collector. // -// bool mark(const Type &x) +// bool mark(Type &x) // Return false if x is already marked. Otherwise, mark x and return true. // // If omitted, the MarkPolicy parameter defaults to js::DefaultMarkPolicy, @@ -213,7 +213,7 @@ class WeakMap : public HashMap, publ bool markedAny = false; for (Range r = Base::all(); !r.empty(); r.popFront()) { const Key &k = r.front().key; - const Value &v = r.front().value; + Value &v = r.front().value; /* If the entry is live, ensure its key and value are marked. */ if (kp.isMarked(k)) { markedAny |= vp.mark(v); @@ -264,10 +264,10 @@ class DefaultMarkPolicy { return !IsAboutToBeFinalized(x); return true; } - bool mark(const HeapValue &x) { + bool mark(HeapValue &x) { if (isMarked(x)) return false; - js::gc::MarkValue(tracer, x, "WeakMap entry"); + js::gc::MarkValue(tracer, &x, "WeakMap entry"); return true; } }; @@ -281,7 +281,7 @@ class DefaultMarkPolicy { bool isMarked(const HeapPtrObject &x) { return !IsAboutToBeFinalized(x); } - bool mark(const HeapPtrObject &x) { + bool mark(HeapPtrObject &x) { if (isMarked(x)) return false; js::gc::MarkObject(tracer, x, "WeakMap entry"); @@ -298,7 +298,7 @@ class DefaultMarkPolicy { bool isMarked(const HeapPtrScript &x) { return !IsAboutToBeFinalized(x); } - bool mark(const HeapPtrScript &x) { + bool mark(HeapPtrScript &x) { if (isMarked(x)) return false; js::gc::MarkScript(tracer, x, "WeakMap entry"); diff --git a/js/src/jswrapper.cpp b/js/src/jswrapper.cpp index 1e0f5af650f9..23b6be62064c 100644 --- a/js/src/jswrapper.cpp +++ b/js/src/jswrapper.cpp @@ -367,7 +367,7 @@ Wrapper::iteratorNext(JSContext *cx, JSObject *wrapper, Value *vp) void Wrapper::trace(JSTracer *trc, JSObject *wrapper) { - MarkValue(trc, wrapper->getReservedSlotRef(JSSLOT_PROXY_PRIVATE), "wrappedObject"); + MarkValue(trc, &wrapper->getReservedSlotRef(JSSLOT_PROXY_PRIVATE), "wrappedObject"); } JSObject * @@ -875,7 +875,7 @@ CrossCompartmentWrapper::iteratorNext(JSContext *cx, JSObject *wrapper, Value *v void CrossCompartmentWrapper::trace(JSTracer *trc, JSObject *wrapper) { - MarkCrossCompartmentValue(trc, wrapper->getReservedSlotRef(JSSLOT_PROXY_PRIVATE), + MarkCrossCompartmentValue(trc, &wrapper->getReservedSlotRef(JSSLOT_PROXY_PRIVATE), "wrappedObject"); } diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index c9a8d113432c..9f8ecc40425b 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -1963,7 +1963,7 @@ stubs::ConvertToTypedFloat(JSContext *cx, Value *vp) void JS_FASTCALL stubs::WriteBarrier(VMFrame &f, Value *addr) { - js::gc::MarkValueUnbarriered(f.cx->compartment->barrierTracer(), *addr, "write barrier"); + gc::MarkValueUnbarriered(f.cx->compartment->barrierTracer(), addr, "write barrier"); } void JS_FASTCALL @@ -1971,5 +1971,5 @@ stubs::GCThingWriteBarrier(VMFrame &f, Value *addr) { gc::Cell *cell = (gc::Cell *)addr->toGCThing(); if (cell && !cell->isMarked()) - gc::MarkValueUnbarriered(f.cx->compartment->barrierTracer(), *addr, "write barrier"); + gc::MarkValueUnbarriered(f.cx->compartment->barrierTracer(), addr, "write barrier"); } diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp index 3c1ce65eb549..720e7bda6bba 100644 --- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -275,7 +275,7 @@ StackFrame::mark(JSTracer *trc) } if (IS_GC_MARKING_TRACER(trc)) script()->compartment()->active = true; - gc::MarkValueUnbarriered(trc, returnValue(), "rval"); + gc::MarkValueUnbarriered(trc, &returnValue(), "rval"); } /*****************************************************************************/ @@ -485,7 +485,7 @@ StackSpace::markFrameSlots(JSTracer *trc, StackFrame *fp, Value *slotsEnd, jsbyt /* Will this slot be synced by the JIT? */ if (!analysis->trackSlot(slot) || analysis->liveness(slot).live(offset)) - gc::MarkValueRoot(trc, *vp, "vm_stack"); + gc::MarkValueRoot(trc, vp, "vm_stack"); else *vp = UndefinedValue(); } diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h index 9b30e2500cd3..c2690d87af84 100644 --- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -999,7 +999,7 @@ class StackFrame return !!(flags_ & HAS_RVAL); } - const Value &returnValue() { + Value &returnValue() { if (!(flags_ & HAS_RVAL)) rval_.setUndefined(); return rval_; From 7d16baf27f0d43b10fa68622ebd66269fc9b6447 Mon Sep 17 00:00:00 2001 From: Dietrich Ayala Date: Thu, 16 Feb 2012 19:50:13 +0100 Subject: [PATCH 56/93] Bug 671041 - batch 'o telemetry metrics for session restore. r=zpao --- .../sessionstore/src/nsSessionStartup.js | 35 ++++++++++++------- .../sessionstore/src/nsSessionStore.js | 9 +++++ .../telemetry/TelemetryHistograms.h | 9 +++++ 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/browser/components/sessionstore/src/nsSessionStartup.js b/browser/components/sessionstore/src/nsSessionStartup.js index d399232b89da..3aed091278c3 100644 --- a/browser/components/sessionstore/src/nsSessionStartup.js +++ b/browser/components/sessionstore/src/nsSessionStartup.js @@ -72,6 +72,7 @@ const Cr = Components.results; const Cu = Components.utils; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource:///modules/TelemetryStopwatch.jsm"); const STATE_RUNNING_STR = "running"; const MAX_FILE_SIZE = 100 * 1024 * 1024; // 100 megabytes @@ -127,23 +128,30 @@ SessionStartup.prototype = { return; // parse the session state into a JS object + // remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0) + if (iniString.charAt(0) == '(') + iniString = iniString.slice(1, -1); + let corruptFile = false; try { - // remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0) - if (iniString.charAt(0) == '(') - iniString = iniString.slice(1, -1); + this._initialState = JSON.parse(iniString); + } + catch (ex) { + debug("The session file contained un-parse-able JSON: " + ex); + // Try to eval. + // evalInSandbox will throw if iniString is not parse-able. try { - this._initialState = JSON.parse(iniString); - } - catch (exJSON) { var s = new Cu.Sandbox("about:blank", {sandboxName: 'nsSessionStartup'}); this._initialState = Cu.evalInSandbox("(" + iniString + ")", s); + } catch(ex) { + debug("The session file contained un-eval-able JSON: " + ex); + corruptFile = true; } - - // If this is a normal restore then throw away any previous session - if (!doResumeSessionOnce) - delete this._initialState.lastSessionState; } - catch (ex) { debug("The session file is invalid: " + ex); } + Services.telemetry.getHistogramById("FX_SESSION_RESTORE_CORRUPT_FILE").add(corruptFile); + + // If this is a normal restore then throw away any previous session + if (!doResumeSessionOnce) + delete this._initialState.lastSessionState; let resumeFromCrash = prefBranch.getBoolPref("sessionstore.resume_from_crash"); let lastSessionCrashed = @@ -154,8 +162,7 @@ SessionStartup.prototype = { // Report shutdown success via telemetry. Shortcoming here are // being-killed-by-OS-shutdown-logic, shutdown freezing after // session restore was written, etc. - let Telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry); - Telemetry.getHistogramById("SHUTDOWN_OK").add(!lastSessionCrashed); + Services.telemetry.getHistogramById("SHUTDOWN_OK").add(!lastSessionCrashed); // set the startup type if (lastSessionCrashed && resumeFromCrash) @@ -296,9 +303,11 @@ SessionStartup.prototype = { * @returns a session state string */ _readStateFile: function sss_readStateFile(aFile) { + TelemetryStopwatch.start("FX_SESSION_RESTORE_READ_FILE_MS"); var stateString = Cc["@mozilla.org/supports-string;1"]. createInstance(Ci.nsISupportsString); stateString.data = this._readFile(aFile) || ""; + TelemetryStopwatch.finish("FX_SESSION_RESTORE_READ_FILE_MS"); Services.obs.notifyObservers(stateString, "sessionstore-state-read", ""); diff --git a/browser/components/sessionstore/src/nsSessionStore.js b/browser/components/sessionstore/src/nsSessionStore.js index d933d4bcb9df..9a5a3bdab590 100644 --- a/browser/components/sessionstore/src/nsSessionStore.js +++ b/browser/components/sessionstore/src/nsSessionStore.js @@ -131,6 +131,7 @@ Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/debug.js"); Cu.import("resource:///modules/TelemetryTimestamps.jsm"); +Cu.import("resource:///modules/TelemetryStopwatch.jsm"); XPCOMUtils.defineLazyGetter(this, "NetUtil", function() { Cu.import("resource://gre/modules/NetUtil.jsm"); @@ -3653,6 +3654,8 @@ SessionStoreService.prototype = { // if we crash. let pinnedOnly = this._loadState == STATE_RUNNING && !this._resume_from_crash; + TelemetryStopwatch.start("FX_SESSION_RESTORE_COLLECT_DATA_MS"); + var oState = this._getCurrentState(aUpdateAll, pinnedOnly); if (!oState) return; @@ -3691,6 +3694,8 @@ SessionStoreService.prototype = { if (this._lastSessionState) oState.lastSessionState = this._lastSessionState; + TelemetryStopwatch.finish("FX_SESSION_RESTORE_COLLECT_DATA_MS"); + this._saveStateObject(oState); }, @@ -3698,9 +3703,11 @@ SessionStoreService.prototype = { * write a state object to disk */ _saveStateObject: function sss_saveStateObject(aStateObj) { + TelemetryStopwatch.start("FX_SESSION_RESTORE_SERIALIZE_DATA_MS"); var stateString = Cc["@mozilla.org/supports-string;1"]. createInstance(Ci.nsISupportsString); stateString.data = this._toJSONString(aStateObj); + TelemetryStopwatch.finish("FX_SESSION_RESTORE_SERIALIZE_DATA_MS"); Services.obs.notifyObservers(stateString, "sessionstore-state-write", ""); @@ -4427,6 +4434,7 @@ SessionStoreService.prototype = { * String data */ _writeFile: function sss_writeFile(aFile, aData) { + TelemetryStopwatch.start("FX_SESSION_RESTORE_WRITE_FILE_MS"); // Initialize the file output stream. var ostream = Cc["@mozilla.org/network/safe-file-output-stream;1"]. createInstance(Ci.nsIFileOutputStream); @@ -4442,6 +4450,7 @@ SessionStoreService.prototype = { var self = this; NetUtil.asyncCopy(istream, ostream, function(rc) { if (Components.isSuccessCode(rc)) { + TelemetryStopwatch.finish("FX_SESSION_RESTORE_WRITE_FILE_MS"); Services.obs.notifyObservers(null, "sessionstore-state-write-complete", ""); diff --git a/toolkit/components/telemetry/TelemetryHistograms.h b/toolkit/components/telemetry/TelemetryHistograms.h index d3eb9200f3d4..360ac7d4a96d 100644 --- a/toolkit/components/telemetry/TelemetryHistograms.h +++ b/toolkit/components/telemetry/TelemetryHistograms.h @@ -344,6 +344,15 @@ HISTOGRAM(FX_BOOKMARKS_TOOLBAR_INIT_MS, 50, 5000, 10, EXPONENTIAL, "Firefox: Tim HISTOGRAM(FX_THUMBNAILS_CAPTURE_TIME_MS, 1, 500, 15, EXPONENTIAL, "THUMBNAILS: Time (ms) it takes to capture a thumbnail") HISTOGRAM(FX_THUMBNAILS_STORE_TIME_MS, 1, 500, 15, EXPONENTIAL, "THUMBNAILS: Time (ms) it takes to store a thumbnail in the cache") HISTOGRAM(FX_THUMBNAILS_HIT_OR_MISS, 0, 1, 2, BOOLEAN, "THUMBNAILS: Thumbnail found") + +/** + * Session restore telemetry + */ +HISTOGRAM(FX_SESSION_RESTORE_COLLECT_DATA_MS, 1, 30000, 10, EXPONENTIAL, "Session restore: Time to collect all window and tab data (ms)") +HISTOGRAM(FX_SESSION_RESTORE_SERIALIZE_DATA_MS, 1, 1000, 10, EXPONENTIAL, "Session restore: Time to JSON serialize session data (ms)") +HISTOGRAM(FX_SESSION_RESTORE_READ_FILE_MS, 1, 3000, 10, EXPONENTIAL, "Session restore: Time to read the session data from the file on disk (ms)") +HISTOGRAM(FX_SESSION_RESTORE_WRITE_FILE_MS, 1, 3000, 10, EXPONENTIAL, "Session restore: Time to write the session data to the file on disk (ms)") +HISTOGRAM_BOOLEAN(FX_SESSION_RESTORE_CORRUPT_FILE, "Session restore: Whether the file read on startup contained parse-able JSON") // #endif HISTOGRAM_BOOLEAN(INNERWINDOWS_WITH_MUTATION_LISTENERS, "Deleted or to-be-reused innerwindow which has had mutation event listeners.") From cf594fa163328f5da16e7f7538c28a92e0235571 Mon Sep 17 00:00:00 2001 From: Mark Finkle Date: Thu, 16 Feb 2012 14:06:58 -0500 Subject: [PATCH 57/93] Bug 726399 - Robotium: Add simple test for 'Open Link' context menu r=gbrown --- mobile/android/base/tests/robocop.ini | 1 + .../android/base/tests/robocop_big_link.html | 12 ++++++ .../tests/testWebContentContextMenu.java.in | 37 +++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 mobile/android/base/tests/robocop_big_link.html create mode 100644 mobile/android/base/tests/testWebContentContextMenu.java.in diff --git a/mobile/android/base/tests/robocop.ini b/mobile/android/base/tests/robocop.ini index 3fe41bbbbba9..d7ccbb2f4831 100644 --- a/mobile/android/base/tests/robocop.ini +++ b/mobile/android/base/tests/robocop.ini @@ -8,6 +8,7 @@ [testOverscroll] [testAxisLocking] [testAboutPage] +[testWebContentContextMenu] # Used for Talos, please don't use in mochitest #[testPan] diff --git a/mobile/android/base/tests/robocop_big_link.html b/mobile/android/base/tests/robocop_big_link.html new file mode 100644 index 000000000000..588f90d57d76 --- /dev/null +++ b/mobile/android/base/tests/robocop_big_link.html @@ -0,0 +1,12 @@ + + + Big Link + + + + + + + diff --git a/mobile/android/base/tests/testWebContentContextMenu.java.in b/mobile/android/base/tests/testWebContentContextMenu.java.in new file mode 100644 index 000000000000..bc72d9a659a8 --- /dev/null +++ b/mobile/android/base/tests/testWebContentContextMenu.java.in @@ -0,0 +1,37 @@ +#filter substitution +package @ANDROID_PACKAGE_NAME@.tests; + +import @ANDROID_PACKAGE_NAME@.*; +import android.app.Activity; +import android.util.Log; +import android.util.DisplayMetrics; + +public class testWebContentContextMenu extends BaseTest { + public void testWebContentContextMenu() { + setTestType("mochitest"); + mActions.expectGeckoEvent("Gecko:Ready").blockForEvent(); + + // Load the about: page + String url = getAbsoluteUrl("/robocop/robocop_big_link.html"); + loadUrl(url); + + DisplayMetrics dm = new DisplayMetrics(); + getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); + Log.i("TBN", "******** density= " + dm.density); + + float top = mDriver.getGeckoTop() + 30 * dm.density; + float left = mDriver.getGeckoLeft() + mDriver.getGeckoWidth() / 2; + mSolo.clickLongOnScreen(left, top); + + mAsserter.ok(mSolo.waitForText("Open"), "looking for context menu action", "found 'Open Link'"); + mSolo.clickOnText("Open"); + + // Wait for the new tab and page to load + mActions.expectGeckoEvent("Tab:Added").blockForEvent(); + mActions.expectGeckoEvent("DOMContentLoaded").blockForEvent(); + + // See tab count + Element tabCount = mDriver.findElement(getActivity(), "tabs_count"); + mAsserter.is(tabCount.getText(), "2", "Number of tabs has increased"); + } +} From 530ec7942001f6a094219b26f3ca0a663deb8020 Mon Sep 17 00:00:00 2001 From: Mark Finkle Date: Thu, 16 Feb 2012 14:07:12 -0500 Subject: [PATCH 58/93] Bug 727730 - Add support for Share Link context menu r=mbrubeck --- .../tests/testWebContentContextMenu.java.in | 6 ++-- mobile/android/chrome/content/browser.js | 35 +++++++++++++++++++ .../locales/en-US/chrome/browser.properties | 1 + 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/mobile/android/base/tests/testWebContentContextMenu.java.in b/mobile/android/base/tests/testWebContentContextMenu.java.in index bc72d9a659a8..f137fc444884 100644 --- a/mobile/android/base/tests/testWebContentContextMenu.java.in +++ b/mobile/android/base/tests/testWebContentContextMenu.java.in @@ -17,17 +17,19 @@ public class testWebContentContextMenu extends BaseTest { DisplayMetrics dm = new DisplayMetrics(); getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); - Log.i("TBN", "******** density= " + dm.density); + // The link is 60px tall in the web content so let's try to tap in the middle float top = mDriver.getGeckoTop() + 30 * dm.density; float left = mDriver.getGeckoLeft() + mDriver.getGeckoWidth() / 2; mSolo.clickLongOnScreen(left, top); mAsserter.ok(mSolo.waitForText("Open"), "looking for context menu action", "found 'Open Link'"); + + Actions.EventExpecter tabEventExpecter = mActions.expectGeckoEvent("Tab:Added"); mSolo.clickOnText("Open"); // Wait for the new tab and page to load - mActions.expectGeckoEvent("Tab:Added").blockForEvent(); + tabEventExpecter.blockForEvent(); mActions.expectGeckoEvent("DOMContentLoaded").blockForEvent(); // See tab count diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 765291a90698..d05b38666623 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -1136,6 +1136,15 @@ var NativeWindow = { NativeWindow.toast.show(label, "short"); }); + this.add(Strings.browser.GetStringFromName("contextmenu.shareLink"), + this.linkShareableContext, + function(aTarget) { + let url = NativeWindow.contextmenus._getLinkURL(aTarget); + let title = aTarget.textContent || aTarget.title; + let sharing = Cc["@mozilla.org/uriloader/external-sharing-app-service;1"].getService(Ci.nsIExternalSharingAppService); + sharing.shareWithDefault(url, "text/plain", title); + }); + this.add(Strings.browser.GetStringFromName("contextmenu.fullScreen"), this.SelectorContext("video:not(:-moz-full-screen)"), function(aTarget) { @@ -1225,6 +1234,32 @@ var NativeWindow = { } }, + linkShareableContext: { + matches: function linkShareableContextMatches(aElement) { + if (aElement.nodeType == Ci.nsIDOMNode.ELEMENT_NODE && + ((aElement instanceof Ci.nsIDOMHTMLAnchorElement && aElement.href) || + (aElement instanceof Ci.nsIDOMHTMLAreaElement && aElement.href) || + aElement instanceof Ci.nsIDOMHTMLLinkElement || + aElement.getAttributeNS(kXLinkNamespace, "type") == "simple")) { + let uri; + try { + let url = NativeWindow.contextmenus._getLinkURL(aElement); + uri = Services.io.newURI(url, null, null); + } catch (e) { + return false; + } + + let scheme = uri.scheme; + if (!scheme) + return false; + + let dontShare = /^(chrome|about|file|javascript|resource)$/; + return (scheme && !dontShare.test(scheme)); + } + return false; + } + }, + textContext: { matches: function textContext(aElement) { return ((aElement instanceof Ci.nsIDOMHTMLInputElement && aElement.mozIsTextField(false)) diff --git a/mobile/android/locales/en-US/chrome/browser.properties b/mobile/android/locales/en-US/chrome/browser.properties index 85dac68bbf1c..612105f5cae5 100644 --- a/mobile/android/locales/en-US/chrome/browser.properties +++ b/mobile/android/locales/en-US/chrome/browser.properties @@ -198,6 +198,7 @@ selectionHelper.textCopied=Text copied to clipboard # Context menu contextmenu.openInNewTab=Open Link in New Tab +contextmenu.shareLink=Share Link contextmenu.changeInputMethod=Select Input Method contextmenu.fullScreen=Full Screen contextmenu.saveImage=Save Image From 3dbcdd7bc944212cb96271c8cf4ca6f213708781 Mon Sep 17 00:00:00 2001 From: Mark Finkle Date: Thu, 16 Feb 2012 14:21:52 -0500 Subject: [PATCH 59/93] Backout eb9c17efd1e4, wrong patch --- mobile/android/base/tests/robocop.ini | 1 - .../android/base/tests/robocop_big_link.html | 12 ------ .../tests/testWebContentContextMenu.java.in | 39 ------------------- 3 files changed, 52 deletions(-) delete mode 100644 mobile/android/base/tests/robocop_big_link.html delete mode 100644 mobile/android/base/tests/testWebContentContextMenu.java.in diff --git a/mobile/android/base/tests/robocop.ini b/mobile/android/base/tests/robocop.ini index d7ccbb2f4831..3fe41bbbbba9 100644 --- a/mobile/android/base/tests/robocop.ini +++ b/mobile/android/base/tests/robocop.ini @@ -8,7 +8,6 @@ [testOverscroll] [testAxisLocking] [testAboutPage] -[testWebContentContextMenu] # Used for Talos, please don't use in mochitest #[testPan] diff --git a/mobile/android/base/tests/robocop_big_link.html b/mobile/android/base/tests/robocop_big_link.html deleted file mode 100644 index 588f90d57d76..000000000000 --- a/mobile/android/base/tests/robocop_big_link.html +++ /dev/null @@ -1,12 +0,0 @@ - - - Big Link - - - - - - - diff --git a/mobile/android/base/tests/testWebContentContextMenu.java.in b/mobile/android/base/tests/testWebContentContextMenu.java.in deleted file mode 100644 index f137fc444884..000000000000 --- a/mobile/android/base/tests/testWebContentContextMenu.java.in +++ /dev/null @@ -1,39 +0,0 @@ -#filter substitution -package @ANDROID_PACKAGE_NAME@.tests; - -import @ANDROID_PACKAGE_NAME@.*; -import android.app.Activity; -import android.util.Log; -import android.util.DisplayMetrics; - -public class testWebContentContextMenu extends BaseTest { - public void testWebContentContextMenu() { - setTestType("mochitest"); - mActions.expectGeckoEvent("Gecko:Ready").blockForEvent(); - - // Load the about: page - String url = getAbsoluteUrl("/robocop/robocop_big_link.html"); - loadUrl(url); - - DisplayMetrics dm = new DisplayMetrics(); - getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); - - // The link is 60px tall in the web content so let's try to tap in the middle - float top = mDriver.getGeckoTop() + 30 * dm.density; - float left = mDriver.getGeckoLeft() + mDriver.getGeckoWidth() / 2; - mSolo.clickLongOnScreen(left, top); - - mAsserter.ok(mSolo.waitForText("Open"), "looking for context menu action", "found 'Open Link'"); - - Actions.EventExpecter tabEventExpecter = mActions.expectGeckoEvent("Tab:Added"); - mSolo.clickOnText("Open"); - - // Wait for the new tab and page to load - tabEventExpecter.blockForEvent(); - mActions.expectGeckoEvent("DOMContentLoaded").blockForEvent(); - - // See tab count - Element tabCount = mDriver.findElement(getActivity(), "tabs_count"); - mAsserter.is(tabCount.getText(), "2", "Number of tabs has increased"); - } -} From 34b729110dc0d96cdd9fb07780a2ae33449e12af Mon Sep 17 00:00:00 2001 From: Mark Finkle Date: Thu, 16 Feb 2012 14:32:33 -0500 Subject: [PATCH 60/93] Bug 726399 - Robotium: Add simple test for 'Open Link' context menu r=gbrown --- mobile/android/base/tests/robocop.ini | 1 + .../android/base/tests/robocop_big_link.html | 12 ++++++ .../tests/testWebContentContextMenu.java.in | 40 +++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 mobile/android/base/tests/robocop_big_link.html create mode 100644 mobile/android/base/tests/testWebContentContextMenu.java.in diff --git a/mobile/android/base/tests/robocop.ini b/mobile/android/base/tests/robocop.ini index 3fe41bbbbba9..d7ccbb2f4831 100644 --- a/mobile/android/base/tests/robocop.ini +++ b/mobile/android/base/tests/robocop.ini @@ -8,6 +8,7 @@ [testOverscroll] [testAxisLocking] [testAboutPage] +[testWebContentContextMenu] # Used for Talos, please don't use in mochitest #[testPan] diff --git a/mobile/android/base/tests/robocop_big_link.html b/mobile/android/base/tests/robocop_big_link.html new file mode 100644 index 000000000000..588f90d57d76 --- /dev/null +++ b/mobile/android/base/tests/robocop_big_link.html @@ -0,0 +1,12 @@ + + + Big Link + + + + + + + diff --git a/mobile/android/base/tests/testWebContentContextMenu.java.in b/mobile/android/base/tests/testWebContentContextMenu.java.in new file mode 100644 index 000000000000..91abeddb0381 --- /dev/null +++ b/mobile/android/base/tests/testWebContentContextMenu.java.in @@ -0,0 +1,40 @@ +#filter substitution +package @ANDROID_PACKAGE_NAME@.tests; + +import @ANDROID_PACKAGE_NAME@.*; +import android.app.Activity; +import android.util.Log; +import android.util.DisplayMetrics; + +public class testWebContentContextMenu extends BaseTest { + public void testWebContentContextMenu() { + setTestType("mochitest"); + mActions.expectGeckoEvent("Gecko:Ready").blockForEvent(); + + // Load the about: page + String url = getAbsoluteUrl("/robocop/robocop_big_link.html"); + loadUrl(url); + + DisplayMetrics dm = new DisplayMetrics(); + getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); + + // The link has a 60px height, so let's try to hit the middle + float top = mDriver.getGeckoTop() + 30 * dm.density; + float left = mDriver.getGeckoLeft() + mDriver.getGeckoWidth() / 2; + mSolo.clickLongOnScreen(left, top); + + mAsserter.ok(mSolo.waitForText("Open"), "looking for context menu action", "found 'Open Link'"); + + Actions.EventExpecter tabEventExpecter = mActions.expectGeckoEvent("Tab:Added"); + Actions.EventExpecter contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded"); + mSolo.clickOnText("Open"); + + // Wait for the new tab and page to load + tabEventExpecter.blockForEvent(); + contentEventExpecter.blockForEvent(); + + // See tab count + Element tabCount = mDriver.findElement(getActivity(), "tabs_count"); + mAsserter.is(tabCount.getText(), "2", "Number of tabs has increased"); + } +} From bb838270340d5a63f00c6b8b350c54ccf2e5cdad Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 16 Feb 2012 12:22:16 -0800 Subject: [PATCH 61/93] Bug 714590 - Use the helper jsclass format everywhere. r=mrbkap --- js/xpconnect/src/XPCQuickStubs.h | 4 ++-- js/xpconnect/src/XPCWrappedNative.cpp | 2 +- js/xpconnect/src/XPCWrappedNativeJSOps.cpp | 7 +++++-- js/xpconnect/src/xpcprivate.h | 10 +++++++--- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/js/xpconnect/src/XPCQuickStubs.h b/js/xpconnect/src/XPCQuickStubs.h index 1f709711dc3c..f903ed633f4d 100644 --- a/js/xpconnect/src/XPCQuickStubs.h +++ b/js/xpconnect/src/XPCQuickStubs.h @@ -539,8 +539,8 @@ castNativeFromWrapper(JSContext *cx, NS_ASSERTION(IS_WRAPPER_CLASS(js::GetObjectClass(cur)), "Not a wrapper?"); - XPCNativeScriptableSharedJSClass *clasp = - (XPCNativeScriptableSharedJSClass*)js::GetObjectClass(cur); + XPCWrappedNativeJSClass *clasp = + (XPCWrappedNativeJSClass*)js::GetObjectClass(cur); if (!(clasp->interfacesBitmap & (1 << interfaceBit))) return nsnull; diff --git a/js/xpconnect/src/XPCWrappedNative.cpp b/js/xpconnect/src/XPCWrappedNative.cpp index 93939fab1d89..4bd06c15afec 100644 --- a/js/xpconnect/src/XPCWrappedNative.cpp +++ b/js/xpconnect/src/XPCWrappedNative.cpp @@ -1091,7 +1091,7 @@ XPCWrappedNative::Init(XPCCallContext& ccx, // create our flatJSObject - JSClass* jsclazz = si ? si->GetJSClass() : Jsvalify(&XPC_WN_NoHelper_JSClass); + JSClass* jsclazz = si ? si->GetJSClass() : Jsvalify(&XPC_WN_NoHelper_JSClass.base); if (isGlobal) { // Resolving a global object's class can cause us to create a global's diff --git a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp index 543217b27893..2367f62ece1d 100644 --- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp +++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp @@ -814,7 +814,8 @@ XPC_WN_OuterObject(JSContext *cx, JSObject *obj) return obj; } -js::Class XPC_WN_NoHelper_JSClass = { +XPCWrappedNativeJSClass XPC_WN_NoHelper_JSClass = { + { // base "XPCWrappedNative_NoHelper", // name; WRAPPER_SLOTS | JSCLASS_PRIVATE_IS_NSISUPPORTS, // flags @@ -885,6 +886,8 @@ js::Class XPC_WN_NoHelper_JSClass = { XPC_WN_JSOp_ThisObject, XPC_WN_JSOp_Clear } + }, + 0 // interfacesBitmap }; @@ -1204,7 +1207,7 @@ XPC_WN_JSOp_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, jsval *statep, jsid *idp) { js::Class *clazz = js::GetObjectClass(obj); - if (!IS_WRAPPER_CLASS(clazz) || clazz == &XPC_WN_NoHelper_JSClass) { + if (!IS_WRAPPER_CLASS(clazz) || clazz == &XPC_WN_NoHelper_JSClass.base) { // obj must be a prototype object or a wrapper w/o a // helper. Short circuit this call to the default // implementation. diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index 3cb76b5f23f1..3f97e1d1a021 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -1351,7 +1351,8 @@ private: // These are the various JSClasses and callbacks whose use that required // visibility from more than one .cpp file. -extern js::Class XPC_WN_NoHelper_JSClass; +struct XPCWrappedNativeJSClass; +extern XPCWrappedNativeJSClass XPC_WN_NoHelper_JSClass; extern js::Class XPC_WN_NoMods_WithCall_Proto_JSClass; extern js::Class XPC_WN_NoMods_NoCall_Proto_JSClass; extern js::Class XPC_WN_ModsAllowed_WithCall_Proto_JSClass; @@ -2035,7 +2036,10 @@ public: // was a big problem when wrappers are reparented to different scopes (and // thus different protos (the DOM does this). -struct XPCNativeScriptableSharedJSClass +// We maintain the invariant that every JSClass for which ext.isWrappedNative +// is true is a contained in an instance of this struct, and can thus be cast +// to it. +struct XPCWrappedNativeJSClass { js::Class base; PRUint32 interfacesBitmap; @@ -2077,7 +2081,7 @@ public: private: XPCNativeScriptableFlags mFlags; - XPCNativeScriptableSharedJSClass mJSClass; + XPCWrappedNativeJSClass mJSClass; JSBool mCanBeSlim; }; From 4d972aba143f53ab88138e010a97b43c05e31957 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Thu, 16 Feb 2012 15:33:04 -0500 Subject: [PATCH 62/93] Bug 683975 - Need infra for developer contributed compilers. r=rail. dowgrade glibc to 2.7. --- build/unix/build-toolchain/build-gcc.py | 2 +- .../unix/build-toolchain/glibc-deterministic.patch | 13 +++++-------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/build/unix/build-toolchain/build-gcc.py b/build/unix/build-toolchain/build-gcc.py index 62cca0e16a53..998e2b606a4a 100755 --- a/build/unix/build-toolchain/build-gcc.py +++ b/build/unix/build-toolchain/build-gcc.py @@ -154,7 +154,7 @@ def build_source_dir(prefix, version): return source_dir + '/' + prefix + version binutils_version = "2.21.1" -glibc_version = "2.9" #FIXME: should probably use 2.5.1 +glibc_version = "2.7" #FIXME: should probably use 2.5.1 tar_version = "1.26" make_version = "3.81" gcc_version = "4.5.2" diff --git a/build/unix/build-toolchain/glibc-deterministic.patch b/build/unix/build-toolchain/glibc-deterministic.patch index 0029831dbd66..ecf408c55e7f 100644 --- a/build/unix/build-toolchain/glibc-deterministic.patch +++ b/build/unix/build-toolchain/glibc-deterministic.patch @@ -40,13 +40,7 @@ diff -ru a/csu/Makefile b/csu/Makefile diff -ru a/elf/Makefile b/elf/Makefile --- a/elf/Makefile 2008-10-31 16:35:11.000000000 -0400 +++ b/elf/Makefile 2012-02-16 12:20:00.038593752 -0500 -@@ -1,4 +1,4 @@ --# Copyright (C) 1995-2007, 2008 Free Software Foundation, Inc. -+# Copyright (C) 1995-2007, 2008, 2009 Free Software Foundation, Inc. - # This file is part of the GNU C Library. - - # The GNU C Library is free software; you can redistribute it and/or -@@ -299,18 +299,11 @@ +@@ -295,20 +295,13 @@ z-now-yes = -Wl,-z,now $(objpfx)ld.so: $(objpfx)librtld.os $(ld-map) @@ -65,8 +59,11 @@ diff -ru a/elf/Makefile b/elf/Makefile + -Wl,-soname=$(rtld-installed-name) \ + -Wl,-defsym=_begin=0 readelf -s $@ \ - | $(AWK) '($$7 ~ /^UND(|EF)$$/ && $$1 != "0:" && $$4 != "REGISTER") { print; p=1 } END { exit p != 0 }' +- | awk '($$7 ~ /^UND(|EF)$$/ && $$1 != "0:" && $$4 != "REGISTER") { print; p=1 } END { exit p != 0 }' ++ | $(AWK) '($$7 ~ /^UND(|EF)$$/ && $$1 != "0:" && $$4 != "REGISTER") { print; p=1 } END { exit p != 0 }' + # interp.c exists just to get this string into the libraries. + CFLAGS-interp.c = -D'RUNTIME_LINKER="$(slibdir)/$(rtld-installed-name)"' \ diff -ru a/Makerules b/Makerules --- a/Makerules 2011-01-17 23:34:07.000000000 -0500 +++ b/Makerules 2012-01-30 08:47:56.565068903 -0500 From 02710cdd5a422ff4ba64b19797f583f7651d8f36 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 16 Feb 2012 21:26:50 +0000 Subject: [PATCH 63/93] bug 727815 - flush shaped-word caches when font-shaping preferences are modified. r=roc --- gfx/thebes/gfxPlatform.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index 7ec3599dd690..b87d239b8aa2 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -1358,11 +1358,19 @@ gfxPlatform::FontsPrefsChanged(const char *aPref) #ifdef MOZ_GRAPHITE } else if (!strcmp(GFX_PREF_GRAPHITE_SHAPING, aPref)) { mGraphiteShapingEnabled = UNINITIALIZED_VALUE; - gfxFontCache::GetCache()->AgeAllGenerations(); + gfxFontCache *fontCache = gfxFontCache::GetCache(); + if (fontCache) { + fontCache->AgeAllGenerations(); + fontCache->FlushShapedWordCaches(); + } #endif } else if (!strcmp(GFX_PREF_HARFBUZZ_SCRIPTS, aPref)) { mUseHarfBuzzScripts = UNINITIALIZED_VALUE; - gfxFontCache::GetCache()->AgeAllGenerations(); + gfxFontCache *fontCache = gfxFontCache::GetCache(); + if (fontCache) { + fontCache->AgeAllGenerations(); + fontCache->FlushShapedWordCaches(); + } } else if (!strcmp(BIDI_NUMERAL_PREF, aPref)) { mBidiNumeralOption = UNINITIALIZED_VALUE; } From 12657aeaef5adc624ba2798c43dddf2d2ad5f9d5 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 16 Feb 2012 21:27:00 +0000 Subject: [PATCH 64/93] bug 662055 - [harfbuzz] permute canonical classes of Hebrew marks to present logical order to OpenType lookups. r=behdad --- gfx/harfbuzz/src/hb-ot-shape-private.hh | 28 +++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/gfx/harfbuzz/src/hb-ot-shape-private.hh b/gfx/harfbuzz/src/hb-ot-shape-private.hh index c49c2b0e36af..3e3efdeac8c1 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-private.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-private.hh @@ -104,12 +104,40 @@ _hb_unicode_modified_combining_class (hb_unicode_funcs_t *ufuncs, { int c = hb_unicode_combining_class (ufuncs, unicode); + /* For Hebrew, we permute the "fixed-position" classes 10-15 into the order + * described in the SBL Hebrew manual http://www.sbl-site.org/Fonts/SBLHebrewUserManual1.5x.pdf + * (as recommended by http://forum.fontlab.com/archive-old-microsoft-volt-group/vista-and-diacritic-ordering-t6751.0.html) + */ + static const int permuted_hebrew_classes[25 - 10 + 1] = { + /* 10 sheva */ 15, + /* 11 hataf segol */ 16, + /* 12 hataf patah */ 17, + /* 13 hataf qamats */ 18, + /* 14 hiriq */ 19, + /* 15 tsere */ 20, + /* 16 segol */ 21, + /* 17 patah */ 22, + /* 18 qamats */ 23, + /* 19 holam */ 14, + /* 20 qubuts */ 24, + /* 21 dagesh */ 12, + /* 22 meteg */ 25, + /* 23 rafe */ 13, + /* 24 shin dot */ 10, + /* 25 sin dot */ 11, + }; + /* Modify the combining-class to suit Arabic better. See: * http://unicode.org/faq/normalization.html#8 * http://unicode.org/faq/normalization.html#9 */ if (unlikely (hb_in_range (c, 27, 33))) c = c == 33 ? 27 : c + 1; + /* The equivalent fix for Hebrew is more complex, + * see the SBL Hebrew manual. + */ + else if (unlikely (hb_in_range (c, 10, 25))) + c = permuted_hebrew_classes[c - 10]; return c; } From 8172c5a17be632d04d75f5b473ccde4ff0039b06 Mon Sep 17 00:00:00 2001 From: Felix Fung Date: Thu, 16 Feb 2012 14:56:06 -0500 Subject: [PATCH 65/93] Bug 495277 - Reduce calls to new Function in Autocomplete.xml. r=gavin --- toolkit/content/tests/chrome/Makefile.in | 1 + .../tests/chrome/test_autocomplete5.xul | 151 ++++++++++++++++++ toolkit/content/widgets/autocomplete.xml | 41 +++-- 3 files changed, 178 insertions(+), 15 deletions(-) create mode 100644 toolkit/content/tests/chrome/test_autocomplete5.xul diff --git a/toolkit/content/tests/chrome/Makefile.in b/toolkit/content/tests/chrome/Makefile.in index 5e5fd4d640b7..6bf709855304 100644 --- a/toolkit/content/tests/chrome/Makefile.in +++ b/toolkit/content/tests/chrome/Makefile.in @@ -87,6 +87,7 @@ _TEST_FILES = findbar_window.xul \ test_autocomplete2.xul \ test_autocomplete3.xul \ test_autocomplete4.xul \ + test_autocomplete5.xul \ test_autocomplete_delayOnPaste.xul \ test_keys.xul \ window_keys.xul \ diff --git a/toolkit/content/tests/chrome/test_autocomplete5.xul b/toolkit/content/tests/chrome/test_autocomplete5.xul new file mode 100644 index 000000000000..855148dadcd2 --- /dev/null +++ b/toolkit/content/tests/chrome/test_autocomplete5.xul @@ -0,0 +1,151 @@ + + + + + + + + + +

+

+ +
+
+ + +
diff --git a/toolkit/content/widgets/autocomplete.xml b/toolkit/content/widgets/autocomplete.xml index 107b95a2fe36..5e31d8a35e55 100644 --- a/toolkit/content/widgets/autocomplete.xml +++ b/toolkit/content/widgets/autocomplete.xml @@ -91,9 +91,19 @@ null false + null + null + null + null + @@ -249,13 +260,16 @@ else this.removeAttribute("nomatch"); - this.fireEvent("searchcomplete"); + if (this._searchCompleteHandler) + this._searchCompleteHandler(); ]]> @@ -263,7 +277,8 @@ @@ -441,18 +456,14 @@ - + From d0d0f25c68106fe378314ff0385dc2d83c879aa0 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 16 Feb 2012 21:37:22 +0000 Subject: [PATCH 66/93] bug 662055 followup - fix typo in comment. DONTBUILD --- gfx/harfbuzz/src/hb-ot-shape-private.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx/harfbuzz/src/hb-ot-shape-private.hh b/gfx/harfbuzz/src/hb-ot-shape-private.hh index 3e3efdeac8c1..c48a4d6c6ea7 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-private.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-private.hh @@ -104,7 +104,7 @@ _hb_unicode_modified_combining_class (hb_unicode_funcs_t *ufuncs, { int c = hb_unicode_combining_class (ufuncs, unicode); - /* For Hebrew, we permute the "fixed-position" classes 10-15 into the order + /* For Hebrew, we permute the "fixed-position" classes 10-25 into the order * described in the SBL Hebrew manual http://www.sbl-site.org/Fonts/SBLHebrewUserManual1.5x.pdf * (as recommended by http://forum.fontlab.com/archive-old-microsoft-volt-group/vista-and-diacritic-ordering-t6751.0.html) */ From bb813207bff8ecad02f8237ca6f6766693a31a9a Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Thu, 16 Feb 2012 14:22:27 -0800 Subject: [PATCH 67/93] Bug 728005 - Crash when entering full screen mode on Android 2.3 [r=sriram] --- mobile/android/base/GeckoApp.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index 2698af98bde7..8d9a9550bb5f 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -1648,7 +1648,8 @@ abstract public class GeckoApp WindowManager.LayoutParams.FLAG_FULLSCREEN : 0, WindowManager.LayoutParams.FLAG_FULLSCREEN); - window.getDecorView().setSystemUiVisibility(fullscreen ? 1 : 0); + if (Build.VERSION.SDK_INT >= 11) + window.getDecorView().setSystemUiVisibility(fullscreen ? 1 : 0); } }); } From 45e2b94c011e9394e0d9533b2fb1f43beadee424 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 16 Feb 2012 22:25:22 +0000 Subject: [PATCH 68/93] bug 727736 - [harfbuzz] force glyphs for zero-width diacritics to actually have zero width, to work around bad fonts. r=behdad --- gfx/harfbuzz/src/hb-ot-layout.cc | 41 +++++++++++++++++++++++++++++++- gfx/harfbuzz/src/hb-ot-layout.h | 2 +- gfx/harfbuzz/src/hb-ot-shape.cc | 27 ++++++++++++++++++--- 3 files changed, 65 insertions(+), 5 deletions(-) diff --git a/gfx/harfbuzz/src/hb-ot-layout.cc b/gfx/harfbuzz/src/hb-ot-layout.cc index f3e07139adba..bfbe890b4ab8 100644 --- a/gfx/harfbuzz/src/hb-ot-layout.cc +++ b/gfx/harfbuzz/src/hb-ot-layout.cc @@ -32,6 +32,7 @@ #include "hb-ot-layout-gsub-table.hh" #include "hb-ot-layout-gpos-table.hh" #include "hb-ot-maxp-table.hh" +#include "hb-ot-shape-private.hh" #include @@ -496,8 +497,46 @@ hb_ot_layout_position_lookup (hb_font_t *font, } void -hb_ot_layout_position_finish (hb_buffer_t *buffer) +hb_ot_layout_position_finish (hb_face_t *face, hb_buffer_t *buffer) { + /* force diacritics to have zero width */ + unsigned int count = buffer->len; + if (hb_ot_layout_has_glyph_classes (face)) { + const GDEF& gdef = _get_gdef (face); + if (buffer->props.direction == HB_DIRECTION_RTL) { + for (unsigned int i = 1; i < count; i++) { + if (gdef.get_glyph_class (buffer->info[i].codepoint) == GDEF::MarkGlyph) { + buffer->pos[i].x_advance = 0; + } + } + } else { + for (unsigned int i = 1; i < count; i++) { + if (gdef.get_glyph_class (buffer->info[i].codepoint) == GDEF::MarkGlyph) { + hb_glyph_position_t& pos = buffer->pos[i]; + pos.x_offset -= pos.x_advance; + pos.x_advance = 0; + } + } + } + } else { + /* no GDEF classes available, so use General Category as a fallback */ + if (buffer->props.direction == HB_DIRECTION_RTL) { + for (unsigned int i = 1; i < count; i++) { + if (buffer->info[i].general_category() == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) { + buffer->pos[i].x_advance = 0; + } + } + } else { + for (unsigned int i = 1; i < count; i++) { + if (buffer->info[i].general_category() == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) { + hb_glyph_position_t& pos = buffer->pos[i]; + pos.x_offset -= pos.x_advance; + pos.x_advance = 0; + } + } + } + } + GPOS::position_finish (buffer); } diff --git a/gfx/harfbuzz/src/hb-ot-layout.h b/gfx/harfbuzz/src/hb-ot-layout.h index 447e35dbfad7..96f25722dea7 100644 --- a/gfx/harfbuzz/src/hb-ot-layout.h +++ b/gfx/harfbuzz/src/hb-ot-layout.h @@ -199,7 +199,7 @@ hb_ot_layout_position_lookup (hb_font_t *font, /* Should be called after all the position_lookup's are done */ void -hb_ot_layout_position_finish (hb_buffer_t *buffer); +hb_ot_layout_position_finish (hb_face_t *face, hb_buffer_t *buffer); HB_END_DECLS diff --git a/gfx/harfbuzz/src/hb-ot-shape.cc b/gfx/harfbuzz/src/hb-ot-shape.cc index 4275afc82516..09db9125cbe6 100644 --- a/gfx/harfbuzz/src/hb-ot-shape.cc +++ b/gfx/harfbuzz/src/hb-ot-shape.cc @@ -299,15 +299,36 @@ hb_ot_position_complex (hb_ot_shape_context_t *c) c->applied_position_complex = TRUE; } - hb_ot_layout_position_finish (c->buffer); + hb_ot_layout_position_finish (c->face, c->buffer); return; } static void -hb_position_complex_fallback (hb_ot_shape_context_t *c HB_UNUSED) +hb_position_complex_fallback (hb_ot_shape_context_t *c) { - /* TODO Mark pos */ + unsigned int count = c->buffer->len; + if (c->buffer->props.direction == HB_DIRECTION_RTL) { + for (unsigned int i = 1; i < count; i++) { + unsigned int gen_cat = c->buffer->info[i].general_category(); + if ((1<buffer->pos[i].x_advance = 0; + } + } + } else { + for (unsigned int i = 1; i < count; i++) { + unsigned int gen_cat = c->buffer->info[i].general_category(); + if ((1<buffer->pos[i]; + pos.x_offset = -pos.x_advance; + pos.x_advance = 0; + } + } + } } static void From e326003e43d2b1dcf1f0241c4b4570c186acb601 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Thu, 16 Feb 2012 14:28:04 -0800 Subject: [PATCH 69/93] Bug 726194 - Sync pairing succeeds, but is OFF. --- .../sync/repositories/android/RepoUtils.java | 24 +++++++++++++++++++ .../setup/activities/AccountActivity.java | 6 +++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/mobile/android/base/sync/repositories/android/RepoUtils.java b/mobile/android/base/sync/repositories/android/RepoUtils.java index 4bb6f7440d14..2e29e0616a0f 100644 --- a/mobile/android/base/sync/repositories/android/RepoUtils.java +++ b/mobile/android/base/sync/repositories/android/RepoUtils.java @@ -54,6 +54,7 @@ import org.mozilla.gecko.sync.repositories.domain.PasswordRecord; import android.content.Context; import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; import android.net.Uri; public class RepoUtils { @@ -165,6 +166,7 @@ public class RepoUtils { return this.query(null, projection, selection, selectionArgs, sortOrder); } + // For ContentProvider queries. public Cursor query(String label, String[] projection, String selection, String[] selectionArgs, String sortOrder) { String logLabel = (label == null) ? this.tag : this.tag + label; long queryStart = android.os.SystemClock.uptimeMillis(); @@ -174,6 +176,17 @@ public class RepoUtils { return c; } + // For SQLiteOpenHelper queries. + public Cursor query(SQLiteDatabase db, String label, String table, String[] columns, + String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) { + String logLabel = (label == null) ? this.tag : this.tag + label; + long queryStart = android.os.SystemClock.uptimeMillis(); + Cursor c = db.query(table, columns, selection, selectionArgs, groupBy, having, orderBy, limit); + long queryEnd = android.os.SystemClock.uptimeMillis(); + RepoUtils.queryTimeLogger(logLabel, queryStart, queryEnd); + return c; + } + public Cursor safeQuery(String label, String[] projection, String selection, String[] selectionArgs, String sortOrder) throws NullCursorException { Cursor c = this.query(label, projection, selection, selectionArgs, sortOrder); if (c == null) { @@ -182,6 +195,17 @@ public class RepoUtils { } return c; } + + public Cursor safeQuery(SQLiteDatabase db, String label, String table, String[] columns, + String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) throws NullCursorException { + Cursor c = this.query(db, label, table, columns, selection, selectionArgs, + groupBy, having, orderBy, limit); + if (c == null) { + Logger.error(tag, "Got null cursor exception in " + tag + ((label == null) ? "" : label)); + throw new NullCursorException(null); + } + return c; + } } public static String getStringFromCursor(Cursor cur, String colId) { diff --git a/mobile/android/base/sync/setup/activities/AccountActivity.java b/mobile/android/base/sync/setup/activities/AccountActivity.java index 4effd15bd060..dadca4a907f6 100644 --- a/mobile/android/base/sync/setup/activities/AccountActivity.java +++ b/mobile/android/base/sync/setup/activities/AccountActivity.java @@ -230,7 +230,8 @@ public class AccountActivity extends AccountAuthenticatorActivity { AccountManager accountManager, String username, String syncKey, - String password, String serverURL) { + String password, + String serverURL) { final Account account = new Account(username, Constants.ACCOUNTTYPE_SYNC); final Bundle userbundle = new Bundle(); @@ -246,7 +247,7 @@ public class AccountActivity extends AccountAuthenticatorActivity { Log.d(LOG_TAG, "Adding account for " + Constants.ACCOUNTTYPE_SYNC); boolean result = accountManager.addAccountExplicitly(account, password, userbundle); - Log.d(LOG_TAG, "Account: " + account.toString() + " added successfully? " + result); + Log.d(LOG_TAG, "Account: " + account + " added successfully? " + result); if (!result) { Log.e(LOG_TAG, "Error adding account!"); } @@ -254,6 +255,7 @@ public class AccountActivity extends AccountAuthenticatorActivity { // Set components to sync (default: all). ContentResolver.setMasterSyncAutomatically(true); ContentResolver.setSyncAutomatically(account, Authorities.BROWSER_AUTHORITY, true); + ContentResolver.setIsSyncable(account, Authorities.BROWSER_AUTHORITY, 1); // TODO: add other ContentProviders as needed (e.g. passwords) // TODO: for each, also add to res/xml to make visible in account settings From e2dbb7fad5a9778ebe0609c163c617c94c2937d8 Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Thu, 16 Feb 2012 14:37:16 -0800 Subject: [PATCH 70/93] Bug 727921 - Add test case --- js/src/jit-test/tests/basic/bug727921.js | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 js/src/jit-test/tests/basic/bug727921.js diff --git a/js/src/jit-test/tests/basic/bug727921.js b/js/src/jit-test/tests/basic/bug727921.js new file mode 100644 index 000000000000..88e6773a7dfa --- /dev/null +++ b/js/src/jit-test/tests/basic/bug727921.js @@ -0,0 +1,10 @@ +(function() { + let(d) { + yield + } +})() +eval("\ + (function(){\ + schedulegc(5), 'a'.replace(/a/,function(){yield})\ + })\ +")() From f918eb6fb9647eb1a410df5b21d9caedc708e6e9 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Thu, 16 Feb 2012 14:27:37 -0800 Subject: [PATCH 71/93] Bug 727980 - Do not mark script atoms as roots; r=billm Fixes a regression from bug 721463. --HG-- extra : rebase_source : 601530388cb62f78b93a4ab35e749a7ee29d5d05 --- js/src/jsgcmark.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/js/src/jsgcmark.cpp b/js/src/jsgcmark.cpp index b287d4715c9d..ec8ed69284d0 100644 --- a/js/src/jsgcmark.cpp +++ b/js/src/jsgcmark.cpp @@ -144,7 +144,8 @@ MarkRoot(JSTracer *trc, T *thing, const char *name) template static void -MarkRange(JSTracer *trc, size_t len, HeapPtr *vec, const char *name) { +MarkRange(JSTracer *trc, size_t len, HeapPtr *vec, const char *name) +{ for (size_t i = 0; i < len; ++i) { if (T *obj = vec[i]) { JS_SET_TRACING_INDEX(trc, name, i); @@ -155,7 +156,8 @@ MarkRange(JSTracer *trc, size_t len, HeapPtr *vec, const char *name) { template static void -MarkRootRange(JSTracer *trc, size_t len, T **vec, const char *name) { +MarkRootRange(JSTracer *trc, size_t len, T **vec, const char *name) +{ for (size_t i = 0; i < len; ++i) { JS_SET_TRACING_INDEX(trc, name, i); MarkInternal(trc, vec[i]); @@ -669,7 +671,10 @@ MarkChildren(JSTracer *trc, JSScript *script) JS_ASSERT_IF(trc->runtime->gcCheckCompartment, script->compartment() == trc->runtime->gcCheckCompartment); - MarkStringRootRange(trc, script->natoms, script->atoms, "atoms"); + for (uint32_t i = 0; i < script->natoms; ++i) { + if (JSAtom *p = script->atoms[i]) + MarkStringUnbarriered(trc, p, "atom"); + } if (JSScript::isValidOffset(script->objectsOffset)) { JSObjectArray *objarray = script->objects(); From 10c4076464b61fbca3578c6a662d7a5e330018ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabrice=20Desr=C3=A9?= Date: Thu, 16 Feb 2012 14:40:43 -0800 Subject: [PATCH 72/93] Bug 727287 - Battery support for akami devices [r=mounir] --- hal/gonk/GonkHal.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/hal/gonk/GonkHal.cpp b/hal/gonk/GonkHal.cpp index 4c98315b003d..a36e4984b148 100644 --- a/hal/gonk/GonkHal.cpp +++ b/hal/gonk/GonkHal.cpp @@ -268,10 +268,29 @@ GetCurrentBatteryInformation(hal::BatteryInformation *aBatteryInfo) } FILE *chargingFile = fopen("/sys/class/power_supply/battery/charging_source", "r"); - int chargingSrc = 1; + int chargingSrc = BATTERY_CHARGING_USB; + bool done = false; if (chargingFile) { fscanf(chargingFile, "%d", &chargingSrc); fclose(chargingFile); + done = true; + } + + if (!done) { + // toro devices support + chargingFile = fopen("/sys/class/power_supply/battery/status", "r"); + if (chargingFile) { + char status[16]; + fscanf(chargingFile, "%s", &status); + if (!strcmp(status, "Charging") || !strcmp(status, "Full")) { + // no way here to know if we're charging from USB or AC. + chargingSrc = BATTERY_CHARGING_USB; + } else { + chargingSrc = BATTERY_NOT_CHARGING; + } + fclose(chargingFile); + done = true; + } } #ifdef DEBUG From d4d3a9c6b06ab6ce42169c7f4939d6079767d052 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Wed, 15 Feb 2012 17:55:25 -0800 Subject: [PATCH 73/93] Bug 723346 - Make sharpObjectMap a modern HashMap; r=Waldo This is the last user of the old-style C hashtables in the JS engine. --HG-- extra : rebase_source : ccf8b296371227c0f0eea59a41b78eb4b63e8275 --- js/src/jsarray.cpp | 11 ++-- js/src/jscntxt.cpp | 1 + js/src/jscntxt.h | 21 +++++-- js/src/jsobj.cpp | 140 ++++++++++++++++++--------------------------- js/src/jsobj.h | 9 +-- 5 files changed, 79 insertions(+), 103 deletions(-) diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index dc1e0bbbc033..80be1d59e576 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -1434,23 +1434,22 @@ JSObject::makeDenseArraySlow(JSContext *cx) class ArraySharpDetector { JSContext *cx; - JSHashEntry *he; + bool success; bool alreadySeen; bool sharp; public: ArraySharpDetector(JSContext *cx) : cx(cx), - he(NULL), + success(false), alreadySeen(false), sharp(false) {} bool init(JSObject *obj) { - he = js_EnterSharpObject(cx, obj, NULL, &alreadySeen); - if (!he) + success = js_EnterSharpObject(cx, obj, NULL, &alreadySeen, &sharp); + if (!success) return false; - sharp = IS_SHARP(he); return true; } @@ -1460,7 +1459,7 @@ class ArraySharpDetector } ~ArraySharpDetector() { - if (he && !sharp) + if (success && !sharp) js_LeaveSharpObject(cx, NULL); } }; diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 663b604a8d00..66ffc9db423b 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -970,6 +970,7 @@ JSContext::JSContext(JSRuntime *rt) stack(thisDuringConstruction()), /* depends on cx->thread_ */ parseMapPool_(NULL), globalObject(NULL), + sharpObjectMap(this), argumentFormatMap(NULL), lastMessage(NULL), errorReporter(NULL), diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index c6f54d95b2d3..c17fd19d8b55 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -76,12 +76,23 @@ JS_BEGIN_EXTERN_C struct DtoaState; JS_END_EXTERN_C -struct JSSharpObjectMap { - jsrefcount depth; - uint32_t sharpgen; - JSHashTable *table; +struct JSSharpInfo { + bool hasGen; + bool isSharp; - JSSharpObjectMap() : depth(0), sharpgen(0), table(NULL) {} + JSSharpInfo() : hasGen(false), isSharp(false) {} +}; + +typedef js::HashMap JSSharpTable; + +struct JSSharpObjectMap { + jsrefcount depth; + uint32_t sharpgen; + JSSharpTable table; + + JSSharpObjectMap(JSContext *cx) : depth(0), sharpgen(0), table(js::TempAllocPolicy(cx)) { + table.init(); + } }; namespace js { diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 8f921b8f9ad0..b29d88059232 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -203,14 +203,8 @@ obj_setProto(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp) #endif /* !JS_HAS_OBJ_PROTO_PROP */ -static JSHashNumber -js_hash_object(const void *key) -{ - return JSHashNumber(uintptr_t(key) >> JS_GCTHING_ALIGN); -} - -static JSHashEntry * -MarkSharpObjects(JSContext *cx, JSObject *obj, JSIdArray **idap) +static bool +MarkSharpObjects(JSContext *cx, JSObject *obj, JSIdArray **idap, JSSharpInfo *value) { JS_CHECK_RECURSION(cx, return NULL); @@ -218,21 +212,15 @@ MarkSharpObjects(JSContext *cx, JSObject *obj, JSIdArray **idap) JSSharpObjectMap *map = &cx->sharpObjectMap; JS_ASSERT(map->depth >= 1); - JSHashTable *table = map->table; - JSHashNumber hash = js_hash_object(obj); - JSHashEntry **hep = JS_HashTableRawLookup(table, hash, obj); - JSHashEntry *he = *hep; - if (!he) { - jsatomid sharpid = 0; - he = JS_HashTableRawAdd(table, hep, hash, obj, (void *) sharpid); - if (!he) { - JS_ReportOutOfMemory(cx); - return NULL; - } + JSSharpInfo sharpid; + JSSharpTable::Ptr p = map->table.lookup(obj); + if (!p) { + if (!map->table.put(obj, sharpid)) + return false; ida = JS_Enumerate(cx, obj); if (!ida) - return NULL; + return false; bool ok = true; for (jsint i = 0, length = ida->length; i < length; i++) { @@ -261,7 +249,7 @@ MarkSharpObjects(JSContext *cx, JSObject *obj, JSIdArray **idap) if (hasSetter) { /* Mark the getter, then set val to setter. */ if (hasGetter && v.value().isObject()) { - ok = !!MarkSharpObjects(cx, &v.value().toObject(), NULL); + ok = MarkSharpObjects(cx, &v.value().toObject(), NULL, NULL); if (!ok) break; } @@ -271,7 +259,7 @@ MarkSharpObjects(JSContext *cx, JSObject *obj, JSIdArray **idap) if (!ok) break; } - if (v.value().isObject() && !MarkSharpObjects(cx, &v.value().toObject(), NULL)) { + if (v.value().isObject() && !MarkSharpObjects(cx, &v.value().toObject(), NULL, NULL)) { ok = false; break; } @@ -279,47 +267,42 @@ MarkSharpObjects(JSContext *cx, JSObject *obj, JSIdArray **idap) if (!ok || !idap) JS_DestroyIdArray(cx, ida); if (!ok) - return NULL; + return false; } else { - jsatomid sharpid = uintptr_t(he->value); - if (sharpid == 0) { - sharpid = ++map->sharpgen << SHARP_ID_SHIFT; - he->value = (void *) sharpid; + if (!p->value.hasGen && !p->value.isSharp) { + p->value.hasGen = true; } + sharpid = p->value; ida = NULL; } if (idap) *idap = ida; - return he; + if (value) + *value = sharpid; + return true; } -JSHashEntry * -js_EnterSharpObject(JSContext *cx, JSObject *obj, JSIdArray **idap, bool *alreadySeen) +bool +js_EnterSharpObject(JSContext *cx, JSObject *obj, JSIdArray **idap, bool *alreadySeen, bool *isSharp) { if (!JS_CHECK_OPERATION_LIMIT(cx)) - return NULL; + return false; *alreadySeen = false; JSSharpObjectMap *map = &cx->sharpObjectMap; - JSHashTable *table = map->table; - if (!table) { - table = JS_NewHashTable(8, js_hash_object, JS_CompareValues, - JS_CompareValues, NULL, NULL); - if (!table) { - JS_ReportOutOfMemory(cx); - return NULL; - } - map->table = table; - JS_KEEP_ATOMS(cx->runtime); - } - JSHashEntry *he; - jsatomid sharpid; + JS_ASSERT_IF(map->depth == 0, map->table.count() == 0); + JS_ASSERT_IF(map->table.count() == 0, map->depth == 0); + + JSSharpTable::Ptr p; + JSSharpInfo sharpid; JSIdArray *ida = NULL; /* From this point the control must flow either through out: or bad:. */ if (map->depth == 0) { + JS_KEEP_ATOMS(cx->runtime); + /* * Although MarkSharpObjects tries to avoid invoking getters, * it ends up doing so anyway under some circumstances; for @@ -332,21 +315,18 @@ js_EnterSharpObject(JSContext *cx, JSObject *obj, JSIdArray **idap, bool *alread * ensure that such a call doesn't free the hash table we're * still using. */ - ++map->depth; - he = MarkSharpObjects(cx, obj, &ida); - --map->depth; - if (!he) + map->depth = 1; + bool success = MarkSharpObjects(cx, obj, &ida, &sharpid); + JS_ASSERT(map->depth == 1); + map->depth = 0; + if (!success) goto bad; - JS_ASSERT((uintptr_t(he->value) & SHARP_BIT) == 0); + JS_ASSERT(!sharpid.isSharp); if (!idap) { JS_DestroyIdArray(cx, ida); ida = NULL; } } else { - JSHashNumber hash = js_hash_object(obj); - JSHashEntry **hep = JS_HashTableRawLookup(table, hash, obj); - he = *hep; - /* * It's possible that the value of a property has changed from the * first time the object's properties are traversed (when the property @@ -354,24 +334,20 @@ js_EnterSharpObject(JSContext *cx, JSObject *obj, JSIdArray **idap, bool *alread * converted to strings), i.e., the JSObject::getProperty() call is not * idempotent. */ - if (!he) { - he = JS_HashTableRawAdd(table, hep, hash, obj, NULL); - if (!he) { - JS_ReportOutOfMemory(cx); + p = map->table.lookup(obj); + if (!p) { + if (!map->table.put(obj, sharpid)) goto bad; - } - sharpid = 0; goto out; } + sharpid = p->value; } - sharpid = uintptr_t(he->value); - if (sharpid != 0) + if (sharpid.isSharp || sharpid.hasGen) *alreadySeen = true; out: - JS_ASSERT(he); - if ((sharpid & SHARP_BIT) == 0) { + if (!sharpid.isSharp) { if (idap && !ida) { ida = JS_Enumerate(cx, obj); if (!ida) @@ -382,17 +358,17 @@ out: if (idap) *idap = ida; - return he; + *isSharp = sharpid.isSharp; + return true; bad: /* Clean up the sharpObjectMap table on outermost error. */ if (map->depth == 0) { JS_UNKEEP_ATOMS(cx->runtime); map->sharpgen = 0; - JS_HashTableDestroy(map->table); - map->table = NULL; + map->table.clear(); } - return NULL; + return false; } void @@ -403,8 +379,7 @@ js_LeaveSharpObject(JSContext *cx, JSIdArray **idap) if (--map->depth == 0) { JS_UNKEEP_ATOMS(cx->runtime); map->sharpgen = 0; - JS_HashTableDestroy(map->table); - map->table = NULL; + map->table.clear(); } if (idap) { if (JSIdArray *ida = *idap) { @@ -414,18 +389,10 @@ js_LeaveSharpObject(JSContext *cx, JSIdArray **idap) } } -static intN -gc_sharp_table_entry_marker(JSHashEntry *he, intN i, void *arg) -{ - MarkObjectRoot((JSTracer *)arg, (JSObject *)he->key, "sharp table entry"); - return JS_DHASH_NEXT; -} - void js_TraceSharpMap(JSTracer *trc, JSSharpObjectMap *map) { JS_ASSERT(map->depth > 0); - JS_ASSERT(map->table); /* * During recursive calls to MarkSharpObjects a non-native object or @@ -447,7 +414,8 @@ js_TraceSharpMap(JSTracer *trc, JSSharpObjectMap *map) * with otherwise unreachable objects. But this is way too complex * to justify spending efforts. */ - JS_HashTableEnumerateEntries(map->table, gc_sharp_table_entry_marker, trc); + for (JSSharpTable::Range r = map->table.all(); !r.empty(); r.popFront()) + MarkObjectRoot(trc, r.front().key, "sharp table entry"); } #if JS_HAS_TOSOURCE @@ -475,8 +443,8 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp) JSIdArray *ida; bool alreadySeen = false; - JSHashEntry *he = js_EnterSharpObject(cx, obj, &ida, &alreadySeen); - if (!he) + bool isSharp = false; + if (!js_EnterSharpObject(cx, obj, &ida, &alreadySeen, &isSharp)) return false; if (!ida) { @@ -491,10 +459,14 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp) vp->setString(str); return true; } - JS_ASSERT(!IS_SHARP(he)); - if (alreadySeen) - MAKE_SHARP(he); + JS_ASSERT(!isSharp); + if (alreadySeen) { + JSSharpTable::Ptr p = cx->sharpObjectMap.table.lookup(obj); + JS_ASSERT(p); + JS_ASSERT(!p->value.isSharp); + p->value.isSharp = true; + } /* Automatically call js_LeaveSharpObject when we leave this frame. */ class AutoLeaveSharpObject { @@ -537,7 +509,6 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp) JSString *s = ToString(cx, IdToValue(id)); if (!s || !(idstr = s->ensureLinear(cx))) return false; - vp->setString(idstr); /* local root */ int valcnt = 0; if (prop) { @@ -576,7 +547,6 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp) s = js_QuoteString(cx, idstr, jschar('\'')); if (!s || !(idstr = s->ensureLinear(cx))) return false; - vp->setString(idstr); /* local root */ } for (int j = 0; j < valcnt; j++) { diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 3f9a322e5812..fe0bb874e493 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -1554,13 +1554,8 @@ class ValueArray { }; /* For manipulating JSContext::sharpObjectMap. */ -#define SHARP_BIT ((jsatomid) 1) -#define SHARP_ID_SHIFT 2 -#define IS_SHARP(he) (uintptr_t((he)->value) & SHARP_BIT) -#define MAKE_SHARP(he) ((he)->value = (void *) (uintptr_t((he)->value)|SHARP_BIT)) - -extern JSHashEntry * -js_EnterSharpObject(JSContext *cx, JSObject *obj, JSIdArray **idap, bool *alreadySeen); +extern bool +js_EnterSharpObject(JSContext *cx, JSObject *obj, JSIdArray **idap, bool *alreadySeen, bool *isSharp); extern void js_LeaveSharpObject(JSContext *cx, JSIdArray **idap); From 312f343570c20b7929ad25844b93f2779550b416 Mon Sep 17 00:00:00 2001 From: Philipp von Weitershausen Date: Thu, 16 Feb 2012 14:50:52 -0800 Subject: [PATCH 74/93] Bug 720632 - Part 1: nsISmsRequestManager. r=cjones,gal --- dom/sms/interfaces/Makefile.in | 5 +- dom/sms/interfaces/nsISmsRequestManager.idl | 80 +++++++++++++++++++++ 2 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 dom/sms/interfaces/nsISmsRequestManager.idl diff --git a/dom/sms/interfaces/Makefile.in b/dom/sms/interfaces/Makefile.in index af249a14d8cc..c7bbeb0a86e4 100644 --- a/dom/sms/interfaces/Makefile.in +++ b/dom/sms/interfaces/Makefile.in @@ -48,13 +48,14 @@ include $(topsrcdir)/dom/dom-config.mk XPIDLSRCS = \ nsIDOMNavigatorSms.idl \ nsIDOMSmsManager.idl \ - nsISmsService.idl \ nsIDOMSmsMessage.idl \ nsIDOMSmsEvent.idl \ - nsISmsDatabaseService.idl \ nsIDOMSmsRequest.idl \ nsIDOMSmsFilter.idl \ nsIDOMSmsCursor.idl \ + nsISmsDatabaseService.idl \ + nsISmsRequestManager.idl \ + nsISmsService.idl \ $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/dom/sms/interfaces/nsISmsRequestManager.idl b/dom/sms/interfaces/nsISmsRequestManager.idl new file mode 100644 index 000000000000..7da44f336995 --- /dev/null +++ b/dom/sms/interfaces/nsISmsRequestManager.idl @@ -0,0 +1,80 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsISupports.idl" + +interface nsIDOMMozSmsMessage; +interface nsIDOMMozSmsRequest; +interface nsPIDOMWindow; +interface nsIScriptContext; + +%{C++ +#define SMS_REQUEST_MANAGER_CID \ +{ 0xa97a3129, 0x1e0b, 0x45da, \ +{ 0xa3, 0x85, 0xcf, 0xe5, 0xb0, 0xb1, 0xc4, 0x8f } } +#define SMS_REQUEST_MANAGER_CONTRACTID "@mozilla.org/sms/smsrequestmanager;1" +%} + +[scriptable, uuid(1638b963-3a45-4937-b6a9-280c1bfb166c)] +interface nsISmsRequestManager : nsISupports +{ + + /** + * All SMS related errors that could apply to SmsRequest objects. + * Make sure to keep this list in sync with the list in: + * embedding/android/GeckoSmsManager.java + */ + const unsigned short NO_ERROR = 0; + const unsigned short NO_SIGNAL_ERROR = 1; + const unsigned short NOT_FOUND_ERROR = 2; + const unsigned short UNKNOWN_ERROR = 3; + const unsigned short INTERNAL_ERROR = 4; + + /** + * Create a new request object. + * + * @return the request ID. + */ + long createRequest(in nsPIDOMWindow aWindow, + in nsIScriptContext aScriptContext, + out nsIDOMMozSmsRequest aRequest); + + /** + * Track an already existing request object. + * + * @return the request ID. + */ + long addRequest(in nsIDOMMozSmsRequest aRequest); + + void notifySmsSent(in long aRequestId, + in nsIDOMMozSmsMessage aMessage); + + void notifySmsSendFailed(in long aRequestId, + in long aError); + + void notifyGotSms(in long aRequestId, + in nsIDOMMozSmsMessage aMessage); + + void notifyGetSmsFailed(in long aRequestId, + in long aError); + + void notifySmsDeleted(in long aRequestId, + in bool aDeleted); + + void notifySmsDeleteFailed(in long aRequestId, + in long aError); + + void notifyNoMessageInList(in long aRequestId); + + void notifyCreateMessageList(in long aRequestId, + in long aListId, + in nsIDOMMozSmsMessage aMessage); + + void notifyGotNextMessage(in long aRequestId, + in nsIDOMMozSmsMessage aMessage); + + void notifyReadMessageListFailed(in long aRequestId, + in long aError); + +}; From 87fbd01b63e14a1522b27f67e3d9432c555d174f Mon Sep 17 00:00:00 2001 From: Philipp von Weitershausen Date: Thu, 16 Feb 2012 14:50:52 -0800 Subject: [PATCH 75/93] Bug 720632 - Part 2: XPCOMtaminate SmsRequestManager. r=cjones,mounir --- dom/sms/src/SmsCursor.cpp | 6 +- dom/sms/src/SmsManager.cpp | 52 ++++++++---- dom/sms/src/SmsRequest.cpp | 38 +++++---- dom/sms/src/SmsRequest.h | 17 +--- dom/sms/src/SmsRequestManager.cpp | 110 +++++++++++-------------- dom/sms/src/SmsRequestManager.h | 36 ++------ dom/sms/src/ipc/SmsChild.cpp | 34 ++++---- embedding/android/GeckoSmsManager.java | 6 +- 8 files changed, 144 insertions(+), 155 deletions(-) diff --git a/dom/sms/src/SmsCursor.cpp b/dom/sms/src/SmsCursor.cpp index b038d003f3f1..4da2c16c8026 100644 --- a/dom/sms/src/SmsCursor.cpp +++ b/dom/sms/src/SmsCursor.cpp @@ -115,7 +115,11 @@ SmsCursor::Continue() mMessage = nsnull; static_cast(mRequest.get())->Reset(); - PRInt32 requestId = SmsRequestManager::GetInstance()->AddRequest(mRequest); + nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); + + PRInt32 requestId; + nsresult rv = requestManager->AddRequest(mRequest, &requestId); + NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr smsDBService = do_GetService(SMS_DATABASE_SERVICE_CONTRACTID); diff --git a/dom/sms/src/SmsManager.cpp b/dom/sms/src/SmsManager.cpp index 6aab2e1bd91f..eee5d9adcc5f 100644 --- a/dom/sms/src/SmsManager.cpp +++ b/dom/sms/src/SmsManager.cpp @@ -146,17 +146,23 @@ SmsManager::Send(JSContext* aCx, JSObject* aGlobal, JSString* aNumber, nsCOMPtr request; - int requestId = - SmsRequestManager::GetInstance()->CreateRequest(mOwner, mScriptContext, - getter_AddRefs(request)); - NS_ASSERTION(request, "The request object must have been created!"); + nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); + + PRInt32 requestId; + nsresult rv = requestManager->CreateRequest(mOwner, mScriptContext, + getter_AddRefs(request), + &requestId); + if (NS_FAILED(rv)) { + NS_ERROR("Failed to create the request!"); + return rv; + } nsDependentJSString number; number.init(aCx, aNumber); smsService->Send(number, aMessage, requestId, 0); - nsresult rv = nsContentUtils::WrapNative(aCx, aGlobal, request, aRequest); + rv = nsContentUtils::WrapNative(aCx, aGlobal, request, aRequest); if (NS_FAILED(rv)) { NS_ERROR("Failed to create the js value!"); return rv; @@ -217,9 +223,15 @@ SmsManager::Send(const jsval& aNumber, const nsAString& aMessage, jsval* aReturn NS_IMETHODIMP SmsManager::GetMessageMoz(PRInt32 aId, nsIDOMMozSmsRequest** aRequest) { - int requestId = - SmsRequestManager::GetInstance()->CreateRequest(mOwner, mScriptContext, aRequest); - NS_ASSERTION(*aRequest, "The request object must have been created!"); + nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); + + PRInt32 requestId; + nsresult rv = requestManager->CreateRequest(mOwner, mScriptContext, aRequest, + &requestId); + if (NS_FAILED(rv)) { + NS_ERROR("Failed to create the request!"); + return rv; + } nsCOMPtr smsDBService = do_GetService(SMS_DATABASE_SERVICE_CONTRACTID); @@ -233,9 +245,15 @@ SmsManager::GetMessageMoz(PRInt32 aId, nsIDOMMozSmsRequest** aRequest) nsresult SmsManager::Delete(PRInt32 aId, nsIDOMMozSmsRequest** aRequest) { - int requestId = - SmsRequestManager::GetInstance()->CreateRequest(mOwner, mScriptContext, aRequest); - NS_ASSERTION(*aRequest, "The request object must have been created!"); + nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); + + PRInt32 requestId; + nsresult rv = requestManager->CreateRequest(mOwner, mScriptContext, aRequest, + &requestId); + if (NS_FAILED(rv)) { + NS_ERROR("Failed to create the request!"); + return rv; + } nsCOMPtr smsDBService = do_GetService(SMS_DATABASE_SERVICE_CONTRACTID); @@ -278,9 +296,15 @@ SmsManager::GetMessages(nsIDOMMozSmsFilter* aFilter, bool aReverse, filter = new SmsFilter(); } - int requestId = - SmsRequestManager::GetInstance()->CreateRequest(mOwner, mScriptContext, aRequest); - NS_ASSERTION(*aRequest, "The request object must have been created!"); + nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); + + PRInt32 requestId; + nsresult rv = requestManager->CreateRequest(mOwner, mScriptContext, aRequest, + &requestId); + if (NS_FAILED(rv)) { + NS_ERROR("Failed to create the request!"); + return rv; + } nsCOMPtr smsDBService = do_GetService(SMS_DATABASE_SERVICE_CONTRACTID); diff --git a/dom/sms/src/SmsRequest.cpp b/dom/sms/src/SmsRequest.cpp index 7dbcba0c22d5..4e2387d9b542 100644 --- a/dom/sms/src/SmsRequest.cpp +++ b/dom/sms/src/SmsRequest.cpp @@ -41,6 +41,7 @@ #include "nsContentUtils.h" #include "nsIDOMSmsMessage.h" #include "nsIDOMSmsCursor.h" +#include "nsISmsRequestManager.h" DOMCI_DATA(MozSmsRequest, mozilla::dom::sms::SmsRequest) @@ -92,7 +93,7 @@ NS_IMPL_EVENT_HANDLER(SmsRequest, error) SmsRequest::SmsRequest(nsPIDOMWindow* aWindow, nsIScriptContext* aScriptContext) : mResult(JSVAL_VOID) , mResultRooted(false) - , mError(eNoError) + , mError(nsISmsRequestManager::NO_ERROR) , mDone(false) { // Those vars come from nsDOMEventTargetHelper. @@ -112,7 +113,8 @@ SmsRequest::Reset() { NS_ASSERTION(mDone, "mDone should be true if we try to reset!"); NS_ASSERTION(mResult != JSVAL_VOID, "mResult should be set if we try to reset!"); - NS_ASSERTION(mError == eNoError, "There should be no error if we try to reset!"); + NS_ASSERTION(mError == nsISmsRequestManager::NO_ERROR, + "There should be no error if we try to reset!"); if (mResultRooted) { UnrootResult(); @@ -148,7 +150,8 @@ void SmsRequest::SetSuccess(bool aResult) { NS_PRECONDITION(!mDone, "mDone shouldn't have been set to true already!"); - NS_PRECONDITION(mError == eNoError, "mError shouldn't have been set!"); + NS_PRECONDITION(mError == nsISmsRequestManager::NO_ERROR, + "mError shouldn't have been set!"); NS_PRECONDITION(mResult == JSVAL_NULL, "mResult shouldn't have been set!"); mResult.setBoolean(aResult); @@ -174,7 +177,8 @@ bool SmsRequest::SetSuccessInternal(nsISupports* aObject) { NS_PRECONDITION(!mDone, "mDone shouldn't have been set to true already!"); - NS_PRECONDITION(mError == eNoError, "mError shouldn't have been set!"); + NS_PRECONDITION(mError == nsISmsRequestManager::NO_ERROR, + "mError shouldn't have been set!"); NS_PRECONDITION(mResult == JSVAL_VOID, "mResult shouldn't have been set!"); JSContext* cx = mScriptContext->GetNativeContext(); @@ -186,7 +190,7 @@ SmsRequest::SetSuccessInternal(nsISupports* aObject) JSAutoRequest ar(cx); JSAutoEnterCompartment ac; if (!ac.enter(cx, global)) { - SetError(eInternalError); + SetError(nsISmsRequestManager::INTERNAL_ERROR); return false; } @@ -195,7 +199,7 @@ SmsRequest::SetSuccessInternal(nsISupports* aObject) if (NS_FAILED(nsContentUtils::WrapNative(cx, global, aObject, &mResult))) { UnrootResult(); mResult = JSVAL_VOID; - SetError(eInternalError); + SetError(nsISmsRequestManager::INTERNAL_ERROR); return false; } @@ -204,10 +208,11 @@ SmsRequest::SetSuccessInternal(nsISupports* aObject) } void -SmsRequest::SetError(ErrorType aError) +SmsRequest::SetError(PRInt32 aError) { NS_PRECONDITION(!mDone, "mDone shouldn't have been set to true already!"); - NS_PRECONDITION(mError == eNoError, "mError shouldn't have been set!"); + NS_PRECONDITION(mError == nsISmsRequestManager::NO_ERROR, + "mError shouldn't have been set!"); NS_PRECONDITION(mResult == JSVAL_VOID, "mResult shouldn't have been set!"); mDone = true; @@ -231,32 +236,35 @@ NS_IMETHODIMP SmsRequest::GetError(nsAString& aError) { if (!mDone) { - NS_ASSERTION(mError == eNoError, + NS_ASSERTION(mError == nsISmsRequestManager::NO_ERROR, "There should be no error if the request is still processing!"); SetDOMStringToNull(aError); return NS_OK; } - NS_ASSERTION(mError == eNoError || mResult == JSVAL_VOID, + NS_ASSERTION(mError == nsISmsRequestManager::NO_ERROR || + mResult == JSVAL_VOID, "mResult should be void when there is an error!"); switch (mError) { - case eNoError: + case nsISmsRequestManager::NO_ERROR: SetDOMStringToNull(aError); break; - case eNoSignalError: + case nsISmsRequestManager::NO_SIGNAL_ERROR: aError.AssignLiteral("NoSignalError"); break; - case eNotFoundError: + case nsISmsRequestManager::NOT_FOUND_ERROR: aError.AssignLiteral("NotFoundError"); break; - case eUnknownError: + case nsISmsRequestManager::UNKNOWN_ERROR: aError.AssignLiteral("UnknownError"); break; - case eInternalError: + case nsISmsRequestManager::INTERNAL_ERROR: aError.AssignLiteral("InternalError"); break; + default: + MOZ_ASSERT(false, "Unknown error value."); } return NS_OK; diff --git a/dom/sms/src/SmsRequest.h b/dom/sms/src/SmsRequest.h index 973a2000bc12..d034ca569ff0 100644 --- a/dom/sms/src/SmsRequest.h +++ b/dom/sms/src/SmsRequest.h @@ -54,19 +54,6 @@ class SmsRequest : public nsIDOMMozSmsRequest public: friend class SmsRequestManager; - /** - * All SMS related errors that could apply to SmsRequest objects. - * Make sure to keep this list in sync with the list in: - * embedding/android/GeckoSmsManager.java - */ - enum ErrorType { - eNoError = 0, - eNoSignalError, - eNotFoundError, - eUnknownError, - eInternalError, - }; - NS_DECL_ISUPPORTS NS_DECL_NSIDOMMOZSMSREQUEST @@ -111,7 +98,7 @@ private: /** * Set the object in an error state with the error type being aError. */ - void SetError(ErrorType aError); + void SetError(PRInt32 aError); /** * Set the object in a success state with the result being the nsISupports @@ -129,7 +116,7 @@ private: jsval mResult; bool mResultRooted; - ErrorType mError; + PRInt32 mError; bool mDone; nsCOMPtr mCursor; diff --git a/dom/sms/src/SmsRequestManager.cpp b/dom/sms/src/SmsRequestManager.cpp index 28bd9229486a..45f55a3cee4c 100644 --- a/dom/sms/src/SmsRequestManager.cpp +++ b/dom/sms/src/SmsRequestManager.cpp @@ -51,33 +51,11 @@ namespace mozilla { namespace dom { namespace sms { -SmsRequestManager* SmsRequestManager::sInstance = nsnull; +NS_IMPL_ISUPPORTS1(SmsRequestManager, nsISmsRequestManager) -void -SmsRequestManager::Init() -{ - NS_PRECONDITION(!sInstance, - "sInstance shouldn't be set. Did you call Init() twice?"); - sInstance = new SmsRequestManager(); -} - -void -SmsRequestManager::Shutdown() -{ - NS_PRECONDITION(sInstance, "sInstance should be set. Did you call Init()?"); - - delete sInstance; - sInstance = nsnull; -} - -/* static */ SmsRequestManager* -SmsRequestManager::GetInstance() -{ - return sInstance; -} - -PRInt32 -SmsRequestManager::AddRequest(nsIDOMMozSmsRequest* aRequest) +NS_IMETHODIMP +SmsRequestManager::AddRequest(nsIDOMMozSmsRequest* aRequest, + PRInt32* aRequestId) { // TODO: merge with CreateRequest PRInt32 size = mRequests.Count(); @@ -89,17 +67,21 @@ SmsRequestManager::AddRequest(nsIDOMMozSmsRequest* aRequest) } mRequests.ReplaceObjectAt(aRequest, i); - return i; + *aRequestId = i; + return NS_OK; } mRequests.AppendObject(aRequest); - return size; + *aRequestId = size; + return NS_OK; } -PRInt32 + +NS_IMETHODIMP SmsRequestManager::CreateRequest(nsPIDOMWindow* aWindow, nsIScriptContext* aScriptContext, - nsIDOMMozSmsRequest** aRequest) + nsIDOMMozSmsRequest** aRequest, + PRInt32* aRequestId) { nsCOMPtr request = new SmsRequest(aWindow, aScriptContext); @@ -114,12 +96,14 @@ SmsRequestManager::CreateRequest(nsPIDOMWindow* aWindow, mRequests.ReplaceObjectAt(request, i); NS_ADDREF(*aRequest = request); - return i; + *aRequestId = i; + return NS_OK; } mRequests.AppendObject(request); NS_ADDREF(*aRequest = request); - return size; + *aRequestId = size; + return NS_OK; } nsresult @@ -149,66 +133,67 @@ SmsRequestManager::GetRequest(PRInt32 aRequestId) } template -void +nsresult SmsRequestManager::NotifySuccess(PRInt32 aRequestId, T aParam) { SmsRequest* request = GetRequest(aRequestId); request->SetSuccess(aParam); - DispatchTrustedEventToRequest(SUCCESS_EVENT_NAME, request); + nsresult rv = DispatchTrustedEventToRequest(SUCCESS_EVENT_NAME, request); mRequests.ReplaceObjectAt(nsnull, aRequestId); + return rv; } -void -SmsRequestManager::NotifyError(PRInt32 aRequestId, SmsRequest::ErrorType aError) +nsresult +SmsRequestManager::NotifyError(PRInt32 aRequestId, PRInt32 aError) { SmsRequest* request = GetRequest(aRequestId); request->SetError(aError); - DispatchTrustedEventToRequest(ERROR_EVENT_NAME, request); + nsresult rv = DispatchTrustedEventToRequest(ERROR_EVENT_NAME, request); mRequests.ReplaceObjectAt(nsnull, aRequestId); + return rv; } -void +NS_IMETHODIMP SmsRequestManager::NotifySmsSent(PRInt32 aRequestId, nsIDOMMozSmsMessage* aMessage) { - NotifySuccess(aRequestId, aMessage); + return NotifySuccess(aRequestId, aMessage); } -void -SmsRequestManager::NotifySmsSendFailed(PRInt32 aRequestId, SmsRequest::ErrorType aError) +NS_IMETHODIMP +SmsRequestManager::NotifySmsSendFailed(PRInt32 aRequestId, PRInt32 aError) { - NotifyError(aRequestId, aError); + return NotifyError(aRequestId, aError); } -void +NS_IMETHODIMP SmsRequestManager::NotifyGotSms(PRInt32 aRequestId, nsIDOMMozSmsMessage* aMessage) { - NotifySuccess(aRequestId, aMessage); + return NotifySuccess(aRequestId, aMessage); } -void -SmsRequestManager::NotifyGetSmsFailed(PRInt32 aRequestId, - SmsRequest::ErrorType aError) +NS_IMETHODIMP +SmsRequestManager::NotifyGetSmsFailed(PRInt32 aRequestId, PRInt32 aError) { - NotifyError(aRequestId, aError); + return NotifyError(aRequestId, aError); } -void +NS_IMETHODIMP SmsRequestManager::NotifySmsDeleted(PRInt32 aRequestId, bool aDeleted) { - NotifySuccess(aRequestId, aDeleted); + return NotifySuccess(aRequestId, aDeleted); } -void -SmsRequestManager::NotifySmsDeleteFailed(PRInt32 aRequestId, SmsRequest::ErrorType aError) +NS_IMETHODIMP +SmsRequestManager::NotifySmsDeleteFailed(PRInt32 aRequestId, PRInt32 aError) { - NotifyError(aRequestId, aError); + return NotifyError(aRequestId, aError); } -void +NS_IMETHODIMP SmsRequestManager::NotifyNoMessageInList(PRInt32 aRequestId) { SmsRequest* request = GetRequest(aRequestId); @@ -220,10 +205,10 @@ SmsRequestManager::NotifyNoMessageInList(PRInt32 aRequestId) static_cast(cursor.get())->Disconnect(); } - NotifySuccess(aRequestId, cursor); + return NotifySuccess(aRequestId, cursor); } -void +NS_IMETHODIMP SmsRequestManager::NotifyCreateMessageList(PRInt32 aRequestId, PRInt32 aListId, nsIDOMMozSmsMessage* aMessage) { @@ -232,10 +217,10 @@ SmsRequestManager::NotifyCreateMessageList(PRInt32 aRequestId, PRInt32 aListId, nsCOMPtr cursor = new SmsCursor(aListId, request); cursor->SetMessage(aMessage); - NotifySuccess(aRequestId, cursor); + return NotifySuccess(aRequestId, cursor); } -void +NS_IMETHODIMP SmsRequestManager::NotifyGotNextMessage(PRInt32 aRequestId, nsIDOMMozSmsMessage* aMessage) { SmsRequest* request = GetRequest(aRequestId); @@ -244,12 +229,11 @@ SmsRequestManager::NotifyGotNextMessage(PRInt32 aRequestId, nsIDOMMozSmsMessage* NS_ASSERTION(cursor, "Request should have an cursor in that case!"); cursor->SetMessage(aMessage); - NotifySuccess(aRequestId, cursor); + return NotifySuccess(aRequestId, cursor); } -void -SmsRequestManager::NotifyReadMessageListFailed(PRInt32 aRequestId, - SmsRequest::ErrorType aError) +NS_IMETHODIMP +SmsRequestManager::NotifyReadMessageListFailed(PRInt32 aRequestId, PRInt32 aError) { SmsRequest* request = GetRequest(aRequestId); @@ -258,7 +242,7 @@ SmsRequestManager::NotifyReadMessageListFailed(PRInt32 aRequestId, static_cast(cursor.get())->Disconnect(); } - NotifyError(aRequestId, aError); + return NotifyError(aRequestId, aError); } } // namespace sms diff --git a/dom/sms/src/SmsRequestManager.h b/dom/sms/src/SmsRequestManager.h index 3b4cd069b1d1..f9464ff3a80a 100644 --- a/dom/sms/src/SmsRequestManager.h +++ b/dom/sms/src/SmsRequestManager.h @@ -41,50 +41,26 @@ #include "nsCOMArray.h" #include "SmsRequest.h" - -class nsIDOMMozSmsRequest; -class nsPIDOMWindow; -class nsIScriptContext; -class nsIDOMMozSmsMessage; +#include "nsISmsRequestManager.h" namespace mozilla { namespace dom { namespace sms { -class SmsRequestManager +class SmsRequestManager : nsISmsRequestManager { public: - static void Init(); - static void Shutdown(); - static SmsRequestManager* GetInstance(); - - PRInt32 CreateRequest(nsPIDOMWindow* aWindow, - nsIScriptContext* aScriptContext, - nsIDOMMozSmsRequest** aRequest); - - PRInt32 AddRequest(nsIDOMMozSmsRequest* aRequest); - - void NotifySmsSent(PRInt32 aRequestId, nsIDOMMozSmsMessage* aMessage); - void NotifySmsSendFailed(PRInt32 aRequestId, SmsRequest::ErrorType aError); - void NotifyGotSms(PRInt32 aRequestId, nsIDOMMozSmsMessage* aMessage); - void NotifyGetSmsFailed(PRInt32 aRequestId, SmsRequest::ErrorType aError); - void NotifySmsDeleted(PRInt32 aRequestId, bool aDeleted); - void NotifySmsDeleteFailed(PRInt32 aRequestId, SmsRequest::ErrorType aError); - void NotifyNoMessageInList(PRInt32 aRequestId); - void NotifyCreateMessageList(PRInt32 aRequestId, PRInt32 aListId, nsIDOMMozSmsMessage* aMessage); - void NotifyGotNextMessage(PRInt32 aRequestId, nsIDOMMozSmsMessage* aMessage); - void NotifyReadMessageListFailed(PRInt32 aRequestId, SmsRequest::ErrorType aError); + NS_DECL_ISUPPORTS + NS_DECL_NSISMSREQUESTMANAGER private: - static SmsRequestManager* sInstance; - nsresult DispatchTrustedEventToRequest(const nsAString& aEventName, nsIDOMMozSmsRequest* aRequest); SmsRequest* GetRequest(PRInt32 aRequestId); template - void NotifySuccess(PRInt32 aRequestId, T aParam); - void NotifyError(PRInt32 aRequestId, SmsRequest::ErrorType aError); + nsresult NotifySuccess(PRInt32 aRequestId, T aParam); + nsresult NotifyError(PRInt32 aRequestId, PRInt32 aError); nsCOMArray mRequests; }; diff --git a/dom/sms/src/ipc/SmsChild.cpp b/dom/sms/src/ipc/SmsChild.cpp index 3b59d532b327..953fa0a18cac 100644 --- a/dom/sms/src/ipc/SmsChild.cpp +++ b/dom/sms/src/ipc/SmsChild.cpp @@ -100,7 +100,8 @@ SmsChild::RecvNotifyRequestSmsSent(const SmsMessageData& aMessage, } nsCOMPtr message = new SmsMessage(aMessage); - SmsRequestManager::GetInstance()->NotifySmsSent(aRequestId, message); + nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); + requestManager->NotifySmsSent(aRequestId, message); return true; } @@ -114,8 +115,8 @@ SmsChild::RecvNotifyRequestSmsSendFailed(const PRInt32& aError, return true; } - SmsRequestManager::GetInstance()->NotifySmsSendFailed(aRequestId, - SmsRequest::ErrorType(aError)); + nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); + requestManager->NotifySmsSendFailed(aRequestId, aError); return true; } @@ -130,7 +131,8 @@ SmsChild::RecvNotifyRequestGotSms(const SmsMessageData& aMessage, } nsCOMPtr message = new SmsMessage(aMessage); - SmsRequestManager::GetInstance()->NotifyGotSms(aRequestId, message); + nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); + requestManager->NotifyGotSms(aRequestId, message); return true; } @@ -144,8 +146,8 @@ SmsChild::RecvNotifyRequestGetSmsFailed(const PRInt32& aError, return true; } - SmsRequestManager::GetInstance()->NotifyGetSmsFailed(aRequestId, - SmsRequest::ErrorType(aError)); + nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); + requestManager->NotifyGetSmsFailed(aRequestId, aError); return true; } @@ -159,7 +161,8 @@ SmsChild::RecvNotifyRequestSmsDeleted(const bool& aDeleted, return true; } - SmsRequestManager::GetInstance()->NotifySmsDeleted(aRequestId, aDeleted); + nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); + requestManager->NotifySmsDeleted(aRequestId, aDeleted); return true; } @@ -173,8 +176,8 @@ SmsChild::RecvNotifyRequestSmsDeleteFailed(const PRInt32& aError, return true; } - SmsRequestManager::GetInstance()->NotifySmsDeleteFailed(aRequestId, - SmsRequest::ErrorType(aError)); + nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); + requestManager->NotifySmsDeleteFailed(aRequestId, aError); return true; } @@ -187,7 +190,8 @@ SmsChild::RecvNotifyRequestNoMessageInList(const PRInt32& aRequestId, return true; } - SmsRequestManager::GetInstance()->NotifyNoMessageInList(aRequestId); + nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); + requestManager->NotifyNoMessageInList(aRequestId); return true; } @@ -202,7 +206,8 @@ SmsChild::RecvNotifyRequestCreateMessageList(const PRInt32& aListId, } nsCOMPtr message = new SmsMessage(aMessageData); - SmsRequestManager::GetInstance()->NotifyCreateMessageList(aRequestId, aListId, message); + nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); + requestManager->NotifyCreateMessageList(aRequestId, aListId, message); return true; } @@ -216,7 +221,8 @@ SmsChild::RecvNotifyRequestGotNextMessage(const SmsMessageData& aMessageData, } nsCOMPtr message = new SmsMessage(aMessageData); - SmsRequestManager::GetInstance()->NotifyGotNextMessage(aRequestId, message); + nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); + requestManager->NotifyGotNextMessage(aRequestId, message); return true; } @@ -229,8 +235,8 @@ SmsChild::RecvNotifyRequestReadListFailed(const PRInt32& aError, return true; } - SmsRequestManager::GetInstance()->NotifyReadMessageListFailed(aRequestId, - SmsRequest::ErrorType(aError)); + nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); + requestManager->NotifyReadMessageListFailed(aRequestId, aError); return true; } diff --git a/embedding/android/GeckoSmsManager.java b/embedding/android/GeckoSmsManager.java index 51018d4e2bbd..46fe1ee3acd8 100644 --- a/embedding/android/GeckoSmsManager.java +++ b/embedding/android/GeckoSmsManager.java @@ -327,9 +327,9 @@ public class GeckoSmsManager public final static String ACTION_SMS_DELIVERED = "org.mozilla.gecko.SMS_DELIVERED"; /* - * Make sure that the following error codes are in sync with |ErrorType| in: - * dom/sms/src/Types.h - * The error code are owned by the DOM. + * Make sure that the following error codes are in sync with the ones + * defined in dom/sms/interfaces/nsISmsRequestManager.idl. They are owned + * owned by the interface. */ public final static int kNoError = 0; public final static int kNoSignalError = 1; From 38b01f750c6ea088005b45762b50da2615eeab1d Mon Sep 17 00:00:00 2001 From: Philipp von Weitershausen Date: Thu, 16 Feb 2012 14:50:52 -0800 Subject: [PATCH 76/93] Bug 720632 - Part 3: Register SmsRequestManager. r=cjones --- layout/build/nsLayoutModule.cpp | 5 +++++ layout/build/nsLayoutStatics.cpp | 5 ----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp index 735fadd868e7..f0cdad33e6a8 100644 --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -252,6 +252,7 @@ static void Shutdown(); #include "nsCSPService.h" #include "nsISmsService.h" #include "nsISmsDatabaseService.h" +#include "mozilla/dom/sms/SmsRequestManager.h" #include "mozilla/dom/sms/SmsServicesFactory.h" #include "nsIPowerManagerService.h" @@ -309,6 +310,7 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsISmsService, SmsServicesFactory::Crea NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsISmsDatabaseService, SmsServicesFactory::CreateSmsDatabaseService) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIPowerManagerService, PowerManagerService::GetInstance) +NS_GENERIC_FACTORY_CONSTRUCTOR(SmsRequestManager) //----------------------------------------------------------------------------- @@ -800,6 +802,7 @@ NS_DEFINE_NAMED_CID(NS_HAPTICFEEDBACK_CID); #endif NS_DEFINE_NAMED_CID(SMS_SERVICE_CID); NS_DEFINE_NAMED_CID(SMS_DATABASE_SERVICE_CID); +NS_DEFINE_NAMED_CID(SMS_REQUEST_MANAGER_CID); NS_DEFINE_NAMED_CID(NS_POWERMANAGERSERVICE_CID); static nsresult @@ -1071,6 +1074,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = { { &kNS_STRUCTUREDCLONECONTAINER_CID, false, NULL, nsStructuredCloneContainerConstructor }, { &kSMS_SERVICE_CID, false, NULL, nsISmsServiceConstructor }, { &kSMS_DATABASE_SERVICE_CID, false, NULL, nsISmsDatabaseServiceConstructor }, + { &kSMS_REQUEST_MANAGER_CID, false, NULL, SmsRequestManagerConstructor }, { &kNS_POWERMANAGERSERVICE_CID, false, NULL, nsIPowerManagerServiceConstructor }, { NULL } }; @@ -1207,6 +1211,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = { { NS_STRUCTUREDCLONECONTAINER_CONTRACTID, &kNS_STRUCTUREDCLONECONTAINER_CID }, { SMS_SERVICE_CONTRACTID, &kSMS_SERVICE_CID }, { SMS_DATABASE_SERVICE_CONTRACTID, &kSMS_DATABASE_SERVICE_CID }, + { SMS_REQUEST_MANAGER_CONTRACTID, &kSMS_REQUEST_MANAGER_CID }, { POWERMANAGERSERVICE_CONTRACTID, &kNS_POWERMANAGERSERVICE_CID }, { NULL } }; diff --git a/layout/build/nsLayoutStatics.cpp b/layout/build/nsLayoutStatics.cpp index df409480b6af..7910e51600c1 100644 --- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -125,7 +125,6 @@ #include "nsHyphenationManager.h" #include "nsEditorSpellCheck.h" #include "nsDOMMemoryReporter.h" -#include "mozilla/dom/sms/SmsRequestManager.h" extern void NS_ShutdownChainItemPool(); @@ -272,16 +271,12 @@ nsLayoutStatics::Initialize() nsDOMMemoryMultiReporter::Init(); - sms::SmsRequestManager::Init(); - return NS_OK; } void nsLayoutStatics::Shutdown() { - sms::SmsRequestManager::Shutdown(); - // Don't need to shutdown nsDOMMemoryReporter, that will be done by the memory // reporter manager. From f49e15d6aafec12235f354f67fed57b769997c37 Mon Sep 17 00:00:00 2001 From: Philipp von Weitershausen Date: Thu, 16 Feb 2012 14:51:54 -0800 Subject: [PATCH 77/93] Bug 720643 - B2G SMS: Notify SMS send success. r=qDot --- dom/sms/src/ril/SmsService.cpp | 2 +- dom/system/b2g/RadioInterfaceLayer.js | 26 ++++++++- dom/system/b2g/nsIRadioInterfaceLayer.idl | 9 ++- dom/system/b2g/ril_worker.js | 71 +++++++++++++++-------- 4 files changed, 79 insertions(+), 29 deletions(-) diff --git a/dom/sms/src/ril/SmsService.cpp b/dom/sms/src/ril/SmsService.cpp index 7d4032826f35..ee25208c4074 100644 --- a/dom/sms/src/ril/SmsService.cpp +++ b/dom/sms/src/ril/SmsService.cpp @@ -89,7 +89,7 @@ SmsService::Send(const nsAString& aNumber, return NS_OK; } - mRIL->SendSMS(aNumber, aMessage); + mRIL->SendSMS(aNumber, aMessage, aRequestId, aProcessId); return NS_OK; } diff --git a/dom/system/b2g/RadioInterfaceLayer.js b/dom/system/b2g/RadioInterfaceLayer.js index 3ef27de99999..3e8a47f5462f 100644 --- a/dom/system/b2g/RadioInterfaceLayer.js +++ b/dom/system/b2g/RadioInterfaceLayer.js @@ -59,11 +59,16 @@ const nsIRadioInterfaceLayer = Ci.nsIRadioInterfaceLayer; const kSmsReceivedObserverTopic = "sms-received"; const DOM_SMS_DELIVERY_RECEIVED = "received"; +const DOM_SMS_DELIVERY_SENT = "sent"; XPCOMUtils.defineLazyServiceGetter(this, "gSmsService", "@mozilla.org/sms/smsservice;1", "nsISmsService"); +XPCOMUtils.defineLazyServiceGetter(this, "gSmsRequestManager", + "@mozilla.org/sms/smsrequestmanager;1", + "nsISmsRequestManager"); + function convertRILCallState(state) { switch (state) { case RIL.CALL_STATE_ACTIVE: @@ -201,6 +206,9 @@ RadioInterfaceLayer.prototype = { case "sms-received": this.handleSmsReceived(message); return; + case "sms-sent": + this.handleSmsSent(message); + return; case "datacallstatechange": this.handleDataCallState(message.datacall); break; @@ -310,6 +318,18 @@ RadioInterfaceLayer.prototype = { Services.obs.notifyObservers(sms, kSmsReceivedObserverTopic, null); }, + handleSmsSent: function handleSmsSent(message) { + let message = gSmsService.createSmsMessage(-1, + DOM_SMS_DELIVERY_SENT, + message.SMSC, + message.number, + message.body, + Date.now()); + //TODO At this point we should save the sms into the DB (bug 712809) + //TODO handle errors (bug 727319) + gSmsRequestManager.notifySmsSent(message.requestId, message); + }, + /** * Handle data call state changes. */ @@ -402,10 +422,12 @@ RadioInterfaceLayer.prototype = { return Math.ceil(text.length / 160); }, - sendSMS: function sendSMS(number, message) { + sendSMS: function sendSMS(number, message, requestId, processId) { this.worker.postMessage({type: "sendSMS", number: number, - body: message}); + body: message, + requestId: requestId, + processId: processId}); }, _callbacks: null, diff --git a/dom/system/b2g/nsIRadioInterfaceLayer.idl b/dom/system/b2g/nsIRadioInterfaceLayer.idl index 0ef216640b56..33014f22f2fc 100644 --- a/dom/system/b2g/nsIRadioInterfaceLayer.idl +++ b/dom/system/b2g/nsIRadioInterfaceLayer.idl @@ -116,7 +116,7 @@ interface nsIRILDataCallback : nsISupports in unsigned long length); }; -[scriptable, uuid(9b7e3a01-9c45-4af3-81bb-1bf08a842226)] +[scriptable, uuid(aeb7ffe7-7d3a-4b7d-9b59-b6d3ae1c72ed)] interface nsIRadioInterfaceLayer : nsISupports { const unsigned short CALL_STATE_UNKNOWN = 0; @@ -177,7 +177,7 @@ interface nsIRadioInterfaceLayer : nsISupports void deactivateDataCall(in DOMString cid, in DOMString reason); void getDataCallList(); - + void registerDataCallCallback(in nsIRILDataCallback callback); void unregisterDataCallCallback(in nsIRILDataCallback callback); @@ -185,5 +185,8 @@ interface nsIRadioInterfaceLayer : nsISupports * SMS-related functionality. */ unsigned short getNumberOfMessagesForText(in DOMString text); - void sendSMS(in DOMString number, in DOMString message); + void sendSMS(in DOMString number, + in DOMString message, + in long requestId, + in unsigned long long processId); }; diff --git a/dom/system/b2g/ril_worker.js b/dom/system/b2g/ril_worker.js index 6f4c2e83780c..97411efe12ec 100644 --- a/dom/system/b2g/ril_worker.js +++ b/dom/system/b2g/ril_worker.js @@ -438,12 +438,14 @@ let Buf = { let response_type = this.readUint32(); let length = this.readIncoming - UINT32_SIZE; - let request_type; + let request_type, options; if (response_type == RESPONSE_TYPE_SOLICITED) { let token = this.readUint32(); let error = this.readUint32(); length -= 2 * UINT32_SIZE; - request_type = this.tokenRequestMap[token]; + + options = this.tokenRequestMap[token]; + request_type = options.rilRequestType; if (error) { //TODO if (DEBUG) { @@ -467,7 +469,7 @@ let Buf = { return; } - RIL.handleParcel(request_type, length); + RIL.handleParcel(request_type, length, options); }, /** @@ -475,15 +477,23 @@ let Buf = { * * @param type * Integer specifying the request type. + * @param options [optional] + * Object containing information about the request, e.g. the + * original main thread message object that led to the RIL request. */ - newParcel: function newParcel(type) { + newParcel: function newParcel(type, options) { if (DEBUG) debug("New outgoing parcel of type " + type); // We're going to leave room for the parcel size at the beginning. this.outgoingIndex = PARCEL_SIZE_SIZE; this.writeUint32(type); let token = this.token; this.writeUint32(token); - this.tokenRequestMap[token] = type; + + if (!options) { + options = {}; + } + options.rilRequestType = type; + this.tokenRequestMap[token] = options; this.token++; return token; }, @@ -753,9 +763,11 @@ let RIL = { /** * Send an SMS. * - * @param smscPDU + * The `options` parameter object should contain the following attributes: + * + * @param SMSC * String containing the SMSC PDU in hex format. - * @param address + * @param number * String containing the recipients address. * @param body * String containing the message body. @@ -765,15 +777,18 @@ let RIL = { * @param bodyLengthInOctets * Byte length of the message body when encoded with the given DCS. */ - sendSMS: function sendSMS(smscPDU, address, body, dcs, bodyLengthInOctets) { - let token = Buf.newParcel(REQUEST_SEND_SMS); + sendSMS: function sendSMS(options) { + let token = Buf.newParcel(REQUEST_SEND_SMS, options); //TODO we want to map token to the input values so that on the // response from the RIL device we know which SMS request was successful // or not. Maybe we should build that functionality into newParcel() and // handle it within tokenRequestMap[]. Buf.writeUint32(2); - Buf.writeString(smscPDU); - GsmPDUHelper.writeMessage(address, body, dcs, bodyLengthInOctets); + Buf.writeString(options.SMSC); + GsmPDUHelper.writeMessage(options.number, + options.body, + options.dcs, + options.bodyLengthInOctets); Buf.sendParcel(); }, @@ -907,11 +922,11 @@ let RIL = { * _is_ the method name, so that's easy. */ - handleParcel: function handleParcel(request_type, length) { + handleParcel: function handleParcel(request_type, length, options) { let method = this[request_type]; if (typeof method == "function") { if (DEBUG) debug("Handling parcel as " + method.name); - method.call(this, length); + method.call(this, length, options); } } }; @@ -1064,11 +1079,11 @@ RIL[REQUEST_RADIO_POWER] = null; RIL[REQUEST_DTMF] = function REQUEST_DTMF() { Phone.onSendTone(); }; -RIL[REQUEST_SEND_SMS] = function REQUEST_SEND_SMS() { - let messageRef = Buf.readUint32(); - let ackPDU = Buf.readString(); - let errorCode = Buf.readUint32(); - Phone.onSendSMS(messageRef, ackPDU, errorCode); +RIL[REQUEST_SEND_SMS] = function REQUEST_SEND_SMS(length, options) { + options.messageRef = Buf.readUint32(); + options.ackPDU = Buf.readString(); + options.errorCode = Buf.readUint32(); + Phone.onSendSMS(options); }; RIL[REQUEST_SEND_SMS_EXPECT_MORE] = null; RIL[REQUEST_SETUP_DATA_CALL] = function REQUEST_SETUP_DATA_CALL() { @@ -1753,8 +1768,9 @@ let Phone = { onSetSMSCAddress: function onSetSMSCAddress() { }, - onSendSMS: function onSendSMS(messageRef, ackPDU, errorCode) { - //TODO + onSendSMS: function onSendSMS(options) { + options.type = "sms-sent"; + this.sendDOMMessage(options); }, onNewSMS: function onNewSMS(payloadLength) { @@ -2013,6 +2029,10 @@ let Phone = { * String containing the recipient number. * @param body * String containing the message text. + * @param requestId + * String identifying the sms request used by the SmsRequestManager. + * @param processId + * String containing the processId for the SmsRequestManager. */ sendSMS: function sendSMS(options) { // Get the SMS Center address @@ -2025,12 +2045,17 @@ let Phone = { } return; } + // We explicitly save this information on the options object so that we + // can refer to it later, in particular on the main thread (where this + // object may get sent eventually.) + options.SMSC = this.SMSC; + //TODO: verify values on 'options' //TODO: the data encoding and length in octets should eventually be // computed on the mainthread and passed down to us. - RIL.sendSMS(this.SMSC, options.number, options.body, - PDU_DCS_MSG_CODING_7BITS_ALPHABET, //TODO: hard-coded for now, - Math.ceil(options.body.length * 7 / 8)); //TODO: ditto + options.dcs = PDU_DCS_MSG_CODING_7BITS_ALPHABET; + options.bodyLengthInOctets = Math.ceil(options.body.length * 7 / 8); + RIL.sendSMS(options); }, /** From 2f575791aa8ebb28868a53268c700ca2bd5902df Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Thu, 16 Feb 2012 14:58:31 -0800 Subject: [PATCH 78/93] Bug 727725 - Incorrect assertion in GlobalSession. --- mobile/android/base/sync/GlobalSession.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/mobile/android/base/sync/GlobalSession.java b/mobile/android/base/sync/GlobalSession.java index 84b3ba43ebd2..d448ba8fa392 100644 --- a/mobile/android/base/sync/GlobalSession.java +++ b/mobile/android/base/sync/GlobalSession.java @@ -148,7 +148,7 @@ public class GlobalSession implements CredentialsSource, PrefsSource { KeyBundle syncKeyBundle, GlobalSessionCallback callback, Context context, - Bundle persisted) + Bundle extras) throws SyncConfigurationException, IllegalArgumentException, IOException, ParseException, NonObjectJSONException { if (callback == null) { throw new IllegalArgumentException("Must provide a callback to GlobalSession constructor."); @@ -158,7 +158,7 @@ public class GlobalSession implements CredentialsSource, PrefsSource { throw new SyncConfigurationException(); } - Log.i(LOG_TAG, "GlobalSession initialized with bundle " + persisted); + Log.i(LOG_TAG, "GlobalSession initialized with bundle " + extras); URI serverURI; try { serverURI = (serverURL == null) ? null : new URI(serverURL); @@ -181,9 +181,7 @@ public class GlobalSession implements CredentialsSource, PrefsSource { config.username = username; config.password = password; config.syncKeyBundle = syncKeyBundle; - // clusterURL and syncID are set through `persisted`, or fetched from the server. - assert(null == persisted); prepareStages(); } From d3d51ae7b005b79c3f38f49665466acb0a810529 Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Thu, 16 Feb 2012 15:15:16 -0800 Subject: [PATCH 79/93] Fix dictionary state when swapping objects, bug 727330. r=luke --- js/src/jsobj.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index b29d88059232..c9f19d20985a 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -3495,6 +3495,11 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved & types::TypeObject::writeBarrierPost(a->type_, &a->type_); types::TypeObject::writeBarrierPost(b->type_, &b->type_); #endif + + if (a->inDictionaryMode()) + a->lastProperty()->listp = &a->shape_; + if (b->inDictionaryMode()) + b->lastProperty()->listp = &b->shape_; } /* From 13ccc35216a7d2138c751b3c17f58395adc7263a Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 16 Feb 2012 15:16:14 -0800 Subject: [PATCH 80/93] Bug 727970: Check formerly-unused rv in TestProtocols.cpp, to fix build warning. r=jduell --- netwerk/test/TestProtocols.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/netwerk/test/TestProtocols.cpp b/netwerk/test/TestProtocols.cpp index f602ec04e927..6dd817101036 100644 --- a/netwerk/test/TestProtocols.cpp +++ b/netwerk/test/TestProtocols.cpp @@ -797,6 +797,12 @@ nsresult LoadURLsFromFile(char *aFileName) if (urlString.Length()) { LOG(("\t%s\n", urlString.get())); rv = StartLoadingURL(urlString.get()); + if (NS_FAILED(rv)) { + // No need to log an error -- StartLoadingURL already + // did that for us, probably. + PR_Close(fd); + return rv; + } } } } From 414e283e4c477b4ee55fed6ec1a15908aa0a1194 Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Thu, 16 Feb 2012 23:18:45 +0000 Subject: [PATCH 81/93] Backout 6c1ded13556d (bug 720643), 5cf0a12c1cf0, ac771e54d7ca & 3bb24b12b0d6 (bug 720632) for Android build failures --- dom/sms/interfaces/Makefile.in | 5 +- dom/sms/interfaces/nsISmsRequestManager.idl | 80 -------------- dom/sms/src/SmsCursor.cpp | 6 +- dom/sms/src/SmsManager.cpp | 52 +++------ dom/sms/src/SmsRequest.cpp | 38 +++---- dom/sms/src/SmsRequest.h | 17 ++- dom/sms/src/SmsRequestManager.cpp | 110 +++++++++++--------- dom/sms/src/SmsRequestManager.h | 36 +++++-- dom/sms/src/ipc/SmsChild.cpp | 34 +++--- dom/sms/src/ril/SmsService.cpp | 2 +- dom/system/b2g/RadioInterfaceLayer.js | 26 +---- dom/system/b2g/nsIRadioInterfaceLayer.idl | 9 +- dom/system/b2g/ril_worker.js | 71 ++++--------- embedding/android/GeckoSmsManager.java | 6 +- layout/build/nsLayoutModule.cpp | 5 - layout/build/nsLayoutStatics.cpp | 5 + 16 files changed, 191 insertions(+), 311 deletions(-) delete mode 100644 dom/sms/interfaces/nsISmsRequestManager.idl diff --git a/dom/sms/interfaces/Makefile.in b/dom/sms/interfaces/Makefile.in index c7bbeb0a86e4..af249a14d8cc 100644 --- a/dom/sms/interfaces/Makefile.in +++ b/dom/sms/interfaces/Makefile.in @@ -48,14 +48,13 @@ include $(topsrcdir)/dom/dom-config.mk XPIDLSRCS = \ nsIDOMNavigatorSms.idl \ nsIDOMSmsManager.idl \ + nsISmsService.idl \ nsIDOMSmsMessage.idl \ nsIDOMSmsEvent.idl \ + nsISmsDatabaseService.idl \ nsIDOMSmsRequest.idl \ nsIDOMSmsFilter.idl \ nsIDOMSmsCursor.idl \ - nsISmsDatabaseService.idl \ - nsISmsRequestManager.idl \ - nsISmsService.idl \ $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/dom/sms/interfaces/nsISmsRequestManager.idl b/dom/sms/interfaces/nsISmsRequestManager.idl deleted file mode 100644 index 7da44f336995..000000000000 --- a/dom/sms/interfaces/nsISmsRequestManager.idl +++ /dev/null @@ -1,80 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsISupports.idl" - -interface nsIDOMMozSmsMessage; -interface nsIDOMMozSmsRequest; -interface nsPIDOMWindow; -interface nsIScriptContext; - -%{C++ -#define SMS_REQUEST_MANAGER_CID \ -{ 0xa97a3129, 0x1e0b, 0x45da, \ -{ 0xa3, 0x85, 0xcf, 0xe5, 0xb0, 0xb1, 0xc4, 0x8f } } -#define SMS_REQUEST_MANAGER_CONTRACTID "@mozilla.org/sms/smsrequestmanager;1" -%} - -[scriptable, uuid(1638b963-3a45-4937-b6a9-280c1bfb166c)] -interface nsISmsRequestManager : nsISupports -{ - - /** - * All SMS related errors that could apply to SmsRequest objects. - * Make sure to keep this list in sync with the list in: - * embedding/android/GeckoSmsManager.java - */ - const unsigned short NO_ERROR = 0; - const unsigned short NO_SIGNAL_ERROR = 1; - const unsigned short NOT_FOUND_ERROR = 2; - const unsigned short UNKNOWN_ERROR = 3; - const unsigned short INTERNAL_ERROR = 4; - - /** - * Create a new request object. - * - * @return the request ID. - */ - long createRequest(in nsPIDOMWindow aWindow, - in nsIScriptContext aScriptContext, - out nsIDOMMozSmsRequest aRequest); - - /** - * Track an already existing request object. - * - * @return the request ID. - */ - long addRequest(in nsIDOMMozSmsRequest aRequest); - - void notifySmsSent(in long aRequestId, - in nsIDOMMozSmsMessage aMessage); - - void notifySmsSendFailed(in long aRequestId, - in long aError); - - void notifyGotSms(in long aRequestId, - in nsIDOMMozSmsMessage aMessage); - - void notifyGetSmsFailed(in long aRequestId, - in long aError); - - void notifySmsDeleted(in long aRequestId, - in bool aDeleted); - - void notifySmsDeleteFailed(in long aRequestId, - in long aError); - - void notifyNoMessageInList(in long aRequestId); - - void notifyCreateMessageList(in long aRequestId, - in long aListId, - in nsIDOMMozSmsMessage aMessage); - - void notifyGotNextMessage(in long aRequestId, - in nsIDOMMozSmsMessage aMessage); - - void notifyReadMessageListFailed(in long aRequestId, - in long aError); - -}; diff --git a/dom/sms/src/SmsCursor.cpp b/dom/sms/src/SmsCursor.cpp index 4da2c16c8026..b038d003f3f1 100644 --- a/dom/sms/src/SmsCursor.cpp +++ b/dom/sms/src/SmsCursor.cpp @@ -115,11 +115,7 @@ SmsCursor::Continue() mMessage = nsnull; static_cast(mRequest.get())->Reset(); - nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); - - PRInt32 requestId; - nsresult rv = requestManager->AddRequest(mRequest, &requestId); - NS_ENSURE_SUCCESS(rv, rv); + PRInt32 requestId = SmsRequestManager::GetInstance()->AddRequest(mRequest); nsCOMPtr smsDBService = do_GetService(SMS_DATABASE_SERVICE_CONTRACTID); diff --git a/dom/sms/src/SmsManager.cpp b/dom/sms/src/SmsManager.cpp index eee5d9adcc5f..6aab2e1bd91f 100644 --- a/dom/sms/src/SmsManager.cpp +++ b/dom/sms/src/SmsManager.cpp @@ -146,23 +146,17 @@ SmsManager::Send(JSContext* aCx, JSObject* aGlobal, JSString* aNumber, nsCOMPtr request; - nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); - - PRInt32 requestId; - nsresult rv = requestManager->CreateRequest(mOwner, mScriptContext, - getter_AddRefs(request), - &requestId); - if (NS_FAILED(rv)) { - NS_ERROR("Failed to create the request!"); - return rv; - } + int requestId = + SmsRequestManager::GetInstance()->CreateRequest(mOwner, mScriptContext, + getter_AddRefs(request)); + NS_ASSERTION(request, "The request object must have been created!"); nsDependentJSString number; number.init(aCx, aNumber); smsService->Send(number, aMessage, requestId, 0); - rv = nsContentUtils::WrapNative(aCx, aGlobal, request, aRequest); + nsresult rv = nsContentUtils::WrapNative(aCx, aGlobal, request, aRequest); if (NS_FAILED(rv)) { NS_ERROR("Failed to create the js value!"); return rv; @@ -223,15 +217,9 @@ SmsManager::Send(const jsval& aNumber, const nsAString& aMessage, jsval* aReturn NS_IMETHODIMP SmsManager::GetMessageMoz(PRInt32 aId, nsIDOMMozSmsRequest** aRequest) { - nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); - - PRInt32 requestId; - nsresult rv = requestManager->CreateRequest(mOwner, mScriptContext, aRequest, - &requestId); - if (NS_FAILED(rv)) { - NS_ERROR("Failed to create the request!"); - return rv; - } + int requestId = + SmsRequestManager::GetInstance()->CreateRequest(mOwner, mScriptContext, aRequest); + NS_ASSERTION(*aRequest, "The request object must have been created!"); nsCOMPtr smsDBService = do_GetService(SMS_DATABASE_SERVICE_CONTRACTID); @@ -245,15 +233,9 @@ SmsManager::GetMessageMoz(PRInt32 aId, nsIDOMMozSmsRequest** aRequest) nsresult SmsManager::Delete(PRInt32 aId, nsIDOMMozSmsRequest** aRequest) { - nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); - - PRInt32 requestId; - nsresult rv = requestManager->CreateRequest(mOwner, mScriptContext, aRequest, - &requestId); - if (NS_FAILED(rv)) { - NS_ERROR("Failed to create the request!"); - return rv; - } + int requestId = + SmsRequestManager::GetInstance()->CreateRequest(mOwner, mScriptContext, aRequest); + NS_ASSERTION(*aRequest, "The request object must have been created!"); nsCOMPtr smsDBService = do_GetService(SMS_DATABASE_SERVICE_CONTRACTID); @@ -296,15 +278,9 @@ SmsManager::GetMessages(nsIDOMMozSmsFilter* aFilter, bool aReverse, filter = new SmsFilter(); } - nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); - - PRInt32 requestId; - nsresult rv = requestManager->CreateRequest(mOwner, mScriptContext, aRequest, - &requestId); - if (NS_FAILED(rv)) { - NS_ERROR("Failed to create the request!"); - return rv; - } + int requestId = + SmsRequestManager::GetInstance()->CreateRequest(mOwner, mScriptContext, aRequest); + NS_ASSERTION(*aRequest, "The request object must have been created!"); nsCOMPtr smsDBService = do_GetService(SMS_DATABASE_SERVICE_CONTRACTID); diff --git a/dom/sms/src/SmsRequest.cpp b/dom/sms/src/SmsRequest.cpp index 4e2387d9b542..7dbcba0c22d5 100644 --- a/dom/sms/src/SmsRequest.cpp +++ b/dom/sms/src/SmsRequest.cpp @@ -41,7 +41,6 @@ #include "nsContentUtils.h" #include "nsIDOMSmsMessage.h" #include "nsIDOMSmsCursor.h" -#include "nsISmsRequestManager.h" DOMCI_DATA(MozSmsRequest, mozilla::dom::sms::SmsRequest) @@ -93,7 +92,7 @@ NS_IMPL_EVENT_HANDLER(SmsRequest, error) SmsRequest::SmsRequest(nsPIDOMWindow* aWindow, nsIScriptContext* aScriptContext) : mResult(JSVAL_VOID) , mResultRooted(false) - , mError(nsISmsRequestManager::NO_ERROR) + , mError(eNoError) , mDone(false) { // Those vars come from nsDOMEventTargetHelper. @@ -113,8 +112,7 @@ SmsRequest::Reset() { NS_ASSERTION(mDone, "mDone should be true if we try to reset!"); NS_ASSERTION(mResult != JSVAL_VOID, "mResult should be set if we try to reset!"); - NS_ASSERTION(mError == nsISmsRequestManager::NO_ERROR, - "There should be no error if we try to reset!"); + NS_ASSERTION(mError == eNoError, "There should be no error if we try to reset!"); if (mResultRooted) { UnrootResult(); @@ -150,8 +148,7 @@ void SmsRequest::SetSuccess(bool aResult) { NS_PRECONDITION(!mDone, "mDone shouldn't have been set to true already!"); - NS_PRECONDITION(mError == nsISmsRequestManager::NO_ERROR, - "mError shouldn't have been set!"); + NS_PRECONDITION(mError == eNoError, "mError shouldn't have been set!"); NS_PRECONDITION(mResult == JSVAL_NULL, "mResult shouldn't have been set!"); mResult.setBoolean(aResult); @@ -177,8 +174,7 @@ bool SmsRequest::SetSuccessInternal(nsISupports* aObject) { NS_PRECONDITION(!mDone, "mDone shouldn't have been set to true already!"); - NS_PRECONDITION(mError == nsISmsRequestManager::NO_ERROR, - "mError shouldn't have been set!"); + NS_PRECONDITION(mError == eNoError, "mError shouldn't have been set!"); NS_PRECONDITION(mResult == JSVAL_VOID, "mResult shouldn't have been set!"); JSContext* cx = mScriptContext->GetNativeContext(); @@ -190,7 +186,7 @@ SmsRequest::SetSuccessInternal(nsISupports* aObject) JSAutoRequest ar(cx); JSAutoEnterCompartment ac; if (!ac.enter(cx, global)) { - SetError(nsISmsRequestManager::INTERNAL_ERROR); + SetError(eInternalError); return false; } @@ -199,7 +195,7 @@ SmsRequest::SetSuccessInternal(nsISupports* aObject) if (NS_FAILED(nsContentUtils::WrapNative(cx, global, aObject, &mResult))) { UnrootResult(); mResult = JSVAL_VOID; - SetError(nsISmsRequestManager::INTERNAL_ERROR); + SetError(eInternalError); return false; } @@ -208,11 +204,10 @@ SmsRequest::SetSuccessInternal(nsISupports* aObject) } void -SmsRequest::SetError(PRInt32 aError) +SmsRequest::SetError(ErrorType aError) { NS_PRECONDITION(!mDone, "mDone shouldn't have been set to true already!"); - NS_PRECONDITION(mError == nsISmsRequestManager::NO_ERROR, - "mError shouldn't have been set!"); + NS_PRECONDITION(mError == eNoError, "mError shouldn't have been set!"); NS_PRECONDITION(mResult == JSVAL_VOID, "mResult shouldn't have been set!"); mDone = true; @@ -236,35 +231,32 @@ NS_IMETHODIMP SmsRequest::GetError(nsAString& aError) { if (!mDone) { - NS_ASSERTION(mError == nsISmsRequestManager::NO_ERROR, + NS_ASSERTION(mError == eNoError, "There should be no error if the request is still processing!"); SetDOMStringToNull(aError); return NS_OK; } - NS_ASSERTION(mError == nsISmsRequestManager::NO_ERROR || - mResult == JSVAL_VOID, + NS_ASSERTION(mError == eNoError || mResult == JSVAL_VOID, "mResult should be void when there is an error!"); switch (mError) { - case nsISmsRequestManager::NO_ERROR: + case eNoError: SetDOMStringToNull(aError); break; - case nsISmsRequestManager::NO_SIGNAL_ERROR: + case eNoSignalError: aError.AssignLiteral("NoSignalError"); break; - case nsISmsRequestManager::NOT_FOUND_ERROR: + case eNotFoundError: aError.AssignLiteral("NotFoundError"); break; - case nsISmsRequestManager::UNKNOWN_ERROR: + case eUnknownError: aError.AssignLiteral("UnknownError"); break; - case nsISmsRequestManager::INTERNAL_ERROR: + case eInternalError: aError.AssignLiteral("InternalError"); break; - default: - MOZ_ASSERT(false, "Unknown error value."); } return NS_OK; diff --git a/dom/sms/src/SmsRequest.h b/dom/sms/src/SmsRequest.h index d034ca569ff0..973a2000bc12 100644 --- a/dom/sms/src/SmsRequest.h +++ b/dom/sms/src/SmsRequest.h @@ -54,6 +54,19 @@ class SmsRequest : public nsIDOMMozSmsRequest public: friend class SmsRequestManager; + /** + * All SMS related errors that could apply to SmsRequest objects. + * Make sure to keep this list in sync with the list in: + * embedding/android/GeckoSmsManager.java + */ + enum ErrorType { + eNoError = 0, + eNoSignalError, + eNotFoundError, + eUnknownError, + eInternalError, + }; + NS_DECL_ISUPPORTS NS_DECL_NSIDOMMOZSMSREQUEST @@ -98,7 +111,7 @@ private: /** * Set the object in an error state with the error type being aError. */ - void SetError(PRInt32 aError); + void SetError(ErrorType aError); /** * Set the object in a success state with the result being the nsISupports @@ -116,7 +129,7 @@ private: jsval mResult; bool mResultRooted; - PRInt32 mError; + ErrorType mError; bool mDone; nsCOMPtr mCursor; diff --git a/dom/sms/src/SmsRequestManager.cpp b/dom/sms/src/SmsRequestManager.cpp index 45f55a3cee4c..28bd9229486a 100644 --- a/dom/sms/src/SmsRequestManager.cpp +++ b/dom/sms/src/SmsRequestManager.cpp @@ -51,11 +51,33 @@ namespace mozilla { namespace dom { namespace sms { -NS_IMPL_ISUPPORTS1(SmsRequestManager, nsISmsRequestManager) +SmsRequestManager* SmsRequestManager::sInstance = nsnull; -NS_IMETHODIMP -SmsRequestManager::AddRequest(nsIDOMMozSmsRequest* aRequest, - PRInt32* aRequestId) +void +SmsRequestManager::Init() +{ + NS_PRECONDITION(!sInstance, + "sInstance shouldn't be set. Did you call Init() twice?"); + sInstance = new SmsRequestManager(); +} + +void +SmsRequestManager::Shutdown() +{ + NS_PRECONDITION(sInstance, "sInstance should be set. Did you call Init()?"); + + delete sInstance; + sInstance = nsnull; +} + +/* static */ SmsRequestManager* +SmsRequestManager::GetInstance() +{ + return sInstance; +} + +PRInt32 +SmsRequestManager::AddRequest(nsIDOMMozSmsRequest* aRequest) { // TODO: merge with CreateRequest PRInt32 size = mRequests.Count(); @@ -67,21 +89,17 @@ SmsRequestManager::AddRequest(nsIDOMMozSmsRequest* aRequest, } mRequests.ReplaceObjectAt(aRequest, i); - *aRequestId = i; - return NS_OK; + return i; } mRequests.AppendObject(aRequest); - *aRequestId = size; - return NS_OK; + return size; } - -NS_IMETHODIMP +PRInt32 SmsRequestManager::CreateRequest(nsPIDOMWindow* aWindow, nsIScriptContext* aScriptContext, - nsIDOMMozSmsRequest** aRequest, - PRInt32* aRequestId) + nsIDOMMozSmsRequest** aRequest) { nsCOMPtr request = new SmsRequest(aWindow, aScriptContext); @@ -96,14 +114,12 @@ SmsRequestManager::CreateRequest(nsPIDOMWindow* aWindow, mRequests.ReplaceObjectAt(request, i); NS_ADDREF(*aRequest = request); - *aRequestId = i; - return NS_OK; + return i; } mRequests.AppendObject(request); NS_ADDREF(*aRequest = request); - *aRequestId = size; - return NS_OK; + return size; } nsresult @@ -133,67 +149,66 @@ SmsRequestManager::GetRequest(PRInt32 aRequestId) } template -nsresult +void SmsRequestManager::NotifySuccess(PRInt32 aRequestId, T aParam) { SmsRequest* request = GetRequest(aRequestId); request->SetSuccess(aParam); - nsresult rv = DispatchTrustedEventToRequest(SUCCESS_EVENT_NAME, request); + DispatchTrustedEventToRequest(SUCCESS_EVENT_NAME, request); mRequests.ReplaceObjectAt(nsnull, aRequestId); - return rv; } -nsresult -SmsRequestManager::NotifyError(PRInt32 aRequestId, PRInt32 aError) +void +SmsRequestManager::NotifyError(PRInt32 aRequestId, SmsRequest::ErrorType aError) { SmsRequest* request = GetRequest(aRequestId); request->SetError(aError); - nsresult rv = DispatchTrustedEventToRequest(ERROR_EVENT_NAME, request); + DispatchTrustedEventToRequest(ERROR_EVENT_NAME, request); mRequests.ReplaceObjectAt(nsnull, aRequestId); - return rv; } -NS_IMETHODIMP +void SmsRequestManager::NotifySmsSent(PRInt32 aRequestId, nsIDOMMozSmsMessage* aMessage) { - return NotifySuccess(aRequestId, aMessage); + NotifySuccess(aRequestId, aMessage); } -NS_IMETHODIMP -SmsRequestManager::NotifySmsSendFailed(PRInt32 aRequestId, PRInt32 aError) +void +SmsRequestManager::NotifySmsSendFailed(PRInt32 aRequestId, SmsRequest::ErrorType aError) { - return NotifyError(aRequestId, aError); + NotifyError(aRequestId, aError); } -NS_IMETHODIMP +void SmsRequestManager::NotifyGotSms(PRInt32 aRequestId, nsIDOMMozSmsMessage* aMessage) { - return NotifySuccess(aRequestId, aMessage); + NotifySuccess(aRequestId, aMessage); } -NS_IMETHODIMP -SmsRequestManager::NotifyGetSmsFailed(PRInt32 aRequestId, PRInt32 aError) +void +SmsRequestManager::NotifyGetSmsFailed(PRInt32 aRequestId, + SmsRequest::ErrorType aError) { - return NotifyError(aRequestId, aError); + NotifyError(aRequestId, aError); } -NS_IMETHODIMP +void SmsRequestManager::NotifySmsDeleted(PRInt32 aRequestId, bool aDeleted) { - return NotifySuccess(aRequestId, aDeleted); + NotifySuccess(aRequestId, aDeleted); } -NS_IMETHODIMP -SmsRequestManager::NotifySmsDeleteFailed(PRInt32 aRequestId, PRInt32 aError) +void +SmsRequestManager::NotifySmsDeleteFailed(PRInt32 aRequestId, SmsRequest::ErrorType aError) { - return NotifyError(aRequestId, aError); + NotifyError(aRequestId, aError); } -NS_IMETHODIMP +void SmsRequestManager::NotifyNoMessageInList(PRInt32 aRequestId) { SmsRequest* request = GetRequest(aRequestId); @@ -205,10 +220,10 @@ SmsRequestManager::NotifyNoMessageInList(PRInt32 aRequestId) static_cast(cursor.get())->Disconnect(); } - return NotifySuccess(aRequestId, cursor); + NotifySuccess(aRequestId, cursor); } -NS_IMETHODIMP +void SmsRequestManager::NotifyCreateMessageList(PRInt32 aRequestId, PRInt32 aListId, nsIDOMMozSmsMessage* aMessage) { @@ -217,10 +232,10 @@ SmsRequestManager::NotifyCreateMessageList(PRInt32 aRequestId, PRInt32 aListId, nsCOMPtr cursor = new SmsCursor(aListId, request); cursor->SetMessage(aMessage); - return NotifySuccess(aRequestId, cursor); + NotifySuccess(aRequestId, cursor); } -NS_IMETHODIMP +void SmsRequestManager::NotifyGotNextMessage(PRInt32 aRequestId, nsIDOMMozSmsMessage* aMessage) { SmsRequest* request = GetRequest(aRequestId); @@ -229,11 +244,12 @@ SmsRequestManager::NotifyGotNextMessage(PRInt32 aRequestId, nsIDOMMozSmsMessage* NS_ASSERTION(cursor, "Request should have an cursor in that case!"); cursor->SetMessage(aMessage); - return NotifySuccess(aRequestId, cursor); + NotifySuccess(aRequestId, cursor); } -NS_IMETHODIMP -SmsRequestManager::NotifyReadMessageListFailed(PRInt32 aRequestId, PRInt32 aError) +void +SmsRequestManager::NotifyReadMessageListFailed(PRInt32 aRequestId, + SmsRequest::ErrorType aError) { SmsRequest* request = GetRequest(aRequestId); @@ -242,7 +258,7 @@ SmsRequestManager::NotifyReadMessageListFailed(PRInt32 aRequestId, PRInt32 aErro static_cast(cursor.get())->Disconnect(); } - return NotifyError(aRequestId, aError); + NotifyError(aRequestId, aError); } } // namespace sms diff --git a/dom/sms/src/SmsRequestManager.h b/dom/sms/src/SmsRequestManager.h index f9464ff3a80a..3b4cd069b1d1 100644 --- a/dom/sms/src/SmsRequestManager.h +++ b/dom/sms/src/SmsRequestManager.h @@ -41,26 +41,50 @@ #include "nsCOMArray.h" #include "SmsRequest.h" -#include "nsISmsRequestManager.h" + +class nsIDOMMozSmsRequest; +class nsPIDOMWindow; +class nsIScriptContext; +class nsIDOMMozSmsMessage; namespace mozilla { namespace dom { namespace sms { -class SmsRequestManager : nsISmsRequestManager +class SmsRequestManager { public: - NS_DECL_ISUPPORTS - NS_DECL_NSISMSREQUESTMANAGER + static void Init(); + static void Shutdown(); + static SmsRequestManager* GetInstance(); + + PRInt32 CreateRequest(nsPIDOMWindow* aWindow, + nsIScriptContext* aScriptContext, + nsIDOMMozSmsRequest** aRequest); + + PRInt32 AddRequest(nsIDOMMozSmsRequest* aRequest); + + void NotifySmsSent(PRInt32 aRequestId, nsIDOMMozSmsMessage* aMessage); + void NotifySmsSendFailed(PRInt32 aRequestId, SmsRequest::ErrorType aError); + void NotifyGotSms(PRInt32 aRequestId, nsIDOMMozSmsMessage* aMessage); + void NotifyGetSmsFailed(PRInt32 aRequestId, SmsRequest::ErrorType aError); + void NotifySmsDeleted(PRInt32 aRequestId, bool aDeleted); + void NotifySmsDeleteFailed(PRInt32 aRequestId, SmsRequest::ErrorType aError); + void NotifyNoMessageInList(PRInt32 aRequestId); + void NotifyCreateMessageList(PRInt32 aRequestId, PRInt32 aListId, nsIDOMMozSmsMessage* aMessage); + void NotifyGotNextMessage(PRInt32 aRequestId, nsIDOMMozSmsMessage* aMessage); + void NotifyReadMessageListFailed(PRInt32 aRequestId, SmsRequest::ErrorType aError); private: + static SmsRequestManager* sInstance; + nsresult DispatchTrustedEventToRequest(const nsAString& aEventName, nsIDOMMozSmsRequest* aRequest); SmsRequest* GetRequest(PRInt32 aRequestId); template - nsresult NotifySuccess(PRInt32 aRequestId, T aParam); - nsresult NotifyError(PRInt32 aRequestId, PRInt32 aError); + void NotifySuccess(PRInt32 aRequestId, T aParam); + void NotifyError(PRInt32 aRequestId, SmsRequest::ErrorType aError); nsCOMArray mRequests; }; diff --git a/dom/sms/src/ipc/SmsChild.cpp b/dom/sms/src/ipc/SmsChild.cpp index 953fa0a18cac..3b59d532b327 100644 --- a/dom/sms/src/ipc/SmsChild.cpp +++ b/dom/sms/src/ipc/SmsChild.cpp @@ -100,8 +100,7 @@ SmsChild::RecvNotifyRequestSmsSent(const SmsMessageData& aMessage, } nsCOMPtr message = new SmsMessage(aMessage); - nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); - requestManager->NotifySmsSent(aRequestId, message); + SmsRequestManager::GetInstance()->NotifySmsSent(aRequestId, message); return true; } @@ -115,8 +114,8 @@ SmsChild::RecvNotifyRequestSmsSendFailed(const PRInt32& aError, return true; } - nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); - requestManager->NotifySmsSendFailed(aRequestId, aError); + SmsRequestManager::GetInstance()->NotifySmsSendFailed(aRequestId, + SmsRequest::ErrorType(aError)); return true; } @@ -131,8 +130,7 @@ SmsChild::RecvNotifyRequestGotSms(const SmsMessageData& aMessage, } nsCOMPtr message = new SmsMessage(aMessage); - nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); - requestManager->NotifyGotSms(aRequestId, message); + SmsRequestManager::GetInstance()->NotifyGotSms(aRequestId, message); return true; } @@ -146,8 +144,8 @@ SmsChild::RecvNotifyRequestGetSmsFailed(const PRInt32& aError, return true; } - nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); - requestManager->NotifyGetSmsFailed(aRequestId, aError); + SmsRequestManager::GetInstance()->NotifyGetSmsFailed(aRequestId, + SmsRequest::ErrorType(aError)); return true; } @@ -161,8 +159,7 @@ SmsChild::RecvNotifyRequestSmsDeleted(const bool& aDeleted, return true; } - nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); - requestManager->NotifySmsDeleted(aRequestId, aDeleted); + SmsRequestManager::GetInstance()->NotifySmsDeleted(aRequestId, aDeleted); return true; } @@ -176,8 +173,8 @@ SmsChild::RecvNotifyRequestSmsDeleteFailed(const PRInt32& aError, return true; } - nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); - requestManager->NotifySmsDeleteFailed(aRequestId, aError); + SmsRequestManager::GetInstance()->NotifySmsDeleteFailed(aRequestId, + SmsRequest::ErrorType(aError)); return true; } @@ -190,8 +187,7 @@ SmsChild::RecvNotifyRequestNoMessageInList(const PRInt32& aRequestId, return true; } - nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); - requestManager->NotifyNoMessageInList(aRequestId); + SmsRequestManager::GetInstance()->NotifyNoMessageInList(aRequestId); return true; } @@ -206,8 +202,7 @@ SmsChild::RecvNotifyRequestCreateMessageList(const PRInt32& aListId, } nsCOMPtr message = new SmsMessage(aMessageData); - nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); - requestManager->NotifyCreateMessageList(aRequestId, aListId, message); + SmsRequestManager::GetInstance()->NotifyCreateMessageList(aRequestId, aListId, message); return true; } @@ -221,8 +216,7 @@ SmsChild::RecvNotifyRequestGotNextMessage(const SmsMessageData& aMessageData, } nsCOMPtr message = new SmsMessage(aMessageData); - nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); - requestManager->NotifyGotNextMessage(aRequestId, message); + SmsRequestManager::GetInstance()->NotifyGotNextMessage(aRequestId, message); return true; } @@ -235,8 +229,8 @@ SmsChild::RecvNotifyRequestReadListFailed(const PRInt32& aError, return true; } - nsCOMPtr requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID); - requestManager->NotifyReadMessageListFailed(aRequestId, aError); + SmsRequestManager::GetInstance()->NotifyReadMessageListFailed(aRequestId, + SmsRequest::ErrorType(aError)); return true; } diff --git a/dom/sms/src/ril/SmsService.cpp b/dom/sms/src/ril/SmsService.cpp index ee25208c4074..7d4032826f35 100644 --- a/dom/sms/src/ril/SmsService.cpp +++ b/dom/sms/src/ril/SmsService.cpp @@ -89,7 +89,7 @@ SmsService::Send(const nsAString& aNumber, return NS_OK; } - mRIL->SendSMS(aNumber, aMessage, aRequestId, aProcessId); + mRIL->SendSMS(aNumber, aMessage); return NS_OK; } diff --git a/dom/system/b2g/RadioInterfaceLayer.js b/dom/system/b2g/RadioInterfaceLayer.js index 3e8a47f5462f..3ef27de99999 100644 --- a/dom/system/b2g/RadioInterfaceLayer.js +++ b/dom/system/b2g/RadioInterfaceLayer.js @@ -59,16 +59,11 @@ const nsIRadioInterfaceLayer = Ci.nsIRadioInterfaceLayer; const kSmsReceivedObserverTopic = "sms-received"; const DOM_SMS_DELIVERY_RECEIVED = "received"; -const DOM_SMS_DELIVERY_SENT = "sent"; XPCOMUtils.defineLazyServiceGetter(this, "gSmsService", "@mozilla.org/sms/smsservice;1", "nsISmsService"); -XPCOMUtils.defineLazyServiceGetter(this, "gSmsRequestManager", - "@mozilla.org/sms/smsrequestmanager;1", - "nsISmsRequestManager"); - function convertRILCallState(state) { switch (state) { case RIL.CALL_STATE_ACTIVE: @@ -206,9 +201,6 @@ RadioInterfaceLayer.prototype = { case "sms-received": this.handleSmsReceived(message); return; - case "sms-sent": - this.handleSmsSent(message); - return; case "datacallstatechange": this.handleDataCallState(message.datacall); break; @@ -318,18 +310,6 @@ RadioInterfaceLayer.prototype = { Services.obs.notifyObservers(sms, kSmsReceivedObserverTopic, null); }, - handleSmsSent: function handleSmsSent(message) { - let message = gSmsService.createSmsMessage(-1, - DOM_SMS_DELIVERY_SENT, - message.SMSC, - message.number, - message.body, - Date.now()); - //TODO At this point we should save the sms into the DB (bug 712809) - //TODO handle errors (bug 727319) - gSmsRequestManager.notifySmsSent(message.requestId, message); - }, - /** * Handle data call state changes. */ @@ -422,12 +402,10 @@ RadioInterfaceLayer.prototype = { return Math.ceil(text.length / 160); }, - sendSMS: function sendSMS(number, message, requestId, processId) { + sendSMS: function sendSMS(number, message) { this.worker.postMessage({type: "sendSMS", number: number, - body: message, - requestId: requestId, - processId: processId}); + body: message}); }, _callbacks: null, diff --git a/dom/system/b2g/nsIRadioInterfaceLayer.idl b/dom/system/b2g/nsIRadioInterfaceLayer.idl index 33014f22f2fc..0ef216640b56 100644 --- a/dom/system/b2g/nsIRadioInterfaceLayer.idl +++ b/dom/system/b2g/nsIRadioInterfaceLayer.idl @@ -116,7 +116,7 @@ interface nsIRILDataCallback : nsISupports in unsigned long length); }; -[scriptable, uuid(aeb7ffe7-7d3a-4b7d-9b59-b6d3ae1c72ed)] +[scriptable, uuid(9b7e3a01-9c45-4af3-81bb-1bf08a842226)] interface nsIRadioInterfaceLayer : nsISupports { const unsigned short CALL_STATE_UNKNOWN = 0; @@ -177,7 +177,7 @@ interface nsIRadioInterfaceLayer : nsISupports void deactivateDataCall(in DOMString cid, in DOMString reason); void getDataCallList(); - + void registerDataCallCallback(in nsIRILDataCallback callback); void unregisterDataCallCallback(in nsIRILDataCallback callback); @@ -185,8 +185,5 @@ interface nsIRadioInterfaceLayer : nsISupports * SMS-related functionality. */ unsigned short getNumberOfMessagesForText(in DOMString text); - void sendSMS(in DOMString number, - in DOMString message, - in long requestId, - in unsigned long long processId); + void sendSMS(in DOMString number, in DOMString message); }; diff --git a/dom/system/b2g/ril_worker.js b/dom/system/b2g/ril_worker.js index 97411efe12ec..6f4c2e83780c 100644 --- a/dom/system/b2g/ril_worker.js +++ b/dom/system/b2g/ril_worker.js @@ -438,14 +438,12 @@ let Buf = { let response_type = this.readUint32(); let length = this.readIncoming - UINT32_SIZE; - let request_type, options; + let request_type; if (response_type == RESPONSE_TYPE_SOLICITED) { let token = this.readUint32(); let error = this.readUint32(); length -= 2 * UINT32_SIZE; - - options = this.tokenRequestMap[token]; - request_type = options.rilRequestType; + request_type = this.tokenRequestMap[token]; if (error) { //TODO if (DEBUG) { @@ -469,7 +467,7 @@ let Buf = { return; } - RIL.handleParcel(request_type, length, options); + RIL.handleParcel(request_type, length); }, /** @@ -477,23 +475,15 @@ let Buf = { * * @param type * Integer specifying the request type. - * @param options [optional] - * Object containing information about the request, e.g. the - * original main thread message object that led to the RIL request. */ - newParcel: function newParcel(type, options) { + newParcel: function newParcel(type) { if (DEBUG) debug("New outgoing parcel of type " + type); // We're going to leave room for the parcel size at the beginning. this.outgoingIndex = PARCEL_SIZE_SIZE; this.writeUint32(type); let token = this.token; this.writeUint32(token); - - if (!options) { - options = {}; - } - options.rilRequestType = type; - this.tokenRequestMap[token] = options; + this.tokenRequestMap[token] = type; this.token++; return token; }, @@ -763,11 +753,9 @@ let RIL = { /** * Send an SMS. * - * The `options` parameter object should contain the following attributes: - * - * @param SMSC + * @param smscPDU * String containing the SMSC PDU in hex format. - * @param number + * @param address * String containing the recipients address. * @param body * String containing the message body. @@ -777,18 +765,15 @@ let RIL = { * @param bodyLengthInOctets * Byte length of the message body when encoded with the given DCS. */ - sendSMS: function sendSMS(options) { - let token = Buf.newParcel(REQUEST_SEND_SMS, options); + sendSMS: function sendSMS(smscPDU, address, body, dcs, bodyLengthInOctets) { + let token = Buf.newParcel(REQUEST_SEND_SMS); //TODO we want to map token to the input values so that on the // response from the RIL device we know which SMS request was successful // or not. Maybe we should build that functionality into newParcel() and // handle it within tokenRequestMap[]. Buf.writeUint32(2); - Buf.writeString(options.SMSC); - GsmPDUHelper.writeMessage(options.number, - options.body, - options.dcs, - options.bodyLengthInOctets); + Buf.writeString(smscPDU); + GsmPDUHelper.writeMessage(address, body, dcs, bodyLengthInOctets); Buf.sendParcel(); }, @@ -922,11 +907,11 @@ let RIL = { * _is_ the method name, so that's easy. */ - handleParcel: function handleParcel(request_type, length, options) { + handleParcel: function handleParcel(request_type, length) { let method = this[request_type]; if (typeof method == "function") { if (DEBUG) debug("Handling parcel as " + method.name); - method.call(this, length, options); + method.call(this, length); } } }; @@ -1079,11 +1064,11 @@ RIL[REQUEST_RADIO_POWER] = null; RIL[REQUEST_DTMF] = function REQUEST_DTMF() { Phone.onSendTone(); }; -RIL[REQUEST_SEND_SMS] = function REQUEST_SEND_SMS(length, options) { - options.messageRef = Buf.readUint32(); - options.ackPDU = Buf.readString(); - options.errorCode = Buf.readUint32(); - Phone.onSendSMS(options); +RIL[REQUEST_SEND_SMS] = function REQUEST_SEND_SMS() { + let messageRef = Buf.readUint32(); + let ackPDU = Buf.readString(); + let errorCode = Buf.readUint32(); + Phone.onSendSMS(messageRef, ackPDU, errorCode); }; RIL[REQUEST_SEND_SMS_EXPECT_MORE] = null; RIL[REQUEST_SETUP_DATA_CALL] = function REQUEST_SETUP_DATA_CALL() { @@ -1768,9 +1753,8 @@ let Phone = { onSetSMSCAddress: function onSetSMSCAddress() { }, - onSendSMS: function onSendSMS(options) { - options.type = "sms-sent"; - this.sendDOMMessage(options); + onSendSMS: function onSendSMS(messageRef, ackPDU, errorCode) { + //TODO }, onNewSMS: function onNewSMS(payloadLength) { @@ -2029,10 +2013,6 @@ let Phone = { * String containing the recipient number. * @param body * String containing the message text. - * @param requestId - * String identifying the sms request used by the SmsRequestManager. - * @param processId - * String containing the processId for the SmsRequestManager. */ sendSMS: function sendSMS(options) { // Get the SMS Center address @@ -2045,17 +2025,12 @@ let Phone = { } return; } - // We explicitly save this information on the options object so that we - // can refer to it later, in particular on the main thread (where this - // object may get sent eventually.) - options.SMSC = this.SMSC; - //TODO: verify values on 'options' //TODO: the data encoding and length in octets should eventually be // computed on the mainthread and passed down to us. - options.dcs = PDU_DCS_MSG_CODING_7BITS_ALPHABET; - options.bodyLengthInOctets = Math.ceil(options.body.length * 7 / 8); - RIL.sendSMS(options); + RIL.sendSMS(this.SMSC, options.number, options.body, + PDU_DCS_MSG_CODING_7BITS_ALPHABET, //TODO: hard-coded for now, + Math.ceil(options.body.length * 7 / 8)); //TODO: ditto }, /** diff --git a/embedding/android/GeckoSmsManager.java b/embedding/android/GeckoSmsManager.java index 46fe1ee3acd8..51018d4e2bbd 100644 --- a/embedding/android/GeckoSmsManager.java +++ b/embedding/android/GeckoSmsManager.java @@ -327,9 +327,9 @@ public class GeckoSmsManager public final static String ACTION_SMS_DELIVERED = "org.mozilla.gecko.SMS_DELIVERED"; /* - * Make sure that the following error codes are in sync with the ones - * defined in dom/sms/interfaces/nsISmsRequestManager.idl. They are owned - * owned by the interface. + * Make sure that the following error codes are in sync with |ErrorType| in: + * dom/sms/src/Types.h + * The error code are owned by the DOM. */ public final static int kNoError = 0; public final static int kNoSignalError = 1; diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp index f0cdad33e6a8..735fadd868e7 100644 --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -252,7 +252,6 @@ static void Shutdown(); #include "nsCSPService.h" #include "nsISmsService.h" #include "nsISmsDatabaseService.h" -#include "mozilla/dom/sms/SmsRequestManager.h" #include "mozilla/dom/sms/SmsServicesFactory.h" #include "nsIPowerManagerService.h" @@ -310,7 +309,6 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsISmsService, SmsServicesFactory::Crea NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsISmsDatabaseService, SmsServicesFactory::CreateSmsDatabaseService) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIPowerManagerService, PowerManagerService::GetInstance) -NS_GENERIC_FACTORY_CONSTRUCTOR(SmsRequestManager) //----------------------------------------------------------------------------- @@ -802,7 +800,6 @@ NS_DEFINE_NAMED_CID(NS_HAPTICFEEDBACK_CID); #endif NS_DEFINE_NAMED_CID(SMS_SERVICE_CID); NS_DEFINE_NAMED_CID(SMS_DATABASE_SERVICE_CID); -NS_DEFINE_NAMED_CID(SMS_REQUEST_MANAGER_CID); NS_DEFINE_NAMED_CID(NS_POWERMANAGERSERVICE_CID); static nsresult @@ -1074,7 +1071,6 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = { { &kNS_STRUCTUREDCLONECONTAINER_CID, false, NULL, nsStructuredCloneContainerConstructor }, { &kSMS_SERVICE_CID, false, NULL, nsISmsServiceConstructor }, { &kSMS_DATABASE_SERVICE_CID, false, NULL, nsISmsDatabaseServiceConstructor }, - { &kSMS_REQUEST_MANAGER_CID, false, NULL, SmsRequestManagerConstructor }, { &kNS_POWERMANAGERSERVICE_CID, false, NULL, nsIPowerManagerServiceConstructor }, { NULL } }; @@ -1211,7 +1207,6 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = { { NS_STRUCTUREDCLONECONTAINER_CONTRACTID, &kNS_STRUCTUREDCLONECONTAINER_CID }, { SMS_SERVICE_CONTRACTID, &kSMS_SERVICE_CID }, { SMS_DATABASE_SERVICE_CONTRACTID, &kSMS_DATABASE_SERVICE_CID }, - { SMS_REQUEST_MANAGER_CONTRACTID, &kSMS_REQUEST_MANAGER_CID }, { POWERMANAGERSERVICE_CONTRACTID, &kNS_POWERMANAGERSERVICE_CID }, { NULL } }; diff --git a/layout/build/nsLayoutStatics.cpp b/layout/build/nsLayoutStatics.cpp index 7910e51600c1..df409480b6af 100644 --- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -125,6 +125,7 @@ #include "nsHyphenationManager.h" #include "nsEditorSpellCheck.h" #include "nsDOMMemoryReporter.h" +#include "mozilla/dom/sms/SmsRequestManager.h" extern void NS_ShutdownChainItemPool(); @@ -271,12 +272,16 @@ nsLayoutStatics::Initialize() nsDOMMemoryMultiReporter::Init(); + sms::SmsRequestManager::Init(); + return NS_OK; } void nsLayoutStatics::Shutdown() { + sms::SmsRequestManager::Shutdown(); + // Don't need to shutdown nsDOMMemoryReporter, that will be done by the memory // reporter manager. From 77faad30c1b12759cd465b775b5879cc6d2420ac Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Thu, 16 Feb 2012 15:21:59 -0800 Subject: [PATCH 82/93] Bug 727921 - Fix schedulegc bustage --- js/src/jit-test/lib/prolog.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/js/src/jit-test/lib/prolog.js b/js/src/jit-test/lib/prolog.js index 84ab993cb5da..7d5979239177 100644 --- a/js/src/jit-test/lib/prolog.js +++ b/js/src/jit-test/lib/prolog.js @@ -8,3 +8,6 @@ if (!("gczeal" in this)) { gczeal = function() { } } +if (!("schedulegc" in this)) { + schedulegc = function() { } +} From 947210ccb1d7d4f64a226868c7e92d94486348e6 Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Thu, 16 Feb 2012 15:26:30 -0800 Subject: [PATCH 83/93] Ensure that generators are never compiled, bug 726799. r=dvander --- js/src/methodjit/Compiler.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 774fc11616c6..0fa45cb53ed9 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -177,6 +177,11 @@ mjit::Compiler::checkAnalysis(JSScript *script) return Compile_Abort; } + if (JSOp(*script->code) == JSOP_GENERATOR) { + JaegerSpew(JSpew_Abort, "script is a generator\n"); + return Compile_Abort; + } + if (!script->ensureRanAnalysis(cx, NULL)) return Compile_Error; if (cx->typeInferenceEnabled() && !script->ensureRanInference(cx)) From c899b32b95efc798af438858fbd5ffa16f5ba9f4 Mon Sep 17 00:00:00 2001 From: Joe Drew Date: Thu, 9 Feb 2012 20:57:26 -0500 Subject: [PATCH 84/93] Bug 725747 - Immediately translate setting the default FBO into our offscreen FBO, rather than setting it and unsetting it before and after GL draw commands. r=jgilbert --- gfx/gl/GLContext.cpp | 2 + gfx/gl/GLContext.h | 152 ++++++++++++++++++++++++++++++------------- 2 files changed, 108 insertions(+), 46 deletions(-) diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp index fe9c39462fcd..f982ce6e52e0 100644 --- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -1452,6 +1452,8 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO, c // We're good, and the framebuffer is already attached. // Now restore the GL state back to what it was before the resize took place. + // If the user was using fb 0, this will bind the offscreen framebuffer we + // just created. BindDrawFBO(curBoundFramebufferDraw); BindReadFBO(curBoundFramebufferRead); fBindTexture(LOCAL_GL_TEXTURE_2D, curBoundTexture); diff --git a/gfx/gl/GLContext.h b/gfx/gl/GLContext.h index a7b1f1f90523..84f8bb40bb78 100644 --- a/gfx/gl/GLContext.h +++ b/gfx/gl/GLContext.h @@ -541,8 +541,10 @@ public: bool aIsOffscreen = false, GLContext *aSharedContext = nsnull) : mFlushGuaranteesResolve(false), - mBoundDrawFBO(0), - mBoundReadFBO(0), + mUserBoundDrawFBO(0), + mUserBoundReadFBO(0), + mInternalBoundDrawFBO(0), + mInternalBoundReadFBO(0), mOffscreenFBOsDirty(false), mInitialized(false), mIsOffscreen(aIsOffscreen), @@ -862,23 +864,67 @@ public: private: - GLuint mBoundDrawFBO; - GLuint mBoundReadFBO; + GLuint mUserBoundDrawFBO; + GLuint mUserBoundReadFBO; + GLuint mInternalBoundDrawFBO; + GLuint mInternalBoundReadFBO; public: void fBindFramebuffer(GLenum target, GLuint framebuffer) { switch (target) { - case LOCAL_GL_FRAMEBUFFER: - mBoundDrawFBO = mBoundReadFBO = framebuffer; - break; case LOCAL_GL_DRAW_FRAMEBUFFER_EXT: - mBoundDrawFBO = framebuffer; + mUserBoundDrawFBO = framebuffer; + + if (framebuffer == 0) { + mInternalBoundDrawFBO = mOffscreenDrawFBO; + } else { + mInternalBoundDrawFBO = mUserBoundDrawFBO; + } + + raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, + mInternalBoundDrawFBO); break; + case LOCAL_GL_READ_FRAMEBUFFER_EXT: - mBoundReadFBO = framebuffer; + mUserBoundReadFBO = framebuffer; + + if (framebuffer == 0) { + mInternalBoundReadFBO = mOffscreenReadFBO; + } else { + mInternalBoundReadFBO = mUserBoundReadFBO; + } + + raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, + mInternalBoundReadFBO); + break; + + case LOCAL_GL_FRAMEBUFFER: + mUserBoundDrawFBO = mUserBoundReadFBO = framebuffer; + + if (framebuffer == 0) { + mInternalBoundDrawFBO = mOffscreenDrawFBO; + mInternalBoundReadFBO = mOffscreenReadFBO; + } else { + mInternalBoundDrawFBO = mUserBoundDrawFBO; + mInternalBoundReadFBO = mUserBoundReadFBO; + } + + if (SupportsOffscreenSplit()) { + raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, + mInternalBoundDrawFBO); + raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, + mInternalBoundReadFBO); + } else { + raw_fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, + mInternalBoundDrawFBO); + } + + break; + + default: + raw_fBindFramebuffer(target, framebuffer); break; } - raw_fBindFramebuffer(target, framebuffer); } GLuint GetBoundDrawFBO() { @@ -886,32 +932,38 @@ public: GLint ret = 0; // Don't need a branch here, because: // LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT == LOCAL_GL_FRAMEBUFFER_BINDING == 0x8CA6 - fGetIntegerv(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT, &ret); + // We use raw_ here because this is debug code and we need to see what + // the driver thinks. + raw_fGetIntegerv(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT, &ret); - if (mBoundDrawFBO != (GLuint)ret) { - printf_stderr("!!! Draw FBO mismatch: Was: %d, Expected: %d\n", ret, mBoundDrawFBO); + if (mInternalBoundDrawFBO != (GLuint)ret) { + printf_stderr("!!! Draw FBO mismatch: Was: %d, Expected: %d\n", ret, mInternalBoundDrawFBO); NS_ABORT(); } #endif - return mBoundDrawFBO; + // We only ever expose the user's bound FBOs + return mUserBoundDrawFBO; } GLuint GetBoundReadFBO() { #ifdef DEBUG GLint ret = 0; + // We use raw_ here because this is debug code and we need to see what + // the driver thinks. if (SupportsOffscreenSplit()) - fGetIntegerv(LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT, &ret); + raw_fGetIntegerv(LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT, &ret); else - fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &ret); + raw_fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &ret); - if (mBoundReadFBO != (GLuint)ret) { - printf_stderr("!!! Read FBO mismatch: Was: %d, Expected: %d\n", ret, mBoundReadFBO); + if (mInternalBoundReadFBO != (GLuint)ret) { + printf_stderr("!!! Read FBO mismatch: Was: %d, Expected: %d\n", ret, mInternalBoundReadFBO); NS_ABORT(); } #endif - return mBoundReadFBO; + // We only ever expose the user's bound FBOs + return mUserBoundReadFBO; } void BindDrawFBO(GLuint name) { @@ -954,8 +1006,6 @@ public: } private: - GLuint mPrevDrawFBOBinding; - GLuint mPrevReadFBOBinding; bool mOffscreenFBOsDirty; void GetShaderPrecisionFormatNonES2(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) { @@ -980,40 +1030,29 @@ private: } } + // Do whatever setup is necessary to draw to our offscreen FBO, if it's + // bound. void BeforeGLDrawCall() { - // Record and rebind if necessary - mPrevDrawFBOBinding = GetBoundDrawFBO(); - if (mPrevDrawFBOBinding == 0) { - BindDrawFBO(mOffscreenDrawFBO); - } else if (mPrevDrawFBOBinding != mOffscreenDrawFBO) + if (mInternalBoundDrawFBO != mOffscreenDrawFBO) return; - // Must be after binding the proper FBO if (mOffscreenDrawFBO == mOffscreenReadFBO) return; - // If we're already dirty, no need to set it again - if (mOffscreenFBOsDirty) - return; - mOffscreenFBOsDirty = true; } + // Do whatever tear-down is necessary after drawing to our offscreen FBO, + // if it's bound. void AfterGLDrawCall() { - if (mPrevDrawFBOBinding == 0) { - BindDrawFBO(0); - } } + // Do whatever setup is necessary to read from our offscreen FBO, if it's + // bound. void BeforeGLReadCall() { - // Record and rebind if necessary - mPrevReadFBOBinding = GetBoundReadFBO(); - if (mPrevReadFBOBinding == 0) { - BindReadFBO(mOffscreenReadFBO); - } else if (mPrevReadFBOBinding != mOffscreenReadFBO) + if (mInternalBoundReadFBO != mOffscreenReadFBO) return; - // Must be after binding the proper FBO if (mOffscreenDrawFBO == mOffscreenReadFBO) return; @@ -1027,7 +1066,7 @@ private: // flip read/draw for blitting GLuint prevDraw = SwapBoundDrawFBO(mOffscreenReadFBO); - BindReadFBO(mOffscreenDrawFBO); // We know that Read must already be mOffscreenRead, so no need to write that down + GLuint prevRead = SwapBoundReadFBO(mOffscreenDrawFBO); GLint width = mOffscreenActualSize.width; GLint height = mOffscreenActualSize.height; @@ -1037,7 +1076,7 @@ private: LOCAL_GL_NEAREST); BindDrawFBO(prevDraw); - BindReadFBO(mOffscreenReadFBO); + BindReadFBO(prevRead); if (scissor) fEnable(LOCAL_GL_SCISSOR_TEST); @@ -1045,10 +1084,9 @@ private: mOffscreenFBOsDirty = false; } + // Do whatever tear-down is necessary after reading from our offscreen FBO, + // if it's bound. void AfterGLReadCall() { - if (mPrevReadFBOBinding == 0) { - BindReadFBO(0); - } } public: @@ -1997,12 +2035,34 @@ public: return retval; } - void fGetIntegerv(GLenum pname, GLint *params) { +private: + void raw_fGetIntegerv(GLenum pname, GLint *params) { BEFORE_GL_CALL; mSymbols.fGetIntegerv(pname, params); AFTER_GL_CALL; } +public: + void fGetIntegerv(GLenum pname, GLint *params) { + switch (pname) + { + // LOCAL_GL_FRAMEBUFFER_BINDING is equal to + // LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT, so we don't need two + // cases. + case LOCAL_GL_FRAMEBUFFER_BINDING: + *params = GetBoundDrawFBO(); + break; + + case LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT: + *params = GetBoundReadFBO(); + break; + + default: + raw_fGetIntegerv(pname, params); + break; + } + } + void fGetFloatv(GLenum pname, GLfloat *params) { BEFORE_GL_CALL; mSymbols.fGetFloatv(pname, params); From 4b54d517e0d4061034419a82bbab1db409f087c1 Mon Sep 17 00:00:00 2001 From: Joe Drew Date: Thu, 16 Feb 2012 18:45:16 -0500 Subject: [PATCH 85/93] Bug 725747 - Seems we run into a driver bug on OS X (on NVIDIA cards only) now. Mark these tests as failing. r=bjacob --- content/canvas/test/webgl/failing_tests_mac.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/content/canvas/test/webgl/failing_tests_mac.txt b/content/canvas/test/webgl/failing_tests_mac.txt index 5bc2bc7c82d9..eaabd7f6f1e8 100644 --- a/content/canvas/test/webgl/failing_tests_mac.txt +++ b/content/canvas/test/webgl/failing_tests_mac.txt @@ -7,3 +7,5 @@ conformance/more/conformance/quickCheckAPI-S_V.html conformance/glsl/misc/attrib-location-length-limits.html conformance/glsl/misc/uniform-location-length-limits.html conformance/programs/program-test.html +conformance/textures/texture-mips.html +conformance/textures/texture-npot.html From ea46243f65b84c971c63c0aeeddfddb9f809f2ee Mon Sep 17 00:00:00 2001 From: Benoit Jacob Date: Thu, 16 Feb 2012 18:45:16 -0500 Subject: [PATCH 86/93] Bug 727614 - Use #ifdef ANDROID instead of #ifdef MOZ_WIDGET_ANDROID to cover B2G too. r=joe --- content/canvas/src/WebGLContextGL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index c0a8fed9c8e3..fd5b6fce0707 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -4377,7 +4377,7 @@ WebGLContext::CompileShader(nsIWebGLShader *sobj) // ESSL backend compiler = ShConstructCompiler((ShShaderType) shader->ShaderType(), SH_WEBGL_SPEC, -#ifdef MOZ_WIDGET_ANDROID +#ifdef ANDROID SH_GLSL_OUTPUT, #else gl->IsGLES2() ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT, From 8f85c825e0120afddf9b611bc2573714c195f235 Mon Sep 17 00:00:00 2001 From: John Schoenick Date: Mon, 13 Feb 2012 11:26:28 -0800 Subject: [PATCH 87/93] Bug 716556 - Fix possible buffer overflow in nsScriptableInputStream (attempt 2). r=bsmedberg --- xpcom/io/nsScriptableInputStream.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xpcom/io/nsScriptableInputStream.cpp b/xpcom/io/nsScriptableInputStream.cpp index 30790de21152..374a7a4cce8a 100644 --- a/xpcom/io/nsScriptableInputStream.cpp +++ b/xpcom/io/nsScriptableInputStream.cpp @@ -72,7 +72,8 @@ nsScriptableInputStream::Read(PRUint32 aCount, char **_retval) { rv = mInputStream->Available(&count); if (NS_FAILED(rv)) return rv; - count = NS_MIN(count, aCount); + // bug716556 - Ensure count+1 doesn't overflow + count = NS_MIN(NS_MIN(count, aCount), PR_UINT32_MAX - 1); buffer = (char*)nsMemory::Alloc(count+1); // make room for '\0' if (!buffer) return NS_ERROR_OUT_OF_MEMORY; From 4cd4c19f07795220e217c070cbb20fa593fc7e10 Mon Sep 17 00:00:00 2001 From: Josh Aas Date: Thu, 16 Feb 2012 21:27:37 -0500 Subject: [PATCH 88/93] Bug 724717: Fix crash at nsPluginInstanceOwner::CARefresh. r=benwa --- dom/plugins/base/nsPluginInstanceOwner.cpp | 62 +++++++++++++--------- dom/plugins/base/nsPluginInstanceOwner.h | 5 +- layout/generic/nsObjectFrame.cpp | 14 ----- 3 files changed, 40 insertions(+), 41 deletions(-) diff --git a/dom/plugins/base/nsPluginInstanceOwner.cpp b/dom/plugins/base/nsPluginInstanceOwner.cpp index b67de18fbcf2..ce741634823f 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.cpp +++ b/dom/plugins/base/nsPluginInstanceOwner.cpp @@ -1390,7 +1390,19 @@ void nsPluginInstanceOwner::CARefresh(nsITimer *aTimer, void *aClosure) { } } -void nsPluginInstanceOwner::AddToCARefreshTimer(nsPluginInstanceOwner *aPluginInstance) { +void nsPluginInstanceOwner::AddToCARefreshTimer() { + if (!mInstance) { + return; + } + + // Flash invokes InvalidateRect for us. + const char* mime = nsnull; + if (NS_SUCCEEDED(mInstance->GetMIMEType(&mime)) && mime) { + if (strcmp(mime, "application/x-shockwave-flash") == 0) { + return; + } + } + if (!sCARefreshListeners) { sCARefreshListeners = new nsTArray(); if (!sCARefreshListeners) { @@ -1398,9 +1410,11 @@ void nsPluginInstanceOwner::AddToCARefreshTimer(nsPluginInstanceOwner *aPluginIn } } - NS_ASSERTION(!sCARefreshListeners->Contains(aPluginInstance), - "pluginInstanceOwner already registered as a listener"); - sCARefreshListeners->AppendElement(aPluginInstance); + if (sCARefreshListeners->Contains(this)) { + return; + } + + sCARefreshListeners->AppendElement(this); if (!sCATimer) { sCATimer = new nsCOMPtr(); @@ -1416,12 +1430,12 @@ void nsPluginInstanceOwner::AddToCARefreshTimer(nsPluginInstanceOwner *aPluginIn } } -void nsPluginInstanceOwner::RemoveFromCARefreshTimer(nsPluginInstanceOwner *aPluginInstance) { - if (!sCARefreshListeners || sCARefreshListeners->Contains(aPluginInstance) == false) { +void nsPluginInstanceOwner::RemoveFromCARefreshTimer() { + if (!sCARefreshListeners || sCARefreshListeners->Contains(this) == false) { return; } - sCARefreshListeners->RemoveElement(aPluginInstance); + sCARefreshListeners->RemoveElement(this); if (sCARefreshListeners->Length() == 0) { if (sCATimer) { @@ -1434,21 +1448,6 @@ void nsPluginInstanceOwner::RemoveFromCARefreshTimer(nsPluginInstanceOwner *aPlu } } -void nsPluginInstanceOwner::SetupCARefresh() -{ - if (!mInstance) { - return; - } - - const char* mime = nsnull; - if (NS_SUCCEEDED(mInstance->GetMIMEType(&mime)) && mime) { - // Flash invokes InvalidateRect for us. - if (strcmp(mime, "application/x-shockwave-flash") != 0) { - AddToCARefreshTimer(this); - } -} -} - void nsPluginInstanceOwner::RenderCoreAnimation(CGContextRef aCGContext, int aWidth, int aHeight) { @@ -2699,7 +2698,7 @@ nsPluginInstanceOwner::Destroy() CancelTimer(); #endif #ifdef XP_MACOSX - RemoveFromCARefreshTimer(this); + RemoveFromCARefreshTimer(); if (mColorProfile) ::CGColorSpaceRelease(mColorProfile); #endif @@ -3277,7 +3276,7 @@ NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void) { NS_ENSURE_TRUE(mPluginWindow, NS_ERROR_NULL_POINTER); - nsresult rv = NS_ERROR_FAILURE; + nsresult rv = NS_ERROR_FAILURE; // Can't call this twice! if (mWidget) { @@ -3318,6 +3317,21 @@ NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void) mWidget->EnableDragDrop(true); mWidget->Show(false); mWidget->Enable(false); + +#ifdef XP_MACOSX + // Now that we have a widget we want to set the event model before + // any events are processed. + nsCOMPtr pluginWidget = do_QueryInterface(mWidget); + if (!pluginWidget) { + return NS_ERROR_FAILURE; + } + pluginWidget->SetPluginEventModel(GetEventModel()); + pluginWidget->SetPluginDrawingModel(GetDrawingModel()); + + if (GetDrawingModel() == NPDrawingModelCoreAnimation) { + AddToCARefreshTimer(); + } +#endif } if (mObjectFrame) { diff --git a/dom/plugins/base/nsPluginInstanceOwner.h b/dom/plugins/base/nsPluginInstanceOwner.h index 4e4a029c2484..1eacec927a32 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.h +++ b/dom/plugins/base/nsPluginInstanceOwner.h @@ -182,9 +182,8 @@ public: bool IsRemoteDrawingCoreAnimation(); NPEventModel GetEventModel(); static void CARefresh(nsITimer *aTimer, void *aClosure); - static void AddToCARefreshTimer(nsPluginInstanceOwner *aPluginInstance); - static void RemoveFromCARefreshTimer(nsPluginInstanceOwner *aPluginInstance); - void SetupCARefresh(); + void AddToCARefreshTimer(); + void RemoveFromCARefreshTimer(); // This calls into the plugin (NPP_SetWindow) and can run script. void* FixUpPluginWindow(PRInt32 inPaintState); void HidePluginWindow(); diff --git a/layout/generic/nsObjectFrame.cpp b/layout/generic/nsObjectFrame.cpp index c2fdf060a37a..a23ba83d453e 100644 --- a/layout/generic/nsObjectFrame.cpp +++ b/layout/generic/nsObjectFrame.cpp @@ -480,20 +480,6 @@ nsObjectFrame::PrepForDrawing(nsIWidget *aWidget) break; } } - -#ifdef XP_MACOSX - // Now that we have a widget we want to set the event model before - // any events are processed. - nsCOMPtr pluginWidget = do_QueryInterface(mWidget); - if (!pluginWidget) - return NS_ERROR_FAILURE; - pluginWidget->SetPluginEventModel(mInstanceOwner->GetEventModel()); - pluginWidget->SetPluginDrawingModel(mInstanceOwner->GetDrawingModel()); - - if (mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreAnimation) { - mInstanceOwner->SetupCARefresh(); - } -#endif } else { // Changing to windowless mode changes the NPWindow geometry. FixupWindow(GetContentRectRelativeToSelf().Size()); From 5544e899b5d1a56440d3f1e3a62eb8f320fff64d Mon Sep 17 00:00:00 2001 From: Jim Mathies Date: Thu, 16 Feb 2012 18:36:04 -0600 Subject: [PATCH 89/93] Bug 718374 - File picker support for choosing Win7 library default folders, and strip sdk ifdefing junk. r=neil --- widget/windows/JumpListItem.cpp | 5 --- widget/windows/WinUtils.cpp | 16 ++++++- widget/windows/WinUtils.h | 27 ++++++++--- widget/windows/nsFilePicker.cpp | 79 +++++++++++---------------------- widget/windows/nsFilePicker.h | 22 +++------ 5 files changed, 65 insertions(+), 84 deletions(-) diff --git a/widget/windows/JumpListItem.cpp b/widget/windows/JumpListItem.cpp index 6394db6bb439..6984223bee40 100644 --- a/widget/windows/JumpListItem.cpp +++ b/widget/windows/JumpListItem.cpp @@ -737,11 +737,6 @@ nsresult JumpListLink::GetShellItem(nsCOMPtr& item, nsRefPtrGetSpec(spec); NS_ENSURE_SUCCESS(rv, rv); - // Load vista+ SHCreateItemFromParsingName - if (!WinUtils::VistaCreateItemFromParsingNameInit()) { - return NS_ERROR_UNEXPECTED; - } - // Create the IShellItem if (FAILED(WinUtils::SHCreateItemFromParsingName( NS_ConvertASCIItoUTF16(spec).get(), NULL, IID_PPV_ARGS(&psi)))) { diff --git a/widget/windows/WinUtils.cpp b/widget/windows/WinUtils.cpp index 5b96db52c1d4..d5763a81e90a 100644 --- a/widget/windows/WinUtils.cpp +++ b/widget/windows/WinUtils.cpp @@ -393,10 +393,24 @@ HRESULT WinUtils::SHCreateItemFromParsingName(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv) { - NS_ENSURE_TRUE(sCreateItemFromParsingName, E_FAIL); + if (!VistaCreateItemFromParsingNameInit()) + return E_FAIL; return sCreateItemFromParsingName(pszPath, pbc, riid, ppv); } +/* static */ +bool +WinUtils::GetShellItemPath(IShellItem* aItem, + nsString& aResultString) +{ + NS_ENSURE_TRUE(aItem, false); + LPWSTR str = NULL; + if (FAILED(aItem->GetDisplayName(SIGDN_FILESYSPATH, &str))) + return false; + aResultString.Assign(str); + CoTaskMemFree(str); + return !aResultString.IsEmpty(); +} } // namespace widget } // namespace mozilla diff --git a/widget/windows/WinUtils.h b/widget/windows/WinUtils.h index e9fa5536fd02..3153d8f817f2 100644 --- a/widget/windows/WinUtils.h +++ b/widget/windows/WinUtils.h @@ -52,6 +52,8 @@ #include "nscore.h" #include #include +#include "nsAutoPtr.h" +#include "nsString.h" class nsWindow; @@ -200,13 +202,6 @@ public: */ static PRUint16 GetMouseInputSource(); - /** - * VistaCreateItemFromParsingNameInit() initializes the static pointer for - * SHCreateItemFromParsingName() API which is usable only on Vista and later. - * This returns TRUE if the API is available. Otherwise, FALSE. - */ - static bool VistaCreateItemFromParsingNameInit(); - /** * SHCreateItemFromParsingName() calls native SHCreateItemFromParsingName() * API. Note that you must call VistaCreateItemFromParsingNameInit() before @@ -215,12 +210,30 @@ public: static HRESULT SHCreateItemFromParsingName(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv); + /** + * GetShellItemPath return the file or directory path of a shell item. + * Internally calls IShellItem's GetDisplayName. + * + * aItem the shell item containing the path. + * aResultString the resulting string path. + * returns true if a path was retreived. + */ + static bool GetShellItemPath(IShellItem* aItem, + nsString& aResultString); + private: typedef HRESULT (WINAPI * SHCreateItemFromParsingNamePtr)(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv); static SHCreateItemFromParsingNamePtr sCreateItemFromParsingName; + + /** + * VistaCreateItemFromParsingNameInit() initializes the static pointer for + * SHCreateItemFromParsingName() API which is usable only on Vista and later. + * This returns TRUE if the API is available. Otherwise, FALSE. + */ + static bool VistaCreateItemFromParsingNameInit(); }; } // namespace widget diff --git a/widget/windows/nsFilePicker.cpp b/widget/windows/nsFilePicker.cpp index 21a4aa171032..e377e7556582 100644 --- a/widget/windows/nsFilePicker.cpp +++ b/widget/windows/nsFilePicker.cpp @@ -206,9 +206,7 @@ private: nsFilePicker::nsFilePicker() : mSelectedType(1) , mDlgWnd(NULL) -#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN , mFDECookie(0) -#endif { CoInitialize(NULL); } @@ -225,7 +223,6 @@ nsFilePicker::~nsFilePicker() NS_IMPL_ISUPPORTS1(nsFilePicker, nsIFilePicker) -#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN STDMETHODIMP nsFilePicker::QueryInterface(REFIID refiid, void** ppvResult) { *ppvResult = NULL; @@ -241,7 +238,6 @@ STDMETHODIMP nsFilePicker::QueryInterface(REFIID refiid, void** ppvResult) return E_NOINTERFACE; } -#endif /* * XP picker callbacks @@ -435,8 +431,6 @@ nsFilePicker::MultiFilePickerHook(HWND hwnd, * Vista+ callbacks */ -#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN - HRESULT nsFilePicker::OnFileOk(IFileDialog *pfd) { @@ -499,8 +493,6 @@ nsFilePicker::OnOverwrite(IFileDialog *pfd, return S_OK; } -#endif // MOZ_NTDDI_LONGHORN - /* * Close on parent close logic */ @@ -598,8 +590,6 @@ nsFilePicker::ShowXPFolderPicker(const nsString& aInitialDir) return result; } -#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN - bool nsFilePicker::ShowFolderPicker(const nsString& aInitialDir) { @@ -618,8 +608,7 @@ nsFilePicker::ShowFolderPicker(const nsString& aInitialDir) // initial strings dialog->SetTitle(mTitle.get()); - if (!aInitialDir.IsEmpty() && - WinUtils::VistaCreateItemFromParsingNameInit()) { + if (!aInitialDir.IsEmpty()) { nsRefPtr folder; if (SUCCEEDED( WinUtils::SHCreateItemFromParsingName(aInitialDir.get(), NULL, @@ -641,18 +630,25 @@ nsFilePicker::ShowFolderPicker(const nsString& aInitialDir) return false; } dialog->Unadvise(mFDECookie); - - // results - LPWSTR str = NULL; - if (FAILED(item->GetDisplayName(SIGDN_FILESYSPATH, &str))) - return false; - mUnicodeFile.Assign(str); - CoTaskMemFree(str); - - return true; -} -#endif // MOZ_WINSDK_TARGETVER + // results + + // If the user chose a Win7 Library, resolve to the library's + // default save folder. + nsRefPtr folderPath; + nsRefPtr shellLib; + CoCreateInstance(CLSID_ShellLibrary, NULL, CLSCTX_INPROC, IID_IShellLibrary, + getter_AddRefs(shellLib)); + if (shellLib && + SUCCEEDED(shellLib->LoadLibraryFromItem(item, STGM_READ)) && + SUCCEEDED(shellLib->GetDefaultSaveFolder(DSFT_DETECT, IID_IShellItem, + getter_AddRefs(folderPath)))) { + item.swap(folderPath); + } + + // get the folder's file system path + return WinUtils::GetShellItemPath(item, mUnicodeFile); +} /* * File open and save picker invocation @@ -870,8 +866,6 @@ nsFilePicker::ShowXPFilePicker(const nsString& aInitialDir) return true; } -#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN - bool nsFilePicker::ShowFilePicker(const nsString& aInitialDir) { @@ -947,8 +941,7 @@ nsFilePicker::ShowFilePicker(const nsString& aInitialDir) } // initial location - if (!aInitialDir.IsEmpty() && - WinUtils::VistaCreateItemFromParsingNameInit()) { + if (!aInitialDir.IsEmpty()) { nsRefPtr folder; if (SUCCEEDED( WinUtils::SHCreateItemFromParsingName(aInitialDir.get(), NULL, @@ -990,16 +983,9 @@ nsFilePicker::ShowFilePicker(const nsString& aInitialDir) // single selection if (mMode != modeOpenMultiple) { nsRefPtr item; - if (FAILED(dialog->GetResult(getter_AddRefs(item))) || !item) { + if (FAILED(dialog->GetResult(getter_AddRefs(item))) || !item) return false; - } - - LPWSTR str = NULL; - if (FAILED(item->GetDisplayName(SIGDN_FILESYSPATH, &str))) - return false; - mUnicodeFile.Assign(str); - CoTaskMemFree(str); - return true; + return WinUtils::GetShellItemPath(item, mUnicodeFile); } // multiple selection @@ -1019,21 +1005,18 @@ nsFilePicker::ShowFilePicker(const nsString& aInitialDir) items->GetCount(&count); for (unsigned int idx = 0; idx < count; idx++) { nsRefPtr item; + nsAutoString str; if (SUCCEEDED(items->GetItemAt(idx, getter_AddRefs(item)))) { - LPWSTR str = NULL; - if (FAILED(item->GetDisplayName(SIGDN_FILESYSPATH, &str))) + if (!WinUtils::GetShellItemPath(item, str)) continue; nsCOMPtr file = do_CreateInstance("@mozilla.org/file/local;1"); - if (file && NS_SUCCEEDED(file->InitWithPath(nsDependentString(str)))) + if (file && NS_SUCCEEDED(file->InitWithPath(str))) mFiles.AppendObject(file); - CoTaskMemFree(str); } } return true; } -#endif // MOZ_WINSDK_TARGETVER - /////////////////////////////////////////////////////////////////////////////// // nsIFilePicker impl. @@ -1062,23 +1045,15 @@ nsFilePicker::ShowW(PRInt16 *aReturnVal) bool result = false; if (mMode == modeGetFolder) { -#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION) result = ShowFolderPicker(initialDir); else result = ShowXPFolderPicker(initialDir); -#else - result = ShowXPFolderPicker(initialDir); -#endif } else { -#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN if (WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION) result = ShowFilePicker(initialDir); else result = ShowXPFilePicker(initialDir); -#else - result = ShowXPFilePicker(initialDir); -#endif } // exit, and return returnCancel in aReturnVal @@ -1347,8 +1322,6 @@ nsFilePicker::IsDefaultPathHtml() return false; } -#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN - void nsFilePicker::ComDlgFilterSpec::Append(const nsAString& aTitle, const nsAString& aFilter) { @@ -1378,5 +1351,3 @@ nsFilePicker::ComDlgFilterSpec::Append(const nsAString& aTitle, const nsAString& } pSpecForward->pszSpec = pStr->get(); } - -#endif // MOZ_WINSDK_TARGETVER diff --git a/widget/windows/nsFilePicker.h b/widget/windows/nsFilePicker.h index c91fd182a7a9..125f349f0e62 100644 --- a/widget/windows/nsFilePicker.h +++ b/widget/windows/nsFilePicker.h @@ -44,8 +44,8 @@ #include -#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN -// For Vista IFileDialog interfaces +// For Vista IFileDialog interfaces which aren't exposed +// unless _WIN32_WINNT >= _WIN32_WINNT_LONGHORN. #if _WIN32_WINNT < _WIN32_WINNT_LONGHORN #define _WIN32_WINNT_bak _WIN32_WINNT #undef _WIN32_WINNT @@ -54,7 +54,6 @@ #undef _WIN32_IE #define _WIN32_IE _WIN32_IE_IE70 #endif -#endif #include "nsILocalFile.h" #include "nsITimer.h" @@ -72,10 +71,9 @@ * Native Windows FileSelector wrapper */ -class nsFilePicker : public nsBaseFilePicker -#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN - , public IFileDialogEvents -#endif +class nsFilePicker : + public nsBaseFilePicker, + public IFileDialogEvents { public: nsFilePicker(); @@ -83,10 +81,8 @@ public: NS_DECL_ISUPPORTS -#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN // IUnknown's QueryInterface STDMETHODIMP QueryInterface(REFIID refiid, void** ppvResult); -#endif // nsIFilePicker (less what's in nsBaseFilePicker) NS_IMETHOD GetDefaultString(nsAString& aDefaultString); @@ -102,7 +98,6 @@ public: NS_IMETHOD ShowW(PRInt16 *aReturnVal); NS_IMETHOD AppendFilter(const nsAString& aTitle, const nsAString& aFilter); -#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN // IFileDialogEvents HRESULT STDMETHODCALLTYPE OnFileOk(IFileDialog *pfd); HRESULT STDMETHODCALLTYPE OnFolderChanging(IFileDialog *pfd, IShellItem *psiFolder); @@ -111,7 +106,6 @@ public: HRESULT STDMETHODCALLTYPE OnShareViolation(IFileDialog *pfd, IShellItem *psi, FDE_SHAREVIOLATION_RESPONSE *pResponse); HRESULT STDMETHODCALLTYPE OnTypeChange(IFileDialog *pfd); HRESULT STDMETHODCALLTYPE OnOverwrite(IFileDialog *pfd, IShellItem *psi, FDE_OVERWRITE_RESPONSE *pResponse); -#endif protected: enum PickerType { @@ -128,10 +122,8 @@ protected: bool FilePickerWrapper(OPENFILENAMEW* ofn, PickerType aType); bool ShowXPFolderPicker(const nsString& aInitialDir); bool ShowXPFilePicker(const nsString& aInitialDir); -#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN bool ShowFolderPicker(const nsString& aInitialDir); bool ShowFilePicker(const nsString& aInitialDir); -#endif void AppendXPFilter(const nsAString& aTitle, const nsAString& aFilter); void RememberLastUsedDirectory(); bool IsPrivacyModeEnabled(); @@ -158,7 +150,6 @@ protected: static PRUnichar *mLastUsedUnicodeDirectory; HWND mDlgWnd; -#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN class ComDlgFilterSpec { public: @@ -185,16 +176,13 @@ protected: ComDlgFilterSpec mComFilterList; DWORD mFDECookie; -#endif }; -#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN #if defined(_WIN32_WINNT_bak) #undef _WIN32_WINNT #define _WIN32_WINNT _WIN32_WINNT_bak #undef _WIN32_IE #define _WIN32_IE _WIN32_IE_bak #endif -#endif #endif // nsFilePicker_h__ From 374aa81278960c1024ad6ce78a90d9d0a108aaf6 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Wed, 15 Feb 2012 17:41:59 -0800 Subject: [PATCH 90/93] Warning patrol. No bug, r=themaid --HG-- extra : rebase_source : 66d872e0ab56b73f1879d1aff9aba1dd3e71e9b3 --- js/src/assembler/wtf/Assertions.h | 10 +++++++++- js/src/jsapi.h | 6 ++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/js/src/assembler/wtf/Assertions.h b/js/src/assembler/wtf/Assertions.h index 537737a5b823..80663ef6de75 100644 --- a/js/src/assembler/wtf/Assertions.h +++ b/js/src/assembler/wtf/Assertions.h @@ -29,8 +29,16 @@ #include "Platform.h" #include "mozilla/Assertions.h" +#ifndef DEBUG + /* + * Prevent unused-variable warnings by defining the macro WTF uses to test + * for assertions taking effect. + */ +# define ASSERT_DISABLED 1 +#endif + #define ASSERT(assertion) MOZ_ASSERT(assertion) -#define ASSERT_UNUSED(variable, assertion) ASSERT(assertion) +#define ASSERT_UNUSED(variable, assertion) (((void)variable), ASSERT(assertion)) #define ASSERT_NOT_REACHED() MOZ_NOT_REACHED("") #define CRASH() MOZ_Crash() #define COMPILE_ASSERT(exp, name) MOZ_STATIC_ASSERT(exp, #name) diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 509c2e17c4b6..7fbbd7806830 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -1860,7 +1860,11 @@ INTERNED_STRING_TO_JSID(JSContext *cx, JSString *str) jsid id; JS_ASSERT(str); JS_ASSERT(((size_t)str & JSID_TYPE_MASK) == 0); +#ifdef DEBUG JS_ASSERT(JS_StringHasBeenInterned(cx, str)); +#else + (void)cx; +#endif JSID_BITS(id) = (size_t)str; return id; } @@ -5314,6 +5318,8 @@ JS_IsConstructing(JSContext *cx, const jsval *vp) } else { JS_ASSERT(JS_GetClass(callee)->construct != NULL); } +#else + (void)cx; #endif return JSVAL_IS_MAGIC_IMPL(JSVAL_TO_IMPL(vp[1])); From c03c421cfb198f110462312ea689fd761d71be27 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Thu, 16 Feb 2012 19:10:45 -0800 Subject: [PATCH 91/93] Bug 728095 - Eliminate all primitive-this machinery from JSObject and relegate it to subclasses. r=bhackett --- js/src/jsbool.cpp | 2 +- js/src/jsboolinlines.h | 4 +++- js/src/jsclone.cpp | 9 ++++++--- js/src/jsnum.cpp | 3 +-- js/src/jsobj.cpp | 6 ++++-- js/src/jsobj.h | 16 ---------------- js/src/jsobjinlines.h | 23 ++++++++--------------- js/src/jsstr.cpp | 9 +++++---- js/src/methodjit/PolyIC.cpp | 5 +++-- js/src/vm/BooleanObject.h | 7 +++---- js/src/vm/NumberObject.h | 7 +++---- js/src/vm/StringObject.h | 16 ++++++++++------ 12 files changed, 47 insertions(+), 60 deletions(-) diff --git a/js/src/jsbool.cpp b/js/src/jsbool.cpp index c1fdd201ea03..277617a853ae 100644 --- a/js/src/jsbool.cpp +++ b/js/src/jsbool.cpp @@ -157,7 +157,7 @@ js_InitBooleanClass(JSContext *cx, JSObject *obj) JSObject *booleanProto = global->createBlankPrototype(cx, &BooleanClass); if (!booleanProto) return NULL; - booleanProto->setPrimitiveThis(BooleanValue(false)); + booleanProto->setFixedSlot(BooleanObject::PRIMITIVE_VALUE_SLOT, BooleanValue(false)); JSFunction *ctor = global->createConstructor(cx, Boolean, &BooleanClass, CLASS_ATOM(cx, Boolean), 1); diff --git a/js/src/jsboolinlines.h b/js/src/jsboolinlines.h index c9f172593461..573f3ed45022 100644 --- a/js/src/jsboolinlines.h +++ b/js/src/jsboolinlines.h @@ -42,13 +42,15 @@ #include "jsobjinlines.h" +#include "vm/BooleanObject-inl.h" + namespace js { inline bool BooleanGetPrimitiveValue(JSContext *cx, JSObject &obj, Value *vp) { if (obj.isBoolean()) { - *vp = obj.getPrimitiveThis(); + *vp = BooleanValue(obj.asBoolean().unbox()); return true; } diff --git a/js/src/jsclone.cpp b/js/src/jsclone.cpp index ef93f5088d77..496a05068216 100644 --- a/js/src/jsclone.cpp +++ b/js/src/jsclone.cpp @@ -42,7 +42,10 @@ #include "jstypedarrayinlines.h" +#include "vm/BooleanObject-inl.h" +#include "vm/NumberObject-inl.h" #include "vm/RegExpObject-inl.h" +#include "vm/StringObject-inl.h" using namespace js; @@ -536,12 +539,12 @@ JSStructuredCloneWriter::startWrite(const js::Value &v) } else if (js_IsArrayBuffer(obj)) { return writeArrayBuffer(obj); } else if (obj->isBoolean()) { - return out.writePair(SCTAG_BOOLEAN_OBJECT, obj->getPrimitiveThis().toBoolean()); + return out.writePair(SCTAG_BOOLEAN_OBJECT, obj->asBoolean().unbox()); } else if (obj->isNumber()) { return out.writePair(SCTAG_NUMBER_OBJECT, 0) && - out.writeDouble(obj->getPrimitiveThis().toNumber()); + out.writeDouble(obj->asNumber().unbox()); } else if (obj->isString()) { - return writeString(SCTAG_STRING_OBJECT, obj->getPrimitiveThis().toString()); + return writeString(SCTAG_STRING_OBJECT, obj->asString().unbox()); } if (callbacks && callbacks->write) diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp index 2dd2471e9ce9..caf05ebef5d9 100644 --- a/js/src/jsnum.cpp +++ b/js/src/jsnum.cpp @@ -490,10 +490,9 @@ Number(JSContext *cx, uintN argc, Value *vp) if (!isConstructing) return true; - JSObject *obj = NewBuiltinClassInstance(cx, &NumberClass); + JSObject *obj = NumberObject::create(cx, vp[0].toNumber()); if (!obj) return false; - obj->setPrimitiveThis(vp[0]); vp->setObject(*obj); return true; } diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index c9f19d20985a..636ad42329e0 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -5862,7 +5862,7 @@ DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp) &StringClass, ATOM_TO_JSID(cx->runtime->atomState.toStringAtom), js_str_toString)) { - *vp = obj->getPrimitiveThis(); + *vp = StringValue(obj->asString().unbox()); return true; } @@ -5885,7 +5885,9 @@ DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp) ClassMethodIsNative(cx, obj, &NumberClass, ATOM_TO_JSID(cx->runtime->atomState.valueOfAtom), js_num_valueOf))) { - *vp = obj->getPrimitiveThis(); + *vp = obj->isString() + ? StringValue(obj->asString().unbox()) + : NumberValue(obj->asNumber().unbox()); return true; } diff --git a/js/src/jsobj.h b/js/src/jsobj.h index fe0bb874e493..ad657b172a40 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -998,22 +998,6 @@ struct JSObject : js::gc::Cell bool isSealed(JSContext *cx, bool *resultp) { return isSealedOrFrozen(cx, SEAL, resultp); } bool isFrozen(JSContext *cx, bool *resultp) { return isSealedOrFrozen(cx, FREEZE, resultp); } - /* - * Primitive-specific getters and setters. - */ - - private: - static const uint32_t JSSLOT_PRIMITIVE_THIS = 0; - - public: - inline const js::Value &getPrimitiveThis() const; - inline void setPrimitiveThis(const js::Value &pthis); - - static size_t getPrimitiveThisOffset() { - /* All primitive objects have their value in a fixed slot. */ - return getFixedSlotOffset(JSSLOT_PRIMITIVE_THIS); - } - /* Accessors for elements. */ js::ObjectElements *getElementsHeader() const { diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 395d06a5e3df..930a807d0b39 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -65,8 +65,12 @@ #include "gc/Barrier.h" #include "js/TemplateLib.h" + +#include "vm/BooleanObject.h" #include "vm/GlobalObject.h" +#include "vm/NumberObject.h" #include "vm/RegExpStatics.h" +#include "vm/StringObject.h" #include "jsatominlines.h" #include "jsfuninlines.h" @@ -436,20 +440,6 @@ JSObject::setReservedSlot(uintN index, const js::Value &v) setSlot(index, v); } -inline const js::Value & -JSObject::getPrimitiveThis() const -{ - JS_ASSERT(isPrimitive()); - return getFixedSlot(JSSLOT_PRIMITIVE_THIS); -} - -inline void -JSObject::setPrimitiveThis(const js::Value &pthis) -{ - JS_ASSERT(isPrimitive()); - setFixedSlot(JSSLOT_PRIMITIVE_THIS, pthis); -} - inline bool JSObject::hasContiguousSlots(size_t start, size_t count) const { @@ -1916,6 +1906,7 @@ class PrimitiveBehavior { public: static inline bool isType(const Value &v) { return v.isString(); } static inline JSString *extract(const Value &v) { return v.toString(); } + static inline JSString *extract(JSObject &obj) { return obj.asString().unbox(); } static inline Class *getClass() { return &StringClass; } }; @@ -1924,6 +1915,7 @@ class PrimitiveBehavior { public: static inline bool isType(const Value &v) { return v.isBoolean(); } static inline bool extract(const Value &v) { return v.toBoolean(); } + static inline bool extract(JSObject &obj) { return obj.asBoolean().unbox(); } static inline Class *getClass() { return &BooleanClass; } }; @@ -1932,6 +1924,7 @@ class PrimitiveBehavior { public: static inline bool isType(const Value &v) { return v.isNumber(); } static inline double extract(const Value &v) { return v.toNumber(); } + static inline double extract(JSObject &obj) { return obj.asNumber().unbox(); } static inline Class *getClass() { return &NumberClass; } }; @@ -1968,7 +1961,7 @@ BoxedPrimitiveMethodGuard(JSContext *cx, CallArgs args, Native native, T *v, boo if (!NonGenericMethodGuard(cx, args, native, Behavior::getClass(), ok)) return false; - *v = Behavior::extract(thisv.toObject().getPrimitiveThis()); + *v = Behavior::extract(thisv.toObject()); return true; } diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index a877b259ecf1..bb8af6008d5a 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -399,7 +399,7 @@ static const uintN STRING_ELEMENT_ATTRS = JSPROP_ENUMERATE | JSPROP_READONLY | J static JSBool str_enumerate(JSContext *cx, JSObject *obj) { - JSString *str = obj->getPrimitiveThis().toString(); + JSString *str = obj->asString().unbox(); for (size_t i = 0, length = str->length(); i < length; i++) { JSString *str1 = js_NewDependentString(cx, str, i, 1); if (!str1) @@ -421,7 +421,7 @@ str_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, if (!JSID_IS_INT(id)) return JS_TRUE; - JSString *str = obj->getPrimitiveThis().toString(); + JSString *str = obj->asString().unbox(); jsint slot = JSID_TO_INT(id); if ((size_t)slot < str->length()) { @@ -472,8 +472,9 @@ ThisToStringForStringProto(JSContext *cx, CallReceiver call) ATOM_TO_JSID(cx->runtime->atomState.toStringAtom), js_str_toString)) { - call.thisv() = obj->getPrimitiveThis(); - return call.thisv().toString(); + JSString *str = obj->asString().unbox(); + call.thisv().setString(str); + return str; } } else if (call.thisv().isNullOrUndefined()) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CONVERT_TO, diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp index 3d06b51a2059..85786eca7735 100644 --- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -53,6 +53,7 @@ #include "jsautooplen.h" #include "vm/ScopeObject-inl.h" +#include "vm/StringObject-inl.h" #if defined JS_POLYIC @@ -944,7 +945,7 @@ class GetPropCompiler : public PICStubCompiler Jump notStringObj = masm.guardShape(pic.objReg, obj); - masm.loadPayload(Address(pic.objReg, JSObject::getPrimitiveThisOffset()), pic.objReg); + masm.loadPayload(Address(pic.objReg, StringObject::getPrimitiveValueOffset()), pic.objReg); masm.loadPtr(Address(pic.objReg, JSString::offsetOfLengthAndFlags()), pic.objReg); masm.urshift32(Imm32(JSString::LENGTH_SHIFT), pic.objReg); masm.move(ImmType(JSVAL_TYPE_INT32), pic.shapeReg); @@ -1885,7 +1886,7 @@ GetPropMaybeCached(VMFrame &f, ic::PICInfo *pic, bool cached) LookupStatus status = cc.generateStringObjLengthStub(); if (status == Lookup_Error) THROW(); - JSString *str = obj->getPrimitiveThis().toString(); + JSString *str = obj->asString().unbox(); f.regs.sp[-1].setInt32(str->length()); } return; diff --git a/js/src/vm/BooleanObject.h b/js/src/vm/BooleanObject.h index c4d5551e26e2..33cd4af068d5 100644 --- a/js/src/vm/BooleanObject.h +++ b/js/src/vm/BooleanObject.h @@ -67,14 +67,13 @@ class BooleanObject : public JSObject */ static inline BooleanObject *createWithProto(JSContext *cx, bool b, JSObject &proto); - Value unbox() const { - JS_ASSERT(getSlot(PRIMITIVE_VALUE_SLOT).isBoolean()); - return getSlot(PRIMITIVE_VALUE_SLOT); + bool unbox() const { + return getFixedSlot(PRIMITIVE_VALUE_SLOT).toBoolean(); } private: inline void setPrimitiveValue(bool b) { - setSlot(PRIMITIVE_VALUE_SLOT, BooleanValue(b)); + setFixedSlot(PRIMITIVE_VALUE_SLOT, BooleanValue(b)); } /* For access to init, as Boolean.prototype is special. */ diff --git a/js/src/vm/NumberObject.h b/js/src/vm/NumberObject.h index f4703b24a208..c2d4cdb9b1e4 100644 --- a/js/src/vm/NumberObject.h +++ b/js/src/vm/NumberObject.h @@ -67,14 +67,13 @@ class NumberObject : public JSObject */ static inline NumberObject *createWithProto(JSContext *cx, jsdouble d, JSObject &proto); - Value unbox() const { - JS_ASSERT(getSlot(PRIMITIVE_VALUE_SLOT).isNumber()); - return getSlot(PRIMITIVE_VALUE_SLOT); + double unbox() const { + return getFixedSlot(PRIMITIVE_VALUE_SLOT).toNumber(); } private: inline void setPrimitiveValue(jsdouble d) { - setSlot(PRIMITIVE_VALUE_SLOT, NumberValue(d)); + setFixedSlot(PRIMITIVE_VALUE_SLOT, NumberValue(d)); } /* For access to init, as Number.prototype is special. */ diff --git a/js/src/vm/StringObject.h b/js/src/vm/StringObject.h index ddcd69f7a3b5..4b06e5cb1761 100644 --- a/js/src/vm/StringObject.h +++ b/js/src/vm/StringObject.h @@ -50,7 +50,7 @@ namespace js { class StringObject : public JSObject { - static const uintN PRIMITIVE_THIS_SLOT = 0; + static const uintN PRIMITIVE_VALUE_SLOT = 0; static const uintN LENGTH_SLOT = 1; public: @@ -69,20 +69,24 @@ class StringObject : public JSObject static inline StringObject *createWithProto(JSContext *cx, JSString *str, JSObject &proto); JSString *unbox() const { - return getSlot(PRIMITIVE_THIS_SLOT).toString(); + return getFixedSlot(PRIMITIVE_VALUE_SLOT).toString(); } inline size_t length() const { - return size_t(getSlot(LENGTH_SLOT).toInt32()); + return size_t(getFixedSlot(LENGTH_SLOT).toInt32()); + } + + static size_t getPrimitiveValueOffset() { + return getFixedSlotOffset(PRIMITIVE_VALUE_SLOT); } private: inline bool init(JSContext *cx, JSString *str); void setStringThis(JSString *str) { - JS_ASSERT(getSlot(PRIMITIVE_THIS_SLOT).isUndefined()); - setSlot(PRIMITIVE_THIS_SLOT, StringValue(str)); - setSlot(LENGTH_SLOT, Int32Value(int32_t(str->length()))); + JS_ASSERT(getReservedSlot(PRIMITIVE_VALUE_SLOT).isUndefined()); + setFixedSlot(PRIMITIVE_VALUE_SLOT, StringValue(str)); + setFixedSlot(LENGTH_SLOT, Int32Value(int32_t(str->length()))); } /* For access to init, as String.prototype is special. */ From 6a945ff523b564ce63270683c2a6e1829654f233 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Thu, 16 Feb 2012 19:10:59 -0800 Subject: [PATCH 92/93] Bug 728105 - Remove JSObject::getThrowTypeError. r=bhackett --- js/src/jsfun.cpp | 12 +++--------- js/src/jsobj.h | 2 -- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 0a01408b113c..dbe974513f5e 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -100,12 +100,6 @@ using namespace js; using namespace js::gc; using namespace js::types; -inline JSObject * -JSObject::getThrowTypeError() const -{ - return global().getThrowTypeError(); -} - JSBool js_GetArgsValue(JSContext *cx, StackFrame *fp, Value *vp) { @@ -475,8 +469,8 @@ strictargs_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject } attrs = JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED; - getter = CastAsPropertyOp(argsobj.getThrowTypeError()); - setter = CastAsStrictPropertyOp(argsobj.getThrowTypeError()); + getter = CastAsPropertyOp(argsobj.global().getThrowTypeError()); + setter = CastAsStrictPropertyOp(argsobj.global().getThrowTypeError()); } Value undef = UndefinedValue(); @@ -1329,7 +1323,7 @@ fun_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, StrictPropertyOp setter; uintN attrs = JSPROP_PERMANENT; if (fun->isInterpreted() ? fun->inStrictMode() : fun->isBoundFunction()) { - JSObject *throwTypeError = fun->getThrowTypeError(); + JSObject *throwTypeError = fun->global().getThrowTypeError(); getter = CastAsPropertyOp(throwTypeError); setter = CastAsStrictPropertyOp(throwTypeError); diff --git a/js/src/jsobj.h b/js/src/jsobj.h index ad657b172a40..8b0bd037cfbc 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -1349,8 +1349,6 @@ struct JSObject : js::gc::Cell static bool thisObject(JSContext *cx, const js::Value &v, js::Value *vp); - inline JSObject *getThrowTypeError() const; - bool swap(JSContext *cx, JSObject *other); inline void initArrayClass(); From 936ba7d3bb15d0174411cf74e4f3291cb4a41e30 Mon Sep 17 00:00:00 2001 From: Cameron McCormack Date: Fri, 17 Feb 2012 14:47:39 +1100 Subject: [PATCH 93/93] Bug 674370 - Make browser windows (and other document-like windows) zoom on creation on OS X 10.7. r=mstange,dao sr=bzbarsky --- browser/base/content/browser.xul | 1 + .../sessionstore/src/nsSessionStore.js | 2 +- browser/devtools/scratchpad/scratchpad.xul | 1 + .../webBrowser/nsIWebBrowserChrome.idl | 54 ++++++++++--------- .../windowwatcher/src/nsWindowWatcher.cpp | 3 ++ widget/cocoa/nsCocoaWindow.h | 20 +++++++ widget/cocoa/nsCocoaWindow.mm | 29 ++++++++++ widget/nsIWidget.h | 14 +++++ widget/nsWidgetInitData.h | 5 +- widget/xpwidgets/nsBaseWidget.h | 1 + xpfe/appshell/src/nsAppShellService.cpp | 3 ++ xpfe/appshell/src/nsXULWindow.cpp | 6 +++ 12 files changed, 112 insertions(+), 27 deletions(-) diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul index 64c99679b3f4..3ac55cb125d3 100644 --- a/browser/base/content/browser.xul +++ b/browser/base/content/browser.xul @@ -90,6 +90,7 @@ lightweightthemes="true" lightweightthemesfooter="browser-bottombox" windowtype="navigator:browser" + macanimationtype="document" screenX="4" screenY="4" browsingmode="normal" persist="screenX screenY width height sizemode"> diff --git a/browser/components/sessionstore/src/nsSessionStore.js b/browser/components/sessionstore/src/nsSessionStore.js index 9a5a3bdab590..f7599b75b533 100644 --- a/browser/components/sessionstore/src/nsSessionStore.js +++ b/browser/components/sessionstore/src/nsSessionStore.js @@ -3816,7 +3816,7 @@ SessionStoreService.prototype = { argString.data = ""; // Build feature string - let features = "chrome,dialog=no,all"; + let features = "chrome,dialog=no,macsuppressanimation,all"; let winState = aState.windows[0]; WINDOW_ATTRIBUTES.forEach(function(aFeature) { // Use !isNaN as an easy way to ignore sizemode and check for numbers diff --git a/browser/devtools/scratchpad/scratchpad.xul b/browser/devtools/scratchpad/scratchpad.xul index c8a4c7e3f7bd..eb3c17b08c21 100644 --- a/browser/devtools/scratchpad/scratchpad.xul +++ b/browser/devtools/scratchpad/scratchpad.xul @@ -51,6 +51,7 @@ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" title="&window.title;" windowtype="devtools:scratchpad" + macanimationtype="document" screenX="4" screenY="4" width="640" height="480" persist="screenX screenY width height sizemode"> diff --git a/embedding/browser/webBrowser/nsIWebBrowserChrome.idl b/embedding/browser/webBrowser/nsIWebBrowserChrome.idl index ffef485bec74..58b03015c509 100644 --- a/embedding/browser/webBrowser/nsIWebBrowserChrome.idl +++ b/embedding/browser/webBrowser/nsIWebBrowserChrome.idl @@ -47,7 +47,7 @@ interface nsIDocShellTreeItem; * containing an embedded Gecko web browser. */ -[scriptable, uuid(BA434C60-9D52-11d3-AFB0-00A024FFC08C)] +[scriptable, uuid(E8C414C4-DC38-4BA3-AB4E-EC4CBBE22907)] interface nsIWebBrowserChrome : nsISupports { const unsigned long STATUS_SCRIPT = 0x00000001; @@ -75,43 +75,47 @@ interface nsIWebBrowserChrome : nsISupports /** * Definitions for the chrome flags */ - const unsigned long CHROME_DEFAULT = 0x00000001; - const unsigned long CHROME_WINDOW_BORDERS = 0x00000002; - const unsigned long CHROME_WINDOW_CLOSE = 0x00000004; - const unsigned long CHROME_WINDOW_RESIZE = 0x00000008; - const unsigned long CHROME_MENUBAR = 0x00000010; - const unsigned long CHROME_TOOLBAR = 0x00000020; - const unsigned long CHROME_LOCATIONBAR = 0x00000040; - const unsigned long CHROME_STATUSBAR = 0x00000080; - const unsigned long CHROME_PERSONAL_TOOLBAR = 0x00000100; - const unsigned long CHROME_SCROLLBARS = 0x00000200; - const unsigned long CHROME_TITLEBAR = 0x00000400; - const unsigned long CHROME_EXTRA = 0x00000800; + const unsigned long CHROME_DEFAULT = 0x00000001; + const unsigned long CHROME_WINDOW_BORDERS = 0x00000002; + const unsigned long CHROME_WINDOW_CLOSE = 0x00000004; + const unsigned long CHROME_WINDOW_RESIZE = 0x00000008; + const unsigned long CHROME_MENUBAR = 0x00000010; + const unsigned long CHROME_TOOLBAR = 0x00000020; + const unsigned long CHROME_LOCATIONBAR = 0x00000040; + const unsigned long CHROME_STATUSBAR = 0x00000080; + const unsigned long CHROME_PERSONAL_TOOLBAR = 0x00000100; + const unsigned long CHROME_SCROLLBARS = 0x00000200; + const unsigned long CHROME_TITLEBAR = 0x00000400; + const unsigned long CHROME_EXTRA = 0x00000800; // createBrowserWindow specific flags - const unsigned long CHROME_WITH_SIZE = 0x00001000; - const unsigned long CHROME_WITH_POSITION = 0x00002000; + const unsigned long CHROME_WITH_SIZE = 0x00001000; + const unsigned long CHROME_WITH_POSITION = 0x00002000; // special cases - const unsigned long CHROME_WINDOW_MIN = 0x00004000; - const unsigned long CHROME_WINDOW_POPUP = 0x00008000; + const unsigned long CHROME_WINDOW_MIN = 0x00004000; + const unsigned long CHROME_WINDOW_POPUP = 0x00008000; - const unsigned long CHROME_WINDOW_RAISED = 0x02000000; - const unsigned long CHROME_WINDOW_LOWERED = 0x04000000; - const unsigned long CHROME_CENTER_SCREEN = 0x08000000; + // Prevents new window animations on Mac OS X Lion. Ignored on other + // platforms. + const unsigned long CHROME_MAC_SUPPRESS_ANIMATION = 0x01000000; + + const unsigned long CHROME_WINDOW_RAISED = 0x02000000; + const unsigned long CHROME_WINDOW_LOWERED = 0x04000000; + const unsigned long CHROME_CENTER_SCREEN = 0x08000000; // Make the new window dependent on the parent. This flag is only // meaningful if CHROME_OPENAS_CHROME is set; content windows should not be // dependent. - const unsigned long CHROME_DEPENDENT = 0x10000000; + const unsigned long CHROME_DEPENDENT = 0x10000000; // Note: The modal style bit just affects the way the window looks and does // mean it's actually modal. - const unsigned long CHROME_MODAL = 0x20000000; - const unsigned long CHROME_OPENAS_DIALOG = 0x40000000; - const unsigned long CHROME_OPENAS_CHROME = 0x80000000; + const unsigned long CHROME_MODAL = 0x20000000; + const unsigned long CHROME_OPENAS_DIALOG = 0x40000000; + const unsigned long CHROME_OPENAS_CHROME = 0x80000000; - const unsigned long CHROME_ALL = 0x00000ffe; + const unsigned long CHROME_ALL = 0x00000ffe; /** * The chrome flags for this browser chrome. The implementation should diff --git a/embedding/components/windowwatcher/src/nsWindowWatcher.cpp b/embedding/components/windowwatcher/src/nsWindowWatcher.cpp index 947681086c89..1ac0bc55c43b 100644 --- a/embedding/components/windowwatcher/src/nsWindowWatcher.cpp +++ b/embedding/components/windowwatcher/src/nsWindowWatcher.cpp @@ -1527,6 +1527,9 @@ PRUint32 nsWindowWatcher::CalculateChromeFlags(const char *aFeatures, else if (WinHasOption(aFeatures, "alwaysRaised", 0, nsnull)) chromeFlags |= nsIWebBrowserChrome::CHROME_WINDOW_RAISED; + chromeFlags |= WinHasOption(aFeatures, "macsuppressanimation", 0, nsnull) ? + nsIWebBrowserChrome::CHROME_MAC_SUPPRESS_ANIMATION : 0; + chromeFlags |= WinHasOption(aFeatures, "chrome", 0, nsnull) ? nsIWebBrowserChrome::CHROME_OPENAS_CHROME : 0; chromeFlags |= WinHasOption(aFeatures, "extrachrome", 0, nsnull) ? diff --git a/widget/cocoa/nsCocoaWindow.h b/widget/cocoa/nsCocoaWindow.h index b114319611aa..f01aebe26973 100644 --- a/widget/cocoa/nsCocoaWindow.h +++ b/widget/cocoa/nsCocoaWindow.h @@ -197,6 +197,21 @@ typedef struct _nsCocoaWindowList { - (void)setDrawsContentsIntoWindowFrame:(BOOL)aState; @end +#if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7) +enum { + NSWindowAnimationBehaviorDefault = 0, + NSWindowAnimationBehaviorNone = 2, + NSWindowAnimationBehaviorDocumentWindow = 3, + NSWindowAnimationBehaviorUtilityWindow = 4, + NSWindowAnimationBehaviorAlertPanel = 5 +}; +typedef NSInteger NSWindowAnimationBehavior; + +@interface NSWindow (LionWindowFeatures) +- (void)setAnimationBehavior:(NSWindowAnimationBehavior)newAnimationBehavior; +@end +#endif + class nsCocoaWindow : public nsBaseWidget, public nsPIWidgetCocoa { private: @@ -266,6 +281,7 @@ public: virtual void SetTransparencyMode(nsTransparencyMode aMode); NS_IMETHOD SetWindowShadowStyle(PRInt32 aStyle); virtual void SetShowsToolbarButton(bool aShow); + virtual void SetWindowAnimationType(WindowAnimationType aType); NS_IMETHOD SetWindowTitlebarColor(nscolor aColor, bool aActive); virtual void SetDrawsInTitlebar(bool aState); virtual nsresult SynthesizeNativeMouseEvent(nsIntPoint aPoint, @@ -335,12 +351,16 @@ protected: PRInt32 mShadowStyle; NSUInteger mWindowFilter; + WindowAnimationType mAnimationType; + bool mWindowMadeHere; // true if we created the window, false for embedding bool mSheetNeedsShow; // if this is a sheet, are we waiting to be shown? // this is used for sibling sheet contention only bool mFullScreen; bool mModal; + bool mIsAnimationSuppressed; + bool mInReportMoveEvent; // true if in a call to ReportMoveEvent(). PRInt32 mNumModalDescendents; diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm index c4c5b5984482..7175679bc08a 100644 --- a/widget/cocoa/nsCocoaWindow.mm +++ b/widget/cocoa/nsCocoaWindow.mm @@ -135,10 +135,12 @@ nsCocoaWindow::nsCocoaWindow() , mPopupContentView(nil) , mShadowStyle(NS_STYLE_WINDOW_SHADOW_DEFAULT) , mWindowFilter(0) +, mAnimationType(nsIWidget::eGenericWindowAnimation) , mWindowMadeHere(false) , mSheetNeedsShow(false) , mFullScreen(false) , mModal(false) +, mIsAnimationSuppressed(false) , mInReportMoveEvent(false) , mNumModalDescendents(0) { @@ -304,6 +306,8 @@ nsresult nsCocoaWindow::Create(nsIWidget *aParent, return CreatePopupContentView(newBounds, aHandleEventFunction, aContext); } + mIsAnimationSuppressed = aInitData->mIsAnimationSuppressed; + return NS_OK; NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; @@ -745,6 +749,26 @@ NS_IMETHODIMP nsCocoaWindow::Show(bool bState) } else { NS_OBJC_BEGIN_TRY_LOGONLY_BLOCK; + if (mWindowType == eWindowType_toplevel && + [mWindow respondsToSelector:@selector(setAnimationBehavior:)]) { + NSWindowAnimationBehavior behavior; + if (mIsAnimationSuppressed) { + behavior = NSWindowAnimationBehaviorNone; + } else { + switch (mAnimationType) { + case nsIWidget::eDocumentWindowAnimation: + behavior = NSWindowAnimationBehaviorDocumentWindow; + break; + default: + NS_NOTREACHED("unexpected mAnimationType value"); + // fall through + case nsIWidget::eGenericWindowAnimation: + behavior = NSWindowAnimationBehaviorDefault; + break; + } + } + [mWindow setAnimationBehavior:behavior]; + } [mWindow makeKeyAndOrderFront:nil]; NS_OBJC_END_TRY_LOGONLY_BLOCK; SendSetZLevelEvent(); @@ -1618,6 +1642,11 @@ void nsCocoaWindow::SetShowsToolbarButton(bool aShow) NS_OBJC_END_TRY_ABORT_BLOCK; } +void nsCocoaWindow::SetWindowAnimationType(nsIWidget::WindowAnimationType aType) +{ + mAnimationType = aType; +} + NS_IMETHODIMP nsCocoaWindow::SetWindowTitlebarColor(nscolor aColor, bool aActive) { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h index eb5e28795816..0f17dfc32b9f 100644 --- a/widget/nsIWidget.h +++ b/widget/nsIWidget.h @@ -1017,6 +1017,20 @@ class nsIWidget : public nsISupports { */ virtual void SetShowsToolbarButton(bool aShow) = 0; + enum WindowAnimationType { + eGenericWindowAnimation, + eDocumentWindowAnimation + }; + + /** + * Sets the kind of top-level window animation this widget should have. On + * Mac OS X, this causes a particular kind of animation to be shown when the + * window is first made visible. + * + * Ignored on child widgets and on non-Mac platforms. + */ + virtual void SetWindowAnimationType(WindowAnimationType aType) = 0; + /** * Hide window chrome (borders, buttons) for this widget. * diff --git a/widget/nsWidgetInitData.h b/widget/nsWidgetInitData.h index 34ffae230719..71c76828650b 100644 --- a/widget/nsWidgetInitData.h +++ b/widget/nsWidgetInitData.h @@ -133,7 +133,8 @@ struct nsWidgetInitData { mUnicode(true), mRTL(false), mNoAutoHide(false), - mIsDragPopup(false) + mIsDragPopup(false), + mIsAnimationSuppressed(false) { } @@ -148,6 +149,8 @@ struct nsWidgetInitData { bool mRTL; bool mNoAutoHide; // true for noautohide panels bool mIsDragPopup; // true for drag feedback panels + bool mIsAnimationSuppressed; // true if window creation animation is + // suppressed, e.g. for session restore }; #endif // nsWidgetInitData_h__ diff --git a/widget/xpwidgets/nsBaseWidget.h b/widget/xpwidgets/nsBaseWidget.h index 4f9647134d7b..9e48cd2122ea 100644 --- a/widget/xpwidgets/nsBaseWidget.h +++ b/widget/xpwidgets/nsBaseWidget.h @@ -123,6 +123,7 @@ public: virtual void GetWindowClipRegion(nsTArray* aRects); NS_IMETHOD SetWindowShadowStyle(PRInt32 aStyle); virtual void SetShowsToolbarButton(bool aShow) {} + virtual void SetWindowAnimationType(WindowAnimationType aType) {} NS_IMETHOD HideWindowChrome(bool aShouldHide); NS_IMETHOD MakeFullScreen(bool aFullScreen); virtual nsDeviceContext* GetDeviceContext(); diff --git a/xpfe/appshell/src/nsAppShellService.cpp b/xpfe/appshell/src/nsAppShellService.cpp index 92e5cacaedb5..bb91c183a48d 100644 --- a/xpfe/appshell/src/nsAppShellService.cpp +++ b/xpfe/appshell/src/nsAppShellService.cpp @@ -308,6 +308,9 @@ nsAppShellService::JustCreateTopWindow(nsIXULWindow *aParent, if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_POPUP) widgetInitData.mWindowType = eWindowType_popup; + if (aChromeMask & nsIWebBrowserChrome::CHROME_MAC_SUPPRESS_ANIMATION) + widgetInitData.mIsAnimationSuppressed = true; + #ifdef XP_MACOSX // Mac OS X sheet support // Adding CHROME_OPENAS_CHROME to sheetMask makes modal windows opened from diff --git a/xpfe/appshell/src/nsXULWindow.cpp b/xpfe/appshell/src/nsXULWindow.cpp index c72964f9d936..d9701a926901 100644 --- a/xpfe/appshell/src/nsXULWindow.cpp +++ b/xpfe/appshell/src/nsXULWindow.cpp @@ -1412,6 +1412,12 @@ void nsXULWindow::SyncAttributesToWidget() if (NS_SUCCEEDED(rv)) { mWindow->SetShowsToolbarButton(attr.LowerCaseEqualsLiteral("true")); } + + // "macanimationtype" attribute + rv = windowElement->GetAttribute(NS_LITERAL_STRING("macanimationtype"), attr); + if (NS_SUCCEEDED(rv) && attr.EqualsLiteral("document")) { + mWindow->SetWindowAnimationType(nsIWidget::eDocumentWindowAnimation); + } } NS_IMETHODIMP nsXULWindow::SavePersistentAttributes()