diff --git a/accessible/src/generic/HyperTextAccessible.cpp b/accessible/src/generic/HyperTextAccessible.cpp index b5d673591152..4f651a70febb 100644 --- a/accessible/src/generic/HyperTextAccessible.cpp +++ b/accessible/src/generic/HyperTextAccessible.cpp @@ -27,6 +27,7 @@ #include "nsIPersistentProperties2.h" #include "nsIScrollableFrame.h" #include "nsIServiceManager.h" +#include "nsITextControlElement.h" #include "nsTextFragment.h" #include "mozilla/Selection.h" #include "mozilla/MathAlgorithms.h" @@ -102,8 +103,19 @@ HyperTextAccessible::NativeState() { uint64_t states = AccessibleWrap::NativeState(); - nsCOMPtr editor = GetEditor(); - if (editor) { + nsCOMPtr textControl = do_QueryInterface(mContent); + bool editable = !!textControl; + Accessible* hyperText = this; + while (!editable && hyperText) { + if (hyperText->IsHyperText()) + editable = hyperText->GetNode()->IsEditable(); + if (hyperText->IsDoc()) + break; + + hyperText = hyperText->Parent(); + } + + if (editable) { states |= states::EDITABLE; } else if (mContent->Tag() == nsGkAtoms::article) { diff --git a/accessible/tests/mochitest/elm/test_HTMLSpec.html b/accessible/tests/mochitest/elm/test_HTMLSpec.html index 0c0bd76cef1b..b2978a1f979b 100644 --- a/accessible/tests/mochitest/elm/test_HTMLSpec.html +++ b/accessible/tests/mochitest/elm/test_HTMLSpec.html @@ -733,17 +733,29 @@ states: STATE_PROTECTED, extraStates: EXT_STATE_EDITABLE, actions: "activate", - children: [ ] + children: [ + { + role: ROLE_TEXT_LEAF + } + ] }; testElm("input_password", obj); + ok(getAccessible("input_password").firstChild.name != "44", + "text leaf for password shouldn't have its real value as its name!"); obj = { role: ROLE_PASSWORD_TEXT, states: STATE_PROTECTED | STATE_READONLY, actions: "activate", - children: [ ] + children: [ + { + role: ROLE_TEXT_LEAF + } + ] }; testElm("input_password_readonly", obj); + ok(getAccessible("input_password_readonly").firstChild.name != "44", + "text leaf for password shouldn't have its real value as its name!"); ////////////////////////////////////////////////////////////////////////// // HTML:input@type="radio" diff --git a/b2g/chrome/content/settings.js b/b2g/chrome/content/settings.js index 4de6ba245763..7173e92a3410 100644 --- a/b2g/chrome/content/settings.js +++ b/b2g/chrome/content/settings.js @@ -378,8 +378,7 @@ let AdbController = { // Check if we have a remote debugging session going on. If so, we won't // disable adb even if the screen is locked. - let isDebugging = DebuggerServer._connections && - Object.keys(DebuggerServer._connections).length > 0; + let isDebugging = RemoteDebugger.isDebugging; if (this.DEBUG) { this.debug("isDebugging=" + isDebugging); } @@ -460,6 +459,8 @@ SettingsListener.observe("lockscreen.enabled", false, AdbController.setLockscreenEnabled.bind(AdbController)); #endif +// Keep the old setting to not break people that won't have updated +// gaia and gecko. SettingsListener.observe('devtools.debugger.remote-enabled', false, function(value) { Services.prefs.setBoolPref('devtools.debugger.remote-enabled', value); // This preference is consulted during startup @@ -475,6 +476,30 @@ SettingsListener.observe('devtools.debugger.remote-enabled', false, function(val #endif }); +SettingsListener.observe('debugger.remote-mode', false, function(value) { + if (['disabled', 'adb-only', 'adb-devtools'].indexOf(value) == -1) { + dump('Illegal value for debugger.remote-mode: ' + value + '\n'); + return; + } + + Services.prefs.setBoolPref('devtools.debugger.remote-enabled', + value == 'adb-devtools'); + // This preference is consulted during startup + Services.prefs.savePrefFile(null); + + try { + (value == 'adb-devtools') ? RemoteDebugger.start() + : RemoteDebugger.stop(); + } catch(e) { + dump("Error while initializing devtools: " + e + "\n" + e.stack + "\n"); + } + +#ifdef MOZ_WIDGET_GONK + AdbController.setRemoteDebuggerState(value != 'disabled'); +#endif +}); + + SettingsListener.observe('debug.log-animations.enabled', false, function(value) { Services.prefs.setBoolPref('layers.offmainthreadcomposition.log-animations', value); }); diff --git a/b2g/chrome/content/shell.js b/b2g/chrome/content/shell.js index 7f0d712df84b..d7cd342c5128 100644 --- a/b2g/chrome/content/shell.js +++ b/b2g/chrome/content/shell.js @@ -1031,6 +1031,7 @@ let IndexedDBPromptHelper = { let RemoteDebugger = { _promptDone: false, _promptAnswer: false, + _running: false, prompt: function debugger_prompt() { this._promptDone = false; @@ -1051,8 +1052,21 @@ let RemoteDebugger = { this._promptDone = true; }, + get isDebugging() { + if (!this._running) { + return false; + } + + return DebuggerServer._connections && + Object.keys(DebuggerServer._connections).length > 0; + }, + // Start the debugger server. start: function debugger_start() { + if (this._running) { + return; + } + if (!DebuggerServer.initialized) { // Ask for remote connections. DebuggerServer.init(this.prompt.bind(this)); @@ -1088,13 +1102,20 @@ let RemoteDebugger = { "/data/local/debugger-socket"; try { DebuggerServer.openListener(path); + this._running = true; } catch (e) { dump('Unable to start debugger server: ' + e + '\n'); } }, stop: function debugger_stop() { + if (!this._running) { + return; + } + if (!DebuggerServer.initialized) { + // Can this really happen if we are running? + this._running = false; return; } @@ -1103,6 +1124,7 @@ let RemoteDebugger = { } catch (e) { dump('Unable to stop debugger server: ' + e + '\n'); } + this._running = false; } } diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index a30921049e1e..128e0397850f 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "3b850fa17c888bdd31f1a163fd7b92f6f020449d", + "revision": "6e971c6a9f947d301a0401fcbc87141b8eba23b6", "repo_path": "/integration/gaia-central" } diff --git a/build/valgrind/mach_commands.py b/build/valgrind/mach_commands.py index 2e32b2d127dd..4f43c4ba6462 100644 --- a/build/valgrind/mach_commands.py +++ b/build/valgrind/mach_commands.py @@ -93,7 +93,7 @@ class MachCommands(MachCommandBase): valgrind, '--error-exitcode=1', '--smc-check=all-non-file', - '--vex-iropt-register-updates=allregs-at-each-insn', + '--vex-iropt-register-updates=allregs-at-mem-access', '--gen-suppressions=all', '--num-callers=20', '--leak-check=full', diff --git a/content/base/src/nsContentAreaDragDrop.cpp b/content/base/src/nsContentAreaDragDrop.cpp index eb09fc83c44a..89befa69608a 100644 --- a/content/base/src/nsContentAreaDragDrop.cpp +++ b/content/base/src/nsContentAreaDragDrop.cpp @@ -738,7 +738,13 @@ DragDataProducer::AddStringsToDataTransfer(nsIContent* aDragNode, if (!mUrlString.IsEmpty() && mIsAnchor) { nsAutoString dragData(mUrlString); dragData.AppendLiteral("\n"); - dragData += mTitleString; + // Remove leading and trailing newlines in the title and replace them with + // space in remaining positions - they confuse PlacesUtils::unwrapNodes + // that expects url\ntitle formatted data for x-moz-url. + nsAutoString title(mTitleString); + title.Trim("\r\n"); + title.ReplaceChar("\r\n", ' '); + dragData += title; AddString(aDataTransfer, NS_LITERAL_STRING(kURLMime), dragData, principal); AddString(aDataTransfer, NS_LITERAL_STRING(kURLDataMime), mUrlString, principal); diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp index 558024223c84..5792b749c523 100644 --- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -34,6 +34,7 @@ #include "nsINameSpaceManager.h" #include "nsIBaseWindow.h" #include "nsISelection.h" +#include "nsITextControlElement.h" #include "nsFrameSelection.h" #include "nsPIDOMWindow.h" #include "nsPIWindowRoot.h" @@ -2795,6 +2796,16 @@ nsEventStateManager::ComputeScrollTarget(nsIFrame* aTargetFrame, continue; } + // Don't scroll vertically by mouse-wheel on a single-line text control. + if (checkIfScrollableY) { + nsIContent* c = scrollFrame->GetContent(); + nsCOMPtr ctrl = + do_QueryInterface(c->IsInAnonymousSubtree() ? c->GetBindingParent() : c); + if (ctrl && ctrl->IsSingleLineTextControl()) { + continue; + } + } + if (!checkIfScrollableX && !checkIfScrollableY) { return frameToScroll; } diff --git a/content/events/test/mochitest.ini b/content/events/test/mochitest.ini index 29d3810cc9e3..b031b8addc2d 100644 --- a/content/events/test/mochitest.ini +++ b/content/events/test/mochitest.ini @@ -87,6 +87,7 @@ skip-if = true # Disabled due to timeouts. [test_bug944847.html] skip-if = toolkit == "gonk" [test_bug944011.html] +[test_bug946632.html] [test_clickevent_on_input.html] [test_continuous_wheel_events.html] [test_dblclick_explicit_original_target.html] diff --git a/content/events/test/test_bug946632.html b/content/events/test/test_bug946632.html new file mode 100644 index 000000000000..2de34ed9517e --- /dev/null +++ b/content/events/test/test_bug946632.html @@ -0,0 +1,139 @@ + + + + + Test for bug 946632 - propagate mouse-wheel vertical scroll events to container + + + + + + +Mozilla Bug 946632 +

