From afdb503690b5e1efe2cd2b793187325b83147566 Mon Sep 17 00:00:00 2001 From: Jonathan Griffin Date: Tue, 8 Nov 2011 13:45:42 -0800 Subject: [PATCH 1/9] Bug 697824 - buildUrl isn't a member of self, a=testonly, DONTBUILD --- testing/tps/tps/testrunner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/tps/tps/testrunner.py b/testing/tps/tps/testrunner.py index bf107b83d6d9..aaf3a134363e 100644 --- a/testing/tps/tps/testrunner.py +++ b/testing/tps/tps/testrunner.py @@ -440,7 +440,7 @@ class TPSTestRunner(object): self.numpassed, self.numfailed, self.config['account']['serverURL'], - self.buildUrl) + buildUrl) subj = "TPS Report: " if self.numfailed == 0 and self.numpassed > 0: From d5f8a2afade9fad62186a24e2bb883bb78511d99 Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Thu, 10 Nov 2011 15:33:56 -0800 Subject: [PATCH 2/9] Bug 604565 - Enable previously-disabled xpcshell tests on OS X; a=philikon It has been a while since these disabled tests have been tested in the build environment. We're enabling them to see if they have magically fixed themselves. If so, great. If not, this commit should be reverted before merging into m-c. --- services/sync/tests/unit/xpcshell.ini | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/services/sync/tests/unit/xpcshell.ini b/services/sync/tests/unit/xpcshell.ini index 30a5cd837512..f8cc583e624f 100644 --- a/services/sync/tests/unit/xpcshell.ini +++ b/services/sync/tests/unit/xpcshell.ini @@ -30,9 +30,8 @@ tail = # Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini) skip-if = os == "android" [test_errorhandler_sync_checkServerError.js] -# Bug 604565: this test intermittently hangs on OS X debug builds. # Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini) -skip-if = (os == "mac" && debug) || os == "android" +skip-if = os == "android" [test_forms_store.js] [test_forms_tracker.js] [test_history_engine.js] @@ -80,13 +79,11 @@ skip-if = os == "win" || os == "android" [test_service_sync_401.js] [test_service_sync_locked.js] [test_service_sync_remoteSetup.js] -# Bug 604565: this test intermittently hangs on OS X debug builds. # Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini) -skip-if = (os == "mac" && debug) || os == "android" +skip-if = os == "android" [test_service_sync_updateEnabledEngines.js] -# Bug 604565: this test intermittently hangs on OS X debug builds. # Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini) -skip-if = (os == "mac" && debug) || os == "android" +skip-if = os == "android" [test_service_verifyLogin.js] [test_service_wipeClient.js] [test_service_wipeServer.js] @@ -94,9 +91,8 @@ skip-if = (os == "mac" && debug) || os == "android" [test_status_checkSetup.js] [test_syncengine.js] [test_syncengine_sync.js] -# Bug 604565: this test intermittently hangs on OS X debug builds. # Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini) -skip-if = (os == "mac" && debug) || os == "android" +skip-if = os == "android" [test_syncscheduler.js] [test_syncstoragerequest.js] [test_tab_engine.js] From 8908975f0166fac1c636b6f13cde7cfb9c668757 Mon Sep 17 00:00:00 2001 From: Jonathan Griffin Date: Fri, 11 Nov 2011 11:16:11 -0800 Subject: [PATCH 3/9] Bug 697874 - disable perma-orange TPS test, r=rnewman, DONTBUILD --- services/sync/tests/tps/all_tests.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/services/sync/tests/tps/all_tests.json b/services/sync/tests/tps/all_tests.json index 9e0178bed882..43f4bedea210 100644 --- a/services/sync/tests/tps/all_tests.json +++ b/services/sync/tests/tps/all_tests.json @@ -21,8 +21,7 @@ "test_privbrw_tabs.js", "test_bookmarks_in_same_named_folder.js", "test_client_wipe.js", - "test_special_tabs.js", - "test_mozmill_sanity.js" + "test_special_tabs.js" ] } From b68bf1210ec4f23f21cad884cee742b2989b0f61 Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Mon, 14 Nov 2011 19:12:14 -0800 Subject: [PATCH 4/9] Bug 701996 - Merge widget/src/android from birch back into mozilla-central. r=dougt/blassey --- embedding/android/GeckoAppShell.java | 19 +++ embedding/android/GeckoEvent.java | 10 +- widget/src/android/AndroidBridge.cpp | 92 ++++++++++- widget/src/android/AndroidBridge.h | 39 +++++ widget/src/android/AndroidJNI.cpp | 21 +++ widget/src/android/AndroidJavaWrappers.cpp | 126 +++++++++++++-- widget/src/android/AndroidJavaWrappers.h | 37 ++++- widget/src/android/Makefile.in | 7 + widget/src/android/nsAppShell.cpp | 18 +++ widget/src/android/nsIAndroidBridge.idl | 7 + widget/src/android/nsWidgetFactory.cpp | 5 + widget/src/android/nsWindow.cpp | 169 ++++++++++++++++++++- widget/src/android/nsWindow.h | 27 ++++ 13 files changed, 543 insertions(+), 34 deletions(-) create mode 100644 widget/src/android/nsIAndroidBridge.idl diff --git a/embedding/android/GeckoAppShell.java b/embedding/android/GeckoAppShell.java index 18a40916e6a9..053d4f16dfc9 100644 --- a/embedding/android/GeckoAppShell.java +++ b/embedding/android/GeckoAppShell.java @@ -62,6 +62,8 @@ import android.webkit.MimeTypeMap; import android.media.MediaScannerConnection; import android.media.MediaScannerConnection.MediaScannerConnectionClient; import android.provider.Settings; +import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.AccessibilityEvent; import android.util.*; import android.net.Uri; @@ -1359,6 +1361,13 @@ public class GeckoAppShell return true; } } + + public static boolean getAccessibilityEnabled() { + AccessibilityManager accessibilityManager = + (AccessibilityManager) GeckoApp.mAppContext.getSystemService(Context.ACCESSIBILITY_SERVICE); + return accessibilityManager.isEnabled(); + } + public static void addPluginView(final View view, final double x, final double y, final double w, final double h) { @@ -1620,6 +1629,16 @@ public class GeckoAppShell } } + // unused + public static String handleGeckoMessage(String message) { + return ""; + } + // unused + static void checkUriVisited(String uri) {} + // unused + static void markUriVisited(final String uri) {} + + public static void enableBatteryNotifications() { GeckoBatteryManager.enableNotifications(); } diff --git a/embedding/android/GeckoEvent.java b/embedding/android/GeckoEvent.java index 7985f2a02526..c164f019e9f7 100644 --- a/embedding/android/GeckoEvent.java +++ b/embedding/android/GeckoEvent.java @@ -73,6 +73,8 @@ public class GeckoEvent { public static final int SURFACE_DESTROYED = 14; public static final int GECKO_EVENT_SYNC = 15; public static final int ACTIVITY_START = 17; + public static final int SAVE_STATE = 18; + public static final int BROADCAST = 19; public static final int IME_COMPOSITION_END = 0; public static final int IME_COMPOSITION_BEGIN = 1; @@ -104,7 +106,7 @@ public class GeckoEvent { public int mMetaState, mFlags; public int mKeyCode, mUnicodeChar; public int mOffset, mCount; - public String mCharacters; + public String mCharacters, mCharactersExtra; public int mRangeType, mRangeStyles; public int mRangeForeColor, mRangeBackColor; public Location mLocation; @@ -223,6 +225,12 @@ public class GeckoEvent { mP1 = new Point(screenw, screenh); } + public GeckoEvent(String subject, String data) { + mType = BROADCAST; + mCharacters = subject; + mCharactersExtra = data; + } + public GeckoEvent(String uri) { mType = LOAD_URI; mCharacters = uri; diff --git a/widget/src/android/AndroidBridge.cpp b/widget/src/android/AndroidBridge.cpp index 48d3cf7da43b..7acc2b50be56 100644 --- a/widget/src/android/AndroidBridge.cpp +++ b/widget/src/android/AndroidBridge.cpp @@ -161,6 +161,11 @@ AndroidBridge::Init(JNIEnv *jEnv, jDisableBatteryNotifications = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "disableBatteryNotifications", "()V"); jGetCurrentBatteryInformation = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getCurrentBatteryInformation", "()[D"); + jGetAccessibilityEnabled = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getAccessibilityEnabled", "()Z"); + jHandleGeckoMessage = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "handleGeckoMessage", "(Ljava/lang/String;)Ljava/lang/String;"); + jCheckUriVisited = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "checkUriVisited", "(Ljava/lang/String;)V"); + jMarkUriVisited = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "markUriVisited", "(Ljava/lang/String;)V"); + jEGLContextClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGLContext")); jEGL10Class = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGL10")); jEGLSurfaceImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLSurfaceImpl")); @@ -670,6 +675,13 @@ AndroidBridge::HideProgressDialogOnce() } } +bool +AndroidBridge::GetAccessibilityEnabled() +{ + ALOG_BRIDGE("AndroidBridge::GetAccessibilityEnabled"); + return mJNIEnv->CallStaticBooleanMethod(mGeckoAppShellClass, jGetAccessibilityEnabled); +} + void AndroidBridge::PerformHapticFeedback(bool aIsLongPress) { @@ -839,6 +851,12 @@ AndroidBridge::SetSurfaceView(jobject obj) mSurfaceView.Init(obj); } +void +AndroidBridge::SetSoftwareLayerClient(jobject obj) +{ + mSoftwareLayerClient.Init(obj); +} + void AndroidBridge::ShowInputMethodPicker() { @@ -1002,10 +1020,8 @@ AndroidBridge::CreateShortcut(const nsAString& aTitle, const nsAString& aURI, co void AndroidBridge::PostToJavaThread(nsIRunnable* aRunnable, bool aMainThread) { - __android_log_print(ANDROID_LOG_INFO, "GeckoBridge", "%s", __PRETTY_FUNCTION__); JNIEnv* env = AndroidBridge::AttachThread(false); if (!env) { - __android_log_print(ANDROID_LOG_INFO, "GeckoBridge", "no jni env in %s!!", __PRETTY_FUNCTION__); return; } mRunnableQueue.AppendObject(aRunnable); @@ -1016,27 +1032,21 @@ AndroidBridge::PostToJavaThread(nsIRunnable* aRunnable, bool aMainThread) env->ExceptionDescribe(); env->ExceptionClear(); } - __android_log_print(ANDROID_LOG_INFO, "GeckoBridge", "leaving %s", __PRETTY_FUNCTION__); } void AndroidBridge::ExecuteNextRunnable() { - __android_log_print(ANDROID_LOG_INFO, "GeckoBridge", "%s", __PRETTY_FUNCTION__); - JNIEnv* env = AndroidBridge::AttachThread(false); if (!env) { - __android_log_print(ANDROID_LOG_INFO, "GeckoBridge", "no jni env in %s!!", __PRETTY_FUNCTION__); return; } if (mRunnableQueue.Count() > 0) { nsIRunnable* r = mRunnableQueue[0]; - __android_log_print(ANDROID_LOG_INFO, "GeckoBridge", "going to run %p", r); r->Run(); mRunnableQueue.RemoveObjectAt(0); } - __android_log_print(ANDROID_LOG_INFO, "GeckoBridge", "leaving %s", __PRETTY_FUNCTION__); } void @@ -1269,6 +1279,54 @@ AndroidBridge::GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInf mJNIEnv->ReleaseDoubleArrayElements(arr, info, 0); } +void +AndroidBridge::HandleGeckoMessage(const nsAString &aMessage, nsAString &aRet) +{ + ALOG_BRIDGE("%s", __PRETTY_FUNCTION__); + JNIEnv* env = AndroidBridge::AttachThread(false); + if (!env) { + ALOG_BRIDGE("no jni env in %s!!", __PRETTY_FUNCTION__); + return; + } + + AutoLocalJNIFrame jniFrame(1); + jstring jMessage = mJNIEnv->NewString(nsPromiseFlatString(aMessage).get(), aMessage.Length()); + jstring returnMessage = static_cast(env->CallStaticObjectMethod(mGeckoAppShellClass, jHandleGeckoMessage, jMessage)); + + jthrowable ex = env->ExceptionOccurred(); + if (ex) { + env->ExceptionDescribe(); + env->ExceptionClear(); + } + nsJNIString jniStr(returnMessage); + aRet.Assign(jniStr); + ALOG_BRIDGE("leaving %s", __PRETTY_FUNCTION__); +} + +void +AndroidBridge::CheckURIVisited(const nsAString& aURI) +{ + AutoLocalJNIFrame jniFrame(1); + jstring jstrURI = mJNIEnv->NewString(nsPromiseFlatString(aURI).get(), aURI.Length()); + mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jCheckUriVisited, jstrURI); +} + +void +AndroidBridge::MarkURIVisited(const nsAString& aURI) +{ + AutoLocalJNIFrame jniFrame(1); + jstring jstrURI = mJNIEnv->NewString(nsPromiseFlatString(aURI).get(), aURI.Length()); + mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jMarkUriVisited, jstrURI); +} + +void AndroidBridge::EmitGeckoAccessibilityEvent (PRInt32 eventType, const nsAString& role, const nsAString& text, const nsAString& description, bool enabled, bool checked, bool password) { + AutoLocalJNIFrame jniFrame; + jstring jstrRole = mJNIEnv->NewString(nsPromiseFlatString(role).get(), role.Length()); + jstring jstrText = mJNIEnv->NewString(nsPromiseFlatString(text).get(), text.Length()); + jstring jstrDescription = mJNIEnv->NewString(nsPromiseFlatString(description).get(), description.Length()); + mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jEmitGeckoAccessibilityEvent, eventType, jstrRole, jstrText, jstrDescription, enabled, checked, password); +} + void * AndroidBridge::LockBitmap(jobject bitmap) { @@ -1379,3 +1437,21 @@ AndroidBridge::UnlockWindow(void* window) return true; } + +/* Implementation file */ +NS_IMPL_ISUPPORTS1(nsAndroidBridge, nsIAndroidBridge) + +nsAndroidBridge::nsAndroidBridge() +{ +} + +nsAndroidBridge::~nsAndroidBridge() +{ +} + +/* void handleGeckoEvent (in AString message); */ +NS_IMETHODIMP nsAndroidBridge::HandleGeckoMessage(const nsAString & message, nsAString &aRet NS_OUTPARAM) +{ + AndroidBridge::Bridge()->HandleGeckoMessage(message, aRet); + return NS_OK; +} diff --git a/widget/src/android/AndroidBridge.h b/widget/src/android/AndroidBridge.h index f9ddb4605f4d..1f3ef976223d 100644 --- a/widget/src/android/AndroidBridge.h +++ b/widget/src/android/AndroidBridge.h @@ -40,6 +40,7 @@ #include #include +#include #include "nsCOMPtr.h" #include "nsCOMArray.h" @@ -52,6 +53,8 @@ #include "nsIMIMEInfo.h" #include "nsColor.h" +#include "nsIAndroidBridge.h" + // Some debug #defines // #define DEBUG_ANDROID_EVENTS // #define DEBUG_ANDROID_WIDGET @@ -147,6 +150,9 @@ public: void ScheduleRestart(); + void SetSoftwareLayerClient(jobject jobj); + AndroidGeckoSoftwareLayerClient &GetSoftwareLayerClient() { return mSoftwareLayerClient; } + void SetSurfaceView(jobject jobj); AndroidGeckoSurfaceView& SurfaceView() { return mSurfaceView; } @@ -222,6 +228,8 @@ public: void FireAndWaitForTracerEvent(); + bool GetAccessibilityEnabled(); + struct AutoLocalJNIFrame { AutoLocalJNIFrame(int nEntries = 128) : mEntries(nEntries) { // Make sure there is enough space to store a local ref to the @@ -289,6 +297,13 @@ public: bool LockWindow(void *window, unsigned char **bits, int *width, int *height, int *format, int *stride); bool UnlockWindow(void *window); + + void HandleGeckoMessage(const nsAString& message, nsAString &aRet); + + void EmitGeckoAccessibilityEvent (PRInt32 eventType, const nsAString& role, const nsAString& text, const nsAString& description, bool enabled, bool checked, bool password); + + void CheckURIVisited(const nsAString& uri); + void MarkURIVisited(const nsAString& uri); bool InitCamera(const nsCString& contentType, PRUint32 camera, PRUint32 *width, PRUint32 *height, PRUint32 *fps); @@ -310,6 +325,7 @@ protected: // the GeckoSurfaceView AndroidGeckoSurfaceView mSurfaceView; + AndroidGeckoSoftwareLayerClient mSoftwareLayerClient; // the GeckoAppShell java class jclass mGeckoAppShellClass; @@ -375,6 +391,11 @@ protected: jmethodID jEnableBatteryNotifications; jmethodID jDisableBatteryNotifications; jmethodID jGetCurrentBatteryInformation; + jmethodID jGetAccessibilityEnabled; + jmethodID jHandleGeckoMessage; + jmethodID jCheckUriVisited; + jmethodID jMarkUriVisited; + jmethodID jEmitGeckoAccessibilityEvent; // stuff we need for CallEglCreateWindowSurface jclass jEGLSurfaceImplClass; @@ -399,6 +420,24 @@ protected: } +#define NS_ANDROIDBRIDGE_CID \ +{ 0x0FE2321D, 0xEBD9, 0x467D, \ + { 0xA7, 0x43, 0x03, 0xA6, 0x8D, 0x40, 0x59, 0x9E } } + +class nsAndroidBridge : public nsIAndroidBridge +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIANDROIDBRIDGE + + nsAndroidBridge(); + +private: + ~nsAndroidBridge(); + +protected: +}; + extern "C" JNIEnv * GetJNIForThread(); extern bool mozilla_AndroidBridge_SetMainThread(void *); extern jclass GetGeckoAppShellClass(); diff --git a/widget/src/android/AndroidJNI.cpp b/widget/src/android/AndroidJNI.cpp index af7f11662c30..476116a41202 100644 --- a/widget/src/android/AndroidJNI.cpp +++ b/widget/src/android/AndroidJNI.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include "nsAppShell.h" #include "nsWindow.h" @@ -52,6 +53,10 @@ #include "mozilla/Services.h" #include "nsINetworkLinkService.h" +#ifdef MOZ_ANDROID_HISTORY +#include "nsAndroidHistory.h" +#endif + #ifdef MOZ_CRASHREPORTER #include "nsICrashReporter.h" #include "nsExceptionHandler.h" @@ -66,6 +71,7 @@ extern "C" { NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_nativeInit(JNIEnv *, jclass); NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoOfEvent(JNIEnv *, jclass, jobject event); NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_processNextNativeEvent(JNIEnv *, jclass); + NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_setSoftwareLayerClient(JNIEnv *jenv, jclass, jobject sv); NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_setSurfaceView(JNIEnv *jenv, jclass, jobject sv); NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_onResume(JNIEnv *, jclass); NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_onLowMemory(JNIEnv *, jclass); @@ -74,6 +80,7 @@ extern "C" { NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_onChangeNetworkLinkStatus(JNIEnv *, jclass, jstring status); NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_reportJavaCrash(JNIEnv *, jclass, jstring stack); NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_executeNextRunnable(JNIEnv *, jclass); + NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyUriVisited(JNIEnv *, jclass, jstring uri); NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyBatteryChange(JNIEnv* jenv, jclass, jdouble, jboolean, jdouble); } @@ -110,6 +117,12 @@ Java_org_mozilla_gecko_GeckoAppShell_setSurfaceView(JNIEnv *jenv, jclass, jobjec AndroidBridge::Bridge()->SetSurfaceView(jenv->NewGlobalRef(obj)); } +NS_EXPORT void JNICALL +Java_org_mozilla_gecko_GeckoAppShell_setSoftwareLayerClient(JNIEnv *jenv, jclass, jobject obj) +{ + AndroidBridge::Bridge()->SetSoftwareLayerClient(jenv->NewGlobalRef(obj)); +} + NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_onLowMemory(JNIEnv *jenv, jclass jc) { @@ -189,6 +202,14 @@ Java_org_mozilla_gecko_GeckoAppShell_executeNextRunnable(JNIEnv *, jclass) __android_log_print(ANDROID_LOG_INFO, "GeckoJNI", "leaving %s", __PRETTY_FUNCTION__); } +NS_EXPORT void JNICALL +Java_org_mozilla_gecko_GeckoAppShell_notifyUriVisited(JNIEnv *jenv, jclass, jstring uri) +{ +#ifdef MOZ_ANDROID_HISTORY + nsAndroidHistory::NotifyURIVisited(nsJNIString(uri, jenv)); +#endif +} + NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyBatteryChange(JNIEnv* jenv, jclass, jdouble aLevel, diff --git a/widget/src/android/AndroidJavaWrappers.cpp b/widget/src/android/AndroidJavaWrappers.cpp index 5c693c8db0a0..7beacbd9bc6d 100644 --- a/widget/src/android/AndroidJavaWrappers.cpp +++ b/widget/src/android/AndroidJavaWrappers.cpp @@ -56,6 +56,7 @@ jfieldID AndroidGeckoEvent::jRectField = 0; jfieldID AndroidGeckoEvent::jNativeWindowField = 0; jfieldID AndroidGeckoEvent::jCharactersField = 0; +jfieldID AndroidGeckoEvent::jCharactersExtraField = 0; jfieldID AndroidGeckoEvent::jKeyCodeField = 0; jfieldID AndroidGeckoEvent::jMetaStateField = 0; jfieldID AndroidGeckoEvent::jFlagsField = 0; @@ -102,6 +103,11 @@ jmethodID AndroidAddress::jGetSubLocalityMethod; jmethodID AndroidAddress::jGetSubThoroughfareMethod; jmethodID AndroidAddress::jGetThoroughfareMethod; +jclass AndroidGeckoSoftwareLayerClient::jGeckoSoftwareLayerClientClass = 0; +jmethodID AndroidGeckoSoftwareLayerClient::jLockBufferMethod = 0; +jmethodID AndroidGeckoSoftwareLayerClient::jUnlockBufferMethod = 0; +jmethodID AndroidGeckoSoftwareLayerClient::jBeginDrawingMethod = 0; +jmethodID AndroidGeckoSoftwareLayerClient::jEndDrawingMethod = 0; jclass AndroidGeckoSurfaceView::jGeckoSurfaceViewClass = 0; jmethodID AndroidGeckoSurfaceView::jBeginDrawingMethod = 0; jmethodID AndroidGeckoSurfaceView::jEndDrawingMethod = 0; @@ -134,6 +140,9 @@ mozilla::InitAndroidJavaWrappers(JNIEnv *jEnv) AndroidPoint::InitPointClass(jEnv); AndroidLocation::InitLocationClass(jEnv); AndroidAddress::InitAddressClass(jEnv); + AndroidRect::InitRectClass(jEnv); + + AndroidGeckoSoftwareLayerClient::InitGeckoSoftwareLayerClientClass(jEnv); } void @@ -157,6 +166,7 @@ AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv) jRectField = getField("mRect", "Landroid/graphics/Rect;"); jCharactersField = getField("mCharacters", "Ljava/lang/String;"); + jCharactersExtraField = getField("mCharactersExtra", "Ljava/lang/String;"); jKeyCodeField = getField("mKeyCode", "I"); jMetaStateField = getField("mMetaState", "I"); jFlagsField = getField("mFlags", "I"); @@ -302,6 +312,22 @@ AndroidRect::InitRectClass(JNIEnv *jEnv) jRightField = getField("right", "I"); } +void +AndroidGeckoSoftwareLayerClient::InitGeckoSoftwareLayerClientClass(JNIEnv *jEnv) +{ +#ifdef MOZ_JAVA_COMPOSITOR + initInit(); + + jGeckoSoftwareLayerClientClass = + getClassGlobalRef("org/mozilla/gecko/gfx/GeckoSoftwareLayerClient"); + + jLockBufferMethod = getMethod("lockBuffer", "()Ljava/nio/ByteBuffer;"); + jUnlockBufferMethod = getMethod("unlockBuffer", "()V"); + jBeginDrawingMethod = getMethod("beginDrawing", "()V"); + jEndDrawingMethod = getMethod("endDrawing", "(IIII)V"); +#endif +} + #undef initInit #undef initClassGlobalRef #undef getField @@ -351,6 +377,27 @@ AndroidGeckoEvent::ReadCharactersField(JNIEnv *jenv) jenv->GetStringRegion(s, 0, len, mCharacters.BeginWriting()); } +void +AndroidGeckoEvent::ReadCharactersExtraField(JNIEnv *jenv) +{ + jstring s = (jstring) jenv->GetObjectField(wrapped_obj, jCharactersExtraField); + if (!s) { + mCharactersExtra.SetIsVoid(PR_TRUE); + return; + } + + int len = jenv->GetStringLength(s); + mCharactersExtra.SetLength(len); + jenv->GetStringRegion(s, 0, len, mCharactersExtra.BeginWriting()); +} + +void +AndroidGeckoEvent::Init(int aType, nsIntRect const& aRect) +{ + mType = aType; + mRect = aRect; +} + void AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj) { @@ -437,6 +484,17 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj) break; } + case BROADCAST: { + ReadCharactersField(jenv); + ReadCharactersExtraField(jenv); + break; + } + + case SAVE_STATE: { + ReadCharactersField(jenv); + break; + } + default: break; } @@ -472,6 +530,25 @@ AndroidGeckoEvent::Init(AndroidGeckoEvent *aResizeEvent) mP1.y = aResizeEvent->mP1.y; } +void +AndroidPoint::Init(JNIEnv *jenv, jobject jobj) +{ + if (jobj) { + mX = jenv->GetIntField(jobj, jXField); + mY = jenv->GetIntField(jobj, jYField); + } else { + mX = 0; + mY = 0; + } +} + +void +AndroidGeckoSoftwareLayerClient::Init(jobject jobj) +{ + NS_ASSERTION(wrapped_obj == nsnull, "Init called on non-null wrapped_obj!"); + wrapped_obj = jobj; +} + void AndroidGeckoSurfaceView::Init(jobject jobj) { @@ -506,6 +583,39 @@ AndroidGeckoSurfaceView::Draw2D(jobject buffer, int stride) JNI()->CallVoidMethod(wrapped_obj, jDraw2DBufferMethod, buffer, stride); } +jobject +AndroidGeckoSoftwareLayerClient::LockBuffer() +{ + NS_ASSERTION(!isNull(), "LockBuffer() called on null software layer client!"); + AndroidBridge::AutoLocalJNIFrame(1); + return JNI()->CallObjectMethod(wrapped_obj, jLockBufferMethod); +} + +void +AndroidGeckoSoftwareLayerClient::UnlockBuffer() +{ + NS_ASSERTION(!isNull(), "UnlockBuffer() called on null software layer client!"); + AndroidBridge::AutoLocalJNIFrame(1); + JNI()->CallVoidMethod(wrapped_obj, jUnlockBufferMethod); +} + +void +AndroidGeckoSoftwareLayerClient::BeginDrawing() +{ + NS_ASSERTION(!isNull(), "BeginDrawing() called on null software layer client!"); + AndroidBridge::AutoLocalJNIFrame(1); + return JNI()->CallVoidMethod(wrapped_obj, jBeginDrawingMethod); +} + +void +AndroidGeckoSoftwareLayerClient::EndDrawing(const nsIntRect &aRect) +{ + NS_ASSERTION(!isNull(), "EndDrawing() called on null software layer client!"); + AndroidBridge::AutoLocalJNIFrame(1); + return JNI()->CallVoidMethod(wrapped_obj, jEndDrawingMethod, aRect.x, aRect.y, aRect.width, + aRect.height); +} + jobject AndroidGeckoSurfaceView::GetSoftwareDrawBitmap() { @@ -530,22 +640,6 @@ AndroidGeckoSurfaceView::GetSurfaceHolder() return JNI()->CallObjectMethod(wrapped_obj, jGetHolderMethod); } -void -AndroidPoint::Init(JNIEnv *jenv, jobject jobj) -{ - NS_ASSERTION(wrapped_obj == nsnull, "Init called on non-null wrapped_obj!"); - - wrapped_obj = jobj; - - if (jobj) { - mX = jenv->GetIntField(jobj, jXField); - mY = jenv->GetIntField(jobj, jYField); - } else { - mX = 0; - mY = 0; - } -} - void AndroidRect::Init(JNIEnv *jenv, jobject jobj) { diff --git a/widget/src/android/AndroidJavaWrappers.h b/widget/src/android/AndroidJavaWrappers.h index 423335227f9b..3a61132ffa9b 100644 --- a/widget/src/android/AndroidJavaWrappers.h +++ b/widget/src/android/AndroidJavaWrappers.h @@ -149,6 +149,32 @@ protected: static jfieldID jTopField; }; +class AndroidGeckoSoftwareLayerClient : public WrappedJavaObject { +public: + static void InitGeckoSoftwareLayerClientClass(JNIEnv *jEnv); + + void Init(jobject jobj); + + AndroidGeckoSoftwareLayerClient() {} + AndroidGeckoSoftwareLayerClient(jobject jobj) { Init(jobj); } + + jobject LockBuffer(); + unsigned char *LockBufferBits(); + void UnlockBuffer(); + void BeginDrawing(); + void EndDrawing(const nsIntRect &aRect); + +private: + static jclass jGeckoSoftwareLayerClientClass; + static jmethodID jLockBufferMethod; + static jmethodID jUnlockBufferMethod; + +protected: + static jmethodID jBeginDrawingMethod; + static jmethodID jEndDrawingMethod; +}; + + class AndroidGeckoSurfaceView : public WrappedJavaObject { public: @@ -388,6 +414,9 @@ public: AndroidGeckoEvent(int x1, int y1, int x2, int y2) { Init(x1, y1, x2, y2); } + AndroidGeckoEvent(int aType, const nsIntRect &aRect) { + Init(aType, aRect); + } AndroidGeckoEvent(JNIEnv *jenv, jobject jobj) { Init(jenv, jobj); } @@ -398,6 +427,7 @@ public: void Init(JNIEnv *jenv, jobject jobj); void Init(int aType); void Init(int x1, int y1, int x2, int y2); + void Init(int aType, const nsIntRect &aRect); void Init(AndroidGeckoEvent *aResizeEvent); int Action() { return mAction; } @@ -413,6 +443,7 @@ public: double Z() { return mZ; } const nsIntRect& Rect() { return mRect; } nsAString& Characters() { return mCharacters; } + nsAString& CharactersExtra() { return mCharactersExtra; } int KeyCode() { return mKeyCode; } int MetaState() { return mMetaState; } int Flags() { return mFlags; } @@ -440,7 +471,7 @@ protected: int mRangeForeColor, mRangeBackColor; double mAlpha, mBeta, mGamma; double mX, mY, mZ; - nsString mCharacters; + nsString mCharacters, mCharactersExtra; nsRefPtr mGeoPosition; nsRefPtr mGeoAddress; @@ -448,6 +479,7 @@ protected: void ReadP1Field(JNIEnv *jenv); void ReadRectField(JNIEnv *jenv); void ReadCharactersField(JNIEnv *jenv); + void ReadCharactersExtraField(JNIEnv *jenv); static jclass jGeckoEventClass; static jfieldID jActionField; @@ -465,6 +497,7 @@ protected: static jfieldID jNativeWindowField; static jfieldID jCharactersField; + static jfieldID jCharactersExtraField; static jfieldID jKeyCodeField; static jfieldID jMetaStateField; static jfieldID jFlagsField; @@ -498,6 +531,8 @@ public: GECKO_EVENT_SYNC = 15, FORCED_RESIZE = 16, ACTIVITY_START = 17, + SAVE_STATE = 18, + BROADCAST = 19, dummy_java_enum_list_end }; diff --git a/widget/src/android/Makefile.in b/widget/src/android/Makefile.in index 5c89001c5fa9..e79727c34a19 100644 --- a/widget/src/android/Makefile.in +++ b/widget/src/android/Makefile.in @@ -44,6 +44,7 @@ include $(DEPTH)/config/autoconf.mk MODULE = widget LIBRARY_NAME = widget_android +XPIDL_MODULE = widget_android EXPORT_LIBRARY = 1 IS_COMPONENT = 1 MODULE_NAME = nsWidgetAndroidModule @@ -78,6 +79,10 @@ NOT_THERE_YET_CPPSRCS = \ nsSound.cpp \ $(NULL) +XPIDLSRCS = \ + nsIAndroidBridge.idl \ + $(NULL) + SHARED_LIBRARY_LIBS = ../xpwidgets/libxpwidgets_s.a EXPORTS = AndroidBridge.h AndroidJavaWrappers.h @@ -91,6 +96,8 @@ LOCAL_INCLUDES += \ -I$(topsrcdir)/widget/src/xpwidgets \ -I$(topsrcdir)/widget/src/shared \ -I$(topsrcdir)/dom/system/android \ + -I$(topsrcdir)/toolkit/components/places \ + -I$(topsrcdir)/docshell/base \ -I$(srcdir) \ $(NULL) diff --git a/widget/src/android/nsAppShell.cpp b/widget/src/android/nsAppShell.cpp index 0de3a1ce6912..9d50114cadca 100644 --- a/widget/src/android/nsAppShell.cpp +++ b/widget/src/android/nsAppShell.cpp @@ -368,12 +368,30 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait) break; } + case AndroidGeckoEvent::BROADCAST: { + + if (curEvent->Characters().Length() == 0) + break; + + nsCOMPtr obsServ = + mozilla::services::GetObserverService(); + + const NS_ConvertUTF16toUTF8 topic(curEvent->Characters()); + const nsPromiseFlatString& data = PromiseFlatString(curEvent->CharactersExtra()); + + obsServ->NotifyObservers(nsnull, topic.get(), data.get()); + break; + } + case AndroidGeckoEvent::LOAD_URI: { nsCOMPtr cmdline (do_CreateInstance("@mozilla.org/toolkit/command-line;1")); if (!cmdline) break; + if (curEvent->Characters().Length() == 0) + break; + char *uri = ToNewUTF8String(curEvent->Characters()); if (!uri) break; diff --git a/widget/src/android/nsIAndroidBridge.idl b/widget/src/android/nsIAndroidBridge.idl new file mode 100644 index 000000000000..433ef514a5f5 --- /dev/null +++ b/widget/src/android/nsIAndroidBridge.idl @@ -0,0 +1,7 @@ +#include "nsISupports.idl" + +[scriptable, uuid(32c345d4-9f45-446a-8a93-8939f3453e87)] +interface nsIAndroidBridge : nsISupports +{ + AString handleGeckoMessage(in AString message); +}; diff --git a/widget/src/android/nsWidgetFactory.cpp b/widget/src/android/nsWidgetFactory.cpp index 875fc9297bc7..e9f959313381 100644 --- a/widget/src/android/nsWidgetFactory.cpp +++ b/widget/src/android/nsWidgetFactory.cpp @@ -41,6 +41,7 @@ #include "nsCOMPtr.h" #include "nsWidgetsCID.h" #include "nsAppShell.h" +#include "AndroidBridge.h" #include "nsWindow.h" #include "nsLookAndFeel.h" @@ -71,6 +72,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintSession, Init) NS_GENERIC_FACTORY_CONSTRUCTOR(nsDeviceContextSpecAndroid) NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter) NS_GENERIC_FACTORY_CONSTRUCTOR(nsIMEPicker) +NS_GENERIC_FACTORY_CONSTRUCTOR(nsAndroidBridge) #include "GfxInfo.h" namespace mozilla { @@ -113,6 +115,7 @@ NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID); NS_DEFINE_NAMED_CID(NS_HTMLFORMATCONVERTER_CID); NS_DEFINE_NAMED_CID(NS_IMEPICKER_CID); NS_DEFINE_NAMED_CID(NS_GFXINFO_CID); +NS_DEFINE_NAMED_CID(NS_ANDROIDBRIDGE_CID); static const mozilla::Module::CIDEntry kWidgetCIDs[] = { { &kNS_WINDOW_CID, false, NULL, nsWindowConstructor }, @@ -130,6 +133,7 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = { { &kNS_HTMLFORMATCONVERTER_CID, false, NULL, nsHTMLFormatConverterConstructor }, { &kNS_IMEPICKER_CID, false, NULL, nsIMEPickerConstructor }, { &kNS_GFXINFO_CID, false, NULL, mozilla::widget::GfxInfoConstructor }, + { &kNS_ANDROIDBRIDGE_CID, false, NULL, nsAndroidBridgeConstructor }, { NULL } }; @@ -149,6 +153,7 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = { { "@mozilla.org/widget/htmlformatconverter;1", &kNS_HTMLFORMATCONVERTER_CID }, { "@mozilla.org/imepicker;1", &kNS_IMEPICKER_CID }, { "@mozilla.org/gfx/info;1", &kNS_GFXINFO_CID }, + { "@mozilla.org/android/bridge;1", &kNS_ANDROIDBRIDGE_CID }, { NULL } }; diff --git a/widget/src/android/nsWindow.cpp b/widget/src/android/nsWindow.cpp index 6cee48844fdf..28deb7b88e69 100644 --- a/widget/src/android/nsWindow.cpp +++ b/widget/src/android/nsWindow.cpp @@ -75,6 +75,14 @@ using mozilla::unused; #include "AndroidBridge.h" +#include "imgIEncoder.h" + +#include "nsStringGlue.h" + +// NB: Keep these in sync with LayerController.java in embedding/android/. +#define TILE_WIDTH 1024 +#define TILE_HEIGHT 2048 + using namespace mozilla; NS_IMPL_ISUPPORTS_INHERITED0(nsWindow, nsBaseWidget) @@ -83,6 +91,10 @@ NS_IMPL_ISUPPORTS_INHERITED0(nsWindow, nsBaseWidget) static gfxIntSize gAndroidBounds; static gfxIntSize gAndroidScreenBounds; +#ifdef ACCESSIBILITY +bool nsWindow::sAccessibilityEnabled = false; +#endif + class ContentCreationNotifier; static nsCOMPtr gContentCreationNotifier; // A helper class to send updates when content processes @@ -176,6 +188,9 @@ nsWindow::nsWindow() : mIsVisible(false), mParent(nsnull), mFocus(nsnull), +#ifdef ACCESSIBILITY + mRootAccessible(nsnull), +#endif mIMEComposing(false) { } @@ -186,6 +201,10 @@ nsWindow::~nsWindow() nsWindow *top = FindTopLevel(); if (top->mFocus == this) top->mFocus = nsnull; +#ifdef ACCESSIBILITY + if (mRootAccessible) + mRootAccessible = nsnull; +#endif ALOG("nsWindow %p destructor", (void*)this); } @@ -283,6 +302,15 @@ nsWindow::ConfigureChildren(const nsTArray& config) return NS_OK; } +void +nsWindow::RedrawAll() +{ + nsIntRect entireRect(0, 0, TILE_WIDTH, TILE_HEIGHT); + AndroidGeckoEvent *event = new AndroidGeckoEvent(AndroidGeckoEvent::DRAW, + entireRect); + nsAppShell::gAppShell->PostEvent(event); +} + NS_IMETHODIMP nsWindow::SetParent(nsIWidget *aNewParent) { @@ -303,7 +331,7 @@ nsWindow::SetParent(nsIWidget *aNewParent) // if we are now in the toplevel window's hierarchy, schedule a redraw if (FindTopLevel() == TopWindow()) - nsAppShell::gAppShell->PostEvent(new AndroidGeckoEvent(-1, -1, -1, -1)); + RedrawAll(); return NS_OK; } @@ -371,9 +399,20 @@ nsWindow::Show(bool aState) } } } else if (FindTopLevel() == TopWindow()) { - nsAppShell::gAppShell->PostEvent(new AndroidGeckoEvent(-1, -1, -1, -1)); + RedrawAll(); } +#ifdef ACCESSIBILITY + static bool sAccessibilityChecked = false; + if (!sAccessibilityChecked) { + sAccessibilityChecked = true; + sAccessibilityEnabled = + AndroidBridge::Bridge()->GetAccessibilityEnabled(); + } + if (aState && sAccessibilityEnabled) + CreateRootAccessible(); +#endif + #ifdef DEBUG_ANDROID_WIDGET DumpWindows(); #endif @@ -381,6 +420,32 @@ nsWindow::Show(bool aState) return NS_OK; } +#ifdef ACCESSIBILITY +void +nsWindow::CreateRootAccessible() +{ + if (IsTopLevel() && !mRootAccessible) { + ALOG(("nsWindow:: Create Toplevel Accessibility\n")); + nsAccessible *acc = DispatchAccessibleEvent(); + + if (acc) { + mRootAccessible = acc; + } + } +} + +nsAccessible* +nsWindow::DispatchAccessibleEvent() +{ + nsAccessibleEvent event(true, NS_GETACCESSIBLE, this); + + nsEventStatus status; + DispatchEvent(&event, status); + + return event.mAccessible; +} +#endif + NS_IMETHODIMP nsWindow::SetModal(bool aState) { @@ -459,7 +524,7 @@ nsWindow::Resize(PRInt32 aX, // Should we skip honoring aRepaint here? if (aRepaint && FindTopLevel() == TopWindow()) - nsAppShell::gAppShell->PostEvent(new AndroidGeckoEvent(-1, -1, -1, -1)); + RedrawAll(); return NS_OK; } @@ -512,7 +577,8 @@ NS_IMETHODIMP nsWindow::Invalidate(const nsIntRect &aRect, bool aIsSynchronous) { - nsAppShell::gAppShell->PostEvent(new AndroidGeckoEvent(-1, -1, -1, -1)); + AndroidGeckoEvent *event = new AndroidGeckoEvent(AndroidGeckoEvent::DRAW, aRect); + nsAppShell::gAppShell->PostEvent(event); return NS_OK; } @@ -588,7 +654,7 @@ nsWindow::BringToFront() // force a window resize nsAppShell::gAppShell->ResendLastResizeEvent(this); - nsAppShell::gAppShell->PostEvent(new AndroidGeckoEvent(-1, -1, -1, -1)); + RedrawAll(); } NS_IMETHODIMP @@ -730,6 +796,66 @@ nsWindow::GetThebesSurface() return new gfxImageSurface(gfxIntSize(5,5), gfxImageSurface::ImageFormatRGB24); } +bool +nsWindow::DrawToFile(const nsAString &path) +{ + if (!IsTopLevel() || !mIsVisible) { + ALOG("### DrawToFile works only for a visible toplevel window!"); + return PR_FALSE; + } + + if (GetLayerManager(nsnull)->GetBackendType() != LayerManager::LAYERS_BASIC) { + ALOG("### DrawToFile works only for a basic layers!"); + return PR_FALSE; + } + + nsRefPtr imgSurface = + new gfxImageSurface(gfxIntSize(mBounds.width, mBounds.height), + gfxImageSurface::ImageFormatARGB32); + + if (imgSurface->CairoStatus()) { + ALOG("### Failed to create a valid surface"); + return PR_FALSE; + } + + nsIntRect boundsRect(0, 0, mBounds.width, mBounds.height); + bool result = DrawTo(imgSurface, boundsRect); + NS_ENSURE_TRUE(result, PR_FALSE); + + nsCOMPtr encoder = do_CreateInstance("@mozilla.org/image/encoder;2?type=image/png"); + NS_ENSURE_TRUE(encoder, PR_FALSE); + + encoder->InitFromData(imgSurface->Data(), + imgSurface->Stride() * mBounds.height, + mBounds.width, + mBounds.height, + imgSurface->Stride(), + imgIEncoder::INPUT_FORMAT_HOSTARGB, + EmptyString()); + + nsCOMPtr file; + NS_NewLocalFile(path, true, getter_AddRefs(file)); + NS_ENSURE_TRUE(file, PR_FALSE); + + PRUint32 length; + encoder->Available(&length); + + nsCOMPtr outputStream; + NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), file); + NS_ENSURE_TRUE(outputStream, PR_FALSE); + + nsCOMPtr bufferedOutputStream; + NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream), + outputStream, length); + NS_ENSURE_TRUE(bufferedOutputStream, PR_FALSE); + + PRUint32 numWritten; + bufferedOutputStream->WriteFrom(encoder, length, &numWritten); + NS_ENSURE_SUCCESS(length == numWritten, PR_FALSE); + + return PR_TRUE; +} + void nsWindow::OnGlobalAndroidEvent(AndroidGeckoEvent *ae) { @@ -882,6 +1008,10 @@ nsWindow::OnGlobalAndroidEvent(AndroidGeckoEvent *ae) AndroidBridge::Bridge()->AcknowledgeEventSync(); break; + case AndroidGeckoEvent::SAVE_STATE: + win->DrawToFile(ae->Characters()); + break; + default: break; } @@ -906,6 +1036,13 @@ nsWindow::OnAndroidEvent(AndroidGeckoEvent *ae) bool nsWindow::DrawTo(gfxASurface *targetSurface) +{ + nsIntRect boundsRect(0, 0, mBounds.width, mBounds.height); + return DrawTo(targetSurface, boundsRect); +} + +bool +nsWindow::DrawTo(gfxASurface *targetSurface, const nsIntRect &invalidRect) { if (!mIsVisible) return false; @@ -927,7 +1064,7 @@ nsWindow::DrawTo(gfxASurface *targetSurface) // If we have no covering child, then we need to render this. if (coveringChildIndex == -1) { nsPaintEvent event(true, NS_PAINT, this); - event.region = boundsRect; + event.region = boundsRect.Intersect(invalidRect); switch (GetLayerManager(nsnull)->GetBackendType()) { case LayerManager::LAYERS_BASIC: { nsRefPtr ctx = new gfxContext(targetSurface); @@ -982,7 +1119,7 @@ nsWindow::DrawTo(gfxASurface *targetSurface) targetSurface->SetDeviceOffset(offset + gfxPoint(mChildren[i]->mBounds.x, mChildren[i]->mBounds.y)); - bool ok = mChildren[i]->DrawTo(targetSurface); + bool ok = mChildren[i]->DrawTo(targetSurface, invalidRect); if (!ok) { ALOG("nsWindow[%p]::DrawTo child %d[%p] returned FALSE!", (void*) this, i, (void*)mChildren[i]); @@ -998,7 +1135,6 @@ nsWindow::DrawTo(gfxASurface *targetSurface) void nsWindow::OnDraw(AndroidGeckoEvent *ae) { - if (!sSurfaceExists) { return; } @@ -1016,6 +1152,23 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae) } AndroidBridge::AutoLocalJNIFrame jniFrame; +#ifdef MOZ_JAVA_COMPOSITOR + AndroidGeckoSoftwareLayerClient &client = + AndroidBridge::Bridge()->GetSoftwareLayerClient(); + client.BeginDrawing(); + unsigned char *bits = client.LockBufferBits(); + nsRefPtr targetSurface = + new gfxImageSurface(bits, gfxIntSize(TILE_WIDTH, TILE_HEIGHT), TILE_WIDTH * 2, + gfxASurface::ImageFormatRGB16_565); + if (targetSurface->CairoStatus()) { + ALOG("### Failed to create a valid surface from the bitmap"); + } else { + DrawTo(targetSurface, ae->Rect()); + client.UnlockBuffer(); + client.EndDrawing(ae->Rect()); + } + return; +#endif AndroidGeckoSurfaceView& sview(AndroidBridge::Bridge()->SurfaceView()); diff --git a/widget/src/android/nsWindow.h b/widget/src/android/nsWindow.h index 7c757d985010..f905bf315ae6 100644 --- a/widget/src/android/nsWindow.h +++ b/widget/src/android/nsWindow.h @@ -43,6 +43,10 @@ #include "nsTArray.h" +#ifdef ACCESSIBILITY +#include "nsAccessible.h" +#endif + class gfxASurface; class nsIdleService; @@ -167,10 +171,17 @@ public: gfxASurface* GetThebesSurface(); NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent); + +#ifdef ACCESSIBILITY + static bool sAccessibilityEnabled; +#endif + protected: void BringToFront(); nsWindow *FindTopLevel(); bool DrawTo(gfxASurface *targetSurface); + bool DrawTo(gfxASurface *targetSurface, const nsIntRect &aRect); + bool DrawToFile(const nsAString &path); bool IsTopLevel(); void OnIMEAddRange(mozilla::AndroidGeckoEvent *ae); @@ -211,6 +222,22 @@ private: void DispatchGestureEvent(PRUint32 msg, PRUint32 direction, double delta, const nsIntPoint &refPoint, PRUint64 time); void HandleSpecialKey(mozilla::AndroidGeckoEvent *ae); + void RedrawAll(); + +#ifdef ACCESSIBILITY + nsRefPtr mRootAccessible; + + /** + * Request to create the accessible for this window if it is top level. + */ + void CreateRootAccessible(); + + /** + * Generate the NS_GETACCESSIBLE event to get accessible for this window + * and return it. + */ + nsAccessible *DispatchAccessibleEvent(); +#endif // ACCESSIBILITY }; #endif /* NSWINDOW_H_ */ From cc665b3b370fffb54f856a4800f9f4ffe8eeef17 Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Mon, 14 Nov 2011 19:12:20 -0800 Subject: [PATCH 5/9] Bug 702029 - Push all console logging to androids adb logcat. r=blassey --- xpcom/base/nsConsoleService.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/xpcom/base/nsConsoleService.cpp b/xpcom/base/nsConsoleService.cpp index 7ca5144775ef..0d29a773358e 100644 --- a/xpcom/base/nsConsoleService.cpp +++ b/xpcom/base/nsConsoleService.cpp @@ -53,6 +53,10 @@ #include "nsConsoleMessage.h" #include "nsIClassInfoImpl.h" +#if defined(ANDROID) +#include +#endif + using namespace mozilla; NS_IMPL_THREADSAFE_ADDREF(nsConsoleService) @@ -135,6 +139,16 @@ nsConsoleService::LogMessage(nsIConsoleMessage *message) { MutexAutoLock lock(mLock); +#if defined(ANDROID) + { + nsXPIDLString msg; + message->GetMessageMoz(getter_Copies(msg)); + __android_log_print(ANDROID_LOG_ERROR, "Gecko *** Console Service *** ", + "%s", + NS_LossyConvertUTF16toASCII(msg).get()); + } +#endif + /* * If there's already a message in the slot we're about to replace, * we've wrapped around, and we need to release the old message. We From 60e3b73d7c5f03eb352ce90eba34f52c1b38e198 Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Mon, 14 Nov 2011 19:12:26 -0800 Subject: [PATCH 6/9] Bug 690201 - dead code - mLastDrawEvent never used. r=mbrubeck --- embedding/android/GeckoAppShell.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/embedding/android/GeckoAppShell.java b/embedding/android/GeckoAppShell.java index 053d4f16dfc9..d5369c233fbf 100644 --- a/embedding/android/GeckoAppShell.java +++ b/embedding/android/GeckoAppShell.java @@ -413,8 +413,6 @@ public class GeckoAppShell GeckoAppShell.nativeRun(combinedArgs); } - private static GeckoEvent mLastDrawEvent; - private static void sendPendingEventsToGecko() { try { while (!gPendingEvents.isEmpty()) { From 30d1a0559e1da8dfa0548ec0156f94ee8fa70364 Mon Sep 17 00:00:00 2001 From: Jonathan Griffin Date: Mon, 14 Nov 2011 21:02:02 -0800 Subject: [PATCH 7/9] Bug 686019 - Add support for testing addon sync in TPS. r=mconnor --- services/sync/tests/tps/test_addon_sanity.js | 50 ++++ services/sync/tests/tps/unsigned-1.0.xml | 27 ++ services/sync/tests/tps/unsigned-1.0.xpi | Bin 0 -> 452 bytes .../tps/extensions/tps/modules/addons.jsm | 252 ++++++++++++++++++ .../sync/tps/extensions/tps/modules/tps.jsm | 80 ++++-- testing/tps/tps/__init__.py | 1 + testing/tps/tps/mozhttpd.py | 111 ++++++++ testing/tps/tps/testrunner.py | 7 +- 8 files changed, 500 insertions(+), 28 deletions(-) create mode 100644 services/sync/tests/tps/test_addon_sanity.js create mode 100644 services/sync/tests/tps/unsigned-1.0.xml create mode 100644 services/sync/tests/tps/unsigned-1.0.xpi create mode 100644 services/sync/tps/extensions/tps/modules/addons.jsm create mode 100644 testing/tps/tps/mozhttpd.py diff --git a/services/sync/tests/tps/test_addon_sanity.js b/services/sync/tests/tps/test_addon_sanity.js new file mode 100644 index 000000000000..78d56f4908dc --- /dev/null +++ b/services/sync/tests/tps/test_addon_sanity.js @@ -0,0 +1,50 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* + * The list of phases mapped to their corresponding profiles. The object + * here must be in strict JSON format, as it will get parsed by the Python + * testrunner (no single quotes, extra comma's, etc). + */ + +var phases = { "phase1": "profile1", + "phase2": "profile1", + "phase3": "profile1", + "phase4": "profile1", + "phase5": "profile1" }; + +/* + * Test phases + */ + +Phase('phase1', [ + [Addons.install, ['unsigned-1.0.xml']], + [Addons.verify, ['unsigned-xpi@tests.mozilla.org'], STATE_DISABLED], + [Sync, SYNC_WIPE_SERVER], +]); + +Phase('phase2', [ + [Sync], + [Addons.verify, ['unsigned-xpi@tests.mozilla.org'], STATE_ENABLED], + [Addons.setState, ['unsigned-xpi@tests.mozilla.org'], STATE_DISABLED], + [Sync], +]); + +Phase('phase3', [ + [Sync], + [Addons.verify, ['unsigned-xpi@tests.mozilla.org'], STATE_DISABLED], + [Addons.setState, ['unsigned-xpi@tests.mozilla.org'], STATE_ENABLED], + [Sync], +]); + +Phase('phase4', [ + [Sync], + [Addons.verify, ['unsigned-xpi@tests.mozilla.org'], STATE_ENABLED], + [Addons.uninstall, ['unsigned-xpi@tests.mozilla.org']], + [Sync], +]); + +Phase('phase5', [ + [Sync], + [Addons.verifyNot, ['unsigned-xpi@tests.mozilla.org']], +]); diff --git a/services/sync/tests/tps/unsigned-1.0.xml b/services/sync/tests/tps/unsigned-1.0.xml new file mode 100644 index 000000000000..e311f47ddcc9 --- /dev/null +++ b/services/sync/tests/tps/unsigned-1.0.xml @@ -0,0 +1,27 @@ + + + + Unsigned Test XPI + Extension + unsigned-xpi@tests.mozilla.org + unsigned-xpi + 1.0 + + + Firefox + 1 + 3.6 + * + {ec8030f7-c20a-464f-9b0e-13a3a9e97384} + + ALL + + http://127.0.0.1:4567/unsigned-1.0.xpi + + 2009-09-14T04:47:42Z + + + 2011-09-05T20:42:09Z + + + \ No newline at end of file diff --git a/services/sync/tests/tps/unsigned-1.0.xpi b/services/sync/tests/tps/unsigned-1.0.xpi new file mode 100644 index 0000000000000000000000000000000000000000..51b00475a9641ea9d608874a3ab7679da3a4374b GIT binary patch literal 452 zcmWIWW@Zs#U}E54_?u^9#dA2DRf~~4Pa^m=!CAB@`#_JRJCLMTP zI9DyV<<;!;^s=<;=fu~BJ&BG`=N0*wGwVpVQP-#IS7-g;+M)E%WsUK%S<7acl?Nw( z&oP^SK626~lcn2k1%78f5zUn++E7tLzE!`U8JT5_uOTuP|ifs?i!UE8+CEYjcYy?ajS z8plGZ?O!gpMb-1SG`8M($7*+F>!j#D=h``2kGE-L^!%E%W6!hu!CPCtPtFy8#3UhH zdHeBp*^fM58gJ}(X{=0b>ML;8jErXXkXxv9p6O?ovig*H-&tb1i#~sHx%bD*`FKOi zcd5uS!$os`<_Ejg2Y53wi8JF0X + * + * 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 ***** */ + +var EXPORTED_SYMBOLS = ["Addon", "STATE_ENABLED", "STATE_DISABLED"]; + +const CC = Components.classes; +const CI = Components.interfaces; +const CU = Components.utils; + +CU.import("resource://gre/modules/AddonManager.jsm"); +CU.import("resource://gre/modules/AddonRepository.jsm"); +CU.import("resource://gre/modules/Services.jsm"); +CU.import("resource://services-sync/async.js"); +CU.import("resource://services-sync/util.js"); +CU.import("resource://tps/logger.jsm"); +var XPIProvider = CU.import("resource://gre/modules/XPIProvider.jsm") + .XPIProvider; + +const ADDONSGETURL = 'http://127.0.0.1:4567/'; +const STATE_ENABLED = 1; +const STATE_DISABLED = 2; + +function GetFileAsText(file) +{ + let channel = Services.io.newChannel(file, null, null); + let inputStream = channel.open(); + if (channel instanceof CI.nsIHttpChannel && + channel.responseStatus != 200) { + return ""; + } + + let streamBuf = ""; + let sis = CC["@mozilla.org/scriptableinputstream;1"] + .createInstance(CI.nsIScriptableInputStream); + sis.init(inputStream); + + let available; + while ((available = sis.available()) != 0) { + streamBuf += sis.read(available); + } + + inputStream.close(); + return streamBuf; +} + +function Addon(TPS, id) { + this.TPS = TPS; + this.id = id; +} + +Addon.prototype = { + _addons_requiring_restart: [], + _addons_pending_install: [], + + Delete: function() { + // find our addon locally + let cb = Async.makeSyncCallback(); + XPIProvider.getAddonsByTypes(null, cb); + let results = Async.waitForSyncCallback(cb); + var addon; + var id = this.id; + results.forEach(function(result) { + if (result.id == id) { + addon = result; + } + }); + Logger.AssertTrue(!!addon, 'could not find addon ' + this.id + ' to uninstall'); + addon.uninstall(); + }, + + Find: function(state) { + let cb = Async.makeSyncCallback(); + let addon_found = false; + var that = this; + + var log_addon = function(addon) { + that.addon = addon; + Logger.logInfo('addon ' + addon.id + ' found, isActive: ' + addon.isActive); + if (state == STATE_ENABLED || state == STATE_DISABLED) { + Logger.AssertEqual(addon.isActive, + state == STATE_ENABLED ? true : false, + "addon " + that.id + " has an incorrect enabled state"); + } + }; + + // first look in the list of all addons + XPIProvider.getAddonsByTypes(null, cb); + let addonlist = Async.waitForSyncCallback(cb); + addonlist.forEach(function(addon) { + if (addon.id == that.id) { + addon_found = true; + log_addon.call(that, addon); + } + }); + + if (!addon_found) { + // then look in the list of recent installs + cb = Async.makeSyncCallback(); + XPIProvider.getInstallsByTypes(null, cb); + addonlist = Async.waitForSyncCallback(cb); + for (var i in addonlist) { + if (addonlist[i].addon && addonlist[i].addon.id == that.id && + addonlist[i].state == AddonManager.STATE_INSTALLED) { + addon_found = true; + log_addon.call(that, addonlist[i].addon); + } + } + } + + return addon_found; + }, + + Install: function() { + // For Install, the id parameter initially passed is really the filename + // for the addon's install .xml; we'll read the actual id from the .xml. + let url = this.id; + + // set the url used by getAddonsByIDs + var prefs = CC["@mozilla.org/preferences-service;1"] + .getService(CI.nsIPrefBranch); + prefs.setCharPref('extensions.getAddons.get.url', ADDONSGETURL + url); + + // read the XML and find the addon id + xml = GetFileAsText(ADDONSGETURL + url); + Logger.AssertTrue(xml.indexOf("") > -1, 'guid not found in ' + url); + this.id = xml.substring(xml.indexOf("") + 6, xml.indexOf(" -1, + "onInstallEnded received for unexpected addon " + addon.addon.id); + this._addons_pending_install.splice( + this._addons_pending_install.indexOf(addon.addon.id), + 1); + } + catch(e) { + // We can't throw during a callback, as it will just get eaten by + // the callback's caller. + Utils.nextTick(function() { + this.DumpError(e); + }, this); + return; + } + this.TPS.FinishAsyncOperation(); + }, + + onInstallFailed: function(addon) { + Logger.logInfo('--------- event observed: addon onInstallFailed'); + Utils.nextTick(function() { + this.DumpError('Installation failed for addon ' + + (addon.addon && addon.addon.id ? addon.addon.id : 'unknown')); + }, this); + }, + + onDownloadFailed: function(addon) { + Logger.logInfo('--------- event observed: addon onDownloadFailed'); + Utils.nextTick(function() { + this.DumpError('Download failed for addon ' + + (addon.addon && addon.addon.id ? addon.addon.id : 'unknown')); + }, this); + }, + +}; diff --git a/services/sync/tps/extensions/tps/modules/tps.jsm b/services/sync/tps/extensions/tps/modules/tps.jsm index d9c20014a4e0..3824405b7a0a 100644 --- a/services/sync/tps/extensions/tps/modules/tps.jsm +++ b/services/sync/tps/extensions/tps/modules/tps.jsm @@ -48,9 +48,11 @@ const CU = Components.utils; CU.import("resource://services-sync/service.js"); CU.import("resource://services-sync/constants.js"); +CU.import("resource://services-sync/async.js"); CU.import("resource://services-sync/util.js"); CU.import("resource://gre/modules/XPCOMUtils.jsm"); CU.import("resource://gre/modules/Services.jsm"); +CU.import("resource://tps/addons.jsm"); CU.import("resource://tps/bookmarks.jsm"); CU.import("resource://tps/logger.jsm"); CU.import("resource://tps/passwords.jsm"); @@ -61,6 +63,8 @@ CU.import("resource://tps/tabs.jsm"); var hh = CC["@mozilla.org/network/protocol;1?name=http"] .getService(CI.nsIHttpProtocolHandler); +var prefs = CC["@mozilla.org/preferences-service;1"] + .getService(CI.nsIPrefBranch); var mozmillInit = {}; CU.import('resource://mozmill/modules/init.js', mozmillInit); @@ -73,37 +77,16 @@ const ACTION_SYNC = "sync"; const ACTION_DELETE = "delete"; const ACTION_PRIVATE_BROWSING = "private-browsing"; const ACTION_WIPE_SERVER = "wipe-server"; +const ACTION_SETSTATE = "set-state"; const ACTIONS = [ACTION_ADD, ACTION_VERIFY, ACTION_VERIFY_NOT, ACTION_MODIFY, ACTION_SYNC, ACTION_DELETE, - ACTION_PRIVATE_BROWSING, ACTION_WIPE_SERVER]; + ACTION_PRIVATE_BROWSING, ACTION_WIPE_SERVER, + ACTION_SETSTATE]; const SYNC_WIPE_SERVER = "wipe-server"; const SYNC_RESET_CLIENT = "reset-client"; const SYNC_WIPE_CLIENT = "wipe-client"; -function GetFileAsText(file) -{ - let channel = Services.io.newChannel(file, null, null); - let inputStream = channel.open(); - if (channel instanceof CI.nsIHttpChannel && - channel.responseStatus != 200) { - return ""; - } - - let streamBuf = ""; - let sis = CC["@mozilla.org/scriptableinputstream;1"] - .createInstance(CI.nsIScriptableInputStream); - sis.init(inputStream); - - let available; - while ((available = sis.available()) != 0) { - streamBuf += sis.read(available); - } - - inputStream.close(); - return streamBuf; -} - var TPS = { _waitingForSync: false, @@ -351,6 +334,33 @@ var TPS = } }, + HandleAddons: function (addons, action, state) { + for (var i in addons) { + Logger.logInfo("executing action " + action.toUpperCase() + + " on addon " + JSON.stringify(addons[i])); + var addon = new Addon(this, addons[i]); + switch(action) { + case ACTION_ADD: + addon.Install(); + break; + case ACTION_DELETE: + addon.Delete(); + break; + case ACTION_VERIFY: + Logger.AssertTrue(addon.Find(state), 'addon ' + addon.id + ' not found'); + break; + case ACTION_VERIFY_NOT: + Logger.AssertTrue(!addon.Find(state), 'addon ' + addon.id + " is present, but it shouldn't be"); + break; + case ACTION_SETSTATE: + Logger.AssertTrue(addon.SetState(state), 'addon ' + addon.id + ' not found'); + break; + } + } + Logger.logPass("executing action " + action.toUpperCase() + + " on addons"); + }, + HandleBookmarks: function (bookmarks, action) { try { let items = []; @@ -460,7 +470,7 @@ var TPS = let phase = this._phaselist["phase" + this._currentPhase]; let action = phase[this._currentAction]; Logger.logInfo("starting action: " + JSON.stringify(action)); - action[0].call(this, action[1]); + action[0].apply(this, action.slice(1)); // if we're in an async operation, don't continue on to the next action if (this._operations_pending) @@ -517,8 +527,6 @@ var TPS = // Store account details as prefs so they're accessible to the mozmill // framework. - let prefs = CC["@mozilla.org/preferences-service;1"] - .getService(CI.nsIPrefBranch); prefs.setCharPref('tps.account.username', this.config.account.username); prefs.setCharPref('tps.account.password', this.config.account.password); prefs.setCharPref('tps.account.passphrase', this.config.account.passphrase); @@ -634,6 +642,24 @@ var TPS = }, }; +var Addons = { + install: function Addons__install(addons) { + TPS.HandleAddons(addons, ACTION_ADD); + }, + setState: function Addons__setState(addons, state) { + TPS.HandleAddons(addons, ACTION_SETSTATE, state); + }, + uninstall: function Addons__uninstall(addons) { + TPS.HandleAddons(addons, ACTION_DELETE); + }, + verify: function Addons__verify(addons, state) { + TPS.HandleAddons(addons, ACTION_VERIFY, state); + }, + verifyNot: function Addons__verifyNot(addons) { + TPS.HandleAddons(addons, ACTION_VERIFY_NOT); + }, +}; + var Bookmarks = { add: function Bookmarks__add(bookmarks) { TPS.HandleBookmarks(bookmarks, ACTION_ADD); diff --git a/testing/tps/tps/__init__.py b/testing/tps/tps/__init__.py index 6d710ca4ce5c..a9ad3167302d 100644 --- a/testing/tps/tps/__init__.py +++ b/testing/tps/tps/__init__.py @@ -38,4 +38,5 @@ from firefoxrunner import TPSFirefoxRunner from pulse import TPSPulseMonitor from testrunner import TPSTestRunner +from mozhttpd import MozHttpd diff --git a/testing/tps/tps/mozhttpd.py b/testing/tps/tps/mozhttpd.py new file mode 100644 index 000000000000..daccf8ff41a2 --- /dev/null +++ b/testing/tps/tps/mozhttpd.py @@ -0,0 +1,111 @@ +#!/usr/bin/python +# +# ***** 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 +# the Mozilla Foundation. +# Portions created by the Initial Developer are Copyright (C) 2011 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Joel Maher +# +# 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 ***** + +import BaseHTTPServer +import SimpleHTTPServer +import threading +import sys +import os +import urllib +import re +from urlparse import urlparse +from SocketServer import ThreadingMixIn + +DOCROOT = '.' + +class EasyServer(ThreadingMixIn, BaseHTTPServer.HTTPServer): + allow_reuse_address = True + +class MozRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): + def translate_path(self, path): + # It appears that the default path is '/' and os.path.join makes the '/' + o = urlparse(path) + return "%s%s" % ('' if sys.platform == 'win32' else '/', '/'.join([i.strip('/') for i in (DOCROOT, o.path)])) + + # I found on my local network that calls to this were timing out + # I believe all of these calls are from log_message + def address_string(self): + return "a.b.c.d" + + # This produces a LOT of noise + def log_message(self, format, *args): + pass + +class MozHttpd(object): + def __init__(self, host="127.0.0.1", port=8888, docroot='.'): + global DOCROOT + self.host = host + self.port = int(port) + DOCROOT = docroot + + def start(self): + self.httpd = EasyServer((self.host, self.port), MozRequestHandler) + self.server = threading.Thread(target=self.httpd.serve_forever) + self.server.setDaemon(True) # don't hang on exit + self.server.start() + #self.testServer() + + #TODO: figure this out + def testServer(self): + fileList = os.listdir(DOCROOT) + filehandle = urllib.urlopen('http://%s:%s' % (self.host, self.port)) + data = filehandle.readlines(); + filehandle.close() + + for line in data: + found = False + # '@' denotes a symlink and we need to ignore it. + webline = re.sub('\<[a-zA-Z0-9\-\_\.\=\"\'\/\\\%\!\@\#\$\^\&\*\(\) ]*\>', '', line.strip('\n')).strip('/').strip().strip('@') + if webline != "": + if webline == "Directory listing for": + found = True + else: + for fileName in fileList: + if fileName == webline: + found = True + + if (found == False): + print "NOT FOUND: " + webline.strip() + + def stop(self): + if self.httpd: + self.httpd.shutdown() + + __del__ = stop + diff --git a/testing/tps/tps/testrunner.py b/testing/tps/tps/testrunner.py index aaf3a134363e..4ecf5287677c 100644 --- a/testing/tps/tps/testrunner.py +++ b/testing/tps/tps/testrunner.py @@ -53,7 +53,7 @@ from mozprofile import Profile from tps.firefoxrunner import TPSFirefoxRunner from tps.phase import TPSTestPhase - +from tps.mozhttpd import MozHttpd class TempFile(object): """Class for temporary files that delete themselves when garbage-collected. @@ -397,6 +397,9 @@ class TPSTestRunner(object): testlist = [os.path.basename(self.testfile)] testdir = os.path.dirname(self.testfile) + self.mozhttpd = MozHttpd(port=4567, docroot=testdir) + self.mozhttpd.start() + # run each test, and save the results for test in testlist: result = self.run_single_test(testdir, test) @@ -415,6 +418,8 @@ class TPSTestRunner(object): else: self.numfailed += 1 + self.mozhttpd.stop() + # generate the postdata we'll use to post the results to the db self.postdata = { 'tests': self.results, 'os':os_string, From 07b0f67bb974b976d2d7841493b296ee04103f42 Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Tue, 15 Nov 2011 09:30:59 -0800 Subject: [PATCH 8/9] Bug 702544 - Follow up to 701996. Landing ifdef to make birch project branch compile r=blassey --- config/autoconf.mk.in | 1 + configure.in | 2 ++ widget/src/android/AndroidJavaWrappers.cpp | 12 ++++++++++-- widget/src/android/Makefile.in | 3 +++ widget/src/android/nsWindow.cpp | 8 ++++---- 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/config/autoconf.mk.in b/config/autoconf.mk.in index 8c5ba5ede5da..555cfd323a6f 100644 --- a/config/autoconf.mk.in +++ b/config/autoconf.mk.in @@ -140,6 +140,7 @@ MOZ_UPDATE_PACKAGING = @MOZ_UPDATE_PACKAGING@ MOZ_DISABLE_PARENTAL_CONTROLS = @MOZ_DISABLE_PARENTAL_CONTROLS@ NS_ENABLE_TSF = @NS_ENABLE_TSF@ MOZ_SPELLCHECK = @MOZ_SPELLCHECK@ +MOZ_JAVA_COMPOSITOR = @MOZ_JAVA_COMPOSITOR@ MOZ_PROFILELOCKING = @MOZ_PROFILELOCKING@ MOZ_FEEDS = @MOZ_FEEDS@ MOZ_TOOLKIT_SEARCH = @MOZ_TOOLKIT_SEARCH@ diff --git a/configure.in b/configure.in index 603e2457970b..9c5ec874090f 100644 --- a/configure.in +++ b/configure.in @@ -4662,6 +4662,7 @@ MOZ_REFLOW_PERF= MOZ_SAFE_BROWSING= MOZ_HELP_VIEWER= MOZ_SPELLCHECK=1 +MOZ_JAVA_COMPOSITOR= MOZ_SVG_DLISTS= MOZ_TOOLKIT_SEARCH=1 MOZ_UI_LOCALE=en-US @@ -8431,6 +8432,7 @@ AC_SUBST(IBMBIDI) AC_SUBST(MOZ_UNIVERSALCHARDET) AC_SUBST(ACCESSIBILITY) AC_SUBST(MOZ_SPELLCHECK) +AC_SUBST(MOZ_JAVA_COMPOSITOR) AC_SUBST(MOZ_USER_DIR) AC_SUBST(MOZ_CRASHREPORTER) AC_SUBST(MOZ_UPDATER) diff --git a/widget/src/android/AndroidJavaWrappers.cpp b/widget/src/android/AndroidJavaWrappers.cpp index 7beacbd9bc6d..07401d9de2d1 100644 --- a/widget/src/android/AndroidJavaWrappers.cpp +++ b/widget/src/android/AndroidJavaWrappers.cpp @@ -136,13 +136,12 @@ void mozilla::InitAndroidJavaWrappers(JNIEnv *jEnv) { AndroidGeckoEvent::InitGeckoEventClass(jEnv); - AndroidGeckoSurfaceView::InitGeckoSurfaceViewClass(jEnv); AndroidPoint::InitPointClass(jEnv); AndroidLocation::InitLocationClass(jEnv); AndroidAddress::InitAddressClass(jEnv); AndroidRect::InitRectClass(jEnv); - AndroidGeckoSoftwareLayerClient::InitGeckoSoftwareLayerClientClass(jEnv); + AndroidGeckoSurfaceView::InitGeckoSurfaceViewClass(jEnv); } void @@ -184,6 +183,7 @@ AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv) void AndroidGeckoSurfaceView::InitGeckoSurfaceViewClass(JNIEnv *jEnv) { +#ifndef MOZ_JAVA_COMPOSITOR initInit(); jGeckoSurfaceViewClass = getClassGlobalRef("org/mozilla/gecko/GeckoSurfaceView"); @@ -196,6 +196,7 @@ AndroidGeckoSurfaceView::InitGeckoSurfaceViewClass(JNIEnv *jEnv) jDraw2DBufferMethod = getMethod("draw2D", "(Ljava/nio/ByteBuffer;I)V"); jGetSurfaceMethod = getMethod("getSurface", "()Landroid/view/Surface;"); jGetHolderMethod = getMethod("getHolder", "()Landroid/view/SurfaceHolder;"); +#endif } void @@ -591,6 +592,13 @@ AndroidGeckoSoftwareLayerClient::LockBuffer() return JNI()->CallObjectMethod(wrapped_obj, jLockBufferMethod); } +unsigned char * +AndroidGeckoSoftwareLayerClient::LockBufferBits() +{ + AndroidBridge::AutoLocalJNIFrame(1); + return reinterpret_cast(JNI()->GetDirectBufferAddress(LockBuffer())); +} + void AndroidGeckoSoftwareLayerClient::UnlockBuffer() { diff --git a/widget/src/android/Makefile.in b/widget/src/android/Makefile.in index e79727c34a19..865142727ab2 100644 --- a/widget/src/android/Makefile.in +++ b/widget/src/android/Makefile.in @@ -51,6 +51,9 @@ MODULE_NAME = nsWidgetAndroidModule GRE_MODULE = 1 LIBXUL_LIBRARY = 1 +ifdef MOZ_JAVA_COMPOSITOR +DEFINES += -DMOZ_JAVA_COMPOSITOR +endif CPPSRCS = \ GfxInfo.cpp \ diff --git a/widget/src/android/nsWindow.cpp b/widget/src/android/nsWindow.cpp index 28deb7b88e69..673da5780f45 100644 --- a/widget/src/android/nsWindow.cpp +++ b/widget/src/android/nsWindow.cpp @@ -1135,10 +1135,6 @@ nsWindow::DrawTo(gfxASurface *targetSurface, const nsIntRect &invalidRect) void nsWindow::OnDraw(AndroidGeckoEvent *ae) { - if (!sSurfaceExists) { - return; - } - if (!IsTopLevel()) { ALOG("##### redraw for window %p, which is not a toplevel window -- sending to toplevel!", (void*) this); DumpWindows(); @@ -1170,6 +1166,10 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae) return; #endif + if (!sSurfaceExists) { + return; + } + AndroidGeckoSurfaceView& sview(AndroidBridge::Bridge()->SurfaceView()); NS_ASSERTION(!sview.isNull(), "SurfaceView is null!"); From 4aa0f5d48d0e98a26c5c7705f78f32cbaa2bb20d Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Tue, 15 Nov 2011 20:47:57 +0200 Subject: [PATCH 9/9] Bug 701342 - Revoke mPendingTitleChangeEvent when unlinking document, r=peterv --- content/base/src/nsDocument.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index a20ee77684c5..8915d789ec7d 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -1954,6 +1954,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument) if (tmp->mAnimationController) { tmp->mAnimationController->Unlink(); } + + tmp->mPendingTitleChangeEvent.Revoke(); tmp->mInUnlinkOrDeletion = false; NS_IMPL_CYCLE_COLLECTION_UNLINK_END