diff --git a/accessible/src/atk/AccessibleWrap.cpp b/accessible/src/atk/AccessibleWrap.cpp index 4495bebdc7d8..f361f318abd8 100644 --- a/accessible/src/atk/AccessibleWrap.cpp +++ b/accessible/src/atk/AccessibleWrap.cpp @@ -982,7 +982,6 @@ AccessibleWrap::HandleAccEvent(AccEvent* aEvent) { a11y::RootAccessible* rootAccWrap = accWrap->RootAccessible(); if (rootAccWrap && rootAccWrap->mActivated) { - atk_focus_tracker_notify(atkObj); // Fire state change event for focus nsRefPtr stateChangeEvent = new AccStateChangeEvent(accessible, states::FOCUSED, true); @@ -1169,7 +1168,6 @@ AccessibleWrap::HandleAccEvent(AccEvent* aEvent) break; case nsIAccessibleEvent::EVENT_MENUPOPUP_START: - atk_focus_tracker_notify(atkObj); // fire extra focus event atk_object_notify_state_change(atkObj, ATK_STATE_VISIBLE, true); atk_object_notify_state_change(atkObj, ATK_STATE_SHOWING, true); break; diff --git a/b2g/chrome/jar.mn b/b2g/chrome/jar.mn index 1514f481cc95..c8c344be72d8 100644 --- a/b2g/chrome/jar.mn +++ b/b2g/chrome/jar.mn @@ -10,7 +10,6 @@ chrome.jar: content/arrow.svg (content/arrow.svg) * content/dbg-browser-actors.js (content/dbg-browser-actors.js) - content/forms.js (content/forms.js) * content/settings.js (content/settings.js) * content/shell.html (content/shell.html) * content/shell.js (content/shell.js) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 398bdddfad1c..e81250eb92b2 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "207a81a6816b8627674a956b521772de2ac6b572", + "revision": "ab0d6e1927a4fbce5d171555044557c1b7ba25c3", "repo_path": "/integration/gaia-central" } diff --git a/browser/confvars.sh b/browser/confvars.sh index 1f2a0dcad12f..de7436f12d16 100755 --- a/browser/confvars.sh +++ b/browser/confvars.sh @@ -61,5 +61,7 @@ fi MOZ_WEBGL_CONFORMANT=1 # Enable navigator.mozPay MOZ_PAY=1 +# Enable activities. These are used for FxOS developers currently. +MOZ_ACTIVITIES=1 MOZ_JSDOWNLOADS=1 diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in index c6249313dde8..75195c7e30bb 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -521,6 +521,19 @@ @BINPATH@/components/TCPSocketParentIntermediary.js @BINPATH@/components/TCPSocket.manifest +#ifdef MOZ_ACTIVITIES +@BINPATH@/components/SystemMessageInternal.js +@BINPATH@/components/SystemMessageManager.js +@BINPATH@/components/SystemMessageManager.manifest + +@BINPATH@/components/Activities.manifest +@BINPATH@/components/ActivityOptions.js +@BINPATH@/components/ActivityProxy.js +@BINPATH@/components/ActivityRequestHandler.js +@BINPATH@/components/ActivityWrapper.js +@BINPATH@/components/ActivityMessageConfigurator.js +#endif + @BINPATH@/components/Payment.js @BINPATH@/components/PaymentFlowInfo.js @BINPATH@/components/PaymentRequestInfo.js diff --git a/build/autoconf/android.m4 b/build/autoconf/android.m4 index 878594ea9dc0..05271a5be79e 100644 --- a/build/autoconf/android.m4 +++ b/build/autoconf/android.m4 @@ -147,9 +147,15 @@ case "$target" in dnl set up compilers TOOLCHAIN_PREFIX="$android_toolchain/bin/$android_tool_prefix-" AS="$android_toolchain"/bin/"$android_tool_prefix"-as - CC="$android_toolchain"/bin/"$android_tool_prefix"-gcc - CXX="$android_toolchain"/bin/"$android_tool_prefix"-g++ - CPP="$android_toolchain"/bin/"$android_tool_prefix"-cpp + if test -z "$CC"; then + CC="$android_toolchain"/bin/"$android_tool_prefix"-gcc + fi + if test -z "$CXX"; then + CXX="$android_toolchain"/bin/"$android_tool_prefix"-g++ + fi + if test -z "$CPP"; then + CPP="$android_toolchain"/bin/"$android_tool_prefix"-cpp + fi LD="$android_toolchain"/bin/"$android_tool_prefix"-ld AR="$android_toolchain"/bin/"$android_tool_prefix"-ar RANLIB="$android_toolchain"/bin/"$android_tool_prefix"-ranlib diff --git a/configure.in b/configure.in index 9a7495b7794a..2f17bbafc445 100644 --- a/configure.in +++ b/configure.in @@ -7360,6 +7360,14 @@ if test -n "$MOZ_PAY"; then fi AC_SUBST(MOZ_PAY) +dnl ======================================================== +dnl = Enable Browser Support for Activities +dnl ======================================================== +if test -n "$MOZ_ACTIVITIES"; then + AC_DEFINE(MOZ_ACTIVITIES) +fi +AC_SUBST(MOZ_ACTIVITIES) + dnl ======================================================== dnl = Enable Support for AudioChannelManager API dnl ======================================================== diff --git a/content/events/src/nsDOMKeyboardEvent.cpp b/content/events/src/nsDOMKeyboardEvent.cpp index addabd32dd98..99bcd050b8bc 100644 --- a/content/events/src/nsDOMKeyboardEvent.cpp +++ b/content/events/src/nsDOMKeyboardEvent.cpp @@ -90,6 +90,20 @@ nsDOMKeyboardEvent::GetMetaKey(bool* aIsDown) return NS_OK; } +bool +nsDOMKeyboardEvent::Repeat() +{ + return mEvent->AsKeyboardEvent()->mIsRepeat; +} + +NS_IMETHODIMP +nsDOMKeyboardEvent::GetRepeat(bool* aIsRepeat) +{ + NS_ENSURE_ARG_POINTER(aIsRepeat); + *aIsRepeat = Repeat(); + return NS_OK; +} + NS_IMETHODIMP nsDOMKeyboardEvent::GetModifierState(const nsAString& aKey, bool* aState) diff --git a/content/events/src/nsDOMKeyboardEvent.h b/content/events/src/nsDOMKeyboardEvent.h index 20d5df18621f..dd925efce741 100644 --- a/content/events/src/nsDOMKeyboardEvent.h +++ b/content/events/src/nsDOMKeyboardEvent.h @@ -43,6 +43,7 @@ public: return GetModifierStateInternal(aKey); } + bool Repeat(); uint32_t CharCode(); uint32_t KeyCode(); virtual uint32_t Which() MOZ_OVERRIDE; diff --git a/dom/apps/src/Webapps.js b/dom/apps/src/Webapps.js index 8bc801bdf699..f007b5f81696 100644 --- a/dom/apps/src/Webapps.js +++ b/dom/apps/src/Webapps.js @@ -79,27 +79,28 @@ WebappsRegistry.prototype = { return uri.prePath; }, - _validateURL: function(aURL) { + // Checks that the URL scheme is appropriate (http or https) and + // asynchronously fire an error on the DOM Request if it isn't. + _validateURL: function(aURL, aRequest) { let uri; let res; + try { uri = Services.io.newURI(aURL, null, null); if (uri.schemeIs("http") || uri.schemeIs("https")) { res = uri.spec; } } catch(e) { - throw new Components.Exception( - "INVALID_URL: '" + aURL + "'", Cr.NS_ERROR_FAILURE - ); + Services.DOMRequest.fireErrorAsync(aRequest, "INVALID_URL"); + return false; } - // The scheme is incorrect, throw an exception. + // The scheme is incorrect, fire DOMRequest error. if (!res) { - throw new Components.Exception( - "INVALID_URL_SCHEME: '" + uri.scheme + "'; must be 'http' or 'https'", - Cr.NS_ERROR_FAILURE - ); + Services.DOMRequest.fireErrorAsync(aRequest, "INVALID_URL"); + return false; } + return uri.spec; }, @@ -113,13 +114,7 @@ WebappsRegistry.prototype = { return true; } - let runnable = { - run: function run() { - Services.DOMRequest.fireError(aRequest, "BACKGROUND_APP"); - } - } - Services.tm.currentThread.dispatch(runnable, - Ci.nsIThread.DISPATCH_NORMAL); + Services.DOMRequest.fireErrorAsync(aRequest, "BACKGROUND_APP"); return false; }, @@ -155,11 +150,11 @@ WebappsRegistry.prototype = { // mozIDOMApplicationRegistry implementation install: function(aURL, aParams) { - let uri = this._validateURL(aURL); - let request = this.createRequest(); - if (this._ensureForeground(request)) { + let uri = this._validateURL(aURL, request); + + if (uri && this._ensureForeground(request)) { this.addMessageListeners("Webapps:Install:Return:KO"); cpmm.sendAsyncMessage("Webapps:Install", this._prepareInstall(uri, request, aParams, false)); @@ -218,11 +213,11 @@ WebappsRegistry.prototype = { }, installPackage: function(aURL, aParams) { - let uri = this._validateURL(aURL); - let request = this.createRequest(); - if (this._ensureForeground(request)) { + let uri = this._validateURL(aURL, request); + + if (uri && this._ensureForeground(request)) { this.addMessageListeners("Webapps:Install:Return:KO"); cpmm.sendAsyncMessage("Webapps:InstallPackage", this._prepareInstall(uri, request, aParams, true)); @@ -471,13 +466,7 @@ WebappsApplication.prototype = { requestID: this.getRequestId(request) } ); } else { - let runnable = { - run: function run() { - Services.DOMRequest.fireError(request, "NO_CLEARABLE_BROWSER"); - } - } - Services.tm.currentThread.dispatch(runnable, - Ci.nsIThread.DISPATCH_NORMAL); + Services.DOMRequest.fireErrorAsync(request, "NO_CLEARABLE_BROWSER"); } return request; }, @@ -751,7 +740,7 @@ WebappsApplicationMgmt.prototype = { var msg = aMessage.json; let req = this.getRequest(msg.requestID); // We want Webapps:Install:Return:OK and Webapps:Uninstall:Broadcast:Return:OK - // to be boradcasted to all instances of mozApps.mgmt. + // to be broadcasted to all instances of mozApps.mgmt. if (!((msg.oid == this._id && req) || aMessage.name == "Webapps:Install:Return:OK" || aMessage.name == "Webapps:Uninstall:Broadcast:Return:OK")) { diff --git a/dom/apps/tests/test_app_update.html b/dom/apps/tests/test_app_update.html index bf011a67e2e4..b35b69ccf05f 100644 --- a/dom/apps/tests/test_app_update.html +++ b/dom/apps/tests/test_app_update.html @@ -56,6 +56,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=826058 launchableValue = SpecialPowers.setAllAppsLaunchable(true); SpecialPowers.setBoolPref("dom.mozBrowserFramesEnabled", true); + // Test Bug 927699 - navigator.mozApps.install(url) lets NS_ERROR_FAILURE + // onto the web + var request = navigator.mozApps.install(""); + request.onerror = function() { + ok(request.error.name == "INVALID_URL", "Got expected INVALID_URL"); + continueTest(); + }; + request.onsuccess = mozAppsError; + yield undefined; + setAppVersion(1, continueTest); yield undefined; SpecialPowers.autoConfirmAppInstall(continueTest); @@ -69,7 +79,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=826058 setAppVersion(2, continueTest); yield undefined; - var request = navigator.mozApps.install(gHostedManifestURL); + request = navigator.mozApps.install(gHostedManifestURL); request.onerror = mozAppsError; request.onsuccess = continueTest; yield undefined; diff --git a/dom/apps/tests/test_packaged_app_install.html b/dom/apps/tests/test_packaged_app_install.html index 43dfaa068c51..956077e5a139 100644 --- a/dom/apps/tests/test_packaged_app_install.html +++ b/dom/apps/tests/test_packaged_app_install.html @@ -94,6 +94,12 @@ var steps = [ function() { PackagedTestHelper.setAppVersion(0, PackagedTestHelper.next); }, + function() { + // Bug 927699 - navigator.mozApps.install(url) lets NS_ERROR_FAILURE onto + // the web. + ok(true, "== TEST == INVALID_URL"); + checkAppInstallError("", "INVALID_URL"); + }, function() { // Test network error. ok(true, "== TEST == Network error"); diff --git a/dom/browser-element/BrowserElementChild.js b/dom/browser-element/BrowserElementChild.js index 3020e8aa99d3..e855a9a493de 100644 --- a/dom/browser-element/BrowserElementChild.js +++ b/dom/browser-element/BrowserElementChild.js @@ -24,9 +24,14 @@ docShell.setFullscreenAllowed(infos.fullscreenAllowed); if (!('BrowserElementIsPreloaded' in this)) { + try { + if (Services.prefs.getBoolPref("dom.mozInputMethod.enabled")) { + Services.scriptloader.loadSubScript("chrome://global/content/forms.js", global); + } + } catch (e) { + } // Those are produc-specific files that's sometimes unavailable. try { - Services.scriptloader.loadSubScript("chrome://browser/content/forms.js"); Services.scriptloader.loadSubScript("chrome://browser/content/ErrorPage.js"); } catch (e) { } diff --git a/dom/inputmethod/Keyboard.jsm b/dom/inputmethod/Keyboard.jsm index f99acde15438..98f5cab3dbcd 100644 --- a/dom/inputmethod/Keyboard.jsm +++ b/dom/inputmethod/Keyboard.jsm @@ -9,7 +9,7 @@ this.EXPORTED_SYMBOLS = ['Keyboard']; const Cu = Components.utils; const Cc = Components.classes; const Ci = Components.interfaces; -const kFormsFrameScript = 'chrome://browser/content/forms.js'; +const kFormsFrameScript = 'chrome://global/content/forms.js'; Cu.import('resource://gre/modules/Services.jsm'); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); @@ -64,27 +64,31 @@ this.Keyboard = { ppmm.broadcastAsyncMessage('Keyboard:FocusChange', { 'type': 'blur' }); } } else { - mm.addMessageListener('Forms:Input', this); - mm.addMessageListener('Forms:SelectionChange', this); - mm.addMessageListener('Forms:GetText:Result:OK', this); - mm.addMessageListener('Forms:GetText:Result:Error', this); - mm.addMessageListener('Forms:SetSelectionRange:Result:OK', this); - mm.addMessageListener('Forms:ReplaceSurroundingText:Result:OK', this); - mm.addMessageListener('Forms:SendKey:Result:OK', this); - mm.addMessageListener('Forms:SequenceError', this); - mm.addMessageListener('Forms:GetContext:Result:OK', this); - mm.addMessageListener('Forms:SetComposition:Result:OK', this); - mm.addMessageListener('Forms:EndComposition:Result:OK', this); + this.initFormsFrameScript(mm); + } + }, - // When not running apps OOP, we need to load forms.js here since this - // won't happen from dom/ipc/preload.js - try { - if (Services.prefs.getBoolPref("dom.ipc.tabs.disabled") === true) { - mm.loadFrameScript(kFormsFrameScript, true); - } - } catch (e) { - dump('Error loading ' + kFormsFrameScript + ' as frame script: ' + e + '\n'); + initFormsFrameScript: function(mm) { + mm.addMessageListener('Forms:Input', this); + mm.addMessageListener('Forms:SelectionChange', this); + mm.addMessageListener('Forms:GetText:Result:OK', this); + mm.addMessageListener('Forms:GetText:Result:Error', this); + mm.addMessageListener('Forms:SetSelectionRange:Result:OK', this); + mm.addMessageListener('Forms:ReplaceSurroundingText:Result:OK', this); + mm.addMessageListener('Forms:SendKey:Result:OK', this); + mm.addMessageListener('Forms:SequenceError', this); + mm.addMessageListener('Forms:GetContext:Result:OK', this); + mm.addMessageListener('Forms:SetComposition:Result:OK', this); + mm.addMessageListener('Forms:EndComposition:Result:OK', this); + + // When not running apps OOP, we need to load forms.js here since this + // won't happen from dom/ipc/preload.js + try { + if (Services.prefs.getBoolPref("dom.ipc.tabs.disabled") === true) { + mm.loadFrameScript(kFormsFrameScript, true); } + } catch (e) { + dump('Error loading ' + kFormsFrameScript + ' as frame script: ' + e + '\n'); } }, diff --git a/b2g/chrome/content/forms.js b/dom/inputmethod/forms.js similarity index 100% rename from b2g/chrome/content/forms.js rename to dom/inputmethod/forms.js diff --git a/dom/inputmethod/jar.mn b/dom/inputmethod/jar.mn new file mode 100644 index 000000000000..e5a38a6d5109 --- /dev/null +++ b/dom/inputmethod/jar.mn @@ -0,0 +1,6 @@ +# 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/. + +toolkit.jar: + content/global/forms.js (forms.js) diff --git a/dom/interfaces/events/nsIDOMKeyEvent.idl b/dom/interfaces/events/nsIDOMKeyEvent.idl index f17bceeca1f9..a8553260c1dc 100644 --- a/dom/interfaces/events/nsIDOMKeyEvent.idl +++ b/dom/interfaces/events/nsIDOMKeyEvent.idl @@ -5,7 +5,7 @@ #include "nsIDOMUIEvent.idl" -[scriptable, builtinclass, uuid(91a3d7f2-223b-4e09-a566-634e7ee0a31d)] +[scriptable, builtinclass, uuid(2bbf1087-e404-45a5-880a-4f3702aebd4e)] interface nsIDOMKeyEvent : nsIDOMUIEvent { const unsigned long DOM_VK_CANCEL = 0x03; @@ -252,6 +252,7 @@ interface nsIDOMKeyEvent : nsIDOMUIEvent const unsigned long DOM_KEY_LOCATION_JOYSTICK = 0x05; readonly attribute unsigned long location; + readonly attribute boolean repeat; readonly attribute DOMString key; }; diff --git a/dom/ipc/preload.js b/dom/ipc/preload.js index ace0263c6ee3..b54faf76ca6e 100644 --- a/dom/ipc/preload.js +++ b/dom/ipc/preload.js @@ -87,9 +87,15 @@ const BrowserElementIsPreloaded = true; } catch(e) { } + try { + if (Services.prefs.getBoolPref("dom.mozInputMethod.enabled")) { + Services.scriptloader.loadSubScript("chrome://global/content/forms.js", global); + } + } catch (e) { + } + // Those are produc-specific files that's sometimes unavailable. try { - Services.scriptloader.loadSubScript("chrome://browser/content/forms.js", global); Services.scriptloader.loadSubScript("chrome://browser/content/ErrorPage.js", global); } catch (e) { } diff --git a/dom/tests/mochitest/webapps/test_install_errors.xul b/dom/tests/mochitest/webapps/test_install_errors.xul index 4f0d1f234658..fadf97e614af 100644 --- a/dom/tests/mochitest/webapps/test_install_errors.xul +++ b/dom/tests/mochitest/webapps/test_install_errors.xul @@ -168,20 +168,27 @@ function invalidMessage(next) { function fileURL(next) { try { - navigator.mozApps.install("file:///nonexistent"); - ok(false, - "attempt to install nonexistent file: URL doesn't throw exception"); + var req = navigator.mozApps.install("file:///nonexistent"); + req.onsuccess = function() { + ok(false, "Unexpected success installing non existent file"); + }; + req.onerror = function() { + is(this.error.name, "INVALID_URL", "Expected INVALID_URL"); + }; } catch(ex) { - is(ex.message, "INVALID_URL_SCHEME: 'file'; must be 'http' or 'https'", - "attempt to install nonexistent file: URL throws exception"); + ok(false, "Unexpected exception " + ex.message); } try { - navigator.mozApps.install("file:///"); - ok(false, "attempt to install existent file: URL doesn't throw exception"); + req = navigator.mozApps.install("file:///"); + req.onsuccess = function() { + ok(false, "Unexpected success installing file: URL"); + }; + req.onerror = function() { + is(this.error.name, "INVALID_URL", "Expected INVALID_URL"); + }; } catch(ex) { - is(ex.message, "INVALID_URL_SCHEME: 'file'; must be 'http' or 'https'", - "attempt to install existent file: URL throws exception"); + ok(false, "Unexpected exception " + ex.message); } next(); diff --git a/dom/webidl/KeyboardEvent.webidl b/dom/webidl/KeyboardEvent.webidl index b6a295969651..ad7e94c231b6 100644 --- a/dom/webidl/KeyboardEvent.webidl +++ b/dom/webidl/KeyboardEvent.webidl @@ -26,6 +26,7 @@ interface KeyboardEvent : UIEvent const unsigned long DOM_KEY_LOCATION_JOYSTICK = 0x05; readonly attribute unsigned long location; + readonly attribute boolean repeat; readonly attribute DOMString key; }; diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index 9ad93ba05fea..270867255adc 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -440,6 +440,11 @@ public: virtual Rect GetStrokedBounds(const StrokeOptions &aStrokeOptions, const Matrix &aTransform = Matrix()) const = 0; + /* Take the contents of this path and stream it to another sink, this works + * regardless of the backend that might be used for the destination sink. + */ + virtual void StreamToSink(PathSink *aSink) const = 0; + /* This gets the fillrule this path's builder was created with. This is not * mutable. */ diff --git a/gfx/2d/HelpersD2D.h b/gfx/2d/HelpersD2D.h index 720b4072e9a4..e592739445e3 100644 --- a/gfx/2d/HelpersD2D.h +++ b/gfx/2d/HelpersD2D.h @@ -143,6 +143,11 @@ static inline Matrix ToMatrix(const D2D1_MATRIX_3X2_F &aTransform) aTransform._31, aTransform._32); } +static inline Point ToPoint(const D2D1_POINT_2F &aPoint) +{ + return Point(aPoint.x, aPoint.y); +} + static inline DXGI_FORMAT DXGIFormat(SurfaceFormat aFormat) { switch (aFormat) { diff --git a/gfx/2d/HelpersSkia.h b/gfx/2d/HelpersSkia.h index 19b6962c25e2..3d9e191a4e82 100644 --- a/gfx/2d/HelpersSkia.h +++ b/gfx/2d/HelpersSkia.h @@ -250,6 +250,12 @@ IntRectToSkIRect(const IntRect& aRect) return SkIRect::MakeXYWH(aRect.x, aRect.y, aRect.width, aRect.height); } +static inline Point +SkPointToPoint(const SkPoint &aPoint) +{ + return Point(SkScalarToFloat(aPoint.x()), SkScalarToFloat(aPoint.y())); +} + static inline SkShader::TileMode ExtendModeToTileMode(ExtendMode aMode) { diff --git a/gfx/2d/PathCG.h b/gfx/2d/PathCG.h index d79c8911081b..91ce32e7f2eb 100644 --- a/gfx/2d/PathCG.h +++ b/gfx/2d/PathCG.h @@ -85,6 +85,8 @@ public: virtual Rect GetStrokedBounds(const StrokeOptions &aStrokeOptions, const Matrix &aTransform = Matrix()) const; + virtual void StreamToSink(PathSink *aSink) const { MOZ_ASSERT(false); } + virtual FillRule GetFillRule() const { return mFillRule; } CGMutablePathRef GetPath() const { return mPath; } diff --git a/gfx/2d/PathCairo.cpp b/gfx/2d/PathCairo.cpp index 22ec35219ed0..63836f0bb4e5 100644 --- a/gfx/2d/PathCairo.cpp +++ b/gfx/2d/PathCairo.cpp @@ -236,6 +236,35 @@ PathCairo::GetStrokedBounds(const StrokeOptions &aStrokeOptions, return aTransform.TransformBounds(bounds); } +void +PathCairo::StreamToSink(PathSink *aSink) const +{ + for (size_t i = 0; i < mPathData.size(); i++) { + switch (mPathData[i].header.type) { + case CAIRO_PATH_MOVE_TO: + i++; + aSink->MoveTo(Point(mPathData[i].point.x, mPathData[i].point.y)); + break; + case CAIRO_PATH_LINE_TO: + i++; + aSink->LineTo(Point(mPathData[i].point.x, mPathData[i].point.y)); + break; + case CAIRO_PATH_CURVE_TO: + aSink->BezierTo(Point(mPathData[i + 1].point.x, mPathData[i + 1].point.y), + Point(mPathData[i + 2].point.x, mPathData[i + 2].point.y), + Point(mPathData[i + 3].point.x, mPathData[i + 3].point.y)); + i += 3; + break; + case CAIRO_PATH_CLOSE_PATH: + aSink->Close(); + break; + default: + // Corrupt path data! + MOZ_ASSERT(false); + } + } +} + void PathCairo::EnsureContainingContext() const { diff --git a/gfx/2d/PathCairo.h b/gfx/2d/PathCairo.h index c0e856628ec9..2279eaf89f7a 100644 --- a/gfx/2d/PathCairo.h +++ b/gfx/2d/PathCairo.h @@ -69,6 +69,8 @@ public: virtual Rect GetStrokedBounds(const StrokeOptions &aStrokeOptions, const Matrix &aTransform = Matrix()) const; + virtual void StreamToSink(PathSink *aSink) const; + virtual FillRule GetFillRule() const { return mFillRule; } void SetPathOnContext(cairo_t *aContext) const; diff --git a/gfx/2d/PathD2D.cpp b/gfx/2d/PathD2D.cpp index ef5d74669af7..a6bd78e1736c 100644 --- a/gfx/2d/PathD2D.cpp +++ b/gfx/2d/PathD2D.cpp @@ -91,6 +91,70 @@ private: bool mNeedsFigureEnded; }; +class StreamingGeometrySink : public ID2D1SimplifiedGeometrySink +{ +public: + StreamingGeometrySink(PathSink *aSink) + : mSink(aSink) + { + } + + HRESULT STDMETHODCALLTYPE QueryInterface(const IID &aIID, void **aPtr) + { + if (!aPtr) { + return E_POINTER; + } + + if (aIID == IID_IUnknown) { + *aPtr = static_cast(this); + return S_OK; + } else if (aIID == IID_ID2D1SimplifiedGeometrySink) { + *aPtr = static_cast(this); + return S_OK; + } + + return E_NOINTERFACE; + } + + ULONG STDMETHODCALLTYPE AddRef() + { + return 1; + } + + ULONG STDMETHODCALLTYPE Release() + { + return 1; + } + + // We ignore SetFillMode, this depends on the destination sink. + STDMETHOD_(void, SetFillMode)(D2D1_FILL_MODE aMode) + { return; } + STDMETHOD_(void, BeginFigure)(D2D1_POINT_2F aPoint, D2D1_FIGURE_BEGIN aBegin) + { mSink->MoveTo(ToPoint(aPoint)); } + STDMETHOD_(void, AddLines)(const D2D1_POINT_2F *aLines, UINT aCount) + { for (UINT i = 0; i < aCount; i++) { mSink->LineTo(ToPoint(aLines[i])); } } + STDMETHOD_(void, AddBeziers)(const D2D1_BEZIER_SEGMENT *aSegments, UINT aCount) + { + for (UINT i = 0; i < aCount; i++) { + mSink->BezierTo(ToPoint(aSegments[i].point1), ToPoint(aSegments[i].point2), ToPoint(aSegments[i].point3)); + } + } + STDMETHOD(Close)() + { /* Should never be called! */ return S_OK; } + STDMETHOD_(void, SetSegmentFlags)(D2D1_PATH_SEGMENT aFlags) + { /* Should never be called! */ } + + STDMETHOD_(void, EndFigure)(D2D1_FIGURE_END aEnd) + { + if (aEnd == D2D1_FIGURE_END_CLOSED) { + return mSink->Close(); + } + } +private: + + PathSink *mSink; +}; + PathBuilderD2D::~PathBuilderD2D() { } @@ -292,6 +356,22 @@ PathD2D::TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule) return pathBuilder; } +void +PathD2D::StreamToSink(PathSink *aSink) const +{ + HRESULT hr; + + StreamingGeometrySink sink(aSink); + + hr = mGeometry->Simplify(D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES, + D2D1::IdentityMatrix(), &sink); + + if (FAILED(hr)) { + gfxWarning() << "Failed to stream D2D path to sink. Code: " << hr; + return; + } +} + bool PathD2D::ContainsPoint(const Point &aPoint, const Matrix &aTransform) const { diff --git a/gfx/2d/PathD2D.h b/gfx/2d/PathD2D.h index 84171efdf9ba..28cc7f827dc4 100644 --- a/gfx/2d/PathD2D.h +++ b/gfx/2d/PathD2D.h @@ -85,6 +85,8 @@ public: virtual Rect GetStrokedBounds(const StrokeOptions &aStrokeOptions, const Matrix &aTransform = Matrix()) const; + virtual void StreamToSink(PathSink *aSink) const; + virtual FillRule GetFillRule() const { return mFillRule; } ID2D1Geometry *GetGeometry() { return mGeometry; } diff --git a/gfx/2d/PathRecording.h b/gfx/2d/PathRecording.h index 8c89cb7e346a..9705503da39e 100644 --- a/gfx/2d/PathRecording.h +++ b/gfx/2d/PathRecording.h @@ -106,7 +106,9 @@ public: virtual Rect GetStrokedBounds(const StrokeOptions &aStrokeOptions, const Matrix &aTransform = Matrix()) const { return mPath->GetStrokedBounds(aStrokeOptions, aTransform); } - + + virtual void StreamToSink(PathSink *aSink) const { mPath->StreamToSink(aSink); } + virtual FillRule GetFillRule() const { return mFillRule; } void StorePath(std::ostream &aStream) const; diff --git a/gfx/2d/PathSkia.cpp b/gfx/2d/PathSkia.cpp index 132e5dc5a5ba..5b4b6d9cd5f5 100644 --- a/gfx/2d/PathSkia.cpp +++ b/gfx/2d/PathSkia.cpp @@ -209,5 +209,39 @@ PathSkia::GetStrokedBounds(const StrokeOptions &aStrokeOptions, return aTransform.TransformBounds(bounds); } +void +PathSkia::StreamToSink(PathSink *aSink) const +{ + SkPath::RawIter iter(mPath); + + SkPoint points[4]; + SkPath::Verb currentVerb; + while ((currentVerb = iter.next(points)) != SkPath::kDone_Verb) { + switch (currentVerb) { + case SkPath::kMove_Verb: + aSink->MoveTo(SkPointToPoint(points[0])); + break; + case SkPath::kLine_Verb: + aSink->LineTo(SkPointToPoint(points[1])); + break; + case SkPath::kCubic_Verb: + aSink->BezierTo(SkPointToPoint(points[1]), + SkPointToPoint(points[2]), + SkPointToPoint(points[3])); + break; + case SkPath::kQuad_Verb: + aSink->QuadraticBezierTo(SkPointToPoint(points[1]), + SkPointToPoint(points[2])); + break; + case SkPath::kClose_Verb: + aSink->Close(); + break; + default: + MOZ_ASSERT(false); + // Unexpected verb found in path! + } + } +} + } } diff --git a/gfx/2d/PathSkia.h b/gfx/2d/PathSkia.h index df6f5718a3a3..14b43a6c8c49 100644 --- a/gfx/2d/PathSkia.h +++ b/gfx/2d/PathSkia.h @@ -66,6 +66,8 @@ public: virtual Rect GetStrokedBounds(const StrokeOptions &aStrokeOptions, const Matrix &aTransform = Matrix()) const; + virtual void StreamToSink(PathSink *aSink) const; + virtual FillRule GetFillRule() const { return mFillRule; } const SkPath& GetPath() const { return mPath; } diff --git a/gfx/layers/Compositor.cpp b/gfx/layers/Compositor.cpp index f65f79168c24..824bee5f7415 100644 --- a/gfx/layers/Compositor.cpp +++ b/gfx/layers/Compositor.cpp @@ -53,8 +53,7 @@ void Compositor::DrawDiagnostics(DiagnosticFlags aFlags, const nsIntRegion& aVisibleRegion, const gfx::Rect& aClipRect, - const gfx::Matrix4x4& aTransform, - const gfx::Point& aOffset) + const gfx::Matrix4x4& aTransform) { if (!ShouldDrawDiagnostics(aFlags)) { return; @@ -66,36 +65,33 @@ Compositor::DrawDiagnostics(DiagnosticFlags aFlags, while (const nsIntRect* rect = screenIter.Next()) { DrawDiagnostics(aFlags | DIAGNOSTIC_REGION_RECT, - ToRect(*rect), aClipRect, aTransform, aOffset); + ToRect(*rect), aClipRect, aTransform); } } DrawDiagnostics(aFlags, ToRect(aVisibleRegion.GetBounds()), - aClipRect, aTransform, aOffset); + aClipRect, aTransform); } void Compositor::DrawDiagnostics(DiagnosticFlags aFlags, const gfx::Rect& aVisibleRect, const gfx::Rect& aClipRect, - const gfx::Matrix4x4& aTransform, - const gfx::Point& aOffset) + const gfx::Matrix4x4& aTransform) { if (!ShouldDrawDiagnostics(aFlags)) { return; } DrawDiagnosticsInternal(aFlags, aVisibleRect, - aClipRect, aTransform, - aOffset); + aClipRect, aTransform); } void Compositor::DrawDiagnosticsInternal(DiagnosticFlags aFlags, const gfx::Rect& aVisibleRect, const gfx::Rect& aClipRect, - const gfx::Matrix4x4& aTransform, - const gfx::Point& aOffset) + const gfx::Matrix4x4& aTransform) { #ifdef MOZ_B2G int lWidth = 4; @@ -138,22 +134,22 @@ Compositor::DrawDiagnosticsInternal(DiagnosticFlags aFlags, this->DrawQuad(gfx::Rect(aVisibleRect.x, aVisibleRect.y, lWidth, aVisibleRect.height), aClipRect, effects, opacity, - aTransform, aOffset); + aTransform); // top this->DrawQuad(gfx::Rect(aVisibleRect.x + lWidth, aVisibleRect.y, aVisibleRect.width - 2 * lWidth, lWidth), aClipRect, effects, opacity, - aTransform, aOffset); + aTransform); // right this->DrawQuad(gfx::Rect(aVisibleRect.x + aVisibleRect.width - lWidth, aVisibleRect.y, lWidth, aVisibleRect.height), aClipRect, effects, opacity, - aTransform, aOffset); + aTransform); // bottom this->DrawQuad(gfx::Rect(aVisibleRect.x + lWidth, aVisibleRect.y + aVisibleRect.height-lWidth, aVisibleRect.width - 2 * lWidth, lWidth), aClipRect, effects, opacity, - aTransform, aOffset); + aTransform); } } // namespace diff --git a/gfx/layers/Compositor.h b/gfx/layers/Compositor.h index 7f148973f125..23c700c6d692 100644 --- a/gfx/layers/Compositor.h +++ b/gfx/layers/Compositor.h @@ -125,8 +125,7 @@ class CompositingRenderTarget; enum SurfaceInitMode { INIT_MODE_NONE, - INIT_MODE_CLEAR, - INIT_MODE_COPY + INIT_MODE_CLEAR }; /** @@ -248,10 +247,13 @@ public: * Creates a Surface that can be used as a rendering target by this * compositor, and initializes the surface by copying from aSource. * If aSource is null, then the current screen buffer is used as source. + * + * aSourcePoint specifies the point in aSource to copy data from. */ virtual TemporaryRef CreateRenderTargetFromSource(const gfx::IntRect& aRect, - const CompositingRenderTarget* aSource) = 0; + const CompositingRenderTarget* aSource, + const gfx::IntPoint& aSourcePoint) = 0; /** * Sets the given surface as the target for subsequent calls to DrawQuad. @@ -280,14 +282,12 @@ public: /** * Tell the compositor to actually draw a quad. What to do draw and how it is * drawn is specified by aEffectChain. aRect is the quad to draw, in user space. - * aTransform transforms from user space to screen space. aOffset is the - * offset of the render target from 0,0 of the screen. If texture coords are + * aTransform transforms from user space to screen space. If texture coords are * required, these will be in the primary effect in the effect chain. */ virtual void DrawQuad(const gfx::Rect& aRect, const gfx::Rect& aClipRect, const EffectChain& aEffectChain, - gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform, - const gfx::Point& aOffset) = 0; + gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform) = 0; /** * Start a new frame. @@ -349,14 +349,12 @@ public: void DrawDiagnostics(DiagnosticFlags aFlags, const gfx::Rect& visibleRect, const gfx::Rect& aClipRect, - const gfx::Matrix4x4& transform, - const gfx::Point& aOffset); + const gfx::Matrix4x4& transform); void DrawDiagnostics(DiagnosticFlags aFlags, const nsIntRegion& visibleRegion, const gfx::Rect& aClipRect, - const gfx::Matrix4x4& transform, - const gfx::Point& aOffset); + const gfx::Matrix4x4& transform); #ifdef MOZ_DUMP_PAINTING @@ -432,8 +430,7 @@ protected: void DrawDiagnosticsInternal(DiagnosticFlags aFlags, const gfx::Rect& aVisibleRect, const gfx::Rect& aClipRect, - const gfx::Matrix4x4& transform, - const gfx::Point& aOffset); + const gfx::Matrix4x4& transform); bool ShouldDrawDiagnostics(DiagnosticFlags); diff --git a/gfx/layers/basic/BasicCompositor.cpp b/gfx/layers/basic/BasicCompositor.cpp index a263b055377b..1931a416ce84 100644 --- a/gfx/layers/basic/BasicCompositor.cpp +++ b/gfx/layers/basic/BasicCompositor.cpp @@ -250,20 +250,20 @@ void BasicCompositor::Destroy() TemporaryRef BasicCompositor::CreateRenderTarget(const IntRect& aRect, SurfaceInitMode aInit) { - MOZ_ASSERT(aInit != INIT_MODE_COPY); RefPtr target = mDrawTarget->CreateSimilarDrawTarget(aRect.Size(), FORMAT_B8G8R8A8); - RefPtr rt = new BasicCompositingRenderTarget(target, aRect.Size()); + RefPtr rt = new BasicCompositingRenderTarget(target, aRect); return rt.forget(); } TemporaryRef BasicCompositor::CreateRenderTargetFromSource(const IntRect &aRect, - const CompositingRenderTarget *aSource) + const CompositingRenderTarget *aSource, + const IntPoint &aSourcePoint) { RefPtr target = mDrawTarget->CreateSimilarDrawTarget(aRect.Size(), FORMAT_B8G8R8A8); - RefPtr rt = new BasicCompositingRenderTarget(target, aRect.Size()); + RefPtr rt = new BasicCompositingRenderTarget(target, aRect); DrawTarget *source; if (aSource) { @@ -276,7 +276,8 @@ BasicCompositor::CreateRenderTargetFromSource(const IntRect &aRect, RefPtr snapshot = source->Snapshot(); - rt->mDrawTarget->CopySurface(snapshot, aRect, IntPoint(0, 0)); + IntRect sourceRect(aSourcePoint, aRect.Size()); + rt->mDrawTarget->CopySurface(snapshot, sourceRect, IntPoint(0, 0)); return rt.forget(); } @@ -330,12 +331,13 @@ DrawSurfaceWithTextureCoords(DrawTarget *aDest, } void -BasicCompositor::DrawQuad(const gfx::Rect& aRect, const gfx::Rect& aClipRect, +BasicCompositor::DrawQuad(const gfx::Rect& aRect, + const gfx::Rect& aClipRect, const EffectChain &aEffectChain, - gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform, - const gfx::Point& aOffset) + gfx::Float aOpacity, + const gfx::Matrix4x4 &aTransform) { - DrawTarget *dest = mRenderTarget ? mRenderTarget->mDrawTarget : mDrawTarget; + DrawTarget *dest = mRenderTarget->mDrawTarget; if (!aTransform.Is2D()) { NS_WARNING("Can't handle 3D transforms yet!"); @@ -346,7 +348,8 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect, const gfx::Rect& aClipRect, Matrix oldTransform = dest->GetTransform(); Matrix newTransform = aTransform.As2D(); - newTransform.Translate(-aOffset.x, -aOffset.y); + IntPoint offset = mRenderTarget->GetOrigin(); + newTransform.Translate(-offset.x, -offset.y); dest->SetTransform(newTransform); RefPtr sourceMask; diff --git a/gfx/layers/basic/BasicCompositor.h b/gfx/layers/basic/BasicCompositor.h index 323f1708cd2f..c3227b6faba5 100644 --- a/gfx/layers/basic/BasicCompositor.h +++ b/gfx/layers/basic/BasicCompositor.h @@ -19,9 +19,10 @@ namespace layers { class BasicCompositingRenderTarget : public CompositingRenderTarget { public: - BasicCompositingRenderTarget(gfx::DrawTarget* aDrawTarget, const gfx::IntSize& aSize) - : mDrawTarget(aDrawTarget) - , mSize(aSize) + BasicCompositingRenderTarget(gfx::DrawTarget* aDrawTarget, const gfx::IntRect& aRect) + : CompositingRenderTarget(aRect.TopLeft()) + , mDrawTarget(aDrawTarget) + , mSize(aRect.Size()) { } virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; } @@ -60,7 +61,8 @@ public: virtual TemporaryRef CreateRenderTargetFromSource(const gfx::IntRect &aRect, - const CompositingRenderTarget *aSource) MOZ_OVERRIDE; + const CompositingRenderTarget *aSource, + const gfx::IntPoint &aSourcePoint) MOZ_OVERRIDE; virtual TemporaryRef CreateDataTextureSource(TextureFlags aFlags = 0) MOZ_OVERRIDE; @@ -76,10 +78,11 @@ public: return mRenderTarget; } - virtual void DrawQuad(const gfx::Rect& aRect, const gfx::Rect& aClipRect, + virtual void DrawQuad(const gfx::Rect& aRect, + const gfx::Rect& aClipRect, const EffectChain &aEffectChain, - gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform, - const gfx::Point& aOffset) MOZ_OVERRIDE; + gfx::Float aOpacity, + const gfx::Matrix4x4 &aTransform) MOZ_OVERRIDE; virtual void BeginFrame(const gfx::Rect *aClipRectIn, const gfxMatrix& aTransform, diff --git a/gfx/layers/composite/CanvasLayerComposite.cpp b/gfx/layers/composite/CanvasLayerComposite.cpp index ca810cb99d73..2f747166a281 100644 --- a/gfx/layers/composite/CanvasLayerComposite.cpp +++ b/gfx/layers/composite/CanvasLayerComposite.cpp @@ -61,8 +61,7 @@ CanvasLayerComposite::GetRenderState() } void -CanvasLayerComposite::RenderLayer(const nsIntPoint& aOffset, - const nsIntRect& aClipRect) +CanvasLayerComposite::RenderLayer(const nsIntRect& aClipRect) { if (!mImageHost || !mImageHost->IsAttached()) { return; @@ -98,7 +97,6 @@ CanvasLayerComposite::RenderLayer(const nsIntPoint& aOffset, mImageHost->Composite(effectChain, GetEffectiveOpacity(), transform, - gfx::Point(aOffset.x, aOffset.y), gfx::ToFilter(filter), clipRect); } diff --git a/gfx/layers/composite/CanvasLayerComposite.h b/gfx/layers/composite/CanvasLayerComposite.h index 4fbd3d5b5738..adb224305078 100644 --- a/gfx/layers/composite/CanvasLayerComposite.h +++ b/gfx/layers/composite/CanvasLayerComposite.h @@ -48,8 +48,7 @@ public: } virtual Layer* GetLayer() MOZ_OVERRIDE; - virtual void RenderLayer(const nsIntPoint& aOffset, - const nsIntRect& aClipRect) MOZ_OVERRIDE; + virtual void RenderLayer(const nsIntRect& aClipRect) MOZ_OVERRIDE; virtual void CleanupResources() MOZ_OVERRIDE; diff --git a/gfx/layers/composite/ColorLayerComposite.cpp b/gfx/layers/composite/ColorLayerComposite.cpp index 9b1fa529242e..f31d6a5cd90a 100644 --- a/gfx/layers/composite/ColorLayerComposite.cpp +++ b/gfx/layers/composite/ColorLayerComposite.cpp @@ -22,8 +22,7 @@ namespace mozilla { namespace layers { void -ColorLayerComposite::RenderLayer(const nsIntPoint& aOffset, - const nsIntRect& aClipRect) +ColorLayerComposite::RenderLayer(const nsIntRect& aClipRect) { EffectChain effects; gfxRGBA color(GetColor()); @@ -46,11 +45,10 @@ ColorLayerComposite::RenderLayer(const nsIntPoint& aOffset, gfx::Matrix4x4 transform; ToMatrix4x4(GetEffectiveTransform(), transform); - mCompositor->DrawQuad(rect, clipRect, effects, opacity, - transform, gfx::Point(aOffset.x, aOffset.y)); + mCompositor->DrawQuad(rect, clipRect, effects, opacity, transform); mCompositor->DrawDiagnostics(DIAGNOSTIC_COLOR, rect, clipRect, - transform, gfx::Point(aOffset.x, aOffset.y)); + transform); } } /* layers */ diff --git a/gfx/layers/composite/ColorLayerComposite.h b/gfx/layers/composite/ColorLayerComposite.h index f3e44acc9b92..c6e0fbc2b1bb 100644 --- a/gfx/layers/composite/ColorLayerComposite.h +++ b/gfx/layers/composite/ColorLayerComposite.h @@ -42,8 +42,7 @@ public: virtual void Destroy() MOZ_OVERRIDE { mDestroyed = true; } - virtual void RenderLayer(const nsIntPoint& aOffset, - const nsIntRect& aClipRect) MOZ_OVERRIDE; + virtual void RenderLayer(const nsIntRect& aClipRect) MOZ_OVERRIDE; virtual void CleanupResources() MOZ_OVERRIDE {}; CompositableHost* GetCompositableHost() MOZ_OVERRIDE { return nullptr; } diff --git a/gfx/layers/composite/CompositableHost.h b/gfx/layers/composite/CompositableHost.h index 776430699b3e..ce00f8571fab 100644 --- a/gfx/layers/composite/CompositableHost.h +++ b/gfx/layers/composite/CompositableHost.h @@ -114,7 +114,6 @@ public: virtual void Composite(EffectChain& aEffectChain, float aOpacity, const gfx::Matrix4x4& aTransform, - const gfx::Point& aOffset, const gfx::Filter& aFilter, const gfx::Rect& aClipRect, const nsIntRegion* aVisibleRegion = nullptr, diff --git a/gfx/layers/composite/ContainerLayerComposite.cpp b/gfx/layers/composite/ContainerLayerComposite.cpp index 8bdbd855343f..8d4737fb27e9 100644 --- a/gfx/layers/composite/ContainerLayerComposite.cpp +++ b/gfx/layers/composite/ContainerLayerComposite.cpp @@ -81,7 +81,6 @@ GetOpaqueRect(Layer* aLayer) template void ContainerRender(ContainerT* aContainer, - const nsIntPoint& aOffset, LayerManagerComposite* aManager, const nsIntRect& aClipRect) { @@ -94,7 +93,6 @@ ContainerRender(ContainerT* aContainer, RefPtr previousTarget = compositor->GetCurrentRenderTarget(); - nsIntPoint childOffset(aOffset); nsIntRect visibleRect = aContainer->GetEffectiveVisibleRegion().GetBounds(); aContainer->mSupportsComponentAlphaChildren = false; @@ -107,6 +105,7 @@ ContainerRender(ContainerT* aContainer, bool surfaceCopyNeeded = false; gfx::IntRect surfaceRect = gfx::IntRect(visibleRect.x, visibleRect.y, visibleRect.width, visibleRect.height); + gfx::IntPoint sourcePoint = gfx::IntPoint(visibleRect.x, visibleRect.y); // we're about to create a framebuffer backed by textures to use as an intermediate // surface. What to do if its size (as given by framebufferRect) would exceed the // maximum texture size supported by the GL? The present code chooses the compromise @@ -131,19 +130,17 @@ ContainerRender(ContainerT* aContainer, // not safe. if (HasOpaqueAncestorLayer(aContainer) && transform3D.Is2D(&transform) && !transform.HasNonIntegerTranslation()) { - mode = gfxPlatform::ComponentAlphaEnabled() ? - INIT_MODE_COPY : INIT_MODE_CLEAR; - surfaceCopyNeeded = (mode == INIT_MODE_COPY); - surfaceRect.x += transform.x0; - surfaceRect.y += transform.y0; + surfaceCopyNeeded = gfxPlatform::ComponentAlphaEnabled(); + sourcePoint.x += transform.x0; + sourcePoint.y += transform.y0; aContainer->mSupportsComponentAlphaChildren = gfxPlatform::ComponentAlphaEnabled(); } } - surfaceRect -= gfx::IntPoint(aOffset.x, aOffset.y); + sourcePoint -= compositor->GetCurrentRenderTarget()->GetOrigin(); if (surfaceCopyNeeded) { - surface = compositor->CreateRenderTargetFromSource(surfaceRect, previousTarget); + surface = compositor->CreateRenderTargetFromSource(surfaceRect, previousTarget, sourcePoint); } else { surface = compositor->CreateRenderTarget(surfaceRect, mode); } @@ -153,8 +150,6 @@ ContainerRender(ContainerT* aContainer, } compositor->SetRenderTarget(surface); - childOffset.x = visibleRect.x; - childOffset.y = visibleRect.y; } else { surface = previousTarget; aContainer->mSupportsComponentAlphaChildren = (aContainer->GetContentFlags() & Layer::CONTENT_OPAQUE) || @@ -203,7 +198,7 @@ ContainerRender(ContainerT* aContainer, // this time & reset composition flag for next composition phase layerToRender->SetLayerComposited(false); } else { - layerToRender->RenderLayer(childOffset, clipRect); + layerToRender->RenderLayer(clipRect); } // invariant: our GL context should be current here, I don't think we can // assert it though @@ -232,7 +227,7 @@ ContainerRender(ContainerT* aContainer, gfx::Rect rect(visibleRect.x, visibleRect.y, visibleRect.width, visibleRect.height); gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height); aManager->GetCompositor()->DrawQuad(rect, clipRect, effectChain, opacity, - transform, gfx::Point(aOffset.x, aOffset.y)); + transform); } if (aContainer->GetFrameMetrics().IsScrollable()) { @@ -245,7 +240,7 @@ ContainerRender(ContainerT* aContainer, gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height); aManager->GetCompositor()->DrawDiagnostics(DIAGNOSTIC_CONTAINER, rect, clipRect, - transform, gfx::Point(aOffset.x, aOffset.y)); + transform); } } @@ -297,10 +292,9 @@ ContainerLayerComposite::GetFirstChildComposite() } void -ContainerLayerComposite::RenderLayer(const nsIntPoint& aOffset, - const nsIntRect& aClipRect) +ContainerLayerComposite::RenderLayer(const nsIntRect& aClipRect) { - ContainerRender(this, aOffset, mCompositeManager, aClipRect); + ContainerRender(this, mCompositeManager, aClipRect); } void @@ -341,10 +335,9 @@ RefLayerComposite::GetFirstChildComposite() } void -RefLayerComposite::RenderLayer(const nsIntPoint& aOffset, - const nsIntRect& aClipRect) +RefLayerComposite::RenderLayer(const nsIntRect& aClipRect) { - ContainerRender(this, aOffset, mCompositeManager, aClipRect); + ContainerRender(this, mCompositeManager, aClipRect); } void diff --git a/gfx/layers/composite/ContainerLayerComposite.h b/gfx/layers/composite/ContainerLayerComposite.h index 8b7f7dfc1bed..cba95c6ff829 100644 --- a/gfx/layers/composite/ContainerLayerComposite.h +++ b/gfx/layers/composite/ContainerLayerComposite.h @@ -25,7 +25,6 @@ class ContainerLayerComposite : public ContainerLayer, { template friend void ContainerRender(ContainerT* aContainer, - const nsIntPoint& aOffset, LayerManagerComposite* aManager, const nsIntRect& aClipRect); public: @@ -40,8 +39,7 @@ public: LayerComposite* GetFirstChildComposite(); - virtual void RenderLayer(const nsIntPoint& aOffset, - const nsIntRect& aClipRect) MOZ_OVERRIDE; + virtual void RenderLayer(const nsIntRect& aClipRect) MOZ_OVERRIDE; virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) MOZ_OVERRIDE { @@ -65,7 +63,6 @@ class RefLayerComposite : public RefLayer, { template friend void ContainerRender(ContainerT* aContainer, - const nsIntPoint& aOffset, LayerManagerComposite* aManager, const nsIntRect& aClipRect); public: @@ -79,8 +76,7 @@ public: LayerComposite* GetFirstChildComposite(); - virtual void RenderLayer(const nsIntPoint& aOffset, - const nsIntRect& aClipRect) MOZ_OVERRIDE; + virtual void RenderLayer(const nsIntRect& aClipRect) MOZ_OVERRIDE; virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) MOZ_OVERRIDE { diff --git a/gfx/layers/composite/ContentHost.cpp b/gfx/layers/composite/ContentHost.cpp index e3cc04759a05..99b735cd2b6d 100644 --- a/gfx/layers/composite/ContentHost.cpp +++ b/gfx/layers/composite/ContentHost.cpp @@ -56,7 +56,6 @@ void ContentHostBase::Composite(EffectChain& aEffectChain, float aOpacity, const gfx::Matrix4x4& aTransform, - const Point& aOffset, const Filter& aFilter, const Rect& aClipRect, const nsIntRegion* aVisibleRegion, @@ -188,12 +187,12 @@ ContentHostBase::Composite(EffectChain& aEffectChain, Float(tileRegionRect.y) / texRect.height, Float(tileRegionRect.width) / texRect.width, Float(tileRegionRect.height) / texRect.height); - GetCompositor()->DrawQuad(rect, aClipRect, aEffectChain, aOpacity, aTransform, aOffset); + GetCompositor()->DrawQuad(rect, aClipRect, aEffectChain, aOpacity, aTransform); if (usingTiles) { DiagnosticTypes diagnostics = DIAGNOSTIC_CONTENT | DIAGNOSTIC_BIGIMAGE; diagnostics |= iterOnWhite ? DIAGNOSTIC_COMPONENT_ALPHA : 0; GetCompositor()->DrawDiagnostics(diagnostics, rect, aClipRect, - aTransform, aOffset); + aTransform); } } } @@ -213,7 +212,7 @@ ContentHostBase::Composite(EffectChain& aEffectChain, DiagnosticTypes diagnostics = DIAGNOSTIC_CONTENT; diagnostics |= iterOnWhite ? DIAGNOSTIC_COMPONENT_ALPHA : 0; - GetCompositor()->DrawDiagnostics(diagnostics, *aVisibleRegion, aClipRect, aTransform, aOffset); + GetCompositor()->DrawDiagnostics(diagnostics, *aVisibleRegion, aClipRect, aTransform); } void diff --git a/gfx/layers/composite/ContentHost.h b/gfx/layers/composite/ContentHost.h index 7c9470beb617..ed606400b626 100644 --- a/gfx/layers/composite/ContentHost.h +++ b/gfx/layers/composite/ContentHost.h @@ -96,7 +96,6 @@ public: virtual void Composite(EffectChain& aEffectChain, float aOpacity, const gfx::Matrix4x4& aTransform, - const gfx::Point& aOffset, const gfx::Filter& aFilter, const gfx::Rect& aClipRect, const nsIntRegion* aVisibleRegion = nullptr, @@ -275,7 +274,6 @@ public: virtual void Composite(EffectChain& aEffectChain, float aOpacity, const gfx::Matrix4x4& aTransform, - const gfx::Point& aOffset, const gfx::Filter& aFilter, const gfx::Rect& aClipRect, const nsIntRegion* aVisibleRegion = nullptr, @@ -284,7 +282,7 @@ public: ProcessTextureUpdates(); ContentHostBase::Composite(aEffectChain, aOpacity, - aTransform, aOffset, aFilter, + aTransform, aFilter, aClipRect, aVisibleRegion, aLayerProperties); } diff --git a/gfx/layers/composite/ImageHost.cpp b/gfx/layers/composite/ImageHost.cpp index 583f1a628560..5285d9de930b 100644 --- a/gfx/layers/composite/ImageHost.cpp +++ b/gfx/layers/composite/ImageHost.cpp @@ -61,7 +61,6 @@ void ImageHost::Composite(EffectChain& aEffectChain, float aOpacity, const gfx::Matrix4x4& aTransform, - const gfx::Point& aOffset, const gfx::Filter& aFilter, const gfx::Rect& aClipRect, const nsIntRegion* aVisibleRegion, @@ -115,15 +114,15 @@ ImageHost::Composite(EffectChain& aEffectChain, effect->mTextureCoords = Rect(0, 0, 1, 1); } GetCompositor()->DrawQuad(rect, aClipRect, aEffectChain, - aOpacity, aTransform, aOffset); + aOpacity, aTransform); GetCompositor()->DrawDiagnostics(DIAGNOSTIC_IMAGE|DIAGNOSTIC_BIGIMAGE, - rect, aClipRect, aTransform, aOffset); + rect, aClipRect, aTransform); } while (it->NextTile()); it->EndTileIteration(); // layer border GetCompositor()->DrawDiagnostics(DIAGNOSTIC_IMAGE, gfxPictureRect, aClipRect, - aTransform, aOffset); + aTransform); } else { IntSize textureSize = source->GetSize(); gfx::Rect rect; @@ -144,10 +143,10 @@ ImageHost::Composite(EffectChain& aEffectChain, } GetCompositor()->DrawQuad(rect, aClipRect, aEffectChain, - aOpacity, aTransform, aOffset); + aOpacity, aTransform); GetCompositor()->DrawDiagnostics(DIAGNOSTIC_IMAGE, rect, aClipRect, - aTransform, aOffset); + aTransform); } mFrontBuffer->Unlock(); } @@ -265,7 +264,6 @@ void DeprecatedImageHostSingle::Composite(EffectChain& aEffectChain, float aOpacity, const gfx::Matrix4x4& aTransform, - const gfx::Point& aOffset, const gfx::Filter& aFilter, const gfx::Rect& aClipRect, const nsIntRegion* aVisibleRegion, @@ -303,9 +301,9 @@ DeprecatedImageHostSingle::Composite(EffectChain& aEffectChain, nsIntRect tileRect = it->GetTileRect(); gfx::Rect rect(tileRect.x, tileRect.y, tileRect.width, tileRect.height); GetCompositor()->DrawQuad(rect, aClipRect, aEffectChain, - aOpacity, aTransform, aOffset); + aOpacity, aTransform); GetCompositor()->DrawDiagnostics(DIAGNOSTIC_IMAGE|DIAGNOSTIC_BIGIMAGE, - rect, aClipRect, aTransform, aOffset); + rect, aClipRect, aTransform); } while (it->NextTile()); it->EndTileIteration(); } else { @@ -329,9 +327,9 @@ DeprecatedImageHostSingle::Composite(EffectChain& aEffectChain, } GetCompositor()->DrawQuad(rect, aClipRect, aEffectChain, - aOpacity, aTransform, aOffset); + aOpacity, aTransform); GetCompositor()->DrawDiagnostics(DIAGNOSTIC_IMAGE, - rect, aClipRect, aTransform, aOffset); + rect, aClipRect, aTransform); } mDeprecatedTextureHost->Unlock(); diff --git a/gfx/layers/composite/ImageHost.h b/gfx/layers/composite/ImageHost.h index 30e22d9fe81b..d2f8c3510a7a 100644 --- a/gfx/layers/composite/ImageHost.h +++ b/gfx/layers/composite/ImageHost.h @@ -49,7 +49,6 @@ public: virtual void Composite(EffectChain& aEffectChain, float aOpacity, const gfx::Matrix4x4& aTransform, - const gfx::Point& aOffset, const gfx::Filter& aFilter, const gfx::Rect& aClipRect, const nsIntRegion* aVisibleRegion = nullptr, @@ -110,7 +109,6 @@ public: virtual void Composite(EffectChain& aEffectChain, float aOpacity, const gfx::Matrix4x4& aTransform, - const gfx::Point& aOffset, const gfx::Filter& aFilter, const gfx::Rect& aClipRect, const nsIntRegion* aVisibleRegion = nullptr, diff --git a/gfx/layers/composite/ImageLayerComposite.cpp b/gfx/layers/composite/ImageLayerComposite.cpp index 31a35749ff7d..8623b1098838 100644 --- a/gfx/layers/composite/ImageLayerComposite.cpp +++ b/gfx/layers/composite/ImageLayerComposite.cpp @@ -78,8 +78,7 @@ ImageLayerComposite::GetLayer() } void -ImageLayerComposite::RenderLayer(const nsIntPoint& aOffset, - const nsIntRect& aClipRect) +ImageLayerComposite::RenderLayer(const nsIntRect& aClipRect) { if (!mImageHost || !mImageHost->IsAttached()) { return; @@ -104,7 +103,6 @@ ImageLayerComposite::RenderLayer(const nsIntPoint& aOffset, mImageHost->Composite(effectChain, GetEffectiveOpacity(), transform, - gfx::Point(aOffset.x, aOffset.y), gfx::ToFilter(mFilter), clipRect); } diff --git a/gfx/layers/composite/ImageLayerComposite.h b/gfx/layers/composite/ImageLayerComposite.h index 170487713521..e5645685030a 100644 --- a/gfx/layers/composite/ImageLayerComposite.h +++ b/gfx/layers/composite/ImageLayerComposite.h @@ -44,8 +44,7 @@ public: virtual Layer* GetLayer() MOZ_OVERRIDE; - virtual void RenderLayer(const nsIntPoint& aOffset, - const nsIntRect& aClipRect); + virtual void RenderLayer(const nsIntRect& aClipRect); virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) MOZ_OVERRIDE; diff --git a/gfx/layers/composite/LayerManagerComposite.cpp b/gfx/layers/composite/LayerManagerComposite.cpp index 9a5edadb4bb3..8bbe8390bbe8 100644 --- a/gfx/layers/composite/LayerManagerComposite.cpp +++ b/gfx/layers/composite/LayerManagerComposite.cpp @@ -303,8 +303,7 @@ LayerManagerComposite::RenderDebugOverlay(const Rect& aBounds) clip, effects, opacity, - gfx::Matrix4x4(), - gfx::Point()); + gfx::Matrix4x4()); } // We intentionally overflow at 2^16. sFrameCount++; @@ -359,7 +358,7 @@ LayerManagerComposite::Render() mCompositor->RestoreState(); // Render our layers. - RootLayer()->RenderLayer(nsIntPoint(0, 0), clipRect); + RootLayer()->RenderLayer(clipRect); // Allow widget to render a custom foreground. mCompositor->SaveState(); diff --git a/gfx/layers/composite/LayerManagerComposite.h b/gfx/layers/composite/LayerManagerComposite.h index 476a4a1afde0..4a4b481124d0 100644 --- a/gfx/layers/composite/LayerManagerComposite.h +++ b/gfx/layers/composite/LayerManagerComposite.h @@ -317,8 +317,7 @@ public: virtual Layer* GetLayer() = 0; - virtual void RenderLayer(const nsIntPoint& aOffset, - const nsIntRect& aClipRect) = 0; + virtual void RenderLayer(const nsIntRect& aClipRect) = 0; virtual void SetCompositableHost(CompositableHost* aHost) { diff --git a/gfx/layers/composite/TextureHost.h b/gfx/layers/composite/TextureHost.h index e3476f8e5dba..ce19bb8f0073 100644 --- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -799,11 +799,19 @@ private: class CompositingRenderTarget : public TextureSource { public: + CompositingRenderTarget(const gfx::IntPoint& aOrigin) + : mOrigin(aOrigin) + {} virtual ~CompositingRenderTarget() {} #ifdef MOZ_DUMP_PAINTING virtual already_AddRefed Dump(Compositor* aCompositor) { return nullptr; } #endif + + const gfx::IntPoint& GetOrigin() { return mOrigin; } + +private: + gfx::IntPoint mOrigin; }; /** diff --git a/gfx/layers/composite/ThebesLayerComposite.cpp b/gfx/layers/composite/ThebesLayerComposite.cpp index 761d2286885e..b417a60e849c 100644 --- a/gfx/layers/composite/ThebesLayerComposite.cpp +++ b/gfx/layers/composite/ThebesLayerComposite.cpp @@ -95,8 +95,7 @@ ThebesLayerComposite::GetRenderState() } void -ThebesLayerComposite::RenderLayer(const nsIntPoint& aOffset, - const nsIntRect& aClipRect) +ThebesLayerComposite::RenderLayer(const nsIntRect& aClipRect) { if (!mBuffer || !mBuffer->IsAttached()) { return; @@ -139,7 +138,6 @@ ThebesLayerComposite::RenderLayer(const nsIntPoint& aOffset, mBuffer->Composite(effectChain, GetEffectiveOpacity(), transform, - gfx::Point(aOffset.x, aOffset.y), gfx::FILTER_LINEAR, clipRect, &visibleRegion, diff --git a/gfx/layers/composite/ThebesLayerComposite.h b/gfx/layers/composite/ThebesLayerComposite.h index 2116e882a7f5..551c41b484f7 100644 --- a/gfx/layers/composite/ThebesLayerComposite.h +++ b/gfx/layers/composite/ThebesLayerComposite.h @@ -53,8 +53,7 @@ public: virtual TiledLayerComposer* GetTiledLayerComposer() MOZ_OVERRIDE; - virtual void RenderLayer(const nsIntPoint& aOffset, - const nsIntRect& aClipRect) MOZ_OVERRIDE; + virtual void RenderLayer(const nsIntRect& aClipRect) MOZ_OVERRIDE; virtual void CleanupResources() MOZ_OVERRIDE; diff --git a/gfx/layers/composite/TiledContentHost.cpp b/gfx/layers/composite/TiledContentHost.cpp index ad326ead8331..673db9cd7579 100644 --- a/gfx/layers/composite/TiledContentHost.cpp +++ b/gfx/layers/composite/TiledContentHost.cpp @@ -146,7 +146,6 @@ void TiledContentHost::Composite(EffectChain& aEffectChain, float aOpacity, const gfx::Matrix4x4& aTransform, - const gfx::Point& aOffset, const gfx::Filter& aFilter, const gfx::Rect& aClipRect, const nsIntRegion* aVisibleRegion /* = nullptr */, @@ -164,8 +163,8 @@ TiledContentHost::Composite(EffectChain& aEffectChain, RenderLayerBuffer(mLowPrecisionVideoMemoryTiledBuffer, mLowPrecisionVideoMemoryTiledBuffer.GetValidRegion(), aEffectChain, aOpacity, - aOffset, aFilter, aClipRect, aLayerProperties->mValidRegion, visibleRect, aTransform); - RenderLayerBuffer(mVideoMemoryTiledBuffer, aLayerProperties->mValidRegion, aEffectChain, aOpacity, aOffset, + aFilter, aClipRect, aLayerProperties->mValidRegion, visibleRect, aTransform); + RenderLayerBuffer(mVideoMemoryTiledBuffer, aLayerProperties->mValidRegion, aEffectChain, aOpacity, aFilter, aClipRect, nsIntRegion(), visibleRect, aTransform); } @@ -175,7 +174,6 @@ TiledContentHost::RenderTile(const TiledTexture& aTile, EffectChain& aEffectChain, float aOpacity, const gfx::Matrix4x4& aTransform, - const gfx::Point& aOffset, const gfx::Filter& aFilter, const gfx::Rect& aClipRect, const nsIntRegion& aScreenRegion, @@ -202,9 +200,9 @@ TiledContentHost::RenderTile(const TiledTexture& aTile, textureRect.y / aTextureBounds.height, textureRect.width / aTextureBounds.width, textureRect.height / aTextureBounds.height); - mCompositor->DrawQuad(graphicsRect, aClipRect, aEffectChain, aOpacity, aTransform, aOffset); + mCompositor->DrawQuad(graphicsRect, aClipRect, aEffectChain, aOpacity, aTransform); mCompositor->DrawDiagnostics(DIAGNOSTIC_CONTENT|DIAGNOSTIC_TILE, - graphicsRect, aClipRect, aTransform, aOffset); + graphicsRect, aClipRect, aTransform); } aTile.mDeprecatedTextureHost->Unlock(); @@ -215,7 +213,6 @@ TiledContentHost::RenderLayerBuffer(TiledLayerBufferComposite& aLayerBuffer, const nsIntRegion& aValidRegion, EffectChain& aEffectChain, float aOpacity, - const gfx::Point& aOffset, const gfx::Filter& aFilter, const gfx::Rect& aClipRect, const nsIntRegion& aMaskRegion, @@ -276,7 +273,7 @@ TiledContentHost::RenderLayerBuffer(TiledLayerBufferComposite& aLayerBuffer, nsIntPoint tileOffset((x - tileStartX) * resolution, (y - tileStartY) * resolution); uint32_t tileSize = aLayerBuffer.GetTileLength(); - RenderTile(tileTexture, aEffectChain, aOpacity, aTransform, aOffset, aFilter, aClipRect, tileDrawRegion, + RenderTile(tileTexture, aEffectChain, aOpacity, aTransform, aFilter, aClipRect, tileDrawRegion, tileOffset, nsIntSize(tileSize, tileSize)); } } @@ -289,7 +286,7 @@ TiledContentHost::RenderLayerBuffer(TiledLayerBufferComposite& aLayerBuffer, gfx::Rect rect(aVisibleRect.x, aVisibleRect.y, aVisibleRect.width, aVisibleRect.height); GetCompositor()->DrawDiagnostics(DIAGNOSTIC_CONTENT, - rect, aClipRect, aTransform, aOffset); + rect, aClipRect, aTransform); } void diff --git a/gfx/layers/composite/TiledContentHost.h b/gfx/layers/composite/TiledContentHost.h index 3c4a55096a11..b702552ec934 100644 --- a/gfx/layers/composite/TiledContentHost.h +++ b/gfx/layers/composite/TiledContentHost.h @@ -202,7 +202,6 @@ public: EffectChain& aEffectChain, float aOpacity, const gfx::Matrix4x4& aTransform, - const gfx::Point& aOffset, const gfx::Filter& aFilter, const gfx::Rect& aClipRect, const nsIntRegion& aScreenRegion, @@ -212,7 +211,6 @@ public: void Composite(EffectChain& aEffectChain, float aOpacity, const gfx::Matrix4x4& aTransform, - const gfx::Point& aOffset, const gfx::Filter& aFilter, const gfx::Rect& aClipRect, const nsIntRegion* aVisibleRegion = nullptr, @@ -260,7 +258,6 @@ private: const nsIntRegion& aValidRegion, EffectChain& aEffectChain, float aOpacity, - const gfx::Point& aOffset, const gfx::Filter& aFilter, const gfx::Rect& aClipRect, const nsIntRegion& aMaskRegion, diff --git a/gfx/layers/d3d11/CompositorD3D11.cpp b/gfx/layers/d3d11/CompositorD3D11.cpp index 0382fb3334cb..9ed4f8253832 100644 --- a/gfx/layers/d3d11/CompositorD3D11.cpp +++ b/gfx/layers/d3d11/CompositorD3D11.cpp @@ -380,7 +380,7 @@ CompositorD3D11::CreateRenderTarget(const gfx::IntRect& aRect, return nullptr; } - RefPtr rt = new CompositingRenderTargetD3D11(texture); + RefPtr rt = new CompositingRenderTargetD3D11(texture, aRect.TopLeft()); rt->SetSize(IntSize(aRect.width, aRect.height)); if (aInit == INIT_MODE_CLEAR) { @@ -393,7 +393,8 @@ CompositorD3D11::CreateRenderTarget(const gfx::IntRect& aRect, TemporaryRef CompositorD3D11::CreateRenderTargetFromSource(const gfx::IntRect &aRect, - const CompositingRenderTarget* aSource) + const CompositingRenderTarget* aSource, + const gfx::IntPoint &aSourcePoint) { CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aRect.width, aRect.height, 1, 1, @@ -411,11 +412,11 @@ CompositorD3D11::CreateRenderTargetFromSource(const gfx::IntRect &aRect, static_cast(aSource); D3D11_BOX srcBox; - srcBox.left = aRect.x; - srcBox.top = aRect.y; + srcBox.left = aSourcePoint.x; + srcBox.top = aSourcePoint.y; srcBox.front = 0; - srcBox.right = aRect.XMost(); - srcBox.bottom = aRect.YMost(); + srcBox.right = aSourcePoint.x + aRect.width; + srcBox.bottom = aSourcePoint.y + aRect.height; srcBox.back = 0; const IntSize& srcSize = sourceD3D11->GetSize(); @@ -431,8 +432,8 @@ CompositorD3D11::CreateRenderTargetFromSource(const gfx::IntRect &aRect, } RefPtr rt = - new CompositingRenderTargetD3D11(texture); - rt->SetSize(IntSize(aRect.width, aRect.height)); + new CompositingRenderTargetD3D11(texture, aRect.TopLeft()); + rt->SetSize(aRect.Size()); return rt; } @@ -480,13 +481,13 @@ CompositorD3D11::DrawQuad(const gfx::Rect& aRect, const gfx::Rect& aClipRect, const EffectChain& aEffectChain, gfx::Float aOpacity, - const gfx::Matrix4x4& aTransform, - const gfx::Point& aOffset) + const gfx::Matrix4x4& aTransform) { MOZ_ASSERT(mCurrentRT, "No render target"); memcpy(&mVSConstants.layerTransform, &aTransform._11, 64); - mVSConstants.renderTargetOffset[0] = aOffset.x; - mVSConstants.renderTargetOffset[1] = aOffset.y; + IntPoint origin = mCurrentRT->GetOrigin(); + mVSConstants.renderTargetOffset[0] = origin.x; + mVSConstants.renderTargetOffset[1] = origin.y; mVSConstants.layerQuad = aRect; mPSConstants.layerOpacity[0] = aOpacity; @@ -785,7 +786,7 @@ CompositorD3D11::UpdateRenderTarget() return; } - mDefaultRT = new CompositingRenderTargetD3D11(backBuf); + mDefaultRT = new CompositingRenderTargetD3D11(backBuf, IntPoint(0, 0)); mDefaultRT->SetSize(mSize); } diff --git a/gfx/layers/d3d11/CompositorD3D11.h b/gfx/layers/d3d11/CompositorD3D11.h index 41712b5de546..fe2b2d33fd65 100644 --- a/gfx/layers/d3d11/CompositorD3D11.h +++ b/gfx/layers/d3d11/CompositorD3D11.h @@ -67,7 +67,8 @@ public: virtual TemporaryRef CreateRenderTargetFromSource(const gfx::IntRect& aRect, - const CompositingRenderTarget* aSource) MOZ_OVERRIDE; + const CompositingRenderTarget* aSource, + const gfx::IntPoint& aSourcePoint) MOZ_OVERRIDE; virtual void SetRenderTarget(CompositingRenderTarget* aSurface) MOZ_OVERRIDE; virtual CompositingRenderTarget* GetCurrentRenderTarget() MOZ_OVERRIDE @@ -93,8 +94,7 @@ public: const gfx::Rect &aClipRect, const EffectChain &aEffectChain, gfx::Float aOpacity, - const gfx::Matrix4x4 &aTransform, - const gfx::Point &aOffset) MOZ_OVERRIDE; + const gfx::Matrix4x4 &aTransform) MOZ_OVERRIDE; /** * Start a new frame. If aClipRectIn is null, sets *aClipRectOut to the diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp index f59cb143684e..7f3d14226325 100644 --- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -39,7 +39,9 @@ CreateDeprecatedTextureHostD3D11(SurfaceDescriptorType aDescriptorType, } -CompositingRenderTargetD3D11::CompositingRenderTargetD3D11(ID3D11Texture2D* aTexture) +CompositingRenderTargetD3D11::CompositingRenderTargetD3D11(ID3D11Texture2D* aTexture, + const gfx::IntPoint& aOrigin) + : CompositingRenderTarget(aOrigin) { MOZ_ASSERT(aTexture); diff --git a/gfx/layers/d3d11/TextureD3D11.h b/gfx/layers/d3d11/TextureD3D11.h index 87ea3a01211b..717dde666f18 100644 --- a/gfx/layers/d3d11/TextureD3D11.h +++ b/gfx/layers/d3d11/TextureD3D11.h @@ -52,7 +52,8 @@ class CompositingRenderTargetD3D11 : public CompositingRenderTarget, public TextureSourceD3D11 { public: - CompositingRenderTargetD3D11(ID3D11Texture2D* aTexture); + CompositingRenderTargetD3D11(ID3D11Texture2D* aTexture, + const gfx::IntPoint& aOrigin); virtual TextureSourceD3D11* AsSourceD3D11() MOZ_OVERRIDE { return this; } diff --git a/gfx/layers/d3d9/CompositorD3D9.cpp b/gfx/layers/d3d9/CompositorD3D9.cpp index d81ee54a56d5..4bafe4844b8e 100644 --- a/gfx/layers/d3d9/CompositorD3D9.cpp +++ b/gfx/layers/d3d9/CompositorD3D9.cpp @@ -98,14 +98,15 @@ CompositorD3D9::CreateRenderTarget(const gfx::IntRect &aRect, } RefPtr rt = - new CompositingRenderTargetD3D9(texture, aInit, IntSize(aRect.width, aRect.height)); + new CompositingRenderTargetD3D9(texture, aInit, aRect); return rt; } TemporaryRef CompositorD3D9::CreateRenderTargetFromSource(const gfx::IntRect &aRect, - const CompositingRenderTarget *aSource) + const CompositingRenderTarget *aSource, + const gfx::IntPoint &aSourcePoint) { RefPtr texture; HRESULT hr = device()->CreateTexture(aRect.width, aRect.height, 1, @@ -130,10 +131,10 @@ CompositorD3D9::CreateRenderTargetFromSource(const gfx::IntRect &aRect, if (sourceSurface && destSurface) { RECT sourceRect; - sourceRect.left = aRect.x; - sourceRect.right = aRect.XMost(); - sourceRect.top = aRect.y; - sourceRect.bottom = aRect.YMost(); + sourceRect.left = aSourcePoint.x; + sourceRect.right = aSourcePoint.x + aRect.width; + sourceRect.top = aSourcePoint.y; + sourceRect.bottom = aSourcePoint.y + aRect.height; RECT destRect; destRect.left = 0; destRect.right = aRect.width; @@ -156,7 +157,7 @@ CompositorD3D9::CreateRenderTargetFromSource(const gfx::IntRect &aRect, RefPtr rt = new CompositingRenderTargetD3D9(texture, INIT_MODE_NONE, - IntSize(aRect.width, aRect.height)); + aRect); return rt; } @@ -190,15 +191,17 @@ ShaderModeForEffectType(EffectTypes aEffectType) } void -CompositorD3D9::DrawQuad(const gfx::Rect &aRect, const gfx::Rect &aClipRect, +CompositorD3D9::DrawQuad(const gfx::Rect &aRect, + const gfx::Rect &aClipRect, const EffectChain &aEffectChain, - gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform, - const gfx::Point &aOffset) + gfx::Float aOpacity, + const gfx::Matrix4x4 &aTransform) { MOZ_ASSERT(mCurrentRT, "No render target"); device()->SetVertexShaderConstantF(CBmLayerTransform, &aTransform._11, 4); - float renderTargetOffset[] = { aOffset.x, aOffset.y, 0, 0 }; + IntPoint origin = mCurrentRT->GetOrigin(); + float renderTargetOffset[] = { origin.x, origin.y, 0, 0 }; device()->SetVertexShaderConstantF(CBvRenderTargetOffset, renderTargetOffset, 1); @@ -475,7 +478,7 @@ CompositorD3D9::BeginFrame(const Rect *aClipRectIn, nsRefPtr backBuffer = mSwapChain->GetBackBuffer(); mDefaultRT = new CompositingRenderTargetD3D9(backBuffer, INIT_MODE_CLEAR, - IntSize(mSize.width, mSize.height)); + IntRect(0, 0, mSize.width, mSize.height)); SetRenderTarget(mDefaultRT); } diff --git a/gfx/layers/d3d9/CompositorD3D9.h b/gfx/layers/d3d9/CompositorD3D9.h index da33b10eb104..f486487c28c9 100644 --- a/gfx/layers/d3d9/CompositorD3D9.h +++ b/gfx/layers/d3d9/CompositorD3D9.h @@ -44,7 +44,8 @@ public: virtual TemporaryRef CreateRenderTargetFromSource(const gfx::IntRect &aRect, - const CompositingRenderTarget *aSource) MOZ_OVERRIDE; + const CompositingRenderTarget *aSource, + const gfx::IntPoint &aSourcePoint) MOZ_OVERRIDE; virtual void SetRenderTarget(CompositingRenderTarget *aSurface); virtual CompositingRenderTarget* GetCurrentRenderTarget() MOZ_OVERRIDE @@ -54,10 +55,11 @@ public: virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) MOZ_OVERRIDE {} - virtual void DrawQuad(const gfx::Rect &aRect, const gfx::Rect &aClipRect, + virtual void DrawQuad(const gfx::Rect &aRect, + const gfx::Rect &aClipRect, const EffectChain &aEffectChain, - gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform, - const gfx::Point &aOffset) MOZ_OVERRIDE; + gfx::Float aOpacity, + const gfx::Matrix4x4 &aTransform) MOZ_OVERRIDE; virtual void BeginFrame(const gfx::Rect *aClipRectIn, const gfxMatrix& aTransform, diff --git a/gfx/layers/d3d9/TextureD3D9.cpp b/gfx/layers/d3d9/TextureD3D9.cpp index d47391c68d6d..e3c97f9894e6 100644 --- a/gfx/layers/d3d9/TextureD3D9.cpp +++ b/gfx/layers/d3d9/TextureD3D9.cpp @@ -41,8 +41,9 @@ CreateDeprecatedTextureHostD3D9(SurfaceDescriptorType aDescriptorType, CompositingRenderTargetD3D9::CompositingRenderTargetD3D9(IDirect3DTexture9* aTexture, SurfaceInitMode aInit, - const gfx::IntSize& aSize) - : mInitMode(aInit) + const gfx::IntRect& aRect) + : CompositingRenderTarget(aRect.TopLeft()) + , mInitMode(aInit) , mInitialized(false) { MOZ_COUNT_CTOR(CompositingRenderTargetD3D9); @@ -51,19 +52,20 @@ CompositingRenderTargetD3D9::CompositingRenderTargetD3D9(IDirect3DTexture9* aTex mTextures[0] = aTexture; HRESULT hr = mTextures[0]->GetSurfaceLevel(0, getter_AddRefs(mSurface)); NS_ASSERTION(mSurface, "Couldn't create surface for texture"); - TextureSourceD3D9::SetSize(aSize); + TextureSourceD3D9::SetSize(aRect.Size()); } CompositingRenderTargetD3D9::CompositingRenderTargetD3D9(IDirect3DSurface9* aSurface, SurfaceInitMode aInit, - const gfx::IntSize& aSize) - : mSurface(aSurface) + const gfx::IntRect& aRect) + : CompositingRenderTarget(aRect.TopLeft()) + , mSurface(aSurface) , mInitMode(aInit) , mInitialized(false) { MOZ_COUNT_CTOR(CompositingRenderTargetD3D9); MOZ_ASSERT(mSurface); - TextureSourceD3D9::SetSize(aSize); + TextureSourceD3D9::SetSize(aRect.Size()); } CompositingRenderTargetD3D9::~CompositingRenderTargetD3D9() diff --git a/gfx/layers/d3d9/TextureD3D9.h b/gfx/layers/d3d9/TextureD3D9.h index 2527f4e8111f..3cacc7b8cc7c 100644 --- a/gfx/layers/d3d9/TextureD3D9.h +++ b/gfx/layers/d3d9/TextureD3D9.h @@ -56,11 +56,11 @@ class CompositingRenderTargetD3D9 : public CompositingRenderTarget, public: CompositingRenderTargetD3D9(IDirect3DTexture9* aTexture, SurfaceInitMode aInit, - const gfx::IntSize& aSize); + const gfx::IntRect& aRect); // use for rendering to the main window, cannot be rendered as a texture CompositingRenderTargetD3D9(IDirect3DSurface9* aSurface, SurfaceInitMode aInit, - const gfx::IntSize& aSize); + const gfx::IntRect& aRect); ~CompositingRenderTargetD3D9(); virtual TextureSourceD3D9* AsSourceD3D9() MOZ_OVERRIDE diff --git a/gfx/layers/opengl/CompositingRenderTargetOGL.h b/gfx/layers/opengl/CompositingRenderTargetOGL.h index 8b83a86d5edf..d1b501806c17 100644 --- a/gfx/layers/opengl/CompositingRenderTargetOGL.h +++ b/gfx/layers/opengl/CompositingRenderTargetOGL.h @@ -62,8 +62,10 @@ class CompositingRenderTargetOGL : public CompositingRenderTarget }; public: - CompositingRenderTargetOGL(CompositorOGL* aCompositor, GLuint aTexure, GLuint aFBO) - : mInitParams() + CompositingRenderTargetOGL(CompositorOGL* aCompositor, const gfx::IntPoint& aOrigin, + GLuint aTexure, GLuint aFBO) + : CompositingRenderTarget(aOrigin) + , mInitParams() , mTransform() , mCompositor(aCompositor) , mGL(aCompositor->gl()) @@ -83,7 +85,7 @@ public: const gfxMatrix& aTransform) { RefPtr result - = new CompositingRenderTargetOGL(aCompositor, 0, 0); + = new CompositingRenderTargetOGL(aCompositor, gfx::IntPoint(0, 0), 0, 0); result->mTransform = aTransform; result->mInitParams = InitParams(aSize, 0, INIT_MODE_NONE); result->mInitParams.mStatus = InitParams::INITIALIZED; diff --git a/gfx/layers/opengl/CompositorOGL.cpp b/gfx/layers/opengl/CompositorOGL.cpp index 55f3f1306ae5..b66d9e761b0f 100644 --- a/gfx/layers/opengl/CompositorOGL.cpp +++ b/gfx/layers/opengl/CompositorOGL.cpp @@ -659,34 +659,36 @@ CompositorOGL::CreateRenderTarget(const IntRect &aRect, SurfaceInitMode aInit) { GLuint tex = 0; GLuint fbo = 0; - CreateFBOWithTexture(aRect, aInit, 0, &fbo, &tex); + CreateFBOWithTexture(aRect, false, 0, &fbo, &tex); RefPtr surface - = new CompositingRenderTargetOGL(this, tex, fbo); - surface->Initialize(IntSize(aRect.width, aRect.height), mFBOTextureTarget, aInit); + = new CompositingRenderTargetOGL(this, aRect.TopLeft(), tex, fbo); + surface->Initialize(aRect.Size(), mFBOTextureTarget, aInit); return surface.forget(); } TemporaryRef CompositorOGL::CreateRenderTargetFromSource(const IntRect &aRect, - const CompositingRenderTarget *aSource) + const CompositingRenderTarget *aSource, + const IntPoint &aSourcePoint) { GLuint tex = 0; GLuint fbo = 0; const CompositingRenderTargetOGL* sourceSurface = static_cast(aSource); + IntRect sourceRect(aSourcePoint, aRect.Size()); if (aSource) { - CreateFBOWithTexture(aRect, INIT_MODE_COPY, sourceSurface->GetFBO(), + CreateFBOWithTexture(sourceRect, true, sourceSurface->GetFBO(), &fbo, &tex); } else { - CreateFBOWithTexture(aRect, INIT_MODE_COPY, 0, + CreateFBOWithTexture(sourceRect, true, 0, &fbo, &tex); } RefPtr surface - = new CompositingRenderTargetOGL(this, tex, fbo); - surface->Initialize(IntSize(aRect.width, aRect.height), + = new CompositingRenderTargetOGL(this, aRect.TopLeft(), tex, fbo); + surface->Initialize(aRect.Size(), mFBOTextureTarget, - INIT_MODE_COPY); + INIT_MODE_NONE); return surface.forget(); } @@ -841,7 +843,7 @@ CompositorOGL::BeginFrame(const Rect *aClipRectIn, const gfxMatrix& aTransform, } void -CompositorOGL::CreateFBOWithTexture(const IntRect& aRect, SurfaceInitMode aInit, +CompositorOGL::CreateFBOWithTexture(const IntRect& aRect, bool aCopyFromSource, GLuint aSourceFrameBuffer, GLuint *aFBO, GLuint *aTexture) { @@ -851,7 +853,7 @@ CompositorOGL::CreateFBOWithTexture(const IntRect& aRect, SurfaceInitMode aInit, mGLContext->fGenTextures(1, &tex); mGLContext->fBindTexture(mFBOTextureTarget, tex); - if (aInit == INIT_MODE_COPY) { + if (aCopyFromSource) { GLuint curFBO = mCurrentRenderTarget->GetFBO(); if (curFBO != aSourceFrameBuffer) { mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aSourceFrameBuffer); @@ -981,10 +983,11 @@ private: }; void -CompositorOGL::DrawQuad(const Rect& aRect, const Rect& aClipRect, +CompositorOGL::DrawQuad(const Rect& aRect, + const Rect& aClipRect, const EffectChain &aEffectChain, - Float aOpacity, const gfx::Matrix4x4 &aTransform, - const Point& aOffset) + Float aOpacity, + const gfx::Matrix4x4 &aTransform) { PROFILER_LABEL("CompositorOGL", "DrawQuad"); MOZ_ASSERT(mFrameInProgress, "frame not started"); @@ -1046,7 +1049,8 @@ CompositorOGL::DrawQuad(const Rect& aRect, const Rect& aClipRect, } program->SetLayerQuadRect(aRect); program->SetLayerTransform(aTransform); - program->SetRenderOffset(aOffset.x, aOffset.y); + IntPoint offset = mCurrentRenderTarget->GetOrigin(); + program->SetRenderOffset(offset.x, offset.y); switch (aEffectChain.mPrimaryEffect->mType) { case EFFECT_SOLID_COLOR: { @@ -1227,7 +1231,7 @@ CompositorOGL::DrawQuad(const Rect& aRect, const Rect& aClipRect, program->SetLayerOpacity(aOpacity); program->SetLayerTransform(aTransform); program->SetTextureTransform(gfx3DMatrix()); - program->SetRenderOffset(aOffset.x, aOffset.y); + program->SetRenderOffset(offset.x, offset.y); program->SetLayerQuadRect(aRect); AutoBindTexture bindMask; if (maskType != MaskNone) { diff --git a/gfx/layers/opengl/CompositorOGL.h b/gfx/layers/opengl/CompositorOGL.h index c5c98a17ba38..3424edaa3c09 100644 --- a/gfx/layers/opengl/CompositorOGL.h +++ b/gfx/layers/opengl/CompositorOGL.h @@ -88,15 +88,17 @@ public: virtual TemporaryRef CreateRenderTargetFromSource(const gfx::IntRect &aRect, - const CompositingRenderTarget *aSource) MOZ_OVERRIDE; + const CompositingRenderTarget *aSource, + const gfx::IntPoint &aSourcePoint) MOZ_OVERRIDE; virtual void SetRenderTarget(CompositingRenderTarget *aSurface) MOZ_OVERRIDE; virtual CompositingRenderTarget* GetCurrentRenderTarget() MOZ_OVERRIDE; - virtual void DrawQuad(const gfx::Rect& aRect, const gfx::Rect& aClipRect, + virtual void DrawQuad(const gfx::Rect& aRect, + const gfx::Rect& aClipRect, const EffectChain &aEffectChain, - gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform, - const gfx::Point& aOffset) MOZ_OVERRIDE; + gfx::Float aOpacity, + const gfx::Matrix4x4 &aTransform) MOZ_OVERRIDE; virtual void EndFrame() MOZ_OVERRIDE; virtual void EndFrameForExternalComposition(const gfxMatrix& aTransform) MOZ_OVERRIDE; @@ -274,7 +276,7 @@ private: * shaders are required to sample from the different * texture types. */ - void CreateFBOWithTexture(const gfx::IntRect& aRect, SurfaceInitMode aInit, + void CreateFBOWithTexture(const gfx::IntRect& aRect, bool aCopyFromSource, GLuint aSourceFrameBuffer, GLuint *aFBO, GLuint *aTexture); diff --git a/gfx/thebes/gfxContext.cpp b/gfx/thebes/gfxContext.cpp index 25f0b2eebd39..8cb8a43be066 100644 --- a/gfx/thebes/gfxContext.cpp +++ b/gfx/thebes/gfxContext.cpp @@ -2153,7 +2153,7 @@ gfxContext::ChangeTransform(const Matrix &aNewMatrix, bool aUpdatePatternTransfo if (aUpdatePatternTransform && (state.pattern || state.sourceSurface) && !state.patternTransformChanged) { - state.patternTransform = mTransform; + state.patternTransform = GetDTTransform(); state.patternTransformChanged = true; } diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index 1957a7fed388..a9c3569736ed 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -938,7 +938,7 @@ gfxPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget) } IntSize size = data->GetSize(); - gfxImageFormat format = OptimalFormatForContent(ContentForFormat(data->GetFormat())); + gfxImageFormat format = SurfaceFormatToImageFormat(data->GetFormat()); nsRefPtr surf = diff --git a/js/src/build/autoconf/android.m4 b/js/src/build/autoconf/android.m4 index 878594ea9dc0..05271a5be79e 100644 --- a/js/src/build/autoconf/android.m4 +++ b/js/src/build/autoconf/android.m4 @@ -147,9 +147,15 @@ case "$target" in dnl set up compilers TOOLCHAIN_PREFIX="$android_toolchain/bin/$android_tool_prefix-" AS="$android_toolchain"/bin/"$android_tool_prefix"-as - CC="$android_toolchain"/bin/"$android_tool_prefix"-gcc - CXX="$android_toolchain"/bin/"$android_tool_prefix"-g++ - CPP="$android_toolchain"/bin/"$android_tool_prefix"-cpp + if test -z "$CC"; then + CC="$android_toolchain"/bin/"$android_tool_prefix"-gcc + fi + if test -z "$CXX"; then + CXX="$android_toolchain"/bin/"$android_tool_prefix"-g++ + fi + if test -z "$CPP"; then + CPP="$android_toolchain"/bin/"$android_tool_prefix"-cpp + fi LD="$android_toolchain"/bin/"$android_tool_prefix"-ld AR="$android_toolchain"/bin/"$android_tool_prefix"-ar RANLIB="$android_toolchain"/bin/"$android_tool_prefix"-ranlib diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index 538904ba2b9b..1f2b5c52d6ed 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -7439,6 +7439,18 @@ GetTemplateObjectForNative(JSContext *cx, HandleScript script, jsbytecode *pc, return true; } + if (native == intrinsic_NewDenseArray) { + res.set(NewDenseUnallocatedArray(cx, 0, nullptr, TenuredObject)); + if (!res) + return false; + + types::TypeObject *type = types::TypeScript::InitObject(cx, script, pc, JSProto_Array); + if (!type) + return false; + res->setType(type); + return true; + } + if (native == js::array_concat) { if (args.thisv().isObject() && args.thisv().toObject().is() && !args.thisv().toObject().hasSingletonType()) @@ -7451,6 +7463,18 @@ GetTemplateObjectForNative(JSContext *cx, HandleScript script, jsbytecode *pc, } } + if (native == js::str_split && args.length() == 1 && args[0].isString()) { + res.set(NewDenseUnallocatedArray(cx, 0, nullptr, TenuredObject)); + if (!res) + return false; + + types::TypeObject *type = types::TypeScript::InitObject(cx, script, pc, JSProto_Array); + if (!type) + return false; + res->setType(type); + return true; + } + if (native == js_String) { RootedString emptyString(cx, cx->runtime()->emptyString); res.set(StringObject::create(cx, emptyString, TenuredObject)); diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index 0f73097be014..ed6c505a4df6 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -4625,6 +4625,19 @@ CodeGenerator::visitFromCharCode(LFromCharCode *lir) return true; } +typedef JSObject *(*StringSplitFn)(JSContext *, HandleTypeObject, HandleString, HandleString); +static const VMFunction StringSplitInfo = FunctionInfo(js::str_split_string); + +bool +CodeGenerator::visitStringSplit(LStringSplit *lir) +{ + pushArg(ToRegister(lir->separator())); + pushArg(ToRegister(lir->string())); + pushArg(ImmGCPtr(lir->mir()->typeObject())); + + return callVM(StringSplitInfo, lir); +} + bool CodeGenerator::visitInitializedLength(LInitializedLength *lir) { diff --git a/js/src/jit/CodeGenerator.h b/js/src/jit/CodeGenerator.h index 95437d321901..f42f56825362 100644 --- a/js/src/jit/CodeGenerator.h +++ b/js/src/jit/CodeGenerator.h @@ -201,6 +201,7 @@ class CodeGenerator : public CodeGeneratorSpecific bool visitConcatPar(LConcatPar *lir); bool visitCharCodeAt(LCharCodeAt *lir); bool visitFromCharCode(LFromCharCode *lir); + bool visitStringSplit(LStringSplit *lir); bool visitFunctionEnvironment(LFunctionEnvironment *lir); bool visitForkJoinSlice(LForkJoinSlice *lir); bool visitGuardThreadLocalObject(LGuardThreadLocalObject *lir); diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index 7e335f7bd425..eb807a97856e 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -5952,8 +5952,8 @@ ClassHasResolveHook(JSCompartment *comp, const Class *clasp, PropertyName *name) return true; } -bool -IonBuilder::testSingletonProperty(JSObject *obj, JSObject *singleton, PropertyName *name) +JSObject * +IonBuilder::testSingletonProperty(JSObject *obj, PropertyName *name) { // We would like to completely no-op property/global accesses which can // produce only a particular JSObject. When indicating the access result is @@ -5971,26 +5971,26 @@ IonBuilder::testSingletonProperty(JSObject *obj, JSObject *singleton, PropertyNa while (obj) { if (!ClassHasEffectlessLookup(obj->getClass())) - return false; + return nullptr; types::TypeObjectKey *objType = types::TypeObjectKey::get(obj); if (objType->unknownProperties()) - return false; + return nullptr; types::HeapTypeSetKey property = objType->property(NameToId(name), context()); if (property.isOwnProperty(constraints())) { if (obj->hasSingletonType()) - return property.singleton(constraints()) == singleton; - return false; + return property.singleton(constraints()); + return nullptr; } if (ClassHasResolveHook(compartment, obj->getClass(), name)) - return false; + return nullptr; obj = obj->getProto(); } - return false; + return nullptr; } bool @@ -6014,7 +6014,7 @@ IonBuilder::testSingletonPropertyTypes(MDefinition *obj, JSObject *singleton, Pr JSObject *objectSingleton = types ? types->getSingleton() : nullptr; if (objectSingleton) - return testSingletonProperty(objectSingleton, singleton, name); + return testSingletonProperty(objectSingleton, name) == singleton; JSProtoKey key; switch (obj->type()) { @@ -6058,7 +6058,7 @@ IonBuilder::testSingletonPropertyTypes(MDefinition *obj, JSObject *singleton, Pr if (JSObject *proto = object->proto().toObjectOrNull()) { // Test this type. - if (!testSingletonProperty(proto, singleton, name)) + if (testSingletonProperty(proto, name) != singleton) return false; } else { // Can't be on the prototype chain with no prototypes... @@ -6070,12 +6070,12 @@ IonBuilder::testSingletonPropertyTypes(MDefinition *obj, JSObject *singleton, Pr return true; } default: - return true; + return false; } JSObject *proto = GetClassPrototypePure(&script()->global(), key); if (proto) - return testSingletonProperty(proto, singleton, name); + return testSingletonProperty(proto, name) == singleton; return false; } @@ -6213,7 +6213,7 @@ IonBuilder::getStaticName(JSObject *staticObject, PropertyName *name, bool *psuc if (!barrier) { if (singleton) { // Try to inline a known constant value. - if (testSingletonProperty(staticObject, singleton, name)) + if (testSingletonProperty(staticObject, name) == singleton) return pushConstant(ObjectValue(*singleton)); } if (knownType == JSVAL_TYPE_UNDEFINED) @@ -7724,25 +7724,7 @@ IonBuilder::annotateGetPropertyCache(MDefinition *obj, MGetPropertyCache *getPro if (ownTypes.isOwnProperty(constraints())) continue; - JSObject *singleton = nullptr; - JSObject *proto = typeObj->proto().toObject(); - while (true) { - types::TypeObjectKey *protoType = types::TypeObjectKey::get(proto); - if (!protoType->unknownProperties()) { - types::HeapTypeSetKey property = protoType->property(NameToId(name)); - - singleton = property.singleton(constraints()); - if (singleton) { - if (singleton->is()) - break; - singleton = nullptr; - } - } - TaggedProto taggedProto = proto->getTaggedProto(); - if (!taggedProto.isObject()) - break; - proto = taggedProto.toObject(); - } + JSObject *singleton = testSingletonProperty(typeObj->proto().toObject(), name); if (!singleton) continue; diff --git a/js/src/jit/IonBuilder.h b/js/src/jit/IonBuilder.h index a774b2f6ee99..a3841ffaacaf 100644 --- a/js/src/jit/IonBuilder.h +++ b/js/src/jit/IonBuilder.h @@ -559,6 +559,7 @@ class IonBuilder : public MIRGenerator // String natives. InliningStatus inlineStringObject(CallInfo &callInfo); + InliningStatus inlineStringSplit(CallInfo &callInfo); InliningStatus inlineStrCharCodeAt(CallInfo &callInfo); InliningStatus inlineStrFromCharCode(CallInfo &callInfo); InliningStatus inlineStrCharAt(CallInfo &callInfo); @@ -642,7 +643,7 @@ class IonBuilder : public MIRGenerator MGetPropertyCache *getInlineableGetPropertyCache(CallInfo &callInfo); - bool testSingletonProperty(JSObject *obj, JSObject *singleton, PropertyName *name); + JSObject *testSingletonProperty(JSObject *obj, PropertyName *name); bool testSingletonPropertyTypes(MDefinition *obj, JSObject *singleton, PropertyName *name, bool *testObject, bool *testString); bool getDefiniteSlot(types::TemporaryTypeSet *types, PropertyName *name, diff --git a/js/src/jit/LIR-Common.h b/js/src/jit/LIR-Common.h index 7a54ba633e0d..44c2b717f3b2 100644 --- a/js/src/jit/LIR-Common.h +++ b/js/src/jit/LIR-Common.h @@ -2720,6 +2720,26 @@ class LFromCharCode : public LInstructionHelper<1, 1, 0> } }; +class LStringSplit : public LCallInstructionHelper<1, 2, 0> +{ + public: + LIR_HEADER(StringSplit) + + LStringSplit(const LAllocation &string, const LAllocation &separator) { + setOperand(0, string); + setOperand(1, separator); + } + const LAllocation *string() { + return getOperand(0); + } + const LAllocation *separator() { + return getOperand(1); + } + const MStringSplit *mir() const { + return mir_->toStringSplit(); + } +}; + // Convert a 32-bit integer to a double. class LInt32ToDouble : public LInstructionHelper<1, 1, 0> { diff --git a/js/src/jit/LOpcodes.h b/js/src/jit/LOpcodes.h index a5f481f9a76a..d3f8fa8809bb 100644 --- a/js/src/jit/LOpcodes.h +++ b/js/src/jit/LOpcodes.h @@ -126,6 +126,7 @@ _(ConcatPar) \ _(CharCodeAt) \ _(FromCharCode) \ + _(StringSplit) \ _(Int32ToDouble) \ _(Float32ToDouble) \ _(DoubleToFloat32) \ diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp index 2ffb2c85938b..7d2f1190acff 100644 --- a/js/src/jit/Lowering.cpp +++ b/js/src/jit/Lowering.cpp @@ -2524,6 +2524,18 @@ LIRGenerator::visitArrayConcat(MArrayConcat *ins) return defineReturn(lir, ins) && assignSafepoint(lir, ins); } +bool +LIRGenerator::visitStringSplit(MStringSplit *ins) +{ + JS_ASSERT(ins->type() == MIRType_Object); + JS_ASSERT(ins->string()->type() == MIRType_String); + JS_ASSERT(ins->separator()->type() == MIRType_String); + + LStringSplit *lir = new LStringSplit(useRegisterAtStart(ins->string()), + useRegisterAtStart(ins->separator())); + return defineReturn(lir, ins) && assignSafepoint(lir, ins); +} + bool LIRGenerator::visitLoadTypedArrayElement(MLoadTypedArrayElement *ins) { diff --git a/js/src/jit/Lowering.h b/js/src/jit/Lowering.h index 1f41413aa2a4..fdd2e453bc8f 100644 --- a/js/src/jit/Lowering.h +++ b/js/src/jit/Lowering.h @@ -148,6 +148,7 @@ class LIRGenerator : public LIRGeneratorSpecific bool visitConcatPar(MConcatPar *ins); bool visitCharCodeAt(MCharCodeAt *ins); bool visitFromCharCode(MFromCharCode *ins); + bool visitStringSplit(MStringSplit *ins); bool visitStart(MStart *start); bool visitOsrEntry(MOsrEntry *entry); bool visitNop(MNop *nop); diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp index e03054c87566..643e8041dda2 100644 --- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -105,6 +105,8 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSNative native) // String natives. if (native == js_String) return inlineStringObject(callInfo); + if (native == js::str_split) + return inlineStringSplit(callInfo); if (native == js_str_charCodeAt) return inlineStrCharCodeAt(callInfo); if (native == js::str_fromCharCode) @@ -910,6 +912,43 @@ IonBuilder::inlineStringObject(CallInfo &callInfo) return InliningStatus_Inlined; } +IonBuilder::InliningStatus +IonBuilder::inlineStringSplit(CallInfo &callInfo) +{ + if (callInfo.argc() != 1 || callInfo.constructing()) + return InliningStatus_NotInlined; + if (callInfo.thisArg()->type() != MIRType_String) + return InliningStatus_NotInlined; + if (callInfo.getArg(0)->type() != MIRType_String) + return InliningStatus_NotInlined; + + JSObject *templateObject = inspector->getTemplateObjectForNative(pc, js::str_split); + if (!templateObject) + return InliningStatus_NotInlined; + JS_ASSERT(templateObject->is()); + + types::TypeObjectKey *retType = types::TypeObjectKey::get(templateObject); + if (retType->unknownProperties()) + return InliningStatus_NotInlined; + + types::HeapTypeSetKey key = retType->property(JSID_VOID); + if (!key.maybeTypes()) + return InliningStatus_NotInlined; + + if (!key.maybeTypes()->hasType(types::Type::StringType())) { + key.freeze(constraints()); + return InliningStatus_NotInlined; + } + + callInfo.unwrapArgs(); + + MStringSplit *ins = MStringSplit::New(callInfo.thisArg(), callInfo.getArg(0), templateObject); + current->add(ins); + current->push(ins); + + return InliningStatus_Inlined; +} + IonBuilder::InliningStatus IonBuilder::inlineStrCharCodeAt(CallInfo &callInfo) { @@ -1362,10 +1401,9 @@ IonBuilder::inlineNewDenseArrayForParallelExecution(CallInfo &callInfo) return InliningStatus_NotInlined; types::TypeObject *typeObject = returnTypes->getTypeObject(0); - JSObject *templateObject = NewDenseAllocatedArray(cx, 0, nullptr, TenuredObject); - if (!templateObject) - return InliningStatus_Error; - templateObject->setType(typeObject); + JSObject *templateObject = inspector->getTemplateObjectForNative(pc, intrinsic_NewDenseArray); + if (!templateObject || templateObject->type() != typeObject) + return InliningStatus_NotInlined; callInfo.unwrapArgs(); diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index e1c466748565..49dfd59b0dca 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -4152,6 +4152,48 @@ class MFromCharCode } }; +class MStringSplit + : public MBinaryInstruction, + public MixPolicy, StringPolicy<1> > +{ + types::TypeObject *typeObject_; + + MStringSplit(MDefinition *string, MDefinition *sep, JSObject *templateObject) + : MBinaryInstruction(string, sep), + typeObject_(templateObject->type()) + { + setResultType(MIRType_Object); + setResultTypeSet(MakeSingletonTypeSet(templateObject)); + } + + public: + INSTRUCTION_HEADER(StringSplit) + + static MStringSplit *New(MDefinition *string, MDefinition *sep, JSObject *templateObject) { + return new MStringSplit(string, sep, templateObject); + } + types::TypeObject *typeObject() const { + return typeObject_; + } + MDefinition *string() const { + return getOperand(0); + } + MDefinition *separator() const { + return getOperand(1); + } + TypePolicy *typePolicy() { + return this; + } + bool possiblyCalls() const { + return true; + } + virtual AliasSet getAliasSet() const { + // Although this instruction returns a new array, we don't have to mark + // it as store instruction, see also MNewArray. + return AliasSet::None(); + } +}; + // Returns an object to use as |this| value. See also ComputeThis and // BoxNonStrictThis in Interpreter.h. class MComputeThis diff --git a/js/src/jit/MOpcodes.h b/js/src/jit/MOpcodes.h index 3a04c4e3b919..7b993dfd7a7a 100644 --- a/js/src/jit/MOpcodes.h +++ b/js/src/jit/MOpcodes.h @@ -72,6 +72,7 @@ namespace jit { _(ConcatPar) \ _(CharCodeAt) \ _(FromCharCode) \ + _(StringSplit) \ _(Return) \ _(Throw) \ _(Box) \ diff --git a/js/src/jit/ParallelSafetyAnalysis.cpp b/js/src/jit/ParallelSafetyAnalysis.cpp index e1e6dd33d578..6152facbec3c 100644 --- a/js/src/jit/ParallelSafetyAnalysis.cpp +++ b/js/src/jit/ParallelSafetyAnalysis.cpp @@ -163,6 +163,7 @@ class ParallelSafetyVisitor : public MInstructionVisitor SAFE_OP(ConcatPar) UNSAFE_OP(CharCodeAt) UNSAFE_OP(FromCharCode) + UNSAFE_OP(StringSplit) SAFE_OP(Return) CUSTOM_OP(Throw) SAFE_OP(Box) // Boxing just creates a JSVal, doesn't alloc. diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index ee06fad26e84..912d76b839d8 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -3005,7 +3005,7 @@ class SplitMatchResult { } /* anonymous namespace */ template -static JSObject * +static ArrayObject * SplitHelper(JSContext *cx, Handle str, uint32_t limit, const Matcher &splitMatch, Handle type) { @@ -3289,6 +3289,28 @@ js::str_split(JSContext *cx, unsigned argc, Value *vp) return true; } +JSObject * +js::str_split_string(JSContext *cx, HandleTypeObject type, HandleString str, HandleString sep) +{ + Rooted linearStr(cx, str->ensureLinear(cx)); + if (!linearStr) + return nullptr; + + Rooted linearSep(cx, sep->ensureLinear(cx)); + if (!linearSep) + return nullptr; + + uint32_t limit = UINT32_MAX; + + SplitStringMatcher matcher(cx, linearSep); + ArrayObject *aobj = SplitHelper(cx, linearStr, limit, matcher, type); + if (!aobj) + return nullptr; + + aobj->setType(type); + return aobj; +} + static bool str_substr(JSContext *cx, unsigned argc, Value *vp) { diff --git a/js/src/jsstr.h b/js/src/jsstr.h index f7ebed4caddf..504b7bd67a56 100644 --- a/js/src/jsstr.h +++ b/js/src/jsstr.h @@ -13,6 +13,7 @@ #include "jsutil.h" #include "NamespaceImports.h" +#include "gc/Rooting.h" #include "js/RootingAPI.h" #include "vm/Unicode.h" @@ -355,6 +356,9 @@ str_search(JSContext *cx, unsigned argc, Value *vp); bool str_split(JSContext *cx, unsigned argc, Value *vp); +JSObject * +str_split_string(JSContext *cx, HandleTypeObject type, HandleString str, HandleString sep); + bool str_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, MutableHandleObject objp); diff --git a/security/nss/TAG-INFO b/security/nss/TAG-INFO index 71a61966051c..ac5b19f2e5a5 100644 --- a/security/nss/TAG-INFO +++ b/security/nss/TAG-INFO @@ -1 +1 @@ -NSS_3_15_3_BETA2 +NSS_3_15_4_BETA1 diff --git a/security/nss/cmd/certutil/certutil.c b/security/nss/cmd/certutil/certutil.c index 6603e80e1068..c81569330b19 100644 --- a/security/nss/cmd/certutil/certutil.c +++ b/security/nss/cmd/certutil/certutil.c @@ -945,7 +945,7 @@ PrintSyntax(char *progName) { #define FPS fprintf(stderr, FPS "Type %s -H for more detailed descriptions\n", progName); - FPS "Usage: %s -N [-d certdir] [-P dbprefix] [-f pwfile]\n", progName); + FPS "Usage: %s -N [-d certdir] [-P dbprefix] [-f pwfile] [--empty-password]\n", progName); FPS "Usage: %s -T [-d certdir] [-P dbprefix] [-h token-name]\n" "\t\t [-f pwfile] [-0 SSO-password]\n", progName); FPS "\t%s -A -n cert-name -t trustargs [-d certdir] [-P dbprefix] [-a] [-i input]\n", @@ -1361,6 +1361,8 @@ static void luN(enum usage_level ul, const char *command) " -d certdir"); FPS "%-20s Cert & Key database prefix\n", " -P dbprefix"); + FPS "%-20s use empty password when creating a new database\n", + " --empty-password"); FPS "\n"); } @@ -2191,6 +2193,7 @@ enum certutilOpts { opt_KeyOpFlagsOn, opt_KeyOpFlagsOff, opt_KeyAttrFlags, + opt_EmptyPassword, opt_Help }; @@ -2298,6 +2301,8 @@ secuCommandFlag options_init[] = "keyOpFlagsOff"}, { /* opt_KeyAttrFlags */ 0, PR_TRUE, 0, PR_FALSE, "keyAttrFlags"}, + { /* opt_EmptyPassword */ 0, PR_FALSE, 0, PR_FALSE, + "empty-password"}, }; #define NUM_OPTIONS ((sizeof options_init) / (sizeof options_init[0])) @@ -2809,7 +2814,10 @@ certutil_main(int argc, char **argv, PRBool initialize) /* If creating new database, initialize the password. */ if (certutil.commands[cmd_NewDBs].activated) { - SECU_ChangePW2(slot, 0, 0, certutil.options[opt_PasswordFile].arg, + if(certutil.options[opt_EmptyPassword].activated && (PK11_NeedUserInit(slot))) + PK11_InitPin(slot, (char*)NULL, ""); + else + SECU_ChangePW2(slot, 0, 0, certutil.options[opt_PasswordFile].arg, certutil.options[opt_NewPasswordFile].arg); } diff --git a/security/nss/cmd/tstclnt/tstclnt.c b/security/nss/cmd/tstclnt/tstclnt.c index d6cb8aa43cce..2e6c068b1d67 100644 --- a/security/nss/cmd/tstclnt/tstclnt.c +++ b/security/nss/cmd/tstclnt/tstclnt.c @@ -528,11 +528,10 @@ ownAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig, csa = SSL_PeerStapledOCSPResponses(fd); if (csa) { for (i = 0; i < csa->len; ++i) { - SECStatus test_rv = - CERT_CacheOCSPResponseFromSideChannel( + PORT_SetError(0); + if (CERT_CacheOCSPResponseFromSideChannel( serverCertAuth->dbHandle, cert, PR_Now(), - &csa->items[i], arg); - if (test_rv != SECSuccess) { + &csa->items[i], arg) != SECSuccess) { PRErrorCode error = PR_GetError(); PORT_Assert(error != 0); } diff --git a/security/nss/coreconf/coreconf.dep b/security/nss/coreconf/coreconf.dep index 590d1bfaeee3..5182f75552c8 100644 --- a/security/nss/coreconf/coreconf.dep +++ b/security/nss/coreconf/coreconf.dep @@ -10,4 +10,3 @@ */ #error "Do not include this header file." - diff --git a/security/nss/doc/certutil.xml b/security/nss/doc/certutil.xml index a2248f5f2448..1f280a9f738e 100644 --- a/security/nss/doc/certutil.xml +++ b/security/nss/doc/certutil.xml @@ -648,6 +648,11 @@ of the attribute codes: Add a Name Constraint extension to the certificate. X.509 certificate extensions are described in RFC 5280. + + --empty-password + Use empty password when creating new certificate database with -N. + + --keyAttrFlags attrflags diff --git a/security/nss/doc/html/certutil.html b/security/nss/doc/html/certutil.html index 5639d6534530..cb7047a92139 100644 --- a/security/nss/doc/html/certutil.html +++ b/security/nss/doc/html/certutil.html @@ -1,4 +1,4 @@ -CERTUTIL

Name

certutil — Manage keys and certificate in both NSS databases and other NSS tokens

Synopsis

certutil [options] [[arguments]]

STATUS

This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 +CERTUTIL

Name

certutil — Manage keys and certificate in both NSS databases and other NSS tokens

Synopsis

certutil [options] [[arguments]]

STATUS

This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477

Description

The Certificate Database Tool, certutil, is a command-line utility that can create and modify certificate and key databases. It can specifically list, generate, modify, or delete certificates, create or change the password, generate new public and private key pairs, display the contents of the key database, or delete key pairs within the key database.

Certificate issuance, part of the key and certificate management process, requires that keys and certificates be created in the key database. This document discusses certificate and key database management. For information on the security module database management, see the modutil manpage.

Command Options and Arguments

Running certutil always requires one and only one command option to specify the type of certificate operation. Each command option may take zero or more arguments. The command option -H will list all the command options and their relevant arguments.

Command Options

-A

Add an existing certificate to a certificate database. The certificate database should already exist; if one is not present, this command option will initialize one by default.

-B

Run a series of commands from the specified batch file. This requires the -i argument.

-C

Create a new binary certificate file from a binary certificate request file. Use the -i argument to specify the certificate request file. If this argument is not used, certutil prompts for a filename.

-D

Delete a certificate from the certificate database.

-E

Add an email certificate to the certificate database.

-F

Delete a private key from a key database. Specify the key to delete with the -n argument. Specify the database from which to delete the key with the -d argument. Use the -k argument to specify explicitly whether to delete a DSA, RSA, or ECC key. If you don't use the -k argument, the option looks for an RSA key matching the specified nickname.

@@ -10,7 +10,7 @@ For certificate requests, ASCII output defaults to standard output unless redire

If this option is not used, the validity check defaults to the current system time.

-c issuer

Identify the certificate of the CA from which a new certificate will derive its authenticity. Use the exact nickname or alias of the CA certificate, or use the CA's email address. Bracket the issuer string - with quotation marks if it contains spaces.

-d [prefix]directory

Specify the database directory containing the certificate and key database files.

certutil supports two types of databases: the legacy security databases (cert8.db, key3.db, and secmod.db) and new SQLite databases (cert9.db, key4.db, and pkcs11.txt).

NSS recognizes the following prefixes:

  • sql: requests the newer database

  • dbm: requests the legacy database

If no prefix is specified the default type is retrieved from NSS_DEFAULT_DB_TYPE. If NSS_DEFAULT_DB_TYPE is not set then dbm: is the default.

-e

Check a certificate's signature during the process of validating a certificate.

-f password-file

Specify a file that will automatically supply the password to include in a certificate + with quotation marks if it contains spaces.

-d [prefix]directory

Specify the database directory containing the certificate and key database files.

certutil supports two types of databases: the legacy security databases (cert8.db, key3.db, and secmod.db) and new SQLite databases (cert9.db, key4.db, and pkcs11.txt).

NSS recognizes the following prefixes:

  • sql: requests the newer database

  • dbm: requests the legacy database

If no prefix is specified the default type is retrieved from NSS_DEFAULT_DB_TYPE. If NSS_DEFAULT_DB_TYPE is not set then dbm: is the default.

-e

Check a certificate's signature during the process of validating a certificate.

--email email-address

Specify the email address of a certificate to list. Used with the -L command option.

-f password-file

Specify a file that will automatically supply the password to include in a certificate or to access a certificate database. This is a plain-text file containing one password. Be sure to prevent unauthorized access to this file.

-g keysize

Set a key size to use when generating new public and private key pairs. The minimum is 512 bits and the maximum is 8192 bits. The default is 1024 bits. Any size between the minimum and maximum is allowed.

-h tokenname

Specify the name of a token to use or act on. If not specified the default token is the internal database slot.

-i input_file

Pass an input file to the command. Depending on the command option, an input file can be a specific certificate, a certificate request file, or a batch file of commands.

-k key-type-or-id

Specify the type or specific ID of a key.

The valid key type options are rsa, dsa, ec, or all. The default @@ -109,7 +109,7 @@ of the attribute codes: msTrustListSign

  • critical -

  • X.509 certificate extensions are described in RFC 5280.

    -7 emailAddrs

    Add a comma-separated list of email addresses to the subject alternative name extension of a certificate or certificate request that is being created or added to the database. Subject alternative name extensions are described in Section 4.2.1.7 of RFC 3280.

    -8 dns-names

    Add a comma-separated list of DNS names to the subject alternative name extension of a certificate or certificate request that is being created or added to the database. Subject alternative name extensions are described in Section 4.2.1.7 of RFC 3280.

    --extAIA

    Add the Authority Information Access extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extSIA

    Add the Subject Information Access extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extCP

    Add the Certificate Policies extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extPM

    Add the Policy Mappings extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extPC

    Add the Policy Constraints extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extIA

    Add the Inhibit Any Policy Access extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extSKID

    Add the Subject Key ID extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extNC

    Add a Name Constraint extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --keyAttrFlags attrflags

    +

    X.509 certificate extensions are described in RFC 5280.

    -7 emailAddrs

    Add a comma-separated list of email addresses to the subject alternative name extension of a certificate or certificate request that is being created or added to the database. Subject alternative name extensions are described in Section 4.2.1.7 of RFC 3280.

    -8 dns-names

    Add a comma-separated list of DNS names to the subject alternative name extension of a certificate or certificate request that is being created or added to the database. Subject alternative name extensions are described in Section 4.2.1.7 of RFC 3280.

    --extAIA

    Add the Authority Information Access extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extSIA

    Add the Subject Information Access extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extCP

    Add the Certificate Policies extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extPM

    Add the Policy Mappings extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extPC

    Add the Policy Constraints extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extIA

    Add the Inhibit Any Policy Access extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extSKID

    Add the Subject Key ID extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extNC

    Add a Name Constraint extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --empty-password

    Use empty password when creating new certificate database with -N.

    --keyAttrFlags attrflags

    PKCS #11 key Attributes. Comma separated list of key attribute flags, selected from the following list of choices: {token | session} {public | private} {sensitive | insensitive} {modifiable | unmodifiable} {extractable | unextractable}

    --keyFlagsOn opflags, --keyFlagsOff opflags

    PKCS #11 key Operation Flags. Comma separated list of one or more of the following: diff --git a/security/nss/doc/html/modutil.html b/security/nss/doc/html/modutil.html index 2d16199c4b12..885fed8ad4a2 100644 --- a/security/nss/doc/html/modutil.html +++ b/security/nss/doc/html/modutil.html @@ -1,4 +1,4 @@ -MODUTIL

    Name

    modutil — Manage PKCS #11 module information within the security module database.

    Synopsis

    modutil [options] [[arguments]]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 +MODUTIL

    Name

    modutil — Manage PKCS #11 module information within the security module database.

    Synopsis

    modutil [options] [[arguments]]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477

    Description

    The Security Module Database Tool, modutil, is a command-line utility for managing PKCS #11 module information both within secmod.db files and within hardware tokens. modutil can add and delete PKCS #11 modules, change passwords on security databases, set defaults, list module contents, enable or disable slots, enable or disable FIPS 140-2 compliance, and assign default providers for cryptographic operations. This tool can also create certificate, key, and module security database files.

    The tasks associated with security module database management are part of a process that typically also involves managing key databases and certificate databases.

    Options

    Running modutil always requires one (and only one) option to specify the type of module operation. Each option may take arguments, anywhere from none to multiple arguments.

    Options

    -add modulename

    Add the named PKCS #11 module to the database. Use this option with the -libfile, -ciphers, and -mechanisms arguments.

    -changepw tokenname

    Change the password on the named token. If the token has not been initialized, this option initializes the password. Use this option with the -pwfile and -newpwfile arguments. A password is equivalent to a personal identification number (PIN).

    -chkfips

    Verify whether the module is in the given FIPS mode. true means to verify that the module is in FIPS mode, while false means to verify that the module is not in FIPS mode.

    -create

    Create new certificate, key, and module databases. Use the -dbdir directory argument to specify a directory. If any of these databases already exist in a specified directory, modutil returns an error message.

    -default modulename

    Specify the security mechanisms for which the named module will be a default provider. The security mechanisms are specified with the -mechanisms argument.

    -delete modulename

    Delete the named module. The default NSS PKCS #11 module cannot be deleted.

    -disable modulename

    Disable all slots on the named module. Use the -slot argument to disable a specific slot.

    -enable modulename

    Enable all slots on the named module. Use the -slot argument to enable a specific slot.

    -fips [true | false]

    Enable (true) or disable (false) FIPS 140-2 compliance for the default NSS module.

    -force

    Disable modutil's interactive prompts so it can be run from a script. Use this option only after manually testing each planned operation to check for warnings and to ensure that bypassing the prompts will cause no security lapses or loss of database integrity.

    -jar JAR-file

    Add a new PKCS #11 module to the database using the named JAR file. Use this command with the -installdir and -tempdir arguments. The JAR file uses the NSS PKCS #11 JAR format to identify all the files to be installed, the module's name, the mechanism flags, and the cipher flags, as well as any files to be installed on the target machine, including the PKCS #11 module library file and other files such as documentation. This is covered in the JAR installation file section in the man page, which details the special script needed to perform an installation through a server or with modutil.

    -list [modulename]

    Display basic information about the contents of the secmod.db file. Specifying a modulename displays detailed information about a particular module and its slots and tokens.

    -rawadd

    Add the module spec string to the secmod.db database.

    -rawlist

    Display the module specs for a specified module or for all loadable modules.

    -undefault modulename

    Specify the security mechanisms for which the named module will not be a default provider. The security mechanisms are specified with the -mechanisms argument.

    Arguments

    MODULE

    Give the security module to access.

    MODULESPEC

    Give the security module spec to load into the security database.

    -ciphers cipher-enable-list

    Enable specific ciphers in a module that is being added to the database. The cipher-enable-list is a colon-delimited list of cipher names. Enclose this list in quotation marks if it contains spaces.

    -dbdir [sql:]directory

    Specify the database directory in which to access or create security module database files.

    modutil supports two types of databases: the legacy security databases (cert8.db, key3.db, and secmod.db) and new SQLite databases (cert9.db, key4.db, and pkcs11.txt). If the prefix sql: is not used, then the tool assumes that the given databases are in the old format.

    --dbprefix prefix

    Specify the prefix used on the database files, such as my_ for my_cert8.db. This option is provided as a special case. Changing the names of the certificate and key databases is not recommended.

    -installdir root-installation-directory

    Specify the root installation directory relative to which files will be installed by the -jar option. This directory should be one below which it is appropriate to store dynamic library files, such as a server's root directory.

    -libfile library-file

    Specify a path to a library file containing the implementation of the PKCS #11 interface module that is being added to the database.

    -mechanisms mechanism-list

    Specify the security mechanisms for which a particular module will be flagged as a default provider. The mechanism-list is a colon-delimited list of mechanism names. Enclose this list in quotation marks if it contains spaces.

    The module becomes a default provider for the listed mechanisms when those mechanisms are enabled. If more than one module claims to be a particular mechanism's default provider, that mechanism's default provider is undefined.

    modutil supports several mechanisms: RSA, DSA, RC2, RC4, RC5, AES, DES, DH, SHA1, SHA256, SHA512, SSL, TLS, MD5, MD2, RANDOM (for random number generation), and FRIENDLY (meaning certificates are publicly readable).

    -newpwfile new-password-file

    Specify a text file containing a token's new or replacement password so that a password can be entered automatically with the -changepw option.

    -nocertdb

    Do not open the certificate or key databases. This has several effects:

    • With the -create command, only a module security file is created; certificate and key databases are not created.

    • With the -jar command, signatures on the JAR file are not checked.

    • With the -changepw command, the password on the NSS internal module cannot be set or changed, since this password is stored in the key database.

    -pwfile old-password-file

    Specify a text file containing a token's existing password so that a password can be entered automatically when the -changepw option is used to change passwords.

    -secmod secmodname

    Give the name of the security module database (like secmod.db) to load.

    -slot slotname

    Specify a particular slot to be enabled or disabled with the -enable or -disable options.

    -string CONFIG_STRING

    Pass a configuration string for the module being added to the database.

    -tempdir temporary-directory

    Give a directory location where temporary files are created during the installation by the -jar option. If no temporary directory is specified, the current directory is used.

    Usage and Examples

    Creating Database Files

    Before any operations can be performed, there must be a set of security databases available. modutil can be used to create these files. The only required argument is the database that where the databases will be located.

    modutil -create -dbdir [sql:]directory

    Adding a Cryptographic Module

    Adding a PKCS #11 module means submitting a supporting library file, enabling its ciphers, and setting default provider status for various security mechanisms. This can be done by supplying all of the information through modutil directly or by running a JAR file and install script. For the most basic case, simply upload the library:

    modutil -add modulename -libfile library-file [-ciphers cipher-enable-list] [-mechanisms mechanism-list] 

    For example: diff --git a/security/nss/doc/html/pk12util.html b/security/nss/doc/html/pk12util.html index e943bad368d0..29d4589f538b 100644 --- a/security/nss/doc/html/pk12util.html +++ b/security/nss/doc/html/pk12util.html @@ -4,7 +4,7 @@ common-options are: [-d [sql:]directory] [-P dbprefix] [-k slotPasswordFile|-K slotPassword] [-w p12filePasswordFile|-W p12filePassword] - ]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 + ]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477

    Description

    The PKCS #12 utility, pk12util, enables sharing certificates among any server that supports PKCS#12. The tool can import certificates and keys from PKCS#12 files into security databases, export certificates, and list certificates and keys.

    Options and Arguments

    Options

    -i p12file

    Import keys and certificates from a PKCS#12 file into a security database.

    -l p12file

    List the keys and certificates in PKCS#12 file.

    -o p12file

    Export keys and certificates from the security database to a PKCS#12 file.

    Arguments

    -n certname

    Specify the nickname of the cert and private key to export.

    -d [sql:]directory

    Specify the database directory into which to import to or export from certificates and keys.

    pk12util supports two types of databases: the legacy security databases (cert8.db, key3.db, and secmod.db) and new SQLite databases (cert9.db, key4.db, and pkcs11.txt). If the prefix sql: is not used, then the tool assumes that the given databases are in the old format.

    -P prefix

    Specify the prefix used on the certificate and key databases. This option is provided as a special case. Changing the names of the certificate and key databases is not recommended.

    -h tokenname

    Specify the name of the token to import into or export from.

    -v

    Enable debug logging when importing.

    -k slotPasswordFile

    Specify the text file containing the slot's password.

    -K slotPassword

    Specify the slot's password.

    -w p12filePasswordFile

    Specify the text file containing the pkcs #12 file password.

    -W p12filePassword

    Specify the pkcs #12 file password.

    -c keyCipher

    Specify the key encryption algorithm.

    -C certCipher

    Specify the key cert (overall package) encryption algorithm.

    -m | --key-len keyLength

    Specify the desired length of the symmetric key to be used to encrypt the private key.

    -n | --cert-key-len certKeyLength

    Specify the desired length of the symmetric key to be used to encrypt the certificates and other meta-data.

    -r

    Dumps all of the data in raw (binary) form. This must be saved as a DER file. The default is to return information in a pretty-print ASCII format, which displays the information about the certificates and public keys in the p12 file.

    Return Codes

    • 0 - No error

    • 1 - User Cancelled

    • 2 - Usage error

    • 6 - NLS init error

    • 8 - Certificate DB open error

    • 9 - Key DB open error

    • 10 - File initialization error

    • 11 - Unicode conversion error

    • 12 - Temporary file creation error

    • 13 - PKCS11 get slot error

    • 14 - PKCS12 decoder start error

    • 15 - error read from import file

    • 16 - pkcs12 decode error

    • 17 - pkcs12 decoder verify error

    • 18 - pkcs12 decoder validate bags error

    • 19 - pkcs12 decoder import bags error

    • 20 - key db conversion version 3 to version 2 error

    • 21 - cert db conversion version 7 to version 5 error

    • 22 - cert and key dbs patch error

    • 23 - get default cert db error

    • 24 - find cert by nickname error

    • 25 - create export context error

    • 26 - PKCS12 add password itegrity error

    • 27 - cert and key Safes creation error

    • 28 - PKCS12 add cert and key error

    • 29 - PKCS12 encode error

    Examples

    Importing Keys and Certificates

    The most basic usage of pk12util for importing a certificate or key is the PKCS#12 input file (-i) and some way to specify the security database being accessed (either -d for a directory or -h for a token).

    pk12util -i p12File [-h tokenname] [-v] [-d [sql:]directory] [-P dbprefix] [-k slotPasswordFile|-K slotPassword] [-w p12filePasswordFile|-W p12filePassword]

    For example:

    # pk12util -i /tmp/cert-files/users.p12 -d sql:/home/my/sharednssdb
    diff --git a/security/nss/doc/html/pp.html b/security/nss/doc/html/pp.html
    index e03902f310ac..c197911dec0e 100644
    --- a/security/nss/doc/html/pp.html
    +++ b/security/nss/doc/html/pp.html
    @@ -1,7 +1,7 @@
    -PP

    Name

    pp — Prints certificates, keys, crls, and pkcs7 files

    Synopsis

    pp -t type [-a] [-i input] [-o output]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 -

    Description

    pp pretty-prints private and public key, certificate, certificate-request, +PP

    Name

    pp — Prints certificates, keys, crls, and pkcs7 files

    Synopsis

    pp -t type [-a] [-i input] [-o output]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 +

    Description

    pp pretty-prints private and public key, certificate, certificate-request, pkcs7 or crl files -

    Options

    -t type

    specify the input, one of {private-key | public-key | certificate | certificate-request | pkcs7 | crl}

    -a
    Input is in ascii encoded form (RFC1113)
    -i inputfile
    Define an input file to use (default is stdin)
    -u outputfile
    Define an output file to use (default is stdout)

    Additional Resources

    NSS is maintained in conjunction with PKI and security-related projects through Mozilla and Fedora. The most closely-related project is Dogtag PKI, with a project wiki at PKI Wiki.

    For information specifically about NSS, the NSS project wiki is located at Mozilla NSS site. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: pki-devel@redhat.com and pki-users@redhat.com

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google.

    +

    Options

    -t type

    specify the input, one of {private-key | public-key | certificate | certificate-request | pkcs7 | crl}

    -a
    Input is in ascii encoded form (RFC1113)
    -i inputfile
    Define an input file to use (default is stdin)
    -u outputfile
    Define an output file to use (default is stdout)

    Additional Resources

    NSS is maintained in conjunction with PKI and security-related projects through Mozilla and Fedora. The most closely-related project is Dogtag PKI, with a project wiki at PKI Wiki.

    For information specifically about NSS, the NSS project wiki is located at Mozilla NSS site. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: pki-devel@redhat.com and pki-users@redhat.com

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google.

    Authors: Elio Maldonado <emaldona@redhat.com>, Deon Lackey <dlackey@redhat.com>.

    LICENSE

    Licensed under 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/.

    diff --git a/security/nss/doc/html/signtool.html b/security/nss/doc/html/signtool.html index 9fb932c38b1e..6439a7b25d80 100644 --- a/security/nss/doc/html/signtool.html +++ b/security/nss/doc/html/signtool.html @@ -1,4 +1,4 @@ -signtool

    Name

    signtool — Digitally sign objects and files.

    Synopsis

    signtool [-k keyName] [[-h]] [[-H]] [[-l]] [[-L]] [[-M]] [[-v]] [[-w]] [[-G nickname]] [[--keysize | -s size]] [[-b basename]] [[-c Compression Level] ] [[-d cert-dir] ] [[-i installer script] ] [[-m metafile] ] [[-x name] ] [[-f filename] ] [[-t|--token tokenname] ] [[-e extension] ] [[-o] ] [[-z] ] [[-X] ] [[--outfile] ] [[--verbose value] ] [[--norecurse] ] [[--leavearc] ] [[-j directory] ] [[-Z jarfile] ] [[-O] ] [[-p password] ] [directory-tree] [archive]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 +signtool

    Name

    signtool — Digitally sign objects and files.

    Synopsis

    signtool [-k keyName] [[-h]] [[-H]] [[-l]] [[-L]] [[-M]] [[-v]] [[-w]] [[-G nickname]] [[--keysize | -s size]] [[-b basename]] [[-c Compression Level] ] [[-d cert-dir] ] [[-i installer script] ] [[-m metafile] ] [[-x name] ] [[-f filename] ] [[-t|--token tokenname] ] [[-e extension] ] [[-o] ] [[-z] ] [[-X] ] [[--outfile] ] [[--verbose value] ] [[--norecurse] ] [[--leavearc] ] [[-j directory] ] [[-Z jarfile] ] [[-O] ] [[-p password] ] [directory-tree] [archive]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477

    Description

    The Signing Tool, signtool, creates digital signatures and uses a Java Archive (JAR) file to associate the signatures with files in a directory. Electronic software distribution over any network involves potential security problems. To help address some of these problems, you can associate digital signatures with the files in a JAR archive. Digital signatures allow SSL-enabled clients to perform two important operations:

    * Confirm the identity of the individual, company, or other entity whose digital signature is associated with the files

    * Check whether the files have been tampered with since being signed

    If you have a signing certificate, you can use Netscape Signing Tool to digitally sign files and package them as a JAR file. An object-signing certificate is a special kind of certificate that allows you to associate your digital signature with one or more files.

    An individual file can potentially be signed with multiple digital signatures. For example, a commercial software developer might sign the files that constitute a software product to prove that the files are indeed from a particular company. A network administrator manager might sign the same files with an additional digital signature based on a company-generated certificate to indicate that the product is approved for use within the company.

    The significance of a digital signature is comparable to the significance of a handwritten signature. Once you have signed a file, it is difficult to claim later that you didn't sign it. In some situations, a digital signature may be considered as legally binding as a handwritten signature. Therefore, you should take great care to ensure that you can stand behind any file you sign and distribute.

    For example, if you are a software developer, you should test your code to make sure it is virus-free before signing it. Similarly, if you are a network administrator, you should make sure, before signing any code, that it comes from a reliable source and will run correctly with the software installed on the machines to which you are distributing it.

    Before you can use Netscape Signing Tool to sign files, you must have an object-signing certificate, which is a special certificate whose associated private key is used to create digital signatures. For testing purposes only, you can create an object-signing certificate with Netscape Signing Tool 1.3. When testing is finished and you are ready to disitribute your software, you should obtain an object-signing certificate from one of two kinds of sources:

    * An independent certificate authority (CA) that authenticates your identity and charges you a fee. You typically get a certificate from an independent CA if you want to sign software that will be distributed over the Internet.

    * CA server software running on your corporate intranet or extranet. Netscape Certificate Management System provides a complete management solution for creating, deploying, and managing certificates, including CAs that issue object-signing certificates.

    You must also have a certificate for the CA that issues your signing certificate before you can sign files. If the certificate authority's certificate isn't already installed in your copy of Communicator, you typically install it by clicking the appropriate link on the certificate authority's web site, for example on the page from which you initiated enrollment for your signing certificate. This is the case for some test certificates, as well as certificates issued by Netscape Certificate Management System: you must download the the CA certificate in addition to obtaining your own signing certificate. CA certificates for several certificate authorities are preinstalled in the Communicator certificate database.

    When you receive an object-signing certificate for your own use, it is automatically installed in your copy of the Communicator client software. Communicator supports the public-key cryptography standard known as PKCS #12, which governs key portability. You can, for example, move an object-signing certificate and its associated private key from one computer to another on a credit-card-sized device called a smart card.

    Options

    -b basename

    Specifies the base filename for the .rsa and .sf files in the META-INF directory to conform with the JAR format. For example, -b signatures causes the files to be named signatures.rsa and signatures.sf. The default is signtool.

    -c#

    Specifies the compression level for the -J or -Z option. The symbol # represents a number from 0 to 9, where 0 means no compression and 9 means maximum compression. The higher the level of compression, the smaller the output but the longer the operation takes. diff --git a/security/nss/doc/html/signver.html b/security/nss/doc/html/signver.html index 4f0a9c3c6f56..bfd67ab41128 100644 --- a/security/nss/doc/html/signver.html +++ b/security/nss/doc/html/signver.html @@ -1,7 +1,7 @@ -SIGNVER

    Name

    signver — Verify a detached PKCS#7 signature for a file.

    Synopsis

    signtool -A | -V -d directory [-a] [-i input_file] [-o output_file] [-s signature_file] [-v]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 -

    Description

    The Signature Verification Tool, signver, is a simple command-line utility that unpacks a base-64-encoded PKCS#7 signed object and verifies the digital signature using standard cryptographic techniques. The Signature Verification Tool can also display the contents of the signed object.

    Options

    -A

    Displays all of the information in the PKCS#7 signature.

    -V

    Verifies the digital signature.

    -d [sql:]directory

    Specify the database directory which contains the certificates and keys.

    signver supports two types of databases: the legacy security databases (cert8.db, key3.db, and secmod.db) and new SQLite databases (cert9.db, key4.db, and pkcs11.txt). If the prefix sql: is not used, then the tool assumes that the given databases are in the old format.

    -a

    Sets that the given signature file is in ASCII format.

    -i input_file

    Gives the input file for the object with signed data.

    -o output_file

    Gives the output file to which to write the results.

    -s signature_file

    Gives the input file for the digital signature.

    -v

    Enables verbose output.

    Extended Examples

    Verifying a Signature

    The -V option verifies that the signature in a given signature file is valid when used to sign the given object (from the input file).

    signver -V -s signature_file -i signed_file -d sql:/home/my/sharednssdb
    +SIGNVER

    Name

    signver — Verify a detached PKCS#7 signature for a file.

    Synopsis

    signtool -A | -V -d directory [-a] [-i input_file] [-o output_file] [-s signature_file] [-v]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 +

    Description

    The Signature Verification Tool, signver, is a simple command-line utility that unpacks a base-64-encoded PKCS#7 signed object and verifies the digital signature using standard cryptographic techniques. The Signature Verification Tool can also display the contents of the signed object.

    Options

    -A

    Displays all of the information in the PKCS#7 signature.

    -V

    Verifies the digital signature.

    -d [sql:]directory

    Specify the database directory which contains the certificates and keys.

    signver supports two types of databases: the legacy security databases (cert8.db, key3.db, and secmod.db) and new SQLite databases (cert9.db, key4.db, and pkcs11.txt). If the prefix sql: is not used, then the tool assumes that the given databases are in the old format.

    -a

    Sets that the given signature file is in ASCII format.

    -i input_file

    Gives the input file for the object with signed data.

    -o output_file

    Gives the output file to which to write the results.

    -s signature_file

    Gives the input file for the digital signature.

    -v

    Enables verbose output.

    Extended Examples

    Verifying a Signature

    The -V option verifies that the signature in a given signature file is valid when used to sign the given object (from the input file).

    signver -V -s signature_file -i signed_file -d sql:/home/my/sharednssdb
     
    -signatureValid=yes

    Printing Signature Data

    +signatureValid=yes

    Printing Signature Data

    The -A option prints all of the information contained in a signature file. Using the -o option prints the signature file information to the given output file rather than stdout.

    signver -A -s signature_file -o output_file

    NSS Database Types

    NSS originally used BerkeleyDB databases to store security information. The last versions of these legacy databases are:

    • diff --git a/security/nss/doc/html/ssltap.html b/security/nss/doc/html/ssltap.html index a3e9b911308b..fce7570acdba 100644 --- a/security/nss/doc/html/ssltap.html +++ b/security/nss/doc/html/ssltap.html @@ -1,4 +1,4 @@ -SSLTAP

      Name

      ssltap — Tap into SSL connections and display the data going by

      Synopsis

      libssltap [-vhfsxl] [-p port] [hostname:port]

      STATUS

      This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 +SSLTAP

      Name

      ssltap — Tap into SSL connections and display the data going by

      Synopsis

      libssltap [-vhfsxl] [-p port] [hostname:port]

      STATUS

      This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477

      Description

      The SSL Debugging Tool ssltap is an SSL-aware command-line proxy. It watches TCP connections and displays the data going by. If a connection is SSL, the data display includes interpreted SSL records and handshaking

      Options

      -v

      Print a version string for the tool.

      -h

      Turn on hex/ASCII printing. Instead of outputting raw data, the command interprets each record as a numbered line of hex values, followed by the same data as ASCII characters. The two parts are separated by a vertical bar. Nonprinting characters are replaced by dots.

      -f

      diff --git a/security/nss/doc/html/vfychain.html b/security/nss/doc/html/vfychain.html index 6d62b9ad3b83..43a07e899b0a 100644 --- a/security/nss/doc/html/vfychain.html +++ b/security/nss/doc/html/vfychain.html @@ -1,4 +1,4 @@ -VFYCHAIN

      Name

      vfychain — vfychain [options] [revocation options] certfile [[options] certfile] ...

      Synopsis

      vfychain

      STATUS

      This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 +VFYCHAIN

      Name

      vfychain — vfychain [options] [revocation options] certfile [[options] certfile] ...

      Synopsis

      vfychain

      STATUS

      This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477

      Description

      The verification Tool, vfychain, verifies certificate chains. modutil can add and delete PKCS #11 modules, change passwords on security databases, set defaults, list module contents, enable or disable slots, enable or disable FIPS 140-2 compliance, and assign default providers for cryptographic operations. This tool can also create certificate, key, and module security database files.

      The tasks associated with security module database management are part of a process that typically also involves managing key databases and certificate databases.

      Options

      -a
      the following certfile is base64 encoded
      -b YYMMDDHHMMZ
      Validate date (default: now)
      -d directory
      database directory
      -f
      Enable cert fetching from AIA URL
      -o oid
      Set policy OID for cert validation(Format OID.1.2.3)
      -p

      Use PKIX Library to validate certificate by calling:

      * CERT_VerifyCertificate if specified once,

      * CERT_PKIXVerifyCert if specified twice and more.

      -r
      Following certfile is raw binary DER (default)
      -t
      Following cert is explicitly trusted (overrides db trust)
      -u usage

      0=SSL client, 1=SSL server, 2=SSL StepUp, 3=SSL CA, 4=Email signer, 5=Email recipient, 6=Object signer, diff --git a/security/nss/doc/html/vfyserv.html b/security/nss/doc/html/vfyserv.html index e7cef7a6676f..fef4fef1c88b 100644 --- a/security/nss/doc/html/vfyserv.html +++ b/security/nss/doc/html/vfyserv.html @@ -1,4 +1,4 @@ -VFYSERV

      Name

      vfyserv — TBD

      Synopsis

      vfyserv

      STATUS

      This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 +VFYSERV

      Name

      vfyserv — TBD

      Synopsis

      vfyserv

      STATUS

      This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477

      Description

      The vfyserv tool verifies a certificate chain

      Options

      Additional Resources

      For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at http://www.mozilla.org/projects/security/pki/nss/. The NSS site relates directly to NSS code changes and releases.

      Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto

      IRC: Freenode at #dogtag-pki

      Authors

      The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google.

      Authors: Elio Maldonado <emaldona@redhat.com>, Deon Lackey <dlackey@redhat.com>.

      LICENSE

      Licensed under 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/. diff --git a/security/nss/doc/nroff/certutil.1 b/security/nss/doc/nroff/certutil.1 index 3ee702b8eccd..7a82532ad5bc 100644 --- a/security/nss/doc/nroff/certutil.1 +++ b/security/nss/doc/nroff/certutil.1 @@ -2,12 +2,12 @@ .\" Title: CERTUTIL .\" Author: [see the "Authors" section] .\" Generator: DocBook XSL Stylesheets v1.78.1 -.\" Date: 19 July 2013 +.\" Date: 5 November 2013 .\" Manual: NSS Security Tools .\" Source: nss-tools .\" Language: English .\" -.TH "CERTUTIL" "1" "19 July 2013" "nss-tools" "NSS Security Tools" +.TH "CERTUTIL" "1" "5 November 2013" "nss-tools" "NSS Security Tools" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -251,6 +251,11 @@ If no prefix is specified the default type is retrieved from NSS_DEFAULT_DB_TYPE Check a certificate\*(Aqs signature during the process of validating a certificate\&. .RE .PP +\-\-email email\-address +.RS 4 +Specify the email address of a certificate to list\&. Used with the \-L command option\&. +.RE +.PP \-f password\-file .RS 4 Specify a file that will automatically supply the password to include in a certificate or to access a certificate database\&. This is a plain\-text file containing one password\&. Be sure to prevent unauthorized access to this file\&. @@ -905,6 +910,11 @@ Add the Subject Key ID extension to the certificate\&. X\&.509 certificate exten Add a Name Constraint extension to the certificate\&. X\&.509 certificate extensions are described in RFC 5280\&. .RE .PP +\-\-empty\-password +.RS 4 +Use empty password when creating new certificate database with \-N\&. +.RE +.PP \-\-keyAttrFlags attrflags .RS 4 PKCS #11 key Attributes\&. Comma separated list of key attribute flags, selected from the following list of choices: {token | session} {public | private} {sensitive | insensitive} {modifiable | unmodifiable} {extractable | unextractable} diff --git a/security/nss/doc/nroff/pk12util.1 b/security/nss/doc/nroff/pk12util.1 index 132bdd08eede..8f392740255a 100644 --- a/security/nss/doc/nroff/pk12util.1 +++ b/security/nss/doc/nroff/pk12util.1 @@ -2,12 +2,12 @@ .\" Title: PK12UTIL .\" Author: [see the "Authors" section] .\" Generator: DocBook XSL Stylesheets v1.78.1 -.\" Date: 19 July 2013 +.\" Date: 5 November 2013 .\" Manual: NSS Security Tools .\" Source: nss-tools .\" Language: English .\" -.TH "PK12UTIL" "1" "19 July 2013" "nss-tools" "NSS Security Tools" +.TH "PK12UTIL" "1" "5 November 2013" "nss-tools" "NSS Security Tools" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/security/nss/doc/nroff/pp.1 b/security/nss/doc/nroff/pp.1 index b6fd6a5ef48a..a72104cb943e 100644 --- a/security/nss/doc/nroff/pp.1 +++ b/security/nss/doc/nroff/pp.1 @@ -2,12 +2,12 @@ .\" Title: PP .\" Author: [see the "Authors" section] .\" Generator: DocBook XSL Stylesheets v1.78.1 -.\" Date: 19 July 2013 +.\" Date: 5 November 2013 .\" Manual: NSS Security Tools .\" Source: nss-tools .\" Language: English .\" -.TH "PP" "1" "19 July 2013" "nss-tools" "NSS Security Tools" +.TH "PP" "1" "5 November 2013" "nss-tools" "NSS Security Tools" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/security/nss/doc/nroff/signtool.1 b/security/nss/doc/nroff/signtool.1 index 26e2eabe0cf4..32a0d54651fb 100644 --- a/security/nss/doc/nroff/signtool.1 +++ b/security/nss/doc/nroff/signtool.1 @@ -2,12 +2,12 @@ .\" Title: signtool .\" Author: [see the "Authors" section] .\" Generator: DocBook XSL Stylesheets v1.78.1 -.\" Date: 19 July 2013 +.\" Date: 5 November 2013 .\" Manual: NSS Security Tools .\" Source: nss-tools .\" Language: English .\" -.TH "SIGNTOOL" "1" "19 July 2013" "nss-tools" "NSS Security Tools" +.TH "SIGNTOOL" "1" "5 November 2013" "nss-tools" "NSS Security Tools" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/security/nss/doc/nroff/signver.1 b/security/nss/doc/nroff/signver.1 index 53c75a4d0ae7..de4324b49907 100644 --- a/security/nss/doc/nroff/signver.1 +++ b/security/nss/doc/nroff/signver.1 @@ -2,12 +2,12 @@ .\" Title: SIGNVER .\" Author: [see the "Authors" section] .\" Generator: DocBook XSL Stylesheets v1.78.1 -.\" Date: 19 July 2013 +.\" Date: 5 November 2013 .\" Manual: NSS Security Tools .\" Source: nss-tools .\" Language: English .\" -.TH "SIGNVER" "1" "19 July 2013" "nss-tools" "NSS Security Tools" +.TH "SIGNVER" "1" "5 November 2013" "nss-tools" "NSS Security Tools" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/security/nss/doc/nroff/ssltap.1 b/security/nss/doc/nroff/ssltap.1 index 89c1c50faabb..74c75f3ffb9e 100644 --- a/security/nss/doc/nroff/ssltap.1 +++ b/security/nss/doc/nroff/ssltap.1 @@ -2,12 +2,12 @@ .\" Title: SSLTAP .\" Author: [see the "Authors" section] .\" Generator: DocBook XSL Stylesheets v1.78.1 -.\" Date: 19 July 2013 +.\" Date: 5 November 2013 .\" Manual: NSS Security Tools .\" Source: nss-tools .\" Language: English .\" -.TH "SSLTAP" "1" "19 July 2013" "nss-tools" "NSS Security Tools" +.TH "SSLTAP" "1" "5 November 2013" "nss-tools" "NSS Security Tools" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/security/nss/doc/nroff/vfychain.1 b/security/nss/doc/nroff/vfychain.1 index 977669b0a9e5..6cd2d06c3056 100644 --- a/security/nss/doc/nroff/vfychain.1 +++ b/security/nss/doc/nroff/vfychain.1 @@ -2,12 +2,12 @@ .\" Title: VFYCHAIN .\" Author: [see the "Authors" section] .\" Generator: DocBook XSL Stylesheets v1.78.1 -.\" Date: 19 July 2013 +.\" Date: 5 November 2013 .\" Manual: NSS Security Tools .\" Source: nss-tools .\" Language: English .\" -.TH "VFYCHAIN" "1" "19 July 2013" "nss-tools" "NSS Security Tools" +.TH "VFYCHAIN" "1" "5 November 2013" "nss-tools" "NSS Security Tools" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/security/nss/doc/nroff/vfyserv.1 b/security/nss/doc/nroff/vfyserv.1 index 2dc0c0e7838a..8290ad945437 100644 --- a/security/nss/doc/nroff/vfyserv.1 +++ b/security/nss/doc/nroff/vfyserv.1 @@ -2,12 +2,12 @@ .\" Title: VFYSERV .\" Author: [see the "Authors" section] .\" Generator: DocBook XSL Stylesheets v1.78.1 -.\" Date: 19 July 2013 +.\" Date: 5 November 2013 .\" Manual: NSS Security Tools .\" Source: nss-tools .\" Language: English .\" -.TH "VFYSERV" "1" "19 July 2013" "nss-tools" "NSS Security Tools" +.TH "VFYSERV" "1" "5 November 2013" "nss-tools" "NSS Security Tools" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/security/nss/lib/nss/nss.h b/security/nss/lib/nss/nss.h index dcb780e3050e..3e7d3686a6e3 100644 --- a/security/nss/lib/nss/nss.h +++ b/security/nss/lib/nss/nss.h @@ -33,10 +33,10 @@ * The format of the version string should be * ".[.[.]][ ][ ]" */ -#define NSS_VERSION "3.15.3" _NSS_ECC_STRING _NSS_CUSTOMIZED " Beta" +#define NSS_VERSION "3.15.4" _NSS_ECC_STRING _NSS_CUSTOMIZED " Beta" #define NSS_VMAJOR 3 #define NSS_VMINOR 15 -#define NSS_VPATCH 3 +#define NSS_VPATCH 4 #define NSS_VBUILD 0 #define NSS_BETA PR_TRUE diff --git a/security/nss/lib/softoken/softkver.h b/security/nss/lib/softoken/softkver.h index bbd82cc8afe7..236870c06330 100644 --- a/security/nss/lib/softoken/softkver.h +++ b/security/nss/lib/softoken/softkver.h @@ -25,10 +25,10 @@ * The format of the version string should be * ".[.[.]][ ][ ]" */ -#define SOFTOKEN_VERSION "3.15.3" SOFTOKEN_ECC_STRING " Beta" +#define SOFTOKEN_VERSION "3.15.4" SOFTOKEN_ECC_STRING " Beta" #define SOFTOKEN_VMAJOR 3 #define SOFTOKEN_VMINOR 15 -#define SOFTOKEN_VPATCH 3 +#define SOFTOKEN_VPATCH 4 #define SOFTOKEN_VBUILD 0 #define SOFTOKEN_BETA PR_TRUE diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index 4cafe5c2506c..bc4bcfa208bf 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -819,6 +819,11 @@ static SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen, int maxOutputLen, const unsigned char *input, int inputLen) { + if (inputLen > maxOutputLen) { + *outputLen = 0; /* Match PK11_CipherOp in setting outputLen */ + PORT_SetError(SEC_ERROR_OUTPUT_LEN); + return SECFailure; + } *outputLen = inputLen; if (input != output) PORT_Memcpy(output, input, inputLen); diff --git a/security/nss/lib/ssl/sslauth.c b/security/nss/lib/ssl/sslauth.c index eda949082af5..ed74d94c630a 100644 --- a/security/nss/lib/ssl/sslauth.c +++ b/security/nss/lib/ssl/sslauth.c @@ -259,11 +259,11 @@ SSL_AuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer) certStatusArray = &ss->sec.ci.sid->peerCertStatus; if (certStatusArray->len) { - SECStatus test_rv = - CERT_CacheOCSPResponseFromSideChannel(handle, ss->sec.peerCert, now, + PORT_SetError(0); + if (CERT_CacheOCSPResponseFromSideChannel(handle, ss->sec.peerCert, now, &certStatusArray->items[0], - ss->pkcs11PinArg); - if (test_rv != SECSuccess) { + ss->pkcs11PinArg) + != SECSuccess) { PRErrorCode error = PR_GetError(); PORT_Assert(error != 0); } diff --git a/security/nss/lib/util/nssutil.h b/security/nss/lib/util/nssutil.h index 230787b46784..5699a531e985 100644 --- a/security/nss/lib/util/nssutil.h +++ b/security/nss/lib/util/nssutil.h @@ -19,10 +19,10 @@ * The format of the version string should be * ".[.[.]][ ]" */ -#define NSSUTIL_VERSION "3.15.3 Beta" +#define NSSUTIL_VERSION "3.15.4 Beta" #define NSSUTIL_VMAJOR 3 #define NSSUTIL_VMINOR 15 -#define NSSUTIL_VPATCH 3 +#define NSSUTIL_VPATCH 4 #define NSSUTIL_VBUILD 0 #define NSSUTIL_BETA PR_TRUE diff --git a/toolkit/components/url-classifier/content/url-crypto-key-manager.js b/toolkit/components/url-classifier/content/url-crypto-key-manager.js index 8361e28689a0..062f53e4a8c8 100644 --- a/toolkit/components/url-classifier/content/url-crypto-key-manager.js +++ b/toolkit/components/url-classifier/content/url-crypto-key-manager.js @@ -353,46 +353,29 @@ PROT_UrlCryptoKeyManager.prototype.onNewKey = function(callback) * loading old key */ PROT_UrlCryptoKeyManager.prototype.maybeLoadOldKey = function() { - - var oldKey = null; - try { - var keyfile = Cc["@mozilla.org/file/directory_service;1"] - .getService(Ci.nsIProperties) - .get("ProfD", Ci.nsILocalFile); /* profile directory */ - keyfile.append(this.keyFilename_); - if (keyfile.exists()) { - try { - var fis = Cc["@mozilla.org/network/file-input-stream;1"] - .createInstance(Ci.nsIFileInputStream); - fis.init(keyfile, 0x01 /* PR_RDONLY */, 0444, 0); - var stream = Cc["@mozilla.org/scriptableinputstream;1"] - .createInstance(Ci.nsIScriptableInputStream); - stream.init(fis); - oldKey = stream.read(stream.available()); - } finally { - if (stream) - stream.close(); - } + let keypath = OS.Path.join(OS.Constants.Path.profileDir, this.keyFilename_); + + let decoder = new TextDecoder(); + let promise = OS.File.read(keypath); + return promise.then(array => { + let oldKey = decoder.decode(array); + if (!oldKey) { + G_Debug(this, "Couldn't find old key."); + return false; } - } catch(e) { + + oldKey = (new G_Protocol4Parser).parse(oldKey); + var clientKey = oldKey[this.CLIENT_KEY_NAME]; + var wrappedKey = oldKey[this.WRAPPED_KEY_NAME]; + + if (oldKey && clientKey && wrappedKey && !this.hasKey()) { + G_Debug(this, "Read old key from disk."); + return this.replaceKey_(clientKey, wrappedKey); + } + }, e => { G_Debug(this, "Caught " + e + " trying to read keyfile"); - return Promise.resolve(false); - } - - if (!oldKey) { - G_Debug(this, "Couldn't find old key."); - return Promise.resolve(false); - } - - oldKey = (new G_Protocol4Parser).parse(oldKey); - var clientKey = oldKey[this.CLIENT_KEY_NAME]; - var wrappedKey = oldKey[this.WRAPPED_KEY_NAME]; - - if (oldKey && clientKey && wrappedKey && !this.hasKey()) { - G_Debug(this, "Read old key from disk."); - return this.replaceKey_(clientKey, wrappedKey); - } - return Promise.resolve(false); + return false; + }); } PROT_UrlCryptoKeyManager.prototype.shutdown = function() { diff --git a/tools/profiler/IntelPowerGadget.cpp b/tools/profiler/IntelPowerGadget.cpp new file mode 100644 index 000000000000..cd96c348cab0 --- /dev/null +++ b/tools/profiler/IntelPowerGadget.cpp @@ -0,0 +1,310 @@ +/* + * Copyright 2013, Intel Corporation + * + * 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. + * + * Author: Joe Olivas + */ + +#include "nsDebug.h" +#include "nsString.h" +#include "IntelPowerGadget.h" +#include "prenv.h" + +IntelPowerGadget::IntelPowerGadget() : + libpowergadget(nullptr), + Initialize(nullptr), + GetNumNodes(nullptr), + GetMsrName(nullptr), + GetMsrFunc(nullptr), + ReadMSR(nullptr), + WriteMSR(nullptr), + GetIAFrequency(nullptr), + GetTDP(nullptr), + GetMaxTemperature(nullptr), + GetThresholds(nullptr), + GetTemperature(nullptr), + ReadSample(nullptr), + GetSysTime(nullptr), + GetRDTSC(nullptr), + GetTimeInterval(nullptr), + GetBaseFrequency(nullptr), + GetPowerData(nullptr), + StartLog(nullptr), + StopLog(nullptr), + GetNumMsrs(nullptr), + packageMSR(-1), + cpuMSR(-1), + freqMSR(-1), + tempMSR(-1) +{ +} + +bool +IntelPowerGadget::Init() +{ + bool success = false; + const char *path = PR_GetEnv("IPG_Dir"); + nsCString ipg_library; + if (path && *path) { + ipg_library.Append(path); + ipg_library.AppendLiteral("/"); + ipg_library.AppendLiteral(PG_LIBRARY_NAME); + libpowergadget = PR_LoadLibrary(ipg_library.get()); + } + + if(libpowergadget) { + Initialize = (IPGInitialize) PR_FindFunctionSymbol(libpowergadget, "IntelEnergyLibInitialize"); + GetNumNodes = (IPGGetNumNodes) PR_FindFunctionSymbol(libpowergadget, "GetNumNodes"); + GetMsrName = (IPGGetMsrName) PR_FindFunctionSymbol(libpowergadget, "GetMsrName"); + GetMsrFunc = (IPGGetMsrFunc) PR_FindFunctionSymbol(libpowergadget, "GetMsrFunc"); + ReadMSR = (IPGReadMSR) PR_FindFunctionSymbol(libpowergadget, "ReadMSR"); + WriteMSR = (IPGWriteMSR) PR_FindFunctionSymbol(libpowergadget, "WriteMSR"); + GetIAFrequency = (IPGGetIAFrequency) PR_FindFunctionSymbol(libpowergadget, "GetIAFrequency"); + GetTDP = (IPGGetTDP) PR_FindFunctionSymbol(libpowergadget, "GetTDP"); + GetMaxTemperature = (IPGGetMaxTemperature) PR_FindFunctionSymbol(libpowergadget, "GetMaxTemperature"); + GetThresholds = (IPGGetThresholds) PR_FindFunctionSymbol(libpowergadget, "GetThresholds"); + GetTemperature = (IPGGetTemperature) PR_FindFunctionSymbol(libpowergadget, "GetTemperature"); + ReadSample = (IPGReadSample) PR_FindFunctionSymbol(libpowergadget, "ReadSample"); + GetSysTime = (IPGGetSysTime) PR_FindFunctionSymbol(libpowergadget, "GetSysTime"); + GetRDTSC = (IPGGetRDTSC) PR_FindFunctionSymbol(libpowergadget, "GetRDTSC"); + GetTimeInterval = (IPGGetTimeInterval) PR_FindFunctionSymbol(libpowergadget, "GetTimeInterval"); + GetBaseFrequency = (IPGGetBaseFrequency) PR_FindFunctionSymbol(libpowergadget, "GetBaseFrequency"); + GetPowerData = (IPGGetPowerData) PR_FindFunctionSymbol(libpowergadget, "GetPowerData"); + StartLog = (IPGStartLog) PR_FindFunctionSymbol(libpowergadget, "StartLog"); + StopLog = (IPGStopLog) PR_FindFunctionSymbol(libpowergadget, "StopLog"); + GetNumMsrs = (IPGGetNumMsrs) PR_FindFunctionSymbol(libpowergadget, "GetNumMsrs"); + } + + if(Initialize) { + Initialize(); + int msrCount = GetNumberMsrs(); + wchar_t name[1024] = {0}; + for(int i = 0; i < msrCount; ++i) { + GetMsrName(i, name); + int func = 0; + GetMsrFunc(i, &func); + // MSR for frequency + if(wcscmp(name, L"CPU Frequency") == 0 && (func == 0)) { + this->freqMSR = i; + } + // MSR for Package + else if(wcscmp(name, L"Processor") == 0 && (func == 1)) { + this->packageMSR = i; + } + // MSR for CPU + else if(wcscmp(name, L"IA") == 0 && (func == 1)) { + this->cpuMSR = i; + } + // MSR for Temperature + else if(wcscmp(name, L"Package") == 0 && (func == 2)) { + this->tempMSR = i; + } + } + // Grab one sample at startup for a diff + TakeSample(); + success = true; + } + return success; +} + +IntelPowerGadget::~IntelPowerGadget() +{ + if(libpowergadget) { + NS_WARNING("Unloading PowerGadget library!\n"); + PR_UnloadLibrary(libpowergadget); + libpowergadget = nullptr; + Initialize = nullptr; + GetNumNodes = nullptr; + GetMsrName = nullptr; + GetMsrFunc = nullptr; + ReadMSR = nullptr; + WriteMSR = nullptr; + GetIAFrequency = nullptr; + GetTDP = nullptr; + GetMaxTemperature = nullptr; + GetThresholds = nullptr; + GetTemperature = nullptr; + ReadSample = nullptr; + GetSysTime = nullptr; + GetRDTSC = nullptr; + GetTimeInterval = nullptr; + GetBaseFrequency = nullptr; + GetPowerData = nullptr; + StartLog = nullptr; + StopLog = nullptr; + GetNumMsrs = nullptr; + } +} + +int +IntelPowerGadget::GetNumberNodes() +{ + int nodes = 0; + if(GetNumNodes) { + int ok = GetNumNodes(&nodes); + } + return nodes; +} + +int +IntelPowerGadget::GetNumberMsrs() +{ + int msrs = 0; + if(GetNumMsrs) { + int ok = GetNumMsrs(&msrs); + } + return msrs; +} + +int +IntelPowerGadget::GetCPUFrequency(int node) +{ + int frequency = 0; + if(GetIAFrequency) { + int ok = GetIAFrequency(node, &frequency); + } + return frequency; +} + +double +IntelPowerGadget::GetTdp(int node) +{ + double tdp = 0.0; + if(GetTDP) { + int ok = GetTDP(node, &tdp); + } + return tdp; +} + +int +IntelPowerGadget::GetMaxTemp(int node) +{ + int maxTemperatureC = 0; + if(GetMaxTemperature) { + int ok = GetMaxTemperature(node, &maxTemperatureC); + } + return maxTemperatureC; +} + +int +IntelPowerGadget::GetTemp(int node) +{ + int temperatureC = 0; + if(GetTemperature) { + int ok = GetTemperature(node, &temperatureC); + } + return temperatureC; +} + +int +IntelPowerGadget::TakeSample() +{ + int ok = 0; + if(ReadSample) { + ok = ReadSample(); + } + return ok; +} + +uint64_t +IntelPowerGadget::GetRdtsc() +{ + uint64_t rdtsc = 0; + if(GetRDTSC) { + int ok = GetRDTSC(&rdtsc); + } + return rdtsc; +} + +double +IntelPowerGadget::GetInterval() +{ + double interval = 0.0; + if(GetTimeInterval) { + int ok = GetTimeInterval(&interval); + } + return interval; +} + +double +IntelPowerGadget::GetCPUBaseFrequency(int node) +{ + double freq = 0.0; + if(GetBaseFrequency) { + int ok = GetBaseFrequency(node, &freq); + } + return freq; +} + +double +IntelPowerGadget::GetTotalPackagePowerInWatts() +{ + int nodes = GetNumberNodes(); + double totalPower = 0.0; + for(int i = 0; i < nodes; ++i) { + totalPower += GetPackagePowerInWatts(i); + } + return totalPower; +} + +double +IntelPowerGadget::GetPackagePowerInWatts(int node) +{ + int numResult = 0; + double result[] = {0.0, 0.0, 0.0}; + if(GetPowerData && packageMSR != -1) { + int ok = GetPowerData(node, packageMSR, result, &numResult); + } + return result[0]; +} + +double +IntelPowerGadget::GetTotalCPUPowerInWatts() +{ + int nodes = GetNumberNodes(); + double totalPower = 0.0; + for(int i = 0; i < nodes; ++i) { + totalPower += GetCPUPowerInWatts(i); + } + return totalPower; +} + +double +IntelPowerGadget::GetCPUPowerInWatts(int node) +{ + int numResult = 0; + double result[] = {0.0, 0.0, 0.0}; + if(GetPowerData && cpuMSR != -1) { + int ok = GetPowerData(node, cpuMSR, result, &numResult); + } + return result[0]; +} + +double +IntelPowerGadget::GetTotalGPUPowerInWatts() +{ + int nodes = GetNumberNodes(); + double totalPower = 0.0; + for(int i = 0; i < nodes; ++i) { + totalPower += GetGPUPowerInWatts(i); + } + return totalPower; +} + +double +IntelPowerGadget::GetGPUPowerInWatts(int node) +{ + return 0.0; +} + diff --git a/tools/profiler/IntelPowerGadget.h b/tools/profiler/IntelPowerGadget.h new file mode 100644 index 000000000000..4a24215b629e --- /dev/null +++ b/tools/profiler/IntelPowerGadget.h @@ -0,0 +1,150 @@ +/* + * Copyright 2013, Intel Corporation + * + * 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. + * + * Author: Joe Olivas + */ + +#ifndef profiler_IntelPowerGadget_h +#define profiler_IntelPowerGadget_h + +#ifdef _MSC_VER +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +#include +#endif +#include "prlink.h" + +typedef int (*IPGInitialize) (); +typedef int (*IPGGetNumNodes) (int *nNodes); +typedef int (*IPGGetNumMsrs) (int *nMsr); +typedef int (*IPGGetMsrName) (int iMsr, wchar_t *szName); +typedef int (*IPGGetMsrFunc) (int iMsr, int *pFuncID); +typedef int (*IPGReadMSR) (int iNode, unsigned int address, uint64_t *value); +typedef int (*IPGWriteMSR) (int iNode, unsigned int address, uint64_t value); +typedef int (*IPGGetIAFrequency) (int iNode, int *freqInMHz); +typedef int (*IPGGetTDP) (int iNode, double *TDP); +typedef int (*IPGGetMaxTemperature) (int iNode, int *degreeC); +typedef int (*IPGGetThresholds) (int iNode, int *degree1C, int *degree2C); +typedef int (*IPGGetTemperature) (int iNode, int *degreeC); +typedef int (*IPGReadSample) (); +typedef int (*IPGGetSysTime) (void *pSysTime); +typedef int (*IPGGetRDTSC) (uint64_t *pTSC); +typedef int (*IPGGetTimeInterval) (double *pOffset); +typedef int (*IPGGetBaseFrequency) (int iNode, double *pBaseFrequency); +typedef int (*IPGGetPowerData) (int iNode, int iMSR, double *pResult, int *nResult); +typedef int (*IPGStartLog) (wchar_t *szFileName); +typedef int (*IPGStopLog) (); + +#if defined(__x86_64__) || defined(__x86_64) || defined(_M_AMD64) +#define PG_LIBRARY_NAME "EnergyLib64" +#else +#define PG_LIBRARY_NAME "EnergyLib32" +#endif + + +class IntelPowerGadget +{ +public: + + IntelPowerGadget(); + ~IntelPowerGadget(); + + // Fails if initialization is incomplete + bool Init(); + + // Returns the number of packages on the system + int GetNumberNodes(); + + // Returns the number of MSRs being tracked + int GetNumberMsrs(); + + // Given a node, returns the temperature + int GetCPUFrequency(int); + + // Returns the TDP of the given node + double GetTdp(int); + + // Returns the maximum temperature for the given node + int GetMaxTemp(int); + + // Returns the current temperature in degrees C + // of the given node + int GetTemp(int); + + // Takes a sample of data. Must be called before + // any current data is retrieved. + int TakeSample(); + + // Gets the timestamp of the most recent sample + uint64_t GetRdtsc(); + + // returns number of seconds between the last + // two samples + double GetInterval(); + + // Returns the base frequency for the given node + double GetCPUBaseFrequency(int node); + + // Returns the combined package power for all + // packages on the system for the last sample. + double GetTotalPackagePowerInWatts(); + double GetPackagePowerInWatts(int node); + + // Returns the combined CPU power for all + // packages on the system for the last sample. + // If the reading is not available, returns 0.0 + double GetTotalCPUPowerInWatts(); + double GetCPUPowerInWatts(int node); + + // Returns the combined GPU power for all + // packages on the system for the last sample. + // If the reading is not available, returns 0.0 + double GetTotalGPUPowerInWatts(); + double GetGPUPowerInWatts(int node); + +private: + + PRLibrary *libpowergadget; + IPGInitialize Initialize; + IPGGetNumNodes GetNumNodes; + IPGGetNumMsrs GetNumMsrs; + IPGGetMsrName GetMsrName; + IPGGetMsrFunc GetMsrFunc; + IPGReadMSR ReadMSR; + IPGWriteMSR WriteMSR; + IPGGetIAFrequency GetIAFrequency; + IPGGetTDP GetTDP; + IPGGetMaxTemperature GetMaxTemperature; + IPGGetThresholds GetThresholds; + IPGGetTemperature GetTemperature; + IPGReadSample ReadSample; + IPGGetSysTime GetSysTime; + IPGGetRDTSC GetRDTSC; + IPGGetTimeInterval GetTimeInterval; + IPGGetBaseFrequency GetBaseFrequency; + IPGGetPowerData GetPowerData; + IPGStartLog StartLog; + IPGStopLog StopLog; + + int packageMSR; + int cpuMSR; + int freqMSR; + int tempMSR; +}; + +#endif // profiler_IntelPowerGadget_h diff --git a/tools/profiler/ProfileEntry.cpp b/tools/profiler/ProfileEntry.cpp index 00666850fb9e..38a218d1ed9e 100644 --- a/tools/profiler/ProfileEntry.cpp +++ b/tools/profiler/ProfileEntry.cpp @@ -390,6 +390,13 @@ void ThreadProfile::BuildJSObject(Builder& b, } } break; + case 'p': + { + if (sample) { + b.DefineProperty(sample, "power", entry.mTagFloat); + } + } + break; case 'f': { if (sample) { diff --git a/tools/profiler/TableTicker.cpp b/tools/profiler/TableTicker.cpp index fa91649642c3..e2757a2537d6 100644 --- a/tools/profiler/TableTicker.cpp +++ b/tools/profiler/TableTicker.cpp @@ -530,6 +530,9 @@ void TableTicker::InplaceTick(TickSample* sample) PseudoStack* stack = currThreadProfile.GetPseudoStack(); bool recordSample = true; +#if defined(XP_WIN) + bool powerSample = false; +#endif /* Don't process the PeudoStack's markers or honour jankOnly if we're immediately sampling the current thread. */ @@ -543,6 +546,13 @@ void TableTicker::InplaceTick(TickSample* sample) } stack->updateGeneration(currThreadProfile.GetGenerationID()); +#if defined(XP_WIN) + if (mProfilePower) { + mIntelPowerGadget->TakeSample(); + powerSample = true; + } +#endif + if (mJankOnly) { // if we are on a different event we can discard any temporary samples // we've kept around @@ -588,6 +598,12 @@ void TableTicker::InplaceTick(TickSample* sample) currThreadProfile.addTag(ProfileEntry('t', delta.ToMilliseconds())); } +#if defined(XP_WIN) + if (powerSample) { + currThreadProfile.addTag(ProfileEntry('p', mIntelPowerGadget->GetTotalPackagePowerInWatts())); + } +#endif + if (sLastFrameNumber != sFrameNumber) { currThreadProfile.addTag(ProfileEntry('f', sFrameNumber)); sLastFrameNumber = sFrameNumber; diff --git a/tools/profiler/TableTicker.h b/tools/profiler/TableTicker.h index 987a6e3d2073..a258afe3744d 100644 --- a/tools/profiler/TableTicker.h +++ b/tools/profiler/TableTicker.h @@ -6,6 +6,7 @@ #include "platform.h" #include "ProfileEntry.h" #include "mozilla/Mutex.h" +#include "IntelPowerGadget.h" static bool hasFeature(const char** aFeatures, uint32_t aFeatureCount, const char* aFeature) { @@ -50,6 +51,9 @@ class TableTicker: public Sampler { , mSaveRequested(false) , mUnwinderThread(false) , mFilterCount(aFilterCount) +#if defined(XP_WIN) + , mIntelPowerGadget(nullptr) +#endif { mUseStackWalk = hasFeature(aFeatures, aFeatureCount, "stackwalk"); @@ -57,12 +61,20 @@ class TableTicker: public Sampler { mJankOnly = hasFeature(aFeatures, aFeatureCount, "jank"); mProfileJS = hasFeature(aFeatures, aFeatureCount, "js"); mProfileJava = hasFeature(aFeatures, aFeatureCount, "java"); + mProfilePower = hasFeature(aFeatures, aFeatureCount, "power"); mProfileThreads = hasFeature(aFeatures, aFeatureCount, "threads"); mUnwinderThread = hasFeature(aFeatures, aFeatureCount, "unwinder") || sps_version2(); mAddLeafAddresses = hasFeature(aFeatures, aFeatureCount, "leaf"); mPrivacyMode = hasFeature(aFeatures, aFeatureCount, "privacy"); mAddMainThreadIO = hasFeature(aFeatures, aFeatureCount, "mainthreadio"); +#if defined(XP_WIN) + if (mProfilePower) { + mIntelPowerGadget = new IntelPowerGadget(); + mProfilePower = mIntelPowerGadget->Init(); + } +#endif + // Deep copy aThreadNameFilters mThreadNameFilters = new char*[aFilterCount]; for (uint32_t i = 0; i < aFilterCount; ++i) { @@ -104,6 +116,9 @@ class TableTicker: public Sampler { } } } +#if defined(XP_WIN) + delete mIntelPowerGadget; +#endif } void RegisterThread(ThreadInfo* aInfo) { @@ -163,6 +178,7 @@ class TableTicker: public Sampler { bool HasUnwinderThread() const { return mUnwinderThread; } bool ProfileJS() const { return mProfileJS; } bool ProfileJava() const { return mProfileJava; } + bool ProfilePower() const { return mProfilePower; } bool ProfileThreads() const { return mProfileThreads; } bool InPrivacyMode() const { return mPrivacyMode; } bool AddMainThreadIO() const { return mAddMainThreadIO; } @@ -189,6 +205,7 @@ protected: bool mProfileThreads; bool mUnwinderThread; bool mProfileJava; + bool mProfilePower; // Keep the thread filter to check against new thread that // are started while profiling @@ -196,5 +213,8 @@ protected: uint32_t mFilterCount; bool mPrivacyMode; bool mAddMainThreadIO; +#if defined(XP_WIN) + IntelPowerGadget* mIntelPowerGadget; +#endif }; diff --git a/tools/profiler/moz.build b/tools/profiler/moz.build index a42de0c9c450..a155e672a456 100644 --- a/tools/profiler/moz.build +++ b/tools/profiler/moz.build @@ -65,6 +65,7 @@ if CONFIG['MOZ_ENABLE_PROFILER_SPS']: ] elif CONFIG['OS_TARGET'] == 'WINNT': SOURCES += [ + 'IntelPowerGadget.cpp', 'platform-win32.cc', 'shared-libraries-win32.cc', ] diff --git a/tools/profiler/platform.cpp b/tools/profiler/platform.cpp index 6b094a2d04aa..ae4982def13e 100644 --- a/tools/profiler/platform.cpp +++ b/tools/profiler/platform.cpp @@ -606,6 +606,10 @@ const char** mozilla_sampler_get_features() "privacy", // Add main thread I/O to the profile "mainthreadio", +#if defined(XP_WIN) + // Add power collection + "power", +#endif NULL }; diff --git a/widget/TextEvents.h b/widget/TextEvents.h index 81719a84e78f..aa0e40ed1a0c 100644 --- a/widget/TextEvents.h +++ b/widget/TextEvents.h @@ -79,7 +79,8 @@ public: WidgetKeyboardEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget) : WidgetInputEvent(aIsTrusted, aMessage, aWidget, NS_KEY_EVENT), keyCode(0), charCode(0), - location(nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD), isChar(0), + location(nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD), + isChar(false), mIsRepeat(false), mKeyNameIndex(mozilla::KEY_NAME_INDEX_Unidentified), mNativeKeyEvent(nullptr), mUniqueId(0) @@ -101,6 +102,9 @@ public: nsTArray alternativeCharCodes; // Indicates whether the event signifies a printable character bool isChar; + // Indicates whether the event is generated by auto repeat or not. + // if this is keyup event, always false. + bool mIsRepeat; // DOM KeyboardEvent.key KeyNameIndex mKeyNameIndex; // OS-specific native event can optionally be preserved @@ -141,6 +145,7 @@ public: location = aEvent.location; alternativeCharCodes = aEvent.alternativeCharCodes; isChar = aEvent.isChar; + mIsRepeat = aEvent.mIsRepeat; mKeyNameIndex = aEvent.mKeyNameIndex; // Don't copy mNativeKeyEvent because it may be referred after its instance // is destroyed. diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index 52f1fcc6e23d..ec52628b7072 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -1623,6 +1623,10 @@ nsWindow::InitKeyEvent(WidgetKeyboardEvent& event, AndroidGeckoEvent& key, key.IsShiftPressed(), key.IsMetaPressed()); } + + event.mIsRepeat = + (event.message == NS_KEY_DOWN || event.message == NS_KEY_PRESS) && + (!!(key.Flags() & AKEY_EVENT_FLAG_LONG_PRESS) || !!key.RepeatCount()); event.location = key.DomKeyLocation(); event.time = key.Time(); diff --git a/widget/cocoa/TextInputHandler.mm b/widget/cocoa/TextInputHandler.mm index 73cf763cad69..a3066a28c1e3 100644 --- a/widget/cocoa/TextInputHandler.mm +++ b/widget/cocoa/TextInputHandler.mm @@ -929,6 +929,9 @@ TISInputSourceWrapper::InitKeyEvent(NSEvent *aNativeKeyEvent, break; } + aKeyEvent.mIsRepeat = + ([aNativeKeyEvent type] == NSKeyDown) ? [aNativeKeyEvent isARepeat] : false; + PR_LOG(gLog, PR_LOG_ALWAYS, ("%p TISInputSourceWrapper::InitKeyEvent, " "shift=%s, ctrl=%s, alt=%s, meta=%s", diff --git a/widget/gonk/nsAppShell.cpp b/widget/gonk/nsAppShell.cpp index 3c1bdb6d5312..54b59727dee5 100644 --- a/widget/gonk/nsAppShell.cpp +++ b/widget/gonk/nsAppShell.cpp @@ -219,10 +219,12 @@ static nsEventStatus sendKeyEventWithMsg(uint32_t keyCode, KeyNameIndex keyNameIndex, uint32_t msg, - uint64_t timeMs) + uint64_t timeMs, + bool isRepeat) { WidgetKeyboardEvent event(true, msg, nullptr); event.keyCode = keyCode; + event.mIsRepeat = isRepeat; event.mKeyNameIndex = keyNameIndex; event.location = nsIDOMKeyEvent::DOM_KEY_LOCATION_MOBILE; event.time = timeMs; @@ -231,25 +233,26 @@ sendKeyEventWithMsg(uint32_t keyCode, static void sendKeyEvent(uint32_t keyCode, KeyNameIndex keyNameIndex, bool down, - uint64_t timeMs) + uint64_t timeMs, bool isRepeat) { EventFlags extraFlags; nsEventStatus status = sendKeyEventWithMsg(keyCode, keyNameIndex, - down ? NS_KEY_DOWN : NS_KEY_UP, timeMs); + down ? NS_KEY_DOWN : NS_KEY_UP, timeMs, isRepeat); if (down && status != nsEventStatus_eConsumeNoDefault) { - sendKeyEventWithMsg(keyCode, keyNameIndex, NS_KEY_PRESS, timeMs); + sendKeyEventWithMsg(keyCode, keyNameIndex, NS_KEY_PRESS, timeMs, + isRepeat); } } static void -maybeSendKeyEvent(int keyCode, bool pressed, uint64_t timeMs) +maybeSendKeyEvent(int keyCode, bool pressed, uint64_t timeMs, bool isRepeat) { uint32_t DOMKeyCode = (keyCode < ArrayLength(kKeyMapping)) ? kKeyMapping[keyCode] : 0; KeyNameIndex DOMKeyNameIndex = GetKeyNameIndex(keyCode); if (DOMKeyCode || DOMKeyNameIndex != KEY_NAME_INDEX_Unidentified) { - sendKeyEvent(DOMKeyCode, DOMKeyNameIndex, pressed, timeMs); + sendKeyEvent(DOMKeyCode, DOMKeyNameIndex, pressed, timeMs, isRepeat); } else { VERBOSE_LOG("Got unknown key event code. type 0x%04x code 0x%04x value %d", keyCode, pressed); @@ -550,12 +553,17 @@ GeckoInputDispatcher::dispatchOnce() status != nsEventStatus_eConsumeNoDefault); break; } - case UserInputData::KEY_DATA: + case UserInputData::KEY_DATA: { + bool isPress = data.action == AKEY_EVENT_ACTION_DOWN; + bool isRepeat = + isPress && (data.flags & AKEY_EVENT_FLAG_LONG_PRESS); maybeSendKeyEvent(data.key.keyCode, - data.action == AKEY_EVENT_ACTION_DOWN, - data.timeMs); + isPress, + data.timeMs, + isRepeat); break; } + } } diff --git a/widget/gtk/nsGtkKeyUtils.cpp b/widget/gtk/nsGtkKeyUtils.cpp index 8e029b433555..740be04f1f5f 100644 --- a/widget/gtk/nsGtkKeyUtils.cpp +++ b/widget/gtk/nsGtkKeyUtils.cpp @@ -39,6 +39,9 @@ namespace widget { #define MOZ_MODIFIER_KEYS "MozKeymapWrapper" KeymapWrapper* KeymapWrapper::sInstance = nullptr; +guint KeymapWrapper::sLastRepeatableHardwareKeyCode = 0; +KeymapWrapper::RepeatState KeymapWrapper::sRepeatState = + KeymapWrapper::NOT_PRESSED; nsIBidiKeyboard* sBidiKeyboard = nullptr; #ifdef PR_LOGGING @@ -194,6 +197,8 @@ KeymapWrapper::Init() InitBySystemSettings(); + gdk_window_add_filter(nullptr, FilterEvents, this); + PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS, ("KeymapWrapper(%p): Init, CapsLock=0x%X, NumLock=0x%X, " "ScrollLock=0x%X, Level3=0x%X, Level5=0x%X, " @@ -210,6 +215,8 @@ KeymapWrapper::Init() void KeymapWrapper::InitXKBExtension() { + PodZero(&mKeyboardState); + int xkbMajorVer = XkbMajorVersion; int xkbMinorVer = XkbMinorVersion; if (!XkbLibraryVersion(&xkbMajorVer, &xkbMinorVer)) { @@ -241,7 +248,25 @@ KeymapWrapper::InitXKBExtension() XkbModifierStateMask, XkbModifierStateMask)) { PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS, ("KeymapWrapper(%p): InitXKBExtension failed due to failure of " - "XkbSelectEventDetails(), display=0x%p", this, display)); + "XkbSelectEventDetails() for XModifierStateMask, display=0x%p", + this, display)); + return; + } + + if (!XkbSelectEventDetails(display, XkbUseCoreKbd, XkbControlsNotify, + XkbPerKeyRepeatMask, XkbPerKeyRepeatMask)) { + PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS, + ("KeymapWrapper(%p): InitXKBExtension failed due to failure of " + "XkbSelectEventDetails() for XkbControlsNotify, display=0x%p", + this, display)); + return; + } + + if (!XGetKeyboardControl(display, &mKeyboardState)) { + PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS, + ("KeymapWrapper(%p): InitXKBExtension failed due to failure of " + "XGetKeyboardControl(), display=0x%p", + this, display)); return; } @@ -416,11 +441,83 @@ KeymapWrapper::InitBySystemSettings() KeymapWrapper::~KeymapWrapper() { + gdk_window_remove_filter(nullptr, FilterEvents, this); NS_IF_RELEASE(sBidiKeyboard); PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS, ("KeymapWrapper(%p): Destructor", this)); } +/* static */ GdkFilterReturn +KeymapWrapper::FilterEvents(GdkXEvent* aXEvent, + GdkEvent* aGdkEvent, + gpointer aData) +{ + XEvent* xEvent = static_cast(aXEvent); + switch (xEvent->type) { + case KeyPress: { + // If the key doesn't support auto repeat, ignore the event because + // even if such key (e.g., Shift) is pressed during auto repeat of + // anoter key, it doesn't stop the auto repeat. + KeymapWrapper* self = static_cast(aData); + if (!self->IsAutoRepeatableKey(xEvent->xkey.keycode)) { + break; + } + if (sRepeatState == NOT_PRESSED) { + sRepeatState = FIRST_PRESS; + } else if (sLastRepeatableHardwareKeyCode == xEvent->xkey.keycode) { + sRepeatState = REPEATING; + } else { + // If a different key is pressed while another key is pressed, + // auto repeat system repeats only the last pressed key. + // So, setting new keycode and setting repeat state as first key + // press should work fine. + sRepeatState = FIRST_PRESS; + } + sLastRepeatableHardwareKeyCode = xEvent->xkey.keycode; + break; + } + case KeyRelease: { + if (sLastRepeatableHardwareKeyCode != xEvent->xkey.keycode) { + // This case means the key release event is caused by + // a non-repeatable key such as Shift or a repeatable key that + // was pressed before sLastRepeatableHardwareKeyCode was + // pressed. + break; + } + sRepeatState = NOT_PRESSED; + break; + } + case FocusOut: { + // At moving focus, we should reset keyboard repeat state. + // Strictly, this causes incorrect behavior. However, this + // correctness must be enough for web applications. + sRepeatState = NOT_PRESSED; + break; + } + default: { + KeymapWrapper* self = static_cast(aData); + if (xEvent->type != self->mXKBBaseEventCode) { + break; + } + XkbEvent* xkbEvent = (XkbEvent*)xEvent; + if (xkbEvent->any.xkb_type != XkbControlsNotify || + !(xkbEvent->ctrls.changed_ctrls & XkbPerKeyRepeatMask)) { + break; + } + if (!XGetKeyboardControl(xkbEvent->any.display, + &self->mKeyboardState)) { + PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS, + ("KeymapWrapper(%p): FilterEvents failed due to failure " + "of XGetKeyboardControl(), display=0x%p", + self, xkbEvent->any.display)); + } + break; + } + } + + return GDK_FILTER_CONTINUE; +} + /* static */ void KeymapWrapper::OnDestroyKeymap(KeymapWrapper* aKeymapWrapper, GdkKeymap *aGdkKeymap) @@ -879,6 +976,8 @@ KeymapWrapper::InitKeyEvent(WidgetKeyboardEvent& aKeyEvent, aKeyEvent.pluginEvent = (void *)aGdkKeyEvent; aKeyEvent.time = aGdkKeyEvent->time; aKeyEvent.mNativeKeyEvent = static_cast(aGdkKeyEvent); + aKeyEvent.mIsRepeat = sRepeatState == REPEATING && + aGdkKeyEvent->hardware_keycode == sLastRepeatableHardwareKeyCode; } /* static */ uint32_t @@ -1001,6 +1100,16 @@ KeymapWrapper::IsLatinGroup(guint8 aGroup) return result; } +bool +KeymapWrapper::IsAutoRepeatableKey(guint aHardwareKeyCode) +{ + uint8_t indexOfArray = aHardwareKeyCode / 8; + MOZ_ASSERT(indexOfArray < ArrayLength(mKeyboardState.auto_repeats), + "invalid index"); + char bitMask = 1 << (aHardwareKeyCode % 8); + return (mKeyboardState.auto_repeats[indexOfArray] & bitMask) != 0; +} + /* static */ bool KeymapWrapper::IsBasicLatinLetterOrNumeral(uint32_t aCharCode) { diff --git a/widget/gtk/nsGtkKeyUtils.h b/widget/gtk/nsGtkKeyUtils.h index 7b903acc847c..734d9c5cb33e 100644 --- a/widget/gtk/nsGtkKeyUtils.h +++ b/widget/gtk/nsGtkKeyUtils.h @@ -12,6 +12,7 @@ #include "mozilla/EventForwards.h" #include +#include namespace mozilla { namespace widget { @@ -205,11 +206,37 @@ protected: */ int mXKBBaseEventCode; + /** + * Only auto_repeats[] stores valid value. If you need to use other + * members, you need to listen notification events for them. + * See a call of XkbSelectEventDetails() with XkbControlsNotify in + * InitXKBExtension(). + */ + XKeyboardState mKeyboardState; + /** * Pointer of the singleton instance. */ static KeymapWrapper* sInstance; + /** + * Auto key repeat management. + */ + static guint sLastRepeatableHardwareKeyCode; + enum RepeatState + { + NOT_PRESSED, + FIRST_PRESS, + REPEATING + }; + static RepeatState sRepeatState; + + /** + * IsAutoRepeatableKey() returns true if the key supports auto repeat. + * Otherwise, false. + */ + bool IsAutoRepeatableKey(guint aHardwareKeyCode); + /** * Signal handlers. */ @@ -295,6 +322,15 @@ protected: */ void InitKeypressEvent(WidgetKeyboardEvent& aKeyEvent, GdkEventKey* aGdkKeyEvent); + + /** + * FilterEvents() listens all events on all our windows. + * Be careful, this may make damage to performance if you add expensive + * code in this method. + */ + static GdkFilterReturn FilterEvents(GdkXEvent* aXEvent, + GdkEvent* aGdkEvent, + gpointer aData); }; } // namespace widget diff --git a/widget/gtk/nsNativeKeyBindings.cpp b/widget/gtk/nsNativeKeyBindings.cpp index d01250ea0658..f0a65c81f40d 100644 --- a/widget/gtk/nsNativeKeyBindings.cpp +++ b/widget/gtk/nsNativeKeyBindings.cpp @@ -16,6 +16,11 @@ #include #include +// X.h defines KeyPress +#ifdef KeyPress +#undef KeyPress +#endif + using namespace mozilla; using namespace mozilla::widget; diff --git a/widget/nsGUIEventIPC.h b/widget/nsGUIEventIPC.h index 982cd4c5052c..b3b0442b2776 100644 --- a/widget/nsGUIEventIPC.h +++ b/widget/nsGUIEventIPC.h @@ -270,6 +270,7 @@ struct ParamTraits WriteParam(aMsg, aParam.keyCode); WriteParam(aMsg, aParam.charCode); WriteParam(aMsg, aParam.isChar); + WriteParam(aMsg, aParam.mIsRepeat); WriteParam(aMsg, aParam.location); WriteParam(aMsg, aParam.mUniqueId); // An OS-specific native event might be attached in |mNativeKeyEvent|, but @@ -285,6 +286,7 @@ struct ParamTraits ReadParam(aMsg, aIter, &aResult->keyCode) && ReadParam(aMsg, aIter, &aResult->charCode) && ReadParam(aMsg, aIter, &aResult->isChar) && + ReadParam(aMsg, aIter, &aResult->mIsRepeat) && ReadParam(aMsg, aIter, &aResult->location) && ReadParam(aMsg, aIter, &aResult->mUniqueId)) { diff --git a/widget/os2/nsWindow.cpp b/widget/os2/nsWindow.cpp index bf159848367e..a8245bd80deb 100644 --- a/widget/os2/nsWindow.cpp +++ b/widget/os2/nsWindow.cpp @@ -2768,6 +2768,7 @@ bool nsWindow::DispatchKeyEvent(MPARAM mp1, MPARAM mp2) event.InitBasicModifiers(fsFlags & KC_CTRL, fsFlags & KC_ALT, fsFlags & KC_SHIFT, false); event.charCode = 0; + event.mIsRepeat = event.message == NS_KEY_DOWN && CHAR3FROMMP(mp1) != 0; // Check for a scroll mouse event vs. a keyboard event. The way we know // this is that the repeat count is 0 and the key is not physically down. diff --git a/widget/qt/nsWindow.cpp b/widget/qt/nsWindow.cpp index 864b4d0d7e04..12585eaf0ab6 100644 --- a/widget/qt/nsWindow.cpp +++ b/widget/qt/nsWindow.cpp @@ -169,6 +169,9 @@ InitKeyEvent(WidgetKeyboardEvent &aEvent, QKeyEvent *aQEvent) aQEvent->modifiers() & Qt::AltModifier, aQEvent->modifiers() & Qt::ShiftModifier, aQEvent->modifiers() & Qt::MetaModifier); + aEvent.mIsRepeat = + (aEvent.message == NS_KEY_DOWN || aEvent.message == NS_KEY_PRESS) && + aQEvent->isAutoRepeat(); aEvent.time = 0; if (sAltGrModifier) { diff --git a/widget/windows/GfxInfo.cpp b/widget/windows/GfxInfo.cpp index ed171f2ea61f..c5224db79c90 100644 --- a/widget/windows/GfxInfo.cpp +++ b/widget/windows/GfxInfo.cpp @@ -906,6 +906,15 @@ GfxInfo::GetGfxDriverInfo() IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMAX3000, V(6,14,10,5218)); IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMAX4500HD, V(6,14,10,4969)); + // StrechRect seems to suffer from precision issues which leads to artifacting + // during content drawing starting with at least version 6.14.10.5082 + // and going until 6.14.10.5160. See bug 919454 for more info. + APPEND_TO_DRIVER_BLOCKLIST_RANGE(DRIVER_OS_WINDOWS_XP, + const_cast(GfxDriverInfo::GetDeviceVendor(VendorIntel)), + const_cast(GfxDriverInfo::GetDeviceFamily(IntelGMAX4500HD)), + GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, + DRIVER_BETWEEN_EXCLUSIVE, V(6,14,10,5076), V(6,14,10,5160), "6.14.10.5160"); + IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMA500, V(3,0,20,3200)); IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMA900, GfxDriverInfo::allDriverVersions); IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMA950, V(7,14,10,1504)); diff --git a/widget/windows/KeyboardLayout.cpp b/widget/windows/KeyboardLayout.cpp index 282839acc724..b124e0beee71 100644 --- a/widget/windows/KeyboardLayout.cpp +++ b/widget/windows/KeyboardLayout.cpp @@ -947,6 +947,7 @@ NativeKey::InitKeyEvent(WidgetKeyboardEvent& aKeyEvent, MOZ_CRASH("Invalid event message"); } + aKeyEvent.mIsRepeat = IsRepeat(); aKeyEvent.mKeyNameIndex = mKeyNameIndex; aKeyEvent.location = GetKeyLocation(); aModKeyState.InitInputEvent(aKeyEvent); diff --git a/widget/windows/KeyboardLayout.h b/widget/windows/KeyboardLayout.h index 560b78679780..61782e139721 100644 --- a/widget/windows/KeyboardLayout.h +++ b/widget/windows/KeyboardLayout.h @@ -298,6 +298,24 @@ private: MOZ_CRASH("The default constructor of NativeKey isn't available"); } + /** + * Returns true if the key event is caused by auto repeat. + */ + bool IsRepeat() const + { + switch (mMsg.message) { + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + case WM_CHAR: + case WM_SYSCHAR: + case WM_DEADCHAR: + case WM_SYSDEADCHAR: + return ((mMsg.lParam & (1 << 30)) != 0); + default: + return false; + } + } + UINT GetScanCodeWithExtendedFlag() const; // The result is one of nsIDOMKeyEvent::DOM_KEY_LOCATION_*.