From 54c06b9f848ccedb54632d4a13e04ee37a030c0d Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Tue, 13 Mar 2012 08:15:43 -0700 Subject: [PATCH 01/57] Bug 734211 - Part 1: extract account creation and querying into SyncAccounts class. r=liuche --- .../android/base/sync/setup/SyncAccounts.java | 106 ++++++++++++++++++ .../setup/activities/AccountActivity.java | 85 ++------------ .../setup/activities/SetupSyncActivity.java | 3 +- mobile/android/sync/java-sources.mn | 2 +- 4 files changed, 116 insertions(+), 80 deletions(-) create mode 100644 mobile/android/base/sync/setup/SyncAccounts.java diff --git a/mobile/android/base/sync/setup/SyncAccounts.java b/mobile/android/base/sync/setup/SyncAccounts.java new file mode 100644 index 000000000000..b4ad9f684709 --- /dev/null +++ b/mobile/android/base/sync/setup/SyncAccounts.java @@ -0,0 +1,106 @@ +/* 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.setup; + +import org.mozilla.gecko.db.BrowserContract; +import org.mozilla.gecko.sync.Logger; +import org.mozilla.gecko.sync.Utils; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.os.AsyncTask; +import android.os.Bundle; +import android.util.Log; + +public class SyncAccounts { + + private final static String DEFAULT_SERVER = "https://auth.services.mozilla.com/"; + private static final String LOG_TAG = "SyncAccounts"; + + /** + * This class provides background-thread abstracted access to whether a + * Firefox Sync account has been set up on this device. + * + * Subclass this task and override `onPostExecute` to act on the result. + */ + public static class AccountsExistTask extends AsyncTask { + @Override + protected Boolean doInBackground(Context... params) { + Context c = params[0]; + return AccountManager.get(c).getAccountsByType("org.mozilla.firefox_sync").length > 0; + } + } + + // TODO: lift this out. + public static Intent createAccount(Context context, + AccountManager accountManager, + String username, + String syncKey, + String password, + String serverURL) { + + final Account account = new Account(username, Constants.ACCOUNTTYPE_SYNC); + final Bundle userbundle = new Bundle(); + + // Add sync key and server URL. + userbundle.putString(Constants.OPTION_SYNCKEY, syncKey); + if (serverURL != null) { + Logger.info(LOG_TAG, "Setting explicit server URL: " + serverURL); + userbundle.putString(Constants.OPTION_SERVER, serverURL); + } else { + userbundle.putString(Constants.OPTION_SERVER, DEFAULT_SERVER); + } + Logger.debug(LOG_TAG, "Adding account for " + Constants.ACCOUNTTYPE_SYNC); + boolean result = false; + try { + result = accountManager.addAccountExplicitly(account, password, userbundle); + } catch (SecurityException e) { + final String message = e.getMessage(); + if (message != null && (message.indexOf("is different than the authenticator's uid") > 0)) { + Log.wtf("FirefoxSync", + "Unable to create account. " + + "If you have more than one version of " + + "Firefox/Beta/Aurora/Nightly/Fennec installed, that's why.", + e); + } else { + Log.e("FirefoxSync", "Unable to create account.", e); + } + } + + Logger.debug(LOG_TAG, "Account: " + account + " added successfully? " + result); + if (!result) { + Logger.error(LOG_TAG, "Failed to add account!"); + } + + // Set components to sync (default: all). + ContentResolver.setMasterSyncAutomatically(true); + + String authority = BrowserContract.AUTHORITY; + Logger.debug(LOG_TAG, "Setting authority " + authority + " to sync automatically."); + ContentResolver.setSyncAutomatically(account, authority, true); + ContentResolver.setIsSyncable(account, 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 + Logger.debug(LOG_TAG, "Finished setting syncables."); + + // TODO: correctly implement Sync Options. + Logger.info(LOG_TAG, "Clearing preferences for this account."); + try { + Utils.getSharedPreferences(context, username, serverURL).edit().clear().commit(); + } catch (Exception e) { + Logger.error(LOG_TAG, "Could not clear prefs path!", e); + } + + final Intent intent = new Intent(); + intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, username); + intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNTTYPE_SYNC); + intent.putExtra(AccountManager.KEY_AUTHTOKEN, Constants.ACCOUNTTYPE_SYNC); + return intent; + } +} diff --git a/mobile/android/base/sync/setup/activities/AccountActivity.java b/mobile/android/base/sync/setup/activities/AccountActivity.java index 9809683095e4..88543a992cfb 100644 --- a/mobile/android/base/sync/setup/activities/AccountActivity.java +++ b/mobile/android/base/sync/setup/activities/AccountActivity.java @@ -7,14 +7,11 @@ package org.mozilla.gecko.sync.setup.activities; import java.util.Locale; import org.mozilla.gecko.R; -import org.mozilla.gecko.db.BrowserContract; -import org.mozilla.gecko.sync.Utils; import org.mozilla.gecko.sync.setup.Constants; +import org.mozilla.gecko.sync.setup.SyncAccounts; -import android.accounts.Account; import android.accounts.AccountAuthenticatorActivity; import android.accounts.AccountManager; -import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.os.Bundle; @@ -31,8 +28,6 @@ import android.widget.EditText; public class AccountActivity extends AccountAuthenticatorActivity { private final static String LOG_TAG = "AccountActivity"; - private final static String DEFAULT_SERVER = "https://auth.services.mozilla.com/"; - private AccountManager mAccountManager; private Context mContext; private String username; @@ -156,9 +151,11 @@ public class AccountActivity extends AccountAuthenticatorActivity { } private boolean validateInputs() { - if (usernameInput.length() == 0 || passwordInput.length() == 0 - || synckeyInput.length() == 0 - || (serverCheckbox.isChecked() && serverInput.length() == 0)) { + if (usernameInput.length() == 0 || + passwordInput.length() == 0 || + synckeyInput.length() == 0 || + (serverCheckbox.isChecked() && + serverInput.length() == 0)) { return false; } return true; @@ -171,7 +168,7 @@ public class AccountActivity extends AccountAuthenticatorActivity { // Create and add account to AccountManager // TODO: only allow one account to be added? Log.d(LOG_TAG, "Using account manager " + mAccountManager); - final Intent intent = createAccount(mContext, mAccountManager, + final Intent intent = SyncAccounts.createAccount(mContext, mAccountManager, username, key, password, server); setAccountAuthenticatorResult(intent.getExtras()); @@ -193,74 +190,6 @@ public class AccountActivity extends AccountAuthenticatorActivity { }); } - // TODO: lift this out. - public static Intent createAccount(Context context, - AccountManager accountManager, - String username, - String syncKey, - String password, - String serverURL) { - - final Account account = new Account(username, Constants.ACCOUNTTYPE_SYNC); - final Bundle userbundle = new Bundle(); - - // Add sync key and server URL. - userbundle.putString(Constants.OPTION_SYNCKEY, syncKey); - if (serverURL != null) { - Log.i(LOG_TAG, "Setting explicit server URL: " + serverURL); - userbundle.putString(Constants.OPTION_SERVER, serverURL); - } else { - userbundle.putString(Constants.OPTION_SERVER, DEFAULT_SERVER); - } - Log.d(LOG_TAG, "Adding account for " + Constants.ACCOUNTTYPE_SYNC); - boolean result = false; - try { - result = accountManager.addAccountExplicitly(account, password, userbundle); - } catch (SecurityException e) { - final String message = e.getMessage(); - if (message != null && (message.indexOf("is different than the authenticator's uid") > 0)) { - Log.wtf("FirefoxSync", - "Unable to create account. " + - "If you have more than one version of " + - "Firefox/Beta/Aurora/Nightly/Fennec installed, that's why.", - e); - } else { - Log.e("FirefoxSync", "Unable to create account.", e); - } - } - - Log.d(LOG_TAG, "Account: " + account + " added successfully? " + result); - if (!result) { - Log.e(LOG_TAG, "Failed to add account!"); - } - - // Set components to sync (default: all). - ContentResolver.setMasterSyncAutomatically(true); - - String authority = BrowserContract.AUTHORITY; - Log.d(LOG_TAG, "Setting authority " + authority + " to sync automatically."); - ContentResolver.setSyncAutomatically(account, authority, true); - ContentResolver.setIsSyncable(account, 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 - Log.d(LOG_TAG, "Finished setting syncables."); - - // TODO: correctly implement Sync Options. - Log.i(LOG_TAG, "Clearing preferences for this account."); - try { - Utils.getSharedPreferences(context, username, serverURL).edit().clear().commit(); - } catch (Exception e) { - Log.e(LOG_TAG, "Could not clear prefs path!", e); - } - - final Intent intent = new Intent(); - intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, username); - intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNTTYPE_SYNC); - intent.putExtra(AccountManager.KEY_AUTHTOKEN, Constants.ACCOUNTTYPE_SYNC); - return intent; - } - @SuppressWarnings("unused") private void authFailure() { enableCredEntry(true); diff --git a/mobile/android/base/sync/setup/activities/SetupSyncActivity.java b/mobile/android/base/sync/setup/activities/SetupSyncActivity.java index bac2175c7d16..3745455ad107 100644 --- a/mobile/android/base/sync/setup/activities/SetupSyncActivity.java +++ b/mobile/android/base/sync/setup/activities/SetupSyncActivity.java @@ -13,6 +13,7 @@ import org.mozilla.gecko.sync.ThreadPool; import org.mozilla.gecko.sync.jpake.JPakeClient; import org.mozilla.gecko.sync.jpake.JPakeNoActivePairingException; import org.mozilla.gecko.sync.setup.Constants; +import org.mozilla.gecko.sync.setup.SyncAccounts; import android.accounts.Account; import android.accounts.AccountAuthenticatorActivity; @@ -362,7 +363,7 @@ public class SetupSyncActivity extends AccountAuthenticatorActivity { String serverURL = (String) jCreds.get(Constants.JSON_KEY_SERVER); Logger.debug(LOG_TAG, "Using account manager " + mAccountManager); - final Intent intent = AccountActivity.createAccount(mContext, mAccountManager, + final Intent intent = SyncAccounts.createAccount(mContext, mAccountManager, accountName, syncKey, password, serverURL); setAccountAuthenticatorResult(intent.getExtras()); diff --git a/mobile/android/sync/java-sources.mn b/mobile/android/sync/java-sources.mn index f4c2e943b26f..95b0ad3737ea 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/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/ClientsDataDelegate.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/JPakeJson.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/stage/CompleteStage.java sync/jpake/stage/ComputeFinalStage.java sync/jpake/stage/ComputeKeyVerificationStage.java sync/jpake/stage/ComputeStepOneStage.java sync/jpake/stage/ComputeStepTwoStage.java sync/jpake/stage/DecryptDataStage.java sync/jpake/stage/GetChannelStage.java sync/jpake/stage/GetRequestStage.java sync/jpake/stage/JPakeStage.java sync/jpake/stage/PutRequestStage.java sync/jpake/stage/VerifyPairingStage.java sync/jpake/Zkp.java sync/KeyBundleProvider.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/middleware/MiddlewareRepositorySession.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/net/WBORequestDelegate.java sync/NoCollectionKeysSetException.java sync/NodeAuthenticationException.java sync/NonArrayJSONException.java sync/NonObjectJSONException.java sync/NullClusterURLException.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/BrowserContractHelpers.java sync/repositories/android/CachedSQLiteOpenHelper.java sync/repositories/android/ClientsDatabase.java sync/repositories/android/ClientsDatabaseAccessor.java sync/repositories/android/FennecTabsRepository.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/ClientRecord.java sync/repositories/domain/ClientRecordFactory.java sync/repositories/domain/HistoryRecord.java sync/repositories/domain/HistoryRecordFactory.java sync/repositories/domain/PasswordRecord.java sync/repositories/domain/Record.java sync/repositories/domain/TabsRecord.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/NoContentProviderException.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/FennecTabsServerSyncStage.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/stage/SyncClientsEngineStage.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/ClientsDataDelegate.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/JPakeJson.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/stage/CompleteStage.java sync/jpake/stage/ComputeFinalStage.java sync/jpake/stage/ComputeKeyVerificationStage.java sync/jpake/stage/ComputeStepOneStage.java sync/jpake/stage/ComputeStepTwoStage.java sync/jpake/stage/DecryptDataStage.java sync/jpake/stage/GetChannelStage.java sync/jpake/stage/GetRequestStage.java sync/jpake/stage/JPakeStage.java sync/jpake/stage/PutRequestStage.java sync/jpake/stage/VerifyPairingStage.java sync/jpake/Zkp.java sync/KeyBundleProvider.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/middleware/MiddlewareRepositorySession.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/net/WBORequestDelegate.java sync/NoCollectionKeysSetException.java sync/NodeAuthenticationException.java sync/NonArrayJSONException.java sync/NonObjectJSONException.java sync/NullClusterURLException.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/BrowserContractHelpers.java sync/repositories/android/CachedSQLiteOpenHelper.java sync/repositories/android/ClientsDatabase.java sync/repositories/android/ClientsDatabaseAccessor.java sync/repositories/android/FennecTabsRepository.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/ClientRecord.java sync/repositories/domain/ClientRecordFactory.java sync/repositories/domain/HistoryRecord.java sync/repositories/domain/HistoryRecordFactory.java sync/repositories/domain/PasswordRecord.java sync/repositories/domain/Record.java sync/repositories/domain/TabsRecord.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/NoContentProviderException.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/SyncAccounts.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/FennecTabsServerSyncStage.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/stage/SyncClientsEngineStage.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 190a53db88233548544908e2b94398116eb450e6 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Tue, 13 Mar 2012 08:15:43 -0700 Subject: [PATCH 02/57] Bug 735137 - Strict mode violation in TabsTray.onCreate. r=mfinkle --- mobile/android/base/TabsTray.java | 70 ++++++++++--------------------- 1 file changed, 22 insertions(+), 48 deletions(-) diff --git a/mobile/android/base/TabsTray.java b/mobile/android/base/TabsTray.java index a2ff0ef91c8b..170bbe28ca5a 100644 --- a/mobile/android/base/TabsTray.java +++ b/mobile/android/base/TabsTray.java @@ -1,39 +1,7 @@ /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Android code. - * - * The Initial Developer of the Original Code is Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Sriram Ramasubramanian - * - * 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 ***** */ +/* 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; @@ -60,6 +28,8 @@ import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.TextView; +import org.mozilla.gecko.sync.setup.SyncAccounts; + public class TabsTray extends Activity implements Tabs.OnTabsChangedListener { private static int sPreferredHeight; @@ -122,19 +92,23 @@ public class TabsTray extends Activity implements Tabs.OnTabsChangedListener { tabs.refreshThumbnails(); onTabChanged(null, null); - // If sync is set up, query the database for remote clients - // Cleanup after Bug: 734211 is fixed - if (AccountManager.get(getApplicationContext()).getAccountsByType("org.mozilla.firefox_sync").length > 0) { - TabsAccessor.areClientsAvailable(getApplicationContext(), new TabsAccessor.OnClientsAvailableListener() { - @Override - public void areAvailable(boolean available) { - if (available) - mRemoteTabs.setVisibility(View.VISIBLE); - else - mRemoteTabs.setVisibility(View.GONE); - } - }); - } + // If Sync is set up, query the database for remote clients. + final Context context = getApplicationContext(); + new SyncAccounts.AccountsExistTask() { + @Override + protected void onPostExecute(Boolean result) { + if (!result.booleanValue()) { + return; + } + TabsAccessor.areClientsAvailable(context, new TabsAccessor.OnClientsAvailableListener() { + @Override + public void areAvailable(boolean available) { + final int visibility = available ? View.VISIBLE : View.GONE; + mRemoteTabs.setVisibility(visibility); + } + }); + } + }.execute(context); } @Override From 27617c9d229205fa3675dc4ff5261c5de5d16431 Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Tue, 13 Mar 2012 08:37:52 -0700 Subject: [PATCH 03/57] Disable regexp cloning optimization for global/sticky regexps, bug 728021. r=dmandelin --- js/src/methodjit/Compiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index aff5cc39773d..0305d27f27c7 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -6931,7 +6931,7 @@ mjit::Compiler::jsop_regexp() */ analyze::SSAUseChain *uses = analysis->useChain(analyze::SSAValue::PushedValue(PC - script->code, 0)); - if (uses && uses->popped && !uses->next) { + if (uses && uses->popped && !uses->next && !reobj->global() && !reobj->sticky()) { jsbytecode *use = script->code + uses->offset; uint32_t which = uses->u.which; if (JSOp(*use) == JSOP_CALLPROP) { From 9296772596c0fd2c8d5813956535b48e6b2ae802 Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Tue, 13 Mar 2012 12:06:21 -0400 Subject: [PATCH 04/57] Bug 421242 - allow relations in anonymous content for binding parent, r=bsaunde, f=smaug --- accessible/src/base/AccIterator.cpp | 90 +++++++++------ accessible/src/base/AccIterator.h | 5 +- accessible/tests/mochitest/relations.js | 2 +- .../tests/mochitest/relations/Makefile.in | 1 + .../mochitest/relations/test_bindings.xhtml | 103 ++++++++++++++++++ 5 files changed, 163 insertions(+), 38 deletions(-) create mode 100644 accessible/tests/mochitest/relations/test_bindings.xhtml diff --git a/accessible/src/base/AccIterator.cpp b/accessible/src/base/AccIterator.cpp index 85e3e4d4400d..58c4de6af7b1 100644 --- a/accessible/src/base/AccIterator.cpp +++ b/accessible/src/base/AccIterator.cpp @@ -41,6 +41,9 @@ #include "nsAccessible.h" #include "mozilla/dom/Element.h" +#include "nsBindingManager.h" + +using namespace mozilla; //////////////////////////////////////////////////////////////////////////////// // AccIterator @@ -129,17 +132,21 @@ RelatedAccIterator::Next() // Return related accessible for the given attribute and if the provider // content is in the same binding in the case of XBL usage. - if (provider->mRelAttr == mRelAttr && - (!mBindingParent || - mBindingParent == provider->mContent->GetBindingParent())) { - nsAccessible* related = mDocument->GetAccessible(provider->mContent); - if (related) - return related; + if (provider->mRelAttr == mRelAttr) { + nsIContent* bindingParent = provider->mContent->GetBindingParent(); + bool inScope = mBindingParent == bindingParent || + mBindingParent == provider->mContent; - // If the document content is pointed by relation then return the document - // itself. - if (provider->mContent == mDocument->GetContent()) - return mDocument; + if (inScope) { + nsAccessible* related = mDocument->GetAccessible(provider->mContent); + if (related) + return related; + + // If the document content is pointed by relation then return the document + // itself. + if (provider->mContent == mDocument->GetContent()) + return mDocument; + } } } @@ -271,18 +278,10 @@ XULDescriptionIterator::Next() //////////////////////////////////////////////////////////////////////////////// IDRefsIterator::IDRefsIterator(nsIContent* aContent, nsIAtom* aIDRefsAttr) : - mCurrIdx(0) + mCurrIdx(0), mContent(aContent) { - if (!aContent->IsInDoc() || - !aContent->GetAttr(kNameSpaceID_None, aIDRefsAttr, mIDs)) - return; - - if (aContent->IsInAnonymousSubtree()) { - mXBLDocument = do_QueryInterface(aContent->OwnerDoc()); - mBindingParent = do_QueryInterface(aContent->GetBindingParent()); - } else { - mDocument = aContent->OwnerDoc(); - } + if (mContent->IsInDoc()) + mContent->GetAttr(kNameSpaceID_None, aIDRefsAttr, mIDs); } const nsDependentSubstring @@ -324,20 +323,45 @@ IDRefsIterator::NextElem() nsIContent* IDRefsIterator::GetElem(const nsDependentSubstring& aID) { - if (mXBLDocument) { - // If content is anonymous subtree then use "anonid" attribute to get - // elements, otherwise search elements in DOM by ID attribute. - - nsCOMPtr refElm; - mXBLDocument->GetAnonymousElementByAttribute(mBindingParent, - NS_LITERAL_STRING("anonid"), - aID, - getter_AddRefs(refElm)); - nsCOMPtr refContent = do_QueryInterface(refElm); - return refContent; + // Get elements in DOM tree by ID attribute if this is an explicit content. + // In case of bound element check its anonymous subtree. + if (!mContent->IsInAnonymousSubtree()) { + dom::Element* refElm = mContent->OwnerDoc()->GetElementById(aID); + if (refElm || !mContent->OwnerDoc()->BindingManager()->GetBinding(mContent)) + return refElm; } - return mDocument->GetElementById(aID); + // If content is in anonymous subtree or an element having anonymous subtree + // then use "anonid" attribute to get elements in anonymous subtree. + nsCOMPtr refDOMElm; + nsCOMPtr xblDocument = + do_QueryInterface(mContent->OwnerDoc()); + + // Check inside the binding the element is contained in. + nsIContent* bindingParent = mContent->GetBindingParent(); + if (bindingParent) { + nsCOMPtr bindingParentElm = do_QueryInterface(bindingParent); + xblDocument->GetAnonymousElementByAttribute(bindingParentElm, + NS_LITERAL_STRING("anonid"), + aID, + getter_AddRefs(refDOMElm)); + nsCOMPtr refElm = do_QueryInterface(refDOMElm); + if (refElm) + return refElm; + } + + // Check inside the binding of the element. + if (mContent->OwnerDoc()->BindingManager()->GetBinding(mContent)) { + nsCOMPtr elm = do_QueryInterface(mContent); + xblDocument->GetAnonymousElementByAttribute(elm, + NS_LITERAL_STRING("anonid"), + aID, + getter_AddRefs(refDOMElm)); + nsCOMPtr refElm = do_QueryInterface(refDOMElm); + return refElm; + } + + return nsnull; } nsAccessible* diff --git a/accessible/src/base/AccIterator.h b/accessible/src/base/AccIterator.h index d91c4ed86960..0be6880a4dd2 100644 --- a/accessible/src/base/AccIterator.h +++ b/accessible/src/base/AccIterator.h @@ -291,11 +291,8 @@ private: IDRefsIterator operator = (const IDRefsIterator&); nsString mIDs; + nsIContent* mContent; nsAString::index_type mCurrIdx; - - nsIDocument* mDocument; - nsCOMPtr mXBLDocument; - nsCOMPtr mBindingParent; }; /** diff --git a/accessible/tests/mochitest/relations.js b/accessible/tests/mochitest/relations.js index 6fd4a0c7b410..f41fe0e218ff 100644 --- a/accessible/tests/mochitest/relations.js +++ b/accessible/tests/mochitest/relations.js @@ -78,7 +78,7 @@ function testRelation(aIdentifier, aRelType, aRelatedIdentifiers) } } - ok(isFound, relatedIds[idx] + " is not a target of" + relDescr); + ok(isFound, prettyName(relatedIds[idx]) + " is not a target of" + relDescr); } // Check if all obtained targets are given related accessibles. diff --git a/accessible/tests/mochitest/relations/Makefile.in b/accessible/tests/mochitest/relations/Makefile.in index 4a1eca4d497a..077884060a66 100644 --- a/accessible/tests/mochitest/relations/Makefile.in +++ b/accessible/tests/mochitest/relations/Makefile.in @@ -46,6 +46,7 @@ include $(DEPTH)/config/autoconf.mk include $(topsrcdir)/config/rules.mk _TEST_FILES =\ + test_bindings.xhtml \ test_embeds.xul \ test_general.html \ test_general.xul \ diff --git a/accessible/tests/mochitest/relations/test_bindings.xhtml b/accessible/tests/mochitest/relations/test_bindings.xhtml new file mode 100644 index 000000000000..65a7a08752cb --- /dev/null +++ b/accessible/tests/mochitest/relations/test_bindings.xhtml @@ -0,0 +1,103 @@ + + + + Accessible relations for bindings + + + + + + + + + + +
+
+
+
+ + + + + +
+ + + + + + + + + + + + + + Mozilla Bug 421242 + + +

+ +
+  
+
+ + +
+ + From 375ef173be02a669e722bda56350bfa3e5b2b6de Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Thu, 8 Mar 2012 22:16:25 -0800 Subject: [PATCH 05/57] Bug 733652 - Remove geolocation address handling (v2). Little adoption, costly implementation r=jdm --- dom/base/nsDOMClassInfo.cpp | 7 -- dom/base/nsDOMClassInfoClasses.h | 1 - dom/interfaces/geolocation/Makefile.in | 1 - .../geolocation/nsIDOMGeoPosition.idl | 5 +- .../geolocation/nsIDOMGeoPositionAddress.idl | 51 --------- dom/src/geolocation/nsGeoPosition.cpp | 106 +----------------- dom/src/geolocation/nsGeoPosition.h | 38 ------- .../geolocation/nsGeoPositionIPCSerialiser.h | 101 +---------------- embedding/android/GeckoEvent.java | 3 +- embedding/android/GeckoSurfaceView.java | 42 +------ mobile/android/base/GeckoApp.java | 43 +------ mobile/android/base/GeckoEvent.java | 3 +- widget/android/AndroidJavaWrappers.cpp | 76 +------------ widget/android/AndroidJavaWrappers.h | 22 ---- widget/android/nsAppShell.cpp | 6 +- 15 files changed, 11 insertions(+), 494 deletions(-) delete mode 100644 dom/interfaces/geolocation/nsIDOMGeoPositionAddress.idl diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index d672d92484c7..845f556b5815 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -1422,9 +1422,6 @@ static nsDOMClassInfoData sClassInfoData[] = { NS_DEFINE_CLASSINFO_DATA(GeoPositionCoords, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) - NS_DEFINE_CLASSINFO_DATA(GeoPositionAddress, nsDOMGenericSH, - DOM_DEFAULT_SCRIPTABLE_FLAGS) - NS_DEFINE_CLASSINFO_DATA(GeoPositionError, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) @@ -4020,10 +4017,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_ENTRY(nsIDOMGeoPositionCoords) DOM_CLASSINFO_MAP_END - DOM_CLASSINFO_MAP_BEGIN(GeoPositionAddress, nsIDOMGeoPositionAddress) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMGeoPositionAddress) - DOM_CLASSINFO_MAP_END - DOM_CLASSINFO_MAP_BEGIN(GeoPositionError, nsIDOMGeoPositionError) DOM_CLASSINFO_MAP_ENTRY(nsIDOMGeoPositionError) DOM_CLASSINFO_MAP_END diff --git a/dom/base/nsDOMClassInfoClasses.h b/dom/base/nsDOMClassInfoClasses.h index 5885454b460b..311edab11809 100644 --- a/dom/base/nsDOMClassInfoClasses.h +++ b/dom/base/nsDOMClassInfoClasses.h @@ -422,7 +422,6 @@ DOMCI_CLASS(MessageEvent) DOMCI_CLASS(GeoGeolocation) DOMCI_CLASS(GeoPosition) DOMCI_CLASS(GeoPositionCoords) -DOMCI_CLASS(GeoPositionAddress) DOMCI_CLASS(GeoPositionError) DOMCI_CLASS(MozBatteryManager) diff --git a/dom/interfaces/geolocation/Makefile.in b/dom/interfaces/geolocation/Makefile.in index 67655d343924..e775bdc5af9a 100644 --- a/dom/interfaces/geolocation/Makefile.in +++ b/dom/interfaces/geolocation/Makefile.in @@ -49,7 +49,6 @@ GRE_MODULE = 1 XPIDLSRCS = \ nsIDOMGeoGeolocation.idl \ nsIDOMGeoPosition.idl \ - nsIDOMGeoPositionAddress.idl \ nsIDOMGeoPositionCoords.idl \ nsIDOMGeoPositionCallback.idl \ nsIDOMGeoPositionError.idl \ diff --git a/dom/interfaces/geolocation/nsIDOMGeoPosition.idl b/dom/interfaces/geolocation/nsIDOMGeoPosition.idl index 6895356b8a83..ee6c19ff1c28 100644 --- a/dom/interfaces/geolocation/nsIDOMGeoPosition.idl +++ b/dom/interfaces/geolocation/nsIDOMGeoPosition.idl @@ -37,13 +37,10 @@ #include "domstubs.idl" #include "nsIDOMGeoPositionCoords.idl" -#include "nsIDOMGeoPositionAddress.idl" -[scriptable, uuid(23E5269F-4DD7-41C4-B52A-75918694C2DE)] +[scriptable, uuid(dd9f7e81-0f74-4fb5-b361-37019bf60c3f)] interface nsIDOMGeoPosition : nsISupports { readonly attribute DOMTimeStamp timestamp; readonly attribute nsIDOMGeoPositionCoords coords; - readonly attribute nsIDOMGeoPositionAddress address; - }; diff --git a/dom/interfaces/geolocation/nsIDOMGeoPositionAddress.idl b/dom/interfaces/geolocation/nsIDOMGeoPositionAddress.idl deleted file mode 100644 index 63ba4df455b2..000000000000 --- a/dom/interfaces/geolocation/nsIDOMGeoPositionAddress.idl +++ /dev/null @@ -1,51 +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 Geolocation. - * - * The Initial Developer of the Original Code is Mozilla Foundation - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Doug Turner (Original Author) - * - * 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 ***** */ - - -#include "domstubs.idl" - -[scriptable, uuid(93abae10-7024-49eb-8e05-1931343b0ebb)] -interface nsIDOMGeoPositionAddress : nsISupports -{ - readonly attribute DOMString streetNumber; - readonly attribute DOMString street; - readonly attribute DOMString premises; - readonly attribute DOMString city; - readonly attribute DOMString county; - readonly attribute DOMString region; - readonly attribute DOMString country; - readonly attribute DOMString postalCode; -}; diff --git a/dom/src/geolocation/nsGeoPosition.cpp b/dom/src/geolocation/nsGeoPosition.cpp index b750b475435f..8981ef7a8144 100644 --- a/dom/src/geolocation/nsGeoPosition.cpp +++ b/dom/src/geolocation/nsGeoPosition.cpp @@ -40,100 +40,6 @@ #include "nsGeoPosition.h" #include "nsDOMClassInfoID.h" -//////////////////////////////////////////////////// -// nsGeoPositionAddress -//////////////////////////////////////////////////// - -nsGeoPositionAddress::nsGeoPositionAddress(const nsAString &aStreetNumber, - const nsAString &aStreet, - const nsAString &aPremises, - const nsAString &aCity, - const nsAString &aCounty, - const nsAString &aRegion, - const nsAString &aCountry, - const nsAString &aPostalCode) - : mStreetNumber(aStreetNumber) - , mStreet(aStreet) - , mPremises(aPremises) - , mCity(aCity) - , mCounty(aCounty) - , mRegion(aRegion) - , mCountry(aCountry) - , mPostalCode(aPostalCode) -{ -} - -nsGeoPositionAddress::~nsGeoPositionAddress() -{ -} - -DOMCI_DATA(GeoPositionAddress, nsGeoPositionAddress) - -NS_INTERFACE_MAP_BEGIN(nsGeoPositionAddress) -NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoPositionAddress) -NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionAddress) -NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(GeoPositionAddress) -NS_INTERFACE_MAP_END - -NS_IMPL_THREADSAFE_ADDREF(nsGeoPositionAddress) -NS_IMPL_THREADSAFE_RELEASE(nsGeoPositionAddress) - -NS_IMETHODIMP -nsGeoPositionAddress::GetStreetNumber(nsAString & aStreetNumber) -{ - aStreetNumber = mStreetNumber; - return NS_OK; -} - -NS_IMETHODIMP -nsGeoPositionAddress::GetStreet(nsAString & aStreet) -{ - aStreet = mStreet; - return NS_OK; -} - -NS_IMETHODIMP -nsGeoPositionAddress::GetPremises(nsAString & aPremises) -{ - aPremises = mPremises; - return NS_OK; -} - -NS_IMETHODIMP -nsGeoPositionAddress::GetCity(nsAString & aCity) -{ - aCity = mCity; - return NS_OK; -} - -NS_IMETHODIMP -nsGeoPositionAddress::GetCounty(nsAString & aCounty) -{ - aCounty = mCounty; - return NS_OK; -} - -NS_IMETHODIMP -nsGeoPositionAddress::GetRegion(nsAString & aRegion) -{ - aRegion = mRegion; - return NS_OK; -} - -NS_IMETHODIMP -nsGeoPositionAddress::GetCountry(nsAString & aCountry) -{ - aCountry = mCountry; - return NS_OK; -} - -NS_IMETHODIMP -nsGeoPositionAddress::GetPostalCode(nsAString & aPostalCode) -{ - aPostalCode = mPostalCode; - return NS_OK; -} - //////////////////////////////////////////////////// // nsGeoPositionCoords //////////////////////////////////////////////////// @@ -239,11 +145,9 @@ nsGeoPosition::nsGeoPosition(nsIDOMGeoPositionCoords *aCoords, } nsGeoPosition::nsGeoPosition(nsIDOMGeoPositionCoords *aCoords, - nsIDOMGeoPositionAddress *aAddress, DOMTimeStamp aTimestamp) : mTimestamp(aTimestamp), - mCoords(aCoords), - mAddress(aAddress) + mCoords(aCoords) { } @@ -275,11 +179,3 @@ nsGeoPosition::GetCoords(nsIDOMGeoPositionCoords * *aCoords) NS_IF_ADDREF(*aCoords = mCoords); return NS_OK; } - -NS_IMETHODIMP -nsGeoPosition::GetAddress(nsIDOMGeoPositionAddress** aAddress) -{ - NS_IF_ADDREF(*aAddress = mAddress); - return NS_OK; -} - diff --git a/dom/src/geolocation/nsGeoPosition.h b/dom/src/geolocation/nsGeoPosition.h index c763b5becd85..a7a29770251f 100644 --- a/dom/src/geolocation/nsGeoPosition.h +++ b/dom/src/geolocation/nsGeoPosition.h @@ -43,42 +43,10 @@ #include "nsAutoPtr.h" #include "nsIClassInfo.h" #include "nsDOMClassInfoID.h" -#include "nsIDOMGeoPositionAddress.h" #include "nsIDOMGeoPositionCoords.h" #include "nsIDOMGeoPosition.h" #include "nsString.h" -//////////////////////////////////////////////////// -// nsGeoPositionAddress -//////////////////////////////////////////////////// - -class nsGeoPositionAddress : public nsIDOMGeoPositionAddress -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSIDOMGEOPOSITIONADDRESS - - nsGeoPositionAddress( const nsAString &aStreetNumber, - const nsAString &aStreet, - const nsAString &aPremises, - const nsAString &aCity, - const nsAString &aCounty, - const nsAString &aRegion, - const nsAString &aCountry, - const nsAString &aPostalCode); - - ~nsGeoPositionAddress(); - private: - const nsString mStreetNumber; - const nsString mStreet; - const nsString mPremises; - const nsString mCity; - const nsString mCounty; - const nsString mRegion; - const nsString mCountry; - const nsString mPostalCode; -}; - //////////////////////////////////////////////////// // nsGeoPositionCoords //////////////////////////////////////////////////// @@ -122,18 +90,12 @@ public: long long aTimestamp); nsGeoPosition(nsIDOMGeoPositionCoords *aCoords, - nsIDOMGeoPositionAddress *aAddress, DOMTimeStamp aTimestamp); - void SetAddress(nsIDOMGeoPositionAddress *address) { - mAddress = address; - } - private: ~nsGeoPosition(); long long mTimestamp; nsRefPtr mCoords; - nsRefPtr mAddress; }; #endif /* nsGeoPosition_h */ diff --git a/dom/src/geolocation/nsGeoPositionIPCSerialiser.h b/dom/src/geolocation/nsGeoPositionIPCSerialiser.h index f4597f8a52fd..89d0c9215148 100644 --- a/dom/src/geolocation/nsGeoPositionIPCSerialiser.h +++ b/dom/src/geolocation/nsGeoPositionIPCSerialiser.h @@ -41,98 +41,11 @@ #include "nsGeoPosition.h" #include "nsIDOMGeoPosition.h" -typedef nsIDOMGeoPositionAddress *GeoPositionAddress; typedef nsGeoPositionCoords *GeoPositionCoords; typedef nsIDOMGeoPosition *GeoPosition; namespace IPC { -template <> -struct ParamTraits -{ - typedef GeoPositionAddress paramType; - - // Function to serialize a geo position address - static void Write(Message *aMsg, const paramType& aParam) - { - bool isNull = !aParam; - WriteParam(aMsg, isNull); - // If it is null, then we are done - if (isNull) return; - - nsString addressLine; - - aParam->GetStreetNumber(addressLine); - WriteParam(aMsg, addressLine); - - aParam->GetStreet(addressLine); - WriteParam(aMsg, addressLine); - - aParam->GetPremises(addressLine); - WriteParam(aMsg, addressLine); - - aParam->GetCity(addressLine); - WriteParam(aMsg, addressLine); - - aParam->GetCounty(addressLine); - WriteParam(aMsg, addressLine); - - aParam->GetRegion(addressLine); - WriteParam(aMsg, addressLine); - - aParam->GetCountry(addressLine); - WriteParam(aMsg, addressLine); - - aParam->GetPostalCode(addressLine); - WriteParam(aMsg, addressLine); - } - - // Function to de-serialize a geoposition - static bool Read(const Message* aMsg, void **aIter, paramType* aResult) - { - // Check if it is the null pointer we have transfered - bool isNull; - if (!ReadParam(aMsg, aIter, &isNull)) return false; - - if (isNull) { - *aResult = 0; - return true; - } - - // We need somewhere to store the address before we create the object - nsString streetNumber; - nsString street; - nsString premises; - nsString city; - nsString county; - nsString region; - nsString country; - nsString postalCode; - - // It's not important to us where it fails, but rather if it fails - if (!(ReadParam(aMsg, aIter, &streetNumber) && - ReadParam(aMsg, aIter, &street ) && - ReadParam(aMsg, aIter, &premises ) && - ReadParam(aMsg, aIter, &city ) && - ReadParam(aMsg, aIter, &county ) && - ReadParam(aMsg, aIter, ®ion ) && - ReadParam(aMsg, aIter, &country ) && - ReadParam(aMsg, aIter, &postalCode ))) return false; - - // We now have all the data - *aResult = new nsGeoPositionAddress(streetNumber, /* aStreetNumber */ - street, /* aStreet */ - premises, /* aPremises */ - city, /* aCity */ - county, /* aCounty */ - region, /* aRegion */ - country, /* aCountry */ - postalCode /* aPostalCode */ - ); - return true; - } -} ; - template <> struct ParamTraits { @@ -235,11 +148,6 @@ struct ParamTraits aParam->GetCoords(getter_AddRefs(coords)); GeoPositionCoords simpleCoords = static_cast(coords.get()); WriteParam(aMsg, simpleCoords); - - nsCOMPtr address; - aParam->GetAddress(getter_AddRefs(address)); - GeoPositionAddress simpleAddress = address.get(); - WriteParam(aMsg, simpleAddress); } // Function to de-serialize a geoposition @@ -256,20 +164,17 @@ struct ParamTraits DOMTimeStamp timeStamp; GeoPositionCoords coords = nsnull; - GeoPositionAddress address; // It's not important to us where it fails, but rather if it fails if (!( ReadParam(aMsg, aIter, &timeStamp) - && ReadParam(aMsg, aIter, &coords ) - && ReadParam(aMsg, aIter, &address ))) { + && ReadParam(aMsg, aIter, &coords ))) { // note it is fine to do "delete nsnull" in case coords hasn't - // been allocated and we will never have a case where address - // gets allocated and we end here + // been allocated delete coords; return false; } - *aResult = new nsGeoPosition(coords, address, timeStamp); + *aResult = new nsGeoPosition(coords, timeStamp); return true; }; diff --git a/embedding/android/GeckoEvent.java b/embedding/android/GeckoEvent.java index c3f4e892b517..3d178baf87fa 100644 --- a/embedding/android/GeckoEvent.java +++ b/embedding/android/GeckoEvent.java @@ -252,10 +252,9 @@ public class GeckoEvent { } } - public GeckoEvent(Location l, Address a) { + public GeckoEvent(Location l) { mType = LOCATION_EVENT; mLocation = l; - mAddress = a; } public GeckoEvent(int imeAction, int offset, int count) { diff --git a/embedding/android/GeckoSurfaceView.java b/embedding/android/GeckoSurfaceView.java index 385c8d1e29ed..77649a447cf7 100644 --- a/embedding/android/GeckoSurfaceView.java +++ b/embedding/android/GeckoSurfaceView.java @@ -580,47 +580,10 @@ class GeckoSurfaceView GeckoAppShell.sendEventToGecko(new GeckoEvent(event)); } - private class GeocoderTask extends AsyncTask { - protected Void doInBackground(Location... location) { - try { - List
addresses = mGeocoder.getFromLocation(location[0].getLatitude(), - location[0].getLongitude(), 1); - // grab the first address. in the future, - // may want to expose multiple, or filter - // for best. - mLastGeoAddress = addresses.get(0); - GeckoAppShell.sendEventToGecko(new GeckoEvent(location[0], mLastGeoAddress)); - } catch (Exception e) { - Log.w(LOG_FILE_NAME, "GeocoderTask "+e); - } - return null; - } - } - // geolocation public void onLocationChanged(Location location) { - if (mGeocoder == null) - mGeocoder = new Geocoder(getContext(), Locale.getDefault()); - - if (mLastGeoAddress == null) { - new GeocoderTask().execute(location); - } - else { - float[] results = new float[1]; - Location.distanceBetween(location.getLatitude(), - location.getLongitude(), - mLastGeoAddress.getLatitude(), - mLastGeoAddress.getLongitude(), - results); - // pfm value. don't want to slam the - // geocoder with very similar values, so - // only call after about 100m - if (results[0] > 100) - new GeocoderTask().execute(location); - } - - GeckoAppShell.sendEventToGecko(new GeckoEvent(location, mLastGeoAddress)); + GeckoAppShell.sendEventToGecko(new GeckoEvent(location)); } public void onProviderDisabled(String provider) @@ -825,9 +788,6 @@ class GeckoSurfaceView ByteBuffer mSoftwareBuffer; Bitmap mSoftwareBufferCopy; - Geocoder mGeocoder; - Address mLastGeoAddress; - final SynchronousQueue mSyncDraws = new SynchronousQueue(); } diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index 59fd71b84add..454418156a39 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -139,8 +139,6 @@ abstract public class GeckoApp public static FormAssistPopup mFormAssistPopup; public Favicons mFavicons; - private Geocoder mGeocoder; - private Address mLastGeoAddress; private static LayerController mLayerController; private static PlaceholderLayerClient mPlaceholderLayerClient; private static GeckoSoftwareLayerClient mSoftwareLayerClient; @@ -2618,51 +2616,12 @@ abstract public class GeckoApp GeckoAppShell.sendEventToGecko(GeckoEvent.createSensorEvent(event)); } - private class GeocoderRunnable implements Runnable { - Location mLocation; - GeocoderRunnable (Location location) { - mLocation = location; - } - public void run() { - try { - List
addresses = mGeocoder.getFromLocation(mLocation.getLatitude(), - mLocation.getLongitude(), 1); - // grab the first address. in the future, - // may want to expose multiple, or filter - // for best. - mLastGeoAddress = addresses.get(0); - GeckoAppShell.sendEventToGecko(GeckoEvent.createLocationEvent(mLocation, mLastGeoAddress)); - } catch (Exception e) { - Log.w(LOGTAG, "GeocoderTask "+e); - } - } - } - // geolocation public void onLocationChanged(Location location) { Log.w(LOGTAG, "onLocationChanged "+location); - if (mGeocoder == null) - mGeocoder = new Geocoder(mLayerController.getView().getContext(), Locale.getDefault()); - if (mLastGeoAddress == null) { - GeckoAppShell.getHandler().post(new GeocoderRunnable(location)); - } - else { - float[] results = new float[1]; - Location.distanceBetween(location.getLatitude(), - location.getLongitude(), - mLastGeoAddress.getLatitude(), - mLastGeoAddress.getLongitude(), - results); - // pfm value. don't want to slam the - // geocoder with very similar values, so - // only call after about 100m - if (results[0] > 100) - GeckoAppShell.getHandler().post(new GeocoderRunnable(location)); - } - - GeckoAppShell.sendEventToGecko(GeckoEvent.createLocationEvent(location, mLastGeoAddress)); + GeckoAppShell.sendEventToGecko(GeckoEvent.createLocationEvent(location)); } public void onProviderDisabled(String provider) diff --git a/mobile/android/base/GeckoEvent.java b/mobile/android/base/GeckoEvent.java index bfea49b4edce..7310b09a06f2 100644 --- a/mobile/android/base/GeckoEvent.java +++ b/mobile/android/base/GeckoEvent.java @@ -305,10 +305,9 @@ public class GeckoEvent { return event; } - public static GeckoEvent createLocationEvent(Location l, Address a) { + public static GeckoEvent createLocationEvent(Location l) { GeckoEvent event = new GeckoEvent(LOCATION_EVENT); event.mLocation = l; - event.mAddress = a; return event; } diff --git a/widget/android/AndroidJavaWrappers.cpp b/widget/android/AndroidJavaWrappers.cpp index 387a9011ee63..f5b414ba61db 100644 --- a/widget/android/AndroidJavaWrappers.cpp +++ b/widget/android/AndroidJavaWrappers.cpp @@ -1,4 +1,4 @@ -/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- +3/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -73,7 +73,6 @@ jfieldID AndroidGeckoEvent::jRangeStylesField = 0; jfieldID AndroidGeckoEvent::jRangeForeColorField = 0; jfieldID AndroidGeckoEvent::jRangeBackColorField = 0; jfieldID AndroidGeckoEvent::jLocationField = 0; -jfieldID AndroidGeckoEvent::jAddressField = 0; jfieldID AndroidGeckoEvent::jBandwidthField = 0; jfieldID AndroidGeckoEvent::jCanBeMeteredField = 0; @@ -96,19 +95,6 @@ jmethodID AndroidLocation::jGetBearingMethod = 0; jmethodID AndroidLocation::jGetSpeedMethod = 0; jmethodID AndroidLocation::jGetTimeMethod = 0; -jclass AndroidAddress::jAddressClass = 0; -jmethodID AndroidAddress::jGetAddressLineMethod; -jmethodID AndroidAddress::jGetAdminAreaMethod; -jmethodID AndroidAddress::jGetCountryNameMethod; -jmethodID AndroidAddress::jGetFeatureNameMethod; -jmethodID AndroidAddress::jGetLocalityMethod; -jmethodID AndroidAddress::jGetPostalCodeMethod; -jmethodID AndroidAddress::jGetPremisesMethod; -jmethodID AndroidAddress::jGetSubAdminAreaMethod; -jmethodID AndroidAddress::jGetSubLocalityMethod; -jmethodID AndroidAddress::jGetSubThoroughfareMethod; -jmethodID AndroidAddress::jGetThoroughfareMethod; - jclass AndroidGeckoSoftwareLayerClient::jGeckoSoftwareLayerClientClass = 0; jmethodID AndroidGeckoSoftwareLayerClient::jLockBufferMethod = 0; jmethodID AndroidGeckoSoftwareLayerClient::jUnlockBufferMethod = 0; @@ -142,7 +128,6 @@ mozilla::InitAndroidJavaWrappers(JNIEnv *jEnv) AndroidGeckoEvent::InitGeckoEventClass(jEnv); AndroidPoint::InitPointClass(jEnv); AndroidLocation::InitLocationClass(jEnv); - AndroidAddress::InitAddressClass(jEnv); AndroidRect::InitRectClass(jEnv); AndroidGeckoSoftwareLayerClient::InitGeckoSoftwareLayerClientClass(jEnv); AndroidGeckoSurfaceView::InitGeckoSurfaceViewClass(jEnv); @@ -186,7 +171,6 @@ AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv) jRangeForeColorField = getField("mRangeForeColor", "I"); jRangeBackColorField = getField("mRangeBackColor", "I"); jLocationField = getField("mLocation", "Landroid/location/Location;"); - jAddressField = getField("mAddress", "Landroid/location/Address;"); jBandwidthField = getField("mBandwidth", "D"); jCanBeMeteredField = getField("mCanBeMetered", "Z"); } @@ -225,60 +209,6 @@ AndroidLocation::InitLocationClass(JNIEnv *jEnv) jGetTimeMethod = getMethod("getTime", "()J"); } -void -AndroidAddress::InitAddressClass(JNIEnv *jEnv) -{ - initInit(); - - jAddressClass = getClassGlobalRef("android/location/Address"); - - jGetAddressLineMethod = getMethod("getAddressLine", "(I)Ljava/lang/String;"); - jGetAdminAreaMethod = getMethod("getAdminArea", "()Ljava/lang/String;"); - jGetCountryNameMethod = getMethod("getCountryName", "()Ljava/lang/String;"); - jGetFeatureNameMethod = getMethod("getFeatureName", "()Ljava/lang/String;"); - jGetLocalityMethod = getMethod("getLocality", "()Ljava/lang/String;"); - jGetPostalCodeMethod = getMethod("getPostalCode", "()Ljava/lang/String;"); - jGetPremisesMethod = getMethod("getPremises", "()Ljava/lang/String;"); - jGetSubAdminAreaMethod = getMethod("getSubAdminArea", "()Ljava/lang/String;"); - jGetSubLocalityMethod = getMethod("getSubLocality", "()Ljava/lang/String;"); - jGetSubThoroughfareMethod = getMethod("getSubThoroughfare", "()Ljava/lang/String;"); - jGetThoroughfareMethod = getMethod("getThoroughfare", "()Ljava/lang/String;"); -} - -nsGeoPositionAddress* -AndroidAddress::CreateGeoPositionAddress(JNIEnv *jenv, jobject jobj) -{ - nsJNIString streetNumber(static_cast(jenv->CallObjectMethod(jobj, jGetSubThoroughfareMethod)), jenv); - nsJNIString street(static_cast(jenv->CallObjectMethod(jobj, jGetThoroughfareMethod)), jenv); - nsJNIString city(static_cast(jenv->CallObjectMethod(jobj, jGetLocalityMethod)), jenv); - nsJNIString county(static_cast(jenv->CallObjectMethod(jobj, jGetSubAdminAreaMethod)), jenv); - nsJNIString country(static_cast(jenv->CallObjectMethod(jobj, jGetCountryNameMethod)), jenv); - nsJNIString premises(static_cast(jenv->CallObjectMethod(jobj, jGetPremisesMethod)), jenv); - nsJNIString postalCode(static_cast(jenv->CallObjectMethod(jobj, jGetPostalCodeMethod)), jenv); - nsJNIString region(static_cast(jenv->CallObjectMethod(jobj, jGetAdminAreaMethod, 0)), jenv); - -#ifdef DEBUG - printf_stderr("!!!!!!!!!!!!!! AndroidAddress::CreateGeoPositionAddress:\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n", - NS_LossyConvertUTF16toASCII(streetNumber).get(), - NS_LossyConvertUTF16toASCII(street).get(), - NS_LossyConvertUTF16toASCII(premises).get(), - NS_LossyConvertUTF16toASCII(city).get(), - NS_LossyConvertUTF16toASCII(county).get(), - NS_LossyConvertUTF16toASCII(region).get(), - NS_LossyConvertUTF16toASCII(country).get(), - NS_LossyConvertUTF16toASCII(postalCode).get()); -#endif - - return new nsGeoPositionAddress(streetNumber, - street, - premises, - city, - county, - region, - country, - postalCode); -} - nsGeoPosition* AndroidLocation::CreateGeoPosition(JNIEnv *jenv, jobject jobj) { @@ -511,11 +441,7 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj) case LOCATION_EVENT: { jobject location = jenv->GetObjectField(jobj, jLocationField); - jobject address = jenv->GetObjectField(jobj, jAddressField); - mGeoPosition = AndroidLocation::CreateGeoPosition(jenv, location); - if (address) - mGeoAddress = AndroidAddress::CreateGeoPositionAddress(jenv, address); break; } diff --git a/widget/android/AndroidJavaWrappers.h b/widget/android/AndroidJavaWrappers.h index 3ae573c1a6f8..2bb9cda55bdf 100644 --- a/widget/android/AndroidJavaWrappers.h +++ b/widget/android/AndroidJavaWrappers.h @@ -384,25 +384,6 @@ public: static jmethodID jGetTimeMethod; }; -class AndroidAddress : public WrappedJavaObject -{ -public: - static void InitAddressClass(JNIEnv *jEnv); - static nsGeoPositionAddress* CreateGeoPositionAddress(JNIEnv *jenv, jobject jobj); - static jclass jAddressClass; - static jmethodID jGetAddressLineMethod; - static jmethodID jGetAdminAreaMethod; - static jmethodID jGetCountryNameMethod; - static jmethodID jGetFeatureNameMethod; - static jmethodID jGetLocalityMethod; - static jmethodID jGetPostalCodeMethod; - static jmethodID jGetPremisesMethod; - static jmethodID jGetSubAdminAreaMethod; - static jmethodID jGetSubLocalityMethod; - static jmethodID jGetSubThoroughfareMethod; - static jmethodID jGetThoroughfareMethod; -}; - class AndroidGeckoEvent : public WrappedJavaObject { public: @@ -461,7 +442,6 @@ public: int RangeForeColor() { return mRangeForeColor; } int RangeBackColor() { return mRangeBackColor; } nsGeoPosition* GeoPosition() { return mGeoPosition; } - nsGeoPositionAddress* GeoAddress() { return mGeoAddress; } double Bandwidth() { return mBandwidth; } bool CanBeMetered() { return mCanBeMetered; } @@ -486,7 +466,6 @@ protected: int mPointerIndex; nsString mCharacters, mCharactersExtra; nsRefPtr mGeoPosition; - nsRefPtr mGeoAddress; double mBandwidth; bool mCanBeMetered; @@ -539,7 +518,6 @@ protected: static jfieldID jRangeForeColorField; static jfieldID jRangeBackColorField; static jfieldID jLocationField; - static jfieldID jAddressField; static jfieldID jBandwidthField; static jfieldID jCanBeMeteredField; diff --git a/widget/android/nsAppShell.cpp b/widget/android/nsAppShell.cpp index 83b24aa81e29..4a44ff40311a 100644 --- a/widget/android/nsAppShell.cpp +++ b/widget/android/nsAppShell.cpp @@ -351,12 +351,8 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait) break; nsGeoPosition* p = curEvent->GeoPosition(); - nsGeoPositionAddress* a = curEvent->GeoAddress(); - - if (p) { - p->SetAddress(a); + if (p) gLocationCallback->Update(curEvent->GeoPosition()); - } else NS_WARNING("Received location event without geoposition!"); break; From ed03402c45e0e2fd294d53d770823c8aca25a3d0 Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Tue, 13 Mar 2012 09:59:23 -0700 Subject: [PATCH 06/57] Bug 733650 - Use smslib as the device orientation backend on the mac. r=jdm --- dom/system/cocoa/Makefile.in | 1 + dom/system/cocoa/nsDeviceMotionSystem.mm | 136 +--- dom/system/cocoa/smslib.h | 159 ++++ dom/system/cocoa/smslib.mm | 937 +++++++++++++++++++++++ toolkit/content/license.html | 54 ++ 5 files changed, 1163 insertions(+), 124 deletions(-) create mode 100644 dom/system/cocoa/smslib.h create mode 100644 dom/system/cocoa/smslib.mm diff --git a/dom/system/cocoa/Makefile.in b/dom/system/cocoa/Makefile.in index bbc3d49fe454..77041a2b87b6 100644 --- a/dom/system/cocoa/Makefile.in +++ b/dom/system/cocoa/Makefile.in @@ -52,6 +52,7 @@ EXPORT_LIBRARY = 1 include $(topsrcdir)/config/config.mk CMMSRCS = \ + smslib.mm \ nsDeviceMotionSystem.mm \ $(NULL) diff --git a/dom/system/cocoa/nsDeviceMotionSystem.mm b/dom/system/cocoa/nsDeviceMotionSystem.mm index 6fc0385c2ee6..6eefae0416c8 100644 --- a/dom/system/cocoa/nsDeviceMotionSystem.mm +++ b/dom/system/cocoa/nsDeviceMotionSystem.mm @@ -42,8 +42,8 @@ #include #include -#define MODEL_NAME_LENGTH 64 -static char gModelName[MODEL_NAME_LENGTH]; +#import "smslib.h" +#define MEAN_GRAVITY 9.80665 nsDeviceMotionSystem::nsDeviceMotionSystem() { @@ -53,24 +53,6 @@ nsDeviceMotionSystem::~nsDeviceMotionSystem() { } -// Data format returned from IOConnectMethodStructureIStructureO. -// I am not sure what the other bits in this structure are, -// or if there are any, but this has to be 40 bytes long or -// the call to read fails. -// -// Since we make the SmsData struct larger than any members we plan to access we -// keep track of the the size of the part of the struct we plan to access for -// use in bounds checking. -#define SMSDATA_PADDING_SIZE 34 -typedef struct -{ - PRInt16 x; - PRInt16 y; - PRInt16 z; - PRInt8 unknown[SMSDATA_PADDING_SIZE]; -} SmsData; -#define SMSDATA_USED_SIZE (sizeof(SmsData) - SMSDATA_PADDING_SIZE) - void nsDeviceMotionSystem::UpdateHandler(nsITimer *aTimer, void *aClosure) { @@ -79,112 +61,19 @@ nsDeviceMotionSystem::UpdateHandler(nsITimer *aTimer, void *aClosure) NS_ERROR("no self"); return; } + sms_acceleration accel; + smsGetData(&accel); - size_t bufferLen = sizeof(SmsData); - - void * input = malloc(bufferLen); - void * output = malloc(bufferLen); - - if (!input || !output) - return; - - memset(input, 0, bufferLen); - memset(output, 0, bufferLen); - - size_t structureOutputSize = bufferLen; -#if (MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4) - kern_return_t result = ::IOConnectMethodStructureIStructureO(self->mSmsConnection, - 5, /* Magic number for SMCMotionSensor */ - bufferLen, - (IOByteCount*)&structureOutputSize, - input, - output); -#else - kern_return_t result = ::IOConnectCallStructMethod((mach_port_t)self->mSmsConnection, - 5, /* Magic number for SMCMotionSensor */ - input, - bufferLen, - output, - &structureOutputSize); -#endif - - if ((result != kIOReturnSuccess) || (structureOutputSize < SMSDATA_USED_SIZE)) { - free(input); - free(output); - return; - } - - SmsData *data = (SmsData*) output; - - float xf, yf, zf; - - // we want to normalize the return result from the chip to - // something between -1 and 1 where 0 is the balance point. - - const int normalizeFactor = 250.5; - - if (!strcmp(gModelName, "MacBookPro5,1")) { - xf = ((float)data->x) / normalizeFactor; - yf = (((float)data->y) / normalizeFactor) * -1; - zf = ((float)data->z) / normalizeFactor; - } - else if (!strcmp(gModelName, "MacBookPro5,3")) { - xf = ((float)data->y) / normalizeFactor; - yf = (((float)data->x) / normalizeFactor) * -1; - zf = (((float)data->z) / normalizeFactor) * -1; - } - else - { - xf = (((float)data->x) / normalizeFactor) * -1; - yf = ((float)data->y) / normalizeFactor; - zf = ((float)data->z) / normalizeFactor; - } - - free(input); - free(output); - - self->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ACCELERATION, xf, yf, zf ); + self->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ACCELERATION, + accel.x * MEAN_GRAVITY, + accel.y * MEAN_GRAVITY, + accel.z * MEAN_GRAVITY); } void nsDeviceMotionSystem::Startup() { - // we can fail, and that just means the caller will not see any changes. - - mach_port_t port; - kern_return_t result = ::IOMasterPort(MACH_PORT_NULL, &port); - if (result != kIOReturnSuccess) - return; - - CFMutableDictionaryRef dict = ::IOServiceMatching("SMCMotionSensor"); - if (!dict) - return; - - io_iterator_t iter; - result = ::IOServiceGetMatchingServices(port, dict, &iter); - if (result != kIOReturnSuccess) - return; - - io_object_t device = ::IOIteratorNext(iter); - - ::IOObjectRelease(iter); - - if (!device) - return; - - result = ::IOServiceOpen(device, mach_task_self(), 0, &mSmsConnection); - ::IOObjectRelease(device); - - if (result != kIOReturnSuccess) - return; - - mach_port_deallocate(mach_task_self(), port); - - /* get the version of the hardware we are running on. */ - int mib[2]; - size_t len = MODEL_NAME_LENGTH; - mib[0] = CTL_HW; - mib[1] = HW_MODEL; - sysctl(mib, 2, gModelName, &len, NULL, 0); + smsStartup(nil, nil); + smsLoadCalibration(); mUpdateTimer = do_CreateInstance("@mozilla.org/timer;1"); if (mUpdateTimer) @@ -196,12 +85,11 @@ void nsDeviceMotionSystem::Startup() void nsDeviceMotionSystem::Shutdown() { - if (mSmsConnection) - ::IOServiceClose(mSmsConnection); - if (mUpdateTimer) { mUpdateTimer->Cancel(); mUpdateTimer = nsnull; } + + smsShutdown(); } diff --git a/dom/system/cocoa/smslib.h b/dom/system/cocoa/smslib.h new file mode 100644 index 000000000000..2f0b2664e459 --- /dev/null +++ b/dom/system/cocoa/smslib.h @@ -0,0 +1,159 @@ +/* + * smslib.h + * + * SMSLib Sudden Motion Sensor Access Library + * Copyright (c) 2010 Suitable Systems + * All rights reserved. + * + * Developed by: Daniel Griscom + * Suitable Systems + * http://www.suitable.com + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal with the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimers. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimers in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the names of Suitable Systems nor the names of its + * contributors may be used to endorse or promote products derived from + * this Software without specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. + * + * For more information about SMSLib, see + * + * or contact + * Daniel Griscom + * Suitable Systems + * 1 Centre Street, Suite 204 + * Wakefield, MA 01880 + * (781) 665-0053 + * + */ + +#import + +#define SMSLIB_VERSION "1.8" + +#pragma mark Structure definitions + +// Structure for specifying a 3-axis acceleration. 0.0 means "zero gravities", +// 1.0 means "one gravity". +typedef struct sms_acceleration { + float x; // Right-left acceleration (positive is rightwards) + float y; // Front-rear acceleration (positive is rearwards) + float z; // Up-down acceleration (positive is upwards) +} sms_acceleration; + +// Structure for specifying a calibration. +typedef struct sms_calibration { + float zeros[3]; // Zero points for three axes (X, Y, Z) + float onegs[3]; // One gravity values for three axes +} sms_calibration; + +#pragma mark Return value definitions + +// These are the return values for accelStartup(), giving the +// various stages where the most successful attempt at accessing +// the accelerometer failed. The higher the value, the further along the +// software progressed before failing. The options are: +// - Didn't match model name +#define SMS_FAIL_MODEL (-7) +// - Failure getting dictionary matching desired services +#define SMS_FAIL_DICTIONARY (-6) +// - Failure getting list of services +#define SMS_FAIL_LIST_SERVICES (-5) +// - Failure if list of services is empty. The process generally fails +// here if run on a machine without a Sudden Motion Sensor. +#define SMS_FAIL_NO_SERVICES (-4) +// - Failure if error opening device. +#define SMS_FAIL_OPENING (-3) +// - Failure if opened, but didn't get a connection +#define SMS_FAIL_CONNECTION (-2) +// - Failure if couldn't access connction using given function and size. This +// is where the process would probably fail with a change in Apple's API. +// Driver problems often also cause failures here. +#define SMS_FAIL_ACCESS (-1) +// - Success! +#define SMS_SUCCESS (0) + +#pragma mark Function declarations + +// This starts up the accelerometer code, trying each possible sensor +// specification. Note that for logging purposes it +// takes an object and a selector; the object's selector is then invoked +// with a single NSString as argument giving progress messages. Example +// logging method: +// - (void)logMessage: (NSString *)theString +// which would be used in accelStartup's invocation thusly: +// result = accelStartup(self, @selector(logMessage:)); +// If the object is nil, then no logging is done. Sets calibation from built-in +// value table. Returns ACCEL_SUCCESS for success, and other (negative) +// values for various failures (returns value indicating result of +// most successful trial). +int smsStartup(id logObject, SEL logSelector); + +// This starts up the library in debug mode, ignoring the actual hardware. +// Returned data is in the form of 1Hz sine waves, with the X, Y and Z +// axes 120 degrees out of phase; "calibrated" data has range +/- (1.0/5); +// "uncalibrated" data has range +/- (256/5). X and Y axes centered on 0.0, +// Z axes centered on 1 (calibrated) or 256 (uncalibrated). +// Don't use smsGetBufferLength or smsGetBufferData. Always returns SMS_SUCCESS. +int smsDebugStartup(id logObject, SEL logSelector); + +// Returns the current calibration values. +void smsGetCalibration(sms_calibration *calibrationRecord); + +// Sets the calibration, but does NOT store it as a preference. If the argument +// is nil then the current calibration is set from the built-in value table. +void smsSetCalibration(sms_calibration *calibrationRecord); + +// Stores the current calibration values as a stored preference. +void smsStoreCalibration(void); + +// Loads the stored preference values into the current calibration. +// Returns YES if successful. +BOOL smsLoadCalibration(void); + +// Deletes any stored calibration, and then takes the current calibration values +// from the built-in value table. +void smsDeleteCalibration(void); + +// Fills in the accel record with calibrated acceleration data. Takes +// 1-2ms to return a value. Returns 0 if success, error number if failure. +int smsGetData(sms_acceleration *accel); + +// Fills in the accel record with uncalibrated acceleration data. +// Returns 0 if success, error number if failure. +int smsGetUncalibratedData(sms_acceleration *accel); + +// Returns the length of a raw block of data for the current type of sensor. +int smsGetBufferLength(void); + +// Takes a pointer to accelGetRawLength() bytes; sets those bytes +// to return value from sensor. Make darn sure the buffer length is right! +void smsGetBufferData(char *buffer); + +// This returns an NSString describing the current calibration in +// human-readable form. Also include a description of the machine. +NSString *smsGetCalibrationDescription(void); + +// Shuts down the accelerometer. +void smsShutdown(void); + diff --git a/dom/system/cocoa/smslib.mm b/dom/system/cocoa/smslib.mm new file mode 100644 index 000000000000..8761a81f48fa --- /dev/null +++ b/dom/system/cocoa/smslib.mm @@ -0,0 +1,937 @@ +/* + * smslib.m + * + * SMSLib Sudden Motion Sensor Access Library + * Copyright (c) 2010 Suitable Systems + * All rights reserved. + * + * Developed by: Daniel Griscom + * Suitable Systems + * http://www.suitable.com + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal with the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimers. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimers in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the names of Suitable Systems nor the names of its + * contributors may be used to endorse or promote products derived from + * this Software without specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. + * + * For more information about SMSLib, see + * + * or contact + * Daniel Griscom + * Suitable Systems + * 1 Centre Street, Suite 204 + * Wakefield, MA 01880 + * (781) 665-0053 + * + */ + +#import +#import +#import +#import "smslib.h" + +#pragma mark Internal structures + +// Represents a single axis of a type of sensor. +typedef struct axisStruct { + int enabled; // Non-zero if axis is valid in this sensor + int index; // Location in struct of first byte + int size; // Number of bytes + float zerog; // Value meaning "zero g" + float oneg; // Change in value meaning "increase of one g" + // (can be negative if axis sensor reversed) +} axisStruct; + +// Represents the configuration of a type of sensor. +typedef struct sensorSpec { + char *model; // Prefix of model to be tested + char *name; // Name of device to be read + unsigned int function; // Kernel function index + int recordSize; // Size of record to be sent/received + axisStruct axes[3]; // Description of three axes (X, Y, Z) +} sensorSpec; + +// Configuration of all known types of sensors. The configurations are +// tried in order until one succeeds in returning data. +// All default values are set here, but each axis' zerog and oneg values +// may be changed to saved (calibrated) values. +// +// These values came from SeisMaCalibrate calibration reports. In general I've +// found the following: +// - All Intel-based SMSs have 250 counts per g, centered on 0, but the signs +// are different (and in one case two axes are swapped) +// - PowerBooks and iBooks all have sensors centered on 0, and reading +// 50-53 steps per gravity (but with differing polarities!) +// - PowerBooks and iBooks of the same model all have the same axis polarities +// - PowerBook and iBook access methods are model- and OS version-specific +// +// So, the sequence of tests is: +// - Try model-specific access methods. Note that the test is for a match to the +// beginning of the model name, e.g. the record with model name "MacBook" +// matches computer models "MacBookPro1,2" and "MacBook1,1" (and "" +// matches any model). +// - If no model-specific record's access fails, then try each model-independent +// access method in order, stopping when one works. +static const sensorSpec sensors[] = { + // ****** Model-dependent methods ****** + // The PowerBook5,6 is one of the G4 models that seems to lose + // SMS access until the next reboot. + {"PowerBook5,6", "IOI2CMotionSensor", 21, 60, { + {1, 0, 1, 0, 51.5}, + {1, 1, 1, 0, -51.5}, + {1, 2, 1, 0, -51.5} + } + }, + // The PowerBook5,7 is one of the G4 models that seems to lose + // SMS access until the next reboot. + {"PowerBook5,7", "IOI2CMotionSensor", 21, 60, { + {1, 0, 1, 0, 51.5}, + {1, 1, 1, 0, 51.5}, + {1, 2, 1, 0, 51.5} + } + }, + // Access seems to be reliable on the PowerBook5,8 + {"PowerBook5,8", "PMUMotionSensor", 21, 60, { + {1, 0, 1, 0, -51.5}, + {1, 1, 1, 0, 51.5}, + {1, 2, 1, 0, -51.5} + } + }, + // Access seems to be reliable on the PowerBook5,9 + {"PowerBook5,9", "PMUMotionSensor", 21, 60, { + {1, 0, 1, 0, 51.5}, + {1, 1, 1, 0, -51.5}, + {1, 2, 1, 0, -51.5} + } + }, + // The PowerBook6,7 is one of the G4 models that seems to lose + // SMS access until the next reboot. + {"PowerBook6,7", "IOI2CMotionSensor", 21, 60, { + {1, 0, 1, 0, 51.5}, + {1, 1, 1, 0, 51.5}, + {1, 2, 1, 0, 51.5} + } + }, + // The PowerBook6,8 is one of the G4 models that seems to lose + // SMS access until the next reboot. + {"PowerBook6,8", "IOI2CMotionSensor", 21, 60, { + {1, 0, 1, 0, 51.5}, + {1, 1, 1, 0, 51.5}, + {1, 2, 1, 0, 51.5} + } + }, + // MacBook Pro Core 2 Duo 17". Note the reversed Y and Z axes. + {"MacBookPro2,1", "SMCMotionSensor", 5, 40, { + {1, 0, 2, 0, 251}, + {1, 2, 2, 0, -251}, + {1, 4, 2, 0, -251} + } + }, + // MacBook Pro Core 2 Duo 15" AND 17" with LED backlight, introduced June '07. + // NOTE! The 17" machines have the signs of their X and Y axes reversed + // from this calibration, but there's no clear way to discriminate between + // the two machines. + {"MacBookPro3,1", "SMCMotionSensor", 5, 40, { + {1, 0, 2, 0, -251}, + {1, 2, 2, 0, 251}, + {1, 4, 2, 0, -251} + } + }, + // ... specs? + {"MacBook5,2", "SMCMotionSensor", 5, 40, { + {1, 0, 2, 0, -251}, + {1, 2, 2, 0, 251}, + {1, 4, 2, 0, -251} + } + }, + // ... specs? + {"MacBookPro5,1", "SMCMotionSensor", 5, 40, { + {1, 0, 2, 0, -251}, + {1, 2, 2, 0, -251}, + {1, 4, 2, 0, 251} + } + }, + // ... specs? + {"MacBookPro5,2", "SMCMotionSensor", 5, 40, { + {1, 0, 2, 0, -251}, + {1, 2, 2, 0, -251}, + {1, 4, 2, 0, 251} + } + }, + // This is speculative, based on a single user's report. Looks like the X and Y axes + // are swapped. This is true for no other known Appple laptop. + {"MacBookPro5,3", "SMCMotionSensor", 5, 40, { + {1, 2, 2, 0, -251}, + {1, 0, 2, 0, -251}, + {1, 4, 2, 0, -251} + } + }, + // ... specs? + {"MacBookPro5,4", "SMCMotionSensor", 5, 40, { + {1, 0, 2, 0, -251}, + {1, 2, 2, 0, -251}, + {1, 4, 2, 0, 251} + } + }, + // ****** Model-independent methods ****** + // Seen once with PowerBook6,8 under system 10.3.9; I suspect + // other G4-based 10.3.* systems might use this + {"", "IOI2CMotionSensor", 24, 60, { + {1, 0, 1, 0, 51.5}, + {1, 1, 1, 0, 51.5}, + {1, 2, 1, 0, 51.5} + } + }, + // PowerBook5,6 , PowerBook5,7 , PowerBook6,7 , PowerBook6,8 + // under OS X 10.4.* + {"", "IOI2CMotionSensor", 21, 60, { + {1, 0, 1, 0, 51.5}, + {1, 1, 1, 0, 51.5}, + {1, 2, 1, 0, 51.5} + } + }, + // PowerBook5,8 , PowerBook5,9 under OS X 10.4.* + {"", "PMUMotionSensor", 21, 60, { + // Each has two out of three gains negative, but it's different + // for the different models. So, this will be right in two out + // of three axis for either model. + {1, 0, 1, 0, -51.5}, + {1, 1, 1, -6, -51.5}, + {1, 2, 1, 0, -51.5} + } + }, + // All MacBook, MacBookPro models. Hardware (at least on early MacBookPro 15") + // is Kionix KXM52-1050 three-axis accelerometer chip. Data is at + // http://kionix.com/Product-Index/product-index.htm. Specific MB and MBP models + // that use this are: + // MacBook1,1 + // MacBook2,1 + // MacBook3,1 + // MacBook4,1 + // MacBook5,1 + // MacBook6,1 + // MacBookAir1,1 + // MacBookPro1,1 + // MacBookPro1,2 + // MacBookPro4,1 + // MacBookPro5,5 + {"", "SMCMotionSensor", 5, 40, { + {1, 0, 2, 0, 251}, + {1, 2, 2, 0, 251}, + {1, 4, 2, 0, 251} + } + } +}; + +#define SENSOR_COUNT (sizeof(sensors)/sizeof(sensorSpec)) + +#pragma mark Internal prototypes + +static int getData(sms_acceleration *accel, int calibrated, id logObject, SEL logSelector); +static float getAxis(int which, int calibrated); +static int signExtend(int value, int size); +static NSString *getModelName(void); +static NSString *getOSVersion(void); +static BOOL loadCalibration(void); +static void storeCalibration(void); +static void defaultCalibration(void); +static void deleteCalibration(void); +static int prefIntRead(NSString *prefName, BOOL *success); +static void prefIntWrite(NSString *prefName, int prefValue); +static float prefFloatRead(NSString *prefName, BOOL *success); +static void prefFloatWrite(NSString *prefName, float prefValue); +static void prefDelete(NSString *prefName); +static void prefSynchronize(void); +// static long getMicroseconds(void); +float fakeData(NSTimeInterval time); + +#pragma mark Static variables + +static int debugging = NO; // True if debugging (synthetic data) +static io_connect_t connection; // Connection for reading accel values +static int running = NO; // True if we successfully started +static int sensorNum = 0; // The current index into sensors[] +static char *serviceName; // The name of the current service +static char *iRecord, *oRecord; // Pointers to read/write records for sensor +static int recordSize; // Size of read/write records +static unsigned int function; // Which kernel function should be used +static float zeros[3]; // X, Y and Z zero calibration values +static float onegs[3]; // X, Y and Z one-g calibration values + +#pragma mark Defines + +// Pattern for building axis letter from axis number +#define INT_TO_AXIS(a) (a == 0 ? @"X" : a == 1 ? @"Y" : @"Z") +// Name of configuration for given axis' zero (axis specified by integer) +#define ZERO_NAME(a) [NSString stringWithFormat:@"%@-Axis-Zero", INT_TO_AXIS(a)] +// Name of configuration for given axis' oneg (axis specified by integer) +#define ONEG_NAME(a) [NSString stringWithFormat:@"%@-Axis-One-g", INT_TO_AXIS(a)] +// Name of "Is calibrated" preference +#define CALIBRATED_NAME (@"Calibrated") +// Application domain for SeisMac library +#define APP_ID ((CFStringRef)@"com.suitable.SeisMacLib") + +// These #defines make the accelStartup code a LOT easier to read. +#define LOG(message) \ + if (logObject) { \ + [logObject performSelector:logSelector withObject:message]; \ + } +#define LOG_ARG(format, var1) \ + if (logObject) { \ + [logObject performSelector:logSelector \ + withObject:[NSString stringWithFormat:format, var1]]; \ + } +#define LOG_2ARG(format, var1, var2) \ + if (logObject) { \ + [logObject performSelector:logSelector \ + withObject:[NSString stringWithFormat:format, var1, var2]]; \ + } +#define LOG_3ARG(format, var1, var2, var3) \ + if (logObject) { \ + [logObject performSelector:logSelector \ + withObject:[NSString stringWithFormat:format, var1, var2, var3]]; \ + } + +#pragma mark Function definitions + +// This starts up the accelerometer code, trying each possible sensor +// specification. Note that for logging purposes it +// takes an object and a selector; the object's selector is then invoked +// with a single NSString as argument giving progress messages. Example +// logging method: +// - (void)logMessage: (NSString *)theString +// which would be used in accelStartup's invocation thusly: +// result = accelStartup(self, @selector(logMessage:)); +// If the object is nil, then no logging is done. Sets calibation from built-in +// value table. Returns ACCEL_SUCCESS for success, and other (negative) +// values for various failures (returns value indicating result of +// most successful trial). +int smsStartup(id logObject, SEL logSelector) { + io_iterator_t iterator; + io_object_t device; + kern_return_t result; + sms_acceleration accel; + int failure_result = SMS_FAIL_MODEL; + + running = NO; + debugging = NO; + + NSString *modelName = getModelName(); + + LOG_ARG(@"Machine model: %@\n", modelName); + LOG_ARG(@"OS X version: %@\n", getOSVersion()); + LOG_ARG(@"Accelerometer library version: %s\n", SMSLIB_VERSION); + + for (sensorNum = 0; sensorNum < SENSOR_COUNT; sensorNum++) { + + // Set up all specs for this type of sensor + serviceName = sensors[sensorNum].name; + recordSize = sensors[sensorNum].recordSize; + function = sensors[sensorNum].function; + + LOG_3ARG(@"Trying service \"%s\" with selector %d and %d byte record:\n", + serviceName, function, recordSize); + + NSString *targetName = [NSString stringWithCString:sensors[sensorNum].model + encoding:NSMacOSRomanStringEncoding]; + LOG_ARG(@" Comparing model name to target \"%@\": ", targetName); + if ([targetName length] == 0 || [modelName hasPrefix:targetName]) { + LOG(@"success.\n"); + } else { + LOG(@"failure.\n"); + // Don't need to increment failure_result. + continue; + } + + LOG(@" Fetching dictionary for service: "); + CFMutableDictionaryRef dict = IOServiceMatching(serviceName); + + if (dict) { + LOG(@"success.\n"); + } else { + LOG(@"failure.\n"); + if (failure_result < SMS_FAIL_DICTIONARY) { + failure_result = SMS_FAIL_DICTIONARY; + } + continue; + } + + LOG(@" Getting list of matching services: "); + result = IOServiceGetMatchingServices(kIOMasterPortDefault, + dict, + &iterator); + + if (result == KERN_SUCCESS) { + LOG(@"success.\n"); + } else { + LOG_ARG(@"failure, with return value 0x%x.\n", result); + if (failure_result < SMS_FAIL_LIST_SERVICES) { + failure_result = SMS_FAIL_LIST_SERVICES; + } + continue; + } + + LOG(@" Getting first device in list: "); + device = IOIteratorNext(iterator); + + if (device == 0) { + LOG(@"failure.\n"); + if (failure_result < SMS_FAIL_NO_SERVICES) { + failure_result = SMS_FAIL_NO_SERVICES; + } + continue; + } else { + LOG(@"success.\n"); + LOG(@" Opening device: "); + } + + result = IOServiceOpen(device, mach_task_self(), 0, &connection); + + if (result != KERN_SUCCESS) { + LOG_ARG(@"failure, with return value 0x%x.\n", result); + IOObjectRelease(device); + if (failure_result < SMS_FAIL_OPENING) { + failure_result = SMS_FAIL_OPENING; + } + continue; + } else if (connection == 0) { + LOG_ARG(@"'success', but didn't get a connection.\n", result); + IOObjectRelease(device); + if (failure_result < SMS_FAIL_CONNECTION) { + failure_result = SMS_FAIL_CONNECTION; + } + continue; + } else { + IOObjectRelease(device); + LOG(@"success.\n"); + } + LOG(@" Testing device.\n"); + + defaultCalibration(); + + iRecord = (char*) malloc(recordSize); + oRecord = (char*) malloc(recordSize); + + running = YES; + result = getData(&accel, true, logObject, logSelector); + running = NO; + + if (result) { + LOG_ARG(@" Failure testing device, with result 0x%x.\n", result); + free(iRecord); + iRecord = 0; + free(oRecord); + oRecord = 0; + if (failure_result < SMS_FAIL_ACCESS) { + failure_result = SMS_FAIL_ACCESS; + } + continue; + } else { + LOG(@" Success testing device!\n"); + running = YES; + return SMS_SUCCESS; + } + } + return failure_result; +} + +// This starts up the library in debug mode, ignoring the actual hardware. +// Returned data is in the form of 1Hz sine waves, with the X, Y and Z +// axes 120 degrees out of phase; "calibrated" data has range +/- (1.0/5); +// "uncalibrated" data has range +/- (256/5). X and Y axes centered on 0.0, +// Z axes centered on 1 (calibrated) or 256 (uncalibrated). +// Don't use smsGetBufferLength or smsGetBufferData. Always returns SMS_SUCCESS. +int smsDebugStartup(id logObject, SEL logSelector) { + LOG(@"Starting up in debug mode\n"); + debugging = YES; + return SMS_SUCCESS; +} + +// Returns the current calibration values. +void smsGetCalibration(sms_calibration *calibrationRecord) { + int x; + + for (x = 0; x < 3; x++) { + calibrationRecord->zeros[x] = (debugging ? 0 : zeros[x]); + calibrationRecord->onegs[x] = (debugging ? 256 : onegs[x]); + } +} + +// Sets the calibration, but does NOT store it as a preference. If the argument +// is nil then the current calibration is set from the built-in value table. +void smsSetCalibration(sms_calibration *calibrationRecord) { + int x; + + if (!debugging) { + if (calibrationRecord) { + for (x = 0; x < 3; x++) { + zeros[x] = calibrationRecord->zeros[x]; + onegs[x] = calibrationRecord->onegs[x]; + } + } else { + defaultCalibration(); + } + } +} + +// Stores the current calibration values as a stored preference. +void smsStoreCalibration(void) { + if (!debugging) + storeCalibration(); +} + +// Loads the stored preference values into the current calibration. +// Returns YES if successful. +BOOL smsLoadCalibration(void) { + if (debugging) { + return YES; + } else if (loadCalibration()) { + return YES; + } else { + defaultCalibration(); + return NO; + } +} + +// Deletes any stored calibration, and then takes the current calibration values +// from the built-in value table. +void smsDeleteCalibration(void) { + if (!debugging) { + deleteCalibration(); + defaultCalibration(); + } +} + +// Fills in the accel record with calibrated acceleration data. Takes +// 1-2ms to return a value. Returns 0 if success, error number if failure. +int smsGetData(sms_acceleration *accel) { + NSTimeInterval time; + if (debugging) { + usleep(1500); // Usually takes 1-2 milliseconds + time = [NSDate timeIntervalSinceReferenceDate]; + accel->x = fakeData(time)/5; + accel->y = fakeData(time - 1)/5; + accel->z = fakeData(time - 2)/5 + 1.0; + return true; + } else { + return getData(accel, true, nil, nil); + } +} + +// Fills in the accel record with uncalibrated acceleration data. +// Returns 0 if success, error number if failure. +int smsGetUncalibratedData(sms_acceleration *accel) { + NSTimeInterval time; + if (debugging) { + usleep(1500); // Usually takes 1-2 milliseconds + time = [NSDate timeIntervalSinceReferenceDate]; + accel->x = fakeData(time) * 256 / 5; + accel->y = fakeData(time - 1) * 256 / 5; + accel->z = fakeData(time - 2) * 256 / 5 + 256; + return true; + } else { + return getData(accel, false, nil, nil); + } +} + +// Returns the length of a raw block of data for the current type of sensor. +int smsGetBufferLength(void) { + if (debugging) { + return 0; + } else if (running) { + return sensors[sensorNum].recordSize; + } else { + return 0; + } +} + +// Takes a pointer to accelGetRawLength() bytes; sets those bytes +// to return value from sensor. Make darn sure the buffer length is right! +void smsGetBufferData(char *buffer) { + IOItemCount iSize = recordSize; + IOByteCount oSize = recordSize; + kern_return_t result; + + if (debugging || running == NO) { + return; + } + + memset(iRecord, 1, iSize); + memset(buffer, 0, oSize); +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + const size_t InStructSize = recordSize; + size_t OutStructSize = recordSize; + result = IOConnectCallStructMethod(connection, + function, // magic kernel function number + (const void *)iRecord, + InStructSize, + (void *)buffer, + &OutStructSize + ); +#else // __MAC_OS_X_VERSION_MIN_REQUIRED 1050 + result = IOConnectMethodStructureIStructureO(connection, + function, // magic kernel function number + iSize, + &oSize, + iRecord, + buffer + ); +#endif // __MAC_OS_X_VERSION_MIN_REQUIRED 1050 + + if (result != KERN_SUCCESS) { + running = NO; + } +} + +// This returns an NSString describing the current calibration in +// human-readable form. Also include a description of the machine. +NSString *smsGetCalibrationDescription(void) { + BOOL success; + NSMutableString *s = [[NSMutableString alloc] init]; + + if (debugging) { + [s release]; + return @"Debugging!"; + } + + [s appendString:@"---- SeisMac Calibration Record ----\n \n"]; + [s appendFormat:@"Machine model: %@\n", + getModelName()]; + [s appendFormat:@"OS X build: %@\n", + getOSVersion()]; + [s appendFormat:@"SeisMacLib version %s, record %d\n \n", + SMSLIB_VERSION, sensorNum]; + [s appendFormat:@"Using service \"%s\", function index %d, size %d\n \n", + serviceName, function, recordSize]; + if (prefIntRead(CALIBRATED_NAME, &success) && success) { + [s appendString:@"Calibration values (from calibration):\n"]; + } else { + [s appendString:@"Calibration values (from defaults):\n"]; + } + [s appendFormat:@" X-Axis-Zero = %.2f\n", zeros[0]]; + [s appendFormat:@" X-Axis-One-g = %.2f\n", onegs[0]]; + [s appendFormat:@" Y-Axis-Zero = %.2f\n", zeros[1]]; + [s appendFormat:@" Y-Axis-One-g = %.2f\n", onegs[1]]; + [s appendFormat:@" Z-Axis-Zero = %.2f\n", zeros[2]]; + [s appendFormat:@" Z-Axis-One-g = %.2f\n \n", onegs[2]]; + [s appendString:@"---- End Record ----\n"]; + return s; +} + +// Shuts down the accelerometer. +void smsShutdown(void) { + if (!debugging) { + running = NO; + if (iRecord) free(iRecord); + if (oRecord) free(oRecord); + IOServiceClose(connection); + } +} + +#pragma mark Internal functions + +// Loads the current calibration from the stored preferences. +// Returns true iff successful. +BOOL loadCalibration(void) { + BOOL thisSuccess, allSuccess; + int x; + + prefSynchronize(); + + if (prefIntRead(CALIBRATED_NAME, &thisSuccess) && thisSuccess) { + // Calibrated. Set all values from saved values. + allSuccess = YES; + for (x = 0; x < 3; x++) { + zeros[x] = prefFloatRead(ZERO_NAME(x), &thisSuccess); + allSuccess &= thisSuccess; + onegs[x] = prefFloatRead(ONEG_NAME(x), &thisSuccess); + allSuccess &= thisSuccess; + } + return allSuccess; + } + + return NO; +} + +// Stores the current calibration into the stored preferences. +static void storeCalibration(void) { + int x; + prefIntWrite(CALIBRATED_NAME, 1); + for (x = 0; x < 3; x++) { + prefFloatWrite(ZERO_NAME(x), zeros[x]); + prefFloatWrite(ONEG_NAME(x), onegs[x]); + } + prefSynchronize(); +} + + +// Sets the calibration to its default values. +void defaultCalibration(void) { + int x; + for (x = 0; x < 3; x++) { + zeros[x] = sensors[sensorNum].axes[x].zerog; + onegs[x] = sensors[sensorNum].axes[x].oneg; + } +} + +// Deletes the stored preferences. +static void deleteCalibration(void) { + int x; + + prefDelete(CALIBRATED_NAME); + for (x = 0; x < 3; x++) { + prefDelete(ZERO_NAME(x)); + prefDelete(ONEG_NAME(x)); + } + prefSynchronize(); +} + +// Read a named floating point value from the stored preferences. Sets +// the success boolean based on, you guessed it, whether it succeeds. +static float prefFloatRead(NSString *prefName, BOOL *success) { + float result = 0.0f; + + CFPropertyListRef ref = CFPreferencesCopyAppValue((CFStringRef)prefName, + APP_ID); + // If there isn't such a preference, fail + if (ref == NULL) { + *success = NO; + return result; + } + CFTypeID typeID = CFGetTypeID(ref); + // Is it a number? + if (typeID == CFNumberGetTypeID()) { + // Is it a floating point number? + if (CFNumberIsFloatType((CFNumberRef)ref)) { + // Yup: grab it. + *success = CFNumberGetValue((__CFNumber*)ref, kCFNumberFloat32Type, &result); + } else { + // Nope: grab as an integer, and convert to a float. + long num; + if (CFNumberGetValue((CFNumberRef)ref, kCFNumberLongType, &num)) { + result = num; + *success = YES; + } else { + *success = NO; + } + } + // Or is it a string (e.g. set by the command line "defaults" command)? + } else if (typeID == CFStringGetTypeID()) { + result = (float)CFStringGetDoubleValue((CFStringRef)ref); + *success = YES; + } else { + // Can't convert to a number: fail. + *success = NO; + } + CFRelease(ref); + return result; +} + +// Writes a named floating point value to the stored preferences. +static void prefFloatWrite(NSString *prefName, float prefValue) { + CFNumberRef cfFloat = CFNumberCreate(kCFAllocatorDefault, + kCFNumberFloatType, + &prefValue); + CFPreferencesSetAppValue((CFStringRef)prefName, + cfFloat, + APP_ID); + CFRelease(cfFloat); +} + +// Reads a named integer value from the stored preferences. +static int prefIntRead(NSString *prefName, BOOL *success) { + Boolean internalSuccess; + CFIndex result = CFPreferencesGetAppIntegerValue((CFStringRef)prefName, + APP_ID, + &internalSuccess); + *success = internalSuccess; + + return result; +} + +// Writes a named integer value to the stored preferences. +static void prefIntWrite(NSString *prefName, int prefValue) { + CFPreferencesSetAppValue((CFStringRef)prefName, + (CFNumberRef)[NSNumber numberWithInt:prefValue], + APP_ID); +} + +// Deletes the named preference values. +static void prefDelete(NSString *prefName) { + CFPreferencesSetAppValue((CFStringRef)prefName, + NULL, + APP_ID); +} + +// Synchronizes the local preferences with the stored preferences. +static void prefSynchronize(void) { + CFPreferencesAppSynchronize(APP_ID); +} + +// Internal version of accelGetData, with logging +int getData(sms_acceleration *accel, int calibrated, id logObject, SEL logSelector) { + IOItemCount iSize = recordSize; + IOByteCount oSize = recordSize; + kern_return_t result; + + if (running == NO) { + return -1; + } + + memset(iRecord, 1, iSize); + memset(oRecord, 0, oSize); + + LOG_2ARG(@" Querying device: ", + sensors[sensorNum].function, sensors[sensorNum].recordSize); + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + const size_t InStructSize = recordSize; + size_t OutStructSize = recordSize; + result = IOConnectCallStructMethod(connection, + function, // magic kernel function number + (const void *)iRecord, + InStructSize, + (void *)oRecord, + &OutStructSize + ); +#else // __MAC_OS_X_VERSION_MIN_REQUIRED 1050 + result = IOConnectMethodStructureIStructureO(connection, + function, // magic kernel function number + iSize, + &oSize, + iRecord, + oRecord + ); +#endif // __MAC_OS_X_VERSION_MIN_REQUIRED 1050 + + if (result != KERN_SUCCESS) { + LOG(@"failed.\n"); + running = NO; + return result; + } else { + LOG(@"succeeded.\n"); + + accel->x = getAxis(0, calibrated); + accel->y = getAxis(1, calibrated); + accel->z = getAxis(2, calibrated); + return 0; + } +} + +// Given the returned record, extracts the value of the given axis. If +// calibrated, then zero G is 0.0, and one G is 1.0. +float getAxis(int which, int calibrated) { + // Get various values (to make code cleaner) + int indx = sensors[sensorNum].axes[which].index; + int size = sensors[sensorNum].axes[which].size; + float zerog = zeros[which]; + float oneg = onegs[which]; + // Storage for value to be returned + int value = 0; + + // Although the values in the returned record should have the proper + // endianness, we still have to get it into the proper end of value. +#if (BYTE_ORDER == BIG_ENDIAN) + // On PowerPC processors + memcpy(((char *)&value) + (sizeof(int) - size), &oRecord[indx], size); +#endif +#if (BYTE_ORDER == LITTLE_ENDIAN) + // On Intel processors + memcpy(&value, &oRecord[indx], size); +#endif + + value = signExtend(value, size); + + if (calibrated) { + // Scale and shift for zero. + return ((float)(value - zerog)) / oneg; + } else { + return value; + } +} + +// Extends the sign, given the length of the value. +int signExtend(int value, int size) { + // Extend sign + switch (size) { + case 1: + if (value & 0x00000080) + value |= 0xffffff00; + break; + case 2: + if (value & 0x00008000) + value |= 0xffff0000; + break; + case 3: + if (value & 0x00800000) + value |= 0xff000000; + break; + } + return value; +} + +// Returns the model name of the computer (e.g. "MacBookPro1,1") +NSString *getModelName(void) { + char model[32]; + size_t len = sizeof(model); + int name[2] = {CTL_HW, HW_MODEL}; + NSString *result; + + if (sysctl(name, 2, &model, &len, NULL, 0) == 0) { + result = [NSString stringWithFormat:@"%s", model]; + } else { + result = @""; + } + + return result; +} + +// Returns the current OS X version and build (e.g. "10.4.7 (build 8J2135a)") +NSString *getOSVersion(void) { + NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile: + @"/System/Library/CoreServices/SystemVersion.plist"]; + NSString *versionString = [dict objectForKey:@"ProductVersion"]; + NSString *buildString = [dict objectForKey:@"ProductBuildVersion"]; + NSString *wholeString = [NSString stringWithFormat:@"%@ (build %@)", + versionString, buildString]; + return wholeString; +} + +// Returns time within the current second in microseconds. +// long getMicroseconds() { +// struct timeval t; +// gettimeofday(&t, 0); +// return t.tv_usec; +//} + +// Returns fake data given the time. Range is +/-1. +float fakeData(NSTimeInterval time) { + long secs = lround(floor(time)); + int secsMod3 = secs % 3; + double angle = time * 10 * M_PI * 2; + double mag = exp(-(time - (secs - secsMod3)) * 2); + return sin(angle) * mag; +} + diff --git a/toolkit/content/license.html b/toolkit/content/license.html index 27775536b334..17b2bebc3510 100644 --- a/toolkit/content/license.html +++ b/toolkit/content/license.html @@ -94,6 +94,7 @@
  • Skia License
  • Snappy License
  • Sparkle License
  • +
  • Suitable Systems License
  • SunSoft License
  • University of California License
  • University of Cambridge License
  • @@ -2234,6 +2235,59 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +
    + +

    Suitable Systems License

    + +

    This license applies to certain files in the directory + dom/system/cocoa/.

    + +
    +SMSLib Sudden Motion Sensor Access Library
    +Copyright (c) 2010 Suitable Systems
    +All rights reserved.
    +
    +Developed by: Daniel Griscom
    +              Suitable Systems
    +              http://www.suitable.com
    +
    +Permission is hereby granted, free of charge, to any person obtaining a
    +copy of this software and associated documentation files (the
    +"Software"), to deal with the Software without restriction, including
    +without limitation the rights to use, copy, modify, merge, publish,
    +distribute, sublicense, and/or sell copies of the Software, and to
    +permit persons to whom the Software is furnished to do so, subject to
    +the following conditions:
    +
    +- Redistributions of source code must retain the above copyright notice,
    +this list of conditions and the following disclaimers.
    +
    +- Redistributions in binary form must reproduce the above copyright
    +notice, this list of conditions and the following disclaimers in the
    +documentation and/or other materials provided with the distribution.
    +
    +- Neither the names of Suitable Systems nor the names of its
    +contributors may be used to endorse or promote products derived from
    +this Software without specific prior written permission.
    +
    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
    +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    +IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR
    +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    +SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
    +
    +For more information about SMSLib, see
    +	
    +or contact
    +	Daniel Griscom
    +	Suitable Systems
    +	1 Centre Street, Suite 204
    +	Wakefield, MA 01880
    +	(781) 665-0053
    +
    +
    From 491131ccdd758e1d6dc19a2ab47cb7ec78f50470 Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Tue, 13 Mar 2012 09:59:24 -0700 Subject: [PATCH 07/57] Bug 733653 - use 100ms as the default sensor poll hint. Ensuring that our sensors are polled allows us to conform to the DeviceOrientation Event Specification. See DeviceMotionEvent.interval. r=jdm --- dom/system/cocoa/nsDeviceMotionSystem.mm | 3 ++- dom/system/nsDeviceMotion.cpp | 13 +++++-------- dom/system/nsDeviceMotion.h | 4 +--- dom/system/unix/nsDeviceMotionSystem.cpp | 4 +++- dom/system/windows/nsDeviceMotionSystem.cpp | 4 +++- mobile/android/base/GeckoAppShell.java | 9 ++++++--- 6 files changed, 20 insertions(+), 17 deletions(-) diff --git a/dom/system/cocoa/nsDeviceMotionSystem.mm b/dom/system/cocoa/nsDeviceMotionSystem.mm index 6eefae0416c8..bdeefdf679d5 100644 --- a/dom/system/cocoa/nsDeviceMotionSystem.mm +++ b/dom/system/cocoa/nsDeviceMotionSystem.mm @@ -44,6 +44,7 @@ #import "smslib.h" #define MEAN_GRAVITY 9.80665 +#define DEFAULT_SENSOR_POLL 100 nsDeviceMotionSystem::nsDeviceMotionSystem() { @@ -79,7 +80,7 @@ void nsDeviceMotionSystem::Startup() if (mUpdateTimer) mUpdateTimer->InitWithFuncCallback(UpdateHandler, this, - mUpdateInterval, + DEFAULT_SENSOR_POLL, nsITimer::TYPE_REPEATING_SLACK); } diff --git a/dom/system/nsDeviceMotion.cpp b/dom/system/nsDeviceMotion.cpp index 9c2230c63893..a986a1b44967 100644 --- a/dom/system/nsDeviceMotion.cpp +++ b/dom/system/nsDeviceMotion.cpp @@ -50,6 +50,9 @@ #include "nsIPrefService.h" #include "nsDOMDeviceMotionEvent.h" +// also see sDefaultSensorHint in mobile/android/base/GeckoAppShell.java +#define DEFAULT_SENSOR_POLL 100 + static const nsTArray::index_type NoIndex = nsTArray::NoIndex; @@ -117,18 +120,12 @@ NS_IMPL_ISUPPORTS2(nsDeviceMotion, nsIDeviceMotion, nsIDeviceMotionUpdate) nsDeviceMotion::nsDeviceMotion() : mStarted(false), - mUpdateInterval(50), /* default to 50 ms */ mEnabled(true) { nsCOMPtr prefSrv = do_GetService(NS_PREFSERVICE_CONTRACTID); if (prefSrv) { - PRInt32 value; - nsresult rv = prefSrv->GetIntPref("device.motion.update.interval", &value); - if (NS_SUCCEEDED(rv)) - mUpdateInterval = value; - bool bvalue; - rv = prefSrv->GetBoolPref("device.motion.enabled", &bvalue); + nsresult rv = prefSrv->GetBoolPref("device.motion.enabled", &bvalue); if (NS_SUCCEEDED(rv) && bvalue == false) mEnabled = false; } @@ -322,7 +319,7 @@ nsDeviceMotion::FireDOMMotionEvent(nsIDOMDocument *domdoc, nsnull, acceleration, nsnull, - 0); + DEFAULT_SENSOR_POLL); nsCOMPtr privateEvent = do_QueryInterface(event); if (privateEvent) diff --git a/dom/system/nsDeviceMotion.h b/dom/system/nsDeviceMotion.h index e2bada95fe6e..eacdd48ccb58 100644 --- a/dom/system/nsDeviceMotion.h +++ b/dom/system/nsDeviceMotion.h @@ -87,9 +87,7 @@ private: double x, double y, double z); - - PRUint32 mUpdateInterval; - bool mEnabled; + bool mEnabled; virtual void Startup() = 0; virtual void Shutdown() = 0; diff --git a/dom/system/unix/nsDeviceMotionSystem.cpp b/dom/system/unix/nsDeviceMotionSystem.cpp index 21e863e78498..7baaeb4aa197 100644 --- a/dom/system/unix/nsDeviceMotionSystem.cpp +++ b/dom/system/unix/nsDeviceMotionSystem.cpp @@ -42,6 +42,8 @@ #include "nsDeviceMotionSystem.h" #include "nsIServiceManager.h" +#define DEFAULT_SENSOR_POLL 100 + using namespace mozilla; typedef struct { @@ -223,7 +225,7 @@ void nsDeviceMotionSystem::Startup() if (mUpdateTimer) mUpdateTimer->InitWithFuncCallback(UpdateHandler, this, - mUpdateInterval, + DEFAULT_SENSOR_POLL, nsITimer::TYPE_REPEATING_SLACK); } diff --git a/dom/system/windows/nsDeviceMotionSystem.cpp b/dom/system/windows/nsDeviceMotionSystem.cpp index 767b9eca1a48..5ad353ae5fd4 100644 --- a/dom/system/windows/nsDeviceMotionSystem.cpp +++ b/dom/system/windows/nsDeviceMotionSystem.cpp @@ -39,6 +39,8 @@ #include "nsIServiceManager.h" #include "windows.h" +#define DEFAULT_SENSOR_POLL 100 + //////////////////////////// // ThinkPad //////////////////////////// @@ -156,7 +158,7 @@ void nsDeviceMotionSystem::Startup() if (mUpdateTimer) mUpdateTimer->InitWithFuncCallback(UpdateHandler, this, - mUpdateInterval, + DEFAULT_SENSOR_POLL, nsITimer::TYPE_REPEATING_SLACK); } diff --git a/mobile/android/base/GeckoAppShell.java b/mobile/android/base/GeckoAppShell.java index 35250a1e034a..065dc5e1c86b 100644 --- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -126,6 +126,9 @@ public class GeckoAppShell * sVibrationMaybePlaying is true. */ private static long sVibrationEndTime = 0; + /* Default value of how fast we should hint the Android sensors. */ + private static int sDefaultSensorHint = 100; + /* The Android-side API: API methods that Android calls */ // Initialization methods @@ -547,9 +550,9 @@ public class GeckoAppShell if (enable) { if (gAccelerometerSensor != null) - sm.registerListener(GeckoApp.mAppContext, gAccelerometerSensor, SensorManager.SENSOR_DELAY_GAME); + sm.registerListener(GeckoApp.mAppContext, gAccelerometerSensor, sDefaultSensorHint); if (gOrientationSensor != null) - sm.registerListener(GeckoApp.mAppContext, gOrientationSensor, SensorManager.SENSOR_DELAY_GAME); + sm.registerListener(GeckoApp.mAppContext, gOrientationSensor, sDefaultSensorHint); } else { if (gAccelerometerSensor != null) sm.unregisterListener(GeckoApp.mAppContext, gAccelerometerSensor); @@ -603,7 +606,7 @@ public class GeckoAppShell if(gProximitySensor == null) gProximitySensor = sm.getDefaultSensor(Sensor.TYPE_PROXIMITY); sm.registerListener(GeckoApp.mAppContext, gProximitySensor, - SensorManager.SENSOR_DELAY_GAME); + sDefaultSensorHint); break; } } From 3e44310837dd23097b048fcfbce75325039e5592 Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Tue, 13 Mar 2012 09:59:24 -0700 Subject: [PATCH 08/57] Bug 734325 - implement compassneedscalibration event. r=jdm --- dom/ipc/ContentChild.cpp | 10 +++++ dom/ipc/ContentChild.h | 2 + dom/ipc/ContentParent.cpp | 6 +++ dom/ipc/PContent.ipdl | 1 + dom/system/nsDeviceMotion.cpp | 58 ++++++++++++++++++++++++++ dom/system/nsDeviceMotion.h | 3 ++ mobile/android/base/GeckoApp.java | 2 + mobile/android/base/GeckoEvent.java | 13 ++++-- widget/android/AndroidJavaWrappers.cpp | 1 + widget/android/AndroidJavaWrappers.h | 1 + widget/android/nsAppShell.cpp | 11 +++-- xpcom/system/nsIDeviceMotion.idl | 6 ++- 12 files changed, 106 insertions(+), 8 deletions(-) diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index c81f30fd0545..459514bf8411 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -753,6 +753,16 @@ ContentChild::RecvDeviceMotionChanged(const long int& type, return true; } +bool +ContentChild::RecvNeedsCalibration() +{ + nsCOMPtr dmu = + do_GetService(NS_DEVICE_MOTION_CONTRACTID); + if (dmu) + dmu->NeedsCalibration(); + return true; +} + bool ContentChild::RecvScreenSizeChanged(const gfxIntSize& size) { diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index 206bf8342002..fafbe50bacd5 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -162,6 +162,8 @@ public: const double& x, const double& y, const double& z); + virtual bool RecvNeedsCalibration(); + virtual bool RecvScreenSizeChanged(const gfxIntSize &size); virtual bool RecvFlushMemory(const nsString& reason); diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 8507ac9a48c8..a237c87dbfff 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -1291,6 +1291,12 @@ ContentParent::OnMotionChange(nsIDeviceMotionData *aDeviceData) { return NS_OK; } +NS_IMETHODIMP +ContentParent::NeedsCalibration() { + unused << SendNeedsCalibration(); + return NS_OK; +} + } // namespace dom } // namespace mozilla diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 32efef5e119a..2e2823aa5600 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -134,6 +134,7 @@ child: AddPermission(Permission permission); DeviceMotionChanged(long type, double x, double y, double z); + NeedsCalibration(); ScreenSizeChanged(gfxIntSize size); diff --git a/dom/system/nsDeviceMotion.cpp b/dom/system/nsDeviceMotion.cpp index a986a1b44967..616f9e2c8926 100644 --- a/dom/system/nsDeviceMotion.cpp +++ b/dom/system/nsDeviceMotion.cpp @@ -261,6 +261,64 @@ nsDeviceMotion::DeviceMotionChanged(PRUint32 type, double x, double y, double z) return NS_OK; } +NS_IMETHODIMP +nsDeviceMotion::NeedsCalibration() +{ + if (!mEnabled) + return NS_ERROR_NOT_INITIALIZED; + + nsCOMArray listeners = mListeners; + for (PRUint32 i = listeners.Count(); i > 0 ; ) { + --i; + listeners[i]->NeedsCalibration(); + } + + nsCOMArray windowListeners; + for (PRUint32 i = 0; i < mWindowListeners.Length(); i++) { + windowListeners.AppendObject(mWindowListeners[i]); + } + + for (PRUint32 i = windowListeners.Count(); i > 0 ; ) { + --i; + + // check to see if this window is in the background. if + // it is, don't send any device motion to it. + nsCOMPtr pwindow = do_QueryInterface(windowListeners[i]); + if (!pwindow || + !pwindow->GetOuterWindow() || + pwindow->GetOuterWindow()->IsBackground()) + continue; + + nsCOMPtr domdoc; + windowListeners[i]->GetDocument(getter_AddRefs(domdoc)); + + if (domdoc) { + nsCOMPtr target = do_QueryInterface(windowListeners[i]); + FireNeedsCalibration(domdoc, target); + } + } + + return NS_OK; +} + +void +nsDeviceMotion::FireNeedsCalibration(nsIDOMDocument *domdoc, + nsIDOMEventTarget *target) +{ + nsCOMPtr event; + domdoc->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event)); + if (!event) + return; + + event->InitEvent(NS_LITERAL_STRING("compassneedscalibration"), true, false); + nsCOMPtr privateEvent = do_QueryInterface(event); + if (privateEvent) + privateEvent->SetTrusted(true); + + bool defaultActionEnabled = true; + target->DispatchEvent(event, &defaultActionEnabled); +} + void nsDeviceMotion::FireDOMOrientationEvent(nsIDOMDocument *domdoc, nsIDOMEventTarget *target, diff --git a/dom/system/nsDeviceMotion.h b/dom/system/nsDeviceMotion.h index eacdd48ccb58..68e0c7087078 100644 --- a/dom/system/nsDeviceMotion.h +++ b/dom/system/nsDeviceMotion.h @@ -76,6 +76,9 @@ private: protected: + void FireNeedsCalibration(nsIDOMDocument *domdoc, + nsIDOMEventTarget *target); + void FireDOMOrientationEvent(class nsIDOMDocument *domDoc, class nsIDOMEventTarget *target, double alpha, diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index 454418156a39..6de76b27ec0c 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -2608,6 +2608,8 @@ abstract public class GeckoApp // accelerometer public void onAccuracyChanged(Sensor sensor, int accuracy) { + Log.w(LOGTAG, "onAccuracyChanged "+accuracy); + GeckoAppShell.sendEventToGecko(GeckoEvent.createSensorAccuracyEvent(accuracy)); } public void onSensorChanged(SensorEvent event) diff --git a/mobile/android/base/GeckoEvent.java b/mobile/android/base/GeckoEvent.java index 7310b09a06f2..63b4244b966a 100644 --- a/mobile/android/base/GeckoEvent.java +++ b/mobile/android/base/GeckoEvent.java @@ -89,6 +89,7 @@ public class GeckoEvent { private static final int PROXIMITY_EVENT = 23; private static final int ACTIVITY_RESUMING = 24; private static final int SCREENSHOT = 25; + private static final int SENSOR_ACCURACY = 26; public static final int IME_COMPOSITION_END = 0; public static final int IME_COMPOSITION_BEGIN = 1; @@ -292,9 +293,9 @@ public class GeckoEvent { case Sensor.TYPE_ORIENTATION: event = new GeckoEvent(ORIENTATION_EVENT); - event.mAlpha = -s.values[0]; - event.mBeta = -s.values[1]; - event.mGamma = -s.values[2]; + event.mAlpha = s.values[0]; + event.mBeta = s.values[1]; + event.mGamma = s.values[2]; break; case Sensor.TYPE_PROXIMITY: @@ -408,4 +409,10 @@ public class GeckoEvent { event.mMetaState = tabId; return event; } + + public static GeckoEvent createSensorAccuracyEvent(int accuracy) { + GeckoEvent event = new GeckoEvent(SENSOR_ACCURACY); + event.mFlags = accuracy; + return event; + } } diff --git a/widget/android/AndroidJavaWrappers.cpp b/widget/android/AndroidJavaWrappers.cpp index f5b414ba61db..b3211988e0cd 100644 --- a/widget/android/AndroidJavaWrappers.cpp +++ b/widget/android/AndroidJavaWrappers.cpp @@ -473,6 +473,7 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj) break; } + case SENSOR_ACCURACY: case ACTIVITY_STOPPING: case ACTIVITY_START: case ACTIVITY_PAUSING: diff --git a/widget/android/AndroidJavaWrappers.h b/widget/android/AndroidJavaWrappers.h index 2bb9cda55bdf..36283bf73861 100644 --- a/widget/android/AndroidJavaWrappers.h +++ b/widget/android/AndroidJavaWrappers.h @@ -549,6 +549,7 @@ public: PROXIMITY_EVENT = 23, ACTIVITY_RESUMING = 24, SCREENSHOT = 25, + SENSOR_ACCURACY = 26, dummy_java_enum_list_end }; diff --git a/widget/android/nsAppShell.cpp b/widget/android/nsAppShell.cpp index 4a44ff40311a..ed34f9ac6cec 100644 --- a/widget/android/nsAppShell.cpp +++ b/widget/android/nsAppShell.cpp @@ -331,6 +331,11 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait) NativeEventCallback(); break; + case AndroidGeckoEvent::SENSOR_ACCURACY: + if (curEvent->Flags() == 0) + gDeviceMotionSystem->NeedsCalibration(); + break; + case AndroidGeckoEvent::ACCELERATION_EVENT: gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ACCELERATION, -curEvent->X(), @@ -340,9 +345,9 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait) case AndroidGeckoEvent::ORIENTATION_EVENT: gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ORIENTATION, - -curEvent->Alpha(), - curEvent->Beta(), - curEvent->Gamma()); + curEvent->Alpha(), + -curEvent->Beta(), + -curEvent->Gamma()); mPendingOrientationEvents = false; break; diff --git a/xpcom/system/nsIDeviceMotion.idl b/xpcom/system/nsIDeviceMotion.idl index f24144f6a3e6..b83c286be4ca 100644 --- a/xpcom/system/nsIDeviceMotion.idl +++ b/xpcom/system/nsIDeviceMotion.idl @@ -51,10 +51,11 @@ interface nsIDeviceMotionData : nsISupports readonly attribute double z; }; -[scriptable, uuid(f01774a2-3b7e-4630-954b-196dc178221f)] +[scriptable, uuid(D29EA788-CCB6-4875-88E0-32A34BB71CBB)] interface nsIDeviceMotionListener : nsISupports { void onMotionChange(in nsIDeviceMotionData aMotionData); + void needsCalibration(); }; [scriptable, uuid(B6E5C463-AAA6-44E2-BD07-7A7DC6192E68)] @@ -73,9 +74,10 @@ interface nsIDeviceMotion : nsISupports /* for use by IPC system to notify non-chrome processes of * device motion events */ -[uuid(d3a56f08-b7b1-46bb-9dc1-fc3665a3631a)] +[uuid(C12C0157-DCFF-41B5-83F3-89179BF6CA4E)] interface nsIDeviceMotionUpdate : nsIDeviceMotion { /* must be called on the main thread or else */ void deviceMotionChanged(in unsigned long type, in double x, in double y, in double z); + void needsCalibration(); }; From 10f24217b743edd7606498079535fdca46775c42 Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Tue, 13 Mar 2012 10:00:02 -0700 Subject: [PATCH 09/57] Bug 734324 - implement device motion - rotation rate and acceleration. r=jdm --- dom/system/nsDeviceMotion.cpp | 29 +++++-- dom/system/nsDeviceMotion.h | 1 + hal/HalSensor.h | 2 + mobile/android/base/GeckoAppShell.java | 102 ++++++++++++++--------- mobile/android/base/GeckoEvent.java | 43 +++++++--- mobile/android/base/GeckoHalDefines.java | 49 +++++++++++ mobile/android/base/Makefile.in | 1 + widget/android/AndroidBridge.cpp | 47 +++++++---- widget/android/AndroidBridge.h | 1 - widget/android/AndroidJavaWrappers.cpp | 23 ++--- widget/android/AndroidJavaWrappers.h | 11 +-- widget/android/nsAppShell.cpp | 57 +++++++++---- widget/android/nsAppShell.h | 2 +- xpcom/system/nsIDeviceMotion.idl | 2 + 14 files changed, 250 insertions(+), 120 deletions(-) create mode 100644 mobile/android/base/GeckoHalDefines.java diff --git a/dom/system/nsDeviceMotion.cpp b/dom/system/nsDeviceMotion.cpp index 616f9e2c8926..240c46422f40 100644 --- a/dom/system/nsDeviceMotion.cpp +++ b/dom/system/nsDeviceMotion.cpp @@ -252,8 +252,10 @@ nsDeviceMotion::DeviceMotionChanged(PRUint32 type, double x, double y, double z) if (domdoc) { nsCOMPtr target = do_QueryInterface(windowListeners[i]); - if (type == nsIDeviceMotionData::TYPE_ACCELERATION) - FireDOMMotionEvent(domdoc, target, x, y, z); + if (type == nsIDeviceMotionData::TYPE_ACCELERATION || + type == nsIDeviceMotionData::TYPE_LINEAR_ACCELERATION || + type == nsIDeviceMotionData::TYPE_GYROSCOPE ) + FireDOMMotionEvent(domdoc, target, type, x, y, z); else if (type == nsIDeviceMotionData::TYPE_ORIENTATION) FireDOMOrientationEvent(domdoc, target, x, y, z); } @@ -355,6 +357,7 @@ nsDeviceMotion::FireDOMOrientationEvent(nsIDOMDocument *domdoc, void nsDeviceMotion::FireDOMMotionEvent(nsIDOMDocument *domdoc, nsIDOMEventTarget *target, + PRUint32 type, double x, double y, double z) { @@ -368,15 +371,29 @@ nsDeviceMotion::FireDOMMotionEvent(nsIDOMDocument *domdoc, return; } - // Currently acceleration as determined includes gravity. - nsRefPtr acceleration = new nsDOMDeviceAcceleration(x, y, z); + nsRefPtr acceleration; + nsRefPtr accelerationIncluduingGravity; + nsRefPtr rotationRate; + + switch (type) { + case nsIDeviceMotionData::TYPE_LINEAR_ACCELERATION: + acceleration = new nsDOMDeviceAcceleration(x, y, z); + break; + case nsIDeviceMotionData::TYPE_ACCELERATION: + accelerationIncluduingGravity = new nsDOMDeviceAcceleration(x, y, z); + break; + case nsIDeviceMotionData::TYPE_GYROSCOPE: + rotationRate = new nsDOMDeviceRotationRate(x, y, z); + break; + } + me->InitDeviceMotionEvent(NS_LITERAL_STRING("devicemotion"), true, false, - nsnull, acceleration, - nsnull, + accelerationIncluduingGravity, + rotationRate, DEFAULT_SENSOR_POLL); nsCOMPtr privateEvent = do_QueryInterface(event); diff --git a/dom/system/nsDeviceMotion.h b/dom/system/nsDeviceMotion.h index 68e0c7087078..ba55f9f201b7 100644 --- a/dom/system/nsDeviceMotion.h +++ b/dom/system/nsDeviceMotion.h @@ -87,6 +87,7 @@ private: void FireDOMMotionEvent(class nsIDOMDocument *domDoc, class nsIDOMEventTarget *target, + PRUint32 type, double x, double y, double z); diff --git a/hal/HalSensor.h b/hal/HalSensor.h index de4d8edac458..521c061787a7 100644 --- a/hal/HalSensor.h +++ b/hal/HalSensor.h @@ -54,6 +54,8 @@ enum SensorType { SENSOR_ORIENTATION, SENSOR_ACCELERATION, SENSOR_PROXIMITY, + SENSOR_LINEAR_ACCELERATION, + SENSOR_GYROSCOPE, NUM_SENSOR_TYPE }; diff --git a/mobile/android/base/GeckoAppShell.java b/mobile/android/base/GeckoAppShell.java index 065dc5e1c86b..0950eb664628 100644 --- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -129,6 +129,12 @@ public class GeckoAppShell /* Default value of how fast we should hint the Android sensors. */ private static int sDefaultSensorHint = 100; + private static Sensor gAccelerometerSensor = null; + private static Sensor gLinearAccelerometerSensor = null; + private static Sensor gGyroscopeSensor = null; + private static Sensor gOrientationSensor = null; + private static Sensor gProximitySensor = null; + /* The Android-side API: API methods that Android calls */ // Initialization methods @@ -536,31 +542,6 @@ public class GeckoAppShell tmp.countDown(); } - static Sensor gAccelerometerSensor = null; - static Sensor gOrientationSensor = null; - - public static void enableDeviceMotion(boolean enable) { - LayerView v = GeckoApp.mAppContext.getLayerController().getView(); - SensorManager sm = (SensorManager) v.getContext().getSystemService(Context.SENSOR_SERVICE); - - if (gAccelerometerSensor == null || gOrientationSensor == null) { - gAccelerometerSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); - gOrientationSensor = sm.getDefaultSensor(Sensor.TYPE_ORIENTATION); - } - - if (enable) { - if (gAccelerometerSensor != null) - sm.registerListener(GeckoApp.mAppContext, gAccelerometerSensor, sDefaultSensorHint); - if (gOrientationSensor != null) - sm.registerListener(GeckoApp.mAppContext, gOrientationSensor, sDefaultSensorHint); - } else { - if (gAccelerometerSensor != null) - sm.unregisterListener(GeckoApp.mAppContext, gAccelerometerSensor); - if (gOrientationSensor != null) - sm.unregisterListener(GeckoApp.mAppContext, gOrientationSensor); - } - } - public static void enableLocation(final boolean enable) { getMainHandler().post(new Runnable() { public void run() { @@ -588,26 +569,46 @@ public class GeckoAppShell }); } - /* - * Keep these values consistent with |SensorType| in Hal.h - */ - private static final int SENSOR_ORIENTATION = 1; - private static final int SENSOR_ACCELERATION = 2; - private static final int SENSOR_PROXIMITY = 3; - - private static Sensor gProximitySensor = null; - public static void enableSensor(int aSensortype) { SensorManager sm = (SensorManager) GeckoApp.mAppContext.getSystemService(Context.SENSOR_SERVICE); switch(aSensortype) { - case SENSOR_PROXIMITY: + case GeckoHalDefines.SENSOR_ORIENTATION: + if(gOrientationSensor == null) + gOrientationSensor = sm.getDefaultSensor(Sensor.TYPE_ORIENTATION); + if (gOrientationSensor != null) + sm.registerListener(GeckoApp.mAppContext, gOrientationSensor, sDefaultSensorHint); + break; + + case GeckoHalDefines.SENSOR_ACCELERATION: + if(gAccelerometerSensor == null) + gAccelerometerSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + if (gAccelerometerSensor != null) + sm.registerListener(GeckoApp.mAppContext, gAccelerometerSensor, sDefaultSensorHint); + break; + + case GeckoHalDefines.SENSOR_PROXIMITY: if(gProximitySensor == null) gProximitySensor = sm.getDefaultSensor(Sensor.TYPE_PROXIMITY); - sm.registerListener(GeckoApp.mAppContext, gProximitySensor, - sDefaultSensorHint); + if (gProximitySensor != null) + sm.registerListener(GeckoApp.mAppContext, gProximitySensor, sDefaultSensorHint); break; + + case GeckoHalDefines.SENSOR_LINEAR_ACCELERATION: + if(gLinearAccelerometerSensor == null) + gLinearAccelerometerSensor = sm.getDefaultSensor(10); + if (gLinearAccelerometerSensor != null) + sm.registerListener(GeckoApp.mAppContext, gLinearAccelerometerSensor, sDefaultSensorHint); + break; + + case GeckoHalDefines.SENSOR_GYROSCOPE: + if(gGyroscopeSensor == null) + gGyroscopeSensor = sm.getDefaultSensor(Sensor.TYPE_GYROSCOPE); + if (gGyroscopeSensor != null) + sm.registerListener(GeckoApp.mAppContext, gGyroscopeSensor, sDefaultSensorHint); + break; + } } @@ -615,9 +616,30 @@ public class GeckoAppShell SensorManager sm = (SensorManager) GeckoApp.mAppContext.getSystemService(Context.SENSOR_SERVICE); - switch(aSensortype) { - case SENSOR_PROXIMITY: - sm.unregisterListener(GeckoApp.mAppContext, gProximitySensor); + switch (aSensortype) { + case GeckoHalDefines.SENSOR_ORIENTATION: + if (gOrientationSensor != null) + sm.unregisterListener(GeckoApp.mAppContext, gOrientationSensor); + break; + + case GeckoHalDefines.SENSOR_ACCELERATION: + if (gAccelerometerSensor != null) + sm.unregisterListener(GeckoApp.mAppContext, gAccelerometerSensor); + break; + + case GeckoHalDefines.SENSOR_PROXIMITY: + if (gProximitySensor != null) + sm.unregisterListener(GeckoApp.mAppContext, gProximitySensor); + break; + + case GeckoHalDefines.SENSOR_LINEAR_ACCELERATION: + if (gLinearAccelerometerSensor != null) + sm.unregisterListener(GeckoApp.mAppContext, gLinearAccelerometerSensor); + break; + + case GeckoHalDefines.SENSOR_GYROSCOPE: + if (gGyroscopeSensor != null) + sm.unregisterListener(GeckoApp.mAppContext, gGyroscopeSensor); break; } } diff --git a/mobile/android/base/GeckoEvent.java b/mobile/android/base/GeckoEvent.java index 63b4244b966a..e3b4f80b986e 100644 --- a/mobile/android/base/GeckoEvent.java +++ b/mobile/android/base/GeckoEvent.java @@ -52,6 +52,7 @@ import android.util.DisplayMetrics; import android.graphics.PointF; import android.text.format.Time; import android.os.SystemClock; +import java.lang.Math; import java.lang.System; import android.util.Log; @@ -68,8 +69,8 @@ public class GeckoEvent { private static final int NATIVE_POKE = 0; private static final int KEY_EVENT = 1; private static final int MOTION_EVENT = 2; - private static final int ORIENTATION_EVENT = 3; - private static final int ACCELERATION_EVENT = 4; + private static final int SENSOR_EVENT = 3; + private static final int UNUSED1_EVENT = 4; private static final int LOCATION_EVENT = 5; private static final int IME_EVENT = 6; private static final int DRAW = 7; @@ -121,7 +122,6 @@ public class GeckoEvent { public Point[] mPointRadii; public Rect mRect; public double mX, mY, mZ; - public double mAlpha, mBeta, mGamma; public double mDistance; public int mMetaState, mFlags; @@ -280,25 +280,46 @@ public class GeckoEvent { } public static GeckoEvent createSensorEvent(SensorEvent s) { - GeckoEvent event = null; int sensor_type = s.sensor.getType(); - + GeckoEvent event = null; + switch(sensor_type) { + case Sensor.TYPE_ACCELEROMETER: - event = new GeckoEvent(ACCELERATION_EVENT); + event = new GeckoEvent(SENSOR_EVENT); + event.mFlags = GeckoHalDefines.SENSOR_ACCELERATION; event.mX = s.values[0]; event.mY = s.values[1]; event.mZ = s.values[2]; break; - + + case 10 /* Requires API Level 9, so just use the raw value - Sensor.TYPE_LINEAR_ACCELEROMETER*/ : + event = new GeckoEvent(SENSOR_EVENT); + event.mFlags = GeckoHalDefines.SENSOR_LINEAR_ACCELERATION; + event.mX = s.values[0]; + event.mY = s.values[1]; + event.mZ = s.values[2]; + break; + case Sensor.TYPE_ORIENTATION: - event = new GeckoEvent(ORIENTATION_EVENT); - event.mAlpha = s.values[0]; - event.mBeta = s.values[1]; - event.mGamma = s.values[2]; + event = new GeckoEvent(SENSOR_EVENT); + event.mFlags = GeckoHalDefines.SENSOR_ORIENTATION; + event.mX = s.values[0]; + event.mY = s.values[1]; + event.mZ = s.values[2]; + break; + + case Sensor.TYPE_GYROSCOPE: + event = new GeckoEvent(SENSOR_EVENT); + event.mFlags = GeckoHalDefines.SENSOR_GYROSCOPE; + event.mX = Math.toDegrees(s.values[0]); + event.mY = Math.toDegrees(s.values[1]); + event.mZ = Math.toDegrees(s.values[2]); break; case Sensor.TYPE_PROXIMITY: + // bug 734854 - maybe we can get rid of this event. is + // values[1] and values[2] valid? event = new GeckoEvent(PROXIMITY_EVENT); event.mDistance = s.values[0]; break; diff --git a/mobile/android/base/GeckoHalDefines.java b/mobile/android/base/GeckoHalDefines.java new file mode 100644 index 000000000000..ea6e02e06513 --- /dev/null +++ b/mobile/android/base/GeckoHalDefines.java @@ -0,0 +1,49 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Android code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2012 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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; + +public class GeckoHalDefines +{ + /* + * Keep these values consistent with |SensorType| in Hal.h + */ + public static final int SENSOR_ORIENTATION = 0; + public static final int SENSOR_ACCELERATION = 1; + public static final int SENSOR_PROXIMITY = 2; + public static final int SENSOR_LINEAR_ACCELERATION = 3; + public static final int SENSOR_GYROSCOPE = 4; +}; diff --git a/mobile/android/base/Makefile.in b/mobile/android/base/Makefile.in index 7e70708fa217..86a416c9ed1d 100644 --- a/mobile/android/base/Makefile.in +++ b/mobile/android/base/Makefile.in @@ -87,6 +87,7 @@ FENNEC_JAVA_FILES = \ GeckoEvent.java \ GeckoEventListener.java \ GeckoEventResponder.java \ + GeckoHalDefines.java \ GeckoInputConnection.java \ GeckoMessageReceiver.java \ GeckoPreferences.java \ diff --git a/widget/android/AndroidBridge.cpp b/widget/android/AndroidBridge.cpp index be5ec97216e9..30311c11ab17 100644 --- a/widget/android/AndroidBridge.cpp +++ b/widget/android/AndroidBridge.cpp @@ -111,14 +111,9 @@ AndroidBridge::Init(JNIEnv *jEnv, jNotifyScreenShot = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "notifyScreenShot", "(Ljava/nio/ByteBuffer;III)V"); jAcknowledgeEventSync = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "acknowledgeEventSync", "()V"); - jEnableDeviceMotion = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "enableDeviceMotion", "(Z)V"); jEnableLocation = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "enableLocation", "(Z)V"); - jEnableSensor = - (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, - "enableSensor", "(I)V"); - jDisableSensor = - (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, - "disableSensor", "(I)V"); + jEnableSensor = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "enableSensor", "(I)V"); + jDisableSensor = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "disableSensor", "(I)V"); jReturnIMEQueryResult = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "returnIMEQueryResult", "(Ljava/lang/String;II)V"); jScheduleRestart = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "scheduleRestart", "()V"); jNotifyXreExit = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "onXreExit", "()V"); @@ -311,13 +306,23 @@ AndroidBridge::EnableDeviceMotion(bool aEnable) { ALOG_BRIDGE("AndroidBridge::EnableDeviceMotion"); - JNIEnv *env = GetJNIEnv(); - if (!env) - return; - - env->CallStaticVoidMethod(mGeckoAppShellClass, jEnableDeviceMotion, aEnable); + // bug 734855 - we probably can make this finer grain based on + // the DOM APIs that are being invoked. + if (aEnable) { + EnableSensor(hal::SENSOR_ORIENTATION); + EnableSensor(hal::SENSOR_ACCELERATION); + EnableSensor(hal::SENSOR_LINEAR_ACCELERATION); + EnableSensor(hal::SENSOR_GYROSCOPE); + } + else { + DisableSensor(hal::SENSOR_ORIENTATION); + DisableSensor(hal::SENSOR_ACCELERATION); + DisableSensor(hal::SENSOR_LINEAR_ACCELERATION); + DisableSensor(hal::SENSOR_GYROSCOPE); + } } + void AndroidBridge::EnableLocation(bool aEnable) { @@ -326,22 +331,30 @@ AndroidBridge::EnableLocation(bool aEnable) JNIEnv *env = GetJNIEnv(); if (!env) return; - + + AutoLocalJNIFrame jniFrame(env, 1); env->CallStaticVoidMethod(mGeckoAppShellClass, jEnableLocation, aEnable); } void AndroidBridge::EnableSensor(int aSensorType) { ALOG_BRIDGE("AndroidBridge::EnableSensor"); - mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jEnableSensor, - aSensorType); + JNIEnv *env = GetJNIEnv(); + if (!env) + return; + + AutoLocalJNIFrame jniFrame(env, 1); + env->CallStaticVoidMethod(mGeckoAppShellClass, jEnableSensor, aSensorType); } void AndroidBridge::DisableSensor(int aSensorType) { ALOG_BRIDGE("AndroidBridge::DisableSensor"); - mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jDisableSensor, - aSensorType); + JNIEnv *env = GetJNIEnv(); + if (!env) + return; + AutoLocalJNIFrame jniFrame(env, 1); + env->CallStaticVoidMethod(mGeckoAppShellClass, jDisableSensor, aSensorType); } void diff --git a/widget/android/AndroidBridge.h b/widget/android/AndroidBridge.h index 54c9e35b8667..391259fb56fe 100644 --- a/widget/android/AndroidBridge.h +++ b/widget/android/AndroidBridge.h @@ -424,7 +424,6 @@ protected: jmethodID jNotifyIMEChange; jmethodID jNotifyScreenShot; jmethodID jAcknowledgeEventSync; - jmethodID jEnableDeviceMotion; jmethodID jEnableLocation; jmethodID jEnableSensor; jmethodID jDisableSensor; diff --git a/widget/android/AndroidJavaWrappers.cpp b/widget/android/AndroidJavaWrappers.cpp index b3211988e0cd..48ff3cc6be95 100644 --- a/widget/android/AndroidJavaWrappers.cpp +++ b/widget/android/AndroidJavaWrappers.cpp @@ -49,9 +49,6 @@ jfieldID AndroidGeckoEvent::jPointIndicies = 0; jfieldID AndroidGeckoEvent::jPressures = 0; jfieldID AndroidGeckoEvent::jPointRadii = 0; jfieldID AndroidGeckoEvent::jOrientations = 0; -jfieldID AndroidGeckoEvent::jAlphaField = 0; -jfieldID AndroidGeckoEvent::jBetaField = 0; -jfieldID AndroidGeckoEvent::jGammaField = 0; jfieldID AndroidGeckoEvent::jXField = 0; jfieldID AndroidGeckoEvent::jYField = 0; jfieldID AndroidGeckoEvent::jZField = 0; @@ -148,9 +145,6 @@ AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv) jOrientations = getField("mOrientations", "[F"); jPressures = getField("mPressures", "[F"); jPointRadii = getField("mPointRadii", "[Landroid/graphics/Point;"); - jAlphaField = getField("mAlpha", "D"); - jBetaField = getField("mBeta", "D"); - jGammaField = getField("mGamma", "D"); jXField = getField("mX", "D"); jYField = getField("mY", "D"); jZField = getField("mZ", "D"); @@ -427,17 +421,12 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj) ReadRectField(jenv); break; - case ORIENTATION_EVENT: - mAlpha = jenv->GetDoubleField(jobj, jAlphaField); - mBeta = jenv->GetDoubleField(jobj, jBetaField); - mGamma = jenv->GetDoubleField(jobj, jGammaField); - break; - - case ACCELERATION_EVENT: - mX = jenv->GetDoubleField(jobj, jXField); - mY = jenv->GetDoubleField(jobj, jYField); - mZ = jenv->GetDoubleField(jobj, jZField); - break; + case SENSOR_EVENT: + mX = jenv->GetDoubleField(jobj, jXField); + mY = jenv->GetDoubleField(jobj, jYField); + mZ = jenv->GetDoubleField(jobj, jZField); + mFlags = jenv->GetIntField(jobj, jFlagsField); + break; case LOCATION_EVENT: { jobject location = jenv->GetObjectField(jobj, jLocationField); diff --git a/widget/android/AndroidJavaWrappers.h b/widget/android/AndroidJavaWrappers.h index 36283bf73861..af3de14482fb 100644 --- a/widget/android/AndroidJavaWrappers.h +++ b/widget/android/AndroidJavaWrappers.h @@ -420,9 +420,6 @@ public: nsTArray Pressures() { return mPressures; } nsTArray Orientations() { return mOrientations; } nsTArray PointRadii() { return mPointRadii; } - double Alpha() { return mAlpha; } - double Beta() { return mBeta; } - double Gamma() { return mGamma; } double X() { return mX; } double Y() { return mY; } double Z() { return mZ; } @@ -460,7 +457,6 @@ protected: int mOffset, mCount; int mRangeType, mRangeStyles; int mRangeForeColor, mRangeBackColor; - double mAlpha, mBeta, mGamma; double mX, mY, mZ; double mDistance; int mPointerIndex; @@ -494,9 +490,6 @@ protected: static jfieldID jOrientations; static jfieldID jPressures; static jfieldID jPointRadii; - static jfieldID jAlphaField; - static jfieldID jBetaField; - static jfieldID jGammaField; static jfieldID jXField; static jfieldID jYField; static jfieldID jZField; @@ -527,8 +520,8 @@ public: NATIVE_POKE = 0, KEY_EVENT = 1, MOTION_EVENT = 2, - ORIENTATION_EVENT = 3, - ACCELERATION_EVENT = 4, + SENSOR_EVENT = 3, + UNUSED1_EVENT = 4, LOCATION_EVENT = 5, IME_EVENT = 6, DRAW = 7, diff --git a/widget/android/nsAppShell.cpp b/widget/android/nsAppShell.cpp index ed34f9ac6cec..631dc52fdd4d 100644 --- a/widget/android/nsAppShell.cpp +++ b/widget/android/nsAppShell.cpp @@ -96,7 +96,7 @@ nsAppShell::nsAppShell() mQueueCond(mCondLock, "nsAppShell.mQueueCond"), mNumDraws(0), mNumViewports(0), - mPendingOrientationEvents(false) + mPendingSensorEvents(false) { gAppShell = this; } @@ -336,20 +336,41 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait) gDeviceMotionSystem->NeedsCalibration(); break; - case AndroidGeckoEvent::ACCELERATION_EVENT: - gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ACCELERATION, - -curEvent->X(), - curEvent->Y(), - curEvent->Z()); - break; + case AndroidGeckoEvent::SENSOR_EVENT: + mPendingSensorEvents = false; + switch (curEvent->Flags()) { + case hal::SENSOR_ORIENTATION: + gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ORIENTATION, + curEvent->X(), + -curEvent->Y(), + -curEvent->Z()); + break; - case AndroidGeckoEvent::ORIENTATION_EVENT: - gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ORIENTATION, - curEvent->Alpha(), - -curEvent->Beta(), - -curEvent->Gamma()); - mPendingOrientationEvents = false; - break; + case hal::SENSOR_ACCELERATION: + gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ACCELERATION, + -curEvent->X(), + curEvent->Y(), + curEvent->Z()); + break; + + case hal::SENSOR_LINEAR_ACCELERATION: + gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_LINEAR_ACCELERATION, + -curEvent->X(), + curEvent->Y(), + curEvent->Z()); + break; + + case hal::SENSOR_GYROSCOPE: + gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_GYROSCOPE, + -curEvent->X(), + curEvent->Y(), + curEvent->Z()); + break; + + default: + __android_log_print(ANDROID_LOG_ERROR, "Gecko", "### SENSOR_EVENT fired, but type wasn't known %d", curEvent->Flags()); + } + break; case AndroidGeckoEvent::LOCATION_EVENT: { if (!gLocationCallback) @@ -603,10 +624,10 @@ nsAppShell::PostEvent(AndroidGeckoEvent *ae) delete event; } } - } else if (ae->Type() == AndroidGeckoEvent::ORIENTATION_EVENT) { - if (!mPendingOrientationEvents) - mEventQueue.AppendElement(ae); - mPendingOrientationEvents = true; + } else if (ae->Type() == AndroidGeckoEvent::SENSOR_EVENT) { + if (!mPendingSensorEvents) + mEventQueue.AppendElement(ae); + mPendingSensorEvents = true; } else { mEventQueue.AppendElement(ae); } diff --git a/widget/android/nsAppShell.h b/widget/android/nsAppShell.h index ef43ae356e21..f86964dd8f59 100644 --- a/widget/android/nsAppShell.h +++ b/widget/android/nsAppShell.h @@ -110,7 +110,7 @@ protected: mozilla::AndroidGeckoEvent *PeekNextEvent(); nsCOMPtr mBrowserApp; - bool mPendingOrientationEvents; + bool mPendingSensorEvents; }; #endif // nsAppShell_h__ diff --git a/xpcom/system/nsIDeviceMotion.idl b/xpcom/system/nsIDeviceMotion.idl index b83c286be4ca..79313d898388 100644 --- a/xpcom/system/nsIDeviceMotion.idl +++ b/xpcom/system/nsIDeviceMotion.idl @@ -43,6 +43,8 @@ interface nsIDeviceMotionData : nsISupports { const unsigned long TYPE_ACCELERATION = 0; const unsigned long TYPE_ORIENTATION = 1; + const unsigned long TYPE_LINEAR_ACCELERATION = 2; + const unsigned long TYPE_GYROSCOPE = 3; readonly attribute unsigned long type; From 49f687955e5e4613aff7aaf3530f337ac51c47da Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Fri, 9 Mar 2012 10:40:43 -0800 Subject: [PATCH 10/57] Bug 734391 - coalesce the device motion events. r=jdm --- dom/system/Makefile.in | 3 ++ dom/system/android/Makefile.in | 1 + dom/system/cocoa/Makefile.in | 3 ++ dom/system/nsDeviceMotion.cpp | 56 +++++++++++++++++++--------------- dom/system/nsDeviceMotion.h | 12 +++++++- dom/system/unix/Makefile.in | 3 ++ dom/system/windows/Makefile.in | 3 ++ 7 files changed, 56 insertions(+), 25 deletions(-) diff --git a/dom/system/Makefile.in b/dom/system/Makefile.in index ce9346ba491e..b5b2062fa996 100644 --- a/dom/system/Makefile.in +++ b/dom/system/Makefile.in @@ -87,6 +87,9 @@ EXPORTS = \ nsDeviceMotion.h \ $(NULL) +# We fire the nsDOMDeviceAcceleration +LOCAL_INCLUDES += -I$(topsrcdir)/content/events/src + include $(topsrcdir)/config/config.mk # we don't want the shared lib, but we want to force the creation of a static lib. diff --git a/dom/system/android/Makefile.in b/dom/system/android/Makefile.in index 48cf9473c350..6f79c35fd085 100644 --- a/dom/system/android/Makefile.in +++ b/dom/system/android/Makefile.in @@ -59,6 +59,7 @@ CPPSRCS = \ $(NULL) LOCAL_INCLUDES += -I$(topsrcdir)/dom/src/geolocation \ + -I$(topsrcdir)/content/events/src $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/dom/system/cocoa/Makefile.in b/dom/system/cocoa/Makefile.in index 77041a2b87b6..7853d19a71d5 100644 --- a/dom/system/cocoa/Makefile.in +++ b/dom/system/cocoa/Makefile.in @@ -49,6 +49,9 @@ LIBXUL_LIBRARY = 1 FORCE_STATIC_LIB = 1 EXPORT_LIBRARY = 1 +# We fire the nsDOMDeviceAcceleration +LOCAL_INCLUDES += -I$(topsrcdir)/content/events/src + include $(topsrcdir)/config/config.mk CMMSRCS = \ diff --git a/dom/system/nsDeviceMotion.cpp b/dom/system/nsDeviceMotion.cpp index 240c46422f40..e16f64a1aa7d 100644 --- a/dom/system/nsDeviceMotion.cpp +++ b/dom/system/nsDeviceMotion.cpp @@ -44,11 +44,11 @@ #include "nsIDOMEventTarget.h" #include "nsIServiceManager.h" #include "nsIPrivateDOMEvent.h" -#include "nsIDOMDeviceOrientationEvent.h" -#include "nsIDOMDeviceMotionEvent.h" #include "nsIServiceManager.h" #include "nsIPrefService.h" -#include "nsDOMDeviceMotionEvent.h" + +using mozilla::TimeStamp; +using mozilla::TimeDuration; // also see sDefaultSensorHint in mobile/android/base/GeckoAppShell.java #define DEFAULT_SENSOR_POLL 100 @@ -361,45 +361,53 @@ nsDeviceMotion::FireDOMMotionEvent(nsIDOMDocument *domdoc, double x, double y, double z) { + // Attempt to coalesce events + bool fireEvent = TimeStamp::Now() > mLastDOMMotionEventTime + TimeDuration::FromMilliseconds(DEFAULT_SENSOR_POLL); + + switch (type) { + case nsIDeviceMotionData::TYPE_LINEAR_ACCELERATION: + mLastAcceleration = new nsDOMDeviceAcceleration(x, y, z); + break; + case nsIDeviceMotionData::TYPE_ACCELERATION: + mLastAccelerationIncluduingGravity = new nsDOMDeviceAcceleration(x, y, z); + break; + case nsIDeviceMotionData::TYPE_GYROSCOPE: + mLastRotationRate = new nsDOMDeviceRotationRate(x, y, z); + break; + } + + if (!fireEvent && (!mLastAcceleration || !mLastAccelerationIncluduingGravity || !mLastRotationRate)) { + return; + } + nsCOMPtr event; - bool defaultActionEnabled = true; domdoc->CreateEvent(NS_LITERAL_STRING("DeviceMotionEvent"), getter_AddRefs(event)); nsCOMPtr me = do_QueryInterface(event); if (!me) { return; -} - - nsRefPtr acceleration; - nsRefPtr accelerationIncluduingGravity; - nsRefPtr rotationRate; - - switch (type) { - case nsIDeviceMotionData::TYPE_LINEAR_ACCELERATION: - acceleration = new nsDOMDeviceAcceleration(x, y, z); - break; - case nsIDeviceMotionData::TYPE_ACCELERATION: - accelerationIncluduingGravity = new nsDOMDeviceAcceleration(x, y, z); - break; - case nsIDeviceMotionData::TYPE_GYROSCOPE: - rotationRate = new nsDOMDeviceRotationRate(x, y, z); - break; } - me->InitDeviceMotionEvent(NS_LITERAL_STRING("devicemotion"), true, false, - acceleration, - accelerationIncluduingGravity, - rotationRate, + mLastAcceleration, + mLastAccelerationIncluduingGravity, + mLastRotationRate, DEFAULT_SENSOR_POLL); nsCOMPtr privateEvent = do_QueryInterface(event); if (privateEvent) privateEvent->SetTrusted(true); + bool defaultActionEnabled = true; target->DispatchEvent(event, &defaultActionEnabled); + + mLastRotationRate = nsnull; + mLastAccelerationIncluduingGravity = nsnull; + mLastAcceleration = nsnull; + mLastDOMMotionEventTime = TimeStamp::Now(); + } diff --git a/dom/system/nsDeviceMotion.h b/dom/system/nsDeviceMotion.h index ba55f9f201b7..1618a6c73b57 100644 --- a/dom/system/nsDeviceMotion.h +++ b/dom/system/nsDeviceMotion.h @@ -43,6 +43,10 @@ #include "nsTArray.h" #include "nsCOMPtr.h" #include "nsITimer.h" +#include "nsIDOMDeviceOrientationEvent.h" +#include "nsIDOMDeviceMotionEvent.h" +#include "nsDOMDeviceMotionEvent.h" +#include "mozilla/TimeStamp.h" #define NS_DEVICE_MOTION_CID \ { 0xecba5203, 0x77da, 0x465a, \ @@ -91,10 +95,16 @@ private: double x, double y, double z); - bool mEnabled; virtual void Startup() = 0; virtual void Shutdown() = 0; + + bool mEnabled; + mozilla::TimeStamp mLastDOMMotionEventTime; + nsRefPtr mLastAcceleration; + nsRefPtr mLastAccelerationIncluduingGravity; + nsRefPtr mLastRotationRate; + }; #endif diff --git a/dom/system/unix/Makefile.in b/dom/system/unix/Makefile.in index fa443281fea6..7414673faeee 100644 --- a/dom/system/unix/Makefile.in +++ b/dom/system/unix/Makefile.in @@ -82,4 +82,7 @@ LOCAL_INCLUDES += $(MOZ_QT_CFLAGS) \ endif endif +# We fire the nsDOMDeviceAcceleration +LOCAL_INCLUDES += -I$(topsrcdir)/content/events/src + include $(topsrcdir)/config/rules.mk diff --git a/dom/system/windows/Makefile.in b/dom/system/windows/Makefile.in index 551a54921bfc..cd8319e75428 100644 --- a/dom/system/windows/Makefile.in +++ b/dom/system/windows/Makefile.in @@ -49,6 +49,9 @@ LIBXUL_LIBRARY = 1 FORCE_STATIC_LIB = 1 EXPORT_LIBRARY = 1 +# We fire the nsDOMDeviceAcceleration +LOCAL_INCLUDES += -I$(topsrcdir)/content/events/src + include $(topsrcdir)/config/config.mk CPPSRCS = \ From b88d1ebc47fa09322daaa2bc875699581a64dc07 Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Tue, 13 Mar 2012 13:01:26 -0400 Subject: [PATCH 11/57] Bug 661293 - add mochitest for content alert() relations, r=marcoz --- .../tests/mochitest/relations/Makefile.in | 1 + .../relations/test_ui_modalprompt.html | 95 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 accessible/tests/mochitest/relations/test_ui_modalprompt.html diff --git a/accessible/tests/mochitest/relations/Makefile.in b/accessible/tests/mochitest/relations/Makefile.in index 077884060a66..a447b4699a01 100644 --- a/accessible/tests/mochitest/relations/Makefile.in +++ b/accessible/tests/mochitest/relations/Makefile.in @@ -52,6 +52,7 @@ _TEST_FILES =\ test_general.xul \ test_tabbrowser.xul \ test_tree.xul \ + test_ui_modalprompt.html \ test_update.html \ $(NULL) diff --git a/accessible/tests/mochitest/relations/test_ui_modalprompt.html b/accessible/tests/mochitest/relations/test_ui_modalprompt.html new file mode 100644 index 000000000000..8ac2e6045e4c --- /dev/null +++ b/accessible/tests/mochitest/relations/test_ui_modalprompt.html @@ -0,0 +1,95 @@ + + + + Modal prompts + + + + + + + + + + + + + + + + + + + Mozilla Bug 661293 + +
    +

    + +
    +  
    + + + From 0ba328a50790a0a584f6ec96eb1523b19506f570 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Mon, 5 Mar 2012 15:33:24 -0800 Subject: [PATCH 12/57] Bug 531396 - Expose detailed GC timing information API; r=smaug,billm Extensions such as MemChaser would really like an easier to parse and more complete record of GC events than what can be gleaned from the message console. This patch adds GC and CC observer messages formatted as JSON containing detailed statistics. --- dom/base/nsJSEnvironment.cpp | 77 ++++++- js/src/gc/Statistics.cpp | 385 +++++++++++++++++++++++++++-------- js/src/gc/Statistics.h | 14 +- js/src/jsarray.cpp | 1 - js/src/jsfriendapi.cpp | 12 ++ js/src/jsfriendapi.h | 10 +- 6 files changed, 392 insertions(+), 107 deletions(-) diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 51049168fd08..b537f582fb43 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -3161,6 +3161,44 @@ nsJSContext::CycleCollectNow(nsICycleCollectorListener *aListener, if (cs) { cs->LogStringMessage(msg.get()); } + + NS_NAMED_MULTILINE_LITERAL_STRING(kJSONFmt, + NS_LL("{ \"duration\": %llu, ") + NS_LL("\"suspected\": %lu, ") + NS_LL("\"visited\": { ") + NS_LL("\"RCed\": %lu, ") + NS_LL("\"GCed\": %lu }, ") + NS_LL("\"collected\": { ") + NS_LL("\"RCed\": %lu, ") + NS_LL("\"GCed\": %lu }, ") + NS_LL("\"waiting_for_gc\": %lu, ") + NS_LL("\"forced_gc\": %d, ") + NS_LL("\"forget_skippable\": { ") + NS_LL("\"times_before_cc\": %lu, ") + NS_LL("\"min\": %lu, ") + NS_LL("\"max\": %lu, ") + NS_LL("\"avg\": %lu, ") + NS_LL("\"total\": %lu, ") + NS_LL("\"removed\": %lu } ") + NS_LL("}")); + nsString json; + json.Adopt(nsTextFormatter::smprintf(kJSONFmt.get(), + (now - start) / PR_USEC_PER_MSEC, suspected, + ccResults.mVisitedRefCounted, ccResults.mVisitedGCed, + ccResults.mFreedRefCounted, ccResults.mFreedGCed, + sCCollectedWaitingForGC, + ccResults.mForcedGC, + sForgetSkippableBeforeCC, + sMinForgetSkippableTime / PR_USEC_PER_MSEC, + sMaxForgetSkippableTime / PR_USEC_PER_MSEC, + (sTotalForgetSkippableTime / cleanups) / + PR_USEC_PER_MSEC, + sTotalForgetSkippableTime / PR_USEC_PER_MSEC, + sRemovedPurples)); + nsCOMPtr observerService = mozilla::services::GetObserverService(); + if (observerService) { + observerService->NotifyObservers(nsnull, "cycle-collection-statistics", json.get()); + } } sMinForgetSkippableTime = PR_UINT32_MAX; sMaxForgetSkippableTime = 0; @@ -3417,12 +3455,39 @@ nsJSContext::GC(js::gcreason::Reason aReason) PokeGC(aReason); } +class NotifyGCEndRunnable : public nsRunnable +{ + nsString mMessage; + +public: + NotifyGCEndRunnable(const nsString& aMessage) : mMessage(aMessage) {} + + NS_DECL_NSIRUNNABLE +}; + +NS_IMETHODIMP +NotifyGCEndRunnable::Run() +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsCOMPtr observerService = mozilla::services::GetObserverService(); + if (!observerService) { + return NS_OK; + } + + const jschar oomMsg[3] = { '{', '}', 0 }; + const jschar *toSend = mMessage.get() ? mMessage.get() : oomMsg; + observerService->NotifyObservers(nsnull, "garbage-collection-statistics", toSend); + + return NS_OK; +} + static void DOMGCSliceCallback(JSRuntime *aRt, js::GCProgress aProgress, const js::GCDescription &aDesc) { NS_ASSERTION(NS_IsMainThread(), "GCs must run on the main thread"); - if (aDesc.logMessage && sPostGCEventsToConsole) { + if (aProgress == js::GC_CYCLE_END && sPostGCEventsToConsole) { PRTime now = PR_Now(); PRTime delta = 0; if (sFirstCollectionTime) { @@ -3432,10 +3497,11 @@ DOMGCSliceCallback(JSRuntime *aRt, js::GCProgress aProgress, const js::GCDescrip } NS_NAMED_LITERAL_STRING(kFmt, "GC(T+%.1f) %s"); - nsString msg; + nsString msg, gcstats; + gcstats.Adopt(aDesc.formatMessage(aRt)); msg.Adopt(nsTextFormatter::smprintf(kFmt.get(), double(delta) / PR_USEC_PER_SEC, - aDesc.logMessage)); + gcstats.get())); nsCOMPtr cs = do_GetService(NS_CONSOLESERVICE_CONTRACTID); if (cs) { cs->LogStringMessage(msg.get()); @@ -3463,6 +3529,11 @@ DOMGCSliceCallback(JSRuntime *aRt, js::GCProgress aProgress, const js::GCDescrip sCCollectedWaitingForGC = 0; sCleanupSinceLastGC = false; + nsString json; + json.Adopt(aDesc.formatJSON(aRt)); + nsRefPtr notify = new NotifyGCEndRunnable(json); + NS_DispatchToMainThread(notify); + if (aDesc.isCompartment) { // If this is a compartment GC, restart it. We still want // a full GC to happen. Compartment GCs usually happen as a diff --git a/js/src/gc/Statistics.cpp b/js/src/gc/Statistics.cpp index 607102d9eaec..1d7fd64ad525 100644 --- a/js/src/gc/Statistics.cpp +++ b/js/src/gc/Statistics.cpp @@ -54,6 +54,210 @@ namespace js { namespace gcstats { +/* Except for the first and last, slices of less than 12ms are not reported. */ +static const int64_t SLICE_MIN_REPORT_TIME = 12 * PRMJ_USEC_PER_MSEC; + +class StatisticsSerializer +{ + typedef Vector CharBuffer; + CharBuffer buf_; + bool asJSON_; + bool needComma_; + bool oom_; + + const static int MaxFieldValueLength = 128; + + public: + enum Mode { + AsJSON = true, + AsText = false + }; + + StatisticsSerializer(Mode asJSON) + : buf_(), asJSON_(asJSON), needComma_(false), oom_(false) + {} + + bool isJSON() { return asJSON_; } + + bool isOOM() { return oom_; } + + void endLine() { + if (!asJSON_) { + p("\n"); + needComma_ = false; + } + } + + void extra(const char *str) { + if (!asJSON_) { + needComma_ = false; + p(str); + } + } + + void appendString(const char *name, const char *value) { + put(name, value, "", true); + } + + void appendNumber(const char *name, const char *vfmt, const char *units, ...) { + va_list va; + va_start(va, units); + append(name, vfmt, va, units); + va_end(va); + } + + void appendIfNonzeroMS(const char *name, double v) { + if (asJSON_ || v) + appendNumber(name, "%.1f", "ms", v); + } + + void beginObject(const char *name) { + if (needComma_) + pJSON(", "); + if (asJSON_ && name) { + putQuoted(name); + pJSON(": "); + } + pJSON("{"); + needComma_ = false; + } + + void endObject() { + needComma_ = false; + pJSON("}"); + needComma_ = true; + } + + void beginArray(const char *name) { + if (needComma_) + pJSON(", "); + if (asJSON_) + putQuoted(name); + pJSON(": ["); + needComma_ = false; + } + + void endArray() { + needComma_ = false; + pJSON("]"); + needComma_ = true; + } + + jschar *finishJSString() { + char *buf = finishCString(); + if (!buf) + return NULL; + + size_t nchars = strlen(buf); + jschar *out = (jschar *)js_malloc(sizeof(jschar) * (nchars + 1)); + if (!out) { + oom_ = true; + js_free(buf); + return NULL; + } + + size_t outlen = nchars; + bool ok = InflateStringToBuffer(NULL, buf, nchars, out, &outlen); + js_free(buf); + if (!ok) { + oom_ = true; + js_free(out); + return NULL; + } + out[nchars] = 0; + + return out; + } + + char *finishCString() { + if (oom_) + return NULL; + + buf_.append('\0'); + + char *buf = buf_.extractRawBuffer(); + if (!buf) + oom_ = true; + + return buf; + } + + private: + void append(const char *name, const char *vfmt, + va_list va, const char *units) + { + char val[MaxFieldValueLength]; + JS_vsnprintf(val, MaxFieldValueLength, vfmt, va); + put(name, val, units, false); + } + + void p(const char *cstr) { + if (oom_) + return; + + if (!buf_.append(cstr, strlen(cstr))) + oom_ = true; + } + + void p(const char c) { + if (oom_) + return; + + if (!buf_.append(c)) + oom_ = true; + } + + void pJSON(const char *str) { + if (asJSON_) + p(str); + } + + void put(const char *name, const char *val, const char *units, bool valueIsQuoted) { + if (needComma_) + p(", "); + needComma_ = true; + + putKey(name); + p(": "); + if (valueIsQuoted) + putQuoted(val); + else + p(val); + if (!asJSON_) + p(units); + } + + void putQuoted(const char *str) { + pJSON("\""); + p(str); + pJSON("\""); + } + + void putKey(const char *str) { + if (!asJSON_) { + p(str); + return; + } + + p("\""); + const char *c = str; + while (*c) { + if (*c == ' ' || *c == '\t') + p('_'); + else if (isupper(*c)) + p(tolower(*c)); + else if (*c == '+') + p("added_"); + else if (*c == '-') + p("removed_"); + else if (*c != '(' && *c != ')') + p(*c); + c++; + } + p("\""); + } +}; + static const char * ExplainReason(gcreason::Reason reason) { @@ -70,57 +274,36 @@ ExplainReason(gcreason::Reason reason) } } -void -Statistics::fmt(const char *f, ...) +static double +t(int64_t t) { - va_list va; - size_t off = strlen(buffer); - - va_start(va, f); - JS_vsnprintf(buffer + off, BUFFER_SIZE - off, f, va); - va_end(va); + return double(t) / PRMJ_USEC_PER_MSEC; } -void -Statistics::fmtIfNonzero(const char *name, double t) +static void +formatPhases(StatisticsSerializer &ss, const char *name, int64_t *times) { - if (t) { - if (needComma) - fmt(", "); - fmt("%s: %.1f", name, t); - needComma = true; - } + ss.beginObject(name); + ss.appendIfNonzeroMS("Mark", t(times[PHASE_MARK])); + ss.appendIfNonzeroMS("Mark Roots", t(times[PHASE_MARK_ROOTS])); + ss.appendIfNonzeroMS("Mark Delayed", t(times[PHASE_MARK_DELAYED])); + ss.appendIfNonzeroMS("Mark Other", t(times[PHASE_MARK_OTHER])); + ss.appendIfNonzeroMS("Sweep", t(times[PHASE_SWEEP])); + ss.appendIfNonzeroMS("Sweep Object", t(times[PHASE_SWEEP_OBJECT])); + ss.appendIfNonzeroMS("Sweep String", t(times[PHASE_SWEEP_STRING])); + ss.appendIfNonzeroMS("Sweep Script", t(times[PHASE_SWEEP_SCRIPT])); + ss.appendIfNonzeroMS("Sweep Shape", t(times[PHASE_SWEEP_SHAPE])); + ss.appendIfNonzeroMS("Discard Code", t(times[PHASE_DISCARD_CODE])); + ss.appendIfNonzeroMS("Discard Analysis", t(times[PHASE_DISCARD_ANALYSIS])); + ss.appendIfNonzeroMS("XPConnect", t(times[PHASE_XPCONNECT])); + ss.appendIfNonzeroMS("Deallocate", t(times[PHASE_DESTROY])); + ss.endObject(); } -void -Statistics::formatPhases(int64_t *times) +bool +Statistics::formatData(StatisticsSerializer &ss) { - needComma = false; - fmtIfNonzero("mark", t(times[PHASE_MARK])); - fmtIfNonzero("mark-roots", t(times[PHASE_MARK_ROOTS])); - fmtIfNonzero("mark-delayed", t(times[PHASE_MARK_DELAYED])); - fmtIfNonzero("mark-other", t(times[PHASE_MARK_OTHER])); - fmtIfNonzero("sweep", t(times[PHASE_SWEEP])); - fmtIfNonzero("sweep-obj", t(times[PHASE_SWEEP_OBJECT])); - fmtIfNonzero("sweep-string", t(times[PHASE_SWEEP_STRING])); - fmtIfNonzero("sweep-script", t(times[PHASE_SWEEP_SCRIPT])); - fmtIfNonzero("sweep-shape", t(times[PHASE_SWEEP_SHAPE])); - fmtIfNonzero("discard-code", t(times[PHASE_DISCARD_CODE])); - fmtIfNonzero("discard-analysis", t(times[PHASE_DISCARD_ANALYSIS])); - fmtIfNonzero("xpconnect", t(times[PHASE_XPCONNECT])); - fmtIfNonzero("deallocate", t(times[PHASE_DESTROY])); -} - -/* Except for the first and last, slices of less than 12ms are not reported. */ -static const int64_t SLICE_MIN_REPORT_TIME = 12 * PRMJ_USEC_PER_MSEC; - -const char * -Statistics::formatData() -{ - buffer[0] = 0x00; - int64_t total = 0, longest = 0; - for (SliceData *slice = slices.begin(); slice != slices.end(); slice++) { total += slice->duration(); if (slice->duration() > longest) @@ -130,47 +313,70 @@ Statistics::formatData() double mmu20 = computeMMU(20 * PRMJ_USEC_PER_MSEC); double mmu50 = computeMMU(50 * PRMJ_USEC_PER_MSEC); - fmt("TotalTime: %.1fms, Type: %s", t(total), compartment ? "compartment" : "global"); - fmt(", MMU(20ms): %d%%, MMU(50ms): %d%%", int(mmu20 * 100), int(mmu50 * 100)); - - if (slices.length() > 1) - fmt(", MaxPause: %.1f", t(longest)); + ss.beginObject(NULL); + ss.appendNumber("Total Time", "%.1f", "ms", t(total)); + ss.appendString("Type", compartment ? "compartment" : "global"); + ss.appendNumber("MMU (20ms)", "%d", "%", int(mmu20 * 100)); + ss.appendNumber("MMU (50ms)", "%d", "%", int(mmu50 * 100)); + if (slices.length() > 1 || ss.isJSON()) + ss.appendNumber("Max Pause", "%.1f", "ms", t(longest)); else - fmt(", Reason: %s", ExplainReason(slices[0].reason)); + ss.appendString("Reason", ExplainReason(slices[0].reason)); + if (nonincrementalReason || ss.isJSON()) { + ss.appendString("Nonincremental Reason", + nonincrementalReason ? nonincrementalReason : "none"); + } + ss.appendNumber("+Chunks", "%d", "", counts[STAT_NEW_CHUNK]); + ss.appendNumber("-Chunks", "%d", "", counts[STAT_DESTROY_CHUNK]); + ss.endLine(); - if (nonincrementalReason) - fmt(", NonIncrementalReason: %s", nonincrementalReason); - - fmt(", +chunks: %d, -chunks: %d\n", counts[STAT_NEW_CHUNK], counts[STAT_DESTROY_CHUNK]); - - if (slices.length() > 1) { + if (slices.length() > 1 || ss.isJSON()) { + ss.beginArray("Slices"); for (size_t i = 0; i < slices.length(); i++) { int64_t width = slices[i].duration(); if (i != 0 && i != slices.length() - 1 && width < SLICE_MIN_REPORT_TIME && - !slices[i].resetReason) + !slices[i].resetReason && !ss.isJSON()) { continue; } - fmt(" Slice %d @ %.1fms (Pause: %.1f, Reason: %s", - i, - t(slices[i].end - slices[0].start), - t(width), - ExplainReason(slices[i].reason)); + ss.beginObject(NULL); + ss.extra(" "); + ss.appendNumber("Slice", "%d", "", i); + ss.appendNumber("Time", "%.1f", "ms", t(slices[i].end - slices[0].start)); + ss.extra(" ("); + ss.appendNumber("Pause", "%.1f", "", t(width)); + ss.appendString("Reason", ExplainReason(slices[i].reason)); if (slices[i].resetReason) - fmt(", Reset: %s", slices[i].resetReason); - fmt("): "); - formatPhases(slices[i].phaseTimes); - fmt("\n"); + ss.appendString("Reset", slices[i].resetReason); + ss.extra("): "); + formatPhases(ss, "times", slices[i].phaseTimes); + ss.endLine(); + ss.endObject(); } - - fmt(" Totals: "); + ss.endArray(); } + ss.extra(" Totals: "); + formatPhases(ss, "totals", phaseTimes); + ss.endObject(); - formatPhases(phaseTimes); - fmt("\n"); + return !ss.isOOM(); +} - return buffer; +jschar * +Statistics::formatMessage() +{ + StatisticsSerializer ss(StatisticsSerializer::AsText); + formatData(ss); + return ss.finishJSString(); +} + +jschar * +Statistics::formatJSON() +{ + StatisticsSerializer ss(StatisticsSerializer::AsJSON); + formatData(ss); + return ss.finishJSString(); } Statistics::Statistics(JSRuntime *rt) @@ -179,8 +385,7 @@ Statistics::Statistics(JSRuntime *rt) fp(NULL), fullFormat(false), compartment(NULL), - nonincrementalReason(NULL), - needComma(false) + nonincrementalReason(NULL) { PodArrayZero(phaseTotals); PodArrayZero(counts); @@ -209,9 +414,13 @@ Statistics::~Statistics() { if (fp) { if (fullFormat) { - buffer[0] = 0x00; - formatPhases(phaseTotals); - fprintf(fp, "TOTALS\n%s\n\n-------\n", buffer); + StatisticsSerializer ss(StatisticsSerializer::AsText); + formatPhases(ss, "", phaseTotals); + char *msg = ss.finishCString(); + if (msg) { + fprintf(fp, "TOTALS\n%s\n\n-------\n", msg); + js_free(msg); + } } if (fp != stdout && fp != stderr) @@ -219,12 +428,6 @@ Statistics::~Statistics() } } -double -Statistics::t(int64_t t) -{ - return double(t) / PRMJ_USEC_PER_MSEC; -} - int64_t Statistics::gcDuration() { @@ -235,9 +438,13 @@ void Statistics::printStats() { if (fullFormat) { - fprintf(fp, "GC(T+%.3fs) %s\n", - t(slices[0].start - startupTime) / 1000.0, - formatData()); + StatisticsSerializer ss(StatisticsSerializer::AsText); + formatData(ss); + char *msg = ss.finishCString(); + if (msg) { + fprintf(fp, "GC(T+%.3fs) %s\n", t(slices[0].start - startupTime) / 1000.0, msg); + js_free(msg); + } } else { fprintf(fp, "%f %f %f\n", t(gcDuration()), @@ -301,10 +508,8 @@ Statistics::beginSlice(JSCompartment *comp, gcreason::Reason reason) if (JSAccumulateTelemetryDataCallback cb = runtime->telemetryCallback) (*cb)(JS_TELEMETRY_GC_REASON, reason); - if (GCSliceCallback cb = runtime->gcSliceCallback) { - GCDescription desc(NULL, !!compartment); - (*cb)(runtime, first ? GC_CYCLE_BEGIN : GC_SLICE_BEGIN, desc); - } + if (GCSliceCallback cb = runtime->gcSliceCallback) + (*cb)(runtime, first ? GC_CYCLE_BEGIN : GC_SLICE_BEGIN, GCDescription(!!compartment)); } void @@ -323,9 +528,9 @@ Statistics::endSlice() if (GCSliceCallback cb = runtime->gcSliceCallback) { if (last) - (*cb)(runtime, GC_CYCLE_END, GCDescription(formatData(), !!compartment)); + (*cb)(runtime, GC_CYCLE_END, GCDescription(!!compartment)); else - (*cb)(runtime, GC_SLICE_END, GCDescription(NULL, !!compartment)); + (*cb)(runtime, GC_SLICE_END, GCDescription(!!compartment)); } } diff --git a/js/src/gc/Statistics.h b/js/src/gc/Statistics.h index 31b8d5d699e8..6767ccade2ac 100644 --- a/js/src/gc/Statistics.h +++ b/js/src/gc/Statistics.h @@ -76,7 +76,7 @@ enum Stat { STAT_LIMIT }; -static const size_t BUFFER_SIZE = 8192; +class StatisticsSerializer; struct Statistics { Statistics(JSRuntime *rt); @@ -96,6 +96,9 @@ struct Statistics { counts[s]++; } + jschar *formatMessage(); + jschar *formatJSON(); + private: JSRuntime *runtime; @@ -136,19 +139,12 @@ struct Statistics { /* Number of events of this type for this GC. */ unsigned int counts[STAT_LIMIT]; - char buffer[BUFFER_SIZE]; - bool needComma; - void beginGC(); void endGC(); int64_t gcDuration(); - double t(int64_t t); void printStats(); - void fmt(const char *f, ...); - void fmtIfNonzero(const char *name, double t); - void formatPhases(int64_t *times); - const char *formatData(); + bool formatData(StatisticsSerializer &ss); double computeMMU(int64_t resolution); }; diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index c1cd20e4fc21..ed441d55e437 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -120,7 +120,6 @@ #include "jsnum.h" #include "jsobj.h" #include "jsscope.h" -#include "jsstr.h" #include "jswrapper.h" #include "methodjit/MethodJIT.h" #include "methodjit/StubCalls.h" diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index f4bd7aa16116..7a25917f3bea 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -717,6 +717,18 @@ SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback) return old; } +jschar * +GCDescription::formatMessage(JSRuntime *rt) const +{ + return rt->gcStats.formatMessage(); +} + +jschar * +GCDescription::formatJSON(JSRuntime *rt) const +{ + return rt->gcStats.formatJSON(); +} + JS_FRIEND_API(bool) WantGCSlice(JSRuntime *rt) { diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index b4d2f0418264..afdb0d5e56c3 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -699,12 +699,14 @@ enum GCProgress { GC_CYCLE_END }; -struct GCDescription { - const char *logMessage; +struct JS_FRIEND_API(GCDescription) { bool isCompartment; - GCDescription(const char *msg, bool isCompartment) - : logMessage(msg), isCompartment(isCompartment) {} + GCDescription(bool isCompartment) + : isCompartment(isCompartment) {} + + jschar *formatMessage(JSRuntime *rt) const; + jschar *formatJSON(JSRuntime *rt) const; }; typedef void From 95ca17bb57f42c93cfeb643d163963c0e5668795 Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Tue, 13 Mar 2012 13:35:26 -0400 Subject: [PATCH 13/57] Bug 735228 - CAccessibleComponent shouldn't use GetComputedStyle, r=tbsaunde --- accessible/src/msaa/CAccessibleComponent.cpp | 109 +++---------------- accessible/src/msaa/CAccessibleComponent.h | 8 -- 2 files changed, 16 insertions(+), 101 deletions(-) diff --git a/accessible/src/msaa/CAccessibleComponent.cpp b/accessible/src/msaa/CAccessibleComponent.cpp index 0036bba5cf48..349effe5b462 100644 --- a/accessible/src/msaa/CAccessibleComponent.cpp +++ b/accessible/src/msaa/CAccessibleComponent.cpp @@ -54,13 +54,6 @@ using namespace mozilla::a11y; -enum { - IA2AlphaShift = 24, - IA2RedShift = 16, - IA2GreenShift = 8, - IA2BlueShift = 0 -}; - // IUnknown STDMETHODIMP @@ -130,110 +123,40 @@ __try { } STDMETHODIMP -CAccessibleComponent::get_foreground(IA2Color *aForeground) +CAccessibleComponent::get_foreground(IA2Color* aForeground) { __try { - return GetARGBValueFromCSSProperty(NS_LITERAL_STRING("color"), aForeground); + nsRefPtr acc(do_QueryObject(this)); + if (acc->IsDefunct()) + return E_FAIL; + + nsIFrame* frame = acc->GetFrame(); + if (frame) + *aForeground = frame->GetStyleColor()->mColor; + + return S_OK; + } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { } return E_FAIL; } STDMETHODIMP -CAccessibleComponent::get_background(IA2Color *aBackground) +CAccessibleComponent::get_background(IA2Color* aBackground) { __try { - return GetARGBValueFromCSSProperty(NS_LITERAL_STRING("background-color"), - aBackground); -} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { } - - return E_FAIL; -} - -HRESULT -CAccessibleComponent::GetARGBValueFromCSSProperty(const nsAString& aPropName, - IA2Color *aColorValue) -{ -__try { - *aColorValue = 0; - nsRefPtr acc(do_QueryObject(this)); if (acc->IsDefunct()) return E_FAIL; - nsCOMPtr styleDecl = - nsWinUtils::GetComputedStyleDeclaration(acc->GetContent()); - NS_ENSURE_STATE(styleDecl); + nsIFrame* frame = acc->GetFrame(); + if (frame) + *aBackground = frame->GetStyleBackground()->mBackgroundColor; - nsCOMPtr cssGenericValue; - styleDecl->GetPropertyCSSValue(aPropName, getter_AddRefs(cssGenericValue)); - - nsCOMPtr cssValue = - do_QueryInterface(cssGenericValue); - if (!cssValue) - return E_FAIL; - - nsCOMPtr rgbColor; - nsresult rv = cssValue->GetRGBColorValue(getter_AddRefs(rgbColor)); - if (NS_FAILED(rv) || !rgbColor) - return GetHRESULT(rv); - - nsCOMPtr rgbaColor(do_QueryInterface(rgbColor)); - if (!rgbaColor) - return GetHRESULT(rv); - - // get alpha - nsCOMPtr alphaValue; - rv = rgbaColor->GetAlpha(getter_AddRefs(alphaValue)); - if (NS_FAILED(rv) || !alphaValue) - return GetHRESULT(rv); - - float alpha = 0.0; - rv = alphaValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &alpha); - if (NS_FAILED(rv)) - return GetHRESULT(rv); - - // get red - nsCOMPtr redValue; - rv = rgbaColor->GetRed(getter_AddRefs(redValue)); - if (NS_FAILED(rv) || !redValue) - return GetHRESULT(rv); - - float red = 0.0; - rv = redValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &red); - if (NS_FAILED(rv)) - return GetHRESULT(rv); - - // get green - nsCOMPtr greenValue; - rv = rgbaColor->GetGreen(getter_AddRefs(greenValue)); - if (NS_FAILED(rv) || !greenValue) - return GetHRESULT(rv); - - float green = 0.0; - rv = greenValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &green); - if (NS_FAILED(rv)) - return GetHRESULT(rv); - - // get blue - nsCOMPtr blueValue; - rv = rgbaColor->GetBlue(getter_AddRefs(blueValue)); - if (NS_FAILED(rv) || !blueValue) - return GetHRESULT(rv); - - float blue = 0.0; - rv = blueValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &blue); - if (NS_FAILED(rv)) - return GetHRESULT(rv); - - // compose ARGB value - *aColorValue = (((IA2Color) blue) << IA2BlueShift) | - (((IA2Color) green) << IA2GreenShift) | - (((IA2Color) red) << IA2RedShift) | - (((IA2Color) (alpha * 0xff)) << IA2AlphaShift); return S_OK; } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { } + return E_FAIL; } diff --git a/accessible/src/msaa/CAccessibleComponent.h b/accessible/src/msaa/CAccessibleComponent.h index 25e874ac023a..4157771c1b42 100644 --- a/accessible/src/msaa/CAccessibleComponent.h +++ b/accessible/src/msaa/CAccessibleComponent.h @@ -65,14 +65,6 @@ public: // nsISupports NS_IMETHOD QueryInterface(const nsIID& uuid, void** result) = 0; - -protected: - - /** - * Return ARGB value for CSS property like 'color' or 'background-color'. - */ - HRESULT GetARGBValueFromCSSProperty(const nsAString& aPropName, - IA2Color *aColorValue); }; #endif From 00de4ae87c97b6160c681b2a4e05b26594724935 Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Tue, 13 Mar 2012 10:38:38 -0700 Subject: [PATCH 14/57] No Bug - Build bustage caused by cset c619bbb2951f. Extra char at begining of file. r=me --- widget/android/AndroidJavaWrappers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widget/android/AndroidJavaWrappers.cpp b/widget/android/AndroidJavaWrappers.cpp index 48ff3cc6be95..841547ed54d7 100644 --- a/widget/android/AndroidJavaWrappers.cpp +++ b/widget/android/AndroidJavaWrappers.cpp @@ -1,4 +1,4 @@ -3/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- +/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * From 1fdae99e653ac826df9fea1b3084762a619ed59c Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Tue, 6 Mar 2012 18:49:00 -0800 Subject: [PATCH 15/57] Bug 704259: part 1, refactor use of cx->generatingError without changing behavior, r=luke --HG-- extra : rebase_source : 748e23ae07d8dc3c2cec165228d858abfc6a535f --- js/src/jscntxt.h | 13 +++++------ js/src/jsexn.cpp | 57 +++++++++++++++--------------------------------- 2 files changed, 23 insertions(+), 47 deletions(-) diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 32ac7340c993..c39036c7bf29 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -827,11 +827,11 @@ struct JSContext : js::ContextFriendFields bool hasVersionOverride; /* Exception state -- the exception member is a GC root by definition. */ - JSBool throwing; /* is there a pending exception? */ - js::Value exception; /* most-recently-thrown exception */ + JSBool throwing; /* is there a pending exception? */ + js::Value exception; /* most-recently-thrown exception */ /* Per-context run options. */ - unsigned runOptions; /* see jsapi.h for JSOPTION_* */ + unsigned runOptions; /* see jsapi.h for JSOPTION_* */ public: int32_t reportGranularity; /* see jsprobes.h */ @@ -841,11 +841,8 @@ struct JSContext : js::ContextFriendFields js::AutoResolving *resolvingList; - /* - * True if generating an error, to prevent runaway recursion. - * NB: generatingError packs with throwing below. - */ - bool generatingError; + /* True if generating an error, to prevent runaway recursion. */ + bool generatingError; /* GC heap compartment. */ JSCompartment *compartment; diff --git a/js/src/jsexn.cpp b/js/src/jsexn.cpp index 3c83f78e55d2..6e97dae5825f 100644 --- a/js/src/jsexn.cpp +++ b/js/src/jsexn.cpp @@ -1074,7 +1074,6 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp, const JSErrorFormatString *errorString; JSExnType exn; jsval tv[4]; - JSBool ok; JSObject *errProto, *errObject; JSString *messageStr, *filenameStr; @@ -1083,7 +1082,7 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp, */ JS_ASSERT(reportp); if (JSREPORT_IS_WARNING(reportp->flags)) - return JS_FALSE; + return false; /* Find the exception index associated with this error. */ errorNumber = (JSErrNum) reportp->errorNumber; @@ -1106,19 +1105,12 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp, * with the given error number. */ if (exn == JSEXN_NONE) - return JS_FALSE; + return false; - /* - * Prevent runaway recursion, via cx->generatingError. If an out-of-memory - * error occurs, no exception object will be created, but we don't assume - * that OOM is the only kind of error that subroutines of this function - * called below might raise. - */ + /* Prevent infinite recursion. */ if (cx->generatingError) - return JS_FALSE; - - MUST_FLOW_THROUGH("out"); - cx->generatingError = JS_TRUE; + return false; + AutoScopedAssign asa(&cx->generatingError, true); /* Protect the newly-created strings below from nesting GCs. */ PodArrayZero(tv); @@ -1129,45 +1121,32 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp, * exception constructor name in the scope chain of the current context's * top stack frame, or in the global object if no frame is active. */ - ok = js_GetClassPrototype(cx, NULL, GetExceptionProtoKey(exn), &errProto); - if (!ok) - goto out; + if (!js_GetClassPrototype(cx, NULL, GetExceptionProtoKey(exn), &errProto)) + return false; tv[0] = OBJECT_TO_JSVAL(errProto); - errObject = NewObjectWithGivenProto(cx, &ErrorClass, errProto, NULL); - if (!errObject) { - ok = JS_FALSE; - goto out; - } + if (!(errObject = NewObjectWithGivenProto(cx, &ErrorClass, errProto, NULL))) + return false; tv[1] = OBJECT_TO_JSVAL(errObject); - messageStr = JS_NewStringCopyZ(cx, message); - if (!messageStr) { - ok = JS_FALSE; - goto out; - } + if (!(messageStr = JS_NewStringCopyZ(cx, message))) + return false; tv[2] = STRING_TO_JSVAL(messageStr); - filenameStr = JS_NewStringCopyZ(cx, reportp->filename); - if (!filenameStr) { - ok = JS_FALSE; - goto out; - } + if (!(filenameStr = JS_NewStringCopyZ(cx, reportp->filename))) + return false; tv[3] = STRING_TO_JSVAL(filenameStr); - ok = InitExnPrivate(cx, errObject, messageStr, filenameStr, - reportp->lineno, reportp, exn); - if (!ok) - goto out; + if (!InitExnPrivate(cx, errObject, messageStr, filenameStr, + reportp->lineno, reportp, exn)) { + return false; + } JS_SetPendingException(cx, OBJECT_TO_JSVAL(errObject)); /* Flag the error report passed in to indicate an exception was raised. */ reportp->flags |= JSREPORT_EXCEPTION; - -out: - cx->generatingError = JS_FALSE; - return ok; + return true; } JSBool From 1e0d41c1cd221b36a18a6becb0504282d4bb7cda Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Tue, 6 Mar 2012 18:49:05 -0800 Subject: [PATCH 16/57] Bug 704259: part 2, don't set cx->generatingError in JS_ReportPendingException, r=luke --- js/src/jsapi.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 8b9f3a048e7e..850dba88622d 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -6445,23 +6445,10 @@ JS_ClearPendingException(JSContext *cx) JS_PUBLIC_API(JSBool) JS_ReportPendingException(JSContext *cx) { - JSBool ok; - bool save; - AssertNoGC(cx); CHECK_REQUEST(cx); - /* - * Set cx->generatingError to suppress the standard error-to-exception - * conversion done by all {js,JS}_Report* functions except for OOM. The - * cx->generatingError flag was added to suppress recursive divergence - * under js_ErrorToException, but it serves for our purposes here too. - */ - save = cx->generatingError; - cx->generatingError = JS_TRUE; - ok = js_ReportUncaughtException(cx); - cx->generatingError = save; - return ok; + return js_ReportUncaughtException(cx); } struct JSExceptionState { From 594565d0a8a0057ccd455d0c087d5cedbb0685ea Mon Sep 17 00:00:00 2001 From: Benoit Girard Date: Sat, 10 Mar 2012 18:08:17 -0500 Subject: [PATCH 17/57] Bug 734685 - Support IPC Thread::SetName on Mac. r=cjones --- ipc/chromium/src/base/platform_thread_mac.mm | 24 +++++++++++++++++++ .../src/base/platform_thread_posix.cc | 4 ++++ 2 files changed, 28 insertions(+) diff --git a/ipc/chromium/src/base/platform_thread_mac.mm b/ipc/chromium/src/base/platform_thread_mac.mm index b055b8ace175..ef558a796847 100644 --- a/ipc/chromium/src/base/platform_thread_mac.mm +++ b/ipc/chromium/src/base/platform_thread_mac.mm @@ -5,6 +5,7 @@ #include "base/platform_thread.h" #import +#include #include "base/logging.h" #include "base/scoped_nsautorelease_pool.h" @@ -51,3 +52,26 @@ void InitThreading() { } } // namespace base + +// static +void PlatformThread::SetName(const char* name) { + // pthread_setname_np is only available in 10.6 or later, so test + // for it at runtime. + int (*dynamic_pthread_setname_np)(const char*); + *reinterpret_cast(&dynamic_pthread_setname_np) = + dlsym(RTLD_DEFAULT, "pthread_setname_np"); + if (!dynamic_pthread_setname_np) + return; + + // Mac OS X does not expose the length limit of the name, so + // hardcode it. + const int kMaxNameLength = 63; + std::string shortened_name = std::string(name).substr(0, kMaxNameLength); + // pthread_setname() fails (harmlessly) in the sandbox, ignore when it does. + // See http://crbug.com/47058 + + // The name parameter is copied thus it's safe to release it after calling. + // Checked against the bionic implementation in bionic/libc/bionic/pthread.c + dynamic_pthread_setname_np(shortened_name.c_str()); +} + diff --git a/ipc/chromium/src/base/platform_thread_posix.cc b/ipc/chromium/src/base/platform_thread_posix.cc index e3f49c7cd657..aa4f66157dc5 100644 --- a/ipc/chromium/src/base/platform_thread_posix.cc +++ b/ipc/chromium/src/base/platform_thread_posix.cc @@ -61,6 +61,9 @@ void PlatformThread::Sleep(int duration_ms) { sleep_time = remaining; } +#ifndef OS_MACOSX +// Mac is implemented in platform_thread_mac.mm. + // static void PlatformThread::SetName(const char* name) { // The POSIX standard does not provide for naming threads, and neither Linux @@ -70,6 +73,7 @@ void PlatformThread::SetName(const char* name) { // TODO(darin): decide whether stuffing the name in TLS or other in-memory // structure would be useful for debugging or not. } +#endif // !OS_MACOSX namespace { From 676749395ddb5b3c5fe2f1ced749bac1655956a9 Mon Sep 17 00:00:00 2001 From: Jason Duell Date: Tue, 13 Mar 2012 11:49:01 -0700 Subject: [PATCH 18/57] Bug 664163 - Fix Get(Local|Remote)(Address|Port) in HttpChannelChild. r=jdm --- netwerk/protocol/http/HttpChannelChild.cpp | 35 +--------- netwerk/protocol/http/HttpChannelChild.h | 4 -- netwerk/test/unit/test_traceable_channel.js | 76 +++++++++++++++++---- 3 files changed, 64 insertions(+), 51 deletions(-) diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/HttpChannelChild.cpp index 4df4d51f61a5..dcaf4dcc2b03 100644 --- a/netwerk/protocol/http/HttpChannelChild.cpp +++ b/netwerk/protocol/http/HttpChannelChild.cpp @@ -291,6 +291,8 @@ HttpChannelChild::OnStartRequest(const nsHttpResponseHead& responseHead, mCacheEntryAvailable = cacheEntryAvailable; mCacheExpirationTime = cacheExpirationTime; mCachedCharset = cachedCharset; + mSelfAddr = selfAddr; + mPeerAddr = peerAddr; AutoEventEnqueuer ensureSerialDispatch(mEventQ); @@ -313,9 +315,6 @@ HttpChannelChild::OnStartRequest(const nsHttpResponseHead& responseHead, rv = ApplyContentConversions(); if (NS_FAILED(rv)) Cancel(rv); - - mSelfAddr = selfAddr; - mPeerAddr = peerAddr; } class TransportAndDataEvent : public ChannelEvent @@ -1113,36 +1112,6 @@ HttpChannelChild::SetupFallbackChannel(const char *aFallbackKey) DROP_DEAD(); } -// The next four _should_ be implemented, but we need to figure out how -// to transfer the data from the chrome process first. - -NS_IMETHODIMP -HttpChannelChild::GetRemoteAddress(nsACString & _result) -{ - return NS_ERROR_NOT_AVAILABLE; -} - -NS_IMETHODIMP -HttpChannelChild::GetRemotePort(PRInt32 * _result) -{ - NS_ENSURE_ARG_POINTER(_result); - return NS_ERROR_NOT_AVAILABLE; -} - -NS_IMETHODIMP -HttpChannelChild::GetLocalAddress(nsACString & _result) -{ - return NS_ERROR_NOT_AVAILABLE; -} - -NS_IMETHODIMP -HttpChannelChild::GetLocalPort(PRInt32 * _result) -{ - NS_ENSURE_ARG_POINTER(_result); - return NS_ERROR_NOT_AVAILABLE; -} - - //----------------------------------------------------------------------------- // HttpChannelChild::nsICacheInfoChannel //----------------------------------------------------------------------------- diff --git a/netwerk/protocol/http/HttpChannelChild.h b/netwerk/protocol/http/HttpChannelChild.h index 43617ef5589c..f9f7c2e0003a 100644 --- a/netwerk/protocol/http/HttpChannelChild.h +++ b/netwerk/protocol/http/HttpChannelChild.h @@ -106,10 +106,6 @@ public: bool aMerge); // nsIHttpChannelInternal NS_IMETHOD SetupFallbackChannel(const char *aFallbackKey); - NS_IMETHOD GetLocalAddress(nsACString& addr); - NS_IMETHOD GetLocalPort(PRInt32* port); - NS_IMETHOD GetRemoteAddress(nsACString& addr); - NS_IMETHOD GetRemotePort(PRInt32* port); // nsISupportsPriority NS_IMETHOD SetPriority(PRInt32 value); // nsIResumableChannel diff --git a/netwerk/test/unit/test_traceable_channel.js b/netwerk/test/unit/test_traceable_channel.js index a62b8a2c92b3..164d65f4c46f 100644 --- a/netwerk/test/unit/test_traceable_channel.js +++ b/netwerk/test/unit/test_traceable_channel.js @@ -22,14 +22,42 @@ TracingListener.prototype = { request.QueryInterface(Components.interfaces.nsIHttpChannelInternal); -// local/remote addresses broken in e10s: disable for now -/* - do_check_eq(request.localAddress, "127.0.0.1"); - do_check_eq(request.localPort > 0, true); - do_check_neq(request.localPort, 4444); - do_check_eq(request.remoteAddress, "127.0.0.1"); - do_check_eq(request.remotePort, 4444); -*/ + var localAddr = "unknown"; + var localPort = "unknown"; + var remoteAddr = "unknown"; + var remotePort = "unknown"; + try { + localAddr = request.localAddress; + dump("got local address\n"); + } catch(e) { + dump("couldn't get local address\n"); + } + try { + localPort = request.localPort; + dump("got local port\n"); + } catch(e) { + dump("couldn't get local port\n"); + } + try { + remoteAddr = request.remoteAddress; + dump("got remote address\n"); + } catch(e) { + dump("couldn't get remote address\n"); + } + try { + remotePort = request.remotePort; + dump("got remote port\n"); + } catch(e) { + dump("couldn't get remote port\n"); + } + + do_check_eq(localAddr, "127.0.0.1"); + do_check_eq(localPort > 0, true); + do_check_eq(remoteAddr, "127.0.0.1"); + do_check_eq(remotePort, 4444); + + request.QueryInterface(Components.interfaces.nsISupportsPriority); + request.priority = Ci.nsISupportsPriority.PRIORITY_LOW; // Make sure listener can't be replaced after OnStartRequest was called. request.QueryInterface(Components.interfaces.nsITraceableChannel); @@ -63,9 +91,10 @@ TracingListener.prototype = { input.close(); } catch (e) { dump("TracingListener.onStopRequest swallowing exception: " + e + "\n"); - } finally { - httpserver.stop(do_test_finished); } + + // we're the last OnStopRequest called by the nsIStreamListenerTee + run_next_test(); }, QueryInterface: function(iid) { @@ -135,18 +164,37 @@ function make_channel(url) { // Check if received body is correctly modified. function channel_finished(request, input, ctx) { - httpserver.stop(do_test_finished); + // No-op: since the nsIStreamListenerTee calls the observer's OnStopRequest + // after this, we call run_next_test() there +} + +// needs to be global or it'll go out of scope before it observes request +var observer = new HttpResponseExaminer(); + +var testRuns = 1; // change this to >1 to run test multiple times +var iteration = 1; + +function run_next_test() { + if (iteration > testRuns) { + dump("Shutting down\n"); + httpserver.stop(do_test_finished); + return; + } + if (iteration > 1) { + dump("^^^ test iteration=" + iteration + "\n"); + } + var channel = make_channel("http://localhost:4444/testdir"); + channel.asyncOpen(new ChannelListener(channel_finished), null); + iteration++; } function run_test() { - var observer = new HttpResponseExaminer(); observer.register(); httpserver = new nsHttpServer(); httpserver.registerPathHandler("/testdir", test_handler); httpserver.start(4444); - var channel = make_channel("http://localhost:4444/testdir"); - channel.asyncOpen(new ChannelListener(channel_finished), null); + run_next_test(); do_test_pending(); } From 4291a6ccc42b01a86911ea8f86d69366f9c821c6 Mon Sep 17 00:00:00 2001 From: Sriram Ramasubramanian Date: Tue, 13 Mar 2012 11:59:02 -0700 Subject: [PATCH 19/57] Bug 735209: No application icon in AwesomeBar's clipboard bar. [r=mfinkle] --- mobile/android/base/Makefile.in | 1 + mobile/android/base/resources/layout/awesomebar_actionbar.xml | 3 +++ mobile/android/base/resources/values-v11/styles.xml | 2 ++ 3 files changed, 6 insertions(+) create mode 100644 mobile/android/base/resources/layout/awesomebar_actionbar.xml diff --git a/mobile/android/base/Makefile.in b/mobile/android/base/Makefile.in index 86a416c9ed1d..79a358c5aa68 100644 --- a/mobile/android/base/Makefile.in +++ b/mobile/android/base/Makefile.in @@ -233,6 +233,7 @@ RES_LAYOUT = \ $(SYNC_RES_LAYOUT) \ res/layout/autocomplete_list_item.xml \ res/layout/awesomebar.xml \ + res/layout/awesomebar_actionbar.xml \ res/layout/awesomebar_folder_row.xml \ res/layout/awesomebar_folder_header_row.xml \ res/layout/awesomebar_header_row.xml \ diff --git a/mobile/android/base/resources/layout/awesomebar_actionbar.xml b/mobile/android/base/resources/layout/awesomebar_actionbar.xml new file mode 100644 index 000000000000..1b6c67d12d68 --- /dev/null +++ b/mobile/android/base/resources/layout/awesomebar_actionbar.xml @@ -0,0 +1,3 @@ + + diff --git a/mobile/android/base/resources/values-v11/styles.xml b/mobile/android/base/resources/values-v11/styles.xml index 6e5b7a0b5e4a..c29b7245c0de 100644 --- a/mobile/android/base/resources/values-v11/styles.xml +++ b/mobile/android/base/resources/values-v11/styles.xml @@ -39,6 +39,8 @@ From b448de886da7a88dada3c2a16e929c51c7025b35 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 13 Mar 2012 14:59:53 -0400 Subject: [PATCH 20/57] Bug 735344 - Use a refcounted pointer to Zip so that the delete doesn't crash Fennec. Also remove some spurious logging. r=glandium --- mozglue/android/APKOpen.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/mozglue/android/APKOpen.cpp b/mozglue/android/APKOpen.cpp index 1a251a7109fc..e550dac4c354 100644 --- a/mozglue/android/APKOpen.cpp +++ b/mozglue/android/APKOpen.cpp @@ -723,7 +723,6 @@ static int loadSQLiteLibs(const char *apkName) static mozglueresult loadNSSLibs(const char *apkName) { - __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "loadNSSLibs"); chdir(getenv("GRE_HOME")); #ifdef MOZ_OLD_LINKER @@ -733,7 +732,7 @@ loadNSSLibs(const char *apkName) } #endif - Zip *zip = new Zip(apkName); + RefPtr zip = new Zip(apkName); if (!lib_mapping) { lib_mapping = (struct mapping_info *)calloc(MAX_MAPPING_INFO, sizeof(*lib_mapping)); } @@ -772,14 +771,11 @@ loadNSSLibs(const char *apkName) #undef MOZLOAD #endif - delete zip; - #ifdef MOZ_CRASHREPORTER free(file_ids); file_ids = NULL; #endif - __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "loadNSSLibs 2"); if (!nss_handle) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get a handle to libnss3!"); return FAILURE; @@ -795,7 +791,6 @@ loadNSSLibs(const char *apkName) return FAILURE; } - __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "loadNSSLibs 3"); return setup_nss_functions(nss_handle, nspr_handle, plc_handle); } From 90ffd8fd2f0b54c49ce509b9db6ee49413d3f864 Mon Sep 17 00:00:00 2001 From: Jonas Sicking Date: Tue, 13 Mar 2012 13:25:05 -0700 Subject: [PATCH 21/57] Bug 735357: Fix Contacts API to use new IndexedDB constants. r=gwagner --- dom/contacts/fallback/ContactDB.jsm | 10 +++++----- dom/indexedDB/IDBCursor.cpp | 2 +- dom/indexedDB/IDBTransaction.cpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dom/contacts/fallback/ContactDB.jsm b/dom/contacts/fallback/ContactDB.jsm index c1a42582eaca..686ebcd7371e 100644 --- a/dom/contacts/fallback/ContactDB.jsm +++ b/dom/contacts/fallback/ContactDB.jsm @@ -123,7 +123,7 @@ ContactDB.prototype = { * Start a new transaction. * * @param txn_type - * Type of transaction (e.g. IDBTransaction.READ_WRITE) + * Type of transaction (e.g. "readwrite") * @param callback * Function to call when the transaction is available. It will * be invoked with the transaction and the 'contacts' object store. @@ -234,7 +234,7 @@ ContactDB.prototype = { saveContact: function saveContact(aContact, successCb, errorCb) { let contact = this.makeImport(aContact); - this.newTxn(Ci.nsIIDBTransaction.READ_WRITE, function (txn, store) { + this.newTxn("readwrite", function (txn, store) { debug("Going to update" + JSON.stringify(contact)); // Look up the existing record and compare the update timestamp. @@ -263,14 +263,14 @@ ContactDB.prototype = { }, removeContact: function removeContact(aId, aSuccessCb, aErrorCb) { - this.newTxn(Ci.nsIIDBTransaction.READ_WRITE, function (txn, store) { + this.newTxn("readwrite", function (txn, store) { debug("Going to delete" + aId); store.delete(aId); }, aSuccessCb, aErrorCb); }, clear: function clear(aSuccessCb, aErrorCb) { - this.newTxn(Ci.nsIIDBTransaction.READ_WRITE, function (txn, store) { + this.newTxn("readwrite", function (txn, store) { debug("Going to clear all!"); store.clear(); }, aSuccessCb, aErrorCb); @@ -297,7 +297,7 @@ ContactDB.prototype = { debug("ContactDB:find val:" + aOptions.filterValue + " by: " + aOptions.filterBy + " op: " + aOptions.filterOp + "\n"); let self = this; - this.newTxn(Ci.nsIIDBTransaction.READ_ONLY, function (txn, store) { + this.newTxn("readonly", function (txn, store) { if (aOptions && aOptions.filterOp == "equals") { self._findWithIndex(txn, store, aOptions); } else if (aOptions && aOptions.filterBy) { diff --git a/dom/indexedDB/IDBCursor.cpp b/dom/indexedDB/IDBCursor.cpp index feb00dd2e4b8..56865fa8cf7a 100644 --- a/dom/indexedDB/IDBCursor.cpp +++ b/dom/indexedDB/IDBCursor.cpp @@ -463,7 +463,7 @@ IDBCursor::GetDirection(nsAString& aDirection) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - switch(mDirection) { + switch (mDirection) { case NEXT: aDirection.AssignLiteral("next"); break; diff --git a/dom/indexedDB/IDBTransaction.cpp b/dom/indexedDB/IDBTransaction.cpp index 4db736cb995c..9729b26233ac 100644 --- a/dom/indexedDB/IDBTransaction.cpp +++ b/dom/indexedDB/IDBTransaction.cpp @@ -532,7 +532,7 @@ IDBTransaction::GetMode(nsAString& aMode) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - switch(mMode) { + switch (mMode) { case READ_ONLY: aMode.AssignLiteral("readonly"); break; From 9aa0ec31e503492c6065c404699913e4cf3dea9b Mon Sep 17 00:00:00 2001 From: Michael Wu Date: Tue, 13 Mar 2012 16:59:26 -0400 Subject: [PATCH 22/57] Bug 734263 - Set offscreen surface format according to screen format, r=cjones --- gfx/thebes/gfxAndroidPlatform.cpp | 11 +++++++++++ gfx/thebes/gfxAndroidPlatform.h | 5 ++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/gfx/thebes/gfxAndroidPlatform.cpp b/gfx/thebes/gfxAndroidPlatform.cpp index 0a1d788a5d41..1540b5eddbcc 100644 --- a/gfx/thebes/gfxAndroidPlatform.cpp +++ b/gfx/thebes/gfxAndroidPlatform.cpp @@ -42,6 +42,8 @@ #include "gfxFT2FontList.h" #include "gfxImageSurface.h" #include "nsXULAppAPI.h" +#include "nsIScreen.h" +#include "nsIScreenManager.h" #include "cairo.h" @@ -57,6 +59,15 @@ static FT_Library gPlatformFTLibrary = NULL; gfxAndroidPlatform::gfxAndroidPlatform() { FT_Init_FreeType(&gPlatformFTLibrary); + + nsCOMPtr screenMgr = do_GetService("@mozilla.org/gfx/screenmanager;1"); + nsCOMPtr screen; + screenMgr->GetPrimaryScreen(getter_AddRefs(screen)); + PRInt32 depth = 24; + screen->GetColorDepth(&depth); + + mOffscreenFormat = depth == 16 ? gfxASurface::ImageFormatRGB16_565 : + gfxASurface::ImageFormatARGB32; } gfxAndroidPlatform::~gfxAndroidPlatform() diff --git a/gfx/thebes/gfxAndroidPlatform.h b/gfx/thebes/gfxAndroidPlatform.h index 851525895f64..0b85749f10f1 100644 --- a/gfx/thebes/gfxAndroidPlatform.h +++ b/gfx/thebes/gfxAndroidPlatform.h @@ -68,7 +68,7 @@ public: virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend) { aBackend = mozilla::gfx::BACKEND_SKIA; return true; } - virtual gfxImageFormat GetOffscreenFormat() { return gfxASurface::ImageFormatRGB16_565; } + virtual gfxImageFormat GetOffscreenFormat() { return mOffscreenFormat; } mozilla::RefPtr GetScaledFontForFont(gfxFont *aFont); @@ -102,6 +102,9 @@ public: virtual bool FontHintingEnabled() MOZ_OVERRIDE; FT_Library GetFTLibrary(); + +private: + gfxImageFormat mOffscreenFormat; }; #endif /* GFX_PLATFORM_ANDROID_H */ From b6a058aba272f176e19888f0c834dbe5c638f704 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Tue, 13 Mar 2012 14:57:28 -0700 Subject: [PATCH 23/57] Bug 621446: followup to investigation patch - wrap MSVC-only pragma in ifdef so other compilers don't complain about it. r=jduell --- netwerk/protocol/http/HttpChannelParent.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/netwerk/protocol/http/HttpChannelParent.cpp b/netwerk/protocol/http/HttpChannelParent.cpp index c0d2fff0fc52..ee901cce07f3 100644 --- a/netwerk/protocol/http/HttpChannelParent.cpp +++ b/netwerk/protocol/http/HttpChannelParent.cpp @@ -333,7 +333,9 @@ HttpChannelParent::RecvUpdateAssociatedContentSecurity(const PRInt32& high, // Bug 621446 investigation, we don't want conditional PR_Aborts bellow to be // merged to a single address. +#ifdef _MSC_VER #pragma warning(disable : 4068) +#endif #pragma GCC optimize ("O0") bool From 5a8fe38d77eaff90ece35bacbc6477dd4194b1e7 Mon Sep 17 00:00:00 2001 From: Jason Duell Date: Tue, 13 Mar 2012 15:10:01 -0700 Subject: [PATCH 24/57] Backed out changeset fd30aea30b03 --- netwerk/protocol/http/HttpChannelChild.cpp | 35 +++++++++- netwerk/protocol/http/HttpChannelChild.h | 4 ++ netwerk/test/unit/test_traceable_channel.js | 76 ++++----------------- 3 files changed, 51 insertions(+), 64 deletions(-) diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/HttpChannelChild.cpp index dcaf4dcc2b03..4df4d51f61a5 100644 --- a/netwerk/protocol/http/HttpChannelChild.cpp +++ b/netwerk/protocol/http/HttpChannelChild.cpp @@ -291,8 +291,6 @@ HttpChannelChild::OnStartRequest(const nsHttpResponseHead& responseHead, mCacheEntryAvailable = cacheEntryAvailable; mCacheExpirationTime = cacheExpirationTime; mCachedCharset = cachedCharset; - mSelfAddr = selfAddr; - mPeerAddr = peerAddr; AutoEventEnqueuer ensureSerialDispatch(mEventQ); @@ -315,6 +313,9 @@ HttpChannelChild::OnStartRequest(const nsHttpResponseHead& responseHead, rv = ApplyContentConversions(); if (NS_FAILED(rv)) Cancel(rv); + + mSelfAddr = selfAddr; + mPeerAddr = peerAddr; } class TransportAndDataEvent : public ChannelEvent @@ -1112,6 +1113,36 @@ HttpChannelChild::SetupFallbackChannel(const char *aFallbackKey) DROP_DEAD(); } +// The next four _should_ be implemented, but we need to figure out how +// to transfer the data from the chrome process first. + +NS_IMETHODIMP +HttpChannelChild::GetRemoteAddress(nsACString & _result) +{ + return NS_ERROR_NOT_AVAILABLE; +} + +NS_IMETHODIMP +HttpChannelChild::GetRemotePort(PRInt32 * _result) +{ + NS_ENSURE_ARG_POINTER(_result); + return NS_ERROR_NOT_AVAILABLE; +} + +NS_IMETHODIMP +HttpChannelChild::GetLocalAddress(nsACString & _result) +{ + return NS_ERROR_NOT_AVAILABLE; +} + +NS_IMETHODIMP +HttpChannelChild::GetLocalPort(PRInt32 * _result) +{ + NS_ENSURE_ARG_POINTER(_result); + return NS_ERROR_NOT_AVAILABLE; +} + + //----------------------------------------------------------------------------- // HttpChannelChild::nsICacheInfoChannel //----------------------------------------------------------------------------- diff --git a/netwerk/protocol/http/HttpChannelChild.h b/netwerk/protocol/http/HttpChannelChild.h index f9f7c2e0003a..43617ef5589c 100644 --- a/netwerk/protocol/http/HttpChannelChild.h +++ b/netwerk/protocol/http/HttpChannelChild.h @@ -106,6 +106,10 @@ public: bool aMerge); // nsIHttpChannelInternal NS_IMETHOD SetupFallbackChannel(const char *aFallbackKey); + NS_IMETHOD GetLocalAddress(nsACString& addr); + NS_IMETHOD GetLocalPort(PRInt32* port); + NS_IMETHOD GetRemoteAddress(nsACString& addr); + NS_IMETHOD GetRemotePort(PRInt32* port); // nsISupportsPriority NS_IMETHOD SetPriority(PRInt32 value); // nsIResumableChannel diff --git a/netwerk/test/unit/test_traceable_channel.js b/netwerk/test/unit/test_traceable_channel.js index 164d65f4c46f..a62b8a2c92b3 100644 --- a/netwerk/test/unit/test_traceable_channel.js +++ b/netwerk/test/unit/test_traceable_channel.js @@ -22,42 +22,14 @@ TracingListener.prototype = { request.QueryInterface(Components.interfaces.nsIHttpChannelInternal); - var localAddr = "unknown"; - var localPort = "unknown"; - var remoteAddr = "unknown"; - var remotePort = "unknown"; - try { - localAddr = request.localAddress; - dump("got local address\n"); - } catch(e) { - dump("couldn't get local address\n"); - } - try { - localPort = request.localPort; - dump("got local port\n"); - } catch(e) { - dump("couldn't get local port\n"); - } - try { - remoteAddr = request.remoteAddress; - dump("got remote address\n"); - } catch(e) { - dump("couldn't get remote address\n"); - } - try { - remotePort = request.remotePort; - dump("got remote port\n"); - } catch(e) { - dump("couldn't get remote port\n"); - } - - do_check_eq(localAddr, "127.0.0.1"); - do_check_eq(localPort > 0, true); - do_check_eq(remoteAddr, "127.0.0.1"); - do_check_eq(remotePort, 4444); - - request.QueryInterface(Components.interfaces.nsISupportsPriority); - request.priority = Ci.nsISupportsPriority.PRIORITY_LOW; +// local/remote addresses broken in e10s: disable for now +/* + do_check_eq(request.localAddress, "127.0.0.1"); + do_check_eq(request.localPort > 0, true); + do_check_neq(request.localPort, 4444); + do_check_eq(request.remoteAddress, "127.0.0.1"); + do_check_eq(request.remotePort, 4444); +*/ // Make sure listener can't be replaced after OnStartRequest was called. request.QueryInterface(Components.interfaces.nsITraceableChannel); @@ -91,10 +63,9 @@ TracingListener.prototype = { input.close(); } catch (e) { dump("TracingListener.onStopRequest swallowing exception: " + e + "\n"); + } finally { + httpserver.stop(do_test_finished); } - - // we're the last OnStopRequest called by the nsIStreamListenerTee - run_next_test(); }, QueryInterface: function(iid) { @@ -164,37 +135,18 @@ function make_channel(url) { // Check if received body is correctly modified. function channel_finished(request, input, ctx) { - // No-op: since the nsIStreamListenerTee calls the observer's OnStopRequest - // after this, we call run_next_test() there -} - -// needs to be global or it'll go out of scope before it observes request -var observer = new HttpResponseExaminer(); - -var testRuns = 1; // change this to >1 to run test multiple times -var iteration = 1; - -function run_next_test() { - if (iteration > testRuns) { - dump("Shutting down\n"); - httpserver.stop(do_test_finished); - return; - } - if (iteration > 1) { - dump("^^^ test iteration=" + iteration + "\n"); - } - var channel = make_channel("http://localhost:4444/testdir"); - channel.asyncOpen(new ChannelListener(channel_finished), null); - iteration++; + httpserver.stop(do_test_finished); } function run_test() { + var observer = new HttpResponseExaminer(); observer.register(); httpserver = new nsHttpServer(); httpserver.registerPathHandler("/testdir", test_handler); httpserver.start(4444); - run_next_test(); + var channel = make_channel("http://localhost:4444/testdir"); + channel.asyncOpen(new ChannelListener(channel_finished), null); do_test_pending(); } From 1f10388ce321b591ce2073964380501f30f23948 Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Tue, 13 Mar 2012 22:29:29 +0000 Subject: [PATCH 25/57] Backout 8b74d5ae78c3 & c619bbb2951f (bug 734391), 772c994fa869 (bug 734324), fd23ff0f9dd1 (bug 734325), d1e037a9390e (bug 733653), 3a7bf79b5b2d (bug 733650) & 9d9392fce538 (bug 733652) for OS X M1 & M3 orange --- dom/base/nsDOMClassInfo.cpp | 7 + dom/base/nsDOMClassInfoClasses.h | 1 + dom/interfaces/geolocation/Makefile.in | 1 + .../geolocation/nsIDOMGeoPosition.idl | 5 +- .../geolocation/nsIDOMGeoPositionAddress.idl | 32 +- dom/ipc/ContentChild.cpp | 10 - dom/ipc/ContentChild.h | 2 - dom/ipc/ContentParent.cpp | 6 - dom/ipc/PContent.ipdl | 1 - dom/src/geolocation/nsGeoPosition.cpp | 106 +- dom/src/geolocation/nsGeoPosition.h | 38 + .../geolocation/nsGeoPositionIPCSerialiser.h | 101 +- dom/system/Makefile.in | 3 - dom/system/android/Makefile.in | 1 - dom/system/cocoa/Makefile.in | 4 - dom/system/cocoa/nsDeviceMotionSystem.mm | 139 ++- dom/system/cocoa/smslib.h | 159 --- dom/system/cocoa/smslib.mm | 937 ------------------ dom/system/nsDeviceMotion.cpp | 122 +-- dom/system/nsDeviceMotion.h | 18 +- dom/system/unix/Makefile.in | 3 - dom/system/unix/nsDeviceMotionSystem.cpp | 4 +- dom/system/windows/Makefile.in | 3 - dom/system/windows/nsDeviceMotionSystem.cpp | 4 +- embedding/android/GeckoEvent.java | 3 +- embedding/android/GeckoSurfaceView.java | 42 +- hal/HalSensor.h | 2 - mobile/android/base/GeckoApp.java | 45 +- mobile/android/base/GeckoAppShell.java | 105 +- mobile/android/base/GeckoEvent.java | 53 +- mobile/android/base/Makefile.in | 1 - toolkit/content/license.html | 54 - widget/android/AndroidBridge.cpp | 47 +- widget/android/AndroidBridge.h | 1 + widget/android/AndroidJavaWrappers.cpp | 98 +- widget/android/AndroidJavaWrappers.h | 34 +- widget/android/nsAppShell.cpp | 66 +- widget/android/nsAppShell.h | 2 +- xpcom/system/nsIDeviceMotion.idl | 8 +- 39 files changed, 725 insertions(+), 1543 deletions(-) rename mobile/android/base/GeckoHalDefines.java => dom/interfaces/geolocation/nsIDOMGeoPositionAddress.idl (73%) delete mode 100644 dom/system/cocoa/smslib.h delete mode 100644 dom/system/cocoa/smslib.mm diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 845f556b5815..d672d92484c7 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -1422,6 +1422,9 @@ static nsDOMClassInfoData sClassInfoData[] = { NS_DEFINE_CLASSINFO_DATA(GeoPositionCoords, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(GeoPositionAddress, nsDOMGenericSH, + DOM_DEFAULT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(GeoPositionError, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) @@ -4017,6 +4020,10 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_ENTRY(nsIDOMGeoPositionCoords) DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(GeoPositionAddress, nsIDOMGeoPositionAddress) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMGeoPositionAddress) + DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(GeoPositionError, nsIDOMGeoPositionError) DOM_CLASSINFO_MAP_ENTRY(nsIDOMGeoPositionError) DOM_CLASSINFO_MAP_END diff --git a/dom/base/nsDOMClassInfoClasses.h b/dom/base/nsDOMClassInfoClasses.h index 311edab11809..5885454b460b 100644 --- a/dom/base/nsDOMClassInfoClasses.h +++ b/dom/base/nsDOMClassInfoClasses.h @@ -422,6 +422,7 @@ DOMCI_CLASS(MessageEvent) DOMCI_CLASS(GeoGeolocation) DOMCI_CLASS(GeoPosition) DOMCI_CLASS(GeoPositionCoords) +DOMCI_CLASS(GeoPositionAddress) DOMCI_CLASS(GeoPositionError) DOMCI_CLASS(MozBatteryManager) diff --git a/dom/interfaces/geolocation/Makefile.in b/dom/interfaces/geolocation/Makefile.in index e775bdc5af9a..67655d343924 100644 --- a/dom/interfaces/geolocation/Makefile.in +++ b/dom/interfaces/geolocation/Makefile.in @@ -49,6 +49,7 @@ GRE_MODULE = 1 XPIDLSRCS = \ nsIDOMGeoGeolocation.idl \ nsIDOMGeoPosition.idl \ + nsIDOMGeoPositionAddress.idl \ nsIDOMGeoPositionCoords.idl \ nsIDOMGeoPositionCallback.idl \ nsIDOMGeoPositionError.idl \ diff --git a/dom/interfaces/geolocation/nsIDOMGeoPosition.idl b/dom/interfaces/geolocation/nsIDOMGeoPosition.idl index ee6c19ff1c28..6895356b8a83 100644 --- a/dom/interfaces/geolocation/nsIDOMGeoPosition.idl +++ b/dom/interfaces/geolocation/nsIDOMGeoPosition.idl @@ -37,10 +37,13 @@ #include "domstubs.idl" #include "nsIDOMGeoPositionCoords.idl" +#include "nsIDOMGeoPositionAddress.idl" -[scriptable, uuid(dd9f7e81-0f74-4fb5-b361-37019bf60c3f)] +[scriptable, uuid(23E5269F-4DD7-41C4-B52A-75918694C2DE)] interface nsIDOMGeoPosition : nsISupports { readonly attribute DOMTimeStamp timestamp; readonly attribute nsIDOMGeoPositionCoords coords; + readonly attribute nsIDOMGeoPositionAddress address; + }; diff --git a/mobile/android/base/GeckoHalDefines.java b/dom/interfaces/geolocation/nsIDOMGeoPositionAddress.idl similarity index 73% rename from mobile/android/base/GeckoHalDefines.java rename to dom/interfaces/geolocation/nsIDOMGeoPositionAddress.idl index ea6e02e06513..63ba4df455b2 100644 --- a/mobile/android/base/GeckoHalDefines.java +++ b/dom/interfaces/geolocation/nsIDOMGeoPositionAddress.idl @@ -1,5 +1,4 @@ -/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- - * ***** BEGIN LICENSE BLOCK ***** +/* ***** 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 @@ -12,13 +11,14 @@ * for the specific language governing rights and limitations under the * License. * - * The Original Code is Mozilla Android code. + * The Original Code is Geolocation. * - * The Initial Developer of the Original Code is Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2012 + * The Initial Developer of the Original Code is Mozilla Foundation + * Portions created by the Initial Developer are Copyright (C) 2008 * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Doug Turner (Original Author) * * 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 @@ -34,16 +34,18 @@ * * ***** END LICENSE BLOCK ***** */ -package org.mozilla.gecko; -public class GeckoHalDefines +#include "domstubs.idl" + +[scriptable, uuid(93abae10-7024-49eb-8e05-1931343b0ebb)] +interface nsIDOMGeoPositionAddress : nsISupports { - /* - * Keep these values consistent with |SensorType| in Hal.h - */ - public static final int SENSOR_ORIENTATION = 0; - public static final int SENSOR_ACCELERATION = 1; - public static final int SENSOR_PROXIMITY = 2; - public static final int SENSOR_LINEAR_ACCELERATION = 3; - public static final int SENSOR_GYROSCOPE = 4; + readonly attribute DOMString streetNumber; + readonly attribute DOMString street; + readonly attribute DOMString premises; + readonly attribute DOMString city; + readonly attribute DOMString county; + readonly attribute DOMString region; + readonly attribute DOMString country; + readonly attribute DOMString postalCode; }; diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 459514bf8411..c81f30fd0545 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -753,16 +753,6 @@ ContentChild::RecvDeviceMotionChanged(const long int& type, return true; } -bool -ContentChild::RecvNeedsCalibration() -{ - nsCOMPtr dmu = - do_GetService(NS_DEVICE_MOTION_CONTRACTID); - if (dmu) - dmu->NeedsCalibration(); - return true; -} - bool ContentChild::RecvScreenSizeChanged(const gfxIntSize& size) { diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index fafbe50bacd5..206bf8342002 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -162,8 +162,6 @@ public: const double& x, const double& y, const double& z); - virtual bool RecvNeedsCalibration(); - virtual bool RecvScreenSizeChanged(const gfxIntSize &size); virtual bool RecvFlushMemory(const nsString& reason); diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index a237c87dbfff..8507ac9a48c8 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -1291,12 +1291,6 @@ ContentParent::OnMotionChange(nsIDeviceMotionData *aDeviceData) { return NS_OK; } -NS_IMETHODIMP -ContentParent::NeedsCalibration() { - unused << SendNeedsCalibration(); - return NS_OK; -} - } // namespace dom } // namespace mozilla diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 2e2823aa5600..32efef5e119a 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -134,7 +134,6 @@ child: AddPermission(Permission permission); DeviceMotionChanged(long type, double x, double y, double z); - NeedsCalibration(); ScreenSizeChanged(gfxIntSize size); diff --git a/dom/src/geolocation/nsGeoPosition.cpp b/dom/src/geolocation/nsGeoPosition.cpp index 8981ef7a8144..b750b475435f 100644 --- a/dom/src/geolocation/nsGeoPosition.cpp +++ b/dom/src/geolocation/nsGeoPosition.cpp @@ -40,6 +40,100 @@ #include "nsGeoPosition.h" #include "nsDOMClassInfoID.h" +//////////////////////////////////////////////////// +// nsGeoPositionAddress +//////////////////////////////////////////////////// + +nsGeoPositionAddress::nsGeoPositionAddress(const nsAString &aStreetNumber, + const nsAString &aStreet, + const nsAString &aPremises, + const nsAString &aCity, + const nsAString &aCounty, + const nsAString &aRegion, + const nsAString &aCountry, + const nsAString &aPostalCode) + : mStreetNumber(aStreetNumber) + , mStreet(aStreet) + , mPremises(aPremises) + , mCity(aCity) + , mCounty(aCounty) + , mRegion(aRegion) + , mCountry(aCountry) + , mPostalCode(aPostalCode) +{ +} + +nsGeoPositionAddress::~nsGeoPositionAddress() +{ +} + +DOMCI_DATA(GeoPositionAddress, nsGeoPositionAddress) + +NS_INTERFACE_MAP_BEGIN(nsGeoPositionAddress) +NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoPositionAddress) +NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionAddress) +NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(GeoPositionAddress) +NS_INTERFACE_MAP_END + +NS_IMPL_THREADSAFE_ADDREF(nsGeoPositionAddress) +NS_IMPL_THREADSAFE_RELEASE(nsGeoPositionAddress) + +NS_IMETHODIMP +nsGeoPositionAddress::GetStreetNumber(nsAString & aStreetNumber) +{ + aStreetNumber = mStreetNumber; + return NS_OK; +} + +NS_IMETHODIMP +nsGeoPositionAddress::GetStreet(nsAString & aStreet) +{ + aStreet = mStreet; + return NS_OK; +} + +NS_IMETHODIMP +nsGeoPositionAddress::GetPremises(nsAString & aPremises) +{ + aPremises = mPremises; + return NS_OK; +} + +NS_IMETHODIMP +nsGeoPositionAddress::GetCity(nsAString & aCity) +{ + aCity = mCity; + return NS_OK; +} + +NS_IMETHODIMP +nsGeoPositionAddress::GetCounty(nsAString & aCounty) +{ + aCounty = mCounty; + return NS_OK; +} + +NS_IMETHODIMP +nsGeoPositionAddress::GetRegion(nsAString & aRegion) +{ + aRegion = mRegion; + return NS_OK; +} + +NS_IMETHODIMP +nsGeoPositionAddress::GetCountry(nsAString & aCountry) +{ + aCountry = mCountry; + return NS_OK; +} + +NS_IMETHODIMP +nsGeoPositionAddress::GetPostalCode(nsAString & aPostalCode) +{ + aPostalCode = mPostalCode; + return NS_OK; +} + //////////////////////////////////////////////////// // nsGeoPositionCoords //////////////////////////////////////////////////// @@ -145,9 +239,11 @@ nsGeoPosition::nsGeoPosition(nsIDOMGeoPositionCoords *aCoords, } nsGeoPosition::nsGeoPosition(nsIDOMGeoPositionCoords *aCoords, + nsIDOMGeoPositionAddress *aAddress, DOMTimeStamp aTimestamp) : mTimestamp(aTimestamp), - mCoords(aCoords) + mCoords(aCoords), + mAddress(aAddress) { } @@ -179,3 +275,11 @@ nsGeoPosition::GetCoords(nsIDOMGeoPositionCoords * *aCoords) NS_IF_ADDREF(*aCoords = mCoords); return NS_OK; } + +NS_IMETHODIMP +nsGeoPosition::GetAddress(nsIDOMGeoPositionAddress** aAddress) +{ + NS_IF_ADDREF(*aAddress = mAddress); + return NS_OK; +} + diff --git a/dom/src/geolocation/nsGeoPosition.h b/dom/src/geolocation/nsGeoPosition.h index a7a29770251f..c763b5becd85 100644 --- a/dom/src/geolocation/nsGeoPosition.h +++ b/dom/src/geolocation/nsGeoPosition.h @@ -43,10 +43,42 @@ #include "nsAutoPtr.h" #include "nsIClassInfo.h" #include "nsDOMClassInfoID.h" +#include "nsIDOMGeoPositionAddress.h" #include "nsIDOMGeoPositionCoords.h" #include "nsIDOMGeoPosition.h" #include "nsString.h" +//////////////////////////////////////////////////// +// nsGeoPositionAddress +//////////////////////////////////////////////////// + +class nsGeoPositionAddress : public nsIDOMGeoPositionAddress +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIDOMGEOPOSITIONADDRESS + + nsGeoPositionAddress( const nsAString &aStreetNumber, + const nsAString &aStreet, + const nsAString &aPremises, + const nsAString &aCity, + const nsAString &aCounty, + const nsAString &aRegion, + const nsAString &aCountry, + const nsAString &aPostalCode); + + ~nsGeoPositionAddress(); + private: + const nsString mStreetNumber; + const nsString mStreet; + const nsString mPremises; + const nsString mCity; + const nsString mCounty; + const nsString mRegion; + const nsString mCountry; + const nsString mPostalCode; +}; + //////////////////////////////////////////////////// // nsGeoPositionCoords //////////////////////////////////////////////////// @@ -90,12 +122,18 @@ public: long long aTimestamp); nsGeoPosition(nsIDOMGeoPositionCoords *aCoords, + nsIDOMGeoPositionAddress *aAddress, DOMTimeStamp aTimestamp); + void SetAddress(nsIDOMGeoPositionAddress *address) { + mAddress = address; + } + private: ~nsGeoPosition(); long long mTimestamp; nsRefPtr mCoords; + nsRefPtr mAddress; }; #endif /* nsGeoPosition_h */ diff --git a/dom/src/geolocation/nsGeoPositionIPCSerialiser.h b/dom/src/geolocation/nsGeoPositionIPCSerialiser.h index 89d0c9215148..f4597f8a52fd 100644 --- a/dom/src/geolocation/nsGeoPositionIPCSerialiser.h +++ b/dom/src/geolocation/nsGeoPositionIPCSerialiser.h @@ -41,11 +41,98 @@ #include "nsGeoPosition.h" #include "nsIDOMGeoPosition.h" +typedef nsIDOMGeoPositionAddress *GeoPositionAddress; typedef nsGeoPositionCoords *GeoPositionCoords; typedef nsIDOMGeoPosition *GeoPosition; namespace IPC { +template <> +struct ParamTraits +{ + typedef GeoPositionAddress paramType; + + // Function to serialize a geo position address + static void Write(Message *aMsg, const paramType& aParam) + { + bool isNull = !aParam; + WriteParam(aMsg, isNull); + // If it is null, then we are done + if (isNull) return; + + nsString addressLine; + + aParam->GetStreetNumber(addressLine); + WriteParam(aMsg, addressLine); + + aParam->GetStreet(addressLine); + WriteParam(aMsg, addressLine); + + aParam->GetPremises(addressLine); + WriteParam(aMsg, addressLine); + + aParam->GetCity(addressLine); + WriteParam(aMsg, addressLine); + + aParam->GetCounty(addressLine); + WriteParam(aMsg, addressLine); + + aParam->GetRegion(addressLine); + WriteParam(aMsg, addressLine); + + aParam->GetCountry(addressLine); + WriteParam(aMsg, addressLine); + + aParam->GetPostalCode(addressLine); + WriteParam(aMsg, addressLine); + } + + // Function to de-serialize a geoposition + static bool Read(const Message* aMsg, void **aIter, paramType* aResult) + { + // Check if it is the null pointer we have transfered + bool isNull; + if (!ReadParam(aMsg, aIter, &isNull)) return false; + + if (isNull) { + *aResult = 0; + return true; + } + + // We need somewhere to store the address before we create the object + nsString streetNumber; + nsString street; + nsString premises; + nsString city; + nsString county; + nsString region; + nsString country; + nsString postalCode; + + // It's not important to us where it fails, but rather if it fails + if (!(ReadParam(aMsg, aIter, &streetNumber) && + ReadParam(aMsg, aIter, &street ) && + ReadParam(aMsg, aIter, &premises ) && + ReadParam(aMsg, aIter, &city ) && + ReadParam(aMsg, aIter, &county ) && + ReadParam(aMsg, aIter, ®ion ) && + ReadParam(aMsg, aIter, &country ) && + ReadParam(aMsg, aIter, &postalCode ))) return false; + + // We now have all the data + *aResult = new nsGeoPositionAddress(streetNumber, /* aStreetNumber */ + street, /* aStreet */ + premises, /* aPremises */ + city, /* aCity */ + county, /* aCounty */ + region, /* aRegion */ + country, /* aCountry */ + postalCode /* aPostalCode */ + ); + return true; + } +} ; + template <> struct ParamTraits { @@ -148,6 +235,11 @@ struct ParamTraits aParam->GetCoords(getter_AddRefs(coords)); GeoPositionCoords simpleCoords = static_cast(coords.get()); WriteParam(aMsg, simpleCoords); + + nsCOMPtr address; + aParam->GetAddress(getter_AddRefs(address)); + GeoPositionAddress simpleAddress = address.get(); + WriteParam(aMsg, simpleAddress); } // Function to de-serialize a geoposition @@ -164,17 +256,20 @@ struct ParamTraits DOMTimeStamp timeStamp; GeoPositionCoords coords = nsnull; + GeoPositionAddress address; // It's not important to us where it fails, but rather if it fails if (!( ReadParam(aMsg, aIter, &timeStamp) - && ReadParam(aMsg, aIter, &coords ))) { + && ReadParam(aMsg, aIter, &coords ) + && ReadParam(aMsg, aIter, &address ))) { // note it is fine to do "delete nsnull" in case coords hasn't - // been allocated + // been allocated and we will never have a case where address + // gets allocated and we end here delete coords; return false; } - *aResult = new nsGeoPosition(coords, timeStamp); + *aResult = new nsGeoPosition(coords, address, timeStamp); return true; }; diff --git a/dom/system/Makefile.in b/dom/system/Makefile.in index b5b2062fa996..ce9346ba491e 100644 --- a/dom/system/Makefile.in +++ b/dom/system/Makefile.in @@ -87,9 +87,6 @@ EXPORTS = \ nsDeviceMotion.h \ $(NULL) -# We fire the nsDOMDeviceAcceleration -LOCAL_INCLUDES += -I$(topsrcdir)/content/events/src - include $(topsrcdir)/config/config.mk # we don't want the shared lib, but we want to force the creation of a static lib. diff --git a/dom/system/android/Makefile.in b/dom/system/android/Makefile.in index 6f79c35fd085..48cf9473c350 100644 --- a/dom/system/android/Makefile.in +++ b/dom/system/android/Makefile.in @@ -59,7 +59,6 @@ CPPSRCS = \ $(NULL) LOCAL_INCLUDES += -I$(topsrcdir)/dom/src/geolocation \ - -I$(topsrcdir)/content/events/src $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/dom/system/cocoa/Makefile.in b/dom/system/cocoa/Makefile.in index 7853d19a71d5..bbc3d49fe454 100644 --- a/dom/system/cocoa/Makefile.in +++ b/dom/system/cocoa/Makefile.in @@ -49,13 +49,9 @@ LIBXUL_LIBRARY = 1 FORCE_STATIC_LIB = 1 EXPORT_LIBRARY = 1 -# We fire the nsDOMDeviceAcceleration -LOCAL_INCLUDES += -I$(topsrcdir)/content/events/src - include $(topsrcdir)/config/config.mk CMMSRCS = \ - smslib.mm \ nsDeviceMotionSystem.mm \ $(NULL) diff --git a/dom/system/cocoa/nsDeviceMotionSystem.mm b/dom/system/cocoa/nsDeviceMotionSystem.mm index bdeefdf679d5..6fc0385c2ee6 100644 --- a/dom/system/cocoa/nsDeviceMotionSystem.mm +++ b/dom/system/cocoa/nsDeviceMotionSystem.mm @@ -42,9 +42,8 @@ #include #include -#import "smslib.h" -#define MEAN_GRAVITY 9.80665 -#define DEFAULT_SENSOR_POLL 100 +#define MODEL_NAME_LENGTH 64 +static char gModelName[MODEL_NAME_LENGTH]; nsDeviceMotionSystem::nsDeviceMotionSystem() { @@ -54,6 +53,24 @@ nsDeviceMotionSystem::~nsDeviceMotionSystem() { } +// Data format returned from IOConnectMethodStructureIStructureO. +// I am not sure what the other bits in this structure are, +// or if there are any, but this has to be 40 bytes long or +// the call to read fails. +// +// Since we make the SmsData struct larger than any members we plan to access we +// keep track of the the size of the part of the struct we plan to access for +// use in bounds checking. +#define SMSDATA_PADDING_SIZE 34 +typedef struct +{ + PRInt16 x; + PRInt16 y; + PRInt16 z; + PRInt8 unknown[SMSDATA_PADDING_SIZE]; +} SmsData; +#define SMSDATA_USED_SIZE (sizeof(SmsData) - SMSDATA_PADDING_SIZE) + void nsDeviceMotionSystem::UpdateHandler(nsITimer *aTimer, void *aClosure) { @@ -62,35 +79,129 @@ nsDeviceMotionSystem::UpdateHandler(nsITimer *aTimer, void *aClosure) NS_ERROR("no self"); return; } - sms_acceleration accel; - smsGetData(&accel); - self->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ACCELERATION, - accel.x * MEAN_GRAVITY, - accel.y * MEAN_GRAVITY, - accel.z * MEAN_GRAVITY); + size_t bufferLen = sizeof(SmsData); + + void * input = malloc(bufferLen); + void * output = malloc(bufferLen); + + if (!input || !output) + return; + + memset(input, 0, bufferLen); + memset(output, 0, bufferLen); + + size_t structureOutputSize = bufferLen; +#if (MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4) + kern_return_t result = ::IOConnectMethodStructureIStructureO(self->mSmsConnection, + 5, /* Magic number for SMCMotionSensor */ + bufferLen, + (IOByteCount*)&structureOutputSize, + input, + output); +#else + kern_return_t result = ::IOConnectCallStructMethod((mach_port_t)self->mSmsConnection, + 5, /* Magic number for SMCMotionSensor */ + input, + bufferLen, + output, + &structureOutputSize); +#endif + + if ((result != kIOReturnSuccess) || (structureOutputSize < SMSDATA_USED_SIZE)) { + free(input); + free(output); + return; + } + + SmsData *data = (SmsData*) output; + + float xf, yf, zf; + + // we want to normalize the return result from the chip to + // something between -1 and 1 where 0 is the balance point. + + const int normalizeFactor = 250.5; + + if (!strcmp(gModelName, "MacBookPro5,1")) { + xf = ((float)data->x) / normalizeFactor; + yf = (((float)data->y) / normalizeFactor) * -1; + zf = ((float)data->z) / normalizeFactor; + } + else if (!strcmp(gModelName, "MacBookPro5,3")) { + xf = ((float)data->y) / normalizeFactor; + yf = (((float)data->x) / normalizeFactor) * -1; + zf = (((float)data->z) / normalizeFactor) * -1; + } + else + { + xf = (((float)data->x) / normalizeFactor) * -1; + yf = ((float)data->y) / normalizeFactor; + zf = ((float)data->z) / normalizeFactor; + } + + free(input); + free(output); + + self->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ACCELERATION, xf, yf, zf ); } void nsDeviceMotionSystem::Startup() { - smsStartup(nil, nil); - smsLoadCalibration(); + // we can fail, and that just means the caller will not see any changes. + + mach_port_t port; + kern_return_t result = ::IOMasterPort(MACH_PORT_NULL, &port); + if (result != kIOReturnSuccess) + return; + + CFMutableDictionaryRef dict = ::IOServiceMatching("SMCMotionSensor"); + if (!dict) + return; + + io_iterator_t iter; + result = ::IOServiceGetMatchingServices(port, dict, &iter); + if (result != kIOReturnSuccess) + return; + + io_object_t device = ::IOIteratorNext(iter); + + ::IOObjectRelease(iter); + + if (!device) + return; + + result = ::IOServiceOpen(device, mach_task_self(), 0, &mSmsConnection); + ::IOObjectRelease(device); + + if (result != kIOReturnSuccess) + return; + + mach_port_deallocate(mach_task_self(), port); + + /* get the version of the hardware we are running on. */ + int mib[2]; + size_t len = MODEL_NAME_LENGTH; + mib[0] = CTL_HW; + mib[1] = HW_MODEL; + sysctl(mib, 2, gModelName, &len, NULL, 0); mUpdateTimer = do_CreateInstance("@mozilla.org/timer;1"); if (mUpdateTimer) mUpdateTimer->InitWithFuncCallback(UpdateHandler, this, - DEFAULT_SENSOR_POLL, + mUpdateInterval, nsITimer::TYPE_REPEATING_SLACK); } void nsDeviceMotionSystem::Shutdown() { + if (mSmsConnection) + ::IOServiceClose(mSmsConnection); + if (mUpdateTimer) { mUpdateTimer->Cancel(); mUpdateTimer = nsnull; } - - smsShutdown(); } diff --git a/dom/system/cocoa/smslib.h b/dom/system/cocoa/smslib.h deleted file mode 100644 index 2f0b2664e459..000000000000 --- a/dom/system/cocoa/smslib.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * smslib.h - * - * SMSLib Sudden Motion Sensor Access Library - * Copyright (c) 2010 Suitable Systems - * All rights reserved. - * - * Developed by: Daniel Griscom - * Suitable Systems - * http://www.suitable.com - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal with the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimers. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimers in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the names of Suitable Systems nor the names of its - * contributors may be used to endorse or promote products derived from - * this Software without specific prior written permission. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. - * - * For more information about SMSLib, see - * - * or contact - * Daniel Griscom - * Suitable Systems - * 1 Centre Street, Suite 204 - * Wakefield, MA 01880 - * (781) 665-0053 - * - */ - -#import - -#define SMSLIB_VERSION "1.8" - -#pragma mark Structure definitions - -// Structure for specifying a 3-axis acceleration. 0.0 means "zero gravities", -// 1.0 means "one gravity". -typedef struct sms_acceleration { - float x; // Right-left acceleration (positive is rightwards) - float y; // Front-rear acceleration (positive is rearwards) - float z; // Up-down acceleration (positive is upwards) -} sms_acceleration; - -// Structure for specifying a calibration. -typedef struct sms_calibration { - float zeros[3]; // Zero points for three axes (X, Y, Z) - float onegs[3]; // One gravity values for three axes -} sms_calibration; - -#pragma mark Return value definitions - -// These are the return values for accelStartup(), giving the -// various stages where the most successful attempt at accessing -// the accelerometer failed. The higher the value, the further along the -// software progressed before failing. The options are: -// - Didn't match model name -#define SMS_FAIL_MODEL (-7) -// - Failure getting dictionary matching desired services -#define SMS_FAIL_DICTIONARY (-6) -// - Failure getting list of services -#define SMS_FAIL_LIST_SERVICES (-5) -// - Failure if list of services is empty. The process generally fails -// here if run on a machine without a Sudden Motion Sensor. -#define SMS_FAIL_NO_SERVICES (-4) -// - Failure if error opening device. -#define SMS_FAIL_OPENING (-3) -// - Failure if opened, but didn't get a connection -#define SMS_FAIL_CONNECTION (-2) -// - Failure if couldn't access connction using given function and size. This -// is where the process would probably fail with a change in Apple's API. -// Driver problems often also cause failures here. -#define SMS_FAIL_ACCESS (-1) -// - Success! -#define SMS_SUCCESS (0) - -#pragma mark Function declarations - -// This starts up the accelerometer code, trying each possible sensor -// specification. Note that for logging purposes it -// takes an object and a selector; the object's selector is then invoked -// with a single NSString as argument giving progress messages. Example -// logging method: -// - (void)logMessage: (NSString *)theString -// which would be used in accelStartup's invocation thusly: -// result = accelStartup(self, @selector(logMessage:)); -// If the object is nil, then no logging is done. Sets calibation from built-in -// value table. Returns ACCEL_SUCCESS for success, and other (negative) -// values for various failures (returns value indicating result of -// most successful trial). -int smsStartup(id logObject, SEL logSelector); - -// This starts up the library in debug mode, ignoring the actual hardware. -// Returned data is in the form of 1Hz sine waves, with the X, Y and Z -// axes 120 degrees out of phase; "calibrated" data has range +/- (1.0/5); -// "uncalibrated" data has range +/- (256/5). X and Y axes centered on 0.0, -// Z axes centered on 1 (calibrated) or 256 (uncalibrated). -// Don't use smsGetBufferLength or smsGetBufferData. Always returns SMS_SUCCESS. -int smsDebugStartup(id logObject, SEL logSelector); - -// Returns the current calibration values. -void smsGetCalibration(sms_calibration *calibrationRecord); - -// Sets the calibration, but does NOT store it as a preference. If the argument -// is nil then the current calibration is set from the built-in value table. -void smsSetCalibration(sms_calibration *calibrationRecord); - -// Stores the current calibration values as a stored preference. -void smsStoreCalibration(void); - -// Loads the stored preference values into the current calibration. -// Returns YES if successful. -BOOL smsLoadCalibration(void); - -// Deletes any stored calibration, and then takes the current calibration values -// from the built-in value table. -void smsDeleteCalibration(void); - -// Fills in the accel record with calibrated acceleration data. Takes -// 1-2ms to return a value. Returns 0 if success, error number if failure. -int smsGetData(sms_acceleration *accel); - -// Fills in the accel record with uncalibrated acceleration data. -// Returns 0 if success, error number if failure. -int smsGetUncalibratedData(sms_acceleration *accel); - -// Returns the length of a raw block of data for the current type of sensor. -int smsGetBufferLength(void); - -// Takes a pointer to accelGetRawLength() bytes; sets those bytes -// to return value from sensor. Make darn sure the buffer length is right! -void smsGetBufferData(char *buffer); - -// This returns an NSString describing the current calibration in -// human-readable form. Also include a description of the machine. -NSString *smsGetCalibrationDescription(void); - -// Shuts down the accelerometer. -void smsShutdown(void); - diff --git a/dom/system/cocoa/smslib.mm b/dom/system/cocoa/smslib.mm deleted file mode 100644 index 8761a81f48fa..000000000000 --- a/dom/system/cocoa/smslib.mm +++ /dev/null @@ -1,937 +0,0 @@ -/* - * smslib.m - * - * SMSLib Sudden Motion Sensor Access Library - * Copyright (c) 2010 Suitable Systems - * All rights reserved. - * - * Developed by: Daniel Griscom - * Suitable Systems - * http://www.suitable.com - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal with the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimers. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimers in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the names of Suitable Systems nor the names of its - * contributors may be used to endorse or promote products derived from - * this Software without specific prior written permission. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. - * - * For more information about SMSLib, see - * - * or contact - * Daniel Griscom - * Suitable Systems - * 1 Centre Street, Suite 204 - * Wakefield, MA 01880 - * (781) 665-0053 - * - */ - -#import -#import -#import -#import "smslib.h" - -#pragma mark Internal structures - -// Represents a single axis of a type of sensor. -typedef struct axisStruct { - int enabled; // Non-zero if axis is valid in this sensor - int index; // Location in struct of first byte - int size; // Number of bytes - float zerog; // Value meaning "zero g" - float oneg; // Change in value meaning "increase of one g" - // (can be negative if axis sensor reversed) -} axisStruct; - -// Represents the configuration of a type of sensor. -typedef struct sensorSpec { - char *model; // Prefix of model to be tested - char *name; // Name of device to be read - unsigned int function; // Kernel function index - int recordSize; // Size of record to be sent/received - axisStruct axes[3]; // Description of three axes (X, Y, Z) -} sensorSpec; - -// Configuration of all known types of sensors. The configurations are -// tried in order until one succeeds in returning data. -// All default values are set here, but each axis' zerog and oneg values -// may be changed to saved (calibrated) values. -// -// These values came from SeisMaCalibrate calibration reports. In general I've -// found the following: -// - All Intel-based SMSs have 250 counts per g, centered on 0, but the signs -// are different (and in one case two axes are swapped) -// - PowerBooks and iBooks all have sensors centered on 0, and reading -// 50-53 steps per gravity (but with differing polarities!) -// - PowerBooks and iBooks of the same model all have the same axis polarities -// - PowerBook and iBook access methods are model- and OS version-specific -// -// So, the sequence of tests is: -// - Try model-specific access methods. Note that the test is for a match to the -// beginning of the model name, e.g. the record with model name "MacBook" -// matches computer models "MacBookPro1,2" and "MacBook1,1" (and "" -// matches any model). -// - If no model-specific record's access fails, then try each model-independent -// access method in order, stopping when one works. -static const sensorSpec sensors[] = { - // ****** Model-dependent methods ****** - // The PowerBook5,6 is one of the G4 models that seems to lose - // SMS access until the next reboot. - {"PowerBook5,6", "IOI2CMotionSensor", 21, 60, { - {1, 0, 1, 0, 51.5}, - {1, 1, 1, 0, -51.5}, - {1, 2, 1, 0, -51.5} - } - }, - // The PowerBook5,7 is one of the G4 models that seems to lose - // SMS access until the next reboot. - {"PowerBook5,7", "IOI2CMotionSensor", 21, 60, { - {1, 0, 1, 0, 51.5}, - {1, 1, 1, 0, 51.5}, - {1, 2, 1, 0, 51.5} - } - }, - // Access seems to be reliable on the PowerBook5,8 - {"PowerBook5,8", "PMUMotionSensor", 21, 60, { - {1, 0, 1, 0, -51.5}, - {1, 1, 1, 0, 51.5}, - {1, 2, 1, 0, -51.5} - } - }, - // Access seems to be reliable on the PowerBook5,9 - {"PowerBook5,9", "PMUMotionSensor", 21, 60, { - {1, 0, 1, 0, 51.5}, - {1, 1, 1, 0, -51.5}, - {1, 2, 1, 0, -51.5} - } - }, - // The PowerBook6,7 is one of the G4 models that seems to lose - // SMS access until the next reboot. - {"PowerBook6,7", "IOI2CMotionSensor", 21, 60, { - {1, 0, 1, 0, 51.5}, - {1, 1, 1, 0, 51.5}, - {1, 2, 1, 0, 51.5} - } - }, - // The PowerBook6,8 is one of the G4 models that seems to lose - // SMS access until the next reboot. - {"PowerBook6,8", "IOI2CMotionSensor", 21, 60, { - {1, 0, 1, 0, 51.5}, - {1, 1, 1, 0, 51.5}, - {1, 2, 1, 0, 51.5} - } - }, - // MacBook Pro Core 2 Duo 17". Note the reversed Y and Z axes. - {"MacBookPro2,1", "SMCMotionSensor", 5, 40, { - {1, 0, 2, 0, 251}, - {1, 2, 2, 0, -251}, - {1, 4, 2, 0, -251} - } - }, - // MacBook Pro Core 2 Duo 15" AND 17" with LED backlight, introduced June '07. - // NOTE! The 17" machines have the signs of their X and Y axes reversed - // from this calibration, but there's no clear way to discriminate between - // the two machines. - {"MacBookPro3,1", "SMCMotionSensor", 5, 40, { - {1, 0, 2, 0, -251}, - {1, 2, 2, 0, 251}, - {1, 4, 2, 0, -251} - } - }, - // ... specs? - {"MacBook5,2", "SMCMotionSensor", 5, 40, { - {1, 0, 2, 0, -251}, - {1, 2, 2, 0, 251}, - {1, 4, 2, 0, -251} - } - }, - // ... specs? - {"MacBookPro5,1", "SMCMotionSensor", 5, 40, { - {1, 0, 2, 0, -251}, - {1, 2, 2, 0, -251}, - {1, 4, 2, 0, 251} - } - }, - // ... specs? - {"MacBookPro5,2", "SMCMotionSensor", 5, 40, { - {1, 0, 2, 0, -251}, - {1, 2, 2, 0, -251}, - {1, 4, 2, 0, 251} - } - }, - // This is speculative, based on a single user's report. Looks like the X and Y axes - // are swapped. This is true for no other known Appple laptop. - {"MacBookPro5,3", "SMCMotionSensor", 5, 40, { - {1, 2, 2, 0, -251}, - {1, 0, 2, 0, -251}, - {1, 4, 2, 0, -251} - } - }, - // ... specs? - {"MacBookPro5,4", "SMCMotionSensor", 5, 40, { - {1, 0, 2, 0, -251}, - {1, 2, 2, 0, -251}, - {1, 4, 2, 0, 251} - } - }, - // ****** Model-independent methods ****** - // Seen once with PowerBook6,8 under system 10.3.9; I suspect - // other G4-based 10.3.* systems might use this - {"", "IOI2CMotionSensor", 24, 60, { - {1, 0, 1, 0, 51.5}, - {1, 1, 1, 0, 51.5}, - {1, 2, 1, 0, 51.5} - } - }, - // PowerBook5,6 , PowerBook5,7 , PowerBook6,7 , PowerBook6,8 - // under OS X 10.4.* - {"", "IOI2CMotionSensor", 21, 60, { - {1, 0, 1, 0, 51.5}, - {1, 1, 1, 0, 51.5}, - {1, 2, 1, 0, 51.5} - } - }, - // PowerBook5,8 , PowerBook5,9 under OS X 10.4.* - {"", "PMUMotionSensor", 21, 60, { - // Each has two out of three gains negative, but it's different - // for the different models. So, this will be right in two out - // of three axis for either model. - {1, 0, 1, 0, -51.5}, - {1, 1, 1, -6, -51.5}, - {1, 2, 1, 0, -51.5} - } - }, - // All MacBook, MacBookPro models. Hardware (at least on early MacBookPro 15") - // is Kionix KXM52-1050 three-axis accelerometer chip. Data is at - // http://kionix.com/Product-Index/product-index.htm. Specific MB and MBP models - // that use this are: - // MacBook1,1 - // MacBook2,1 - // MacBook3,1 - // MacBook4,1 - // MacBook5,1 - // MacBook6,1 - // MacBookAir1,1 - // MacBookPro1,1 - // MacBookPro1,2 - // MacBookPro4,1 - // MacBookPro5,5 - {"", "SMCMotionSensor", 5, 40, { - {1, 0, 2, 0, 251}, - {1, 2, 2, 0, 251}, - {1, 4, 2, 0, 251} - } - } -}; - -#define SENSOR_COUNT (sizeof(sensors)/sizeof(sensorSpec)) - -#pragma mark Internal prototypes - -static int getData(sms_acceleration *accel, int calibrated, id logObject, SEL logSelector); -static float getAxis(int which, int calibrated); -static int signExtend(int value, int size); -static NSString *getModelName(void); -static NSString *getOSVersion(void); -static BOOL loadCalibration(void); -static void storeCalibration(void); -static void defaultCalibration(void); -static void deleteCalibration(void); -static int prefIntRead(NSString *prefName, BOOL *success); -static void prefIntWrite(NSString *prefName, int prefValue); -static float prefFloatRead(NSString *prefName, BOOL *success); -static void prefFloatWrite(NSString *prefName, float prefValue); -static void prefDelete(NSString *prefName); -static void prefSynchronize(void); -// static long getMicroseconds(void); -float fakeData(NSTimeInterval time); - -#pragma mark Static variables - -static int debugging = NO; // True if debugging (synthetic data) -static io_connect_t connection; // Connection for reading accel values -static int running = NO; // True if we successfully started -static int sensorNum = 0; // The current index into sensors[] -static char *serviceName; // The name of the current service -static char *iRecord, *oRecord; // Pointers to read/write records for sensor -static int recordSize; // Size of read/write records -static unsigned int function; // Which kernel function should be used -static float zeros[3]; // X, Y and Z zero calibration values -static float onegs[3]; // X, Y and Z one-g calibration values - -#pragma mark Defines - -// Pattern for building axis letter from axis number -#define INT_TO_AXIS(a) (a == 0 ? @"X" : a == 1 ? @"Y" : @"Z") -// Name of configuration for given axis' zero (axis specified by integer) -#define ZERO_NAME(a) [NSString stringWithFormat:@"%@-Axis-Zero", INT_TO_AXIS(a)] -// Name of configuration for given axis' oneg (axis specified by integer) -#define ONEG_NAME(a) [NSString stringWithFormat:@"%@-Axis-One-g", INT_TO_AXIS(a)] -// Name of "Is calibrated" preference -#define CALIBRATED_NAME (@"Calibrated") -// Application domain for SeisMac library -#define APP_ID ((CFStringRef)@"com.suitable.SeisMacLib") - -// These #defines make the accelStartup code a LOT easier to read. -#define LOG(message) \ - if (logObject) { \ - [logObject performSelector:logSelector withObject:message]; \ - } -#define LOG_ARG(format, var1) \ - if (logObject) { \ - [logObject performSelector:logSelector \ - withObject:[NSString stringWithFormat:format, var1]]; \ - } -#define LOG_2ARG(format, var1, var2) \ - if (logObject) { \ - [logObject performSelector:logSelector \ - withObject:[NSString stringWithFormat:format, var1, var2]]; \ - } -#define LOG_3ARG(format, var1, var2, var3) \ - if (logObject) { \ - [logObject performSelector:logSelector \ - withObject:[NSString stringWithFormat:format, var1, var2, var3]]; \ - } - -#pragma mark Function definitions - -// This starts up the accelerometer code, trying each possible sensor -// specification. Note that for logging purposes it -// takes an object and a selector; the object's selector is then invoked -// with a single NSString as argument giving progress messages. Example -// logging method: -// - (void)logMessage: (NSString *)theString -// which would be used in accelStartup's invocation thusly: -// result = accelStartup(self, @selector(logMessage:)); -// If the object is nil, then no logging is done. Sets calibation from built-in -// value table. Returns ACCEL_SUCCESS for success, and other (negative) -// values for various failures (returns value indicating result of -// most successful trial). -int smsStartup(id logObject, SEL logSelector) { - io_iterator_t iterator; - io_object_t device; - kern_return_t result; - sms_acceleration accel; - int failure_result = SMS_FAIL_MODEL; - - running = NO; - debugging = NO; - - NSString *modelName = getModelName(); - - LOG_ARG(@"Machine model: %@\n", modelName); - LOG_ARG(@"OS X version: %@\n", getOSVersion()); - LOG_ARG(@"Accelerometer library version: %s\n", SMSLIB_VERSION); - - for (sensorNum = 0; sensorNum < SENSOR_COUNT; sensorNum++) { - - // Set up all specs for this type of sensor - serviceName = sensors[sensorNum].name; - recordSize = sensors[sensorNum].recordSize; - function = sensors[sensorNum].function; - - LOG_3ARG(@"Trying service \"%s\" with selector %d and %d byte record:\n", - serviceName, function, recordSize); - - NSString *targetName = [NSString stringWithCString:sensors[sensorNum].model - encoding:NSMacOSRomanStringEncoding]; - LOG_ARG(@" Comparing model name to target \"%@\": ", targetName); - if ([targetName length] == 0 || [modelName hasPrefix:targetName]) { - LOG(@"success.\n"); - } else { - LOG(@"failure.\n"); - // Don't need to increment failure_result. - continue; - } - - LOG(@" Fetching dictionary for service: "); - CFMutableDictionaryRef dict = IOServiceMatching(serviceName); - - if (dict) { - LOG(@"success.\n"); - } else { - LOG(@"failure.\n"); - if (failure_result < SMS_FAIL_DICTIONARY) { - failure_result = SMS_FAIL_DICTIONARY; - } - continue; - } - - LOG(@" Getting list of matching services: "); - result = IOServiceGetMatchingServices(kIOMasterPortDefault, - dict, - &iterator); - - if (result == KERN_SUCCESS) { - LOG(@"success.\n"); - } else { - LOG_ARG(@"failure, with return value 0x%x.\n", result); - if (failure_result < SMS_FAIL_LIST_SERVICES) { - failure_result = SMS_FAIL_LIST_SERVICES; - } - continue; - } - - LOG(@" Getting first device in list: "); - device = IOIteratorNext(iterator); - - if (device == 0) { - LOG(@"failure.\n"); - if (failure_result < SMS_FAIL_NO_SERVICES) { - failure_result = SMS_FAIL_NO_SERVICES; - } - continue; - } else { - LOG(@"success.\n"); - LOG(@" Opening device: "); - } - - result = IOServiceOpen(device, mach_task_self(), 0, &connection); - - if (result != KERN_SUCCESS) { - LOG_ARG(@"failure, with return value 0x%x.\n", result); - IOObjectRelease(device); - if (failure_result < SMS_FAIL_OPENING) { - failure_result = SMS_FAIL_OPENING; - } - continue; - } else if (connection == 0) { - LOG_ARG(@"'success', but didn't get a connection.\n", result); - IOObjectRelease(device); - if (failure_result < SMS_FAIL_CONNECTION) { - failure_result = SMS_FAIL_CONNECTION; - } - continue; - } else { - IOObjectRelease(device); - LOG(@"success.\n"); - } - LOG(@" Testing device.\n"); - - defaultCalibration(); - - iRecord = (char*) malloc(recordSize); - oRecord = (char*) malloc(recordSize); - - running = YES; - result = getData(&accel, true, logObject, logSelector); - running = NO; - - if (result) { - LOG_ARG(@" Failure testing device, with result 0x%x.\n", result); - free(iRecord); - iRecord = 0; - free(oRecord); - oRecord = 0; - if (failure_result < SMS_FAIL_ACCESS) { - failure_result = SMS_FAIL_ACCESS; - } - continue; - } else { - LOG(@" Success testing device!\n"); - running = YES; - return SMS_SUCCESS; - } - } - return failure_result; -} - -// This starts up the library in debug mode, ignoring the actual hardware. -// Returned data is in the form of 1Hz sine waves, with the X, Y and Z -// axes 120 degrees out of phase; "calibrated" data has range +/- (1.0/5); -// "uncalibrated" data has range +/- (256/5). X and Y axes centered on 0.0, -// Z axes centered on 1 (calibrated) or 256 (uncalibrated). -// Don't use smsGetBufferLength or smsGetBufferData. Always returns SMS_SUCCESS. -int smsDebugStartup(id logObject, SEL logSelector) { - LOG(@"Starting up in debug mode\n"); - debugging = YES; - return SMS_SUCCESS; -} - -// Returns the current calibration values. -void smsGetCalibration(sms_calibration *calibrationRecord) { - int x; - - for (x = 0; x < 3; x++) { - calibrationRecord->zeros[x] = (debugging ? 0 : zeros[x]); - calibrationRecord->onegs[x] = (debugging ? 256 : onegs[x]); - } -} - -// Sets the calibration, but does NOT store it as a preference. If the argument -// is nil then the current calibration is set from the built-in value table. -void smsSetCalibration(sms_calibration *calibrationRecord) { - int x; - - if (!debugging) { - if (calibrationRecord) { - for (x = 0; x < 3; x++) { - zeros[x] = calibrationRecord->zeros[x]; - onegs[x] = calibrationRecord->onegs[x]; - } - } else { - defaultCalibration(); - } - } -} - -// Stores the current calibration values as a stored preference. -void smsStoreCalibration(void) { - if (!debugging) - storeCalibration(); -} - -// Loads the stored preference values into the current calibration. -// Returns YES if successful. -BOOL smsLoadCalibration(void) { - if (debugging) { - return YES; - } else if (loadCalibration()) { - return YES; - } else { - defaultCalibration(); - return NO; - } -} - -// Deletes any stored calibration, and then takes the current calibration values -// from the built-in value table. -void smsDeleteCalibration(void) { - if (!debugging) { - deleteCalibration(); - defaultCalibration(); - } -} - -// Fills in the accel record with calibrated acceleration data. Takes -// 1-2ms to return a value. Returns 0 if success, error number if failure. -int smsGetData(sms_acceleration *accel) { - NSTimeInterval time; - if (debugging) { - usleep(1500); // Usually takes 1-2 milliseconds - time = [NSDate timeIntervalSinceReferenceDate]; - accel->x = fakeData(time)/5; - accel->y = fakeData(time - 1)/5; - accel->z = fakeData(time - 2)/5 + 1.0; - return true; - } else { - return getData(accel, true, nil, nil); - } -} - -// Fills in the accel record with uncalibrated acceleration data. -// Returns 0 if success, error number if failure. -int smsGetUncalibratedData(sms_acceleration *accel) { - NSTimeInterval time; - if (debugging) { - usleep(1500); // Usually takes 1-2 milliseconds - time = [NSDate timeIntervalSinceReferenceDate]; - accel->x = fakeData(time) * 256 / 5; - accel->y = fakeData(time - 1) * 256 / 5; - accel->z = fakeData(time - 2) * 256 / 5 + 256; - return true; - } else { - return getData(accel, false, nil, nil); - } -} - -// Returns the length of a raw block of data for the current type of sensor. -int smsGetBufferLength(void) { - if (debugging) { - return 0; - } else if (running) { - return sensors[sensorNum].recordSize; - } else { - return 0; - } -} - -// Takes a pointer to accelGetRawLength() bytes; sets those bytes -// to return value from sensor. Make darn sure the buffer length is right! -void smsGetBufferData(char *buffer) { - IOItemCount iSize = recordSize; - IOByteCount oSize = recordSize; - kern_return_t result; - - if (debugging || running == NO) { - return; - } - - memset(iRecord, 1, iSize); - memset(buffer, 0, oSize); -#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 - const size_t InStructSize = recordSize; - size_t OutStructSize = recordSize; - result = IOConnectCallStructMethod(connection, - function, // magic kernel function number - (const void *)iRecord, - InStructSize, - (void *)buffer, - &OutStructSize - ); -#else // __MAC_OS_X_VERSION_MIN_REQUIRED 1050 - result = IOConnectMethodStructureIStructureO(connection, - function, // magic kernel function number - iSize, - &oSize, - iRecord, - buffer - ); -#endif // __MAC_OS_X_VERSION_MIN_REQUIRED 1050 - - if (result != KERN_SUCCESS) { - running = NO; - } -} - -// This returns an NSString describing the current calibration in -// human-readable form. Also include a description of the machine. -NSString *smsGetCalibrationDescription(void) { - BOOL success; - NSMutableString *s = [[NSMutableString alloc] init]; - - if (debugging) { - [s release]; - return @"Debugging!"; - } - - [s appendString:@"---- SeisMac Calibration Record ----\n \n"]; - [s appendFormat:@"Machine model: %@\n", - getModelName()]; - [s appendFormat:@"OS X build: %@\n", - getOSVersion()]; - [s appendFormat:@"SeisMacLib version %s, record %d\n \n", - SMSLIB_VERSION, sensorNum]; - [s appendFormat:@"Using service \"%s\", function index %d, size %d\n \n", - serviceName, function, recordSize]; - if (prefIntRead(CALIBRATED_NAME, &success) && success) { - [s appendString:@"Calibration values (from calibration):\n"]; - } else { - [s appendString:@"Calibration values (from defaults):\n"]; - } - [s appendFormat:@" X-Axis-Zero = %.2f\n", zeros[0]]; - [s appendFormat:@" X-Axis-One-g = %.2f\n", onegs[0]]; - [s appendFormat:@" Y-Axis-Zero = %.2f\n", zeros[1]]; - [s appendFormat:@" Y-Axis-One-g = %.2f\n", onegs[1]]; - [s appendFormat:@" Z-Axis-Zero = %.2f\n", zeros[2]]; - [s appendFormat:@" Z-Axis-One-g = %.2f\n \n", onegs[2]]; - [s appendString:@"---- End Record ----\n"]; - return s; -} - -// Shuts down the accelerometer. -void smsShutdown(void) { - if (!debugging) { - running = NO; - if (iRecord) free(iRecord); - if (oRecord) free(oRecord); - IOServiceClose(connection); - } -} - -#pragma mark Internal functions - -// Loads the current calibration from the stored preferences. -// Returns true iff successful. -BOOL loadCalibration(void) { - BOOL thisSuccess, allSuccess; - int x; - - prefSynchronize(); - - if (prefIntRead(CALIBRATED_NAME, &thisSuccess) && thisSuccess) { - // Calibrated. Set all values from saved values. - allSuccess = YES; - for (x = 0; x < 3; x++) { - zeros[x] = prefFloatRead(ZERO_NAME(x), &thisSuccess); - allSuccess &= thisSuccess; - onegs[x] = prefFloatRead(ONEG_NAME(x), &thisSuccess); - allSuccess &= thisSuccess; - } - return allSuccess; - } - - return NO; -} - -// Stores the current calibration into the stored preferences. -static void storeCalibration(void) { - int x; - prefIntWrite(CALIBRATED_NAME, 1); - for (x = 0; x < 3; x++) { - prefFloatWrite(ZERO_NAME(x), zeros[x]); - prefFloatWrite(ONEG_NAME(x), onegs[x]); - } - prefSynchronize(); -} - - -// Sets the calibration to its default values. -void defaultCalibration(void) { - int x; - for (x = 0; x < 3; x++) { - zeros[x] = sensors[sensorNum].axes[x].zerog; - onegs[x] = sensors[sensorNum].axes[x].oneg; - } -} - -// Deletes the stored preferences. -static void deleteCalibration(void) { - int x; - - prefDelete(CALIBRATED_NAME); - for (x = 0; x < 3; x++) { - prefDelete(ZERO_NAME(x)); - prefDelete(ONEG_NAME(x)); - } - prefSynchronize(); -} - -// Read a named floating point value from the stored preferences. Sets -// the success boolean based on, you guessed it, whether it succeeds. -static float prefFloatRead(NSString *prefName, BOOL *success) { - float result = 0.0f; - - CFPropertyListRef ref = CFPreferencesCopyAppValue((CFStringRef)prefName, - APP_ID); - // If there isn't such a preference, fail - if (ref == NULL) { - *success = NO; - return result; - } - CFTypeID typeID = CFGetTypeID(ref); - // Is it a number? - if (typeID == CFNumberGetTypeID()) { - // Is it a floating point number? - if (CFNumberIsFloatType((CFNumberRef)ref)) { - // Yup: grab it. - *success = CFNumberGetValue((__CFNumber*)ref, kCFNumberFloat32Type, &result); - } else { - // Nope: grab as an integer, and convert to a float. - long num; - if (CFNumberGetValue((CFNumberRef)ref, kCFNumberLongType, &num)) { - result = num; - *success = YES; - } else { - *success = NO; - } - } - // Or is it a string (e.g. set by the command line "defaults" command)? - } else if (typeID == CFStringGetTypeID()) { - result = (float)CFStringGetDoubleValue((CFStringRef)ref); - *success = YES; - } else { - // Can't convert to a number: fail. - *success = NO; - } - CFRelease(ref); - return result; -} - -// Writes a named floating point value to the stored preferences. -static void prefFloatWrite(NSString *prefName, float prefValue) { - CFNumberRef cfFloat = CFNumberCreate(kCFAllocatorDefault, - kCFNumberFloatType, - &prefValue); - CFPreferencesSetAppValue((CFStringRef)prefName, - cfFloat, - APP_ID); - CFRelease(cfFloat); -} - -// Reads a named integer value from the stored preferences. -static int prefIntRead(NSString *prefName, BOOL *success) { - Boolean internalSuccess; - CFIndex result = CFPreferencesGetAppIntegerValue((CFStringRef)prefName, - APP_ID, - &internalSuccess); - *success = internalSuccess; - - return result; -} - -// Writes a named integer value to the stored preferences. -static void prefIntWrite(NSString *prefName, int prefValue) { - CFPreferencesSetAppValue((CFStringRef)prefName, - (CFNumberRef)[NSNumber numberWithInt:prefValue], - APP_ID); -} - -// Deletes the named preference values. -static void prefDelete(NSString *prefName) { - CFPreferencesSetAppValue((CFStringRef)prefName, - NULL, - APP_ID); -} - -// Synchronizes the local preferences with the stored preferences. -static void prefSynchronize(void) { - CFPreferencesAppSynchronize(APP_ID); -} - -// Internal version of accelGetData, with logging -int getData(sms_acceleration *accel, int calibrated, id logObject, SEL logSelector) { - IOItemCount iSize = recordSize; - IOByteCount oSize = recordSize; - kern_return_t result; - - if (running == NO) { - return -1; - } - - memset(iRecord, 1, iSize); - memset(oRecord, 0, oSize); - - LOG_2ARG(@" Querying device: ", - sensors[sensorNum].function, sensors[sensorNum].recordSize); - -#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 - const size_t InStructSize = recordSize; - size_t OutStructSize = recordSize; - result = IOConnectCallStructMethod(connection, - function, // magic kernel function number - (const void *)iRecord, - InStructSize, - (void *)oRecord, - &OutStructSize - ); -#else // __MAC_OS_X_VERSION_MIN_REQUIRED 1050 - result = IOConnectMethodStructureIStructureO(connection, - function, // magic kernel function number - iSize, - &oSize, - iRecord, - oRecord - ); -#endif // __MAC_OS_X_VERSION_MIN_REQUIRED 1050 - - if (result != KERN_SUCCESS) { - LOG(@"failed.\n"); - running = NO; - return result; - } else { - LOG(@"succeeded.\n"); - - accel->x = getAxis(0, calibrated); - accel->y = getAxis(1, calibrated); - accel->z = getAxis(2, calibrated); - return 0; - } -} - -// Given the returned record, extracts the value of the given axis. If -// calibrated, then zero G is 0.0, and one G is 1.0. -float getAxis(int which, int calibrated) { - // Get various values (to make code cleaner) - int indx = sensors[sensorNum].axes[which].index; - int size = sensors[sensorNum].axes[which].size; - float zerog = zeros[which]; - float oneg = onegs[which]; - // Storage for value to be returned - int value = 0; - - // Although the values in the returned record should have the proper - // endianness, we still have to get it into the proper end of value. -#if (BYTE_ORDER == BIG_ENDIAN) - // On PowerPC processors - memcpy(((char *)&value) + (sizeof(int) - size), &oRecord[indx], size); -#endif -#if (BYTE_ORDER == LITTLE_ENDIAN) - // On Intel processors - memcpy(&value, &oRecord[indx], size); -#endif - - value = signExtend(value, size); - - if (calibrated) { - // Scale and shift for zero. - return ((float)(value - zerog)) / oneg; - } else { - return value; - } -} - -// Extends the sign, given the length of the value. -int signExtend(int value, int size) { - // Extend sign - switch (size) { - case 1: - if (value & 0x00000080) - value |= 0xffffff00; - break; - case 2: - if (value & 0x00008000) - value |= 0xffff0000; - break; - case 3: - if (value & 0x00800000) - value |= 0xff000000; - break; - } - return value; -} - -// Returns the model name of the computer (e.g. "MacBookPro1,1") -NSString *getModelName(void) { - char model[32]; - size_t len = sizeof(model); - int name[2] = {CTL_HW, HW_MODEL}; - NSString *result; - - if (sysctl(name, 2, &model, &len, NULL, 0) == 0) { - result = [NSString stringWithFormat:@"%s", model]; - } else { - result = @""; - } - - return result; -} - -// Returns the current OS X version and build (e.g. "10.4.7 (build 8J2135a)") -NSString *getOSVersion(void) { - NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile: - @"/System/Library/CoreServices/SystemVersion.plist"]; - NSString *versionString = [dict objectForKey:@"ProductVersion"]; - NSString *buildString = [dict objectForKey:@"ProductBuildVersion"]; - NSString *wholeString = [NSString stringWithFormat:@"%@ (build %@)", - versionString, buildString]; - return wholeString; -} - -// Returns time within the current second in microseconds. -// long getMicroseconds() { -// struct timeval t; -// gettimeofday(&t, 0); -// return t.tv_usec; -//} - -// Returns fake data given the time. Range is +/-1. -float fakeData(NSTimeInterval time) { - long secs = lround(floor(time)); - int secsMod3 = secs % 3; - double angle = time * 10 * M_PI * 2; - double mag = exp(-(time - (secs - secsMod3)) * 2); - return sin(angle) * mag; -} - diff --git a/dom/system/nsDeviceMotion.cpp b/dom/system/nsDeviceMotion.cpp index e16f64a1aa7d..9c2230c63893 100644 --- a/dom/system/nsDeviceMotion.cpp +++ b/dom/system/nsDeviceMotion.cpp @@ -44,14 +44,11 @@ #include "nsIDOMEventTarget.h" #include "nsIServiceManager.h" #include "nsIPrivateDOMEvent.h" +#include "nsIDOMDeviceOrientationEvent.h" +#include "nsIDOMDeviceMotionEvent.h" #include "nsIServiceManager.h" #include "nsIPrefService.h" - -using mozilla::TimeStamp; -using mozilla::TimeDuration; - -// also see sDefaultSensorHint in mobile/android/base/GeckoAppShell.java -#define DEFAULT_SENSOR_POLL 100 +#include "nsDOMDeviceMotionEvent.h" static const nsTArray::index_type NoIndex = nsTArray::NoIndex; @@ -120,12 +117,18 @@ NS_IMPL_ISUPPORTS2(nsDeviceMotion, nsIDeviceMotion, nsIDeviceMotionUpdate) nsDeviceMotion::nsDeviceMotion() : mStarted(false), + mUpdateInterval(50), /* default to 50 ms */ mEnabled(true) { nsCOMPtr prefSrv = do_GetService(NS_PREFSERVICE_CONTRACTID); if (prefSrv) { + PRInt32 value; + nsresult rv = prefSrv->GetIntPref("device.motion.update.interval", &value); + if (NS_SUCCEEDED(rv)) + mUpdateInterval = value; + bool bvalue; - nsresult rv = prefSrv->GetBoolPref("device.motion.enabled", &bvalue); + rv = prefSrv->GetBoolPref("device.motion.enabled", &bvalue); if (NS_SUCCEEDED(rv) && bvalue == false) mEnabled = false; } @@ -252,10 +255,8 @@ nsDeviceMotion::DeviceMotionChanged(PRUint32 type, double x, double y, double z) if (domdoc) { nsCOMPtr target = do_QueryInterface(windowListeners[i]); - if (type == nsIDeviceMotionData::TYPE_ACCELERATION || - type == nsIDeviceMotionData::TYPE_LINEAR_ACCELERATION || - type == nsIDeviceMotionData::TYPE_GYROSCOPE ) - FireDOMMotionEvent(domdoc, target, type, x, y, z); + if (type == nsIDeviceMotionData::TYPE_ACCELERATION) + FireDOMMotionEvent(domdoc, target, x, y, z); else if (type == nsIDeviceMotionData::TYPE_ORIENTATION) FireDOMOrientationEvent(domdoc, target, x, y, z); } @@ -263,64 +264,6 @@ nsDeviceMotion::DeviceMotionChanged(PRUint32 type, double x, double y, double z) return NS_OK; } -NS_IMETHODIMP -nsDeviceMotion::NeedsCalibration() -{ - if (!mEnabled) - return NS_ERROR_NOT_INITIALIZED; - - nsCOMArray listeners = mListeners; - for (PRUint32 i = listeners.Count(); i > 0 ; ) { - --i; - listeners[i]->NeedsCalibration(); - } - - nsCOMArray windowListeners; - for (PRUint32 i = 0; i < mWindowListeners.Length(); i++) { - windowListeners.AppendObject(mWindowListeners[i]); - } - - for (PRUint32 i = windowListeners.Count(); i > 0 ; ) { - --i; - - // check to see if this window is in the background. if - // it is, don't send any device motion to it. - nsCOMPtr pwindow = do_QueryInterface(windowListeners[i]); - if (!pwindow || - !pwindow->GetOuterWindow() || - pwindow->GetOuterWindow()->IsBackground()) - continue; - - nsCOMPtr domdoc; - windowListeners[i]->GetDocument(getter_AddRefs(domdoc)); - - if (domdoc) { - nsCOMPtr target = do_QueryInterface(windowListeners[i]); - FireNeedsCalibration(domdoc, target); - } - } - - return NS_OK; -} - -void -nsDeviceMotion::FireNeedsCalibration(nsIDOMDocument *domdoc, - nsIDOMEventTarget *target) -{ - nsCOMPtr event; - domdoc->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event)); - if (!event) - return; - - event->InitEvent(NS_LITERAL_STRING("compassneedscalibration"), true, false); - nsCOMPtr privateEvent = do_QueryInterface(event); - if (privateEvent) - privateEvent->SetTrusted(true); - - bool defaultActionEnabled = true; - target->DispatchEvent(event, &defaultActionEnabled); -} - void nsDeviceMotion::FireDOMOrientationEvent(nsIDOMDocument *domdoc, nsIDOMEventTarget *target, @@ -357,57 +300,34 @@ nsDeviceMotion::FireDOMOrientationEvent(nsIDOMDocument *domdoc, void nsDeviceMotion::FireDOMMotionEvent(nsIDOMDocument *domdoc, nsIDOMEventTarget *target, - PRUint32 type, double x, double y, double z) { - // Attempt to coalesce events - bool fireEvent = TimeStamp::Now() > mLastDOMMotionEventTime + TimeDuration::FromMilliseconds(DEFAULT_SENSOR_POLL); - - switch (type) { - case nsIDeviceMotionData::TYPE_LINEAR_ACCELERATION: - mLastAcceleration = new nsDOMDeviceAcceleration(x, y, z); - break; - case nsIDeviceMotionData::TYPE_ACCELERATION: - mLastAccelerationIncluduingGravity = new nsDOMDeviceAcceleration(x, y, z); - break; - case nsIDeviceMotionData::TYPE_GYROSCOPE: - mLastRotationRate = new nsDOMDeviceRotationRate(x, y, z); - break; - } - - if (!fireEvent && (!mLastAcceleration || !mLastAccelerationIncluduingGravity || !mLastRotationRate)) { - return; - } - nsCOMPtr event; + bool defaultActionEnabled = true; domdoc->CreateEvent(NS_LITERAL_STRING("DeviceMotionEvent"), getter_AddRefs(event)); nsCOMPtr me = do_QueryInterface(event); if (!me) { return; - } +} + + // Currently acceleration as determined includes gravity. + nsRefPtr acceleration = new nsDOMDeviceAcceleration(x, y, z); me->InitDeviceMotionEvent(NS_LITERAL_STRING("devicemotion"), true, false, - mLastAcceleration, - mLastAccelerationIncluduingGravity, - mLastRotationRate, - DEFAULT_SENSOR_POLL); + nsnull, + acceleration, + nsnull, + 0); nsCOMPtr privateEvent = do_QueryInterface(event); if (privateEvent) privateEvent->SetTrusted(true); - bool defaultActionEnabled = true; target->DispatchEvent(event, &defaultActionEnabled); - - mLastRotationRate = nsnull; - mLastAccelerationIncluduingGravity = nsnull; - mLastAcceleration = nsnull; - mLastDOMMotionEventTime = TimeStamp::Now(); - } diff --git a/dom/system/nsDeviceMotion.h b/dom/system/nsDeviceMotion.h index 1618a6c73b57..e2bada95fe6e 100644 --- a/dom/system/nsDeviceMotion.h +++ b/dom/system/nsDeviceMotion.h @@ -43,10 +43,6 @@ #include "nsTArray.h" #include "nsCOMPtr.h" #include "nsITimer.h" -#include "nsIDOMDeviceOrientationEvent.h" -#include "nsIDOMDeviceMotionEvent.h" -#include "nsDOMDeviceMotionEvent.h" -#include "mozilla/TimeStamp.h" #define NS_DEVICE_MOTION_CID \ { 0xecba5203, 0x77da, 0x465a, \ @@ -80,9 +76,6 @@ private: protected: - void FireNeedsCalibration(nsIDOMDocument *domdoc, - nsIDOMEventTarget *target); - void FireDOMOrientationEvent(class nsIDOMDocument *domDoc, class nsIDOMEventTarget *target, double alpha, @@ -91,20 +84,15 @@ private: void FireDOMMotionEvent(class nsIDOMDocument *domDoc, class nsIDOMEventTarget *target, - PRUint32 type, double x, double y, double z); + PRUint32 mUpdateInterval; + bool mEnabled; + virtual void Startup() = 0; virtual void Shutdown() = 0; - - bool mEnabled; - mozilla::TimeStamp mLastDOMMotionEventTime; - nsRefPtr mLastAcceleration; - nsRefPtr mLastAccelerationIncluduingGravity; - nsRefPtr mLastRotationRate; - }; #endif diff --git a/dom/system/unix/Makefile.in b/dom/system/unix/Makefile.in index 7414673faeee..fa443281fea6 100644 --- a/dom/system/unix/Makefile.in +++ b/dom/system/unix/Makefile.in @@ -82,7 +82,4 @@ LOCAL_INCLUDES += $(MOZ_QT_CFLAGS) \ endif endif -# We fire the nsDOMDeviceAcceleration -LOCAL_INCLUDES += -I$(topsrcdir)/content/events/src - include $(topsrcdir)/config/rules.mk diff --git a/dom/system/unix/nsDeviceMotionSystem.cpp b/dom/system/unix/nsDeviceMotionSystem.cpp index 7baaeb4aa197..21e863e78498 100644 --- a/dom/system/unix/nsDeviceMotionSystem.cpp +++ b/dom/system/unix/nsDeviceMotionSystem.cpp @@ -42,8 +42,6 @@ #include "nsDeviceMotionSystem.h" #include "nsIServiceManager.h" -#define DEFAULT_SENSOR_POLL 100 - using namespace mozilla; typedef struct { @@ -225,7 +223,7 @@ void nsDeviceMotionSystem::Startup() if (mUpdateTimer) mUpdateTimer->InitWithFuncCallback(UpdateHandler, this, - DEFAULT_SENSOR_POLL, + mUpdateInterval, nsITimer::TYPE_REPEATING_SLACK); } diff --git a/dom/system/windows/Makefile.in b/dom/system/windows/Makefile.in index cd8319e75428..551a54921bfc 100644 --- a/dom/system/windows/Makefile.in +++ b/dom/system/windows/Makefile.in @@ -49,9 +49,6 @@ LIBXUL_LIBRARY = 1 FORCE_STATIC_LIB = 1 EXPORT_LIBRARY = 1 -# We fire the nsDOMDeviceAcceleration -LOCAL_INCLUDES += -I$(topsrcdir)/content/events/src - include $(topsrcdir)/config/config.mk CPPSRCS = \ diff --git a/dom/system/windows/nsDeviceMotionSystem.cpp b/dom/system/windows/nsDeviceMotionSystem.cpp index 5ad353ae5fd4..767b9eca1a48 100644 --- a/dom/system/windows/nsDeviceMotionSystem.cpp +++ b/dom/system/windows/nsDeviceMotionSystem.cpp @@ -39,8 +39,6 @@ #include "nsIServiceManager.h" #include "windows.h" -#define DEFAULT_SENSOR_POLL 100 - //////////////////////////// // ThinkPad //////////////////////////// @@ -158,7 +156,7 @@ void nsDeviceMotionSystem::Startup() if (mUpdateTimer) mUpdateTimer->InitWithFuncCallback(UpdateHandler, this, - DEFAULT_SENSOR_POLL, + mUpdateInterval, nsITimer::TYPE_REPEATING_SLACK); } diff --git a/embedding/android/GeckoEvent.java b/embedding/android/GeckoEvent.java index 3d178baf87fa..c3f4e892b517 100644 --- a/embedding/android/GeckoEvent.java +++ b/embedding/android/GeckoEvent.java @@ -252,9 +252,10 @@ public class GeckoEvent { } } - public GeckoEvent(Location l) { + public GeckoEvent(Location l, Address a) { mType = LOCATION_EVENT; mLocation = l; + mAddress = a; } public GeckoEvent(int imeAction, int offset, int count) { diff --git a/embedding/android/GeckoSurfaceView.java b/embedding/android/GeckoSurfaceView.java index 77649a447cf7..385c8d1e29ed 100644 --- a/embedding/android/GeckoSurfaceView.java +++ b/embedding/android/GeckoSurfaceView.java @@ -580,10 +580,47 @@ class GeckoSurfaceView GeckoAppShell.sendEventToGecko(new GeckoEvent(event)); } + private class GeocoderTask extends AsyncTask { + protected Void doInBackground(Location... location) { + try { + List
    addresses = mGeocoder.getFromLocation(location[0].getLatitude(), + location[0].getLongitude(), 1); + // grab the first address. in the future, + // may want to expose multiple, or filter + // for best. + mLastGeoAddress = addresses.get(0); + GeckoAppShell.sendEventToGecko(new GeckoEvent(location[0], mLastGeoAddress)); + } catch (Exception e) { + Log.w(LOG_FILE_NAME, "GeocoderTask "+e); + } + return null; + } + } + // geolocation public void onLocationChanged(Location location) { - GeckoAppShell.sendEventToGecko(new GeckoEvent(location)); + if (mGeocoder == null) + mGeocoder = new Geocoder(getContext(), Locale.getDefault()); + + if (mLastGeoAddress == null) { + new GeocoderTask().execute(location); + } + else { + float[] results = new float[1]; + Location.distanceBetween(location.getLatitude(), + location.getLongitude(), + mLastGeoAddress.getLatitude(), + mLastGeoAddress.getLongitude(), + results); + // pfm value. don't want to slam the + // geocoder with very similar values, so + // only call after about 100m + if (results[0] > 100) + new GeocoderTask().execute(location); + } + + GeckoAppShell.sendEventToGecko(new GeckoEvent(location, mLastGeoAddress)); } public void onProviderDisabled(String provider) @@ -788,6 +825,9 @@ class GeckoSurfaceView ByteBuffer mSoftwareBuffer; Bitmap mSoftwareBufferCopy; + Geocoder mGeocoder; + Address mLastGeoAddress; + final SynchronousQueue mSyncDraws = new SynchronousQueue(); } diff --git a/hal/HalSensor.h b/hal/HalSensor.h index 521c061787a7..de4d8edac458 100644 --- a/hal/HalSensor.h +++ b/hal/HalSensor.h @@ -54,8 +54,6 @@ enum SensorType { SENSOR_ORIENTATION, SENSOR_ACCELERATION, SENSOR_PROXIMITY, - SENSOR_LINEAR_ACCELERATION, - SENSOR_GYROSCOPE, NUM_SENSOR_TYPE }; diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index 6de76b27ec0c..59fd71b84add 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -139,6 +139,8 @@ abstract public class GeckoApp public static FormAssistPopup mFormAssistPopup; public Favicons mFavicons; + private Geocoder mGeocoder; + private Address mLastGeoAddress; private static LayerController mLayerController; private static PlaceholderLayerClient mPlaceholderLayerClient; private static GeckoSoftwareLayerClient mSoftwareLayerClient; @@ -2608,8 +2610,6 @@ abstract public class GeckoApp // accelerometer public void onAccuracyChanged(Sensor sensor, int accuracy) { - Log.w(LOGTAG, "onAccuracyChanged "+accuracy); - GeckoAppShell.sendEventToGecko(GeckoEvent.createSensorAccuracyEvent(accuracy)); } public void onSensorChanged(SensorEvent event) @@ -2618,12 +2618,51 @@ abstract public class GeckoApp GeckoAppShell.sendEventToGecko(GeckoEvent.createSensorEvent(event)); } + private class GeocoderRunnable implements Runnable { + Location mLocation; + GeocoderRunnable (Location location) { + mLocation = location; + } + public void run() { + try { + List
    addresses = mGeocoder.getFromLocation(mLocation.getLatitude(), + mLocation.getLongitude(), 1); + // grab the first address. in the future, + // may want to expose multiple, or filter + // for best. + mLastGeoAddress = addresses.get(0); + GeckoAppShell.sendEventToGecko(GeckoEvent.createLocationEvent(mLocation, mLastGeoAddress)); + } catch (Exception e) { + Log.w(LOGTAG, "GeocoderTask "+e); + } + } + } + // geolocation public void onLocationChanged(Location location) { Log.w(LOGTAG, "onLocationChanged "+location); + if (mGeocoder == null) + mGeocoder = new Geocoder(mLayerController.getView().getContext(), Locale.getDefault()); - GeckoAppShell.sendEventToGecko(GeckoEvent.createLocationEvent(location)); + if (mLastGeoAddress == null) { + GeckoAppShell.getHandler().post(new GeocoderRunnable(location)); + } + else { + float[] results = new float[1]; + Location.distanceBetween(location.getLatitude(), + location.getLongitude(), + mLastGeoAddress.getLatitude(), + mLastGeoAddress.getLongitude(), + results); + // pfm value. don't want to slam the + // geocoder with very similar values, so + // only call after about 100m + if (results[0] > 100) + GeckoAppShell.getHandler().post(new GeocoderRunnable(location)); + } + + GeckoAppShell.sendEventToGecko(GeckoEvent.createLocationEvent(location, mLastGeoAddress)); } public void onProviderDisabled(String provider) diff --git a/mobile/android/base/GeckoAppShell.java b/mobile/android/base/GeckoAppShell.java index 0950eb664628..35250a1e034a 100644 --- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -126,15 +126,6 @@ public class GeckoAppShell * sVibrationMaybePlaying is true. */ private static long sVibrationEndTime = 0; - /* Default value of how fast we should hint the Android sensors. */ - private static int sDefaultSensorHint = 100; - - private static Sensor gAccelerometerSensor = null; - private static Sensor gLinearAccelerometerSensor = null; - private static Sensor gGyroscopeSensor = null; - private static Sensor gOrientationSensor = null; - private static Sensor gProximitySensor = null; - /* The Android-side API: API methods that Android calls */ // Initialization methods @@ -542,6 +533,31 @@ public class GeckoAppShell tmp.countDown(); } + static Sensor gAccelerometerSensor = null; + static Sensor gOrientationSensor = null; + + public static void enableDeviceMotion(boolean enable) { + LayerView v = GeckoApp.mAppContext.getLayerController().getView(); + SensorManager sm = (SensorManager) v.getContext().getSystemService(Context.SENSOR_SERVICE); + + if (gAccelerometerSensor == null || gOrientationSensor == null) { + gAccelerometerSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + gOrientationSensor = sm.getDefaultSensor(Sensor.TYPE_ORIENTATION); + } + + if (enable) { + if (gAccelerometerSensor != null) + sm.registerListener(GeckoApp.mAppContext, gAccelerometerSensor, SensorManager.SENSOR_DELAY_GAME); + if (gOrientationSensor != null) + sm.registerListener(GeckoApp.mAppContext, gOrientationSensor, SensorManager.SENSOR_DELAY_GAME); + } else { + if (gAccelerometerSensor != null) + sm.unregisterListener(GeckoApp.mAppContext, gAccelerometerSensor); + if (gOrientationSensor != null) + sm.unregisterListener(GeckoApp.mAppContext, gOrientationSensor); + } + } + public static void enableLocation(final boolean enable) { getMainHandler().post(new Runnable() { public void run() { @@ -569,46 +585,26 @@ public class GeckoAppShell }); } + /* + * Keep these values consistent with |SensorType| in Hal.h + */ + private static final int SENSOR_ORIENTATION = 1; + private static final int SENSOR_ACCELERATION = 2; + private static final int SENSOR_PROXIMITY = 3; + + private static Sensor gProximitySensor = null; + public static void enableSensor(int aSensortype) { SensorManager sm = (SensorManager) GeckoApp.mAppContext.getSystemService(Context.SENSOR_SERVICE); switch(aSensortype) { - case GeckoHalDefines.SENSOR_ORIENTATION: - if(gOrientationSensor == null) - gOrientationSensor = sm.getDefaultSensor(Sensor.TYPE_ORIENTATION); - if (gOrientationSensor != null) - sm.registerListener(GeckoApp.mAppContext, gOrientationSensor, sDefaultSensorHint); - break; - - case GeckoHalDefines.SENSOR_ACCELERATION: - if(gAccelerometerSensor == null) - gAccelerometerSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); - if (gAccelerometerSensor != null) - sm.registerListener(GeckoApp.mAppContext, gAccelerometerSensor, sDefaultSensorHint); - break; - - case GeckoHalDefines.SENSOR_PROXIMITY: + case SENSOR_PROXIMITY: if(gProximitySensor == null) gProximitySensor = sm.getDefaultSensor(Sensor.TYPE_PROXIMITY); - if (gProximitySensor != null) - sm.registerListener(GeckoApp.mAppContext, gProximitySensor, sDefaultSensorHint); + sm.registerListener(GeckoApp.mAppContext, gProximitySensor, + SensorManager.SENSOR_DELAY_GAME); break; - - case GeckoHalDefines.SENSOR_LINEAR_ACCELERATION: - if(gLinearAccelerometerSensor == null) - gLinearAccelerometerSensor = sm.getDefaultSensor(10); - if (gLinearAccelerometerSensor != null) - sm.registerListener(GeckoApp.mAppContext, gLinearAccelerometerSensor, sDefaultSensorHint); - break; - - case GeckoHalDefines.SENSOR_GYROSCOPE: - if(gGyroscopeSensor == null) - gGyroscopeSensor = sm.getDefaultSensor(Sensor.TYPE_GYROSCOPE); - if (gGyroscopeSensor != null) - sm.registerListener(GeckoApp.mAppContext, gGyroscopeSensor, sDefaultSensorHint); - break; - } } @@ -616,30 +612,9 @@ public class GeckoAppShell SensorManager sm = (SensorManager) GeckoApp.mAppContext.getSystemService(Context.SENSOR_SERVICE); - switch (aSensortype) { - case GeckoHalDefines.SENSOR_ORIENTATION: - if (gOrientationSensor != null) - sm.unregisterListener(GeckoApp.mAppContext, gOrientationSensor); - break; - - case GeckoHalDefines.SENSOR_ACCELERATION: - if (gAccelerometerSensor != null) - sm.unregisterListener(GeckoApp.mAppContext, gAccelerometerSensor); - break; - - case GeckoHalDefines.SENSOR_PROXIMITY: - if (gProximitySensor != null) - sm.unregisterListener(GeckoApp.mAppContext, gProximitySensor); - break; - - case GeckoHalDefines.SENSOR_LINEAR_ACCELERATION: - if (gLinearAccelerometerSensor != null) - sm.unregisterListener(GeckoApp.mAppContext, gLinearAccelerometerSensor); - break; - - case GeckoHalDefines.SENSOR_GYROSCOPE: - if (gGyroscopeSensor != null) - sm.unregisterListener(GeckoApp.mAppContext, gGyroscopeSensor); + switch(aSensortype) { + case SENSOR_PROXIMITY: + sm.unregisterListener(GeckoApp.mAppContext, gProximitySensor); break; } } diff --git a/mobile/android/base/GeckoEvent.java b/mobile/android/base/GeckoEvent.java index e3b4f80b986e..bfea49b4edce 100644 --- a/mobile/android/base/GeckoEvent.java +++ b/mobile/android/base/GeckoEvent.java @@ -52,7 +52,6 @@ import android.util.DisplayMetrics; import android.graphics.PointF; import android.text.format.Time; import android.os.SystemClock; -import java.lang.Math; import java.lang.System; import android.util.Log; @@ -69,8 +68,8 @@ public class GeckoEvent { private static final int NATIVE_POKE = 0; private static final int KEY_EVENT = 1; private static final int MOTION_EVENT = 2; - private static final int SENSOR_EVENT = 3; - private static final int UNUSED1_EVENT = 4; + private static final int ORIENTATION_EVENT = 3; + private static final int ACCELERATION_EVENT = 4; private static final int LOCATION_EVENT = 5; private static final int IME_EVENT = 6; private static final int DRAW = 7; @@ -90,7 +89,6 @@ public class GeckoEvent { private static final int PROXIMITY_EVENT = 23; private static final int ACTIVITY_RESUMING = 24; private static final int SCREENSHOT = 25; - private static final int SENSOR_ACCURACY = 26; public static final int IME_COMPOSITION_END = 0; public static final int IME_COMPOSITION_BEGIN = 1; @@ -122,6 +120,7 @@ public class GeckoEvent { public Point[] mPointRadii; public Rect mRect; public double mX, mY, mZ; + public double mAlpha, mBeta, mGamma; public double mDistance; public int mMetaState, mFlags; @@ -280,46 +279,25 @@ public class GeckoEvent { } public static GeckoEvent createSensorEvent(SensorEvent s) { - int sensor_type = s.sensor.getType(); GeckoEvent event = null; - + int sensor_type = s.sensor.getType(); + switch(sensor_type) { - case Sensor.TYPE_ACCELEROMETER: - event = new GeckoEvent(SENSOR_EVENT); - event.mFlags = GeckoHalDefines.SENSOR_ACCELERATION; + event = new GeckoEvent(ACCELERATION_EVENT); event.mX = s.values[0]; event.mY = s.values[1]; event.mZ = s.values[2]; break; - - case 10 /* Requires API Level 9, so just use the raw value - Sensor.TYPE_LINEAR_ACCELEROMETER*/ : - event = new GeckoEvent(SENSOR_EVENT); - event.mFlags = GeckoHalDefines.SENSOR_LINEAR_ACCELERATION; - event.mX = s.values[0]; - event.mY = s.values[1]; - event.mZ = s.values[2]; - break; - + case Sensor.TYPE_ORIENTATION: - event = new GeckoEvent(SENSOR_EVENT); - event.mFlags = GeckoHalDefines.SENSOR_ORIENTATION; - event.mX = s.values[0]; - event.mY = s.values[1]; - event.mZ = s.values[2]; - break; - - case Sensor.TYPE_GYROSCOPE: - event = new GeckoEvent(SENSOR_EVENT); - event.mFlags = GeckoHalDefines.SENSOR_GYROSCOPE; - event.mX = Math.toDegrees(s.values[0]); - event.mY = Math.toDegrees(s.values[1]); - event.mZ = Math.toDegrees(s.values[2]); + event = new GeckoEvent(ORIENTATION_EVENT); + event.mAlpha = -s.values[0]; + event.mBeta = -s.values[1]; + event.mGamma = -s.values[2]; break; case Sensor.TYPE_PROXIMITY: - // bug 734854 - maybe we can get rid of this event. is - // values[1] and values[2] valid? event = new GeckoEvent(PROXIMITY_EVENT); event.mDistance = s.values[0]; break; @@ -327,9 +305,10 @@ public class GeckoEvent { return event; } - public static GeckoEvent createLocationEvent(Location l) { + public static GeckoEvent createLocationEvent(Location l, Address a) { GeckoEvent event = new GeckoEvent(LOCATION_EVENT); event.mLocation = l; + event.mAddress = a; return event; } @@ -430,10 +409,4 @@ public class GeckoEvent { event.mMetaState = tabId; return event; } - - public static GeckoEvent createSensorAccuracyEvent(int accuracy) { - GeckoEvent event = new GeckoEvent(SENSOR_ACCURACY); - event.mFlags = accuracy; - return event; - } } diff --git a/mobile/android/base/Makefile.in b/mobile/android/base/Makefile.in index 79a358c5aa68..7f56871d9683 100644 --- a/mobile/android/base/Makefile.in +++ b/mobile/android/base/Makefile.in @@ -87,7 +87,6 @@ FENNEC_JAVA_FILES = \ GeckoEvent.java \ GeckoEventListener.java \ GeckoEventResponder.java \ - GeckoHalDefines.java \ GeckoInputConnection.java \ GeckoMessageReceiver.java \ GeckoPreferences.java \ diff --git a/toolkit/content/license.html b/toolkit/content/license.html index 17b2bebc3510..27775536b334 100644 --- a/toolkit/content/license.html +++ b/toolkit/content/license.html @@ -94,7 +94,6 @@
  • Skia License
  • Snappy License
  • Sparkle License
  • -
  • Suitable Systems License
  • SunSoft License
  • University of California License
  • University of Cambridge License
  • @@ -2235,59 +2234,6 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
    - -

    Suitable Systems License

    - -

    This license applies to certain files in the directory - dom/system/cocoa/.

    - -
    -SMSLib Sudden Motion Sensor Access Library
    -Copyright (c) 2010 Suitable Systems
    -All rights reserved.
    -
    -Developed by: Daniel Griscom
    -              Suitable Systems
    -              http://www.suitable.com
    -
    -Permission is hereby granted, free of charge, to any person obtaining a
    -copy of this software and associated documentation files (the
    -"Software"), to deal with the Software without restriction, including
    -without limitation the rights to use, copy, modify, merge, publish,
    -distribute, sublicense, and/or sell copies of the Software, and to
    -permit persons to whom the Software is furnished to do so, subject to
    -the following conditions:
    -
    -- Redistributions of source code must retain the above copyright notice,
    -this list of conditions and the following disclaimers.
    -
    -- Redistributions in binary form must reproduce the above copyright
    -notice, this list of conditions and the following disclaimers in the
    -documentation and/or other materials provided with the distribution.
    -
    -- Neither the names of Suitable Systems nor the names of its
    -contributors may be used to endorse or promote products derived from
    -this Software without specific prior written permission.
    -
    -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
    -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    -IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR
    -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    -SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
    -
    -For more information about SMSLib, see
    -	
    -or contact
    -	Daniel Griscom
    -	Suitable Systems
    -	1 Centre Street, Suite 204
    -	Wakefield, MA 01880
    -	(781) 665-0053
    -
    -
    diff --git a/widget/android/AndroidBridge.cpp b/widget/android/AndroidBridge.cpp index 30311c11ab17..be5ec97216e9 100644 --- a/widget/android/AndroidBridge.cpp +++ b/widget/android/AndroidBridge.cpp @@ -111,9 +111,14 @@ AndroidBridge::Init(JNIEnv *jEnv, jNotifyScreenShot = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "notifyScreenShot", "(Ljava/nio/ByteBuffer;III)V"); jAcknowledgeEventSync = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "acknowledgeEventSync", "()V"); + jEnableDeviceMotion = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "enableDeviceMotion", "(Z)V"); jEnableLocation = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "enableLocation", "(Z)V"); - jEnableSensor = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "enableSensor", "(I)V"); - jDisableSensor = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "disableSensor", "(I)V"); + jEnableSensor = + (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, + "enableSensor", "(I)V"); + jDisableSensor = + (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, + "disableSensor", "(I)V"); jReturnIMEQueryResult = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "returnIMEQueryResult", "(Ljava/lang/String;II)V"); jScheduleRestart = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "scheduleRestart", "()V"); jNotifyXreExit = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "onXreExit", "()V"); @@ -306,22 +311,12 @@ AndroidBridge::EnableDeviceMotion(bool aEnable) { ALOG_BRIDGE("AndroidBridge::EnableDeviceMotion"); - // bug 734855 - we probably can make this finer grain based on - // the DOM APIs that are being invoked. - if (aEnable) { - EnableSensor(hal::SENSOR_ORIENTATION); - EnableSensor(hal::SENSOR_ACCELERATION); - EnableSensor(hal::SENSOR_LINEAR_ACCELERATION); - EnableSensor(hal::SENSOR_GYROSCOPE); - } - else { - DisableSensor(hal::SENSOR_ORIENTATION); - DisableSensor(hal::SENSOR_ACCELERATION); - DisableSensor(hal::SENSOR_LINEAR_ACCELERATION); - DisableSensor(hal::SENSOR_GYROSCOPE); - } -} + JNIEnv *env = GetJNIEnv(); + if (!env) + return; + env->CallStaticVoidMethod(mGeckoAppShellClass, jEnableDeviceMotion, aEnable); +} void AndroidBridge::EnableLocation(bool aEnable) @@ -331,30 +326,22 @@ AndroidBridge::EnableLocation(bool aEnable) JNIEnv *env = GetJNIEnv(); if (!env) return; - - AutoLocalJNIFrame jniFrame(env, 1); + env->CallStaticVoidMethod(mGeckoAppShellClass, jEnableLocation, aEnable); } void AndroidBridge::EnableSensor(int aSensorType) { ALOG_BRIDGE("AndroidBridge::EnableSensor"); - JNIEnv *env = GetJNIEnv(); - if (!env) - return; - - AutoLocalJNIFrame jniFrame(env, 1); - env->CallStaticVoidMethod(mGeckoAppShellClass, jEnableSensor, aSensorType); + mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jEnableSensor, + aSensorType); } void AndroidBridge::DisableSensor(int aSensorType) { ALOG_BRIDGE("AndroidBridge::DisableSensor"); - JNIEnv *env = GetJNIEnv(); - if (!env) - return; - AutoLocalJNIFrame jniFrame(env, 1); - env->CallStaticVoidMethod(mGeckoAppShellClass, jDisableSensor, aSensorType); + mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jDisableSensor, + aSensorType); } void diff --git a/widget/android/AndroidBridge.h b/widget/android/AndroidBridge.h index 391259fb56fe..54c9e35b8667 100644 --- a/widget/android/AndroidBridge.h +++ b/widget/android/AndroidBridge.h @@ -424,6 +424,7 @@ protected: jmethodID jNotifyIMEChange; jmethodID jNotifyScreenShot; jmethodID jAcknowledgeEventSync; + jmethodID jEnableDeviceMotion; jmethodID jEnableLocation; jmethodID jEnableSensor; jmethodID jDisableSensor; diff --git a/widget/android/AndroidJavaWrappers.cpp b/widget/android/AndroidJavaWrappers.cpp index 841547ed54d7..387a9011ee63 100644 --- a/widget/android/AndroidJavaWrappers.cpp +++ b/widget/android/AndroidJavaWrappers.cpp @@ -49,6 +49,9 @@ jfieldID AndroidGeckoEvent::jPointIndicies = 0; jfieldID AndroidGeckoEvent::jPressures = 0; jfieldID AndroidGeckoEvent::jPointRadii = 0; jfieldID AndroidGeckoEvent::jOrientations = 0; +jfieldID AndroidGeckoEvent::jAlphaField = 0; +jfieldID AndroidGeckoEvent::jBetaField = 0; +jfieldID AndroidGeckoEvent::jGammaField = 0; jfieldID AndroidGeckoEvent::jXField = 0; jfieldID AndroidGeckoEvent::jYField = 0; jfieldID AndroidGeckoEvent::jZField = 0; @@ -70,6 +73,7 @@ jfieldID AndroidGeckoEvent::jRangeStylesField = 0; jfieldID AndroidGeckoEvent::jRangeForeColorField = 0; jfieldID AndroidGeckoEvent::jRangeBackColorField = 0; jfieldID AndroidGeckoEvent::jLocationField = 0; +jfieldID AndroidGeckoEvent::jAddressField = 0; jfieldID AndroidGeckoEvent::jBandwidthField = 0; jfieldID AndroidGeckoEvent::jCanBeMeteredField = 0; @@ -92,6 +96,19 @@ jmethodID AndroidLocation::jGetBearingMethod = 0; jmethodID AndroidLocation::jGetSpeedMethod = 0; jmethodID AndroidLocation::jGetTimeMethod = 0; +jclass AndroidAddress::jAddressClass = 0; +jmethodID AndroidAddress::jGetAddressLineMethod; +jmethodID AndroidAddress::jGetAdminAreaMethod; +jmethodID AndroidAddress::jGetCountryNameMethod; +jmethodID AndroidAddress::jGetFeatureNameMethod; +jmethodID AndroidAddress::jGetLocalityMethod; +jmethodID AndroidAddress::jGetPostalCodeMethod; +jmethodID AndroidAddress::jGetPremisesMethod; +jmethodID AndroidAddress::jGetSubAdminAreaMethod; +jmethodID AndroidAddress::jGetSubLocalityMethod; +jmethodID AndroidAddress::jGetSubThoroughfareMethod; +jmethodID AndroidAddress::jGetThoroughfareMethod; + jclass AndroidGeckoSoftwareLayerClient::jGeckoSoftwareLayerClientClass = 0; jmethodID AndroidGeckoSoftwareLayerClient::jLockBufferMethod = 0; jmethodID AndroidGeckoSoftwareLayerClient::jUnlockBufferMethod = 0; @@ -125,6 +142,7 @@ mozilla::InitAndroidJavaWrappers(JNIEnv *jEnv) AndroidGeckoEvent::InitGeckoEventClass(jEnv); AndroidPoint::InitPointClass(jEnv); AndroidLocation::InitLocationClass(jEnv); + AndroidAddress::InitAddressClass(jEnv); AndroidRect::InitRectClass(jEnv); AndroidGeckoSoftwareLayerClient::InitGeckoSoftwareLayerClientClass(jEnv); AndroidGeckoSurfaceView::InitGeckoSurfaceViewClass(jEnv); @@ -145,6 +163,9 @@ AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv) jOrientations = getField("mOrientations", "[F"); jPressures = getField("mPressures", "[F"); jPointRadii = getField("mPointRadii", "[Landroid/graphics/Point;"); + jAlphaField = getField("mAlpha", "D"); + jBetaField = getField("mBeta", "D"); + jGammaField = getField("mGamma", "D"); jXField = getField("mX", "D"); jYField = getField("mY", "D"); jZField = getField("mZ", "D"); @@ -165,6 +186,7 @@ AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv) jRangeForeColorField = getField("mRangeForeColor", "I"); jRangeBackColorField = getField("mRangeBackColor", "I"); jLocationField = getField("mLocation", "Landroid/location/Location;"); + jAddressField = getField("mAddress", "Landroid/location/Address;"); jBandwidthField = getField("mBandwidth", "D"); jCanBeMeteredField = getField("mCanBeMetered", "Z"); } @@ -203,6 +225,60 @@ AndroidLocation::InitLocationClass(JNIEnv *jEnv) jGetTimeMethod = getMethod("getTime", "()J"); } +void +AndroidAddress::InitAddressClass(JNIEnv *jEnv) +{ + initInit(); + + jAddressClass = getClassGlobalRef("android/location/Address"); + + jGetAddressLineMethod = getMethod("getAddressLine", "(I)Ljava/lang/String;"); + jGetAdminAreaMethod = getMethod("getAdminArea", "()Ljava/lang/String;"); + jGetCountryNameMethod = getMethod("getCountryName", "()Ljava/lang/String;"); + jGetFeatureNameMethod = getMethod("getFeatureName", "()Ljava/lang/String;"); + jGetLocalityMethod = getMethod("getLocality", "()Ljava/lang/String;"); + jGetPostalCodeMethod = getMethod("getPostalCode", "()Ljava/lang/String;"); + jGetPremisesMethod = getMethod("getPremises", "()Ljava/lang/String;"); + jGetSubAdminAreaMethod = getMethod("getSubAdminArea", "()Ljava/lang/String;"); + jGetSubLocalityMethod = getMethod("getSubLocality", "()Ljava/lang/String;"); + jGetSubThoroughfareMethod = getMethod("getSubThoroughfare", "()Ljava/lang/String;"); + jGetThoroughfareMethod = getMethod("getThoroughfare", "()Ljava/lang/String;"); +} + +nsGeoPositionAddress* +AndroidAddress::CreateGeoPositionAddress(JNIEnv *jenv, jobject jobj) +{ + nsJNIString streetNumber(static_cast(jenv->CallObjectMethod(jobj, jGetSubThoroughfareMethod)), jenv); + nsJNIString street(static_cast(jenv->CallObjectMethod(jobj, jGetThoroughfareMethod)), jenv); + nsJNIString city(static_cast(jenv->CallObjectMethod(jobj, jGetLocalityMethod)), jenv); + nsJNIString county(static_cast(jenv->CallObjectMethod(jobj, jGetSubAdminAreaMethod)), jenv); + nsJNIString country(static_cast(jenv->CallObjectMethod(jobj, jGetCountryNameMethod)), jenv); + nsJNIString premises(static_cast(jenv->CallObjectMethod(jobj, jGetPremisesMethod)), jenv); + nsJNIString postalCode(static_cast(jenv->CallObjectMethod(jobj, jGetPostalCodeMethod)), jenv); + nsJNIString region(static_cast(jenv->CallObjectMethod(jobj, jGetAdminAreaMethod, 0)), jenv); + +#ifdef DEBUG + printf_stderr("!!!!!!!!!!!!!! AndroidAddress::CreateGeoPositionAddress:\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n", + NS_LossyConvertUTF16toASCII(streetNumber).get(), + NS_LossyConvertUTF16toASCII(street).get(), + NS_LossyConvertUTF16toASCII(premises).get(), + NS_LossyConvertUTF16toASCII(city).get(), + NS_LossyConvertUTF16toASCII(county).get(), + NS_LossyConvertUTF16toASCII(region).get(), + NS_LossyConvertUTF16toASCII(country).get(), + NS_LossyConvertUTF16toASCII(postalCode).get()); +#endif + + return new nsGeoPositionAddress(streetNumber, + street, + premises, + city, + county, + region, + country, + postalCode); +} + nsGeoPosition* AndroidLocation::CreateGeoPosition(JNIEnv *jenv, jobject jobj) { @@ -421,16 +497,25 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj) ReadRectField(jenv); break; - case SENSOR_EVENT: - mX = jenv->GetDoubleField(jobj, jXField); - mY = jenv->GetDoubleField(jobj, jYField); - mZ = jenv->GetDoubleField(jobj, jZField); - mFlags = jenv->GetIntField(jobj, jFlagsField); - break; + case ORIENTATION_EVENT: + mAlpha = jenv->GetDoubleField(jobj, jAlphaField); + mBeta = jenv->GetDoubleField(jobj, jBetaField); + mGamma = jenv->GetDoubleField(jobj, jGammaField); + break; + + case ACCELERATION_EVENT: + mX = jenv->GetDoubleField(jobj, jXField); + mY = jenv->GetDoubleField(jobj, jYField); + mZ = jenv->GetDoubleField(jobj, jZField); + break; case LOCATION_EVENT: { jobject location = jenv->GetObjectField(jobj, jLocationField); + jobject address = jenv->GetObjectField(jobj, jAddressField); + mGeoPosition = AndroidLocation::CreateGeoPosition(jenv, location); + if (address) + mGeoAddress = AndroidAddress::CreateGeoPositionAddress(jenv, address); break; } @@ -462,7 +547,6 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj) break; } - case SENSOR_ACCURACY: case ACTIVITY_STOPPING: case ACTIVITY_START: case ACTIVITY_PAUSING: diff --git a/widget/android/AndroidJavaWrappers.h b/widget/android/AndroidJavaWrappers.h index af3de14482fb..3ae573c1a6f8 100644 --- a/widget/android/AndroidJavaWrappers.h +++ b/widget/android/AndroidJavaWrappers.h @@ -384,6 +384,25 @@ public: static jmethodID jGetTimeMethod; }; +class AndroidAddress : public WrappedJavaObject +{ +public: + static void InitAddressClass(JNIEnv *jEnv); + static nsGeoPositionAddress* CreateGeoPositionAddress(JNIEnv *jenv, jobject jobj); + static jclass jAddressClass; + static jmethodID jGetAddressLineMethod; + static jmethodID jGetAdminAreaMethod; + static jmethodID jGetCountryNameMethod; + static jmethodID jGetFeatureNameMethod; + static jmethodID jGetLocalityMethod; + static jmethodID jGetPostalCodeMethod; + static jmethodID jGetPremisesMethod; + static jmethodID jGetSubAdminAreaMethod; + static jmethodID jGetSubLocalityMethod; + static jmethodID jGetSubThoroughfareMethod; + static jmethodID jGetThoroughfareMethod; +}; + class AndroidGeckoEvent : public WrappedJavaObject { public: @@ -420,6 +439,9 @@ public: nsTArray Pressures() { return mPressures; } nsTArray Orientations() { return mOrientations; } nsTArray PointRadii() { return mPointRadii; } + double Alpha() { return mAlpha; } + double Beta() { return mBeta; } + double Gamma() { return mGamma; } double X() { return mX; } double Y() { return mY; } double Z() { return mZ; } @@ -439,6 +461,7 @@ public: int RangeForeColor() { return mRangeForeColor; } int RangeBackColor() { return mRangeBackColor; } nsGeoPosition* GeoPosition() { return mGeoPosition; } + nsGeoPositionAddress* GeoAddress() { return mGeoAddress; } double Bandwidth() { return mBandwidth; } bool CanBeMetered() { return mCanBeMetered; } @@ -457,11 +480,13 @@ protected: int mOffset, mCount; int mRangeType, mRangeStyles; int mRangeForeColor, mRangeBackColor; + double mAlpha, mBeta, mGamma; double mX, mY, mZ; double mDistance; int mPointerIndex; nsString mCharacters, mCharactersExtra; nsRefPtr mGeoPosition; + nsRefPtr mGeoAddress; double mBandwidth; bool mCanBeMetered; @@ -490,6 +515,9 @@ protected: static jfieldID jOrientations; static jfieldID jPressures; static jfieldID jPointRadii; + static jfieldID jAlphaField; + static jfieldID jBetaField; + static jfieldID jGammaField; static jfieldID jXField; static jfieldID jYField; static jfieldID jZField; @@ -511,6 +539,7 @@ protected: static jfieldID jRangeForeColorField; static jfieldID jRangeBackColorField; static jfieldID jLocationField; + static jfieldID jAddressField; static jfieldID jBandwidthField; static jfieldID jCanBeMeteredField; @@ -520,8 +549,8 @@ public: NATIVE_POKE = 0, KEY_EVENT = 1, MOTION_EVENT = 2, - SENSOR_EVENT = 3, - UNUSED1_EVENT = 4, + ORIENTATION_EVENT = 3, + ACCELERATION_EVENT = 4, LOCATION_EVENT = 5, IME_EVENT = 6, DRAW = 7, @@ -542,7 +571,6 @@ public: PROXIMITY_EVENT = 23, ACTIVITY_RESUMING = 24, SCREENSHOT = 25, - SENSOR_ACCURACY = 26, dummy_java_enum_list_end }; diff --git a/widget/android/nsAppShell.cpp b/widget/android/nsAppShell.cpp index 631dc52fdd4d..83b24aa81e29 100644 --- a/widget/android/nsAppShell.cpp +++ b/widget/android/nsAppShell.cpp @@ -96,7 +96,7 @@ nsAppShell::nsAppShell() mQueueCond(mCondLock, "nsAppShell.mQueueCond"), mNumDraws(0), mNumViewports(0), - mPendingSensorEvents(false) + mPendingOrientationEvents(false) { gAppShell = this; } @@ -331,54 +331,32 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait) NativeEventCallback(); break; - case AndroidGeckoEvent::SENSOR_ACCURACY: - if (curEvent->Flags() == 0) - gDeviceMotionSystem->NeedsCalibration(); + case AndroidGeckoEvent::ACCELERATION_EVENT: + gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ACCELERATION, + -curEvent->X(), + curEvent->Y(), + curEvent->Z()); break; - case AndroidGeckoEvent::SENSOR_EVENT: - mPendingSensorEvents = false; - switch (curEvent->Flags()) { - case hal::SENSOR_ORIENTATION: - gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ORIENTATION, - curEvent->X(), - -curEvent->Y(), - -curEvent->Z()); - break; - - case hal::SENSOR_ACCELERATION: - gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ACCELERATION, - -curEvent->X(), - curEvent->Y(), - curEvent->Z()); - break; - - case hal::SENSOR_LINEAR_ACCELERATION: - gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_LINEAR_ACCELERATION, - -curEvent->X(), - curEvent->Y(), - curEvent->Z()); - break; - - case hal::SENSOR_GYROSCOPE: - gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_GYROSCOPE, - -curEvent->X(), - curEvent->Y(), - curEvent->Z()); - break; - - default: - __android_log_print(ANDROID_LOG_ERROR, "Gecko", "### SENSOR_EVENT fired, but type wasn't known %d", curEvent->Flags()); - } - break; + case AndroidGeckoEvent::ORIENTATION_EVENT: + gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ORIENTATION, + -curEvent->Alpha(), + curEvent->Beta(), + curEvent->Gamma()); + mPendingOrientationEvents = false; + break; case AndroidGeckoEvent::LOCATION_EVENT: { if (!gLocationCallback) break; nsGeoPosition* p = curEvent->GeoPosition(); - if (p) + nsGeoPositionAddress* a = curEvent->GeoAddress(); + + if (p) { + p->SetAddress(a); gLocationCallback->Update(curEvent->GeoPosition()); + } else NS_WARNING("Received location event without geoposition!"); break; @@ -624,10 +602,10 @@ nsAppShell::PostEvent(AndroidGeckoEvent *ae) delete event; } } - } else if (ae->Type() == AndroidGeckoEvent::SENSOR_EVENT) { - if (!mPendingSensorEvents) - mEventQueue.AppendElement(ae); - mPendingSensorEvents = true; + } else if (ae->Type() == AndroidGeckoEvent::ORIENTATION_EVENT) { + if (!mPendingOrientationEvents) + mEventQueue.AppendElement(ae); + mPendingOrientationEvents = true; } else { mEventQueue.AppendElement(ae); } diff --git a/widget/android/nsAppShell.h b/widget/android/nsAppShell.h index f86964dd8f59..ef43ae356e21 100644 --- a/widget/android/nsAppShell.h +++ b/widget/android/nsAppShell.h @@ -110,7 +110,7 @@ protected: mozilla::AndroidGeckoEvent *PeekNextEvent(); nsCOMPtr mBrowserApp; - bool mPendingSensorEvents; + bool mPendingOrientationEvents; }; #endif // nsAppShell_h__ diff --git a/xpcom/system/nsIDeviceMotion.idl b/xpcom/system/nsIDeviceMotion.idl index 79313d898388..f24144f6a3e6 100644 --- a/xpcom/system/nsIDeviceMotion.idl +++ b/xpcom/system/nsIDeviceMotion.idl @@ -43,8 +43,6 @@ interface nsIDeviceMotionData : nsISupports { const unsigned long TYPE_ACCELERATION = 0; const unsigned long TYPE_ORIENTATION = 1; - const unsigned long TYPE_LINEAR_ACCELERATION = 2; - const unsigned long TYPE_GYROSCOPE = 3; readonly attribute unsigned long type; @@ -53,11 +51,10 @@ interface nsIDeviceMotionData : nsISupports readonly attribute double z; }; -[scriptable, uuid(D29EA788-CCB6-4875-88E0-32A34BB71CBB)] +[scriptable, uuid(f01774a2-3b7e-4630-954b-196dc178221f)] interface nsIDeviceMotionListener : nsISupports { void onMotionChange(in nsIDeviceMotionData aMotionData); - void needsCalibration(); }; [scriptable, uuid(B6E5C463-AAA6-44E2-BD07-7A7DC6192E68)] @@ -76,10 +73,9 @@ interface nsIDeviceMotion : nsISupports /* for use by IPC system to notify non-chrome processes of * device motion events */ -[uuid(C12C0157-DCFF-41B5-83F3-89179BF6CA4E)] +[uuid(d3a56f08-b7b1-46bb-9dc1-fc3665a3631a)] interface nsIDeviceMotionUpdate : nsIDeviceMotion { /* must be called on the main thread or else */ void deviceMotionChanged(in unsigned long type, in double x, in double y, in double z); - void needsCalibration(); }; From 9e3f8ed0c52c6a477f6a21e6147f7e76367689bc Mon Sep 17 00:00:00 2001 From: Joshua M Date: Tue, 13 Mar 2012 23:31:29 +0100 Subject: [PATCH 26/57] Bug 734374 - Adjust the URL and search bar border color on Aero basic & glass. r=dao --HG-- extra : rebase_source : a7dde9c189a16c7b7fef9ce37f38d0e1638bdc20 --- browser/themes/winstripe/browser-aero.css | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/browser/themes/winstripe/browser-aero.css b/browser/themes/winstripe/browser-aero.css index c1c9df5077e6..1bca806e2d84 100644 --- a/browser/themes/winstripe/browser-aero.css +++ b/browser/themes/winstripe/browser-aero.css @@ -66,6 +66,21 @@ -moz-linear-gradient(@customToolbarColor@, @customToolbarColor@); } + #navigator-toolbox[tabsontop=true] #urlbar:not(:-moz-lwtheme), + #navigator-toolbox[tabsontop=true] .searchbar-textbox:not(:-moz-lwtheme) { + border-color: hsla(210,54%,20%,.25) hsla(210,54%,20%,.27) hsla(210,54%,20%,.3); + } + + #navigator-toolbox[tabsontop=true] #urlbar:not(:-moz-lwtheme):not([focused]):hover, + #navigator-toolbox[tabsontop=true] .searchbar-textbox:not(:-moz-lwtheme):not([focused]):hover { + border-color: hsla(210,54%,20%,.35) hsla(210,54%,20%,.37) hsla(210,54%,20%,.4); + } + + #navigator-toolbox[tabsontop=true] #urlbar:not(:-moz-lwtheme)[focused], + #navigator-toolbox[tabsontop=true] .searchbar-textbox:not(:-moz-lwtheme)[focused] { + border-color: hsla(206,100%,60%,.65) hsla(206,100%,55%,.65) hsla(206,100%,50%,.65); + } + #sidebar-splitter { border: 0; -moz-border-end: 1px solid #A9B7C9; From 243eb49a832d8f949c1838b9985122a8905ef2f1 Mon Sep 17 00:00:00 2001 From: Masatoshi Kimura Date: Tue, 13 Mar 2012 23:31:55 +0100 Subject: [PATCH 27/57] Bug 735268 - Restore StorageEvent test which is accidentally removed. r=sicking --HG-- extra : rebase_source : 07a34decab41334160ff6314beb76a0c38cf520d --- content/events/test/test_eventctors.html | 42 ++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/content/events/test/test_eventctors.html b/content/events/test/test_eventctors.html index 4efecf7c6037..516e9e17e75c 100644 --- a/content/events/test/test_eventctors.html +++ b/content/events/test/test_eventctors.html @@ -326,10 +326,48 @@ is(e.view, window, "view should be window"); document.dispatchEvent(e); is(receivedEvent, e, "Wrong event!"); -// UIEvent +// StorageEvent try { - e = new UIEvent(); + e = new StorageEvent(); +} catch(exp) { + ex = true; +} +ok(ex, "First parameter is required!"); +ex = false; + +e = new StorageEvent("hello"); +ok(e.type, "hello", "Wrong event type!"); +ok(!e.isTrusted, "Event shouldn't be trusted!"); +ok(!e.bubbles, "Event shouldn't bubble!"); +ok(!e.cancelable, "Event shouldn't be cancelable!"); +is(e.key, "", "key should be ''"); +is(e.oldValue, null, "oldValue should be null"); +is(e.newValue, null, "newValue should be null"); +is(e.url, "", "url should be ''"); +document.dispatchEvent(e); +is(receivedEvent, e, "Wrong event!"); + +e = new StorageEvent("hello", + { bubbles: true, cancelable: true, key: "key", + oldValue: "oldValue", newValue: "newValue", url: "url", + storageArea: localStorage }); +ok(e.type, "hello", "Wrong event type!"); +ok(!e.isTrusted, "Event shouldn't be trusted!"); +ok(e.bubbles, "Event should bubble!"); +ok(e.cancelable, "Event should be cancelable!"); +is(e.key, "key", "Wrong value"); +is(e.oldValue, "oldValue", "Wrong value"); +is(e.newValue, "newValue", "Wrong value"); +is(e.url, "url", "Wrong value"); +is(e.storageArea, localStorage, "Wrong value"); +document.dispatchEvent(e); +is(receivedEvent, e, "Wrong event!"); + +// MouseEvent + +try { + e = new MouseEvent(); } catch(exp) { ex = true; } From e2b9a9b0ecbb346ea21e05c8d96cc6b253168ca0 Mon Sep 17 00:00:00 2001 From: David Rajchenbach-Teller Date: Tue, 13 Mar 2012 23:32:53 +0100 Subject: [PATCH 28/57] Bug 699856 - Refactor nsSearchService.js to not use a database engine. r=gavin --HG-- extra : rebase_source : 80f5830b5d6efcc2e6ec21495709f847d53aac7b --- toolkit/components/search/nsSearchService.js | 416 +++++++++++++----- .../tests/xpcshell/data/chrome.manifest | 2 + .../search/tests/xpcshell/data/engine.src | 18 + .../search/tests/xpcshell/data/engine.xml | 18 + .../xpcshell/data/ico-size-16x16-png.ico | Bin 0 -> 901 bytes .../tests/xpcshell/data/search-metadata.json | 28 ++ .../search/tests/xpcshell/data/search.sqlite | Bin 0 -> 65536 bytes .../search/tests/xpcshell/head_search.js | 83 ++-- .../search/tests/xpcshell/test_645970.js | 18 +- .../search/tests/xpcshell/test_migratedb.js | 38 ++ .../search/tests/xpcshell/test_nodb.js | 37 ++ .../tests/xpcshell/test_nodb_pluschanges.js | 87 ++++ .../search/tests/xpcshell/xpcshell.ini | 3 + 13 files changed, 581 insertions(+), 167 deletions(-) create mode 100644 toolkit/components/search/tests/xpcshell/data/engine.src create mode 100644 toolkit/components/search/tests/xpcshell/data/engine.xml create mode 100644 toolkit/components/search/tests/xpcshell/data/ico-size-16x16-png.ico create mode 100644 toolkit/components/search/tests/xpcshell/data/search-metadata.json create mode 100644 toolkit/components/search/tests/xpcshell/data/search.sqlite create mode 100644 toolkit/components/search/tests/xpcshell/test_migratedb.js create mode 100644 toolkit/components/search/tests/xpcshell/test_nodb.js create mode 100644 toolkit/components/search/tests/xpcshell/test_nodb_pluschanges.js diff --git a/toolkit/components/search/nsSearchService.js b/toolkit/components/search/nsSearchService.js index d9e94cb86a91..82663d9a6cef 100644 --- a/toolkit/components/search/nsSearchService.js +++ b/toolkit/components/search/nsSearchService.js @@ -43,6 +43,7 @@ const Cc = Components.classes; const Cr = Components.results; Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); +Components.utils.import("resource://gre/modules/Services.jsm"); const PERMS_FILE = 0644; const PERMS_DIRECTORY = 0755; @@ -76,6 +77,19 @@ const SEARCH_ENGINE_CHANGED = "engine-changed"; const SEARCH_ENGINE_LOADED = "engine-loaded"; const SEARCH_ENGINE_CURRENT = "engine-current"; +// The following constants are left undocumented in nsIBrowserSearchService.idl +// For the moment, they are meant for testing/debugging purposes only. + +/** + * Topic used for events involving the service itself. + */ +const SEARCH_SERVICE_TOPIC = "browser-search-service"; + +/** + * Sent whenever metadata is fully written to disk. + */ +const SEARCH_SERVICE_METADATA_WRITTEN = "write-metadata-to-disk-complete"; + const SEARCH_TYPE_MOZSEARCH = Ci.nsISearchEngine.TYPE_MOZSEARCH; const SEARCH_TYPE_OPENSEARCH = Ci.nsISearchEngine.TYPE_OPENSEARCH; const SEARCH_TYPE_SHERLOCK = Ci.nsISearchEngine.TYPE_SHERLOCK; @@ -218,6 +232,12 @@ __defineGetter__("gPrefSvc", function() { getService(Ci.nsIPrefBranch); }); +__defineGetter__("FileUtils", function() { + delete this.FileUtils; + Components.utils.import("resource://gre/modules/FileUtils.jsm"); + return FileUtils; +}); + __defineGetter__("NetUtil", function() { delete this.NetUtil; Components.utils.import("resource://gre/modules/NetUtil.jsm"); @@ -309,6 +329,64 @@ function ENSURE_WARN(assertion, message, resultCode) { throw Components.Exception(message, resultCode); } +/** + * A delayed treatment that may be delayed even further. + * + * Use this for instance if you write data to a file and you expect + * that you may have to rewrite data very soon afterwards. With + * |Lazy|, the treatment is delayed by a few milliseconds and, + * should a new change to the data occur during this period, + * 1/ only the final version of the data is actually written; + * 2/ a further grace delay is added to take into account other + * changes. + * + * @constructor + * @param {Function} code The code to execute after the delay. + * @param {number=} delay An optional delay, in milliseconds. + */ +function Lazy(code, delay) { + LOG("Lazy: Creating a Lazy"); + this._callback = + (function(){ + code(); + this._timer = null; + }).bind(this); + this._delay = delay || LAZY_SERIALIZE_DELAY; + this._timer = null; +} +Lazy.prototype = { + /** + * Start (or postpone) treatment. + */ + go: function Lazy_go() { + LOG("Lazy_go: starting"); + if (this._timer) { + LOG("Lazy_go: reusing active timer"); + this._timer.delay = this._delay; + } else { + LOG("Lazy_go: creating timer"); + this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + this._timer. + initWithCallback(this._callback, + this._delay, + Ci.nsITimer.TYPE_ONE_SHOT); + } + }, + /** + * Perform any postponed treatment immediately. + */ + flush: function Lazy_flush() { + LOG("Lazy_flush: starting"); + if (!this._timer) { + return; + } + this._timer.cancel(); + this._timer = null; + this._callback(); + } +}; + + function loadListener(aChannel, aEngine, aCallback) { this._channel = aChannel; this._bytes = []; @@ -718,6 +796,12 @@ function notifyAction(aEngine, aVerb) { } } +function parseJsonFromStream(aInputStream) { + const json = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON); + const data = json.decodeFromStream(aInputStream, aInputStream.available()); + return data; +} + /** * Simple object representing a name/value pair. */ @@ -2576,6 +2660,7 @@ SearchService.prototype = { }, _loadEngines: function SRCH_SVC__loadEngines() { + LOG("_loadEngines: start"); // See if we have a cache file so we don't have to parse a bunch of XML. let cache = {}; let cacheEnabled = getBoolPref(BROWSER_SEARCH_PREF + "cache.enabled", true); @@ -2633,8 +2718,11 @@ SearchService.prototype = { return; } + LOG("_loadEngines: loading from cache directories"); for each (let dir in cache.directories) this._loadEnginesFromCache(dir); + + LOG("_loadEngines: done"); }, _readCacheFile: function SRCH_SVC__readCacheFile(aFile) { @@ -2810,7 +2898,7 @@ SearchService.prototype = { try { this._convertSherlockFile(addedEngine, fileURL.fileBaseName); } catch (ex) { - LOG("_loadEnginesFromDir: Failed to convert: " + fileURL.path + "\n" + ex); + LOG("_loadEnginesFromDir: Failed to convert: " + fileURL.path + "\n" + ex + "\n" + ex.stack); // The engine couldn't be converted, mark it as read-only addedEngine._readOnly = true; } @@ -2907,23 +2995,29 @@ SearchService.prototype = { _saveSortedEngineList: function SRCH_SVC_saveSortedEngineList() { // We only need to write the prefs. if something has changed. + LOG("SRCH_SVC_saveSortedEngineList: starting"); if (!this._needToSetOrderPrefs) return; + LOG("SRCH_SVC_saveSortedEngineList: something to do"); + // Set the useDB pref to indicate that from now on we should use the order // information stored in the database. gPrefSvc.setBoolPref(BROWSER_SEARCH_PREF + "useDBForOrder", true); var engines = this._getSortedEngines(true); - var values = []; - var names = []; + let instructions = []; for (var i = 0; i < engines.length; ++i) { - names[i] = "order"; - values[i] = i + 1; + instructions.push( + {key: "order", + value: i+1, + engine: engines[i] + }); } - engineMetadataService.setAttrs(engines, names, values); + engineMetadataService.setAttrs(instructions); + LOG("SRCH_SVC_saveSortedEngineList: done"); }, _buildSortedEngineList: function SRCH_SVC_buildSortedEngineList() { @@ -2936,6 +3030,7 @@ SearchService.prototype = { // information from the engineMetadataService instead of the default // prefs. if (getBoolPref(BROWSER_SEARCH_PREF + "useDBForOrder", false)) { + LOG("_buildSortedEngineList: using db for order"); for each (engine in this._engines) { var orderNumber = engineMetadataService.getAttr(engine, "order"); @@ -3434,7 +3529,7 @@ SearchService.prototype = { this._batchTimer.cancel(); this._buildCache(); } - engineMetadataService.closeDB(); + engineMetadataService.flush(); break; } }, @@ -3499,135 +3594,216 @@ SearchService.prototype = { }; var engineMetadataService = { - get mDB() { - var engineDataTable = "id INTEGER PRIMARY KEY, engineid STRING, name STRING, value STRING"; - var file = getDir(NS_APP_USER_PROFILE_50_DIR); - file.append("search.sqlite"); - var dbService = Cc["@mozilla.org/storage/service;1"]. - getService(Ci.mozIStorageService); - var db; - try { - db = dbService.openDatabase(file); - } catch (ex) { - if (ex.result == 0x8052000b) { /* NS_ERROR_FILE_CORRUPTED */ - // delete and try again - file.remove(false); - db = dbService.openDatabase(file); - } else { - throw ex; + /** + * @type {nsIFile|null} The file holding the metadata. + */ + get _jsonFile() { + delete this._jsonFile; + return this._jsonFile = FileUtils.getFile(NS_APP_USER_PROFILE_50_DIR, + ["search-metadata.json"]); + }, + + /** + * Lazy getter for the file containing json data. + */ + get _store() { + delete this._store; + return this._store = this._loadStore(); + }, + + // Perform loading the first time |_store| is accessed. + _loadStore: function() { + let jsonFile = this._jsonFile; + if (!jsonFile.exists()) { + LOG("loadStore: search-metadata.json does not exist"); + + // First check to see whether there's an existing SQLite DB to migrate + let store = this._migrateOldDB(); + if (store) { + // Commit the migrated store to disk immediately + LOG("Committing the migrated store to disk"); + this._commit(store); + return store; } + + // Migration failed, or this is a first-run - just use an empty store + return {}; } + LOG("loadStore: attempting to load store from JSON file"); try { - db.createTable("engine_data", engineDataTable); - } catch (ex) { - // Fails if the table already exists, which is fine + return parseJsonFromStream(NetUtil.newChannel(jsonFile).open()); + } catch (x) { + LOG("loadStore failed to load file: "+x); + return {}; } - - delete this.mDB; - return this.mDB = db; - }, - - get mGetData() { - delete this.mGetData; - return this.mGetData = this.mDB.createStatement( - "SELECT value FROM engine_data WHERE engineid = :engineid AND name = :name"); - }, - get mDeleteData() { - delete this.mDeleteData; - return this.mDeleteData = this.mDB.createStatement( - "DELETE FROM engine_data WHERE engineid = :engineid AND name = :name"); - }, - get mInsertData() { - delete this.mInsertData; - return this.mInsertData = this.mDB.createStatement( - "INSERT INTO engine_data (engineid, name, value) " + - "VALUES (:engineid, :name, :value)"); }, getAttr: function epsGetAttr(engine, name) { - // attr names must be lower case - name = name.toLowerCase(); - - var stmt = this.mGetData; - stmt.reset(); - var pp = stmt.params; - pp.engineid = engine._id; - pp.name = name; - - var value = null; - if (stmt.executeStep()) - value = stmt.row.value; - stmt.reset(); - return value; - }, - - setAttr: function epsSetAttr(engine, name, value) { - // attr names must be lower case - name = name.toLowerCase(); - - this.mDB.beginTransaction(); - - var pp = this.mDeleteData.params; - pp.engineid = engine._id; - pp.name = name; - this.mDeleteData.executeStep(); - this.mDeleteData.reset(); - - pp = this.mInsertData.params; - pp.engineid = engine._id; - pp.name = name; - pp.value = value; - this.mInsertData.executeStep(); - this.mInsertData.reset(); - - this.mDB.commitTransaction(); - }, - - setAttrs: function epsSetAttrs(engines, names, values) { - this.mDB.beginTransaction(); - - for (var i = 0; i < engines.length; i++) { - // attr names must be lower case - var name = names[i].toLowerCase(); - - var pp = this.mDeleteData.params; - pp.engineid = engines[i]._id; - pp.name = names[i]; - this.mDeleteData.executeStep(); - this.mDeleteData.reset(); - - pp = this.mInsertData.params; - pp.engineid = engines[i]._id; - pp.name = names[i]; - pp.value = values[i]; - this.mInsertData.executeStep(); - this.mInsertData.reset(); + let record = this._store[engine._id]; + if (!record) { + return null; } - this.mDB.commitTransaction(); + // attr names must be lower case + return record[name.toLowerCase()]; }, - deleteEngineData: function epsDelData(engine, name) { + _setAttr: function epsSetAttr(engine, name, value) { // attr names must be lower case name = name.toLowerCase(); - - var pp = this.mDeleteData.params; - pp.engineid = engine._id; - pp.name = name; - this.mDeleteData.executeStep(); - this.mDeleteData.reset(); + let db = this._store; + let record = db[engine._id]; + if (!record) { + record = db[engine._id] = {}; + } + if (record[name] != value) { + record[name] = value; + return true; + } + return false; }, - closeDB: function epsCloseDB() { - ["mInsertData", "mDeleteData", "mGetData"].forEach(function(aStmt) { - if (Object.getOwnPropertyDescriptor(this, aStmt).value !== undefined) - this[aStmt].finalize(); - }, this); - if (Object.getOwnPropertyDescriptor(this, "mDB").value !== undefined) - this.mDB.close(); - } -} + /** + * Set one metadata attribute for an engine. + * + * If an actual change has taken place, the attribute is committed + * automatically (and lazily), using this._commit. + * + * @param {nsISearchEngine} engine The engine to update. + * @param {string} key The name of the attribute. Case-insensitive. In + * the current implementation, this _must not_ conflict with properties + * of |Object|. + * @param {*} value A value to store. + */ + setAttr: function epsSetAttr(engine, key, value) { + if (this._setAttr(engine, key, value)) { + this._commit(); + } + }, + + /** + * Bulk set metadata attributes for a number of engines. + * + * If actual changes have taken place, the store is committed + * automatically (and lazily), using this._commit. + * + * @param {Array.<{engine: nsISearchEngine, key: string, value: *}>} changes + * The list of changes to effect. See |setAttr| for the documentation of + * |engine|, |key|, |value|. + */ + setAttrs: function epsSetAttrs(changes) { + let self = this; + let changed = false; + changes.forEach(function(change) { + changed |= self._setAttr(change.engine, change.key, change.value); + }); + if (changed) { + this._commit(); + } + }, + + /** + * Flush any waiting write. + */ + flush: function epsFlush() { + if (this._lazyWriter) { + this._lazyWriter.flush(); + } + }, + + /** + * Migrate search.sqlite + * + * Notes: + * - we do not remove search.sqlite after migration, so as to allow + * downgrading and forensics; + */ + _migrateOldDB: function SRCH_SVC_EMS_migrate() { + LOG("SRCH_SVC_EMS_migrate start"); + let sqliteFile = FileUtils.getFile(NS_APP_USER_PROFILE_50_DIR, + ["search.sqlite"]); + if (!sqliteFile.exists()) { + LOG("SRCH_SVC_EMS_migrate search.sqlite does not exist"); + return null; + } + let store = {}; + try { + LOG("SRCH_SVC_EMS_migrate Migrating data from SQL"); + const sqliteDb = Services.storage.openDatabase(sqliteFile); + const statement = sqliteDb.createStatement("SELECT * from engine_data"); + while (statement.executeStep()) { + let row = statement.row; + let engine = row.engineid; + let name = row.name; + let value = row.value; + if (!store[engine]) { + store[engine] = {}; + } + store[engine][name] = value; + } + statement.finalize(); + sqliteDb.close(); + } catch (ex) { + LOG("SRCH_SVC_EMS_migrate failed: " + ex); + return null; + } + return store; + }, + + /** + * Commit changes to disk, asynchronously. + * + * Calls to this function are actually delayed by LAZY_SERIALIZE_DELAY + * (= 100ms). If the function is called again before the expiration of + * the delay, commits are merged and the function is again delayed by + * the same amount of time. + * + * @param aStore is an optional parameter specifying the object to serialize. + * If not specified, this._store is used. + */ + _commit: function epsCommit(aStore) { + LOG("epsCommit: start"); + + let store = aStore || this._store; + if (!store) { + LOG("epsCommit: nothing to do"); + return; + } + + if (!this._lazyWriter) { + LOG("epsCommit: initializing lazy writer"); + let jsonFile = this._jsonFile; + function writeCommit() { + LOG("epsWriteCommit: start"); + let ostream = FileUtils. + openSafeFileOutputStream(jsonFile, + MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE); + + // Obtain a converter to convert our data to a UTF-8 encoded input stream. + let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]. + createInstance(Ci.nsIScriptableUnicodeConverter); + converter.charset = "UTF-8"; + + let callback = function(result) { + if (Components.isSuccessCode(result)) { + gObsSvc.notifyObservers(null, + SEARCH_SERVICE_TOPIC, + SEARCH_SERVICE_METADATA_WRITTEN); + } + LOG("epsWriteCommit: done " + result); + }; + // Asynchronously copy the data to the file. + let istream = converter.convertToInputStream(JSON.stringify(store)); + NetUtil.asyncCopy(istream, ostream, callback); + } + this._lazyWriter = new Lazy(writeCommit); + } + LOG("epsCommit: (re)setting timer"); + this._lazyWriter.go(); + }, + _lazyWriter: null, +}; const SEARCH_UPDATE_LOG_PREFIX = "*** Search update: "; diff --git a/toolkit/components/search/tests/xpcshell/data/chrome.manifest b/toolkit/components/search/tests/xpcshell/data/chrome.manifest index ac459af7e013..ec412e05081f 100644 --- a/toolkit/components/search/tests/xpcshell/data/chrome.manifest +++ b/toolkit/components/search/tests/xpcshell/data/chrome.manifest @@ -1 +1,3 @@ locale testsearchplugin ar jar:jar:searchTest.jar!/chrome/searchTest.jar!/ +content testsearchplugin ./ + diff --git a/toolkit/components/search/tests/xpcshell/data/engine.src b/toolkit/components/search/tests/xpcshell/data/engine.src new file mode 100644 index 000000000000..bd5fff1793d4 --- /dev/null +++ b/toolkit/components/search/tests/xpcshell/data/engine.src @@ -0,0 +1,18 @@ + + + + + + + diff --git a/toolkit/components/search/tests/xpcshell/data/engine.xml b/toolkit/components/search/tests/xpcshell/data/engine.xml new file mode 100644 index 000000000000..aba350f4f430 --- /dev/null +++ b/toolkit/components/search/tests/xpcshell/data/engine.xml @@ -0,0 +1,18 @@ + + +Test search engine +A test search engine (based on Google search) +UTF-8 +data:image/png;base64,AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADs9Pt8xetPtu9FsfFNtu%2BTzvb2%2B%2Fne4dFJeBw0egA%2FfAJAfAA8ewBBegAAAAD%2B%2FPtft98Mp%2BwWsfAVsvEbs%2FQeqvF8xO7%2F%2F%2F63yqkxdgM7gwE%2FggM%2BfQA%2BegBDeQDe7PIbotgQufcMufEPtfIPsvAbs%2FQvq%2Bfz%2Bf%2F%2B%2B%2FZKhR05hgBBhQI8hgBAgAI9ewD0%2B%2Fg3pswAtO8Cxf4Kw%2FsJvvYAqupKsNv%2B%2Fv7%2F%2FP5VkSU0iQA7jQA9hgBDgQU%2BfQH%2F%2Ff%2FQ6fM4sM4KsN8AteMCruIqqdbZ7PH8%2Fv%2Fg6Nc%2Fhg05kAA8jAM9iQI%2BhQA%2BgQDQu6b97uv%2F%2F%2F7V8Pqw3eiWz97q8%2Ff%2F%2F%2F%2F7%2FPptpkkqjQE4kwA7kAA5iwI8iAA8hQCOSSKdXjiyflbAkG7u2s%2F%2B%2F%2F39%2F%2F7r8utrqEYtjQE8lgA7kwA7kwA9jwA9igA9hACiWSekVRyeSgiYSBHx6N%2F%2B%2Fv7k7OFRmiYtlAA5lwI7lwI4lAA7kgI9jwE9iwI4iQCoVhWcTxCmb0K%2BooT8%2Fv%2F7%2F%2F%2FJ2r8fdwI1mwA3mQA3mgA8lAE8lAE4jwA9iwE%2BhwGfXifWvqz%2B%2Ff%2F58u%2Fev6Dt4tr%2B%2F%2F2ZuIUsggA7mgM6mAM3lgA5lgA6kQE%2FkwBChwHt4dv%2F%2F%2F728ei1bCi7VAC5XQ7kz7n%2F%2F%2F6bsZkgcB03lQA9lgM7kwA2iQktZToPK4r9%2F%2F%2F9%2F%2F%2FSqYK5UwDKZAS9WALIkFn%2B%2F%2F3%2F%2BP8oKccGGcIRJrERILYFEMwAAuEAAdX%2F%2Ff7%2F%2FP%2B%2BfDvGXQLIZgLEWgLOjlf7%2F%2F%2F%2F%2F%2F9QU90EAPQAAf8DAP0AAfMAAOUDAtr%2F%2F%2F%2F7%2B%2Fu2bCTIYwDPZgDBWQDSr4P%2F%2Fv%2F%2F%2FP5GRuABAPkAA%2FwBAfkDAPAAAesAAN%2F%2F%2B%2Fz%2F%2F%2F64g1C5VwDMYwK8Yg7y5tz8%2Fv%2FV1PYKDOcAAP0DAf4AAf0AAfYEAOwAAuAAAAD%2F%2FPvi28ymXyChTATRrIb8%2F%2F3v8fk6P8MAAdUCAvoAAP0CAP0AAfYAAO4AAACAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAA + + + + + + + + + + +http://www.google.com/ + diff --git a/toolkit/components/search/tests/xpcshell/data/ico-size-16x16-png.ico b/toolkit/components/search/tests/xpcshell/data/ico-size-16x16-png.ico new file mode 100644 index 0000000000000000000000000000000000000000..442ab4dc8093602a04c8e5affb02510d84853e9c GIT binary patch literal 901 zcmV;01A6=b0096201yxW0096X0B8gN02TlM0EtjeM-2)Z3IG5A4M|8uQUCw|5C8xG z5C{eU001BJ|6u?C12#!SK~y-61;I^h+XNVZ;m`SLoU}q>u_w6ECYgFo7iWmuLSuez zw8RmJ)1t=HxUFs6Nt|efBaK@baX{P(Ns4wHtD}lrrNw39HmOdL;DWRm0hhEXmzU>} ztN-Ts=PJSPvpIg9CHQ$Z$KzR&?`BE9oF)0}D#g9o9G_e!d4Cq?t;;0KvpHV7RC#5Z zLZ*Mmh$113gkU20kUn>&V6PI8h*s17Q>hejxM%g-#&2 zf#3wfMj+Gz!3+`@ry262EZS&^%(G?W;#eW_g|RQ3`ohsr=naLAFSx$2?F$>eLhUGy zd6c2->*W1Kw4)-Kr?-%cA7ey)VcZu^2MWW1LjO?k4u$qWXboaC2MMfR2D6{#R)2}Y zpvd*XZ5Dd(A=7UZqK*)Dgi}u#c7=f_bUmT%DL7u7W=F;9=v2KW%3hIt_cpq>#(d{v z0YDm<}lku%5H^1dkx)fu;6}*Ts%;iIKsFk z1diZ4Lf;WOtr%Zyr)jk`Hk?H)XN9U$!En~eI}J2vi%jbQGQAfkx+|R9LSQQlZH2xa zr_)U1+8R6d61H8WZdWkvHOh8_g1w2}+-0Hp5Se}yBdRN$TMEC_6nraAua@TPT9&qz zW5+6DTNSMO8r6D(l69YaeGkprC-dRA$n@Pf6H_=}RS2pH{HjXN%;HsZw5uyPW(C{) z0LyGpHSbe4Kc`^sqnqC|zxo)NzNs)Vgs>Fj*-aI{l%;Ph(J@wVjkj@1>oko!)Ql}w z%exrmee&f4G~*{SrDNn`InJaI=PaKlC|qM$SY%LG!7Eg7Z>-}K8r&^xVdZx*Z#=@t zACNCRLC>EspL>o>uP1q#RS7knKwIQkzsaFip{uRa)*EbVo7nmuR`x5Z+5si)2|4Wq zO?yEmdyf2@R`^p*@j}%(QS&@amH9!f@<^?-r#9J4?{FvWvaWWisC|m+kT=pJURB4W bQh)G2Kinzq-|`j^H^Jy{9Ur(|+TN&4$jQYKCKaP6`hyAz`#0SMB4v)tD zL4OpVkA}~Bqm%fwf3p4eQkx!+N5iARcARIke0ey}%CqjYwb8yRZOYJmYrZ!>nzH$I z^_eyV2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkL{e+t~ao`&6<$;)i9 zc(q$!6m^}SKKwW<&pzan5U-`-Q5R;j>~l4rRQ20xw!CpWO~Y1qBR|MKEt7leY1r$M bi{gE;$R|a%jPKk?!%i1Zt7=;2U6%X?UteZ1 literal 0 HcmV?d00001 diff --git a/toolkit/components/search/tests/xpcshell/head_search.js b/toolkit/components/search/tests/xpcshell/head_search.js index 110d94547b88..2b45f0f135c8 100644 --- a/toolkit/components/search/tests/xpcshell/head_search.js +++ b/toolkit/components/search/tests/xpcshell/head_search.js @@ -1,37 +1,10 @@ /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** 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 Initial Developer of the Original Code is POTI Inc. - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ + +Components.utils.import("resource://gre/modules/Services.jsm"); +Components.utils.import("resource://gre/modules/NetUtil.jsm"); +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); + const XULAPPINFO_CONTRACTID = "@mozilla.org/xre/app-info;1"; const XULAPPINFO_CID = Components.ID("{c763b610-9d49-455a-bbd2-ede71682a1ac}"); @@ -90,3 +63,49 @@ function createAppInfo(id, name, version, platformVersion) // Need to create and register a profile folder. var gProfD = do_get_profile(); +function dumpn(text) +{ + dump(text+"\n"); +} + +/** + * Clean the profile of any metadata files left from a previous run. + */ +function removeMetadata() +{ + let file = gProfD.clone(); + file.append("search-metadata.json"); + if (file.exists()) { + file.remove(false); + } + + file = gProfD.clone(); + file.append("search.sqlite"); + if (file.exists()) { + file.remove(false); + } +} + +/** + * Run some callback once metadata has been committed to disk. + */ +function afterCommit(callback) +{ + let obs = function(result, topic, verb) { + if (verb == "write-metadata-to-disk-complete") { + callback(result); + } else { + dump("TOPIC: " + topic+ "\n"); + } + } + Services.obs.addObserver(obs, "browser-search-service", false); +} + +function parseJsonFromStream(aInputStream) { + const json = Cc["@mozilla.org/dom/json;1"].createInstance(Components.interfaces.nsIJSON); + const data = json.decodeFromStream(aInputStream, aInputStream.available()); + return data; +} + +Services.prefs.setBoolPref("browser.search.log", true); +//Otherwise, error logs contain no useful data diff --git a/toolkit/components/search/tests/xpcshell/test_645970.js b/toolkit/components/search/tests/xpcshell/test_645970.js index 811dd2b4a35b..6a9b99c4b55f 100644 --- a/toolkit/components/search/tests/xpcshell/test_645970.js +++ b/toolkit/components/search/tests/xpcshell/test_645970.js @@ -33,16 +33,6 @@ * * ***** END LICENSE BLOCK ***** */ -let Cc = Components.classes; -let Ci = Components.interfaces; -let Cu = Components.utils; - -Cu.import("resource://gre/modules/Services.jsm"); - - -var gPrefService = Cc["@mozilla.org/preferences-service;1"] - .getService(Ci.nsIPrefService) - .QueryInterface(Ci.nsIPrefBranch); /** * Test nsSearchService with nested jar: uris */ @@ -52,15 +42,13 @@ function run_test() { do_load_manifest("data/chrome.manifest"); let url = "chrome://testsearchplugin/locale/searchplugins/"; - gPrefService.setCharPref("browser.search.jarURIs", url); + Services.prefs.setCharPref("browser.search.jarURIs", url); - gPrefService.setBoolPref("browser.search.loadFromJars", true); + Services.prefs.setBoolPref("browser.search.loadFromJars", true); // The search service needs to be started after the jarURIs pref has been // set in order to initiate it correctly - let searchService = Cc["@mozilla.org/browser/search-service;1"] - .getService(Ci.nsIBrowserSearchService); - let engine = searchService.getEngineByName("bug645970"); + let engine = Services.search.getEngineByName("bug645970"); do_check_neq(engine, null); Services.obs.notifyObservers(null, "quit-application", null); } diff --git a/toolkit/components/search/tests/xpcshell/test_migratedb.js b/toolkit/components/search/tests/xpcshell/test_migratedb.js new file mode 100644 index 000000000000..906818970f90 --- /dev/null +++ b/toolkit/components/search/tests/xpcshell/test_migratedb.js @@ -0,0 +1,38 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* + * test_migratedb: Start search engine + * - without search-metadata.json + * - with search.sqlite + * + * Ensure that nothing explodes. + */ + +function run_test() +{ + removeMetadata(); + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "2"); + + let search_sqlite = do_get_file("data/search.sqlite"); + search_sqlite.copyTo(gProfD, "search.sqlite"); + + let search = Services.search; + + do_test_pending(); + afterCommit( + function() + { + //Check that search-metadata.json has been created + let metadata = gProfD.clone(); + metadata.append("search-metadata.json"); + do_check_true(metadata.exists()); + + removeMetadata(); + do_test_finished(); + } + ); + + search.getEngines(); +} diff --git a/toolkit/components/search/tests/xpcshell/test_nodb.js b/toolkit/components/search/tests/xpcshell/test_nodb.js new file mode 100644 index 000000000000..dd6f07df6edf --- /dev/null +++ b/toolkit/components/search/tests/xpcshell/test_nodb.js @@ -0,0 +1,37 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* + * test_nodb: Start search engine + * - without search-metadata.json + * - without search.sqlite + * + * Ensure that : + * - nothing explodes; + * - no search-metadata.json is created. + */ + + +function run_test() +{ + removeMetadata(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "2"); + + let search = Services.search; // Cause service initialization + + do_test_pending(); + do_timeout(500, + function() + { + // Check that search-metadata.json has not been created + // Note that we cannot du much better than a timeout for + // checking a non-event. + let metadata = gProfD.clone(); + metadata.append("search-metadata.json"); + do_check_true(!metadata.exists()); + removeMetadata(); + + do_test_finished(); + } + ); +} diff --git a/toolkit/components/search/tests/xpcshell/test_nodb_pluschanges.js b/toolkit/components/search/tests/xpcshell/test_nodb_pluschanges.js new file mode 100644 index 000000000000..062ecad9ff91 --- /dev/null +++ b/toolkit/components/search/tests/xpcshell/test_nodb_pluschanges.js @@ -0,0 +1,87 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + + +/* + * test_nodb: Start search engine + * - without search-metadata.json + * - without search.sqlite + * + * Ensure that : + * - nothing explodes; + * - if we change the order, search-metadata.json is created; + * - this search-medata.json can be parsed; + * - the order stored in search-metadata.json is consistent. + * + * Notes: + * - we install the search engines of test "test_downloadAndAddEngines.js" + * to ensure that this test is independent from locale, commercial agreements + * and configuration of Firefox. + */ + +do_load_httpd_js(); + +function run_test() +{ + removeMetadata(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "2"); + do_load_manifest("data/chrome.manifest"); + + let httpServer = new nsHttpServer(); + httpServer.start(4444); + httpServer.registerDirectory("/", do_get_cwd()); + + let search = Services.search; + + function observer(aSubject, aTopic, aData) { + if ("engine-added" == aData) { + let engine1 = search.getEngineByName("Test search engine"); + let engine2 = search.getEngineByName("Sherlock test search engine"); + dumpn("Got engine 2: "+engine2); + if(engine1 && engine2) + { + search.moveEngine(engine1, 0); + search.moveEngine(engine2, 1); + do_timeout(0, + function() { + // Force flush + // Note: the timeout is needed, to avoid some reentrency + // issues in nsSearchService. + search.QueryInterface(Ci.nsIObserver). + observe(observer, "quit-application", ""); + }); + afterCommit( + function() + { + // Check that search-metadata.json has been created + let metadata = gProfD.clone(); + metadata.append("search-metadata.json"); + do_check_true(metadata.exists()); + + // Check that the entries are placed as specified correctly + let stream = NetUtil.newChannel(metadata).open(); + let json = parseJsonFromStream(stream); + do_check_eq(json["[app]/test-search-engine.xml"].order, 1); + do_check_eq(json["[profile]/sherlock-test-search-engine.xml"].order, 2); + httpServer.stop(function() {}); + stream.close(); // Stream must be closed under Windows + removeMetadata(); + do_test_finished(); + } + ); + } + } + }; + Services.obs.addObserver(observer, "browser-search-engine-modified", + false); + + do_test_pending(); + + search.addEngine("http://localhost:4444/data/engine.xml", + Ci.nsISearchEngine.DATA_XML, + null, false); + search.addEngine("http://localhost:4444/data/engine.src", + Ci.nsISearchEngine.DATA_TEXT, + "http://localhost:4444/data/ico-size-16x16-png.ico", + false); +} diff --git a/toolkit/components/search/tests/xpcshell/xpcshell.ini b/toolkit/components/search/tests/xpcshell/xpcshell.ini index 5c7a961fc084..7f215e0d6ba0 100644 --- a/toolkit/components/search/tests/xpcshell/xpcshell.ini +++ b/toolkit/components/search/tests/xpcshell/xpcshell.ini @@ -2,4 +2,7 @@ head = head_search.js tail = +[test_nodb.js] +[test_nodb_pluschanges.js] +[test_migratedb.js] [test_645970.js] From 4ce018517d463100c1028529456b085049b78cf8 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Tue, 13 Mar 2012 15:38:05 -0700 Subject: [PATCH 29/57] Bug 735491 - Fix possible recursion when tracing Debugger objects; r=billm --HG-- extra : rebase_source : 9a1365dd7dffdd4a34f2390bc1739b490369cbe5 --- js/src/vm/Debugger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index a3adef846250..680da9941ee8 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -2163,7 +2163,7 @@ DebuggerScript_trace(JSTracer *trc, JSObject *obj) /* This comes from a private pointer, so no barrier needed. */ if (JSScript *script = GetScriptReferent(obj)) { MarkScriptUnbarriered(trc, &script, "Debugger.Script referent"); - SetScriptReferent(obj, script); + obj->setPrivateUnbarriered(script); } } } From 93297761bbc12e304437943a93c0929e8ec3554b Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Tue, 13 Mar 2012 15:48:18 -0700 Subject: [PATCH 30/57] Bug 735490 - Delete mobile/android/chrome/tests/. r=mbrubeck --- mobile/android/chrome/tests/Makefile.in | 142 ----- .../addons/browser_install1_1/bootstrap.js | 9 - .../addons/browser_install1_1/install.rdf | 24 - .../addons/browser_install1_2/install.rdf | 22 - .../addons/browser_install1_3/install.rdf | 23 - .../tests/addons/browser_locale1/boostrap.js | 9 - .../addons/browser_locale1/chrome.manifest | 4 - .../tests/addons/browser_locale1/install.rdf | 24 - mobile/android/chrome/tests/browser_addons.js | 503 ------------------ .../chrome/tests/browser_addons_locales.js | 64 --- .../android/chrome/tests/browser_appmenu.js | 139 ----- .../chrome/tests/browser_autocomplete.html | 34 -- .../chrome/tests/browser_autocomplete.js | 184 ------- .../tests/browser_autocompletesearch.js | 108 ---- .../chrome/tests/browser_awesomescreen.js | 470 ---------------- .../chrome/tests/browser_blank_01.html | 6 - .../chrome/tests/browser_blank_02.html | 7 - .../chrome/tests/browser_blank_03.html | 6 - .../android/chrome/tests/browser_bookmarks.js | 304 ----------- .../chrome/tests/browser_bookmarks_star.js | 248 --------- .../chrome/tests/browser_bookmarks_tags.js | 192 ------- .../chrome/tests/browser_click_content.html | 7 - .../chrome/tests/browser_click_content.js | 128 ----- .../android/chrome/tests/browser_contacts.js | 88 --- .../chrome/tests/browser_contentpopup.html | 26 - .../chrome/tests/browser_contentpopup.js | 89 ---- .../android/chrome/tests/browser_dragger.js | 89 ---- mobile/android/chrome/tests/browser_escape.js | 128 ----- mobile/android/chrome/tests/browser_find.js | 39 -- .../android/chrome/tests/browser_focus.html | 7 - mobile/android/chrome/tests/browser_focus.js | 52 -- .../android/chrome/tests/browser_forms.html | 51 -- mobile/android/chrome/tests/browser_forms.js | 242 --------- .../chrome/tests/browser_formsZoom.html | 66 --- .../android/chrome/tests/browser_formsZoom.js | 214 -------- .../android/chrome/tests/browser_history.js | 75 --- .../android/chrome/tests/browser_install.xml | 58 -- .../chrome/tests/browser_localepicker.js | 282 ---------- .../tests/browser_localepicker_escape.js | 44 -- .../chrome/tests/browser_localerepository.js | 39 -- .../tests/browser_localerepository_buildid.js | 41 -- .../tests/browser_localerepository_pref.js | 35 -- mobile/android/chrome/tests/browser_mainui.js | 27 - .../chrome/tests/browser_navigation.js | 403 -------------- .../tests/browser_preferences_fulltoggle.js | 67 --- .../chrome/tests/browser_preferences_text.js | 131 ----- mobile/android/chrome/tests/browser_rect.js | 107 ---- .../chrome/tests/browser_rememberPassword.js | 60 --- .../android/chrome/tests/browser_scroll.html | 16 - mobile/android/chrome/tests/browser_scroll.js | 19 - .../android/chrome/tests/browser_scrollbar.js | 181 ------- .../chrome/tests/browser_scrollbar.sjs | 67 --- .../android/chrome/tests/browser_select.html | 99 ---- mobile/android/chrome/tests/browser_select.js | 87 --- .../chrome/tests/browser_sessionstore.js | 116 ---- .../android/chrome/tests/browser_sidebars.js | 220 -------- mobile/android/chrome/tests/browser_tabs.js | 192 ------- .../chrome/tests/browser_tap_content.html | 24 - .../chrome/tests/browser_tap_contentedit.html | 14 - .../android/chrome/tests/browser_tapping.js | 306 ----------- .../chrome/tests/browser_tapping_edit.js | 279 ---------- mobile/android/chrome/tests/browser_test.js | 20 - .../chrome/tests/browser_thumbnails.js | 155 ------ mobile/android/chrome/tests/browser_title.sjs | 67 --- .../android/chrome/tests/browser_upgrade.rdf | 45 -- .../android/chrome/tests/browser_viewport.js | 209 -------- .../android/chrome/tests/browser_viewport.sjs | 65 --- mobile/android/chrome/tests/browser_vkb.js | 150 ------ mobile/android/chrome/tests/head.js | 122 ----- mobile/android/chrome/tests/locales_list.sjs | 121 ----- .../chrome/tests/mock_autocomplete.json | 22 - .../chrome/tests/remote_autocomplete.js | 22 - .../chrome/tests/remote_contentpopup.js | 18 - mobile/android/chrome/tests/remote_focus.js | 16 - mobile/android/chrome/tests/remote_forms.js | 171 ------ .../android/chrome/tests/remote_formsZoom.js | 9 - mobile/android/chrome/tests/remote_head.js | 35 -- mobile/android/chrome/tests/remote_vkb.js | 6 - 78 files changed, 7990 deletions(-) delete mode 100644 mobile/android/chrome/tests/Makefile.in delete mode 100644 mobile/android/chrome/tests/addons/browser_install1_1/bootstrap.js delete mode 100644 mobile/android/chrome/tests/addons/browser_install1_1/install.rdf delete mode 100644 mobile/android/chrome/tests/addons/browser_install1_2/install.rdf delete mode 100644 mobile/android/chrome/tests/addons/browser_install1_3/install.rdf delete mode 100644 mobile/android/chrome/tests/addons/browser_locale1/boostrap.js delete mode 100644 mobile/android/chrome/tests/addons/browser_locale1/chrome.manifest delete mode 100644 mobile/android/chrome/tests/addons/browser_locale1/install.rdf delete mode 100644 mobile/android/chrome/tests/browser_addons.js delete mode 100644 mobile/android/chrome/tests/browser_addons_locales.js delete mode 100644 mobile/android/chrome/tests/browser_appmenu.js delete mode 100644 mobile/android/chrome/tests/browser_autocomplete.html delete mode 100644 mobile/android/chrome/tests/browser_autocomplete.js delete mode 100644 mobile/android/chrome/tests/browser_autocompletesearch.js delete mode 100644 mobile/android/chrome/tests/browser_awesomescreen.js delete mode 100644 mobile/android/chrome/tests/browser_blank_01.html delete mode 100644 mobile/android/chrome/tests/browser_blank_02.html delete mode 100644 mobile/android/chrome/tests/browser_blank_03.html delete mode 100644 mobile/android/chrome/tests/browser_bookmarks.js delete mode 100644 mobile/android/chrome/tests/browser_bookmarks_star.js delete mode 100644 mobile/android/chrome/tests/browser_bookmarks_tags.js delete mode 100644 mobile/android/chrome/tests/browser_click_content.html delete mode 100644 mobile/android/chrome/tests/browser_click_content.js delete mode 100644 mobile/android/chrome/tests/browser_contacts.js delete mode 100644 mobile/android/chrome/tests/browser_contentpopup.html delete mode 100644 mobile/android/chrome/tests/browser_contentpopup.js delete mode 100644 mobile/android/chrome/tests/browser_dragger.js delete mode 100644 mobile/android/chrome/tests/browser_escape.js delete mode 100644 mobile/android/chrome/tests/browser_find.js delete mode 100644 mobile/android/chrome/tests/browser_focus.html delete mode 100644 mobile/android/chrome/tests/browser_focus.js delete mode 100644 mobile/android/chrome/tests/browser_forms.html delete mode 100644 mobile/android/chrome/tests/browser_forms.js delete mode 100644 mobile/android/chrome/tests/browser_formsZoom.html delete mode 100644 mobile/android/chrome/tests/browser_formsZoom.js delete mode 100644 mobile/android/chrome/tests/browser_history.js delete mode 100644 mobile/android/chrome/tests/browser_install.xml delete mode 100644 mobile/android/chrome/tests/browser_localepicker.js delete mode 100644 mobile/android/chrome/tests/browser_localepicker_escape.js delete mode 100644 mobile/android/chrome/tests/browser_localerepository.js delete mode 100644 mobile/android/chrome/tests/browser_localerepository_buildid.js delete mode 100644 mobile/android/chrome/tests/browser_localerepository_pref.js delete mode 100644 mobile/android/chrome/tests/browser_mainui.js delete mode 100644 mobile/android/chrome/tests/browser_navigation.js delete mode 100644 mobile/android/chrome/tests/browser_preferences_fulltoggle.js delete mode 100644 mobile/android/chrome/tests/browser_preferences_text.js delete mode 100644 mobile/android/chrome/tests/browser_rect.js delete mode 100644 mobile/android/chrome/tests/browser_rememberPassword.js delete mode 100644 mobile/android/chrome/tests/browser_scroll.html delete mode 100644 mobile/android/chrome/tests/browser_scroll.js delete mode 100644 mobile/android/chrome/tests/browser_scrollbar.js delete mode 100644 mobile/android/chrome/tests/browser_scrollbar.sjs delete mode 100644 mobile/android/chrome/tests/browser_select.html delete mode 100644 mobile/android/chrome/tests/browser_select.js delete mode 100644 mobile/android/chrome/tests/browser_sessionstore.js delete mode 100644 mobile/android/chrome/tests/browser_sidebars.js delete mode 100644 mobile/android/chrome/tests/browser_tabs.js delete mode 100644 mobile/android/chrome/tests/browser_tap_content.html delete mode 100644 mobile/android/chrome/tests/browser_tap_contentedit.html delete mode 100644 mobile/android/chrome/tests/browser_tapping.js delete mode 100644 mobile/android/chrome/tests/browser_tapping_edit.js delete mode 100644 mobile/android/chrome/tests/browser_test.js delete mode 100644 mobile/android/chrome/tests/browser_thumbnails.js delete mode 100644 mobile/android/chrome/tests/browser_title.sjs delete mode 100644 mobile/android/chrome/tests/browser_upgrade.rdf delete mode 100644 mobile/android/chrome/tests/browser_viewport.js delete mode 100644 mobile/android/chrome/tests/browser_viewport.sjs delete mode 100644 mobile/android/chrome/tests/browser_vkb.js delete mode 100644 mobile/android/chrome/tests/head.js delete mode 100644 mobile/android/chrome/tests/locales_list.sjs delete mode 100644 mobile/android/chrome/tests/mock_autocomplete.json delete mode 100644 mobile/android/chrome/tests/remote_autocomplete.js delete mode 100644 mobile/android/chrome/tests/remote_contentpopup.js delete mode 100644 mobile/android/chrome/tests/remote_focus.js delete mode 100644 mobile/android/chrome/tests/remote_forms.js delete mode 100644 mobile/android/chrome/tests/remote_formsZoom.js delete mode 100644 mobile/android/chrome/tests/remote_head.js delete mode 100644 mobile/android/chrome/tests/remote_vkb.js diff --git a/mobile/android/chrome/tests/Makefile.in b/mobile/android/chrome/tests/Makefile.in deleted file mode 100644 index 5780f544d803..000000000000 --- a/mobile/android/chrome/tests/Makefile.in +++ /dev/null @@ -1,142 +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 Mozilla. -# -# The Initial Developer of the Original Code is -# the Mozilla Foundation . -# Portions created by the Initial Developer are Copyright (C) 2008 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Finkle -# -# 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 ***** - -DEPTH = ../../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ -relativesrcdir = mobile/chrome/tests -TESTXPI = $(CURDIR)/$(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)/addons -ADDONSRC = $(srcdir)/addons - -include $(DEPTH)/config/autoconf.mk -include $(topsrcdir)/config/rules.mk - -_BROWSER_FILES = \ - head.js \ - remote_autocomplete.js \ - remote_contentpopup.js \ - remote_head.js \ - remote_focus.js \ - remote_forms.js \ - remote_formsZoom.js \ - remote_vkb.js \ - browser_addons.js \ - browser_addons_locales.js \ - browser_appmenu.js \ - browser_autocompletesearch.js \ - $(info browser_awesomescreen.js is disabled because the localepicker is disabled (bug 693524)) \ - browser_blank_01.html \ - browser_blank_02.html \ - browser_blank_03.html \ - browser_bookmarks.js \ - browser_contacts.js \ - browser_dragger.js \ - browser_escape.js \ - browser_find.js \ - browser_focus.html \ - browser_focus.js \ - browser_forms.html \ - $(warning browser_forms.js disabled due to failures) \ - browser_formsZoom.html \ - $(warning browser_formsZoom.js disabled due to failures) \ - $(info browser_history.js is disabled because it is random orange on XUL fennec (bug 700537)) \ - $(info browser_localepicker.js is disabled because the localepicker is disabled (bug 694047)) \ - browser_localepicker_escape.js \ - browser_mainui.js \ - browser_preferences_text.js \ - browser_preferences_fulltoggle.js \ - browser_rect.js \ - $(info browser_rememberPassword.js is disabled because it is random orange on XUL fennec (bug 698387)) \ - browser_scroll.js \ - browser_scroll.html \ - browser_scrollbar.js \ - browser_select.html \ - browser_select.js \ - browser_sessionstore.js \ - $(info browser_tabs.js is disabled because it is random orange on XUL fennec (bug 700537)) \ - $(info browser_tapping.js is disabled because it is random orange on XUL fennec (bug 698387)) \ - $(info browser_tap_content.html is disabled because it is random orange on XUL fennec (bug 698387)) \ - browser_tapping_edit.js \ - browser_tap_contentedit.html \ - browser_test.js \ - browser_vkb.js \ - $(warning browser_viewport.js disabled due to failures) \ - browser_viewport.sjs \ - browser_scrollbar.sjs \ - browser_title.sjs \ - $(info browser_thumbnails.js is disabled because it is random orange on XUL fennec (bug 700537)) \ - browser_install.xml \ - browser_upgrade.rdf\ - browser_localerepository.js \ - browser_localerepository_pref.js \ - browser_localerepository_buildid.js \ - locales_list.sjs \ - mock_autocomplete.json\ - $(NULL) - -ifneq ($(OS_TARGET),Android) -_BROWSER_FILES += \ - browser_autocomplete.html \ - browser_autocomplete.js \ - browser_bookmarks_star.js \ - browser_bookmarks_tags.js \ - browser_click_content.html \ - browser_click_content.js \ - browser_contentpopup.html \ - browser_contentpopup.js \ - browser_navigation.js \ - $(NULL) -ifndef MOZ_PLATFORM_MAEMO -_BROWSER_FILES += browser_sidebars.js -endif -endif - -libs:: $(_BROWSER_FILES) - $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir) - -libs:: - rm -rf $(TESTXPI) - $(NSINSTALL) -D $(TESTXPI) - if [ -d $(ADDONSRC) ]; then \ - $(EXIT_ON_ERROR) \ - for dir in $(ADDONSRC)/*; do \ - base=`basename $$dir` ; \ - (cd $$dir && zip $(TESTXPI)/$$base.xpi *) \ - done \ - fi - diff --git a/mobile/android/chrome/tests/addons/browser_install1_1/bootstrap.js b/mobile/android/chrome/tests/addons/browser_install1_1/bootstrap.js deleted file mode 100644 index 7b86e419a3b3..000000000000 --- a/mobile/android/chrome/tests/addons/browser_install1_1/bootstrap.js +++ /dev/null @@ -1,9 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -function install(data, reason) {} -function startup(data, reason) {} -function shutdown(data, reason) {} -function uninstall(data, reason) {} - diff --git a/mobile/android/chrome/tests/addons/browser_install1_1/install.rdf b/mobile/android/chrome/tests/addons/browser_install1_1/install.rdf deleted file mode 100644 index 0825d11aa0cb..000000000000 --- a/mobile/android/chrome/tests/addons/browser_install1_1/install.rdf +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - addon1@tests.mozilla.org - 1.0 - http://example.com/browser/mobile/chrome/tests/browser_upgrade.rdf - true - - - - toolkit@mozilla.org - 0 - * - - - - - Install Tests - - - diff --git a/mobile/android/chrome/tests/addons/browser_install1_2/install.rdf b/mobile/android/chrome/tests/addons/browser_install1_2/install.rdf deleted file mode 100644 index 945afb22b014..000000000000 --- a/mobile/android/chrome/tests/addons/browser_install1_2/install.rdf +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - addon2@tests.mozilla.org - 2.0 - - - - toolkit@mozilla.org - 0 - * - - - - - Install Tests 2 - - - diff --git a/mobile/android/chrome/tests/addons/browser_install1_3/install.rdf b/mobile/android/chrome/tests/addons/browser_install1_3/install.rdf deleted file mode 100644 index 2c10f4921628..000000000000 --- a/mobile/android/chrome/tests/addons/browser_install1_3/install.rdf +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - addon1@tests.mozilla.org - 3.0 - http://example.com/browser/mobile/chrome/tests/browser_upgrade.rdf - - - - toolkit@mozilla.org - 0 - * - - - - - Install Tests - - - diff --git a/mobile/android/chrome/tests/addons/browser_locale1/boostrap.js b/mobile/android/chrome/tests/addons/browser_locale1/boostrap.js deleted file mode 100644 index 7b86e419a3b3..000000000000 --- a/mobile/android/chrome/tests/addons/browser_locale1/boostrap.js +++ /dev/null @@ -1,9 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -function install(data, reason) {} -function startup(data, reason) {} -function shutdown(data, reason) {} -function uninstall(data, reason) {} - diff --git a/mobile/android/chrome/tests/addons/browser_locale1/chrome.manifest b/mobile/android/chrome/tests/addons/browser_locale1/chrome.manifest deleted file mode 100644 index a909200d5b02..000000000000 --- a/mobile/android/chrome/tests/addons/browser_locale1/chrome.manifest +++ /dev/null @@ -1,4 +0,0 @@ -locale mozapps te-st chrome # locale -locale browser te-st chrome # duplicate locale -locale browser te-st-a chrome # second locale -locale branding te-st-3 chrome # wrong component diff --git a/mobile/android/chrome/tests/addons/browser_locale1/install.rdf b/mobile/android/chrome/tests/addons/browser_locale1/install.rdf deleted file mode 100644 index ba92a4581869..000000000000 --- a/mobile/android/chrome/tests/addons/browser_locale1/install.rdf +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - locale1@tests.mozilla.org - 1.0 - 8 - true - - - - toolkit@mozilla.org - 0 - * - - - - - Test Locale - - - diff --git a/mobile/android/chrome/tests/browser_addons.js b/mobile/android/chrome/tests/browser_addons.js deleted file mode 100644 index 7b465e2e5cdf..000000000000 --- a/mobile/android/chrome/tests/browser_addons.js +++ /dev/null @@ -1,503 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -Components.utils.import("resource://gre/modules/AddonManager.jsm"); -Components.utils.import("resource://gre/modules/AddonUpdateChecker.jsm"); -Components.utils.import("resource://gre/modules/Services.jsm"); -Components.utils.import("resource://gre/modules/NetUtil.jsm"); - -const RELATIVE_DIR = "browser/mobile/chrome/tests/"; -const TESTROOT = "http://example.com/" + RELATIVE_DIR; -const TESTROOT2 = "http://example.org/" + RELATIVE_DIR; -const PREF_LOGGING_ENABLED = "extensions.logging.enabled"; -const PREF_SEARCH_MAXRESULTS = "extensions.getAddons.maxResults"; -const CHROME_NAME = "mochikit"; -const PREF_AUTOUPDATE_DEFAULT = "extensions.update.autoUpdateDefault" -const PREF_GETADDONS_BROWSESEARCHRESULTS = "extensions.getAddons.search.browseURL"; -const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; -const PREF_GETADDONS_GETRECOMMENDED = "extensions.getAddons.recommended.url"; -const PREF_GETADDONS_BROWSERECOMMENDED = "extensions.getAddons.recommended.browseURL"; -const PREF_GETADDONS_UPDATE = "extensions.update.url"; -const PREF_ADDONS_LOGGING = "extensions.logging.enabled"; -const PREF_ADDONS_SECURITY = "extensions.checkUpdateSecurity"; -const SEARCH_URL = TESTROOT + "browser_details.xml"; -const ADDON_IMG = "chrome://browser/skin/images/alert-addons-30.png"; - -var addons = [{ - id: "addon1@tests.mozilla.org", - name : "Install Tests", - iconURL: "http://example.com/icon.png", - homepageURL: "http://example.com/", - version: "1.0", - description: "Test add-on", - sourceURL: TESTROOT + "addons/browser_install1_1.xpi", - bootstrapped: true, - willFail: false, - updateIndex: 2, -}, -{ - id: "addon2@tests.mozilla.org", - name : "Install Tests 2", - iconURL: "http://example.com/icon.png", - homepageURL: "http://example.com/", - version: "1.0", - description: "Test add-on 2", - sourceURL: TESTROOT + "addons/browser_install1_2.xpi", - bootstrapped: false, - willFail: false, -}, -{ - id: "addon1@tests.mozilla.org", - name : "Install Tests 3", - iconURL: "http://example.com/icon.png", - homepageURL: "http://example.com/", - version: "1.0", - description: "Test add-on 3", - sourceURL: TESTROOT + "addons/browser_install1_3.xpi", - bootstrapped: false, - willFail: false, -}]; - - -var gPendingTests = []; -var gTestsRun = 0; -var gTestStart = null; -var gDate = new Date(2010, 7, 1); -var gApp = Strings.brand.GetStringFromName("brandShortName"); -var gCategoryUtilities; -var gSearchCount = 0; -var gTestURL = TESTROOT + "browser_blank_01.html"; -var gCurrentTab = null; - -function test() { - waitForExplicitFinish(); - requestLongerTimeout(2); - Services.prefs.setCharPref(PREF_GETADDONS_GETRECOMMENDED, TESTROOT + "browser_install.xml"); - Services.prefs.setCharPref(PREF_GETADDONS_BROWSERECOMMENDED, TESTROOT + "browser_install.xml"); - Services.prefs.setCharPref(PREF_GETADDONS_BROWSESEARCHRESULTS, TESTROOT + "browser_install.xml"); - Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, TESTROOT + "browser_install.xml"); - Services.prefs.setCharPref(PREF_GETADDONS_UPDATE, TESTROOT + "browser_upgrade.rdf"); - Services.prefs.setBoolPref(PREF_ADDONS_SECURITY, false); - Services.prefs.setBoolPref(PREF_ADDONS_LOGGING, true); - run_next_test(); -} - -function end_test() { - close_manager(); - Services.prefs.clearUserPref(PREF_GETADDONS_GETRECOMMENDED); - Services.prefs.clearUserPref(PREF_GETADDONS_BROWSERECOMMENDED); - Services.prefs.clearUserPref(PREF_GETADDONS_BROWSESEARCHRESULTS); - Services.prefs.clearUserPref(PREF_GETADDONS_GETSEARCHRESULTS); - Services.prefs.clearUserPref(PREF_GETADDONS_UPDATE); - Services.prefs.clearUserPref(PREF_ADDONS_SECURITY); - Services.prefs.clearUserPref(PREF_ADDONS_LOGGING); -} - -registerCleanupFunction(end_test); - -function add_test(test) { - gPendingTests.push(test); -} - -function run_next_test() { - if (gTestsRun > 0) - info("Test " + gTestsRun + " took " + (Date.now() - gTestStart) + "ms"); - - if (!gPendingTests.length) { - finish(); - return; - } - - gTestsRun++; - let test = gPendingTests.shift(); - if (test.name) - info("Running test " + gTestsRun + " (" + test.name + ")"); - else - info("Running test " + gTestsRun); - - gTestStart = Date.now(); - test(); -} - -function checkAttribute(aElt, aAttr, aVal) { - ok(aElt.hasAttribute(aAttr), "Element has " + aAttr + " attribute"); - if(aVal) - is(aElt.getAttribute(aAttr), aVal, "Element has " + aAttr + " attribute with value " + aVal); -} - -function installExtension(elt, aListener) { - elt.parentNode.ensureElementIsVisible(elt); - elt.install.addListener(aListener) - - let button = document.getAnonymousElementByAttribute(elt, "class", "addon-install hide-on-install hide-on-restart"); - ok(!!button, "Extension has install button"); - ExtensionsView.installFromRepo(elt); -} - -function isRestartShown(aShown, isUpdate, aCallback) { - let msg = document.getElementById("addons-messages"); - ok(!!msg, "Have message box"); - - let done = function(aNotification) { - is(!!aNotification, aShown, "Restart exists = " + aShown); - if (aShown && aNotification) { - let showsUpdate = aNotification.label.match(/update/i) != null; - // this test regularly fails due to race conditions here - is(showsUpdate, isUpdate, "Restart shows correct message"); - } - msg.removeAllNotifications(true); - aCallback(); - } - - let notification = msg.getNotificationWithValue("restart-app"); - if (!notification && aShown) { - window.addEventListener("AlertActive", function() { - window.removeEventListener("AlertActive", arguments.callee, true); - notification = msg.getNotificationWithValue("restart-app"); - done(notification); - }, true); - } else { - done(notification); - } -} - -function checkInstallAlert(aShown, aCallback) { - checkAlert(null, "xpinstall", null, aShown, function(aNotifyBox, aNotification) { - if (aShown) { - let button = aNotification.childNodes[0]; - ok(!!button, "Notification has button"); - if (button) - button.click(); - } - aNotifyBox.removeAllNotifications(true); - if (aCallback) - aCallback(); - }); -} - -function checkDownloadNotification(aCallback) { - let msg = /download/i; - checkNotification(/Add-ons/, msg, ADDON_IMG, aCallback); -} - -function checkInstallNotification(aRestart, aCallback) { - let msg = null; - if (aRestart) - msg = /restart/i; - checkNotification(/Add-ons/, msg, ADDON_IMG, aCallback); -} - -function checkNotification(aTitle, aMessage, aIcon, aCallback) { - let doTest = function() { - ok(document.getElementById("alerts-container").classList.contains("showing"), "Alert shown"); - let title = document.getElementById("alerts-title").value; - let msg = document.getElementById("alerts-text").textContent; - let img = document.getElementById("alerts-image").getAttribute("src"); - - if (aTitle) - ok(aTitle.test(title), "Correct title alert shown: " + title); - if (aMessage) - ok(aMessage.test(msg), "Correct message shown: " + msg); - if (aIcon) - is(img, aIcon, "Correct image shown: " + aIcon); - - // make sure this is hidden before another test asks about it - AlertsHelper.container.classList.remove("showing"); - AlertsHelper.container.height = 0; - AlertsHelper.container.hidden = true; - aCallback(); - }; - - let sysInfo = Cc["@mozilla.org/system-info;1"].getService(Ci.nsIPropertyBag2); - if (sysInfo.get("device")) - aCallback(); - else - waitFor(doTest, function() { return AlertsHelper.container.hidden == false; }); -} - -function checkAlert(aId, aName, aLabel, aShown, aCallback) { - let msg = null; - if (aId) - msg = document.getElementById(aId); - else - msg = window.getNotificationBox(gCurrentTab.browser); - ok(!!msg, "Have notification box"); - - let haveNotification = function(notify) { - is(!!notify, aShown, "Notification alert exists = " + aShown); - if (notify && aLabel) - ok(aLabel.test(notify.label), "Notification shows correct message"); - if (aCallback) - aCallback(msg, notify); - } - - let notification = msg.getNotificationWithValue(aName); - if (!notification && aShown) { - window.addEventListener("AlertActive", function() { - window.removeEventListener("AlertActive", arguments.callee, true); - notification = msg.getNotificationWithValue(aName); - haveNotification(notification); - }, true); - } else { - haveNotification(notification); - } -} - -function checkAddonListing(aAddon, elt, aType) { - ok(!!elt, "Element exists for addon"); - checkAttribute(elt, "id", "urn:mozilla:item:" + aAddon.id); - checkAttribute(elt, "addonID", aAddon.id); - checkAttribute(elt, "typeName", aType); - checkAttribute(elt, "name", aAddon.name); - checkAttribute(elt, "version", aAddon.version); - if (aType == "search") { - checkAttribute(elt, "iconURL", aAddon.iconURL); - checkAttribute(elt, "description", aAddon.description) - checkAttribute(elt, "homepageURL", aAddon.homepageURL); - checkAttribute(elt, "sourceURL", aAddon.sourceURL); - ok(elt.install, "Extension has install property"); - } -} - -function checkUpdate(aSettings) { - let os = Services.obs; - let ul = new updateListener(aSettings); - os.addObserver(ul, "addon-update-ended", false); - - ExtensionsView.updateAll(); -} - -function get_addon_element(aId) { - return document.getElementById("urn:mozilla:item:" + aId); -} - -function open_manager(aView, aCallback) { - BrowserUI.showPanel("addons-container"); - - ExtensionsView.init(); - ExtensionsView.delayedInit(); - - window.addEventListener("ViewChanged", function() { - window.removeEventListener("ViewChanged", arguments.callee, true); - aCallback(); - }, true); -} - -function close_manager(aCallback) { - let prefsButton = document.getElementById("tool-preferences"); - prefsButton.click(); - - ExtensionsView.clearSection(); - ExtensionsView.clearSection("local"); - ExtensionsView._list = null; - ExtensionsView._restartCount = 0; - BrowserUI.hidePanel(); - - if (aCallback) - aCallback(); -} - -function loadUrl(aURL, aCallback, aNewTab) { - if (aNewTab) - gCurrentTab = Browser.addTab(aURL, true); - else - Browser.loadURI(aURL); - - gCurrentTab.browser.messageManager.addMessageListener("pageshow", function(aMessage) { - if (gCurrentTab.browser.currentURI.spec == aURL) { - gCurrentTab.browser.messageManager.removeMessageListener(aMessage.name, arguments.callee); - if (aCallback) - setTimeout(aCallback, 0); - } - }); -} - -function checkInstallPopup(aName, aCallback) { - testPrompt("Installing Add-on", aName, [ {label: "Install", click: true}, - {label: "Cancel", click: false}], - aCallback); -} - -function testPrompt(aTitle, aMessage, aButtons, aCallback) { - function doTest() { - let prompt = document.getElementById("prompt-confirm-dialog"); - ok(!!prompt, "Prompt shown"); - - if (prompt) { - let title = document.getElementById("prompt-confirm-title"); - let message = document.getElementById("prompt-confirm-message"); - is(aTitle, title.textContent, "Correct title shown"); - is(aMessage, message.textContent, "Correct message shown"); - - let buttons = document.querySelectorAll("#prompt-confirm-buttons-box .prompt-button"); - let clickButton = null; - is(buttons.length, aButtons.length, "Prompt has correct number of buttons"); - if (buttons.length == aButtons.length) { - for (let i = 0; i < buttons.length; i++) { - is(buttons[i].label, aButtons[i].label, "Button has correct label"); - if (aButtons[i].click) - clickButton = buttons[i]; - } - } - if (clickButton) - clickButton.click(); - } - if (aCallback) - aCallback(); - } - - if (!document.getElementById("prompt-confirm-dialog")) { - window.addEventListener("DOMWillOpenModalDialog", function() { - window.removeEventListener("DOMWillOpenModalDialog", arguments.callee, true); - // without this timeout, this can cause the prompt service to fail - setTimeout(doTest, 500); - }, true); - } else { - doTest(); - } -} - -// Installs an addon via the urlbar. -function installFromURLBar(aAddon) { - return function() { - AddonManager.addInstallListener({ - onInstallEnded: function (install) { - AddonManager.removeInstallListener(this); - checkInstallNotification(!aAddon.bootstrapped, function() { - open_manager(true, function() { - isRestartShown(!aAddon.bootstrapped, false, function() { - let elt = get_addon_element(aAddon.id); - if (aAddon.bootstrapped) { - checkAddonListing(aAddon, elt, "local"); - let button = document.getAnonymousElementByAttribute(elt, "anonid", "uninstall-button"); - ok(!!button, "Extension has uninstall button"); - - let updateButton = document.getElementById("addons-update-all"); - is(updateButton.disabled, false, "Update button is enabled"); - - ExtensionsView.uninstall(elt); - - elt = get_addon_element(aAddon.id); - ok(!elt, "Addon element removed during uninstall"); - Browser.closeTab(gCurrentTab); - close_manager(run_next_test); - } else { - ok(!elt, "Extension not in list"); - AddonManager.getAllInstalls(function(aInstalls) { - for(let i = 0; i < aInstalls.length; i++) { - aInstalls[i].cancel(); - } - Browser.closeTab(gCurrentTab); - close_manager(run_next_test); - }); - } - }); - }); - }); - } - }); - loadUrl(gTestURL, function() { - loadUrl(aAddon.sourceURL, null, false); - checkInstallAlert(true, function() { - checkDownloadNotification(function() { - checkInstallPopup(aAddon.name, function() { }); - }); - }); - }, true); - }; -} - -// Installs an addon from the addons pref pane, and then -// updates it if requested. Checks to make sure -// restart notifications are shown at the right time -function installFromAddonsPage(aAddon, aDoUpdate) { - return function() { - open_manager(null, function() { - let elt = get_addon_element(aAddon.id); - checkAddonListing(aAddon, elt); - installExtension(elt, new installListener({ - addon: aAddon, - onComplete: function() { - if (aDoUpdate) { - checkUpdate({ - addon: addons[aAddon.updateIndex], - onComplete: function() { - close_manager(); - run_next_test(); - } - }); - } else { - close_manager(); - run_next_test(); - } - } - })); - }); - } -} - -add_test(installFromURLBar(addons[0])); -add_test(installFromURLBar(addons[1])); -add_test(installFromAddonsPage(addons[0], true)); -add_test(installFromAddonsPage(addons[1], false)); - -function installListener(aSettings) { - this.onComplete = aSettings.onComplete; - this.addon = aSettings.addon; -} - -installListener.prototype = { - onNewInstall : function(install) { }, - onDownloadStarted : function(install) { }, - onDownloadProgress : function(install) { }, - onDownloadEnded : function(install) { }, - onDownloadCancelled : function(install) { }, - onDownloadFailed : function(install) { - if(this.addon.willFail) - ok(false, "Install failed"); - }, - onInstallStarted : function(install) { }, - onInstallEnded : function(install, addon) { - let self = this; - isRestartShown(!this.addon.bootstrapped, false, function() { - if(self.onComplete) - self.onComplete(); - }); - }, - onInstallCancelled : function(install) { }, - onInstallFailed : function(install) { - if(this.willFail) - ok(false, "Install failed"); - }, - onExternalInstall : function(install, existing, needsRestart) { }, -}; - -function updateListener(aSettings) { - this.onComplete = aSettings.onComplete; - this.addon = aSettings.addon; -} - -updateListener.prototype = { - observe: function (aSubject, aTopic, aData) { - switch(aTopic) { - case "addon-update-ended" : - let json = aSubject.QueryInterface(Ci.nsISupportsString).data; - let update = JSON.parse(json); - if(update.id == this.addon.id) { - let os = Services.obs; - os.removeObserver(this, "addon-update-ended", false); - - let element = get_addon_element(update.id); - ok(!!element, "Have element for upgrade"); - - let self = this; - isRestartShown(!this.addon.bootstrapped, true, function() { - if(self.onComplete) - self.onComplete(); - }); - } - break; - } - }, -} diff --git a/mobile/android/chrome/tests/browser_addons_locales.js b/mobile/android/chrome/tests/browser_addons_locales.js deleted file mode 100644 index 1d9bc1add664..000000000000 --- a/mobile/android/chrome/tests/browser_addons_locales.js +++ /dev/null @@ -1,64 +0,0 @@ -var localeList = serverRoot + "locales_list.sjs"; -var PREF_LOCALE_LIST = "extensions.getLocales.get.url"; - -Components.utils.import("resource://gre/modules/Services.jsm"); -Components.utils.import("resource://gre/modules/LocaleRepository.jsm"); -Components.utils.import("resource://gre/modules/AddonManager.jsm"); - -function test() { - waitForExplicitFinish(); - runNextTest(); -} - -function end_test() { - Services.prefs.clearUserPref(PREF_LOCALE_LIST); -} - -registerCleanupFunction(end_test); - -gTests.push({ - addon: null, - desc: "Test the values returned from _getLocalesInAddon", - run: function() { - Services.prefs.setCharPref(PREF_LOCALE_LIST, localeList); - LocaleRepository.getLocales(this.listLoaded.bind(this)); - }, - - listLoaded: function(aLocales) { - is(aLocales.length, 1, "Correct number of locales were found"); - aLocales[0].addon.install.addListener(this); - aLocales[0].addon.install.install(); - }, - - onInstallEnded: function(aInstall, aAddon) { - aInstall.removeListener(this); - this.addon = aAddon; - info("Installed " + aAddon.id); - - try { - ExtensionsView._getLocalesInAddon(aAddon, null); - ok(false, "_getLocalesInAddon should have thrown with a null callback"); - } catch(ex) { - ok(ex, "_getLocalesInAddon requires a callback") - } - - try { - ExtensionsView._getLocalesInAddon(aAddon, "foo"); - ok(false, "_getLocalesInAddons should have thrown without a non-function callback"); - } catch(ex) { - ok(ex, "_getLocalesInAddon requires the callback be a function") - } - - ExtensionsView._getLocalesInAddon(aAddon, this.gotLocales.bind(this)); - }, - - gotLocales: function(aLocales) { - is(aLocales.length, 2, "Correct number of locales were found"); - ok(aLocales.indexOf("te-st") > -1, "te-st locale found"); - ok(aLocales.indexOf("te-st-a") > -1, "te-st-a locale found"); - - // locales can't be restartless yet, so we can't really test the uninstall code - this.addon.install.cancel(); - runNextTest(); - } -}); diff --git a/mobile/android/chrome/tests/browser_appmenu.js b/mobile/android/chrome/tests/browser_appmenu.js deleted file mode 100644 index 972b0ba0d817..000000000000 --- a/mobile/android/chrome/tests/browser_appmenu.js +++ /dev/null @@ -1,139 +0,0 @@ -let gTests = []; -let gCurrentTest = null; -let Panels = [AllPagesList, HistoryList, BookmarkList]; - -let removedForTestButtons = []; - -function test() { - waitForExplicitFinish(); - - // Make sure we start the test with less than a full menu - let menu = document.getElementById("appmenu"); - while (menu.children.length > 5) - removedForTestButtons.push(menu.removeChild(menu.lastChild)); - - setTimeout(runNextTest, 200); -} - -//------------------------------------------------------------------------------ -// Iterating tests by shifting test out one by one as runNextTest is called. -function runNextTest() { - // Run the next test until all tests completed - if (gTests.length > 0) { - gCurrentTest = gTests.shift(); - info(gCurrentTest.desc); - gCurrentTest.run(); - } else { - // Add back any removed buttons - let menu = document.getElementById("appmenu"); - removedForTestButtons.forEach(function(aButton) { - menu.appendChild(aButton); - }); - - // Close the awesome panel just in case - AwesomeScreen.activePanel = null; - finish(); - } -} - -gTests.push({ -// This test will keep adding buttons and checking the result until there are a -// total of 9 buttons, then it will (one at a time) hide 3 items and check the -// result again. - - desc: "Test for showing the application menu", - newButtons: [], - hidden: 0, - - run: function() { - addEventListener("PopupChanged", gCurrentTest.popupOpened, false) - CommandUpdater.doCommand("cmd_menu"); - }, - - addButton: function() { - info("Adding a new button\n"); - let menu = document.getElementById("appmenu"); - let newButton = menu.children[0].cloneNode(true); - menu.appendChild(newButton); - gCurrentTest.newButtons.push(newButton); - }, - - popupOpened: function() { - removeEventListener("PopupChanged", gCurrentTest.popupOpened, false); - let menu = document.getElementById("appmenu"); - ok(!menu.hidden, "App menu is shown"); - - let more = document.getElementById("appmenu-more-button"); - if (menu.children.length > 6) { - ok(!!more, "More button is shown"); - addEventListener("PopupChanged", gCurrentTest.moreShown, false); - more.click(); - } else { - ok(!more, "More button is hidden"); - addEventListener("PopupChanged", gCurrentTest.popupClosed, false); - EventUtils.synthesizeKey("VK_ESCAPE", {}, window); - } - }, - - popupClosed: function() { - removeEventListener("PopupChanged", gCurrentTest.popupClosed, false); - let menu = document.getElementById("appmenu"); - ok(document.getElementById("appmenu").hidden, "Esc hides menus"); - if (menu.children.length < 9) { - gCurrentTest.addButton(); - gCurrentTest.run(); - } else { - menu.children[gCurrentTest.hidden].hidden = true; - gCurrentTest.hidden++; - addEventListener("PopupChanged", gCurrentTest.menuitemHidden, false) - CommandUpdater.doCommand("cmd_menu"); - } - }, - - moreShown: function(aEvent) { - // AppMenu hiding - if (!aEvent.detail) - return; - - let menu = document.getElementById("appmenu"); - ok(document.getElementById("appmenu").hidden, "Clicking more button hides menu"); - - removeEventListener("PopupChanged", gCurrentTest.moreShown, false); - let listbox = document.getElementById("appmenu-overflow-commands"); - is(listbox.childNodes.length, (menu.childNodes.length - 5), "Menu popup only shows overflow children"); - - addEventListener("PopupChanged", gCurrentTest.popupClosed, false); - EventUtils.synthesizeKey("VK_ESCAPE", {}, window); - }, - - menuitemHidden: function() { - removeEventListener("PopupChanged", gCurrentTest.menuitemHidden, false); - let menu = document.getElementById("appmenu"); - ok(!document.getElementById("appmenu").hidden, "App menu is shown"); - - let more = document.getElementById("appmenu-more-button"); - if (menu.children.length - gCurrentTest.hidden > 6) { - ok(more, "More button is shown"); - addEventListener("PopupChanged", gCurrentTest.popupClosed, false); - } else { - ok(!more, "More button is hidden"); - addEventListener("PopupChanged", gCurrentTest.popupClosedAgain, false); - } - EventUtils.synthesizeKey("VK_ESCAPE", {}, window); - }, - - popupClosedAgain: function() { - removeEventListener("PopupChanged", gCurrentTest.popupClosedAgain, false) - let menu = document.getElementById("appmenu"); - while (gCurrentTest.hidden > 0) { - gCurrentTest.hidden--; - menu.children[gCurrentTest.hidden].hidden = false; - } - - gCurrentTest.newButtons.forEach(function(aButton) { - menu.removeChild(aButton); - }); - - runNextTest(); - } -}); diff --git a/mobile/android/chrome/tests/browser_autocomplete.html b/mobile/android/chrome/tests/browser_autocomplete.html deleted file mode 100644 index 93d424fa627e..000000000000 --- a/mobile/android/chrome/tests/browser_autocomplete.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - -

    - - - - - - - - - - - - -

    - - - - - - -

    - - - diff --git a/mobile/android/chrome/tests/browser_autocomplete.js b/mobile/android/chrome/tests/browser_autocomplete.js deleted file mode 100644 index 5649946722a9..000000000000 --- a/mobile/android/chrome/tests/browser_autocomplete.js +++ /dev/null @@ -1,184 +0,0 @@ -let testURL = chromeRoot + "browser_autocomplete.html"; -messageManager.loadFrameScript(chromeRoot + "remote_autocomplete.js", true); - -let newTab = null; - -// A queue to order the tests and a handle for each test -var gTests = []; -var gCurrentTest = null; - -function test() { - // This test is async - waitForExplicitFinish(); - - // Ensure the form helper is initialized - try { - FormHelperUI.enabled; - } - catch(e) { - FormHelperUI.init(); - } - - // Need to wait until the page is loaded - messageManager.addMessageListener("pageshow", function(aMessage) { - if (newTab && newTab.browser.currentURI.spec != "about:blank") { - messageManager.removeMessageListener(aMessage.name, arguments.callee); - BrowserUI.closeAutoComplete(true); - setTimeout(runNextTest, 0); - } - }); - - newTab = Browser.addTab(testURL, true); -} - - -//------------------------------------------------------------------------------ -// Iterating tests by shifting test out one by one as runNextTest is called. -function runNextTest() { - // Run the next test until all tests completed - if (gTests.length > 0) { - gCurrentTest = gTests.shift(); - info(gCurrentTest.desc); - gCurrentTest.run(); - } - else { - // Cleanup. All tests are completed at this point - try { - // Add any cleanup code here - - // Close our tab when finished - Browser.closeTab(newTab); - } - finally { - // We must finialize the tests - finish(); - } - } -} - -function waitForAutocomplete(aCallback) { - window.addEventListener("contentpopupshown", function(aEvent) { - window.removeEventListener(aEvent.type, arguments.callee, false); - setTimeout(function() { - aCallback(FormHelperUI._currentElement.list); - }, 0); - }, false); -}; - -let data = [ - { label: "foo", value: "foo" }, - { label: "Somewhat bar", value: "bar" }, - { label: "foobar", value: "_" } -]; - -//------------------------------------------------------------------------------ -// Case: Click on a datalist element and show suggestions -gTests.push({ - desc: "Click on a datalist element and show suggestions", - - run: function() { - waitForAutocomplete(gCurrentTest.checkData); - AsyncTests.waitFor("TestRemoteAutocomplete:Click", - { id: "input-datalist-1" }, function(json) {}); - }, - - // Check that the data returned by the autocomplete handler on the content - // side is correct - checkData: function(aOptions) { - for (let i = 0; i < aOptions.length; i++) { - let option = aOptions[i]; - let valid = data[i]; - - is(option.label, valid.label, "Label should be equal (" + option.label + ", " + valid.label +")"); - is(option.value, valid.value, "Value should be equal (" + option.value + ", " + valid.value +")"); - } - - // Wait until suggestions box has been popupated - waitFor(gCurrentTest.checkUI, function() { - let suggestionsBox = document.getElementById("form-helper-suggestions"); - return suggestionsBox.childNodes.length; - }); - }, - - // Check that the UI reflect the specificity of the data - checkUI: function() { - let suggestionsBox = document.getElementById("form-helper-suggestions"); - let suggestions = suggestionsBox.childNodes; - - for (let i = 0; i < suggestions.length; i++) { - let suggestion = suggestions[i]; - let valid = data[i]; - let label = suggestion.getAttribute("value"); - let value = suggestion.getAttribute("data"); - - is(label, valid.label, "Label should be equal (" + label + ", " + valid.label +")"); - is(value, valid.value, "Value should be equal (" + value + ", " + valid.value +")"); - } - - gCurrentTest.checkUIClick(0); - }, - - // Ensure that clicking on a given datalist element set the right value in - // the input box - checkUIClick: function(aIndex) { - let suggestionsBox = document.getElementById("form-helper-suggestions"); - - let suggestion = suggestionsBox.childNodes[aIndex]; - if (!suggestion) { - gCurrentTest.finish(); - return; - } - - // Use the form helper autocompletion helper - FormHelperUI.doAutoComplete(suggestion); - - AsyncTests.waitFor("TestRemoteAutocomplete:Check", { id: "input-datalist-1" }, function(json) { - is(json.result, suggestion.getAttribute("data"), "The target input value should be set to " + data); - gCurrentTest.checkUIClick(aIndex + 1); - }); - }, - - finish: function() { - // Close the form assistant - FormHelperUI.hide(); - - - AsyncTests.waitFor("TestRemoteAutocomplete:Reset", { id: "input-datalist-1" }, function(json) { - runNextTest(); - }); - } -}); - -//------------------------------------------------------------------------------ -// Case: Check arrows visibility -gTests.push({ - desc: "Check arrows visibility", - - run: function() { - let popup = document.getElementById("form-helper-suggestions-container"); - popup.addEventListener("contentpopupshown", function(aEvent) { - aEvent.target.removeEventListener(aEvent.type, arguments.callee, false); - waitFor(gCurrentTest.checkNoArrows, function() { - return FormHelperUI._open; - }); - }, false); - - AsyncTests.waitFor("TestRemoteAutocomplete:Click", - { id: "input-datalist-3" }, function(json) {}); - }, - - checkNoArrows: function() { - let scrollbox = document.getElementById("form-helper-suggestions"); - todo_is(scrollbox._scrollButtonUp.collapsed, true, "Left button should be collapsed"); - todo_is(scrollbox._scrollButtonDown.collapsed, true, "Right button should be collapsed"); - gCurrentTest.finish(); - }, - - finish: function() { - // Close the form assistant - FormHelperUI.hide(); - - runNextTest(); - } -}); - diff --git a/mobile/android/chrome/tests/browser_autocompletesearch.js b/mobile/android/chrome/tests/browser_autocompletesearch.js deleted file mode 100644 index e7129eafe8ec..000000000000 --- a/mobile/android/chrome/tests/browser_autocompletesearch.js +++ /dev/null @@ -1,108 +0,0 @@ -Components.utils.import("resource://gre/modules/Services.jsm"); - -let match= [ - ["http://example.com/a", "A", "favicon", "http://example.com/a/favicon.png"], - ["http://example.com/b", "B", "favicon", "http://example.com/b/favicon.png"], - ["http://example.com/c", "C", "favicon", "http://example.com/c/favicon.png"], - ["http://example.com/d", "D", "bookmark", "http://example.com/d/favicon.png"], - ["http://example.com/e", "E", "boolmark", "http://example.com/e/favicon.png"] -]; - -var gAutocomplete = null; -var gProfileDir = null; - -function test() { - waitForExplicitFinish(); - - gProfileDir = Services.dirsvc.get("ProfD", Ci.nsIFile); - - // First we need to remove the existing cache file so we can control the state of the service - let oldCacheFile = gProfileDir.clone(); - oldCacheFile.append("autocomplete.json"); - if (oldCacheFile.exists()) - oldCacheFile.remove(true); - - // Since we removed the cache file, we know the service will need to write out a new - // file. We use that as a trigger to move forward. - Services.obs.addObserver(function (aSubject, aTopic, aData) { - Services.obs.removeObserver(arguments.callee, aTopic, false); - saveMockCache(); - }, "browser:cache-session-history-write-complete", false); - - // This might trigger an init or it may have already happened. That's why we need - // to do some work to control the state. - gAutocomplete = Cc["@mozilla.org/autocomplete/search;1?name=history"].getService(Ci.nsIAutoCompleteSearch); - - // Trigger the new cache to be written out, since the existing was removed - Services.obs.notifyObservers(null, "browser:cache-session-history-reload", ""); -} - -function saveMockCache() { - // Now we write our own mock data cache into the profile - let oldCacheFile = gProfileDir.clone(); - oldCacheFile.append("autocomplete.json"); - if (oldCacheFile.exists()) - oldCacheFile.remove(true); - - let mockCachePath = gTestPath; - info("mock path: " + mockCachePath); - let mockCacheURI = getResolvedURI(mockCachePath); - info("mock URI: " + mockCacheURI.spec); - if (mockCacheURI instanceof Ci.nsIJARURI) { - // Android tests are stored in a JAR file, so we need to extract the mock_autocomplete.json file - info("jar file: " + mockCacheURI.JARFile.spec); - let zReader = Cc["@mozilla.org/libjar/zip-reader;1"].createInstance(Ci.nsIZipReader); - let fileHandler = Cc["@mozilla.org/network/protocol;1?name=file"].getService(Ci.nsIFileProtocolHandler); - let fileName = fileHandler.getFileFromURLSpec(mockCacheURI.JARFile.spec); - zReader.open(fileName); - - let extract = mockCacheURI.spec.split("!")[1]; - extract = extract.substring(1, extract.lastIndexOf("/") + 1); - extract += "mock_autocomplete.json"; - info("extract path: " + extract); - let target = gProfileDir.clone(); - target.append("autocomplete.json"); - info("target path: " + target.path); - zReader.extract(extract, target); - } else { - // Tests are run from a folder, so we can just copy the mock_autocomplete.json file - let mockCacheFile = getChromeDir(mockCacheURI); - info("mock file: " + mockCacheFile.path); - mockCacheFile.append("mock_autocomplete.json"); - mockCacheFile.copyToFollowingLinks(gProfileDir, "autocomplete.json"); - } - - // Listen for when the mock cache has been loaded - Services.obs.addObserver(function (aSubject, aTopic, aData) { - Services.obs.removeObserver(arguments.callee, aTopic, false); - runTest(); - }, "browser:cache-session-history-read-complete", false); - - // Trigger the new mock cache to be loaded - Services.obs.notifyObservers(null, "browser:cache-session-history-reload", ""); -} - -function runTest() { - let cacheFile = gProfileDir.clone(); - cacheFile.append("autocomplete.json"); - ok(cacheFile.exists(), "Mock autocomplete JSON cache file exists"); - - // Compare the mock data, which should be used now that we loaded it into the service - gAutocomplete.startSearch("", "", null, { - onSearchResult: function(search, result) { - is(result.matchCount, 5, "matchCount is correct"); - - for (let i=0; i<5; i++) { - is(result.getValueAt(i), match[i][0], "value matches"); - is(result.getCommentAt(i), match[i][1], "comment matches"); - is(result.getStyleAt(i), match[i][2], "style matches"); - is(result.getImageAt(i), match[i][3], "image matches"); - } - - if (cacheFile.exists()) - cacheFile.remove(true); - - finish(); - } - }); -} diff --git a/mobile/android/chrome/tests/browser_awesomescreen.js b/mobile/android/chrome/tests/browser_awesomescreen.js deleted file mode 100644 index 6283881b1dfc..000000000000 --- a/mobile/android/chrome/tests/browser_awesomescreen.js +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Bug 436069 - Fennec browser-chrome tests to verify correct navigation into the - * differents part of the awesome panel - */ - -let testURL_01 = chromeRoot + "browser_blank_01.html"; - -let gTests = []; -let gCurrentTest = null; -let Panels = [AllPagesList, HistoryList, BookmarkList]; - -function test() { - // The "runNextTest" approach is async, so we need to call "waitForExplicitFinish()" - // We call "finish()" when the tests are finished - waitForExplicitFinish(); - - // Start the tests - setTimeout(runNextTest, 200); -} - -//------------------------------------------------------------------------------ -// Iterating tests by shifting test out one by one as runNextTest is called. -function runNextTest() { - // Run the next test until all tests completed - if (gTests.length > 0) { - gCurrentTest = gTests.shift(); - info(gCurrentTest.desc); - - // Ensure all tests start with hidden awesome screen - AwesomeScreen.activePanel = null; - - gCurrentTest.run(); - } - else { - // Close the awesome panel just in case - AwesomeScreen.activePanel = null; - finish(); - } -} - -function waitForNavigationPanel(aCallback, aWaitForHide) { - let evt = aWaitForHide ? "NavigationPanelHidden" : "NavigationPanelShown"; - info("waitFor " + evt + "(" + Components.stack.caller + ")"); - window.addEventListener(evt, function(aEvent) { - info("receive " + evt); - window.removeEventListener(aEvent.type, arguments.callee, false); - setTimeout(aCallback, 0); - }, false); -} - -//------------------------------------------------------------------------------ -// Case: Test awesome bar collapsed state -gTests.push({ - desc: "Test awesome bar collapsed state", - - run: function() { - waitForNavigationPanel(gCurrentTest.onPopupShown); - AllPagesList.doCommand(); - }, - - onPopupShown: function() { - is(AwesomeScreen.activePanel, AllPagesList, "AllPagesList should be visible"); - ok(!BrowserUI._edit.collapsed, "The urlbar edit element is visible"); - ok(BrowserUI._title.collapsed, "The urlbar title element is not visible"); - - waitForNavigationPanel(gCurrentTest.onPopupHidden, true); - - EventUtils.synthesizeKey("VK_ESCAPE", {type: "keypress"}, window); - }, - - onPopupHidden: function() { - is(AwesomeScreen.activePanel, null, "AllPagesList should be dismissed"); - ok(BrowserUI._edit.collapsed, "The urlbar edit element is not visible"); - ok(!BrowserUI._title.collapsed, "The urlbar title element is visible"); - - runNextTest(); - } -}); - - -//------------------------------------------------------------------------------ -// Case: Test typing a character should dismiss the awesome header -gTests.push({ - desc: "Test typing a character should dismiss the awesome header", - - run: function() { - waitForNavigationPanel(gCurrentTest.onPopupReady); - AllPagesList.doCommand(); - }, - - onPopupReady: function() { - is(AwesomeScreen.activePanel == AllPagesList, true, "AllPagesList should be visible"); - - let awesomeHeader = document.getElementById("awesome-header"); - is(awesomeHeader.hidden, false, "Awesome header should be visible"); - - BrowserUI._edit.addEventListener("onsearchbegin", function(aEvent) { - if (BrowserUI._edit.value == "") - return; - - BrowserUI._edit.removeEventListener(aEvent.type, arguments.callee, true); - let awesomeHeader = document.getElementById("awesome-header"); - is(awesomeHeader.hidden, true, "Awesome header should be hidden"); - gCurrentTest.onKeyPress(); - }, true); - EventUtils.synthesizeKey("A", {}, window); - }, - - onKeyPress: function(aKey, aHidden) { - waitForNavigationPanel(function() { - let awesomeHeader = document.getElementById("awesome-header"); - is(awesomeHeader.hidden, false, "Awesome header should be visible"); - runNextTest(); - }, true); - - EventUtils.synthesizeKey("VK_ESCAPE", {type: "keypress"}, window); - } -}); - -//------------------------------------------------------------------------------ -// Case: Test typing a character should open the awesome bar -gTests.push({ - desc: "Test typing a character should open the All Pages List", - - run: function() { - waitForNavigationPanel(gCurrentTest.onPopupReady); - BookmarkList.doCommand(); - }, - - onPopupReady: function() { - BrowserUI._edit.addEventListener("onsearchbegin", function(aEvent) { - BrowserUI._edit.removeEventListener(aEvent.type, arguments.callee, false); - gCurrentTest.onSearchBegin(); - }, false); - EventUtils.synthesizeKey("I", {}, window); - }, - - onSearchBegin: function() { - let awesomeHeader = document.getElementById("awesome-header"); - is(awesomeHeader.hidden, true, "Awesome header should be hidden"); - is(AwesomeScreen.activePanel == AllPagesList, true, "AllPagesList should be opened on a keydown"); - is(BrowserUI._edit.readOnly, false, "urlbar should not be readonly after an input"); - - waitForNavigationPanel(gCurrentTest.onPopupHidden, true); - EventUtils.synthesizeKey("VK_ESCAPE", {type: "keypress"}, window); - }, - - onPopupHidden: function() { - is(AwesomeScreen.activePanel == null, true, "VK_ESCAPE should have dismissed the awesome panel"); - runNextTest(); - } -}); - -//------------------------------------------------------------------------------ -// Case: Test opening the awesome panel and checking the urlbar readonly state -gTests.push({ - desc: "Test opening the awesome panel and checking the urlbar readonly state", - - run: function() { - is(BrowserUI._edit.readOnly, true, "urlbar input textbox should be readonly"); - - waitForNavigationPanel(gCurrentTest.onPopupReady); - AllPagesList.doCommand(); - }, - - onPopupReady: function() { - is(Elements.urlbarState.getAttribute("mode"), "edit", "bcast_urlbarState mode attribute should be equal to 'edit'"); - - let edit = BrowserUI._edit; - is(edit.readOnly, BrowserUI._isKeyboardFullscreen(), "urlbar input textbox is readonly if keyboard is fullscreen, editable otherwise"); - - let urlString = BrowserUI.getDisplayURI(Browser.selectedBrowser); - if (Util.isURLEmpty(urlString)) - urlString = ""; - - let firstPanel = true; - Panels.forEach(function(aPanel) { - aPanel.doCommand(); - is(AwesomeScreen.activePanel, aPanel, "The panel " + aPanel.panel.id + " should be selected"); - if (firstPanel) { - // First panel will have selected text, if we are in portrait - is(edit.readOnly, BrowserUI._isKeyboardFullscreen(), "urlbar input textbox is readonly if keyboard is fullscreen, editable otherwise"); - } else { - is(edit.readOnly, true, "urlbar input textbox be readonly if not the first panel"); - } - edit.click(); - is(edit.readOnly, false, "urlbar input textbox should not be readonly after a click, in both landscape and portrait"); - is(edit.value, urlString, "urlbar value should be equal to the page uri"); - - firstPanel = false; - }); - - setTimeout(function() { - runNextTest(); - }, 0); - } -}); - -//------------------------------------------------------------------------------ -// Case: Test opening the awesome panel and checking the urlbar selection -gTests.push({ - desc: "Test opening the awesome panel and checking the urlbar selection", - - run: function() { - BrowserUI.closeAutoComplete(true); - this.currentTab = BrowserUI.newTab(testURL_01); - - // Need to wait until the page is loaded - messageManager.addMessageListener("pageshow", - function(aMessage) { - if (gCurrentTest.currentTab.browser.currentURI.spec != "about:blank") { - messageManager.removeMessageListener(aMessage.name, arguments.callee); - setTimeout(gCurrentTest.onPageReady, 0); - } - }); - }, - - onPageReady: function() { - waitForNavigationPanel(gCurrentTest.onPopupReady); - - AllPagesList.doCommand(); - }, - - onPopupReady: function() { - let edit = BrowserUI._edit; - - let firstPanel = true; - Panels.forEach(function(aPanel) { - aPanel.doCommand(); - if (firstPanel && !BrowserUI._isKeyboardFullscreen()) { - // First panel will have selected text, if we are in portrait - ok(edit.selectionStart == 0 && edit.selectionEnd == edit.textLength, "[case 1] urlbar text should be selected on a simple show"); - edit.click(); - // The click is not sync enough for this to work - todo(edit.selectionStart == edit.selectionEnd, "[case 1] urlbar text should not be selected on a click"); - } else { - ok(edit.selectionStart == edit.selectionEnd, "[case 2] urlbar text should not be selected on a simple show"); - edit.click(); - ok(edit.selectionStart == 0 && edit.selectionEnd == edit.textLength, "[case 2] urlbar text should be selected on a click"); - } - firstPanel = false; - }); - - // We are disabling it early, otherwise calling edit.click(); quickly made input.js though this is a double click (sigh) - let oldDoubleClickSelectsAll = Services.prefs.getBoolPref("browser.urlbar.doubleClickSelectsAll"); - Services.prefs.setBoolPref("browser.urlbar.doubleClickSelectsAll", false); - - let oldClickSelectsAll = edit.clickSelectsAll; - edit.clickSelectsAll = false; - firstPanel = true; - Panels.forEach(function(aPanel) { - aPanel.doCommand(); - if (firstPanel && !BrowserUI._isKeyboardFullscreen()) { - // First panel will have selected text, if we are in portrait - ok(edit.selectionStart == 0 && edit.selectionEnd == edit.textLength, "[case 1] urlbar text should be selected on a simple show"); - edit.click(); - // The click is not sync enough for this to work - todo(edit.selectionStart == edit.selectionEnd, "[case 1] urlbar text should not be selected on a click"); - } else { - ok(edit.selectionStart == edit.selectionEnd, "[case 2] urlbar text should not be selected on a simple show"); - edit.click(); - ok(edit.selectionStart == edit.selectionEnd, "[case 2] urlbar text should not be selected on a click"); - } - - firstPanel = false; - }); - - Panels.forEach(function(aPanel) { - aPanel.doCommand(); - ok(edit.selectionStart == edit.selectionEnd, "urlbar text should not be selected on a simple show"); - edit.click(); - edit.click(); - ok(edit.selectionStart == edit.selectionEnd, "urlbar text should not be selected on a double click"); - }); - - Services.prefs.setBoolPref("browser.urlbar.doubleClickSelectsAll", oldDoubleClickSelectsAll); - - Panels.forEach(function(aPanel) { - aPanel.doCommand(); - ok(edit.selectionStart == edit.selectionEnd, "urlbar text should not be selected on a simple show"); - edit.click(); - edit.click(); - ok(edit.selectionStart == 0 && edit.selectionEnd == edit.textLength, "urlbar text should be selected on a double click"); - }); - - edit.clickSelectsAll = oldClickSelectsAll; - - // Ensure the tab is well closed before doing the rest of the code, otherwise - // this cause some bugs with the composition events - let tabCount = Browser.tabs.length; - Browser.closeTab(gCurrentTest.currentTab, { forceClose: true }); - waitFor(runNextTest, function() Browser.tabs.length == tabCount - 1); - } -}); - -// Case: Test context clicks on awesome panel -gTests.push({ - desc: "Test context clicks on awesome panel", - - _panelIndex : 0, - _contextOpts : [ - ["link-openable", "link-shareable"], - ["link-openable", "link-shareable"], - ["edit-bookmark", "link-shareable", "link-openable"], - ], - - clearContextTypes: function clearContextTypes() { - if (ContextHelper.popupState) - ContextHelper.hide(); - }, - - checkContextTypes: function checkContextTypes(aTypes) { - let commandlist = document.getElementById("context-commands"); - - for (let i=0; i -1) { - // command should be visible - if(command.hidden == true) - return false; - } else { - if(command.hidden == false) - return false; - } - } - return true; - }, - - run: function() { - waitForNavigationPanel(gCurrentTest.onPopupReady); - AllPagesList.doCommand(); - }, - - onPopupReady: function() { - let self = this; - if(self._panelIndex < Panels.length) { - let panel = Panels[self._panelIndex]; - panel.doCommand(); - - self.clearContextTypes(); - - EventUtils.synthesizeMouse(panel.panel, panel.panel.width / 2, panel.panel.height / 2, { type: "mousedown" }); - setTimeout(function() { - EventUtils.synthesizeMouse(panel.panel, panel.panel.width / 2, panel.panel.height / 2, { type: "mouseup" }); - ok(self.checkContextTypes(self._contextOpts[self._panelIndex]), "Correct context menu shown for panel"); - self.clearContextTypes(); - - self._panelIndex++; - self.onPopupReady(); - }, 500); - } else { - runNextTest(); - } - } -}); - - -// Case: Test compositionevent -gTests.push({ - desc: "Test sending composition events", - _textValue: null, - get popup() { - delete this.popup; - return this.popup = document.getElementById("popup_autocomplete"); - }, - - get popupHeader() { - delete this.popupHeader; - return this.popupHeader = document.getElementById("awesome-header"); - }, - - get inputField() { - delete this.inputField; - return this.inputField = document.getElementById("urlbar-edit"); - }, - - run: function() { - // Saving value to compare the result before and after the composition event - gCurrentTest._textValue = gCurrentTest.inputField.value; - - window.addEventListener("popupshown", function() { - window.removeEventListener("popupshown", arguments.callee, false); - if (BrowserUI._isKeyboardFullscreen()) - gCurrentTest.inputField.readOnly = false; - setTimeout(gCurrentTest.onPopupReady, 0); - }, false); - AllPagesList.doCommand(); - }, - - _checkState: function() { - ok(gCurrentTest.popup._popupOpen, "AutoComplete popup should be opened"); - is(gCurrentTest.popupHeader.hidden, false, "AutoComplete popup header should be visible"); - is(gCurrentTest.inputField.value, gCurrentTest._textValue, "Value should not have changed"); - }, - - onPopupReady: function() { - gCurrentTest._checkState(); - - window.addEventListener("compositionstart", function() { - window.removeEventListener("compositionstart", arguments.callee, false); - setTimeout(gCurrentTest.onCompositionStart, 0) - }, false); - Browser.windowUtils.sendCompositionEvent("compositionstart", "", ""); - }, - - onCompositionStart: function() { - gCurrentTest._checkState(); - - window.addEventListener("compositionend", function() { - window.removeEventListener("compositionend", arguments.callee, false); - setTimeout(gCurrentTest.onCompositionEnd, 0) - }, false); - Browser.windowUtils.sendCompositionEvent("compositionend", "", ""); - }, - - onCompositionEnd: function() { - /* TODO: This is currently failing (bug 642771) - gCurrentTest._checkState(); - - let isHiddenHeader = function() { - return gCurrentTest.popupHeader.hidden; - } - - // Wait to be sure there the header won't dissapear - // XXX this sucks because it means we'll be stuck 500ms if the test succeed - // but I don't have a better idea about how to do it for now since we don't - // that to happen! - - waitForAndContinue(function() { - gCurrentTest._checkState(); - runNextTest(); - }, isHiddenHeader, Date.now() + 500); - */ - runNextTest(); - } -}); - -// Case: Test context popup dismiss on top of awesome panel -gTests.push({ - desc: "Case: Test context popup dismiss on top of awesome panel", - - run: function() { - waitForNavigationPanel(gCurrentTest.onPopupReady); - AllPagesList.doCommand(); - }, - - onPopupReady: function() { - EventUtils.synthesizeMouse(AllPagesList.panel, AllPagesList.panel.width / 2, - AllPagesList.panel.height / 2, { type: "mousedown" }); - - // Simulate a long tap - setTimeout(function(self) { - EventUtils.synthesizeMouse(AllPagesList.panel, AllPagesList.panel.width / 2, - AllPagesList.panel.height / 2, { type: "mouseup" }); - - let contextContainer = document.getElementById("context-container"); - - ok(!AllPagesList.panel.hidden, "The context popup is still visible after long tap"); - ok(!contextContainer.hidden, "The context popup is visible after long tap"); - - EventUtils.synthesizeMouse(AllPagesList.panel, 0, 0, {}); - - ok(contextContainer.hidden, "The context popup is not visible after tap"); - ok(!AllPagesList.panel.hidden, "The awesome panel is still visible after popup is dismissed"); - - AwesomeScreen.activePanel = null; - runNextTest(); - }, 500, this); - } -}); diff --git a/mobile/android/chrome/tests/browser_blank_01.html b/mobile/android/chrome/tests/browser_blank_01.html deleted file mode 100644 index 8fd14cc1bebd..000000000000 --- a/mobile/android/chrome/tests/browser_blank_01.html +++ /dev/null @@ -1,6 +0,0 @@ - -Browser Blank Page 01 - -

    Browser Blank Page 01

    - - diff --git a/mobile/android/chrome/tests/browser_blank_02.html b/mobile/android/chrome/tests/browser_blank_02.html deleted file mode 100644 index 61d6b1f61acc..000000000000 --- a/mobile/android/chrome/tests/browser_blank_02.html +++ /dev/null @@ -1,7 +0,0 @@ - -Browser Blank Page 02 - - -

    Browser Blank Page 02

    - - diff --git a/mobile/android/chrome/tests/browser_blank_03.html b/mobile/android/chrome/tests/browser_blank_03.html deleted file mode 100644 index 57b38163dd30..000000000000 --- a/mobile/android/chrome/tests/browser_blank_03.html +++ /dev/null @@ -1,6 +0,0 @@ - -Browser Blank Page 03 - -

    Browser Blank Page 03

    - - diff --git a/mobile/android/chrome/tests/browser_bookmarks.js b/mobile/android/chrome/tests/browser_bookmarks.js deleted file mode 100644 index f71b597ad197..000000000000 --- a/mobile/android/chrome/tests/browser_bookmarks.js +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Bug 486490 - Fennec browser-chrome tests to verify correct implementation of chrome - * code in mobile/chrome/content in terms of integration with Places - * component, specifically for bookmark management. - */ - -var testURL_01 = chromeRoot + "browser_blank_01.html"; -var testURL_02 = chromeRoot + "browser_blank_02.html"; - -// A queue to order the tests and a handle for each test -var gTests = []; -var gCurrentTest = null; - -//------------------------------------------------------------------------------ -// Entry point (must be named "test") -function test() { - // The "runNextTest" approach is async, so we need to call "waitForExplicitFinish()" - // We call "finish()" when the tests are finished - waitForExplicitFinish(); - - // Start the tests - runNextTest(); -} - -//------------------------------------------------------------------------------ -// Iterating tests by shifting test out one by one as runNextTest is called. -function runNextTest() { - // Run the next test until all tests completed - if (gTests.length > 0) { - gCurrentTest = gTests.shift(); - info(gCurrentTest.desc); - gCurrentTest.run(); - } - else { - // Cleanup. All tests are completed at this point - try { - PlacesUtils.bookmarks.removeFolderChildren(BookmarkList.panel.mobileRoot); - } - finally { - // We must finialize the tests - finish(); - } - } -} - -function waitForPageShow(aCallback) { - messageManager.addMessageListener("pageshow", function(aMessage) { - if (gCurrentTest._currentTab.browser.currentURI.spec != "about:blank") { - messageManager.removeMessageListener(aMessage.name, arguments.callee); - setTimeout(aCallback, 0); - } - }); -} - -function waitForNavigationPanel(aCallback, aWaitForHide) { - let evt = aWaitForHide ? "NavigationPanelHidden" : "NavigationPanelShown"; - info("waitFor " + evt + "(" + Components.stack.caller + ")"); - window.addEventListener(evt, function(aEvent) { - info("receive " + evt); - window.removeEventListener(aEvent.type, arguments.callee, false); - setTimeout(aCallback, 0); - }, false); -} - -//------------------------------------------------------------------------------ -// Case: Test adding a bookmark with the Star button -gTests.push({ - desc: "Test adding a bookmark with the Star button", - _currentTab: null, - - run: function() { - this._currentTab = Browser.addTab(testURL_01, true); - - // Need to wait until the page is loaded - waitForPageShow(gCurrentTest.onPageReady); - }, - - onPageReady: function() { - let starbutton = document.getElementById("tool-star"); - starbutton.click(); - window.addEventListener("BookmarkCreated", function(aEvent) { - window.removeEventListener(aEvent.type, arguments.callee, false); - let bookmark = PlacesUtils.getMostRecentBookmarkForURI(makeURI(testURL_01)); - ok(bookmark != -1, testURL_01 + " should be added."); - - Browser.closeTab(gCurrentTest._currentTab); - - runNextTest(); - }, false); - } -}); - -//------------------------------------------------------------------------------ -// Case: Test clicking on a bookmark loads the web page -gTests.push({ - desc: "Test clicking on a bookmark loads the web page", - _currentTab: null, - - run: function() { - BrowserUI.closeAutoComplete(true); - this._currentTab = Browser.addTab(testURL_02, true); - - // Need to wait until the page is loaded - waitForPageShow(gCurrentTest.onPageReady); - }, - - onPageReady: function() { - // Wait for the bookmarks to load, then do the test - waitForNavigationPanel(gCurrentTest.onBookmarksReady); - BrowserUI.doCommand("cmd_bookmarks"); - }, - - onBookmarksReady: function() { - let bookmarkitem = document.getAnonymousElementByAttribute(BookmarkList.panel, "uri", testURL_01); - bookmarkitem.control.scrollBoxObject.ensureElementIsVisible(bookmarkitem); - - isnot(bookmarkitem, null, "Found the bookmark"); - is(bookmarkitem.getAttribute("uri"), testURL_01, "Bookmark has the right URL via attribute"); - is(bookmarkitem.spec, testURL_01, "Bookmark has the right URL via property"); - - // Create a listener for the opening bookmark - waitForPageShow(function() { - if (Services.appinfo.OS == "Android") - todo_is(gCurrentTest._currentTab.browser.currentURI.spec, testURL_01, "Opened the right bookmark"); - else - is(gCurrentTest._currentTab.browser.currentURI.spec, testURL_01, "Opened the right bookmark"); - - Browser.closeTab(gCurrentTest._currentTab); - - runNextTest(); - }); - - EventUtils.synthesizeMouse(bookmarkitem, bookmarkitem.width / 2, bookmarkitem.height / 2, {}); - } -}); - -//------------------------------------------------------------------------------ -// Case: Test editing URI of existing bookmark -gTests.push({ - desc: "Test editing URI of existing bookmark", - - run: function() { - // Wait for the bookmarks to load, then do the test - waitForNavigationPanel(gCurrentTest.onBookmarksReady); - BrowserUI.doCommand("cmd_bookmarks"); - }, - - onBookmarksReady: function() { - // Go into edit mode - let bookmark = BookmarkList.panel.items[0]; - bookmark.startEditing(); - - waitFor(gCurrentTest.onEditorReady, function() { return bookmark.isEditing == true; }); - }, - - onEditorReady: function() { - let bookmarkitem = document.getAnonymousElementByAttribute(BookmarkList.panel, "uri", testURL_01); - EventUtils.synthesizeMouse(bookmarkitem, bookmarkitem.width / 2, bookmarkitem.height / 2, {}); - - let uritextbox = document.getAnonymousElementByAttribute(bookmarkitem, "anonid", "uri"); - uritextbox.value = testURL_02; - - let donebutton = document.getAnonymousElementByAttribute(bookmarkitem, "anonid", "done-button"); - donebutton.click(); - - let bookmark = PlacesUtils.getMostRecentBookmarkForURI(makeURI(testURL_01)); - is(bookmark, -1, testURL_01 + " should no longer in bookmark"); - bookmark = PlacesUtils.getMostRecentBookmarkForURI(makeURI(testURL_02)); - isnot(bookmark, -1, testURL_02 + " is in bookmark"); - - AwesomeScreen.activePanel = null; - - runNextTest(); - } -}); - -//------------------------------------------------------------------------------ -// Case: Test editing title of existing bookmark -gTests.push({ - desc: "Test editing title of existing bookmark", - - run: function() { - // Wait for the bookmarks to load, then do the test - waitForNavigationPanel(gCurrentTest.onBookmarksReady); - BrowserUI.doCommand("cmd_bookmarks"); - }, - - onBookmarksReady: function() { - // Go into edit mode - let bookmark = BookmarkList.panel.items[0]; - bookmark.startEditing(); - - waitFor(gCurrentTest.onEditorReady, function() { return bookmark.isEditing == true; }); - }, - - onEditorReady: function() { - let bookmark = PlacesUtils.getMostRecentBookmarkForURI(makeURI(testURL_02)); - is(PlacesUtils.bookmarks.getItemTitle(bookmark), "Browser Blank Page 01", "Title remains the same."); - - let bookmarkitem = document.getAnonymousElementByAttribute(BookmarkList.panel, "uri", testURL_02); - EventUtils.synthesizeMouse(bookmarkitem, bookmarkitem.width / 2, bookmarkitem.height / 2, {}); - - let titletextbox = document.getAnonymousElementByAttribute(bookmarkitem, "anonid", "name"); - let newtitle = "Changed Title"; - titletextbox.value = newtitle; - - let donebutton = document.getAnonymousElementByAttribute(bookmarkitem, "anonid", "done-button"); - donebutton.click(); - - isnot(PlacesUtils.getMostRecentBookmarkForURI(makeURI(testURL_02)), -1, testURL_02 + " is still in bookmark."); - is(PlacesUtils.bookmarks.getItemTitle(bookmark), newtitle, "Title is changed."); - - AwesomeScreen.activePanel = null; - - runNextTest(); - } -}); - -//------------------------------------------------------------------------------ -// Case: Test removing existing bookmark -gTests.push({ - desc: "Test removing existing bookmark", - bookmarkitem: null, - - run: function() { - // Wait for the bookmarks to load, then do the test - waitForNavigationPanel(gCurrentTest.onBookmarksReady); - BrowserUI.doCommand("cmd_bookmarks"); - }, - - onBookmarksReady: function() { - // Go into edit mode - let bookmark = BookmarkList.panel.items[0]; - bookmark.startEditing(); - - waitFor(gCurrentTest.onEditorReady, function() { return bookmark.isEditing == true; }); - }, - - onEditorReady: function() { - let bookmark = document.getAnonymousElementByAttribute(BookmarkList.panel, "uri", testURL_02); - bookmark.remove(); - - let bookmark = PlacesUtils.getMostRecentBookmarkForURI(makeURI(testURL_02)); - ok(bookmark == -1, testURL_02 + " should no longer in bookmark"); - bookmark = PlacesUtils.getMostRecentBookmarkForURI(makeURI(testURL_01)); - ok(bookmark == -1, testURL_01 + " should no longer in bookmark"); - - AwesomeScreen.activePanel = null; - - runNextTest(); - } -}); - -//------------------------------------------------------------------------------ -// Case: Test editing title of desktop folder -gTests.push({ - desc: "Test editing title of desktop folder", - bmId: null, - - run: function() { - // Add a bookmark to the desktop area so the desktop folder is displayed - gCurrentTest.bmId = PlacesUtils.bookmarks - .insertBookmark(PlacesUtils.unfiledBookmarksFolderId, - makeURI(testURL_02), - Ci.nsINavBookmarksService.DEFAULT_INDEX, - testURL_02); - - // Wait for the bookmarks to load, then do the test - waitForNavigationPanel(gCurrentTest.onBookmarksReady); - BrowserUI.doCommand("cmd_bookmarks"); - }, - - onBookmarksReady: function() { - // Go into edit mode - let bookmarksPanel = BookmarkList.panel; - let bookmark = bookmarksPanel.items[0]; - bookmark.startEditing(); - - // Is the "desktop" folder showing? - let first = bookmarksPanel._children.firstChild; - is(first.itemId, bookmarksPanel._desktopFolderId, "Desktop folder is showing"); - - // Is the "desktop" folder in edit mode? - is(first.isEditing, false, "Desktop folder is not in edit mode"); - - // Do not allow the "desktop" folder to be editable by tap - EventUtils.synthesizeMouse(first, first.width / 2, first.height / 2, {}); - - // A tap on the "desktop" folder _should_ open the folder, not put it into edit mode. - // So we need to get the first item again. - first = bookmarksPanel._children.firstChild; - - // It should not be the "desktop" folder - isnot(first.itemId, bookmarksPanel._desktopFolderId, "Desktop folder is not showing after mouse click"); - - // But it should be one of the other readonly bookmark roots - isnot(bookmarksPanel._readOnlyFolders.indexOf(parseInt(first.itemId)), -1, "Desktop subfolder is showing after mouse click"); - - PlacesUtils.bookmarks.removeItem(gCurrentTest.bmId); - - AwesomeScreen.activePanel = null; - runNextTest(); - } -}); diff --git a/mobile/android/chrome/tests/browser_bookmarks_star.js b/mobile/android/chrome/tests/browser_bookmarks_star.js deleted file mode 100644 index 3dfac0eb5aec..000000000000 --- a/mobile/android/chrome/tests/browser_bookmarks_star.js +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Bug 486490 - Fennec browser-chrome tests to verify correct implementation of chrome - * code in mobile/chrome/content in terms of integration with Places - * component, specifically for bookmark management. - */ - -let testURL_01 = chromeRoot + "browser_blank_01.html"; -let testURL_02 = chromeRoot + "browser_blank_02.html"; - -function test() { - BookmarkHelper.logging = true; - - // The "runNextTest" approach is async, so we need to call "waitForExplicitFinish()" - // We call "finish()" when the tests are finished - waitForExplicitFinish(); - - // Start the tests - runNextTest(); -} - -registerCleanupFunction(function() { - BookmarkHelper.logging = false; - PlacesUtils.bookmarks.removeFolderChildren(BookmarkList.panel.mobileRoot); -}); - -//------------------------------------------------------------------------------ -// Case: Test appearance and behavior of the bookmark popup -gTests.push({ - desc: "Test appearance and behavior of the bookmark popup", - _currentTab: null, - - run: function() { - this._currentTab = Browser.addTab(testURL_02, true); - - messageManager.addMessageListener("pageshow", - function(aMessage) { - if (gCurrentTest._currentTab.browser.currentURI.spec != "about:blank") { - messageManager.removeMessageListener(aMessage.name, arguments.callee); - - // Wait a bit until Places is initialized - waitFor(gCurrentTest.onPageLoad, function() { - let mobileRoot = PlacesUtils.annotations.getItemsWithAnnotation("mobile/bookmarksRoot", {})[0]; - return mobileRoot; - }); - } - }); - }, - - onPageLoad: function() { - let starbutton = document.getElementById("tool-star"); - starbutton.click(); - - waitFor(gCurrentTest.onPopupReady, function() { return BookmarkPopup.box.hidden == false; }); - }, - - onPopupReady: function() { - // Let's make it disappear again by clicking the star again - let starbutton = document.getElementById("tool-star"); - starbutton.click(); - - waitFor(gCurrentTest.onPopupGone, function() { return BookmarkPopup.box.hidden == true; }); - }, - - onPopupGone: function() { - // Make sure it's hidden again - is(BookmarkPopup.box.hidden, true, "Bookmark popup should be hidden by clicking star"); - - // Let's make it appear again and continue the test - let starbutton = document.getElementById("tool-star"); - starbutton.click(); - - waitFor(gCurrentTest.onPopupReady2, function() { return BookmarkPopup.box.hidden == false; }); - }, - - onPopupReady2: function() { - // Let's make it disappear again by clicking somewhere - let contentarea = document.getElementById("browsers"); - EventUtils.synthesizeMouse(contentarea, contentarea.clientWidth / 2, contentarea.clientHeight / 2, {}); - - waitFor(gCurrentTest.onPopupGone2, function() { return BookmarkPopup.box.hidden == true; }); - }, - - onPopupGone2: function() { - // Make sure it's hidden again - is(BookmarkPopup.box.hidden, true, "Bookmark popup should be hidden by clicking in content"); - - BookmarkHelper.removeBookmarksForURI(getBrowser().currentURI); - BrowserUI.closeTab(this._currentTab); - - runNextTest(); - } -}); - -//------------------------------------------------------------------------------ -// Case: Test adding tags via star icon -gTests.push({ - desc: "Test adding tags via star icon", - _currentTab: null, - - run: function() { - this._currentTab = Browser.addTab(testURL_02, true); - - messageManager.addMessageListener("pageshow", - function(aMessage) { - if (gCurrentTest._currentTab.browser.currentURI.spec != "about:blank") { - messageManager.removeMessageListener(aMessage.name, arguments.callee); - gCurrentTest.onPageLoad(); - } - }); - }, - - onPageLoad: function() { - let starbutton = document.getElementById("tool-star"); - starbutton.click(); - - waitFor(gCurrentTest.onPopupReady, function() { return BookmarkPopup.box.hidden == false }); - }, - - onPopupReady: function() { - let editbutton = document.getElementById("bookmark-popup-edit"); - editbutton.click(); - - waitFor(gCurrentTest.onEditorReady, function() { - let item = document.getElementById("bookmark-item"); - return item && item.isEditing == true; - }); - }, - - onEditorReady: function() { - let bookmarkitem = document.getElementById("bookmark-item"); - bookmarkitem.tags = "tagone, tag two, tag-three, tag4"; - - let donebutton = document.getAnonymousElementByAttribute(bookmarkitem, "anonid", "done-button"); - donebutton.click(); - - waitFor(gCurrentTest.onEditorDone, function() { return document.getElementById("bookmark-container").hidden == true; }); - }, - - onEditorDone: function() { - let uri = makeURI(testURL_02); - let tagsarray = PlacesUtils.tagging.getTagsForURI(uri, {}); - is(tagsarray.length, 4, "All tags are added."); - - BookmarkHelper.removeBookmarksForURI(uri); - BrowserUI.closeTab(this._currentTab); - - runNextTest(); - } -}); - -//------------------------------------------------------------------------------ -// Case: Test editing uri via star icon -gTests.push({ - desc: "Test editing uri via star icon", - _currentTab: null, - - run: function() { - this._currentTab = Browser.addTab(testURL_02, true); - - messageManager.addMessageListener("pageshow", - function(aMessage) { - if (gCurrentTest._currentTab.browser.currentURI.spec != "about:blank") { - messageManager.removeMessageListener(aMessage.name, arguments.callee); - gCurrentTest.onPageLoad(); - } - }); - }, - - onPageLoad: function() { - let starbutton = document.getElementById("tool-star"); - starbutton.click(); - - waitFor(gCurrentTest.onPopupReady, function() { - return BookmarkPopup.box.hidden == false && - PlacesUtils.getMostRecentBookmarkForURI(makeURI(testURL_02)) != -1; - }); - }, - - onPopupReady: function() { - let editbutton = document.getElementById("bookmark-popup-edit"); - editbutton.click(); - - waitFor(gCurrentTest.onEditorReady, function() { - let item = document.getElementById("bookmark-item"); - return item && item.isEditing == true; - }); - }, - - onEditorReady: function() { - let bookmarkitem = document.getElementById("bookmark-item"); - bookmarkitem.spec = testURL_01; - - let donebutton = document.getAnonymousElementByAttribute(bookmarkitem, "anonid", "done-button"); - donebutton.click(); - - waitFor(gCurrentTest.onEditorDone, function() { return document.getElementById("bookmark-container").hidden == true; }); - }, - - onEditorDone: function() { - isnot(PlacesUtils.getMostRecentBookmarkForURI(makeURI(testURL_01)), -1, testURL_01 + " is now bookmarked"); - is(PlacesUtils.getMostRecentBookmarkForURI(makeURI(testURL_02)), -1, testURL_02 + " is no longer bookmarked"); - - BookmarkHelper.removeBookmarksForURI(makeURI(testURL_02)); - BrowserUI.closeTab(this._currentTab); - - runNextTest(); - } -}); - -//------------------------------------------------------------------------------ -// Case: Test removing existing bookmark via popup -gTests.push({ - desc: "Test removing existing bookmark via popup", - _currentTab: null, - run: function() { - this._currentTab = Browser.addTab(testURL_01, true); - - messageManager.addMessageListener("pageshow", - function(aMessage) { - if (gCurrentTest._currentTab.browser.currentURI.spec != "about:blank") { - messageManager.removeMessageListener(aMessage.name, arguments.callee); - gCurrentTest.onPageLoad(); - } - }); - }, - - onPageLoad: function() { - let starbutton = document.getElementById("tool-star"); - starbutton.click(); - - waitFor(gCurrentTest.onPopupReady, function() { - return BookmarkPopup.box.hidden == false && - PlacesUtils.getMostRecentBookmarkForURI(makeURI(testURL_01)) != -1; - }); - }, - - onPopupReady: function() { - let removebutton = document.getElementById("bookmark-popup-remove"); - removebutton.click(); - - let bookmark = PlacesUtils.getMostRecentBookmarkForURI(makeURI(testURL_01)); - ok(bookmark == -1, testURL_01 + " should no longer in bookmark"); - - BrowserUI.closeTab(this._currentTab); - - runNextTest(); - } -}); diff --git a/mobile/android/chrome/tests/browser_bookmarks_tags.js b/mobile/android/chrome/tests/browser_bookmarks_tags.js deleted file mode 100644 index 43849e3ce25c..000000000000 --- a/mobile/android/chrome/tests/browser_bookmarks_tags.js +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Bug 486490 - Fennec browser-chrome tests to verify correct implementation of chrome - * code in mobile/chrome/content in terms of integration with Places - * component, specifically for bookmark management. - */ - -var testURL_01 = chromeRoot + "browser_blank_01.html"; -var testURL_02 = chromeRoot + "browser_blank_02.html"; - -// A queue to order the tests and a handle for each test -var gTests = []; -var gCurrentTest = null; - -//------------------------------------------------------------------------------ -// Entry point (must be named "test") -function test() { - // The "runNextTest" approach is async, so we need to call "waitForExplicitFinish()" - // We call "finish()" when the tests are finished - waitForExplicitFinish(); - - // Start the tests - runNextTest(); -} - -//------------------------------------------------------------------------------ -// Iterating tests by shifting test out one by one as runNextTest is called. -function runNextTest() { - // Run the next test until all tests completed - if (gTests.length > 0) { - gCurrentTest = gTests.shift(); - info(gCurrentTest.desc); - gCurrentTest.run(); - } - else { - // Cleanup. All tests are completed at this point - try { - PlacesUtils.bookmarks.removeFolderChildren(BookmarkList.panel.mobileRoot); - } - finally { - // We must finialize the tests - finish(); - } - } -} - -//------------------------------------------------------------------------------ -// Case: Test adding tags to bookmark -gTests.push({ - desc: "Test adding tags to a bookmark", - _currentTab: null, - - run: function() { - this._currentTab = Browser.addTab(testURL_02, true); - function handleEvent() { - gCurrentTest._currentTab.browser.removeEventListener("load", handleEvent, true); - gCurrentTest.onPageLoad(); - }; - this._currentTab.browser.addEventListener("load", handleEvent , true); - }, - - onPageLoad: function() { - let starbutton = document.getElementById("tool-star"); - starbutton.click(); - - window.addEventListener("BookmarkCreated", function(aEvent) { - window.removeEventListener(aEvent.type, arguments.callee, false); - let bookmarkItem = PlacesUtils.getMostRecentBookmarkForURI(makeURI(testURL_02)); - ok(bookmarkItem != -1, testURL_02 + " should be added."); - - // Wait for the bookmarks to load, then do the test - window.addEventListener("NavigationPanelShown", gCurrentTest.onBookmarksReady, false); - BrowserUI.doCommand("cmd_bookmarks"); - }, false); - }, - - onBookmarksReady: function() { - window.removeEventListener("NavigationPanelShown", gCurrentTest.onBookmarksReady, false); - - // Go into edit mode - let bookmark = document.getAnonymousElementByAttribute(BookmarkList.panel, "uri", testURL_02); - bookmark.startEditing(); - - waitFor(gCurrentTest.onEditorReady, function() { return bookmark.isEditing == true; }); - }, - - onEditorReady: function() { - let bookmark = document.getAnonymousElementByAttribute(BookmarkList.panel, "uri", testURL_02); - let tagstextbox = document.getAnonymousElementByAttribute(bookmark, "anonid", "tags"); - tagstextbox.value = "tagone, tag two, tag-three, tag4"; - - let donebutton = document.getAnonymousElementByAttribute(bookmark, "anonid", "done-button"); - donebutton.click(); - - let tagsarray = PlacesUtils.tagging.getTagsForURI(makeURI(testURL_02), {}); - is(tagsarray.length, 4, "All tags are associated with specified bookmark"); - - AwesomeScreen.activePanel = null; - - Browser.closeTab(gCurrentTest._currentTab); - - runNextTest(); - } -}); - -//------------------------------------------------------------------------------ -// Case: Test editing tags to bookmark -gTests.push({ - desc: "Test editing tags to bookmark", - - run: function() { - // Wait for the bookmarks to load, then do the test - window.addEventListener("NavigationPanelShown", gCurrentTest.onBookmarksReady, false); - BrowserUI.doCommand("cmd_bookmarks"); - }, - - onBookmarksReady: function() { - window.removeEventListener("NavigationPanelShown", gCurrentTest.onBookmarksReady, false); - - - // Go into edit mode - let bookmark = document.getAnonymousElementByAttribute(BookmarkList.panel, "uri", testURL_02); - bookmark.startEditing(); - - waitFor(gCurrentTest.onEditorReady, function() { return bookmark.isEditing == true; }); - }, - - onEditorReady: function() { - let bookmark = document.getAnonymousElementByAttribute(BookmarkList.panel, "uri", testURL_02); - - let taggeduri = PlacesUtils.tagging.getURIsForTag("tag-three"); - is(taggeduri[0].spec, testURL_02, "Old tag still associated with bookmark"); - - let tagstextbox = document.getAnonymousElementByAttribute(bookmark, "anonid", "tags"); - tagstextbox.value = "tagone, tag two, edited-tag-three, tag4"; - - let donebutton = document.getAnonymousElementByAttribute(bookmark, "anonid", "done-button"); - donebutton.click(); - - let untaggeduri = PlacesUtils.tagging.getURIsForTag("tag-three"); - is(untaggeduri, "", "Old tag is not associated with any bookmark"); - taggeduri = PlacesUtils.tagging.getURIsForTag("edited-tag-three"); - is(taggeduri[0].spec, testURL_02, "New tag is added to bookmark"); - let tagsarray = PlacesUtils.tagging.getTagsForURI(makeURI(testURL_02), {}); - is(tagsarray.length, 4, "Bookmark still has same number of tags"); - - AwesomeScreen.activePanel = null; - - runNextTest(); - } -}); - - -//------------------------------------------------------------------------------ -// Case: Test removing tags from bookmark -gTests.push({ - desc: "Test removing tags from a bookmark", - _currentTab: null, - - run: function() { - // Wait for the bookmarks to load, then do the test - window.addEventListener("NavigationPanelShown", gCurrentTest.onBookmarksReady, false); - BrowserUI.doCommand("cmd_bookmarks"); - }, - - onBookmarksReady: function() { - window.removeEventListener("NavigationPanelShown", gCurrentTest.onBookmarksReady, false); - - // Go into edit mode - let bookmark = document.getAnonymousElementByAttribute(BookmarkList.panel, "uri", testURL_02); - bookmark.startEditing(); - - waitFor(gCurrentTest.onEditorReady, function() { return bookmark.isEditing == true; }); - }, - - onEditorReady: function() { - let bookmark = document.getAnonymousElementByAttribute(BookmarkList.panel, "uri", testURL_02); - - let tagstextbox = document.getAnonymousElementByAttribute(bookmark, "anonid", "tags"); - tagstextbox.value = "tagone, tag two, tag4"; - - let donebutton = document.getAnonymousElementByAttribute(bookmark, "anonid", "done-button"); - donebutton.click(); - - let untaggeduri = PlacesUtils.tagging.getURIsForTag("edited-tag-three"); - is(untaggeduri, "", "Old tag is not associated with any bookmark"); - let tagsarray = PlacesUtils.tagging.getTagsForURI(makeURI(testURL_02), {}); - is(tagsarray.length, 3, "Tag is successfully deleted"); - - AwesomeScreen.activePanel = null; - runNextTest(); - } -}); diff --git a/mobile/android/chrome/tests/browser_click_content.html b/mobile/android/chrome/tests/browser_click_content.html deleted file mode 100644 index 071ce21c24ba..000000000000 --- a/mobile/android/chrome/tests/browser_click_content.html +++ /dev/null @@ -1,7 +0,0 @@ - -Browser Click Page 01 - - - - - diff --git a/mobile/android/chrome/tests/browser_click_content.js b/mobile/android/chrome/tests/browser_click_content.js deleted file mode 100644 index f06428f90e2d..000000000000 --- a/mobile/android/chrome/tests/browser_click_content.js +++ /dev/null @@ -1,128 +0,0 @@ -let testURL_click = chromeRoot + "browser_click_content.html"; - -let currentTab; -let element; -let clickPosition = { x: null, y: null}; - -//------------------------------------------------------------------------------ -// Entry point (must be named "test") -function test() { - // This test is async - waitForExplicitFinish(); - - // Add new tab - currentTab = Browser.addTab(testURL_click, true); - ok(currentTab, "Tab Opened"); - - // Wait for the tab to load, then do the test - messageManager.addMessageListener("pageshow", function() { - if (currentTab.browser.currentURI.spec == testURL_click) { - messageManager.removeMessageListener("pageshow", arguments.callee); - testClickAndPosition(); - }}); -} - -function clickFired(aEvent) { - let [x, y] = browserViewToClient(aEvent.clientX, aEvent.clientY); - clickPosition.x = x; - clickPosition.y = y; -} - -function testClickAndPosition() { - // Do sanity tests - let uri = currentTab.browser.currentURI.spec; - is(uri, testURL_click, "URL Matches newly created Tab"); - - // Check click - element = currentTab.browser.contentDocument.getElementById("iframe-1"); - element.addEventListener("click", function(aEvent) { - element.removeEventListener("click", arguments.callee, true); - clickFired(aEvent); - is(aEvent.type, "click", "Click fired"); - checkClick(); - }, true); - - EventUtils.synthesizeMouseForContent(element, 1, 1, {}, window); -} - -function checkClick() { - // Check position - element = currentTab.browser.contentDocument.documentElement; - element.addEventListener("click", function(aEvent) { - element.removeEventListener("click", arguments.callee, true); - clickFired(aEvent); - checkPosition(); - }, true); - - let rect = getBoundingContentRect(element); - EventUtils.synthesizeMouse(element, 1, rect.height + 10, {}, window); -} - -function checkPosition() { - let rect = getBoundingContentRect(element); - is(clickPosition.x, 1, "X position is correct"); - is(clickPosition.y, rect.height + 10, "Y position is correct"); - - checkThickBorder(); -} - -function checkThickBorder() { - let frame = currentTab.browser.contentDocument.getElementById("iframe-2"); - let element = frame.contentDocument.getElementsByTagName("input")[0]; - - let frameRect = getBoundingContentRect(frame); - let frameLeftBorder = window.getComputedStyle(frame, "").borderLeftWidth; - let frameTopBorder = window.getComputedStyle(frame, "").borderTopWidth; - - let elementRect = getBoundingContentRect(element); - ok((frameRect.left + parseInt(frameLeftBorder)) < elementRect.left, "X position of nested element ok"); - ok((frameRect.top + parseInt(frameTopBorder)) < elementRect.top, "Y position of nested element ok"); - - close(); -} - -function close() { - // Close the tab - Browser.closeTab(currentTab); - - // We must finialize the tests - finish(); -} - -// XXX copied from chrome/content/content.js -function getBoundingContentRect(aElement) { - if (!aElement) - return new Rect(0, 0, 0, 0); - - let document = aElement.ownerDocument; - while(document.defaultView.frameElement) - document = document.defaultView.frameElement.ownerDocument; - - let content = document.defaultView; - let cwu = content.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); - let scrollX = {}, scrollY = {}; - cwu.getScrollXY(false, scrollX, scrollY); - let offset = new Point(scrollX.value, scrollY.value); - let r = aElement.getBoundingClientRect(); - - // step out of iframes and frames, offsetting scroll values - for (let frame = aElement.ownerDocument.defaultView; frame != content; frame = frame.parent) { - // adjust client coordinates' origin to be top left of iframe viewport - let rect = frame.frameElement.getBoundingClientRect(); - let left = frame.getComputedStyle(frame.frameElement, "").borderLeftWidth; - let top = frame.getComputedStyle(frame.frameElement, "").borderTopWidth; - offset.add(rect.left + parseInt(left), rect.top + parseInt(top)); - } - - return new Rect(r.left + offset.x, r.top + offset.y, r.width, r.height); -} - -function browserViewToClient(x, y) { - let container = document.getElementById("browsers"); - let containerBCR = container.getBoundingClientRect(); - - let x0 = Math.round(-containerBCR.left); - let y0 = Math.round(-containerBCR.top); - - return [x - x0, y - y0]; -} diff --git a/mobile/android/chrome/tests/browser_contacts.js b/mobile/android/chrome/tests/browser_contacts.js deleted file mode 100644 index 47d61ac93cf7..000000000000 --- a/mobile/android/chrome/tests/browser_contacts.js +++ /dev/null @@ -1,88 +0,0 @@ - -// pull in the Contacts service -Components.utils.import("resource:///modules/contacts.jsm"); - -let fac = Cc["@mozilla.org/satchel/form-autocomplete;1"].getService(Ci.nsIFormAutoComplete); -let fh = Cc["@mozilla.org/satchel/form-history;1"].getService(Ci.nsIFormHistory2); - -function test() { - ok(Contacts, "Contacts class exists"); - for (var fname in tests) { - tests[fname](); - } -} - -let MockContactsProvider = { - getContacts: function() { - let contacts = [ - { - fullName: "-Billy One", - emails: [], - phoneNumbers: ["999-888-7777"] - }, - { - fullName: "-Billy Two", - emails: ["billy.two@fake.com", "btwo@work.com"], - phoneNumbers: ["111-222-3333", "123-123-1234"] - }, - { - fullName: "-Joe Schmo", - emails: ["joeschmo@foo.com"], - phoneNumbers: ["555-555-5555"] - } - ]; - - return contacts; - } -}; - -// In case there are real contacts that could mess up our test counts -let preEmailCount = fac.autoCompleteSearch("email", "", null, null).matchCount; -let prePhoneCount = fac.autoCompleteSearch("tel", "", null, null).matchCount; - -Contacts.addProvider(MockContactsProvider); - -let tests = { - testBasicMatch: function() { - // Search for any emails - let results = fac.autoCompleteSearch("email", "", null, null); - is(results.matchCount, 3 + preEmailCount, "Found 3 emails for un-filtered search"); - - // Do some filtered searches - results = fac.autoCompleteSearch("email", "-Billy", null, null); - is(results.matchCount, 2, "Found 2 emails '-Billy'"); - - results = fac.autoCompleteSearch("tel", "-Billy", null, null); - is(results.matchCount, 3, "Found 3 phone numbers '-Billy'"); - - results = fac.autoCompleteSearch("skip", "-Billy", null, null); - is(results.matchCount, 0, "Found nothing for a non-contact field"); - - results = fac.autoCompleteSearch("phone", "-Jo", null, null); - is(results.matchCount, 1, "Found 1 phone number '-Jo'"); - }, - - testMixingData: function() { - // Add a simple value to the non-contact system - fh.addEntry("email", "super.cool@place.com"); - - let results = fac.autoCompleteSearch("email", "", null, null); - is(results.matchCount, 4 + preEmailCount, "Found 4 emails for un-filtered search"); - - let firstEmail = results.getValueAt(0); - is(firstEmail, "super.cool@place.com", "The non-contact entry is first"); - - fh.removeAllEntries(); - }, - - testFakeInputField: function() { - let attributes = ["type", "id", "class"]; - for (let i = 0; i < attributes.length; i++) { - let field = document.createElementNS("http://www.w3.org/1999/xhtml", "html:input"); - field.setAttribute(attributes[i], "tel"); - - let results = fac.autoCompleteSearch("", "-Jo", field, null); - is(results.matchCount, 1 + prePhoneCount, "Found 1 phone number -Jo"); - } - } -}; diff --git a/mobile/android/chrome/tests/browser_contentpopup.html b/mobile/android/chrome/tests/browser_contentpopup.html deleted file mode 100644 index 882759457815..000000000000 --- a/mobile/android/chrome/tests/browser_contentpopup.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - -

    - - - - - - - - - - - - - - - diff --git a/mobile/android/chrome/tests/browser_contentpopup.js b/mobile/android/chrome/tests/browser_contentpopup.js deleted file mode 100644 index 305a7bf0f78e..000000000000 --- a/mobile/android/chrome/tests/browser_contentpopup.js +++ /dev/null @@ -1,89 +0,0 @@ -let testURL = chromeRoot + "browser_contentpopup.html"; -messageManager.loadFrameScript(chromeRoot + "remote_contentpopup.js", true); - -let newTab = null; - -// A queue to order the tests and a handle for each test -var gTests = []; -var gCurrentTest = null; - -function test() { - // This test is async - waitForExplicitFinish(); - - // Need to wait until the page is loaded - messageManager.addMessageListener("pageshow", function(aMessage) { - if (newTab && newTab.browser.currentURI.spec != "about:blank") { - messageManager.removeMessageListener(aMessage.name, arguments.callee); - BrowserUI.closeAutoComplete(true); - setTimeout(runNextTest, 0); - } - }); - - waitForFirstPaint(function() { - newTab = Browser.addTab(testURL, true); - }); -} - -//------------------------------------------------------------------------------ -// Iterating tests by shifting test out one by one as runNextTest is called. -function runNextTest() { - // Run the next test until all tests completed - if (gTests.length > 0) { - gCurrentTest = gTests.shift(); - info(gCurrentTest.desc); - gCurrentTest.run(); - } - else { - // Cleanup. All tests are completed at this point - try { - // Add any cleanup code here - - // Close our tab when finished - Browser.closeTab(newTab); - } - finally { - // We must finalize the tests - finish(); - } - } -} - -//------------------------------------------------------------------------------ -// Case: Show/Hide the content popup helper -gTests.push({ - desc: "Show/Hide the content popup helper", - - run: function() { - let popup = document.getElementById("form-helper-suggestions-container"); - popup.addEventListener("contentpopupshown", function(aEvent) { - aEvent.target.removeEventListener(aEvent.type, arguments.callee, false); - ok(!popup.hidden, "Content popup should be visible"); - waitFor(gCurrentTest.hidePopup, function() { - return FormHelperUI._open; - }); - }, false); - - AsyncTests.waitFor("TestRemoteAutocomplete:Click", - { id: "input-datalist-1" }, function(json) {}); - }, - - hidePopup: function() { - let popup = document.getElementById("form-helper-suggestions-container"); - popup.addEventListener("contentpopuphidden", function(aEvent) { - popup.removeEventListener("contentpopuphidden", arguments.callee, false); - ok(popup.hidden, "Content popup should be hidden"); - waitFor(gCurrentTest.finish, function() { - return !FormHelperUI._open; - }); - }, false); - - // Close the form assistant - FormHelperUI.hide(); - }, - - finish: function() { - runNextTest(); - } -}); - diff --git a/mobile/android/chrome/tests/browser_dragger.js b/mobile/android/chrome/tests/browser_dragger.js deleted file mode 100644 index 0b873ddc4ee0..000000000000 --- a/mobile/android/chrome/tests/browser_dragger.js +++ /dev/null @@ -1,89 +0,0 @@ -"use strict"; - -const testURL_01 = chromeRoot + "browser_blank_01.html"; -const testURL_01_Remote = serverRoot + "browser_blank_01.html"; - -function test() { - waitForExplicitFinish(); - runNextTest(); -} - -gTests.push({ - desc: "Test that kinetic panning does not open sidebars.", - tab: null, - - run: function() { - gCurrentTest.tab = Browser.addTab(testURL_01, true); - onMessageOnce(gCurrentTest.tab.browser.messageManager, "Browser:FirstPaint", gCurrentTest.checkPan); - }, - - checkPan: function() { - let browser = gCurrentTest.tab.browser; - let docWidth = browser.contentDocumentWidth * browser.scale; - let winWidth = window.innerWidth; - info("Browser document width is " + docWidth); - info("Window width is " + winWidth); - ok(docWidth <= winWidth, - "Sanity check. Blank document cannot be panned left or right."); - - function dragAndCheck(dx) { - let dragger = Elements.browsers.customDragger; - try { - dragger.dragStart(0, 0, null, null); - dragger.dragMove(dx, 0, null, true); - - let [leftVis, rightVis] = Browser.computeSidebarVisibility(); - is(leftVis, 0, "Left sidebar is not visible"); - is(rightVis, 0, "Right sidebar is not visible"); - } finally { - // Be fail tolerant and hide sidebars in case tests failed. - Browser.hideSidebars(); - dragger.dragStop(); - } - } - - dragAndCheck(-20); - dragAndCheck(20); - - Browser._doCloseTab(gCurrentTest.tab); - runNextTest(); - } -}); - -gTests.push({ - desc: "Test that urlbar cannot be panned in when content is captured.", - tab: null, - - run: function() { - gCurrentTest.tab = Browser.addTab(testURL_01_Remote, true); - Browser.selectedTab = gCurrentTest.tab; - onMessageOnce(gCurrentTest.tab.browser.messageManager, "MozScrolledAreaChanged", gCurrentTest.mouseMove); - }, - - mouseMove: function(json) { - let inputHandler = gCurrentTest.tab.browser.parentNode; - function fireMouseEvent(y, type) { - EventUtils.synthesizeMouse(inputHandler, 0, y, { type: type }); - } - - Browser.hideTitlebar(); - let rect = Elements.browsers.getBoundingClientRect(); - is(rect.top, 0, "Titlebar begins hidden"); - - let dragger = Elements.browsers.customDragger; - try { - dragger.contentCanCapture = true; - dragger.dragStart(0, 0, null, null); - dragger.dragMove(0, 20, null, true); - dragger.dragStop(); - } finally { - dragger.contentCanCapture = false; - } - - rect = Elements.browsers.getBoundingClientRect(); - is(rect.top, 0, "Titlebar is still hidden"); - - Browser._doCloseTab(gCurrentTest.tab); - runNextTest(); - } -}); diff --git a/mobile/android/chrome/tests/browser_escape.js b/mobile/android/chrome/tests/browser_escape.js deleted file mode 100644 index a08272725c94..000000000000 --- a/mobile/android/chrome/tests/browser_escape.js +++ /dev/null @@ -1,128 +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 Mozilla Mobile Browser. - * - * The Initial Developer of the Original Code is - * Mozilla Corporation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Matt Brubeck - * - * 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 ***** */ - -"use strict"; -const url1 = baseURI + "browser_blank_01.html"; -const url2 = baseURI + "browser_blank_02.html"; -const url3 = baseURI + "browser_blank_03.html"; -let tab1, tab2; - -function test() { - waitForExplicitFinish(); - testGoBack(); - - registerCleanupFunction(closeTabs); -} - -function testGoBack() { - tab1 = Browser.addTab("about:blank", true); - tab2 = Browser.addTab("about:blank", true, tab1); - let browser = tab2.browser; - - // Load each of these URLs, then use escape to step backward through them. - let urls = [url1, url2, url3]; - let i = 0, step = 1; - let expectedURI; - - function loadNextPage() { - expectedURI = urls[i]; - if (step == 1) { - // go forward - Browser.loadURI(expectedURI); - } else { - // go back by pressing the escape key - Browser.selectedBrowser.focus(); - EventUtils.synthesizeKey("VK_ESCAPE", {type: "keypress"}, window); - } - } - - browser.messageManager.addMessageListener("pageshow", function listener(aMessage) { - let uri = browser.currentURI.spec; - if (uri == "about:blank") { - loadNextPage(); - return; - } - is(uri, expectedURI, "Page " + i + " loaded"); - - if (i == urls.length - 1) - step = -1; // start going back when we get to the end - i += step; - - if (i >= 0) { - loadNextPage(); - //setTimeout(loadNextPage, 1000); - } else { - // All done. Go to the next test. - browser.messageManager.removeMessageListener("pageshow", listener); - closeTabs(); - testReturnToOwner(); - } - }); -} - -function testReturnToOwner() { - tab1 = Browser.addTab("about:blank", true); - tab2 = Browser.addTab("about:blank", true, tab1); - is(Browser.selectedTab, tab2, "tab2 is selected"); - EventUtils.sendKey("ESCAPE"); - is(Browser.selectedTab, tab1, "tab1 is selected"); - closeTabs(); - testContextMenu(); -} - -function testContextMenu() { - ContextHelper.showPopup({ - json: { - types: ['link'] - }, - target: Browser.selectedBrowser - }); - ok(ContextHelper.popupState, "Context menu is shown"); - Browser.selectedBrowser.focus(); - EventUtils.synthesizeKey("VK_ESCAPE", {type: "keypress"}, window); - ok(!ContextHelper.popupState, "Context menu is dismissed"); - finish(); -} - -function closeTabs() { - try { - Browser.closeTab(tab1); - Browser.closeTab(tab2); - } finally { - tab1 = tab2 = null; - } -} diff --git a/mobile/android/chrome/tests/browser_find.js b/mobile/android/chrome/tests/browser_find.js deleted file mode 100644 index 89d0392c1b92..000000000000 --- a/mobile/android/chrome/tests/browser_find.js +++ /dev/null @@ -1,39 +0,0 @@ -// Tests for the Find In Page UI - -//------------------------------------------------------------------------------ -// Entry point (must be named "test") -function test() { - addEventListener("PopupChanged", popupOpened, false); - CommandUpdater.doCommand("cmd_menu"); -} - -function popupOpened() { - removeEventListener("PopupChanged", popupOpened, false); - - let menu = document.getElementById("appmenu"); - ok(!menu.hidden, "App menu is shown"); - - let navigator = document.getElementById("content-navigator"); - ok(!navigator.isActive, "Toolbar is closed"); - - addEventListener("PopupChanged", findOpened, false); - let item = document.getElementsByClassName("appmenu-findinpage-button")[0]; - item.click(); -} - -function findOpened() { - removeEventListener("PopupChanged", findOpened, false); - - let menu = document.getElementById("appmenu"); - ok(menu.hidden, "App menu is closed"); - - let navigator = document.getElementById("content-navigator"); - ok(navigator.isActive, "Toolbar is open"); - - is(navigator._previousButton.disabled, true, "Previous button should be disabled"); - is(navigator._nextButton.disabled, true, "Previous button should be disabled"); - - EventUtils.synthesizeKey("VK_ESCAPE", {}, window); - ok(menu.hidden, "Site menu is closed"); - ok(!navigator.isActive, "Toolbar is closed"); -} diff --git a/mobile/android/chrome/tests/browser_focus.html b/mobile/android/chrome/tests/browser_focus.html deleted file mode 100644 index 95550379da60..000000000000 --- a/mobile/android/chrome/tests/browser_focus.html +++ /dev/null @@ -1,7 +0,0 @@ - - - Focus/Activate test - - - - diff --git a/mobile/android/chrome/tests/browser_focus.js b/mobile/android/chrome/tests/browser_focus.js deleted file mode 100644 index 5b53f4339c48..000000000000 --- a/mobile/android/chrome/tests/browser_focus.js +++ /dev/null @@ -1,52 +0,0 @@ -"use strict"; -let testURL = chromeRoot + "browser_focus.html"; -let newTab = null; - -function test() { - waitForExplicitFinish(); - - registerCleanupFunction(function() { - try { - messageManager.sendAsyncMessage("Test:E10SFocusTestFinished", {}); - Browser.closeTab(newTab); - } finally { - newTab = null; - } - }); - - messageManager.addMessageListener("pageshow", function listener(aMessage) { - if (newTab && newTab.browser.currentURI.spec != "about:blank") { - messageManager.removeMessageListener("pageshow", listener); - setTimeout(onTabLoaded, 0); - } - }); - - newTab = Browser.addTab(testURL, true); -} - -function onTabLoaded() { - // ensure that the is not already focused - newTab.browser.blur(); - messageManager.loadFrameScript(chromeRoot + "remote_focus.js", false); - testFocus(); -} - -function testFocus() { - onMessageOnce(messageManager, "Test:E10SFocusReceived", function() { - ok("Focus in triggered activateRemoteFrame as expected"); - testBlur(); - }); - newTab.browser.focus(); -} - -function testBlur() { - onMessageOnce(messageManager, "Test:E10SBlurReceived", function() { - ok("Blur in triggerered deactivateRemoteFrame as expected"); - endTest(); - }); - newTab.browser.blur(); -} - -function endTest() { - finish(); -} diff --git a/mobile/android/chrome/tests/browser_forms.html b/mobile/android/chrome/tests/browser_forms.html deleted file mode 100644 index 5566bbe5bb52..000000000000 --- a/mobile/android/chrome/tests/browser_forms.html +++ /dev/null @@ -1,51 +0,0 @@ - - - Browser Form Assistant - - - - - - - - - - text - -
    click here
    - - -
    - - - dumb type - - -
    div
    - - - - - - - - - - - - - - - - - - - - - - diff --git a/mobile/android/chrome/tests/browser_forms.js b/mobile/android/chrome/tests/browser_forms.js deleted file mode 100644 index 37589eb19b07..000000000000 --- a/mobile/android/chrome/tests/browser_forms.js +++ /dev/null @@ -1,242 +0,0 @@ -let testURL = chromeRoot + "browser_forms.html"; -messageManager.loadFrameScript(chromeRoot + "remote_forms.js", true); - -let newTab = null; - -function test() { - // This test is async - waitForExplicitFinish(); - - // Need to wait until the page is loaded - messageManager.addMessageListener("pageshow", function(aMessage) { - if (newTab && newTab.browser.currentURI.spec != "about:blank") { - messageManager.removeMessageListener(aMessage.name, arguments.callee); - setTimeout(onTabLoaded, 0); - } - }); - - // Add new tab to hold the page - newTab = Browser.addTab(testURL, true); -} - -function onTabLoaded() { - BrowserUI.closeAutoComplete(true); - testMouseEvents(); -} - -function testMouseEvents() { - // Sending a synthesized event directly on content should not work - we - // don't want web content to be able to open the form helper without the - // user consent, so we have to pass through the canvas tile-container - AsyncTests.waitFor("Test:Click", {}, function(json) { - is(json.result, false, "Form Assistant should stay closed"); - }); - - AsyncTests.waitFor("Test:Focus", { value: "#root" }, function(json) { - is(json.result, false, "Form Assistant should stay closed"); - }); - - AsyncTests.waitFor("Test:FocusRedirect", { value: "*[tabindex='0']" }, function(json) { - is(json.result, false, "Form Assistant should stay closed"); - testOpenUIWithSyncFocus(); - }); -}; - -function waitForFormAssist(aCallback) { - messageManager.addMessageListener("FormAssist:Show", function(aMessage) { - messageManager.removeMessageListener(aMessage.name, arguments.callee); - setTimeout(function() { - ok(FormHelperUI._open, "Form Assistant should be open"); - setTimeout(aCallback, 0); - }); - }); -}; - -function testOpenUIWithSyncFocus() { - AsyncTests.waitFor("Test:Open", { value: "*[tabindex='0']" }, function(json) {}); - waitForFormAssist(testOpenUI); -}; - -function testOpenUI() { - AsyncTests.waitFor("Test:Open", { value: "*[tabindex='0']" }, function(json) {}); - waitForFormAssist(testOpenUIWithFocusRedirect); -}; - -function testOpenUIWithFocusRedirect() { - AsyncTests.waitFor("Test:OpenWithFocusRedirect", { value: "*[tabindex='0']" }, function(json) {}); - waitForFormAssist(testShowUIForSelect); -}; - -function testShowUIForSelect() { - AsyncTests.waitFor("Test:CanShowUI", { value: "#select"}, function(json) { - ok(json.result, "canShowUI for select element'"); - }); - - AsyncTests.waitFor("Test:CanShowUI", { value: "#select", disabled: true }, function(json) { - is(json.result, false, "!canShowUI for disabled select element'"); - }); - - AsyncTests.waitFor("Test:CanShowUI", { value: "#option"}, function(json) { - ok(json.result, "canShowUI for option element'"); - }); - - AsyncTests.waitFor("Test:CanShowUISelect", { value: "#option", disabled: true }, function(json) { - is(json.result, false, "!canShowUI for option element with a disabled parent select element'"); - }); - - AsyncTests.waitFor("Test:CanShowUI", { value: "#option", disabled: true }, function(json) { - is(json.result, false, "!canShowUI for disabled option element'"); - testShowUIForElements(); - }); -} - -function testShowUIForElements() { - AsyncTests.waitFor("Test:CanShowUI", { value: "*[tabindex='1']" }, function(json) { - ok(json.result, "canShowUI for input type='text'"); - }); - - AsyncTests.waitFor("Test:CanShowUI", { value: "*[tabindex='1']", disabled: true }, function(json) { - is(json.result, false, "!canShowUI for disabled input type='text'"); - }); - - AsyncTests.waitFor("Test:CanShowUI", { value: "*[tabindex='2']" }, function(json) { - ok(json.result, "canShowUI for input type='password'"); - }); - - AsyncTests.waitFor("Test:CanShowUI", { value: "*[tabindex='2']", disabled: true }, function(json) { - is(json.result, false, "!canShowUI for disabled input type='password'"); - }); - - AsyncTests.waitFor("Test:CanShowUI", { value: "*[tabindex='8']" }, function(json) { - ok(json.result, "canShowUI for contenteditable div"); - }); - - AsyncTests.waitFor("Test:CanShowUI", { value: "*[tabindex='8']", disabled: true }, function(json) { - is(json.result, false, "!canShowUI for disabled contenteditable div"); - }); - - AsyncTests.waitFor("Test:CanShowUI", { value: "*[tabindex='3']" }, function(json) { - is(json.result, false, "!canShowUI for input type='submit'"); - }); - - AsyncTests.waitFor("Test:CanShowUI", { value: "*[tabindex='4']" }, function(json) { - is(json.result, false, "!canShowUI for input type='file'"); - }); - - AsyncTests.waitFor("Test:CanShowUI", { value: "*[tabindex='5']" }, function(json) { - is(json.result, false, "!canShowUI for input button type='submit'"); - }); - - AsyncTests.waitFor("Test:CanShowUI", { value: "*[tabindex='6']" }, function(json) { - is(json.result, false, "!canShowUI for input div@role='button'"); - }); - - AsyncTests.waitFor("Test:CanShowUI", { value: "*[tabindex='6']" }, function(json) { - is(json.result, false, "!canShowUI for input type='image'"); - }); - - // Open the Form Helper - AsyncTests.waitFor("Test:Open", { value: "*[tabindex='1']" }, function(json) { - ok(json.result, "Form Assistant should be open"); - testTabIndexNavigation(); - }); -}; - -function testTabIndexNavigation() { - AsyncTests.waitFor("Test:Previous", { value: "*[tabindex='0']" }, function(json) { - is(json.result, false, "Focus should not have changed"); - }); - - AsyncTests.waitFor("Test:Next", { value: "*[tabindex='2']" }, function(json) { - is(json.result, true, "Focus should be on element with tab-index : 2"); - }); - - AsyncTests.waitFor("Test:Previous", { value: "*[tabindex='1']" }, function(json) { - is(json.result, true, "Focus should be on element with tab-index : 1"); - }); - - AsyncTests.waitFor("Test:Next"); - AsyncTests.waitFor("Test:Next"); - AsyncTests.waitFor("Test:Next"); - AsyncTests.waitFor("Test:Next"); - AsyncTests.waitFor("Test:Next"); - - AsyncTests.waitFor("Test:Next", { value: "*[tabindex='7']" }, function(json) { - is(json.result, true, "Focus should be on element with tab-index : 7"); - }); - - AsyncTests.waitFor("Test:Next", { value: "*[tabindex='8']" }, function(json) { - is(json.result, true, "Focus should be on element with tab-index : 8"); - }); - - AsyncTests.waitFor("Test:Next", { value: "*[tabindex='0']" }, function(json) { - is(json.result, true, "Focus should be on element with tab-index : 0"); - }); - - let ids = ["next", "select", "dumb", "reset", "checkbox", "radio0", "radio4", "last", "last"]; - for (let i = 0; i < ids.length; i++) { - let id = ids[i]; - AsyncTests.waitFor("Test:Next", { value: "#" + id }, function(json) { - is(json.result, true, "Focus should be on element with #id: " + id + ""); - }); - }; - - FormHelperUI.hide(); - let container = document.getElementById("content-navigator"); - is(container.hidden, true, "Form Assistant should be close"); - - AsyncTests.waitFor("Test:Open", { value: "*[tabindex='0']" }, function(json) { - ok(FormHelperUI._open, "Form Assistant should be open"); - testFocusChanges(); - }); -}; - -function testFocusChanges() { - AsyncTests.waitFor("Test:Focus", { value: "*[tabindex='1']" }, function(json) { - ok(json.result, "Form Assistant should be open"); - }); - - AsyncTests.waitFor("Test:Focus", { value: "#select" }, function(json) { - ok(json.result, "Form Assistant should stay open"); - }); - - AsyncTests.waitFor("Test:Focus", { value: "*[type='hidden']" }, function(json) { - ok(json.result, "Form Assistant should stay open"); - loadNestedIFrames(); - }); -} - -function loadNestedIFrames() { - AsyncTests.waitFor("Test:Iframe", { }, function(json) { - is(json.result, true, "Iframe should have loaded"); - navigateIntoNestedIFrames(); - }); -} - -function navigateIntoNestedIFrames() { - AsyncTests.waitFor("Test:IframeOpen", { }, function(json) { - is(json.result, true, "Form Assistant should have been opened"); - }); - - AsyncTests.waitFor("Test:IframePrevious", { value: 0 }, function(json) { - is(json.result, true, "Focus should not have move"); - }); - - AsyncTests.waitFor("Test:IframeNext", { value: 1 }, function(json) { - is(json.result, true, "Focus should have move"); - }); - - AsyncTests.waitFor("Test:IframeNext", { value: 1 }, function(json) { - is(json.result, true, "Focus should not have move"); - - // Close the form assistant - FormHelperUI.hide(); - - // Close our tab when finished - Browser.closeTab(newTab); - - // We must finalize the tests - finish(); - }); -}; - diff --git a/mobile/android/chrome/tests/browser_formsZoom.html b/mobile/android/chrome/tests/browser_formsZoom.html deleted file mode 100644 index 36f641d0d0dd..000000000000 --- a/mobile/android/chrome/tests/browser_formsZoom.html +++ /dev/null @@ -1,66 +0,0 @@ - - - Browser Zoom Test - - -















    -
    -
    -
    - -
    - - diff --git a/mobile/android/chrome/tests/browser_formsZoom.js b/mobile/android/chrome/tests/browser_formsZoom.js deleted file mode 100644 index d78a26771690..000000000000 --- a/mobile/android/chrome/tests/browser_formsZoom.js +++ /dev/null @@ -1,214 +0,0 @@ -let testURL_01 = chromeRoot + "browser_formsZoom.html"; -let testURL_02 = baseURI + "browser_formsZoom.html"; -messageManager.loadFrameScript(baseURI + "remote_formsZoom.js", true); - -// A queue to order the tests and a handle for each test -var gTests = []; -var gCurrentTest = null; - -//------------------------------------------------------------------------------ -// Entry point (must be named "test") -function test() { - // The "runNextTest" approach is async, so we need to call "waitForExplicitFinish()" - // We call "finish()" when the tests are finished - waitForExplicitFinish(); - // Start the tests - runNextTest(); -} - -function waitForPageShow(aPageURL, aCallback) { - messageManager.addMessageListener("pageshow", function(aMessage) { - if (aMessage.target.currentURI.spec == aPageURL) { - messageManager.removeMessageListener("pageshow", arguments.callee); - setTimeout(function() { aCallback(); }, 0); - } - }); -}; - -//------------------------------------------------------------------------------ -// Iterating tests by shifting test out one by one as runNextTest is called. -function runNextTest() { - // Run the next test until all tests completed - if (gTests.length > 0) { - gCurrentTest = gTests.shift(); - info(gCurrentTest.desc); - setTimeout(gCurrentTest.run, 0); - } - else { - // Cleanup. All tests are completed at this point - try { - // Add any cleanup code here - } - finally { - // We must finialize the tests - finish(); - } - } -} - -function waitForZoom(aCallback) { - if (AnimatedZoom.isZooming()) { - let self = this; - window.addEventListener("AnimatedZoomEnd", function() { - window.removeEventListener("AnimatedZoomEnd", arguments.callee, false); - setTimeout(aCallback, 0); - }, false); - } - else setTimeout(aCallback, 0); -} - -function isElementVisible(aElement) { - let elementRect = Rect.fromRect(aElement.rect); - let caretRect = Rect.fromRect(aElement.caretRect); - - let browser = getBrowser(); - let zoomRect = Rect.fromRect(browser.getBoundingClientRect()); - let scroll = browser.getRootView().getPosition(); - let browserRect = new Rect(scroll.x, scroll.y, zoomRect.width, zoomRect.height); - - info("CanZoom: " +Browser.selectedTab.allowZoom); - - info("Browser rect: " + browserRect + " - scale: " + browser.scale); - info("Element rect: " + elementRect + " - caret rect: " + caretRect); - info("Scale element rect: " + elementRect.clone().scale(browser.scale, browser.scale) + " - scale caretRect: " + caretRect.clone().scale(browser.scale, browser.scale)); - info("Resulting zoom rect: " + Browser._getZoomRectForPoint(elementRect.center().x, elementRect.y, browser.scale)); - - let isCaretSyncEnabled = Services.prefs.getBoolPref("formhelper.autozoom.caret"); - if (isCaretSyncEnabled) { - ok(browserRect.contains(caretRect.clone().scale(browser.scale, browser.scale)), "Caret rect should be completely visible"); - } - else { - elementRect = elementRect.clone().scale(browser.scale, browser.scale); - let resultRect = browserRect.intersect(elementRect); - ok(!resultRect.isEmpty() && elementRect.x > browserRect.x && elementRect.y > browserRect.y, "Element should be partially visible"); - } -} - - -//------------------------------------------------------------------------------ -// Case: Loading a page and Zoom into textarea field with caret sync disabled -gTests.push({ - desc: "Loading a page and Zoom into textarea field with caret sync enabled", - elements: ["textarea-1", "textarea-2", "textarea-3", "textarea-4"], - _currentTab: null, - - run: function() { - Services.prefs.setBoolPref("formhelper.autozoom.caret", false); - gCurrentTest._currentTab = BrowserUI.newTab(testURL_01); - - waitForPageShow(testURL_01, function() { gCurrentTest.zoomNext(); }); - }, - - zoomNext: function() { - let id = this.elements.shift(); - if (!id) { - BrowserUI.closeTab(); - runNextTest(); - return; - } - - info("Zooming to " + id); - AsyncTests.waitFor("FormAssist:Show", { id: id }, function(json) { - waitForZoom(function() { - isElementVisible(json.current); - gCurrentTest.zoomNext(); - }); - }); - } -}); - -//------------------------------------------------------------------------------ -// Case: Loading a page and Zoom into textarea field with caret sync enabled -gTests.push({ - desc: "Loading a page and Zoom into textarea field with caret sync enabled", - elements: ["textarea-1", "textarea-2", "textarea-3", "textarea-4"], - _currentTab: null, - - run: function() { - Services.prefs.setBoolPref("formhelper.autozoom.caret", true); - gCurrentTest._currentTab = BrowserUI.newTab(testURL_01); - - waitForPageShow(testURL_01, function() { gCurrentTest.zoomNext(); }); - }, - - zoomNext: function() { - let id = this.elements.shift(); - if (!id) { - BrowserUI.closeTab(); - runNextTest(); - return; - } - - AsyncTests.waitFor("FormAssist:Show", { id: id }, function(json) { - waitForZoom(function() { - isElementVisible(json.current); - gCurrentTest.zoomNext(); - }); - }); - } -}); - -//------------------------------------------------------------------------------ -// Case: Loading a remote page and Zoom into textarea field with caret sync disabled -gTests.push({ - desc: "Loading a remote page and Zoom into textarea field with caret sync disabled", - elements: ["textarea-1", "textarea-2", "textarea-3", "textarea-4"], - _currentTab: null, - - run: function() { - Services.prefs.setBoolPref("formhelper.autozoom.caret", false); - gCurrentTest._currentTab = BrowserUI.newTab(testURL_02); - - waitForPageShow(testURL_02, function() { gCurrentTest.zoomNext(); }); - }, - - zoomNext: function() { - let id = this.elements.shift(); - if (!id) { - BrowserUI.closeTab(); - runNextTest(); - return; - } - - AsyncTests.waitFor("FormAssist:Show", { id: id }, function(json) { - waitForZoom(function() { - isElementVisible(json.current); - gCurrentTest.zoomNext(); - }); - }); - } -}); - -//------------------------------------------------------------------------------ -// Case: Loading a remote page and Zoom into textarea field with caret sync enabled -gTests.push({ - desc: "Loading a remote page and Zoom into textarea field with caret sync enabled", - elements: ["textarea-1", "textarea-2"], - _currentTab: null, - - run: function() { - Services.prefs.setBoolPref("formhelper.autozoom.caret", true); - gCurrentTest._currentTab = BrowserUI.newTab(testURL_02); - - waitForPageShow(testURL_02, function() { gCurrentTest.zoomNext(); }); - }, - - zoomNext: function() { - let id = this.elements.shift(); - if (!id) { - todo(false, "textarea-3 caret should be synced, but for some reason it is not"); - todo(false, "textarea-4 caret should be synced, but for some reason it is not"); - BrowserUI.closeTab(); - runNextTest(); - return; - } - - AsyncTests.waitFor("FormAssist:Show", { id: id }, function(json) { - waitForZoom(function() { - isElementVisible(json.current); - gCurrentTest.zoomNext(); - }); - }); - } -}); - diff --git a/mobile/android/chrome/tests/browser_history.js b/mobile/android/chrome/tests/browser_history.js deleted file mode 100644 index dd4ad8061cea..000000000000 --- a/mobile/android/chrome/tests/browser_history.js +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Make sure history is being recorded when we visit websites. - */ - -var testURL_01 = baseURI + "browser_blank_01.html"; - -// A queue to order the tests and a handle for each test -var gTests = []; -var gCurrentTest = null; - -//------------------------------------------------------------------------------ -// Entry point (must be named "test") -function test() { - // The "runNextTest" approach is async, so we need to call "waitForExplicitFinish()" - // We call "finish()" when the tests are finished - waitForExplicitFinish(); - - // Start the tests - runNextTest(); -} - -//------------------------------------------------------------------------------ -// Iterating tests by shifting test out one by one as runNextTest is called. -function runNextTest() { - // Run the next test until all tests completed - if (gTests.length > 0) { - gCurrentTest = gTests.shift(); - info(gCurrentTest.desc); - gCurrentTest.run(); - } - else { - // Cleanup. All tests are completed at this point - try { - } - finally { - // We must finialize the tests - finish(); - } - } -} - -/** - * One-time observer callback. - */ -function waitForObserve(name, callback) { - var observerService = Cc["@mozilla.org/observer-service;1"] - .getService(Ci.nsIObserverService); - var observer = { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]), - observe: function(subject, topic, data) { - observerService.removeObserver(observer, name); - observer = null; - callback(subject, topic, data); - } - }; - - observerService.addObserver(observer, name, false); -} - -//------------------------------------------------------------------------------ - -gTests.push({ - desc: "Test history being added with page visit", - _currentTab: null, - - run: function() { - this._currentTab = Browser.addTab(testURL_01, true); - waitForObserve("uri-visit-saved", function(subject, topic, data) { - let uri = subject.QueryInterface(Ci.nsIURI); - ok(uri.spec == testURL_01, "URI was saved to history"); - Browser.closeTab(gCurrentTest._currentTab); - runNextTest(); - }); - } -}); diff --git a/mobile/android/chrome/tests/browser_install.xml b/mobile/android/chrome/tests/browser_install.xml deleted file mode 100644 index 3e96873c2afd..000000000000 --- a/mobile/android/chrome/tests/browser_install.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - Install Tests - Extension - addon1@tests.mozilla.org - 1.0 - http://example.com/icon.png - http://example.com/ - - - Test Creator - http://example.com/creator.html - - - Public - Test add-on - Test add-on - - - Fennec - {a23983c0-fd0e-11dc-95ff-0800200c9a66} - 0 - * - - - ALL - http://example.com/browser/mobile/chrome/tests/addons/browser_install1_1.xpi - - - - Install Tests 2 - Extension - addon2@tests.mozilla.org - 1.0 - http://example.com/icon.png - http://example.com/ - - - Test Creator - http://example.com/creator.html - - - Public - Test add-on 2 - Test add-on 2 - - - Fennec - {a23983c0-fd0e-11dc-95ff-0800200c9a66} - 0 - * - - - ALL - http://example.com/browser/mobile/chrome/tests/addons/browser_install1_2.xpi - - diff --git a/mobile/android/chrome/tests/browser_localepicker.js b/mobile/android/chrome/tests/browser_localepicker.js deleted file mode 100644 index 1acef76c559e..000000000000 --- a/mobile/android/chrome/tests/browser_localepicker.js +++ /dev/null @@ -1,282 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -Components.utils.import("resource://gre/modules/Services.jsm"); -Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); - -const RELATIVE_DIR = "browser/mobile/chrome/tests/"; -const TESTROOT = "http://example.com/" + RELATIVE_DIR; -const PREF_GET_LOCALES = "extensions.getLocales.get.url"; - -var gAvailable = []; - -var restartObserver = { - observe: function(aSubject, aTopic, aData) { - // cancel restart requests - aSubject.QueryInterface(Ci.nsISupportsPRBool); - aSubject.data = true; - }, - QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]) -} - -function test() { - Services.obs.addObserver(restartObserver, "quit-application-requested", false); - waitForExplicitFinish(); - Services.prefs.setCharPref(PREF_GET_LOCALES, TESTROOT + "locales_list.sjs?numvalid=2"); - - let chromeReg = Components.classes["@mozilla.org/chrome/chrome-registry;1"].getService(Components.interfaces.nsIXULChromeRegistry); - chromeReg.QueryInterface(Ci.nsIToolkitChromeRegistry); - let availableLocales = chromeReg.getLocalesForPackage("browser"); - while (availableLocales.hasMore()) - gAvailable.push( availableLocales.getNext() ); - - - // in order to test restart notifications being shown, we much open the settings panel once - let settingsButton = document.getElementById("tool-panel-open"); - settingsButton.click(); - waitForAndContinue(runNextTest, function() { - return !document.getElementById("panel-container").hidden; - }); -} - -function end_test() { - BrowserUI.hidePanel(); - Services.prefs.clearUserPref(PREF_GET_LOCALES); - Services.obs.removeObserver(restartObserver, "quit-application-requested"); -} - -registerCleanupFunction(end_test); - -function CheckListLoad(aList, aLength) { - return function() { - return aList.childNodes.length == aLength; - } -} - -function CheckDeck(aDeck, aPanel) { - return function() { - return aDeck.selectedPanel == aPanel; - } -} - -function LocaleTest(aName, aOptions) { - var install = null; - return { - desc: aName, - win: null, - run: function lt_run() { - this.loadedWindow = this.loadedWindow.bind(this); - this.windowClosed = this.windowClosed.bind(this); - this.win = Services.ww.openWindow(aOptions.opener, "chrome://browser/content/localePicker.xul", "_browser", "chrome,dialog=no,all", null); - this.win.addEventListener("load", this.loadedWindow, false); - }, - - loadedWindow: function lt_loadedWindow() { - this.win.removeEventListener("load", this.loadedWindow, false); - if (aOptions.opener) - setTimeout(this.delayedLoadPicker.bind(this), 0); - else - setTimeout(this.delayedLoadMain.bind(this), 0); - }, - - delayedLoadMain: function lt_delayedLoadMain() { - let deck = this.win.document.getElementById("language-deck"); - let mainPage = this.win.document.getElementById("main-page"); - is(deck.selectedPanel, mainPage, "Deck is showing the main page"); - - if (aOptions.loadLocalesList) { - // load the locales list - let changeButton = this.win.document.getElementById("change-language"); - changeButton.click(); - this.delayedLoadPicker(); - } else { - // click the "Continue in English" button - let continueButton = this.win.document.getElementById("continue-in-button"); - ok(/english/i.test(continueButton.textContent), "Continue button says English"); - this.win.addEventListener("unload", this.windowClosed, false); - continueButton.click(); - } - }, - - delayedLoadPicker: function lt_delayedLoadPicker() { - let deck = this.win.document.getElementById("language-deck"); - let pickerPage = this.win.document.getElementById("picker-page"); - is(deck.selectedPanel, pickerPage, "Deck is showing the picker page"); - - let list = this.win.document.getElementById("language-list"); - // wait till the list shows the number of locales bundled with this build + the 2 from the downloaded list - waitForAndContinue(this.listLoaded.bind(this), CheckListLoad(list, gAvailable.length + 2)); - }, - - listLoaded: function() { - let continueButton = this.win.document.getElementById("continue-button"); - let cancelButton = this.win.document.getElementById("cancel-button"); - ok(/continue/i.test(continueButton.textContent), "Continue button has correct text"); - ok(/cancel/i.test(cancelButton.textContent), "Cancel button has correct text"); - - let list = this.win.document.getElementById("language-list"); - is(list.childNodes.length, gAvailable.length + 2, "List has correct number of children"); - - let nextSelected = null; - let selectedItem = null; - for(var i = 0; i < list.childNodes.length; i++) { - let child = list.childNodes[i]; - if (/english/i.test(child.textContent)) { - ok(child.hasAttribute("selected"), "English is initially selected"); - selectedItem = child; - } else { - ok(!child.hasAttribute("selected"), "Language is not selected"); - if (aOptions.selectAddon && child.textContent == aOptions.selectAddon.name) - nextSelected = child; - } - } - this.testInstallingItem(nextSelected); - }, - - testInstallingItem: function lt_testInstallingItem(aSelect) { - let continueButton = this.win.document.getElementById("continue-button"); - let cancelButton = this.win.document.getElementById("cancel-button"); - - if (aSelect) { - aSelect.click(); - is(continueButton.textContent, aOptions.selectAddon.continueButton, "Continue button says " + aOptions.selectAddon.continueButton); - is(cancelButton.textContent, aOptions.selectAddon.cancelButton, "Cancel button says " + aOptions.selectAddon.cancelButton); - let title = this.win.document.getElementById("picker-title"); - is(title.textContent, aOptions.selectAddon.title, "Title says " + aOptions.selectAddon.title); - continueButton.click(); - - let deck = this.win.document.getElementById("language-deck"); - let installerPage = this.win.document.getElementById("installer-page"); - is(deck.selectedPanel, installerPage, "Deck is showing the installer page"); - - let installingPage = this.win.document.getElementById("installer-page-installing"); - is(installerPage.selectedPanel, installingPage, "Installer is showing installing page"); - let installMsg = this.win.document.getElementById("installing-message"); - is(installMsg.textContent, aOptions.selectAddon.installMessage, "Installer is showing correct message"); - - if (aOptions.selectAddon.willFail) { - let failedPage = this.win.document.getElementById("installer-page-error"); - waitForAndContinue(this.installFailed.bind(this), CheckDeck(installerPage, failedPage)); - } else { - let install = aSelect.locale; - this.win.addEventListener("unload", this.windowClosed, false); - } - } else { - this.cancelList(); - } - }, - - installFailed: function lt_installFailed() { - let continueButton = this.win.document.getElementById("install-continue"); - is(continueButton.textContent, aOptions.selectAddon.installFailed, "Install failed button has correct label"); - continueButton.click(); - - let deck = this.win.document.getElementById("language-deck"); - let pickerPage = this.win.document.getElementById("picker-page"); - is(deck.selectedPanel, pickerPage, "Deck is showing the picker page"); - this.cancelList(); - }, - - cancelList: function lt_cancelList() { - this.win.addEventListener("unload", this.windowClosed, false); - - let cancelButton = this.win.document.getElementById("cancel-button"); - cancelButton.click(); - if (!aOptions.opener) { - // canceling out of the list, should revert back to english ui - let deck = this.win.document.getElementById("language-deck"); - let mainPage = this.win.document.getElementById("main-page"); - is(deck.selectedPanel, mainPage, "Deck is showing the main page again"); - let continueButton = this.win.document.getElementById("continue-in-button"); - ok(/english/i.test(continueButton.textContent), "Cancelling returned the UI to English"); - continueButton.click(); - } - }, - - windowClosed: function lt_windowClosed(aEvent) { - this.checkMainUI(aOptions.selectAddon); - - Services.prefs.clearUserPref("intl.locale.matchOS"); - Services.prefs.clearUserPref("general.useragent.locale"); - window.PreferencesView.hideRestart(); - - if (install) - install.uninstall(); - - runNextTest(); - }, - - checkMainUI: function(aAddon) { - let systemPref = ""; - let userAgentPref = ""; - try { - systemPref = Services.prefs.getBoolPref("intl.locale.matchOS"); - userAgentPref = Services.prefs.getCharPref("general.useragent.locale") - } catch(ex) { } - - let notification = document.getElementById("prefs-messages").getNotificationWithValue("restart-app"); - let showRestart = aAddon ? !aAddon.willFail : false; - is(!!notification, showRestart, "Restart message is " + (showRestart ? "" : "not ") + "shown"); - - // check that locale pref has been updated - let localeName = aAddon ? aAddon.locale : "en-US"; - is(systemPref, false, "Match system locale is false"); - is(userAgentPref, localeName, "User agent locale is " + localeName); - let buttonLabel = aAddon ? aAddon.localeName : "English (US)"; - is(document.getElementById("prefs-uilanguage-button").getAttribute("label"), buttonLabel, "Locale button says " + buttonLabel); - } - } -} - -let invalidInstall = { - name: "Test Locale 0", - installMessage: "INSTALLINGTest Locale 0", - continueButton: "CONTINUE", - cancelButton: "CANCEL", - title: "CHOOSELANGUAGE", - installFailed: "CONTINUE", - locale: "en-US", - localeName: "English (US)", - willFail: true -}; -let validInstall = { - name: "Test Locale 1", - installMessage: "INSTALLINGTest Locale 1", - continueButton: "CONTINUE", - cancelButton: "CANCEL", - title: "CHOOSELANGUAGE", - locale: "test1", - localeName: "test1", - willFail: false -} - -gTests.push(new LocaleTest("Load locale picker with no opener and continue", - { opener: null, - loadLocalesList: false, - selectAddon: null - })); - -gTests.push(new LocaleTest("Load locale picker with no opener and try to install an invalid language", - { opener: null, - loadLocalesList: true, - selectAddon: invalidInstall - })); - -gTests.push(new LocaleTest("Load locale picker with no opener and try to install a valid language", - { opener: null, - loadLocalesList: true, - selectAddon: validInstall - })); - -gTests.push(new LocaleTest("Load locale picker with opener and try to install an invalid language", - { opener: this.window, - loadLocalesList: true, - selectAddon: invalidInstall - })); - -gTests.push(new LocaleTest("Load locale picker with opener and try to install a valid language", - { opener: this.window, - loadLocalesList: true, - selectAddon: validInstall - })); diff --git a/mobile/android/chrome/tests/browser_localepicker_escape.js b/mobile/android/chrome/tests/browser_localepicker_escape.js deleted file mode 100644 index 4968d48c0504..000000000000 --- a/mobile/android/chrome/tests/browser_localepicker_escape.js +++ /dev/null @@ -1,44 +0,0 @@ -Components.utils.import("resource://gre/modules/Services.jsm"); - -var gWin; - -function test() { - waitForExplicitFinish(); - gWin = Services.ww.openWindow(window, "chrome://browser/content/localePicker.xul", "_browser", "chrome,dialog=no,all", null); - gWin.addEventListener("load", onload, false); -} - -function onload(aEvent) { - gWin.removeEventListener("load", onload, false); - ok(true, "Locale picker is opened."); - setTimeout(afterLoad, 0); -} - -function afterLoad() { - let ui = gWin.LocaleUI; - is(ui.selectedPanel, ui.pickerpage, "Picker page is selected."); - - ui.selectedPanel = ui.mainPage; - is(ui.selectedPanel, ui.mainPage, "Select the main page."); - sendEscape(); - is(ui.selectedPanel, ui.mainPage, "Main page is still selected (escape key does nothing)."); - - ui.selectedPanel = ui.installerPage; - is(ui.selectedPanel, ui.installerPage, "Select the installer page."); - sendEscape(); - is(ui.selectedPanel, ui.pickerpage, "Escape key goes back to the picker page."); - - gWin.addEventListener("unload", windowClosed, false); - sendEscape(); -} - -function windowClosed() { - gWin.removeEventListener("unload", windowClosed, false); - ok(true, "Locale picker is closed."); - finish(); -} - -function sendEscape() { - info("Sending escape key."); - EventUtils.synthesizeKey("VK_ESCAPE", { type: "keypress" }, gWin); -} diff --git a/mobile/android/chrome/tests/browser_localerepository.js b/mobile/android/chrome/tests/browser_localerepository.js deleted file mode 100644 index 63de102580bf..000000000000 --- a/mobile/android/chrome/tests/browser_localerepository.js +++ /dev/null @@ -1,39 +0,0 @@ -var localeList = serverRoot + "locales_list.sjs"; -var PREF_LOCALE_LIST = "extensions.getLocales.get.url"; - -Components.utils.import("resource://gre/modules/Services.jsm"); -Components.utils.import("resource://gre/modules/LocaleRepository.jsm"); - -function test() { - waitForExplicitFinish(); - runNextTest(); -} - -function end_test() { - Services.prefs.clearUserPref(PREF_LOCALE_LIST); -} - -registerCleanupFunction(end_test); - -gTests.push({ - desc: "Test getting a list of compatable locales", - run: function() { - Services.prefs.setCharPref(PREF_LOCALE_LIST, localeList); - LocaleRepository.getLocales(this.listLoaded); - }, - - listLoaded: function(aLocales) { - is(aLocales.length, 1, "Correct number of locales were found"); - isnot(aLocales[0].addon, null, "Locale has an addon"); - is(aLocales[0].xpiURL, "http://www.example.com/browser/mobile/chrome/tests/addons/browser_locale1.xpi", "Locale has correct xpi url"); - is(aLocales[0].xpiHash, null, "Locale has correct hash"); - - is(aLocales[0].addon.id, "langpack-test1@firefox-mobile.mozilla.org", "Locale has correct id"); - is(aLocales[0].addon.name, "Test Locale 1", "Locale has correct name"); - is(aLocales[0].addon.type, "language", "Locale has correct type"); - - is(aLocales[0].addon.targetLocale, "test1", "Locale has correct target locale"); - is(aLocales[0].addon.version, "1.0", "Locale has correct version"); - runNextTest(); - } -}); diff --git a/mobile/android/chrome/tests/browser_localerepository_buildid.js b/mobile/android/chrome/tests/browser_localerepository_buildid.js deleted file mode 100644 index 9a3689c565ae..000000000000 --- a/mobile/android/chrome/tests/browser_localerepository_buildid.js +++ /dev/null @@ -1,41 +0,0 @@ -var localeList = serverRoot + "locales_list.sjs"; -var PREF_LOCALE_LIST = "extensions.getLocales.get.url"; - -Components.utils.import("resource://gre/modules/Services.jsm"); -Components.utils.import("resource://gre/modules/LocaleRepository.jsm"); - -function test() { - waitForExplicitFinish(); - runNextTest(); -} - -function end_test() { - Services.prefs.clearUserPref(PREF_LOCALE_LIST); -} - -registerCleanupFunction(end_test); - -gTests.push({ - desc: "Test dynamically changing extensions.getLocales.get.url", - run: function() { - Services.prefs.setCharPref(PREF_LOCALE_LIST, localeList + "?buildid=%BUILDID_EXPANDED%"); - LocaleRepository.getLocales(this.listLoaded.bind(this), {buildID: "00001122334455"}); - }, - - listLoaded: function(aLocales) { - is(aLocales.length, 1, "Correct number of locales were found"); - is(aLocales[0].addon.name, "0000-11-22-33-44-55", "Buildid was correctly replaced"); - - Services.prefs.setCharPref(PREF_LOCALE_LIST, localeList + "?buildid=%BUILDID_EXPANDED%"); - LocaleRepository.getLocales(this.secondListLoaded.bind(this)); - }, - - secondListLoaded: function(aLocales) { - is(aLocales.length, 1, "Correct number of locales were found"); - - let buildID = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo).QueryInterface(Ci.nsIXULRuntime).appBuildID; - is(aLocales[0].addon.name.replace(/-/g, ""), buildID, "Buildid was correctly replaced"); - - runNextTest(); - } -}); diff --git a/mobile/android/chrome/tests/browser_localerepository_pref.js b/mobile/android/chrome/tests/browser_localerepository_pref.js deleted file mode 100644 index bc94c1280fc9..000000000000 --- a/mobile/android/chrome/tests/browser_localerepository_pref.js +++ /dev/null @@ -1,35 +0,0 @@ -var localeList = serverRoot + "locales_list.sjs"; -var PREF_LOCALE_LIST = "extensions.getLocales.get.url"; - -Components.utils.import("resource://gre/modules/Services.jsm"); -Components.utils.import("resource://gre/modules/LocaleRepository.jsm"); - -function test() { - waitForExplicitFinish(); - runNextTest(); -} - -function end_test() { - Services.prefs.clearUserPref(PREF_LOCALE_LIST); -} - -registerCleanupFunction(end_test); - -gTests.push({ - desc: "Test dynamically changing extensions.getLocales.get.url", - run: function() { - Services.prefs.setCharPref(PREF_LOCALE_LIST, localeList); - LocaleRepository.getLocales(this.listLoaded.bind(this)); - }, - - listLoaded: function(aLocales) { - is(aLocales.length, 1, "Correct number of locales were found"); - Services.prefs.setCharPref(PREF_LOCALE_LIST, localeList + "?numvalid=2"); - LocaleRepository.getLocales(this.secondListLoaded.bind(this)); - }, - - secondListLoaded: function(aLocales) { - is(aLocales.length, 2, "Correct number of locales were found"); - runNextTest(); - } -}); diff --git a/mobile/android/chrome/tests/browser_mainui.js b/mobile/android/chrome/tests/browser_mainui.js deleted file mode 100644 index 386858ade07d..000000000000 --- a/mobile/android/chrome/tests/browser_mainui.js +++ /dev/null @@ -1,27 +0,0 @@ -// Very basic tests for the main window UI - -const Cc = Components.classes; -const Ci = Components.interfaces; - -//------------------------------------------------------------------------------ -// Entry point (must be named "test") -function test() { - is(window.location.href, "chrome://browser/content/browser.xul", "Main window should be browser.xul"); - - window.focus(); - - let browser = Browser.selectedBrowser; - isnot(browser, null, "Should have a browser"); - - is(browser.currentURI.spec, Browser.selectedTab.browser.currentURI.spec, "selectedBrowser == selectedTab.browser"); - - testContentContainerSize(); -} - -function testContentContainerSize() { - let container = document.getElementById("content-viewport"); - - let rect = container.getBoundingClientRect(); - is(rect.width, window.innerWidth, "Content container is same width as window"); - is(rect.height, window.innerHeight, "Content container is same height as window"); -} diff --git a/mobile/android/chrome/tests/browser_navigation.js b/mobile/android/chrome/tests/browser_navigation.js deleted file mode 100644 index aa69a0ff7615..000000000000 --- a/mobile/android/chrome/tests/browser_navigation.js +++ /dev/null @@ -1,403 +0,0 @@ -var testURL_01 = chromeRoot + "browser_blank_01.html"; -var testURL_02 = chromeRoot + "browser_blank_02.html"; - -var titleURL = baseURI + "browser_title.sjs?"; -var pngURL = "data:image/gif;base64,R0lGODlhCwALAIAAAAAA3pn/ZiH5BAEAAAEALAAAAAALAAsAAAIUhA+hkcuO4lmNVindo7qyrIXiGBYAOw=="; - -// A queue to order the tests and a handle for each test -var gTests = []; -var gCurrentTest = null; - -var back = document.getElementById("tool-back"); -var forward = document.getElementById("tool-forward"); - -function pageLoaded(aURL) { - return function() { - let tab = gCurrentTest._currentTab; - return !tab.isLoading() && tab.browser.currentURI.spec == aURL; - } -} - -//------------------------------------------------------------------------------ -// Entry point (must be named "test") -function test() { - // The "runNextTest" approach is async, so we need to call "waitForExplicitFinish()" - // We call "finish()" when the tests are finished - waitForExplicitFinish(); - // Start the tests - runNextTest(); -} - -function waitForPageShow(aPageURL, aCallback) { - messageManager.addMessageListener("pageshow", function(aMessage) { - if (aMessage.target.currentURI.spec == aPageURL) { - messageManager.removeMessageListener("pageshow", arguments.callee); - setTimeout(function() { aCallback(); }, 0); - } - }); -}; - -//------------------------------------------------------------------------------ -// Iterating tests by shifting test out one by one as runNextTest is called. -function runNextTest() { - // Run the next test until all tests completed - if (gTests.length > 0) { - gCurrentTest = gTests.shift(); - info(gCurrentTest.desc); - gCurrentTest.run(); - } - else { - // Cleanup. All tests are completed at this point - try { - // Add any cleanup code here - } - finally { - // We must finialize the tests - finish(); - } - } -} - -//------------------------------------------------------------------------------ -// Case: Loading a page into the URLBar with VK_RETURN -gTests.push({ - desc: "Loading a page into the URLBar with VK_RETURN", - _currentTab: null, - - run: function() { - gCurrentTest._currentTab = BrowserUI.newTab(testURL_01); - - // Wait for the tab to load, then do the test - waitFor(gCurrentTest.onPageReady, pageLoaded(testURL_01)); - }, - - onPageReady: function() { - // Test the mode - let urlIcons = document.getElementById("urlbar-icons"); - is(urlIcons.getAttribute("mode"), "view", "URL Mode is set to 'view'"); - - // Test back button state - is(back.disabled, !gCurrentTest._currentTab.browser.canGoBack, "Back button check"); - - // Test forward button state - is(forward.disabled, !gCurrentTest._currentTab.browser.canGoForward, "Forward button check"); - - // Focus the url edit - let urlbarTitle = document.getElementById("urlbar-title"); - - // Wait for the awesomebar to load, then do the test - window.addEventListener("NavigationPanelShown", function() { - window.removeEventListener("NavigationPanelShown", arguments.callee, false); - setTimeout(gCurrentTest.onFocusReady, 0); - }, false); - EventUtils.synthesizeMouse(urlbarTitle, urlbarTitle.width / 2, urlbarTitle.height / 2, {}); - }, - - onFocusReady: function() { - // Test mode - let urlIcons = document.getElementById("urlbar-icons"); - is(urlIcons.getAttribute("mode"), "edit", "URL Mode is set to 'edit'"); - - // Test back button state - is(back.disabled, !gCurrentTest._currentTab.browser.canGoBack, "Back button check"); - - // Test forward button state - is(forward.disabled, !gCurrentTest._currentTab.browser.canGoForward, "Forward button check"); - - // Check button states (url edit is focused) - let search = document.getElementById("tool-search"); - let searchStyle = window.getComputedStyle(search, null); - is(searchStyle.visibility, "visible", "SEARCH is visible"); - - let stop = document.getElementById("tool-stop"); - let stopStyle = window.getComputedStyle(stop, null); - is(stopStyle.visibility, "collapse", "STOP is hidden"); - - let reload = document.getElementById("tool-reload"); - let reloadStyle = window.getComputedStyle(reload, null); - is(reloadStyle.visibility, "collapse", "RELOAD is hidden"); - - // Send the string and press return - EventUtils.synthesizeString(testURL_02, window); - - // It looks like there is a race condition somewhere that result having - // testURL_01 concatenate with testURL_02 as a urlbar value, so to - // workaround that we're waiting for the readonly state to be fully updated - function URLIsReadWrite() { - return BrowserUI._edit.readOnly == false; - } - - waitFor(function() { - // Wait for the tab to load, then do the test - waitFor(gCurrentTest.onPageFinish, pageLoaded(testURL_02)); - - setTimeout(function() { - is(BrowserUI._edit.value, testURL_02, "URL value should be equal to the string sent via synthesizeString"); - EventUtils.synthesizeKey("VK_RETURN", {}, window); - }, 0); - }, URLIsReadWrite); - }, - - onPageFinish: function() { - let urlIcons = document.getElementById("urlbar-icons"); - is(urlIcons.getAttribute("mode"), "view", "URL Mode is set to 'view'"); - - // Check button states (url edit is not focused) - let search = document.getElementById("tool-search"); - let searchStyle = window.getComputedStyle(search, null); - is(searchStyle.visibility, "collapse", "SEARCH is hidden"); - - let stop = document.getElementById("tool-stop"); - let stopStyle = window.getComputedStyle(stop, null); - is(stopStyle.visibility, "collapse", "STOP is hidden"); - - let reload = document.getElementById("tool-reload"); - let reloadStyle = window.getComputedStyle(reload, null); - is(reloadStyle.visibility, "visible", "RELOAD is visible"); - - let uri = gCurrentTest._currentTab.browser.currentURI.spec; - is(uri, testURL_02, "URL Matches newly created Tab"); - - // Go back in session - gCurrentTest._currentTab.browser.goBack(); - - // Wait for the tab to load, then do the test - waitFor(gCurrentTest.onPageBack, pageLoaded(testURL_01)); - }, - - onPageBack: function() { - // Test back button state - is(back.disabled, !gCurrentTest._currentTab.browser.canGoBack, "Back button check"); - - // Test forward button state - is(forward.disabled, !gCurrentTest._currentTab.browser.canGoForward, "Forward button check"); - - BrowserUI.closeTab(gCurrentTest._currentTab); - runNextTest(); - } -}); - -// Bug 611327 ----------------------------------------------------------------- -// Check for urlbar label value -gTests.push({ - desc: "Check for urlbar label value on different cases", - _currentTab: null, - - run: function() { - gCurrentTest._currentTab = BrowserUI.newTab(titleURL + "no_title"); - waitForPageShow(titleURL + "no_title", gCurrentTest.onPageLoadWithoutTitle); - }, - - onPageLoadWithoutTitle: function() { - let urlbarTitle = document.getElementById("urlbar-title"); - is(urlbarTitle.value, titleURL + "no_title", "The title should be equal to the URL"); - - BrowserUI.closeTab(gCurrentTest._currentTab); - - gCurrentTest._currentTab = BrowserUI.newTab(titleURL + "english_title"); - waitForPageShow(titleURL + "english_title", gCurrentTest.onPageLoadWithTitle); - }, - - onPageLoadWithTitle: function() { - let urlbarTitle = document.getElementById("urlbar-title"); - is(urlbarTitle.value, "English Title Page", "The title should be equal to the page title"); - - BrowserUI.closeTab(gCurrentTest._currentTab); - - gCurrentTest._currentTab = BrowserUI.newTab(titleURL + "dynamic_title"); - messageManager.addMessageListener("pageshow", function(aMessage) { - messageManager.removeMessageListener("pageshow", arguments.callee); - gCurrentTest.onBeforePageTitleChanged(); - }); - - messageManager.addMessageListener("DOMTitleChanged", function(aMessage) { - messageManager.removeMessageListener("DOMTitleChanged", arguments.callee); - urlbarTitle.addEventListener("DOMAttrModified", function(aEvent) { - if (aEvent.attrName == "value") { - urlbarTitle.removeEventListener("DOMAttrModified", arguments.callee, false); - setTimeout(gCurrentTest.onPageTitleChanged, 0); - } - }, false); - }); - }, - - onBeforePageTitleChanged: function() { - let urlbarTitle = document.getElementById("urlbar-title"); - isnot(urlbarTitle.value, "This is not a french title", "The title should not be equal to the new page title yet"); - }, - - onPageTitleChanged: function() { - let urlbarTitle = document.getElementById("urlbar-title"); - is(urlbarTitle.value, "This is not a french title", "The title should be equal to the new page title"); - - BrowserUI.closeTab(gCurrentTest._currentTab); - - gCurrentTest._currentTab = BrowserUI.newTab(titleURL + "redirect"); - waitForPageShow(titleURL + "no_title", gCurrentTest.onPageRedirect); - }, - - onPageRedirect: function() { - let urlbarTitle = document.getElementById("urlbar-title"); - is(urlbarTitle.value, gCurrentTest._currentTab.browser.currentURI.spec, "The title should be equal to the redirected page url"); - - BrowserUI.closeTab(gCurrentTest._currentTab); - - gCurrentTest._currentTab = BrowserUI.newTab(titleURL + "location"); - waitForPageShow(titleURL + "no_title", gCurrentTest.onPageLocation); - }, - - onPageLocation: function() { - let urlbarTitle = document.getElementById("urlbar-title"); - is(urlbarTitle.value, gCurrentTest._currentTab.browser.currentURI.spec, "The title should be equal to the relocate page url"); - - BrowserUI.closeTab(gCurrentTest._currentTab); - - // Wait for the awesomebar to load, then do the test - window.addEventListener("NavigationPanelShown", function() { - window.removeEventListener("NavigationPanelShown", arguments.callee, false); - - setTimeout(function() { - EventUtils.synthesizeString(testURL_02, window); - EventUtils.synthesizeKey("VK_RETURN", {}, window); - - waitForPageShow(testURL_02, gCurrentTest.onUserTypedValue); - }, 0); - - }, false); - - gCurrentTest._currentTab = BrowserUI.newTab("about:blank"); - }, - - onUserTypedValue: function() { - let urlbarTitle = document.getElementById("urlbar-title"); - is(urlbarTitle.value, "Browser Blank Page 02", "The title should be equal to the typed page url title"); - - // about:blank has been closed, so we need to close the last selected one - BrowserUI.closeTab(Browser.selectedTab); - - // Wait for the awesomebar to load, then do the test - window.addEventListener("NavigationPanelShown", function() { - window.removeEventListener("NavigationPanelShown", arguments.callee, false); - - EventUtils.synthesizeString("no_title", window); - - // Wait until the no_title result row is here - let popup = document.getElementById("popup_autocomplete"); - let result = null; - function hasResults() { - result = popup._items.childNodes[0]; - if (result) - return result.getAttribute("value") == (titleURL + "no_title"); - - return false; - }; - waitFor(function() { EventUtils.synthesizeMouse(result, result.width / 2, result.height / 2, {}); }, hasResults); - - urlbarTitle.addEventListener("DOMAttrModified", function(aEvent) { - if (aEvent.attrName == "value") { - urlbarTitle.removeEventListener("DOMAttrModified", arguments.callee, false); - is(urlbarTitle.value, titleURL + "no_title", "The title should be equal to the url of the clicked row"); - } - }, false); - - waitForPageShow(titleURL + "no_title", gCurrentTest.onUserSelectValue); - }, false); - - gCurrentTest._currentTab = BrowserUI.newTab("about:blank"); - }, - - onUserSelectValue: function() { - let urlbarTitle = document.getElementById("urlbar-title"); - is(urlbarTitle.value, Browser.selectedTab.browser.currentURI.spec, "The title should be equal to the clicked page url"); - - // about:blank has been closed, so we need to close the last selected one - BrowserUI.closeTab(Browser.selectedTab); - - //is(urlbarTitle.value, "Browser Blank Page 02", "The title of the second page must be displayed"); - runNextTest(); - } -}); - -// Case: Check for appearance of the favicon -gTests.push({ - desc: "Check for appearance of the favicon", - _currentTab: null, - - run: function() { - gCurrentTest._currentTab = BrowserUI.newTab(testURL_01); - waitForPageShow(testURL_01, gCurrentTest.onPageReady); - }, - - onPageReady: function() { - let favicon = document.getElementById("urlbar-favicon"); - is(favicon.src, "", "The default favicon must be loaded"); - BrowserUI.closeTab(gCurrentTest._currentTab); - - gCurrentTest._currentTab = BrowserUI.newTab(testURL_02); - waitForPageShow(testURL_02, gCurrentTest.onPageFinish); - }, - - onPageFinish: function(){ - let favicon = document.getElementById("urlbar-favicon"); - is(favicon.src, pngURL, "The page favicon must be loaded"); - BrowserUI.closeTab(gCurrentTest._currentTab); - runNextTest(); - } -}); - -// Bug 600707 - Back and forward buttons are updated when navigating within a page -// -// These tests use setTimeout instead of waitFor or addEventListener, because -// in-page navigation does not fire any loading events or progress -// notifications, and happens more or less instantly. -gTests.push({ - desc: "Navigating within a page via URI fragments", - _currentTab: null, - - run: function() { - gCurrentTest._currentTab = BrowserUI.newTab(testURL_01); - waitFor(gCurrentTest.onPageReady, pageLoaded(testURL_01)); - }, - - onPageReady: function() { - ok(back.disabled, "Can't go back"); - ok(forward.disabled, "Can't go forward"); - - messageManager.addMessageListener("Content:LocationChange", gCurrentTest.onFragmentLoaded); - Browser.loadURI(testURL_01 + "#fragment"); - }, - - onFragmentLoaded: function() { - messageManager.removeMessageListener("Content:LocationChange", arguments.callee); - - ok(!back.disabled, "Can go back"); - ok(forward.disabled, "Can't go forward"); - - messageManager.addMessageListener("Content:LocationChange", gCurrentTest.onBack); - CommandUpdater.doCommand("cmd_back"); - }, - - onBack: function() { - messageManager.removeMessageListener("Content:LocationChange", arguments.callee); - - ok(back.disabled, "Can't go back"); - ok(!forward.disabled, "Can go forward"); - - messageManager.addMessageListener("Content:LocationChange", gCurrentTest.onForward); - CommandUpdater.doCommand("cmd_forward"); - }, - - onForward: function() { - messageManager.removeMessageListener("Content:LocationChange", arguments.callee); - - ok(!back.disabled, "Can go back"); - ok(forward.disabled, "Can't go forward"); - - gCurrentTest.finish(); - }, - - finish: function() { - BrowserUI.closeTab(gCurrentTest._currentTab); - runNextTest(); - } -}); diff --git a/mobile/android/chrome/tests/browser_preferences_fulltoggle.js b/mobile/android/chrome/tests/browser_preferences_fulltoggle.js deleted file mode 100644 index 9ce68fbe22f9..000000000000 --- a/mobile/android/chrome/tests/browser_preferences_fulltoggle.js +++ /dev/null @@ -1,67 +0,0 @@ -// browser-chrome test for fennec preferences to toggle values while clicking on the preference name - -var gTests = []; -var gCurrentTest = null; - -function test() { - // The "runNextTest" approach is async, so we need to call "waitForExplicitFinish()" - // We call "finish()" when the tests are finished - waitForExplicitFinish(); - - // Start the tests - runNextTest(); -} -//------------------------------------------------------------------------------ -// Iterating tests by shifting test out one by one as runNextTest is called. -function runNextTest() { - // Run the next test until all tests completed - if (gTests.length > 0) { - gCurrentTest = gTests.shift(); - info(gCurrentTest.desc); - gCurrentTest.run(); - } - else { - // Cleanup. All tests are completed at this point - finish(); - } -} - -// ----------------------------------------------------------------------------------------- -// Verify preferences and text -gTests.push({ - desc: "Verify full toggle on Preferences", - - run: function(){ - // 1.Click preferences to view prefs - document.getElementById("tool-panel-open").click(); - is(document.getElementById("panel-container").hidden, false, "Preferences should be visible"); - - var contentRegion = document.getElementById("prefs-content"); - - // Check for *Show images* - var imageRegion = document.getAnonymousElementByAttribute(contentRegion, "pref", "permissions.default.image"); - var imageValue = imageRegion.value; - var imageTitle = document.getAnonymousElementByAttribute(imageRegion, "class", "preferences-title"); - var imageButton = document.getAnonymousElementByAttribute(imageRegion, "anonid", "input"); - - var ibEvent = document.createEvent("MouseEvents"); - ibEvent.initEvent("TapSingle", true, false); - imageButton.dispatchEvent(ibEvent); - is(imageRegion.value, !imageValue, "Tapping on input control should change the value"); - - var itEvent = document.createEvent("MouseEvents"); - itEvent.initEvent("TapSingle", true, false); - imageTitle.dispatchEvent(itEvent); - is(imageRegion.value, imageValue, "Tapping on the title should change the value"); - - var irEvent = document.createEvent("MouseEvents"); - irEvent.initEvent("TapSingle", true, false); - imageRegion.dispatchEvent(irEvent); - is(imageRegion.value, !imageValue, "Tapping on the setting should change the value"); - - BrowserUI.hidePanel(); - is(document.getElementById("panel-container").hidden, true, "Preferences panel should be closed"); - runNextTest(); - } -}); - diff --git a/mobile/android/chrome/tests/browser_preferences_text.js b/mobile/android/chrome/tests/browser_preferences_text.js deleted file mode 100644 index de21f56fd5e0..000000000000 --- a/mobile/android/chrome/tests/browser_preferences_text.js +++ /dev/null @@ -1,131 +0,0 @@ -// Bug 571866 - --browser-chrome test for fennec preferences and text values - -var gTests = []; -var gCurrentTest = null; -var expected = { - "aboutButton": {"tagName": "button", "element_id": "prefs-about-button"}, - "homepage": {"element_id": "prefs-homepage", - "home_page": "prefs-homepage-default", - "blank_page": "prefs-homepage-none", - "current_page": "prefs-homepage-currentpage"}, - "doneButton": {"tagName": "button"}, - "contentRegion": {"element_id": "prefs-content"}, - "imageRegion": {"pref": "permissions.default.image", "anonid": "input", "localName": "checkbox"}, - "jsRegion": {"pref": "javascript.enabled", "anonid": "input", "localName": "checkbox"}, - "privacyRegion": {"element_id": "prefs-privacy" }, - "cookiesRegion": {"pref": "network.cookie.cookieBehavior", "anonid": "input", "localName": "checkbox"}, - "passwordsRegion": {"pref": "signon.rememberSignons", "anonid": "input", "localName": "checkbox"}, - "clearDataButton": {"element_id": "prefs-clear-data", "tagName": "button"} -}; - -function getPreferencesElements() { - let prefElements = {}; - prefElements.panelOpen = document.getElementById("tool-panel-open"); - prefElements.panelContainer = document.getElementById("panel-container"); - prefElements.homeButton = document.getElementById("prefs-homepage-options"); - prefElements.doneButton = document.getElementById("select-buttons-done"); - prefElements.homePageControl = document.getElementById("prefs-homepage"); - prefElements.selectContainer = document.getElementById("menulist-container"); - return prefElements; -} - -function test() { - // The "runNextTest" approach is async, so we need to call "waitForExplicitFinish()" - // We call "finish()" when the tests are finished - waitForExplicitFinish(); - - // Start the tests - runNextTest(); -} -//------------------------------------------------------------------------------ -// Iterating tests by shifting test out one by one as runNextTest is called. -function runNextTest() { - // Run the next test until all tests completed - if (gTests.length > 0) { - gCurrentTest = gTests.shift(); - info(gCurrentTest.desc); - gCurrentTest.run(); - } - else { - // Cleanup. All tests are completed at this point - finish(); - } -} - -// ----------------------------------------------------------------------------------------- -// Verify preferences and text -gTests.push({ - desc: "Verify Preferences and Text", - - run: function(){ - var prefs = getPreferencesElements(); - // 1.Click preferences to view prefs - prefs.panelOpen.click(); - - // 2. For each prefs *verify text *the button/option type *verify height of each field to be the same - is(prefs.panelContainer.hidden, false, "Preferences should be visible"); - - var prefsList = document.getElementById("prefs-messages"); - - // Check for *About page* - let about = expected.aboutButton; - var aboutRegion = document.getAnonymousElementByAttribute(prefsList, "title", "About Fennec"); - var aboutButton = document.getElementById(about.element_id); - is(aboutButton.tagName, about.tagName, "The About Fennec input must be a button"); - - // Check for *Startpage* - let homepage = expected.homepage; - var homepageRegion = document.getElementById(homepage.element_id); - prefs.homeButton.click(); - - is(prefs.selectContainer.hidden, false, "Homepage select dialog must be visible"); - - EventUtils.synthesizeKey("VK_ESCAPE", {}, window); - is(prefs.selectContainer.hidden, true, "Homepage select dialog must be closed"); - - let content = expected.contentRegion; - var contentRegion = document.getElementById(content.element_id); - - // Check for *Show images* - var images = expected.imageRegion; - var imageRegion = document.getAnonymousElementByAttribute(contentRegion, "pref", images.pref); - var imageButton = document.getAnonymousElementByAttribute(imageRegion, "anonid", images.anonid); - is(imageButton.localName, images.localName, "Show images checkbox check"); - // Checkbox or radiobutton? - - // Check for *Enable javascript* - let js = expected.jsRegion; - var jsRegion = document.getAnonymousElementByAttribute(contentRegion, "pref", js.pref); - var jsButton = document.getAnonymousElementByAttribute(jsRegion, "anonid", js.anonid); - is(jsButton.localName, js.localName, "Enable JavaScript checkbox check"); - // Checkbox or radiobutton? - - let privacyRegion = expected.privacyRegion; - var prefsPrivacy = document.getElementById(privacyRegion.element_id); - - // Check for *Allow cookies* - let cookies = expected.cookiesRegion; - var cookiesRegion = document.getAnonymousElementByAttribute(prefsPrivacy, "pref", cookies.pref); - var cookiesButton = document.getAnonymousElementByAttribute(cookiesRegion, "anonid", cookies.anonid); - is(cookiesButton.localName, cookies.localName, "Allow cookies checkbox check"); - // Checkbox or radiobutton? - - // Check for *Remember password* - let passwords = expected.passwordsRegion; - var passwordsRegion = document.getAnonymousElementByAttribute(prefsPrivacy, "pref", passwords.pref); - var passwordsButton = document.getAnonymousElementByAttribute(passwordsRegion, "anonid", passwords.anonid); - is(passwordsButton.localName, passwords.localName, "Allow cookies checkbox check"); - // Checkbox or radiobutton? - - // Check for *Clear Private Data* - let clearData = expected.clearDataButton; - var clearDataRegion = prefsPrivacy.lastChild; - var clearDataButton = document.getElementById(clearData.element_id); - is(clearDataButton.tagName, clearData.tagName, "Check for Clear Private Data button type"); - - BrowserUI.hidePanel(); - is(document.getElementById("panel-container").hidden, true, "Preferences panel should be closed"); - runNextTest(); - } -}); - diff --git a/mobile/android/chrome/tests/browser_rect.js b/mobile/android/chrome/tests/browser_rect.js deleted file mode 100644 index fb8be8cc4d25..000000000000 --- a/mobile/android/chrome/tests/browser_rect.js +++ /dev/null @@ -1,107 +0,0 @@ -function test() { - waitForExplicitFinish(); - - ok(Rect, "Rect class exists"); - - for (let test in tests) { - tests[test](); - } - - finish(); -} - -let tests = { - testGetDimensions: function() { - let r = new Rect(5, 10, 100, 50); - ok(r.left == 5, "rect has correct left value"); - ok(r.top == 10, "rect has correct top value"); - ok(r.right == 105, "rect has correct right value"); - ok(r.bottom == 60, "rect has correct bottom value"); - ok(r.width == 100, "rect has correct width value"); - ok(r.height == 50, "rect has correct height value"); - ok(r.x == 5, "rect has correct x value"); - ok(r.y == 10, "rect has correct y value"); - }, - - testIsEmpty: function() { - let r = new Rect(0, 0, 0, 10); - ok(r.isEmpty(), "rect with nonpositive width is empty"); - let r = new Rect(0, 0, 10, 0); - ok(r.isEmpty(), "rect with nonpositive height is empty"); - let r = new Rect(0, 0, 10, 10); - ok(!r.isEmpty(), "rect with positive dimensions is not empty"); - }, - - testRestrictTo: function() { - let r1 = new Rect(10, 10, 100, 100); - let r2 = new Rect(50, 50, 100, 100); - r1.restrictTo(r2); - ok(r1.equals(new Rect(50, 50, 60, 60)), "intersection is non-empty"); - - let r1 = new Rect(10, 10, 100, 100); - let r2 = new Rect(120, 120, 100, 100); - r1.restrictTo(r2); - ok(r1.isEmpty(), "intersection is empty"); - - let r1 = new Rect(10, 10, 100, 100); - let r2 = new Rect(0, 0, 0, 0); - r1.restrictTo(r2); - ok(r1.isEmpty(), "intersection of rect and empty is empty"); - - let r1 = new Rect(0, 0, 0, 0); - let r2 = new Rect(0, 0, 0, 0); - r1.restrictTo(r2); - ok(r1.isEmpty(), "intersection of empty and empty is empty"); - }, - - testExpandToContain: function() { - let r1 = new Rect(10, 10, 100, 100); - let r2 = new Rect(50, 50, 100, 100); - r1.expandToContain(r2); - ok(r1.equals(new Rect(10, 10, 140, 140)), "correct expandToContain on intersecting rectangles"); - - let r1 = new Rect(10, 10, 100, 100); - let r2 = new Rect(120, 120, 100, 100); - r1.expandToContain(r2); - ok(r1.equals(new Rect(10, 10, 210, 210)), "correct expandToContain on non-intersecting rectangles"); - - let r1 = new Rect(10, 10, 100, 100); - let r2 = new Rect(0, 0, 0, 0); - r1.expandToContain(r2); - ok(r1.equals(new Rect(10, 10, 100, 100)), "expandToContain of rect and empty is rect"); - - let r1 = new Rect(10, 10, 0, 0); - let r2 = new Rect(0, 0, 0, 0); - r1.expandToContain(r2); - ok(r1.isEmpty(), "expandToContain of empty and empty is empty"); - }, - - testSubtract: function testSubtract() { - function equals(rects1, rects2) { - return rects1.length == rects2.length && rects1.every(function(r, i) { - return r.equals(rects2[i]); - }); - } - - let r1 = new Rect(0, 0, 100, 100); - let r2 = new Rect(500, 500, 100, 100); - ok(equals(r1.subtract(r2), [r1]), "subtract area outside of region yields same region"); - - let r1 = new Rect(0, 0, 100, 100); - let r2 = new Rect(-10, -10, 50, 120); - ok(equals(r1.subtract(r2), [new Rect(40, 0, 60, 100)]), "subtracting vertical bar from edge leaves one rect"); - - let r1 = new Rect(0, 0, 100, 100); - let r2 = new Rect(-10, -10, 120, 50); - ok(equals(r1.subtract(r2), [new Rect(0, 40, 100, 60)]), "subtracting horizontal bar from edge leaves one rect"); - - let r1 = new Rect(0, 0, 100, 100); - let r2 = new Rect(40, 40, 20, 20); - ok(equals(r1.subtract(r2), [ - new Rect(0, 0, 40, 100), - new Rect(40, 0, 20, 40), - new Rect(40, 60, 20, 40), - new Rect(60, 0, 40, 100)]), - "subtracting rect in middle leaves union of rects"); - }, -}; diff --git a/mobile/android/chrome/tests/browser_rememberPassword.js b/mobile/android/chrome/tests/browser_rememberPassword.js deleted file mode 100644 index f2708a4b16e8..000000000000 --- a/mobile/android/chrome/tests/browser_rememberPassword.js +++ /dev/null @@ -1,60 +0,0 @@ -var testURL_01 = chromeRoot + "browser_blank_01.html"; - -// Tests for the Remember Password UI - -let gCurrentTab = null; -function test() { - waitForExplicitFinish(); - - messageManager.addMessageListener("pageshow", function() { - if (gCurrentTab.browser.currentURI.spec == testURL_01) { - messageManager.removeMessageListener("pageshow", arguments.callee); - pageLoaded(); - } - }); - - gCurrentTab = Browser.addTab(testURL_01, true); -} - -function pageLoaded() { - let iHandler = getIdentityHandler(); - let iPassword = document.getElementById("pageaction-password"); - let lm = getLoginManager(); - let host = gCurrentTab.browser.currentURI.prePath; - let nullSubmit = createLogin(host, host, null); - let nullForm = createLogin(host, null, "realm"); - - lm.removeAllLogins(); - - iHandler.show(); - is(iPassword.hidden, true, "Remember password hidden for no logins"); - iHandler.hide(); - - lm.addLogin(nullSubmit); - iHandler.show(); - is(iPassword.hidden, false, "Remember password shown for form logins"); - iPassword.click(); - is(iPassword.hidden, true, "Remember password hidden after click"); - is(lm.countLogins(host, "", null), 0, "Logins deleted when clicked"); - iHandler.hide(); - - lm.addLogin(nullForm); - iHandler.show(); - is(iPassword.hidden, false, "Remember password shown for protocol logins"); - iPassword.click(); - is(iPassword.hidden, true, "Remember password hidden after click"); - is(lm.countLogins(host, null, ""), 0, "Logins deleted when clicked"); - iHandler.hide(); - - Browser.closeTab(gCurrentTab); - finish(); -} - -function getLoginManager() { - return Components.classes["@mozilla.org/login-manager;1"].getService(Components.interfaces.nsILoginManager); -} - -function createLogin(aHostname, aFormSubmitURL, aRealm) { - let nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1", Components.interfaces.nsILoginInfo, "init"); - return new nsLoginInfo(aHostname, aFormSubmitURL, aRealm, "username", "password", "uname", "pword"); -} diff --git a/mobile/android/chrome/tests/browser_scroll.html b/mobile/android/chrome/tests/browser_scroll.html deleted file mode 100644 index e0f816a9617c..000000000000 --- a/mobile/android/chrome/tests/browser_scroll.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - scrollTo test - - - - -

    scrollTo test

    -

    The urlbar should scroll out of view after this page loads.

    - - diff --git a/mobile/android/chrome/tests/browser_scroll.js b/mobile/android/chrome/tests/browser_scroll.js deleted file mode 100644 index 5445280589bc..000000000000 --- a/mobile/android/chrome/tests/browser_scroll.js +++ /dev/null @@ -1,19 +0,0 @@ -// Test behavior of window.scrollTo during page load (bug 654122). -"use strict"; - -var gTab; -registerCleanupFunction(function() Browser.closeTab(gTab)); - -const TEST_URL = baseURI + "browser_scroll.html"; - -function test() { - waitForExplicitFinish(); - gTab = Browser.addTab(TEST_URL, true); - onMessageOnce(gTab.browser.messageManager, "Browser:FirstPaint", function() { - executeSoon(function() { - let rect = Elements.browsers.getBoundingClientRect(); - is(rect.top, 0, "Titlebar is hidden."); - finish(); - }); - }); -} diff --git a/mobile/android/chrome/tests/browser_scrollbar.js b/mobile/android/chrome/tests/browser_scrollbar.js deleted file mode 100644 index 231b6fde4c65..000000000000 --- a/mobile/android/chrome/tests/browser_scrollbar.js +++ /dev/null @@ -1,181 +0,0 @@ -let testURL_01 = baseURI + "browser_scrollbar.sjs?"; - -let gCurrentTest = null; -let gTests = []; -let gOpenedTabs = []; // for cleanup - -//------------------------------------------------------------------------------ -// Iterating tests by shifting test out one by one as runNextTest is called. -function runNextTest() { - // Run the next test until all tests completed - if (gTests.length > 0) { - gCurrentTest = gTests.shift(); - info(gCurrentTest.desc); - gCurrentTest.run(); - } - else { - // Close the awesome panel just in case - AwesomeScreen.activePanel = null; - finish(); - } -} - -function waitForPageShow(aPageURL, aCallback) { - messageManager.addMessageListener("pageshow", function(aMessage) { - if (aMessage.target.currentURI.spec == aPageURL) { - messageManager.removeMessageListener("pageshow", arguments.callee); - - setTimeout(aCallback, 0); - } - }); -}; - -//------------------------------------------------------------------------------ -// Entry point (must be named "test") -function test() { - // This test is async - waitForExplicitFinish(); - runNextTest(); -} - -let horizontalScrollbar = document.getElementById("horizontal-scroller"); -let verticalScrollbar = document.getElementById("vertical-scroller"); - -function checkScrollbars(aHorizontalVisible, aVerticalVisible, aHorizontalPosition, aVerticalPosition) { - let browser = getBrowser(); - let width = browser.getBoundingClientRect().width; - let height = browser.getBoundingClientRect().height; - EventUtils.synthesizeMouse(browser, width / 2, height / 4, { type: "mousedown" }); - EventUtils.synthesizeMouse(browser, width / 2, height * 3 / 4, { type: "mousemove" }); - - let horizontalVisible = horizontalScrollbar.hasAttribute("panning"), - verticalVisible = verticalScrollbar.hasAttribute("panning"); - is(horizontalVisible, aHorizontalVisible, "The horizontal scrollbar should be " + (aHorizontalVisible ? "visible" : "hidden")); - is(verticalVisible, aVerticalVisible, "The vertical scrollbar should be " + (aVerticalVisible ? "visible" : "hidden")); - - EventUtils.synthesizeMouse(browser, width / 2, height * 3 / 4, { type: "mouseup" }); -} - -function checkScrollbarsPosition(aX) { - let browser = getBrowser(); - let width = browser.getBoundingClientRect().width; - let height = browser.getBoundingClientRect().height; - EventUtils.synthesizeMouse(browser, width / 2, height / 4, { type: "mousedown" }); - EventUtils.synthesizeMouse(browser, width / 2, height * 3 / 4, { type: "mousemove" }); - - let verticalRect = verticalScrollbar.getBoundingClientRect(); - let margin = parseInt(verticalScrollbar.getAttribute("end")); - let matches = verticalScrollbar.style.MozTransform.match(/^translate\(([-0-9]+)px/); - let translateX = matches ? parseInt(matches[1]) : 0; - let expectedPosition = window.innerWidth - aX - margin + translateX; - is(verticalRect.right, expectedPosition, "The vertical scrollbar should be position to " + expectedPosition + " (got " + verticalRect.right + ")"); - - EventUtils.synthesizeMouse(browser, width / 2, height * 3 / 4, { type: "mouseup" }); -} - -gTests.push({ - desc: "Testing visibility of scrollbars", - - run: function() { - waitForPageShow(testURL_01 + "blank", gCurrentTest.checkNotScrollable); - gOpenedTabs.push(Browser.addTab(testURL_01 + "blank", true)); - }, - - checkNotScrollable: function() { - checkScrollbars(false, false); - - waitForPageShow(testURL_01 + "horizontal", gCurrentTest.checkHorizontalScrollable); - gOpenedTabs.push(Browser.addTab(testURL_01 + "horizontal", true)); - }, - - checkHorizontalScrollable: function() { - checkScrollbars(true, false); - - waitForPageShow(testURL_01 + "vertical", gCurrentTest.checkVerticalScrollable); - gOpenedTabs.push(Browser.addTab(testURL_01 + "vertical", true)); - }, - - checkVerticalScrollable: function() { - checkScrollbars(false, true); - - waitForPageShow(testURL_01 + "both", gCurrentTest.checkBothScrollable); - gOpenedTabs.push(Browser.addTab(testURL_01 + "both", true)); - }, - - checkBothScrollable: function() { - checkScrollbars(true, true); - Elements.browsers.addEventListener("PanFinished", function(aEvent) { - Elements.browsers.removeEventListener("PanFinished", arguments.callee, false); - setTimeout(function() { - Browser.hideSidebars(); - }, 0); - runNextTest(); - }, false); - } -}); - -gTests.push({ - desc: "Testing position of scrollbars", - - run: function() { - waitForPageShow(testURL_01 + "vertical", gCurrentTest.checkScrollbarsPosition); - gOpenedTabs.push(Browser.addTab(testURL_01 + "vertical", true)); - }, - - checkScrollbarsPosition: function() { - let [,, tabsWidth, controlsWidth] = Browser.computeSidebarVisibility(); - - checkScrollbarsPosition(0); - - // Show the left sidebar and ensure scrollbar is visible - Browser.controlsScrollboxScroller.scrollTo(0, 0); - checkScrollbarsPosition(-tabsWidth); - - // Show the right sidebar and ensure scrollbar is visible - Browser.controlsScrollboxScroller.scrollTo(tabsWidth + controlsWidth, 0); - checkScrollbarsPosition(controlsWidth); - - gCurrentTest.finish(); - }, - - finish: function() { - Elements.browsers.addEventListener("PanFinished", function(aEvent) { - Elements.browsers.removeEventListener("PanFinished", arguments.callee, false); - setTimeout(function() { - Browser.hideSidebars(); - }, 0); - runNextTest(); - }, false); - } -}); - - -gTests.push({ - desc: "Check scrollbar visibility when the touch sequence is cancelled", - - run: function() { - waitForPageShow(testURL_01 + "both", gCurrentTest.checkVisibility); - gOpenedTabs.push(Browser.addTab(testURL_01 + "both", true)); - }, - - checkVisibility: function() { - let browser = getBrowser(); - let width = browser.getBoundingClientRect().width; - let height = browser.getBoundingClientRect().height; - EventUtils.synthesizeMouse(browser, width / 2, height / 4, { type: "mousedown" }); - EventUtils.synthesizeMouse(browser, width / 2, height * 3 / 4, { type: "mousemove" }); - - let event = document.createEvent("Events"); - event.initEvent("CancelTouchSequence", true, false); - document.dispatchEvent(event); - - let horizontalVisible = horizontalScrollbar.hasAttribute("panning"), - verticalVisible = verticalScrollbar.hasAttribute("panning"); - is(horizontalVisible, false, "The horizontal scrollbar should be hidden when a canceltouchsequence is fired"); - is(verticalVisible, false, "The vertical scrollbar should be hidden should be hidden when a canceltouchsequence is called"); - - for (let iTab=0; iTab"); - response.write(""); - - let body = "" + query + ""; - switch (query) { - case "blank": - response.write("This is a not a scrollable page"); - break; - case "horizontal": - response.write("This is a horizontally scrollable page"); - body += "\n
    Browser scrollbar test
    "; - break; - case "vertical": - response.write("This is a vertically scrollable page"); - body += "\n
    Browser scrollbar test
    "; - break; - case "both": - response.write("This is a scrollable page in both directions"); - body += "\n
    Browser scrollbar test
    "; - break; - default: - break; - } - response.write("" + body + ""); -} diff --git a/mobile/android/chrome/tests/browser_select.html b/mobile/android/chrome/tests/browser_select.html deleted file mode 100644 index 4de8ead4e201..000000000000 --- a/mobile/android/chrome/tests/browser_select.html +++ /dev/null @@ -1,99 +0,0 @@ - -Browser Blank Page 01 - - - -
    - onchange: (selectedIndex) [value] -
    - - -
    - - - -
    -
    - - -
    - onchange: (selectedIndex) [value] -
    - - -
    -
    - - -
    -
    - -
    OptGroup Combobox:
    - -
    -
    - - -
    - -
    
    -
    -
    -
    diff --git a/mobile/android/chrome/tests/browser_select.js b/mobile/android/chrome/tests/browser_select.js
    deleted file mode 100644
    index ccf0fd29959b..000000000000
    --- a/mobile/android/chrome/tests/browser_select.js
    +++ /dev/null
    @@ -1,87 +0,0 @@
    -let testURL = chromeRoot + "browser_select.html";
    -let new_tab = null;
    -
    -//------------------------------------------------------------------------------
    -// Entry point (must be named "test")
    -function test() {
    -  // This test is async
    -  waitForExplicitFinish();
    -
    -  // Add new tab to hold the 
    -  
    -
    -  
    - -
    - - - diff --git a/mobile/android/chrome/tests/browser_tapping.js b/mobile/android/chrome/tests/browser_tapping.js deleted file mode 100644 index 12c203a9e651..000000000000 --- a/mobile/android/chrome/tests/browser_tapping.js +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Testing the tapping interactions: - * single tap, double tap & long tap - */ - -let testURL = chromeRoot + "browser_tap_content.html"; - -let gTests = []; -let gCurrentTest = null; -let gCurrentTab; - -const kDoubleClickIntervalPlus = kDoubleClickInterval + 100; - -let gEvents = []; -function dumpEvents(aEvent) { - if (aEvent.target != gCurrentTab.browser.parentNode) - return; - - gEvents.push(aEvent.type); -} - -function clearEvents() { - gEvents = []; -} - -function checkEvents(aEvents) { - if (aEvents.length != gEvents.length) { - info("---- event check: failed length (" + aEvents.length + " != " + gEvents.length + ")\n"); - info("---- expected: [" + aEvents.join(",") + "] actual: [" + gEvents.join(",") + "]\n"); - return false; - } - - for (let i=0; i 0) { - gCurrentTest = gTests.shift(); - info(gCurrentTest.desc); - gCurrentTest.run(); - } - else { - window.removeEventListener("TapSingle", dumpEvents, true); - window.removeEventListener("TapDouble", dumpEvents, true); - window.removeEventListener("TapLong", dumpEvents, true); - - SelectionHelper.enabled = true; - Browser.closeTab(gCurrentTab); - - finish(); - } -} - -//------------------------------------------------------------------------------ -// Case: Test the double tap behavior -gTests.push({ - desc: "Test the double tap behavior", - - run: function() { - let inputHandler = gCurrentTab.browser.parentNode; - let width = inputHandler.getBoundingClientRect().width; - let height = inputHandler.getBoundingClientRect().height; - - // Should fire "TapSingle" - info("Test good single tap"); - clearEvents(); - EventUtils.synthesizeMouse(document.documentElement, width / 2, height / 2, {}); - - // We wait a bit because of the delay allowed for double clicking on device - // where it is not native - setTimeout(function() { - ok(checkEvents(["TapSingle"]), "Fired a good single tap"); - clearEvents(); - gCurrentTest.doubleTapTest(); - }, kDoubleClickIntervalPlus); - }, - - doubleTapTest: function() { - let inputHandler = gCurrentTab.browser.parentNode; - let width = inputHandler.getBoundingClientRect().width; - let height = inputHandler.getBoundingClientRect().height; - - // Should fire "TapDouble" - info("Test good double tap"); - clearEvents(); - EventUtils.synthesizeMouse(document.documentElement, width / 2, height / 2, {}); - EventUtils.synthesizeMouse(document.documentElement, width / 2, height / 2, {}); - - setTimeout(function() { - let sysInfo = Cc["@mozilla.org/system-info;1"].getService(Ci.nsIPropertyBag2); - if (sysInfo.get("device")) - todo(checkEvents(["TapDouble"]), "Fired a good double tap"); - else - ok(checkEvents(["TapDouble"]), "Fired a good double tap"); - - clearEvents(); - - gCurrentTest.doubleTapFailTest(); - }, kDoubleClickIntervalPlus); - }, - - doubleTapFailTest: function() { - let inputHandler = gCurrentTab.browser.parentNode; - let width = inputHandler.getBoundingClientRect().width; - let height = inputHandler.getBoundingClientRect().height; - - // Should fire "TapSingle", "TapSingle" - info("Test two single taps in different locations"); - clearEvents(); - EventUtils.synthesizeMouse(document.documentElement, width / 3, height / 3, {}); - EventUtils.synthesizeMouse(document.documentElement, width * 2 / 3, height * 2 / 3, {}); - - setTimeout(function() { - ok(checkEvents(["TapSingle", "TapSingle"]), "Fired two single taps in different places, not a double tap"); - clearEvents(); - - gCurrentTest.tapPanTest(); - }, 500); - }, - - tapPanTest: function() { - let inputHandler = gCurrentTab.browser.parentNode; - let width = inputHandler.getBoundingClientRect().width; - let height = inputHandler.getBoundingClientRect().height; - - info("Test a pan - non-tap event"); - clearEvents(); - EventUtils.synthesizeMouse(document.documentElement, width / 2, height / 3, { type: "mousedown" }); - EventUtils.synthesizeMouse(document.documentElement, width / 2, height * 2 / 3, { type: "mousemove" }); - EventUtils.synthesizeMouse(document.documentElement, width / 2, height * 2 / 3, { type: "mouseup" }); - ok(checkEvents([]), "Fired a pan which should be seen as a non event"); - clearEvents(); - - setTimeout(function() { gCurrentTest.longTapFailTest(); }, 500); - }, - - longTapFailTest: function() { - let inputHandler = gCurrentTab.browser.parentNode; - let width = inputHandler.getBoundingClientRect().width; - let height = inputHandler.getBoundingClientRect().height; - - info("Test a long pan - non-tap event"); - clearEvents(); - EventUtils.synthesizeMouse(document.documentElement, width / 2, height / 3, { type: "mousedown" }); - EventUtils.synthesizeMouse(document.documentElement, width / 2, height * 2 / 3, { type: "mousemove" }); - setTimeout(function() { - EventUtils.synthesizeMouse(document.documentElement, width / 2, height * 2 / 3, { type: "mouseup" }); - ok(checkEvents([]), "Fired a pan + delay which should be seen as a non-event"); - clearEvents(); - - window.addEventListener("PanFinished", function() { - window.removeEventListener("PanFinished", arguments.callee, true); - setTimeout(gCurrentTest.longTapPassTest, 0); - }, true); - }, 500); - }, - - longTapPassTest: function() { - let browser = gCurrentTab.browser; - let inputHandler = browser.parentNode; - let width = inputHandler.getBoundingClientRect().width; - let height = inputHandler.getBoundingClientRect().height; - - window.addEventListener("TapLong", function() { - window.removeEventListener("TapLong", arguments.callee, true); - EventUtils.synthesizeMouse(document.documentElement, width / 2, height / 2, { type: "mouseup" }); - ok(checkEvents(["TapLong"]), "Fired a good long tap"); - clearEvents(); - }, true); - - browser.messageManager.addMessageListener("Browser:ContextMenu", function(aMessage) { - browser.messageManager.removeMessageListener(aMessage.name, arguments.callee); - setTimeout(gCurrentTest.contextPlainLinkTest, 0); - }); - - info("Test a good long pan"); - clearEvents(); - EventUtils.synthesizeMouse(document.documentElement, width / 2, height / 2, { type: "mousedown" }); - }, - - contextPlainLinkTest: function() { - waitForContextMenu(function(aJSON) { - is(aJSON.linkTitle, "A blank page - nothing interesting", "Text content should be the content of the second link"); - ok(checkContextTypes(["link", "link-openable"]), "Plain link context types"); - }, gCurrentTest.contextPlainImageTest); - - let browser = gCurrentTab.browser; - let linkDisabled = browser.contentDocument.getElementById("link-disabled"); - let event = content.document.createEvent("PopupEvents"); - event.initEvent("contextmenu", true, true); - linkDisabled.dispatchEvent(event); - - let link = browser.contentDocument.getElementById("link-single"); - let event = content.document.createEvent("PopupEvents"); - event.initEvent("contextmenu", true, true); - link.dispatchEvent(event); - }, - - contextPlainImageTest: function() { - waitForContextMenu(function() { - ok(checkContextTypes(["image","image-shareable","image-loaded", "content-text"]), "Plain image context types"); - }, gCurrentTest.contextNestedImageTest); - - let browser = gCurrentTab.browser; - let img = browser.contentDocument.getElementById("img-single"); - let event = content.document.createEvent("PopupEvents"); - event.initEvent("contextmenu", true, true); - img.dispatchEvent(event); - }, - - contextNestedImageTest: function() { - waitForContextMenu(function() { - ok(checkContextTypes(["link","image","image-shareable","image-loaded","link-openable"]), "Nested image context types"); - }, runNextTest); - - let browser = gCurrentTab.browser; - let img = browser.contentDocument.getElementById("img-nested"); - let event = content.document.createEvent("PopupEvents"); - event.initEvent("contextmenu", true, true); - img.dispatchEvent(event); - } -}); - diff --git a/mobile/android/chrome/tests/browser_tapping_edit.js b/mobile/android/chrome/tests/browser_tapping_edit.js deleted file mode 100644 index b1e4c139a476..000000000000 --- a/mobile/android/chrome/tests/browser_tapping_edit.js +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Testing the context menus on editboxes: - * plain and url - */ - -let testURL = chromeRoot + "browser_tap_contentedit.html"; - -let gTests = []; -let gCurrentTest = null; -let gCurrentTab; - -const kDoubleClickIntervalPlus = kDoubleClickInterval + 100; - -let gEvents = []; -function dumpEvents(aEvent) { - if (aEvent.target != gCurrentTab.browser.parentNode) - return; - - gEvents.push(aEvent.type); -} - -function clearEvents() { - gEvents = []; -} - -function checkEvents(aEvents) { - if (aEvents.length != gEvents.length) { - info("---- event check: failed length (" + aEvents.length + " != " + gEvents.length + ")\n"); - info("---- expected: [" + aEvents.join(",") + "] actual: [" + gEvents.join(",") + "]\n"); - return false; - } - - for (let i=0; i 0) { - gCurrentTest = gTests.shift(); - info(gCurrentTest.desc); - gCurrentTest.run(); - } - else { - let clipboard = Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard); - clipboard.emptyClipboard(Ci.nsIClipboard.kGlobalClipboard); - - window.removeEventListener("TapSingle", dumpEvents, true); - window.removeEventListener("TapDouble", dumpEvents, true); - window.removeEventListener("TapLong", dumpEvents, true); - - SelectionHelper.enabled = true; - Browser.closeTab(gCurrentTab); - - finish(); - } -} - -//------------------------------------------------------------------------------ -gTests.push({ - desc: "Test empty plain textbox", - - run: function() { - waitForContextMenu(function(aJSON) { - ok(checkContextTypes(["input-text"]), "Editbox with no text, no selection and no clipboard"); - }, runNextTest); - - let browser = gCurrentTab.browser; - let plainEdit = browser.contentDocument.getElementById("plain-edit"); - plainEdit.readOnly = false; - plainEdit.value = ""; - - // Try very hard to keep "paste" from if the clipboard has data - let clipboard = Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard); - clipboard.emptyClipboard(Ci.nsIClipboard.kGlobalClipboard); - plainEdit.readOnly = true; - - let event = content.document.createEvent("PopupEvents"); - event.initEvent("contextmenu", true, true); - plainEdit.dispatchEvent(event); - } -}); - -//------------------------------------------------------------------------------ -gTests.push({ - desc: "Test plain textbox with text fully selected", - - run: function() { - waitForContextMenu(function(aJSON) { - ok(checkContextTypes(["input-text", "copy"]), "Editbox with text and full selection, but no clipboard"); - }, runNextTest); - - let browser = gCurrentTab.browser; - let plainEdit = browser.contentDocument.getElementById("plain-edit"); - plainEdit.readOnly = false; - plainEdit.value = "Every time we fix a bug, Stuart call's the President"; - let plainEdit = plainEdit.QueryInterface(Ci.nsIDOMNSEditableElement); - plainEdit.editor.selectAll(); - - // Try very hard to keep "paste" from if the clipboard has data - let clipboard = Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard); - clipboard.emptyClipboard(Ci.nsIClipboard.kGlobalClipboard); - plainEdit.readOnly = true; - - let event = content.document.createEvent("PopupEvents"); - event.initEvent("contextmenu", true, true); - plainEdit.dispatchEvent(event); - } -}); - -//------------------------------------------------------------------------------ -gTests.push({ - desc: "Test plain textbox with text no selection", - - run: function() { - waitForContextMenu(function(aJSON) { - ok(checkContextTypes(["input-text", "copy-all", "select-all"]), "Editbox with text, but no selection and no clipboard"); - }, runNextTest); - - let browser = gCurrentTab.browser; - let plainEdit = browser.contentDocument.getElementById("plain-edit"); - plainEdit.readOnly = false; - plainEdit.value = "Every time we fix a bug, Stuart call's the President"; - plainEdit.selectionStart = 0; - plainEdit.selectionEnd = 0; - - // Try very hard to keep "paste" from if the clipboard has data - let clipboard = Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard); - clipboard.emptyClipboard(Ci.nsIClipboard.kGlobalClipboard); - plainEdit.readOnly = true; - - let event = content.document.createEvent("PopupEvents"); - event.initEvent("contextmenu", true, true); - plainEdit.dispatchEvent(event); - } -}); - -//------------------------------------------------------------------------------ -gTests.push({ - desc: "Test plain textbox with text no selection and text on clipboard", - - run: function() { - waitForContextMenu(function(aJSON) { - ok(checkContextTypes(["input-text", "copy-all", "select-all", "paste"]), "Editbox with text and clipboard, but no selection"); - }, runNextTest); - - let browser = gCurrentTab.browser; - let plainEdit = browser.contentDocument.getElementById("plain-edit"); - plainEdit.readOnly = false; - plainEdit.value = "Every time we fix a bug, Stuart call's the President"; - plainEdit.selectionStart = 0; - plainEdit.selectionEnd = 0; - - // Put some data on the clipboard to get "paste" to be active - let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper); - clipboard.copyString("We are testing Firefox"); - - let event = content.document.createEvent("PopupEvents"); - event.initEvent("contextmenu", true, true); - plainEdit.dispatchEvent(event); - } -}); - -//------------------------------------------------------------------------------ -gTests.push({ - desc: "Test that tapping on input box causes mouse events to fire", - - run: function() { - let browser = gCurrentTab.browser; - let plainEdit = browser.contentDocument.getElementById("plain-edit"); - plainEdit.blur(); - plainEdit.value = ''; - - let eventArray = ['mouseover', 'mousedown', 'mouseup', 'click']; - - while (eventArray.length > 0) { - let currentEventType = eventArray.shift(); - browser.contentWindow.addEventListener(currentEventType, function(e) { - browser.contentWindow.removeEventListener(currentEventType, arguments.callee, true); - ok(e.target == plainEdit, e.type + " should fire over input id=" + plainEdit.id); - plainEdit.value += e.type + ' '; - - if (e.type == 'click') { - ok(plainEdit.value == 'mouseover mousedown mouseup click ', - 'Events should fire in this order: mouseover mousedown mouseup click '); - runNextTest(); - } - } , true); - } - - EventUtils.synthesizeMouse(plainEdit, browser.getBoundingClientRect().left + plainEdit.getBoundingClientRect().left + 2, - browser.getBoundingClientRect().top + plainEdit.getBoundingClientRect().top + 2, {}); - } -}); - diff --git a/mobile/android/chrome/tests/browser_test.js b/mobile/android/chrome/tests/browser_test.js deleted file mode 100644 index c0a987eb4c04..000000000000 --- a/mobile/android/chrome/tests/browser_test.js +++ /dev/null @@ -1,20 +0,0 @@ -// Tests for the test functions in head.js - -function test() { - waitForExplicitFinish(); - testWaitForAndContinue(); -} - -function testWaitForAndContinue() { - waitForAndContinue(function() { - ok(true, "continues on success") - testWaitForAndContinue2(); - }, function() true); -} - -function testWaitForAndContinue2() { - waitForAndContinue(function() { - ok(true, "continues on failure"); - finish(); - }, function() false); -} diff --git a/mobile/android/chrome/tests/browser_thumbnails.js b/mobile/android/chrome/tests/browser_thumbnails.js deleted file mode 100644 index 59ac82d731e0..000000000000 --- a/mobile/android/chrome/tests/browser_thumbnails.js +++ /dev/null @@ -1,155 +0,0 @@ -// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*- -/* - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Mobile Browser. - * - * The Initial Developer of the Original Code is - * Mozilla Corporation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Wes Johnston - * - * 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 ***** */ - -let testURL_blank = baseURI + "browser_blank_01.html"; - -const DEFAULT_WIDTH = 800; - -function testURL(n) { - if (n < 0) - return testURL_blank; - - return baseURI + "browser_viewport.sjs?" + encodeURIComponent(gTestData[n].metadata); -} - -function scaleRatio(n) { - if ("scaleRatio" in gTestData[n]) - return gTestData[n].scaleRatio; - return 150; // Default value matches our main target hardware (N900, Nexus One, etc.) -} - -let currentTab; - -let loadURL = function loadURL(aPageURL) { - BrowserUI.goToURI(aPageURL); -}; - -let gTestData = [ - { metadata: "", width: DEFAULT_WIDTH, scale: 1 }, - { metadata: "width=device-width, initial-scale=1" }, - { metadata: "width=device-width" }, - { metadata: "width=320, initial-scale=1" }, - { metadata: "initial-scale=1.0, user-scalable=no" }, - { metadata: "width=200,height=500" }, - { metadata: "width=2000, minimum-scale=0.75" }, - { metadata: "width=100, maximum-scale=2.0" }, - { metadata: "width=2000, initial-scale=0.75" }, - { metadata: "width=20000, initial-scale=100" }, - { metadata: "XHTML" }, - /* testing opening and switching between pages without a viewport */ - { metadata: "style=width:400px;margin:0px;" }, - { metadata: "style=width:1000px;margin:0px;" }, - { metadata: "style=width:800px;margin:0px;" }, - { metadata: "style=width:800px;height:300px;margin:0px;" }, - { metadata: "style=width:800px;height:1000px;margin:0px;" }, -]; - - - -//------------------------------------------------------------------------------ -// Entry point (must be named "test") -let gCurrentTest = -1; -let secondPass = false; -let oldRendererFactory; -let gDevice = null; -function test() { - oldRendererFactory = rendererFactory; - rendererFactory = newRendererFactory; - - // if we are on desktop, we can run tests in both portrait and landscape modes - // on devices we should just use the current orientation - let sysInfo = Cc["@mozilla.org/system-info;1"].getService(Ci.nsIPropertyBag2); - gDevice = sysInfo.get("device"); - if (gDevice != null) - secondPass = true; - - // This test is async - waitForExplicitFinish(); - - currentTab = Browser.addTab("about:blank", true); - ok(currentTab, "Tab Opened"); - - startTest(gCurrentTest); -} - -function startTest(n) { - let url = testURL(gCurrentTest); - info("Testing: " + url) - loadURL(url); -} - -function newRendererFactory(aBrowser, aCanvas) { - let wrapper = {}; - let ctx = aCanvas.MozGetIPCContext("2d"); - let draw = function(browser, aLeft, aTop, aWidth, aHeight, aColor, aFlags) { - is(aLeft, 0,"Thumbnail drawn at x=0"); - is(aTop, 0,"Thumbnail drawn at y=0"); - ok(aWidth <= browser.contentDocumentWidth, "Thumbnail ok width: " + aWidth + " <= " + browser.contentDocumentWidth); - ok(aHeight <= browser.contentDocumentHeight,"Thumbnail ok height:" + aHeight + " <= " + browser.contentDocumentHeight); - finishTest(); - }; - wrapper.checkBrowser = function(browser) { - return browser.contentWindow; - }; - wrapper.drawContent = function(callback) { - callback(ctx, draw); - }; - - return wrapper; -}; - -function finishTest() { - gCurrentTest++; - if (gCurrentTest < gTestData.length) { - startTest(gCurrentTest); - } else if (secondPass) { - - if (gDevice == null) - window.top.resizeTo(480,800); - - Browser.closeTab(currentTab); - rendererFactory = oldRendererFactory; - finish(); - } else { - secondPass = true; - gCurrentTest = -1; - window.top.resizeTo(800,480); - startTest(gCurrentTest); - } -} diff --git a/mobile/android/chrome/tests/browser_title.sjs b/mobile/android/chrome/tests/browser_title.sjs deleted file mode 100644 index a523c1de5de6..000000000000 --- a/mobile/android/chrome/tests/browser_title.sjs +++ /dev/null @@ -1,67 +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 Mozilla Mobile Browser. - * - * The Initial Developer of the Original Code is - * Mozilla Corporation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Aditya Rao - * Vivien Nicolas <21@vingtetun.org> - * - * 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 ***** */ - -function handleRequest(request, response) { - response.setStatusLine(request.httpVersion, 200, "OK"); - response.setHeader("Content-Type", "text/html", false); - - let action = ""; - let query = decodeURIComponent(request.queryString || ""); - response.write(""); - - switch (query) { - case "no_title": - break; - case "english_title": - response.write("English Title Page"); - break; - case "dynamic_title": - response.write("This is an english title page"); - response.write(""); - break; - case "redirect": - response.write(""); - break; - case "location": - response.write(""); - break; - default: - break; - } - response.write("" + query + ""); -} diff --git a/mobile/android/chrome/tests/browser_upgrade.rdf b/mobile/android/chrome/tests/browser_upgrade.rdf deleted file mode 100644 index bfde13200e03..000000000000 --- a/mobile/android/chrome/tests/browser_upgrade.rdf +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - -
  • - - 2.0 - - - toolkit@mozilla.org - 0 - * - http://example.com/browser/mobile/chrome/tests/addons/browser_install1_3.xpi - - - -
  • -
    -
    -
    - - - - -
  • - - 1.0 - - - mochikit@mozilla.org - 0 - * - - - -
  • -
    -
    -
    - -
    diff --git a/mobile/android/chrome/tests/browser_viewport.js b/mobile/android/chrome/tests/browser_viewport.js deleted file mode 100644 index bb95cc2eb6d2..000000000000 --- a/mobile/android/chrome/tests/browser_viewport.js +++ /dev/null @@ -1,209 +0,0 @@ -// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*- -/* - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Mobile Browser. - * - * The Initial Developer of the Original Code is - * Mozilla Corporation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Mark Finkle - * Matt Brubeck - * - * 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 ***** */ - -let testURL_blank = baseURI + "browser_blank_01.html"; - -const DEFAULT_WIDTH = 800; - -function testURL(n) { - return baseURI + "browser_viewport.sjs" + - "?metadata=" + encodeURIComponent(gTestData[n].metadata || "") + - "&style=" + encodeURIComponent(gTestData[n].style || "") + - "&xhtml=" + encodeURIComponent(!!gTestData[n].xhtml); -} - -function scaleRatio(n) { - if ("scaleRatio" in gTestData[n]) - return gTestData[n].scaleRatio; - return 150; // Default value matches our main target hardware (N900, Nexus One, etc.) -} - -let currentTab; - -let loadURL = function loadURL(aPageURL, aCallback, aScale) { - messageManager.addMessageListener("pageshow", function(aMessage) { - if (aMessage.target.currentURI.spec == aPageURL) { - messageManager.removeMessageListener(aMessage.name, arguments.callee); - - waitFor(aCallback, function() { - return !aScale || aScale == aMessage.target.scale; - }); - } - }); - - BrowserUI.goToURI(aPageURL); -}; - -// XXX Tests do not yet run correctly in portrait. -window.resizeTo(800, 480); - -let gTestData = [ - { metadata: "", width: DEFAULT_WIDTH, scale: 1 }, - { metadata: "width=device-width, initial-scale=1", width: 533.33, scale: 1.5 }, - { metadata: "width=device-width", width: 533.33, scale: 1.5 }, - { metadata: "width=device-width, initial-scale=1", scaleRatio: 100, width: 800, scale: 1 }, - { metadata: "width=320, initial-scale=1", width: 533.33, scale: 1.5 }, - { metadata: "initial-scale=1.0, user-scalable=no", width: 533.33, scale: 1.5, disableZoom: true }, - { metadata: "initial-scale=1.0, user-scalable=0", width: 533.33, scale: 1.5, disableZoom: true }, - { metadata: "initial-scale=1.0, user-scalable=false", width: 533.33, scale: 1.5, disableZoom: true }, - { metadata: "initial-scale=1.0, user-scalable=NO", width: 533.33, scale: 1.5, disableZoom: false }, // values are case-sensitive - { metadata: "width=200,height=500", width: 200, scale: 4 }, - { metadata: "width=2000, minimum-scale=0.75", width: 2000, scale: 1.125, minScale: 1.125 }, - { metadata: "width=100, maximum-scale=2.0", width: 266.67, scale: 3, maxScale: 3 }, - { metadata: "width=2000, initial-scale=0.75", width: 2000, scale: 1.125 }, - { metadata: "width=20000, initial-scale=100", width: 10000, scale: 4 }, - { xhtml: true, width: 533.33, scale: 1.5, disableZoom: false }, - /* testing spaces between arguments (bug 572696) */ - { metadata: "width= 2000, minimum-scale=0.75", width: 2000, scale: 1.125 }, - { metadata: "width = 2000, minimum-scale=0.75", width: 2000, scale: 1.125 }, - { metadata: "width = 2000 , minimum-scale=0.75", width: 2000, scale: 1.125 }, - { metadata: "width = 2000 , minimum-scale =0.75", width: 2000, scale: 1.125 }, - { metadata: "width = 2000 , minimum-scale = 0.75", width: 2000, scale: 1.125 }, - { metadata: "width = 2000 , minimum-scale = 0.75", width: 2000, scale: 1.125 }, - /* testing opening and switching between pages without a viewport */ - { style: "width:400px;margin:0px;", width: DEFAULT_WIDTH, scale: 1 }, - { style: "width:2000px;margin:0px;", width: 980, scale: window.innerWidth/2000 }, - { style: "width:800px;margin:0px;", width: DEFAULT_WIDTH, scale: 1 }, -]; - - -//------------------------------------------------------------------------------ -// Entry point (must be named "test") -function test() { - // This test is async - waitForExplicitFinish(); - requestLongerTimeout(2); - - currentTab = Browser.addTab("about:blank", true); - ok(currentTab, "Tab Opened"); - - startTest(0); -} - -function startTest(n) { - info(JSON.stringify(gTestData[n])); - BrowserUI.goToURI(testURL_blank); - loadURL(testURL_blank, verifyBlank(n)); - Services.prefs.setIntPref("browser.viewport.scaleRatio", scaleRatio(n)); -} - -function verifyBlank(n) { - return function() { - // Do sanity tests - let uri = currentTab.browser.currentURI.spec; - is(uri, testURL_blank, "URL Matches blank page " + n); - - waitFor(function() { - loadURL(testURL(n), verifyTest(n), gTestData[n].scale); - }, function() { - return currentTab.browser.contentWindowWidth == DEFAULT_WIDTH; - }); - } -} - -function is_approx(actual, expected, fuzz, description) { - ok(Math.abs(actual - expected) <= fuzz, - description + " [got " + actual + ", expected " + expected + "]"); -} - -function verifyTest(n) { - let assumedWidth = 480; - if (!Util.isPortrait()) - assumedWidth = 800; - - return function() { - is(window.innerWidth, assumedWidth, "Test assumes window width is " + assumedWidth + "px"); - - // Do sanity tests - let uri = currentTab.browser.currentURI.spec; - is(uri, testURL(n), "URL is " + testURL(n)); - - let data = gTestData[n]; - let actualWidth = currentTab.browser.contentWindowWidth; - is_approx(actualWidth, parseFloat(data.width), .01, "Viewport width=" + data.width); - - let zoomLevel = getBrowser().scale; - is_approx(zoomLevel, parseFloat(data.scale), .01, "Viewport scale=" + data.scale); - - // Test zooming - if (data.disableZoom) { - ok(!currentTab.allowZoom, "Zoom disabled"); - - Browser.zoom(-1); - is(getBrowser().scale, zoomLevel, "Zoom in does nothing"); - - Browser.zoom(1); - is(getBrowser().scale, zoomLevel, "Zoom out does nothing"); - } - else { - ok(Browser.selectedTab.allowZoom, "Zoom enabled"); - } - - - if (data.minScale) { - do { // Zoom out until we can't go any farther. - zoomLevel = getBrowser().scale; - Browser.zoom(1); - } while (getBrowser().scale != zoomLevel); - ok(getBrowser().scale >= data.minScale, "Zoom out limited"); - } - - if (data.maxScale) { - do { // Zoom in until we can't go any farther. - zoomLevel = getBrowser().scale; - Browser.zoom(-1); - } while (getBrowser().scale != zoomLevel); - ok(getBrowser().scale <= data.maxScale, "Zoom in limited"); - } - - finishTest(n); - } -} - -function finishTest(n) { - Services.prefs.clearUserPref("browser.viewport.scaleRatio"); - if (n + 1 < gTestData.length) { - startTest(n + 1); - } else { - window.resizeTo(480, 800); - Browser.closeTab(currentTab); - finish(); - } -} diff --git a/mobile/android/chrome/tests/browser_viewport.sjs b/mobile/android/chrome/tests/browser_viewport.sjs deleted file mode 100644 index e7351a3f6754..000000000000 --- a/mobile/android/chrome/tests/browser_viewport.sjs +++ /dev/null @@ -1,65 +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 Mozilla Mobile Browser. - * - * The Initial Developer of the Original Code is - * Mozilla Corporation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Matt Brubeck - * - * 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 ***** */ - - function decodeQuery(query) { - let result = {}; - query.split("&").forEach(function(pair) { - let [key, val] = pair.split("="); - result[key] = decodeURIComponent(val); - }); - return result; - } - -function handleRequest(request, response) { - response.setStatusLine(request.httpVersion, 200, "OK"); - response.setHeader("Content-Type", "text/html", false); - - let params = decodeQuery(request.queryString || ""); - - if (params.xhtml == "true") { - response.write(""); - response.write(""); - } - response.write("Browser Viewport Test"); - if (params.metadata) - response.write(""); - response.write(" "); -} diff --git a/mobile/android/chrome/tests/browser_vkb.js b/mobile/android/chrome/tests/browser_vkb.js deleted file mode 100644 index d20efe6c75a2..000000000000 --- a/mobile/android/chrome/tests/browser_vkb.js +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Check VKB show/hide behavior - */ -let testURL_01 = chromeRoot + "browser_forms.html"; -messageManager.loadFrameScript(chromeRoot + "remote_vkb.js", true); - -/* ============================= Tests Utils =============================== */ -let gTests = []; -let gCurrentTest = null; - -// Iterating tests by shifting test out one by one as runNextTest is called. -function runNextTest() { - // Run the next test until all tests completed - if (gTests.length > 0) { - gCurrentTest = gTests.shift(); - info(gCurrentTest.desc); - gCurrentTest.run(); - } - else { - // Close the awesome panel just in case - AwesomeScreen.activePanel = null; - finish(); - } -} - -function test() { - // The "runNextTest" approach is async, so we need to call "waitForExplicitFinish()" - // We call "finish()" when the tests are finished - waitForExplicitFinish(); - - // Start the tests - if ("gTimeout" in window) - setTimeout(runNextTest, gTimeout); - else - runNextTest(); -} -/* ============================ End Utils ================================== */ - -Components.utils.import("resource://gre/modules/Services.jsm"); -let VKBStateHasChanged = false; -let VKBObserver = { - _enabled: false, - observe: function(aTopic, aSubject, aData) { - if (this._enabled != parseInt(aData)) { - this._enabled = parseInt(aData); - VKBstateHasChanged = true; - } - } -}; -Services.obs.addObserver(VKBObserver, "ime-enabled-state-changed", false); - -function waitForVKBChange(aCallback, aState) { - waitForAndContinue(aCallback, function() { - if (VKBStateHasChanged) { - VKBStateHasChanged = false; - return true; - } - - return VKBStateHasChanged; - }); -} - -let newTab = null; - -function waitForPageShow(aPageURL, aCallback) { - messageManager.addMessageListener("pageshow", function(aMessage) { - if (aMessage.target.currentURI.spec == aPageURL) { - messageManager.removeMessageListener("pageshow", arguments.callee); - setTimeout(function() { aCallback(); }, 0); - } - }); -}; - -function dragElement(element, x1, y1, x2, y2) { - EventUtils.synthesizeMouse(element, x1, y1, { type: "mousedown" }); - EventUtils.synthesizeMouse(element, x2, y2, { type: "mousemove" }); - EventUtils.synthesizeMouse(element, x2, y2, { type: "mouseup" }); -} - -//------------------------------------------------------------------------------ -// Case: Test interactions with a VKB from content -gTests.push({ - desc: "Test interactions with a VKB from content", - run: function() { - waitForPageShow(testURL_01, gCurrentTest.focusContentInputField); - - newTab = Browser.addTab(testURL_01, true); - ok(newTab, "Tab Opened"); - }, - - focusContentInputField: function() { - is(VKBObserver._enabled, false, "Initially the VKB should be closed"); - - AsyncTests.waitFor("Test:FocusRoot", {}, function(json) { - waitForVKBChange(gCurrentTest.showLeftSidebar); - }) - }, - - showLeftSidebar: function() { - is(VKBObserver._enabled, true, "When focusing an input field the VKB should be opened"); - - let browsers = document.getElementById("browsers"); - dragElement(browsers, window.innerWidth / 2, window.innerHeight / 2, 1000, 1000); - waitForVKBChange(gCurrentTest.showRightSidebar); - }, - - showRightSidebar: function() { - is(VKBObserver._enabled, true, "When pannning to the leftSidebar the VKB state should not changed"); - - let browsers = document.getElementById("browsers"); - dragElement(browsers, window.innerWidth / 2, window.innerHeight / 2, -1000, -1000); - waitForVKBChange(gCurrentTest.changeTab); - }, - - changeTab: function() { - is(VKBObserver._enabled, true, "When panning to the right sidebar the VKB state should not changed"); - - let firstTab = document.getElementById("tabs").children.firstChild; - BrowserUI.selectTab(firstTab); - waitForVKBChange(gCurrentTest.prepareOpenRightPanel); - }, - - prepareOpenRightPanel: function() { - is(VKBObserver._enabled, false, "Switching tab should close the VKB"); - - BrowserUI.selectTab(newTab); - - // Give back the focus to the content input and launch and check - // interaction with the right panel - AsyncTests.waitFor("Test:FocusRoot", {}, function(json) { - waitForVKBChange(gCurrentTest.openRightPanel); - }); - }, - - openRightPanel: function() { - is(VKBObserver._enabled, true, "Re-cliking on an input field should re-open the VKB"); - - let toolsButton = document.getElementById("tool-panel-open"); - let rect = toolsButton.getBoundingClientRect(); - EventUtils.synthesizeMouse(toolsButton, rect.width / 2, rect.height / 2, {}); - waitForVKBChange(function() { - is(VKBObserver._enabled, false, "Opening the right panel should close the VKB"); - BrowserUI.hidePanel(); - Browser.hideSidebars(); - BrowserUI.closeTab(newTab); - Services.obs.removeObserver(VKBObserver, "ime-enabled-state-changed"); - runNextTest(); - }); - } -}); diff --git a/mobile/android/chrome/tests/head.js b/mobile/android/chrome/tests/head.js deleted file mode 100644 index 965858ec96f7..000000000000 --- a/mobile/android/chrome/tests/head.js +++ /dev/null @@ -1,122 +0,0 @@ -/*============================================================================= - Common Helpers functions -=============================================================================*/ - -const kDefaultWait = 2000; -// Wait for a condition and call a supplied callback if condition is met within -// alloted time. If condition is not met, cause a hard failure, stopping the test. -function waitFor(callback, test, timeout) { - if (test()) { - callback(); - return; - } - - timeout = timeout || Date.now(); - if (Date.now() - timeout > kDefaultWait) - throw "waitFor timeout"; - setTimeout(waitFor, 50, callback, test, timeout); -}; - -// Wait for a condition and call a supplied callback if condition is met within -// alloted time. If condition is not met, continue anyway. Use this helper if the -// callback will test for the outcome, but not stop the entire test. -function waitForAndContinue(callback, test, timeout) { - if (test()) { - callback(); - return; - } - - timeout = timeout || Date.now(); - if (Date.now() - timeout > kDefaultWait) { - callback(); - return; - } - setTimeout(waitForAndContinue, 50, callback, test, timeout); -}; - -// Listen for the specified message once, then remove the listener. -function onMessageOnce(aMessageManager, aName, aCallback) { - aMessageManager.addMessageListener(aName, function onMessage(aMessage) { - aMessageManager.removeMessageListener(aName, onMessage); - setTimeout(function() { - aCallback(aMessage); - }, 0); - }); -}; - -// This function is useful for debugging one test where you need to wait for -// application to be ready -function waitForFirstPaint(aCallback) { - function hasFirstPaint() { - let startupInfo = Cc["@mozilla.org/toolkit/app-startup;1"].getService(Ci.nsIAppStartup).getStartupInfo(); - return ("firstPaint" in startupInfo); - } - - if (!hasFirstPaint()) { - waitFor(aCallback, hasFirstPaint, Date.now() + 3000); - return; - } - - aCallback(); -}; - -function makeURI(spec) { - return Services.io.newURI(spec, null, null); -}; - -EventUtils.synthesizeString = function synthesizeString(aString, aWindow) { - for (let i = 0; i < aString.length; i++) { - EventUtils.synthesizeKey(aString.charAt(i), {}, aWindow); - } -}; - -EventUtils.synthesizeMouseForContent = function synthesizeMouseForContent(aElement, aOffsetX, aOffsetY, aEvent, aWindow) { - let container = document.getElementById("browsers"); - let rect = container.getBoundingClientRect(); - - EventUtils.synthesizeMouse(aElement, rect.left + aOffsetX, rect.top + aOffsetY, aEvent, aWindow); -}; - -let AsyncTests = { - _tests: {}, - waitFor: function(aMessage, aData, aCallback) { - messageManager.addMessageListener(aMessage, this); - if (!this._tests[aMessage]) - this._tests[aMessage] = []; - - this._tests[aMessage].push(aCallback || function() {}); - setTimeout(function() { - Browser.selectedBrowser.messageManager.sendAsyncMessage(aMessage, aData || { }); - }, 0); - }, - - receiveMessage: function(aMessage) { - let test = this._tests[aMessage.name]; - let callback = test.shift(); - if (callback) - callback(aMessage.json); - } -}; - -let gCurrentTest = null; -let gTests = []; - -// Iterating tests by shifting test out one by one as runNextTest is called. -function runNextTest() { - // Run the next test until all tests completed - if (gTests.length > 0) { - gCurrentTest = gTests.shift(); - info(gCurrentTest.desc); - gCurrentTest.run(); - } - else { - finish(); - } -} - -let serverRoot = "http://example.com/browser/mobile/chrome/tests/"; -let baseURI = "http://mochi.test:8888/browser/mobile/chrome/tests/"; - -let chromeRoot = getRootDirectory(gTestPath); -messageManager.loadFrameScript(chromeRoot + "remote_head.js", true); -messageManager.loadFrameScript("chrome://mochikit/content/tests/SimpleTest/EventUtils.js", true); diff --git a/mobile/android/chrome/tests/locales_list.sjs b/mobile/android/chrome/tests/locales_list.sjs deleted file mode 100644 index 5843a82450c2..000000000000 --- a/mobile/android/chrome/tests/locales_list.sjs +++ /dev/null @@ -1,121 +0,0 @@ -let fennecID = "{a23983c0-fd0e-11dc-95ff-0800200c9a66}"; -Components.utils.import("resource://gre/modules/Services.jsm"); - -function getLocale(aLocaleParams, aAppParams) { - let l = { - TARGETLOCALE: "test{IDNUMBER}", - NAME: "Test Locale {IDNUMBER}", - VERSION: "1.0", - INSTALL: "http://www.example.com/browser/mobile/chrome/tests/addons/browser_locale{IDNUMBER}.xpi", - TYPENUMBER: 5, - TYPENAME: "Language Pack (Application)", - IDNUMBER: "", - }; - let a = { - APPNAME: "Fennec", - MINVERSION: "4.0", MAXVERSION: "*", - APPID: fennecID - }; - - if (aLocaleParams) { - for (var entry in aLocaleParams) { - l[entry] = aLocaleParams[entry]; - } - } - - if (aAppParams) { - for (var entry in aAppParams) { - a[entry] = aAppParams[entry]; - } - } - - l.app = a; - return l; -} - -let appTemplate = "" + -"{APPNAME}" + - "{MINVERSION}" + - "{MAXVERSION}" + - "{APPID}" + -""; - -let template = ""+ - "{TARGETLOCALE}" + - "{NAME}"+ - "{TYPENAME}"+ - "langpack-{TARGETLOCALE}@firefox-mobile.mozilla.org"+ - "{VERSION}"+ - "Public"+ - "{APPS}"+ - "ALL"+ - "{INSTALL}\n" + - "title=TITLE\n" + - "continueIn=CONTINUEIN%S\n" + - "name=NAME\n" + - "choose=CHOOSE\n" + - "chooseLanguage=CHOOSELANGUAGE\n" + - "cancel=CANCEL\n" + - "continue=CONTINUE\n" + - "installing=INSTALLING%S\n" + - "installerror=INSTALLERROR\n" + - "loading=LOADING" + - ""+ -""; - -function handleRequest(request, response) { - - response.setStatusLine(request.httpVersion, 200, "OK"); - response.setHeader("Content-Type", "text/xml", false); - - response.write(""); - response.write(""); - - let locales = []; - let query = decodeURIComponent(request.queryString || "").split("="); - switch(query[0]) { - case "numvalid": - let numValid = parseInt(query[1]); - for (let i = 0; i < numValid; i++) { - locales.push( getLocale({IDNUMBER: i}) ); - } - break; - case "buildid": - locales.push( getLocale({IDNUMBER: 1, NAME: query[1]}) ); - break; - default : - locales.push( getLocale({IDNUMBER: 1}) ); - /* These locales should fail in the LocaleRepository */ - locales.push( getLocale({IDNUMBER: 1}) ); // no duplicate ids - locales.push( getLocale({IDNUMBER: 2, INSTALL: "INVALID_URL"}) ); - locales.push( getLocale({IDNUMBER: 3}, {APPID: "INVALID_ID"}) ); - locales.push( getLocale({IDNUMBER: 3}, {MAXVERSION: "0"}) ); - locales.push( getLocale({IDNUMBER: 4, TARGETLOCALE: ""}) ); - locales.push( getLocale({IDNUMBER: 5, NAME: ""}) ); - locales.push( getLocale({IDNUMBER: 6, VERSION: ""}) ); - locales.push( getLocale({IDNUMBER: 7, TYPENUMBER: ""}) ); - break; - } - - for(var i = 0; i < locales.length; i++) { - let t = template; - t = t.replace(/{TARGETLOCALE}/g, locales[i].TARGETLOCALE); - t = t.replace(/{NAME}/, locales[i].NAME); - t = t.replace(/{VERSION}/, locales[i].VERSION); - t = t.replace(/{INSTALL}/, locales[i].INSTALL); - t = t.replace(/{TYPENUMBER}/, locales[i].TYPENUMBER); - t = t.replace(/{TYPENAME}/, locales[i].TYPENAME); - t = t.replace(/{IDNUMBER}/g, locales[i].IDNUMBER) - - let a = appTemplate; - a = a.replace(/{APPNAME}/, locales[i].app.APPNAME); - a = a.replace(/{MINVERSION}/, locales[i].app.MINVERSION); - a = a.replace(/{MAXVERSION}/, locales[i].app.MAXVERSION); - a = a.replace(/{APPID}/, locales[i].app.APPID); - - t = t.replace(/{APPS}/, a); - response.write(t); - } - - response.write(""); -} diff --git a/mobile/android/chrome/tests/mock_autocomplete.json b/mobile/android/chrome/tests/mock_autocomplete.json deleted file mode 100644 index ef5e43d6fa55..000000000000 --- a/mobile/android/chrome/tests/mock_autocomplete.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "version": 1, - "result": { - "searchResult": 4, - "RESULT_NOMATCH_ONGOING": 5, - "RESULT_SUCCESS_ONGOING": 6, - "searchString": "", - "defaultIndex": 0, - "errorDescription": "", - "matchCount": 5, - "RESULT_IGNORED": 1, - "RESULT_FAILURE": 2, - "RESULT_NOMATCH": 3, - "RESULT_SUCCESS": 4, - "data": [["http://example.com/a", "A", "favicon", "http://example.com/a/favicon.png"], - ["http://example.com/b", "B", "favicon", "http://example.com/b/favicon.png"], - ["http://example.com/c", "C", "favicon", "http://example.com/c/favicon.png"], - ["http://example.com/d", "D", "bookmark", "http://example.com/d/favicon.png"], - ["http://example.com/e", "E", "boolmark", "http://example.com/e/favicon.png"] - ] - } -} diff --git a/mobile/android/chrome/tests/remote_autocomplete.js b/mobile/android/chrome/tests/remote_autocomplete.js deleted file mode 100644 index 991671aa6ef4..000000000000 --- a/mobile/android/chrome/tests/remote_autocomplete.js +++ /dev/null @@ -1,22 +0,0 @@ -dump("====================== Content Script Loaded =======================\n"); - -let assistant = Content.formAssistant; - -AsyncTests.add("TestRemoteAutocomplete:Click", function(aMessage, aJson) { - let element = content.document.getElementById(aJson.id); - assistant.open(element); - return true; -}); - -AsyncTests.add("TestRemoteAutocomplete:Check", function(aMessage, aJson) { - let element = content.document.getElementById(aJson.id); - return element.value; -}); - -AsyncTests.add("TestRemoteAutocomplete:Reset", function(aMessage, aJson) { - gFocusManager.focusedElement = null; - let element = content.document.getElementById(aJson.id); - element.value = ""; - return true; -}); - diff --git a/mobile/android/chrome/tests/remote_contentpopup.js b/mobile/android/chrome/tests/remote_contentpopup.js deleted file mode 100644 index f2156d700c5d..000000000000 --- a/mobile/android/chrome/tests/remote_contentpopup.js +++ /dev/null @@ -1,18 +0,0 @@ -dump("====================== Content Script Loaded =======================\n"); - -let assistant = Content.formAssistant; - -AsyncTests.add("TestRemoteAutocomplete:Click", function(aMessage, aJson) { - let element = content.document.getElementById(aJson.id); - assistant.open(element); - assistant._executeDelayed(function(assistant) { - sendAsyncMessage("FormAssist:AutoComplete", assistant._getJSON()); - }); - return true; -}); - -AsyncTests.add("TestRemoteAutocomplete:Check", function(aMessage, aJson) { - let element = content.document.getElementById(aJson.id); - return element.value; -}); - diff --git a/mobile/android/chrome/tests/remote_focus.js b/mobile/android/chrome/tests/remote_focus.js deleted file mode 100644 index d3c4544c2715..000000000000 --- a/mobile/android/chrome/tests/remote_focus.js +++ /dev/null @@ -1,16 +0,0 @@ -function focusReceived() { - sendAsyncMessage("Test:E10SFocusReceived"); -} - -function blurReceived() { - sendAsyncMessage("Test:E10SBlurReceived"); -} - -addEventListener("focus", focusReceived, true); -addEventListener("blur", blurReceived, true); - -addMessageListener("Test:E10SFocusTestFinished", function testFinished() { - removeEventListener("focus", focusReceived, true); - removeEventListener("blur", blurReceived, true); - removeMessageListener("Test:E10SFocusTestFinished", testFinished); -}); diff --git a/mobile/android/chrome/tests/remote_forms.js b/mobile/android/chrome/tests/remote_forms.js deleted file mode 100644 index 36779f5ae150..000000000000 --- a/mobile/android/chrome/tests/remote_forms.js +++ /dev/null @@ -1,171 +0,0 @@ -dump("====================== Content Script Loaded =======================\n"); - -let assistant = Content.formAssistant; - -// Copied from http://mxr.mozilla.org/mozilla-central/source/testing/mochitest/tests/SimpleTest/EventUtils.js -// except the netscape.security.PrivilegeManager.enablePrivilege call -function sendMouseEvent(aEvent, aTarget, aWindow) { - if (['click', 'mousedown', 'mouseup', 'mouseover', 'mouseout'].indexOf(aEvent.type) == -1) { - throw new Error("sendMouseEvent doesn't know about event type '" + aEvent.type + "'"); - } - - if (!aWindow) { - aWindow = window; - } - - if (!(aTarget instanceof Element)) { - aTarget = aWindow.document.getElementById(aTarget); - } - - let event = aWindow.document.createEvent('MouseEvent'); - - let typeArg = aEvent.type; - let canBubbleArg = true; - let cancelableArg = true; - let viewArg = aWindow; - let detailArg = aEvent.detail || (aEvent.type == 'click' || - aEvent.type == 'mousedown' || - aEvent.type == 'mouseup' ? 1 : 0); - let screenXArg = aEvent.screenX || 0; - let screenYArg = aEvent.screenY || 0; - let clientXArg = aEvent.clientX || 0; - let clientYArg = aEvent.clientY || 0; - let ctrlKeyArg = aEvent.ctrlKey || false; - let altKeyArg = aEvent.altKey || false; - let shiftKeyArg = aEvent.shiftKey || false; - let metaKeyArg = aEvent.metaKey || false; - let buttonArg = aEvent.button || 0; - let relatedTargetArg = aEvent.relatedTarget || null; - - event.initMouseEvent(typeArg, canBubbleArg, cancelableArg, viewArg, detailArg, - screenXArg, screenYArg, clientXArg, clientYArg, - ctrlKeyArg, altKeyArg, shiftKeyArg, metaKeyArg, - buttonArg, relatedTargetArg); - - aTarget.dispatchEvent(event); -} - -AsyncTests.add("Test:Click", function(aMessage, aJson) { - sendMouseEvent({type: "click"}, "root", content); - return assistant._open; -}); - -AsyncTests.add("Test:Focus", function(aMessage, aJson) { - let targetElement = content.document.querySelector(aJson.value); - targetElement.focus(); - assistant._executeDelayed(function() { - sendAsyncMessage(aMessage, { result: assistant._open }); - }); -}); - -AsyncTests.add("Test:FocusRedirect", function(aMessage, aJson) { - let element = content.document.querySelector(aJson.value); - element.addEventListener("focus", function(aEvent) { - element.removeEventListener("focus", arguments.callee, false); - content.document.getElementById("root").focus(); - }, false); - element.focus(); - - assistant._executeDelayed(function() { - sendAsyncMessage(aMessage, { result: assistant._open }); - }); -}); - -// It should be only 2 ways to open the FormAssistant, the first one is -// by manually synchronizing the focus to the form helper and the other -// one is by a user click on an authorized element -AsyncTests.add("Test:OpenUIWithSyncFocus", function(aMessage, aJson) { - let element = content.document.querySelector(aJson.value); - - assistant._open = false; - assitant.focusSync = true; - element.focus(); - assistant._executeDelayed(function() { - assistant.focusSync = false; - sendAsyncMessage(aMessage, { result: assistant._open }); - }); -}); - -AsyncTests.add("Test:Open", function(aMessage, aJson) { - let element = content.document.querySelector(aJson.value); - assistant._open = false; - return assistant.open(element); -}); - -AsyncTests.add("Test:OpenWithFocusRedirect", function(aMessage, aJson) { - let element = content.document.querySelector(aJson.value); - assistant._open = false; - assistant.focusSync = true; - assistant.open(element); - assistant._executeDelayed(function() { - assistant.focusSync = false; - sendAsyncMessage(aMessage, { result: assistant._open }); - }); -}); - -AsyncTests.add("Test:CanShowUI", function(aMessage, aJson) { - let element = content.document.querySelector(aJson.value); - element.disabled = aJson.disabled; - assistant._open = false; - let open = assistant.open(element); - element.disabled = false; - return open; -}); - -AsyncTests.add("Test:CanShowUISelect", function(aMessage, aJson) { - let select = content.document.getElementById("select"); - select.disabled = aJson.disabled; - - let element = content.document.querySelector(aJson.value); - assistant._open = false; - let open = assistant.open(element); - select.disabled = false; - return open; -}); - -AsyncTests.add("Test:Previous", function(aMessage, aJson) { - let targetElement = content.document.querySelector(aJson.value); - assistant.currentIndex--; - return (assistant.currentElement == targetElement); -}); - -AsyncTests.add("Test:Next", function(aMessage, aJson) { - let targetElement = content.document.querySelector(aJson.value); - assistant.currentIndex++; - return (assistant.currentElement == targetElement); -}); - -// ============= iframe navigation ================== -let iframe = null; -let iframeInputs = null; -AsyncTests.add("Test:Iframe", function(aMessage, aJson) { - iframe = content.document.createElement("iframe"); - iframe.setAttribute("src", "data:text/html;charset=utf-8,%3Ciframe%20src%3D%22data%3Atext/html%3Bcharset%3Dutf-8%2C%253Cinput%253E%253Cbr%253E%253Cinput%253E%250A%22%3E%3C/iframe%3E"); - iframe.setAttribute("width", "300"); - iframe.setAttribute("height", "100"); - - iframe.addEventListener("load", function() { - iframe.removeEventListener("load", arguments.callee, false); - iframeInputs = iframe.contentDocument - .querySelector("iframe").contentDocument - .getElementsByTagName("input"); - sendAsyncMessage(aMessage, { result: true }); - }, false); - - content.document.body.appendChild(iframe); -}); - -AsyncTests.add("Test:IframeOpen", function(aMessage, aJson) { - return assistant.open(iframeInputs[0]); -}); - -AsyncTests.add("Test:IframePrevious", function(aMessage, aJson) { - assistant.currentIndex--; - return (assistant.currentElement == iframeInputs[aJson.value]); -}); - -AsyncTests.add("Test:IframeNext", function(aMessage, aJson) { - assistant.currentIndex++; - return (assistant.currentElement == iframeInputs[aJson.value]); -}); - diff --git a/mobile/android/chrome/tests/remote_formsZoom.js b/mobile/android/chrome/tests/remote_formsZoom.js deleted file mode 100644 index 74cffac37d9c..000000000000 --- a/mobile/android/chrome/tests/remote_formsZoom.js +++ /dev/null @@ -1,9 +0,0 @@ -dump("====================== Content Script Loaded =======================\n"); - -let assistant = Content.formAssistant; - -AsyncTests.add("FormAssist:Show", function(aMessage, aJson) { - let element = content.document.getElementById(aJson.id); - assistant.open(element); -}); - diff --git a/mobile/android/chrome/tests/remote_head.js b/mobile/android/chrome/tests/remote_head.js deleted file mode 100644 index 157d2e7b8252..000000000000 --- a/mobile/android/chrome/tests/remote_head.js +++ /dev/null @@ -1,35 +0,0 @@ -// XXX Those constants are here because EventUtils.js need them -window = content.document.defaultView.wrappedJSObject; -Element = Components.interfaces.nsIDOMElement; -netscape = window.netscape; - -let AsyncTests = { - _tests: [], - - add: function(aMessage, aCallback) { - addMessageListener(aMessage, this); - this._tests.push({ name: aMessage, callback: aCallback }); - }, - - receiveMessage: function(aMessage) { - let rv = { }; - let name = aMessage.name; - try { - let tests = this._tests; - for (let i = 0; i < tests.length; i++) { - if (tests[i].name == name) { - rv.result = tests[i].callback(name, aMessage.json); - break; - } - } - // Don't send test callback if rv.result == undefined, this allow to - // use a custom callback - if (rv.result != undefined) - sendAsyncMessage(name, rv); - } - catch(e) { - dump("receiveMessage: " + name + " - " + e + "\n"); - } - } -}; - diff --git a/mobile/android/chrome/tests/remote_vkb.js b/mobile/android/chrome/tests/remote_vkb.js deleted file mode 100644 index eb6b8283afc6..000000000000 --- a/mobile/android/chrome/tests/remote_vkb.js +++ /dev/null @@ -1,6 +0,0 @@ -dump("====================== Content Script Loaded =======================\n"); - -AsyncTests.add("Test:FocusRoot", function(aMessage, aJson) { - content.document.getElementById("root").focus(); - return true; -}); From 6f5e3062f091dc4f2b89adf9a98ad77abeaf2109 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Tue, 13 Mar 2012 15:48:26 -0700 Subject: [PATCH 31/57] Bug 735297 - Documentation for RepositorySession. r=nalexander --- .../sync/repositories/RepositorySession.java | 80 ++++++++----------- .../android/base/sync/setup/SyncAccounts.java | 32 +++++--- 2 files changed, 58 insertions(+), 54 deletions(-) diff --git a/mobile/android/base/sync/repositories/RepositorySession.java b/mobile/android/base/sync/repositories/RepositorySession.java index 205735b26892..743fe11019d3 100644 --- a/mobile/android/base/sync/repositories/RepositorySession.java +++ b/mobile/android/base/sync/repositories/RepositorySession.java @@ -1,40 +1,6 @@ -/* ***** 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 ***** */ +/* 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.repositories; @@ -53,16 +19,22 @@ import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionWipeDelega import org.mozilla.gecko.sync.repositories.domain.Record; /** - * A RepositorySession is created and used thusly: + * A RepositorySession is created and used thusly: * - * * Construct, with a reference to its parent Repository, by calling - * Repository.createSession(). - * * Populate with saved information by calling unbundle(). - * * Begin a sync by calling begin(). - * * Perform operations such as fetchSince() and store(). - * * Finish by calling finish(), retrieving and storing the current bundle. + *
      + *
    • Construct, with a reference to its parent {@link Repository}, by calling + * {@link Repository#createSession(RepositorySessionCreationDelegate, android.content.Context)}.
    • + *
    • Populate with saved information by calling {@link #unbundle(RepositorySessionBundle)}.
    • + *
    • Begin a sync by calling {@link #begin(RepositorySessionBeginDelegate)}. begin() + * is an appropriate place to initialize expensive resources.
    • + *
    • Perform operations such as {@link #fetchSince(long, RepositorySessionFetchRecordsDelegate)} and + * {@link #store(Record)}.
    • + *
    • Finish by calling {@link #finish(RepositorySessionFinishDelegate)}, retrieving and storing + * the current bundle.
    • + *
    * - * @author rnewman + * If finish() is not called, {@link #abort()} must be called. These calls must + * always be paired with begin(). * */ public abstract class RepositorySession { @@ -192,6 +164,13 @@ public abstract class RepositorySession { this.transitionFrom(SessionStatus.UNSTARTED, SessionStatus.ACTIVE); } + /** + * Start the session. This is an appropriate place to initialize + * data access components such as database handles. + * + * @param delegate + * @throws InvalidSessionTransitionException + */ public void begin(RepositorySessionBeginDelegate delegate) throws InvalidSessionTransitionException { sharedBegin(); delegate.deferredBeginDelegate(delegateQueue).onBeginSucceeded(this); @@ -228,6 +207,10 @@ public abstract class RepositorySession { delegate.deferredFinishDelegate(delegateQueue).onFinishSucceeded(this, this.getBundle(null)); } + /** + * Abnormally terminate the repository session, freeing or closing + * any resources that were opened during the lifetime of the session. + */ public void abort() { // TODO: do something here. this.setStatus(SessionStatus.ABORTED); @@ -243,6 +226,13 @@ public abstract class RepositorySession { } } + /** + * End the repository session, freeing or closing any resources + * that were opened during the lifetime of the session. + * + * @param delegate notified of success or failure. + * @throws InactiveSessionException + */ public void finish(final RepositorySessionFinishDelegate delegate) throws InactiveSessionException { try { this.transitionFrom(SessionStatus.ACTIVE, SessionStatus.DONE); diff --git a/mobile/android/base/sync/setup/SyncAccounts.java b/mobile/android/base/sync/setup/SyncAccounts.java index b4ad9f684709..fd7b1c1f5d67 100644 --- a/mobile/android/base/sync/setup/SyncAccounts.java +++ b/mobile/android/base/sync/setup/SyncAccounts.java @@ -17,11 +17,26 @@ import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; +/** + * This class contains utilities that are of use to Fennec + * and Sync setup activities. + * + * Do not break these APIs without correcting upstream code! + */ public class SyncAccounts { private final static String DEFAULT_SERVER = "https://auth.services.mozilla.com/"; private static final String LOG_TAG = "SyncAccounts"; + /** + * Returns true if a Sync account is set up. + * + * Do not call this method from the main thread. + */ + public static boolean syncAccountsExist(Context c) { + return AccountManager.get(c).getAccountsByType("org.mozilla.firefox_sync").length > 0; + } + /** * This class provides background-thread abstracted access to whether a * Firefox Sync account has been set up on this device. @@ -32,11 +47,10 @@ public class SyncAccounts { @Override protected Boolean doInBackground(Context... params) { Context c = params[0]; - return AccountManager.get(c).getAccountsByType("org.mozilla.firefox_sync").length > 0; + return syncAccountsExist(c); } } - // TODO: lift this out. public static Intent createAccount(Context context, AccountManager accountManager, String username, @@ -46,7 +60,7 @@ public class SyncAccounts { final Account account = new Account(username, Constants.ACCOUNTTYPE_SYNC); final Bundle userbundle = new Bundle(); - + // Add sync key and server URL. userbundle.putString(Constants.OPTION_SYNCKEY, syncKey); if (serverURL != null) { @@ -71,24 +85,24 @@ public class SyncAccounts { Log.e("FirefoxSync", "Unable to create account.", e); } } - + Logger.debug(LOG_TAG, "Account: " + account + " added successfully? " + result); if (!result) { Logger.error(LOG_TAG, "Failed to add account!"); } - + // Set components to sync (default: all). ContentResolver.setMasterSyncAutomatically(true); - + String authority = BrowserContract.AUTHORITY; Logger.debug(LOG_TAG, "Setting authority " + authority + " to sync automatically."); ContentResolver.setSyncAutomatically(account, authority, true); ContentResolver.setIsSyncable(account, 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 Logger.debug(LOG_TAG, "Finished setting syncables."); - + // TODO: correctly implement Sync Options. Logger.info(LOG_TAG, "Clearing preferences for this account."); try { @@ -96,7 +110,7 @@ public class SyncAccounts { } catch (Exception e) { Logger.error(LOG_TAG, "Could not clear prefs path!", e); } - + final Intent intent = new Intent(); intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, username); intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNTTYPE_SYNC); From acdc6d177c6407d6fdde3a1e689e4e707dec02ec Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Tue, 13 Mar 2012 15:48:26 -0700 Subject: [PATCH 32/57] Bug 735475 - Invert AndroidBrowserRepositorySession.checkRecordType into shouldIgnore. r=nalexander --- ...roidBrowserBookmarksRepositorySession.java | 10 ++-- .../AndroidBrowserRepositorySession.java | 54 +++++-------------- 2 files changed, 17 insertions(+), 47 deletions(-) diff --git a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java index 3fa15fbe5812..81af2e45395f 100644 --- a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java @@ -459,21 +459,21 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo } @Override - protected boolean checkRecordType(Record record) { + protected boolean shouldIgnore(Record record) { if (!(record instanceof BookmarkRecord)) { - return false; + return true; } if (record.deleted) { - return true; + return false; } BookmarkRecord bmk = (BookmarkRecord) record; if (bmk.isBookmark() || bmk.isFolder()) { - return true; + return false; } Logger.info(LOG_TAG, "Ignoring record with guid: " + bmk.guid + " and type: " + bmk.type); - return false; + return true; } @Override diff --git a/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java b/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java index 8505f423b75a..2207b8b6909b 100644 --- a/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java @@ -1,40 +1,6 @@ -/* ***** 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 ***** */ +/* 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.repositories.android; @@ -118,9 +84,13 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos */ protected abstract Record retrieveDuringFetch(Cursor cur) throws NoGuidForIdException, NullCursorException, ParentNotFoundException; - // Must be overriden by AndroidBookmarkRepositorySession. - protected boolean checkRecordType(Record record) { - return true; + /** + * Override this to allow records to be skipped during insertion. + * + * For example, a session subclass might skip records of an unsupported type. + */ + protected boolean shouldIgnore(Record record) { + return false; } /** @@ -393,8 +363,8 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos // including livemarks and queries, are simply ignored. // 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)) { - Logger.debug(LOG_TAG, "Ignoring record " + record.guid + " due to unknown record type."); + if (shouldIgnore(record)) { + Logger.debug(LOG_TAG, "Ignoring record " + record.guid); // Don't throw: we don't want to abort the entire sync when we get a livemark! // delegate.onRecordStoreFailed(new InvalidBookmarkTypeException(null)); From 7b6c9af6674f7b80ffd895f099de537adfb7bd16 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Tue, 13 Mar 2012 15:59:42 -0700 Subject: [PATCH 33/57] Bug 735490 - Makefile change to reflect test deletion. r=mbrubeck --- mobile/android/makefiles.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/mobile/android/makefiles.sh b/mobile/android/makefiles.sh index 1e27c17a1960..30578d80bf9d 100644 --- a/mobile/android/makefiles.sh +++ b/mobile/android/makefiles.sh @@ -58,9 +58,3 @@ if [ ! "$LIBXUL_SDK" ]; then mobile/android/components/build/Makefile " fi - -if [ "$ENABLE_TESTS" ]; then - add_makefiles " - mobile/android/chrome/tests/Makefile - " -fi From 720b93e4797f400cfaab975dc65eda8c9e229b8d Mon Sep 17 00:00:00 2001 From: Gregor Wagner Date: Tue, 13 Mar 2012 16:12:25 -0700 Subject: [PATCH 34/57] Bug 731406 - Contacts API: Incremental Search. r=bent --- dom/contacts/fallback/ContactDB.jsm | 97 +++++++++----------- dom/contacts/tests/test_contacts_basics.html | 92 +++++++++++++++++-- 2 files changed, 126 insertions(+), 63 deletions(-) diff --git a/dom/contacts/fallback/ContactDB.jsm b/dom/contacts/fallback/ContactDB.jsm index 686ebcd7371e..ad68beb9a444 100644 --- a/dom/contacts/fallback/ContactDB.jsm +++ b/dom/contacts/fallback/ContactDB.jsm @@ -25,7 +25,7 @@ const STORE_NAME = "contacts"; function ContactDB(aGlobal) { debug("Constructor"); - this._indexedDB = aGlobal.mozIndexedDB; + this._global = aGlobal; } ContactDB.prototype = { @@ -54,7 +54,7 @@ ContactDB.prototype = { let self = this; debug("try to open database:" + DB_NAME + " " + DB_VERSION); - let request = this._indexedDB.open(DB_NAME, DB_VERSION); + let request = this._global.mozIndexedDB.open(DB_NAME, DB_VERSION); request.onsuccess = function (event) { debug("Opened database:", DB_NAME, DB_VERSION); self.db = event.target.result; @@ -116,6 +116,14 @@ ContactDB.prototype = { objectStore.createIndex("email", "properties.email", { unique: false, multiEntry: true }); objectStore.createIndex("note", "properties.note", { unique: false, multiEntry: true }); + objectStore.createIndex("nicknameLowerCase", "search.nickname", { unique: false, multiEntry: true }); + objectStore.createIndex("nameLowerCase", "search.name", { unique: false, multiEntry: true }); + objectStore.createIndex("familyNameLowerCase", "search.familyName", { unique: false, multiEntry: true }); + objectStore.createIndex("givenNameLowerCase", "search.givenName", { unique: false, multiEntry: true }); + objectStore.createIndex("telLowerCase", "search.tel", { unique: false, multiEntry: true }); + objectStore.createIndex("emailLowerCase", "search.email", { unique: false, multiEntry: true }); + objectStore.createIndex("noteLowerCase", "search.note", { unique: false, multiEntry: true }); + debug("Created object stores and indexes"); }, @@ -171,7 +179,6 @@ ContactDB.prototype = { }, failureCb); }, - // Todo: add searchfields. "Tom" should be a result with T, t, To, to... makeImport: function makeImport(aContact) { let contact = {}; contact.properties = { @@ -197,9 +204,33 @@ ContactDB.prototype = { genderIdentity: null }; + contact.search = { + name: [], + honorificPrefix: [], + givenName: [], + additionalName: [], + familyName: [], + honorificSuffix: [], + nickname: [], + email: [], + category: [], + tel: [], + org: [], + note: [], + impp: [] + }; + for (let field in aContact.properties) { contact.properties[field] = aContact.properties[field]; + // Add search fields + if (aContact.properties[field] && contact.search[field]) { + for (let i = 0; i <= aContact.properties[field].length; i++) { + if (aContact.properties[field][i]) + contact.search[field].push(aContact.properties[field][i].toLowerCase()); + } + } } + debug("contact:" + JSON.stringify(contact)); contact.updated = aContact.updated; contact.published = aContact.published; @@ -208,7 +239,6 @@ ContactDB.prototype = { return contact; }, - // Needed to remove searchfields makeExport: function makeExport(aRecord) { let contact = {}; contact.properties = aRecord.properties; @@ -298,10 +328,8 @@ ContactDB.prototype = { let self = this; this.newTxn("readonly", function (txn, store) { - if (aOptions && aOptions.filterOp == "equals") { + if (aOptions && (aOptions.filterOp == "equals" || aOptions.filterOp == "contains")) { self._findWithIndex(txn, store, aOptions); - } else if (aOptions && aOptions.filterBy) { - self._findWithSearch(txn, store, aOptions); } else { self._findAll(txn, store, aOptions); } @@ -334,10 +362,17 @@ ContactDB.prototype = { if (key == "id") { // store.get would return an object and not an array request = store.getAll(options.filterValue); - } else { + } else if (options.filterOp == "equals") { debug("Getting index: " + key); + // case sensitive let index = store.index(key); request = index.getAll(options.filterValue, options.filterLimit); + } else { + // not case sensitive + let tmp = options.filterValue.toLowerCase(); + let range = this._global.IDBKeyRange.bound(tmp, tmp + "\uFFFF"); + let index = store.index(key + "LowerCase"); + request = index.getAll(range, options.filterLimit); } if (!txn.result) txn.result = {}; @@ -350,52 +385,6 @@ ContactDB.prototype = { } }, - // Will be replaced by _findWithIndex once all searchfields are added. - _findWithSearch: function _findWithSearch(txn, store, options) { - debug("_findWithSearch:" + options.filterValue + options.filterOp) - store.getAll().onsuccess = function (event) { - debug("Request successful." + event.target.result); - txn.result = event.target.result.filter(function (record) { - let properties = record.properties; - for (let i = 0; i < options.filterBy.length; i++) { - let field = options.filterBy[i]; - if (!properties[field]) - continue; - let value = ''; - switch (field) { - case "name": - case "familyName": - case "givenName": - case "nickname": - case "email": - case "tel": - case "note": - value = [f for each (f in [properties[field]])].join("\n") || ''; - break; - default: - value = properties[field]; - debug("unknown field: " + field); - } - let match = false; - switch (options.filterOp) { - case "icontains": - match = value.toLowerCase().indexOf(options.filterValue.toLowerCase()) != -1; - break; - case "contains": - match = value.indexOf(options.filterValue) != -1; - break; - case "equals": - match = value == options.filterValue; - break - } - if (match) - return true; - } - return false; - }).map(this.makeExport.bind(this)); - }.bind(this); - }, - _findAll: function _findAll(txn, store, options) { debug("ContactDB:_findAll: " + JSON.stringify(options)); if (!txn.result) diff --git a/dom/contacts/tests/test_contacts_basics.html b/dom/contacts/tests/test_contacts_basics.html index 0b59521de052..546aff74a471 100644 --- a/dom/contacts/tests/test_contacts_basics.html +++ b/dom/contacts/tests/test_contacts_basics.html @@ -46,7 +46,7 @@ var adr2 = { var properties1 = { name: "Testname1", - familyName: "TestFamilyName", + familyName: ["TestFamilyName","Wagner"], givenName: ["Test1","Test2"], nickname: "nicktest", tel: ["123456"], @@ -211,6 +211,66 @@ var steps = [ }; req.onerror = onFailure; }, + function () { + ok(true, "Retrieving by substring"); + var options = {filterBy: ["name"], + filterOp: "contains", + filterValue: properties1.name.substring(0,3)}; + req = mozContacts.find(options); + req.onsuccess = function () { + ok(req.result.length == 1, "Found exactly 1 contact."); + findResult1 = req.result[0]; + ok(findResult1.id == sample_id1, "Same ID"); + checkContacts(createResult1, properties1); + next(); + }; + req.onerror = onFailure; + }, + function () { + ok(true, "Retrieving by substring2"); + var options = {filterBy: ["givenName"], + filterOp: "contains", + filterValue: properties1.givenName[0].substring(0,3)}; + req = mozContacts.find(options); + req.onsuccess = function () { + ok(req.result.length == 1, "Found exactly 1 contact."); + findResult1 = req.result[0]; + ok(findResult1.id == sample_id1, "Same ID"); + checkContacts(createResult1, properties1); + next(); + }; + req.onerror = onFailure; + }, + function () { + ok(true, "Retrieving by substring3"); + var options = {filterBy: ["name", "givenName"], + filterOp: "contains", + filterValue: properties1.givenName[0].substring(0,3)}; + req = mozContacts.find(options); + req.onsuccess = function () { + ok(req.result.length == 1, "Found exactly 1 contact."); + findResult1 = req.result[0]; + ok(findResult1.id == sample_id1, "Same ID"); + checkContacts(createResult1, properties1); + next(); + }; + req.onerror = onFailure; + }, + function () { + ok(true, "Retrieving by substring3, Testing multi entry"); + var options = {filterBy: ["name", "givenName", "familyName"], + filterOp: "contains", + filterValue: properties1.familyName[1].substring(0,3).toLowerCase()}; + req = mozContacts.find(options); + req.onsuccess = function () { + ok(req.result.length == 1, "Found exactly 1 contact."); + findResult1 = req.result[0]; + ok(findResult1.id == sample_id1, "Same ID"); + checkContacts(createResult1, properties1); + next(); + }; + req.onerror = onFailure; + }, function () { ok(true, "Retrieving all contacts"); req = mozContacts.find({}); @@ -306,7 +366,7 @@ var steps = [ function () { ok(true, "Searching contacts by query"); var options = {filterBy: ["name", "email"], - filterOp: "icontains", + filterOp: "contains", filterValue: properties1.name[0].substring(0,4)}; req = mozContacts.find(options); req.onsuccess = function () { @@ -321,7 +381,7 @@ var steps = [ function () { ok(true, "Searching contacts by query"); var options = {filterBy: ["nickname", "email"], - filterOp: "icontains", + filterOp: "contains", filterValue: properties1.nickname}; req = mozContacts.find(options); req.onsuccess = function () { @@ -429,7 +489,7 @@ var steps = [ function () { console.log("Searching contacts by query1"); var options = {filterBy: ["name", "email"], - filterOp: "icontains", + filterOp: "contains", filterValue: properties1.name[0].substring(0, 4)} req = mozContacts.find(options) req.onsuccess = function () { @@ -444,7 +504,7 @@ var steps = [ function () { ok(true, "Searching contacts by query2"); var options = {filterBy: ["name", "email"], - filterOp: "icontains", + filterOp: "contains", filterValue: properties2.name[0].substring(0, 4)}; req = mozContacts.find(options); req.onsuccess = function () { @@ -538,9 +598,9 @@ var steps = [ function () { ok(true, "Retrieving all contacts2"); var options = {filterBy: ["name"], - filterOp: "icontains", - filterValue: properties2.name[0].substring(0, 4)}; - req = mozContacts.find({}); + filterOp: "contains", + filterValue: properties1.name[0].substring(0, 4)}; + req = mozContacts.find(options); req.onsuccess = function () { ok(req.result.length == 100, "100 Entries."); checkContacts(createResult1, req.result[99]); @@ -548,6 +608,20 @@ var steps = [ } req.onerror = onFailure; }, + function () { + ok(true, "Retrieving all contacts3"); + var options = {filterBy: ["name", "givenName", "tel", "email", "note"], + filterOp: "contains", + filterValue: properties1.name[0].substring(0, 4), + filterLimit: 15 }; + req = mozContacts.find(options); + req.onsuccess = function () { + ok(req.result.length == 15, "15 Entries."); + checkContacts(createResult1, req.result[10]); + next(); + } + req.onerror = onFailure; + }, function () { ok(true, "Deleting database"); req = mozContacts.clear(); @@ -588,7 +662,7 @@ var steps = [ function () { ok(true, "Retrieving all contacts"); var options = {filterBy: ["name"], - filterOp: "icontains", + filterOp: "contains", filterValue: properties2.name[0].substring(0, 4)}; req = mozContacts.find({}); req.onsuccess = function () { From 0d7cf15ad0701e1cafae0553cca4490e0f7693a6 Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Thu, 8 Mar 2012 22:16:25 -0800 Subject: [PATCH 35/57] Bug 733652 - Remove geolocation address handling (v2). Little adoption, costly implementation r=jdm --- dom/base/nsDOMClassInfo.cpp | 7 -- dom/base/nsDOMClassInfoClasses.h | 1 - dom/interfaces/geolocation/Makefile.in | 1 - .../geolocation/nsIDOMGeoPosition.idl | 5 +- .../geolocation/nsIDOMGeoPositionAddress.idl | 51 --------- dom/src/geolocation/nsGeoPosition.cpp | 106 +----------------- dom/src/geolocation/nsGeoPosition.h | 38 ------- .../geolocation/nsGeoPositionIPCSerialiser.h | 101 +---------------- embedding/android/GeckoEvent.java | 3 +- embedding/android/GeckoSurfaceView.java | 42 +------ mobile/android/base/GeckoApp.java | 43 +------ mobile/android/base/GeckoEvent.java | 3 +- widget/android/AndroidJavaWrappers.cpp | 74 ------------ widget/android/AndroidJavaWrappers.h | 22 ---- widget/android/nsAppShell.cpp | 6 +- 15 files changed, 10 insertions(+), 493 deletions(-) delete mode 100644 dom/interfaces/geolocation/nsIDOMGeoPositionAddress.idl diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index d672d92484c7..845f556b5815 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -1422,9 +1422,6 @@ static nsDOMClassInfoData sClassInfoData[] = { NS_DEFINE_CLASSINFO_DATA(GeoPositionCoords, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) - NS_DEFINE_CLASSINFO_DATA(GeoPositionAddress, nsDOMGenericSH, - DOM_DEFAULT_SCRIPTABLE_FLAGS) - NS_DEFINE_CLASSINFO_DATA(GeoPositionError, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) @@ -4020,10 +4017,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_ENTRY(nsIDOMGeoPositionCoords) DOM_CLASSINFO_MAP_END - DOM_CLASSINFO_MAP_BEGIN(GeoPositionAddress, nsIDOMGeoPositionAddress) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMGeoPositionAddress) - DOM_CLASSINFO_MAP_END - DOM_CLASSINFO_MAP_BEGIN(GeoPositionError, nsIDOMGeoPositionError) DOM_CLASSINFO_MAP_ENTRY(nsIDOMGeoPositionError) DOM_CLASSINFO_MAP_END diff --git a/dom/base/nsDOMClassInfoClasses.h b/dom/base/nsDOMClassInfoClasses.h index 5885454b460b..311edab11809 100644 --- a/dom/base/nsDOMClassInfoClasses.h +++ b/dom/base/nsDOMClassInfoClasses.h @@ -422,7 +422,6 @@ DOMCI_CLASS(MessageEvent) DOMCI_CLASS(GeoGeolocation) DOMCI_CLASS(GeoPosition) DOMCI_CLASS(GeoPositionCoords) -DOMCI_CLASS(GeoPositionAddress) DOMCI_CLASS(GeoPositionError) DOMCI_CLASS(MozBatteryManager) diff --git a/dom/interfaces/geolocation/Makefile.in b/dom/interfaces/geolocation/Makefile.in index 67655d343924..e775bdc5af9a 100644 --- a/dom/interfaces/geolocation/Makefile.in +++ b/dom/interfaces/geolocation/Makefile.in @@ -49,7 +49,6 @@ GRE_MODULE = 1 XPIDLSRCS = \ nsIDOMGeoGeolocation.idl \ nsIDOMGeoPosition.idl \ - nsIDOMGeoPositionAddress.idl \ nsIDOMGeoPositionCoords.idl \ nsIDOMGeoPositionCallback.idl \ nsIDOMGeoPositionError.idl \ diff --git a/dom/interfaces/geolocation/nsIDOMGeoPosition.idl b/dom/interfaces/geolocation/nsIDOMGeoPosition.idl index 6895356b8a83..ee6c19ff1c28 100644 --- a/dom/interfaces/geolocation/nsIDOMGeoPosition.idl +++ b/dom/interfaces/geolocation/nsIDOMGeoPosition.idl @@ -37,13 +37,10 @@ #include "domstubs.idl" #include "nsIDOMGeoPositionCoords.idl" -#include "nsIDOMGeoPositionAddress.idl" -[scriptable, uuid(23E5269F-4DD7-41C4-B52A-75918694C2DE)] +[scriptable, uuid(dd9f7e81-0f74-4fb5-b361-37019bf60c3f)] interface nsIDOMGeoPosition : nsISupports { readonly attribute DOMTimeStamp timestamp; readonly attribute nsIDOMGeoPositionCoords coords; - readonly attribute nsIDOMGeoPositionAddress address; - }; diff --git a/dom/interfaces/geolocation/nsIDOMGeoPositionAddress.idl b/dom/interfaces/geolocation/nsIDOMGeoPositionAddress.idl deleted file mode 100644 index 63ba4df455b2..000000000000 --- a/dom/interfaces/geolocation/nsIDOMGeoPositionAddress.idl +++ /dev/null @@ -1,51 +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 Geolocation. - * - * The Initial Developer of the Original Code is Mozilla Foundation - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Doug Turner (Original Author) - * - * 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 ***** */ - - -#include "domstubs.idl" - -[scriptable, uuid(93abae10-7024-49eb-8e05-1931343b0ebb)] -interface nsIDOMGeoPositionAddress : nsISupports -{ - readonly attribute DOMString streetNumber; - readonly attribute DOMString street; - readonly attribute DOMString premises; - readonly attribute DOMString city; - readonly attribute DOMString county; - readonly attribute DOMString region; - readonly attribute DOMString country; - readonly attribute DOMString postalCode; -}; diff --git a/dom/src/geolocation/nsGeoPosition.cpp b/dom/src/geolocation/nsGeoPosition.cpp index b750b475435f..8981ef7a8144 100644 --- a/dom/src/geolocation/nsGeoPosition.cpp +++ b/dom/src/geolocation/nsGeoPosition.cpp @@ -40,100 +40,6 @@ #include "nsGeoPosition.h" #include "nsDOMClassInfoID.h" -//////////////////////////////////////////////////// -// nsGeoPositionAddress -//////////////////////////////////////////////////// - -nsGeoPositionAddress::nsGeoPositionAddress(const nsAString &aStreetNumber, - const nsAString &aStreet, - const nsAString &aPremises, - const nsAString &aCity, - const nsAString &aCounty, - const nsAString &aRegion, - const nsAString &aCountry, - const nsAString &aPostalCode) - : mStreetNumber(aStreetNumber) - , mStreet(aStreet) - , mPremises(aPremises) - , mCity(aCity) - , mCounty(aCounty) - , mRegion(aRegion) - , mCountry(aCountry) - , mPostalCode(aPostalCode) -{ -} - -nsGeoPositionAddress::~nsGeoPositionAddress() -{ -} - -DOMCI_DATA(GeoPositionAddress, nsGeoPositionAddress) - -NS_INTERFACE_MAP_BEGIN(nsGeoPositionAddress) -NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoPositionAddress) -NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionAddress) -NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(GeoPositionAddress) -NS_INTERFACE_MAP_END - -NS_IMPL_THREADSAFE_ADDREF(nsGeoPositionAddress) -NS_IMPL_THREADSAFE_RELEASE(nsGeoPositionAddress) - -NS_IMETHODIMP -nsGeoPositionAddress::GetStreetNumber(nsAString & aStreetNumber) -{ - aStreetNumber = mStreetNumber; - return NS_OK; -} - -NS_IMETHODIMP -nsGeoPositionAddress::GetStreet(nsAString & aStreet) -{ - aStreet = mStreet; - return NS_OK; -} - -NS_IMETHODIMP -nsGeoPositionAddress::GetPremises(nsAString & aPremises) -{ - aPremises = mPremises; - return NS_OK; -} - -NS_IMETHODIMP -nsGeoPositionAddress::GetCity(nsAString & aCity) -{ - aCity = mCity; - return NS_OK; -} - -NS_IMETHODIMP -nsGeoPositionAddress::GetCounty(nsAString & aCounty) -{ - aCounty = mCounty; - return NS_OK; -} - -NS_IMETHODIMP -nsGeoPositionAddress::GetRegion(nsAString & aRegion) -{ - aRegion = mRegion; - return NS_OK; -} - -NS_IMETHODIMP -nsGeoPositionAddress::GetCountry(nsAString & aCountry) -{ - aCountry = mCountry; - return NS_OK; -} - -NS_IMETHODIMP -nsGeoPositionAddress::GetPostalCode(nsAString & aPostalCode) -{ - aPostalCode = mPostalCode; - return NS_OK; -} - //////////////////////////////////////////////////// // nsGeoPositionCoords //////////////////////////////////////////////////// @@ -239,11 +145,9 @@ nsGeoPosition::nsGeoPosition(nsIDOMGeoPositionCoords *aCoords, } nsGeoPosition::nsGeoPosition(nsIDOMGeoPositionCoords *aCoords, - nsIDOMGeoPositionAddress *aAddress, DOMTimeStamp aTimestamp) : mTimestamp(aTimestamp), - mCoords(aCoords), - mAddress(aAddress) + mCoords(aCoords) { } @@ -275,11 +179,3 @@ nsGeoPosition::GetCoords(nsIDOMGeoPositionCoords * *aCoords) NS_IF_ADDREF(*aCoords = mCoords); return NS_OK; } - -NS_IMETHODIMP -nsGeoPosition::GetAddress(nsIDOMGeoPositionAddress** aAddress) -{ - NS_IF_ADDREF(*aAddress = mAddress); - return NS_OK; -} - diff --git a/dom/src/geolocation/nsGeoPosition.h b/dom/src/geolocation/nsGeoPosition.h index c763b5becd85..a7a29770251f 100644 --- a/dom/src/geolocation/nsGeoPosition.h +++ b/dom/src/geolocation/nsGeoPosition.h @@ -43,42 +43,10 @@ #include "nsAutoPtr.h" #include "nsIClassInfo.h" #include "nsDOMClassInfoID.h" -#include "nsIDOMGeoPositionAddress.h" #include "nsIDOMGeoPositionCoords.h" #include "nsIDOMGeoPosition.h" #include "nsString.h" -//////////////////////////////////////////////////// -// nsGeoPositionAddress -//////////////////////////////////////////////////// - -class nsGeoPositionAddress : public nsIDOMGeoPositionAddress -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSIDOMGEOPOSITIONADDRESS - - nsGeoPositionAddress( const nsAString &aStreetNumber, - const nsAString &aStreet, - const nsAString &aPremises, - const nsAString &aCity, - const nsAString &aCounty, - const nsAString &aRegion, - const nsAString &aCountry, - const nsAString &aPostalCode); - - ~nsGeoPositionAddress(); - private: - const nsString mStreetNumber; - const nsString mStreet; - const nsString mPremises; - const nsString mCity; - const nsString mCounty; - const nsString mRegion; - const nsString mCountry; - const nsString mPostalCode; -}; - //////////////////////////////////////////////////// // nsGeoPositionCoords //////////////////////////////////////////////////// @@ -122,18 +90,12 @@ public: long long aTimestamp); nsGeoPosition(nsIDOMGeoPositionCoords *aCoords, - nsIDOMGeoPositionAddress *aAddress, DOMTimeStamp aTimestamp); - void SetAddress(nsIDOMGeoPositionAddress *address) { - mAddress = address; - } - private: ~nsGeoPosition(); long long mTimestamp; nsRefPtr mCoords; - nsRefPtr mAddress; }; #endif /* nsGeoPosition_h */ diff --git a/dom/src/geolocation/nsGeoPositionIPCSerialiser.h b/dom/src/geolocation/nsGeoPositionIPCSerialiser.h index f4597f8a52fd..89d0c9215148 100644 --- a/dom/src/geolocation/nsGeoPositionIPCSerialiser.h +++ b/dom/src/geolocation/nsGeoPositionIPCSerialiser.h @@ -41,98 +41,11 @@ #include "nsGeoPosition.h" #include "nsIDOMGeoPosition.h" -typedef nsIDOMGeoPositionAddress *GeoPositionAddress; typedef nsGeoPositionCoords *GeoPositionCoords; typedef nsIDOMGeoPosition *GeoPosition; namespace IPC { -template <> -struct ParamTraits -{ - typedef GeoPositionAddress paramType; - - // Function to serialize a geo position address - static void Write(Message *aMsg, const paramType& aParam) - { - bool isNull = !aParam; - WriteParam(aMsg, isNull); - // If it is null, then we are done - if (isNull) return; - - nsString addressLine; - - aParam->GetStreetNumber(addressLine); - WriteParam(aMsg, addressLine); - - aParam->GetStreet(addressLine); - WriteParam(aMsg, addressLine); - - aParam->GetPremises(addressLine); - WriteParam(aMsg, addressLine); - - aParam->GetCity(addressLine); - WriteParam(aMsg, addressLine); - - aParam->GetCounty(addressLine); - WriteParam(aMsg, addressLine); - - aParam->GetRegion(addressLine); - WriteParam(aMsg, addressLine); - - aParam->GetCountry(addressLine); - WriteParam(aMsg, addressLine); - - aParam->GetPostalCode(addressLine); - WriteParam(aMsg, addressLine); - } - - // Function to de-serialize a geoposition - static bool Read(const Message* aMsg, void **aIter, paramType* aResult) - { - // Check if it is the null pointer we have transfered - bool isNull; - if (!ReadParam(aMsg, aIter, &isNull)) return false; - - if (isNull) { - *aResult = 0; - return true; - } - - // We need somewhere to store the address before we create the object - nsString streetNumber; - nsString street; - nsString premises; - nsString city; - nsString county; - nsString region; - nsString country; - nsString postalCode; - - // It's not important to us where it fails, but rather if it fails - if (!(ReadParam(aMsg, aIter, &streetNumber) && - ReadParam(aMsg, aIter, &street ) && - ReadParam(aMsg, aIter, &premises ) && - ReadParam(aMsg, aIter, &city ) && - ReadParam(aMsg, aIter, &county ) && - ReadParam(aMsg, aIter, ®ion ) && - ReadParam(aMsg, aIter, &country ) && - ReadParam(aMsg, aIter, &postalCode ))) return false; - - // We now have all the data - *aResult = new nsGeoPositionAddress(streetNumber, /* aStreetNumber */ - street, /* aStreet */ - premises, /* aPremises */ - city, /* aCity */ - county, /* aCounty */ - region, /* aRegion */ - country, /* aCountry */ - postalCode /* aPostalCode */ - ); - return true; - } -} ; - template <> struct ParamTraits { @@ -235,11 +148,6 @@ struct ParamTraits aParam->GetCoords(getter_AddRefs(coords)); GeoPositionCoords simpleCoords = static_cast(coords.get()); WriteParam(aMsg, simpleCoords); - - nsCOMPtr address; - aParam->GetAddress(getter_AddRefs(address)); - GeoPositionAddress simpleAddress = address.get(); - WriteParam(aMsg, simpleAddress); } // Function to de-serialize a geoposition @@ -256,20 +164,17 @@ struct ParamTraits DOMTimeStamp timeStamp; GeoPositionCoords coords = nsnull; - GeoPositionAddress address; // It's not important to us where it fails, but rather if it fails if (!( ReadParam(aMsg, aIter, &timeStamp) - && ReadParam(aMsg, aIter, &coords ) - && ReadParam(aMsg, aIter, &address ))) { + && ReadParam(aMsg, aIter, &coords ))) { // note it is fine to do "delete nsnull" in case coords hasn't - // been allocated and we will never have a case where address - // gets allocated and we end here + // been allocated delete coords; return false; } - *aResult = new nsGeoPosition(coords, address, timeStamp); + *aResult = new nsGeoPosition(coords, timeStamp); return true; }; diff --git a/embedding/android/GeckoEvent.java b/embedding/android/GeckoEvent.java index c3f4e892b517..3d178baf87fa 100644 --- a/embedding/android/GeckoEvent.java +++ b/embedding/android/GeckoEvent.java @@ -252,10 +252,9 @@ public class GeckoEvent { } } - public GeckoEvent(Location l, Address a) { + public GeckoEvent(Location l) { mType = LOCATION_EVENT; mLocation = l; - mAddress = a; } public GeckoEvent(int imeAction, int offset, int count) { diff --git a/embedding/android/GeckoSurfaceView.java b/embedding/android/GeckoSurfaceView.java index 385c8d1e29ed..77649a447cf7 100644 --- a/embedding/android/GeckoSurfaceView.java +++ b/embedding/android/GeckoSurfaceView.java @@ -580,47 +580,10 @@ class GeckoSurfaceView GeckoAppShell.sendEventToGecko(new GeckoEvent(event)); } - private class GeocoderTask extends AsyncTask { - protected Void doInBackground(Location... location) { - try { - List
    addresses = mGeocoder.getFromLocation(location[0].getLatitude(), - location[0].getLongitude(), 1); - // grab the first address. in the future, - // may want to expose multiple, or filter - // for best. - mLastGeoAddress = addresses.get(0); - GeckoAppShell.sendEventToGecko(new GeckoEvent(location[0], mLastGeoAddress)); - } catch (Exception e) { - Log.w(LOG_FILE_NAME, "GeocoderTask "+e); - } - return null; - } - } - // geolocation public void onLocationChanged(Location location) { - if (mGeocoder == null) - mGeocoder = new Geocoder(getContext(), Locale.getDefault()); - - if (mLastGeoAddress == null) { - new GeocoderTask().execute(location); - } - else { - float[] results = new float[1]; - Location.distanceBetween(location.getLatitude(), - location.getLongitude(), - mLastGeoAddress.getLatitude(), - mLastGeoAddress.getLongitude(), - results); - // pfm value. don't want to slam the - // geocoder with very similar values, so - // only call after about 100m - if (results[0] > 100) - new GeocoderTask().execute(location); - } - - GeckoAppShell.sendEventToGecko(new GeckoEvent(location, mLastGeoAddress)); + GeckoAppShell.sendEventToGecko(new GeckoEvent(location)); } public void onProviderDisabled(String provider) @@ -825,9 +788,6 @@ class GeckoSurfaceView ByteBuffer mSoftwareBuffer; Bitmap mSoftwareBufferCopy; - Geocoder mGeocoder; - Address mLastGeoAddress; - final SynchronousQueue mSyncDraws = new SynchronousQueue(); } diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index 59fd71b84add..454418156a39 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -139,8 +139,6 @@ abstract public class GeckoApp public static FormAssistPopup mFormAssistPopup; public Favicons mFavicons; - private Geocoder mGeocoder; - private Address mLastGeoAddress; private static LayerController mLayerController; private static PlaceholderLayerClient mPlaceholderLayerClient; private static GeckoSoftwareLayerClient mSoftwareLayerClient; @@ -2618,51 +2616,12 @@ abstract public class GeckoApp GeckoAppShell.sendEventToGecko(GeckoEvent.createSensorEvent(event)); } - private class GeocoderRunnable implements Runnable { - Location mLocation; - GeocoderRunnable (Location location) { - mLocation = location; - } - public void run() { - try { - List
    addresses = mGeocoder.getFromLocation(mLocation.getLatitude(), - mLocation.getLongitude(), 1); - // grab the first address. in the future, - // may want to expose multiple, or filter - // for best. - mLastGeoAddress = addresses.get(0); - GeckoAppShell.sendEventToGecko(GeckoEvent.createLocationEvent(mLocation, mLastGeoAddress)); - } catch (Exception e) { - Log.w(LOGTAG, "GeocoderTask "+e); - } - } - } - // geolocation public void onLocationChanged(Location location) { Log.w(LOGTAG, "onLocationChanged "+location); - if (mGeocoder == null) - mGeocoder = new Geocoder(mLayerController.getView().getContext(), Locale.getDefault()); - if (mLastGeoAddress == null) { - GeckoAppShell.getHandler().post(new GeocoderRunnable(location)); - } - else { - float[] results = new float[1]; - Location.distanceBetween(location.getLatitude(), - location.getLongitude(), - mLastGeoAddress.getLatitude(), - mLastGeoAddress.getLongitude(), - results); - // pfm value. don't want to slam the - // geocoder with very similar values, so - // only call after about 100m - if (results[0] > 100) - GeckoAppShell.getHandler().post(new GeocoderRunnable(location)); - } - - GeckoAppShell.sendEventToGecko(GeckoEvent.createLocationEvent(location, mLastGeoAddress)); + GeckoAppShell.sendEventToGecko(GeckoEvent.createLocationEvent(location)); } public void onProviderDisabled(String provider) diff --git a/mobile/android/base/GeckoEvent.java b/mobile/android/base/GeckoEvent.java index bfea49b4edce..7310b09a06f2 100644 --- a/mobile/android/base/GeckoEvent.java +++ b/mobile/android/base/GeckoEvent.java @@ -305,10 +305,9 @@ public class GeckoEvent { return event; } - public static GeckoEvent createLocationEvent(Location l, Address a) { + public static GeckoEvent createLocationEvent(Location l) { GeckoEvent event = new GeckoEvent(LOCATION_EVENT); event.mLocation = l; - event.mAddress = a; return event; } diff --git a/widget/android/AndroidJavaWrappers.cpp b/widget/android/AndroidJavaWrappers.cpp index 387a9011ee63..eb56c2699008 100644 --- a/widget/android/AndroidJavaWrappers.cpp +++ b/widget/android/AndroidJavaWrappers.cpp @@ -73,7 +73,6 @@ jfieldID AndroidGeckoEvent::jRangeStylesField = 0; jfieldID AndroidGeckoEvent::jRangeForeColorField = 0; jfieldID AndroidGeckoEvent::jRangeBackColorField = 0; jfieldID AndroidGeckoEvent::jLocationField = 0; -jfieldID AndroidGeckoEvent::jAddressField = 0; jfieldID AndroidGeckoEvent::jBandwidthField = 0; jfieldID AndroidGeckoEvent::jCanBeMeteredField = 0; @@ -96,19 +95,6 @@ jmethodID AndroidLocation::jGetBearingMethod = 0; jmethodID AndroidLocation::jGetSpeedMethod = 0; jmethodID AndroidLocation::jGetTimeMethod = 0; -jclass AndroidAddress::jAddressClass = 0; -jmethodID AndroidAddress::jGetAddressLineMethod; -jmethodID AndroidAddress::jGetAdminAreaMethod; -jmethodID AndroidAddress::jGetCountryNameMethod; -jmethodID AndroidAddress::jGetFeatureNameMethod; -jmethodID AndroidAddress::jGetLocalityMethod; -jmethodID AndroidAddress::jGetPostalCodeMethod; -jmethodID AndroidAddress::jGetPremisesMethod; -jmethodID AndroidAddress::jGetSubAdminAreaMethod; -jmethodID AndroidAddress::jGetSubLocalityMethod; -jmethodID AndroidAddress::jGetSubThoroughfareMethod; -jmethodID AndroidAddress::jGetThoroughfareMethod; - jclass AndroidGeckoSoftwareLayerClient::jGeckoSoftwareLayerClientClass = 0; jmethodID AndroidGeckoSoftwareLayerClient::jLockBufferMethod = 0; jmethodID AndroidGeckoSoftwareLayerClient::jUnlockBufferMethod = 0; @@ -142,7 +128,6 @@ mozilla::InitAndroidJavaWrappers(JNIEnv *jEnv) AndroidGeckoEvent::InitGeckoEventClass(jEnv); AndroidPoint::InitPointClass(jEnv); AndroidLocation::InitLocationClass(jEnv); - AndroidAddress::InitAddressClass(jEnv); AndroidRect::InitRectClass(jEnv); AndroidGeckoSoftwareLayerClient::InitGeckoSoftwareLayerClientClass(jEnv); AndroidGeckoSurfaceView::InitGeckoSurfaceViewClass(jEnv); @@ -186,7 +171,6 @@ AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv) jRangeForeColorField = getField("mRangeForeColor", "I"); jRangeBackColorField = getField("mRangeBackColor", "I"); jLocationField = getField("mLocation", "Landroid/location/Location;"); - jAddressField = getField("mAddress", "Landroid/location/Address;"); jBandwidthField = getField("mBandwidth", "D"); jCanBeMeteredField = getField("mCanBeMetered", "Z"); } @@ -225,60 +209,6 @@ AndroidLocation::InitLocationClass(JNIEnv *jEnv) jGetTimeMethod = getMethod("getTime", "()J"); } -void -AndroidAddress::InitAddressClass(JNIEnv *jEnv) -{ - initInit(); - - jAddressClass = getClassGlobalRef("android/location/Address"); - - jGetAddressLineMethod = getMethod("getAddressLine", "(I)Ljava/lang/String;"); - jGetAdminAreaMethod = getMethod("getAdminArea", "()Ljava/lang/String;"); - jGetCountryNameMethod = getMethod("getCountryName", "()Ljava/lang/String;"); - jGetFeatureNameMethod = getMethod("getFeatureName", "()Ljava/lang/String;"); - jGetLocalityMethod = getMethod("getLocality", "()Ljava/lang/String;"); - jGetPostalCodeMethod = getMethod("getPostalCode", "()Ljava/lang/String;"); - jGetPremisesMethod = getMethod("getPremises", "()Ljava/lang/String;"); - jGetSubAdminAreaMethod = getMethod("getSubAdminArea", "()Ljava/lang/String;"); - jGetSubLocalityMethod = getMethod("getSubLocality", "()Ljava/lang/String;"); - jGetSubThoroughfareMethod = getMethod("getSubThoroughfare", "()Ljava/lang/String;"); - jGetThoroughfareMethod = getMethod("getThoroughfare", "()Ljava/lang/String;"); -} - -nsGeoPositionAddress* -AndroidAddress::CreateGeoPositionAddress(JNIEnv *jenv, jobject jobj) -{ - nsJNIString streetNumber(static_cast(jenv->CallObjectMethod(jobj, jGetSubThoroughfareMethod)), jenv); - nsJNIString street(static_cast(jenv->CallObjectMethod(jobj, jGetThoroughfareMethod)), jenv); - nsJNIString city(static_cast(jenv->CallObjectMethod(jobj, jGetLocalityMethod)), jenv); - nsJNIString county(static_cast(jenv->CallObjectMethod(jobj, jGetSubAdminAreaMethod)), jenv); - nsJNIString country(static_cast(jenv->CallObjectMethod(jobj, jGetCountryNameMethod)), jenv); - nsJNIString premises(static_cast(jenv->CallObjectMethod(jobj, jGetPremisesMethod)), jenv); - nsJNIString postalCode(static_cast(jenv->CallObjectMethod(jobj, jGetPostalCodeMethod)), jenv); - nsJNIString region(static_cast(jenv->CallObjectMethod(jobj, jGetAdminAreaMethod, 0)), jenv); - -#ifdef DEBUG - printf_stderr("!!!!!!!!!!!!!! AndroidAddress::CreateGeoPositionAddress:\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n", - NS_LossyConvertUTF16toASCII(streetNumber).get(), - NS_LossyConvertUTF16toASCII(street).get(), - NS_LossyConvertUTF16toASCII(premises).get(), - NS_LossyConvertUTF16toASCII(city).get(), - NS_LossyConvertUTF16toASCII(county).get(), - NS_LossyConvertUTF16toASCII(region).get(), - NS_LossyConvertUTF16toASCII(country).get(), - NS_LossyConvertUTF16toASCII(postalCode).get()); -#endif - - return new nsGeoPositionAddress(streetNumber, - street, - premises, - city, - county, - region, - country, - postalCode); -} - nsGeoPosition* AndroidLocation::CreateGeoPosition(JNIEnv *jenv, jobject jobj) { @@ -511,11 +441,7 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj) case LOCATION_EVENT: { jobject location = jenv->GetObjectField(jobj, jLocationField); - jobject address = jenv->GetObjectField(jobj, jAddressField); - mGeoPosition = AndroidLocation::CreateGeoPosition(jenv, location); - if (address) - mGeoAddress = AndroidAddress::CreateGeoPositionAddress(jenv, address); break; } diff --git a/widget/android/AndroidJavaWrappers.h b/widget/android/AndroidJavaWrappers.h index 3ae573c1a6f8..2bb9cda55bdf 100644 --- a/widget/android/AndroidJavaWrappers.h +++ b/widget/android/AndroidJavaWrappers.h @@ -384,25 +384,6 @@ public: static jmethodID jGetTimeMethod; }; -class AndroidAddress : public WrappedJavaObject -{ -public: - static void InitAddressClass(JNIEnv *jEnv); - static nsGeoPositionAddress* CreateGeoPositionAddress(JNIEnv *jenv, jobject jobj); - static jclass jAddressClass; - static jmethodID jGetAddressLineMethod; - static jmethodID jGetAdminAreaMethod; - static jmethodID jGetCountryNameMethod; - static jmethodID jGetFeatureNameMethod; - static jmethodID jGetLocalityMethod; - static jmethodID jGetPostalCodeMethod; - static jmethodID jGetPremisesMethod; - static jmethodID jGetSubAdminAreaMethod; - static jmethodID jGetSubLocalityMethod; - static jmethodID jGetSubThoroughfareMethod; - static jmethodID jGetThoroughfareMethod; -}; - class AndroidGeckoEvent : public WrappedJavaObject { public: @@ -461,7 +442,6 @@ public: int RangeForeColor() { return mRangeForeColor; } int RangeBackColor() { return mRangeBackColor; } nsGeoPosition* GeoPosition() { return mGeoPosition; } - nsGeoPositionAddress* GeoAddress() { return mGeoAddress; } double Bandwidth() { return mBandwidth; } bool CanBeMetered() { return mCanBeMetered; } @@ -486,7 +466,6 @@ protected: int mPointerIndex; nsString mCharacters, mCharactersExtra; nsRefPtr mGeoPosition; - nsRefPtr mGeoAddress; double mBandwidth; bool mCanBeMetered; @@ -539,7 +518,6 @@ protected: static jfieldID jRangeForeColorField; static jfieldID jRangeBackColorField; static jfieldID jLocationField; - static jfieldID jAddressField; static jfieldID jBandwidthField; static jfieldID jCanBeMeteredField; diff --git a/widget/android/nsAppShell.cpp b/widget/android/nsAppShell.cpp index 83b24aa81e29..4a44ff40311a 100644 --- a/widget/android/nsAppShell.cpp +++ b/widget/android/nsAppShell.cpp @@ -351,12 +351,8 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait) break; nsGeoPosition* p = curEvent->GeoPosition(); - nsGeoPositionAddress* a = curEvent->GeoAddress(); - - if (p) { - p->SetAddress(a); + if (p) gLocationCallback->Update(curEvent->GeoPosition()); - } else NS_WARNING("Received location event without geoposition!"); break; From 71c690b58e0da6b6eee9e6ca8942f3e57b6a76bb Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Tue, 13 Mar 2012 16:57:09 -0700 Subject: [PATCH 36/57] Bug 733650 - Use smslib as the device orientation backend on the mac. r=jdm --- dom/system/cocoa/Makefile.in | 1 + dom/system/cocoa/nsDeviceMotionSystem.mm | 136 +--- dom/system/cocoa/smslib.h | 159 ++++ dom/system/cocoa/smslib.mm | 937 +++++++++++++++++++++++ toolkit/content/license.html | 54 ++ 5 files changed, 1163 insertions(+), 124 deletions(-) create mode 100644 dom/system/cocoa/smslib.h create mode 100644 dom/system/cocoa/smslib.mm diff --git a/dom/system/cocoa/Makefile.in b/dom/system/cocoa/Makefile.in index bbc3d49fe454..77041a2b87b6 100644 --- a/dom/system/cocoa/Makefile.in +++ b/dom/system/cocoa/Makefile.in @@ -52,6 +52,7 @@ EXPORT_LIBRARY = 1 include $(topsrcdir)/config/config.mk CMMSRCS = \ + smslib.mm \ nsDeviceMotionSystem.mm \ $(NULL) diff --git a/dom/system/cocoa/nsDeviceMotionSystem.mm b/dom/system/cocoa/nsDeviceMotionSystem.mm index 6fc0385c2ee6..6eefae0416c8 100644 --- a/dom/system/cocoa/nsDeviceMotionSystem.mm +++ b/dom/system/cocoa/nsDeviceMotionSystem.mm @@ -42,8 +42,8 @@ #include #include -#define MODEL_NAME_LENGTH 64 -static char gModelName[MODEL_NAME_LENGTH]; +#import "smslib.h" +#define MEAN_GRAVITY 9.80665 nsDeviceMotionSystem::nsDeviceMotionSystem() { @@ -53,24 +53,6 @@ nsDeviceMotionSystem::~nsDeviceMotionSystem() { } -// Data format returned from IOConnectMethodStructureIStructureO. -// I am not sure what the other bits in this structure are, -// or if there are any, but this has to be 40 bytes long or -// the call to read fails. -// -// Since we make the SmsData struct larger than any members we plan to access we -// keep track of the the size of the part of the struct we plan to access for -// use in bounds checking. -#define SMSDATA_PADDING_SIZE 34 -typedef struct -{ - PRInt16 x; - PRInt16 y; - PRInt16 z; - PRInt8 unknown[SMSDATA_PADDING_SIZE]; -} SmsData; -#define SMSDATA_USED_SIZE (sizeof(SmsData) - SMSDATA_PADDING_SIZE) - void nsDeviceMotionSystem::UpdateHandler(nsITimer *aTimer, void *aClosure) { @@ -79,112 +61,19 @@ nsDeviceMotionSystem::UpdateHandler(nsITimer *aTimer, void *aClosure) NS_ERROR("no self"); return; } + sms_acceleration accel; + smsGetData(&accel); - size_t bufferLen = sizeof(SmsData); - - void * input = malloc(bufferLen); - void * output = malloc(bufferLen); - - if (!input || !output) - return; - - memset(input, 0, bufferLen); - memset(output, 0, bufferLen); - - size_t structureOutputSize = bufferLen; -#if (MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4) - kern_return_t result = ::IOConnectMethodStructureIStructureO(self->mSmsConnection, - 5, /* Magic number for SMCMotionSensor */ - bufferLen, - (IOByteCount*)&structureOutputSize, - input, - output); -#else - kern_return_t result = ::IOConnectCallStructMethod((mach_port_t)self->mSmsConnection, - 5, /* Magic number for SMCMotionSensor */ - input, - bufferLen, - output, - &structureOutputSize); -#endif - - if ((result != kIOReturnSuccess) || (structureOutputSize < SMSDATA_USED_SIZE)) { - free(input); - free(output); - return; - } - - SmsData *data = (SmsData*) output; - - float xf, yf, zf; - - // we want to normalize the return result from the chip to - // something between -1 and 1 where 0 is the balance point. - - const int normalizeFactor = 250.5; - - if (!strcmp(gModelName, "MacBookPro5,1")) { - xf = ((float)data->x) / normalizeFactor; - yf = (((float)data->y) / normalizeFactor) * -1; - zf = ((float)data->z) / normalizeFactor; - } - else if (!strcmp(gModelName, "MacBookPro5,3")) { - xf = ((float)data->y) / normalizeFactor; - yf = (((float)data->x) / normalizeFactor) * -1; - zf = (((float)data->z) / normalizeFactor) * -1; - } - else - { - xf = (((float)data->x) / normalizeFactor) * -1; - yf = ((float)data->y) / normalizeFactor; - zf = ((float)data->z) / normalizeFactor; - } - - free(input); - free(output); - - self->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ACCELERATION, xf, yf, zf ); + self->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ACCELERATION, + accel.x * MEAN_GRAVITY, + accel.y * MEAN_GRAVITY, + accel.z * MEAN_GRAVITY); } void nsDeviceMotionSystem::Startup() { - // we can fail, and that just means the caller will not see any changes. - - mach_port_t port; - kern_return_t result = ::IOMasterPort(MACH_PORT_NULL, &port); - if (result != kIOReturnSuccess) - return; - - CFMutableDictionaryRef dict = ::IOServiceMatching("SMCMotionSensor"); - if (!dict) - return; - - io_iterator_t iter; - result = ::IOServiceGetMatchingServices(port, dict, &iter); - if (result != kIOReturnSuccess) - return; - - io_object_t device = ::IOIteratorNext(iter); - - ::IOObjectRelease(iter); - - if (!device) - return; - - result = ::IOServiceOpen(device, mach_task_self(), 0, &mSmsConnection); - ::IOObjectRelease(device); - - if (result != kIOReturnSuccess) - return; - - mach_port_deallocate(mach_task_self(), port); - - /* get the version of the hardware we are running on. */ - int mib[2]; - size_t len = MODEL_NAME_LENGTH; - mib[0] = CTL_HW; - mib[1] = HW_MODEL; - sysctl(mib, 2, gModelName, &len, NULL, 0); + smsStartup(nil, nil); + smsLoadCalibration(); mUpdateTimer = do_CreateInstance("@mozilla.org/timer;1"); if (mUpdateTimer) @@ -196,12 +85,11 @@ void nsDeviceMotionSystem::Startup() void nsDeviceMotionSystem::Shutdown() { - if (mSmsConnection) - ::IOServiceClose(mSmsConnection); - if (mUpdateTimer) { mUpdateTimer->Cancel(); mUpdateTimer = nsnull; } + + smsShutdown(); } diff --git a/dom/system/cocoa/smslib.h b/dom/system/cocoa/smslib.h new file mode 100644 index 000000000000..2f0b2664e459 --- /dev/null +++ b/dom/system/cocoa/smslib.h @@ -0,0 +1,159 @@ +/* + * smslib.h + * + * SMSLib Sudden Motion Sensor Access Library + * Copyright (c) 2010 Suitable Systems + * All rights reserved. + * + * Developed by: Daniel Griscom + * Suitable Systems + * http://www.suitable.com + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal with the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimers. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimers in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the names of Suitable Systems nor the names of its + * contributors may be used to endorse or promote products derived from + * this Software without specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. + * + * For more information about SMSLib, see + * + * or contact + * Daniel Griscom + * Suitable Systems + * 1 Centre Street, Suite 204 + * Wakefield, MA 01880 + * (781) 665-0053 + * + */ + +#import + +#define SMSLIB_VERSION "1.8" + +#pragma mark Structure definitions + +// Structure for specifying a 3-axis acceleration. 0.0 means "zero gravities", +// 1.0 means "one gravity". +typedef struct sms_acceleration { + float x; // Right-left acceleration (positive is rightwards) + float y; // Front-rear acceleration (positive is rearwards) + float z; // Up-down acceleration (positive is upwards) +} sms_acceleration; + +// Structure for specifying a calibration. +typedef struct sms_calibration { + float zeros[3]; // Zero points for three axes (X, Y, Z) + float onegs[3]; // One gravity values for three axes +} sms_calibration; + +#pragma mark Return value definitions + +// These are the return values for accelStartup(), giving the +// various stages where the most successful attempt at accessing +// the accelerometer failed. The higher the value, the further along the +// software progressed before failing. The options are: +// - Didn't match model name +#define SMS_FAIL_MODEL (-7) +// - Failure getting dictionary matching desired services +#define SMS_FAIL_DICTIONARY (-6) +// - Failure getting list of services +#define SMS_FAIL_LIST_SERVICES (-5) +// - Failure if list of services is empty. The process generally fails +// here if run on a machine without a Sudden Motion Sensor. +#define SMS_FAIL_NO_SERVICES (-4) +// - Failure if error opening device. +#define SMS_FAIL_OPENING (-3) +// - Failure if opened, but didn't get a connection +#define SMS_FAIL_CONNECTION (-2) +// - Failure if couldn't access connction using given function and size. This +// is where the process would probably fail with a change in Apple's API. +// Driver problems often also cause failures here. +#define SMS_FAIL_ACCESS (-1) +// - Success! +#define SMS_SUCCESS (0) + +#pragma mark Function declarations + +// This starts up the accelerometer code, trying each possible sensor +// specification. Note that for logging purposes it +// takes an object and a selector; the object's selector is then invoked +// with a single NSString as argument giving progress messages. Example +// logging method: +// - (void)logMessage: (NSString *)theString +// which would be used in accelStartup's invocation thusly: +// result = accelStartup(self, @selector(logMessage:)); +// If the object is nil, then no logging is done. Sets calibation from built-in +// value table. Returns ACCEL_SUCCESS for success, and other (negative) +// values for various failures (returns value indicating result of +// most successful trial). +int smsStartup(id logObject, SEL logSelector); + +// This starts up the library in debug mode, ignoring the actual hardware. +// Returned data is in the form of 1Hz sine waves, with the X, Y and Z +// axes 120 degrees out of phase; "calibrated" data has range +/- (1.0/5); +// "uncalibrated" data has range +/- (256/5). X and Y axes centered on 0.0, +// Z axes centered on 1 (calibrated) or 256 (uncalibrated). +// Don't use smsGetBufferLength or smsGetBufferData. Always returns SMS_SUCCESS. +int smsDebugStartup(id logObject, SEL logSelector); + +// Returns the current calibration values. +void smsGetCalibration(sms_calibration *calibrationRecord); + +// Sets the calibration, but does NOT store it as a preference. If the argument +// is nil then the current calibration is set from the built-in value table. +void smsSetCalibration(sms_calibration *calibrationRecord); + +// Stores the current calibration values as a stored preference. +void smsStoreCalibration(void); + +// Loads the stored preference values into the current calibration. +// Returns YES if successful. +BOOL smsLoadCalibration(void); + +// Deletes any stored calibration, and then takes the current calibration values +// from the built-in value table. +void smsDeleteCalibration(void); + +// Fills in the accel record with calibrated acceleration data. Takes +// 1-2ms to return a value. Returns 0 if success, error number if failure. +int smsGetData(sms_acceleration *accel); + +// Fills in the accel record with uncalibrated acceleration data. +// Returns 0 if success, error number if failure. +int smsGetUncalibratedData(sms_acceleration *accel); + +// Returns the length of a raw block of data for the current type of sensor. +int smsGetBufferLength(void); + +// Takes a pointer to accelGetRawLength() bytes; sets those bytes +// to return value from sensor. Make darn sure the buffer length is right! +void smsGetBufferData(char *buffer); + +// This returns an NSString describing the current calibration in +// human-readable form. Also include a description of the machine. +NSString *smsGetCalibrationDescription(void); + +// Shuts down the accelerometer. +void smsShutdown(void); + diff --git a/dom/system/cocoa/smslib.mm b/dom/system/cocoa/smslib.mm new file mode 100644 index 000000000000..8761a81f48fa --- /dev/null +++ b/dom/system/cocoa/smslib.mm @@ -0,0 +1,937 @@ +/* + * smslib.m + * + * SMSLib Sudden Motion Sensor Access Library + * Copyright (c) 2010 Suitable Systems + * All rights reserved. + * + * Developed by: Daniel Griscom + * Suitable Systems + * http://www.suitable.com + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal with the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimers. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimers in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the names of Suitable Systems nor the names of its + * contributors may be used to endorse or promote products derived from + * this Software without specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. + * + * For more information about SMSLib, see + * + * or contact + * Daniel Griscom + * Suitable Systems + * 1 Centre Street, Suite 204 + * Wakefield, MA 01880 + * (781) 665-0053 + * + */ + +#import +#import +#import +#import "smslib.h" + +#pragma mark Internal structures + +// Represents a single axis of a type of sensor. +typedef struct axisStruct { + int enabled; // Non-zero if axis is valid in this sensor + int index; // Location in struct of first byte + int size; // Number of bytes + float zerog; // Value meaning "zero g" + float oneg; // Change in value meaning "increase of one g" + // (can be negative if axis sensor reversed) +} axisStruct; + +// Represents the configuration of a type of sensor. +typedef struct sensorSpec { + char *model; // Prefix of model to be tested + char *name; // Name of device to be read + unsigned int function; // Kernel function index + int recordSize; // Size of record to be sent/received + axisStruct axes[3]; // Description of three axes (X, Y, Z) +} sensorSpec; + +// Configuration of all known types of sensors. The configurations are +// tried in order until one succeeds in returning data. +// All default values are set here, but each axis' zerog and oneg values +// may be changed to saved (calibrated) values. +// +// These values came from SeisMaCalibrate calibration reports. In general I've +// found the following: +// - All Intel-based SMSs have 250 counts per g, centered on 0, but the signs +// are different (and in one case two axes are swapped) +// - PowerBooks and iBooks all have sensors centered on 0, and reading +// 50-53 steps per gravity (but with differing polarities!) +// - PowerBooks and iBooks of the same model all have the same axis polarities +// - PowerBook and iBook access methods are model- and OS version-specific +// +// So, the sequence of tests is: +// - Try model-specific access methods. Note that the test is for a match to the +// beginning of the model name, e.g. the record with model name "MacBook" +// matches computer models "MacBookPro1,2" and "MacBook1,1" (and "" +// matches any model). +// - If no model-specific record's access fails, then try each model-independent +// access method in order, stopping when one works. +static const sensorSpec sensors[] = { + // ****** Model-dependent methods ****** + // The PowerBook5,6 is one of the G4 models that seems to lose + // SMS access until the next reboot. + {"PowerBook5,6", "IOI2CMotionSensor", 21, 60, { + {1, 0, 1, 0, 51.5}, + {1, 1, 1, 0, -51.5}, + {1, 2, 1, 0, -51.5} + } + }, + // The PowerBook5,7 is one of the G4 models that seems to lose + // SMS access until the next reboot. + {"PowerBook5,7", "IOI2CMotionSensor", 21, 60, { + {1, 0, 1, 0, 51.5}, + {1, 1, 1, 0, 51.5}, + {1, 2, 1, 0, 51.5} + } + }, + // Access seems to be reliable on the PowerBook5,8 + {"PowerBook5,8", "PMUMotionSensor", 21, 60, { + {1, 0, 1, 0, -51.5}, + {1, 1, 1, 0, 51.5}, + {1, 2, 1, 0, -51.5} + } + }, + // Access seems to be reliable on the PowerBook5,9 + {"PowerBook5,9", "PMUMotionSensor", 21, 60, { + {1, 0, 1, 0, 51.5}, + {1, 1, 1, 0, -51.5}, + {1, 2, 1, 0, -51.5} + } + }, + // The PowerBook6,7 is one of the G4 models that seems to lose + // SMS access until the next reboot. + {"PowerBook6,7", "IOI2CMotionSensor", 21, 60, { + {1, 0, 1, 0, 51.5}, + {1, 1, 1, 0, 51.5}, + {1, 2, 1, 0, 51.5} + } + }, + // The PowerBook6,8 is one of the G4 models that seems to lose + // SMS access until the next reboot. + {"PowerBook6,8", "IOI2CMotionSensor", 21, 60, { + {1, 0, 1, 0, 51.5}, + {1, 1, 1, 0, 51.5}, + {1, 2, 1, 0, 51.5} + } + }, + // MacBook Pro Core 2 Duo 17". Note the reversed Y and Z axes. + {"MacBookPro2,1", "SMCMotionSensor", 5, 40, { + {1, 0, 2, 0, 251}, + {1, 2, 2, 0, -251}, + {1, 4, 2, 0, -251} + } + }, + // MacBook Pro Core 2 Duo 15" AND 17" with LED backlight, introduced June '07. + // NOTE! The 17" machines have the signs of their X and Y axes reversed + // from this calibration, but there's no clear way to discriminate between + // the two machines. + {"MacBookPro3,1", "SMCMotionSensor", 5, 40, { + {1, 0, 2, 0, -251}, + {1, 2, 2, 0, 251}, + {1, 4, 2, 0, -251} + } + }, + // ... specs? + {"MacBook5,2", "SMCMotionSensor", 5, 40, { + {1, 0, 2, 0, -251}, + {1, 2, 2, 0, 251}, + {1, 4, 2, 0, -251} + } + }, + // ... specs? + {"MacBookPro5,1", "SMCMotionSensor", 5, 40, { + {1, 0, 2, 0, -251}, + {1, 2, 2, 0, -251}, + {1, 4, 2, 0, 251} + } + }, + // ... specs? + {"MacBookPro5,2", "SMCMotionSensor", 5, 40, { + {1, 0, 2, 0, -251}, + {1, 2, 2, 0, -251}, + {1, 4, 2, 0, 251} + } + }, + // This is speculative, based on a single user's report. Looks like the X and Y axes + // are swapped. This is true for no other known Appple laptop. + {"MacBookPro5,3", "SMCMotionSensor", 5, 40, { + {1, 2, 2, 0, -251}, + {1, 0, 2, 0, -251}, + {1, 4, 2, 0, -251} + } + }, + // ... specs? + {"MacBookPro5,4", "SMCMotionSensor", 5, 40, { + {1, 0, 2, 0, -251}, + {1, 2, 2, 0, -251}, + {1, 4, 2, 0, 251} + } + }, + // ****** Model-independent methods ****** + // Seen once with PowerBook6,8 under system 10.3.9; I suspect + // other G4-based 10.3.* systems might use this + {"", "IOI2CMotionSensor", 24, 60, { + {1, 0, 1, 0, 51.5}, + {1, 1, 1, 0, 51.5}, + {1, 2, 1, 0, 51.5} + } + }, + // PowerBook5,6 , PowerBook5,7 , PowerBook6,7 , PowerBook6,8 + // under OS X 10.4.* + {"", "IOI2CMotionSensor", 21, 60, { + {1, 0, 1, 0, 51.5}, + {1, 1, 1, 0, 51.5}, + {1, 2, 1, 0, 51.5} + } + }, + // PowerBook5,8 , PowerBook5,9 under OS X 10.4.* + {"", "PMUMotionSensor", 21, 60, { + // Each has two out of three gains negative, but it's different + // for the different models. So, this will be right in two out + // of three axis for either model. + {1, 0, 1, 0, -51.5}, + {1, 1, 1, -6, -51.5}, + {1, 2, 1, 0, -51.5} + } + }, + // All MacBook, MacBookPro models. Hardware (at least on early MacBookPro 15") + // is Kionix KXM52-1050 three-axis accelerometer chip. Data is at + // http://kionix.com/Product-Index/product-index.htm. Specific MB and MBP models + // that use this are: + // MacBook1,1 + // MacBook2,1 + // MacBook3,1 + // MacBook4,1 + // MacBook5,1 + // MacBook6,1 + // MacBookAir1,1 + // MacBookPro1,1 + // MacBookPro1,2 + // MacBookPro4,1 + // MacBookPro5,5 + {"", "SMCMotionSensor", 5, 40, { + {1, 0, 2, 0, 251}, + {1, 2, 2, 0, 251}, + {1, 4, 2, 0, 251} + } + } +}; + +#define SENSOR_COUNT (sizeof(sensors)/sizeof(sensorSpec)) + +#pragma mark Internal prototypes + +static int getData(sms_acceleration *accel, int calibrated, id logObject, SEL logSelector); +static float getAxis(int which, int calibrated); +static int signExtend(int value, int size); +static NSString *getModelName(void); +static NSString *getOSVersion(void); +static BOOL loadCalibration(void); +static void storeCalibration(void); +static void defaultCalibration(void); +static void deleteCalibration(void); +static int prefIntRead(NSString *prefName, BOOL *success); +static void prefIntWrite(NSString *prefName, int prefValue); +static float prefFloatRead(NSString *prefName, BOOL *success); +static void prefFloatWrite(NSString *prefName, float prefValue); +static void prefDelete(NSString *prefName); +static void prefSynchronize(void); +// static long getMicroseconds(void); +float fakeData(NSTimeInterval time); + +#pragma mark Static variables + +static int debugging = NO; // True if debugging (synthetic data) +static io_connect_t connection; // Connection for reading accel values +static int running = NO; // True if we successfully started +static int sensorNum = 0; // The current index into sensors[] +static char *serviceName; // The name of the current service +static char *iRecord, *oRecord; // Pointers to read/write records for sensor +static int recordSize; // Size of read/write records +static unsigned int function; // Which kernel function should be used +static float zeros[3]; // X, Y and Z zero calibration values +static float onegs[3]; // X, Y and Z one-g calibration values + +#pragma mark Defines + +// Pattern for building axis letter from axis number +#define INT_TO_AXIS(a) (a == 0 ? @"X" : a == 1 ? @"Y" : @"Z") +// Name of configuration for given axis' zero (axis specified by integer) +#define ZERO_NAME(a) [NSString stringWithFormat:@"%@-Axis-Zero", INT_TO_AXIS(a)] +// Name of configuration for given axis' oneg (axis specified by integer) +#define ONEG_NAME(a) [NSString stringWithFormat:@"%@-Axis-One-g", INT_TO_AXIS(a)] +// Name of "Is calibrated" preference +#define CALIBRATED_NAME (@"Calibrated") +// Application domain for SeisMac library +#define APP_ID ((CFStringRef)@"com.suitable.SeisMacLib") + +// These #defines make the accelStartup code a LOT easier to read. +#define LOG(message) \ + if (logObject) { \ + [logObject performSelector:logSelector withObject:message]; \ + } +#define LOG_ARG(format, var1) \ + if (logObject) { \ + [logObject performSelector:logSelector \ + withObject:[NSString stringWithFormat:format, var1]]; \ + } +#define LOG_2ARG(format, var1, var2) \ + if (logObject) { \ + [logObject performSelector:logSelector \ + withObject:[NSString stringWithFormat:format, var1, var2]]; \ + } +#define LOG_3ARG(format, var1, var2, var3) \ + if (logObject) { \ + [logObject performSelector:logSelector \ + withObject:[NSString stringWithFormat:format, var1, var2, var3]]; \ + } + +#pragma mark Function definitions + +// This starts up the accelerometer code, trying each possible sensor +// specification. Note that for logging purposes it +// takes an object and a selector; the object's selector is then invoked +// with a single NSString as argument giving progress messages. Example +// logging method: +// - (void)logMessage: (NSString *)theString +// which would be used in accelStartup's invocation thusly: +// result = accelStartup(self, @selector(logMessage:)); +// If the object is nil, then no logging is done. Sets calibation from built-in +// value table. Returns ACCEL_SUCCESS for success, and other (negative) +// values for various failures (returns value indicating result of +// most successful trial). +int smsStartup(id logObject, SEL logSelector) { + io_iterator_t iterator; + io_object_t device; + kern_return_t result; + sms_acceleration accel; + int failure_result = SMS_FAIL_MODEL; + + running = NO; + debugging = NO; + + NSString *modelName = getModelName(); + + LOG_ARG(@"Machine model: %@\n", modelName); + LOG_ARG(@"OS X version: %@\n", getOSVersion()); + LOG_ARG(@"Accelerometer library version: %s\n", SMSLIB_VERSION); + + for (sensorNum = 0; sensorNum < SENSOR_COUNT; sensorNum++) { + + // Set up all specs for this type of sensor + serviceName = sensors[sensorNum].name; + recordSize = sensors[sensorNum].recordSize; + function = sensors[sensorNum].function; + + LOG_3ARG(@"Trying service \"%s\" with selector %d and %d byte record:\n", + serviceName, function, recordSize); + + NSString *targetName = [NSString stringWithCString:sensors[sensorNum].model + encoding:NSMacOSRomanStringEncoding]; + LOG_ARG(@" Comparing model name to target \"%@\": ", targetName); + if ([targetName length] == 0 || [modelName hasPrefix:targetName]) { + LOG(@"success.\n"); + } else { + LOG(@"failure.\n"); + // Don't need to increment failure_result. + continue; + } + + LOG(@" Fetching dictionary for service: "); + CFMutableDictionaryRef dict = IOServiceMatching(serviceName); + + if (dict) { + LOG(@"success.\n"); + } else { + LOG(@"failure.\n"); + if (failure_result < SMS_FAIL_DICTIONARY) { + failure_result = SMS_FAIL_DICTIONARY; + } + continue; + } + + LOG(@" Getting list of matching services: "); + result = IOServiceGetMatchingServices(kIOMasterPortDefault, + dict, + &iterator); + + if (result == KERN_SUCCESS) { + LOG(@"success.\n"); + } else { + LOG_ARG(@"failure, with return value 0x%x.\n", result); + if (failure_result < SMS_FAIL_LIST_SERVICES) { + failure_result = SMS_FAIL_LIST_SERVICES; + } + continue; + } + + LOG(@" Getting first device in list: "); + device = IOIteratorNext(iterator); + + if (device == 0) { + LOG(@"failure.\n"); + if (failure_result < SMS_FAIL_NO_SERVICES) { + failure_result = SMS_FAIL_NO_SERVICES; + } + continue; + } else { + LOG(@"success.\n"); + LOG(@" Opening device: "); + } + + result = IOServiceOpen(device, mach_task_self(), 0, &connection); + + if (result != KERN_SUCCESS) { + LOG_ARG(@"failure, with return value 0x%x.\n", result); + IOObjectRelease(device); + if (failure_result < SMS_FAIL_OPENING) { + failure_result = SMS_FAIL_OPENING; + } + continue; + } else if (connection == 0) { + LOG_ARG(@"'success', but didn't get a connection.\n", result); + IOObjectRelease(device); + if (failure_result < SMS_FAIL_CONNECTION) { + failure_result = SMS_FAIL_CONNECTION; + } + continue; + } else { + IOObjectRelease(device); + LOG(@"success.\n"); + } + LOG(@" Testing device.\n"); + + defaultCalibration(); + + iRecord = (char*) malloc(recordSize); + oRecord = (char*) malloc(recordSize); + + running = YES; + result = getData(&accel, true, logObject, logSelector); + running = NO; + + if (result) { + LOG_ARG(@" Failure testing device, with result 0x%x.\n", result); + free(iRecord); + iRecord = 0; + free(oRecord); + oRecord = 0; + if (failure_result < SMS_FAIL_ACCESS) { + failure_result = SMS_FAIL_ACCESS; + } + continue; + } else { + LOG(@" Success testing device!\n"); + running = YES; + return SMS_SUCCESS; + } + } + return failure_result; +} + +// This starts up the library in debug mode, ignoring the actual hardware. +// Returned data is in the form of 1Hz sine waves, with the X, Y and Z +// axes 120 degrees out of phase; "calibrated" data has range +/- (1.0/5); +// "uncalibrated" data has range +/- (256/5). X and Y axes centered on 0.0, +// Z axes centered on 1 (calibrated) or 256 (uncalibrated). +// Don't use smsGetBufferLength or smsGetBufferData. Always returns SMS_SUCCESS. +int smsDebugStartup(id logObject, SEL logSelector) { + LOG(@"Starting up in debug mode\n"); + debugging = YES; + return SMS_SUCCESS; +} + +// Returns the current calibration values. +void smsGetCalibration(sms_calibration *calibrationRecord) { + int x; + + for (x = 0; x < 3; x++) { + calibrationRecord->zeros[x] = (debugging ? 0 : zeros[x]); + calibrationRecord->onegs[x] = (debugging ? 256 : onegs[x]); + } +} + +// Sets the calibration, but does NOT store it as a preference. If the argument +// is nil then the current calibration is set from the built-in value table. +void smsSetCalibration(sms_calibration *calibrationRecord) { + int x; + + if (!debugging) { + if (calibrationRecord) { + for (x = 0; x < 3; x++) { + zeros[x] = calibrationRecord->zeros[x]; + onegs[x] = calibrationRecord->onegs[x]; + } + } else { + defaultCalibration(); + } + } +} + +// Stores the current calibration values as a stored preference. +void smsStoreCalibration(void) { + if (!debugging) + storeCalibration(); +} + +// Loads the stored preference values into the current calibration. +// Returns YES if successful. +BOOL smsLoadCalibration(void) { + if (debugging) { + return YES; + } else if (loadCalibration()) { + return YES; + } else { + defaultCalibration(); + return NO; + } +} + +// Deletes any stored calibration, and then takes the current calibration values +// from the built-in value table. +void smsDeleteCalibration(void) { + if (!debugging) { + deleteCalibration(); + defaultCalibration(); + } +} + +// Fills in the accel record with calibrated acceleration data. Takes +// 1-2ms to return a value. Returns 0 if success, error number if failure. +int smsGetData(sms_acceleration *accel) { + NSTimeInterval time; + if (debugging) { + usleep(1500); // Usually takes 1-2 milliseconds + time = [NSDate timeIntervalSinceReferenceDate]; + accel->x = fakeData(time)/5; + accel->y = fakeData(time - 1)/5; + accel->z = fakeData(time - 2)/5 + 1.0; + return true; + } else { + return getData(accel, true, nil, nil); + } +} + +// Fills in the accel record with uncalibrated acceleration data. +// Returns 0 if success, error number if failure. +int smsGetUncalibratedData(sms_acceleration *accel) { + NSTimeInterval time; + if (debugging) { + usleep(1500); // Usually takes 1-2 milliseconds + time = [NSDate timeIntervalSinceReferenceDate]; + accel->x = fakeData(time) * 256 / 5; + accel->y = fakeData(time - 1) * 256 / 5; + accel->z = fakeData(time - 2) * 256 / 5 + 256; + return true; + } else { + return getData(accel, false, nil, nil); + } +} + +// Returns the length of a raw block of data for the current type of sensor. +int smsGetBufferLength(void) { + if (debugging) { + return 0; + } else if (running) { + return sensors[sensorNum].recordSize; + } else { + return 0; + } +} + +// Takes a pointer to accelGetRawLength() bytes; sets those bytes +// to return value from sensor. Make darn sure the buffer length is right! +void smsGetBufferData(char *buffer) { + IOItemCount iSize = recordSize; + IOByteCount oSize = recordSize; + kern_return_t result; + + if (debugging || running == NO) { + return; + } + + memset(iRecord, 1, iSize); + memset(buffer, 0, oSize); +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + const size_t InStructSize = recordSize; + size_t OutStructSize = recordSize; + result = IOConnectCallStructMethod(connection, + function, // magic kernel function number + (const void *)iRecord, + InStructSize, + (void *)buffer, + &OutStructSize + ); +#else // __MAC_OS_X_VERSION_MIN_REQUIRED 1050 + result = IOConnectMethodStructureIStructureO(connection, + function, // magic kernel function number + iSize, + &oSize, + iRecord, + buffer + ); +#endif // __MAC_OS_X_VERSION_MIN_REQUIRED 1050 + + if (result != KERN_SUCCESS) { + running = NO; + } +} + +// This returns an NSString describing the current calibration in +// human-readable form. Also include a description of the machine. +NSString *smsGetCalibrationDescription(void) { + BOOL success; + NSMutableString *s = [[NSMutableString alloc] init]; + + if (debugging) { + [s release]; + return @"Debugging!"; + } + + [s appendString:@"---- SeisMac Calibration Record ----\n \n"]; + [s appendFormat:@"Machine model: %@\n", + getModelName()]; + [s appendFormat:@"OS X build: %@\n", + getOSVersion()]; + [s appendFormat:@"SeisMacLib version %s, record %d\n \n", + SMSLIB_VERSION, sensorNum]; + [s appendFormat:@"Using service \"%s\", function index %d, size %d\n \n", + serviceName, function, recordSize]; + if (prefIntRead(CALIBRATED_NAME, &success) && success) { + [s appendString:@"Calibration values (from calibration):\n"]; + } else { + [s appendString:@"Calibration values (from defaults):\n"]; + } + [s appendFormat:@" X-Axis-Zero = %.2f\n", zeros[0]]; + [s appendFormat:@" X-Axis-One-g = %.2f\n", onegs[0]]; + [s appendFormat:@" Y-Axis-Zero = %.2f\n", zeros[1]]; + [s appendFormat:@" Y-Axis-One-g = %.2f\n", onegs[1]]; + [s appendFormat:@" Z-Axis-Zero = %.2f\n", zeros[2]]; + [s appendFormat:@" Z-Axis-One-g = %.2f\n \n", onegs[2]]; + [s appendString:@"---- End Record ----\n"]; + return s; +} + +// Shuts down the accelerometer. +void smsShutdown(void) { + if (!debugging) { + running = NO; + if (iRecord) free(iRecord); + if (oRecord) free(oRecord); + IOServiceClose(connection); + } +} + +#pragma mark Internal functions + +// Loads the current calibration from the stored preferences. +// Returns true iff successful. +BOOL loadCalibration(void) { + BOOL thisSuccess, allSuccess; + int x; + + prefSynchronize(); + + if (prefIntRead(CALIBRATED_NAME, &thisSuccess) && thisSuccess) { + // Calibrated. Set all values from saved values. + allSuccess = YES; + for (x = 0; x < 3; x++) { + zeros[x] = prefFloatRead(ZERO_NAME(x), &thisSuccess); + allSuccess &= thisSuccess; + onegs[x] = prefFloatRead(ONEG_NAME(x), &thisSuccess); + allSuccess &= thisSuccess; + } + return allSuccess; + } + + return NO; +} + +// Stores the current calibration into the stored preferences. +static void storeCalibration(void) { + int x; + prefIntWrite(CALIBRATED_NAME, 1); + for (x = 0; x < 3; x++) { + prefFloatWrite(ZERO_NAME(x), zeros[x]); + prefFloatWrite(ONEG_NAME(x), onegs[x]); + } + prefSynchronize(); +} + + +// Sets the calibration to its default values. +void defaultCalibration(void) { + int x; + for (x = 0; x < 3; x++) { + zeros[x] = sensors[sensorNum].axes[x].zerog; + onegs[x] = sensors[sensorNum].axes[x].oneg; + } +} + +// Deletes the stored preferences. +static void deleteCalibration(void) { + int x; + + prefDelete(CALIBRATED_NAME); + for (x = 0; x < 3; x++) { + prefDelete(ZERO_NAME(x)); + prefDelete(ONEG_NAME(x)); + } + prefSynchronize(); +} + +// Read a named floating point value from the stored preferences. Sets +// the success boolean based on, you guessed it, whether it succeeds. +static float prefFloatRead(NSString *prefName, BOOL *success) { + float result = 0.0f; + + CFPropertyListRef ref = CFPreferencesCopyAppValue((CFStringRef)prefName, + APP_ID); + // If there isn't such a preference, fail + if (ref == NULL) { + *success = NO; + return result; + } + CFTypeID typeID = CFGetTypeID(ref); + // Is it a number? + if (typeID == CFNumberGetTypeID()) { + // Is it a floating point number? + if (CFNumberIsFloatType((CFNumberRef)ref)) { + // Yup: grab it. + *success = CFNumberGetValue((__CFNumber*)ref, kCFNumberFloat32Type, &result); + } else { + // Nope: grab as an integer, and convert to a float. + long num; + if (CFNumberGetValue((CFNumberRef)ref, kCFNumberLongType, &num)) { + result = num; + *success = YES; + } else { + *success = NO; + } + } + // Or is it a string (e.g. set by the command line "defaults" command)? + } else if (typeID == CFStringGetTypeID()) { + result = (float)CFStringGetDoubleValue((CFStringRef)ref); + *success = YES; + } else { + // Can't convert to a number: fail. + *success = NO; + } + CFRelease(ref); + return result; +} + +// Writes a named floating point value to the stored preferences. +static void prefFloatWrite(NSString *prefName, float prefValue) { + CFNumberRef cfFloat = CFNumberCreate(kCFAllocatorDefault, + kCFNumberFloatType, + &prefValue); + CFPreferencesSetAppValue((CFStringRef)prefName, + cfFloat, + APP_ID); + CFRelease(cfFloat); +} + +// Reads a named integer value from the stored preferences. +static int prefIntRead(NSString *prefName, BOOL *success) { + Boolean internalSuccess; + CFIndex result = CFPreferencesGetAppIntegerValue((CFStringRef)prefName, + APP_ID, + &internalSuccess); + *success = internalSuccess; + + return result; +} + +// Writes a named integer value to the stored preferences. +static void prefIntWrite(NSString *prefName, int prefValue) { + CFPreferencesSetAppValue((CFStringRef)prefName, + (CFNumberRef)[NSNumber numberWithInt:prefValue], + APP_ID); +} + +// Deletes the named preference values. +static void prefDelete(NSString *prefName) { + CFPreferencesSetAppValue((CFStringRef)prefName, + NULL, + APP_ID); +} + +// Synchronizes the local preferences with the stored preferences. +static void prefSynchronize(void) { + CFPreferencesAppSynchronize(APP_ID); +} + +// Internal version of accelGetData, with logging +int getData(sms_acceleration *accel, int calibrated, id logObject, SEL logSelector) { + IOItemCount iSize = recordSize; + IOByteCount oSize = recordSize; + kern_return_t result; + + if (running == NO) { + return -1; + } + + memset(iRecord, 1, iSize); + memset(oRecord, 0, oSize); + + LOG_2ARG(@" Querying device: ", + sensors[sensorNum].function, sensors[sensorNum].recordSize); + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + const size_t InStructSize = recordSize; + size_t OutStructSize = recordSize; + result = IOConnectCallStructMethod(connection, + function, // magic kernel function number + (const void *)iRecord, + InStructSize, + (void *)oRecord, + &OutStructSize + ); +#else // __MAC_OS_X_VERSION_MIN_REQUIRED 1050 + result = IOConnectMethodStructureIStructureO(connection, + function, // magic kernel function number + iSize, + &oSize, + iRecord, + oRecord + ); +#endif // __MAC_OS_X_VERSION_MIN_REQUIRED 1050 + + if (result != KERN_SUCCESS) { + LOG(@"failed.\n"); + running = NO; + return result; + } else { + LOG(@"succeeded.\n"); + + accel->x = getAxis(0, calibrated); + accel->y = getAxis(1, calibrated); + accel->z = getAxis(2, calibrated); + return 0; + } +} + +// Given the returned record, extracts the value of the given axis. If +// calibrated, then zero G is 0.0, and one G is 1.0. +float getAxis(int which, int calibrated) { + // Get various values (to make code cleaner) + int indx = sensors[sensorNum].axes[which].index; + int size = sensors[sensorNum].axes[which].size; + float zerog = zeros[which]; + float oneg = onegs[which]; + // Storage for value to be returned + int value = 0; + + // Although the values in the returned record should have the proper + // endianness, we still have to get it into the proper end of value. +#if (BYTE_ORDER == BIG_ENDIAN) + // On PowerPC processors + memcpy(((char *)&value) + (sizeof(int) - size), &oRecord[indx], size); +#endif +#if (BYTE_ORDER == LITTLE_ENDIAN) + // On Intel processors + memcpy(&value, &oRecord[indx], size); +#endif + + value = signExtend(value, size); + + if (calibrated) { + // Scale and shift for zero. + return ((float)(value - zerog)) / oneg; + } else { + return value; + } +} + +// Extends the sign, given the length of the value. +int signExtend(int value, int size) { + // Extend sign + switch (size) { + case 1: + if (value & 0x00000080) + value |= 0xffffff00; + break; + case 2: + if (value & 0x00008000) + value |= 0xffff0000; + break; + case 3: + if (value & 0x00800000) + value |= 0xff000000; + break; + } + return value; +} + +// Returns the model name of the computer (e.g. "MacBookPro1,1") +NSString *getModelName(void) { + char model[32]; + size_t len = sizeof(model); + int name[2] = {CTL_HW, HW_MODEL}; + NSString *result; + + if (sysctl(name, 2, &model, &len, NULL, 0) == 0) { + result = [NSString stringWithFormat:@"%s", model]; + } else { + result = @""; + } + + return result; +} + +// Returns the current OS X version and build (e.g. "10.4.7 (build 8J2135a)") +NSString *getOSVersion(void) { + NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile: + @"/System/Library/CoreServices/SystemVersion.plist"]; + NSString *versionString = [dict objectForKey:@"ProductVersion"]; + NSString *buildString = [dict objectForKey:@"ProductBuildVersion"]; + NSString *wholeString = [NSString stringWithFormat:@"%@ (build %@)", + versionString, buildString]; + return wholeString; +} + +// Returns time within the current second in microseconds. +// long getMicroseconds() { +// struct timeval t; +// gettimeofday(&t, 0); +// return t.tv_usec; +//} + +// Returns fake data given the time. Range is +/-1. +float fakeData(NSTimeInterval time) { + long secs = lround(floor(time)); + int secsMod3 = secs % 3; + double angle = time * 10 * M_PI * 2; + double mag = exp(-(time - (secs - secsMod3)) * 2); + return sin(angle) * mag; +} + diff --git a/toolkit/content/license.html b/toolkit/content/license.html index 27775536b334..17b2bebc3510 100644 --- a/toolkit/content/license.html +++ b/toolkit/content/license.html @@ -94,6 +94,7 @@
  • Skia License
  • Snappy License
  • Sparkle License
  • +
  • Suitable Systems License
  • SunSoft License
  • University of California License
  • University of Cambridge License
  • @@ -2234,6 +2235,59 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +
    + +

    Suitable Systems License

    + +

    This license applies to certain files in the directory + dom/system/cocoa/.

    + +
    +SMSLib Sudden Motion Sensor Access Library
    +Copyright (c) 2010 Suitable Systems
    +All rights reserved.
    +
    +Developed by: Daniel Griscom
    +              Suitable Systems
    +              http://www.suitable.com
    +
    +Permission is hereby granted, free of charge, to any person obtaining a
    +copy of this software and associated documentation files (the
    +"Software"), to deal with the Software without restriction, including
    +without limitation the rights to use, copy, modify, merge, publish,
    +distribute, sublicense, and/or sell copies of the Software, and to
    +permit persons to whom the Software is furnished to do so, subject to
    +the following conditions:
    +
    +- Redistributions of source code must retain the above copyright notice,
    +this list of conditions and the following disclaimers.
    +
    +- Redistributions in binary form must reproduce the above copyright
    +notice, this list of conditions and the following disclaimers in the
    +documentation and/or other materials provided with the distribution.
    +
    +- Neither the names of Suitable Systems nor the names of its
    +contributors may be used to endorse or promote products derived from
    +this Software without specific prior written permission.
    +
    +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
    +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    +IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR
    +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    +SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
    +
    +For more information about SMSLib, see
    +	
    +or contact
    +	Daniel Griscom
    +	Suitable Systems
    +	1 Centre Street, Suite 204
    +	Wakefield, MA 01880
    +	(781) 665-0053
    +
    +
    From 277d8e613f9d0888c8606ec612204f1ccd5238dd Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Tue, 13 Mar 2012 16:57:09 -0700 Subject: [PATCH 37/57] Bug 733653 - use 100ms as the default sensor poll hint. Ensuring that our sensors are polled allows us to conform to the DeviceOrientation Event Specification. See DeviceMotionEvent.interval. r=jdm --- dom/system/cocoa/nsDeviceMotionSystem.mm | 3 ++- dom/system/nsDeviceMotion.cpp | 13 +++++-------- dom/system/nsDeviceMotion.h | 4 +--- dom/system/unix/nsDeviceMotionSystem.cpp | 4 +++- dom/system/windows/nsDeviceMotionSystem.cpp | 4 +++- mobile/android/base/GeckoAppShell.java | 9 ++++++--- 6 files changed, 20 insertions(+), 17 deletions(-) diff --git a/dom/system/cocoa/nsDeviceMotionSystem.mm b/dom/system/cocoa/nsDeviceMotionSystem.mm index 6eefae0416c8..bdeefdf679d5 100644 --- a/dom/system/cocoa/nsDeviceMotionSystem.mm +++ b/dom/system/cocoa/nsDeviceMotionSystem.mm @@ -44,6 +44,7 @@ #import "smslib.h" #define MEAN_GRAVITY 9.80665 +#define DEFAULT_SENSOR_POLL 100 nsDeviceMotionSystem::nsDeviceMotionSystem() { @@ -79,7 +80,7 @@ void nsDeviceMotionSystem::Startup() if (mUpdateTimer) mUpdateTimer->InitWithFuncCallback(UpdateHandler, this, - mUpdateInterval, + DEFAULT_SENSOR_POLL, nsITimer::TYPE_REPEATING_SLACK); } diff --git a/dom/system/nsDeviceMotion.cpp b/dom/system/nsDeviceMotion.cpp index 9c2230c63893..a986a1b44967 100644 --- a/dom/system/nsDeviceMotion.cpp +++ b/dom/system/nsDeviceMotion.cpp @@ -50,6 +50,9 @@ #include "nsIPrefService.h" #include "nsDOMDeviceMotionEvent.h" +// also see sDefaultSensorHint in mobile/android/base/GeckoAppShell.java +#define DEFAULT_SENSOR_POLL 100 + static const nsTArray::index_type NoIndex = nsTArray::NoIndex; @@ -117,18 +120,12 @@ NS_IMPL_ISUPPORTS2(nsDeviceMotion, nsIDeviceMotion, nsIDeviceMotionUpdate) nsDeviceMotion::nsDeviceMotion() : mStarted(false), - mUpdateInterval(50), /* default to 50 ms */ mEnabled(true) { nsCOMPtr prefSrv = do_GetService(NS_PREFSERVICE_CONTRACTID); if (prefSrv) { - PRInt32 value; - nsresult rv = prefSrv->GetIntPref("device.motion.update.interval", &value); - if (NS_SUCCEEDED(rv)) - mUpdateInterval = value; - bool bvalue; - rv = prefSrv->GetBoolPref("device.motion.enabled", &bvalue); + nsresult rv = prefSrv->GetBoolPref("device.motion.enabled", &bvalue); if (NS_SUCCEEDED(rv) && bvalue == false) mEnabled = false; } @@ -322,7 +319,7 @@ nsDeviceMotion::FireDOMMotionEvent(nsIDOMDocument *domdoc, nsnull, acceleration, nsnull, - 0); + DEFAULT_SENSOR_POLL); nsCOMPtr privateEvent = do_QueryInterface(event); if (privateEvent) diff --git a/dom/system/nsDeviceMotion.h b/dom/system/nsDeviceMotion.h index e2bada95fe6e..eacdd48ccb58 100644 --- a/dom/system/nsDeviceMotion.h +++ b/dom/system/nsDeviceMotion.h @@ -87,9 +87,7 @@ private: double x, double y, double z); - - PRUint32 mUpdateInterval; - bool mEnabled; + bool mEnabled; virtual void Startup() = 0; virtual void Shutdown() = 0; diff --git a/dom/system/unix/nsDeviceMotionSystem.cpp b/dom/system/unix/nsDeviceMotionSystem.cpp index 21e863e78498..7baaeb4aa197 100644 --- a/dom/system/unix/nsDeviceMotionSystem.cpp +++ b/dom/system/unix/nsDeviceMotionSystem.cpp @@ -42,6 +42,8 @@ #include "nsDeviceMotionSystem.h" #include "nsIServiceManager.h" +#define DEFAULT_SENSOR_POLL 100 + using namespace mozilla; typedef struct { @@ -223,7 +225,7 @@ void nsDeviceMotionSystem::Startup() if (mUpdateTimer) mUpdateTimer->InitWithFuncCallback(UpdateHandler, this, - mUpdateInterval, + DEFAULT_SENSOR_POLL, nsITimer::TYPE_REPEATING_SLACK); } diff --git a/dom/system/windows/nsDeviceMotionSystem.cpp b/dom/system/windows/nsDeviceMotionSystem.cpp index 767b9eca1a48..5ad353ae5fd4 100644 --- a/dom/system/windows/nsDeviceMotionSystem.cpp +++ b/dom/system/windows/nsDeviceMotionSystem.cpp @@ -39,6 +39,8 @@ #include "nsIServiceManager.h" #include "windows.h" +#define DEFAULT_SENSOR_POLL 100 + //////////////////////////// // ThinkPad //////////////////////////// @@ -156,7 +158,7 @@ void nsDeviceMotionSystem::Startup() if (mUpdateTimer) mUpdateTimer->InitWithFuncCallback(UpdateHandler, this, - mUpdateInterval, + DEFAULT_SENSOR_POLL, nsITimer::TYPE_REPEATING_SLACK); } diff --git a/mobile/android/base/GeckoAppShell.java b/mobile/android/base/GeckoAppShell.java index 35250a1e034a..065dc5e1c86b 100644 --- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -126,6 +126,9 @@ public class GeckoAppShell * sVibrationMaybePlaying is true. */ private static long sVibrationEndTime = 0; + /* Default value of how fast we should hint the Android sensors. */ + private static int sDefaultSensorHint = 100; + /* The Android-side API: API methods that Android calls */ // Initialization methods @@ -547,9 +550,9 @@ public class GeckoAppShell if (enable) { if (gAccelerometerSensor != null) - sm.registerListener(GeckoApp.mAppContext, gAccelerometerSensor, SensorManager.SENSOR_DELAY_GAME); + sm.registerListener(GeckoApp.mAppContext, gAccelerometerSensor, sDefaultSensorHint); if (gOrientationSensor != null) - sm.registerListener(GeckoApp.mAppContext, gOrientationSensor, SensorManager.SENSOR_DELAY_GAME); + sm.registerListener(GeckoApp.mAppContext, gOrientationSensor, sDefaultSensorHint); } else { if (gAccelerometerSensor != null) sm.unregisterListener(GeckoApp.mAppContext, gAccelerometerSensor); @@ -603,7 +606,7 @@ public class GeckoAppShell if(gProximitySensor == null) gProximitySensor = sm.getDefaultSensor(Sensor.TYPE_PROXIMITY); sm.registerListener(GeckoApp.mAppContext, gProximitySensor, - SensorManager.SENSOR_DELAY_GAME); + sDefaultSensorHint); break; } } From b8e66a3424d00d8724451e2b9d111e3f74b0d446 Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Tue, 13 Mar 2012 16:57:09 -0700 Subject: [PATCH 38/57] Bug 734325 - implement compassneedscalibration event. r=jdm --- dom/ipc/ContentChild.cpp | 10 +++++ dom/ipc/ContentChild.h | 2 + dom/ipc/ContentParent.cpp | 6 +++ dom/ipc/PContent.ipdl | 1 + dom/system/nsDeviceMotion.cpp | 58 ++++++++++++++++++++++++++ dom/system/nsDeviceMotion.h | 3 ++ mobile/android/base/GeckoApp.java | 2 + mobile/android/base/GeckoEvent.java | 13 ++++-- widget/android/AndroidJavaWrappers.cpp | 1 + widget/android/AndroidJavaWrappers.h | 1 + widget/android/nsAppShell.cpp | 11 +++-- xpcom/system/nsIDeviceMotion.idl | 6 ++- 12 files changed, 106 insertions(+), 8 deletions(-) diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index c81f30fd0545..459514bf8411 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -753,6 +753,16 @@ ContentChild::RecvDeviceMotionChanged(const long int& type, return true; } +bool +ContentChild::RecvNeedsCalibration() +{ + nsCOMPtr dmu = + do_GetService(NS_DEVICE_MOTION_CONTRACTID); + if (dmu) + dmu->NeedsCalibration(); + return true; +} + bool ContentChild::RecvScreenSizeChanged(const gfxIntSize& size) { diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index 206bf8342002..fafbe50bacd5 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -162,6 +162,8 @@ public: const double& x, const double& y, const double& z); + virtual bool RecvNeedsCalibration(); + virtual bool RecvScreenSizeChanged(const gfxIntSize &size); virtual bool RecvFlushMemory(const nsString& reason); diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 8507ac9a48c8..a237c87dbfff 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -1291,6 +1291,12 @@ ContentParent::OnMotionChange(nsIDeviceMotionData *aDeviceData) { return NS_OK; } +NS_IMETHODIMP +ContentParent::NeedsCalibration() { + unused << SendNeedsCalibration(); + return NS_OK; +} + } // namespace dom } // namespace mozilla diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 32efef5e119a..2e2823aa5600 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -134,6 +134,7 @@ child: AddPermission(Permission permission); DeviceMotionChanged(long type, double x, double y, double z); + NeedsCalibration(); ScreenSizeChanged(gfxIntSize size); diff --git a/dom/system/nsDeviceMotion.cpp b/dom/system/nsDeviceMotion.cpp index a986a1b44967..616f9e2c8926 100644 --- a/dom/system/nsDeviceMotion.cpp +++ b/dom/system/nsDeviceMotion.cpp @@ -261,6 +261,64 @@ nsDeviceMotion::DeviceMotionChanged(PRUint32 type, double x, double y, double z) return NS_OK; } +NS_IMETHODIMP +nsDeviceMotion::NeedsCalibration() +{ + if (!mEnabled) + return NS_ERROR_NOT_INITIALIZED; + + nsCOMArray listeners = mListeners; + for (PRUint32 i = listeners.Count(); i > 0 ; ) { + --i; + listeners[i]->NeedsCalibration(); + } + + nsCOMArray windowListeners; + for (PRUint32 i = 0; i < mWindowListeners.Length(); i++) { + windowListeners.AppendObject(mWindowListeners[i]); + } + + for (PRUint32 i = windowListeners.Count(); i > 0 ; ) { + --i; + + // check to see if this window is in the background. if + // it is, don't send any device motion to it. + nsCOMPtr pwindow = do_QueryInterface(windowListeners[i]); + if (!pwindow || + !pwindow->GetOuterWindow() || + pwindow->GetOuterWindow()->IsBackground()) + continue; + + nsCOMPtr domdoc; + windowListeners[i]->GetDocument(getter_AddRefs(domdoc)); + + if (domdoc) { + nsCOMPtr target = do_QueryInterface(windowListeners[i]); + FireNeedsCalibration(domdoc, target); + } + } + + return NS_OK; +} + +void +nsDeviceMotion::FireNeedsCalibration(nsIDOMDocument *domdoc, + nsIDOMEventTarget *target) +{ + nsCOMPtr event; + domdoc->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event)); + if (!event) + return; + + event->InitEvent(NS_LITERAL_STRING("compassneedscalibration"), true, false); + nsCOMPtr privateEvent = do_QueryInterface(event); + if (privateEvent) + privateEvent->SetTrusted(true); + + bool defaultActionEnabled = true; + target->DispatchEvent(event, &defaultActionEnabled); +} + void nsDeviceMotion::FireDOMOrientationEvent(nsIDOMDocument *domdoc, nsIDOMEventTarget *target, diff --git a/dom/system/nsDeviceMotion.h b/dom/system/nsDeviceMotion.h index eacdd48ccb58..68e0c7087078 100644 --- a/dom/system/nsDeviceMotion.h +++ b/dom/system/nsDeviceMotion.h @@ -76,6 +76,9 @@ private: protected: + void FireNeedsCalibration(nsIDOMDocument *domdoc, + nsIDOMEventTarget *target); + void FireDOMOrientationEvent(class nsIDOMDocument *domDoc, class nsIDOMEventTarget *target, double alpha, diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index 454418156a39..6de76b27ec0c 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -2608,6 +2608,8 @@ abstract public class GeckoApp // accelerometer public void onAccuracyChanged(Sensor sensor, int accuracy) { + Log.w(LOGTAG, "onAccuracyChanged "+accuracy); + GeckoAppShell.sendEventToGecko(GeckoEvent.createSensorAccuracyEvent(accuracy)); } public void onSensorChanged(SensorEvent event) diff --git a/mobile/android/base/GeckoEvent.java b/mobile/android/base/GeckoEvent.java index 7310b09a06f2..63b4244b966a 100644 --- a/mobile/android/base/GeckoEvent.java +++ b/mobile/android/base/GeckoEvent.java @@ -89,6 +89,7 @@ public class GeckoEvent { private static final int PROXIMITY_EVENT = 23; private static final int ACTIVITY_RESUMING = 24; private static final int SCREENSHOT = 25; + private static final int SENSOR_ACCURACY = 26; public static final int IME_COMPOSITION_END = 0; public static final int IME_COMPOSITION_BEGIN = 1; @@ -292,9 +293,9 @@ public class GeckoEvent { case Sensor.TYPE_ORIENTATION: event = new GeckoEvent(ORIENTATION_EVENT); - event.mAlpha = -s.values[0]; - event.mBeta = -s.values[1]; - event.mGamma = -s.values[2]; + event.mAlpha = s.values[0]; + event.mBeta = s.values[1]; + event.mGamma = s.values[2]; break; case Sensor.TYPE_PROXIMITY: @@ -408,4 +409,10 @@ public class GeckoEvent { event.mMetaState = tabId; return event; } + + public static GeckoEvent createSensorAccuracyEvent(int accuracy) { + GeckoEvent event = new GeckoEvent(SENSOR_ACCURACY); + event.mFlags = accuracy; + return event; + } } diff --git a/widget/android/AndroidJavaWrappers.cpp b/widget/android/AndroidJavaWrappers.cpp index eb56c2699008..6e352d2a4011 100644 --- a/widget/android/AndroidJavaWrappers.cpp +++ b/widget/android/AndroidJavaWrappers.cpp @@ -473,6 +473,7 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj) break; } + case SENSOR_ACCURACY: case ACTIVITY_STOPPING: case ACTIVITY_START: case ACTIVITY_PAUSING: diff --git a/widget/android/AndroidJavaWrappers.h b/widget/android/AndroidJavaWrappers.h index 2bb9cda55bdf..36283bf73861 100644 --- a/widget/android/AndroidJavaWrappers.h +++ b/widget/android/AndroidJavaWrappers.h @@ -549,6 +549,7 @@ public: PROXIMITY_EVENT = 23, ACTIVITY_RESUMING = 24, SCREENSHOT = 25, + SENSOR_ACCURACY = 26, dummy_java_enum_list_end }; diff --git a/widget/android/nsAppShell.cpp b/widget/android/nsAppShell.cpp index 4a44ff40311a..ed34f9ac6cec 100644 --- a/widget/android/nsAppShell.cpp +++ b/widget/android/nsAppShell.cpp @@ -331,6 +331,11 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait) NativeEventCallback(); break; + case AndroidGeckoEvent::SENSOR_ACCURACY: + if (curEvent->Flags() == 0) + gDeviceMotionSystem->NeedsCalibration(); + break; + case AndroidGeckoEvent::ACCELERATION_EVENT: gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ACCELERATION, -curEvent->X(), @@ -340,9 +345,9 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait) case AndroidGeckoEvent::ORIENTATION_EVENT: gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ORIENTATION, - -curEvent->Alpha(), - curEvent->Beta(), - curEvent->Gamma()); + curEvent->Alpha(), + -curEvent->Beta(), + -curEvent->Gamma()); mPendingOrientationEvents = false; break; diff --git a/xpcom/system/nsIDeviceMotion.idl b/xpcom/system/nsIDeviceMotion.idl index f24144f6a3e6..b83c286be4ca 100644 --- a/xpcom/system/nsIDeviceMotion.idl +++ b/xpcom/system/nsIDeviceMotion.idl @@ -51,10 +51,11 @@ interface nsIDeviceMotionData : nsISupports readonly attribute double z; }; -[scriptable, uuid(f01774a2-3b7e-4630-954b-196dc178221f)] +[scriptable, uuid(D29EA788-CCB6-4875-88E0-32A34BB71CBB)] interface nsIDeviceMotionListener : nsISupports { void onMotionChange(in nsIDeviceMotionData aMotionData); + void needsCalibration(); }; [scriptable, uuid(B6E5C463-AAA6-44E2-BD07-7A7DC6192E68)] @@ -73,9 +74,10 @@ interface nsIDeviceMotion : nsISupports /* for use by IPC system to notify non-chrome processes of * device motion events */ -[uuid(d3a56f08-b7b1-46bb-9dc1-fc3665a3631a)] +[uuid(C12C0157-DCFF-41B5-83F3-89179BF6CA4E)] interface nsIDeviceMotionUpdate : nsIDeviceMotion { /* must be called on the main thread or else */ void deviceMotionChanged(in unsigned long type, in double x, in double y, in double z); + void needsCalibration(); }; From 49f90f168cb6be51f7421ea0d18624fdec677aa2 Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Tue, 13 Mar 2012 16:57:51 -0700 Subject: [PATCH 39/57] Bug 734324 - implement device motion - rotation rate and acceleration. r=jdm --- dom/system/nsDeviceMotion.cpp | 29 +++++-- dom/system/nsDeviceMotion.h | 1 + hal/HalSensor.h | 2 + mobile/android/base/GeckoAppShell.java | 102 ++++++++++++++--------- mobile/android/base/GeckoEvent.java | 43 +++++++--- mobile/android/base/GeckoHalDefines.java | 49 +++++++++++ mobile/android/base/Makefile.in | 1 + widget/android/AndroidBridge.cpp | 47 +++++++---- widget/android/AndroidBridge.h | 1 - widget/android/AndroidJavaWrappers.cpp | 23 ++--- widget/android/AndroidJavaWrappers.h | 11 +-- widget/android/nsAppShell.cpp | 57 +++++++++---- widget/android/nsAppShell.h | 2 +- xpcom/system/nsIDeviceMotion.idl | 2 + 14 files changed, 250 insertions(+), 120 deletions(-) create mode 100644 mobile/android/base/GeckoHalDefines.java diff --git a/dom/system/nsDeviceMotion.cpp b/dom/system/nsDeviceMotion.cpp index 616f9e2c8926..240c46422f40 100644 --- a/dom/system/nsDeviceMotion.cpp +++ b/dom/system/nsDeviceMotion.cpp @@ -252,8 +252,10 @@ nsDeviceMotion::DeviceMotionChanged(PRUint32 type, double x, double y, double z) if (domdoc) { nsCOMPtr target = do_QueryInterface(windowListeners[i]); - if (type == nsIDeviceMotionData::TYPE_ACCELERATION) - FireDOMMotionEvent(domdoc, target, x, y, z); + if (type == nsIDeviceMotionData::TYPE_ACCELERATION || + type == nsIDeviceMotionData::TYPE_LINEAR_ACCELERATION || + type == nsIDeviceMotionData::TYPE_GYROSCOPE ) + FireDOMMotionEvent(domdoc, target, type, x, y, z); else if (type == nsIDeviceMotionData::TYPE_ORIENTATION) FireDOMOrientationEvent(domdoc, target, x, y, z); } @@ -355,6 +357,7 @@ nsDeviceMotion::FireDOMOrientationEvent(nsIDOMDocument *domdoc, void nsDeviceMotion::FireDOMMotionEvent(nsIDOMDocument *domdoc, nsIDOMEventTarget *target, + PRUint32 type, double x, double y, double z) { @@ -368,15 +371,29 @@ nsDeviceMotion::FireDOMMotionEvent(nsIDOMDocument *domdoc, return; } - // Currently acceleration as determined includes gravity. - nsRefPtr acceleration = new nsDOMDeviceAcceleration(x, y, z); + nsRefPtr acceleration; + nsRefPtr accelerationIncluduingGravity; + nsRefPtr rotationRate; + + switch (type) { + case nsIDeviceMotionData::TYPE_LINEAR_ACCELERATION: + acceleration = new nsDOMDeviceAcceleration(x, y, z); + break; + case nsIDeviceMotionData::TYPE_ACCELERATION: + accelerationIncluduingGravity = new nsDOMDeviceAcceleration(x, y, z); + break; + case nsIDeviceMotionData::TYPE_GYROSCOPE: + rotationRate = new nsDOMDeviceRotationRate(x, y, z); + break; + } + me->InitDeviceMotionEvent(NS_LITERAL_STRING("devicemotion"), true, false, - nsnull, acceleration, - nsnull, + accelerationIncluduingGravity, + rotationRate, DEFAULT_SENSOR_POLL); nsCOMPtr privateEvent = do_QueryInterface(event); diff --git a/dom/system/nsDeviceMotion.h b/dom/system/nsDeviceMotion.h index 68e0c7087078..ba55f9f201b7 100644 --- a/dom/system/nsDeviceMotion.h +++ b/dom/system/nsDeviceMotion.h @@ -87,6 +87,7 @@ private: void FireDOMMotionEvent(class nsIDOMDocument *domDoc, class nsIDOMEventTarget *target, + PRUint32 type, double x, double y, double z); diff --git a/hal/HalSensor.h b/hal/HalSensor.h index de4d8edac458..521c061787a7 100644 --- a/hal/HalSensor.h +++ b/hal/HalSensor.h @@ -54,6 +54,8 @@ enum SensorType { SENSOR_ORIENTATION, SENSOR_ACCELERATION, SENSOR_PROXIMITY, + SENSOR_LINEAR_ACCELERATION, + SENSOR_GYROSCOPE, NUM_SENSOR_TYPE }; diff --git a/mobile/android/base/GeckoAppShell.java b/mobile/android/base/GeckoAppShell.java index 065dc5e1c86b..0950eb664628 100644 --- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -129,6 +129,12 @@ public class GeckoAppShell /* Default value of how fast we should hint the Android sensors. */ private static int sDefaultSensorHint = 100; + private static Sensor gAccelerometerSensor = null; + private static Sensor gLinearAccelerometerSensor = null; + private static Sensor gGyroscopeSensor = null; + private static Sensor gOrientationSensor = null; + private static Sensor gProximitySensor = null; + /* The Android-side API: API methods that Android calls */ // Initialization methods @@ -536,31 +542,6 @@ public class GeckoAppShell tmp.countDown(); } - static Sensor gAccelerometerSensor = null; - static Sensor gOrientationSensor = null; - - public static void enableDeviceMotion(boolean enable) { - LayerView v = GeckoApp.mAppContext.getLayerController().getView(); - SensorManager sm = (SensorManager) v.getContext().getSystemService(Context.SENSOR_SERVICE); - - if (gAccelerometerSensor == null || gOrientationSensor == null) { - gAccelerometerSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); - gOrientationSensor = sm.getDefaultSensor(Sensor.TYPE_ORIENTATION); - } - - if (enable) { - if (gAccelerometerSensor != null) - sm.registerListener(GeckoApp.mAppContext, gAccelerometerSensor, sDefaultSensorHint); - if (gOrientationSensor != null) - sm.registerListener(GeckoApp.mAppContext, gOrientationSensor, sDefaultSensorHint); - } else { - if (gAccelerometerSensor != null) - sm.unregisterListener(GeckoApp.mAppContext, gAccelerometerSensor); - if (gOrientationSensor != null) - sm.unregisterListener(GeckoApp.mAppContext, gOrientationSensor); - } - } - public static void enableLocation(final boolean enable) { getMainHandler().post(new Runnable() { public void run() { @@ -588,26 +569,46 @@ public class GeckoAppShell }); } - /* - * Keep these values consistent with |SensorType| in Hal.h - */ - private static final int SENSOR_ORIENTATION = 1; - private static final int SENSOR_ACCELERATION = 2; - private static final int SENSOR_PROXIMITY = 3; - - private static Sensor gProximitySensor = null; - public static void enableSensor(int aSensortype) { SensorManager sm = (SensorManager) GeckoApp.mAppContext.getSystemService(Context.SENSOR_SERVICE); switch(aSensortype) { - case SENSOR_PROXIMITY: + case GeckoHalDefines.SENSOR_ORIENTATION: + if(gOrientationSensor == null) + gOrientationSensor = sm.getDefaultSensor(Sensor.TYPE_ORIENTATION); + if (gOrientationSensor != null) + sm.registerListener(GeckoApp.mAppContext, gOrientationSensor, sDefaultSensorHint); + break; + + case GeckoHalDefines.SENSOR_ACCELERATION: + if(gAccelerometerSensor == null) + gAccelerometerSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + if (gAccelerometerSensor != null) + sm.registerListener(GeckoApp.mAppContext, gAccelerometerSensor, sDefaultSensorHint); + break; + + case GeckoHalDefines.SENSOR_PROXIMITY: if(gProximitySensor == null) gProximitySensor = sm.getDefaultSensor(Sensor.TYPE_PROXIMITY); - sm.registerListener(GeckoApp.mAppContext, gProximitySensor, - sDefaultSensorHint); + if (gProximitySensor != null) + sm.registerListener(GeckoApp.mAppContext, gProximitySensor, sDefaultSensorHint); break; + + case GeckoHalDefines.SENSOR_LINEAR_ACCELERATION: + if(gLinearAccelerometerSensor == null) + gLinearAccelerometerSensor = sm.getDefaultSensor(10); + if (gLinearAccelerometerSensor != null) + sm.registerListener(GeckoApp.mAppContext, gLinearAccelerometerSensor, sDefaultSensorHint); + break; + + case GeckoHalDefines.SENSOR_GYROSCOPE: + if(gGyroscopeSensor == null) + gGyroscopeSensor = sm.getDefaultSensor(Sensor.TYPE_GYROSCOPE); + if (gGyroscopeSensor != null) + sm.registerListener(GeckoApp.mAppContext, gGyroscopeSensor, sDefaultSensorHint); + break; + } } @@ -615,9 +616,30 @@ public class GeckoAppShell SensorManager sm = (SensorManager) GeckoApp.mAppContext.getSystemService(Context.SENSOR_SERVICE); - switch(aSensortype) { - case SENSOR_PROXIMITY: - sm.unregisterListener(GeckoApp.mAppContext, gProximitySensor); + switch (aSensortype) { + case GeckoHalDefines.SENSOR_ORIENTATION: + if (gOrientationSensor != null) + sm.unregisterListener(GeckoApp.mAppContext, gOrientationSensor); + break; + + case GeckoHalDefines.SENSOR_ACCELERATION: + if (gAccelerometerSensor != null) + sm.unregisterListener(GeckoApp.mAppContext, gAccelerometerSensor); + break; + + case GeckoHalDefines.SENSOR_PROXIMITY: + if (gProximitySensor != null) + sm.unregisterListener(GeckoApp.mAppContext, gProximitySensor); + break; + + case GeckoHalDefines.SENSOR_LINEAR_ACCELERATION: + if (gLinearAccelerometerSensor != null) + sm.unregisterListener(GeckoApp.mAppContext, gLinearAccelerometerSensor); + break; + + case GeckoHalDefines.SENSOR_GYROSCOPE: + if (gGyroscopeSensor != null) + sm.unregisterListener(GeckoApp.mAppContext, gGyroscopeSensor); break; } } diff --git a/mobile/android/base/GeckoEvent.java b/mobile/android/base/GeckoEvent.java index 63b4244b966a..e3b4f80b986e 100644 --- a/mobile/android/base/GeckoEvent.java +++ b/mobile/android/base/GeckoEvent.java @@ -52,6 +52,7 @@ import android.util.DisplayMetrics; import android.graphics.PointF; import android.text.format.Time; import android.os.SystemClock; +import java.lang.Math; import java.lang.System; import android.util.Log; @@ -68,8 +69,8 @@ public class GeckoEvent { private static final int NATIVE_POKE = 0; private static final int KEY_EVENT = 1; private static final int MOTION_EVENT = 2; - private static final int ORIENTATION_EVENT = 3; - private static final int ACCELERATION_EVENT = 4; + private static final int SENSOR_EVENT = 3; + private static final int UNUSED1_EVENT = 4; private static final int LOCATION_EVENT = 5; private static final int IME_EVENT = 6; private static final int DRAW = 7; @@ -121,7 +122,6 @@ public class GeckoEvent { public Point[] mPointRadii; public Rect mRect; public double mX, mY, mZ; - public double mAlpha, mBeta, mGamma; public double mDistance; public int mMetaState, mFlags; @@ -280,25 +280,46 @@ public class GeckoEvent { } public static GeckoEvent createSensorEvent(SensorEvent s) { - GeckoEvent event = null; int sensor_type = s.sensor.getType(); - + GeckoEvent event = null; + switch(sensor_type) { + case Sensor.TYPE_ACCELEROMETER: - event = new GeckoEvent(ACCELERATION_EVENT); + event = new GeckoEvent(SENSOR_EVENT); + event.mFlags = GeckoHalDefines.SENSOR_ACCELERATION; event.mX = s.values[0]; event.mY = s.values[1]; event.mZ = s.values[2]; break; - + + case 10 /* Requires API Level 9, so just use the raw value - Sensor.TYPE_LINEAR_ACCELEROMETER*/ : + event = new GeckoEvent(SENSOR_EVENT); + event.mFlags = GeckoHalDefines.SENSOR_LINEAR_ACCELERATION; + event.mX = s.values[0]; + event.mY = s.values[1]; + event.mZ = s.values[2]; + break; + case Sensor.TYPE_ORIENTATION: - event = new GeckoEvent(ORIENTATION_EVENT); - event.mAlpha = s.values[0]; - event.mBeta = s.values[1]; - event.mGamma = s.values[2]; + event = new GeckoEvent(SENSOR_EVENT); + event.mFlags = GeckoHalDefines.SENSOR_ORIENTATION; + event.mX = s.values[0]; + event.mY = s.values[1]; + event.mZ = s.values[2]; + break; + + case Sensor.TYPE_GYROSCOPE: + event = new GeckoEvent(SENSOR_EVENT); + event.mFlags = GeckoHalDefines.SENSOR_GYROSCOPE; + event.mX = Math.toDegrees(s.values[0]); + event.mY = Math.toDegrees(s.values[1]); + event.mZ = Math.toDegrees(s.values[2]); break; case Sensor.TYPE_PROXIMITY: + // bug 734854 - maybe we can get rid of this event. is + // values[1] and values[2] valid? event = new GeckoEvent(PROXIMITY_EVENT); event.mDistance = s.values[0]; break; diff --git a/mobile/android/base/GeckoHalDefines.java b/mobile/android/base/GeckoHalDefines.java new file mode 100644 index 000000000000..ea6e02e06513 --- /dev/null +++ b/mobile/android/base/GeckoHalDefines.java @@ -0,0 +1,49 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Android code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2012 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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; + +public class GeckoHalDefines +{ + /* + * Keep these values consistent with |SensorType| in Hal.h + */ + public static final int SENSOR_ORIENTATION = 0; + public static final int SENSOR_ACCELERATION = 1; + public static final int SENSOR_PROXIMITY = 2; + public static final int SENSOR_LINEAR_ACCELERATION = 3; + public static final int SENSOR_GYROSCOPE = 4; +}; diff --git a/mobile/android/base/Makefile.in b/mobile/android/base/Makefile.in index 7f56871d9683..79a358c5aa68 100644 --- a/mobile/android/base/Makefile.in +++ b/mobile/android/base/Makefile.in @@ -87,6 +87,7 @@ FENNEC_JAVA_FILES = \ GeckoEvent.java \ GeckoEventListener.java \ GeckoEventResponder.java \ + GeckoHalDefines.java \ GeckoInputConnection.java \ GeckoMessageReceiver.java \ GeckoPreferences.java \ diff --git a/widget/android/AndroidBridge.cpp b/widget/android/AndroidBridge.cpp index be5ec97216e9..30311c11ab17 100644 --- a/widget/android/AndroidBridge.cpp +++ b/widget/android/AndroidBridge.cpp @@ -111,14 +111,9 @@ AndroidBridge::Init(JNIEnv *jEnv, jNotifyScreenShot = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "notifyScreenShot", "(Ljava/nio/ByteBuffer;III)V"); jAcknowledgeEventSync = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "acknowledgeEventSync", "()V"); - jEnableDeviceMotion = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "enableDeviceMotion", "(Z)V"); jEnableLocation = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "enableLocation", "(Z)V"); - jEnableSensor = - (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, - "enableSensor", "(I)V"); - jDisableSensor = - (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, - "disableSensor", "(I)V"); + jEnableSensor = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "enableSensor", "(I)V"); + jDisableSensor = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "disableSensor", "(I)V"); jReturnIMEQueryResult = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "returnIMEQueryResult", "(Ljava/lang/String;II)V"); jScheduleRestart = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "scheduleRestart", "()V"); jNotifyXreExit = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "onXreExit", "()V"); @@ -311,13 +306,23 @@ AndroidBridge::EnableDeviceMotion(bool aEnable) { ALOG_BRIDGE("AndroidBridge::EnableDeviceMotion"); - JNIEnv *env = GetJNIEnv(); - if (!env) - return; - - env->CallStaticVoidMethod(mGeckoAppShellClass, jEnableDeviceMotion, aEnable); + // bug 734855 - we probably can make this finer grain based on + // the DOM APIs that are being invoked. + if (aEnable) { + EnableSensor(hal::SENSOR_ORIENTATION); + EnableSensor(hal::SENSOR_ACCELERATION); + EnableSensor(hal::SENSOR_LINEAR_ACCELERATION); + EnableSensor(hal::SENSOR_GYROSCOPE); + } + else { + DisableSensor(hal::SENSOR_ORIENTATION); + DisableSensor(hal::SENSOR_ACCELERATION); + DisableSensor(hal::SENSOR_LINEAR_ACCELERATION); + DisableSensor(hal::SENSOR_GYROSCOPE); + } } + void AndroidBridge::EnableLocation(bool aEnable) { @@ -326,22 +331,30 @@ AndroidBridge::EnableLocation(bool aEnable) JNIEnv *env = GetJNIEnv(); if (!env) return; - + + AutoLocalJNIFrame jniFrame(env, 1); env->CallStaticVoidMethod(mGeckoAppShellClass, jEnableLocation, aEnable); } void AndroidBridge::EnableSensor(int aSensorType) { ALOG_BRIDGE("AndroidBridge::EnableSensor"); - mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jEnableSensor, - aSensorType); + JNIEnv *env = GetJNIEnv(); + if (!env) + return; + + AutoLocalJNIFrame jniFrame(env, 1); + env->CallStaticVoidMethod(mGeckoAppShellClass, jEnableSensor, aSensorType); } void AndroidBridge::DisableSensor(int aSensorType) { ALOG_BRIDGE("AndroidBridge::DisableSensor"); - mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jDisableSensor, - aSensorType); + JNIEnv *env = GetJNIEnv(); + if (!env) + return; + AutoLocalJNIFrame jniFrame(env, 1); + env->CallStaticVoidMethod(mGeckoAppShellClass, jDisableSensor, aSensorType); } void diff --git a/widget/android/AndroidBridge.h b/widget/android/AndroidBridge.h index 54c9e35b8667..391259fb56fe 100644 --- a/widget/android/AndroidBridge.h +++ b/widget/android/AndroidBridge.h @@ -424,7 +424,6 @@ protected: jmethodID jNotifyIMEChange; jmethodID jNotifyScreenShot; jmethodID jAcknowledgeEventSync; - jmethodID jEnableDeviceMotion; jmethodID jEnableLocation; jmethodID jEnableSensor; jmethodID jDisableSensor; diff --git a/widget/android/AndroidJavaWrappers.cpp b/widget/android/AndroidJavaWrappers.cpp index 6e352d2a4011..841547ed54d7 100644 --- a/widget/android/AndroidJavaWrappers.cpp +++ b/widget/android/AndroidJavaWrappers.cpp @@ -49,9 +49,6 @@ jfieldID AndroidGeckoEvent::jPointIndicies = 0; jfieldID AndroidGeckoEvent::jPressures = 0; jfieldID AndroidGeckoEvent::jPointRadii = 0; jfieldID AndroidGeckoEvent::jOrientations = 0; -jfieldID AndroidGeckoEvent::jAlphaField = 0; -jfieldID AndroidGeckoEvent::jBetaField = 0; -jfieldID AndroidGeckoEvent::jGammaField = 0; jfieldID AndroidGeckoEvent::jXField = 0; jfieldID AndroidGeckoEvent::jYField = 0; jfieldID AndroidGeckoEvent::jZField = 0; @@ -148,9 +145,6 @@ AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv) jOrientations = getField("mOrientations", "[F"); jPressures = getField("mPressures", "[F"); jPointRadii = getField("mPointRadii", "[Landroid/graphics/Point;"); - jAlphaField = getField("mAlpha", "D"); - jBetaField = getField("mBeta", "D"); - jGammaField = getField("mGamma", "D"); jXField = getField("mX", "D"); jYField = getField("mY", "D"); jZField = getField("mZ", "D"); @@ -427,17 +421,12 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj) ReadRectField(jenv); break; - case ORIENTATION_EVENT: - mAlpha = jenv->GetDoubleField(jobj, jAlphaField); - mBeta = jenv->GetDoubleField(jobj, jBetaField); - mGamma = jenv->GetDoubleField(jobj, jGammaField); - break; - - case ACCELERATION_EVENT: - mX = jenv->GetDoubleField(jobj, jXField); - mY = jenv->GetDoubleField(jobj, jYField); - mZ = jenv->GetDoubleField(jobj, jZField); - break; + case SENSOR_EVENT: + mX = jenv->GetDoubleField(jobj, jXField); + mY = jenv->GetDoubleField(jobj, jYField); + mZ = jenv->GetDoubleField(jobj, jZField); + mFlags = jenv->GetIntField(jobj, jFlagsField); + break; case LOCATION_EVENT: { jobject location = jenv->GetObjectField(jobj, jLocationField); diff --git a/widget/android/AndroidJavaWrappers.h b/widget/android/AndroidJavaWrappers.h index 36283bf73861..af3de14482fb 100644 --- a/widget/android/AndroidJavaWrappers.h +++ b/widget/android/AndroidJavaWrappers.h @@ -420,9 +420,6 @@ public: nsTArray Pressures() { return mPressures; } nsTArray Orientations() { return mOrientations; } nsTArray PointRadii() { return mPointRadii; } - double Alpha() { return mAlpha; } - double Beta() { return mBeta; } - double Gamma() { return mGamma; } double X() { return mX; } double Y() { return mY; } double Z() { return mZ; } @@ -460,7 +457,6 @@ protected: int mOffset, mCount; int mRangeType, mRangeStyles; int mRangeForeColor, mRangeBackColor; - double mAlpha, mBeta, mGamma; double mX, mY, mZ; double mDistance; int mPointerIndex; @@ -494,9 +490,6 @@ protected: static jfieldID jOrientations; static jfieldID jPressures; static jfieldID jPointRadii; - static jfieldID jAlphaField; - static jfieldID jBetaField; - static jfieldID jGammaField; static jfieldID jXField; static jfieldID jYField; static jfieldID jZField; @@ -527,8 +520,8 @@ public: NATIVE_POKE = 0, KEY_EVENT = 1, MOTION_EVENT = 2, - ORIENTATION_EVENT = 3, - ACCELERATION_EVENT = 4, + SENSOR_EVENT = 3, + UNUSED1_EVENT = 4, LOCATION_EVENT = 5, IME_EVENT = 6, DRAW = 7, diff --git a/widget/android/nsAppShell.cpp b/widget/android/nsAppShell.cpp index ed34f9ac6cec..631dc52fdd4d 100644 --- a/widget/android/nsAppShell.cpp +++ b/widget/android/nsAppShell.cpp @@ -96,7 +96,7 @@ nsAppShell::nsAppShell() mQueueCond(mCondLock, "nsAppShell.mQueueCond"), mNumDraws(0), mNumViewports(0), - mPendingOrientationEvents(false) + mPendingSensorEvents(false) { gAppShell = this; } @@ -336,20 +336,41 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait) gDeviceMotionSystem->NeedsCalibration(); break; - case AndroidGeckoEvent::ACCELERATION_EVENT: - gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ACCELERATION, - -curEvent->X(), - curEvent->Y(), - curEvent->Z()); - break; + case AndroidGeckoEvent::SENSOR_EVENT: + mPendingSensorEvents = false; + switch (curEvent->Flags()) { + case hal::SENSOR_ORIENTATION: + gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ORIENTATION, + curEvent->X(), + -curEvent->Y(), + -curEvent->Z()); + break; - case AndroidGeckoEvent::ORIENTATION_EVENT: - gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ORIENTATION, - curEvent->Alpha(), - -curEvent->Beta(), - -curEvent->Gamma()); - mPendingOrientationEvents = false; - break; + case hal::SENSOR_ACCELERATION: + gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ACCELERATION, + -curEvent->X(), + curEvent->Y(), + curEvent->Z()); + break; + + case hal::SENSOR_LINEAR_ACCELERATION: + gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_LINEAR_ACCELERATION, + -curEvent->X(), + curEvent->Y(), + curEvent->Z()); + break; + + case hal::SENSOR_GYROSCOPE: + gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_GYROSCOPE, + -curEvent->X(), + curEvent->Y(), + curEvent->Z()); + break; + + default: + __android_log_print(ANDROID_LOG_ERROR, "Gecko", "### SENSOR_EVENT fired, but type wasn't known %d", curEvent->Flags()); + } + break; case AndroidGeckoEvent::LOCATION_EVENT: { if (!gLocationCallback) @@ -603,10 +624,10 @@ nsAppShell::PostEvent(AndroidGeckoEvent *ae) delete event; } } - } else if (ae->Type() == AndroidGeckoEvent::ORIENTATION_EVENT) { - if (!mPendingOrientationEvents) - mEventQueue.AppendElement(ae); - mPendingOrientationEvents = true; + } else if (ae->Type() == AndroidGeckoEvent::SENSOR_EVENT) { + if (!mPendingSensorEvents) + mEventQueue.AppendElement(ae); + mPendingSensorEvents = true; } else { mEventQueue.AppendElement(ae); } diff --git a/widget/android/nsAppShell.h b/widget/android/nsAppShell.h index ef43ae356e21..f86964dd8f59 100644 --- a/widget/android/nsAppShell.h +++ b/widget/android/nsAppShell.h @@ -110,7 +110,7 @@ protected: mozilla::AndroidGeckoEvent *PeekNextEvent(); nsCOMPtr mBrowserApp; - bool mPendingOrientationEvents; + bool mPendingSensorEvents; }; #endif // nsAppShell_h__ diff --git a/xpcom/system/nsIDeviceMotion.idl b/xpcom/system/nsIDeviceMotion.idl index b83c286be4ca..79313d898388 100644 --- a/xpcom/system/nsIDeviceMotion.idl +++ b/xpcom/system/nsIDeviceMotion.idl @@ -43,6 +43,8 @@ interface nsIDeviceMotionData : nsISupports { const unsigned long TYPE_ACCELERATION = 0; const unsigned long TYPE_ORIENTATION = 1; + const unsigned long TYPE_LINEAR_ACCELERATION = 2; + const unsigned long TYPE_GYROSCOPE = 3; readonly attribute unsigned long type; From f564b11cf60afd65f773e1419718672aea54b828 Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Fri, 9 Mar 2012 10:40:43 -0800 Subject: [PATCH 40/57] Bug 734391 - coalesce the device motion events. r=jdm --- dom/system/Makefile.in | 3 ++ dom/system/android/Makefile.in | 1 + dom/system/cocoa/Makefile.in | 3 ++ dom/system/nsDeviceMotion.cpp | 57 ++++++++++++++++++++-------------- dom/system/nsDeviceMotion.h | 12 ++++++- dom/system/unix/Makefile.in | 3 ++ dom/system/windows/Makefile.in | 3 ++ 7 files changed, 57 insertions(+), 25 deletions(-) diff --git a/dom/system/Makefile.in b/dom/system/Makefile.in index ce9346ba491e..b5b2062fa996 100644 --- a/dom/system/Makefile.in +++ b/dom/system/Makefile.in @@ -87,6 +87,9 @@ EXPORTS = \ nsDeviceMotion.h \ $(NULL) +# We fire the nsDOMDeviceAcceleration +LOCAL_INCLUDES += -I$(topsrcdir)/content/events/src + include $(topsrcdir)/config/config.mk # we don't want the shared lib, but we want to force the creation of a static lib. diff --git a/dom/system/android/Makefile.in b/dom/system/android/Makefile.in index 48cf9473c350..6f79c35fd085 100644 --- a/dom/system/android/Makefile.in +++ b/dom/system/android/Makefile.in @@ -59,6 +59,7 @@ CPPSRCS = \ $(NULL) LOCAL_INCLUDES += -I$(topsrcdir)/dom/src/geolocation \ + -I$(topsrcdir)/content/events/src $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/dom/system/cocoa/Makefile.in b/dom/system/cocoa/Makefile.in index 77041a2b87b6..7853d19a71d5 100644 --- a/dom/system/cocoa/Makefile.in +++ b/dom/system/cocoa/Makefile.in @@ -49,6 +49,9 @@ LIBXUL_LIBRARY = 1 FORCE_STATIC_LIB = 1 EXPORT_LIBRARY = 1 +# We fire the nsDOMDeviceAcceleration +LOCAL_INCLUDES += -I$(topsrcdir)/content/events/src + include $(topsrcdir)/config/config.mk CMMSRCS = \ diff --git a/dom/system/nsDeviceMotion.cpp b/dom/system/nsDeviceMotion.cpp index 240c46422f40..c1048ac9fcc2 100644 --- a/dom/system/nsDeviceMotion.cpp +++ b/dom/system/nsDeviceMotion.cpp @@ -44,11 +44,11 @@ #include "nsIDOMEventTarget.h" #include "nsIServiceManager.h" #include "nsIPrivateDOMEvent.h" -#include "nsIDOMDeviceOrientationEvent.h" -#include "nsIDOMDeviceMotionEvent.h" #include "nsIServiceManager.h" #include "nsIPrefService.h" -#include "nsDOMDeviceMotionEvent.h" + +using mozilla::TimeStamp; +using mozilla::TimeDuration; // also see sDefaultSensorHint in mobile/android/base/GeckoAppShell.java #define DEFAULT_SENSOR_POLL 100 @@ -129,6 +129,7 @@ nsDeviceMotion::nsDeviceMotion() if (NS_SUCCEEDED(rv) && bvalue == false) mEnabled = false; } + mLastDOMMotionEventTime = TimeStamp::Now(); } nsDeviceMotion::~nsDeviceMotion() @@ -361,45 +362,53 @@ nsDeviceMotion::FireDOMMotionEvent(nsIDOMDocument *domdoc, double x, double y, double z) { + // Attempt to coalesce events + bool fireEvent = TimeStamp::Now() > mLastDOMMotionEventTime + TimeDuration::FromMilliseconds(DEFAULT_SENSOR_POLL); + + switch (type) { + case nsIDeviceMotionData::TYPE_LINEAR_ACCELERATION: + mLastAcceleration = new nsDOMDeviceAcceleration(x, y, z); + break; + case nsIDeviceMotionData::TYPE_ACCELERATION: + mLastAccelerationIncluduingGravity = new nsDOMDeviceAcceleration(x, y, z); + break; + case nsIDeviceMotionData::TYPE_GYROSCOPE: + mLastRotationRate = new nsDOMDeviceRotationRate(x, y, z); + break; + } + + if (!fireEvent && (!mLastAcceleration || !mLastAccelerationIncluduingGravity || !mLastRotationRate)) { + return; + } + nsCOMPtr event; - bool defaultActionEnabled = true; domdoc->CreateEvent(NS_LITERAL_STRING("DeviceMotionEvent"), getter_AddRefs(event)); nsCOMPtr me = do_QueryInterface(event); if (!me) { return; -} - - nsRefPtr acceleration; - nsRefPtr accelerationIncluduingGravity; - nsRefPtr rotationRate; - - switch (type) { - case nsIDeviceMotionData::TYPE_LINEAR_ACCELERATION: - acceleration = new nsDOMDeviceAcceleration(x, y, z); - break; - case nsIDeviceMotionData::TYPE_ACCELERATION: - accelerationIncluduingGravity = new nsDOMDeviceAcceleration(x, y, z); - break; - case nsIDeviceMotionData::TYPE_GYROSCOPE: - rotationRate = new nsDOMDeviceRotationRate(x, y, z); - break; } - me->InitDeviceMotionEvent(NS_LITERAL_STRING("devicemotion"), true, false, - acceleration, - accelerationIncluduingGravity, - rotationRate, + mLastAcceleration, + mLastAccelerationIncluduingGravity, + mLastRotationRate, DEFAULT_SENSOR_POLL); nsCOMPtr privateEvent = do_QueryInterface(event); if (privateEvent) privateEvent->SetTrusted(true); + bool defaultActionEnabled = true; target->DispatchEvent(event, &defaultActionEnabled); + + mLastRotationRate = nsnull; + mLastAccelerationIncluduingGravity = nsnull; + mLastAcceleration = nsnull; + mLastDOMMotionEventTime = TimeStamp::Now(); + } diff --git a/dom/system/nsDeviceMotion.h b/dom/system/nsDeviceMotion.h index ba55f9f201b7..1618a6c73b57 100644 --- a/dom/system/nsDeviceMotion.h +++ b/dom/system/nsDeviceMotion.h @@ -43,6 +43,10 @@ #include "nsTArray.h" #include "nsCOMPtr.h" #include "nsITimer.h" +#include "nsIDOMDeviceOrientationEvent.h" +#include "nsIDOMDeviceMotionEvent.h" +#include "nsDOMDeviceMotionEvent.h" +#include "mozilla/TimeStamp.h" #define NS_DEVICE_MOTION_CID \ { 0xecba5203, 0x77da, 0x465a, \ @@ -91,10 +95,16 @@ private: double x, double y, double z); - bool mEnabled; virtual void Startup() = 0; virtual void Shutdown() = 0; + + bool mEnabled; + mozilla::TimeStamp mLastDOMMotionEventTime; + nsRefPtr mLastAcceleration; + nsRefPtr mLastAccelerationIncluduingGravity; + nsRefPtr mLastRotationRate; + }; #endif diff --git a/dom/system/unix/Makefile.in b/dom/system/unix/Makefile.in index fa443281fea6..7414673faeee 100644 --- a/dom/system/unix/Makefile.in +++ b/dom/system/unix/Makefile.in @@ -82,4 +82,7 @@ LOCAL_INCLUDES += $(MOZ_QT_CFLAGS) \ endif endif +# We fire the nsDOMDeviceAcceleration +LOCAL_INCLUDES += -I$(topsrcdir)/content/events/src + include $(topsrcdir)/config/rules.mk diff --git a/dom/system/windows/Makefile.in b/dom/system/windows/Makefile.in index 551a54921bfc..cd8319e75428 100644 --- a/dom/system/windows/Makefile.in +++ b/dom/system/windows/Makefile.in @@ -49,6 +49,9 @@ LIBXUL_LIBRARY = 1 FORCE_STATIC_LIB = 1 EXPORT_LIBRARY = 1 +# We fire the nsDOMDeviceAcceleration +LOCAL_INCLUDES += -I$(topsrcdir)/content/events/src + include $(topsrcdir)/config/config.mk CPPSRCS = \ From feb306dd5d1afcdb9c698b8d20cf6712a261995a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 12 Mar 2012 23:00:18 -0700 Subject: [PATCH 41/57] Bug 713799 - Rearrange the "window-objects" sub-tree in about:memory to make per-tab memory usage more obvious. r=jst. --HG-- extra : rebase_source : f4e9407ad9a5c20ae8523d2ec087b4ee99c43877 --- dom/base/nsWindowMemoryReporter.cpp | 160 +++++++----------- .../tests/test_memoryReporters.xul | 8 +- 2 files changed, 69 insertions(+), 99 deletions(-) diff --git a/dom/base/nsWindowMemoryReporter.cpp b/dom/base/nsWindowMemoryReporter.cpp index b94e7afe6834..9be4e1bc356a 100644 --- a/dom/base/nsWindowMemoryReporter.cpp +++ b/dom/base/nsWindowMemoryReporter.cpp @@ -53,7 +53,7 @@ nsWindowMemoryReporter::Init() NS_RegisterMemoryMultiReporter(new nsWindowMemoryReporter()); } -static bool +static void AppendWindowURI(nsGlobalWindow *aWindow, nsACString& aStr) { nsCOMPtr doc = do_QueryInterface(aWindow->GetExtantDocument()); @@ -71,21 +71,19 @@ AppendWindowURI(nsGlobalWindow *aWindow, nsACString& aStr) } } - if (!uri) { - return false; + if (uri) { + nsCString spec; + uri->GetSpec(spec); + + // A hack: replace forward slashes with '\\' so they aren't + // treated as path separators. Users of the reporters + // (such as about:memory) have to undo this change. + spec.ReplaceChar('/', '\\'); + + aStr += spec; + } else { + aStr += NS_LITERAL_CSTRING("[system]"); } - - nsCString spec; - uri->GetSpec(spec); - - // A hack: replace forward slashes with '\\' so they aren't - // treated as path separators. Users of the reporters - // (such as about:memory) have to undo this change. - spec.ReplaceChar('/', '\\'); - - aStr += spec; - - return true; } NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMStyleMallocSizeOf, "windows") @@ -104,99 +102,68 @@ CollectWindowReports(nsGlobalWindow *aWindow, // cached) yet held alive by either a website or our code. The // latter case may be a memory leak, but not necessarily. // - // For inner windows we show how much memory the window and its - // document etc use, and we report those per URI, where the URI is - // the document URI, if available, or the codebase of the principal - // in the window. In the case where we're unable to find a URI we're - // dealing with a chrome window with no document in it (or - // somesuch), and for that we make the URI be the string "[system]". + // For each window we show how much memory the window and its + // document, etc, use, and we report those per URI, where the URI is + // the document URI, if available, or the codebase of the principal in + // the window. In the case where we're unable to find a URI we're + // dealing with a chrome window with no document in it (or somesuch), + // and for that we make the URI be the string "[system]". // - // For outer windows we simply group them all together and just show - // the combined count and amount of memory used, which is generally - // a constant amount per window (since all the actual data lives in - // the inner window). + // Outer windows are lumped in with inner windows, because the amount + // of memory used by outer windows is small. // - // The path we give to the reporter callback for inner windows are - // as follows: + // The path we give to the reporter callback for "active" and "cached" + // windows (both inner and outer) is as follows: // - // explicit/window-objects//top= (inner=)/inner-window(id=, uri=) + // explicit/window-objects/top(, id=)//window()/... + // + // The path we give for "other" windows is as follows: + // + // explicit/window-objects/top(none)/window()/... // // Where: - // - is active, cached, or other, as described above. + // - is "active" or "cached", as described above. // - is the window id (nsPIDOMWindow::WindowID()) of // the top outer window (i.e. tab, or top level chrome window). - // - is the window id of the top window's inner - // window. - // - is the window id of the inner window in question. - // - is the URI per above description. + // - is the URI of the top outer window. Excepting + // special windows (such as browser.xul or hiddenWindow.html) it's + // what the address bar shows for the tab. + // - is the URI of aWindow. // - // Exposing the window ids is done to get logical grouping in - // about:memory, and also for debuggability since one can get to the - // nsGlobalWindow for a window id by calling the static method - // nsGlobalWindow::GetInnerWindowWithId(id) (or - // GetOuterWindowWithId(id) in a debugger. - // - // For outer windows we simply use: - // - // explicit/window-objects//outer-windows - // - // Which gives us simple counts of how many outer windows (and their - // combined sizes) per category. + // Exposing the top-outer-id ensures that each tab gets its own + // sub-tree, even if multiple tabs are showing the same URI. nsCAutoString windowPath("explicit/window-objects/"); - nsIDocShell *docShell = aWindow->GetDocShell(); - nsGlobalWindow *top = aWindow->GetTop(); - nsWindowSizes windowSizes(DOMStyleMallocSizeOf); - aWindow->SizeOfIncludingThis(&windowSizes); - - if (docShell && aWindow->IsFrozen()) { - windowPath += NS_LITERAL_CSTRING("cached/"); - } else if (docShell) { - windowPath += NS_LITERAL_CSTRING("active/"); + windowPath += NS_LITERAL_CSTRING("top("); + if (top) { + AppendWindowURI(top, windowPath); + windowPath += NS_LITERAL_CSTRING(", id="); + windowPath.AppendInt(top->WindowID()); } else { - windowPath += NS_LITERAL_CSTRING("other/"); + windowPath += NS_LITERAL_CSTRING("none"); + } + windowPath += NS_LITERAL_CSTRING(")/"); + + nsIDocShell *docShell = aWindow->GetDocShell(); + if (docShell) { + MOZ_ASSERT(top, "'cached' or 'active' window lacks a top window"); + windowPath += aWindow->IsFrozen() ? NS_LITERAL_CSTRING("cached/") + : NS_LITERAL_CSTRING("active/"); + } else { + MOZ_ASSERT(!top, "'other' window has a top window"); } - if (aWindow->IsInnerWindow()) { - windowPath += NS_LITERAL_CSTRING("top="); + windowPath += NS_LITERAL_CSTRING("window("); + AppendWindowURI(aWindow, windowPath); + windowPath += NS_LITERAL_CSTRING(")"); - if (top) { - windowPath.AppendInt(top->WindowID()); - - nsGlobalWindow *topInner = top->GetCurrentInnerWindowInternal(); - if (topInner) { - windowPath += NS_LITERAL_CSTRING(" (inner="); - windowPath.AppendInt(topInner->WindowID()); - windowPath += NS_LITERAL_CSTRING(")"); - } - } else { - windowPath += NS_LITERAL_CSTRING("none"); - } - - windowPath += NS_LITERAL_CSTRING("/inner-window(id="); - windowPath.AppendInt(aWindow->WindowID()); - windowPath += NS_LITERAL_CSTRING(", uri="); - - if (!AppendWindowURI(aWindow, windowPath)) { - windowPath += NS_LITERAL_CSTRING("[system]"); - } - - windowPath += NS_LITERAL_CSTRING(")"); - } else { - // Combine all outer windows per section (active/cached/other) as - // they basically never contain anything of interest, and are - // always pretty much the same size. - - windowPath += NS_LITERAL_CSTRING("outer-windows"); - } - -#define REPORT(_path1, _path2, _amount, _desc) \ +#define REPORT(_pathTail, _amount, _desc) \ do { \ if (_amount > 0) { \ - nsCAutoString path(_path1); \ - path += _path2; \ + nsCAutoString path(windowPath); \ + path += _pathTail; \ nsresult rv; \ rv = aCb->Callback(EmptyCString(), path, nsIMemoryReporter::KIND_HEAP,\ nsIMemoryReporter::UNITS_BYTES, _amount, \ @@ -205,24 +172,27 @@ CollectWindowReports(nsGlobalWindow *aWindow, } \ } while (0) - REPORT(windowPath, "/dom", windowSizes.mDOM, + nsWindowSizes windowSizes(DOMStyleMallocSizeOf); + aWindow->SizeOfIncludingThis(&windowSizes); + + REPORT("/dom", windowSizes.mDOM, "Memory used by a window and the DOM within it."); aWindowTotalSizes->mDOM += windowSizes.mDOM; - REPORT(windowPath, "/style-sheets", windowSizes.mStyleSheets, + REPORT("/style-sheets", windowSizes.mStyleSheets, "Memory used by style sheets within a window."); aWindowTotalSizes->mStyleSheets += windowSizes.mStyleSheets; - REPORT(windowPath, "/layout/arenas", windowSizes.mLayoutArenas, + REPORT("/layout/arenas", windowSizes.mLayoutArenas, "Memory used by layout PresShell, PresContext, and other related " "areas within a window."); aWindowTotalSizes->mLayoutArenas += windowSizes.mLayoutArenas; - REPORT(windowPath, "/layout/style-sets", windowSizes.mLayoutStyleSets, + REPORT("/layout/style-sets", windowSizes.mLayoutStyleSets, "Memory used by style sets within a window."); aWindowTotalSizes->mLayoutStyleSets += windowSizes.mLayoutStyleSets; - REPORT(windowPath, "/layout/text-runs", windowSizes.mLayoutTextRuns, + REPORT("/layout/text-runs", windowSizes.mLayoutTextRuns, "Memory used for text-runs (glyph layout) in the PresShell's frame " "tree, within a window."); aWindowTotalSizes->mLayoutTextRuns += windowSizes.mLayoutTextRuns; diff --git a/toolkit/components/aboutmemory/tests/test_memoryReporters.xul b/toolkit/components/aboutmemory/tests/test_memoryReporters.xul index 27774929ce35..0b6ed554b50d 100644 --- a/toolkit/components/aboutmemory/tests/test_memoryReporters.xul +++ b/toolkit/components/aboutmemory/tests/test_memoryReporters.xul @@ -44,7 +44,7 @@ let areJsCompartmentsPresent = false; let isSandboxLocationShown = false; - let areInnerWindowsPresent = false; + let areWindowObjectsPresent = false; let isPlacesPresent = false; let isImagesPresent = false; let isXptiWorkingSetPresent = false; @@ -72,8 +72,8 @@ // Check the presence of some other notable reporters. } else if (aPath.search(/^explicit\/js\/compartment\(/) >= 0) { areJsCompartmentsPresent = true; - } else if (aPath.search(/^explicit\/window-objects\/.*inner-window\(/) >= 0) { - areInnerWindowsPresent = true; + } else if (aPath.search(/^explicit\/window-objects\/top\(/) >= 0) { + areWindowObjectsPresent = true; } else if (aPath.search(/^explicit\/storage\/sqlite\/places.sqlite/) >= 0) { isPlacesPresent = true; } else if (aPath.search(/^explicit\/images/) >= 0) { @@ -131,7 +131,7 @@ ok(areJsCompartmentsPresent, "js compartments are present"); ok(isSandboxLocationShown, "sandbox locations are present"); - ok(areInnerWindowsPresent, "inner-windows are present"); + ok(areWindowObjectsPresent, "window objects are present"); ok(isPlacesPresent, "places is present"); ok(isImagesPresent, "images is present"); ok(isXptiWorkingSetPresent, "xpti-working-set is present"); From c76f86d8905998b9de63015f9c29b3f6583d0832 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Tue, 13 Mar 2012 17:21:06 -0700 Subject: [PATCH 42/57] Bug 735533 - Don't copyright empty files; r=dmandelin --- js/src/tests/ecma_2/browser.js | 37 --------------------- js/src/tests/ecma_3/Date/browser.js | 37 --------------------- js/src/tests/ecma_3/browser.js | 36 -------------------- js/src/tests/ecma_3/shell.js | 39 ---------------------- js/src/tests/ecma_3_1/browser.js | 36 -------------------- js/src/tests/ecma_3_1/shell.js | 39 ---------------------- js/src/tests/ecma_5/Array/browser.js | 1 - js/src/tests/ecma_5/Expressions/shell.js | 7 ---- js/src/tests/ecma_5/Function/browser.js | 1 - js/src/tests/ecma_5/Global/browser.js | 1 - js/src/tests/ecma_5/JSON/browser.js | 1 - js/src/tests/ecma_5/Object/browser.js | 1 - js/src/tests/ecma_5/RegExp/browser.js | 1 - js/src/tests/ecma_5/String/browser.js | 1 - js/src/tests/ecma_5/Types/browser.js | 1 - js/src/tests/ecma_5/browser.js | 36 -------------------- js/src/tests/ecma_5/eval/browser.js | 1 - js/src/tests/ecma_5/extensions/browser.js | 1 - js/src/tests/ecma_5/misc/browser.js | 1 - js/src/tests/js1_1/browser.js | 37 --------------------- js/src/tests/js1_1/shell.js | 38 --------------------- js/src/tests/js1_2/browser.js | 37 --------------------- js/src/tests/js1_2/shell.js | 39 ---------------------- js/src/tests/js1_2/version120/browser.js | 37 --------------------- js/src/tests/js1_3/browser.js | 36 -------------------- js/src/tests/js1_3/shell.js | 39 ---------------------- js/src/tests/js1_4/browser.js | 37 --------------------- js/src/tests/js1_4/shell.js | 38 --------------------- js/src/tests/js1_5/browser.js | 37 --------------------- js/src/tests/js1_5/decompilation/shell.js | 1 - js/src/tests/js1_5/shell.js | 40 ----------------------- js/src/tests/js1_6/browser.js | 36 -------------------- js/src/tests/js1_6/shell.js | 39 ---------------------- js/src/tests/js1_7/browser.js | 36 -------------------- js/src/tests/js1_8/browser.js | 36 -------------------- js/src/tests/js1_8_1/browser.js | 36 -------------------- 36 files changed, 877 deletions(-) diff --git a/js/src/tests/ecma_2/browser.js b/js/src/tests/ecma_2/browser.js index 4cde9b062900..e69de29bb2d1 100644 --- a/js/src/tests/ecma_2/browser.js +++ b/js/src/tests/ecma_2/browser.js @@ -1,37 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ - diff --git a/js/src/tests/ecma_3/Date/browser.js b/js/src/tests/ecma_3/Date/browser.js index 4cde9b062900..e69de29bb2d1 100644 --- a/js/src/tests/ecma_3/Date/browser.js +++ b/js/src/tests/ecma_3/Date/browser.js @@ -1,37 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ - diff --git a/js/src/tests/ecma_3/browser.js b/js/src/tests/ecma_3/browser.js index 2339522cb644..e69de29bb2d1 100644 --- a/js/src/tests/ecma_3/browser.js +++ b/js/src/tests/ecma_3/browser.js @@ -1,36 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ diff --git a/js/src/tests/ecma_3/shell.js b/js/src/tests/ecma_3/shell.js index 789059f6b15a..e69de29bb2d1 100644 --- a/js/src/tests/ecma_3/shell.js +++ b/js/src/tests/ecma_3/shell.js @@ -1,39 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ - diff --git a/js/src/tests/ecma_3_1/browser.js b/js/src/tests/ecma_3_1/browser.js index 2339522cb644..e69de29bb2d1 100644 --- a/js/src/tests/ecma_3_1/browser.js +++ b/js/src/tests/ecma_3_1/browser.js @@ -1,36 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ diff --git a/js/src/tests/ecma_3_1/shell.js b/js/src/tests/ecma_3_1/shell.js index 789059f6b15a..e69de29bb2d1 100644 --- a/js/src/tests/ecma_3_1/shell.js +++ b/js/src/tests/ecma_3_1/shell.js @@ -1,39 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ - diff --git a/js/src/tests/ecma_5/Array/browser.js b/js/src/tests/ecma_5/Array/browser.js index 8b137891791f..e69de29bb2d1 100644 --- a/js/src/tests/ecma_5/Array/browser.js +++ b/js/src/tests/ecma_5/Array/browser.js @@ -1 +0,0 @@ - diff --git a/js/src/tests/ecma_5/Expressions/shell.js b/js/src/tests/ecma_5/Expressions/shell.js index 9c3e4eaf81fa..e69de29bb2d1 100644 --- a/js/src/tests/ecma_5/Expressions/shell.js +++ b/js/src/tests/ecma_5/Expressions/shell.js @@ -1,7 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ - -/* - * Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/licenses/publicdomain/ - */ - diff --git a/js/src/tests/ecma_5/Function/browser.js b/js/src/tests/ecma_5/Function/browser.js index 8b137891791f..e69de29bb2d1 100644 --- a/js/src/tests/ecma_5/Function/browser.js +++ b/js/src/tests/ecma_5/Function/browser.js @@ -1 +0,0 @@ - diff --git a/js/src/tests/ecma_5/Global/browser.js b/js/src/tests/ecma_5/Global/browser.js index 8b137891791f..e69de29bb2d1 100644 --- a/js/src/tests/ecma_5/Global/browser.js +++ b/js/src/tests/ecma_5/Global/browser.js @@ -1 +0,0 @@ - diff --git a/js/src/tests/ecma_5/JSON/browser.js b/js/src/tests/ecma_5/JSON/browser.js index 8b137891791f..e69de29bb2d1 100644 --- a/js/src/tests/ecma_5/JSON/browser.js +++ b/js/src/tests/ecma_5/JSON/browser.js @@ -1 +0,0 @@ - diff --git a/js/src/tests/ecma_5/Object/browser.js b/js/src/tests/ecma_5/Object/browser.js index 8b137891791f..e69de29bb2d1 100644 --- a/js/src/tests/ecma_5/Object/browser.js +++ b/js/src/tests/ecma_5/Object/browser.js @@ -1 +0,0 @@ - diff --git a/js/src/tests/ecma_5/RegExp/browser.js b/js/src/tests/ecma_5/RegExp/browser.js index 8b137891791f..e69de29bb2d1 100644 --- a/js/src/tests/ecma_5/RegExp/browser.js +++ b/js/src/tests/ecma_5/RegExp/browser.js @@ -1 +0,0 @@ - diff --git a/js/src/tests/ecma_5/String/browser.js b/js/src/tests/ecma_5/String/browser.js index 8b137891791f..e69de29bb2d1 100644 --- a/js/src/tests/ecma_5/String/browser.js +++ b/js/src/tests/ecma_5/String/browser.js @@ -1 +0,0 @@ - diff --git a/js/src/tests/ecma_5/Types/browser.js b/js/src/tests/ecma_5/Types/browser.js index 8b137891791f..e69de29bb2d1 100644 --- a/js/src/tests/ecma_5/Types/browser.js +++ b/js/src/tests/ecma_5/Types/browser.js @@ -1 +0,0 @@ - diff --git a/js/src/tests/ecma_5/browser.js b/js/src/tests/ecma_5/browser.js index 2339522cb644..e69de29bb2d1 100644 --- a/js/src/tests/ecma_5/browser.js +++ b/js/src/tests/ecma_5/browser.js @@ -1,36 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ diff --git a/js/src/tests/ecma_5/eval/browser.js b/js/src/tests/ecma_5/eval/browser.js index 8b137891791f..e69de29bb2d1 100644 --- a/js/src/tests/ecma_5/eval/browser.js +++ b/js/src/tests/ecma_5/eval/browser.js @@ -1 +0,0 @@ - diff --git a/js/src/tests/ecma_5/extensions/browser.js b/js/src/tests/ecma_5/extensions/browser.js index 8b137891791f..e69de29bb2d1 100644 --- a/js/src/tests/ecma_5/extensions/browser.js +++ b/js/src/tests/ecma_5/extensions/browser.js @@ -1 +0,0 @@ - diff --git a/js/src/tests/ecma_5/misc/browser.js b/js/src/tests/ecma_5/misc/browser.js index 8b137891791f..e69de29bb2d1 100644 --- a/js/src/tests/ecma_5/misc/browser.js +++ b/js/src/tests/ecma_5/misc/browser.js @@ -1 +0,0 @@ - diff --git a/js/src/tests/js1_1/browser.js b/js/src/tests/js1_1/browser.js index 4cde9b062900..e69de29bb2d1 100644 --- a/js/src/tests/js1_1/browser.js +++ b/js/src/tests/js1_1/browser.js @@ -1,37 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ - diff --git a/js/src/tests/js1_1/shell.js b/js/src/tests/js1_1/shell.js index 086eec9fd35e..e69de29bb2d1 100644 --- a/js/src/tests/js1_1/shell.js +++ b/js/src/tests/js1_1/shell.js @@ -1,38 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ - - diff --git a/js/src/tests/js1_2/browser.js b/js/src/tests/js1_2/browser.js index 6774b3998877..e69de29bb2d1 100644 --- a/js/src/tests/js1_2/browser.js +++ b/js/src/tests/js1_2/browser.js @@ -1,37 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ diff --git a/js/src/tests/js1_2/shell.js b/js/src/tests/js1_2/shell.js index 008c7f189e18..e69de29bb2d1 100644 --- a/js/src/tests/js1_2/shell.js +++ b/js/src/tests/js1_2/shell.js @@ -1,39 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ - - diff --git a/js/src/tests/js1_2/version120/browser.js b/js/src/tests/js1_2/version120/browser.js index 4cde9b062900..e69de29bb2d1 100644 --- a/js/src/tests/js1_2/version120/browser.js +++ b/js/src/tests/js1_2/version120/browser.js @@ -1,37 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ - diff --git a/js/src/tests/js1_3/browser.js b/js/src/tests/js1_3/browser.js index 2339522cb644..e69de29bb2d1 100644 --- a/js/src/tests/js1_3/browser.js +++ b/js/src/tests/js1_3/browser.js @@ -1,36 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ diff --git a/js/src/tests/js1_3/shell.js b/js/src/tests/js1_3/shell.js index 008c7f189e18..e69de29bb2d1 100644 --- a/js/src/tests/js1_3/shell.js +++ b/js/src/tests/js1_3/shell.js @@ -1,39 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ - - diff --git a/js/src/tests/js1_4/browser.js b/js/src/tests/js1_4/browser.js index 4cde9b062900..e69de29bb2d1 100644 --- a/js/src/tests/js1_4/browser.js +++ b/js/src/tests/js1_4/browser.js @@ -1,37 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ - diff --git a/js/src/tests/js1_4/shell.js b/js/src/tests/js1_4/shell.js index 086eec9fd35e..e69de29bb2d1 100644 --- a/js/src/tests/js1_4/shell.js +++ b/js/src/tests/js1_4/shell.js @@ -1,38 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ - - diff --git a/js/src/tests/js1_5/browser.js b/js/src/tests/js1_5/browser.js index 4cde9b062900..e69de29bb2d1 100644 --- a/js/src/tests/js1_5/browser.js +++ b/js/src/tests/js1_5/browser.js @@ -1,37 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ - diff --git a/js/src/tests/js1_5/decompilation/shell.js b/js/src/tests/js1_5/decompilation/shell.js index 8d1c8b69c3fc..e69de29bb2d1 100644 --- a/js/src/tests/js1_5/decompilation/shell.js +++ b/js/src/tests/js1_5/decompilation/shell.js @@ -1 +0,0 @@ - diff --git a/js/src/tests/js1_5/shell.js b/js/src/tests/js1_5/shell.js index 56a369e27f77..e69de29bb2d1 100644 --- a/js/src/tests/js1_5/shell.js +++ b/js/src/tests/js1_5/shell.js @@ -1,40 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ - - diff --git a/js/src/tests/js1_6/browser.js b/js/src/tests/js1_6/browser.js index 2339522cb644..e69de29bb2d1 100644 --- a/js/src/tests/js1_6/browser.js +++ b/js/src/tests/js1_6/browser.js @@ -1,36 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ diff --git a/js/src/tests/js1_6/shell.js b/js/src/tests/js1_6/shell.js index 789059f6b15a..e69de29bb2d1 100644 --- a/js/src/tests/js1_6/shell.js +++ b/js/src/tests/js1_6/shell.js @@ -1,39 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ - diff --git a/js/src/tests/js1_7/browser.js b/js/src/tests/js1_7/browser.js index 2339522cb644..e69de29bb2d1 100644 --- a/js/src/tests/js1_7/browser.js +++ b/js/src/tests/js1_7/browser.js @@ -1,36 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ diff --git a/js/src/tests/js1_8/browser.js b/js/src/tests/js1_8/browser.js index 2339522cb644..e69de29bb2d1 100644 --- a/js/src/tests/js1_8/browser.js +++ b/js/src/tests/js1_8/browser.js @@ -1,36 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ diff --git a/js/src/tests/js1_8_1/browser.js b/js/src/tests/js1_8_1/browser.js index 2339522cb644..e69de29bb2d1 100644 --- a/js/src/tests/js1_8_1/browser.js +++ b/js/src/tests/js1_8_1/browser.js @@ -1,36 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ From 0d8a907889b10a9ab48c05b7b539610fd7e788dc Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Tue, 13 Mar 2012 18:23:26 -0700 Subject: [PATCH 43/57] Bug 735490 - Yet another place to kill makefiles. a=bustage --- mobile/android/chrome/Makefile.in | 3 --- 1 file changed, 3 deletions(-) diff --git a/mobile/android/chrome/Makefile.in b/mobile/android/chrome/Makefile.in index 599b5b42668d..4d31adb28a32 100644 --- a/mobile/android/chrome/Makefile.in +++ b/mobile/android/chrome/Makefile.in @@ -47,7 +47,4 @@ DEFINES += -DAB_CD=$(MOZ_UI_LOCALE) \ -DMOZ_APP_VERSION=$(MOZ_APP_VERSION) \ $(NULL) - -TEST_DIRS += tests - include $(topsrcdir)/config/rules.mk From 2f19124e5e2ed41ec8956fb9ae30acb575e56415 Mon Sep 17 00:00:00 2001 From: Johnny Stenback Date: Thu, 5 Jan 2012 18:24:10 +0200 Subject: [PATCH 44/57] backout Bug 679971 - remove Navigator.taintEnabled() --- dom/base/Navigator.cpp | 7 +++++++ dom/interfaces/base/nsIDOMNavigator.idl | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index 4311a5196442..64664fbad750 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -567,6 +567,13 @@ Navigator::JavaEnabled(bool* aReturn) return NS_OK; } +NS_IMETHODIMP +Navigator::TaintEnabled(bool *aReturn) +{ + *aReturn = false; + return NS_OK; +} + void Navigator::RefreshMIMEArray() { diff --git a/dom/interfaces/base/nsIDOMNavigator.idl b/dom/interfaces/base/nsIDOMNavigator.idl index 90bddee82d9b..2df1d2294d2a 100644 --- a/dom/interfaces/base/nsIDOMNavigator.idl +++ b/dom/interfaces/base/nsIDOMNavigator.idl @@ -39,7 +39,7 @@ #include "domstubs.idl" -[scriptable, uuid(e610c037-db58-4cd7-8ed3-0d7f1422b4d3)] +[scriptable, uuid(e0737ed5-89c5-4fe3-891e-a75bf3a1bb55)] interface nsIDOMNavigator : nsISupports { readonly attribute DOMString appCodeName; @@ -62,6 +62,7 @@ interface nsIDOMNavigator : nsISupports readonly attribute nsIDOMMozPowerManager mozPower; boolean javaEnabled(); + boolean taintEnabled(); /** * Pulse the device's vibrator, if it has one. If the device does not have a From 49f13cc9a727102ab2c017b7ff67f2818063bb9e Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Tue, 13 Mar 2012 07:34:39 -0700 Subject: [PATCH 45/57] Bug 735152: Disable the offending tests. r=me --- content/base/test/test_XHR_timeout.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/content/base/test/test_XHR_timeout.js b/content/base/test/test_XHR_timeout.js index 408d33874d3a..bbe95650b7c2 100644 --- a/content/base/test/test_XHR_timeout.js +++ b/content/base/test/test_XHR_timeout.js @@ -276,12 +276,13 @@ var TestRequests = [ // Aborted requests. new AbortedRequest(false), new AbortedRequest(true, -1), - new AbortedRequest(true, 0), - new AbortedRequest(true, 1000), new AbortedRequest(true, 5000), ]; var MainThreadTestRequests = [ + new AbortedRequest(true, 0), + new AbortedRequest(true, 1000), + // Synchronous requests. SyncRequestSettingTimeoutAfterOpen, SyncRequestSettingTimeoutBeforeOpen From e8c71019e8562ca110e161f214813a723756533a Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Mon, 12 Mar 2012 18:36:27 -0700 Subject: [PATCH 46/57] Bug 734946 - Disable incremental GC for Firefox 13 (r=dmandelin) --- modules/libpref/src/init/all.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 10d8d184420d..cce7203493ee 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -663,7 +663,7 @@ pref("javascript.options.typeinference", true); pref("javascript.options.mem.high_water_mark", 128); pref("javascript.options.mem.max", -1); pref("javascript.options.mem.gc_per_compartment", true); -pref("javascript.options.mem.gc_incremental", true); +pref("javascript.options.mem.gc_incremental", false); pref("javascript.options.mem.gc_incremental_slice_ms", 10); pref("javascript.options.mem.log", false); pref("javascript.options.gc_on_memory_pressure", true); From 5df3bd922ad9c10cc894f5a8cf74b7b5f48fa662 Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Tue, 21 Feb 2012 17:04:53 -0800 Subject: [PATCH 47/57] Bug 728686 - JS_NewPropertyIterator shouldn't disable IGC (r=igor) --- js/src/jsapi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 8b9f3a048e7e..1d9243f425ae 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4284,7 +4284,7 @@ prop_iter_trace(JSTracer *trc, JSObject *obj) static Class prop_iter_class = { "PropertyIterator", - JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1), + JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(1), JS_PropertyStub, /* addProperty */ JS_PropertyStub, /* delProperty */ JS_PropertyStub, /* getProperty */ From 6725af19c1f4c03cfc223c3162f61a12c7a46f6f Mon Sep 17 00:00:00 2001 From: Serge Gautherie Date: Tue, 13 Mar 2012 17:57:14 +0100 Subject: [PATCH 48/57] Bug 735139. (Av1a) Improve browser_pageInfo.js a little. r=dao. --- browser/base/content/test/browser_pageInfo.js | 30 +++++++------------ 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/browser/base/content/test/browser_pageInfo.js b/browser/base/content/test/browser_pageInfo.js index 8dca2c10f110..c0159380cdcb 100644 --- a/browser/base/content/test/browser_pageInfo.js +++ b/browser/base/content/test/browser_pageInfo.js @@ -2,41 +2,33 @@ function test() { waitForExplicitFinish(); var pageInfo; + gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function () { - gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true); - pageInfo = BrowserPageInfo(); + gBrowser.selectedBrowser.addEventListener("load", function loadListener() { + gBrowser.selectedBrowser.removeEventListener("load", loadListener, true); + Services.obs.addObserver(observer, "page-info-dialog-loaded", false); + pageInfo = BrowserPageInfo(); }, true); content.location = "https://example.com/browser/browser/base/content/test/feed_tab.html"; function observer(win, topic, data) { - if (topic != "page-info-dialog-loaded") - return; - - Services.obs.removeObserver(observer, topic); + Services.obs.removeObserver(observer, "page-info-dialog-loaded"); handlePageInfo(); } - function $(aId) { return pageInfo.document.getElementById(aId) }; - function handlePageInfo() { - var feedTab = $("feedTab"); - var feedListbox = $("feedListbox"); - - ok(feedListbox, "Feed list is null (feeds tab is broken)"); + ok(pageInfo.document.getElementById("feedTab"), "Feed tab"); + let feedListbox = pageInfo.document.getElementById("feedListbox"); + ok(feedListbox, "Feed list"); var feedRowsNum = feedListbox.getRowCount(); - - ok(feedRowsNum == 3, "Number of feeds listed: " + - feedRowsNum + ", should be 3"); - + is(feedRowsNum, 3, "Number of feeds listed"); for (var i = 0; i < feedRowsNum; i++) { let feedItem = feedListbox.getItemAtIndex(i); - ok(feedItem.getAttribute("name") == (i+1), - "Name given: " + feedItem.getAttribute("name") + ", should be " + (i+1)); + is(feedItem.getAttribute("name"), i + 1, "Feed name"); } pageInfo.close(); From 2289b5607f41d4427ed37a970c8cf63bb4ee79a9 Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Tue, 13 Mar 2012 10:22:14 -0700 Subject: [PATCH 49/57] No bug: Fix ply being dumb. r=ted --- xpcom/idl-parser/header.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/xpcom/idl-parser/header.py b/xpcom/idl-parser/header.py index 948c824d99be..b8d69408c70c 100644 --- a/xpcom/idl-parser/header.py +++ b/xpcom/idl-parser/header.py @@ -40,7 +40,7 @@ """Print a C++ header file for the IDL files specified on the command line""" -import sys, os.path, re, xpidl, itertools +import sys, os.path, re, xpidl, itertools, glob printdoccomments = False @@ -499,13 +499,21 @@ if __name__ == '__main__': os.mkdir(options.cachedir) sys.path.append(options.cachedir) - # Instantiate the parser. - p = xpidl.IDLParser(outputdir=options.cachedir) - # The only thing special about a regen is that there are no input files. if options.regen: if options.cachedir is None: print >>sys.stderr, "--regen useless without --cachedir" + # Delete the lex/yacc files. Ply is too stupid to regenerate them + # properly + deadfiles = os.path.join(options.cachedir, "*.py*") + for filename in glob.glob(deadfiles): + print filename + os.remove(filename) + + # Instantiate the parser. + p = xpidl.IDLParser(outputdir=options.cachedir) + + if options.regen: sys.exit(0) if options.depfile is not None and options.outfile is None: From 0c22f68bf63b8780f23a030aad6bd385669637a0 Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Tue, 13 Mar 2012 10:31:53 -0700 Subject: [PATCH 50/57] No bug: Fix ply being stupid, take 2. r=me --- js/xpconnect/src/Makefile.in | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/js/xpconnect/src/Makefile.in b/js/xpconnect/src/Makefile.in index d59225b717d5..7dc781291a32 100644 --- a/js/xpconnect/src/Makefile.in +++ b/js/xpconnect/src/Makefile.in @@ -172,7 +172,7 @@ dombindings_gen.h: $(srcdir)/dombindings.conf \ -I$(topsrcdir)/xpcom/idl-parser \ $(srcdir)/dombindingsgen.py \ --idlpath=$(DEPTH)/dist/idl \ - --cachedir=$(DEPTH)/xpcom/idl-parser/cache \ + --cachedir=$(DEPTH)/xpcom/idl-parser \ --header-output dombindings_gen.h \ $(srcdir)/dombindings.conf @@ -189,7 +189,7 @@ dombindings_gen.cpp: $(srcdir)/dombindings.conf \ -I$(topsrcdir)/xpcom/idl-parser \ $(srcdir)/dombindingsgen.py \ --idlpath=$(DEPTH)/dist/idl \ - --cachedir=$(DEPTH)/xpcom/idl-parser/cache \ + --cachedir=$(DEPTH)/xpcom/idl-parser \ --stub-output dombindings_gen.cpp \ --makedepend-output $(MDDEPDIR)/dombindingsgen.pp \ $(srcdir)/dombindings.conf @@ -208,7 +208,7 @@ DictionaryHelpers.h: $(srcdir)/dictionary_helper_gen.conf \ -I$(topsrcdir)/xpcom/idl-parser \ $(srcdir)/dictionary_helper_gen.py \ -I $(DEPTH)/dist/idl \ - --cachedir=$(DEPTH)/xpcom/idl-parser/cache \ + --cachedir=$(DEPTH)/xpcom/idl-parser \ --header-output DictionaryHelpers.h \ $(srcdir)/dictionary_helper_gen.conf @@ -223,7 +223,7 @@ DictionaryHelpers.cpp: $(srcdir)/dictionary_helper_gen.conf \ -I$(topsrcdir)/xpcom/idl-parser \ $(srcdir)/dictionary_helper_gen.py \ -I $(DEPTH)/dist/idl \ - --cachedir=$(DEPTH)/xpcom/idl-parser/cache \ + --cachedir=$(DEPTH)/xpcom/idl-parser \ --header-output DictionaryHelpers.h \ --stub-output DictionaryHelpers.cpp \ --makedepend-output $(MDDEPDIR)/dictionary_helper_gen.pp \ @@ -248,9 +248,6 @@ GARBAGE += \ $(MDDEPDIR)/dombindingsgen.pp \ $(MDDEPDIR)/dictionary_helper_gen.pp \ $(wildcard $(topsrcdir)/other-licenses/ply/ply/*.pyc) \ - $(wildcard $(topsrcdir)/xpcom/idl-parser/*.pyc) \ $(NULL) -GARBAGE_DIRS += $(DEPTH)/xpcom/idl-parser/cache - DEFINES += -D_IMPL_NS_LAYOUT From d05a6ebaf772af151d65f632138087ceacc65210 Mon Sep 17 00:00:00 2001 From: cltbld Date: Tue, 13 Mar 2012 13:33:44 -0700 Subject: [PATCH 51/57] Added tag FIREFOX_AURORA_13_BASE for changeset b6627f28b7ec --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index b357128e0106..9211295d8858 100644 --- a/.hgtags +++ b/.hgtags @@ -78,3 +78,4 @@ bbc7014db2de49e2301680d2a86be8a53108a88a AURORA_BASE_20120131 0000000000000000000000000000000000000000 AURORA_BASE_20120131 0000000000000000000000000000000000000000 AURORA_BASE_20120131 bbc7014db2de49e2301680d2a86be8a53108a88a AURORA_BASE_20120131 +b6627f28b7ec17e1b46a594df0f780d3a40847e4 FIREFOX_AURORA_13_BASE From 221bdcc6e639340576bf2992298432c3d0579fc0 Mon Sep 17 00:00:00 2001 From: Lukas Blakk Date: Tue, 13 Mar 2012 13:38:38 -0700 Subject: [PATCH 52/57] Merging in version bump NO BUG --- browser/config/version.txt | 2 +- config/milestone.txt | 2 +- js/src/config/milestone.txt | 2 +- mobile/android/confvars.sh | 2 +- mobile/xul/confvars.sh | 2 +- xpcom/components/Module.h | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/browser/config/version.txt b/browser/config/version.txt index d4157f8df484..644225a35f36 100644 --- a/browser/config/version.txt +++ b/browser/config/version.txt @@ -1 +1 @@ -13.0a1 +14.0a1 diff --git a/config/milestone.txt b/config/milestone.txt index f780391e9db5..17f7a63fad30 100644 --- a/config/milestone.txt +++ b/config/milestone.txt @@ -10,4 +10,4 @@ # hardcoded milestones in the tree from these two files. #-------------------------------------------------------- -13.0a1 +14.0a1 diff --git a/js/src/config/milestone.txt b/js/src/config/milestone.txt index f780391e9db5..17f7a63fad30 100644 --- a/js/src/config/milestone.txt +++ b/js/src/config/milestone.txt @@ -10,4 +10,4 @@ # hardcoded milestones in the tree from these two files. #-------------------------------------------------------- -13.0a1 +14.0a1 diff --git a/mobile/android/confvars.sh b/mobile/android/confvars.sh index 1de42e51365e..0709cf005d98 100644 --- a/mobile/android/confvars.sh +++ b/mobile/android/confvars.sh @@ -38,7 +38,7 @@ MOZ_APP_BASENAME=Fennec MOZ_APP_VENDOR=Mozilla -MOZ_APP_VERSION=13.0a1 +MOZ_APP_VERSION=14.0a1 MOZ_APP_UA_NAME=Firefox MOZ_BRANDING_DIRECTORY=mobile/android/branding/unofficial diff --git a/mobile/xul/confvars.sh b/mobile/xul/confvars.sh index 53f1f3b3da29..84034c69d0ab 100644 --- a/mobile/xul/confvars.sh +++ b/mobile/xul/confvars.sh @@ -38,7 +38,7 @@ MOZ_APP_BASENAME=Fennec MOZ_APP_VENDOR=Mozilla -MOZ_APP_VERSION=13.0a1 +MOZ_APP_VERSION=14.0a1 MOZ_BRANDING_DIRECTORY=mobile/xul/branding/unofficial MOZ_OFFICIAL_BRANDING_DIRECTORY=mobile/xul/branding/official diff --git a/xpcom/components/Module.h b/xpcom/components/Module.h index 4501daa756f4..091294f2039c 100644 --- a/xpcom/components/Module.h +++ b/xpcom/components/Module.h @@ -53,7 +53,7 @@ namespace mozilla { */ struct Module { - static const unsigned int kVersion = 13; + static const unsigned int kVersion = 14; struct CIDEntry; From 5716d96e06710f6f3aea7f739061488912c0fbab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabrice=20Desr=C3=A9?= Date: Tue, 13 Mar 2012 15:11:16 -0700 Subject: [PATCH 53/57] Bug 735305 - Update WebTelephony impl to use the new DOMEventTargetHelper API [r=smaug,bent] --- dom/telephony/Telephony.cpp | 41 +++++++++++++++++++++------------ dom/telephony/Telephony.h | 12 ---------- dom/telephony/TelephonyCall.cpp | 4 ++-- 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/dom/telephony/Telephony.cpp b/dom/telephony/Telephony.cpp index 6bec4e5237cd..fd7d162fc4c8 100644 --- a/dom/telephony/Telephony.cpp +++ b/dom/telephony/Telephony.cpp @@ -164,8 +164,8 @@ Telephony::Create(nsPIDOMWindow* aOwner, nsIRadioInterfaceLayer* aRIL) nsRefPtr telephony = new Telephony(); - telephony->mOwner = aOwner; - telephony->mScriptContext.swap(scriptContext); + telephony->BindToOwner(aOwner); + telephony->mRIL = aRIL; telephony->mRILTelephonyCallback = new RILTelephonyCallback(telephony); @@ -328,12 +328,16 @@ Telephony::GetActive(jsval* aActive) return NS_OK; } - nsresult rv = - nsContentUtils::WrapNative(mScriptContext->GetNativeContext(), - mScriptContext->GetNativeGlobal(), - mActiveCall->ToISupports(), aActive); + nsresult rv; + nsIScriptContext* sc = GetContextForEventHandlers(&rv); NS_ENSURE_SUCCESS(rv, rv); - + if (sc) { + rv = + nsContentUtils::WrapNative(sc->GetNativeContext(), + sc->GetNativeGlobal(), + mActiveCall->ToISupports(), aActive); + NS_ENSURE_SUCCESS(rv, rv); + } return NS_OK; } @@ -342,17 +346,24 @@ Telephony::GetCalls(jsval* aCalls) { JSObject* calls = mCallsArray; if (!calls) { - nsresult rv = - nsTArrayToJSArray(mScriptContext->GetNativeContext(), - mScriptContext->GetNativeGlobal(), mCalls, &calls); + nsresult rv; + nsIScriptContext* sc = GetContextForEventHandlers(&rv); NS_ENSURE_SUCCESS(rv, rv); + if (sc) { + rv = + nsTArrayToJSArray(sc->GetNativeContext(), + sc->GetNativeGlobal(), mCalls, &calls); + NS_ENSURE_SUCCESS(rv, rv); - if (!mRooted) { - NS_HOLD_JS_OBJECTS(this, Telephony); - mRooted = true; + if (!mRooted) { + NS_HOLD_JS_OBJECTS(this, Telephony); + mRooted = true; + } + + mCallsArray = calls; + } else { + NS_ENSURE_SUCCESS(rv, rv); } - - mCallsArray = calls; } aCalls->setObject(*calls); diff --git a/dom/telephony/Telephony.h b/dom/telephony/Telephony.h index c374331f51ba..c602737b73da 100644 --- a/dom/telephony/Telephony.h +++ b/dom/telephony/Telephony.h @@ -118,18 +118,6 @@ public: return mRIL; } - nsPIDOMWindow* - Owner() const - { - return mOwner; - } - - nsIScriptContext* - ScriptContext() const - { - return mScriptContext; - } - private: Telephony(); ~Telephony(); diff --git a/dom/telephony/TelephonyCall.cpp b/dom/telephony/TelephonyCall.cpp index 81c7c0b2b717..421167a0d388 100644 --- a/dom/telephony/TelephonyCall.cpp +++ b/dom/telephony/TelephonyCall.cpp @@ -57,8 +57,8 @@ TelephonyCall::Create(Telephony* aTelephony, const nsAString& aNumber, nsRefPtr call = new TelephonyCall(); - call->mOwner = aTelephony->Owner(); - call->mScriptContext = aTelephony->ScriptContext(); + call->BindToOwner(aTelephony->GetOwner()); + call->mTelephony = aTelephony; call->mNumber = aNumber; call->mCallIndex = aCallIndex; From 95eecd06bcc0eb0b8ebd95c25dc2ebbd034e0bdc Mon Sep 17 00:00:00 2001 From: Jason Duell Date: Tue, 13 Mar 2012 18:46:30 -0700 Subject: [PATCH 54/57] Bug 664163: Yes this will get backed out: see bug. r=jdm --- netwerk/protocol/http/HttpChannelChild.cpp | 41 +++-------- netwerk/protocol/http/HttpChannelChild.h | 4 -- netwerk/protocol/http/HttpChannelParent.cpp | 11 ++- netwerk/test/unit/test_traceable_channel.js | 76 +++++++++++++++++---- 4 files changed, 80 insertions(+), 52 deletions(-) diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/HttpChannelChild.cpp index 4df4d51f61a5..7b8320b6aff0 100644 --- a/netwerk/protocol/http/HttpChannelChild.cpp +++ b/netwerk/protocol/http/HttpChannelChild.cpp @@ -287,10 +287,18 @@ HttpChannelChild::OnStartRequest(const nsHttpResponseHead& responseHead, getter_AddRefs(mSecurityInfo)); } + // Sanity check: we should have either set both remote/local socket addresses + // or neither of them. + if (selfAddr.raw.family != peerAddr.raw.family) { + NS_RUNTIMEABORT("Child: socket has multiple address families!"); + } + mIsFromCache = isFromCache; mCacheEntryAvailable = cacheEntryAvailable; mCacheExpirationTime = cacheExpirationTime; mCachedCharset = cachedCharset; + mSelfAddr = selfAddr; + mPeerAddr = peerAddr; AutoEventEnqueuer ensureSerialDispatch(mEventQ); @@ -313,9 +321,6 @@ HttpChannelChild::OnStartRequest(const nsHttpResponseHead& responseHead, rv = ApplyContentConversions(); if (NS_FAILED(rv)) Cancel(rv); - - mSelfAddr = selfAddr; - mPeerAddr = peerAddr; } class TransportAndDataEvent : public ChannelEvent @@ -1113,36 +1118,6 @@ HttpChannelChild::SetupFallbackChannel(const char *aFallbackKey) DROP_DEAD(); } -// The next four _should_ be implemented, but we need to figure out how -// to transfer the data from the chrome process first. - -NS_IMETHODIMP -HttpChannelChild::GetRemoteAddress(nsACString & _result) -{ - return NS_ERROR_NOT_AVAILABLE; -} - -NS_IMETHODIMP -HttpChannelChild::GetRemotePort(PRInt32 * _result) -{ - NS_ENSURE_ARG_POINTER(_result); - return NS_ERROR_NOT_AVAILABLE; -} - -NS_IMETHODIMP -HttpChannelChild::GetLocalAddress(nsACString & _result) -{ - return NS_ERROR_NOT_AVAILABLE; -} - -NS_IMETHODIMP -HttpChannelChild::GetLocalPort(PRInt32 * _result) -{ - NS_ENSURE_ARG_POINTER(_result); - return NS_ERROR_NOT_AVAILABLE; -} - - //----------------------------------------------------------------------------- // HttpChannelChild::nsICacheInfoChannel //----------------------------------------------------------------------------- diff --git a/netwerk/protocol/http/HttpChannelChild.h b/netwerk/protocol/http/HttpChannelChild.h index 43617ef5589c..f9f7c2e0003a 100644 --- a/netwerk/protocol/http/HttpChannelChild.h +++ b/netwerk/protocol/http/HttpChannelChild.h @@ -106,10 +106,6 @@ public: bool aMerge); // nsIHttpChannelInternal NS_IMETHOD SetupFallbackChannel(const char *aFallbackKey); - NS_IMETHOD GetLocalAddress(nsACString& addr); - NS_IMETHOD GetLocalPort(PRInt32* port); - NS_IMETHOD GetRemoteAddress(nsACString& addr); - NS_IMETHOD GetRemotePort(PRInt32* port); // nsISupportsPriority NS_IMETHOD SetPriority(PRInt32 value); // nsIResumableChannel diff --git a/netwerk/protocol/http/HttpChannelParent.cpp b/netwerk/protocol/http/HttpChannelParent.cpp index ee901cce07f3..1fc1a69bb25b 100644 --- a/netwerk/protocol/http/HttpChannelParent.cpp +++ b/netwerk/protocol/http/HttpChannelParent.cpp @@ -450,6 +450,15 @@ HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) } nsHttpChannel *httpChan = static_cast(mChannel.get()); + + // Sanity check: we should have either set both remote/local socket addresses + // or neither of them. + PRNetAddr selfAddr = httpChan->GetSelfAddr(); + PRNetAddr peerAddr = httpChan->GetPeerAddr(); + if (selfAddr.raw.family != peerAddr.raw.family) { + NS_RUNTIMEABORT("Parent: socket has multiple address families!"); + } + if (mIPCClosed || !SendOnStartRequest(responseHead ? *responseHead : nsHttpResponseHead(), !!responseHead, @@ -457,7 +466,7 @@ HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) isFromCache, mCacheDescriptor ? true : false, expirationTime, cachedCharset, secInfoSerialization, - httpChan->GetSelfAddr(), httpChan->GetPeerAddr())) + selfAddr, peerAddr)) { return NS_ERROR_UNEXPECTED; } diff --git a/netwerk/test/unit/test_traceable_channel.js b/netwerk/test/unit/test_traceable_channel.js index a62b8a2c92b3..164d65f4c46f 100644 --- a/netwerk/test/unit/test_traceable_channel.js +++ b/netwerk/test/unit/test_traceable_channel.js @@ -22,14 +22,42 @@ TracingListener.prototype = { request.QueryInterface(Components.interfaces.nsIHttpChannelInternal); -// local/remote addresses broken in e10s: disable for now -/* - do_check_eq(request.localAddress, "127.0.0.1"); - do_check_eq(request.localPort > 0, true); - do_check_neq(request.localPort, 4444); - do_check_eq(request.remoteAddress, "127.0.0.1"); - do_check_eq(request.remotePort, 4444); -*/ + var localAddr = "unknown"; + var localPort = "unknown"; + var remoteAddr = "unknown"; + var remotePort = "unknown"; + try { + localAddr = request.localAddress; + dump("got local address\n"); + } catch(e) { + dump("couldn't get local address\n"); + } + try { + localPort = request.localPort; + dump("got local port\n"); + } catch(e) { + dump("couldn't get local port\n"); + } + try { + remoteAddr = request.remoteAddress; + dump("got remote address\n"); + } catch(e) { + dump("couldn't get remote address\n"); + } + try { + remotePort = request.remotePort; + dump("got remote port\n"); + } catch(e) { + dump("couldn't get remote port\n"); + } + + do_check_eq(localAddr, "127.0.0.1"); + do_check_eq(localPort > 0, true); + do_check_eq(remoteAddr, "127.0.0.1"); + do_check_eq(remotePort, 4444); + + request.QueryInterface(Components.interfaces.nsISupportsPriority); + request.priority = Ci.nsISupportsPriority.PRIORITY_LOW; // Make sure listener can't be replaced after OnStartRequest was called. request.QueryInterface(Components.interfaces.nsITraceableChannel); @@ -63,9 +91,10 @@ TracingListener.prototype = { input.close(); } catch (e) { dump("TracingListener.onStopRequest swallowing exception: " + e + "\n"); - } finally { - httpserver.stop(do_test_finished); } + + // we're the last OnStopRequest called by the nsIStreamListenerTee + run_next_test(); }, QueryInterface: function(iid) { @@ -135,18 +164,37 @@ function make_channel(url) { // Check if received body is correctly modified. function channel_finished(request, input, ctx) { - httpserver.stop(do_test_finished); + // No-op: since the nsIStreamListenerTee calls the observer's OnStopRequest + // after this, we call run_next_test() there +} + +// needs to be global or it'll go out of scope before it observes request +var observer = new HttpResponseExaminer(); + +var testRuns = 1; // change this to >1 to run test multiple times +var iteration = 1; + +function run_next_test() { + if (iteration > testRuns) { + dump("Shutting down\n"); + httpserver.stop(do_test_finished); + return; + } + if (iteration > 1) { + dump("^^^ test iteration=" + iteration + "\n"); + } + var channel = make_channel("http://localhost:4444/testdir"); + channel.asyncOpen(new ChannelListener(channel_finished), null); + iteration++; } function run_test() { - var observer = new HttpResponseExaminer(); observer.register(); httpserver = new nsHttpServer(); httpserver.registerPathHandler("/testdir", test_handler); httpserver.start(4444); - var channel = make_channel("http://localhost:4444/testdir"); - channel.asyncOpen(new ChannelListener(channel_finished), null); + run_next_test(); do_test_pending(); } From b75cba041028958db190dae3dc00e56f19716da0 Mon Sep 17 00:00:00 2001 From: Phil Ringnalda Date: Tue, 13 Mar 2012 22:11:55 -0700 Subject: [PATCH 55/57] Back out 9899522b6ad9 (bug 664163) --- netwerk/protocol/http/HttpChannelChild.cpp | 41 ++++++++--- netwerk/protocol/http/HttpChannelChild.h | 4 ++ netwerk/protocol/http/HttpChannelParent.cpp | 11 +-- netwerk/test/unit/test_traceable_channel.js | 76 ++++----------------- 4 files changed, 52 insertions(+), 80 deletions(-) diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/HttpChannelChild.cpp index 7b8320b6aff0..4df4d51f61a5 100644 --- a/netwerk/protocol/http/HttpChannelChild.cpp +++ b/netwerk/protocol/http/HttpChannelChild.cpp @@ -287,18 +287,10 @@ HttpChannelChild::OnStartRequest(const nsHttpResponseHead& responseHead, getter_AddRefs(mSecurityInfo)); } - // Sanity check: we should have either set both remote/local socket addresses - // or neither of them. - if (selfAddr.raw.family != peerAddr.raw.family) { - NS_RUNTIMEABORT("Child: socket has multiple address families!"); - } - mIsFromCache = isFromCache; mCacheEntryAvailable = cacheEntryAvailable; mCacheExpirationTime = cacheExpirationTime; mCachedCharset = cachedCharset; - mSelfAddr = selfAddr; - mPeerAddr = peerAddr; AutoEventEnqueuer ensureSerialDispatch(mEventQ); @@ -321,6 +313,9 @@ HttpChannelChild::OnStartRequest(const nsHttpResponseHead& responseHead, rv = ApplyContentConversions(); if (NS_FAILED(rv)) Cancel(rv); + + mSelfAddr = selfAddr; + mPeerAddr = peerAddr; } class TransportAndDataEvent : public ChannelEvent @@ -1118,6 +1113,36 @@ HttpChannelChild::SetupFallbackChannel(const char *aFallbackKey) DROP_DEAD(); } +// The next four _should_ be implemented, but we need to figure out how +// to transfer the data from the chrome process first. + +NS_IMETHODIMP +HttpChannelChild::GetRemoteAddress(nsACString & _result) +{ + return NS_ERROR_NOT_AVAILABLE; +} + +NS_IMETHODIMP +HttpChannelChild::GetRemotePort(PRInt32 * _result) +{ + NS_ENSURE_ARG_POINTER(_result); + return NS_ERROR_NOT_AVAILABLE; +} + +NS_IMETHODIMP +HttpChannelChild::GetLocalAddress(nsACString & _result) +{ + return NS_ERROR_NOT_AVAILABLE; +} + +NS_IMETHODIMP +HttpChannelChild::GetLocalPort(PRInt32 * _result) +{ + NS_ENSURE_ARG_POINTER(_result); + return NS_ERROR_NOT_AVAILABLE; +} + + //----------------------------------------------------------------------------- // HttpChannelChild::nsICacheInfoChannel //----------------------------------------------------------------------------- diff --git a/netwerk/protocol/http/HttpChannelChild.h b/netwerk/protocol/http/HttpChannelChild.h index f9f7c2e0003a..43617ef5589c 100644 --- a/netwerk/protocol/http/HttpChannelChild.h +++ b/netwerk/protocol/http/HttpChannelChild.h @@ -106,6 +106,10 @@ public: bool aMerge); // nsIHttpChannelInternal NS_IMETHOD SetupFallbackChannel(const char *aFallbackKey); + NS_IMETHOD GetLocalAddress(nsACString& addr); + NS_IMETHOD GetLocalPort(PRInt32* port); + NS_IMETHOD GetRemoteAddress(nsACString& addr); + NS_IMETHOD GetRemotePort(PRInt32* port); // nsISupportsPriority NS_IMETHOD SetPriority(PRInt32 value); // nsIResumableChannel diff --git a/netwerk/protocol/http/HttpChannelParent.cpp b/netwerk/protocol/http/HttpChannelParent.cpp index 1fc1a69bb25b..ee901cce07f3 100644 --- a/netwerk/protocol/http/HttpChannelParent.cpp +++ b/netwerk/protocol/http/HttpChannelParent.cpp @@ -450,15 +450,6 @@ HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) } nsHttpChannel *httpChan = static_cast(mChannel.get()); - - // Sanity check: we should have either set both remote/local socket addresses - // or neither of them. - PRNetAddr selfAddr = httpChan->GetSelfAddr(); - PRNetAddr peerAddr = httpChan->GetPeerAddr(); - if (selfAddr.raw.family != peerAddr.raw.family) { - NS_RUNTIMEABORT("Parent: socket has multiple address families!"); - } - if (mIPCClosed || !SendOnStartRequest(responseHead ? *responseHead : nsHttpResponseHead(), !!responseHead, @@ -466,7 +457,7 @@ HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) isFromCache, mCacheDescriptor ? true : false, expirationTime, cachedCharset, secInfoSerialization, - selfAddr, peerAddr)) + httpChan->GetSelfAddr(), httpChan->GetPeerAddr())) { return NS_ERROR_UNEXPECTED; } diff --git a/netwerk/test/unit/test_traceable_channel.js b/netwerk/test/unit/test_traceable_channel.js index 164d65f4c46f..a62b8a2c92b3 100644 --- a/netwerk/test/unit/test_traceable_channel.js +++ b/netwerk/test/unit/test_traceable_channel.js @@ -22,42 +22,14 @@ TracingListener.prototype = { request.QueryInterface(Components.interfaces.nsIHttpChannelInternal); - var localAddr = "unknown"; - var localPort = "unknown"; - var remoteAddr = "unknown"; - var remotePort = "unknown"; - try { - localAddr = request.localAddress; - dump("got local address\n"); - } catch(e) { - dump("couldn't get local address\n"); - } - try { - localPort = request.localPort; - dump("got local port\n"); - } catch(e) { - dump("couldn't get local port\n"); - } - try { - remoteAddr = request.remoteAddress; - dump("got remote address\n"); - } catch(e) { - dump("couldn't get remote address\n"); - } - try { - remotePort = request.remotePort; - dump("got remote port\n"); - } catch(e) { - dump("couldn't get remote port\n"); - } - - do_check_eq(localAddr, "127.0.0.1"); - do_check_eq(localPort > 0, true); - do_check_eq(remoteAddr, "127.0.0.1"); - do_check_eq(remotePort, 4444); - - request.QueryInterface(Components.interfaces.nsISupportsPriority); - request.priority = Ci.nsISupportsPriority.PRIORITY_LOW; +// local/remote addresses broken in e10s: disable for now +/* + do_check_eq(request.localAddress, "127.0.0.1"); + do_check_eq(request.localPort > 0, true); + do_check_neq(request.localPort, 4444); + do_check_eq(request.remoteAddress, "127.0.0.1"); + do_check_eq(request.remotePort, 4444); +*/ // Make sure listener can't be replaced after OnStartRequest was called. request.QueryInterface(Components.interfaces.nsITraceableChannel); @@ -91,10 +63,9 @@ TracingListener.prototype = { input.close(); } catch (e) { dump("TracingListener.onStopRequest swallowing exception: " + e + "\n"); + } finally { + httpserver.stop(do_test_finished); } - - // we're the last OnStopRequest called by the nsIStreamListenerTee - run_next_test(); }, QueryInterface: function(iid) { @@ -164,37 +135,18 @@ function make_channel(url) { // Check if received body is correctly modified. function channel_finished(request, input, ctx) { - // No-op: since the nsIStreamListenerTee calls the observer's OnStopRequest - // after this, we call run_next_test() there -} - -// needs to be global or it'll go out of scope before it observes request -var observer = new HttpResponseExaminer(); - -var testRuns = 1; // change this to >1 to run test multiple times -var iteration = 1; - -function run_next_test() { - if (iteration > testRuns) { - dump("Shutting down\n"); - httpserver.stop(do_test_finished); - return; - } - if (iteration > 1) { - dump("^^^ test iteration=" + iteration + "\n"); - } - var channel = make_channel("http://localhost:4444/testdir"); - channel.asyncOpen(new ChannelListener(channel_finished), null); - iteration++; + httpserver.stop(do_test_finished); } function run_test() { + var observer = new HttpResponseExaminer(); observer.register(); httpserver = new nsHttpServer(); httpserver.registerPathHandler("/testdir", test_handler); httpserver.start(4444); - run_next_test(); + var channel = make_channel("http://localhost:4444/testdir"); + channel.asyncOpen(new ChannelListener(channel_finished), null); do_test_pending(); } From 0169280ddf4f157c128401098e08fac88a848f51 Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Tue, 13 Mar 2012 22:18:29 -0700 Subject: [PATCH 56/57] Bug 696533 - (1/2) XBL bindings for add-on settings on Android [r=mfinkle] --- mobile/android/chrome/content/bindings.xml | 93 --------------- .../chrome/content/bindings/settings.xml | 62 ++++++++++ mobile/android/chrome/content/browser.css | 46 -------- mobile/android/chrome/jar.mn | 1 + mobile/android/themes/core/aboutAddons.css | 111 ++++++++++++++++-- 5 files changed, 167 insertions(+), 146 deletions(-) create mode 100644 mobile/android/chrome/content/bindings/settings.xml diff --git a/mobile/android/chrome/content/bindings.xml b/mobile/android/chrome/content/bindings.xml index 70e68f8bb670..103a2b9cba64 100644 --- a/mobile/android/chrome/content/bindings.xml +++ b/mobile/android/chrome/content/bindings.xml @@ -109,33 +109,6 @@ - - - - - - - - - - - - - - - - - - - @@ -261,70 +234,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mobile/android/chrome/content/bindings/settings.xml b/mobile/android/chrome/content/bindings/settings.xml new file mode 100644 index 000000000000..afc54c9d6aa3 --- /dev/null +++ b/mobile/android/chrome/content/bindings/settings.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mobile/android/chrome/content/browser.css b/mobile/android/chrome/content/browser.css index a01513f94125..a8657db596db 100644 --- a/mobile/android/chrome/content/browser.css +++ b/mobile/android/chrome/content/browser.css @@ -1,45 +1,3 @@ -settings { - -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#settings"); -} - -setting[type="bool"] { - -moz-binding: url("chrome://browser/content/bindings.xml#setting-fulltoggle-bool"); -} - -setting[type="bool"][localized="true"] { - -moz-binding: url("chrome://browser/content/bindings.xml#setting-fulltoggle-localized-bool"); -} - -setting[type="boolint"] { - -moz-binding: url("chrome://browser/content/bindings.xml#setting-fulltoggle-boolint"); -} - -setting[type="integer"] { - -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-integer"); -} - -setting[type="control"] { - -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-control"); -} - -setting[type="string"] { - -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-string"); -} - -setting[type="color"] { - -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-color"); -} - -setting[type="file"], -setting[type="directory"] { - -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-path"); -} - -setting[type="radio"], -setting[type="menulist"] { - -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-multi"); -} - radio { -moz-binding: url("chrome://global/content/bindings/radio.xml#radio"); } @@ -52,10 +10,6 @@ menulist { -moz-binding: url("chrome://browser/content/bindings.xml#menulist"); } -.chrome-select-option { - -moz-binding: url("chrome://browser/content/bindings.xml#chrome-select-option"); -} - /* richlist defaults ------------------------------------------------------- */ richlistbox[batch] { -moz-binding: url("chrome://browser/content/bindings.xml#richlistbox-batch"); diff --git a/mobile/android/chrome/jar.mn b/mobile/android/chrome/jar.mn index 7fe708b425ab..3b89c73f57b2 100644 --- a/mobile/android/chrome/jar.mn +++ b/mobile/android/chrome/jar.mn @@ -16,6 +16,7 @@ chrome.jar: * content/browser.js (content/browser.js) * content/bindings.xml (content/bindings.xml) content/bindings/checkbox.xml (content/bindings/checkbox.xml) + content/bindings/settings.xml (content/bindings/settings.xml) content/bindings/dialog.xml (content/bindings/dialog.xml) content/browser.css (content/browser.css) content/cursor.css (content/cursor.css) diff --git a/mobile/android/themes/core/aboutAddons.css b/mobile/android/themes/core/aboutAddons.css index efa774d99f14..f095dd31b4e8 100644 --- a/mobile/android/themes/core/aboutAddons.css +++ b/mobile/android/themes/core/aboutAddons.css @@ -79,13 +79,6 @@ body { color: #999999; } -.addon-item:not([optionsURL]) .options-header, -.addon-item[optionsURL=""] .options-header, -.addon-item:not([optionsURL]) .options-box, -.addon-item[optionsURL=""] .options-box { - display: none; -} - .inner { background-image: url("chrome://browser/skin/images/row-bg-light.png"); min-height: 70px; @@ -176,3 +169,107 @@ body[dir="ltr"] .favicon { .addon-item[isDisabled="true"] .favicon { opacity: 0.3; } + +.options-header { + font-weight: bold; + padding: 12px 24px; +} + +.options-box { + margin: 0 12px; +} + +.addon-item:not([optionsURL]) .options-header, +.addon-item[optionsURL=""] .options-header, +.addon-item:not([optionsURL]) .options-box, +.addon-item[optionsURL=""] .options-box { + display: none; +} + +setting { + padding: 12px 18px; + border-top: 2px solid; + -moz-border-top-colors: #bac2ac #ffffff; + -moz-box-sizing: border-box; + width: 100%; +} + +setting > vbox { + -moz-box-flex: 1; +} + +.preferences-title { + font-weight: bold; +} + +.preferences-description:empty { + display: none; +} + +/* Put setting textboxes on a separate row */ +setting[type="integer"], +setting[type="string"] { + -moz-box-align: stretch; + -moz-box-orient: vertical; +} + +setting[type="integer"] > .preferences-alignment > textbox, +setting[type="string"] > .preferences-alignment > textbox { + width: 100%; +} + +.preferences-alignment > textbox { + font-size: 22px !important; +} + +.preferences-alignment > input[type="checkbox"] { + -moz-appearance: none !important; + width: 22px !important; + height: 22px !important; +} + +/* XBL bindings */ + +settings { + -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#settings"); +} + +setting { + display: none; +} + +setting[type="bool"] { + display: -moz-box; + -moz-binding: url("chrome://browser/content/bindings/settings.xml#setting-fulltoggle-bool"); +} + +setting[type="bool"][localized="true"] { + display: -moz-box; + -moz-binding: url("chrome://browser/content/bindings/settings.xml#setting-fulltoggle-localized-bool"); +} + +setting[type="boolint"] { + display: -moz-box; + -moz-binding: url("chrome://browser/content/bindings/settings.xml#setting-fulltoggle-boolint"); +} + +setting[type="integer"] { + display: -moz-box; + -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-integer"); +} + +setting[type="control"] { + display: -moz-box; + -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-control"); +} + +setting[type="string"] { + display: -moz-box; + -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-string"); +} + +setting[type="radio"], +setting[type="menulist"] { + display: -moz-box; + -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-multi"); +} From 11bd319e9c41e30d1e66ed0168cea495ec1c42c0 Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Tue, 13 Mar 2012 22:19:02 -0700 Subject: [PATCH 57/57] Bug 696533 - (2/2) Theme changes for add-on preferences on Android [r=mfinkle] --- mobile/android/themes/core/aboutAddons.css | 50 ++++++++++++++---- .../themes/core/images/checkbox_checked.png | Bin 0 -> 3091 bytes .../core/images/checkbox_checked_disabled.png | Bin 0 -> 3068 bytes .../core/images/checkbox_checked_pressed.png | Bin 0 -> 3297 bytes .../themes/core/images/checkbox_unchecked.png | Bin 0 -> 2825 bytes .../images/checkbox_unchecked_disabled.png | Bin 0 -> 2836 bytes .../images/checkbox_unchecked_pressed.png | Bin 0 -> 2968 bytes mobile/android/themes/core/jar.mn | 18 +++++++ 8 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 mobile/android/themes/core/images/checkbox_checked.png create mode 100644 mobile/android/themes/core/images/checkbox_checked_disabled.png create mode 100644 mobile/android/themes/core/images/checkbox_checked_pressed.png create mode 100644 mobile/android/themes/core/images/checkbox_unchecked.png create mode 100644 mobile/android/themes/core/images/checkbox_unchecked_disabled.png create mode 100644 mobile/android/themes/core/images/checkbox_unchecked_pressed.png diff --git a/mobile/android/themes/core/aboutAddons.css b/mobile/android/themes/core/aboutAddons.css index f095dd31b4e8..c0833cbb1798 100644 --- a/mobile/android/themes/core/aboutAddons.css +++ b/mobile/android/themes/core/aboutAddons.css @@ -172,7 +172,7 @@ body[dir="ltr"] .favicon { .options-header { font-weight: bold; - padding: 12px 24px; + padding: 18px 24px; } .options-box { @@ -187,9 +187,10 @@ body[dir="ltr"] .favicon { } setting { - padding: 12px 18px; + padding: 18px 12px; border-top: 2px solid; -moz-border-top-colors: #bac2ac #ffffff; + -moz-box-align: center; -moz-box-sizing: border-box; width: 100%; } @@ -213,21 +214,48 @@ setting[type="string"] { -moz-box-orient: vertical; } -setting[type="integer"] > .preferences-alignment > textbox, -setting[type="string"] > .preferences-alignment > textbox { - width: 100%; -} - .preferences-alignment > textbox { + margin-top: 12px; font-size: 22px !important; } -.preferences-alignment > input[type="checkbox"] { - -moz-appearance: none !important; - width: 22px !important; - height: 22px !important; +checkbox { + -moz-binding: url("chrome://global/content/bindings/checkbox.xml#checkbox-with-spacing") !important; } +.checkbox-check { + border: 2px transparent; + -moz-border-top-colors: -moz-initial; + -moz-border-right-colors: -moz-initial; + -moz-border-bottom-colors: -moz-initial; + -moz-border-left-colors: -moz-initial; + -moz-box-sizing: border-box; + width: 48px; + height: 48px; + background: url("chrome://browser/skin/images/checkbox_unchecked.png") no-repeat 50% 50%; +} + +setting:active checkbox > .checkbox-spacer-box > .checkbox-check { + background-image: url("chrome://browser/skin/images/checkbox_unchecked_pressed.png"); +} + +checkbox[disabled="true"] > .checkbox-spacer-box > .checkbox-check { + background-image: url("chrome://browser/skin/images/checkbox_unchecked_disabled.png"); +} + +checkbox[checked="true"] > .checkbox-spacer-box > .checkbox-check { + background-image: url("chrome://browser/skin/images/checkbox_checked.png"); +} + +setting:active checkbox[checked="true"] > .checkbox-spacer-box > .checkbox-check { + background-image: url("chrome://browser/skin/images/checkbox_checked_pressed.png"); +} + +checkbox[checked="true"][disabled="true"] > .checkbox-spacer-box > .checkbox-check { + background-image: url("chrome://browser/skin/images/checkbox_checked_disabled.png"); +} + + /* XBL bindings */ settings { diff --git a/mobile/android/themes/core/images/checkbox_checked.png b/mobile/android/themes/core/images/checkbox_checked.png new file mode 100644 index 0000000000000000000000000000000000000000..e87e6146b04bc680c1d8370315c0c78390b06dc3 GIT binary patch literal 3091 zcmV+u4D9oXP)EX>4Tx0C?J+Q)g6D=@vcr-tj1^HV42lZa2jn55j)S9!ipu-pd!uXCy!YnK{> z2n?1;Gf_2w45>mM5#WQz#Kz&|EGkvK~TfD`~gdX7S-06<0ofSs5oQvjd@0AR~wV&ec% zEdXFAf9BHwfSvf6djSAjlpz%XppgI|6J>}*0BAb^tj|`8MF3bZ02F3R#5n-iEdVe{ zS7t~6u(trf&JYW-00;~KFj0twDF6g}0AR=?BX|IWnE(_<@>e|ZE3OddDgXd@nX){& zBsoQaTL>+22Uk}v9w^R97b_GtVFF>AKrX_0nHe&HG!NkO%m4tOkrff(gY*4(&JM25 z&Nhy=4qq+mzXtyzVq)X|<DpKGaQJ>aJVl|9x!Kv}EM4F8AGNmGkLXs)P zCDQ+7;@>R$13uq10I+I40eg`xs9j?N_Dd%aSaiVR_W%I$yKlkNCzL=651DUOSSq$Ed=-((3YAKgCY2j1FI1_jrmEhm z3sv(~%T$l4UQ>OpMpZLYTc&xiMv2YpRx)mRPGut5K^*>%BIv?Wdil zy+ylO`+*KY$4Vz$Cr4+G&IO(4Q`uA9rwXSQO+7mGt}d!;r5mBUM0dY#r|y`ZzFvTy zOmC;&dA;ZQ9DOhSRQ+xGr}ak+SO&8UBnI0I&KNw!HF0k|9WTe*@liuv!$3o&VU=N* z;e?U7(LAHoMvX=fjA_PP<0Rv4#%;!P6gpNq-kQ#w?mvCS^p@!_XIRe=&)75LwiC-K#A%&Vo6|>U7iYP1 zgY$@siA#dZE|)$on;XX6$i3uBboFsv;d;{botv|p!tJQrukJSPY3_&IpUgC$DV|v~ zbI`-cL*P;6(LW2Hl`w1HtbR{JPl0E(=OZs;FOgTR*RZ#xcdGYc?-xGyK60PqKI1$$ z-ZI`wBrnsy*W_HW0Wrec-#cqqYFCLW#$!oKa ztOZ#u3bsO~=u}!L*D43HXJuDrzs-rtIhL!QE6wf9v&!3$H=OUE|LqdO65*1zrG`sa zEge|qy{u|EvOIBl+X~|q1uKSD2CO`|inc0k)laMKSC_7Sy(W51Yk^+D%7VeQ0c-0E zRSM;Wee2xU?Ojh;FInHUVfu!h8$K0@imnvf7nc=(*eKk1(e4|2y!JHg)!SRV_x(P}zS~s+RZZ1q)n)rh`?L2yu8FGY z_?G)^U9C=SaqY(g(gXbmBM!FLxzyDi(mhmCkJc;eM-ImyzW$x>cP$Mz4ONYt#^NJz zM0w=t_X*$k9t}F$c8q(h;Rn+nb{%IOFKR-X@|s4QQ=0o*Vq3aT%s$c9>fU<%N829{ zoHRUHc}nwC$!Xf@g42^{^3RN&m7RTlF8SPG+oHC6=VQ*_Y7cMkx)5~X(nbG^=R3SR z&Rp`ibn>#>OB6F(@)2{oV%K?xm;_x?s~noduI3P8=g1L-SoYA z@fQEq)t)&$-M#aAZ}-Lb_1_lVesU-M&da;mcPH+xyidGe^g!)F*+boj)jwPQ+}Q8j ze`>&Yp!3n(NB0JWgU|kv^^Xrj1&^7J%Z3ex>z+71IXU7#a{cN2r$f(V&nBK1{-XZN zt``^}my^G3e5L*B!0Q>W+s4Ai9=^$VGcjKDR{QP2cieX!@1x%j zPvm?ce<=TG`LXp=(5L&88IzO$1Ou4!{O>iCf&c&kiAh93RA}Dqm$6C%K@f&NL%_z$ z_WCrIQwRYeAXe$}1cH?y2!VhYu~LLUAgH9W@BwVMvGN7BQY=KU+R8SKg zkte=%d2wL?9AykWr{bSQ>nlqZKh6=~oh80Bd2yk?sJObkxUg4ZP7i1=Dy}M@c8o`H zp;IvD3g~EvtI1Ebx}Lbu&JjP+5?7HI7cMedU4Jq_I;T)vMCu}PDkAG;_pT}&{5`M_ zBpCs|flZ)W;>2q}3%DM?b)%oWZzk_R0|*(z1K?bEX>4Tx0C?J+Q)g6D=@vcr-tj1^HV42lZa2jn55j)S9!ipu-pd!uXCy!YnK{> z2n?1;Gf_2w45>mM5#WQz#Kz&|EGkvK~TfD`~gdX7S-06<0ofSs5oQvjd@0AR~wV&ec% zEdXFAf9BHwfSvf6djSAjlpz%XppgI|6J>}*0BAb^tj|`8MF3bZ02F3R#5n-iEdVe{ zS7t~6u(trf&JYW-00;~KFj0twDF6g}0AR=?BX|IWnE(_<@>e|ZE3OddDgXd@nX){& zBsoQaTL>+22Uk}v9w^R97b_GtVFF>AKrX_0nHe&HG!NkO%m4tOkrff(gY*4(&JM25 z&Nhy=4qq+mzXtyzVq)X|<DpKGaQJ>aJVl|9x!Kv}EM4F8AGNmGkLXs)P zCDQ+7;@>R$13uq10I+I40eg`xs9j?N_Dd%aSaiVR_W%I$yKlkNCzL=651DUOSSq$Ed=-((3YAKgCY2j1FI1_jrmEhm z3sv(~%T$l4UQ>OpMpZLYTc&xiMv2YpRx)mRPGut5K^*>%BIv?Wdil zy+ylO`+*KY$4Vz$Cr4+G&IO(4Q`uA9rwXSQO+7mGt}d!;r5mBUM0dY#r|y`ZzFvTy zOmC;&dA;ZQ9DOhSRQ+xGr}ak+SO&8UBnI0I&KNw!HF0k|9WTe*@liuv!$3o&VU=N* z;e?U7(LAHoMvX=fjA_PP<0Rv4#%;!P6gpNq-kQ#w?mvCS^p@!_XIRe=&)75LwiC-K#A%&Vo6|>U7iYP1 zgY$@siA#dZE|)$on;XX6$i3uBboFsv;d;{botv|p!tJQrukJSPY3_&IpUgC$DV|v~ zbI`-cL*P;6(LW2Hl`w1HtbR{JPl0E(=OZs;FOgTR*RZ#xcdGYc?-xGyK60PqKI1$$ z-ZI`wBrnsy*W_HW0Wrec-#cqqYFCLW#$!oKa ztOZ#u3bsO~=u}!L*D43HXJuDrzs-rtIhL!QE6wf9v&!3$H=OUE|LqdO65*1zrG`sa zEge|qy{u|EvOIBl+X~|q1uKSD2CO`|inc0k)laMKSC_7Sy(W51Yk^+D%7VeQ0c-0E zRSM;Wee2xU?Ojh;FInHUVfu!h8$K0@imnvf7nc=(*eKk1(e4|2y!JHg)!SRV_x(P}zS~s+RZZ1q)n)rh`?L2yu8FGY z_?G)^U9C=SaqY(g(gXbmBM!FLxzyDi(mhmCkJc;eM-ImyzW$x>cP$Mz4ONYt#^NJz zM0w=t_X*$k9t}F$c8q(h;Rn+nb{%IOFKR-X@|s4QQ=0o*Vq3aT%s$c9>fU<%N829{ zoHRUHc}nwC$!Xf@g42^{^3RN&m7RTlF8SPG+oHC6=VQ*_Y7cMkx)5~X(nbG^=R3SR z&Rp`ibn>#>OB6F(@)2{oV%K?xm;_x?s~noduI3P8=g1L-SoYA z@fQEq)t)&$-M#aAZ}-Lb_1_lVesU-M&da;mcPH+xyidGe^g!)F*+boj)jwPQ+}Q8j ze`>&Yp!3n(NB0JWgU|kv^^Xrj1&^7J%Z3ex>z+71IXU7#a{cN2r$f(V&nBK1{-XZN zt``^}my^G3e5L*B!0Q>W+s4Ai9=^$VGcjKDR{QP2cieX!@1x%j zPvm?ce<=TG`LXp=(5L&88IzO$1Ou4!{O>iCf&c&ka!Eu%RA}Dqm$6R6Fcd{Ep$iO< zvC6>22Y_x>1OickK&>jZ-@u<$@C)!0h{wvp#NsYU2qCdBuz0AVBo66wQ;B!B#EE@w z;ygQmVHk#C7)E0@*G-7zILopf=bWo^{l*_V?*JHTON+?8?|%fK?@vF7$W!RvPQx)j z0DLMx`Qd^*0E|f{BJvm`z+6OLmF15Ln))Q4MdYXK-ee8t{B?=^JAhf0eCq+c{Bec+ zSE!GqMfs~`)z^VQ2zB`=D{)DPDDu&^61fo3=UaRfu`)jbZCQH2*$8(<#&?xvlJyt};N{bU?!}48t%CLyuqirKiqBy$L}80000< KMNUMnLSTY28P5*@ literal 0 HcmV?d00001 diff --git a/mobile/android/themes/core/images/checkbox_checked_pressed.png b/mobile/android/themes/core/images/checkbox_checked_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..688a8282ef3151cca94c0d4e9662b56983852526 GIT binary patch literal 3297 zcmV<73?B1|P)EX>4Tx0C?J+Q)g6D=@vcr-tj1^HV42lZa2jn55j)S9!ipu-pd!uXCy!YnK{> z2n?1;Gf_2w45>mM5#WQz#Kz&|EGkvK~TfD`~gdX7S-06<0ofSs5oQvjd@0AR~wV&ec% zEdXFAf9BHwfSvf6djSAjlpz%XppgI|6J>}*0BAb^tj|`8MF3bZ02F3R#5n-iEdVe{ zS7t~6u(trf&JYW-00;~KFj0twDF6g}0AR=?BX|IWnE(_<@>e|ZE3OddDgXd@nX){& zBsoQaTL>+22Uk}v9w^R97b_GtVFF>AKrX_0nHe&HG!NkO%m4tOkrff(gY*4(&JM25 z&Nhy=4qq+mzXtyzVq)X|<DpKGaQJ>aJVl|9x!Kv}EM4F8AGNmGkLXs)P zCDQ+7;@>R$13uq10I+I40eg`xs9j?N_Dd%aSaiVR_W%I$yKlkNCzL=651DUOSSq$Ed=-((3YAKgCY2j1FI1_jrmEhm z3sv(~%T$l4UQ>OpMpZLYTc&xiMv2YpRx)mRPGut5K^*>%BIv?Wdil zy+ylO`+*KY$4Vz$Cr4+G&IO(4Q`uA9rwXSQO+7mGt}d!;r5mBUM0dY#r|y`ZzFvTy zOmC;&dA;ZQ9DOhSRQ+xGr}ak+SO&8UBnI0I&KNw!HF0k|9WTe*@liuv!$3o&VU=N* z;e?U7(LAHoMvX=fjA_PP<0Rv4#%;!P6gpNq-kQ#w?mvCS^p@!_XIRe=&)75LwiC-K#A%&Vo6|>U7iYP1 zgY$@siA#dZE|)$on;XX6$i3uBboFsv;d;{botv|p!tJQrukJSPY3_&IpUgC$DV|v~ zbI`-cL*P;6(LW2Hl`w1HtbR{JPl0E(=OZs;FOgTR*RZ#xcdGYc?-xGyK60PqKI1$$ z-ZI`wBrnsy*W_HW0Wrec-#cqqYFCLW#$!oKa ztOZ#u3bsO~=u}!L*D43HXJuDrzs-rtIhL!QE6wf9v&!3$H=OUE|LqdO65*1zrG`sa zEge|qy{u|EvOIBl+X~|q1uKSD2CO`|inc0k)laMKSC_7Sy(W51Yk^+D%7VeQ0c-0E zRSM;Wee2xU?Ojh;FInHUVfu!h8$K0@imnvf7nc=(*eKk1(e4|2y!JHg)!SRV_x(P}zS~s+RZZ1q)n)rh`?L2yu8FGY z_?G)^U9C=SaqY(g(gXbmBM!FLxzyDi(mhmCkJc;eM-ImyzW$x>cP$Mz4ONYt#^NJz zM0w=t_X*$k9t}F$c8q(h;Rn+nb{%IOFKR-X@|s4QQ=0o*Vq3aT%s$c9>fU<%N829{ zoHRUHc}nwC$!Xf@g42^{^3RN&m7RTlF8SPG+oHC6=VQ*_Y7cMkx)5~X(nbG^=R3SR z&Rp`ibn>#>OB6F(@)2{oV%K?xm;_x?s~noduI3P8=g1L-SoYA z@fQEq)t)&$-M#aAZ}-Lb_1_lVesU-M&da;mcPH+xyidGe^g!)F*+boj)jwPQ+}Q8j ze`>&Yp!3n(NB0JWgU|kv^^Xrj1&^7J%Z3ex>z+71IXU7#a{cN2r$f(V&nBK1{-XZN zt``^}my^G3e5L*B!0Q>W+s4Ai9=^$VGcjKDR{QP2cieX!@1x%j zPvm?ce<=TG`LXp=(5L&88IzO$1Ou4!{O>iCf&c&lS4l)cRA}Dqm`iIDQ51l`Odd{3 zf;ECl>!#2o;zBHhAfh0GA`yh@FAx{mi4a`5Rb1H6sH-mg3ocAM3PM3}C50^97!1v( zGsbEruO=B9UkhWwCQjS*<}os7J9D|;cjlgRhU)-eVPy(<2%G~Z8SPMkw?Kk;M0K>` zGr&Qt6*_QU0+JSl2M7T7CEzO7jY|^Xv9N$o!s1~I*aEh|h=pfE$7$59Dd4V`2&Lx; zDydydI9OQuxtC2&Jbxe@{KNHoxa%dtFCKBARs^7N_&6V9clhS@o33^BvY~Nk0%QEB z;LInt-~q;pYXp@P*=u+C;g-b;)F#3d!)JxU%hfL(&#IFrP2q=L1FlAe(Bgbo_`<2n zsAq1BZV|g06~gHxa^-W+@Iw>W%KSdzha%u=)(9=m<1K&MH@r{*cfG{a@-v*9O>_8k zQW$*CUC6AHc&cB?#cuQ6+3&Ft--X%|`gC;1S4F~$oddg&5DhPW zkeNvI1HM0#xQj%;;Drq`v%=o=1^NcxKY>3I7jN0O61KpoM^822*Rr@9WuYKmT^pQ$ zT+)zB+DLqXJ>Lu2HDC+a0=9rH@ZSkkEX=AK+}rZ2NDwTNDi0*URgw> f*=CIpkK}&=Q#A4vv;!~c00000NkvXXu0mjf;i)aJ literal 0 HcmV?d00001 diff --git a/mobile/android/themes/core/images/checkbox_unchecked.png b/mobile/android/themes/core/images/checkbox_unchecked.png new file mode 100644 index 0000000000000000000000000000000000000000..c34c4dff247d7229277766a76d33f7640520cc61 GIT binary patch literal 2825 zcmV+k3-EX>4Tx0C?J+Q)g6D=@vcr-tj1^HV42lZa2jn55j)S9!ipu-pd!uXCy!YnK{> z2n?1;Gf_2w45>mM5#WQz#Kz&|EGkvK~TfD`~gdX7S-06<0ofSs5oQvjd@0AR~wV&ec% zEdXFAf9BHwfSvf6djSAjlpz%XppgI|6J>}*0BAb^tj|`8MF3bZ02F3R#5n-iEdVe{ zS7t~6u(trf&JYW-00;~KFj0twDF6g}0AR=?BX|IWnE(_<@>e|ZE3OddDgXd@nX){& zBsoQaTL>+22Uk}v9w^R97b_GtVFF>AKrX_0nHe&HG!NkO%m4tOkrff(gY*4(&JM25 z&Nhy=4qq+mzXtyzVq)X|<DpKGaQJ>aJVl|9x!Kv}EM4F8AGNmGkLXs)P zCDQ+7;@>R$13uq10I+I40eg`xs9j?N_Dd%aSaiVR_W%I$yKlkNCzL=651DUOSSq$Ed=-((3YAKgCY2j1FI1_jrmEhm z3sv(~%T$l4UQ>OpMpZLYTc&xiMv2YpRx)mRPGut5K^*>%BIv?Wdil zy+ylO`+*KY$4Vz$Cr4+G&IO(4Q`uA9rwXSQO+7mGt}d!;r5mBUM0dY#r|y`ZzFvTy zOmC;&dA;ZQ9DOhSRQ+xGr}ak+SO&8UBnI0I&KNw!HF0k|9WTe*@liuv!$3o&VU=N* z;e?U7(LAHoMvX=fjA_PP<0Rv4#%;!P6gpNq-kQ#w?mvCS^p@!_XIRe=&)75LwiC-K#A%&Vo6|>U7iYP1 zgY$@siA#dZE|)$on;XX6$i3uBboFsv;d;{botv|p!tJQrukJSPY3_&IpUgC$DV|v~ zbI`-cL*P;6(LW2Hl`w1HtbR{JPl0E(=OZs;FOgTR*RZ#xcdGYc?-xGyK60PqKI1$$ z-ZI`wBrnsy*W_HW0Wrec-#cqqYFCLW#$!oKa ztOZ#u3bsO~=u}!L*D43HXJuDrzs-rtIhL!QE6wf9v&!3$H=OUE|LqdO65*1zrG`sa zEge|qy{u|EvOIBl+X~|q1uKSD2CO`|inc0k)laMKSC_7Sy(W51Yk^+D%7VeQ0c-0E zRSM;Wee2xU?Ojh;FInHUVfu!h8$K0@imnvf7nc=(*eKk1(e4|2y!JHg)!SRV_x(P}zS~s+RZZ1q)n)rh`?L2yu8FGY z_?G)^U9C=SaqY(g(gXbmBM!FLxzyDi(mhmCkJc;eM-ImyzW$x>cP$Mz4ONYt#^NJz zM0w=t_X*$k9t}F$c8q(h;Rn+nb{%IOFKR-X@|s4QQ=0o*Vq3aT%s$c9>fU<%N829{ zoHRUHc}nwC$!Xf@g42^{^3RN&m7RTlF8SPG+oHC6=VQ*_Y7cMkx)5~X(nbG^=R3SR z&Rp`ibn>#>OB6F(@)2{oV%K?xm;_x?s~noduI3P8=g1L-SoYA z@fQEq)t)&$-M#aAZ}-Lb_1_lVesU-M&da;mcPH+xyidGe^g!)F*+boj)jwPQ+}Q8j ze`>&Yp!3n(NB0JWgU|kv^^Xrj1&^7J%Z3ex>z+71IXU7#a{cN2r$f(V&nBK1{-XZN zt``^}my^G3e5L*B!0Q>W+s4Ai9=^$VGcjKDR{QP2cieX!@1x%j zPvm?ce<=TG`LXp=(5L&88IzO$1Ou4!{O>iCf&c&je@R3^RA}Dq*P#u7Fc3!JgP<9J z1rW#|gY3erfW&Z;eK0K0OQ9jWFR5$Od!nLd00030)#M(KbUZnbyU#iMyWl;WneByV zU(77!9*PE>?!K0sUQ!EX>4Tx0C?J+Q)g6D=@vcr-tj1^HV42lZa2jn55j)S9!ipu-pd!uXCy!YnK{> z2n?1;Gf_2w45>mM5#WQz#Kz&|EGkvK~TfD`~gdX7S-06<0ofSs5oQvjd@0AR~wV&ec% zEdXFAf9BHwfSvf6djSAjlpz%XppgI|6J>}*0BAb^tj|`8MF3bZ02F3R#5n-iEdVe{ zS7t~6u(trf&JYW-00;~KFj0twDF6g}0AR=?BX|IWnE(_<@>e|ZE3OddDgXd@nX){& zBsoQaTL>+22Uk}v9w^R97b_GtVFF>AKrX_0nHe&HG!NkO%m4tOkrff(gY*4(&JM25 z&Nhy=4qq+mzXtyzVq)X|<DpKGaQJ>aJVl|9x!Kv}EM4F8AGNmGkLXs)P zCDQ+7;@>R$13uq10I+I40eg`xs9j?N_Dd%aSaiVR_W%I$yKlkNCzL=651DUOSSq$Ed=-((3YAKgCY2j1FI1_jrmEhm z3sv(~%T$l4UQ>OpMpZLYTc&xiMv2YpRx)mRPGut5K^*>%BIv?Wdil zy+ylO`+*KY$4Vz$Cr4+G&IO(4Q`uA9rwXSQO+7mGt}d!;r5mBUM0dY#r|y`ZzFvTy zOmC;&dA;ZQ9DOhSRQ+xGr}ak+SO&8UBnI0I&KNw!HF0k|9WTe*@liuv!$3o&VU=N* z;e?U7(LAHoMvX=fjA_PP<0Rv4#%;!P6gpNq-kQ#w?mvCS^p@!_XIRe=&)75LwiC-K#A%&Vo6|>U7iYP1 zgY$@siA#dZE|)$on;XX6$i3uBboFsv;d;{botv|p!tJQrukJSPY3_&IpUgC$DV|v~ zbI`-cL*P;6(LW2Hl`w1HtbR{JPl0E(=OZs;FOgTR*RZ#xcdGYc?-xGyK60PqKI1$$ z-ZI`wBrnsy*W_HW0Wrec-#cqqYFCLW#$!oKa ztOZ#u3bsO~=u}!L*D43HXJuDrzs-rtIhL!QE6wf9v&!3$H=OUE|LqdO65*1zrG`sa zEge|qy{u|EvOIBl+X~|q1uKSD2CO`|inc0k)laMKSC_7Sy(W51Yk^+D%7VeQ0c-0E zRSM;Wee2xU?Ojh;FInHUVfu!h8$K0@imnvf7nc=(*eKk1(e4|2y!JHg)!SRV_x(P}zS~s+RZZ1q)n)rh`?L2yu8FGY z_?G)^U9C=SaqY(g(gXbmBM!FLxzyDi(mhmCkJc;eM-ImyzW$x>cP$Mz4ONYt#^NJz zM0w=t_X*$k9t}F$c8q(h;Rn+nb{%IOFKR-X@|s4QQ=0o*Vq3aT%s$c9>fU<%N829{ zoHRUHc}nwC$!Xf@g42^{^3RN&m7RTlF8SPG+oHC6=VQ*_Y7cMkx)5~X(nbG^=R3SR z&Rp`ibn>#>OB6F(@)2{oV%K?xm;_x?s~noduI3P8=g1L-SoYA z@fQEq)t)&$-M#aAZ}-Lb_1_lVesU-M&da;mcPH+xyidGe^g!)F*+boj)jwPQ+}Q8j ze`>&Yp!3n(NB0JWgU|kv^^Xrj1&^7J%Z3ex>z+71IXU7#a{cN2r$f(V&nBK1{-XZN zt``^}my^G3e5L*B!0Q>W+s4Ai9=^$VGcjKDR{QP2cieX!@1x%j zPvm?ce<=TG`LXp=(5L&88IzO$1Ou4!{O>iCf&c&jib+I4RA}Dq*Rc)4Fc5{|M-)+{ zh@e4Yj<-ZcW{F!O4MnQ-DQFk~pDsa&|C8L=^8JMiO8@`>|LfGU*>*2!+HsyOA|5RV z`s786q-XK)cS+aQL)m~eBIe5JZ4a4%?$_S{0R#|0009ILKmY**5I_I{-;(_k-)x_Y mXSp01Fuqr{O#lD@_}B|cpbh^^%V#hE0000EX>4Tx0C?J+Q)g6D=@vcr-tj1^HV42lZa2jn55j)S9!ipu-pd!uXCy!YnK{> z2n?1;Gf_2w45>mM5#WQz#Kz&|EGkvK~TfD`~gdX7S-06<0ofSs5oQvjd@0AR~wV&ec% zEdXFAf9BHwfSvf6djSAjlpz%XppgI|6J>}*0BAb^tj|`8MF3bZ02F3R#5n-iEdVe{ zS7t~6u(trf&JYW-00;~KFj0twDF6g}0AR=?BX|IWnE(_<@>e|ZE3OddDgXd@nX){& zBsoQaTL>+22Uk}v9w^R97b_GtVFF>AKrX_0nHe&HG!NkO%m4tOkrff(gY*4(&JM25 z&Nhy=4qq+mzXtyzVq)X|<DpKGaQJ>aJVl|9x!Kv}EM4F8AGNmGkLXs)P zCDQ+7;@>R$13uq10I+I40eg`xs9j?N_Dd%aSaiVR_W%I$yKlkNCzL=651DUOSSq$Ed=-((3YAKgCY2j1FI1_jrmEhm z3sv(~%T$l4UQ>OpMpZLYTc&xiMv2YpRx)mRPGut5K^*>%BIv?Wdil zy+ylO`+*KY$4Vz$Cr4+G&IO(4Q`uA9rwXSQO+7mGt}d!;r5mBUM0dY#r|y`ZzFvTy zOmC;&dA;ZQ9DOhSRQ+xGr}ak+SO&8UBnI0I&KNw!HF0k|9WTe*@liuv!$3o&VU=N* z;e?U7(LAHoMvX=fjA_PP<0Rv4#%;!P6gpNq-kQ#w?mvCS^p@!_XIRe=&)75LwiC-K#A%&Vo6|>U7iYP1 zgY$@siA#dZE|)$on;XX6$i3uBboFsv;d;{botv|p!tJQrukJSPY3_&IpUgC$DV|v~ zbI`-cL*P;6(LW2Hl`w1HtbR{JPl0E(=OZs;FOgTR*RZ#xcdGYc?-xGyK60PqKI1$$ z-ZI`wBrnsy*W_HW0Wrec-#cqqYFCLW#$!oKa ztOZ#u3bsO~=u}!L*D43HXJuDrzs-rtIhL!QE6wf9v&!3$H=OUE|LqdO65*1zrG`sa zEge|qy{u|EvOIBl+X~|q1uKSD2CO`|inc0k)laMKSC_7Sy(W51Yk^+D%7VeQ0c-0E zRSM;Wee2xU?Ojh;FInHUVfu!h8$K0@imnvf7nc=(*eKk1(e4|2y!JHg)!SRV_x(P}zS~s+RZZ1q)n)rh`?L2yu8FGY z_?G)^U9C=SaqY(g(gXbmBM!FLxzyDi(mhmCkJc;eM-ImyzW$x>cP$Mz4ONYt#^NJz zM0w=t_X*$k9t}F$c8q(h;Rn+nb{%IOFKR-X@|s4QQ=0o*Vq3aT%s$c9>fU<%N829{ zoHRUHc}nwC$!Xf@g42^{^3RN&m7RTlF8SPG+oHC6=VQ*_Y7cMkx)5~X(nbG^=R3SR z&Rp`ibn>#>OB6F(@)2{oV%K?xm;_x?s~noduI3P8=g1L-SoYA z@fQEq)t)&$-M#aAZ}-Lb_1_lVesU-M&da;mcPH+xyidGe^g!)F*+boj)jwPQ+}Q8j ze`>&Yp!3n(NB0JWgU|kv^^Xrj1&^7J%Z3ex>z+71IXU7#a{cN2r$f(V&nBK1{-XZN zt``^}my^G3e5L*B!0Q>W+s4Ai9=^$VGcjKDR{QP2cieX!@1x%j zPvm?ce<=TG`LXp=(5L&88IzO$1Ou4!{O>iCf&c&k4oO5oRA}Dq+M#O#aTvz&@BKEE zfglJ&u!&`1m@bKBVaet{an(AkE)J~z2`g(R!-`R`7+e^Gh2b$cI1oe^X7K(2kGr`S zpQr!e`S9ZnFT5TAqgfpo0&Sqe|4sxEz{yx(HF%y%>M@f*3|~zw|AKW zt{1PV02*Qe1Q0*~0R#|0009ILKmY+!Ce=<{3g5Z-*<`-d{~4edhp86uJmN8${b~jT z5I_I{&Kj^Y+<)zWv0=c(0X+^EAl4EA501e91e(Azurg45m2_