+
+ + x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +
+ +
+
+
+ + diff --git a/content/media/plugins/MediaPluginHost.cpp b/content/media/plugins/MediaPluginHost.cpp index 15c53005321f..7e487b87186a 100644 --- a/content/media/plugins/MediaPluginHost.cpp +++ b/content/media/plugins/MediaPluginHost.cpp @@ -152,7 +152,13 @@ static const char* GetOmxLibraryName() return nullptr; #if defined(ANDROID) && !defined(MOZ_WIDGET_GONK) - if (version == 13 || version == 12 || version == 11) { + /* + if (version >= 19) { + */ + if (version >= 16) { + return "libomxpluginkk.so"; + } + else if (version == 13 || version == 12 || version == 11) { return "libomxpluginhc.so"; } else if (version == 10 && release_version >= NS_LITERAL_STRING("2.3.6")) { @@ -180,7 +186,7 @@ static const char* GetOmxLibraryName() return nullptr; } - // Default libomxplugin for non-gingerbread devices + // Ice Cream Sandwich and Jellybean return "libomxplugin.so"; #elif defined(ANDROID) && defined(MOZ_WIDGET_GONK) diff --git a/dom/downloads/src/DownloadsAPI.js b/dom/downloads/src/DownloadsAPI.js index 56586bb99698..668c24c70af2 100644 --- a/dom/downloads/src/DownloadsAPI.js +++ b/dom/downloads/src/DownloadsAPI.js @@ -198,6 +198,7 @@ function createDOMDownloadObject(aWindow, aDownload) { function DOMDownloadImpl() { debug("DOMDownloadImpl constructor "); + this.wrappedJSObject = this; this.totalBytes = 0; this.currentBytes = 0; @@ -205,8 +206,10 @@ function DOMDownloadImpl() { this.path = null; this.state = "stopped"; this.contentType = null; - this.startTime = Date.now(); - this.error = null; + + /* fields that require getters/setters */ + this._error = null; + this._startTime = new Date(); /* private fields */ this.id = null; @@ -244,6 +247,27 @@ DOMDownloadImpl.prototype = { return this.__DOM_IMPL__.getEventHandler("onstatechange"); }, + get error() { + return this._error; + }, + + set error(aError) { + this._error = aError; + }, + + get startTime() { + return this._startTime; + }, + + set startTime(aStartTime) { + if (aStartTime instanceof Date) { + this._startTime = aStartTime; + } + else { + this._startTime = new Date(aStartTime); + } + }, + _init: function(aWindow, aDownload) { this._window = aWindow; this.id = aDownload.id; diff --git a/dom/downloads/tests/test_downloads_basic.html b/dom/downloads/tests/test_downloads_basic.html index 7efb1ed87460..c5ada1a0ea65 100644 --- a/dom/downloads/tests/test_downloads_basic.html +++ b/dom/downloads/tests/test_downloads_basic.html @@ -24,6 +24,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=938023 SimpleTest.waitForExplicitFinish(); var index = -1; +var todayDate = new Date(); +var baseServeURL = "http://mochi.test:8888/tests/dom/downloads/tests/"; +var baseDownloadPath = "/mnt/sdcard/downloads/"; +var lastKnownCurrentBytes = 0; function next() { index += 1; @@ -38,16 +42,54 @@ function next() { } } +function checkConsistentDownloadAttributes(download) { + var href = document.getElementById("download1").getAttribute("href"); + var expectedServeURL = baseServeURL + href; + var expectedDownloadPath = baseDownloadPath + "test.bin"; + + // bug 945323: Download path isn't honoring download attribute + todo(download.path === expectedDownloadPath, + "Download path = " + expectedDownloadPath); + + ok(download.startTime >= todayDate, + "Download start time should be greater than or equal to today"); + + is(download.error, null, "Download does not have an error"); + + is(download.url, expectedServeURL, + "Download URL = " + expectedServeURL); + ok(download.id !== null, "Download id is defined"); + is(download.contentType, "application/octet-stream", + "Download content type is application/octet-stream"); +} + function downloadChange(evt) { var download = evt.download; - if (download.state == "succeeded") { - ok(download.totalBytes == 1024, "Download size is 1024 bytes."); - ok(download.contentType == "application/octet-stream", - "contentType is application/octet-stream."); + checkConsistentDownloadAttributes(download); + is(download.totalBytes, 1024, "Download total size is 1024 bytes"); + + if (download.state === "succeeded") { + is(download.currentBytes, 1024, "Download current size is 1024 bytes"); SimpleTest.finish(); + } else if (download.state === "downloading") { + ok(download.currentBytes > lastKnownCurrentBytes, + "Download current size is larger than last download change event"); + lastKnownCurrentBytes = download.currentBytes; + } else { + ok(false, "Unexpected download state = " + download.state); } } +function downloadStart(evt) { + var download = evt.download; + checkConsistentDownloadAttributes(download); + + is(download.currentBytes, 0, "Download current size is zero"); + is(download.state, "downloading", "Download state is downloading"); + + download.onstatechange = downloadChange; +} + var steps = [ // Start by setting the pref to true. function() { @@ -61,11 +103,7 @@ var steps = [ SpecialPowers.pushPermissions([ {type: "downloads", allow: true, context: document} ], function() { - navigator.mozDownloadManager.ondownloadstart = - function(evt) { - ok(true, "Download started"); - evt.download.addEventListener("statechange", downloadChange); - } + navigator.mozDownloadManager.ondownloadstart = downloadStart; next(); }); }, @@ -82,3 +120,4 @@ next(); + diff --git a/dom/indexedDB/ipc/IndexedDBParent.cpp b/dom/indexedDB/ipc/IndexedDBParent.cpp index ca23d65f3026..886530fca22a 100644 --- a/dom/indexedDB/ipc/IndexedDBParent.cpp +++ b/dom/indexedDB/ipc/IndexedDBParent.cpp @@ -131,7 +131,7 @@ IndexedDBParent::CloneProtocol(Channel* aChannel, bool IndexedDBParent::CheckPermissionInternal(const nsAString& aDatabaseName, - const nsDependentCString& aPermission) + const nsACString& aPermission) { MOZ_ASSERT(!mASCIIOrigin.IsEmpty()); MOZ_ASSERT(mManagerContent || mManagerTab); diff --git a/dom/indexedDB/ipc/IndexedDBParent.h b/dom/indexedDB/ipc/IndexedDBParent.h index 2df96af82f77..c778f5b4052f 100644 --- a/dom/indexedDB/ipc/IndexedDBParent.h +++ b/dom/indexedDB/ipc/IndexedDBParent.h @@ -201,7 +201,7 @@ public: protected: bool CheckPermissionInternal(const nsAString& aDatabaseName, - const nsDependentCString& aPermission); + const nsACString& aPermission); virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index ba105b1fe824..8ecec17bdbec 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -611,7 +611,7 @@ TabChild::HandlePossibleViewportChange() // The page must have been refreshed in some way such as a new document or // new CSS viewport, so we know that there's no velocity, acceleration, and // we have no idea how long painting will take. - metrics, gfx::Point(0.0f, 0.0f), gfx::Point(0.0f, 0.0f), 0.0); + metrics, ScreenPoint(0.0f, 0.0f), gfx::Point(0.0f, 0.0f), 0.0); metrics.mCumulativeResolution = metrics.mZoom / metrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1); // This is the root layer, so the cumulative resolution is the same // as the resolution. diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index a72f3599e192..4e66f8c07c66 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -754,6 +754,16 @@ static SourceSet * class GetUserMediaRunnable : public nsRunnable { public: + /** + * GetUserMediaRunnable is meant for dispatch off main thread, where it would + * be illegal to free JS callbacks. Therefore, it uses a rather risky strategy + * of holding "already_AddRefed" references to the JS callbacks that must be + * transfered and released in consequent dispatches arriving on main thread. + * + * A special Arm() method must be called before dispatch to enable this + * behavior, because GetUserMediaRunnables are held in other circumstances. + */ + GetUserMediaRunnable( const MediaStreamConstraintsInternal& aConstraints, already_AddRefed aSuccess, @@ -761,8 +771,10 @@ public: uint64_t aWindowID, GetUserMediaCallbackMediaStreamListener *aListener, MediaEnginePrefs &aPrefs) : mConstraints(aConstraints) - , mSuccess(aSuccess) - , mError(aError) + , mSuccess(nullptr) + , mError(nullptr) + , mSuccessHolder(aSuccess) + , mErrorHolder(aError) , mWindowID(aWindowID) , mListener(aListener) , mPrefs(aPrefs) @@ -783,8 +795,10 @@ public: MediaEnginePrefs &aPrefs, MediaEngine* aBackend) : mConstraints(aConstraints) - , mSuccess(aSuccess) - , mError(aError) + , mSuccess(nullptr) + , mError(nullptr) + , mSuccessHolder(aSuccess) + , mErrorHolder(aError) , mWindowID(aWindowID) , mListener(aListener) , mPrefs(aPrefs) @@ -800,10 +814,24 @@ public: } } + /** + * Once "armed", GetUserMediaRunnable will leak its JS callbacks if destroyed. + * Arm() must be called before the runnable can be dispatched or used, and the + * runnable must be dispatched or used once armed. Callbacks get released on + * the main thread at the runnable's completion. + */ + void + Arm() { + mSuccess = mSuccessHolder.forget(); + mError = mErrorHolder.forget(); + } + NS_IMETHOD Run() { NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread"); + MOZ_ASSERT(mSuccess.mRawPtr); + MOZ_ASSERT(mError.mRawPtr); // Was a backend provided? if (!mBackendChosen) { @@ -842,8 +870,11 @@ public: nsresult Denied(const nsAString& aErrorMsg) { - // We add a disabled listener to the StreamListeners array until accepted - // If this was the only active MediaStream, remove the window from the list. + MOZ_ASSERT(mSuccess.mRawPtr); + MOZ_ASSERT(mError.mRawPtr); + + // We add a disabled listener to the StreamListeners array until accepted + // If this was the only active MediaStream, remove the window from the list. if (NS_IsMainThread()) { // This is safe since we're on main-thread, and the window can only // be invalidated from the main-thread (see OnNavigation) @@ -886,6 +917,8 @@ public: nsresult SelectDevice() { + MOZ_ASSERT(mSuccess.mRawPtr); + MOZ_ASSERT(mError.mRawPtr); if (mConstraints.mPicture || mConstraints.mVideo) { ScopedDeletePtr sources (GetSources(mBackend, mConstraints.mVideom, &MediaEngine::EnumerateVideoDevices)); @@ -924,6 +957,8 @@ public: void ProcessGetUserMedia(MediaEngineSource* aAudioSource, MediaEngineSource* aVideoSource) { + MOZ_ASSERT(mSuccess.mRawPtr); + MOZ_ASSERT(mError.mRawPtr); nsresult rv; if (aAudioSource) { rv = aAudioSource->Allocate(mPrefs); @@ -962,6 +997,8 @@ public: void ProcessGetUserMediaSnapshot(MediaEngineSource* aSource, int aDuration) { + MOZ_ASSERT(mSuccess.mRawPtr); + MOZ_ASSERT(mError.mRawPtr); nsresult rv = aSource->Allocate(mPrefs); if (NS_FAILED(rv)) { NS_DispatchToMainThread(new ErrorCallbackRunnable( @@ -988,6 +1025,8 @@ private: already_AddRefed mSuccess; already_AddRefed mError; + nsCOMPtr mSuccessHolder; + nsCOMPtr mErrorHolder; uint64_t mWindowID; nsRefPtr mListener; nsRefPtr mAudioDevice; @@ -1296,7 +1335,6 @@ MediaManager::GetUserMedia(JSContext* aCx, bool aPrivileged, // Store the WindowID in a hash table and mark as active. The entry is removed // when this window is closed or navigated away from. uint64_t windowID = aWindow->WindowID(); - nsRefPtr gUMRunnable; // This is safe since we're on main-thread, and the windowlist can only // be invalidated from the main-thread (see OnNavigation) StreamListeners* listeners = GetActiveWindows()->Get(windowID); @@ -1340,17 +1378,15 @@ MediaManager::GetUserMedia(JSContext* aCx, bool aPrivileged, c.mVideo = false; } - /** - * Pass runnables along to GetUserMediaRunnable so it can add the - * MediaStreamListener to the runnable list. - */ + // Pass callbacks and MediaStreamListener along to GetUserMediaRunnable. + nsRefPtr runnable; if (c.mFake) { // Fake stream from default backend. - gUMRunnable = new GetUserMediaRunnable(c, onSuccess.forget(), + runnable = new GetUserMediaRunnable(c, onSuccess.forget(), onError.forget(), windowID, listener, mPrefs, new MediaEngineDefault()); } else { // Stream from default device from WebRTC backend. - gUMRunnable = new GetUserMediaRunnable(c, onSuccess.forget(), + runnable = new GetUserMediaRunnable(c, onSuccess.forget(), onError.forget(), windowID, listener, mPrefs); } @@ -1363,13 +1399,15 @@ MediaManager::GetUserMedia(JSContext* aCx, bool aPrivileged, #if defined(ANDROID) && !defined(MOZ_WIDGET_GONK) if (c.mPicture) { // ShowFilePickerForMimeType() must run on the Main Thread! (on Android) - NS_DispatchToMainThread(gUMRunnable); + runnable->Arm(); + NS_DispatchToMainThread(runnable); return NS_OK; } #endif // XXX No full support for picture in Desktop yet (needs proper UI) if (aPrivileged || c.mFake) { - mMediaThread->Dispatch(gUMRunnable, NS_DISPATCH_NORMAL); + runnable->Arm(); + mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL); } else { // Ask for user permission, and dispatch runnable (or not) when a response // is received via an observer notification. Each call is paired with its @@ -1388,9 +1426,18 @@ MediaManager::GetUserMedia(JSContext* aCx, bool aPrivileged, id.ToProvidedString(buffer); NS_ConvertUTF8toUTF16 callID(buffer); - // Store the current callback. - mActiveCallbacks.Put(callID, gUMRunnable); + // Store the current unarmed runnable w/callbacks. + mActiveCallbacks.Put(callID, runnable); + // Add a WindowID cross-reference so OnNavigation can tear things down + nsTArray* array; + if (!mCallIds.Get(windowID, &array)) { + array = new nsTArray(); + array->AppendElement(callID); + mCallIds.Put(windowID, array); + } else { + array->AppendElement(callID); + } nsCOMPtr obs = services::GetObserverService(); nsRefPtr req = new GetUserMediaRequest(aWindow, callID, c); @@ -1471,6 +1518,14 @@ MediaManager::OnNavigation(uint64_t aWindowID) // Invalidate this window. The runnables check this value before making // a call to content. + nsTArray* callIds; + if (mCallIds.Get(aWindowID, &callIds)) { + for (int i = 0, len = callIds->Length(); i < len; ++i) { + mActiveCallbacks.Remove((*callIds)[i]); + } + mCallIds.Remove(aWindowID); + } + // This is safe since we're on main-thread, and the windowlist can only // be added to from the main-thread StreamListeners* listeners = GetWindowListeners(aWindowID); @@ -1606,6 +1661,7 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic, MutexAutoLock lock(mMutex); GetActiveWindows()->Clear(); mActiveCallbacks.Clear(); + mCallIds.Clear(); LOG(("Releasing MediaManager singleton and thread")); sSingleton = nullptr; } @@ -1614,25 +1670,24 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic, } else if (!strcmp(aTopic, "getUserMedia:response:allow")) { nsString key(aData); - nsRefPtr runnable; + nsRefPtr runnable; if (!mActiveCallbacks.Get(key, getter_AddRefs(runnable))) { return NS_OK; } mActiveCallbacks.Remove(key); + runnable->Arm(); if (aSubject) { // A particular device or devices were chosen by the user. // NOTE: does not allow setting a device to null; assumes nullptr - GetUserMediaRunnable* gUMRunnable = - static_cast(runnable.get()); - nsCOMPtr array(do_QueryInterface(aSubject)); MOZ_ASSERT(array); uint32_t len = 0; array->Count(&len); MOZ_ASSERT(len); if (!len) { - gUMRunnable->Denied(NS_LITERAL_STRING("PERMISSION_DENIED")); // neither audio nor video were selected + // neither audio nor video were selected + runnable->Denied(NS_LITERAL_STRING("PERMISSION_DENIED")); return NS_OK; } for (uint32_t i = 0; i < len; i++) { @@ -1644,9 +1699,9 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic, nsString type; device->GetType(type); if (type.EqualsLiteral("video")) { - gUMRunnable->SetVideoDevice(static_cast(device.get())); + runnable->SetVideoDevice(static_cast(device.get())); } else if (type.EqualsLiteral("audio")) { - gUMRunnable->SetAudioDevice(static_cast(device.get())); + runnable->SetAudioDevice(static_cast(device.get())); } else { NS_WARNING("Unknown device type in getUserMedia"); } @@ -1670,15 +1725,13 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic, } nsString key(aData); - nsRefPtr runnable; + nsRefPtr runnable; if (!mActiveCallbacks.Get(key, getter_AddRefs(runnable))) { return NS_OK; } mActiveCallbacks.Remove(key); - - GetUserMediaRunnable* gUMRunnable = - static_cast(runnable.get()); - gUMRunnable->Denied(errorMessage); + runnable->Arm(); + runnable->Denied(errorMessage); return NS_OK; } else if (!strcmp(aTopic, "getUserMedia:revoke")) { diff --git a/dom/media/MediaManager.h b/dom/media/MediaManager.h index f326119db671..2a4de143f5b7 100644 --- a/dom/media/MediaManager.h +++ b/dom/media/MediaManager.h @@ -241,6 +241,7 @@ typedef enum { } MediaOperation; class MediaManager; +class GetUserMediaRunnable; /** * Send an error back to content. The error is the form a string. @@ -524,7 +525,8 @@ private: // ONLY access from MainThread so we don't need to lock WindowTable mActiveWindows; - nsRefPtrHashtable mActiveCallbacks; + nsRefPtrHashtable mActiveCallbacks; + nsClassHashtable> mCallIds; // Always exists nsCOMPtr mMediaThread; diff --git a/dom/src/geolocation/nsGeolocation.cpp b/dom/src/geolocation/nsGeolocation.cpp index 07842b75b184..995aa39009eb 100644 --- a/dom/src/geolocation/nsGeolocation.cpp +++ b/dom/src/geolocation/nsGeolocation.cpp @@ -80,6 +80,7 @@ class nsGeolocationRequest void SendLocation(nsIDOMGeoPosition* location); bool WantsHighAccuracy() {return !mShutdown && mOptions && mOptions->mEnableHighAccuracy;} void SetTimeoutTimer(); + void StopTimeoutTimer(); void NotifyErrorAndShutdown(uint16_t); nsIPrincipal* GetPrincipal(); @@ -348,6 +349,7 @@ NS_IMPL_CYCLE_COLLECTION_3(nsGeolocationRequest, mCallback, mErrorCallback, mLoc NS_IMETHODIMP nsGeolocationRequest::Notify(nsITimer* aTimer) { + StopTimeoutTimer(); NotifyErrorAndShutdown(nsIDOMGeoPositionError::TIMEOUT); return NS_OK; } @@ -363,10 +365,6 @@ nsGeolocationRequest::NotifyErrorAndShutdown(uint16_t aErrorCode) } NotifyError(aErrorCode); - - if (!mShutdown) { - SetTimeoutTimer(); - } } NS_IMETHODIMP @@ -475,10 +473,7 @@ nsGeolocationRequest::Allow() void nsGeolocationRequest::SetTimeoutTimer() { - if (mTimeoutTimer) { - mTimeoutTimer->Cancel(); - mTimeoutTimer = nullptr; - } + StopTimeoutTimer(); int32_t timeout; if (mOptions && (timeout = mOptions->mTimeout) != 0) { @@ -494,6 +489,15 @@ nsGeolocationRequest::SetTimeoutTimer() } } +void +nsGeolocationRequest::StopTimeoutTimer() +{ + if (mTimeoutTimer) { + mTimeoutTimer->Cancel(); + mTimeoutTimer = nullptr; + } +} + void nsGeolocationRequest::SendLocation(nsIDOMGeoPosition* aPosition) { @@ -539,12 +543,9 @@ nsGeolocationRequest::SendLocation(nsIDOMGeoPosition* aPosition) callback->HandleEvent(aPosition); } - if (!mShutdown) { - // For watch requests, the handler may have called clearWatch - MOZ_ASSERT(mIsWatchPositionRequest, - "non-shutdown getCurrentPosition request after callback!"); - SetTimeoutTimer(); - } + StopTimeoutTimer(); + MOZ_ASSERT(mShutdown || mIsWatchPositionRequest, + "non-shutdown getCurrentPosition request after callback!"); } nsIPrincipal* @@ -564,6 +565,16 @@ nsGeolocationRequest::Update(nsIDOMGeoPosition* aPosition) return NS_OK; } +NS_IMETHODIMP +nsGeolocationRequest::LocationUpdatePending() +{ + if (!mTimeoutTimer) { + SetTimeoutTimer(); + } + + return NS_OK; +} + NS_IMETHODIMP nsGeolocationRequest::NotifyError(uint16_t aErrorCode) { @@ -809,6 +820,16 @@ nsGeolocationService::Update(nsIDOMGeoPosition *aSomewhere) return NS_OK; } +NS_IMETHODIMP +nsGeolocationService::LocationUpdatePending() +{ + for (uint32_t i = 0; i< mGeolocators.Length(); i++) { + mGeolocators[i]->LocationUpdatePending(); + } + + return NS_OK; +} + NS_IMETHODIMP nsGeolocationService::NotifyError(uint16_t aErrorCode) { @@ -1130,6 +1151,17 @@ Geolocation::Update(nsIDOMGeoPosition *aSomewhere) return NS_OK; } +NS_IMETHODIMP +Geolocation::LocationUpdatePending() +{ + // this event is only really interesting for watch callbacks + for (uint32_t i = 0; i < mWatchingCallbacks.Length(); i++) { + mWatchingCallbacks[i]->LocationUpdatePending(); + } + + return NS_OK; +} + NS_IMETHODIMP Geolocation::NotifyError(uint16_t aErrorCode) { diff --git a/dom/system/NetworkGeolocationProvider.js b/dom/system/NetworkGeolocationProvider.js index 144cd8f9765d..c8621cf87cae 100755 --- a/dom/system/NetworkGeolocationProvider.js +++ b/dom/system/NetworkGeolocationProvider.js @@ -143,6 +143,9 @@ WifiGeoPositionProvider.prototype = { LOG("onChange called, highAccuracy = " + (this.highAccuracy?"TRUE":"FALSE")); this.hasSeenWiFi = true; + Cc["@mozilla.org/geolocation/service;1"].getService(Ci.nsIGeolocationUpdate) + .locationUpdatePending(); + let url = Services.urlFormatter.formatURLPref("geo.wifi.uri"); function isPublic(ap) { diff --git a/dom/system/mac/CoreLocationLocationProvider.h b/dom/system/mac/CoreLocationLocationProvider.h index eea71fbd879b..98e5d0ecc771 100644 --- a/dom/system/mac/CoreLocationLocationProvider.h +++ b/dom/system/mac/CoreLocationLocationProvider.h @@ -24,16 +24,16 @@ class CoreLocationObjects; class CoreLocationLocationProvider : public nsIGeolocationProvider - , public nsIGeolocationUpdate { public: NS_DECL_ISUPPORTS - NS_DECL_NSIGEOLOCATIONUPDATE NS_DECL_NSIGEOLOCATIONPROVIDER CoreLocationLocationProvider(); static bool IsCoreLocationAvailable(); + void NotifyError(uint16_t aErrorCode); + void Update(nsIDOMGeoPosition* aSomewhere); private: virtual ~CoreLocationLocationProvider() {}; diff --git a/dom/system/mac/CoreLocationLocationProvider.mm b/dom/system/mac/CoreLocationLocationProvider.mm index 84d07352eaa1..582bd79a9600 100644 --- a/dom/system/mac/CoreLocationLocationProvider.mm +++ b/dom/system/mac/CoreLocationLocationProvider.mm @@ -218,19 +218,16 @@ CoreLocationLocationProvider::SetHighAccuracy(bool aEnable) return NS_OK; } -NS_IMETHODIMP +void CoreLocationLocationProvider::Update(nsIDOMGeoPosition* aSomewhere) { if (aSomewhere && mCallback) { mCallback->Update(aSomewhere); } - - return NS_OK; } -NS_IMETHODIMP +void CoreLocationLocationProvider::NotifyError(uint16_t aErrorCode) { mCallback->NotifyError(aErrorCode); - return NS_OK; } diff --git a/dom/webidl/Downloads.webidl b/dom/webidl/Downloads.webidl index e547868991b3..862e3b807c3f 100644 --- a/dom/webidl/Downloads.webidl +++ b/dom/webidl/Downloads.webidl @@ -59,7 +59,7 @@ interface DOMDownload : EventTarget { // A DOM error object, that will be not null when a download is stopped // because something failed. - readonly attribute DOMError error; + readonly attribute DOMError? error; // Pauses the download. Promise pause(); diff --git a/gfx/cairo/cairo/src/cairo-win32-surface.c b/gfx/cairo/cairo/src/cairo-win32-surface.c index e14705b22355..3a3d82989b9e 100644 --- a/gfx/cairo/cairo/src/cairo-win32-surface.c +++ b/gfx/cairo/cairo/src/cairo-win32-surface.c @@ -502,6 +502,16 @@ _cairo_win32_surface_finish (void *abstract_surface) return CAIRO_STATUS_SUCCESS; } +static void +get_d3d9_dc_and_clear_clip (cairo_win32_surface_t *surface) +{ + IDirect3DSurface9_GetDC (surface->d3d9surface, &surface->dc); + // The DC that we get back from the surface will not have + // a clip so clear surface->clip_region so that we don't think we have + // one when we don't. + _cairo_win32_surface_set_clip_region (surface, NULL); +} + static cairo_status_t _cairo_win32_surface_d3d9_lock_rect (cairo_win32_surface_t *surface, int x, @@ -521,7 +531,7 @@ _cairo_win32_surface_d3d9_lock_rect (cairo_win32_surface_t *surface, &rectout, &rectin, 0); surface->dc = 0; // Don't use the DC when this is locked! if (hr) { - IDirect3DSurface9_GetDC (surface->d3d9surface, &surface->dc); + get_d3d9_dc_and_clear_clip (surface); return CAIRO_INT_STATUS_UNSUPPORTED; } local = cairo_image_surface_create_for_data (rectout.pBits, @@ -530,12 +540,12 @@ _cairo_win32_surface_d3d9_lock_rect (cairo_win32_surface_t *surface, rectout.Pitch); if (local == NULL) { IDirect3DSurface9_UnlockRect (surface->d3d9surface); - IDirect3DSurface9_GetDC (surface->d3d9surface, &surface->dc); + get_d3d9_dc_and_clear_clip (surface); return CAIRO_INT_STATUS_UNSUPPORTED; } if (local->base.status) { IDirect3DSurface9_UnlockRect (surface->d3d9surface); - IDirect3DSurface9_GetDC (surface->d3d9surface, &surface->dc); + get_d3d9_dc_and_clear_clip (surface); return local->base.status; } @@ -709,7 +719,7 @@ _cairo_win32_surface_release_source_image (void *abstract_surf if (local && local->d3d9surface) { IDirect3DSurface9_UnlockRect (local->d3d9surface); - IDirect3DSurface9_GetDC (local->d3d9surface, &local->dc); + get_d3d9_dc_and_clear_clip (surface); cairo_surface_destroy ((cairo_surface_t *)image); } else { cairo_surface_destroy ((cairo_surface_t *)local); @@ -784,7 +794,7 @@ _cairo_win32_surface_release_dest_image (void *abstract_surfa if (local->d3d9surface) { IDirect3DSurface9_UnlockRect (local->d3d9surface); - IDirect3DSurface9_GetDC (local->d3d9surface, &local->dc); + get_d3d9_dc_and_clear_clip (surface); cairo_surface_destroy ((cairo_surface_t *)image); } else { diff --git a/gfx/layers/RotatedBuffer.cpp b/gfx/layers/RotatedBuffer.cpp index 2e88200539b5..0745821b7e40 100644 --- a/gfx/layers/RotatedBuffer.cpp +++ b/gfx/layers/RotatedBuffer.cpp @@ -154,8 +154,6 @@ RotatedBuffer::DrawBufferQuadrant(gfx::DrawTarget* aTarget, if (aOperator == OP_SOURCE) { aTarget->PopClip(); } - - aTarget->Flush(); } void @@ -391,6 +389,17 @@ ComputeBufferRect(const nsIntRect& aRequestedRect) return rect; } +void +RotatedContentBuffer::FlushBuffers() +{ + if (mDTBuffer) { + mDTBuffer->Flush(); + } + if (mDTBufferOnWhite) { + mDTBufferOnWhite->Flush(); + } +} + RotatedContentBuffer::PaintState RotatedContentBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType, uint32_t aFlags) diff --git a/gfx/layers/RotatedBuffer.h b/gfx/layers/RotatedBuffer.h index a371f1ce9b34..2dbeeeda5a28 100644 --- a/gfx/layers/RotatedBuffer.h +++ b/gfx/layers/RotatedBuffer.h @@ -75,6 +75,8 @@ public: BUFFER_WHITE, // The buffer with white background, only valid with component alpha. BUFFER_BOTH // The combined black/white buffers, only valid for writing operations, not reading. }; + // It is the callers repsonsibility to ensure aTarget is flushed after calling + // this method. void DrawBufferWithRotation(gfx::DrawTarget* aTarget, ContextSource aSource, float aOpacity = 1.0, gfx::CompositionOp aOperator = gfx::OP_OVER, @@ -396,6 +398,10 @@ protected: */ bool EnsureBuffer(); bool EnsureBufferOnWhite(); + + // Flush our buffers if they are mapped. + void FlushBuffers(); + /** * True if we have a buffer where we can get it (but not necessarily * mapped currently). diff --git a/gfx/layers/client/ContentClient.cpp b/gfx/layers/client/ContentClient.cpp index b9ed4a01a66d..bba3f54fe5b0 100644 --- a/gfx/layers/client/ContentClient.cpp +++ b/gfx/layers/client/ContentClient.cpp @@ -598,6 +598,8 @@ ContentClientDoubleBuffered::SyncFrontBufferToBackBuffer() mFrontBufferRect, mFrontBufferRotation); UpdateDestinationFrom(frontBuffer, updateRegion); + // We need to flush our buffers before we unlock our front textures + FlushBuffers(); mFrontClient->Unlock(); if (mFrontClientOnWhite) { mFrontClientOnWhite->Unlock(); @@ -816,6 +818,9 @@ DeprecatedContentClientDoubleBuffered::SyncFrontBufferToBackBuffer() mFrontBufferRotation); UpdateDestinationFrom(frontBuffer, updateRegion); + // We need to flush our buffers before we unlock our front textures + FlushBuffers(); + mFrontAndBackBufferDiffer = false; } diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index 07bd1d6620f4..58e5582aae72 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -168,10 +168,10 @@ static int32_t gPanRepaintInterval = 250; static int32_t gFlingRepaintInterval = 75; /** - * Minimum amount of speed along an axis before we begin painting far ahead by - * adjusting the displayport. + * Minimum amount of speed along an axis before we switch to "skate" multipliers + * rather than using the "stationary" multipliers. */ -static float gMinSkateSpeed = 0.7f; +static float gMinSkateSpeed = 1.0f; /** * Duration of a zoom to animation. @@ -207,22 +207,26 @@ static int gTouchListenerTimeout = 300; */ static int gNumPaintDurationSamples = 3; -/** The multiplier we apply to a dimension's length if it is skating. That is, - * if it's going above sMinSkateSpeed. We prefer to increase the size of the +/** + * The multiplier we apply to the displayport size if it is skating (current + * velocity is above gMinSkateSpeed). We prefer to increase the size of the * Y axis because it is more natural in the case that a user is reading a page * that scrolls up/down. Note that one, both or neither of these may be used * at any instant. + * In general we want g[XY]SkateSizeMultiplier to be smaller than the corresponding + * stationary size multiplier because when panning fast we would like to paint + * less and get faster, more predictable paint times. When panning slowly we + * can afford to paint more even though it's slower. */ -static float gXSkateSizeMultiplier = 3.0f; -static float gYSkateSizeMultiplier = 3.5f; +static float gXSkateSizeMultiplier = 1.5f; +static float gYSkateSizeMultiplier = 2.5f; -/** The multiplier we apply to a dimension's length if it is stationary. We - * prefer to increase the size of the Y axis because it is more natural in the - * case that a user is reading a page that scrolls up/down. Note that one, - * both or neither of these may be used at any instant. +/** + * The multiplier we apply to the displayport size if it is not skating (see + * documentation for gXSkateSizeMultiplier). */ -static float gXStationarySizeMultiplier = 1.5f; -static float gYStationarySizeMultiplier = 2.5f; +static float gXStationarySizeMultiplier = 3.0f; +static float gYStationarySizeMultiplier = 3.5f; /** * The time period in ms that throttles mozbrowserasyncscroll event. @@ -931,8 +935,8 @@ float AsyncPanZoomController::PanDistance() { return NS_hypot(mX.PanDistance(), mY.PanDistance()); } -const gfx::Point AsyncPanZoomController::GetVelocityVector() { - return gfx::Point(mX.GetVelocity(), mY.GetVelocity()); +const ScreenPoint AsyncPanZoomController::GetVelocityVector() { + return ScreenPoint(mX.GetVelocity(), mY.GetVelocity()); } const gfx::Point AsyncPanZoomController::GetAccelerationVector() { @@ -1159,103 +1163,65 @@ void AsyncPanZoomController::ScaleWithFocus(float aScale, mFrameMetrics.mScrollOffset = (mFrameMetrics.mScrollOffset + aFocus) - (aFocus / aScale); } -bool AsyncPanZoomController::EnlargeDisplayPortAlongAxis(float aSkateSizeMultiplier, - double aEstimatedPaintDuration, - float aCompositionBounds, - float aVelocity, - float aAcceleration, - float* aDisplayPortOffset, - float* aDisplayPortLength) +/** + * Attempts to enlarge the displayport along a single axis based on the + * velocity. aOffset and aLength are in/out parameters; they are initially set + * to the currently visible area and will be transformed to the area we should + * be drawing to minimize checkerboarding. + */ +static void +EnlargeDisplayPortAlongAxis(float* aOutOffset, float* aOutLength, + double aEstimatedPaintDurationMillis, float aVelocity, + float aStationarySizeMultiplier, float aSkateSizeMultiplier) { - if (fabsf(aVelocity) > gMinSkateSpeed) { - // Enlarge the area we paint. - *aDisplayPortLength = aCompositionBounds * aSkateSizeMultiplier; - // Position the area we paint such that all of the excess that extends past - // the screen is on the side towards the velocity. - *aDisplayPortOffset = aVelocity > 0 ? 0 : aCompositionBounds - *aDisplayPortLength; + // Scale up the length using the appropriate multiplier and center the + // displayport around the visible area. + float multiplier = (fabsf(aVelocity) < gMinSkateSpeed + ? aStationarySizeMultiplier + : aSkateSizeMultiplier); + float newLength = (*aOutLength) * multiplier; + *aOutOffset -= (newLength - (*aOutLength)) / 2; + *aOutLength = newLength; - // Only compensate for acceleration when we actually have any. Otherwise - // we'll overcompensate when a user is just panning around without flinging. - if (aAcceleration > 1.01f) { - // Compensate for acceleration and how long we expect a paint to take. We - // try to predict where the viewport will be when painting has finished. - *aDisplayPortOffset += - fabsf(aAcceleration) * aVelocity * aCompositionBounds * aEstimatedPaintDuration; - // If our velocity is in the negative direction of the axis, we have to - // compensate for the fact that our scroll offset is the top-left position - // of the viewport. In this case, let's make it relative to the - // bottom-right. That way, we'll always be growing the displayport upwards - // and to the left when skating negatively. - *aDisplayPortOffset -= aVelocity < 0 ? aCompositionBounds : 0; - } - return true; - } - return false; + // Project the displayport out based on the estimated time it will take to paint + *aOutOffset += (aVelocity * aEstimatedPaintDurationMillis); } +/* static */ const CSSRect AsyncPanZoomController::CalculatePendingDisplayPort( const FrameMetrics& aFrameMetrics, - const gfx::Point& aVelocity, + const ScreenPoint& aVelocity, const gfx::Point& aAcceleration, double aEstimatedPaintDuration) { - // If we don't get an estimated paint duration, we probably don't have any - // data. In this case, we're dealing with either a stationary frame or a first - // paint. In either of these cases, we can just assume it'll take 1 second to - // paint. Getting this correct is not important anyways since it's only really - // useful when accelerating, which can't be happening at this point. - double estimatedPaintDuration = - aEstimatedPaintDuration > EPSILON ? aEstimatedPaintDuration : 1.0; + // convert to milliseconds + double estimatedPaintDurationMillis = aEstimatedPaintDuration * 1000; - CSSIntRect compositionBounds = gfx::RoundedIn(aFrameMetrics.mCompositionBounds / aFrameMetrics.mZoom); + CSSRect compositionBounds = aFrameMetrics.CalculateCompositedRectInCssPixels(); + CSSPoint scrollOffset = aFrameMetrics.mScrollOffset; + CSSRect displayPort(scrollOffset, compositionBounds.Size()); + CSSPoint velocity = aVelocity / aFrameMetrics.mZoom; + + // Enlarge the displayport along both axes depending on how fast we're moving + // on that axis and how long it takes to paint. Apply some heuristics to try + // to minimize checkerboarding. + EnlargeDisplayPortAlongAxis(&(displayPort.x), &(displayPort.width), + estimatedPaintDurationMillis, velocity.x, + gXStationarySizeMultiplier, gXSkateSizeMultiplier); + EnlargeDisplayPortAlongAxis(&(displayPort.y), &(displayPort.height), + estimatedPaintDurationMillis, velocity.y, + gYStationarySizeMultiplier, gYSkateSizeMultiplier); CSSRect scrollableRect = aFrameMetrics.GetExpandedScrollableRect(); - CSSPoint scrollOffset = aFrameMetrics.mScrollOffset; + displayPort = displayPort.ForceInside(scrollableRect) - scrollOffset; - CSSRect displayPort = CSSRect(compositionBounds); - displayPort.MoveTo(0, 0); - displayPort.Scale(gXStationarySizeMultiplier, gYStationarySizeMultiplier); + APZC_LOG_FM(aFrameMetrics, + "Calculated displayport as (%f %f %f %f) from velocity (%f %f) acceleration (%f %f) paint time %f metrics", + displayPort.x, displayPort.y, displayPort.width, displayPort.height, + aVelocity.x, aVelocity.y, aAcceleration.x, aAcceleration.y, + (float)estimatedPaintDurationMillis); - // If there's motion along an axis of movement, and it's above a threshold, - // then we want to paint a larger area in the direction of that motion so that - // it's less likely to checkerboard. - bool enlargedX = EnlargeDisplayPortAlongAxis( - gXSkateSizeMultiplier, estimatedPaintDuration, - compositionBounds.width, aVelocity.x, aAcceleration.x, - &displayPort.x, &displayPort.width); - bool enlargedY = EnlargeDisplayPortAlongAxis( - gYSkateSizeMultiplier, estimatedPaintDuration, - compositionBounds.height, aVelocity.y, aAcceleration.y, - &displayPort.y, &displayPort.height); - - if (!enlargedX && !enlargedY) { - // Position the x and y such that the screen falls in the middle of the displayport. - displayPort.x = -(displayPort.width - compositionBounds.width) / 2; - displayPort.y = -(displayPort.height - compositionBounds.height) / 2; - } else if (!enlargedX) { - displayPort.width = compositionBounds.width; - } else if (!enlargedY) { - displayPort.height = compositionBounds.height; - } - - // If we go over the bounds when trying to predict where we will be when this - // paint finishes, move it back into the range of the CSS content rect. - // FIXME/bug 780395: Generalize this. This code is pretty hacky as it will - // probably not work at all for RTL content. This is not intended to be - // incredibly accurate; it'll just prevent the entire displayport from being - // outside the content rect (which causes bad things to happen). - if (scrollOffset.x + compositionBounds.width > scrollableRect.width) { - scrollOffset.x -= compositionBounds.width + scrollOffset.x - scrollableRect.width; - } else if (scrollOffset.x < scrollableRect.x) { - scrollOffset.x = scrollableRect.x; - } - if (scrollOffset.y + compositionBounds.height > scrollableRect.height) { - scrollOffset.y -= compositionBounds.height + scrollOffset.y - scrollableRect.height; - } else if (scrollOffset.y < scrollableRect.y) { - scrollOffset.y = scrollableRect.y; - } - - return displayPort.ForceInside(scrollableRect - scrollOffset); + return displayPort; } void AsyncPanZoomController::ScheduleComposite() { @@ -1598,7 +1564,7 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) { endZoomToMetrics.mScrollOffset = aRect.TopLeft(); endZoomToMetrics.mDisplayPort = CalculatePendingDisplayPort(endZoomToMetrics, - gfx::Point(0,0), + ScreenPoint(0,0), gfx::Point(0,0), 0); diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index 21f2bd24d5cf..3d67f5694035 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -229,7 +229,7 @@ public: */ static const CSSRect CalculatePendingDisplayPort( const FrameMetrics& aFrameMetrics, - const gfx::Point& aVelocity, + const ScreenPoint& aVelocity, const gfx::Point& aAcceleration, double aEstimatedPaintDuration); @@ -408,7 +408,7 @@ protected: /** * Gets a vector of the velocities of each axis. */ - const gfx::Point GetVelocityVector(); + const ScreenPoint GetVelocityVector(); /** * Gets a vector of the acceleration factors of each axis. @@ -439,22 +439,6 @@ protected: */ void TrackTouch(const MultiTouchInput& aEvent); - /** - * Attempts to enlarge the displayport along a single axis. Returns whether or - * not the displayport was enlarged. This will fail in circumstances where the - * velocity along that axis is not high enough to need any changes. The - * displayport metrics are expected to be passed into |aDisplayPortOffset| and - * |aDisplayPortLength|. If enlarged, these will be updated with the new - * metrics. - */ - static bool EnlargeDisplayPortAlongAxis(float aSkateSizeMultiplier, - double aEstimatedPaintDuration, - float aCompositionBounds, - float aVelocity, - float aAcceleration, - float* aDisplayPortOffset, - float* aDisplayPortLength); - /** * Utility function to send updated FrameMetrics to Gecko so that it can paint * the displayport area. Calls into GeckoContentController to do the actual diff --git a/image/public/ImageLogging.h b/image/public/ImageLogging.h index 55291a113ba1..f40009b209bf 100644 --- a/image/public/ImageLogging.h +++ b/image/public/ImageLogging.h @@ -29,111 +29,98 @@ extern PRLogModuleInfo *GetImgLog(); class LogScope { public: - LogScope(PRLogModuleInfo *aLog, void *from, const nsACString &fn) : + LogScope(PRLogModuleInfo *aLog, void *from, const char *fn) : mLog(aLog), mFrom(from), mFunc(fn) { PR_LOG(mLog, PR_LOG_DEBUG, ("%d [this=%p] %s {ENTER}\n", - GIVE_ME_MS_NOW(), - mFrom, mFunc.get())); + GIVE_ME_MS_NOW(), mFrom, mFunc)); } /* const char * constructor */ - LogScope(PRLogModuleInfo *aLog, void *from, const nsACString &fn, - const nsDependentCString ¶mName, const char *paramValue) : + LogScope(PRLogModuleInfo *aLog, void *from, const char *fn, + const char *paramName, const char *paramValue) : mLog(aLog), mFrom(from), mFunc(fn) { PR_LOG(mLog, PR_LOG_DEBUG, ("%d [this=%p] %s (%s=\"%s\") {ENTER}\n", - GIVE_ME_MS_NOW(), - mFrom, mFunc.get(), - paramName.get(), - paramValue)); + GIVE_ME_MS_NOW(), mFrom, mFunc, + paramName, paramValue)); } /* void ptr constructor */ - LogScope(PRLogModuleInfo *aLog, void *from, const nsACString &fn, - const nsDependentCString ¶mName, const void *paramValue) : + LogScope(PRLogModuleInfo *aLog, void *from, const char *fn, + const char *paramName, const void *paramValue) : mLog(aLog), mFrom(from), mFunc(fn) { PR_LOG(mLog, PR_LOG_DEBUG, ("%d [this=%p] %s (%s=%p) {ENTER}\n", - GIVE_ME_MS_NOW(), - mFrom, mFunc.get(), - paramName.get(), - paramValue)); + GIVE_ME_MS_NOW(), mFrom, mFunc, + paramName, paramValue)); } /* int32_t constructor */ - LogScope(PRLogModuleInfo *aLog, void *from, const nsACString &fn, - const nsDependentCString ¶mName, int32_t paramValue) : + LogScope(PRLogModuleInfo *aLog, void *from, const char *fn, + const char *paramName, int32_t paramValue) : mLog(aLog), mFrom(from), mFunc(fn) { PR_LOG(mLog, PR_LOG_DEBUG, ("%d [this=%p] %s (%s=\"%d\") {ENTER}\n", - GIVE_ME_MS_NOW(), - mFrom, mFunc.get(), - paramName.get(), - paramValue)); + GIVE_ME_MS_NOW(), mFrom, mFunc, + paramName, paramValue)); } /* uint32_t constructor */ - LogScope(PRLogModuleInfo *aLog, void *from, const nsACString &fn, - const nsDependentCString ¶mName, uint32_t paramValue) : + LogScope(PRLogModuleInfo *aLog, void *from, const char *fn, + const char *paramName, uint32_t paramValue) : mLog(aLog), mFrom(from), mFunc(fn) { PR_LOG(mLog, PR_LOG_DEBUG, ("%d [this=%p] %s (%s=\"%d\") {ENTER}\n", - GIVE_ME_MS_NOW(), - mFrom, mFunc.get(), - paramName.get(), - paramValue)); + GIVE_ME_MS_NOW(), mFrom, mFunc, + paramName, paramValue)); } ~LogScope() { PR_LOG(mLog, PR_LOG_DEBUG, ("%d [this=%p] %s {EXIT}\n", - GIVE_ME_MS_NOW(), - mFrom, mFunc.get())); + GIVE_ME_MS_NOW(), mFrom, mFunc)); } private: PRLogModuleInfo *mLog; void *mFrom; - nsAutoCString mFunc; + const char *mFunc; }; class LogFunc { public: - LogFunc(PRLogModuleInfo *aLog, void *from, const nsDependentCString &fn) + LogFunc(PRLogModuleInfo *aLog, void *from, const char *fn) { PR_LOG(aLog, PR_LOG_DEBUG, ("%d [this=%p] %s\n", - GIVE_ME_MS_NOW(), from, - fn.get())); + GIVE_ME_MS_NOW(), from, fn)); } - LogFunc(PRLogModuleInfo *aLog, void *from, const nsDependentCString &fn, - const nsDependentCString ¶mName, const char *paramValue) + LogFunc(PRLogModuleInfo *aLog, void *from, const char *fn, + const char *paramName, const char *paramValue) { PR_LOG(aLog, PR_LOG_DEBUG, ("%d [this=%p] %s (%s=\"%s\")\n", - GIVE_ME_MS_NOW(), from, - fn.get(), - paramName.get(), paramValue)); + GIVE_ME_MS_NOW(), from, fn, + paramName, paramValue)); } - LogFunc(PRLogModuleInfo *aLog, void *from, const nsDependentCString &fn, - const nsDependentCString ¶mName, const void *paramValue) + LogFunc(PRLogModuleInfo *aLog, void *from, const char *fn, + const char *paramName, const void *paramValue) { PR_LOG(aLog, PR_LOG_DEBUG, ("%d [this=%p] %s (%s=\"%p\")\n", - GIVE_ME_MS_NOW(), from, - fn.get(), - paramName.get(), paramValue)); + GIVE_ME_MS_NOW(), from, fn, + paramName, paramValue)); } - LogFunc(PRLogModuleInfo *aLog, void *from, const nsDependentCString &fn, - const nsDependentCString ¶mName, uint32_t paramValue) + LogFunc(PRLogModuleInfo *aLog, void *from, const char *fn, + const char *paramName, uint32_t paramValue) { PR_LOG(aLog, PR_LOG_DEBUG, ("%d [this=%p] %s (%s=\"%d\")\n", GIVE_ME_MS_NOW(), from, - fn.get(), - paramName.get(), paramValue)); + fn, + paramName, paramValue)); } }; @@ -141,13 +128,11 @@ public: class LogMessage { public: - LogMessage(PRLogModuleInfo *aLog, void *from, const nsDependentCString &fn, - const nsDependentCString &msg) + LogMessage(PRLogModuleInfo *aLog, void *from, const char *fn, + const char *msg) { PR_LOG(aLog, PR_LOG_DEBUG, ("%d [this=%p] %s -- %s\n", - GIVE_ME_MS_NOW(), from, - fn.get(), - msg.get())); + GIVE_ME_MS_NOW(), from, fn, msg)); } }; @@ -156,45 +141,22 @@ public: #define LOG_SCOPE_APPEND_LINE_NUMBER(id) LOG_SCOPE_APPEND_LINE_NUMBER_EXPAND(id, __LINE__) #define LOG_SCOPE(l, s) \ - LogScope LOG_SCOPE_APPEND_LINE_NUMBER(LOG_SCOPE_TMP_VAR) (l, \ - static_cast(this), \ - NS_LITERAL_CSTRING(s)) + LogScope LOG_SCOPE_APPEND_LINE_NUMBER(LOG_SCOPE_TMP_VAR) (l, this, s) #define LOG_SCOPE_WITH_PARAM(l, s, pn, pv) \ - LogScope LOG_SCOPE_APPEND_LINE_NUMBER(LOG_SCOPE_TMP_VAR) (l, \ - static_cast(this), \ - NS_LITERAL_CSTRING(s), \ - NS_LITERAL_CSTRING(pn), pv) + LogScope LOG_SCOPE_APPEND_LINE_NUMBER(LOG_SCOPE_TMP_VAR) (l, this, s, pn, pv) -#define LOG_FUNC(l, s) \ - LogFunc(l, \ - static_cast(this), \ - NS_LITERAL_CSTRING(s)) +#define LOG_FUNC(l, s) LogFunc(l, this, s) -#define LOG_FUNC_WITH_PARAM(l, s, pn, pv) \ - LogFunc(l, \ - static_cast(this), \ - NS_LITERAL_CSTRING(s), \ - NS_LITERAL_CSTRING(pn), pv) +#define LOG_FUNC_WITH_PARAM(l, s, pn, pv) LogFunc(l, this, s, pn, pv) -#define LOG_STATIC_FUNC(l, s) \ - LogFunc(l, \ - nullptr, \ - NS_LITERAL_CSTRING(s)) +#define LOG_STATIC_FUNC(l, s) LogFunc(l, nullptr, s) -#define LOG_STATIC_FUNC_WITH_PARAM(l, s, pn, pv) \ - LogFunc(l, \ - nullptr, \ - NS_LITERAL_CSTRING(s), \ - NS_LITERAL_CSTRING(pn), pv) +#define LOG_STATIC_FUNC_WITH_PARAM(l, s, pn, pv) LogFunc(l, nullptr, s, pn, pv) -#define LOG_MSG(l, s, m) \ - LogMessage(l, \ - static_cast(this), \ - NS_LITERAL_CSTRING(s), \ - NS_LITERAL_CSTRING(m)) +#define LOG_MSG(l, s, m) LogMessage(l, this, s, m) #else diff --git a/ipc/glue/IPCMessageUtils.h b/ipc/glue/IPCMessageUtils.h index 2a897277058b..d61ae8863b2a 100644 --- a/ipc/glue/IPCMessageUtils.h +++ b/ipc/glue/IPCMessageUtils.h @@ -314,6 +314,12 @@ struct ParamTraits : ParamTraits typedef nsCString paramType; }; +template <> +struct ParamTraits : ParamTraits +{ + typedef nsLiteralCString paramType; +}; + #ifdef MOZILLA_INTERNAL_API template<> @@ -330,6 +336,12 @@ struct ParamTraits : ParamTraits typedef nsString paramType; }; +template <> +struct ParamTraits : ParamTraits +{ + typedef nsLiteralString paramType; +}; + template struct ParamTraits > { diff --git a/js/src/builtin/SIMD.cpp b/js/src/builtin/SIMD.cpp index 2c06122c3b23..60d67f9a2dbb 100644 --- a/js/src/builtin/SIMD.cpp +++ b/js/src/builtin/SIMD.cpp @@ -335,6 +335,14 @@ const Class SIMDObject::class_ = { JSObject * SIMDObject::initClass(JSContext *cx, Handle global) { + // SIMD relies on having the TypedObject module initialized. + // In particular, the self-hosted code for array() wants + // to be able to call GetTypedObjectModule(). It is NOT necessary + // to install the TypedObjectModule global, but at the moment + // those two things are not separable. + if (!global->getOrCreateTypedObjectModule(cx)) + return nullptr; + // Create SIMD Object. RootedObject objProto(cx, global->getOrCreateObjectPrototype(cx)); if(!objProto) diff --git a/js/src/builtin/TypeRepresentation.cpp b/js/src/builtin/TypeRepresentation.cpp index 024e47cb66a9..957a80bef2d3 100644 --- a/js/src/builtin/TypeRepresentation.cpp +++ b/js/src/builtin/TypeRepresentation.cpp @@ -947,6 +947,8 @@ SizedTypeRepresentation::initInstance(const JSRuntime *rt, uint8_t *mem, size_t length) { + JS_ASSERT(length >= 1); + MemoryInitVisitor visitor(rt); // Initialize the 0th instance diff --git a/js/src/builtin/TypeRepresentation.h b/js/src/builtin/TypeRepresentation.h index b1c8a2e6800b..482f17493475 100644 --- a/js/src/builtin/TypeRepresentation.h +++ b/js/src/builtin/TypeRepresentation.h @@ -231,7 +231,8 @@ class SizedTypeRepresentation : public TypeRepresentation { size_t size() const { return size_; } size_t alignment() const { return alignment_; } - // Initializes memory that contains `count` instances of this type + // Initializes memory that contains `count` instances of this type. + // `count` must be at least 1. void initInstance(const JSRuntime *rt, uint8_t *mem, size_t count); // Traces memory that contains `count` instances of this type. diff --git a/js/src/builtin/TypedObject.cpp b/js/src/builtin/TypedObject.cpp index 25ce74ed551d..e7a5489bf322 100644 --- a/js/src/builtin/TypedObject.cpp +++ b/js/src/builtin/TypedObject.cpp @@ -2339,7 +2339,8 @@ TypedObject::createZeroed(JSContext *cx, if (!memory) return nullptr; - elementTypeRepr->initInstance(cx->runtime(), memory, length); + if (length) + elementTypeRepr->initInstance(cx->runtime(), memory, length); obj->attach(memory); return obj; } diff --git a/js/src/jit-test/tests/TypedObject/bug953108.js b/js/src/jit-test/tests/TypedObject/bug953108.js new file mode 100644 index 000000000000..e73ff458a99e --- /dev/null +++ b/js/src/jit-test/tests/TypedObject/bug953108.js @@ -0,0 +1,10 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +if (!this.hasOwnProperty("TypedObject")) + quit(); + +var float32x4 = SIMD.float32x4; +float32x4.array(1); diff --git a/js/src/jit-test/tests/TypedObject/bug953111.js b/js/src/jit-test/tests/TypedObject/bug953111.js new file mode 100644 index 000000000000..bcd98f27c3fd --- /dev/null +++ b/js/src/jit-test/tests/TypedObject/bug953111.js @@ -0,0 +1,18 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +if (!this.hasOwnProperty("TypedObject")) + quit(); + +// bug 953111 + +var A = TypedObject.uint8.array(); +var a = new A(0); +a.forEach(function(val, i) {}); + +// bug 951356 (dup, but a dup that is more likely to crash) + +var AA = TypedObject.uint8.array(2147483647).array(); +var aa = new AA(0); diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index 13c77d3c9548..80e22490c2d7 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -6686,7 +6686,7 @@ IonBuilder::getElemTryScalarElemOfTypedObject(bool *emitted, TypeRepresentationSet elemTypeReprs, size_t elemSize) { - JS_ASSERT(objTypeReprs.kind() == TypeRepresentation::SizedArray); + JS_ASSERT(objTypeReprs.allOfArrayKind()); // Must always be loading the same scalar type if (!elemTypeReprs.singleton()) diff --git a/js/src/jit/arm/CodeGenerator-arm.cpp b/js/src/jit/arm/CodeGenerator-arm.cpp index 23bd7888d9e3..668fe4d1105e 100644 --- a/js/src/jit/arm/CodeGenerator-arm.cpp +++ b/js/src/jit/arm/CodeGenerator-arm.cpp @@ -703,19 +703,21 @@ CodeGeneratorARM::modICommon(MMod *mir, Register lhs, Register rhs, Register out // the flags necessary for LT to trigger, we don't test X, and take the // bailout because the EQ flag is set. // if (Y > 0), we don't set EQ, and we don't trigger LT, so we don't take the bailout. - masm.ma_cmp(rhs, Imm32(0)); - masm.ma_cmp(lhs, Imm32(0), Assembler::LessThan); - if (mir->isTruncated()) { - // NaN|0 == 0 and (0 % -X)|0 == 0 - Label skip; - masm.ma_b(&skip, Assembler::NotEqual); - masm.ma_mov(Imm32(0), output); - masm.ma_b(&done); - masm.bind(&skip); - } else { - JS_ASSERT(mir->fallible()); - if (!bailoutIf(Assembler::Equal, snapshot)) - return false; + if (mir->canBeDivideByZero() || mir->canBeNegativeDividend()) { + masm.ma_cmp(rhs, Imm32(0)); + masm.ma_cmp(lhs, Imm32(0), Assembler::LessThan); + if (mir->isTruncated()) { + // NaN|0 == 0 and (0 % -X)|0 == 0 + Label skip; + masm.ma_b(&skip, Assembler::NotEqual); + masm.ma_mov(Imm32(0), output); + masm.ma_b(&done); + masm.bind(&skip); + } else { + JS_ASSERT(mir->fallible()); + if (!bailoutIf(Assembler::Equal, snapshot)) + return false; + } } return true; @@ -740,16 +742,18 @@ CodeGeneratorARM::visitModI(LModI *ins) masm.ma_smod(lhs, rhs, output); // If X%Y == 0 and X < 0, then we *actually* wanted to return -0.0 - if (mir->isTruncated()) { - // -0.0|0 == 0 - } else { - JS_ASSERT(mir->fallible()); - // See if X < 0 - masm.ma_cmp(output, Imm32(0)); - masm.ma_b(&done, Assembler::NotEqual); - masm.ma_cmp(callTemp, Imm32(0)); - if (!bailoutIf(Assembler::Signed, ins->snapshot())) - return false; + if (mir->canBeNegativeDividend()) { + if (mir->isTruncated()) { + // -0.0|0 == 0 + } else { + JS_ASSERT(mir->fallible()); + // See if X < 0 + masm.ma_cmp(output, Imm32(0)); + masm.ma_b(&done, Assembler::NotEqual); + masm.ma_cmp(callTemp, Imm32(0)); + if (!bailoutIf(Assembler::Signed, ins->snapshot())) + return false; + } } masm.bind(&done); @@ -802,16 +806,18 @@ CodeGeneratorARM::visitSoftModI(LSoftModI *ins) masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, __aeabi_idivmod)); // If X%Y == 0 and X < 0, then we *actually* wanted to return -0.0 - if (mir->isTruncated()) { - // -0.0|0 == 0 - } else { - JS_ASSERT(mir->fallible()); - // See if X < 0 - masm.ma_cmp(r1, Imm32(0)); - masm.ma_b(&done, Assembler::NotEqual); - masm.ma_cmp(callTemp, Imm32(0)); - if (!bailoutIf(Assembler::Signed, ins->snapshot())) - return false; + if (mir->canBeNegativeDividend()) { + if (mir->isTruncated()) { + // -0.0|0 == 0 + } else { + JS_ASSERT(mir->fallible()); + // See if X < 0 + masm.ma_cmp(r1, Imm32(0)); + masm.ma_b(&done, Assembler::NotEqual); + masm.ma_cmp(callTemp, Imm32(0)); + if (!bailoutIf(Assembler::Signed, ins->snapshot())) + return false; + } } masm.bind(&done); return true; @@ -830,12 +836,14 @@ CodeGeneratorARM::visitModPowTwoI(LModPowTwoI *ins) masm.ma_rsb(Imm32(0), out, NoSetCond, Assembler::Signed); masm.ma_and(Imm32((1<shift())-1), out); masm.ma_rsb(Imm32(0), out, SetCond, Assembler::Signed); - if (!mir->isTruncated()) { - JS_ASSERT(mir->fallible()); - if (!bailoutIf(Assembler::Zero, ins->snapshot())) - return false; - } else { - // -0|0 == 0 + if (mir->canBeNegativeDividend()) { + if (!mir->isTruncated()) { + JS_ASSERT(mir->fallible()); + if (!bailoutIf(Assembler::Zero, ins->snapshot())) + return false; + } else { + // -0|0 == 0 + } } masm.bind(&fin); return true; @@ -849,12 +857,14 @@ CodeGeneratorARM::visitModMaskI(LModMaskI *ins) Register tmp = ToRegister(ins->getTemp(0)); MMod *mir = ins->mir(); masm.ma_mod_mask(src, dest, tmp, ins->shift()); - if (!mir->isTruncated()) { - JS_ASSERT(mir->fallible()); - if (!bailoutIf(Assembler::Zero, ins->snapshot())) - return false; - } else { - // -0|0 == 0 + if (mir->canBeNegativeDividend()) { + if (!mir->isTruncated()) { + JS_ASSERT(mir->fallible()); + if (!bailoutIf(Assembler::Zero, ins->snapshot())) + return false; + } else { + // -0|0 == 0 + } } return true; } diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 9988efdf4807..f955e9fa9555 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -3209,7 +3209,7 @@ TypeObject::clearNewScriptAddendum(ExclusiveContext *cx) } if (!finished) { - if (!obj->rollbackProperties(cx, numProperties)) + if (!JSObject::rollbackProperties(cx, obj, numProperties)) cx->compartment()->types.setPendingNukeTypes(cx); } } diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 56323b2585ca..3017658383ef 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -416,7 +416,8 @@ class JSObject : public js::ObjectImpl elements[i].js::HeapSlot::~HeapSlot(); } - bool rollbackProperties(js::ExclusiveContext *cx, uint32_t slotSpan); + static bool rollbackProperties(js::ExclusiveContext *cx, js::HandleObject obj, + uint32_t slotSpan); void nativeSetSlot(uint32_t slot, const js::Value &value) { JS_ASSERT(isNative()); diff --git a/js/src/vm/Shape.cpp b/js/src/vm/Shape.cpp index 223706f5ef06..8fb4a09c0a4c 100644 --- a/js/src/vm/Shape.cpp +++ b/js/src/vm/Shape.cpp @@ -1156,26 +1156,26 @@ JSObject::clear(JSContext *cx, HandleObject obj) obj->checkShapeConsistency(); } -bool -JSObject::rollbackProperties(ExclusiveContext *cx, uint32_t slotSpan) +/* static */ bool +JSObject::rollbackProperties(ExclusiveContext *cx, HandleObject obj, uint32_t slotSpan) { /* * Remove properties from this object until it has a matching slot span. * The object cannot have escaped in a way which would prevent safe * removal of the last properties. */ - JS_ASSERT(!inDictionaryMode() && slotSpan <= this->slotSpan()); + JS_ASSERT(!obj->inDictionaryMode() && slotSpan <= obj->slotSpan()); while (true) { - if (lastProperty()->isEmptyShape()) { + if (obj->lastProperty()->isEmptyShape()) { JS_ASSERT(slotSpan == 0); break; } else { - uint32_t slot = lastProperty()->slot(); + uint32_t slot = obj->lastProperty()->slot(); if (slot < slotSpan) break; - JS_ASSERT(getSlot(slot).isUndefined()); + JS_ASSERT(obj->getSlot(slot).isUndefined()); } - if (!removeProperty(cx, lastProperty()->propid())) + if (!obj->removeProperty(cx, obj->lastProperty()->propid())) return false; } diff --git a/js/xpconnect/src/XPCString.cpp b/js/xpconnect/src/XPCString.cpp index 9a5017e8895d..5f06f4a1b091 100644 --- a/js/xpconnect/src/XPCString.cpp +++ b/js/xpconnect/src/XPCString.cpp @@ -47,6 +47,15 @@ XPCStringConvert::ClearZoneCache(JS::Zone *zone) } } +// static +void +XPCStringConvert::FinalizeLiteral(const JSStringFinalizer *fin, jschar *chars) +{ +} + +const JSStringFinalizer XPCStringConvert::sLiteralFinalizer = + { XPCStringConvert::FinalizeLiteral }; + // static void XPCStringConvert::FinalizeDOMString(const JSStringFinalizer *fin, jschar *chars) @@ -74,6 +83,16 @@ XPCStringConvert::ReadableToJSVal(JSContext *cx, return true; } + if (readable.IsLiteral()) { + JSString *str = JS_NewExternalString(cx, + static_cast(readable.BeginReading()), + length, &sLiteralFinalizer); + if (!str) + return false; + vp.setString(str); + return true; + } + nsStringBuffer *buf = nsStringBuffer::FromString(readable); if (buf) { bool shared; diff --git a/js/xpconnect/src/xpcpublic.h b/js/xpconnect/src/xpcpublic.h index 9b43aa7dbaeb..3ae63c99823d 100644 --- a/js/xpconnect/src/xpcpublic.h +++ b/js/xpconnect/src/xpcpublic.h @@ -238,7 +238,9 @@ public: static void ClearZoneCache(JS::Zone *zone); private: - static const JSStringFinalizer sDOMStringFinalizer; + static const JSStringFinalizer sLiteralFinalizer, sDOMStringFinalizer; + + static void FinalizeLiteral(const JSStringFinalizer *fin, jschar *chars); static void FinalizeDOMString(const JSStringFinalizer *fin, jschar *chars); diff --git a/layout/generic/nsFirstLetterFrame.cpp b/layout/generic/nsFirstLetterFrame.cpp index 01a4a8bd13b0..1584c777dc22 100644 --- a/layout/generic/nsFirstLetterFrame.cpp +++ b/layout/generic/nsFirstLetterFrame.cpp @@ -376,7 +376,9 @@ nsFirstLetterFrame::DrainOverflowFrames(nsPresContext* aPresContext) if (kidContent) { NS_ASSERTION(kidContent->IsNodeOfType(nsINode::eTEXT), "should contain only text nodes"); - sc = aPresContext->StyleSet()->ResolveStyleForNonElement(mStyleContext); + nsStyleContext* parentSC = prevInFlow ? mStyleContext->GetParent() : + mStyleContext; + sc = aPresContext->StyleSet()->ResolveStyleForNonElement(parentSC); kid->SetStyleContext(sc); } } diff --git a/layout/generic/nsFlexContainerFrame.cpp b/layout/generic/nsFlexContainerFrame.cpp index 1b0c1b150878..5da05bda0228 100644 --- a/layout/generic/nsFlexContainerFrame.cpp +++ b/layout/generic/nsFlexContainerFrame.cpp @@ -1359,8 +1359,9 @@ nsFlexContainerFrame::SanityCheckAnonymousFlexItems() const "but it isn't"); if (child->StyleContext()->GetPseudo() == nsCSSAnonBoxes::anonymousFlexItem) { - MOZ_ASSERT(!prevChildWasAnonFlexItem, - "two anon flex items in a row (shouldn't happen)"); + MOZ_ASSERT(!prevChildWasAnonFlexItem || mChildrenHaveBeenReordered, + "two anon flex items in a row (shouldn't happen, unless our " + "children have been reordered with the 'order' property)"); nsIFrame* firstWrappedChild = child->GetFirstPrincipalChild(); MOZ_ASSERT(firstWrappedChild, diff --git a/layout/reftests/bugs/953334-win32-clipping-ref.html b/layout/reftests/bugs/953334-win32-clipping-ref.html new file mode 100644 index 000000000000..e07bf159eb09 --- /dev/null +++ b/layout/reftests/bugs/953334-win32-clipping-ref.html @@ -0,0 +1,22 @@ + + +
+

 

