author | Sebastian Hengst <archaeopteryx@coole-files.de> |
Thu, 12 Oct 2017 23:58:31 +0200 | |
changeset 385860 | 25aad10380b10b6efa50c2b4d97245f078d870a0 |
parent 385822 | 46a75c66bb512d652dd883435afe242c22be9ac3 (current diff) |
parent 385859 | 1f4d35d137631cde34f318fac0c33421d5360dc3 (diff) |
child 385861 | 6bcef82b2f30e242d55ac951fe5c1e78a4930dfb |
child 385956 | 1b6a3e8b08935eddd2291d8c1fb83a70dd5e7e47 |
child 386027 | 782e1972037f3830bd04cf70ac529969bb796a56 |
push id | 32669 |
push user | archaeopteryx@coole-files.de |
push date | Thu, 12 Oct 2017 21:58:56 +0000 |
treeherder | mozilla-central@25aad10380b1 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge, merge |
milestone | 58.0a1 |
first release with | nightly linux32
25aad10380b1
/
58.0a1
/
20171012220111
/
files
nightly linux64
25aad10380b1
/
58.0a1
/
20171012220111
/
files
nightly mac
25aad10380b1
/
58.0a1
/
20171012220111
/
files
nightly win32
25aad10380b1
/
58.0a1
/
20171012220111
/
files
nightly win64
25aad10380b1
/
58.0a1
/
20171012220111
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
58.0a1
/
20171012220111
/
pushlog to previous
nightly linux64
58.0a1
/
20171012220111
/
pushlog to previous
nightly mac
58.0a1
/
20171012220111
/
pushlog to previous
nightly win32
58.0a1
/
20171012220111
/
pushlog to previous
nightly win64
58.0a1
/
20171012220111
/
pushlog to previous
|
build/pgo/profileserver.py | file | annotate | diff | comparison | revisions | |
modules/libpref/init/all.js | file | annotate | diff | comparison | revisions |
new file mode 100644 --- /dev/null +++ b/build/pgo/prefs_override.js @@ -0,0 +1,2 @@ +// Turn off budget throttling for the profile server +user_pref("dom.timeout.enable_budget_timer_throttling", false);
old mode 100644 new mode 100755 --- a/build/pgo/profileserver.py +++ b/build/pgo/profileserver.py @@ -40,23 +40,29 @@ if __name__ == '__main__': locations.add_host(host='127.0.0.1', port=PORT, options='primary,privileged') with TemporaryDirectory() as profilePath: # TODO: refactor this into mozprofile prefpath = os.path.join( build.topsrcdir, "testing", "profiles", "prefs_general.js") + overridepath = os.path.join( + build.topsrcdir, "build", "pgo", "prefs_override.js") + prefs = {} prefs.update(Preferences.read_prefs(prefpath)) + prefs.update(Preferences.read_prefs(overridepath)) + interpolation = {"server": "%s:%d" % httpd.httpd.server_address, "OOP": "false"} prefs = json.loads(json.dumps(prefs) % interpolation) for pref in prefs: prefs[pref] = Preferences.cast(prefs[pref]) + profile = FirefoxProfile(profile=profilePath, preferences=prefs, addons=[os.path.join( build.topsrcdir, 'tools', 'quitter', 'quitter@mozilla.org.xpi')], locations=locations) env = os.environ.copy() env["MOZ_CRASHREPORTER_NO_REPORT"] = "1"
--- a/dom/base/ChromeUtils.cpp +++ b/dom/base/ChromeUtils.cpp @@ -5,16 +5,20 @@ #include "ChromeUtils.h" #include "jsfriendapi.h" #include "WrapperFactory.h" #include "mozilla/Base64.h" #include "mozilla/BasePrincipal.h" +#include "mozilla/TimeStamp.h" +#include "mozilla/dom/IdleDeadline.h" +#include "mozilla/dom/WindowBinding.h" // For IdleRequestCallback/Options +#include "nsThreadUtils.h" namespace mozilla { namespace dom { /* static */ void ThreadSafeChromeUtils::NondeterministicGetWeakMapKeys(GlobalObject& aGlobal, JS::Handle<JS::Value> aMap, JS::MutableHandle<JS::Value> aRetval, @@ -259,16 +263,119 @@ ChromeUtils::ShallowClone(GlobalObject& if (aTarget && !JS_WrapObject(cx, &obj)) { return; } cleanup.release(); aRetval.set(obj); } +namespace { + class IdleDispatchRunnable final : public IdleRunnable + , public nsITimerCallback + { + public: + NS_DECL_ISUPPORTS_INHERITED + + IdleDispatchRunnable(nsIGlobalObject* aParent, + IdleRequestCallback& aCallback) + : IdleRunnable("ChromeUtils::IdleDispatch") + , mCallback(&aCallback) + , mParent(aParent) + {} + + NS_IMETHOD Run() override + { + if (mCallback) { + CancelTimer(); + + auto deadline = mDeadline - TimeStamp::ProcessCreation(); + + ErrorResult rv; + RefPtr<IdleDeadline> idleDeadline = + new IdleDeadline(mParent, mTimedOut, deadline.ToMilliseconds()); + + mCallback->Call(*idleDeadline, rv, "ChromeUtils::IdleDispatch handler"); + mCallback = nullptr; + mParent = nullptr; + + rv.SuppressException(); + return rv.StealNSResult(); + } + return NS_OK; + } + + void SetDeadline(TimeStamp aDeadline) override + { + mDeadline = aDeadline; + } + + NS_IMETHOD Notify(nsITimer* aTimer) override + { + mTimedOut = true; + SetDeadline(TimeStamp::Now()); + return Run(); + } + + void SetTimer(uint32_t aDelay, nsIEventTarget* aTarget) override + { + MOZ_ASSERT(aTarget); + MOZ_ASSERT(!mTimer); + mTimer = do_CreateInstance(NS_TIMER_CONTRACTID); + if (mTimer) { + mTimer->SetTarget(aTarget); + mTimer->InitWithCallback(this, aDelay, nsITimer::TYPE_ONE_SHOT); + } + } + + protected: + virtual ~IdleDispatchRunnable() + { + CancelTimer(); + } + + private: + void CancelTimer() + { + if (mTimer) { + mTimer->Cancel(); + mTimer = nullptr; + } + } + + RefPtr<IdleRequestCallback> mCallback; + nsCOMPtr<nsIGlobalObject> mParent; + + nsCOMPtr<nsITimer> mTimer; + + TimeStamp mDeadline{}; + bool mTimedOut = false; + }; + + NS_IMPL_ISUPPORTS_INHERITED(IdleDispatchRunnable, IdleRunnable, nsITimerCallback) +} // anonymous namespace + +/* static */ void +ChromeUtils::IdleDispatch(const GlobalObject& aGlobal, + IdleRequestCallback& aCallback, + const IdleRequestOptions& aOptions, + ErrorResult& aRv) +{ + nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports()); + MOZ_ASSERT(global); + + auto runnable = MakeRefPtr<IdleDispatchRunnable>(global, aCallback); + + if (aOptions.mTimeout.WasPassed()) { + aRv = NS_IdleDispatchToCurrentThread(runnable.forget(), aOptions.mTimeout.Value()); + } else { + aRv = NS_IdleDispatchToCurrentThread(runnable.forget()); + } +} + /* static */ void ChromeUtils::OriginAttributesToSuffix(dom::GlobalObject& aGlobal, const dom::OriginAttributesDictionary& aAttrs, nsCString& aSuffix) { OriginAttributes attrs(aAttrs); attrs.CreateSuffix(aSuffix);
--- a/dom/base/ChromeUtils.h +++ b/dom/base/ChromeUtils.h @@ -16,16 +16,18 @@ namespace mozilla { namespace devtools { class HeapSnapshot; } // namespace devtools namespace dom { class ArrayBufferViewOrArrayBuffer; +class IdleRequestCallback; +struct IdleRequestOptions; class PrecompiledScript; class Promise; class ThreadSafeChromeUtils { private: // Implemented in devtools/shared/heapsnapshot/HeapSnapshot.cpp static void SaveHeapSnapshotShared(GlobalObject& global, @@ -140,14 +142,19 @@ public: bool aUnwrap, nsAString& aRetval); static void ShallowClone(GlobalObject& aGlobal, JS::HandleObject aObj, JS::HandleObject aTarget, JS::MutableHandleObject aRetval, ErrorResult& aRv); + + static void IdleDispatch(const GlobalObject& global, + IdleRequestCallback& callback, + const IdleRequestOptions& options, + ErrorResult& aRv); }; } // namespace dom } // namespace mozilla #endif // mozilla_dom_ChromeUtils__
--- a/dom/base/IdleDeadline.cpp +++ b/dom/base/IdleDeadline.cpp @@ -12,30 +12,41 @@ #include "nsCOMPtr.h" #include "nsCycleCollectionParticipant.h" #include "nsDOMNavigationTiming.h" #include "nsPIDOMWindow.h" namespace mozilla { namespace dom { -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(IdleDeadline, mWindow) +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(IdleDeadline, mWindow, mGlobal) NS_IMPL_CYCLE_COLLECTING_ADDREF(IdleDeadline) NS_IMPL_CYCLE_COLLECTING_RELEASE(IdleDeadline) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleDeadline) NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_END IdleDeadline::IdleDeadline(nsPIDOMWindowInner* aWindow, bool aDidTimeout, DOMHighResTimeStamp aDeadline) : mWindow(aWindow) , mDidTimeout(aDidTimeout) , mDeadline(aDeadline) { + bool hasHadSHO; + mGlobal = aWindow->GetDoc()->GetScriptHandlingObject(hasHadSHO); +} + +IdleDeadline::IdleDeadline(nsIGlobalObject* aGlobal, bool aDidTimeout, + DOMHighResTimeStamp aDeadline) + : mWindow(nullptr) + , mGlobal(aGlobal) + , mDidTimeout(aDidTimeout) + , mDeadline(aDeadline) +{ } IdleDeadline::~IdleDeadline() { } JSObject* IdleDeadline::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) @@ -45,24 +56,31 @@ IdleDeadline::WrapObject(JSContext* aCx, DOMHighResTimeStamp IdleDeadline::TimeRemaining() { if (mDidTimeout) { return 0.0; } - RefPtr<Performance> performance = mWindow->GetPerformance(); - if (!performance) { - // If there is no performance object the window is partially torn - // down, so we can safely say that there is no time remaining. - return 0.0; + if (mWindow) { + RefPtr<Performance> performance = mWindow->GetPerformance(); + if (!performance) { + // If there is no performance object the window is partially torn + // down, so we can safely say that there is no time remaining. + return 0.0; + } + + return std::max(mDeadline - performance->Now(), 0.0); } - return std::max(mDeadline - performance->Now(), 0.0); + // If there's no window, we're in a system scope, and can just use + // a high-resolution TimeStamp::Now(); + auto timestamp = TimeStamp::Now() - TimeStamp::ProcessCreation(); + return std::max(mDeadline - timestamp.ToMilliseconds(), 0.0); } bool IdleDeadline::DidTimeout() const { return mDidTimeout; }
--- a/dom/base/IdleDeadline.h +++ b/dom/base/IdleDeadline.h @@ -12,44 +12,49 @@ #include "mozilla/ErrorResult.h" #include "mozilla/Maybe.h" #include "mozilla/dom/BindingDeclarations.h" #include "nsCOMPtr.h" #include "nsCycleCollectionParticipant.h" #include "nsDOMNavigationTiming.h" #include "nsWrapperCache.h" +class nsIGlobalObject; class nsPIDOMWindowInner; namespace mozilla { namespace dom { class IdleDeadline final : public nsISupports , public nsWrapperCache { public: IdleDeadline(nsPIDOMWindowInner* aWindow, bool aDidTimeout, DOMHighResTimeStamp aDeadline); - nsPIDOMWindowInner* GetParentObject() const { return mWindow; } + IdleDeadline(nsIGlobalObject* aGlobal, bool aDidTimeout, + DOMHighResTimeStamp aDeadline); + + nsIGlobalObject* GetParentObject() const { return mGlobal; } virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; DOMHighResTimeStamp TimeRemaining(); bool DidTimeout() const; NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IdleDeadline) private: ~IdleDeadline(); nsCOMPtr<nsPIDOMWindowInner> mWindow; + nsCOMPtr<nsIGlobalObject> mGlobal; const bool mDidTimeout; const DOMHighResTimeStamp mDeadline; }; } // namespace dom } // namespace mozilla #endif // mozilla_dom_IdleDeadline_h
--- a/dom/base/WebSocket.cpp +++ b/dom/base/WebSocket.cpp @@ -1661,28 +1661,27 @@ WebSocketImpl::Init(JSContext* aCx, nsCOMPtr<nsIGlobalObject> globalObject(GetEntryGlobal()); if (globalObject) { principal = globalObject->PrincipalOrNull(); } nsCOMPtr<nsPIDOMWindowInner> innerWindow; while (true) { - if (principal) { - bool isNullPrincipal = true; - isNullPrincipal = principal->GetIsNullPrincipal(); - if (isNullPrincipal || nsContentUtils::IsSystemPrincipal(principal)) { - break; - } + if (principal && !principal->GetIsNullPrincipal()) { + break; } if (!innerWindow) { innerWindow = do_QueryInterface(globalObject); - if (NS_WARN_IF(!innerWindow)) { - return NS_ERROR_DOM_SECURITY_ERR; + if (!innerWindow) { + // If we are in a XPConnect sandbox or in a JS component, + // innerWindow will be null. There is nothing on top of this to be + // considered. + break; } } nsCOMPtr<nsPIDOMWindowOuter> parentWindow = innerWindow->GetScriptableParent(); if (NS_WARN_IF(!parentWindow)) { return NS_ERROR_DOM_SECURITY_ERR; }
--- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -8151,34 +8151,34 @@ nsGlobalWindow::PrintOuter(ErrorResult& if (printSettingsService) { bool printSettingsAreGlobal = Preferences::GetBool("print.use_global_printsettings", false); if (printSettingsAreGlobal) { printSettingsService->GetGlobalPrintSettings(getter_AddRefs(printSettings)); nsAutoString printerName; - printSettings->GetPrinterName(getter_Copies(printerName)); + printSettings->GetPrinterName(printerName); bool shouldGetDefaultPrinterName = printerName.IsEmpty(); #ifdef MOZ_X11 // In Linux, GTK backend does not support per printer settings. // Calling GetDefaultPrinterName causes a sandbox violation (see Bug 1329216). // The printer name is not needed anywhere else on Linux before it gets to the parent. // In the parent, we will then query the default printer name if no name is set. // Unless we are in the parent, we will skip this part. if (!XRE_IsParentProcess()) { shouldGetDefaultPrinterName = false; } #endif if (shouldGetDefaultPrinterName) { - printSettingsService->GetDefaultPrinterName(getter_Copies(printerName)); - printSettings->SetPrinterName(printerName.get()); + printSettingsService->GetDefaultPrinterName(printerName); + printSettings->SetPrinterName(printerName); } - printSettingsService->InitPrintSettingsFromPrinter(printerName.get(), + printSettingsService->InitPrintSettingsFromPrinter(printerName, printSettings); printSettingsService->InitPrintSettingsFromPrefs(printSettings, true, nsIPrintSettings::kInitSaveAll); } else { printSettingsService->GetNewPrintSettings(getter_AddRefs(printSettings)); }
--- a/dom/base/nsNodeUtils.cpp +++ b/dom/base/nsNodeUtils.cpp @@ -611,16 +611,19 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNod MOZ_ASSERT(IsDOMObject(wrapper)); JSAutoCompartment ac(cx, wrapper); ReparentWrapper(cx, wrapper, aError); if (aError.Failed()) { if (wasRegistered) { aNode->OwnerDoc()->UnregisterActivityObserver(aNode->AsElement()); } aNode->mNodeInfo.swap(newNodeInfo); + if (elem) { + elem->NodeInfoChanged(newDoc); + } if (wasRegistered) { aNode->OwnerDoc()->RegisterActivityObserver(aNode->AsElement()); } return nullptr; } } } }
new file mode 100644 --- /dev/null +++ b/dom/base/test/iframe_webSocket_sandbox.html @@ -0,0 +1,65 @@ +<html><body> +<iframe id="frame" sandbox="allow-scripts allow-popups"></iframe> +<script type="application/javascript;version=1.8"> +onmessage = function(e) { + parent.postMessage(e.data, '*'); +} + +var ifr = document.getElementById('frame'); + +if (location.search == '?nested') { + var url = new URL(location); + url.search = ""; + ifr.src = url.href; +} else if (location.search == '?popup') { + var url = new URL(location); + url.search = "?opener"; + + ifr.srcdoc = "<html><script>" + + "window.open('" + url.href + "', 'foobar');" + + "onmessage = function(e) { " + + " parent.postMessage(e.data, '*'); " + + "}" + + "</scr" + "ipt></html>"; +} else if (location.search == '?opener') { + try{ + var socket = new WebSocket('ws://mochi.test:8888/tests/dom/base/test/file_websocket_basic'); + socket.onerror = function(e) { + opener.postMessage('WS onerror', '*'); + close(); + }; + socket.onopen = function(event) { + opener.postMessage('WS onopen', '*'); + close(); + }; + } catch(e) { + if (e.name == 'SecurityError') { + opener.postMessage('WS Throws!', '*'); + } else { + opener.postMessage('WS Throws something else!', '*'); + } + close(); + } +} else { + ifr.srcdoc = ` + <html><script> + try{ + var socket = new WebSocket('ws://mochi.test:8888/tests/dom/base/test/file_websocket_basic'); + socket.onerror = function(e) { + parent.postMessage('WS onerror', '*'); + }; + socket.onopen = function(event) { + parent.postMessage('WS onopen', '*'); + }; + } catch(e) { + if (e.name == 'SecurityError') { + parent.postMessage('WS Throws!', '*'); + } else { + parent.postMessage('WS Throws something else!', '*'); + } + } + </scr`+`ipt> + </html>`; +} +</script> +</body></html>
--- a/dom/base/test/mochitest.ini +++ b/dom/base/test/mochitest.ini @@ -801,16 +801,19 @@ tags = audiochannel [test_webaudioNotificationStopOnNavigation.html] tags = audiochannel [test_websocket_basic.html] skip-if = toolkit == 'android' [test_websocket_hello.html] skip-if = toolkit == 'android' [test_websocket_permessage_deflate.html] skip-if = toolkit == 'android' +[test_webSocket_sandbox.html] +skip-if = toolkit == 'android' +support-files = iframe_webSocket_sandbox.html [test_websocket1.html] skip-if = toolkit == 'android' [test_websocket2.html] skip-if = toolkit == 'android' [test_websocket3.html] skip-if = toolkit == 'android' [test_websocket4.html] skip-if = toolkit == 'android'
--- a/dom/base/test/test_bug1222633.html +++ b/dom/base/test/test_bug1222633.html @@ -83,18 +83,20 @@ function testChangePrefetchToPreload(url }; const SJS_PATH = window.location.pathname.replace(/[^/]+$/, "file_bug1268962.sjs"); const SAME_ORIGIN = "http://mochi.test:8888" + SJS_PATH; const CROSS_ORIGIN = "http://example.com" + SJS_PATH; SimpleTest.waitForExplicitFinish(); +SpecialPowers.pushPrefEnv({"set": [["network.preload", true]]}) + // test same origin -testPreloadEvent(SAME_ORIGIN + "?statusCode=200&cacheControl=no-cache", false, false) +.then(() => testPreloadEvent(SAME_ORIGIN + "?statusCode=200&cacheControl=no-cache", false, false)) .then(() => testPreloadEvent(SAME_ORIGIN + "?statusCode=404&cacheControl=no-cache", false, false)) .then(() => testPreloadEvent(SAME_ORIGIN + "?statusCode=200&cacheControl=max-age%3D120", false, true)) .then(() => testPreloadEvent(SAME_ORIGIN + "?statusCode=404&cacheControl=max-age%3D120", false, false)) // test cross origin without CORS .then(() => testPreloadEvent(CROSS_ORIGIN + "?statusCode=200&cacheControl=no-cache", false, true)) .then(() => testPreloadEvent(CROSS_ORIGIN + "?statusCode=404&cacheControl=no-cache", false, true)) .then(() => testPreloadEvent(CROSS_ORIGIN + "?statusCode=200&cacheControl=max-age%3D120", false, true))
--- a/dom/base/test/test_bug1222633_link_update.html +++ b/dom/base/test/test_bug1222633_link_update.html @@ -117,18 +117,20 @@ function testPreloadEventSetCrossOrigin( } const SJS_PATH = window.location.pathname.replace(/[^/]+$/, "file_bug1268962.sjs"); const SAME_ORIGIN = "http://mochi.test:8888" + SJS_PATH; const CROSS_ORIGIN = "http://example.com" + SJS_PATH; SimpleTest.waitForExplicitFinish(); +SpecialPowers.pushPrefEnv({"set": [["network.preload", true]]}) + // Test changing as parameter from a wrong to a correct one. -testPreloadEventAsAttributeChange(SAME_ORIGIN + "?statusCode=200&cacheControl=max-age%3D120") +.then(() => testPreloadEventAsAttributeChange(SAME_ORIGIN + "?statusCode=200&cacheControl=max-age%3D120")) // Test changing type parameter from a wrong to a correct one for given as parameter. .then(() => testPreloadEventAttributeChange(SAME_ORIGIN + "?statusCode=200&cacheControl=max-age%3D120", "type", "text/vtt", "image/png", false, true)) // Test changing media parameter from a wrong to a correct one. .then(() => testPreloadEventAttributeChange(SAME_ORIGIN + "?statusCode=200&cacheControl=max-age%3D120", "media", "foo", "all", false, true)) // Test changing crossorigin parameter. .then(() => testPreloadEventSetCrossOrigin(CROSS_ORIGIN + "?statusCode=404&cacheControl=max-age%3D120&allowOrigin=*")) .catch((err) => ok(false, "promise rejected: " + err))
new file mode 100644 --- /dev/null +++ b/dom/base/test/test_webSocket_sandbox.html @@ -0,0 +1,34 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Bug 1252751</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<div id="container"></div> +<iframe id="frame"></iframe> +<script type="application/javascript;version=1.8"> +var urls = [ "https://example.com/tests/dom/base/test/iframe_webSocket_sandbox.html", + "https://example.com/tests/dom/base/test/iframe_webSocket_sandbox.html?nested", + "https://example.com/tests/dom/base/test/iframe_webSocket_sandbox.html?popup" ]; + +onmessage = function(e) { + is(e.data, "WS Throws!", "ws://URI cannot be used by a https iframe"); + runTest(); +} + +function runTest() { + if (!urls.length) { + SimpleTest.finish(); + return; + } + + document.getElementById("frame").src = urls.shift(); +} + +SimpleTest.waitForExplicitFinish(); +runTest(); +</script> +</body> +</html>
--- a/dom/html/HTMLLinkElement.cpp +++ b/dom/html/HTMLLinkElement.cpp @@ -386,21 +386,38 @@ static const DOMTokenListSupportedToken "alternate", "preconnect", "icon", "search", "preload", nullptr }; +static const DOMTokenListSupportedToken sSupportedRelValuesNoPreload[] = { + // Keep this in sync with ToLinkMask in nsStyleLinkElement.cpp. + // "import" must come first because it's conditional. + "prefetch", + "dns-prefetch", + "stylesheet", + "next", + "alternate", + "preconnect", + "icon", + "search", + nullptr +}; nsDOMTokenList* HTMLLinkElement::RelList() { if (!mRelList) { - mRelList = new nsDOMTokenList(this, nsGkAtoms::rel, sSupportedRelValues); + if (Preferences::GetBool("network.preload")) { + mRelList = new nsDOMTokenList(this, nsGkAtoms::rel, sSupportedRelValues); + } else { + mRelList = new nsDOMTokenList(this, nsGkAtoms::rel, sSupportedRelValuesNoPreload); + } } return mRelList; } already_AddRefed<nsIURI> HTMLLinkElement::GetHrefURI() const { return GetHrefURIForAnchors();
--- a/dom/webauthn/WebAuthnManager.cpp +++ b/dom/webauthn/WebAuthnManager.cpp @@ -229,16 +229,17 @@ WebAuthnManager::MaybeClearTransaction() RefPtr<WebAuthnTransactionChild> c; mChild.swap(c); c->Send__delete__(c); } } WebAuthnManager::~WebAuthnManager() { + MOZ_ASSERT(NS_IsMainThread()); MaybeClearTransaction(); } RefPtr<WebAuthnManager::BackgroundActorPromise> WebAuthnManager::GetOrCreateBackgroundActor() { MOZ_ASSERT(NS_IsMainThread()); @@ -258,16 +259,17 @@ WebAuthnManager::GetOrCreateBackgroundAc return promise; } //static WebAuthnManager* WebAuthnManager::GetOrCreate() { MOZ_ASSERT(NS_IsMainThread()); + if (gWebAuthnManager) { return gWebAuthnManager; } gWebAuthnManager = new WebAuthnManager(); ClearOnShutdown(&gWebAuthnManager); return gWebAuthnManager; } @@ -279,25 +281,26 @@ WebAuthnManager::Get() MOZ_ASSERT(NS_IsMainThread()); return gWebAuthnManager; } already_AddRefed<Promise> WebAuthnManager::MakeCredential(nsPIDOMWindowInner* aParent, const MakePublicKeyCredentialOptions& aOptions) { + MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aParent); MaybeClearTransaction(); nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aParent); ErrorResult rv; RefPtr<Promise> promise = Promise::Create(global, rv); - if(rv.Failed()) { + if (rv.Failed()) { return nullptr; } nsString origin; nsCString rpId; rv = GetOrigin(aParent, origin, rpId); if (NS_WARN_IF(rv.Failed())) { promise->MaybeReject(rv); @@ -511,48 +514,55 @@ WebAuthnManager::MakeCredential(nsPIDOMW mInfo = Some(info); ListenForVisibilityEvents(aParent, this); return promise.forget(); } void WebAuthnManager::StartRegister() { + MOZ_ASSERT(NS_IsMainThread()); + if (mChild) { mChild->SendRequestRegister(mInfo.ref()); } } void WebAuthnManager::StartSign() { + MOZ_ASSERT(NS_IsMainThread()); + if (mChild) { mChild->SendRequestSign(mInfo.ref()); } } void WebAuthnManager::StartCancel() { + MOZ_ASSERT(NS_IsMainThread()); + if (mChild) { mChild->SendRequestCancel(); } } already_AddRefed<Promise> WebAuthnManager::GetAssertion(nsPIDOMWindowInner* aParent, const PublicKeyCredentialRequestOptions& aOptions) { + MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aParent); MaybeClearTransaction(); nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aParent); ErrorResult rv; RefPtr<Promise> promise = Promise::Create(global, rv); - if(rv.Failed()) { + if (rv.Failed()) { return nullptr; } nsString origin; nsCString rpId; rv = GetOrigin(aParent, origin, rpId); if (NS_WARN_IF(rv.Failed())) { promise->MaybeReject(rv); @@ -685,16 +695,17 @@ WebAuthnManager::GetAssertion(nsPIDOMWin ListenForVisibilityEvents(aParent, this); return promise.forget(); } void WebAuthnManager::FinishMakeCredential(nsTArray<uint8_t>& aRegBuffer) { + MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mTransactionPromise); MOZ_ASSERT(mInfo.isSome()); CryptoBuffer regData; if (NS_WARN_IF(!regData.Assign(aRegBuffer.Elements(), aRegBuffer.Length()))) { Cancel(NS_ERROR_OUT_OF_MEMORY); return; } @@ -808,16 +819,17 @@ WebAuthnManager::FinishMakeCredential(ns mTransactionPromise->MaybeResolve(credential); MaybeClearTransaction(); } void WebAuthnManager::FinishGetAssertion(nsTArray<uint8_t>& aCredentialId, nsTArray<uint8_t>& aSigBuffer) { + MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mTransactionPromise); MOZ_ASSERT(mInfo.isSome()); CryptoBuffer tokenSignatureData; if (NS_WARN_IF(!tokenSignatureData.Assign(aSigBuffer.Elements(), aSigBuffer.Length()))) { Cancel(NS_ERROR_OUT_OF_MEMORY); return; @@ -900,16 +912,17 @@ WebAuthnManager::Cancel(const nsresult& } MaybeClearTransaction(); } NS_IMETHODIMP WebAuthnManager::HandleEvent(nsIDOMEvent* aEvent) { + MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aEvent); nsAutoString type; aEvent->GetType(type); if (!type.Equals(kVisibilityChange)) { return NS_ERROR_FAILURE; } @@ -949,19 +962,21 @@ WebAuthnManager::ActorCreated(PBackgroun MOZ_ASSERT(constructedMgr == mgr); mChild = mgr.forget(); mPBackgroundCreationPromise.Resolve(NS_OK, __func__); } void WebAuthnManager::ActorDestroyed() { + MOZ_ASSERT(NS_IsMainThread()); mChild = nullptr; } void WebAuthnManager::ActorFailed() { + MOZ_ASSERT(NS_IsMainThread()); MOZ_CRASH("We shouldn't be here!"); } } }
--- a/dom/webidl/ChromeUtils.webidl +++ b/dom/webidl/ChromeUtils.webidl @@ -96,16 +96,25 @@ interface ChromeUtils : ThreadSafeChrome * target compartment (or the caller compartment if no target is provided). * Property values themeselves are not cloned. * * Ignores non-enumerable properties, properties on prototypes, and properties * with getters or setters. */ [Throws] static object shallowClone(object obj, optional object? target = null); + + /** + * Dispatches the given callback to the main thread when it would be + * otherwise idle. Similar to Window.requestIdleCallback, but not bound to a + * particular DOM windw. + */ + [Throws] + static void idleDispatch(IdleRequestCallback callback, + optional IdleRequestOptions options); }; /** * Used by principals and the script security manager to represent origin * attributes. The first dictionary is designed to contain the full set of * OriginAttributes, the second is used for pattern-matching (i.e. does this * OriginAttributesDictionary match the non-empty attributes in this pattern). *
--- a/dom/webidl/IdleDeadline.webidl +++ b/dom/webidl/IdleDeadline.webidl @@ -2,13 +2,14 @@ /* 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/. * * The origin of this IDL file is: * https://w3c.github.io/requestidlecallback/ */ -[Func="nsGlobalWindow::IsRequestIdleCallbackEnabled"] +[Exposed=(Window,System), + Func="nsGlobalWindow::IsRequestIdleCallbackEnabled"] interface IdleDeadline { DOMHighResTimeStamp timeRemaining(); readonly attribute boolean didTimeout; };
new file mode 100644 --- /dev/null +++ b/dom/workers/test/crashtests/1348882.html @@ -0,0 +1,18 @@ +<!DOCTYPE> +<html> +<head> +<meta charset="UTF-8"> +<script> +function boom() { + let r = new Request("#a#a"); + setTimeout(function(){ + r.formData(); + setTimeout(function(){ + r.blob(); + }, 0); + }, 0); +} +addEventListener("DOMContentLoaded", boom); +</script> +</head> +</html>
--- a/dom/workers/test/crashtests/crashtests.list +++ b/dom/workers/test/crashtests/crashtests.list @@ -1,5 +1,6 @@ load 779707.html load 943516.html load 1153636.html load 1158031.html load 1228456.html +load 1348882.html
--- a/dom/xul/templates/nsIXULTemplateBuilder.idl +++ b/dom/xul/templates/nsIXULTemplateBuilder.idl @@ -1,25 +1,29 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "domstubs.idl" -interface nsAtom; // not a real interface; used in [noscript] methods only interface nsIContent; interface nsIXULBuilderListener; interface nsIXULTemplateResult; interface nsIXULTemplateRuleFilter; interface nsIXULTemplateQueryProcessor; interface nsIRDFResource; interface nsIRDFCompositeDataSource; interface nsIDOMDataTransfer; +%{C++ +class nsAtom; +%} +[ptr] native nsAtomPtr(nsAtom); + /** * A template builder, given an input source of data, a template, and a * reference point, generates a list of results from the input, and copies * part of the template for each result. Templates may generate content * recursively, using the same template, but with the previous iteration's * results as the reference point. As an example, for an XML datasource the * initial reference point would be a specific node in the DOM tree and a * template might generate a list of all child nodes. For the next iteration, @@ -263,17 +267,17 @@ interface nsIXULTemplateBuilder : nsISup * intended to be called only by the RDF query processor. If aTag is set, * the content must have a tag name that matches aTag. aTag may be ignored * for builders that don't generate real DOM content. * * @param aNode node to check * @param aTag tag that must match */ [noscript] boolean hasGeneratedContent(in nsIRDFResource aNode, - in nsAtom aTag); + in nsAtomPtr aTag); /** * Adds a rule filter for a given rule, which may be used for specialized * rule filtering. Any existing filter on the rule is removed. The default * conditions specified inside the <rule> tag are applied before the * rule filter is applied, meaning that the filter may be used to further * filter out results but not reaccept results that have already been * rejected.
--- a/dom/xul/templates/nsIXULTemplateQueryProcessor.idl +++ b/dom/xul/templates/nsIXULTemplateQueryProcessor.idl @@ -1,22 +1,26 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "domstubs.idl" -interface nsAtom; // not a real interface; used in [noscript] methods only interface nsIArray; interface nsISimpleEnumerator; interface nsIXULTemplateResult; interface nsIXULTemplateRuleFilter; interface nsIXULTemplateBuilder; +%{C++ +class nsAtom; +%} +[ptr] native nsAtomPtr(nsAtom); + /** * A query processor takes a template query and generates results for it given * a datasource and a reference point. There is a one-to-one relationship * between a template builder and a query processor. The template builder * creates the query processor, and there is no other means to retrieve it. * * A template query is the contents inside a <query> element within the * template. The actual syntax is opaque to the template builder and defined @@ -159,18 +163,18 @@ interface nsIXULTemplateQueryProcessor : * @param aQuery <query> node to compile * @param aRefVariable the reference variable * @param aMemberVariable the member variable * * @returns a compiled query object */ [noscript] nsISupports compileQuery(in nsIXULTemplateBuilder aBuilder, in nsIDOMNode aQuery, - in nsAtom aRefVariable, - in nsAtom aMemberVariable); + in nsAtomPtr aRefVariable, + in nsAtomPtr aMemberVariable); /** * Generate the results of a query and return them in an enumerator. The * enumerator must contain nsIXULTemplateResult objects. If there are no * results, an empty enumerator must be returned. * * The datasource will be the same as the one passed to the earlier * initializeForBuilding method. The context reference (aRef) is a reference @@ -218,18 +222,18 @@ interface nsIXULTemplateQueryProcessor : * the syntax '+2' to mean add two to the reference. * * @param aRuleNode rule to add the binding to * @param aVar variable that will be bound * @param aRef variable that holds reference value * @param aExpr expression used to compute the value to assign */ [noscript] void addBinding(in nsIDOMNode aRuleNode, - in nsAtom aVar, - in nsAtom aRef, + in nsAtomPtr aVar, + in nsAtomPtr aRef, in AString aExpr); /** * Translate a ref attribute string into a result. This is used as the * reference point by the template builder when generating the first level * of content. For recursive generation, the result from the parent * generation phase will be used directly as the reference so a translation * is not needed. This allows all levels to be generated using objects that @@ -266,11 +270,11 @@ interface nsIXULTemplateQueryProcessor : * @param aLeft the left result to compare * @param aRight the right result to compare * @param aVar variable to compare * * @param returns -1 if less, 0 if equal, or 1 if greater */ [noscript] int32_t compareResults(in nsIXULTemplateResult aLeft, in nsIXULTemplateResult aRight, - in nsAtom aVar, + in nsAtomPtr aVar, in unsigned long aSortHints); };
--- a/dom/xul/templates/nsIXULTemplateResult.idl +++ b/dom/xul/templates/nsIXULTemplateResult.idl @@ -1,19 +1,23 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsISupports.idl" -interface nsAtom; // not a real interface; used in [noscript] methods only interface nsIDOMNode; interface nsIRDFResource; +%{C++ +class nsAtom; +%} +[ptr] native nsAtomPtr(nsAtom); + /** * A single result generated from a template query. Each result is identified * by an id, which must be unique within the set of results produced from a * query. The result may optionally be identified by an RDF resource. * * Generally, the result and its id will be able to uniquely identify a node * in the source data, such as an RDF or XML node. In other contexts, such as * a database query, a result would represent a particular record. @@ -75,30 +79,30 @@ interface nsIXULTemplateResult : nsISupp * attribute within the action body, it will be replaced with the result * of this method. The question mark is considered part of the variable * name, thus aVar should be ?name and not simply name. * * @param aVar the variable to look up * * @return the value for the variable or a null string if it has no value */ - [noscript] AString getBindingFor(in nsAtom aVar); + [noscript] AString getBindingFor(in nsAtomPtr aVar); /** * Get an object value for a variable such as ?name for this result. * * This method may return null for a variable, even if getBindingFor returns * a non-null value for the same variable. This method is provided as a * convenience when sorting results. * * @param aVar the variable to look up * * @return the value for the variable or null if it has no value */ - [noscript] nsISupports getBindingObjectFor(in nsAtom aVar); + [noscript] nsISupports getBindingObjectFor(in nsAtomPtr aVar); /** * Indicate that a particular rule of a query has matched and that output * will be generated for it. Both the query as compiled by the query * processor's compileQuery method and the XUL <rule> element are supplied. * The query must always be one that was compiled by the query processor * that created this result. The <rule> element must always be a child of * the <query> element that was used to compile the query.
new file mode 100644 --- /dev/null +++ b/editor/libeditor/crashtests/1383747.html @@ -0,0 +1,15 @@ +<html> + <head> + <script> + try { o1 = window.getSelection() } catch(e) { } + try { o2 = document.createElement('map') } catch(e) { }; + try { o3 = document.createElement('select') } catch(e) { } + try { document.documentElement.appendChild(o2) } catch(e) { }; + try { o2.contentEditable = 'true' } catch(e) { }; + try { o2.offsetTop } catch(e) { }; + try { document.replaceChild(document.implementation.createHTMLDocument().documentElement, document.documentElement); } catch(e) { } + try { document.documentElement.appendChild(o3) } catch(e) { } + try { o1.modify('extend', 'forward', 'word') } catch(e) { } + </script> + </head> +</html> \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/editor/libeditor/crashtests/1383763.html @@ -0,0 +1,17 @@ +<xsl:stylesheet id='xsl'> +<script id='script'> +try { o1 = document.createElement('table') } catch(e) { } +try { o3 = document.createElement('area') } catch(e) { } +try { o4 = document.createElement('script'); } catch(e) { } +try { o5 = document.getSelection() } catch(e) { } +try { document.implementation.createDocument('', '', null).adoptNode(o1); } catch(e) { } +try { o1.appendChild(o3) } catch(e) { } +try { o5.addRange(new Range()); } catch(e) { } +try { document.documentElement.appendChild(o4) } catch(e) { } +try { o4.textContent = 'XX' } catch(e) { } +try { o7 = o4.firstChild } catch(e) { } +try { o4.parentNode.insertBefore(o7, o4); } catch(e) { } +try { o5.modify('extend', 'forward', 'line') } catch(e) { } +try { o5.selectAllChildren(o3) } catch(e) { } +try { o7.splitText(1) } catch(e) { } +</script> \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/editor/libeditor/crashtests/1384161.html @@ -0,0 +1,17 @@ +<html> + <head> + <script> + try { o1 = document.createElement('caption') } catch(e) { } + try { o2 = document.createElement('select') } catch(e) { } + try { o3 = document.createElement('map') } catch(e) { } + try { o4 = window.getSelection() } catch(e) { } + try { document.documentElement.appendChild(o1) } catch(e) { } + try { o1.style.display = 'contents' } catch(e) { } + try { document.prepend(o2, document) } catch(e) { } + try { document.designMode = 'on'; } catch(e) { } + try { o3.ownerDocument.execCommand('outdent', false, null) } catch(e) { } + try { document.designMode = 'off'; } catch(e) { } + try { o4.extend(o2, 0) } catch(e) { } + </script> + </head> +</html> \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/editor/libeditor/crashtests/1393171.html @@ -0,0 +1,10 @@ +<script> +window.onload=function(){ + window.getSelection().addRange(document.createRange()); + document.getElementById('a').appendChild(document.createElement('option')); + window.getSelection().modify('extend','backward','lineboundary'); +} +</script> +<div></div> +<textarea autofocus='true'></textarea> +<del id='a'>
--- a/editor/libeditor/crashtests/crashtests.list +++ b/editor/libeditor/crashtests/crashtests.list @@ -75,13 +75,17 @@ load 1324505.html needs-focus load 1343918.html load 1345015.html load 1348851.html load 1350772.html load 1364133.html load 1366176.html load 1375131.html load 1381541.html +load 1383747.html load 1383755.html +load 1383763.html +load 1384161.html load 1388075.html +load 1393171.html load 1402469.html load 1402904.html load 1405747.html
--- a/gfx/harfbuzz/src/hb-shape-plan.cc +++ b/gfx/harfbuzz/src/hb-shape-plan.cc @@ -515,25 +515,27 @@ hb_shape_plan_create_cached2 (hb_face_t if (unlikely (!proposal.shaper_func)) return hb_shape_plan_get_empty (); } retry: hb_face_t::plan_node_t *cached_plan_nodes = (hb_face_t::plan_node_t *) hb_atomic_ptr_get (&face->shape_plans); - for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next) - if (hb_shape_plan_matches (node->shape_plan, &proposal)) - { - DEBUG_MSG_FUNC (SHAPE_PLAN, node->shape_plan, "fulfilled from cache"); - return hb_shape_plan_reference (node->shape_plan); - } + + /* Don't look for plan in the cache if there were variation coordinates XXX Fix me. */ + if (!hb_coords_present (coords, num_coords)) + for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next) + if (hb_shape_plan_matches (node->shape_plan, &proposal)) + { + DEBUG_MSG_FUNC (SHAPE_PLAN, node->shape_plan, "fulfilled from cache"); + return hb_shape_plan_reference (node->shape_plan); + } /* Not found. */ - hb_shape_plan_t *shape_plan = hb_shape_plan_create2 (face, props, user_features, num_user_features, coords, num_coords, shaper_list); /* Don't add to the cache if face is inert. */ if (unlikely (hb_object_is_inert (face))) return shape_plan;
--- a/gfx/layers/ipc/PWebRenderBridge.ipdl +++ b/gfx/layers/ipc/PWebRenderBridge.ipdl @@ -54,16 +54,19 @@ parent: WebRenderScrollData aScrollData, OpUpdateResource[] aResourceUpdates, Shmem[] aSmallShmems, Shmem[] aLargeShmems, IdNamespace aIdNamespace, TimeStamp txnStartTime, TimeStamp fwdTime); sync SetDisplayListSync(IntSize aSize, WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId, LayoutSize aContentSize, ByteBuffer aDL, BuiltDisplayListDescriptor aDLDesc, WebRenderScrollData aScrollData, OpUpdateResource[] aResourceUpdates, Shmem[] aSmallShmems, Shmem[] aLargeShmems, IdNamespace aIdNamespace, TimeStamp txnStartTime, TimeStamp fwdTime); + async EmptyTransaction(FocusTarget focusTarget, + WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId, + IdNamespace aIdNamespace, TimeStamp txnStartTime, TimeStamp fwdTime); async SetFocusTarget(FocusTarget focusTarget); async UpdateResources(OpUpdateResource[] aResourceUpdates, Shmem[] aSmallShmems, Shmem[] aLargeShmems); async ParentCommands(WebRenderParentCommand[] commands); sync GetSnapshot(PTexture texture); async AddPipelineIdForCompositable(PipelineId aImageId, CompositableHandle aHandle, bool aAsync); async RemovePipelineIdForCompositable(PipelineId aPipelineId); async AddExternalImageIdForCompositable(ExternalImageId aImageId, CompositableHandle aHandle); async RemoveExternalImageId(ExternalImageId aImageId);
--- a/gfx/layers/wr/IpcResourceUpdateQueue.cpp +++ b/gfx/layers/wr/IpcResourceUpdateQueue.cpp @@ -36,20 +36,28 @@ ShmSegmentsWriter::Write(Range<uint8_t> memcpy(dstPtr, aBytes.begin().get(), length); return range; } int remainingBytesToCopy = length; size_t srcCursor = 0; size_t dstCursor = mCursor; + size_t currAllocLen = mSmallAllocs.Length(); while (remainingBytesToCopy > 0) { if (dstCursor >= mSmallAllocs.Length() * mChunkSize) { - AllocChunk(); + if (!AllocChunk()) { + for (size_t i = mSmallAllocs.Length() ; currAllocLen <= i ; i--) { + ipc::Shmem shm = mSmallAllocs.ElementAt(i); + mShmAllocator->DeallocShmem(shm); + mSmallAllocs.RemoveElementAt(i); + } + return layers::OffsetRange(0, start, 0); + } continue; } const size_t dstMaxOffset = mChunkSize * mSmallAllocs.Length(); const size_t dstBaseOffset = mChunkSize * (mSmallAllocs.Length() - 1); MOZ_ASSERT(dstCursor >= dstBaseOffset); MOZ_ASSERT(dstCursor <= dstMaxOffset); @@ -70,36 +78,39 @@ ShmSegmentsWriter::Write(Range<uint8_t> MOZ_ASSERT(remainingBytesToCopy >= 0); } mCursor += length; return layers::OffsetRange(0, start, length); } -void +bool ShmSegmentsWriter::AllocChunk() { ipc::Shmem shm; auto shmType = ipc::SharedMemory::SharedMemoryType::TYPE_BASIC; if (!mShmAllocator->AllocShmem(mChunkSize, shmType, &shm)) { - gfxCriticalError() << "ShmSegmentsWriter failed to allocate chunk #" << mSmallAllocs.Length(); - MOZ_CRASH(); + gfxCriticalNote << "ShmSegmentsWriter failed to allocate chunk #" << mSmallAllocs.Length(); + MOZ_ASSERT(false, "ShmSegmentsWriter fails to allocate chunk"); + return false; } mSmallAllocs.AppendElement(shm); + return true; } layers::OffsetRange ShmSegmentsWriter::AllocLargeChunk(size_t aSize) { ipc::Shmem shm; auto shmType = ipc::SharedMemory::SharedMemoryType::TYPE_BASIC; if (!mShmAllocator->AllocShmem(aSize, shmType, &shm)) { - gfxCriticalError() << "ShmSegmentsWriter failed to allocate large chunk of size " << aSize; - MOZ_CRASH(); + gfxCriticalNote << "ShmSegmentsWriter failed to allocate large chunk of size " << aSize; + MOZ_ASSERT(false, "ShmSegmentsWriter fails to allocate large chunk"); + return layers::OffsetRange(0, 0, 0); } mLargeAllocs.AppendElement(shm); return layers::OffsetRange(mLargeAllocs.Length(), 0, aSize); } void ShmSegmentsWriter::Flush(nsTArray<ipc::Shmem>& aSmallAllocs, nsTArray<ipc::Shmem>& aLargeAllocs) @@ -217,67 +228,87 @@ ShmSegmentsReader::Read(const layers::Of return aInto.Length() - initialLength == aRange.length(); } IpcResourceUpdateQueue::IpcResourceUpdateQueue(ipc::IShmemAllocator* aAllocator, size_t aChunkSize) : mWriter(Move(aAllocator), aChunkSize) {} -void +bool IpcResourceUpdateQueue::AddImage(ImageKey key, const ImageDescriptor& aDescriptor, Range<uint8_t> aBytes) { auto bytes = mWriter.Write(aBytes); + if (!bytes.length()) { + return false; + } mUpdates.AppendElement(layers::OpAddImage(aDescriptor, bytes, 0, key)); + return true; } -void +bool IpcResourceUpdateQueue::AddBlobImage(ImageKey key, const ImageDescriptor& aDescriptor, Range<uint8_t> aBytes) { auto bytes = mWriter.Write(aBytes); + if (!bytes.length()) { + return false; + } mUpdates.AppendElement(layers::OpAddBlobImage(aDescriptor, bytes, 0, key)); + return true; } void IpcResourceUpdateQueue::AddExternalImage(wr::ExternalImageId aExtId, wr::ImageKey aKey) { mUpdates.AppendElement(layers::OpAddExternalImage(aExtId, aKey)); } -void +bool IpcResourceUpdateQueue::UpdateImageBuffer(ImageKey aKey, const ImageDescriptor& aDescriptor, Range<uint8_t> aBytes) { auto bytes = mWriter.Write(aBytes); + if (!bytes.length()) { + return false; + } mUpdates.AppendElement(layers::OpUpdateImage(aDescriptor, bytes, aKey)); + return true; } -void +bool IpcResourceUpdateQueue::UpdateBlobImage(ImageKey aKey, const ImageDescriptor& aDescriptor, Range<uint8_t> aBytes) { auto bytes = mWriter.Write(aBytes); + if (!bytes.length()) { + return false; + } mUpdates.AppendElement(layers::OpUpdateBlobImage(aDescriptor, bytes, aKey)); + return true; } void IpcResourceUpdateQueue::DeleteImage(ImageKey aKey) { mUpdates.AppendElement(layers::OpDeleteImage(aKey)); } -void +bool IpcResourceUpdateQueue::AddRawFont(wr::FontKey aKey, Range<uint8_t> aBytes, uint32_t aIndex) { auto bytes = mWriter.Write(aBytes); + if (!bytes.length()) { + return false; + } mUpdates.AppendElement(layers::OpAddRawFont(bytes, aIndex, aKey)); + return true; } void IpcResourceUpdateQueue::DeleteFont(wr::FontKey aKey) { mUpdates.AppendElement(layers::OpDeleteFont(aKey)); }
--- a/gfx/layers/wr/IpcResourceUpdateQueue.h +++ b/gfx/layers/wr/IpcResourceUpdateQueue.h @@ -29,17 +29,17 @@ public: return Write(Range<uint8_t>((uint8_t*)aValues.begin().get(), aValues.length() * sizeof(T))); } void Flush(nsTArray<ipc::Shmem>& aSmallAllocs, nsTArray<ipc::Shmem>& aLargeAllocs); void Clear(); protected: - void AllocChunk(); + bool AllocChunk(); layers::OffsetRange AllocLargeChunk(size_t aSize); nsTArray<ipc::Shmem> mSmallAllocs; nsTArray<ipc::Shmem> mLargeAllocs; ipc::IShmemAllocator* mShmAllocator; size_t mCursor; size_t mChunkSize; }; @@ -62,43 +62,43 @@ protected: class IpcResourceUpdateQueue { public: // Because we are using shmems, the size should be a multiple of the page size. // Each shmem has two guard pages, and the minimum shmem size (at least one Windows) // is 64k which is already quite large for a lot of the resources we use here. // So we pick 64k - 2 * 4k = 57344 bytes as the defautl alloc explicit IpcResourceUpdateQueue(ipc::IShmemAllocator* aAllocator, size_t aChunkSize = 57344); - void AddImage(wr::ImageKey aKey, + bool AddImage(wr::ImageKey aKey, const ImageDescriptor& aDescriptor, Range<uint8_t> aBytes); - void AddBlobImage(wr::ImageKey aKey, + bool AddBlobImage(wr::ImageKey aKey, const ImageDescriptor& aDescriptor, Range<uint8_t> aBytes); void AddExternalImage(wr::ExternalImageId aExtId, wr::ImageKey aKey); - void UpdateImageBuffer(wr::ImageKey aKey, + bool UpdateImageBuffer(wr::ImageKey aKey, const ImageDescriptor& aDescriptor, Range<uint8_t> aBytes); - void UpdateBlobImage(wr::ImageKey aKey, + bool UpdateBlobImage(wr::ImageKey aKey, const ImageDescriptor& aDescriptor, Range<uint8_t> aBytes); void UpdateExternalImage(ImageKey aKey, const ImageDescriptor& aDescriptor, ExternalImageId aExtID, wr::WrExternalImageBufferType aBufferType, uint8_t aChannelIndex = 0); void DeleteImage(wr::ImageKey aKey); - void AddRawFont(wr::FontKey aKey, Range<uint8_t> aBytes, uint32_t aIndex); + bool AddRawFont(wr::FontKey aKey, Range<uint8_t> aBytes, uint32_t aIndex); void DeleteFont(wr::FontKey aKey); void AddFontInstance(wr::FontInstanceKey aKey, wr::FontKey aFontKey, float aGlyphSize, const wr::FontInstanceOptions* aOptions, const wr::FontInstancePlatformOptions* aPlatformOptions,
--- a/gfx/layers/wr/WebRenderBridgeChild.cpp +++ b/gfx/layers/wr/WebRenderBridgeChild.cpp @@ -153,16 +153,38 @@ WebRenderBridgeChild::EndTransaction(con } mParentCommands.Clear(); mDestroyedActors.Clear(); mIsInTransaction = false; } void +WebRenderBridgeChild::EndEmptyTransaction(const FocusTarget& aFocusTarget, + uint64_t aTransactionId, + const mozilla::TimeStamp& aTxnStartTime) +{ + MOZ_ASSERT(!mDestroyed); + MOZ_ASSERT(mIsInTransaction); + + TimeStamp fwdTime; +#if defined(ENABLE_FRAME_LATENCY_LOG) + fwdTime = TimeStamp::Now(); +#endif + + this->SendEmptyTransaction(aFocusTarget, + mParentCommands, mDestroyedActors, + GetFwdTransactionId(), aTransactionId, + mIdNamespace, aTxnStartTime, fwdTime); + mParentCommands.Clear(); + mDestroyedActors.Clear(); + mIsInTransaction = false; +} + +void WebRenderBridgeChild::ProcessWebRenderParentCommands() { MOZ_ASSERT(!mDestroyed); if (mParentCommands.IsEmpty()) { return; } this->SendParentCommands(mParentCommands);
--- a/gfx/layers/wr/WebRenderBridgeChild.h +++ b/gfx/layers/wr/WebRenderBridgeChild.h @@ -70,16 +70,19 @@ public: void BeginTransaction(); void EndTransaction(const wr::LayoutSize& aContentSize, wr::BuiltDisplayList& dl, wr::IpcResourceUpdateQueue& aResources, const gfx::IntSize& aSize, bool aIsSync, uint64_t aTransactionId, const WebRenderScrollData& aScrollData, const mozilla::TimeStamp& aTxnStartTime); + void EndEmptyTransaction(const FocusTarget& aFocusTarget, + uint64_t aTransactionId, + const mozilla::TimeStamp& aTxnStartTime); void ProcessWebRenderParentCommands(); CompositorBridgeChild* GetCompositorBridgeChild(); wr::PipelineId GetPipeline() { return mPipelineId; } // KnowsCompositor TextureForwarder* GetTextureForwarder() override;
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp +++ b/gfx/layers/wr/WebRenderBridgeParent.cpp @@ -610,16 +610,58 @@ WebRenderBridgeParent::RecvSetDisplayLis return RecvSetDisplayList(aSize, Move(aCommands), Move(aToDestroy), aFwdTransactionId, aTransactionId, aContentSize, dl, dlDesc, aScrollData, Move(aResourceUpdates), Move(aSmallShmems), Move(aLargeShmems), aIdNamespace, aTxnStartTime, aFwdTime); } mozilla::ipc::IPCResult +WebRenderBridgeParent::RecvEmptyTransaction(const FocusTarget& aFocusTarget, + InfallibleTArray<WebRenderParentCommand>&& aCommands, + InfallibleTArray<OpDestroy>&& aToDestroy, + const uint64_t& aFwdTransactionId, + const uint64_t& aTransactionId, + const wr::IdNamespace& aIdNamespace, + const TimeStamp& aTxnStartTime, + const TimeStamp& aFwdTime) +{ + if (mDestroyed) { + for (const auto& op : aToDestroy) { + DestroyActor(op); + } + return IPC_OK(); + } + + AutoProfilerTracing tracing("Paint", "EmptyTransaction"); + UpdateFwdTransactionId(aFwdTransactionId); + AutoClearReadLocks clearLocks(mReadLocks); + + // This ensures that destroy operations are always processed. It is not safe + // to early-return without doing so. + AutoWebRenderBridgeParentAsyncMessageSender autoAsyncMessageSender(this, &aToDestroy); + + if (!aCommands.IsEmpty()) { + mAsyncImageManager->SetCompositionTime(TimeStamp::Now()); + ProcessWebRenderParentCommands(aCommands); + mCompositorScheduler->ScheduleComposition(); + } + + mScrollData.SetFocusTarget(aFocusTarget); + UpdateAPZ(false); + + // XXX Call DidComposite at correct timing. + TimeStamp now = TimeStamp::Now(); + HoldPendingTransactionId(mWrEpoch, aTransactionId, aTxnStartTime, aFwdTime); + mCompositorBridge->DidComposite(wr::AsUint64(mPipelineId), now, now); + + return IPC_OK(); +} + +mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetFocusTarget(const FocusTarget& aFocusTarget) { mScrollData.SetFocusTarget(aFocusTarget); UpdateAPZ(false); return IPC_OK(); } mozilla::ipc::IPCResult
--- a/gfx/layers/wr/WebRenderBridgeParent.h +++ b/gfx/layers/wr/WebRenderBridgeParent.h @@ -101,16 +101,24 @@ public: const wr::BuiltDisplayListDescriptor& dlDesc, const WebRenderScrollData& aScrollData, nsTArray<OpUpdateResource>&& aResourceUpdates, nsTArray<ipc::Shmem>&& aSmallShmems, nsTArray<ipc::Shmem>&& aLargeShmems, const wr::IdNamespace& aIdNamespace, const TimeStamp& aTxnStartTime, const TimeStamp& aFwdTime) override; + mozilla::ipc::IPCResult RecvEmptyTransaction(const FocusTarget& aFocusTarget, + InfallibleTArray<WebRenderParentCommand>&& aCommands, + InfallibleTArray<OpDestroy>&& aToDestroy, + const uint64_t& aFwdTransactionId, + const uint64_t& aTransactionId, + const wr::IdNamespace& aIdNamespace, + const TimeStamp& aTxnStartTime, + const TimeStamp& aFwdTime) override; mozilla::ipc::IPCResult RecvSetFocusTarget(const FocusTarget& aFocusTarget) override; mozilla::ipc::IPCResult RecvParentCommands(nsTArray<WebRenderParentCommand>&& commands) override; mozilla::ipc::IPCResult RecvGetSnapshot(PTextureParent* aTexture) override; mozilla::ipc::IPCResult RecvAddPipelineIdForCompositable(const wr::PipelineId& aPipelineIds, const CompositableHandle& aHandle, const bool& aAsync) override; mozilla::ipc::IPCResult RecvRemovePipelineIdForCompositable(const wr::PipelineId& aPipelineId) override;
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp +++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp @@ -27,16 +27,33 @@ namespace layers { void WebRenderCommandBuilder::Destroy() { mLastCanvasDatas.Clear(); RemoveUnusedAndResetWebRenderUserData(); } void +WebRenderCommandBuilder::EmptyTransaction() +{ + // We need to update canvases that might have changed. + for (auto iter = mLastCanvasDatas.Iter(); !iter.Done(); iter.Next()) { + RefPtr<WebRenderCanvasData> canvasData = iter.Get()->GetKey(); + WebRenderCanvasRendererAsync* canvas = canvasData->GetCanvasRenderer(); + canvas->UpdateCompositableClient(); + } +} + +bool +WebRenderCommandBuilder::NeedsEmptyTransaction() +{ + return !mLastCanvasDatas.IsEmpty(); +} + +void WebRenderCommandBuilder::BuildWebRenderCommands(wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResourceUpdates, nsDisplayList* aDisplayList, nsDisplayListBuilder* aDisplayListBuilder, WebRenderScrollData& aScrollData, wr::LayoutSize& aContentSize) { { // scoping for StackingContextHelper RAII @@ -494,17 +511,19 @@ WebRenderCommandBuilder::GenerateFallbac RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateRecordingDrawTarget(recorder, dummyDt, paintSize.ToUnknownSize()); PaintItemByDrawTarget(aItem, dt, paintRect, offset, aDisplayListBuilder, fallbackData->mBasicLayerManager, mManager, scale); recorder->Finish(); Range<uint8_t> bytes((uint8_t*)recorder->mOutputStream.mData, recorder->mOutputStream.mLength); wr::ImageKey key = mManager->WrBridge()->GetNextImageKey(); wr::ImageDescriptor descriptor(paintSize.ToUnknownSize(), 0, dt->GetFormat(), isOpaque); - aResources.AddBlobImage(key, descriptor, bytes); + if (!aResources.AddBlobImage(key, descriptor, bytes)) { + return nullptr; + } fallbackData->SetKey(key); } else { fallbackData->CreateImageClientIfNeeded(); RefPtr<ImageClient> imageClient = fallbackData->GetImageClient(); RefPtr<ImageContainer> imageContainer = LayerManager::CreateImageContainer(); { UpdateImageHelper helper(imageContainer, imageClient, paintSize.ToUnknownSize(), format);
--- a/gfx/layers/wr/WebRenderCommandBuilder.h +++ b/gfx/layers/wr/WebRenderCommandBuilder.h @@ -35,16 +35,20 @@ class WebRenderCommandBuilder { public: explicit WebRenderCommandBuilder(WebRenderLayerManager* aManager) : mManager(aManager) , mLastAsr(nullptr) {} void Destroy(); + void EmptyTransaction(); + + bool NeedsEmptyTransaction(); + void BuildWebRenderCommands(wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResourceUpdates, nsDisplayList* aDisplayList, nsDisplayListBuilder* aDisplayListBuilder, WebRenderScrollData& aScrollData, wr::LayoutSize& aContentSize); Maybe<wr::ImageKey> CreateImageKey(nsDisplayItem* aItem,
--- a/gfx/layers/wr/WebRenderLayerManager.cpp +++ b/gfx/layers/wr/WebRenderLayerManager.cpp @@ -173,31 +173,48 @@ WebRenderLayerManager::BeginTransaction( bool WebRenderLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags) { // With the WebRenderLayerManager we reject attempts to set most kind of // "pending data" for empty transactions. Any place that attempts to update // transforms or scroll offset, for example, will get failure return values // back, and will fall back to a full transaction. Therefore the only piece - // of "pending" information we need to send in an empty transaction is the - // APZ focus state. - WrBridge()->SendSetFocusTarget(mFocusTarget); + // of "pending" information we need to send in an empty transaction are the + // APZ focus state and canvases's CompositableOperations. + + if (aFlags & EndTransactionFlags::END_NO_COMPOSITE && + !mWebRenderCommandBuilder.NeedsEmptyTransaction()) { + MOZ_ASSERT(!mTarget); + WrBridge()->SendSetFocusTarget(mFocusTarget); + return true; + } + + LayoutDeviceIntSize size = mWidget->GetClientSize(); + WrBridge()->BeginTransaction(); + + mWebRenderCommandBuilder.EmptyTransaction(); - // We also need to update canvases that might have changed, but this code - // as-is causes crashes so comment it out for now. - //for (auto iter = mLastCanvasDatas.Iter(); !iter.Done(); iter.Next()) { - // RefPtr<WebRenderCanvasData> canvasData = iter.Get()->GetKey(); - // WebRenderCanvasRendererAsync* canvas = canvasData->GetCanvasRenderer(); - // canvas->UpdateCompositableClient(); - //} + WrBridge()->ClearReadLocks(); + + mLatestTransactionId = mTransactionIdAllocator->GetTransactionId(/*aThrottle*/ true); + TimeStamp transactionStart = mTransactionIdAllocator->GetTransactionStart(); - if (!(aFlags & EndTransactionFlags::END_NO_COMPOSITE)) { - ScheduleComposite(); + // Skip the synchronization for buffer since we also skip the painting during + // device-reset status. + if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) { + if (WrBridge()->GetSyncObject() && + WrBridge()->GetSyncObject()->IsSyncObjectValid()) { + WrBridge()->GetSyncObject()->Synchronize(); + } } + + WrBridge()->EndEmptyTransaction(mFocusTarget, mLatestTransactionId, transactionStart); + + MakeSnapshotIfRequired(size); return true; } /*static*/ int32_t PopulateScrollData(WebRenderScrollData& aTarget, Layer* aLayer) { MOZ_ASSERT(aLayer);
new file mode 100644 --- /dev/null +++ b/gfx/tests/crashtests/1278305.html @@ -0,0 +1,20 @@ +<html> +<head> +<style> +body { + mask: url(#mymask); +} +div::after { + content: counter(n); +} +</style> +<script> +window.onload = function(){ + document.getElementsByTagName('body')[0].animate( + [{"transform": "skewy(11rad)"}, + {"transform": "rotatex(0.125turn)"}], + {"fill":"forwards", "iterations": 0.75, "duration": 1}); +}; +</script></head> +<body><div></div></body> +</html>
--- a/gfx/tests/crashtests/crashtests.list +++ b/gfx/tests/crashtests/crashtests.list @@ -126,13 +126,14 @@ skip-if(webrender&&debug) load 944579.ht pref(security.fileuri.strict_origin_policy,false) load 950000.html load 1034403-1.html load 1056516.html load 1205900.html load 1134549-1.svg load balinese-letter-spacing.html load 1216832-1.html load 1225125-1.html +load 1278305.html load 1308394.html load 1317403-1.html # bug 1331533 load 1325159-1.html load 1331683.html skip-if(Android) pref(dom.disable_open_during_load,false) load 1343666.html
--- a/gfx/thebes/gfxHarfBuzzShaper.cpp +++ b/gfx/thebes/gfxHarfBuzzShaper.cpp @@ -1278,16 +1278,25 @@ gfxHarfBuzzShaper::Initialize() HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS); mHBFont = hb_font_create(mHBFace); hb_font_set_funcs(mHBFont, sHBFontFuncs, &mCallbackData, nullptr); hb_font_set_ppem(mHBFont, mFont->GetAdjustedSize(), mFont->GetAdjustedSize()); uint32_t scale = FloatToFixed(mFont->GetAdjustedSize()); // 16.16 fixed-point hb_font_set_scale(mHBFont, scale, scale); + const auto& vars = mFont->GetStyle()->variationSettings; + size_t len = vars.Length(); + if (len > 0) { + // Fortunately, the hb_variation_t struct is compatible with our + // gfxFontFeature, so we can simply cast here. + auto hbVars = reinterpret_cast<const hb_variation_t*>(vars.Elements()); + hb_font_set_variations(mHBFont, hbVars, len); + } + return true; } bool gfxHarfBuzzShaper::LoadHmtxTable() { // Read mNumLongHMetrics from metrics-head table without caching its // blob, and preload/cache the metrics table.
--- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -29,16 +29,17 @@ class AutoLockGC; class AutoLockHelperThreadState; class VerifyPreTracer; namespace gc { typedef Vector<ZoneGroup*, 4, SystemAllocPolicy> ZoneGroupVector; using BlackGrayEdgeVector = Vector<TenuredCell*, 0, SystemAllocPolicy>; +class AutoCallGCCallbacks; class AutoMaybeStartBackgroundAllocation; class AutoRunParallelTask; class AutoTraceSession; class MarkingValidator; struct MovingTracer; class WeakCacheSweepIterator; enum IncrementalProgress @@ -1045,16 +1046,20 @@ class GCRuntime gcstats::ZoneGCStats scanZonesBeforeGC(); void collect(bool nonincrementalByAPI, SliceBudget budget, JS::gcreason::Reason reason) JS_HAZ_GC_CALL; MOZ_MUST_USE IncrementalResult gcCycle(bool nonincrementalByAPI, SliceBudget& budget, JS::gcreason::Reason reason); bool shouldRepeatForDeadZone(JS::gcreason::Reason reason); void incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason reason, AutoLockForExclusiveAccess& lock); + friend class AutoCallGCCallbacks; + void maybeCallBeginCallback(); + void maybeCallEndCallback(); + void pushZealSelectedObjects(); void purgeRuntime(AutoLockForExclusiveAccess& lock); MOZ_MUST_USE bool beginMarkPhase(JS::gcreason::Reason reason, AutoLockForExclusiveAccess& lock); bool prepareZonesForCollection(JS::gcreason::Reason reason, bool* isFullOut, AutoLockForExclusiveAccess& lock); bool shouldPreserveJITCode(JSCompartment* comp, int64_t currentTime, JS::gcreason::Reason reason, bool canAllocateMoreCode); void traceRuntimeForMajorGC(JSTracer* trc, AutoLockForExclusiveAccess& lock); @@ -1403,16 +1408,18 @@ class GCRuntime ActiveThreadData<bool> deterministicOnly; ActiveThreadData<int> incrementalLimit; ActiveThreadData<Vector<JSObject*, 0, SystemAllocPolicy>> selectedForMarking; #endif ActiveThreadData<bool> fullCompartmentChecks; + ActiveThreadData<uint32_t> gcBeginCallbackDepth; + Callback<JSGCCallback> gcCallback; Callback<JS::DoCycleCollectionCallback> gcDoCycleCollectionCallback; Callback<JSObjectsTenuredCallback> tenuredCallback; CallbackVector<JSFinalizeCallback> finalizeCallbacks; CallbackVector<JSWeakPointerZonesCallback> updateWeakPointerZonesCallbacks; CallbackVector<JSWeakPointerCompartmentCallback> updateWeakPointerCompartmentCallbacks; MemoryCounter<GCRuntime> mallocCounter;
--- a/js/src/gc/Zone.cpp +++ b/js/src/gc/Zone.cpp @@ -53,16 +53,17 @@ JS::Zone::Zone(JSRuntime* rt, ZoneGroup* nurseryShapes_(group), data(group, nullptr), isSystem(group, false), #ifdef DEBUG gcLastSweepGroupIndex(group, 0), #endif jitZone_(group, nullptr), gcScheduled_(false), + gcScheduledSaved_(false), gcPreserveCode_(group, false), keepShapeTables_(group, false), listNext_(group, NotOnList) { /* Ensure that there are no vtables to mess us up here. */ MOZ_ASSERT(reinterpret_cast<JS::shadow::Zone*>(this) == static_cast<JS::shadow::Zone*>(this));
--- a/js/src/gc/Zone.h +++ b/js/src/gc/Zone.h @@ -690,16 +690,17 @@ struct Zone : public JS::shadow::Zone, updateMallocCounter(bytes); return p; } private: js::ZoneGroupData<js::jit::JitZone*> jitZone_; js::ActiveThreadData<bool> gcScheduled_; + js::ActiveThreadData<bool> gcScheduledSaved_; js::ZoneGroupData<bool> gcPreserveCode_; js::ZoneGroupData<bool> keepShapeTables_; // Allow zones to be linked into a list friend class js::gc::ZoneList; static Zone * const NotOnList; js::ZoneGroupOrGCTaskData<Zone*> listNext_; bool isOnList() const;
new file mode 100644 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1407058.js @@ -0,0 +1,16 @@ +"use strict"; +function f() { + var o = {}; + Object.defineProperty(o, "x", {get: undefined, set: undefined}); + for (var i = 0; i < 20; i++) { + var ex = null; + try { + o.x = 9; + } catch (e) { + ex = e; + } + assertEq(ex instanceof TypeError, true); + assertEq(o.x, undefined); + } +} +f();
new file mode 100644 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/enable-profiling-in-import.js @@ -0,0 +1,9 @@ +var module = new WebAssembly.Module(wasmTextToBinary(` + (module + (import "global" "func") + (func (export "f") + call 0 + ) + ) +`)); +new WebAssembly.Instance(module, { global: { func: enableGeckoProfiling } }).exports.f();
--- a/js/src/jit/ExecutableAllocator.cpp +++ b/js/src/jit/ExecutableAllocator.cpp @@ -123,17 +123,18 @@ ExecutableAllocator::ExecutableAllocator } ExecutableAllocator::~ExecutableAllocator() { for (size_t i = 0; i < m_smallPools.length(); i++) m_smallPools[i]->release(/* willDestroy = */true); // If this asserts we have a pool leak. - MOZ_ASSERT_IF(m_pools.initialized(), m_pools.empty()); + MOZ_ASSERT_IF(m_pools.initialized() && rt_->gc.shutdownCollectedEverything(), + m_pools.empty()); } ExecutablePool* ExecutableAllocator::poolForSize(size_t n) { // Try to fit in an existing small allocator. Use the pool with the // least available space that is big enough (best-fit). This is the // best strategy because (a) it maximizes the chance of the next
--- a/js/src/jit/JSJitFrameIter.h +++ b/js/src/jit/JSJitFrameIter.h @@ -298,17 +298,17 @@ class JSJitProfilingFrameIterator void fixBaselineReturnAddress(); void moveToCppEntryFrame(); void moveToWasmFrame(CommonFrameLayout* frame); void moveToNextFrame(CommonFrameLayout* frame); public: JSJitProfilingFrameIterator(JSContext* cx, - const JS::ProfilingFrameIterator::RegisterState& state); + const JS::ProfilingFrameIterator::RegisterState& state); explicit JSJitProfilingFrameIterator(void* exitFrame); void operator++(); bool done() const { return fp_ == nullptr; } void* fp() const { MOZ_ASSERT(!done()); return fp_; } void* stackAddress() const { return fp(); } FrameType frameType() const { MOZ_ASSERT(!done()); return type_; }
--- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -936,16 +936,17 @@ GCRuntime::GCRuntime(JSRuntime* rt) : #ifdef JS_GC_ZEAL zealModeBits(0), zealFrequency(0), nextScheduled(0), deterministicOnly(false), incrementalLimit(0), #endif fullCompartmentChecks(false), + gcBeginCallbackDepth(0), alwaysPreserveCode(false), #ifdef DEBUG arenasEmptyAtShutdown(true), #endif lock(mutexid::GCLock), allocTask(rt, emptyChunks_.ref()), decommitTask(rt), helperState(rt), @@ -1643,35 +1644,16 @@ GCRuntime::setObjectsTenuredCallback(JSO void GCRuntime::callObjectsTenuredCallback() { if (tenuredCallback.op) tenuredCallback.op(TlsContext.get(), tenuredCallback.data); } -namespace { - -class AutoNotifyGCActivity { - public: - explicit AutoNotifyGCActivity(GCRuntime& gc) : gc_(gc) { - if (!gc_.isIncrementalGCInProgress()) - gc_.callGCCallback(JSGC_BEGIN); - } - ~AutoNotifyGCActivity() { - if (!gc_.isIncrementalGCInProgress()) - gc_.callGCCallback(JSGC_END); - } - - private: - GCRuntime& gc_; -}; - -} // (anon) - bool GCRuntime::addFinalizeCallback(JSFinalizeCallback callback, void* data) { return finalizeCallbacks.ref().append(Callback<JSFinalizeCallback>(callback, data)); } void GCRuntime::removeFinalizeCallback(JSFinalizeCallback callback) @@ -7100,30 +7082,77 @@ class AutoScheduleZonesForGC ~AutoScheduleZonesForGC() { for (ZonesIter zone(rt_, WithAtoms); !zone.done(); zone.next()) zone->unscheduleGC(); } }; } /* anonymous namespace */ +class js::gc::AutoCallGCCallbacks { + GCRuntime& gc_; + + public: + explicit AutoCallGCCallbacks(GCRuntime& gc) : gc_(gc) { + gc_.maybeCallBeginCallback(); + } + ~AutoCallGCCallbacks() { + gc_.maybeCallEndCallback(); + } +}; + +void +GCRuntime::maybeCallBeginCallback() +{ + if (isIncrementalGCInProgress()) + return; + + if (gcBeginCallbackDepth == 0) { + // Save scheduled zone information in case the callback changes it. + for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) + zone->gcScheduledSaved_ = zone->gcScheduled_; + } + + gcBeginCallbackDepth++; + + callGCCallback(JSGC_BEGIN); + + MOZ_ASSERT(gcBeginCallbackDepth != 0); + gcBeginCallbackDepth--; + + if (gcBeginCallbackDepth == 0) { + // Restore scheduled zone information again. + for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) + zone->gcScheduled_ = zone->gcScheduledSaved_; + } +} + +void +GCRuntime::maybeCallEndCallback() +{ + if (isIncrementalGCInProgress()) + return; + + callGCCallback(JSGC_END); +} + /* * Run one GC "cycle" (either a slice of incremental GC or an entire * non-incremental GC. We disable inlining to ensure that the bottom of the * stack with possible GC roots recorded in MarkRuntime excludes any pointers we * use during the marking implementation. * * Returns true if we "reset" an existing incremental GC, which would force us * to run another cycle. */ MOZ_NEVER_INLINE GCRuntime::IncrementalResult GCRuntime::gcCycle(bool nonincrementalByAPI, SliceBudget& budget, JS::gcreason::Reason reason) { - // Note that the following is allowed to re-enter GC in the finalizer. - AutoNotifyGCActivity notify(*this); + // Note that GC callbacks are allowed to re-enter GC. + AutoCallGCCallbacks callCallbacks(*this); gcstats::AutoGCSlice agc(stats(), scanZonesBeforeGC(), invocationKind, budget, reason); minorGC(reason, gcstats::PhaseKind::EVICT_NURSERY_FOR_MAJOR_GC); AutoTraceSession session(rt, JS::HeapState::MajorCollecting); majorGCTriggerReason = JS::gcreason::NO_REASON;
--- a/js/src/vm/GeckoProfiler.cpp +++ b/js/src/vm/GeckoProfiler.cpp @@ -64,24 +64,33 @@ GeckoProfilerRuntime::setEventMarker(voi // Get a pointer to the top-most profiling frame, given the exit frame pointer. static void* GetTopProfilingJitFrame(Activation* act) { if (!act || !act->isJit()) return nullptr; - // For null exitFrame, there is no previous exit frame, just return. - uint8_t* jsExitFP = act->asJit()->jsExitFP(); - if (!jsExitFP) + jit::JitActivation* jitActivation = act->asJit(); + + // If there is no exit frame set, just return. + if (!jitActivation->hasExitFP()) return nullptr; - jit::JSJitProfilingFrameIterator iter(jsExitFP); - MOZ_ASSERT(!iter.done()); - return iter.fp(); + // Skip wasm frames that might be in the way. + JitFrameIter iter(jitActivation); + while (!iter.done() && iter.isWasm()) + ++iter; + + if (!iter.isJSJit()) + return nullptr; + + jit::JSJitProfilingFrameIterator jitIter(iter.asJSJit().fp()); + MOZ_ASSERT(!jitIter.done()); + return jitIter.fp(); } void GeckoProfilerRuntime::enable(bool enabled) { #ifdef DEBUG // All cooperating contexts must have profile stacks installed before the // profiler can be enabled. Cooperating threads created while the profiler
--- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -3130,19 +3130,16 @@ CASE(JSOP_FUNCALL) } } } funScript = fun->nonLazyScript(); if (!activation.pushInlineFrame(args, funScript, construct)) goto error; - - if (createSingleton) - REGS.fp()->setCreateSingleton(); } SET_SCRIPT(REGS.fp()->script()); { TraceLoggerEvent event(TraceLogger_Scripts, script); TraceLogStartEvent(logger, event); TraceLogStartEvent(logger, TraceLogger_Interpreter);
--- a/js/src/vm/Shape.cpp +++ b/js/src/vm/Shape.cpp @@ -741,17 +741,17 @@ NativeObject::putProperty(JSContext* cx, /* * If the caller wants to allocate a slot, but doesn't care which slot, * copy the existing shape's slot into slot so we can match shape, if all * other members match. */ bool hadSlot = shape->isDataProperty(); uint32_t oldSlot = shape->maybeSlot(); - bool needSlot = !getter && !setter; + bool needSlot = Shape::isDataProperty(attrs, getter, setter); if (needSlot && slot == SHAPE_INVALID_SLOT && hadSlot) slot = oldSlot; Rooted<UnownedBaseShape*> nbase(cx); { RootedShape shape(cx, obj->lastProperty()); nbase = GetBaseShapeForNewShape(cx, shape, id); if (!nbase) @@ -784,17 +784,17 @@ NativeObject::putProperty(JSContext* cx, if (obj->inDictionaryMode()) { /* * Updating some property in a dictionary-mode object. Create a new * shape for the existing property, and also generate a new shape for * the last property of the dictionary (unless the modified property * is also the last property). */ bool updateLast = (shape == obj->lastProperty()); - bool accessorShape = getter || setter || (attrs & (JSPROP_GETTER | JSPROP_SETTER)); + bool accessorShape = !Shape::isDataProperty(attrs, getter, setter); shape = NativeObject::replaceWithNewEquivalentShape(cx, obj, shape, nullptr, accessorShape); if (!shape) return nullptr; if (!updateLast && !NativeObject::generateOwnShape(cx, obj)) return nullptr; /* @@ -867,17 +867,17 @@ NativeObject::putProperty(JSContext* cx, /* static */ Shape* NativeObject::changeProperty(JSContext* cx, HandleNativeObject obj, HandleShape shape, unsigned attrs, GetterOp getter, SetterOp setter) { MOZ_ASSERT(obj->containsPure(shape)); /* Allow only shared (slotless) => unshared (slotful) transition. */ #ifdef DEBUG - bool needSlot = !getter && !setter; + bool needSlot = Shape::isDataProperty(attrs, getter, setter); MOZ_ASSERT_IF(shape->isDataProperty() != needSlot, needSlot); #endif MarkTypePropertyNonData(cx, obj, shape->propid()); AssertCanChangeAttrs(shape, attrs); if (shape->attrs == attrs && shape->getter() == getter && shape->setter() == setter)
--- a/js/src/vm/Shape.h +++ b/js/src/vm/Shape.h @@ -1008,19 +1008,23 @@ class Shape : public gc::TenuredCell maybeSlot() == aslot && attrs == aattrs && getter() == rawGetter && setter() == rawSetter; } BaseShape* base() const { return base_.get(); } + static bool isDataProperty(unsigned attrs, GetterOp getter, SetterOp setter) { + return !(attrs & (JSPROP_GETTER | JSPROP_SETTER)) && !getter && !setter; + } + bool isDataProperty() const { MOZ_ASSERT(!isEmptyShape()); - return !getter() && !setter(); + return isDataProperty(attrs, getter(), setter()); } uint32_t slot() const { MOZ_ASSERT(isDataProperty() && !hasMissingSlot()); return maybeSlot(); } uint32_t maybeSlot() const { return slotInfo & SLOT_MASK; } bool isEmptyShape() const { MOZ_ASSERT_IF(JSID_IS_EMPTY(propid_), hasMissingSlot()); @@ -1471,17 +1475,17 @@ struct StackShape flags &= ~Shape::ACCESSOR_SHAPE; this->rawGetter = rawGetter; this->rawSetter = rawSetter; } bool isDataProperty() const { MOZ_ASSERT(!JSID_IS_EMPTY(propid)); - return !rawGetter && !rawSetter; + return Shape::isDataProperty(attrs, rawGetter, rawSetter); } bool hasMissingSlot() const { return maybeSlot() == SHAPE_INVALID_SLOT; } uint32_t slot() const { MOZ_ASSERT(isDataProperty() && !hasMissingSlot()); return slot_; } uint32_t maybeSlot() const { return slot_; } void setSlot(uint32_t slot) { MOZ_ASSERT(slot <= SHAPE_INVALID_SLOT);
--- a/js/src/vm/Stack-inl.h +++ b/js/src/vm/Stack-inl.h @@ -558,24 +558,16 @@ AbstractFramePtr::hasInitialEnvironment( if (isInterpreterFrame()) return asInterpreterFrame()->hasInitialEnvironment(); if (isBaselineFrame()) return asBaselineFrame()->hasInitialEnvironment(); return asRematerializedFrame()->hasInitialEnvironment(); } inline bool -AbstractFramePtr::createSingleton() const -{ - if (isInterpreterFrame()) - return asInterpreterFrame()->createSingleton(); - return false; -} - -inline bool AbstractFramePtr::isGlobalFrame() const { if (isInterpreterFrame()) return asInterpreterFrame()->isGlobalFrame(); if (isBaselineFrame()) return asBaselineFrame()->isGlobalFrame(); if (isWasmDebugFrame()) return false;
--- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -265,17 +265,16 @@ class AbstractFramePtr inline unsigned numFormalArgs() const; inline Value* argv() const; inline bool hasArgs() const; inline bool hasArgsObj() const; inline ArgumentsObject& argsObj() const; inline void initArgsObj(ArgumentsObject& argsobj) const; - inline bool createSingleton() const; inline Value& unaliasedLocal(uint32_t i); inline Value& unaliasedFormal(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING); inline Value& unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING); template <class Op> inline void unaliasedForEachActual(JSContext* cx, Op op); inline bool prevUpToDate() const; inline void setPrevUpToDate() const; @@ -334,25 +333,22 @@ class InterpreterFrame HAS_PUSHED_PROF_FRAME = 0x80, /* Gecko Profiler was notified of entry */ /* * If set, we entered one of the JITs and ScriptFrameIter should skip * this frame. */ RUNNING_IN_JIT = 0x100, - /* Miscellaneous state. */ - CREATE_SINGLETON = 0x200, /* Constructed |this| object should be singleton. */ - /* * If set, this frame has been on the stack when * |js::SavedStacks::saveCurrentStack| was called, and so there is a * |js::SavedFrame| object cached for this frame. */ - HAS_CACHED_SAVED_FRAME = 0x400, + HAS_CACHED_SAVED_FRAME = 0x200, }; mutable uint32_t flags_; /* bits described by Flags */ uint32_t nactual_; /* number of actual arguments, for function frames */ JSScript* script_; /* the script we're executing */ JSObject* envChain_; /* current environment chain */ Value rval_; /* if HAS_RVAL, return value of the frame */ ArgumentsObject* argsObj_; /* if HAS_ARGS_OBJ, the call's arguments object */ @@ -754,25 +750,16 @@ class InterpreterFrame return flags_ & HAS_INITIAL_ENV; } bool hasArgsObj() const { MOZ_ASSERT(script()->needsArgsObj()); return flags_ & HAS_ARGS_OBJ; } - void setCreateSingleton() { - MOZ_ASSERT(isConstructing()); - flags_ |= CREATE_SINGLETON; - } - bool createSingleton() const { - MOZ_ASSERT(isConstructing()); - return flags_ & CREATE_SINGLETON; - } - /* * Debugger eval frames. * * - If evalInFramePrev_ is non-null, frame was created for an "eval in * frame" call, which can push a successor to any live frame; so its * logical "prev" frame is not necessarily the previous frame in memory. * Iteration should treat evalInFramePrev_ as this frame's previous frame. *
--- a/js/src/wasm/WasmBuiltins.cpp +++ b/js/src/wasm/WasmBuiltins.cpp @@ -287,38 +287,44 @@ WasmReportOutOfBounds() static void WasmReportUnalignedAccess() { JSContext* cx = TlsContext.get(); JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_WASM_UNALIGNED_ACCESS); } static int32_t -CoerceInPlace_ToInt32(MutableHandleValue val) +CoerceInPlace_ToInt32(Value* rawVal) { JSContext* cx = TlsContext.get(); int32_t i32; - if (!ToInt32(cx, val, &i32)) + RootedValue val(cx, *rawVal); + if (!ToInt32(cx, val, &i32)) { + *rawVal = PoisonedObjectValue(0x42); return false; - val.set(Int32Value(i32)); + } + *rawVal = Int32Value(i32); return true; } static int32_t -CoerceInPlace_ToNumber(MutableHandleValue val) +CoerceInPlace_ToNumber(Value* rawVal) { JSContext* cx = TlsContext.get(); double dbl; - if (!ToNumber(cx, val, &dbl)) + RootedValue val(cx, *rawVal); + if (!ToNumber(cx, val, &dbl)) { + *rawVal = PoisonedObjectValue(0x42); return false; - val.set(DoubleValue(dbl)); + } + *rawVal = DoubleValue(dbl); return true; } static int64_t DivI64(uint32_t x_hi, uint32_t x_lo, uint32_t y_hi, uint32_t y_lo) { int64_t x = ((uint64_t)x_hi << 32) + x_lo; int64_t y = ((uint64_t)y_hi << 32) + y_lo;
--- a/js/src/wasm/WasmStubs.cpp +++ b/js/src/wasm/WasmStubs.cpp @@ -765,16 +765,25 @@ GenerateImportJitExit(MacroAssembler& ma masm.loadBaselineOrIonNoArgCheck(callee, callee, nullptr); Label rejoinBeforeCall; masm.bind(&rejoinBeforeCall); AssertStackAlignment(masm, JitStackAlignment, sizeOfRetAddr); masm.callJitNoProfiler(callee); + // Note that there might be a GC thing in the JSReturnOperand now. + // In all the code paths from here: + // - either the value is unboxed because it was a primitive and we don't + // need to worry about rooting anymore. + // - or the value needs to be rooted, but nothing can cause a GC between + // here and CoerceInPlace, which roots before coercing to a primitive. + // In particular, this is true because wasm::InInterruptibleCode will + // return false when PC is in the jit exit. + // The JIT callee clobbers all registers, including WasmTlsReg and // FramePointer, so restore those here. During this sequence of // instructions, FP can't be trusted by the profiling frame iterator. offsets->untrustedFPStart = masm.currentOffset(); AssertStackAlignment(masm, JitStackAlignment, sizeOfRetAddr); masm.loadWasmTlsRegFromFrame(); masm.moveStackPtrTo(FramePointer);
--- a/layout/generic/nsPageFrame.cpp +++ b/layout/generic/nsPageFrame.cpp @@ -637,27 +637,27 @@ nsPageFrame::PaintHeaderFooter(gfxContex nscoord visibleHeight = 0; if (fontMet) { visibleHeight = fontMet->MaxHeight(); ascent = fontMet->MaxAscent(); } // print document headers and footers nsString headerLeft, headerCenter, headerRight; - mPD->mPrintSettings->GetHeaderStrLeft(getter_Copies(headerLeft)); - mPD->mPrintSettings->GetHeaderStrCenter(getter_Copies(headerCenter)); - mPD->mPrintSettings->GetHeaderStrRight(getter_Copies(headerRight)); + mPD->mPrintSettings->GetHeaderStrLeft(headerLeft); + mPD->mPrintSettings->GetHeaderStrCenter(headerCenter); + mPD->mPrintSettings->GetHeaderStrRight(headerRight); DrawHeaderFooter(aRenderingContext, *fontMet, eHeader, headerLeft, headerCenter, headerRight, rect, ascent, visibleHeight); nsString footerLeft, footerCenter, footerRight; - mPD->mPrintSettings->GetFooterStrLeft(getter_Copies(footerLeft)); - mPD->mPrintSettings->GetFooterStrCenter(getter_Copies(footerCenter)); - mPD->mPrintSettings->GetFooterStrRight(getter_Copies(footerRight)); + mPD->mPrintSettings->GetFooterStrLeft(footerLeft); + mPD->mPrintSettings->GetFooterStrCenter(footerCenter); + mPD->mPrintSettings->GetFooterStrRight(footerRight); DrawHeaderFooter(aRenderingContext, *fontMet, eFooter, footerLeft, footerCenter, footerRight, rect, ascent, visibleHeight); } void nsPageFrame::SetSharedPageData(nsSharedPageData* aPD) {
--- a/layout/printing/nsPrintEngine.cpp +++ b/layout/printing/nsPrintEngine.cpp @@ -1006,29 +1006,29 @@ nsPrintEngine::CheckForPrinters(nsIPrint if (!XRE_IsParentProcess()) { return NS_OK; } #endif NS_ENSURE_ARG_POINTER(aPrintSettings); // See if aPrintSettings already has a printer nsString printerName; - nsresult rv = aPrintSettings->GetPrinterName(getter_Copies(printerName)); + nsresult rv = aPrintSettings->GetPrinterName(printerName); if (NS_SUCCEEDED(rv) && !printerName.IsEmpty()) { return NS_OK; } // aPrintSettings doesn't have a printer set. Try to fetch the default. nsCOMPtr<nsIPrintSettingsService> printSettingsService = do_GetService(sPrintSettingsServiceContractID, &rv); NS_ENSURE_SUCCESS(rv, rv); - rv = printSettingsService->GetDefaultPrinterName(getter_Copies(printerName)); + rv = printSettingsService->GetDefaultPrinterName(printerName); if (NS_SUCCEEDED(rv) && !printerName.IsEmpty()) { - rv = aPrintSettings->SetPrinterName(printerName.get()); + rv = aPrintSettings->SetPrinterName(printerName); } return rv; #endif } //---------------------------------------------------------------------- // Set up to use the "pluggable" Print Progress Dialog void @@ -1450,31 +1450,18 @@ nsPrintEngine::GetDisplayTitleAndURL(con return; aTitle.Truncate(); aURLStr.Truncate(); // First check to see if the PrintSettings has defined an alternate title // and use that if it did if (mPrt->mPrintSettings) { - char16_t * docTitleStrPS = nullptr; - char16_t * docURLStrPS = nullptr; - mPrt->mPrintSettings->GetTitle(&docTitleStrPS); - mPrt->mPrintSettings->GetDocURL(&docURLStrPS); - - if (docTitleStrPS) { - aTitle = docTitleStrPS; - } - - if (docURLStrPS) { - aURLStr = docURLStrPS; - } - - free(docTitleStrPS); - free(docURLStrPS); + mPrt->mPrintSettings->GetTitle(aTitle); + mPrt->mPrintSettings->GetDocURL(aURLStr); } nsAutoString docTitle; nsAutoString docUrl; GetDocumentTitleAndURL(aPO->mDocument, docTitle, docUrl); if (aURLStr.IsEmpty() && !docUrl.IsEmpty()) { aURLStr = docUrl; @@ -1823,17 +1810,17 @@ nsPrintEngine::SetupToPrintContent() } nsAutoString fileNameStr; // check to see if we are printing to a file bool isPrintToFile = false; printData->mPrintSettings->GetPrintToFile(&isPrintToFile); if (isPrintToFile) { // On some platforms The BeginDocument needs to know the name of the file. - printData->mPrintSettings->GetToFileName(getter_Copies(fileNameStr)); + printData->mPrintSettings->GetToFileName(fileNameStr); } nsAutoString docTitleStr; nsAutoString docURLStr; GetDisplayTitleAndURL(printData->mPrintObject, docTitleStr, docURLStr, eDocTitleDefURLDoc); int32_t startPage = 1;
--- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -2107,17 +2107,17 @@ pref("network.ftp.idleConnectionTimeout" // 3: XUL directory viewer // all other values are treated like 2 pref("network.dir.format", 2); // enables the prefetch service (i.e., prefetching of <link rel="next"> and // <link rel="prefetch"> URLs). pref("network.prefetch-next", true); // enables the preloading (i.e., preloading of <link rel="preload"> URLs). -pref("network.preload", true); +pref("network.preload", false); // enables the predictive service pref("network.predictor.enabled", true); pref("network.predictor.enable-hover-on-ssl", false); pref("network.predictor.enable-prefetch", false); pref("network.predictor.page-degradation.day", 0); pref("network.predictor.page-degradation.week", 5); pref("network.predictor.page-degradation.month", 10);
--- a/rdf/base/nsIRDFXMLSerializer.idl +++ b/rdf/base/nsIRDFXMLSerializer.idl @@ -2,27 +2,30 @@ * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsISupports.idl" #include "nsIRDFDataSource.idl" -interface nsAtom; // not a real interface; used in [noscript] methods only +%{C++ +class nsAtom; +%} +[ptr] native nsAtomPtr(nsAtom); [scriptable, uuid(8ae1fbf8-1dd2-11b2-bd21-d728069cca92)] interface nsIRDFXMLSerializer : nsISupports { /** * Initialize the serializer with the specified datasource. * @param aDataSource the datasource from which data will be * serialized */ void init(in nsIRDFDataSource aDataSource); /** * Add the specified namespace to the serializer. * @param aPrefix the attribute namespace prefix * @param aURI the namespace URI */ - [noscript] void addNameSpace(in nsAtom aPrefix, in DOMString aURI); + [noscript] void addNameSpace(in nsAtomPtr aPrefix, in DOMString aURI); };
--- a/rdf/base/nsIRDFXMLSink.idl +++ b/rdf/base/nsIRDFXMLSink.idl @@ -7,17 +7,20 @@ Interfaces for the RDF/XML sink, which parses RDF/XML into a graph representation. */ #include "nsISupports.idl" -interface nsAtom; // not a real interface; used in [noscript] methods only +%{C++ +class nsAtom; +%} +[ptr] native nsAtomPtr(nsAtom); // XXX Until these get scriptable. See nsIRDFXMLSink::AddNameSpace() [ref] native nsStringRef(nsString); %{C++ #include "nsStringFwd.h" %} interface nsIRDFXMLSink; @@ -97,17 +100,17 @@ interface nsIRDFXMLSink : nsISupports */ void endLoad(); /** * Add namespace information to the RDF/XML sink. * @param aPrefix the namespace prefix * @param aURI the namespace URI */ - [noscript] void addNameSpace(in nsAtom aPrefix, + [noscript] void addNameSpace(in nsAtomPtr aPrefix, [const] in nsStringRef aURI); /** * Add an observer that will be notified as the RDF/XML load * progresses. * <p> * * Note that the sink will acquire a strong reference to the
--- a/security/nss/coreconf/coreconf.dep +++ b/security/nss/coreconf/coreconf.dep @@ -5,9 +5,8 @@ /* * A dummy header file that is a dependency for all the object files. * Used to force a full recompilation of NSS in Mozilla's Tinderbox * depend builds. See comments in rules.mk. */ #error "Do not include this header file." -
--- a/security/nss/gtests/pk11_gtest/pk11_ecdsa_unittest.cc +++ b/security/nss/gtests/pk11_gtest/pk11_ecdsa_unittest.cc @@ -10,145 +10,159 @@ #include "gtest/gtest.h" #include "scoped_ptrs.h" #include "pk11_ecdsa_vectors.h" #include "pk11_signature_test.h" namespace nss_test { -class Pkcs11EcdsaTest : public Pk11SignatureTest { +class Pkcs11EcdsaTestBase : public Pk11SignatureTest { protected: - CK_MECHANISM_TYPE mechanism() { return CKM_ECDSA; } - SECItem* parameters() { return nullptr; } + Pkcs11EcdsaTestBase(SECOidTag hash_oid) + : Pk11SignatureTest(CKM_ECDSA, hash_oid) {} }; -class Pkcs11EcdsaSha256Test : public Pkcs11EcdsaTest { - protected: - SECOidTag hashOID() { return SEC_OID_SHA256; } +struct Pkcs11EcdsaTestParams { + SECOidTag hash_oid_; + Pkcs11SignatureTestParams sig_params_; }; -class Pkcs11EcdsaSha384Test : public Pkcs11EcdsaTest { - protected: - SECOidTag hashOID() { return SEC_OID_SHA384; } -}; - -class Pkcs11EcdsaSha512Test : public Pkcs11EcdsaTest { - protected: - SECOidTag hashOID() { return SEC_OID_SHA512; } +class Pkcs11EcdsaTest + : public Pkcs11EcdsaTestBase, + public ::testing::WithParamInterface<Pkcs11EcdsaTestParams> { + public: + Pkcs11EcdsaTest() : Pkcs11EcdsaTestBase(GetParam().hash_oid_) {} }; -TEST_F(Pkcs11EcdsaSha256Test, VerifyP256) { - SIG_TEST_VECTOR_VERIFY(kP256Spki, kP256Data, kP256Signature) -} -TEST_F(Pkcs11EcdsaSha256Test, SignAndVerifyP256) { - SIG_TEST_VECTOR_SIGN_VERIFY(kP256Pkcs8, kP256Spki, kP256Data) +TEST_P(Pkcs11EcdsaTest, Verify) { Verify(GetParam().sig_params_); } + +TEST_P(Pkcs11EcdsaTest, SignAndVerify) { + SignAndVerify(GetParam().sig_params_); } -TEST_F(Pkcs11EcdsaSha384Test, VerifyP384) { - SIG_TEST_VECTOR_VERIFY(kP384Spki, kP384Data, kP384Signature) -} -TEST_F(Pkcs11EcdsaSha384Test, SignAndVerifyP384) { - SIG_TEST_VECTOR_SIGN_VERIFY(kP384Pkcs8, kP384Spki, kP384Data) -} +static const Pkcs11EcdsaTestParams kEcdsaVectors[] = { + {SEC_OID_SHA256, + {DataBuffer(kP256Pkcs8, sizeof(kP256Pkcs8)), + DataBuffer(kP256Spki, sizeof(kP256Spki)), + DataBuffer(kP256Data, sizeof(kP256Data)), + DataBuffer(kP256Signature, sizeof(kP256Signature))}}, + {SEC_OID_SHA384, + {DataBuffer(kP384Pkcs8, sizeof(kP384Pkcs8)), + DataBuffer(kP384Spki, sizeof(kP384Spki)), + DataBuffer(kP384Data, sizeof(kP384Data)), + DataBuffer(kP384Signature, sizeof(kP384Signature))}}, + {SEC_OID_SHA512, + {DataBuffer(kP521Pkcs8, sizeof(kP521Pkcs8)), + DataBuffer(kP521Spki, sizeof(kP521Spki)), + DataBuffer(kP521Data, sizeof(kP521Data)), + DataBuffer(kP521Signature, sizeof(kP521Signature))}}}; -TEST_F(Pkcs11EcdsaSha512Test, VerifyP521) { - SIG_TEST_VECTOR_VERIFY(kP521Spki, kP521Data, kP521Signature) -} -TEST_F(Pkcs11EcdsaSha512Test, SignAndVerifyP521) { - SIG_TEST_VECTOR_SIGN_VERIFY(kP521Pkcs8, kP521Spki, kP521Data) -} +INSTANTIATE_TEST_CASE_P(EcdsaSignVerify, Pkcs11EcdsaTest, + ::testing::ValuesIn(kEcdsaVectors)); + +class Pkcs11EcdsaSha256Test : public Pkcs11EcdsaTestBase { + public: + Pkcs11EcdsaSha256Test() : Pkcs11EcdsaTestBase(SEC_OID_SHA256) {} +}; // Importing a private key in PKCS#8 format must fail when the outer AlgID // struct contains neither id-ecPublicKey nor a namedCurve parameter. TEST_F(Pkcs11EcdsaSha256Test, ImportNoCurveOIDOrAlgorithmParams) { - EXPECT_FALSE(ImportPrivateKey(kP256Pkcs8NoCurveOIDOrAlgorithmParams, - sizeof(kP256Pkcs8NoCurveOIDOrAlgorithmParams))); + DataBuffer k(kP256Pkcs8NoCurveOIDOrAlgorithmParams, + sizeof(kP256Pkcs8NoCurveOIDOrAlgorithmParams)); + EXPECT_FALSE(ImportPrivateKey(k)); }; // Importing a private key in PKCS#8 format must succeed when only the outer // AlgID struct contains the namedCurve parameters. TEST_F(Pkcs11EcdsaSha256Test, ImportOnlyAlgorithmParams) { - EXPECT_TRUE(ImportPrivateKeyAndSignHashedData( - kP256Pkcs8OnlyAlgorithmParams, sizeof(kP256Pkcs8OnlyAlgorithmParams), - kP256Data, sizeof(kP256Data))); + DataBuffer k(kP256Pkcs8OnlyAlgorithmParams, + sizeof(kP256Pkcs8OnlyAlgorithmParams)); + DataBuffer data(kP256Data, sizeof(kP256Data)); + DataBuffer sig; + EXPECT_TRUE(ImportPrivateKeyAndSignHashedData(k, data, &sig)); }; // Importing a private key in PKCS#8 format must succeed when the outer AlgID // struct and the inner ECPrivateKey contain the same namedCurve parameters. // The inner curveOID is always ignored, so only the outer one will be used. TEST_F(Pkcs11EcdsaSha256Test, ImportMatchingCurveOIDAndAlgorithmParams) { - EXPECT_TRUE(ImportPrivateKeyAndSignHashedData( - kP256Pkcs8MatchingCurveOIDAndAlgorithmParams, - sizeof(kP256Pkcs8MatchingCurveOIDAndAlgorithmParams), kP256Data, - sizeof(kP256Data))); + DataBuffer k(kP256Pkcs8MatchingCurveOIDAndAlgorithmParams, + sizeof(kP256Pkcs8MatchingCurveOIDAndAlgorithmParams)); + DataBuffer data(kP256Data, sizeof(kP256Data)); + DataBuffer sig; + EXPECT_TRUE(ImportPrivateKeyAndSignHashedData(k, data, &sig)); }; // Importing a private key in PKCS#8 format must succeed when the outer AlgID // struct and the inner ECPrivateKey contain dissimilar namedCurve parameters. // The inner curveOID is always ignored, so only the outer one will be used. TEST_F(Pkcs11EcdsaSha256Test, ImportDissimilarCurveOIDAndAlgorithmParams) { - EXPECT_TRUE(ImportPrivateKeyAndSignHashedData( - kP256Pkcs8DissimilarCurveOIDAndAlgorithmParams, - sizeof(kP256Pkcs8DissimilarCurveOIDAndAlgorithmParams), kP256Data, - sizeof(kP256Data))); + DataBuffer k(kP256Pkcs8DissimilarCurveOIDAndAlgorithmParams, + sizeof(kP256Pkcs8DissimilarCurveOIDAndAlgorithmParams)); + DataBuffer data(kP256Data, sizeof(kP256Data)); + DataBuffer sig; + EXPECT_TRUE(ImportPrivateKeyAndSignHashedData(k, data, &sig)); }; // Importing a private key in PKCS#8 format must fail when the outer ASN.1 // AlgorithmID struct contains only id-ecPublicKey but no namedCurve parameter. TEST_F(Pkcs11EcdsaSha256Test, ImportNoAlgorithmParams) { - EXPECT_FALSE(ImportPrivateKey(kP256Pkcs8NoAlgorithmParams, - sizeof(kP256Pkcs8NoAlgorithmParams))); + DataBuffer k(kP256Pkcs8NoAlgorithmParams, + sizeof(kP256Pkcs8NoAlgorithmParams)); + EXPECT_FALSE(ImportPrivateKey(k)); }; // Importing a private key in PKCS#8 format must fail when id-ecPublicKey is // given (so we know it's an EC key) but the namedCurve parameter is unknown. TEST_F(Pkcs11EcdsaSha256Test, ImportInvalidAlgorithmParams) { - EXPECT_FALSE(ImportPrivateKey(kP256Pkcs8InvalidAlgorithmParams, - sizeof(kP256Pkcs8InvalidAlgorithmParams))); + DataBuffer k(kP256Pkcs8InvalidAlgorithmParams, + sizeof(kP256Pkcs8InvalidAlgorithmParams)); + EXPECT_FALSE(ImportPrivateKey(k)); }; // Importing a private key in PKCS#8 format with a point not on the curve will // succeed. Using the contained public key however will fail when trying to // import it before using it for any operation. TEST_F(Pkcs11EcdsaSha256Test, ImportPointNotOnCurve) { - ScopedSECKEYPrivateKey privKey(ImportPrivateKey( - kP256Pkcs8PointNotOnCurve, sizeof(kP256Pkcs8PointNotOnCurve))); + DataBuffer k(kP256Pkcs8PointNotOnCurve, sizeof(kP256Pkcs8PointNotOnCurve)); + ScopedSECKEYPrivateKey privKey(ImportPrivateKey(k)); ASSERT_TRUE(privKey); ScopedSECKEYPublicKey pubKey(SECKEY_ConvertToPublicKey(privKey.get())); ASSERT_TRUE(pubKey); ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); ASSERT_TRUE(slot); auto handle = PK11_ImportPublicKey(slot.get(), pubKey.get(), false); EXPECT_EQ(handle, static_cast<decltype(handle)>(CK_INVALID_HANDLE)); }; // Importing a private key in PKCS#8 format must fail when no point is given. // PK11 currently offers no APIs to derive raw public keys from private values. TEST_F(Pkcs11EcdsaSha256Test, ImportNoPublicKey) { - EXPECT_FALSE( - ImportPrivateKey(kP256Pkcs8NoPublicKey, sizeof(kP256Pkcs8NoPublicKey))); + DataBuffer k(kP256Pkcs8NoPublicKey, sizeof(kP256Pkcs8NoPublicKey)); + EXPECT_FALSE(ImportPrivateKey(k)); }; // Importing a public key in SPKI format must fail when id-ecPublicKey is // given (so we know it's an EC key) but the namedCurve parameter is missing. TEST_F(Pkcs11EcdsaSha256Test, ImportSpkiNoAlgorithmParams) { - EXPECT_FALSE(ImportPublicKey(kP256SpkiNoAlgorithmParams, - sizeof(kP256SpkiNoAlgorithmParams))); + DataBuffer k(kP256SpkiNoAlgorithmParams, sizeof(kP256SpkiNoAlgorithmParams)); + EXPECT_FALSE(ImportPublicKey(k)); } // Importing a public key in SPKI format with a point not on the curve will // succeed. Using the public key however will fail when trying to import // it before using it for any operation. TEST_F(Pkcs11EcdsaSha256Test, ImportSpkiPointNotOnCurve) { - ScopedSECKEYPublicKey pubKey(ImportPublicKey( - kP256SpkiPointNotOnCurve, sizeof(kP256SpkiPointNotOnCurve))); + DataBuffer k(kP256SpkiPointNotOnCurve, sizeof(kP256SpkiPointNotOnCurve)); + ScopedSECKEYPublicKey pubKey(ImportPublicKey(k)); ASSERT_TRUE(pubKey); ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); ASSERT_TRUE(slot); auto handle = PK11_ImportPublicKey(slot.get(), pubKey.get(), false); EXPECT_EQ(handle, static_cast<decltype(handle)>(CK_INVALID_HANDLE)); }
--- a/security/nss/gtests/pk11_gtest/pk11_rsapss_unittest.cc +++ b/security/nss/gtests/pk11_gtest/pk11_rsapss_unittest.cc @@ -7,44 +7,42 @@ #include <memory> #include "nss.h" #include "pk11pub.h" #include "sechash.h" #include "gtest/gtest.h" #include "scoped_ptrs.h" +#include "pk11_signature_test.h" #include "pk11_rsapss_vectors.h" -#include "pk11_signature_test.h" namespace nss_test { -class Pkcs11RsaPssVectorTest : public Pk11SignatureTest { +class Pkcs11RsaPssTest : public Pk11SignatureTest { public: - Pkcs11RsaPssVectorTest() { + Pkcs11RsaPssTest() : Pk11SignatureTest(CKM_RSA_PKCS_PSS, SEC_OID_SHA1) { rsaPssParams_.hashAlg = CKM_SHA_1; rsaPssParams_.mgf = CKG_MGF1_SHA1; rsaPssParams_.sLen = HASH_ResultLenByOidTag(SEC_OID_SHA1); params_.type = siBuffer; params_.data = reinterpret_cast<unsigned char*>(&rsaPssParams_); params_.len = sizeof(rsaPssParams_); } protected: - CK_MECHANISM_TYPE mechanism() { return CKM_RSA_PKCS_PSS; } - SECItem* parameters() { return ¶ms_; } - SECOidTag hashOID() { return SEC_OID_SHA1; } + const SECItem* parameters() const { return ¶ms_; } private: CK_RSA_PKCS_PSS_PARAMS rsaPssParams_; SECItem params_; }; -TEST_F(Pkcs11RsaPssVectorTest, GenerateAndSignAndVerify) { +TEST_F(Pkcs11RsaPssTest, GenerateAndSignAndVerify) { // Sign data with a 1024-bit RSA key, using PSS/SHA-256. SECOidTag hashOid = SEC_OID_SHA256; CK_MECHANISM_TYPE hashMech = CKM_SHA256; CK_RSA_PKCS_MGF_TYPE mgf = CKG_MGF1_SHA256; PK11RSAGenParams rsaGenParams = {1024, 0x10001}; // Generate RSA key pair. ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); @@ -90,110 +88,61 @@ TEST_F(Pkcs11RsaPssVectorTest, GenerateA // Verification with original data but the wrong signature must fail. data.data[0] ^= 0xff; // Revert previous changes. sig.data[0] ^= 0xff; rv = PK11_VerifyWithMechanism(pubKey.get(), mechanism(), ¶ms, &sig, &data, nullptr); EXPECT_EQ(rv, SECFailure); } -// RSA-PSS test vectors, pss-vect.txt, Example 1.1: A 1024-bit RSA Key Pair -// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> -TEST_F(Pkcs11RsaPssVectorTest, VerifyKnownSignature1) { - SIG_TEST_VECTOR_VERIFY(kTestVector1Spki, kTestVector1Data, kTestVector1Sig); -} -TEST_F(Pkcs11RsaPssVectorTest, SignAndVerify1) { - SIG_TEST_VECTOR_SIGN_VERIFY(kTestVector1Pkcs8, kTestVector1Spki, - kTestVector1Data); -} +class Pkcs11RsaPssVectorTest + : public Pkcs11RsaPssTest, + public ::testing::WithParamInterface<Pkcs11SignatureTestParams> {}; -// RSA-PSS test vectors, pss-vect.txt, Example 2.1: A 1025-bit RSA Key Pair -// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> -TEST_F(Pkcs11RsaPssVectorTest, VerifyKnownSignature2) { - SIG_TEST_VECTOR_VERIFY(kTestVector2Spki, kTestVector2Data, kTestVector2Sig); -} -TEST_F(Pkcs11RsaPssVectorTest, SignAndVerify2) { - SIG_TEST_VECTOR_SIGN_VERIFY(kTestVector2Pkcs8, kTestVector2Spki, - kTestVector2Data); -} +TEST_P(Pkcs11RsaPssVectorTest, Verify) { Verify(GetParam()); } + +TEST_P(Pkcs11RsaPssVectorTest, SignAndVerify) { SignAndVerify(GetParam()); } -// RSA-PSS test vectors, pss-vect.txt, Example 3.1: A 1026-bit RSA Key Pair -// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> -TEST_F(Pkcs11RsaPssVectorTest, VerifyKnownSignature3) { - SIG_TEST_VECTOR_VERIFY(kTestVector3Spki, kTestVector3Data, kTestVector3Sig); -} -TEST_F(Pkcs11RsaPssVectorTest, SignAndVerify3) { - SIG_TEST_VECTOR_SIGN_VERIFY(kTestVector3Pkcs8, kTestVector3Spki, - kTestVector3Data); -} - -// RSA-PSS test vectors, pss-vect.txt, Example 4.1: A 1027-bit RSA Key Pair -// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> -TEST_F(Pkcs11RsaPssVectorTest, VerifyKnownSignature4) { - SIG_TEST_VECTOR_VERIFY(kTestVector4Spki, kTestVector4Data, kTestVector4Sig); -} -TEST_F(Pkcs11RsaPssVectorTest, SignAndVerify4) { - SIG_TEST_VECTOR_SIGN_VERIFY(kTestVector4Pkcs8, kTestVector4Spki, - kTestVector4Data); -} - -// RSA-PSS test vectors, pss-vect.txt, Example 5.1: A 1028-bit RSA Key Pair -// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> -TEST_F(Pkcs11RsaPssVectorTest, VerifyKnownSignature5) { - SIG_TEST_VECTOR_VERIFY(kTestVector5Spki, kTestVector5Data, kTestVector5Sig); -} -TEST_F(Pkcs11RsaPssVectorTest, SignAndVerify5) { - SIG_TEST_VECTOR_SIGN_VERIFY(kTestVector5Pkcs8, kTestVector5Spki, - kTestVector5Data); -} +#define VECTOR(pkcs8, spki, data, sig) \ + { \ + DataBuffer(pkcs8, sizeof(pkcs8)), DataBuffer(spki, sizeof(spki)), \ + DataBuffer(data, sizeof(data)), DataBuffer(sig, sizeof(sig)) \ + } +#define VECTOR_N(n) \ + VECTOR(kTestVector##n##Pkcs8, kTestVector##n##Spki, kTestVector##n##Data, \ + kTestVector##n##Sig) -// RSA-PSS test vectors, pss-vect.txt, Example 6.1: A 1029-bit RSA Key Pair -// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> -TEST_F(Pkcs11RsaPssVectorTest, VerifyKnownSignature6) { - SIG_TEST_VECTOR_VERIFY(kTestVector6Spki, kTestVector6Data, kTestVector6Sig); -} -TEST_F(Pkcs11RsaPssVectorTest, SignAndVerify6) { - SIG_TEST_VECTOR_SIGN_VERIFY(kTestVector6Pkcs8, kTestVector6Spki, - kTestVector6Data); -} - -// RSA-PSS test vectors, pss-vect.txt, Example 7.1: A 1030-bit RSA Key Pair -// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> -TEST_F(Pkcs11RsaPssVectorTest, VerifyKnownSignature7) { - SIG_TEST_VECTOR_VERIFY(kTestVector7Spki, kTestVector7Data, kTestVector7Sig); -} -TEST_F(Pkcs11RsaPssVectorTest, SignAndVerify7) { - SIG_TEST_VECTOR_SIGN_VERIFY(kTestVector7Pkcs8, kTestVector7Spki, - kTestVector7Data); -} +static const Pkcs11SignatureTestParams kRsaPssVectors[] = { + // RSA-PSS test vectors, pss-vect.txt, Example 1.1: A 1024-bit RSA Key Pair + // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> + VECTOR_N(1), + // RSA-PSS test vectors, pss-vect.txt, Example 2.1: A 1025-bit RSA Key Pair + // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> + VECTOR_N(2), + // RSA-PSS test vectors, pss-vect.txt, Example 3.1: A 1026-bit RSA Key Pair + // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> + VECTOR_N(3), + // RSA-PSS test vectors, pss-vect.txt, Example 4.1: A 1027-bit RSA Key Pair + // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> + VECTOR_N(4), + // RSA-PSS test vectors, pss-vect.txt, Example 5.1: A 1028-bit RSA Key Pair + // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> + VECTOR_N(5), + // RSA-PSS test vectors, pss-vect.txt, Example 6.1: A 1029-bit RSA Key Pair + // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> + VECTOR_N(6), + // RSA-PSS test vectors, pss-vect.txt, Example 7.1: A 1030-bit RSA Key Pair + // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> + VECTOR_N(7), + // RSA-PSS test vectors, pss-vect.txt, Example 8.1: A 1031-bit RSA Key Pair + // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> + VECTOR_N(8), + // RSA-PSS test vectors, pss-vect.txt, Example 9.1: A 1536-bit RSA Key Pair + // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> + VECTOR_N(9), + // RSA-PSS test vectors, pss-vect.txt, Example 10.1: A 2048-bit RSA Key Pair + // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> + VECTOR_N(10)}; -// RSA-PSS test vectors, pss-vect.txt, Example 8.1: A 1031-bit RSA Key Pair -// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> -TEST_F(Pkcs11RsaPssVectorTest, VerifyKnownSignature8) { - SIG_TEST_VECTOR_VERIFY(kTestVector8Spki, kTestVector8Data, kTestVector8Sig); -} -TEST_F(Pkcs11RsaPssVectorTest, SignAndVerify8) { - SIG_TEST_VECTOR_SIGN_VERIFY(kTestVector8Pkcs8, kTestVector8Spki, - kTestVector8Data); -} - -// RSA-PSS test vectors, pss-vect.txt, Example 9.1: A 1536-bit RSA Key Pair -// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> -TEST_F(Pkcs11RsaPssVectorTest, VerifyKnownSignature9) { - SIG_TEST_VECTOR_VERIFY(kTestVector9Spki, kTestVector9Data, kTestVector9Sig); -} -TEST_F(Pkcs11RsaPssVectorTest, SignAndVerify9) { - SIG_TEST_VECTOR_SIGN_VERIFY(kTestVector9Pkcs8, kTestVector9Spki, - kTestVector9Data); -} - -// RSA-PSS test vectors, pss-vect.txt, Example 10.1: A 2048-bit RSA Key Pair -// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip> -TEST_F(Pkcs11RsaPssVectorTest, VerifyKnownSignature10) { - SIG_TEST_VECTOR_VERIFY(kTestVector10Spki, kTestVector10Data, - kTestVector10Sig); -} -TEST_F(Pkcs11RsaPssVectorTest, SignAndVerify10) { - SIG_TEST_VECTOR_SIGN_VERIFY(kTestVector10Pkcs8, kTestVector10Spki, - kTestVector10Data); -} +INSTANTIATE_TEST_CASE_P(RsaPssSignVerify, Pkcs11RsaPssVectorTest, + ::testing::ValuesIn(kRsaPssVectors)); } // namespace nss_test
--- a/security/nss/gtests/pk11_gtest/pk11_signature_test.h +++ b/security/nss/gtests/pk11_gtest/pk11_signature_test.h @@ -4,135 +4,133 @@ #include <memory> #include "nss.h" #include "pk11pub.h" #include "sechash.h" #include "cpputil.h" #include "scoped_ptrs.h" +#include "databuffer.h" #include "gtest/gtest.h" namespace nss_test { +// For test vectors. +struct Pkcs11SignatureTestParams { + const DataBuffer pkcs8_; + const DataBuffer spki_; + const DataBuffer data_; + const DataBuffer signature_; +}; + class Pk11SignatureTest : public ::testing::Test { protected: - virtual CK_MECHANISM_TYPE mechanism() = 0; - virtual SECItem* parameters() = 0; - virtual SECOidTag hashOID() = 0; + Pk11SignatureTest(CK_MECHANISM_TYPE mechanism, SECOidTag hash_oid) + : mechanism_(mechanism), hash_oid_(hash_oid) {} - ScopedSECKEYPrivateKey ImportPrivateKey(const uint8_t* pkcs8, - size_t pkcs8_len) { + virtual const SECItem* parameters() const { return nullptr; } + CK_MECHANISM_TYPE mechanism() const { return mechanism_; } + + ScopedSECKEYPrivateKey ImportPrivateKey(const DataBuffer& pkcs8) { ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); if (!slot) { + ADD_FAILURE() << "No slot"; return nullptr; } - SECItem pkcs8Item = {siBuffer, toUcharPtr(pkcs8), - static_cast<unsigned int>(pkcs8_len)}; + SECItem pkcs8Item = {siBuffer, toUcharPtr(pkcs8.data()), + static_cast<unsigned int>(pkcs8.len())}; SECKEYPrivateKey* key = nullptr; SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( slot.get(), &pkcs8Item, nullptr, nullptr, false, false, KU_ALL, &key, nullptr); if (rv != SECSuccess) { return nullptr; } return ScopedSECKEYPrivateKey(key); } - ScopedSECKEYPublicKey ImportPublicKey(const uint8_t* spki, size_t spki_len) { - SECItem spkiItem = {siBuffer, toUcharPtr(spki), - static_cast<unsigned int>(spki_len)}; + ScopedSECKEYPublicKey ImportPublicKey(const DataBuffer& spki) { + SECItem spkiItem = {siBuffer, toUcharPtr(spki.data()), + static_cast<unsigned int>(spki.len())}; ScopedCERTSubjectPublicKeyInfo certSpki( SECKEY_DecodeDERSubjectPublicKeyInfo(&spkiItem)); return ScopedSECKEYPublicKey(SECKEY_ExtractPublicKey(certSpki.get())); } - ScopedSECItem ComputeHash(const uint8_t* data, size_t len) { - unsigned int hLen = HASH_ResultLenByOidTag(hashOID()); - ScopedSECItem hash(SECITEM_AllocItem(nullptr, nullptr, hLen)); - if (!hash) { - return nullptr; - } - - SECStatus rv = PK11_HashBuf(hashOID(), hash->data, data, len); - if (rv != SECSuccess) { - return nullptr; - } - - return hash; + bool ComputeHash(const DataBuffer& data, DataBuffer* hash) { + hash->Allocate(static_cast<size_t>(HASH_ResultLenByOidTag(hash_oid_))); + SECStatus rv = + PK11_HashBuf(hash_oid_, hash->data(), data.data(), data.len()); + return rv == SECSuccess; } - ScopedSECItem SignHashedData(ScopedSECKEYPrivateKey& privKey, - ScopedSECItem& hash) { - unsigned int sLen = PK11_SignatureLen(privKey.get()); - ScopedSECItem sig(SECITEM_AllocItem(nullptr, nullptr, sLen)); - if (!sig) { - return nullptr; - } - - SECStatus rv = PK11_SignWithMechanism(privKey.get(), mechanism(), - parameters(), sig.get(), hash.get()); - if (rv != SECSuccess) { - return nullptr; - } - - return sig; + bool SignHashedData(ScopedSECKEYPrivateKey& privKey, const DataBuffer& hash, + DataBuffer* sig) { + SECItem hashItem = {siBuffer, toUcharPtr(hash.data()), + static_cast<unsigned int>(hash.len())}; + int sigLen = PK11_SignatureLen(privKey.get()); + EXPECT_LT(0, sigLen); + sig->Allocate(static_cast<size_t>(sigLen)); + SECItem sigItem = {siBuffer, toUcharPtr(sig->data()), + static_cast<unsigned int>(sig->len())}; + SECStatus rv = PK11_SignWithMechanism(privKey.get(), mechanism_, + parameters(), &sigItem, &hashItem); + return rv == SECSuccess; } - ScopedSECItem ImportPrivateKeyAndSignHashedData(const uint8_t* pkcs8, - size_t pkcs8_len, - const uint8_t* data, - size_t data_len) { - ScopedSECKEYPrivateKey privKey(ImportPrivateKey(pkcs8, pkcs8_len)); + bool ImportPrivateKeyAndSignHashedData(const DataBuffer& pkcs8, + const DataBuffer& data, + DataBuffer* sig) { + ScopedSECKEYPrivateKey privKey(ImportPrivateKey(pkcs8)); if (!privKey) { - return nullptr; - } - - ScopedSECItem hash(ComputeHash(data, data_len)); - if (!hash) { - return nullptr; + return false; } - return ScopedSECItem(SignHashedData(privKey, hash)); + DataBuffer hash; + if (!ComputeHash(data, &hash)) { + ADD_FAILURE() << "Failed to compute hash"; + return false; + } + return SignHashedData(privKey, hash, sig); } - void Verify(const uint8_t* spki, size_t spki_len, const uint8_t* data, - size_t data_len, const uint8_t* sig, size_t sig_len) { - ScopedSECKEYPublicKey pubKey(ImportPublicKey(spki, spki_len)); + void Verify(const Pkcs11SignatureTestParams& params, const DataBuffer& sig) { + ScopedSECKEYPublicKey pubKey(ImportPublicKey(params.spki_)); ASSERT_TRUE(pubKey); - ScopedSECItem hash(ComputeHash(data, data_len)); - ASSERT_TRUE(hash); - - SECItem sigItem = {siBuffer, toUcharPtr(sig), - static_cast<unsigned int>(sig_len)}; + DataBuffer hash; + ASSERT_TRUE(ComputeHash(params.data_, &hash)); // Verify. + SECItem hashItem = {siBuffer, toUcharPtr(hash.data()), + static_cast<unsigned int>(hash.len())}; + SECItem sigItem = {siBuffer, toUcharPtr(sig.data()), + static_cast<unsigned int>(sig.len())}; SECStatus rv = PK11_VerifyWithMechanism( - pubKey.get(), mechanism(), parameters(), &sigItem, hash.get(), nullptr); + pubKey.get(), mechanism_, parameters(), &sigItem, &hashItem, nullptr); EXPECT_EQ(rv, SECSuccess); } - void SignAndVerify(const uint8_t* pkcs8, size_t pkcs8_len, - const uint8_t* spki, size_t spki_len, const uint8_t* data, - size_t data_len) { - ScopedSECItem sig( - ImportPrivateKeyAndSignHashedData(pkcs8, pkcs8_len, data, data_len)); - ASSERT_TRUE(sig); + void Verify(const Pkcs11SignatureTestParams& params) { + Verify(params, params.signature_); + } - Verify(spki, spki_len, data, data_len, sig->data, sig->len); + void SignAndVerify(const Pkcs11SignatureTestParams& params) { + DataBuffer sig; + ASSERT_TRUE( + ImportPrivateKeyAndSignHashedData(params.pkcs8_, params.data_, &sig)); + Verify(params, sig); } + + private: + CK_MECHANISM_TYPE mechanism_; + SECOidTag hash_oid_; }; -#define SIG_TEST_VECTOR_VERIFY(spki, data, sig) \ - Verify(spki, sizeof(spki), data, sizeof(data), sig, sizeof(sig)); - -#define SIG_TEST_VECTOR_SIGN_VERIFY(pkcs8, spki, data) \ - SignAndVerify(pkcs8, sizeof(pkcs8), spki, sizeof(spki), data, sizeof(data)); - } // namespace nss_test
--- a/security/nss/gtests/softoken_gtest/softoken_gtest.cc +++ b/security/nss/gtests/softoken_gtest/softoken_gtest.cc @@ -1,10 +1,12 @@ #include <cstdlib> +#include "cert.h" +#include "certdb.h" #include "nspr.h" #include "nss.h" #include "pk11pub.h" #include "secerr.h" #include "scoped_ptrs.h" #define GTEST_HAS_RTTI 0 @@ -195,16 +197,120 @@ TEST_F(SoftokenTest, CreateObjectChangeT EXPECT_EQ(SEC_ERROR_TOKEN_NOT_LOGGED_IN, PORT_GetError()); ScopedPK11GenericObject obj(PK11_CreateGenericObject( slot.get(), attributes, PR_ARRAY_SIZE(attributes), true)); // Because there's no password we can't logout and the operation should have // succeeded. EXPECT_NE(nullptr, obj); } +// This is just any X509 certificate. Its contents don't matter. +static unsigned char certDER[] = { + 0x30, 0x82, 0x01, 0xEF, 0x30, 0x82, 0x01, 0x94, 0xA0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x14, 0x49, 0xC4, 0xC4, 0x4A, 0xB6, 0x86, 0x07, 0xA3, 0x06, + 0xDC, 0x4D, 0xC8, 0xC3, 0xFE, 0xC7, 0x21, 0x3A, 0x2D, 0xE4, 0xDA, 0x30, + 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, + 0x30, 0x0F, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x04, 0x74, 0x65, 0x73, 0x74, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, + 0x35, 0x31, 0x31, 0x32, 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, + 0x18, 0x0F, 0x32, 0x30, 0x31, 0x38, 0x30, 0x32, 0x30, 0x35, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x5A, 0x30, 0x0F, 0x31, 0x0D, 0x30, 0x0B, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x04, 0x74, 0x65, 0x73, 0x74, 0x30, 0x82, + 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, + 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xBA, 0x88, 0x51, 0xA8, 0x44, + 0x8E, 0x16, 0xD6, 0x41, 0xFD, 0x6E, 0xB6, 0x88, 0x06, 0x36, 0x10, 0x3D, + 0x3C, 0x13, 0xD9, 0xEA, 0xE4, 0x35, 0x4A, 0xB4, 0xEC, 0xF5, 0x68, 0x57, + 0x6C, 0x24, 0x7B, 0xC1, 0xC7, 0x25, 0xA8, 0xE0, 0xD8, 0x1F, 0xBD, 0xB1, + 0x9C, 0x06, 0x9B, 0x6E, 0x1A, 0x86, 0xF2, 0x6B, 0xE2, 0xAF, 0x5A, 0x75, + 0x6B, 0x6A, 0x64, 0x71, 0x08, 0x7A, 0xA5, 0x5A, 0xA7, 0x45, 0x87, 0xF7, + 0x1C, 0xD5, 0x24, 0x9C, 0x02, 0x7E, 0xCD, 0x43, 0xFC, 0x1E, 0x69, 0xD0, + 0x38, 0x20, 0x29, 0x93, 0xAB, 0x20, 0xC3, 0x49, 0xE4, 0xDB, 0xB9, 0x4C, + 0xC2, 0x6B, 0x6C, 0x0E, 0xED, 0x15, 0x82, 0x0F, 0xF1, 0x7E, 0xAD, 0x69, + 0x1A, 0xB1, 0xD3, 0x02, 0x3A, 0x8B, 0x2A, 0x41, 0xEE, 0xA7, 0x70, 0xE0, + 0x0F, 0x0D, 0x8D, 0xFD, 0x66, 0x0B, 0x2B, 0xB0, 0x24, 0x92, 0xA4, 0x7D, + 0xB9, 0x88, 0x61, 0x79, 0x90, 0xB1, 0x57, 0x90, 0x3D, 0xD2, 0x3B, 0xC5, + 0xE0, 0xB8, 0x48, 0x1F, 0xA8, 0x37, 0xD3, 0x88, 0x43, 0xEF, 0x27, 0x16, + 0xD8, 0x55, 0xB7, 0x66, 0x5A, 0xAA, 0x7E, 0x02, 0x90, 0x2F, 0x3A, 0x7B, + 0x10, 0x80, 0x06, 0x24, 0xCC, 0x1C, 0x6C, 0x97, 0xAD, 0x96, 0x61, 0x5B, + 0xB7, 0xE2, 0x96, 0x12, 0xC0, 0x75, 0x31, 0xA3, 0x0C, 0x91, 0xDD, 0xB4, + 0xCA, 0xF7, 0xFC, 0xAD, 0x1D, 0x25, 0xD3, 0x09, 0xEF, 0xB9, 0x17, 0x0E, + 0xA7, 0x68, 0xE1, 0xB3, 0x7B, 0x2F, 0x22, 0x6F, 0x69, 0xE3, 0xB4, 0x8A, + 0x95, 0x61, 0x1D, 0xEE, 0x26, 0xD6, 0x25, 0x9D, 0xAB, 0x91, 0x08, 0x4E, + 0x36, 0xCB, 0x1C, 0x24, 0x04, 0x2C, 0xBF, 0x16, 0x8B, 0x2F, 0xE5, 0xF1, + 0x8F, 0x99, 0x17, 0x31, 0xB8, 0xB3, 0xFE, 0x49, 0x23, 0xFA, 0x72, 0x51, + 0xC4, 0x31, 0xD5, 0x03, 0xAC, 0xDA, 0x18, 0x0A, 0x35, 0xED, 0x8D, 0x02, + 0x03, 0x01, 0x00, 0x01, 0x30, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, + 0x5C, 0x75, 0x51, 0x9F, 0x13, 0x11, 0x50, 0xCD, 0x5D, 0x8A, 0xDE, 0x20, + 0xA3, 0xBC, 0x06, 0x30, 0x91, 0xFF, 0xB2, 0x73, 0x75, 0x5F, 0x31, 0x64, + 0xEC, 0xFD, 0xCB, 0x42, 0x80, 0x0A, 0x70, 0xE6, 0x02, 0x21, 0x00, 0x82, + 0x12, 0xF7, 0xE5, 0xEA, 0x40, 0x27, 0xFD, 0xF7, 0xC0, 0x0E, 0x25, 0xF3, + 0x3E, 0x34, 0x95, 0x80, 0xB9, 0xA3, 0x38, 0xE0, 0x56, 0x68, 0xDA, 0xE5, + 0xC1, 0xF5, 0x37, 0xC7, 0xB5, 0xCE, 0x0D}; + +struct PasswordPair { + const char *mInitialPassword; + const char *mSecondPassword; +}; + +class SoftokenPasswordChangeTest + : public SoftokenTest, + public ::testing::WithParamInterface<PasswordPair> {}; + +TEST_P(SoftokenPasswordChangeTest, KeepTrustAfterPasswordChange) { + const PasswordPair &passwords = GetParam(); + ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); + ASSERT_TRUE(slot); + // Set a password. + EXPECT_EQ(SECSuccess, + PK11_InitPin(slot.get(), nullptr, passwords.mInitialPassword)); + SECItem certDERItem = {siBuffer, certDER, sizeof(certDER)}; + // Import a certificate. + ScopedCERTCertificate cert(CERT_NewTempCertificate( + CERT_GetDefaultCertDB(), &certDERItem, nullptr, true, true)); + EXPECT_TRUE(cert); + SECStatus result = + PK11_ImportCert(slot.get(), cert.get(), CK_INVALID_HANDLE, "test", false); + EXPECT_EQ(SECSuccess, result); + // Set a trust value. + CERTCertTrust trust = {CERTDB_TRUSTED_CLIENT_CA | CERTDB_NS_TRUSTED_CA | + CERTDB_TRUSTED_CA | CERTDB_VALID_CA, + 0, 0}; + result = CERT_ChangeCertTrust(nullptr, cert.get(), &trust); + EXPECT_EQ(SECSuccess, result); + // Release the certificate to ensure we get it from the DB rather than an + // in-memory cache, below. + cert = nullptr; + // Change the password. + result = PK11_ChangePW(slot.get(), passwords.mInitialPassword, + passwords.mSecondPassword); + EXPECT_EQ(SECSuccess, result); + // Look up the certificate again. + ScopedCERTCertificate newCert( + PK11_FindCertFromDERCertItem(slot.get(), &certDERItem, nullptr)); + EXPECT_TRUE(newCert.get()); + // The trust should be the same as before. + CERTCertTrust newTrust = {0, 0, 0}; + result = CERT_GetCertTrust(newCert.get(), &newTrust); + EXPECT_EQ(SECSuccess, result); + EXPECT_EQ(trust.sslFlags, newTrust.sslFlags); + EXPECT_EQ(trust.emailFlags, newTrust.emailFlags); + EXPECT_EQ(trust.objectSigningFlags, newTrust.objectSigningFlags); +} + +static const PasswordPair PASSWORD_CHANGE_TESTS[] = { + {"password", ""}, // non-empty to empty password + {"", "password"}, // empty to non-empty password + {"password", "password2"}, // non-empty to non-empty password +}; + +INSTANTIATE_TEST_CASE_P(SoftokenPasswordChangeTests, SoftokenPasswordChangeTest, + ::testing::ValuesIn(PASSWORD_CHANGE_TESTS)); + class SoftokenNoDBTest : public ::testing::Test {}; TEST_F(SoftokenNoDBTest, NeedUserInitNoDB) { ASSERT_EQ(SECSuccess, NSS_NoDB_Init(".")); ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); ASSERT_TRUE(slot); EXPECT_EQ(PR_FALSE, PK11_NeedUserInit(slot.get()));
--- a/security/nss/lib/softoken/sftkdb.c +++ b/security/nss/lib/softoken/sftkdb.c @@ -35,17 +35,17 @@ * are endian/length independent except those attributes that pass CK_ULONG. * * The following functions fixes up the CK_ULONG type attributes so that the data * base sees a machine independent view. CK_ULONGs are stored as 4 byte network * byte order values (big endian). */ #define BBP 8 -static PRBool +PRBool sftkdb_isULONGAttribute(CK_ATTRIBUTE_TYPE type) { switch (type) { case CKA_CERTIFICATE_CATEGORY: case CKA_CERTIFICATE_TYPE: case CKA_CLASS: case CKA_JAVA_MIDP_SECURITY_DOMAIN: case CKA_KEY_GEN_MECHANISM: @@ -1365,34 +1365,35 @@ sftkdb_SetAttributeValue(SFTKDBHandle *h } ntemplate = sftkdb_fixupTemplateIn(template, count, &data); if (ntemplate == NULL) { return CKR_HOST_MEMORY; } /* make sure we don't have attributes that conflict with the existing DB */ - crv = sftkdb_checkConflicts(db, object->objclass, template, count, objectID); + crv = sftkdb_checkConflicts(db, object->objclass, ntemplate, count, + objectID); if (crv != CKR_OK) { goto loser; } arena = PORT_NewArena(256); if (arena == NULL) { crv = CKR_HOST_MEMORY; goto loser; } crv = (*db->sdb_Begin)(db); if (crv != CKR_OK) { goto loser; } inTransaction = PR_TRUE; - crv = sftkdb_setAttributeValue(arena, handle, db, - objectID, template, count); + crv = sftkdb_setAttributeValue(arena, handle, db, objectID, ntemplate, + count); if (crv != CKR_OK) { goto loser; } crv = (*db->sdb_Commit)(db); loser: if (crv != CKR_OK && inTransaction) { (*db->sdb_Abort)(db); }
--- a/security/nss/lib/softoken/sftkdbti.h +++ b/security/nss/lib/softoken/sftkdbti.h @@ -44,15 +44,16 @@ SECStatus sftkdb_SignAttribute(PLArenaPo CK_OBJECT_HANDLE objectID, CK_ATTRIBUTE_TYPE attrType, SECItem *plainText, SECItem **sigText); SECStatus sftkdb_VerifyAttribute(SECItem *passKey, CK_OBJECT_HANDLE objectID, CK_ATTRIBUTE_TYPE attrType, SECItem *plainText, SECItem *sigText); +PRBool sftkdb_isULONGAttribute(CK_ATTRIBUTE_TYPE type); void sftk_ULong2SDBULong(unsigned char *data, CK_ULONG value); CK_RV sftkdb_Update(SFTKDBHandle *handle, SECItem *key); CK_RV sftkdb_PutAttributeSignature(SFTKDBHandle *handle, SDB *keyTarget, CK_OBJECT_HANDLE objectID, CK_ATTRIBUTE_TYPE type, SECItem *signText); #endif
--- a/security/nss/lib/softoken/sftkpwd.c +++ b/security/nss/lib/softoken/sftkpwd.c @@ -921,16 +921,23 @@ sftk_updateMacs(PLArenaPool *arena, SFTK SECItem *signText; SECItem plainText; SECStatus rv; if ((authAttrs[i].ulValueLen == -1) || (authAttrs[i].ulValueLen == 0)) { continue; } + if (authAttrs[i].ulValueLen == sizeof(CK_ULONG) && + sftkdb_isULONGAttribute(authAttrs[i].type)) { + CK_ULONG value = *(CK_ULONG *)authAttrs[i].pValue; + sftk_ULong2SDBULong(authAttrs[i].pValue, value); + authAttrs[i].ulValueLen = SDB_ULONG_SIZE; + } + plainText.data = authAttrs[i].pValue; plainText.len = authAttrs[i].ulValueLen; rv = sftkdb_SignAttribute(arena, newKey, id, authAttrs[i].type, &plainText, &signText); if (rv != SECSuccess) { return CKR_GENERAL_ERROR; } rv = sftkdb_PutAttributeSignature(handle, keyTarget, id,
--- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp +++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp @@ -33,20 +33,16 @@ // processes and so they will be unloaded if they attempt to load. const std::vector<std::wstring> kDllsToUnload = { // HitmanPro - SurfRight now part of Sophos (bug 1400637) L"hmpalert.dll", // K7 Computing (bug 1400637) L"k7pswsen.dll", - // Symantec (bug 1400637) - L"prntm64.dll", - L"sysfer.dll", - // Avast Antivirus (bug 1400637) L"snxhk64.dll", L"snxhk.dll", // Webroot SecureAnywhere (bug 1400637) L"wrusr.dll", };
--- a/services/sync/modules/engines/history.js +++ b/services/sync/modules/engines/history.js @@ -240,26 +240,27 @@ HistoryStore.prototype = { + record.uri.spec + ": can't add this URI."); return false; } // We dupe visits by date and type. So an incoming visit that has // the same timestamp and type as a local one won't get applied. // To avoid creating new objects, we rewrite the query result so we // can simply check for containment below. - let curVisits = []; + let curVisitsAsArray = []; + let curVisits = new Set(); try { - curVisits = await PlacesSyncUtils.history.fetchVisitsForURL(record.histUri); + curVisitsAsArray = await PlacesSyncUtils.history.fetchVisitsForURL(record.histUri); } catch (e) { this._log.error("Error while fetching visits for URL ${record.histUri}", record.histUri); } let i, k; - for (i = 0; i < curVisits.length; i++) { - curVisits[i] = curVisits[i].date + "," + curVisits[i].type; + for (i = 0; i < curVisitsAsArray.length; i++) { + curVisits.add(curVisitsAsArray[i].date + "," + curVisitsAsArray[i].type); } // Walk through the visits, make sure we have sound data, and eliminate // dupes. The latter is done by rewriting the array in-place. for (i = 0, k = 0; i < record.visits.length; i++) { let visit = record.visits[k] = record.visits[i]; if (!visit.date || typeof visit.date != "number" || !Number.isInteger(visit.date)) { @@ -277,25 +278,25 @@ HistoryStore.prototype = { // Dates need to be integers. Future and far past dates are clamped to the // current date and earliest sensible date, respectively. let originalVisitDate = PlacesUtils.toDate(Math.round(visit.date)); visit.date = PlacesSyncUtils.history.clampVisitDate(originalVisitDate); let visitDateAsPRTime = PlacesUtils.toPRTime(visit.date); let visitKey = visitDateAsPRTime + "," + visit.type; - if (curVisits.indexOf(visitKey) != -1) { + if (curVisits.has(visitKey)) { // Visit is a dupe, don't increment 'k' so the element will be // overwritten. continue; } // Note the visit key, so that we don't add duplicate visits with // clamped timestamps. - curVisits.push(visitKey); + curVisits.add(visitKey); visit.transition = visit.type; k += 1; } record.visits.length = k; // truncate array // No update if there aren't any visits to apply. // mozIAsyncHistory::updatePlaces() wants at least one visit.
--- a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox.py +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox.py @@ -185,17 +185,18 @@ class FirefoxBrowser(Browser): self.profile = FirefoxProfile(locations=locations, preferences=preferences) self.profile.set_preferences({"marionette.port": self.marionette_port, "dom.disable_open_during_load": False, "network.dns.localDomains": ",".join(hostnames), "network.proxy.type": 0, "places.history.enabled": False, - "dom.send_after_paint_to_content": True}) + "dom.send_after_paint_to_content": True, + "network.preload": True}) if self.e10s: self.profile.set_preferences({"browser.tabs.remote.autostart": True}) if self.test_type == "reftest": self.profile.set_preferences({"layout.interruptible-reflow.enabled": False}) if self.leak_check and kwargs.get("check_leaks", True): self.leak_report_file = os.path.join(self.profile.profile, "runtests_leaks.log")
--- a/toolkit/components/extensions/ExtensionParent.jsm +++ b/toolkit/components/extensions/ExtensionParent.jsm @@ -766,29 +766,33 @@ ParentAPIManager = { async addListener(data, target) { let context = this.getContextById(data.childId); if (context.parentMessageManager !== target.messageManager) { throw new Error("Got message on unexpected message manager"); } let {childId} = data; let handlingUserInput = false; + let lowPriority = data.path.startsWith("webRequest."); function listener(...listenerArgs) { return context.sendMessage( context.parentMessageManager, "API:RunListener", { childId, handlingUserInput, listenerId: data.listenerId, path: data.path, - args: new StructuredCloneHolder(listenerArgs), + get args() { + return new StructuredCloneHolder(listenerArgs); + }, }, { + lowPriority, recipient: {childId}, }).then(result => { return result && result.deserialize(global); }); } context.listenerProxies.set(data.listenerId, listener);
--- a/toolkit/components/extensions/MessageChannel.jsm +++ b/toolkit/components/extensions/MessageChannel.jsm @@ -107,16 +107,62 @@ Cu.import("resource://gre/modules/Extens Cu.import("resource://gre/modules/Services.jsm"); const { MessageManagerProxy, } = ExtensionUtils; const {DEBUG} = AppConstants; +// Idle callback timeout for low-priority message dispatch. +const LOW_PRIORITY_TIMEOUT_MS = 250; + +const MESSAGE_MESSAGES = "MessageChannel:Messages"; +const MESSAGE_RESPONSE = "MessageChannel:Response"; + +// ESLint can't tell that these are referenced, so tell it that they're +// exported to make it happy. +/* exported _deferredResult, _makeDeferred */ +var _deferredResult; +var _makeDeferred = (resolve, reject) => { + // We use arrow functions here and refer to the outer variables via + // `this`, to avoid a lexical name lookup. Yes, it makes a difference. + // No, I don't like it any more than you do. + this._deferredResult.resolve = resolve; + this._deferredResult.reject = reject; +}; + +/** + * Helper to create a new Promise without allocating any closures to + * receive its resolution functions. + * + * I know what you're thinking: "This is crazy. There is no possible way + * this can be necessary. Just use the ordinary Promise constructor the + * way it was meant to be used, you lunatic." + * + * And, against all odds, it turns out that you're wrong. Creating + * lambdas to receive promise resolution functions consistently turns + * out to be one of the most expensive parts of message dispatch in this + * code. + * + * So we do the stupid micro-optimization, and try to live with + * ourselves for it. + * + * (See also bug 1404950.) + * + * @returns {object} + */ +let Deferred = () => { + let res = {}; + this._deferredResult = res; + res.promise = new Promise(this._makeDeferred); + this._deferredResult = null; + return res; +}; + /** * Handles the mapping and dispatching of messages to their registered * handlers. There is one broker per message manager and class of * messages. Each class of messages is mapped to one native message * name, e.g., "MessageChannel:Message", and is dispatched to handlers * based on an internal message name, e.g., "Extension:ExecuteScript". */ class FilteringMessageManager { @@ -144,42 +190,48 @@ class FilteringMessageManager { this.messageManager = messageManager; this.messageManager.addMessageListener(this.messageName, this, true); this.handlers = new Map(); } /** - * Receives a message from our message manager, maps it to a handler, and - * passes the result to our message callback. + * Receives a set of messages from our message manager, maps each to a + * handler, and passes the results to our message callbacks. */ receiveMessage({data, target}) { - let handlers = Array.from(this.getHandlers(data.messageName, data.sender || null, data.recipient)); + data.forEach(msg => { + if (msg) { + let handlers = Array.from(this.getHandlers(msg.messageName, + msg.sender || null, + msg.recipient)); - data.target = target; - this.callback(handlers, data); + msg.target = target; + this.callback(handlers, msg); + } + }); } /** * Iterates over all handlers for the given message name. If `recipient` * is provided, only iterates over handlers whose filters match it. * * @param {string|number} messageName * The message for which to return handlers. * @param {object} sender * The sender data on which to filter handlers. * @param {object} recipient * The recipient data on which to filter handlers. */ * getHandlers(messageName, sender, recipient) { let handlers = this.handlers.get(messageName) || new Set(); for (let handler of handlers) { - if (MessageChannel.matchesFilter(handler.messageFilterStrict || {}, recipient) && - MessageChannel.matchesFilter(handler.messageFilterPermissive || {}, recipient, false) && + if (MessageChannel.matchesFilter(handler.messageFilterStrict || null, recipient) && + MessageChannel.matchesFilter(handler.messageFilterPermissive || null, recipient, false) && (!handler.filterMessage || handler.filterMessage(sender, recipient))) { yield handler; } } } /** * Registers a handler for the given message. @@ -213,20 +265,96 @@ class FilteringMessageManager { removeHandler(messageName, handler) { if (this.handlers.has(messageName)) { this.handlers.get(messageName).delete(handler); } } } /** - * A simplified subclass of FilteringMessageManager that only supports - * one handler per message, and does not support filtering. + * A message dispatch and response manager that wrapse a single native + * message manager. Handles dispatching messages through the manager + * (optionally coalescing several low-priority messages and dispatching + * them during an idle slice), and mapping their responses to the + * appropriate response callbacks. + * + * Note that this is a simplified subclass of FilteringMessageManager + * that only supports one handler per message, and does not support + * filtering. */ class ResponseManager extends FilteringMessageManager { + constructor(messageName, callback, messageManager) { + super(messageName, callback, messageManager); + + this.idleMessages = []; + this.idleScheduled = false; + this.onIdle = this.onIdle.bind(this); + } + + /** + * Schedules a new idle callback to dispatch pending low-priority + * messages, if one is not already scheduled. + */ + scheduleIdleCallback() { + if (!this.idleScheduled) { + ChromeUtils.idleDispatch(this.onIdle, {timeout: LOW_PRIORITY_TIMEOUT_MS}); + this.idleScheduled = true; + } + } + + /** + * Called when the event queue is idle, and dispatches any pending + * low-priority messages in a single chunk. + * + * @param {IdleDeadline} deadline + */ + onIdle(deadline) { + this.idleScheduled = false; + + let messages = this.idleMessages; + this.idleMessages = []; + + let msgs = messages.map(msg => msg.getMessage()); + try { + this.messageManager.sendAsyncMessage(MESSAGE_MESSAGES, msgs); + } catch (e) { + for (let msg of messages) { + msg.reject(e); + } + } + } + + /** + * Sends a message through our wrapped message manager, or schedules + * it for low-priority dispatch during an idle callback. + * + * @param {any} message + * The message to send. + * @param {object} [options] + * Message dispatch options. + * @param {boolean} [options.lowPriority = false] + * If true, dispatches the message in a single chunk with other + * low-priority messages the next time the event queue is idle. + */ + sendMessage(message, options = {}) { + if (options.lowPriority) { + this.idleMessages.push(message); + this.scheduleIdleCallback(); + } else { + this.messageManager.sendAsyncMessage(MESSAGE_MESSAGES, [message.getMessage()]); + } + } + + receiveMessage({data, target}) { + data.target = target; + + this.callback(this.handlers.get(data.messageName), + data); + } + * getHandlers(messageName, sender, recipient) { let handler = this.handlers.get(messageName); if (handler) { yield handler; } } addHandler(messageName, handler) { @@ -286,45 +414,140 @@ class FilteringMessageManagerMap extends * message manager. * * @param {nsIMessageListenerManager} target * The message manager for which to return a broker. * * @returns {FilteringMessageManager} */ get(target) { - if (this.has(target)) { - return super.get(target); + let broker = super.get(target); + if (broker) { + return broker; } - let broker = new this._constructor(this.messageName, this.callback, target); + broker = new this._constructor(this.messageName, this.callback, target); this.set(target, broker); if (target instanceof Ci.nsIDOMEventTarget) { let onUnload = event => { target.removeEventListener("unload", onUnload); this.delete(target); }; target.addEventListener("unload", onUnload); } return broker; } } -const MESSAGE_MESSAGE = "MessageChannel:Message"; -const MESSAGE_RESPONSE = "MessageChannel:Response"; +/** + * Represents a message being sent through a MessageChannel, which may + * or may not have been dispatched yet, and is pending a response. + * + * When a response has been received, or the message has been canceled, + * this class is responsible for settling the response promise as + * appropriate. + * + * @param {number} channelId + * The unique ID for this message. + * @param {any} message + * The message contents. + * @param {object} sender + * An object describing the sender of the message, used by + * `abortResponses` to determine whether the message should be + * aborted. + * @param {ResponseManager} broker + * The response broker on which we're expected to receive a + * reply. + */ +class PendingMessage { + constructor(channelId, message, sender, broker) { + this.channelId = channelId; + this.message = message; + this.sender = sender; + this.broker = broker; + this.deferred = Deferred(); + + MessageChannel.pendingResponses.add(this); + } + + /** + * Cleans up after this message once we've received or aborted a + * response. + */ + cleanup() { + if (this.broker) { + this.broker.removeHandler(this.channelId, this); + MessageChannel.pendingResponses.delete(this); + + this.message = null; + this.broker = null; + } + } + + /** + * Returns the promise which will resolve when we've received or + * aborted a response to this message. + */ + get promise() { + return this.deferred.promise; + } + + /** + * Resolves the message's response promise, and cleans up. + * + * @param {any} value + */ + resolve(value) { + this.cleanup(); + this.deferred.resolve(value); + } + + /** + * Rejects the message's response promise, and cleans up. + * + * @param {any} value + */ + reject(value) { + this.cleanup(); + this.deferred.reject(value); + } + + get messageManager() { + return this.broker.messageManager; + } + + /** + * Returns the contents of the message to be sent over a message + * manager, and registers the response with our response broker. + * + * Returns null if the response has already been canceled, and the + * message should not be sent. + * + * @returns {any} + */ + getMessage() { + let msg = null; + if (this.broker) { + this.broker.addHandler(this.channelId, this); + msg = this.message; + this.message = null; + } + return msg; + } +} this.MessageChannel = { init() { Services.obs.addObserver(this, "message-manager-close"); Services.obs.addObserver(this, "message-manager-disconnect"); this.messageManagers = new FilteringMessageManagerMap( - MESSAGE_MESSAGE, this._handleMessage.bind(this)); + MESSAGE_MESSAGES, this._handleMessage.bind(this)); this.responseManagers = new FilteringMessageManagerMap( MESSAGE_RESPONSE, this._handleResponse.bind(this), ResponseManager); /** * @property {Set<Deferred>} pendingResponses * Contains a set of pending responses, either waiting to be @@ -431,28 +654,31 @@ this.MessageChannel = { }, /** * Returns true if the properties of the `data` object match those in * the `filter` object. Matching is done on a strict equality basis, * and the behavior varies depending on the value of the `strict` * parameter. * - * @param {object} filter + * @param {object?} filter * The filter object to match against. * @param {object} data * The data object being matched. * @param {boolean} [strict=true] * If true, all properties in the `filter` object have a * corresponding property in `data` with the same value. If * false, properties present in both objects must have the same * value. * @returns {boolean} True if the objects match. */ matchesFilter(filter, data, strict = true) { + if (!filter) { + return true; + } if (strict) { return Object.keys(filter).every(key => { return key in data && data[key] === filter[key]; }); } return Object.keys(filter).every(key => { return !(key in data) || data[key] === filter[key]; }); @@ -570,71 +796,55 @@ this.MessageChannel = { * `messageFilterPermissive` filters defined by recipients in order * for the message to be received. * @param {object} [options.sender] * A structured-clone-compatible object to identify the message * sender. This object may also be used to avoid delivering the * message to the sender, and as a filter to prematurely * abort responses when the sender is being destroyed. * @see `abortResponses`. - * @param {integer} [options.responseType=RESPONSE_SINGLE] + * @param {boolean} [options.lowPriority = false] + * If true, treat this as a low-priority message, and attempt to + * send it in the same chunk as other messages to the same target + * the next time the event queue is idle. This option reduces + * messaging overhead at the expense of adding some latency. + * @param {integer} [options.responseType = RESPONSE_SINGLE] * Specifies the type of response expected. See the `RESPONSE_*` * contents for details. * @returns {Promise} */ sendMessage(target, messageName, data, options = {}) { let sender = options.sender || {}; let recipient = options.recipient || {}; let responseType = options.responseType || this.RESPONSE_SINGLE; let channelId = ExtensionUtils.getUniqueId(); let message = {messageName, channelId, sender, recipient, data, responseType}; data = null; if (responseType == this.RESPONSE_NONE) { try { - target.sendAsyncMessage(MESSAGE_MESSAGE, message); + target.sendAsyncMessage(MESSAGE_MESSAGES, [message]); } catch (e) { // Caller is not expecting a reply, so dump the error to the console. Cu.reportError(e); return Promise.reject(e); } return Promise.resolve(); // Not expecting any reply. } - let deferred = {}; - deferred.promise = new Promise((resolve, reject) => { - deferred.resolve = resolve; - deferred.reject = reject; - }); - deferred.sender = recipient; - deferred.messageManager = target; - deferred.channelId = channelId; - - // The channel ID is used as the message name when routing responses. - // Add a message listener to the response broker, and remove it once - // we've gotten (or canceled) a response. let broker = this.responseManagers.get(target); - broker.addHandler(channelId, deferred); - - this.pendingResponses.add(deferred); - - let cleanup = () => { - broker.removeHandler(channelId, deferred); - this.pendingResponses.delete(deferred); - }; - deferred.promise.then(cleanup, cleanup); - + let pending = new PendingMessage(channelId, message, recipient, broker); + message = null; try { - target.sendAsyncMessage(MESSAGE_MESSAGE, message); + broker.sendMessage(pending, options); } catch (e) { - deferred.reject(e); + pending.reject(e); } - message = null; - return deferred.promise; + return pending.promise; }, _callHandlers(handlers, data) { let responseType = data.responseType; // At least one handler is required for all response types but // RESPONSE_ALL. if (handlers.length == 0 && responseType != this.RESPONSE_ALL) { @@ -776,39 +986,36 @@ this.MessageChannel = { cleanup(); Cu.reportError(e); }); }, /** * Handles message callbacks from the response brokers. * - * Each handler object is a deferred object created by `sendMessage`, and - * should be resolved or rejected based on the contents of the response. - * - * @param {Array<MessageHandler>} handlers + * @param {MessageHandler?} handler + * A deferred object created by `sendMessage`, to be resolved + * or rejected based on the contents of the response. * @param {object} data * @param {nsIMessageSender|{messageManager:nsIMessageSender}} data.target */ - _handleResponse(handlers, data) { + _handleResponse(handler, data) { // If we have an error at this point, we have handler to report it to, // so just log it. - if (handlers.length == 0) { + if (!handler) { if (this.abortedResponses.has(data.messageName)) { this.abortedResponses.delete(data.messageName); Services.console.logStringMessage(`Ignoring response to aborted listener for ${data.messageName}`); } else { Cu.reportError(`No matching message response handler for ${data.messageName}`); } - } else if (handlers.length > 1) { - Cu.reportError(`Multiple matching response handlers for ${data.messageName}`); } else if (data.result === this.RESULT_SUCCESS) { - handlers[0].resolve(data.value); + handler.resolve(data.value); } else { - handlers[0].reject(data.error); + handler.reject(data.error); } }, /** * Aborts pending message response for the specific channel. * * @param {string} channelId * A string for channelId of the response.
--- a/toolkit/components/extensions/test/mochitest/test_ext_webrequest_hsts.html +++ b/toolkit/components/extensions/test/mochitest/test_ext_webrequest_hsts.html @@ -49,16 +49,17 @@ add_task(async function test_hsts_reques browser.webRequest.onBeforeRedirect.addListener(details => { browser.test.assertEq(expect.shift(), "onBeforeRedirect"); }, {urls}); browser.webRequest.onResponseStarted.addListener(details => { browser.test.assertEq(expect.shift(), "onResponseStarted"); }, {urls}); browser.webRequest.onCompleted.addListener(details => { browser.test.assertEq(expect.shift(), "onCompleted"); + browser.test.sendMessage("onCompleted", details.url); }, {urls}); browser.webRequest.onErrorOccurred.addListener(details => { browser.test.notifyFail(`onErrorOccurred ${JSON.stringify(details)}`); }, {urls}); async function onUpdated(tabId, tabInfo, tab) { if (tabInfo.status !== "complete") { return; @@ -79,33 +80,38 @@ add_task(async function test_hsts_reques let sample = "https://example.org/tests/toolkit/components/extensions/test/mochitest/file_sample.html"; extension.sendMessage(`https://${testPath}/redirect_auto.sjs?redirect_uri=${sample}`, ["onBeforeRequest", "onBeforeSendHeaders", "onSendHeaders", "onHeadersReceived", "onBeforeRedirect", "onBeforeRequest", "onBeforeSendHeaders", "onSendHeaders", "onHeadersReceived", "onResponseStarted", "onCompleted"]); // redirect_auto adds a query string ok((await extension.awaitMessage("tabs-done")).startsWith(sample), "redirection ok"); + ok((await extension.awaitMessage("onCompleted")).startsWith(sample), "redirection ok"); // priming hsts extension.sendMessage(`https://${testPath}/hsts.sjs`, ["onBeforeRequest", "onBeforeSendHeaders", "onSendHeaders", "onHeadersReceived", "onResponseStarted", "onCompleted"]); is(await extension.awaitMessage("tabs-done"), "https://example.org/tests/toolkit/components/extensions/test/mochitest/hsts.sjs", "hsts primed"); + is(await extension.awaitMessage("onCompleted"), + "https://example.org/tests/toolkit/components/extensions/test/mochitest/hsts.sjs"); // test upgrade extension.sendMessage(`http://${testPath}/hsts.sjs`, ["onBeforeRequest", "onBeforeRedirect", "onBeforeRequest", "onBeforeSendHeaders", "onSendHeaders", "onHeadersReceived", "onResponseStarted", "onCompleted"]); is(await extension.awaitMessage("tabs-done"), "https://example.org/tests/toolkit/components/extensions/test/mochitest/hsts.sjs", "hsts upgraded"); + is(await extension.awaitMessage("onCompleted"), + "https://example.org/tests/toolkit/components/extensions/test/mochitest/hsts.sjs"); await extension.unload(); }); </script> </head> <body> </body>
--- a/toolkit/components/printingui/ipc/PrintingParent.cpp +++ b/toolkit/components/printingui/ipc/PrintingParent.cpp @@ -132,36 +132,35 @@ PrintingParent::ShowPrintDialog(PBrowser rv = mPrintSettingsSvc->DeserializeToPrintSettings(aData, settings); NS_ENSURE_SUCCESS(rv, rv); rv = settings->SetPrintSilent(printSilently); NS_ENSURE_SUCCESS(rv, rv); nsString printerName; - settings->GetPrinterName(getter_Copies(printerName)); + settings->GetPrinterName(printerName); #ifdef MOZ_X11 // Requesting the default printer name on Linux has been removed in the child, // because it was causing a sandbox violation (see Bug 1329216). // If no printer name is set at this point, use the print settings service // to get the default printer name. if (printerName.IsEmpty()) { - mPrintSettingsSvc->GetDefaultPrinterName(getter_Copies(printerName)); - settings->SetPrinterName(printerName.get()); + mPrintSettingsSvc->GetDefaultPrinterName(printerName); + settings->SetPrinterName(printerName); } - mPrintSettingsSvc->InitPrintSettingsFromPrinter(printerName.get(), settings); + mPrintSettingsSvc->InitPrintSettingsFromPrinter(printerName, settings); #endif // If this is for print preview or we are printing silently then we just need // to initialize the print settings with anything specific from the printer. if (isPrintPreview || printSilently || Preferences::GetBool("print.always_print_silent", printSilently)) { settings->SetIsInitializedFromPrinter(false); - mPrintSettingsSvc->InitPrintSettingsFromPrinter(printerName.get(), - settings); + mPrintSettingsSvc->InitPrintSettingsFromPrinter(printerName, settings); } else { rv = pps->ShowPrintDialog(parentWin, wbp, settings); NS_ENSURE_SUCCESS(rv, rv); } if (isPrintPreview) { // For print preview we don't want a RemotePrintJob just the settings. rv = mPrintSettingsSvc->SerializeToPrintData(settings, nullptr, aResult);
--- a/toolkit/components/printingui/win/nsPrintDialogUtil.cpp +++ b/toolkit/components/printingui/win/nsPrintDialogUtil.cpp @@ -530,17 +530,17 @@ CreateGlobalDevModeAndInit(const nsStrin } //------------------------------------------------------------------ // helper static void GetDefaultPrinterNameFromGlobalPrinters(nsAString &printerName) { nsCOMPtr<nsIPrinterEnumerator> prtEnum = do_GetService("@mozilla.org/gfx/printerenumerator;1"); if (prtEnum) { - prtEnum->GetDefaultPrinterName(getter_Copies(printerName)); + prtEnum->GetDefaultPrinterName(printerName); } } // Determine whether we have a completely native dialog // or whether we cshould extend it static bool ShouldExtendPrintDialog() { nsresult rv; @@ -565,17 +565,17 @@ ShowNativePrintDialog(HWND { //NS_ENSURE_ARG_POINTER(aHWnd); NS_ENSURE_ARG_POINTER(aPrintSettings); gDialogWasExtended = false; // Get the Print Name to be used nsString printerName; - aPrintSettings->GetPrinterName(getter_Copies(printerName)); + aPrintSettings->GetPrinterName(printerName); // If there is no name then use the default printer if (printerName.IsEmpty()) { GetDefaultPrinterNameFromGlobalPrinters(printerName); } else { HANDLE hPrinter = nullptr; if(!::OpenPrinterW(const_cast<wchar_t*>(static_cast<const wchar_t*>(printerName.get())), &hPrinter, nullptr)) { @@ -691,39 +691,39 @@ ShowNativePrintDialog(HWND // NOTE: // As per Microsoft SDK documentation the returned value offset from // devnames->wOutputOffset is either "FILE:" or nullptr // if the "Print To File" checkbox is checked it MUST be "FILE:" // We assert as an extra safety check. if (prntdlg.Flags & PD_PRINTTOFILE) { char16ptr_t fileName = &(((wchar_t *)devnames)[devnames->wOutputOffset]); NS_ASSERTION(wcscmp(fileName, L"FILE:") == 0, "FileName must be `FILE:`"); - aPrintSettings->SetToFileName(fileName); + aPrintSettings->SetToFileName(nsDependentString(fileName)); aPrintSettings->SetPrintToFile(true); } else { // clear "print to file" info aPrintSettings->SetPrintToFile(false); - aPrintSettings->SetToFileName(nullptr); + aPrintSettings->SetToFileName(EmptyString()); } nsCOMPtr<nsIPrintSettingsWin> psWin(do_QueryInterface(aPrintSettings)); if (!psWin) { return NS_ERROR_FAILURE; } // Setup local Data members - psWin->SetDeviceName(device); - psWin->SetDriverName(driver); + psWin->SetDeviceName(nsDependentString(device)); + psWin->SetDriverName(nsDependentString(driver)); #if defined(DEBUG_rods) || defined(DEBUG_dcone) wprintf(L"printer: driver %s, device %s flags: %d\n", driver, device, prntdlg.Flags); #endif // fill the print options with the info from the dialog - aPrintSettings->SetPrinterName(device); + aPrintSettings->SetPrinterName(nsDependentString(device)); if (prntdlg.Flags & PD_SELECTION) { aPrintSettings->SetPrintRange(nsIPrintSettings::kRangeSelection); } else if (prntdlg.Flags & PD_PAGENUMS) { aPrintSettings->SetPrintRange(nsIPrintSettings::kRangeSpecifiedPageRange); aPrintSettings->SetStartPageRange(prntdlg.nFromPage); aPrintSettings->SetEndPageRange(prntdlg.nToPage);
--- a/view/nsViewManager.cpp +++ b/view/nsViewManager.cpp @@ -95,17 +95,17 @@ nsViewManager::~nsViewManager() if (gViewManagers->IsEmpty()) { // There aren't any more view managers so // release the global array of view managers delete gViewManagers; gViewManagers = nullptr; } - mPresShell = nullptr; + MOZ_RELEASE_ASSERT(!mPresShell, "Releasing nsViewManager without having called Destroy on the PresShell!"); } // We don't hold a reference to the presentation context because it // holds a reference to us. nsresult nsViewManager::Init(nsDeviceContext* aContext) { NS_PRECONDITION(nullptr != aContext, "null ptr");
--- a/widget/android/nsDeviceContextAndroid.cpp +++ b/widget/android/nsDeviceContextAndroid.cpp @@ -57,17 +57,17 @@ nsDeviceContextSpecAndroid::BeginDocumen return NS_OK; } NS_IMETHODIMP nsDeviceContextSpecAndroid::EndDocument() { nsString targetPath; nsCOMPtr<nsIFile> destFile; - mPrintSettings->GetToFileName(getter_Copies(targetPath)); + mPrintSettings->GetToFileName(targetPath); nsresult rv = NS_NewLocalFile(targetPath, false, getter_AddRefs(destFile)); NS_ENSURE_SUCCESS(rv, rv); nsAutoString destLeafName; rv = destFile->GetLeafName(destLeafName); NS_ENSURE_SUCCESS(rv, rv);
--- a/widget/android/nsPrintOptionsAndroid.cpp +++ b/widget/android/nsPrintOptionsAndroid.cpp @@ -7,18 +7,17 @@ #include "nsPrintSettingsImpl.h" class nsPrintSettingsAndroid : public nsPrintSettings { public: nsPrintSettingsAndroid() { // The aim here is to set up the objects enough that silent printing works SetOutputFormat(nsIPrintSettings::kOutputFormatPDF); - SetPrinterName(u"PDF printer"); - + SetPrinterName(NS_LITERAL_STRING("PDF printer")); } }; nsPrintOptionsAndroid::nsPrintOptionsAndroid() { } nsPrintOptionsAndroid::~nsPrintOptionsAndroid()
--- a/widget/cocoa/nsPrintDialogX.mm +++ b/widget/cocoa/nsPrintDialogX.mm @@ -510,42 +510,42 @@ static const char sHeaderFooterTags[][4] [self addLabel:"pageFootersTitleMac" withFrame:NSMakeRect(0, 0, 151, 22)]; [self addCenteredLabel:"left" withFrame:NSMakeRect(156, 22, 100, 22)]; [self addCenteredLabel:"center" withFrame:NSMakeRect(256, 22, 100, 22)]; [self addCenteredLabel:"right" withFrame:NSMakeRect(356, 22, 100, 22)]; // Lists nsString sel; - mSettings->GetHeaderStrLeft(getter_Copies(sel)); + mSettings->GetHeaderStrLeft(sel); mHeaderLeftList = [self headerFooterItemListWithFrame:NSMakeRect(156, 44, 100, 22) selectedItem:sel]; [self addSubview:mHeaderLeftList]; - mSettings->GetHeaderStrCenter(getter_Copies(sel)); + mSettings->GetHeaderStrCenter(sel); mHeaderCenterList = [self headerFooterItemListWithFrame:NSMakeRect(256, 44, 100, 22) selectedItem:sel]; [self addSubview:mHeaderCenterList]; - mSettings->GetHeaderStrRight(getter_Copies(sel)); + mSettings->GetHeaderStrRight(sel); mHeaderRightList = [self headerFooterItemListWithFrame:NSMakeRect(356, 44, 100, 22) selectedItem:sel]; [self addSubview:mHeaderRightList]; - mSettings->GetFooterStrLeft(getter_Copies(sel)); + mSettings->GetFooterStrLeft(sel); mFooterLeftList = [self headerFooterItemListWithFrame:NSMakeRect(156, 0, 100, 22) selectedItem:sel]; [self addSubview:mFooterLeftList]; - mSettings->GetFooterStrCenter(getter_Copies(sel)); + mSettings->GetFooterStrCenter(sel); mFooterCenterList = [self headerFooterItemListWithFrame:NSMakeRect(256, 0, 100, 22) selectedItem:sel]; [self addSubview:mFooterCenterList]; - mSettings->GetFooterStrRight(getter_Copies(sel)); + mSettings->GetFooterStrRight(sel); mFooterRightList = [self headerFooterItemListWithFrame:NSMakeRect(356, 0, 100, 22) selectedItem:sel]; [self addSubview:mFooterRightList]; } // Export settings - (int16_t)chosenFrameSetting @@ -565,32 +565,32 @@ static const char sHeaderFooterTags[][4] NS_ASSERTION(index < NSInteger(ArrayLength(sHeaderFooterTags)), "Index of dropdown is higher than expected!"); return sHeaderFooterTags[index]; } - (void)exportHeaderFooterSettings { const char* headerFooterStr; headerFooterStr = [self headerFooterStringForList:mHeaderLeftList]; - mSettings->SetHeaderStrLeft(NS_ConvertUTF8toUTF16(headerFooterStr).get()); + mSettings->SetHeaderStrLeft(NS_ConvertUTF8toUTF16(headerFooterStr)); headerFooterStr = [self headerFooterStringForList:mHeaderCenterList]; - mSettings->SetHeaderStrCenter(NS_ConvertUTF8toUTF16(headerFooterStr).get()); + mSettings->SetHeaderStrCenter(NS_ConvertUTF8toUTF16(headerFooterStr)); headerFooterStr = [self headerFooterStringForList:mHeaderRightList]; - mSettings->SetHeaderStrRight(NS_ConvertUTF8toUTF16(headerFooterStr).get()); + mSettings->SetHeaderStrRight(NS_ConvertUTF8toUTF16(headerFooterStr)); headerFooterStr = [self headerFooterStringForList:mFooterLeftList]; - mSettings->SetFooterStrLeft(NS_ConvertUTF8toUTF16(headerFooterStr).get()); + mSettings->SetFooterStrLeft(NS_ConvertUTF8toUTF16(headerFooterStr)); headerFooterStr = [self headerFooterStringForList:mFooterCenterList]; - mSettings->SetFooterStrCenter(NS_ConvertUTF8toUTF16(headerFooterStr).get()); + mSettings->SetFooterStrCenter(NS_ConvertUTF8toUTF16(headerFooterStr)); headerFooterStr = [self headerFooterStringForList:mFooterRightList]; - mSettings->SetFooterStrRight(NS_ConvertUTF8toUTF16(headerFooterStr).get()); + mSettings->SetFooterStrRight(NS_ConvertUTF8toUTF16(headerFooterStr)); } // Summary - (NSString*)summaryValueForCheckbox:(NSButton*)aCheckbox { if (![aCheckbox isEnabled]) return [self localizedString:"summaryNAValue"];
--- a/widget/cocoa/nsPrintSettingsX.h +++ b/widget/cocoa/nsPrintSettingsX.h @@ -63,17 +63,17 @@ public: nsresult InitAdjustedPaperSize(); void SetInchesScale(float aWidthScale, float aHeightScale); void GetInchesScale(float *aWidthScale, float *aHeightScale); NS_IMETHOD SetScaling(double aScaling) override; NS_IMETHOD GetScaling(double *aScaling) override; - NS_IMETHOD SetToFileName(const char16_t * aToFileName) override; + NS_IMETHOD SetToFileName(const nsAString& aToFileName) override; NS_IMETHOD GetOrientation(int32_t *aOrientation) override; NS_IMETHOD SetOrientation(int32_t aOrientation) override; NS_IMETHOD SetUnwriteableMarginTop(double aUnwriteableMarginTop) override; NS_IMETHOD SetUnwriteableMarginLeft(double aUnwriteableMarginLeft) override; NS_IMETHOD SetUnwriteableMarginBottom(double aUnwriteableMarginBottom) override; NS_IMETHOD SetUnwriteableMarginRight(double aUnwriteableMarginRight) override;
--- a/widget/cocoa/nsPrintSettingsX.mm +++ b/widget/cocoa/nsPrintSettingsX.mm @@ -323,33 +323,32 @@ nsPrintSettingsX::GetScaling(double *aSc *aScaling = round(*aScaling * 100.0) / 100.0; return NS_OK; NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; } NS_IMETHODIMP -nsPrintSettingsX::SetToFileName(const char16_t *aToFileName) +nsPrintSettingsX::SetToFileName(const nsAString& aToFileName) { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; if (XRE_IsContentProcess() && Preferences::GetBool("print.print_via_parent")) { // On content sandbox, NSPrintJobSavingURL will returns error since // sandbox disallows file access. return nsPrintSettings::SetToFileName(aToFileName); } NSMutableDictionary* printInfoDict = [mPrintInfo dictionary]; - if (aToFileName && aToFileName[0]) { + if (!aToFileName.IsEmpty()) { NSURL* jobSavingURL = - [NSURL fileURLWithPath: nsCocoaUtils::ToNSString( - nsDependentString(aToFileName))]; + [NSURL fileURLWithPath: nsCocoaUtils::ToNSString(aToFileName)]; if (jobSavingURL) { [printInfoDict setObject: NSPrintSaveJob forKey: NSPrintJobDisposition]; [printInfoDict setObject: jobSavingURL forKey: NSPrintJobSavingURL]; } mToFileName = aToFileName; } else { mToFileName.Truncate(); }
--- a/widget/gtk/nsDeviceContextSpecG.cpp +++ b/widget/gtk/nsDeviceContextSpecG.cpp @@ -58,17 +58,17 @@ public: void FreeGlobalPrinters(); nsresult InitializeGlobalPrinters(); bool PrintersAreAllocated() { return mGlobalPrinterList != nullptr; } uint32_t GetNumPrinters() { return mGlobalPrinterList ? mGlobalPrinterList->Length() : 0; } nsString* GetStringAt(int32_t aInx) { return &mGlobalPrinterList->ElementAt(aInx); } - void GetDefaultPrinterName(char16_t **aDefaultPrinterName); + void GetDefaultPrinterName(nsAString& aDefaultPrinterName); protected: GlobalPrinters() {} static GlobalPrinters mGlobalPrinters; static nsTArray<nsString>* mGlobalPrinterList; }; @@ -241,17 +241,17 @@ ns_release_macro(gpointer aData) { /* static */ gboolean nsDeviceContextSpecGTK::PrinterEnumerator(GtkPrinter *aPrinter, gpointer aData) { nsDeviceContextSpecGTK *spec = (nsDeviceContextSpecGTK*)aData; // Find the printer whose name matches the one inside the settings. nsString printerName; nsresult rv = - spec->mPrintSettings->GetPrinterName(getter_Copies(printerName)); + spec->mPrintSettings->GetPrinterName(printerName); if (NS_SUCCEEDED(rv) && !printerName.IsVoid()) { NS_ConvertUTF16toUTF8 requestedName(printerName); const char* currentName = gtk_printer_get_name(aPrinter); if (requestedName.Equals(currentName)) { spec->mPrintSettings->SetGtkPrinter(aPrinter); // Bug 1145916 - attempting to kick off a print job for this printer // during this tick of the event loop will result in the printer backend @@ -323,17 +323,17 @@ NS_IMETHODIMP nsDeviceContextSpecGTK::En NewRunnableMethod("nsDeviceContextSpecGTK::EnumeratePrinters", this, &nsDeviceContextSpecGTK::EnumeratePrinters)); } } else { // Handle print-to-file ourselves for the benefit of embedders nsString targetPath; nsCOMPtr<nsIFile> destFile; - mPrintSettings->GetToFileName(getter_Copies(targetPath)); + mPrintSettings->GetToFileName(targetPath); nsresult rv = NS_NewLocalFile(targetPath, false, getter_AddRefs(destFile)); NS_ENSURE_SUCCESS(rv, rv); nsAutoString destLeafName; rv = destFile->GetLeafName(destLeafName); NS_ENSURE_SUCCESS(rv, rv); @@ -383,28 +383,29 @@ NS_IMETHODIMP nsPrinterEnumeratorGTK::Ge { printers->AppendElement(*GlobalPrinters::GetInstance()->GetStringAt(count++)); } GlobalPrinters::GetInstance()->FreeGlobalPrinters(); return NS_NewAdoptingStringEnumerator(aPrinterNameList, printers); } -NS_IMETHODIMP nsPrinterEnumeratorGTK::GetDefaultPrinterName(char16_t **aDefaultPrinterName) +NS_IMETHODIMP nsPrinterEnumeratorGTK::GetDefaultPrinterName(nsAString& aDefaultPrinterName) { DO_PR_DEBUG_LOG(("nsPrinterEnumeratorGTK::GetDefaultPrinterName()\n")); - NS_ENSURE_ARG_POINTER(aDefaultPrinterName); GlobalPrinters::GetInstance()->GetDefaultPrinterName(aDefaultPrinterName); - DO_PR_DEBUG_LOG(("GetDefaultPrinterName(): default printer='%s'.\n", NS_ConvertUTF16toUTF8(*aDefaultPrinterName).get())); + DO_PR_DEBUG_LOG(("GetDefaultPrinterName(): default printer='%s'.\n", NS_ConvertUTF16toUTF8(aDefaultPrinterName).get())); return NS_OK; } -NS_IMETHODIMP nsPrinterEnumeratorGTK::InitPrintSettingsFromPrinter(const char16_t *aPrinterName, nsIPrintSettings *aPrintSettings) +NS_IMETHODIMP +nsPrinterEnumeratorGTK::InitPrintSettingsFromPrinter(const nsAString& aPrinterName, + nsIPrintSettings *aPrintSettings) { DO_PR_DEBUG_LOG(("nsPrinterEnumeratorGTK::InitPrintSettingsFromPrinter()")); NS_ENSURE_ARG_POINTER(aPrintSettings); /* Set filename */ nsAutoCString filename; const char *path; @@ -413,17 +414,17 @@ NS_IMETHODIMP nsPrinterEnumeratorGTK::In path = PR_GetEnv("HOME"); if (path) filename = nsPrintfCString("%s/mozilla.pdf", path); else filename.AssignLiteral("mozilla.pdf"); DO_PR_DEBUG_LOG(("Setting default filename to '%s'\n", filename.get())); - aPrintSettings->SetToFileName(NS_ConvertUTF8toUTF16(filename).get()); + aPrintSettings->SetToFileName(NS_ConvertUTF8toUTF16(filename)); aPrintSettings->SetIsInitializedFromPrinter(true); return NS_OK; } //---------------------------------------------------------------------- nsresult GlobalPrinters::InitializeGlobalPrinters () @@ -465,32 +466,32 @@ void GlobalPrinters::FreeGlobalPrinters( { if (mGlobalPrinterList) { delete mGlobalPrinterList; mGlobalPrinterList = nullptr; } } void -GlobalPrinters::GetDefaultPrinterName(char16_t **aDefaultPrinterName) +GlobalPrinters::GetDefaultPrinterName(nsAString& aDefaultPrinterName) { - *aDefaultPrinterName = nullptr; + aDefaultPrinterName.Truncate(); bool allocate = !GlobalPrinters::GetInstance()->PrintersAreAllocated(); if (allocate) { nsresult rv = GlobalPrinters::GetInstance()->InitializeGlobalPrinters(); if (NS_FAILED(rv)) { return; } } NS_ASSERTION(GlobalPrinters::GetInstance()->PrintersAreAllocated(), "no GlobalPrinters"); if (GlobalPrinters::GetInstance()->GetNumPrinters() == 0) return; - *aDefaultPrinterName = ToNewUnicode(*GlobalPrinters::GetInstance()->GetStringAt(0)); + aDefaultPrinterName = *GlobalPrinters::GetInstance()->GetStringAt(0); if (allocate) { GlobalPrinters::GetInstance()->FreeGlobalPrinters(); } }
--- a/widget/gtk/nsPrintDialogGTK.cpp +++ b/widget/gtk/nsPrintDialogGTK.cpp @@ -272,38 +272,38 @@ nsPrintDialogWidgetGTK::nsPrintDialogWid GtkWidget* header_footer_container = gtk_alignment_new(0, 0, 0, 0); gtk_alignment_set_padding(GTK_ALIGNMENT(header_footer_container), 8, 0, 12, 0); // --- Table for making the header and footer options --- GtkWidget* header_footer_table = gtk_table_new(3, 3, FALSE); // 3x3 table nsString header_footer_str[3]; - aSettings->GetHeaderStrLeft(getter_Copies(header_footer_str[0])); - aSettings->GetHeaderStrCenter(getter_Copies(header_footer_str[1])); - aSettings->GetHeaderStrRight(getter_Copies(header_footer_str[2])); + aSettings->GetHeaderStrLeft(header_footer_str[0]); + aSettings->GetHeaderStrCenter(header_footer_str[1]); + aSettings->GetHeaderStrRight(header_footer_str[2]); for (unsigned int i = 0; i < ArrayLength(header_dropdown); i++) { header_dropdown[i] = ConstructHeaderFooterDropdown(header_footer_str[i].get()); // Those 4 magic numbers in the middle provide the position in the table. // The last two numbers mean 2 px padding on every side. gtk_table_attach(GTK_TABLE(header_footer_table), header_dropdown[i], i, (i + 1), 0, 1, (GtkAttachOptions) 0, (GtkAttachOptions) 0, 2, 2); } const char labelKeys[][7] = {"left", "center", "right"}; for (unsigned int i = 0; i < ArrayLength(labelKeys); i++) { gtk_table_attach(GTK_TABLE(header_footer_table), gtk_label_new(GetUTF8FromBundle(labelKeys[i]).get()), i, (i + 1), 1, 2, (GtkAttachOptions) 0, (GtkAttachOptions) 0, 2, 2); } - aSettings->GetFooterStrLeft(getter_Copies(header_footer_str[0])); - aSettings->GetFooterStrCenter(getter_Copies(header_footer_str[1])); - aSettings->GetFooterStrRight(getter_Copies(header_footer_str[2])); + aSettings->GetFooterStrLeft(header_footer_str[0]); + aSettings->GetFooterStrCenter(header_footer_str[1]); + aSettings->GetFooterStrRight(header_footer_str[2]); for (unsigned int i = 0; i < ArrayLength(footer_dropdown); i++) { footer_dropdown[i] = ConstructHeaderFooterDropdown(header_footer_str[i].get()); gtk_table_attach(GTK_TABLE(header_footer_table), footer_dropdown[i], i, (i + 1), 2, 3, (GtkAttachOptions) 0, (GtkAttachOptions) 0, 2, 2); } // --- @@ -366,32 +366,32 @@ nsPrintDialogWidgetGTK::ExportFramePrint aNS->SetPrintFrameType(nsIPrintSettings::kNoFrames); } void nsPrintDialogWidgetGTK::ExportHeaderFooter(nsIPrintSettings *aNS) { const char* header_footer_str; header_footer_str = OptionWidgetToString(header_dropdown[0]); - aNS->SetHeaderStrLeft(NS_ConvertUTF8toUTF16(header_footer_str).get()); + aNS->SetHeaderStrLeft(NS_ConvertUTF8toUTF16(header_footer_str)); header_footer_str = OptionWidgetToString(header_dropdown[1]); - aNS->SetHeaderStrCenter(NS_ConvertUTF8toUTF16(header_footer_str).get()); + aNS->SetHeaderStrCenter(NS_ConvertUTF8toUTF16(header_footer_str)); header_footer_str = OptionWidgetToString(header_dropdown[2]); - aNS->SetHeaderStrRight(NS_ConvertUTF8toUTF16(header_footer_str).get()); + aNS->SetHeaderStrRight(NS_ConvertUTF8toUTF16(header_footer_str)); header_footer_str = OptionWidgetToString(footer_dropdown[0]); - aNS->SetFooterStrLeft(NS_ConvertUTF8toUTF16(header_footer_str).get()); + aNS->SetFooterStrLeft(NS_ConvertUTF8toUTF16(header_footer_str)); header_footer_str = OptionWidgetToString(footer_dropdown[1]); - aNS->SetFooterStrCenter(NS_ConvertUTF8toUTF16(header_footer_str).get()); + aNS->SetFooterStrCenter(NS_ConvertUTF8toUTF16(header_footer_str)); header_footer_str = OptionWidgetToString(footer_dropdown[2]); - aNS->SetFooterStrRight(NS_ConvertUTF8toUTF16(header_footer_str).get()); + aNS->SetFooterStrRight(NS_ConvertUTF8toUTF16(header_footer_str)); } nsresult nsPrintDialogWidgetGTK::ImportSettings(nsIPrintSettings *aNSSettings) { NS_PRECONDITION(aNSSettings, "aSettings must not be null"); NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE); @@ -578,20 +578,20 @@ nsPrintDialogServiceGTK::ShowPageSetup(n nsCOMPtr<nsPrintSettingsGTK> aNSSettingsGTK(do_QueryInterface(aNSSettings)); if (!aNSSettingsGTK) return NS_ERROR_FAILURE; // We need to init the prefs here because aNSSettings in its current form is a dummy in both uses of the word nsCOMPtr<nsIPrintSettingsService> psService = do_GetService("@mozilla.org/gfx/printsettings-service;1"); if (psService) { nsString printName; - aNSSettings->GetPrinterName(getter_Copies(printName)); + aNSSettings->GetPrinterName(printName); if (printName.IsVoid()) { - psService->GetDefaultPrinterName(getter_Copies(printName)); - aNSSettings->SetPrinterName(printName.get()); + psService->GetDefaultPrinterName(printName); + aNSSettings->SetPrinterName(printName); } psService->InitPrintSettingsFromPrefs(aNSSettings, true, nsIPrintSettings::kInitSaveAll); } GtkPrintSettings* gtkSettings = aNSSettingsGTK->GetGtkPrintSettings(); GtkPageSetup* oldPageSetup = aNSSettingsGTK->GetGtkPageSetup(); GtkPageSetup* newPageSetup = gtk_print_run_page_setup_dialog(gtkParent, oldPageSetup, gtkSettings);
--- a/widget/gtk/nsPrintSettingsGTK.cpp +++ b/widget/gtk/nsPrintSettingsGTK.cpp @@ -404,93 +404,86 @@ nsPrintSettingsGTK::SetOrientation(int32 gtkOrient = GTK_PAGE_ORIENTATION_PORTRAIT; gtk_print_settings_set_orientation(mPrintSettings, gtkOrient); gtk_page_setup_set_orientation(mPageSetup, gtkOrient); return NS_OK; } NS_IMETHODIMP -nsPrintSettingsGTK::GetToFileName(char16_t * *aToFileName) +nsPrintSettingsGTK::GetToFileName(nsAString& aToFileName) { // Get the gtk output filename const char* gtk_output_uri = gtk_print_settings_get(mPrintSettings, GTK_PRINT_SETTINGS_OUTPUT_URI); if (!gtk_output_uri) { - *aToFileName = ToNewUnicode(mToFileName); + aToFileName = mToFileName; return NS_OK; } // Convert to an nsIFile nsCOMPtr<nsIFile> file; nsresult rv = NS_GetFileFromURLSpec(nsDependentCString(gtk_output_uri), getter_AddRefs(file)); if (NS_FAILED(rv)) return rv; // Extract the path - nsAutoString path; - rv = file->GetPath(path); - NS_ENSURE_SUCCESS(rv, rv); - - *aToFileName = ToNewUnicode(path); - return NS_OK; + return file->GetPath(aToFileName); } NS_IMETHODIMP -nsPrintSettingsGTK::SetToFileName(const char16_t * aToFileName) +nsPrintSettingsGTK::SetToFileName(const nsAString& aToFileName) { - if (aToFileName[0] == 0) { + if (aToFileName.IsEmpty()) { mToFileName.SetLength(0); gtk_print_settings_set(mPrintSettings, GTK_PRINT_SETTINGS_OUTPUT_URI, nullptr); return NS_OK; } - if (StringEndsWith(nsDependentString(aToFileName), NS_LITERAL_STRING(".ps"))) { + if (StringEndsWith(aToFileName, NS_LITERAL_STRING(".ps"))) { gtk_print_settings_set(mPrintSettings, GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT, "ps"); } else { gtk_print_settings_set(mPrintSettings, GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT, "pdf"); } nsCOMPtr<nsIFile> file; - nsresult rv = NS_NewLocalFile(nsDependentString(aToFileName), true, - getter_AddRefs(file)); + nsresult rv = NS_NewLocalFile(aToFileName, true, getter_AddRefs(file)); NS_ENSURE_SUCCESS(rv, rv); // Convert the nsIFile to a URL nsAutoCString url; rv = NS_GetURLSpecFromFile(file, url); NS_ENSURE_SUCCESS(rv, rv); gtk_print_settings_set(mPrintSettings, GTK_PRINT_SETTINGS_OUTPUT_URI, url.get()); mToFileName = aToFileName; return NS_OK; } NS_IMETHODIMP -nsPrintSettingsGTK::GetPrinterName(char16_t * *aPrinter) +nsPrintSettingsGTK::GetPrinterName(nsAString& aPrinter) { const char* gtkPrintName = gtk_print_settings_get_printer(mPrintSettings); if (!gtkPrintName) { if (GTK_IS_PRINTER(mGTKPrinter)) { gtkPrintName = gtk_printer_get_name(mGTKPrinter); } else { // This mimics what nsPrintSettingsImpl does when we try to Get before we Set - nsString nullPrintName; - *aPrinter = ToNewUnicode(nullPrintName); + aPrinter.Truncate(); return NS_OK; } } - *aPrinter = UTF8ToNewUnicode(nsDependentCString(gtkPrintName)); + aPrinter = NS_ConvertUTF8toUTF16(gtkPrintName); return NS_OK; } NS_IMETHODIMP -nsPrintSettingsGTK::SetPrinterName(const char16_t * aPrinter) +nsPrintSettingsGTK::SetPrinterName(const nsAString& aPrinter) { NS_ConvertUTF16toUTF8 gtkPrinter(aPrinter); if (StringBeginsWith(gtkPrinter, NS_LITERAL_CSTRING("CUPS/"))) { // Strip off "CUPS/"; GTK might recognize the rest gtkPrinter.Cut(0, strlen("CUPS/")); } @@ -532,26 +525,25 @@ nsPrintSettingsGTK::GetScaling(double *a NS_IMETHODIMP nsPrintSettingsGTK::SetScaling(double aScaling) { gtk_print_settings_set_scale(mPrintSettings, aScaling * 100.0); return NS_OK; } NS_IMETHODIMP -nsPrintSettingsGTK::GetPaperName(char16_t * *aPaperName) +nsPrintSettingsGTK::GetPaperName(nsAString& aPaperName) { - NS_ENSURE_ARG_POINTER(aPaperName); const gchar* name = gtk_paper_size_get_name(gtk_page_setup_get_paper_size(mPageSetup)); - *aPaperName = ToNewUnicode(NS_ConvertUTF8toUTF16(name)); + aPaperName = NS_ConvertUTF8toUTF16(name); return NS_OK; } NS_IMETHODIMP -nsPrintSettingsGTK::SetPaperName(const char16_t * aPaperName) +nsPrintSettingsGTK::SetPaperName(const nsAString& aPaperName) { NS_ConvertUTF16toUTF8 gtkPaperName(aPaperName); // Convert these Gecko names to GTK names if (gtkPaperName.EqualsIgnoreCase("letter")) gtkPaperName.AssignLiteral(GTK_PAPER_NAME_LETTER); else if (gtkPaperName.EqualsIgnoreCase("legal")) gtkPaperName.AssignLiteral(GTK_PAPER_NAME_LEGAL);
--- a/widget/gtk/nsPrintSettingsGTK.h +++ b/widget/gtk/nsPrintSettingsGTK.h @@ -63,34 +63,34 @@ public: NS_IMETHOD SetPrintReversed(bool aPrintReversed) override; NS_IMETHOD GetPrintInColor(bool *aPrintInColor) override; NS_IMETHOD SetPrintInColor(bool aPrintInColor) override; NS_IMETHOD GetOrientation(int32_t *aOrientation) override; NS_IMETHOD SetOrientation(int32_t aOrientation) override; - NS_IMETHOD GetToFileName(char16_t * *aToFileName) override; - NS_IMETHOD SetToFileName(const char16_t * aToFileName) override; + NS_IMETHOD GetToFileName(nsAString& aToFileName) override; + NS_IMETHOD SetToFileName(const nsAString& aToFileName) override; // Gets/Sets the printer name in the GtkPrintSettings. If no printer name is specified there, // you will get back the name of the current internal GtkPrinter. - NS_IMETHOD GetPrinterName(char16_t * *aPrinter) override; - NS_IMETHOD SetPrinterName(const char16_t * aPrinter) override; + NS_IMETHOD GetPrinterName(nsAString& Printer) override; + NS_IMETHOD SetPrinterName(const nsAString& aPrinter) override; // Number of copies is stored/gotten from the GtkPrintSettings. NS_IMETHOD GetNumCopies(int32_t *aNumCopies) override; NS_IMETHOD SetNumCopies(int32_t aNumCopies) override; NS_IMETHOD GetScaling(double *aScaling) override; NS_IMETHOD SetScaling(double aScaling) override; // A name recognised by GTK is strongly advised here, as this is used to create a GtkPaperSize. - NS_IMETHOD GetPaperName(char16_t * *aPaperName) override; - NS_IMETHOD SetPaperName(const char16_t * aPaperName) override; + NS_IMETHOD GetPaperName(nsAString& aPaperName) override; + NS_IMETHOD SetPaperName(const nsAString& aPaperName) override; NS_IMETHOD SetUnwriteableMarginInTwips(nsIntMargin& aUnwriteableMargin) override; NS_IMETHOD SetUnwriteableMarginTop(double aUnwriteableMarginTop) override; NS_IMETHOD SetUnwriteableMarginLeft(double aUnwriteableMarginLeft) override; NS_IMETHOD SetUnwriteableMarginBottom(double aUnwriteableMarginBottom) override; NS_IMETHOD SetUnwriteableMarginRight(double aUnwriteableMarginRight) override; NS_IMETHOD GetPaperWidth(double *aPaperWidth) override;
--- a/widget/nsIPrintSettings.idl +++ b/widget/nsIPrintSettings.idl @@ -197,51 +197,51 @@ interface nsIPrintSettings : nsISupports attribute double unwriteableMarginRight; attribute double scaling; /* values 0.0 - 1.0 */ attribute boolean printBGColors; /* Print Background Colors */ attribute boolean printBGImages; /* Print Background Images */ attribute short printRange; - attribute wstring title; - attribute wstring docURL; + attribute AString title; + attribute AString docURL; - attribute wstring headerStrLeft; - attribute wstring headerStrCenter; - attribute wstring headerStrRight; + attribute AString headerStrLeft; + attribute AString headerStrCenter; + attribute AString headerStrRight; - attribute wstring footerStrLeft; - attribute wstring footerStrCenter; - attribute wstring footerStrRight; + attribute AString footerStrLeft; + attribute AString footerStrCenter; + attribute AString footerStrRight; attribute short howToEnableFrameUI; /* indicates how to enable the frameset UI */ attribute boolean isCancelled; /* indicates whether the print job has been cancelled */ attribute short printFrameTypeUsage; /* indicates whether to use the interal value or not */ attribute short printFrameType; attribute boolean printSilent; /* print without putting up the dialog */ attribute boolean shrinkToFit; /* shrinks content to fit on page */ attribute boolean showPrintProgress; /* indicates whether the progress dialog should be shown */ /* Additional XP Related */ - attribute wstring paperName; /* name of paper */ + attribute AString paperName; /* name of paper */ attribute short paperData; /* native data value */ attribute double paperWidth; /* width of the paper in inches or mm */ attribute double paperHeight; /* height of the paper in inches or mm */ attribute short paperSizeUnit; /* paper is in inches or mm */ attribute boolean printReversed; attribute boolean printInColor; /* a false means grayscale */ attribute long orientation; /* see orientation consts */ attribute long numCopies; - attribute wstring printerName; /* name of destination printer */ + attribute AString printerName; /* name of destination printer */ attribute boolean printToFile; - attribute wstring toFileName; + attribute AString toFileName; attribute short outputFormat; attribute long printPageDelay; /* in milliseconds */ attribute long resolution; /* print resolution (dpi) */ attribute long duplex; /* duplex mode */
--- a/widget/nsIPrintSettingsService.idl +++ b/widget/nsIPrintSettingsService.idl @@ -53,27 +53,28 @@ interface nsIPrintSettingsService : nsIS * (Note: this may not happen if there is an OS specific implementation.) * */ readonly attribute nsIPrintSettings newPrintSettings; /** * The name of the last printer used, or else the system default printer. */ - readonly attribute wstring defaultPrinterName; + readonly attribute AString defaultPrinterName; /** * Initializes certain settings from the native printer into the PrintSettings * if aPrinterName is null then it uses the default printer name if it can * These settings include, but are not limited to: * Page Orientation * Page Size * Number of Copies */ - void initPrintSettingsFromPrinter(in wstring aPrinterName, in nsIPrintSettings aPrintSettings); + void initPrintSettingsFromPrinter(in AString aPrinterName, + in nsIPrintSettings aPrintSettings); /** * Reads PrintSettings values from Prefs, * the values to be read are indicated by the "flags" arg. * * aPrintSettings should be initialized with the name of a printer. First * it reads in the PrintSettings from the last print job. Then it uses the * PrinterName in the PrinterSettings to read any settings that were saved
--- a/widget/nsIPrintSettingsWin.idl +++ b/widget/nsIPrintSettingsWin.idl @@ -30,18 +30,18 @@ interface nsIPrintSettingsWin : nsISuppo * you own the memory. * * The following three pieces of data are needed * to create a DC for printing. These are typcially * gotten via the PrintDLG call ro can be obtained * via the "m_pd" data member of the CPrintDialog * in MFC. */ - [noscript] attribute wstring deviceName; - [noscript] attribute wstring driverName; + [noscript] attribute AString deviceName; + [noscript] attribute AString driverName; [noscript] attribute nsDevMode devMode; /** * On Windows we use the printable width and height for the printing surface. * We don't want to have to create native print device contexts in the content * process, so we need to store these in the settings. * Storing in Inches is most convenient as they are retrieved from the device
--- a/widget/nsIPrinterEnumerator.idl +++ b/widget/nsIPrinterEnumerator.idl @@ -13,25 +13,26 @@ interface nsIStringEnumerator; interface nsIPrinterEnumerator : nsISupports { /** * The name of the system default printer. This name should also be * present in printerNameList below. This is not necessarily gecko's * default printer; see nsIPrintSettingsService.defaultPrinterName * for that. */ - readonly attribute wstring defaultPrinterName; + readonly attribute AString defaultPrinterName; /** * Initializes certain settings from the native printer into the PrintSettings * These settings include, but are not limited to: * Page Orientation * Page Size * Number of Copies */ - void initPrintSettingsFromPrinter(in wstring aPrinterName, in nsIPrintSettings aPrintSettings); + void initPrintSettingsFromPrinter(in AString aPrinterName, + in nsIPrintSettings aPrintSettings); /** * The list of printer names */ readonly attribute nsIStringEnumerator printerNameList; };
--- a/widget/nsPrintOptionsImpl.cpp +++ b/widget/nsPrintOptionsImpl.cpp @@ -133,83 +133,52 @@ nsPrintOptions::SerializeToPrintData(nsI aSettings->GetUnwriteableMarginRight(&data->unwriteableMarginRight()); aSettings->GetScaling(&data->scaling()); aSettings->GetPrintBGColors(&data->printBGColors()); aSettings->GetPrintBGImages(&data->printBGImages()); aSettings->GetPrintRange(&data->printRange()); - // I have no idea if I'm doing this string copying correctly... - nsString title; - aSettings->GetTitle(getter_Copies(title)); - data->title() = title; - - nsString docURL; - aSettings->GetDocURL(getter_Copies(docURL)); - data->docURL() = docURL; - - // Header strings... - nsString headerStrLeft; - aSettings->GetHeaderStrLeft(getter_Copies(headerStrLeft)); - data->headerStrLeft() = headerStrLeft; + aSettings->GetTitle(data->title()); + aSettings->GetDocURL(data->docURL()); - nsString headerStrCenter; - aSettings->GetHeaderStrCenter(getter_Copies(headerStrCenter)); - data->headerStrCenter() = headerStrCenter; - - nsString headerStrRight; - aSettings->GetHeaderStrRight(getter_Copies(headerStrRight)); - data->headerStrRight() = headerStrRight; + aSettings->GetHeaderStrLeft(data->headerStrLeft()); + aSettings->GetHeaderStrCenter(data->headerStrCenter()); + aSettings->GetHeaderStrRight(data->headerStrRight()); - // Footer strings... - nsString footerStrLeft; - aSettings->GetFooterStrLeft(getter_Copies(footerStrLeft)); - data->footerStrLeft() = footerStrLeft; - - nsString footerStrCenter; - aSettings->GetFooterStrCenter(getter_Copies(footerStrCenter)); - data->footerStrCenter() = footerStrCenter; - - nsString footerStrRight; - aSettings->GetFooterStrRight(getter_Copies(footerStrRight)); - data->footerStrRight() = footerStrRight; + aSettings->GetFooterStrLeft(data->footerStrLeft()); + aSettings->GetFooterStrCenter(data->footerStrCenter()); + aSettings->GetFooterStrRight(data->footerStrRight()); aSettings->GetHowToEnableFrameUI(&data->howToEnableFrameUI()); aSettings->GetIsCancelled(&data->isCancelled()); aSettings->GetPrintFrameTypeUsage(&data->printFrameTypeUsage()); aSettings->GetPrintFrameType(&data->printFrameType()); aSettings->GetPrintSilent(&data->printSilent()); aSettings->GetShrinkToFit(&data->shrinkToFit()); aSettings->GetShowPrintProgress(&data->showPrintProgress()); - nsString paperName; - aSettings->GetPaperName(getter_Copies(paperName)); - data->paperName() = paperName; - + aSettings->GetPaperName(data->paperName()); aSettings->GetPaperData(&data->paperData()); aSettings->GetPaperWidth(&data->paperWidth()); aSettings->GetPaperHeight(&data->paperHeight()); aSettings->GetPaperSizeUnit(&data->paperSizeUnit()); aSettings->GetPrintReversed(&data->printReversed()); aSettings->GetPrintInColor(&data->printInColor()); aSettings->GetOrientation(&data->orientation()); aSettings->GetNumCopies(&data->numCopies()); - nsString printerName; - aSettings->GetPrinterName(getter_Copies(printerName)); - data->printerName() = printerName; + aSettings->GetPrinterName(data->printerName()); aSettings->GetPrintToFile(&data->printToFile()); - nsString toFileName; - aSettings->GetToFileName(getter_Copies(toFileName)); - data->toFileName() = toFileName; + aSettings->GetToFileName(data->toFileName()); aSettings->GetOutputFormat(&data->outputFormat()); aSettings->GetPrintPageDelay(&data->printPageDelay()); aSettings->GetResolution(&data->resolution()); aSettings->GetDuplex(&data->duplex()); aSettings->GetIsInitializedFromPrinter(&data->isInitializedFromPrinter()); aSettings->GetIsInitializedFromPrefs(&data->isInitializedFromPrefs()); @@ -271,56 +240,55 @@ nsPrintOptions::DeserializeToPrintSettin settings->SetUnwriteableMarginRight(data.unwriteableMarginRight()); settings->SetScaling(data.scaling()); settings->SetPrintBGColors(data.printBGColors()); settings->SetPrintBGImages(data.printBGImages()); settings->SetPrintRange(data.printRange()); - // I have no idea if I'm doing this string copying correctly... - settings->SetTitle(data.title().get()); - settings->SetDocURL(data.docURL().get()); + settings->SetTitle(data.title()); + settings->SetDocURL(data.docURL()); // Header strings... - settings->SetHeaderStrLeft(data.headerStrLeft().get()); - settings->SetHeaderStrCenter(data.headerStrCenter().get()); - settings->SetHeaderStrRight(data.headerStrRight().get()); + settings->SetHeaderStrLeft(data.headerStrLeft()); + settings->SetHeaderStrCenter(data.headerStrCenter()); + settings->SetHeaderStrRight(data.headerStrRight()); // Footer strings... - settings->SetFooterStrLeft(data.footerStrLeft().get()); - settings->SetFooterStrCenter(data.footerStrCenter().get()); - settings->SetFooterStrRight(data.footerStrRight().get()); + settings->SetFooterStrLeft(data.footerStrLeft()); + settings->SetFooterStrCenter(data.footerStrCenter()); + settings->SetFooterStrRight(data.footerStrRight()); settings->SetHowToEnableFrameUI(data.howToEnableFrameUI()); settings->SetIsCancelled(data.isCancelled()); settings->SetPrintFrameTypeUsage(data.printFrameTypeUsage()); settings->SetPrintFrameType(data.printFrameType()); settings->SetPrintSilent(data.printSilent()); settings->SetShrinkToFit(data.shrinkToFit()); settings->SetShowPrintProgress(data.showPrintProgress()); - settings->SetPaperName(data.paperName().get()); + settings->SetPaperName(data.paperName()); settings->SetPaperData(data.paperData()); settings->SetPaperWidth(data.paperWidth()); settings->SetPaperHeight(data.paperHeight()); settings->SetPaperSizeUnit(data.paperSizeUnit()); settings->SetPrintReversed(data.printReversed()); settings->SetPrintInColor(data.printInColor()); settings->SetOrientation(data.orientation()); settings->SetNumCopies(data.numCopies()); - settings->SetPrinterName(data.printerName().get()); + settings->SetPrinterName(data.printerName()); settings->SetPrintToFile(data.printToFile()); - settings->SetToFileName(data.toFileName().get()); + settings->SetToFileName(data.toFileName()); settings->SetOutputFormat(data.outputFormat()); settings->SetPrintPageDelay(data.printPageDelay()); settings->SetResolution(data.resolution()); settings->SetDuplex(data.duplex()); settings->SetIsInitializedFromPrinter(data.isInitializedFromPrinter()); settings->SetIsInitializedFromPrefs(data.isInitializedFromPrefs()); @@ -528,17 +496,17 @@ nsPrintOptions::ReadPrefs(nsIPrintSettin if (success) { aPS->SetPaperSizeUnit(sizeUnit); DUMP_INT(kReadStr, kPrintPaperSizeUnit, sizeUnit); aPS->SetPaperWidth(width); DUMP_DBL(kReadStr, kPrintPaperWidth, width); aPS->SetPaperHeight(height); DUMP_DBL(kReadStr, kPrintPaperHeight, height); - aPS->SetPaperName(str.get()); + aPS->SetPaperName(str); DUMP_STR(kReadStr, kPrintPaperName, str.get()); #if defined(XP_WIN) if (saveSanitizedSizePrefs) { SavePrintSettingsToPrefs(aPS, !aPrinterName.IsEmpty(), nsIPrintSettings::kInitSavePaperSize); } #endif } @@ -555,52 +523,52 @@ nsPrintOptions::ReadPrefs(nsIPrintSettin if (GETBOOLPREF(kPrintOddPages, &b)) { aPS->SetPrintOptions(nsIPrintSettings::kPrintOddPages, b); DUMP_BOOL(kReadStr, kPrintOddPages, b); } } if (aFlags & nsIPrintSettings::kInitSaveHeaderLeft) { if (GETSTRPREF(kPrintHeaderStrLeft, str)) { - aPS->SetHeaderStrLeft(str.get()); + aPS->SetHeaderStrLeft(str); DUMP_STR(kReadStr, kPrintHeaderStrLeft, str.get()); } } if (aFlags & nsIPrintSettings::kInitSaveHeaderCenter) { if (GETSTRPREF(kPrintHeaderStrCenter, str)) { - aPS->SetHeaderStrCenter(str.get()); + aPS->SetHeaderStrCenter(str); DUMP_STR(kReadStr, kPrintHeaderStrCenter, str.get()); } } if (aFlags & nsIPrintSettings::kInitSaveHeaderRight) { if (GETSTRPREF(kPrintHeaderStrRight, str)) { - aPS->SetHeaderStrRight(str.get()); + aPS->SetHeaderStrRight(str); DUMP_STR(kReadStr, kPrintHeaderStrRight, str.get()); } } if (aFlags & nsIPrintSettings::kInitSaveFooterLeft) { if (GETSTRPREF(kPrintFooterStrLeft, str)) { - aPS->SetFooterStrLeft(str.get()); + aPS->SetFooterStrLeft(str); DUMP_STR(kReadStr, kPrintFooterStrLeft, str.get()); } } if (aFlags & nsIPrintSettings::kInitSaveFooterCenter) { if (GETSTRPREF(kPrintFooterStrCenter, str)) { - aPS->SetFooterStrCenter(str.get()); + aPS->SetFooterStrCenter(str); DUMP_STR(kReadStr, kPrintFooterStrCenter, str.get()); } } if (aFlags & nsIPrintSettings::kInitSaveFooterRight) { if (GETSTRPREF(kPrintFooterStrRight, str)) { - aPS->SetFooterStrRight(str.get()); + aPS->SetFooterStrRight(str); DUMP_STR(kReadStr, kPrintFooterStrRight, str.get()); } } if (aFlags & nsIPrintSettings::kInitSaveBGColors) { if (GETBOOLPREF(kPrintBGColors, &b)) { aPS->SetPrintBGColors(b); DUMP_BOOL(kReadStr, kPrintBGColors, b); @@ -646,17 +614,17 @@ nsPrintOptions::ReadPrefs(nsIPrintSettin if (GETBOOLPREF(kPrintToFile, &b)) { aPS->SetPrintToFile(b); DUMP_BOOL(kReadStr, kPrintToFile, b); } } if (aFlags & nsIPrintSettings::kInitSaveToFileName) { if (GETSTRPREF(kPrintToFileName, str)) { - aPS->SetToFileName(str.get()); + aPS->SetToFileName(str); DUMP_STR(kReadStr, kPrintToFileName, str.get()); } } if (aFlags & nsIPrintSettings::kInitSavePageDelay) { if (GETINTPREF(kPrintPageDelay, &iVal)) { aPS->SetPrintPageDelay(iVal); DUMP_INT(kReadStr, kPrintPageDelay, iVal); @@ -766,17 +734,17 @@ nsPrintOptions::WritePrefs(nsIPrintSetti int16_t sizeUnit; double width, height; nsString name; if ( NS_SUCCEEDED(aPS->GetPaperSizeUnit(&sizeUnit)) && NS_SUCCEEDED(aPS->GetPaperWidth(&width)) && NS_SUCCEEDED(aPS->GetPaperHeight(&height)) && - NS_SUCCEEDED(aPS->GetPaperName(getter_Copies(name))) + NS_SUCCEEDED(aPS->GetPaperName(name)) ) { DUMP_INT(kWriteStr, kPrintPaperSizeUnit, sizeUnit); Preferences::SetInt(GetPrefName(kPrintPaperSizeUnit, aPrinterName), int32_t(sizeUnit)); DUMP_DBL(kWriteStr, kPrintPaperWidth, width); WritePrefDouble(GetPrefName(kPrintPaperWidth, aPrinterName), width); DUMP_DBL(kWriteStr, kPrintPaperHeight, height); WritePrefDouble(GetPrefName(kPrintPaperHeight, aPrinterName), height); @@ -817,57 +785,57 @@ nsPrintOptions::WritePrefs(nsIPrintSetti if (NS_SUCCEEDED(aPS->GetPrintOptions(nsIPrintSettings::kPrintOddPages, &b))) { DUMP_BOOL(kWriteStr, kPrintOddPages, b); Preferences::SetBool(GetPrefName(kPrintOddPages, aPrinterName), b); } } if (aFlags & nsIPrintSettings::kInitSaveHeaderLeft) { - if (NS_SUCCEEDED(aPS->GetHeaderStrLeft(getter_Copies(uStr)))) { + if (NS_SUCCEEDED(aPS->GetHeaderStrLeft(uStr))) { DUMP_STR(kWriteStr, kPrintHeaderStrLeft, uStr.get()); Preferences::SetString(GetPrefName(kPrintHeaderStrLeft, aPrinterName), uStr); } } if (aFlags & nsIPrintSettings::kInitSaveHeaderCenter) { - if (NS_SUCCEEDED(aPS->GetHeaderStrCenter(getter_Copies(uStr)))) { + if (NS_SUCCEEDED(aPS->GetHeaderStrCenter(uStr))) { DUMP_STR(kWriteStr, kPrintHeaderStrCenter, uStr.get()); Preferences::SetString(GetPrefName(kPrintHeaderStrCenter, aPrinterName), uStr); } } if (aFlags & nsIPrintSettings::kInitSaveHeaderRight) { - if (NS_SUCCEEDED(aPS->GetHeaderStrRight(getter_Copies(uStr)))) { + if (NS_SUCCEEDED(aPS->GetHeaderStrRight(uStr))) { DUMP_STR(kWriteStr, kPrintHeaderStrRight, uStr.get()); Preferences::SetString(GetPrefName(kPrintHeaderStrRight, aPrinterName), uStr); } } if (aFlags & nsIPrintSettings::kInitSaveFooterLeft) { - if (NS_SUCCEEDED(aPS->GetFooterStrLeft(getter_Copies(uStr)))) { + if (NS_SUCCEEDED(aPS->GetFooterStrLeft(uStr))) { DUMP_STR(kWriteStr, kPrintFooterStrLeft, uStr.get()); Preferences::SetString(GetPrefName(kPrintFooterStrLeft, aPrinterName), uStr); } } if (aFlags & nsIPrintSettings::kInitSaveFooterCenter) { - if (NS_SUCCEEDED(aPS->GetFooterStrCenter(getter_Copies(uStr)))) { + if (NS_SUCCEEDED(aPS->GetFooterStrCenter(uStr))) { DUMP_STR(kWriteStr, kPrintFooterStrCenter, uStr.get()); Preferences::SetString(GetPrefName(kPrintFooterStrCenter, aPrinterName), uStr); } } if (aFlags & nsIPrintSettings::kInitSaveFooterRight) { - if (NS_SUCCEEDED(aPS->GetFooterStrRight(getter_Copies(uStr)))) { + if (NS_SUCCEEDED(aPS->GetFooterStrRight(uStr))) { DUMP_STR(kWriteStr, kPrintFooterStrRight, uStr.get()); Preferences::SetString(GetPrefName(kPrintFooterStrRight, aPrinterName), uStr); } } if (aFlags & nsIPrintSettings::kInitSaveBGColors) { if (NS_SUCCEEDED(aPS->GetPrintBGColors(&b))) { @@ -910,31 +878,31 @@ nsPrintOptions::WritePrefs(nsIPrintSetti DUMP_INT(kWriteStr, kPrintOrientation, iVal); Preferences::SetInt(GetPrefName(kPrintOrientation, aPrinterName), iVal); } } // Only the general version of this pref is saved if ((aFlags & nsIPrintSettings::kInitSavePrinterName) && aPrinterName.IsEmpty()) { - if (NS_SUCCEEDED(aPS->GetPrinterName(getter_Copies(uStr)))) { + if (NS_SUCCEEDED(aPS->GetPrinterName(uStr))) { DUMP_STR(kWriteStr, kPrinterName, uStr.get()); Preferences::SetString(kPrinterName, uStr); } } if (aFlags & nsIPrintSettings::kInitSavePrintToFile) { if (NS_SUCCEEDED(aPS->GetPrintToFile(&b))) { DUMP_BOOL(kWriteStr, kPrintToFile, b); Preferences::SetBool(GetPrefName(kPrintToFile, aPrinterName), b); } } if (aFlags & nsIPrintSettings::kInitSaveToFileName) { - if (NS_SUCCEEDED(aPS->GetToFileName(getter_Copies(uStr)))) { + if (NS_SUCCEEDED(aPS->GetToFileName(uStr))) { DUMP_STR(kWriteStr, kPrintToFileName, uStr.get()); Preferences::SetString(GetPrefName(kPrintToFileName, aPrinterName), uStr); } } if (aFlags & nsIPrintSettings::kInitSavePageDelay) { if (NS_SUCCEEDED(aPS->GetPrintPageDelay(&iVal))) { DUMP_INT(kWriteStr, kPrintPageDelay, iVal); @@ -980,19 +948,19 @@ nsresult nsPrintOptions::_CreatePrintSet { // does not initially ref count nsPrintSettings * printSettings = new nsPrintSettings(); NS_ENSURE_TRUE(printSettings, NS_ERROR_OUT_OF_MEMORY); NS_ADDREF(*_retval = printSettings); // ref count nsString printerName; - nsresult rv = GetDefaultPrinterName(getter_Copies(printerName)); + nsresult rv = GetDefaultPrinterName(printerName); NS_ENSURE_SUCCESS(rv, rv); - (*_retval)->SetPrinterName(printerName.get()); + (*_retval)->SetPrinterName(printerName); (void)InitPrintSettingsFromPrefs(*_retval, false, nsIPrintSettings::kInitSaveAll); return NS_OK; } NS_IMETHODIMP @@ -1010,17 +978,17 @@ nsPrintOptions::GetGlobalPrintSettings(n NS_IMETHODIMP nsPrintOptions::GetNewPrintSettings(nsIPrintSettings * *aNewPrintSettings) { return _CreatePrintSettings(aNewPrintSettings); } NS_IMETHODIMP -nsPrintOptions::GetDefaultPrinterName(char16_t * *aDefaultPrinterName) +nsPrintOptions::GetDefaultPrinterName(nsAString& aDefaultPrinterName) { nsresult rv; nsCOMPtr<nsIPrinterEnumerator> prtEnum = do_GetService(NS_PRINTER_ENUMERATOR_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); // Look up the printer from the last print job nsAutoString lastPrinterName; @@ -1035,43 +1003,42 @@ nsPrintOptions::GetDefaultPrinterName(ch while (NS_SUCCEEDED(printers->HasMore(&hasMore)) && hasMore) { nsAutoString printer; if (NS_SUCCEEDED(printers->GetNext(printer)) && lastPrinterName.Equals(printer)) { isValid = true; break; } } if (isValid) { - *aDefaultPrinterName = ToNewUnicode(lastPrinterName); + aDefaultPrinterName = lastPrinterName; return NS_OK; } } } // There is no last printer preference, or it doesn't name a valid printer. // Return the default from the printer enumeration. return prtEnum->GetDefaultPrinterName(aDefaultPrinterName); } NS_IMETHODIMP -nsPrintOptions::InitPrintSettingsFromPrinter(const char16_t *aPrinterName, +nsPrintOptions::InitPrintSettingsFromPrinter(const nsAString& aPrinterName, nsIPrintSettings *aPrintSettings) { // Don't get print settings from the printer in the child when printing via // parent, these will be retrieved in the parent later in the print process. if (XRE_IsContentProcess() && Preferences::GetBool("print.print_via_parent")) { return NS_OK; } NS_ENSURE_ARG_POINTER(aPrintSettings); - NS_ENSURE_ARG_POINTER(aPrinterName); #ifdef DEBUG nsString printerName; - aPrintSettings->GetPrinterName(getter_Copies(printerName)); + aPrintSettings->GetPrinterName(printerName); if (!printerName.Equals(aPrinterName)) { NS_WARNING("Printer names should match!"); } #endif bool isInitialized; aPrintSettings->GetIsInitializedFromPrinter(&isInitialized); if (isInitialized) @@ -1100,17 +1067,17 @@ GetAdjustedPrinterName(nsIPrintSettings* NS_ENSURE_ARG_POINTER(aPS); aPrinterName.Truncate(); if (!aUsePNP) return NS_OK; // Get the Printer Name from the PrintSettings // to use as a prefix for Pref Names - nsresult rv = aPS->GetPrinterName(getter_Copies(aPrinterName)); + nsresult rv = aPS->GetPrinterName(aPrinterName); NS_ENSURE_SUCCESS(rv, rv); // Convert any whitespaces, carriage returns or newlines to _ // The below algorithm is supposedly faster than using iterators NS_NAMED_LITERAL_STRING(replSubstr, "_"); const char* replaceStr = " \n\r"; int32_t x;
--- a/widget/nsPrintSettingsImpl.cpp +++ b/widget/nsPrintSettingsImpl.cpp @@ -187,29 +187,25 @@ NS_IMETHODIMP nsPrintSettings::GetDuplex return NS_OK; } NS_IMETHODIMP nsPrintSettings::SetDuplex(const int32_t aDuplex) { mDuplex = aDuplex; return NS_OK; } -NS_IMETHODIMP nsPrintSettings::GetPrinterName(char16_t * *aPrinter) +NS_IMETHODIMP nsPrintSettings::GetPrinterName(nsAString& aPrinter) { - NS_ENSURE_ARG_POINTER(aPrinter); - - *aPrinter = ToNewUnicode(mPrinter); - NS_ENSURE_TRUE(*aPrinter, NS_ERROR_OUT_OF_MEMORY); - + aPrinter = mPrinter; return NS_OK; } -NS_IMETHODIMP nsPrintSettings::SetPrinterName(const char16_t * aPrinter) +NS_IMETHODIMP nsPrintSettings::SetPrinterName(const nsAString& aPrinter) { - if (!aPrinter || !mPrinter.Equals(aPrinter)) { + if (!mPrinter.Equals(aPrinter)) { mIsInitedFromPrinter = false; mIsInitedFromPrefs = false; } mPrinter.Assign(aPrinter); return NS_OK; } @@ -232,29 +228,24 @@ NS_IMETHODIMP nsPrintSettings::GetPrintT return NS_OK; } NS_IMETHODIMP nsPrintSettings::SetPrintToFile(bool aPrintToFile) { mPrintToFile = aPrintToFile; return NS_OK; } -NS_IMETHODIMP nsPrintSettings::GetToFileName(char16_t * *aToFileName) +NS_IMETHODIMP nsPrintSettings::GetToFileName(nsAString& aToFileName) { - //NS_ENSURE_ARG_POINTER(aToFileName); - *aToFileName = ToNewUnicode(mToFileName); + aToFileName = mToFileName; return NS_OK; } -NS_IMETHODIMP nsPrintSettings::SetToFileName(const char16_t * aToFileName) +NS_IMETHODIMP nsPrintSettings::SetToFileName(const nsAString& aToFileName) { - if (aToFileName) { - mToFileName = aToFileName; - } else { - mToFileName.SetLength(0); - } + mToFileName = aToFileName; return NS_OK; } NS_IMETHODIMP nsPrintSettings::GetOutputFormat(int16_t *aOutputFormat) { NS_ENSURE_ARG_POINTER(aOutputFormat); *aOutputFormat = mOutputFormat; return NS_OK; @@ -496,53 +487,35 @@ NS_IMETHODIMP nsPrintSettings::GetPrintR return NS_OK; } NS_IMETHODIMP nsPrintSettings::SetPrintRange(int16_t aPrintRange) { mPrintRange = aPrintRange; return NS_OK; } -NS_IMETHODIMP nsPrintSettings::GetTitle(char16_t * *aTitle) +NS_IMETHODIMP nsPrintSettings::GetTitle(nsAString& aTitle) { - NS_ENSURE_ARG_POINTER(aTitle); - if (!mTitle.IsEmpty()) { - *aTitle = ToNewUnicode(mTitle); - } else { - *aTitle = nullptr; - } + aTitle = mTitle; return NS_OK; } -NS_IMETHODIMP nsPrintSettings::SetTitle(const char16_t * aTitle) +NS_IMETHODIMP nsPrintSettings::SetTitle(const nsAString& aTitle) { - if (aTitle) { - mTitle = aTitle; - } else { - mTitle.SetLength(0); - } + mTitle = aTitle; return NS_OK; } -NS_IMETHODIMP nsPrintSettings::GetDocURL(char16_t * *aDocURL) +NS_IMETHODIMP nsPrintSettings::GetDocURL(nsAString& aDocURL) { - NS_ENSURE_ARG_POINTER(aDocURL); - if (!mURL.IsEmpty()) { - *aDocURL = ToNewUnicode(mURL); - } else { - *aDocURL = nullptr; - } + aDocURL = mURL; return NS_OK; } -NS_IMETHODIMP nsPrintSettings::SetDocURL(const char16_t * aDocURL) +NS_IMETHODIMP nsPrintSettings::SetDocURL(const nsAString& aDocURL) { - if (aDocURL) { - mURL = aDocURL; - } else { - mURL.SetLength(0); - } + mURL = aDocURL; return NS_OK; } /** --------------------------------------------------- * See documentation in nsPrintSettingsImpl.h * @update 1/12/01 rods */ NS_IMETHODIMP @@ -581,113 +554,80 @@ nsPrintSettings::GetPrintOptionsBits(int NS_IMETHODIMP nsPrintSettings::SetPrintOptionsBits(int32_t aBits) { mPrintOptions = aBits; return NS_OK; } -nsresult -nsPrintSettings::GetMarginStrs(char16_t * *aTitle, - nsHeaderFooterEnum aType, - int16_t aJust) +NS_IMETHODIMP nsPrintSettings::GetHeaderStrLeft(nsAString& aTitle) { - NS_ENSURE_ARG_POINTER(aTitle); - *aTitle = nullptr; - if (aType == eHeader) { - switch (aJust) { - case kJustLeft: *aTitle = ToNewUnicode(mHeaderStrs[0]);break; - case kJustCenter: *aTitle = ToNewUnicode(mHeaderStrs[1]);break; - case kJustRight: *aTitle = ToNewUnicode(mHeaderStrs[2]);break; - } //switch - } else { - switch (aJust) { - case kJustLeft: *aTitle = ToNewUnicode(mFooterStrs[0]);break; - case kJustCenter: *aTitle = ToNewUnicode(mFooterStrs[1]);break; - case kJustRight: *aTitle = ToNewUnicode(mFooterStrs[2]);break; - } //switch - } + aTitle = mHeaderStrs[0]; + return NS_OK; +} +NS_IMETHODIMP nsPrintSettings::SetHeaderStrLeft(const nsAString& aTitle) +{ + mHeaderStrs[0] = aTitle; return NS_OK; } -nsresult -nsPrintSettings::SetMarginStrs(const char16_t * aTitle, - nsHeaderFooterEnum aType, - int16_t aJust) +NS_IMETHODIMP nsPrintSettings::GetHeaderStrCenter(nsAString& aTitle) { - NS_ENSURE_ARG_POINTER(aTitle); - if (aType == eHeader) { - switch (aJust) { - case kJustLeft: mHeaderStrs[0] = aTitle;break; - case kJustCenter: mHeaderStrs[1] = aTitle;break; - case kJustRight: mHeaderStrs[2] = aTitle;break; - } //switch - } else { - switch (aJust) { - case kJustLeft: mFooterStrs[0] = aTitle;break; - case kJustCenter: mFooterStrs[1] = aTitle;break; - case kJustRight: mFooterStrs[2] = aTitle;break; - } //switch - } + aTitle = mHeaderStrs[1]; + return NS_OK; +} +NS_IMETHODIMP nsPrintSettings::SetHeaderStrCenter(const nsAString& aTitle) +{ + mHeaderStrs[1] = aTitle; return NS_OK; } -NS_IMETHODIMP nsPrintSettings::GetHeaderStrLeft(char16_t * *aTitle) +NS_IMETHODIMP nsPrintSettings::GetHeaderStrRight(nsAString& aTitle) { - return GetMarginStrs(aTitle, eHeader, kJustLeft); -} -NS_IMETHODIMP nsPrintSettings::SetHeaderStrLeft(const char16_t * aTitle) -{ - return SetMarginStrs(aTitle, eHeader, kJustLeft); + aTitle = mHeaderStrs[2]; + return NS_OK; } - -NS_IMETHODIMP nsPrintSettings::GetHeaderStrCenter(char16_t * *aTitle) +NS_IMETHODIMP nsPrintSettings::SetHeaderStrRight(const nsAString& aTitle) { - return GetMarginStrs(aTitle, eHeader, kJustCenter); -} -NS_IMETHODIMP nsPrintSettings::SetHeaderStrCenter(const char16_t * aTitle) -{ - return SetMarginStrs(aTitle, eHeader, kJustCenter); + mHeaderStrs[2] = aTitle; + return NS_OK; } -NS_IMETHODIMP nsPrintSettings::GetHeaderStrRight(char16_t * *aTitle) +NS_IMETHODIMP nsPrintSettings::GetFooterStrLeft(nsAString& aTitle) { - return GetMarginStrs(aTitle, eHeader, kJustRight); + aTitle = mFooterStrs[0]; + return NS_OK; } -NS_IMETHODIMP nsPrintSettings::SetHeaderStrRight(const char16_t * aTitle) +NS_IMETHODIMP nsPrintSettings::SetFooterStrLeft(const nsAString& aTitle) { - return SetMarginStrs(aTitle, eHeader, kJustRight); + mFooterStrs[0] = aTitle; + return NS_OK; } -NS_IMETHODIMP nsPrintSettings::GetFooterStrLeft(char16_t * *aTitle) +NS_IMETHODIMP nsPrintSettings::GetFooterStrCenter(nsAString& aTitle) { - return GetMarginStrs(aTitle, eFooter, kJustLeft); + aTitle = mFooterStrs[1]; + return NS_OK; } -NS_IMETHODIMP nsPrintSettings::SetFooterStrLeft(const char16_t * aTitle) +NS_IMETHODIMP nsPrintSettings::SetFooterStrCenter(const nsAString& aTitle) { - return SetMarginStrs(aTitle, eFooter, kJustLeft); + mFooterStrs[1] = aTitle; + return NS_OK; } -NS_IMETHODIMP nsPrintSettings::GetFooterStrCenter(char16_t * *aTitle) +NS_IMETHODIMP nsPrintSettings::GetFooterStrRight(nsAString& aTitle) { - return GetMarginStrs(aTitle, eFooter, kJustCenter); -} -NS_IMETHODIMP nsPrintSettings::SetFooterStrCenter(const char16_t * aTitle) -{ - return SetMarginStrs(aTitle, eFooter, kJustCenter); + aTitle = mFooterStrs[2]; + return NS_OK; } - -NS_IMETHODIMP nsPrintSettings::GetFooterStrRight(char16_t * *aTitle) +NS_IMETHODIMP nsPrintSettings::SetFooterStrRight(const nsAString& aTitle) { - return GetMarginStrs(aTitle, eFooter, kJustRight); -} -NS_IMETHODIMP nsPrintSettings::SetFooterStrRight(const char16_t * aTitle) -{ - return SetMarginStrs(aTitle, eFooter, kJustRight); + mFooterStrs[2] = aTitle; + return NS_OK; } NS_IMETHODIMP nsPrintSettings::GetPrintFrameTypeUsage(int16_t *aPrintFrameTypeUsage) { NS_ENSURE_ARG_POINTER(aPrintFrameTypeUsage); *aPrintFrameTypeUsage = mPrintFrameTypeUsage; return NS_OK; } @@ -740,33 +680,24 @@ NS_IMETHODIMP nsPrintSettings::GetShowPr return NS_OK; } NS_IMETHODIMP nsPrintSettings::SetShowPrintProgress(bool aShowPrintProgress) { mShowPrintProgress = aShowPrintProgress; return NS_OK; } -NS_IMETHODIMP nsPrintSettings::GetPaperName(char16_t * *aPaperName) +NS_IMETHODIMP nsPrintSettings::GetPaperName(nsAString& aPaperName) { - NS_ENSURE_ARG_POINTER(aPaperName); - if (!mPaperName.IsEmpty()) { - *aPaperName = ToNewUnicode(mPaperName); - } else { - *aPaperName = nullptr; - } + aPaperName = mPaperName; return NS_OK; } -NS_IMETHODIMP nsPrintSettings::SetPaperName(const char16_t * aPaperName) +NS_IMETHODIMP nsPrintSettings::SetPaperName(const nsAString& aPaperName) { - if (aPaperName) { - mPaperName = aPaperName; - } else { - mPaperName.SetLength(0); - } + mPaperName = aPaperName; return NS_OK; } NS_IMETHODIMP nsPrintSettings::GetHowToEnableFrameUI(int16_t *aHowToEnableFrameUI) { NS_ENSURE_ARG_POINTER(aHowToEnableFrameUI); *aHowToEnableFrameUI = mHowToEnableFrameUI; return NS_OK;
--- a/widget/nsPrintSettingsImpl.h +++ b/widget/nsPrintSettingsImpl.h @@ -37,19 +37,16 @@ protected: virtual nsresult _Assign(nsIPrintSettings *aPS); typedef enum { eHeader, eFooter } nsHeaderFooterEnum; - nsresult GetMarginStrs(char16_t * *aTitle, nsHeaderFooterEnum aType, int16_t aJust); - nsresult SetMarginStrs(const char16_t * aTitle, nsHeaderFooterEnum aType, int16_t aJust); - // Members nsWeakPtr mSession; // Should never be touched by Clone or Assign // mMargin, mEdge, and mUnwriteableMargin are stored in twips nsIntMargin mMargin; nsIntMargin mEdge; nsIntMargin mUnwriteableMargin;
--- a/widget/windows/nsDeviceContextSpecWin.cpp +++ b/widget/windows/nsDeviceContextSpecWin.cpp @@ -63,17 +63,17 @@ public: static GlobalPrinters* GetInstance() { return &mGlobalPrinters; } ~GlobalPrinters() { FreeGlobalPrinters(); } void FreeGlobalPrinters(); bool PrintersAreAllocated() { return mPrinters != nullptr; } LPWSTR GetItemFromList(int32_t aInx) { return mPrinters?mPrinters->ElementAt(aInx):nullptr; } nsresult EnumeratePrinterList(); - void GetDefaultPrinterName(nsString& aDefaultPrinterName); + void GetDefaultPrinterName(nsAString& aDefaultPrinterName); uint32_t GetNumPrinters() { return mPrinters?mPrinters->Length():0; } protected: GlobalPrinters() {} nsresult EnumerateNativePrinters(); void ReallocatePrinters(); static GlobalPrinters mGlobalPrinters; @@ -89,18 +89,16 @@ struct AutoFreeGlobalPrinters ~AutoFreeGlobalPrinters() { GlobalPrinters::GetInstance()->FreeGlobalPrinters(); } }; //---------------------------------------------------------------------------------- nsDeviceContextSpecWin::nsDeviceContextSpecWin() { - mDriverName = nullptr; - mDeviceName = nullptr; mDevMode = nullptr; #ifdef MOZ_ENABLE_SKIA_PDF mPrintViaSkPDF = false; mDC = NULL; mPDFPageCount = 0; mPDFCurrentPageNum = 0; mPrintViaPDFInProgress = false; #endif @@ -108,46 +106,34 @@ nsDeviceContextSpecWin::nsDeviceContextS //---------------------------------------------------------------------------------- NS_IMPL_ISUPPORTS(nsDeviceContextSpecWin, nsIDeviceContextSpec) nsDeviceContextSpecWin::~nsDeviceContextSpecWin() { - SetDeviceName(nullptr); - SetDriverName(nullptr); SetDevMode(nullptr); nsCOMPtr<nsIPrintSettingsWin> psWin(do_QueryInterface(mPrintSettings)); if (psWin) { - psWin->SetDeviceName(nullptr); - psWin->SetDriverName(nullptr); + psWin->SetDeviceName(EmptyString()); + psWin->SetDriverName(EmptyString()); psWin->SetDevMode(nullptr); } #ifdef MOZ_ENABLE_SKIA_PDF if (mPrintViaSkPDF ) { CleanupPrintViaPDF(); } #endif // Free them, we won't need them for a while GlobalPrinters::GetInstance()->FreeGlobalPrinters(); } - -//------------------------------------------------------------------ -// helper -static char16_t * GetDefaultPrinterNameFromGlobalPrinters() -{ - nsAutoString printerName; - GlobalPrinters::GetInstance()->GetDefaultPrinterName(printerName); - return ToNewUnicode(printerName); -} - //---------------------------------------------------------------------------------- NS_IMETHODIMP nsDeviceContextSpecWin::Init(nsIWidget* aWidget, nsIPrintSettings* aPrintSettings, bool aIsPrintPreview) { mPrintSettings = aPrintSettings; nsresult rv = NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE; @@ -166,91 +152,68 @@ NS_IMETHODIMP nsDeviceContextSpecWin::In if ((XRE_IsContentProcess() && Preferences::GetBool("print.print_via_parent")) || mOutputFormat == nsIPrintSettings::kOutputFormatPDF) { return NS_OK; } nsCOMPtr<nsIPrintSettingsWin> psWin(do_QueryInterface(aPrintSettings)); if (psWin) { - char16_t* deviceName; - char16_t* driverName; - psWin->GetDeviceName(&deviceName); // creates new memory (makes a copy) - psWin->GetDriverName(&driverName); // creates new memory (makes a copy) + nsAutoString deviceName; + nsAutoString driverName; + psWin->GetDeviceName(deviceName); + psWin->GetDriverName(driverName); LPDEVMODEW devMode; psWin->GetDevMode(&devMode); // creates new memory (makes a copy) - if (deviceName && driverName && devMode) { + if (!deviceName.IsEmpty() && !driverName.IsEmpty() && devMode) { // Scaling is special, it is one of the few // devMode items that we control in layout if (devMode->dmFields & DM_SCALE) { double scale = double(devMode->dmScale) / 100.0f; if (scale != 1.0) { aPrintSettings->SetScaling(scale); devMode->dmScale = 100; } } SetDeviceName(deviceName); SetDriverName(driverName); SetDevMode(devMode); - // clean up - free(deviceName); - free(driverName); - return NS_OK; } else { PR_PL(("***** nsDeviceContextSpecWin::Init - deviceName/driverName/devMode was NULL!\n")); - if (deviceName) free(deviceName); - if (driverName) free(driverName); if (devMode) ::HeapFree(::GetProcessHeap(), 0, devMode); } } } else { PR_PL(("***** nsDeviceContextSpecWin::Init - aPrintSettingswas NULL!\n")); } // Get the Printer Name to be used and output format. - char16_t * printerName = nullptr; + nsAutoString printerName; if (mPrintSettings) { - mPrintSettings->GetPrinterName(&printerName); + mPrintSettings->GetPrinterName(printerName); } // If there is no name then use the default printer - if (!printerName || (printerName && !*printerName)) { - printerName = GetDefaultPrinterNameFromGlobalPrinters(); + if (printerName.IsEmpty()) { + GlobalPrinters::GetInstance()->GetDefaultPrinterName(printerName); } - NS_ASSERTION(printerName, "We have to have a printer name"); - if (!printerName || !*printerName) return rv; + if (printerName.IsEmpty()) { + return rv; + } return GetDataFromPrinter(printerName, mPrintSettings); } //---------------------------------------------------------- -// Helper Function - Free and reallocate the string -static void CleanAndCopyString(wchar_t*& aStr, const wchar_t* aNewStr) -{ - if (aStr != nullptr) { - if (aNewStr != nullptr && wcslen(aStr) > wcslen(aNewStr)) { // reuse it if we can - wcscpy(aStr, aNewStr); - return; - } else { - free(aStr); - aStr = nullptr; - } - } - - if (nullptr != aNewStr) { - aStr = (wchar_t*) malloc(sizeof(wchar_t) * (wcslen(aNewStr) + 1)); - wcscpy(aStr, aNewStr); - } -} already_AddRefed<PrintTarget> nsDeviceContextSpecWin::MakePrintTarget() { NS_ASSERTION(mDevMode, "DevMode can't be NULL here"); #ifdef MOZ_ENABLE_SKIA_PDF if (mPrintViaSkPDF) { double width, height; @@ -261,17 +224,17 @@ already_AddRefed<PrintTarget> nsDeviceCo // convert twips to points width /= TWIPS_PER_POINT_FLOAT; height /= TWIPS_PER_POINT_FLOAT; IntSize size = IntSize::Truncate(width, height); if (mOutputFormat == nsIPrintSettings::kOutputFormatPDF) { nsString filename; - mPrintSettings->GetToFileName(getter_Copies(filename)); + mPrintSettings->GetToFileName(filename); nsAutoCString printFile(NS_ConvertUTF16toUTF8(filename).get()); auto skStream = MakeUnique<SkFILEWStream>(printFile.get()); return PrintTargetSkPDF::CreateOrNull(Move(skStream), size); } if (mDevMode) { // When printing to a printer via Skia PDF we open a temporary file that @@ -306,17 +269,17 @@ already_AddRefed<PrintTarget> nsDeviceCo auto skStream = MakeUnique<SkFILEWStream>(filePath.get()); return PrintTargetSkPDF::CreateOrNull(Move(skStream), size); } } #endif if (mOutputFormat == nsIPrintSettings::kOutputFormatPDF) { nsString filename; - mPrintSettings->GetToFileName(getter_Copies(filename)); + mPrintSettings->GetToFileName(filename); double width, height; mPrintSettings->GetEffectivePageSize(&width, &height); if (width <= 0 || height <= 0) { return nullptr; } // convert twips to points @@ -334,18 +297,18 @@ already_AddRefed<PrintTarget> nsDeviceCo if (NS_FAILED(rv)) { return nullptr; } return PrintTargetPDF::CreateOrNull(stream, IntSize::Truncate(width, height)); } if (mDevMode) { - NS_WARNING_ASSERTION(mDriverName, "No driver!"); - HDC dc = ::CreateDCW(mDriverName, mDeviceName, nullptr, mDevMode); + NS_WARNING_ASSERTION(!mDriverName.IsEmpty(), "No driver!"); + HDC dc = ::CreateDCW(mDriverName.get(), mDeviceName.get(), nullptr, mDevMode); if (!dc) { gfxCriticalError(gfxCriticalError::DefaultOptions(false)) << "Failed to create device context in GetSurfaceForPrinter"; return nullptr; } // The PrintTargetWindows takes over ownership of this DC return PrintTargetWindows::CreateOrNull(dc); @@ -452,18 +415,18 @@ nsDeviceContextSpecWin::BeginDocument(co int32_t aEndPage) { #ifdef MOZ_ENABLE_SKIA_PDF if (mPrintViaSkPDF && (mOutputFormat != nsIPrintSettings::kOutputFormatPDF)) { // Here we create mDC which we'll draw each page from our temporary PDF file // to once we reach EndDocument. The only reason we create it here rather // than in EndDocument is so that we don't need to store aTitle and // aPrintToFileName as member data. - NS_WARNING_ASSERTION(mDriverName, "No driver!"); - mDC = ::CreateDCW(mDriverName, mDeviceName, nullptr, mDevMode); + NS_WARNING_ASSERTION(!mDriverName.IsEmpty(), "No driver!"); + mDC = ::CreateDCW(mDriverName.get(), mDeviceName.get(), nullptr, mDevMode); if (mDC == NULL) { gfxCriticalError(gfxCriticalError::DefaultOptions(false)) << "Failed to create device context in GetSurfaceForPrinter"; return NS_ERROR_FAILURE; } const uint32_t DOC_TITLE_LENGTH = MAX_PATH - 1; nsString title(aTitle); @@ -522,25 +485,25 @@ nsDeviceContextSpecWin::EndDocument() NS_WARNING("Failed to dispatch to the current thread!"); } } #endif return rv; } //---------------------------------------------------------------------------------- -void nsDeviceContextSpecWin::SetDeviceName(char16ptr_t aDeviceName) +void nsDeviceContextSpecWin::SetDeviceName(const nsAString& aDeviceName) { - CleanAndCopyString(mDeviceName, aDeviceName); + mDeviceName = aDeviceName; } //---------------------------------------------------------------------------------- -void nsDeviceContextSpecWin::SetDriverName(char16ptr_t aDriverName) +void nsDeviceContextSpecWin::SetDriverName(const nsAString& aDriverName) { - CleanAndCopyString(mDriverName, aDriverName); + mDriverName = aDriverName; } //---------------------------------------------------------------------------------- void nsDeviceContextSpecWin::SetDevMode(LPDEVMODEW aDevMode) { if (mDevMode) { ::HeapFree(::GetProcessHeap(), 0, mDevMode); } @@ -555,46 +518,48 @@ nsDeviceContextSpecWin::GetDevMode(LPDEV aDevMode = mDevMode; } #define DISPLAY_LAST_ERROR //---------------------------------------------------------------------------------- // Setup the object's data member with the selected printer's data nsresult -nsDeviceContextSpecWin::GetDataFromPrinter(char16ptr_t aName, nsIPrintSettings* aPS) +nsDeviceContextSpecWin::GetDataFromPrinter(const nsAString& aName, + nsIPrintSettings* aPS) { nsresult rv = NS_ERROR_FAILURE; if (!GlobalPrinters::GetInstance()->PrintersAreAllocated()) { rv = GlobalPrinters::GetInstance()->EnumeratePrinterList(); if (NS_FAILED(rv)) { PR_PL(("***** nsDeviceContextSpecWin::GetDataFromPrinter - Couldn't enumerate printers!\n")); DISPLAY_LAST_ERROR } NS_ENSURE_SUCCESS(rv, rv); } nsHPRINTER hPrinter = nullptr; - wchar_t *name = (wchar_t*)aName; // Windows APIs use non-const name argument + const nsString& flat = PromiseFlatString(aName); + wchar_t* name = (wchar_t*)flat.get(); // Windows APIs use non-const name argument BOOL status = ::OpenPrinterW(name, &hPrinter, nullptr); if (status) { nsAutoPrinter autoPrinter(hPrinter); LPDEVMODEW pDevMode; // Allocate a buffer of the correct size. LONG needed = ::DocumentPropertiesW(nullptr, hPrinter, name, nullptr, nullptr, 0); if (needed < 0) { PR_PL(("**** nsDeviceContextSpecWin::GetDataFromPrinter - Couldn't get " "size of DEVMODE using DocumentPropertiesW(pDeviceName = \"%s\"). " "GetLastEror() = %08x\n", - aName ? NS_ConvertUTF16toUTF8(aName).get() : "", GetLastError())); + NS_ConvertUTF16toUTF8(aName).get(), GetLastError())); return NS_ERROR_FAILURE; } pDevMode = (LPDEVMODEW)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, needed); if (!pDevMode) return NS_ERROR_FAILURE; // Get the default DevMode for the printer and modify it for our needs. @@ -609,17 +574,17 @@ nsDeviceContextSpecWin::GetDataFromPrint ret = ::DocumentPropertiesW(nullptr, hPrinter, name, pDevMode, pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER); // We need to copy the final DEVMODE settings back to our print settings, // because they may have been set from invalid prefs. if (ret == IDOK) { // We need to get information from the device as well. - nsAutoHDC printerDC(::CreateICW(kDriverName, aName, nullptr, pDevMode)); + nsAutoHDC printerDC(::CreateICW(kDriverName, name, nullptr, pDevMode)); if (NS_WARN_IF(!printerDC)) { ::HeapFree(::GetProcessHeap(), 0, pDevMode); return NS_ERROR_FAILURE; } psWin->CopyFromNative(printerDC, pDevMode); } } @@ -630,17 +595,17 @@ nsDeviceContextSpecWin::GetDataFromPrint DISPLAY_LAST_ERROR return NS_ERROR_FAILURE; } SetDevMode(pDevMode); // cache the pointer and takes responsibility for the memory SetDeviceName(aName); - SetDriverName(kDriverName); + SetDriverName(nsDependentString(kDriverName)); rv = NS_OK; } else { rv = NS_ERROR_GFX_PRINTER_NAME_NOT_FOUND; PR_PL(("***** nsDeviceContextSpecWin::GetDataFromPrinter - Couldn't open printer: [%s]\n", NS_ConvertUTF16toUTF8(aName).get())); DISPLAY_LAST_ERROR } return rv; @@ -659,32 +624,29 @@ nsPrinterEnumeratorWin::~nsPrinterEnumer // GlobalPrinters::GetInstance()->FreeGlobalPrinters(); } NS_IMPL_ISUPPORTS(nsPrinterEnumeratorWin, nsIPrinterEnumerator) //---------------------------------------------------------------------------------- // Return the Default Printer name NS_IMETHODIMP -nsPrinterEnumeratorWin::GetDefaultPrinterName(char16_t * *aDefaultPrinterName) +nsPrinterEnumeratorWin::GetDefaultPrinterName(nsAString& aDefaultPrinterName) { - NS_ENSURE_ARG_POINTER(aDefaultPrinterName); - - *aDefaultPrinterName = GetDefaultPrinterNameFromGlobalPrinters(); // helper - + GlobalPrinters::GetInstance()->GetDefaultPrinterName(aDefaultPrinterName); return NS_OK; } NS_IMETHODIMP -nsPrinterEnumeratorWin::InitPrintSettingsFromPrinter(const char16_t *aPrinterName, nsIPrintSettings *aPrintSettings) +nsPrinterEnumeratorWin::InitPrintSettingsFromPrinter(const nsAString& aPrinterName, + nsIPrintSettings *aPrintSettings) { - NS_ENSURE_ARG_POINTER(aPrinterName); NS_ENSURE_ARG_POINTER(aPrintSettings); - if (!*aPrinterName) { + if (aPrinterName.IsEmpty()) { return NS_OK; } // When printing to PDF on Windows there is no associated printer driver. int16_t outputFormat; aPrintSettings->GetOutputFormat(&outputFormat); if (outputFormat == nsIPrintSettings::kOutputFormatPDF) { return NS_OK; @@ -719,17 +681,18 @@ nsPrinterEnumeratorWin::InitPrintSetting devSpecWin->GetDevMode(devmode); if (NS_WARN_IF(!devmode)) { return NS_ERROR_FAILURE; } aPrintSettings->SetPrinterName(aPrinterName); // We need to get information from the device as well. - char16ptr_t printerName = aPrinterName; + const nsString& flat = PromiseFlatString(aPrinterName); + char16ptr_t printerName = flat.get(); HDC dc = ::CreateICW(kDriverName, printerName, nullptr, devmode); if (NS_WARN_IF(!dc)) { return NS_ERROR_FAILURE; } nsCOMPtr<nsIPrintSettingsWin> psWin = do_QueryInterface(aPrintSettings); MOZ_ASSERT(psWin); psWin->CopyFromNative(dc, devmode); @@ -828,17 +791,17 @@ GlobalPrinters::EnumerateNativePrinters( } PR_PL(("-----------------------\n")); return rv; } //------------------------------------------------------------------ // Uses the GetProfileString to get the default printer from the registry void -GlobalPrinters::GetDefaultPrinterName(nsString& aDefaultPrinterName) +GlobalPrinters::GetDefaultPrinterName(nsAString& aDefaultPrinterName) { aDefaultPrinterName.Truncate(); WCHAR szDefaultPrinterName[1024]; DWORD status = GetProfileStringW(L"windows", L"device", 0, szDefaultPrinterName, ArrayLength(szDefaultPrinterName)); if (status > 0) { WCHAR comma = ','; @@ -848,17 +811,18 @@ GlobalPrinters::GetDefaultPrinterName(ns if (*sPtr == comma) { *sPtr = 0; } aDefaultPrinterName = szDefaultPrinterName; } else { aDefaultPrinterName = EmptyString(); } - PR_PL(("DEFAULT PRINTER [%s]\n", aDefaultPrinterName.get())); + PR_PL(("DEFAULT PRINTER [%s]\n", + PromiseFlatString(aDefaultPrinterName).get())); } //---------------------------------------------------------------------------------- // This goes and gets the list of available printers and puts // the default printer at the beginning of the list nsresult GlobalPrinters::EnumeratePrinterList() {
--- a/widget/windows/nsDeviceContextSpecWin.h +++ b/widget/windows/nsDeviceContextSpecWin.h @@ -46,38 +46,39 @@ public: NS_IMETHOD EndPage() override { return NS_OK; } NS_IMETHOD Init(nsIWidget* aWidget, nsIPrintSettings* aPS, bool aIsPrintPreview) override; float GetDPI() final; float GetPrintingScale() final; - void GetDriverName(wchar_t *&aDriverName) const { aDriverName = mDriverName; } - void GetDeviceName(wchar_t *&aDeviceName) const { aDeviceName = mDeviceName; } + void GetDriverName(nsAString& aDriverName) const { aDriverName = mDriverName; } + void GetDeviceName(nsAString& aDeviceName) const { aDeviceName = mDeviceName; } // The GetDevMode will return a pointer to a DevMode // whether it is from the Global memory handle or just the DevMode // To get the DevMode from the Global memory Handle it must lock it // So this call must be paired with a call to UnlockGlobalHandle void GetDevMode(LPDEVMODEW &aDevMode); // helper functions - nsresult GetDataFromPrinter(char16ptr_t aName, nsIPrintSettings* aPS = nullptr); + nsresult GetDataFromPrinter(const nsAString& aName, + nsIPrintSettings* aPS = nullptr); protected: - void SetDeviceName(char16ptr_t aDeviceName); - void SetDriverName(char16ptr_t aDriverName); + void SetDeviceName(const nsAString& aDeviceName); + void SetDriverName(const nsAString& aDriverName); void SetDevMode(LPDEVMODEW aDevMode); virtual ~nsDeviceContextSpecWin(); - wchar_t* mDriverName; - wchar_t* mDeviceName; + nsString mDriverName; + nsString mDeviceName; LPDEVMODEW mDevMode; nsCOMPtr<nsIPrintSettings> mPrintSettings; int16_t mOutputFormat = nsIPrintSettings::kOutputFormatNative; #ifdef MOZ_ENABLE_SKIA_PDF void FinishPrintViaPDF(); void CleanupPrintViaPDF();
--- a/widget/windows/nsPrintOptionsWin.cpp +++ b/widget/windows/nsPrintOptionsWin.cpp @@ -50,28 +50,25 @@ nsPrintOptionsWin::SerializeToPrintData( aWBP->GetIsRangeSelection(&data->isRangeSelection()); } nsCOMPtr<nsIPrintSettingsWin> psWin = do_QueryInterface(aSettings); if (!psWin) { return NS_ERROR_FAILURE; } - char16_t* deviceName; - char16_t* driverName; + nsAutoString deviceName; + nsAutoString driverName; - psWin->GetDeviceName(&deviceName); - psWin->GetDriverName(&driverName); + psWin->GetDeviceName(deviceName); + psWin->GetDriverName(driverName); data->deviceName().Assign(deviceName); data->driverName().Assign(driverName); - free(deviceName); - free(driverName); - // When creating the print dialog on Windows, we only need to send certain // print settings information from the parent to the child not vice versa. if (XRE_IsParentProcess()) { psWin->GetPrintableWidthInInches(&data->printableWidthInInches()); psWin->GetPrintableHeightInInches(&data->printableHeightInInches()); // A DEVMODE can actually be of arbitrary size. If it turns out that it'll // make our IPC message larger than the limit, then we'll error out. @@ -112,18 +109,18 @@ nsPrintOptionsWin::DeserializeToPrintSet NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIPrintSettingsWin> psWin = do_QueryInterface(settings); if (!settings) { return NS_ERROR_FAILURE; } if (XRE_IsContentProcess()) { - psWin->SetDeviceName(data.deviceName().get()); - psWin->SetDriverName(data.driverName().get()); + psWin->SetDeviceName(data.deviceName()); + psWin->SetDriverName(data.driverName()); psWin->SetPrintableWidthInInches(data.printableWidthInInches()); psWin->SetPrintableHeightInInches(data.printableHeightInInches()); if (data.devModeData().IsEmpty()) { psWin->SetDevMode(nullptr); } else { // Check minimum length of DEVMODE data.
--- a/widget/windows/nsPrintSettingsWin.cpp +++ b/widget/windows/nsPrintSettingsWin.cpp @@ -149,62 +149,50 @@ nsPrintSettingsWin::nsPrintSettingsWin() { } /** --------------------------------------------------- * See documentation in nsPrintSettingsWin.h * @update */ -nsPrintSettingsWin::nsPrintSettingsWin(const nsPrintSettingsWin& aPS) : - mDeviceName(nullptr), - mDriverName(nullptr), - mDevMode(nullptr) +nsPrintSettingsWin::nsPrintSettingsWin(const nsPrintSettingsWin& aPS) + : mDevMode(nullptr) { *this = aPS; } /** --------------------------------------------------- * See documentation in nsPrintSettingsWin.h * @update */ nsPrintSettingsWin::~nsPrintSettingsWin() { - if (mDeviceName) free(mDeviceName); - if (mDriverName) free(mDriverName); if (mDevMode) ::HeapFree(::GetProcessHeap(), 0, mDevMode); } -NS_IMETHODIMP nsPrintSettingsWin::SetDeviceName(const char16_t * aDeviceName) +NS_IMETHODIMP nsPrintSettingsWin::SetDeviceName(const nsAString& aDeviceName) { - if (mDeviceName) { - free(mDeviceName); - } - mDeviceName = aDeviceName?wcsdup(char16ptr_t(aDeviceName)):nullptr; + mDeviceName = aDeviceName; return NS_OK; } -NS_IMETHODIMP nsPrintSettingsWin::GetDeviceName(char16_t **aDeviceName) +NS_IMETHODIMP nsPrintSettingsWin::GetDeviceName(nsAString& aDeviceName) { - NS_ENSURE_ARG_POINTER(aDeviceName); - *aDeviceName = mDeviceName?reinterpret_cast<char16_t*>(wcsdup(mDeviceName)):nullptr; + aDeviceName = mDeviceName; return NS_OK; } -NS_IMETHODIMP nsPrintSettingsWin::SetDriverName(const char16_t * aDriverName) +NS_IMETHODIMP nsPrintSettingsWin::SetDriverName(const nsAString& aDriverName) { - if (mDriverName) { - free(mDriverName); - } - mDriverName = aDriverName?wcsdup(char16ptr_t(aDriverName)):nullptr; + mDriverName = aDriverName; return NS_OK; } -NS_IMETHODIMP nsPrintSettingsWin::GetDriverName(char16_t **aDriverName) +NS_IMETHODIMP nsPrintSettingsWin::GetDriverName(nsAString& aDriverName) { - NS_ENSURE_ARG_POINTER(aDriverName); - *aDriverName = mDriverName?reinterpret_cast<char16_t*>(wcsdup(mDriverName)):nullptr; + aDriverName = mDriverName; return NS_OK; } void nsPrintSettingsWin::CopyDevMode(DEVMODEW* aInDevMode, DEVMODEW *& aOutDevMode) { aOutDevMode = nullptr; size_t size = aInDevMode->dmSize + aInDevMode->dmDriverExtra; aOutDevMode = (LPDEVMODEW)::HeapAlloc (::GetProcessHeap(), HEAP_ZERO_MEMORY, size); @@ -420,31 +408,23 @@ nsPrintSettingsWin::_Clone(nsIPrintSetti nsPrintSettingsWin& nsPrintSettingsWin::operator=(const nsPrintSettingsWin& rhs) { if (this == &rhs) { return *this; } ((nsPrintSettings&) *this) = rhs; - if (mDeviceName) { - free(mDeviceName); - } - - if (mDriverName) { - free(mDriverName); - } - // Use free because we used the native malloc to create the memory if (mDevMode) { ::HeapFree(::GetProcessHeap(), 0, mDevMode); } - mDeviceName = rhs.mDeviceName?wcsdup(rhs.mDeviceName):nullptr; - mDriverName = rhs.mDriverName?wcsdup(rhs.mDriverName):nullptr; + mDeviceName = rhs.mDeviceName; + mDriverName = rhs.mDriverName; if (rhs.mDevMode) { CopyDevMode(rhs.mDevMode, mDevMode); } else { mDevMode = nullptr; } return *this;
--- a/widget/windows/nsPrintSettingsWin.h +++ b/widget/windows/nsPrintSettingsWin.h @@ -42,18 +42,18 @@ public: */ nsPrintSettingsWin& operator=(const nsPrintSettingsWin& rhs); NS_IMETHOD GetEffectivePageSize(double *aWidth, double *aHeight) override; protected: void CopyDevMode(DEVMODEW* aInDevMode, DEVMODEW *& aOutDevMode); - wchar_t* mDeviceName; - wchar_t* mDriverName; + nsString mDeviceName; + nsString mDriverName; LPDEVMODEW mDevMode; double mPrintableWidthInInches = 0l; double mPrintableHeightInInches = 0l; }; #endif /* nsPrintSettingsWin_h__ */
--- a/xpcom/ds/nsAtom.h +++ b/xpcom/ds/nsAtom.h @@ -62,17 +62,20 @@ public: nsStringBuffer* GetStringBuffer() const { // See the comment on |mString|'s declaration. return nsStringBuffer::FromData(mString); } // A hashcode that is better distributed than the actual atom pointer, for - // use in situations that need a well-distributed hashcode. + // use in situations that need a well-distributed hashcode. It's called hash() + // rather than Hash() so we can use mozilla::BloomFilter<N, nsAtom>, because + // BloomFilter requires elements to implement a function called hash(). + // uint32_t hash() const { MOZ_ASSERT(!IsHTML5Atom()); return mHash; } // We can't use NS_INLINE_DECL_THREADSAFE_REFCOUNTING because the refcounting // of this type is special.
--- a/xpcom/ds/nsAtomTable.cpp +++ b/xpcom/ds/nsAtomTable.cpp @@ -133,68 +133,67 @@ private: }; UniquePtr<nsTArray<FakeBufferRefcountHelper>> gFakeBuffers; #endif // This constructor is for dynamic atoms and HTML5 atoms. nsAtom::nsAtom(AtomKind aKind, const nsAString& aString, uint32_t aHash) : mRefCnt(1) + , mLength(aString.Length()) + , mKind(static_cast<uint32_t>(aKind)) + , mHash(aHash) { - mLength = aString.Length(); - SetKind(aKind); - MOZ_ASSERT(IsDynamicAtom() || IsHTML5Atom()); + MOZ_ASSERT(aKind == AtomKind::DynamicAtom || aKind == AtomKind::HTML5Atom); RefPtr<nsStringBuffer> buf = nsStringBuffer::FromString(aString); if (buf) { mString = static_cast<char16_t*>(buf->Data()); } else { const size_t size = (mLength + 1) * sizeof(char16_t); buf = nsStringBuffer::Alloc(size); if (MOZ_UNLIKELY(!buf)) { // We OOM because atom allocations should be small and it's hard to // handle them more gracefully in a constructor. NS_ABORT_OOM(size); } mString = static_cast<char16_t*>(buf->Data()); CopyUnicodeTo(aString, 0, mString, mLength); mString[mLength] = char16_t(0); } - mHash = aHash; MOZ_ASSERT_IF(IsDynamicAtom(), mHash == HashString(mString, mLength)); - NS_ASSERTION(mString[mLength] == char16_t(0), "null terminated"); - NS_ASSERTION(buf && buf->StorageSize() >= (mLength + 1) * sizeof(char16_t), - "enough storage"); - NS_ASSERTION(Equals(aString), "correct data"); + MOZ_ASSERT(mString[mLength] == char16_t(0), "null terminated"); + MOZ_ASSERT(buf && buf->StorageSize() >= (mLength + 1) * sizeof(char16_t), + "enough storage"); + MOZ_ASSERT(Equals(aString), "correct data"); // Take ownership of buffer mozilla::Unused << buf.forget(); } // This constructor is for static atoms. nsAtom::nsAtom(nsStringBuffer* aStringBuffer, uint32_t aLength, uint32_t aHash) + : mLength(aLength) + , mKind(static_cast<uint32_t>(AtomKind::StaticAtom)) + , mHash(aHash) + , mString(static_cast<char16_t*>(aStringBuffer->Data())) { - mLength = aLength; - SetKind(AtomKind::StaticAtom); - mString = static_cast<char16_t*>(aStringBuffer->Data()); - #if defined(NS_BUILD_REFCNT_LOGGING) MOZ_ASSERT(NS_IsMainThread()); if (!gFakeBuffers) { gFakeBuffers = MakeUnique<nsTArray<FakeBufferRefcountHelper>>(); } gFakeBuffers->AppendElement(aStringBuffer); #endif // Technically we could currently avoid doing this addref by instead making // the static atom buffers have an initial refcount of 2. aStringBuffer->AddRef(); - mHash = aHash; MOZ_ASSERT(mHash == HashString(mString, mLength)); MOZ_ASSERT(mString[mLength] == char16_t(0), "null terminated"); MOZ_ASSERT(aStringBuffer && aStringBuffer->StorageSize() == (mLength + 1) * sizeof(char16_t), "correct storage"); }