+

 

+

 

+
+ diff --git a/layout/reftests/bugs/953334-win32-clipping.html b/layout/reftests/bugs/953334-win32-clipping.html new file mode 100644 index 000000000000..91db71af63d6 --- /dev/null +++ b/layout/reftests/bugs/953334-win32-clipping.html @@ -0,0 +1,22 @@ + + +
+

 

+

 

+

sed diam nonummy nibh

+
+ diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 51d3b4bb42b7..845139ce744d 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -1791,5 +1791,6 @@ fuzzy-if(OSX==10.6,2,30) == 933264-1.html 933264-1-ref.html == 941940-1.html 941940-1-ref.html == 942017.html 942017-ref.html == 942672-1.html 942672-1-ref.html +== 953334-win32-clipping.html 953334-win32-clipping-ref.html == 956513-1.svg 956513-1-ref.svg == 944291-1.html 944291-1-ref.html diff --git a/layout/reftests/w3c-css/submitted/flexbox/flexbox-anonymous-items-1-ref.html b/layout/reftests/w3c-css/submitted/flexbox/flexbox-anonymous-items-1-ref.html new file mode 100644 index 000000000000..d14234b453bb --- /dev/null +++ b/layout/reftests/w3c-css/submitted/flexbox/flexbox-anonymous-items-1-ref.html @@ -0,0 +1,15 @@ + + + + + CSS Reftest Reference + + + + + a ab bx x + + diff --git a/layout/reftests/w3c-css/submitted/flexbox/flexbox-anonymous-items-1.html b/layout/reftests/w3c-css/submitted/flexbox/flexbox-anonymous-items-1.html new file mode 100644 index 000000000000..c1bcd6945ea5 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/flexbox/flexbox-anonymous-items-1.html @@ -0,0 +1,26 @@ + + + + + CSS Test: Testing that we gracefully handle cases where two anonymous flex items become adjacent due to "order" reordering + + + + + + + +
+ a a +
x x
+ b b +
+ + diff --git a/layout/reftests/w3c-css/submitted/flexbox/reftest.list b/layout/reftests/w3c-css/submitted/flexbox/reftest.list index b646c43fc261..bbec218e6d75 100644 --- a/layout/reftests/w3c-css/submitted/flexbox/reftest.list +++ b/layout/reftests/w3c-css/submitted/flexbox/reftest.list @@ -1,3 +1,6 @@ +# Tests for handling anonymous flex items +== flexbox-anonymous-items-1.html flexbox-anonymous-items-1-ref.html + # Tests for alignment of flex lines (align-content property) == flexbox-align-content-horiz-1a.xhtml flexbox-align-content-horiz-1-ref.xhtml == flexbox-align-content-horiz-1b.xhtml flexbox-align-content-horiz-1-ref.xhtml diff --git a/media/omx-plugin/OmxPlugin.cpp b/media/omx-plugin/OmxPlugin.cpp index c2ff759ef2fe..b1e0e5469b23 100644 --- a/media/omx-plugin/OmxPlugin.cpp +++ b/media/omx-plugin/OmxPlugin.cpp @@ -23,6 +23,9 @@ #include "android/log.h" +#define MAX_DECODER_NAME_LEN 256 +#define AVC_MIME_TYPE "video/avc" + #if !defined(MOZ_ANDROID_FROYO) #define DEFAULT_STAGEFRIGHT_FLAGS OMXCodec::kClientNeedsFramebuffer #else @@ -239,7 +242,13 @@ static uint32_t GetVideoCreationFlags(PluginHost* aPluginHost) #endif } -static bool +enum ColorFormatSupport { + ColorFormatNotSupported = 0, + ColorFormatSupportOK, + ColorFormatSupportPreferred, +}; + +static ColorFormatSupport IsColorFormatSupported(OMX_COLOR_FORMATTYPE aColorFormat) { switch (aColorFormat) { @@ -250,15 +259,19 @@ IsColorFormatSupported(OMX_COLOR_FORMATTYPE aColorFormat) case OMX_QCOM_COLOR_FormatYVU420SemiPlanar: case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar: LOG("Colour format %#x supported natively.", aColorFormat); - return true; + // Prefer natively supported colour formats over formats that need another + // slow software conversion. + return ColorFormatSupportPreferred; default: break; } + // These formats are okay if we can't find a better one; Android provides a + // software conversion to a sane colour format. #if !defined(MOZ_ANDROID_HC) if (ColorConverter(aColorFormat, OMX_COLOR_Format16bitRGB565).isValid()) { LOG("Colour format %#x supported by Android ColorConverter.", aColorFormat); - return true; + return ColorFormatSupportOK; } #endif @@ -268,12 +281,64 @@ IsColorFormatSupported(OMX_COLOR_FORMATTYPE aColorFormat) if (yuvConverter.isLoaded() && yuvConverter.getDecoderOutputFormat() == aColorFormat) { LOG("Colour format %#x supported by Android I420ColorConverter.", aColorFormat); - return true; + return ColorFormatSupportOK; } #endif + return ColorFormatNotSupported; +} + +#if defined(MOZ_ANDROID_KK) +/** + * Look for a decoder that supports a colour format that we support. + */ +static bool +FindPreferredDecoderAndColorFormat(const sp& aOmx, + char *aDecoderName, + size_t aDecoderLen, + OMX_COLOR_FORMATTYPE *aColorFormat) +{ + Vector codecs; + + // Get all AVC decoder/colour format pairs that this device supports. + QueryCodecs(aOmx, AVC_MIME_TYPE, true /* queryDecoders */, &codecs); + + // We assume that faster (hardware accelerated) decoders come first in the + // list, so we choose the first decoder with a colour format we can use. + for (uint32_t i = 0; i < codecs.size(); i++) { + const CodecCapabilities &caps = codecs[i]; + const Vector &colors = caps.mColorFormats; + + bool found = false; + for (uint32_t j = 0; j < colors.size(); j++) { + OMX_COLOR_FORMATTYPE color = (OMX_COLOR_FORMATTYPE)colors[j]; + + LOG("Decoder %s can output colour format %#x.\n", + caps.mComponentName.string(), color); + + ColorFormatSupport supported = IsColorFormatSupported(color); + + if (supported) { + strncpy(aDecoderName, caps.mComponentName.string(), aDecoderLen); + *aColorFormat = (OMX_COLOR_FORMATTYPE)color; + found = true; + } + + if (supported == ColorFormatSupportPreferred) { + // The colour format is natively supported -- that's as good as we're + // going to get. + break; + } + } + + if (found) { + return true; + } + } + return false; } +#endif static sp CreateVideoSource(PluginHost* aPluginHost, const sp& aOmx, @@ -281,10 +346,29 @@ static sp CreateVideoSource(PluginHost* aPluginHost, { uint32_t flags = GetVideoCreationFlags(aPluginHost); + char decoderName[MAX_DECODER_NAME_LEN] = ""; + sp videoFormat = aVideoTrack->getFormat(); + +#if defined(MOZ_ANDROID_KK) + OMX_COLOR_FORMATTYPE colorFormat = (OMX_COLOR_FORMATTYPE)0; + if (FindPreferredDecoderAndColorFormat(aOmx, + decoderName, sizeof(decoderName), + &colorFormat)) { + // We found a colour format that we can handle. Tell OMXCodec to use it in + // case it isn't the default. + videoFormat->setInt32(kKeyColorFormat, colorFormat); + + LOG("Found compatible decoder %s with colour format %#x.\n", + decoderName, colorFormat); + } +#endif + if (flags == DEFAULT_STAGEFRIGHT_FLAGS) { // Let Stagefright choose hardware or software decoder. - sp videoSource = OMXCodec::Create(aOmx, aVideoTrack->getFormat(), - false, aVideoTrack, nullptr, flags); + sp videoSource = OMXCodec::Create(aOmx, videoFormat, + false, aVideoTrack, + decoderName[0] ? decoderName : nullptr, + flags); if (videoSource == nullptr) return nullptr; diff --git a/media/omx-plugin/include/ics/utils/Vector.h b/media/omx-plugin/include/ics/utils/Vector.h index b908e2ab2e2c..e30071d16d0b 100644 --- a/media/omx-plugin/include/ics/utils/Vector.h +++ b/media/omx-plugin/include/ics/utils/Vector.h @@ -21,7 +21,8 @@ #include #include -#include +#include + #include #include @@ -43,11 +44,11 @@ class Vector : private VectorImpl { public: typedef TYPE value_type; - - /*! + + /*! * Constructors and destructors */ - + Vector(); Vector(const Vector& rhs); explicit Vector(const SortedVector& rhs); @@ -55,7 +56,7 @@ public: /*! copy operator */ const Vector& operator = (const Vector& rhs) const; - Vector& operator = (const Vector& rhs); + Vector& operator = (const Vector& rhs); const Vector& operator = (const SortedVector& rhs) const; Vector& operator = (const SortedVector& rhs); @@ -66,29 +67,35 @@ public: inline void clear() { VectorImpl::clear(); } - /*! + /*! * vector stats */ //! returns number of items in the vector inline size_t size() const { return VectorImpl::size(); } - //! returns wether or not the vector is empty + //! returns whether or not the vector is empty inline bool isEmpty() const { return VectorImpl::isEmpty(); } //! returns how many items can be stored without reallocating the backing store inline size_t capacity() const { return VectorImpl::capacity(); } - //! setst the capacity. capacity can never be reduced less than size() + //! sets the capacity. capacity can never be reduced less than size() inline ssize_t setCapacity(size_t size) { return VectorImpl::setCapacity(size); } - /*! + /*! + * set the size of the vector. items are appended with the default + * constructor, or removed from the end as needed. + */ + inline ssize_t resize(size_t size) { return VectorImpl::resize(size); } + + /*! * C-style array access */ - - //! read-only C-style access + + //! read-only C-style access inline const TYPE* array() const; //! read-write C-style access TYPE* editArray(); - - /*! + + /*! * accessors */ @@ -98,22 +105,20 @@ public: inline const TYPE& itemAt(size_t index) const; //! stack-usage of the vector. returns the top of the stack (last element) const TYPE& top() const; - //! same as operator [], but allows to access the vector backward (from the end) with a negative index - const TYPE& mirrorItemAt(ssize_t index) const; /*! - * modifing the array + * modifying the array */ //! copy-on write support, grants write access to an item TYPE& editItemAt(size_t index); - //! grants right acces to the top of the stack (last element) + //! grants right access to the top of the stack (last element) TYPE& editTop(); - /*! + /*! * append/insert another vector */ - + //! insert another vector at a given index ssize_t insertVectorAt(const Vector& vector, size_t index); @@ -127,10 +132,10 @@ public: //! append an array at the end of this vector ssize_t appendArray(const TYPE* array, size_t length); - /*! + /*! * add/insert/replace items */ - + //! insert one or several items initialized with their default constructor inline ssize_t insertAt(size_t index, size_t numItems = 1); //! insert one or several items initialized from a prototype item @@ -144,7 +149,7 @@ public: //! same as push() but returns the index the item was added at (or an error) inline ssize_t add(); //! same as push() but returns the index the item was added at (or an error) - ssize_t add(const TYPE& item); + ssize_t add(const TYPE& item); //! replace an item with a new one initialized with its default constructor inline ssize_t replaceAt(size_t index); //! replace an item with a new one @@ -162,10 +167,10 @@ public: /*! * sort (stable) the array */ - + typedef int (*compar_t)(const TYPE* lhs, const TYPE* rhs); typedef int (*compar_r_t)(const TYPE* lhs, const TYPE* rhs, void* state); - + inline status_t sort(compar_t cmp); inline status_t sort(compar_r_t cmp, void* state); @@ -186,10 +191,11 @@ public: inline const_iterator end() const { return array() + size(); } inline void reserve(size_t n) { setCapacity(n); } inline bool empty() const{ return isEmpty(); } - inline void push_back(const TYPE& item) { insertAt(item, size()); } - inline void push_front(const TYPE& item) { insertAt(item, 0); } + inline void push_back(const TYPE& item) { insertAt(item, size(), 1); } + inline void push_front(const TYPE& item) { insertAt(item, 0, 1); } inline iterator erase(iterator pos) { - return begin() + removeItemsAt(pos-array()); + ssize_t index = removeItemsAt(pos-array()); + return begin() + index; } protected: @@ -201,6 +207,9 @@ protected: virtual void do_move_backward(void* dest, const void* from, size_t num) const; }; +// Vector can be trivially moved using memcpy() because moving does not +// require any change to the underlying SharedBuffer contents or reference count. +template struct trait_trivial_move > { enum { value = true }; }; // --------------------------------------------------------------------------- // No user serviceable parts from here... @@ -234,7 +243,7 @@ Vector::~Vector() { template inline Vector& Vector::operator = (const Vector& rhs) { VectorImpl::operator = (rhs); - return *this; + return *this; } template inline @@ -252,7 +261,7 @@ Vector& Vector::operator = (const SortedVector& rhs) { template inline const Vector& Vector::operator = (const SortedVector& rhs) const { VectorImpl::operator = (rhs); - return *this; + return *this; } template inline @@ -268,8 +277,9 @@ TYPE* Vector::editArray() { template inline const TYPE& Vector::operator[](size_t index) const { - LOG_FATAL_IF( index>=size(), - "itemAt: index %d is past size %d", (int)index, (int)size() ); + LOG_FATAL_IF(index>=size(), + "%s: index=%u out of range (%u)", __PRETTY_FUNCTION__, + int(index), int(size())); return *(array() + index); } @@ -278,14 +288,6 @@ const TYPE& Vector::itemAt(size_t index) const { return operator[](index); } -template inline -const TYPE& Vector::mirrorItemAt(ssize_t index) const { - LOG_FATAL_IF( (index>0 ? index : -index)>=size(), - "mirrorItemAt: index %d is past size %d", - (int)index, (int)size() ); - return *(array() + ((index<0) ? (size()-index) : index)); -} - template inline const TYPE& Vector::top() const { return *(array() + size() - 1); @@ -419,3 +421,4 @@ void Vector::do_move_backward(void* dest, const void* from, size_t num) co // --------------------------------------------------------------------------- #endif // ANDROID_VECTOR_H + diff --git a/media/omx-plugin/include/ics/utils/VectorImpl.h b/media/omx-plugin/include/ics/utils/VectorImpl.h index c4ec2ff97f66..720b2546c409 100644 --- a/media/omx-plugin/include/ics/utils/VectorImpl.h +++ b/media/omx-plugin/include/ics/utils/VectorImpl.h @@ -53,24 +53,25 @@ public: /*! must be called from subclasses destructor */ void finish_vector(); - VectorImpl& operator = (const VectorImpl& rhs); - + VectorImpl& operator = (const VectorImpl& rhs); + /*! C-style array access */ inline const void* arrayImpl() const { return mStorage; } void* editArrayImpl(); - + /*! vector stats */ inline size_t size() const { return mCount; } inline bool isEmpty() const { return mCount == 0; } size_t capacity() const; ssize_t setCapacity(size_t size); + ssize_t resize(size_t size); /*! append/insert another vector or array */ ssize_t insertVectorAt(const VectorImpl& vector, size_t index); ssize_t appendVector(const VectorImpl& vector); ssize_t insertArrayAt(const void* array, size_t index, size_t length); ssize_t appendArray(const void* array, size_t length); - + /*! add/insert/replace items */ ssize_t insertAt(size_t where, size_t numItems = 1); ssize_t insertAt(const void* item, size_t where, size_t numItems = 1); @@ -105,16 +106,6 @@ protected: virtual void do_move_forward(void* dest, const void* from, size_t num) const = 0; virtual void do_move_backward(void* dest, const void* from, size_t num) const = 0; - // take care of FBC... - virtual void reservedVectorImpl1(); - virtual void reservedVectorImpl2(); - virtual void reservedVectorImpl3(); - virtual void reservedVectorImpl4(); - virtual void reservedVectorImpl5(); - virtual void reservedVectorImpl6(); - virtual void reservedVectorImpl7(); - virtual void reservedVectorImpl8(); - private: void* _grow(size_t where, size_t amount); void _shrink(size_t where, size_t amount); @@ -143,8 +134,8 @@ public: SortedVectorImpl(size_t itemSize, uint32_t flags); SortedVectorImpl(const VectorImpl& rhs); virtual ~SortedVectorImpl(); - - SortedVectorImpl& operator = (const SortedVectorImpl& rhs); + + SortedVectorImpl& operator = (const SortedVectorImpl& rhs); //! finds the index of an item ssize_t indexOf(const void* item) const; @@ -158,23 +149,13 @@ public: //! merges a vector into this one ssize_t merge(const VectorImpl& vector); ssize_t merge(const SortedVectorImpl& vector); - + //! removes an item ssize_t remove(const void* item); - + protected: virtual int do_compare(const void* lhs, const void* rhs) const = 0; - // take care of FBC... - virtual void reservedSortedVectorImpl1(); - virtual void reservedSortedVectorImpl2(); - virtual void reservedSortedVectorImpl3(); - virtual void reservedSortedVectorImpl4(); - virtual void reservedSortedVectorImpl5(); - virtual void reservedSortedVectorImpl6(); - virtual void reservedSortedVectorImpl7(); - virtual void reservedSortedVectorImpl8(); - private: ssize_t _indexOrderOf(const void* item, size_t* order = 0) const; @@ -200,3 +181,4 @@ private: // --------------------------------------------------------------------------- #endif // ANDROID_VECTOR_IMPL_H + diff --git a/media/omx-plugin/kk/Makefile.in b/media/omx-plugin/kk/Makefile.in new file mode 100644 index 000000000000..bde23cfe2060 --- /dev/null +++ b/media/omx-plugin/kk/Makefile.in @@ -0,0 +1,31 @@ +# Copyright 2012 Mozilla Foundation and Mozilla contributors +# +# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Don't use STL wrappers; this isn't Gecko code +STL_FLAGS = + +# must link statically with the CRT; this isn't Gecko code +USE_STATIC_LIBS = 1 + +include $(topsrcdir)/config/rules.mk + +EXTRA_DSO_LDOPTS += \ + -L$(DEPTH)/media/omx-plugin/lib/ics/libutils \ + -lutils \ + -L$(DEPTH)/media/omx-plugin/lib/ics/libstagefright \ + -lstagefright \ + -L$(DEPTH)/media/omx-plugin/lib/ics/libvideoeditorplayer \ + -lvideoeditorplayer \ + $(NULL) + diff --git a/media/omx-plugin/kk/OmxPluginKitKat.cpp b/media/omx-plugin/kk/OmxPluginKitKat.cpp new file mode 100644 index 000000000000..d33552c1587e --- /dev/null +++ b/media/omx-plugin/kk/OmxPluginKitKat.cpp @@ -0,0 +1,8 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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/. */ +#define MOZ_STAGEFRIGHT_OFF_T off64_t +#define MOZ_ANDROID_KK +#include "../OmxPlugin.cpp" diff --git a/media/omx-plugin/kk/moz.build b/media/omx-plugin/kk/moz.build new file mode 100644 index 000000000000..88fde1abdfcf --- /dev/null +++ b/media/omx-plugin/kk/moz.build @@ -0,0 +1,20 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +SOURCES += [ + 'OmxPluginKitKat.cpp', +] + +LIBRARY_NAME = 'omxpluginkk' + +FORCE_SHARED_LIB = True + +LOCAL_INCLUDES += [ + '../../../content/media/plugins', + '../include/ics', + '../include/ics/media/stagefright/openmax', +] + diff --git a/media/omx-plugin/lib/ics/libstagefright/libstagefright.cpp b/media/omx-plugin/lib/ics/libstagefright/libstagefright.cpp index 43bee539fd8d..a998c4a569f9 100644 --- a/media/omx-plugin/lib/ics/libstagefright/libstagefright.cpp +++ b/media/omx-plugin/lib/ics/libstagefright/libstagefright.cpp @@ -61,6 +61,12 @@ MetaData::findInt32(uint32_t key, int32_t *value) return false; } +MOZ_EXPORT bool +MetaData::setInt32(uint32_t, int32_t) +{ + return false; +} + MOZ_EXPORT bool MetaData::findInt64(uint32_t key, int64_t *value) { @@ -176,4 +182,12 @@ ColorConverter::convert(const void *srcBits, { return 0; } + +MOZ_EXPORT status_t QueryCodecs(const sp &omx, + const char *mimeType, bool queryDecoders, + Vector *results) +{ + return 0; +} + } diff --git a/media/omx-plugin/lib/ics/libutils/libutils.cpp b/media/omx-plugin/lib/ics/libutils/libutils.cpp index a93124a62971..67f5a540a817 100644 --- a/media/omx-plugin/lib/ics/libutils/libutils.cpp +++ b/media/omx-plugin/lib/ics/libutils/libutils.cpp @@ -7,6 +7,7 @@ #include "utils/RefBase.h" #include "utils/String16.h" #include "utils/String8.h" +#include "utils/Vector.h" namespace android { MOZ_EXPORT RefBase::RefBase() : mRefs(0) @@ -54,7 +55,30 @@ MOZ_EXPORT String8::String8() { } +MOZ_EXPORT String8::String8(const String8 &) +{ +} + MOZ_EXPORT String8::~String8() { } + +MOZ_EXPORT VectorImpl::VectorImpl(size_t, uint32_t) + : mFlags(0), mItemSize(0) +{ +} + +MOZ_EXPORT VectorImpl::VectorImpl(const VectorImpl &) + : mFlags(0), mItemSize(0) +{ +} + +MOZ_EXPORT VectorImpl::~VectorImpl() +{ +} + +MOZ_EXPORT void VectorImpl::finish_vector() +{ +} + } diff --git a/mobile/android/installer/package-manifest.in b/mobile/android/installer/package-manifest.in index cbca8cefcc2b..9b17fbfe3bcd 100644 --- a/mobile/android/installer/package-manifest.in +++ b/mobile/android/installer/package-manifest.in @@ -47,6 +47,7 @@ @BINPATH@/@DLL_PREFIX@omxplugingb@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@omxplugingb235@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@omxpluginhc@DLL_SUFFIX@ +@BINPATH@/@DLL_PREFIX@omxpluginkk@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@omxpluginfroyo@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@xul@DLL_SUFFIX@ diff --git a/netwerk/protocol/http/nsHttpConnection.cpp b/netwerk/protocol/http/nsHttpConnection.cpp index 4fc6980000cc..51630bba8f58 100644 --- a/netwerk/protocol/http/nsHttpConnection.cpp +++ b/netwerk/protocol/http/nsHttpConnection.cpp @@ -1381,6 +1381,9 @@ nsHttpConnection::OnSocketReadable() PRIntervalTime now = PR_IntervalNow(); PRIntervalTime delta = now - mLastReadTime; + // Reset mResponseTimeoutEnabled to stop response timeout checks. + mResponseTimeoutEnabled = false; + if (mKeepAliveMask && (delta >= mMaxHangTime)) { LOG(("max hang time exceeded!\n")); // give the handler a chance to create a new persistent connection to diff --git a/python/mozboot/mozboot/osx.py b/python/mozboot/mozboot/osx.py index 63b1f2cfc81c..8c42e8629aae 100644 --- a/python/mozboot/mozboot/osx.py +++ b/python/mozboot/mozboot/osx.py @@ -23,7 +23,8 @@ XCODE_APP_STORE = 'macappstore://itunes.apple.com/app/id497799835?mt=12' XCODE_LEGACY = 'https://developer.apple.com/downloads/download.action?path=Developer_Tools/xcode_3.2.6_and_ios_sdk_4.3__final/xcode_3.2.6_and_ios_sdk_4.3.dmg' HOMEBREW_AUTOCONF213 = 'https://raw.github.com/Homebrew/homebrew-versions/master/autoconf213.rb' -MACPORTS_URL = {'8': 'https://distfiles.macports.org/MacPorts/MacPorts-2.1.3-10.8-MountainLion.pkg', +MACPORTS_URL = {'9': 'https://distfiles.macports.org/MacPorts/MacPorts-2.2.1-10.9-Mavericks.pkg', + '8': 'https://distfiles.macports.org/MacPorts/MacPorts-2.1.3-10.8-MountainLion.pkg', '7': 'https://distfiles.macports.org/MacPorts/MacPorts-2.1.3-10.7-Lion.pkg', '6': 'https://distfiles.macports.org/MacPorts/MacPorts-2.1.3-10.6-SnowLeopard.pkg',} diff --git a/testing/marionette/client/marionette/tests/unit/test_wait.py b/testing/marionette/client/marionette/tests/unit/test_wait.py index c82cae9c5e45..7135375e3968 100644 --- a/testing/marionette/client/marionette/tests/unit/test_wait.py +++ b/testing/marionette/client/marionette/tests/unit/test_wait.py @@ -209,3 +209,8 @@ class WaitUntilTest(MarionetteTestCase): self.w.until(lambda x: x.true(wait=4), is_true=at_third_attempt) self.assertEqual(self.clock.ticks, 2) + + def test_timeout_elapsed_duration(self): + with self.assertRaisesRegexp(errors.TimeoutException, + "Timed out after 2 seconds"): + self.w.until(lambda x: x.true(wait=4), is_true=at_third_attempt) diff --git a/testing/marionette/client/marionette/wait.py b/testing/marionette/client/marionette/wait.py index d7158b5ebcd8..856d3b4e9f73 100644 --- a/testing/marionette/client/marionette/wait.py +++ b/testing/marionette/client/marionette/wait.py @@ -40,7 +40,7 @@ class Wait(object): # every 5 seconds. wait = Wait(marionette, timeout=30, interval=5, ignored_exceptions=errors.NoSuchWindowException) - window = wait.until(lambda marionette: marionette.switch_to_window(42)) + window = wait.until(lambda m: m.switch_to_window(42)) :param marionette: The input value to be provided to conditions, usually a Marionette instance. @@ -78,7 +78,6 @@ class Wait(object): exceptions.append(ignored_exceptions) self.exceptions = tuple(set(exceptions)) - def until(self, condition, is_true=None): """Repeatedly runs condition until its return value evaluates to true, or its timeout expires or the predicate evaluates to true. @@ -109,6 +108,7 @@ class Wait(object): rv = None last_exc = None until = is_true or until_pred + start = self.clock.now while not until(self.clock, self.end): try: @@ -130,7 +130,8 @@ class Wait(object): if last_exc is not None: raise last_exc - raise errors.TimeoutException + raise errors.TimeoutException( + "Timed out after %s seconds" % (self.clock.now - start)) def until_pred(clock, end): return clock.now >= end diff --git a/testing/mochitest/android.json b/testing/mochitest/android.json index 9ed14f75b659..cca8acb7a763 100644 --- a/testing/mochitest/android.json +++ b/testing/mochitest/android.json @@ -187,6 +187,8 @@ "dom/tests/mochitest/geolocation/test_mozsettings.html": "mozSettings is undefined", "dom/tests/mochitest/geolocation/test_mozsettingsWatch.html": "mozSettings is undefined", "dom/tests/mochitest/geolocation/test_shutdown.html": "TIMED_OUT", + "dom/tests/mochitest/geolocation/test_timeoutWatch.html": "TIMED_OUT", + "dom/tests/mochitest/geolocation/test_timerRestartWatch.html": "TIMED_OUT", "dom/tests/mochitest/geolocation/test_windowClose.html": "TIMED_OUT", "dom/tests/mochitest/geolocation/test_worseAccuracyDoesNotBlockCallback.html": "TIMED_OUT", "dom/tests/mochitest/localstorage/test_bug624047.html": "TIMED_OUT", diff --git a/toolkit/components/downloads/nsDownloadManager.cpp b/toolkit/components/downloads/nsDownloadManager.cpp index 34be39b7e1dd..07caf1cda36f 100644 --- a/toolkit/components/downloads/nsDownloadManager.cpp +++ b/toolkit/components/downloads/nsDownloadManager.cpp @@ -1093,7 +1093,7 @@ nsDownloadManager::GetDownloadFromDB(const nsACString& aGUID, nsDownload **retVa MOZ_ASSERT(!FindDownload(aGUID), "If it is a current download, you should not call this method!"); - nsDependentCString query = NS_LITERAL_CSTRING( + NS_NAMED_LITERAL_CSTRING(query, "SELECT id, state, startTime, source, target, tempPath, name, referrer, " "entityID, currBytes, maxBytes, mimeType, preferredAction, " "preferredApplication, autoResume, guid " diff --git a/toolkit/mozapps/installer/packager.mk b/toolkit/mozapps/installer/packager.mk index c3c51019b75e..76c12a09b45e 100644 --- a/toolkit/mozapps/installer/packager.mk +++ b/toolkit/mozapps/installer/packager.mk @@ -408,7 +408,8 @@ INNER_MAKE_GECKOVIEW_LIBRARY=echo 'GeckoView library packaging is only enabled o endif ifdef MOZ_OMX_PLUGIN -DIST_FILES += libomxplugin.so libomxplugingb.so libomxplugingb235.so libomxpluginhc.so libomxpluginfroyo.so +DIST_FILES += libomxplugin.so libomxplugingb.so libomxplugingb235.so \ + libomxpluginhc.so libomxpluginfroyo.so libomxpluginkk.so endif SO_LIBRARIES := $(filter %.so,$(DIST_FILES)) diff --git a/toolkit/toolkit.mozbuild b/toolkit/toolkit.mozbuild index eeee4ec3045f..b88a1a2390c1 100644 --- a/toolkit/toolkit.mozbuild +++ b/toolkit/toolkit.mozbuild @@ -87,6 +87,7 @@ if CONFIG['MOZ_OMX_PLUGIN']: 'media/omx-plugin/froyo', 'media/omx-plugin/lib/hc/libstagefright', 'media/omx-plugin/hc', + 'media/omx-plugin/kk', ]) if CONFIG['ENABLE_TESTS']: diff --git a/widget/cocoa/nsAppShell.h b/widget/cocoa/nsAppShell.h index 9a3b27c7a547..eaaf98ea5d66 100644 --- a/widget/cocoa/nsAppShell.h +++ b/widget/cocoa/nsAppShell.h @@ -109,7 +109,6 @@ protected: // to 3%-4%). See bmo bug 395397. static const uint32_t kHadMoreEventsCountMax = 3; - int32_t mRecursionDepth; int32_t mNativeEventCallbackDepth; // Can be set from different threads, so must be modified atomically int32_t mNativeEventScheduledDepth; diff --git a/widget/cocoa/nsAppShell.mm b/widget/cocoa/nsAppShell.mm index 55a059fec587..2104de2c5315 100644 --- a/widget/cocoa/nsAppShell.mm +++ b/widget/cocoa/nsAppShell.mm @@ -210,7 +210,6 @@ nsAppShell::nsAppShell() , mTerminated(false) , mSkippedNativeCallback(false) , mHadMoreEventsCount(0) -, mRecursionDepth(0) , mNativeEventCallbackDepth(0) , mNativeEventScheduledDepth(0) { @@ -712,11 +711,14 @@ nsAppShell::ProcessNextNativeEvent(bool aMayWait) bool nsAppShell::InGeckoMainEventLoop() { - if ((gXULModalLevel > 0) || (mRecursionDepth > 0)) + if (gXULModalLevel > 0) return false; if (mNativeEventCallbackDepth <= 0) return false; - return true; + + bool isProcessingEvents = false; + NS_GetCurrentThread()->GetIsProcessingEvents(&isProcessingEvents); + return !isProcessingEvents; } // Run @@ -818,8 +820,6 @@ nsAppShell::OnProcessNextEvent(nsIThreadInternal *aThread, bool aMayWait, { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - mRecursionDepth = aRecursionDepth; - NS_ASSERTION(mAutoreleasePools, "No stack on which to store autorelease pool"); @@ -845,8 +845,6 @@ nsAppShell::AfterProcessNextEvent(nsIThreadInternal *aThread, { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - mRecursionDepth = aRecursionDepth; - CFIndex count = ::CFArrayGetCount(mAutoreleasePools); NS_ASSERTION(mAutoreleasePools && count, diff --git a/xpcom/base/nsStackWalk.cpp b/xpcom/base/nsStackWalk.cpp index a1a767c791a7..b5441871f228 100644 --- a/xpcom/base/nsStackWalk.cpp +++ b/xpcom/base/nsStackWalk.cpp @@ -66,11 +66,21 @@ stack_callback(void *pc, void *sp, void *closure) } #ifdef DEBUG -#include "nsCocoaFeatures.h" +#define MAC_OS_X_VERSION_10_7_HEX 0x00001070 + +static int32_t OSXVersion() +{ + static int32_t gOSXVersion = 0x0; + if (gOSXVersion == 0x0) { + OSErr err = ::Gestalt(gestaltSystemVersion, (SInt32*)&gOSXVersion); + MOZ_ASSERT(err == noErr); + } + return gOSXVersion; +} static bool OnLionOrLater() { - return nsCocoaFeatures::OnLionOrLater(); + return (OSXVersion() >= MAC_OS_X_VERSION_10_7_HEX); } #endif diff --git a/xpcom/io/nsLocalFileUnix.cpp b/xpcom/io/nsLocalFileUnix.cpp index 215388e9d415..9297851657fb 100644 --- a/xpcom/io/nsLocalFileUnix.cpp +++ b/xpcom/io/nsLocalFileUnix.cpp @@ -1892,8 +1892,7 @@ nsLocalFile::Launch() if (NS_SUCCEEDED(rv)) rv = mimeService->GetTypeFromFile(this, type); - nsDependentCString fileUri = NS_LITERAL_CSTRING("file://"); - fileUri.Append(mPath); + nsAutoCString fileUri = NS_LITERAL_CSTRING("file://") + mPath; return GeckoAppShell::OpenUriExternal(NS_ConvertUTF8toUTF16(fileUri), NS_ConvertUTF8toUTF16(type)) ? NS_OK : NS_ERROR_FAILURE; #elif defined(MOZ_WIDGET_COCOA) CFURLRef url; diff --git a/xpcom/string/public/moz.build b/xpcom/string/public/moz.build index d998d9b63f95..23f8ef1e579d 100644 --- a/xpcom/string/public/moz.build +++ b/xpcom/string/public/moz.build @@ -23,6 +23,7 @@ EXPORTS += [ 'nsSubstringTuple.h', 'nsTDependentString.h', 'nsTDependentSubstring.h', + 'nsTLiteralString.h', 'nsTPromiseFlatString.h', 'nsTString.h', 'nsTSubstring.h', diff --git a/xpcom/string/public/nsAString.h b/xpcom/string/public/nsAString.h index 46f008b8d5fd..79d90b60303a 100644 --- a/xpcom/string/public/nsAString.h +++ b/xpcom/string/public/nsAString.h @@ -16,14 +16,6 @@ #include "nsStringIterator.h" #endif -// If some platform(s) can't handle our template that matches literal strings, -// then we'll disable it on those platforms. -#ifndef NS_DISABLE_LITERAL_TEMPLATE -# if (defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x560)) || (defined(__HP_aCC) && (__HP_aCC <= 012100)) -# define NS_DISABLE_LITERAL_TEMPLATE -# endif -#endif /* !NS_DISABLE_LITERAL_TEMPLATE */ - #include #include diff --git a/xpcom/string/public/nsLiteralString.h b/xpcom/string/public/nsLiteralString.h index ad0a0280fd2e..7a9ab67c3cb7 100644 --- a/xpcom/string/public/nsLiteralString.h +++ b/xpcom/string/public/nsLiteralString.h @@ -10,46 +10,32 @@ #include "nscore.h" #endif -#ifndef nsDependentString_h___ -#include "nsDependentString.h" +#ifndef nsString_h___ +#include "nsString.h" #endif + // declare nsLiteralString +#include "string-template-def-unichar.h" +#include "nsTLiteralString.h" +#include "string-template-undef.h" + + // declare nsLiteralCString +#include "string-template-def-char.h" +#include "nsTLiteralString.h" +#include "string-template-undef.h" + #include "mozilla/Char16.h" -namespace mozilla { -namespace internal { +#define NS_MULTILINE_LITERAL_STRING(s) static_cast(nsLiteralString(s)) +#define NS_MULTILINE_LITERAL_STRING_INIT(n,s) n(s) +#define NS_NAMED_MULTILINE_LITERAL_STRING(n,s) const nsLiteralString n(s) -// This is the same as sizeof(c) - 1, except it won't compile if c isn't a -// string literal. This ensures that NS_LITERAL_CSTRING doesn't compile if you -// pass it a char* (or something else for that matter). -template -inline uint32_t LiteralStringLength(const char (&c)[n]) -{ - return n - 1; -} +#define NS_LITERAL_STRING(s) static_cast(nsLiteralString(MOZ_UTF16(s))) +#define NS_LITERAL_STRING_INIT(n,s) n(MOZ_UTF16(s)) +#define NS_NAMED_LITERAL_STRING(n,s) const nsLiteralString n(MOZ_UTF16(s)) -template -inline uint32_t LiteralWStringLength(const char16_t (&c)[n]) -{ - return n - 1; -} - -} // namespace internal -} // namespace mozilla - -#define NS_MULTILINE_LITERAL_STRING(s) nsDependentString(reinterpret_cast(s), mozilla::internal::LiteralWStringLength(s)) -#define NS_MULTILINE_LITERAL_STRING_INIT(n,s) n(reinterpret_cast(s), mozilla::internal::LiteralWStringLength(s)) -#define NS_NAMED_MULTILINE_LITERAL_STRING(n,s) const nsDependentString n(reinterpret_cast(s), mozilla::internal::LiteralWStringLength(s)) -typedef nsDependentString nsLiteralString; - -#define NS_LITERAL_STRING(s) static_cast(NS_MULTILINE_LITERAL_STRING(MOZ_UTF16(s))) -#define NS_LITERAL_STRING_INIT(n,s) NS_MULTILINE_LITERAL_STRING_INIT(n, MOZ_UTF16(s)) -#define NS_NAMED_LITERAL_STRING(n,s) NS_NAMED_MULTILINE_LITERAL_STRING(n, MOZ_UTF16(s)) - -#define NS_LITERAL_CSTRING(s) static_cast(nsDependentCString(s, mozilla::internal::LiteralStringLength(s))) -#define NS_LITERAL_CSTRING_INIT(n,s) n(s, mozilla::internal::LiteralStringLength(s)) -#define NS_NAMED_LITERAL_CSTRING(n,s) const nsDependentCString n(s, mozilla::internal::LiteralStringLength(s)) - -typedef nsDependentCString nsLiteralCString; +#define NS_LITERAL_CSTRING(s) static_cast(nsLiteralCString(s)) +#define NS_LITERAL_CSTRING_INIT(n,s) n(s) +#define NS_NAMED_LITERAL_CSTRING(n,s) const nsLiteralCString n(s) #endif /* !defined(nsLiteralString_h___) */ diff --git a/xpcom/string/public/nsTLiteralString.h b/xpcom/string/public/nsTLiteralString.h new file mode 100644 index 000000000000..e52f37dcc669 --- /dev/null +++ b/xpcom/string/public/nsTLiteralString.h @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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/. */ + + + /** + * nsTLiteralString_CharT + * + * Stores a null-terminated, immutable sequence of characters. + * + * Subclass of nsTString that restricts string value to a literal + * character sequence. This class does not own its data. The data is + * assumed to be permanent. In practice this is true because this code + * is only usable by and for libxul. + */ +class nsTLiteralString_CharT : public nsTString_CharT + { + public: + + typedef nsTLiteralString_CharT self_type; + + public: + + /** + * constructor + */ + + template + nsTLiteralString_CharT( const char_type (&str)[N] ) + : string_type(const_cast(str), N - 1, F_TERMINATED | F_LITERAL) + { + } + + private: + + // NOT TO BE IMPLEMENTED + template + nsTLiteralString_CharT( char_type (&str)[N] ) MOZ_DELETE; + }; diff --git a/xpcom/string/public/nsTSubstring.h b/xpcom/string/public/nsTSubstring.h index 848737d80fe9..8eef2c0ddb9f 100644 --- a/xpcom/string/public/nsTSubstring.h +++ b/xpcom/string/public/nsTSubstring.h @@ -214,11 +214,21 @@ class nsTSubstring_CharT return mLength; } + uint32_t Flags() const + { + return mFlags; + } + bool IsEmpty() const { return mLength == 0; } + bool IsLiteral() const + { + return (mFlags & F_LITERAL) != 0; + } + bool IsVoid() const { return (mFlags & F_VOIDED) != 0; @@ -297,24 +307,11 @@ class nsTSubstring_CharT // non-constant char array variable. Use EqualsASCII for them. // The template trick to acquire the array length at compile time without // using a macro is due to Corey Kosak, with much thanks. -#ifdef NS_DISABLE_LITERAL_TEMPLATE - inline bool EqualsLiteral( const char* str ) const - { - return EqualsASCII(str); - } -#else template inline bool EqualsLiteral( const char (&str)[N] ) const { return EqualsASCII(str, N-1); } - template - inline bool EqualsLiteral( char (&str)[N] ) const - { - const char* s = str; - return EqualsASCII(s, N-1); - } -#endif // The LowerCaseEquals methods compare the ASCII-lowercase version of // this string (lowercasing only ASCII uppercase characters) to some @@ -330,24 +327,11 @@ class nsTSubstring_CharT // explicit size. Do not attempt to use it with a regular char* // pointer, or with a non-constant char array variable. Use // LowerCaseEqualsASCII for them. -#ifdef NS_DISABLE_LITERAL_TEMPLATE - inline bool LowerCaseEqualsLiteral( const char* str ) const - { - return LowerCaseEqualsASCII(str); - } -#else template inline bool LowerCaseEqualsLiteral( const char (&str)[N] ) const { return LowerCaseEqualsASCII(str, N-1); } - template - inline bool LowerCaseEqualsLiteral( char (&str)[N] ) const - { - const char* s = str; - return LowerCaseEqualsASCII(s, N-1); - } -#endif /** * assignment @@ -406,16 +390,13 @@ class nsTSubstring_CharT // non-constant char array variable. Use AssignASCII for those. // There are not fallible version of these methods because they only really // apply to small allocations that we wouldn't want to check anyway. -#ifdef NS_DISABLE_LITERAL_TEMPLATE - void AssignLiteral( const char* str ) - { AssignASCII(str); } -#else + template + void AssignLiteral( const char_type (&str)[N] ) + { AssignLiteral(str, N - 1); } +#ifdef CharT_is_PRUnichar template void AssignLiteral( const char (&str)[N] ) { AssignASCII(str, N-1); } - template - void AssignLiteral( char (&str)[N] ) - { AssignASCII(str, N-1); } #endif self_type& operator=( char_type c ) { Assign(c); return *this; } @@ -440,6 +421,12 @@ class nsTSubstring_CharT void NS_FASTCALL ReplaceASCII( index_type cutStart, size_type cutLength, const char* data, size_type length = size_type(-1) ); + // ReplaceLiteral must ONLY be applied to an actual literal string. + // Do not attempt to use it with a regular char* pointer, or with a char + // array variable. Use Replace or ReplaceASCII for those. + template + void ReplaceLiteral( index_type cutStart, size_type cutLength, const char_type (&str)[N] ) { ReplaceLiteral(cutStart, cutLength, str, N - 1); } + void Append( char_type c ) { Replace(mLength, 0, c); } void Append( const char_type* data, size_type length = size_type(-1) ) { Replace(mLength, 0, data, length); } @@ -496,17 +483,13 @@ class nsTSubstring_CharT // AppendLiteral must ONLY be applied to an actual literal string. // Do not attempt to use it with a regular char* pointer, or with a char - // array variable. Use AppendASCII for those. -#ifdef NS_DISABLE_LITERAL_TEMPLATE - void AppendLiteral( const char* str ) - { AppendASCII(str); } -#else + // array variable. Use Append or AppendASCII for those. + template + void AppendLiteral( const char_type (&str)[N] ) { ReplaceLiteral(mLength, 0, str, N - 1); } +#ifdef CharT_is_PRUnichar template void AppendLiteral( const char (&str)[N] ) { AppendASCII(str, N-1); } - template - void AppendLiteral( char (&str)[N] ) - { AppendASCII(str, N-1); } #endif self_type& operator+=( char_type c ) { Append(c); return *this; } @@ -526,6 +509,12 @@ class nsTSubstring_CharT void Insert( const self_type& str, index_type pos ) { Replace(pos, 0, str); } void Insert( const substring_tuple_type& tuple, index_type pos ) { Replace(pos, 0, tuple); } + // InsertLiteral must ONLY be applied to an actual literal string. + // Do not attempt to use it with a regular char* pointer, or with a char + // array variable. Use Insert for those. + template + void InsertLiteral( const char_type (&str)[N], index_type pos ) { ReplaceLiteral(pos, 0, str, N - 1); } + void Cut( index_type cutStart, size_type cutLength ) { Replace(cutStart, cutLength, char_traits::sEmptyBuffer, 0); } @@ -845,6 +834,9 @@ class nsTSubstring_CharT mFlags = dataFlags | (mFlags & 0xFFFF0000); } + void NS_FASTCALL AssignLiteral( const char_type* data, size_type length ); + void NS_FASTCALL ReplaceLiteral( index_type cutStart, size_type cutLength, const char_type* data, size_type length ); + static int AppendFunc( void* arg, const char* s, uint32_t len); public: @@ -865,6 +857,7 @@ class nsTSubstring_CharT F_SHARED = 1 << 2, // mData points to a heap-allocated, shared buffer F_OWNED = 1 << 3, // mData points to a heap-allocated, raw buffer F_FIXED = 1 << 4, // mData points to a fixed-size writable, dependent buffer + F_LITERAL = 1 << 5, // mData points to a string literal; F_TERMINATED will also be set // class flags are in the upper 16-bits F_CLASS_FIXED = 1 << 16 // indicates that |this| is of type nsTFixedString diff --git a/xpcom/string/public/string-template-def-char.h b/xpcom/string/public/string-template-def-char.h index 18cbae1eca11..2422f7ae7a7f 100644 --- a/xpcom/string/public/string-template-def-char.h +++ b/xpcom/string/public/string-template-def-char.h @@ -17,6 +17,7 @@ #define nsTDefaultStringComparator_CharT nsDefaultCStringComparator #define nsTDependentString_CharT nsDependentCString #define nsTDependentSubstring_CharT nsDependentCSubstring +#define nsTLiteralString_CharT nsLiteralCString #define nsTXPIDLString_CharT nsXPIDLCString #define nsTGetterCopies_CharT nsCGetterCopies #define nsTAdoptingString_CharT nsAdoptingCString diff --git a/xpcom/string/public/string-template-def-unichar.h b/xpcom/string/public/string-template-def-unichar.h index 72da57204814..2eed8a495bfc 100644 --- a/xpcom/string/public/string-template-def-unichar.h +++ b/xpcom/string/public/string-template-def-unichar.h @@ -17,6 +17,7 @@ #define nsTDefaultStringComparator_CharT nsDefaultStringComparator #define nsTDependentString_CharT nsDependentString #define nsTDependentSubstring_CharT nsDependentSubstring +#define nsTLiteralString_CharT nsLiteralString #define nsTXPIDLString_CharT nsXPIDLString #define nsTGetterCopies_CharT nsGetterCopies #define nsTAdoptingString_CharT nsAdoptingString diff --git a/xpcom/string/public/string-template-undef.h b/xpcom/string/public/string-template-undef.h index 6690b15aca4b..59b4b347aa26 100644 --- a/xpcom/string/public/string-template-undef.h +++ b/xpcom/string/public/string-template-undef.h @@ -18,6 +18,7 @@ #undef nsTDefaultStringComparator_CharT #undef nsTDependentString_CharT #undef nsTDependentSubstring_CharT +#undef nsTLiteralString_CharT #undef nsTXPIDLString_CharT #undef nsTGetterCopies_CharT #undef nsTAdoptingString_CharT diff --git a/xpcom/string/src/nsTDependentString.cpp b/xpcom/string/src/nsTDependentString.cpp index a88fa2822cfe..455e0d09a82f 100644 --- a/xpcom/string/src/nsTDependentString.cpp +++ b/xpcom/string/src/nsTDependentString.cpp @@ -7,6 +7,8 @@ void nsTDependentString_CharT::Rebind( const string_type& str, uint32_t startPos ) { + NS_ABORT_IF_FALSE(str.Flags() & F_TERMINATED, "Unterminated flat string"); + // If we currently own a buffer, release it. Finalize(); @@ -18,5 +20,5 @@ nsTDependentString_CharT::Rebind( const string_type& str, uint32_t startPos ) mData = const_cast(static_cast(str.Data())) + startPos; mLength = strLength - startPos; - SetDataFlags(F_TERMINATED); + SetDataFlags(str.Flags() & (F_TERMINATED | F_LITERAL)); } diff --git a/xpcom/string/src/nsTPromiseFlatString.cpp b/xpcom/string/src/nsTPromiseFlatString.cpp index a1db4c2c3771..0a1cdc93e231 100644 --- a/xpcom/string/src/nsTPromiseFlatString.cpp +++ b/xpcom/string/src/nsTPromiseFlatString.cpp @@ -11,7 +11,8 @@ nsTPromiseFlatString_CharT::Init(const substring_type& str) { mData = const_cast(static_cast(str.Data())); mLength = str.Length(); - mFlags = F_TERMINATED; // does not promote F_VOIDED + mFlags = str.mFlags & (F_TERMINATED | F_LITERAL); + // does not promote F_VOIDED } else { diff --git a/xpcom/string/src/nsTSubstring.cpp b/xpcom/string/src/nsTSubstring.cpp index 0776bc256a10..7c61f5ffa09e 100644 --- a/xpcom/string/src/nsTSubstring.cpp +++ b/xpcom/string/src/nsTSubstring.cpp @@ -351,6 +351,15 @@ nsTSubstring_CharT::AssignASCII( const char* data, size_type length, const falli return true; } +void +nsTSubstring_CharT::AssignLiteral( const char_type* data, size_type length ) + { + ::ReleaseData(mData, mFlags); + mData = const_cast(data); + mLength = length; + SetDataFlags(F_TERMINATED | F_LITERAL); + } + void nsTSubstring_CharT::Assign( const self_type& str ) { @@ -391,6 +400,13 @@ nsTSubstring_CharT::Assign( const self_type& str, const fallible_t& ) nsStringBuffer::FromData(mData)->AddRef(); return true; } + else if (str.mFlags & F_LITERAL) + { + NS_ABORT_IF_FALSE(str.mFlags & F_TERMINATED, "Unterminated literal"); + + AssignLiteral(str.mData, str.mLength); + return true; + } // else, treat this like an ordinary assignment. return Assign(str.Data(), str.Length(), fallible_t()); @@ -536,6 +552,17 @@ nsTSubstring_CharT::Replace( index_type cutStart, size_type cutLength, const sub tuple.WriteTo(mData + cutStart, length); } +void +nsTSubstring_CharT::ReplaceLiteral( index_type cutStart, size_type cutLength, const char_type* data, size_type length ) + { + cutStart = XPCOM_MIN(cutStart, Length()); + + if (!cutStart && cutLength == Length()) + AssignLiteral(data, length); + else if (ReplacePrep(cutStart, cutLength, length) && length > 0) + char_traits::copy(mData + cutStart, data, length); + } + void nsTSubstring_CharT::SetCapacity( size_type capacity ) { diff --git a/xpcom/system/nsIGeolocationProvider.idl b/xpcom/system/nsIGeolocationProvider.idl index 44d930dab379..482dec317537 100644 --- a/xpcom/system/nsIGeolocationProvider.idl +++ b/xpcom/system/nsIGeolocationProvider.idl @@ -17,7 +17,7 @@ interface nsIGeolocationPrompt; * Interface provides a way for a geolocation provider to * notify the system that a new location is available. */ -[scriptable, uuid(f00ff730-acff-4e8c-9991-0d4c84ba0e10)] +[scriptable, uuid(643dc5e9-b911-4b2c-8d44-603162696baf)] interface nsIGeolocationUpdate : nsISupports { /** @@ -27,6 +27,13 @@ interface nsIGeolocationUpdate : nsISupports { */ void update(in nsIDOMGeoPosition position); + /** + * Notify the geolocation service that the location has + * potentially changed, and thus a new position is in the + * process of being acquired. + */ + void locationUpdatePending(); + /** * Notify the geolocation service of an error. * This must be called on the main thread. diff --git a/xpcom/threads/LazyIdleThread.cpp b/xpcom/threads/LazyIdleThread.cpp index 4bc8da9dfaa5..91b489a83dff 100644 --- a/xpcom/threads/LazyIdleThread.cpp +++ b/xpcom/threads/LazyIdleThread.cpp @@ -462,6 +462,17 @@ LazyIdleThread::ProcessNextEvent(bool aMayWait, return NS_ERROR_UNEXPECTED; } +NS_IMETHODIMP +LazyIdleThread::GetIsProcessingEvents(bool* aIsProcessing) +{ + if (mThread) { + return mThread->GetIsProcessingEvents(aIsProcessing); + } + + *aIsProcessing = false; + return NS_OK; +} + NS_IMETHODIMP LazyIdleThread::Notify(nsITimer* aTimer) { diff --git a/xpcom/threads/nsIThread.idl b/xpcom/threads/nsIThread.idl index feeae695ec92..b199b8c933f6 100644 --- a/xpcom/threads/nsIThread.idl +++ b/xpcom/threads/nsIThread.idl @@ -17,7 +17,7 @@ * * See nsIThreadManager for the API used to create and locate threads. */ -[scriptable, uuid(9c889946-a73a-4af3-ae9a-ea64f7d4e3ca)] +[scriptable, uuid(4df07d3a-e759-4256-ba4e-7e2265354ec3)] interface nsIThread : nsIEventTarget { /** @@ -82,4 +82,10 @@ interface nsIThread : nsIEventTarget * not the current thread. */ boolean processNextEvent(in boolean mayWait); + + /** + * true if we're processing runnables or thread observers and if this is the + * current thread. + */ + readonly attribute boolean isProcessingEvents; }; diff --git a/xpcom/threads/nsThread.cpp b/xpcom/threads/nsThread.cpp index ff6a609c8f56..023e840057fb 100644 --- a/xpcom/threads/nsThread.cpp +++ b/xpcom/threads/nsThread.cpp @@ -304,6 +304,7 @@ nsThread::nsThread(MainThreadFlag aMainThread, uint32_t aStackSize) , mThread(nullptr) , mRunningEvent(0) , mStackSize(aStackSize) + , mProcessingEvent(0) , mShutdownContext(nullptr) , mShutdownRequired(false) , mEventsAreDoomed(false) @@ -596,6 +597,8 @@ nsThread::ProcessNextEvent(bool mayWait, bool *result) } } + ++mProcessingEvent; + bool notifyMainThreadObserver = (MAIN_THREAD == mIsMainThread) && sMainThreadObserver; if (notifyMainThreadObserver) @@ -650,9 +653,22 @@ nsThread::ProcessNextEvent(bool mayWait, bool *result) if (notifyMainThreadObserver && sMainThreadObserver) sMainThreadObserver->AfterProcessNextEvent(this, mRunningEvent, *result); + --mProcessingEvent; + return rv; } +NS_IMETHODIMP +nsThread::GetIsProcessingEvents(bool* aIsProcessing) +{ + if (NS_WARN_IF(PR_GetCurrentThread() != mThread)) { + return NS_ERROR_NOT_SAME_THREAD; + } + + *aIsProcessing = mProcessingEvent != 0; + return NS_OK; +} + //----------------------------------------------------------------------------- // nsISupportsPriority diff --git a/xpcom/threads/nsThread.h b/xpcom/threads/nsThread.h index 714fef38ec65..76e744577163 100644 --- a/xpcom/threads/nsThread.h +++ b/xpcom/threads/nsThread.h @@ -150,6 +150,8 @@ protected: uint32_t mRunningEvent; // counter uint32_t mStackSize; + uint32_t mProcessingEvent; + struct nsThreadShutdownContext *mShutdownContext; bool mShutdownRequired;