diff options
Diffstat (limited to 'dom')
-rw-r--r-- | dom/base/DOMIntersectionObserver.cpp | 3 | ||||
-rw-r--r-- | dom/base/Element.cpp | 10 | ||||
-rwxr-xr-x | dom/base/moz.build | 11 | ||||
-rw-r--r-- | dom/base/nsAttrValue.cpp | 10 | ||||
-rw-r--r-- | dom/base/nsContentSink.cpp | 3 | ||||
-rw-r--r-- | dom/base/nsContentUtils.cpp | 16 | ||||
-rw-r--r-- | dom/base/nsNodeInfoManager.cpp | 33 | ||||
-rw-r--r-- | dom/base/nsNodeInfoManager.h | 3 | ||||
-rw-r--r-- | dom/bindings/moz.build | 2 | ||||
-rw-r--r-- | dom/canvas/CanvasRenderingContext2D.cpp | 6 | ||||
-rw-r--r-- | dom/canvas/WebGLBuffer.cpp | 2 | ||||
-rw-r--r-- | dom/html/HTMLCanvasElement.cpp | 28 | ||||
-rw-r--r-- | dom/ipc/ContentParent.cpp | 17 | ||||
-rw-r--r-- | dom/push/PushServiceAndroidGCM.jsm | 275 | ||||
-rw-r--r-- | dom/push/moz.build | 14 | ||||
-rw-r--r-- | dom/webidl/moz.build | 2 |
16 files changed, 87 insertions, 348 deletions
diff --git a/dom/base/DOMIntersectionObserver.cpp b/dom/base/DOMIntersectionObserver.cpp index 389b93071..70b5534ba 100644 --- a/dom/base/DOMIntersectionObserver.cpp +++ b/dom/base/DOMIntersectionObserver.cpp @@ -339,6 +339,7 @@ DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time for (size_t i = 0; i < mObservationTargets.Length(); ++i) { Element* target = mObservationTargets.ElementAt(i); nsIFrame* targetFrame = target->GetPrimaryFrame(); + nsIFrame* originalTargetFrame = targetFrame; nsRect targetRect; Maybe<nsRect> intersectionRect; bool isSameDoc = root && root->GetComposedDoc() == target->GetComposedDoc(); @@ -424,7 +425,7 @@ DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time ); if (intersectionRect.isSome() && !isSameDoc) { nsRect rect = intersectionRect.value(); - nsPresContext* presContext = targetFrame->PresContext(); + nsPresContext* presContext = originalTargetFrame->PresContext(); nsLayoutUtils::TransformRect(rootFrame, presContext->PresShell()->GetRootScrollFrame(), rect); intersectionRect = Some(rect); diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index 5c3277e84..0054f4800 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -1283,7 +1283,7 @@ Element::ToggleAttribute(const nsAString& aName, if (aForce.WasPassed() && !aForce.Value()) { return false; } - nsCOMPtr<nsIAtom> nameAtom = NS_Atomize(nameToUse); + nsCOMPtr<nsIAtom> nameAtom = NS_AtomizeMainThread(nameToUse); if (!nameAtom) { aError.Throw(NS_ERROR_OUT_OF_MEMORY); return false; @@ -1316,7 +1316,7 @@ Element::SetAttribute(const nsAString& aName, nsAutoString nameToUse; const nsAttrName* name = InternalGetAttrNameFromQName(aName, &nameToUse); if (!name) { - nsCOMPtr<nsIAtom> nameAtom = NS_Atomize(nameToUse); + nsCOMPtr<nsIAtom> nameAtom = NS_AtomizeMainThread(nameToUse); if (!nameAtom) { aError.Throw(NS_ERROR_OUT_OF_MEMORY); return; @@ -1398,7 +1398,7 @@ Element::GetAttributeNS(const nsAString& aNamespaceURI, return; } - nsCOMPtr<nsIAtom> name = NS_Atomize(aLocalName); + nsCOMPtr<nsIAtom> name = NS_AtomizeMainThread(aLocalName); bool hasAttr = GetAttr(nsid, name, aReturn); if (!hasAttr) { SetDOMStringToNull(aReturn); @@ -1430,7 +1430,7 @@ Element::RemoveAttributeNS(const nsAString& aNamespaceURI, const nsAString& aLocalName, ErrorResult& aError) { - nsCOMPtr<nsIAtom> name = NS_Atomize(aLocalName); + nsCOMPtr<nsIAtom> name = NS_AtomizeMainThread(aLocalName); int32_t nsid = nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI, nsContentUtils::IsChromeDoc(OwnerDoc())); @@ -1518,7 +1518,7 @@ Element::HasAttributeNS(const nsAString& aNamespaceURI, return false; } - nsCOMPtr<nsIAtom> name = NS_Atomize(aLocalName); + nsCOMPtr<nsIAtom> name = NS_AtomizeMainThread(aLocalName); return HasAttr(nsid, name); } diff --git a/dom/base/moz.build b/dom/base/moz.build index 77eb01ba6..ebb76d617 100755 --- a/dom/base/moz.build +++ b/dom/base/moz.build @@ -410,17 +410,12 @@ EXTRA_COMPONENTS += [ 'contentAreaDropListener.manifest', 'messageWakeupService.js', 'messageWakeupService.manifest', + 'SiteSpecificUserAgent.js', + 'SiteSpecificUserAgent.manifest', 'SlowScriptDebug.js', 'SlowScriptDebug.manifest', ] -# Firefox for Android provides an alternate version of this component -if not CONFIG['MOZ_FENNEC']: - EXTRA_COMPONENTS += [ - 'SiteSpecificUserAgent.js', - 'SiteSpecificUserAgent.manifest', - ] - EXTRA_JS_MODULES += [ 'DOMRequestHelper.jsm', 'IndexedDBHelper.jsm', @@ -471,7 +466,7 @@ include('/ipc/chromium/chromium-config.mozbuild') FINAL_LIBRARY = 'xul' -if CONFIG['MOZ_PHOENIX'] or CONFIG['MOZ_FENNEC'] or CONFIG['MOZ_XULRUNNER']: +if CONFIG['MOZ_PHOENIX'] or CONFIG['MOZ_XULRUNNER']: DEFINES['HAVE_SIDEBAR'] = True if CONFIG['MOZ_X11']: diff --git a/dom/base/nsAttrValue.cpp b/dom/base/nsAttrValue.cpp index 8eb1aaf97..ebddcb7ed 100644 --- a/dom/base/nsAttrValue.cpp +++ b/dom/base/nsAttrValue.cpp @@ -742,7 +742,7 @@ nsAttrValue::GetAsAtom() const { switch (Type()) { case eString: - return NS_Atomize(GetStringValue()); + return NS_AtomizeMainThread(GetStringValue()); case eAtom: { @@ -754,7 +754,7 @@ nsAttrValue::GetAsAtom() const { nsAutoString val; ToString(val); - return NS_Atomize(val); + return NS_AtomizeMainThread(val); } } } @@ -1267,7 +1267,7 @@ nsAttrValue::ParseAtomArray(const nsAString& aValue) ++iter; } while (iter != end && !nsContentUtils::IsHTMLWhitespace(*iter)); - nsCOMPtr<nsIAtom> classAtom = NS_Atomize(Substring(start, iter)); + nsCOMPtr<nsIAtom> classAtom = NS_AtomizeMainThread(Substring(start, iter)); if (!classAtom) { Reset(); return; @@ -1308,7 +1308,7 @@ nsAttrValue::ParseAtomArray(const nsAString& aValue) ++iter; } while (iter != end && !nsContentUtils::IsHTMLWhitespace(*iter)); - classAtom = NS_Atomize(Substring(start, iter)); + classAtom = NS_AtomizeMainThread(Substring(start, iter)); if (!array->AppendElement(classAtom)) { Reset(); @@ -1757,7 +1757,7 @@ nsAttrValue::SetMiscAtomOrString(const nsAString* aValue) "Empty string?"); MiscContainer* cont = GetMiscContainer(); if (len <= NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM) { - nsCOMPtr<nsIAtom> atom = NS_Atomize(*aValue); + nsCOMPtr<nsIAtom> atom = NS_AtomizeMainThread(*aValue); if (atom) { cont->mStringBits = reinterpret_cast<uintptr_t>(atom.forget().take()) | eAtomBase; diff --git a/dom/base/nsContentSink.cpp b/dom/base/nsContentSink.cpp index 85b3d07bf..490f0ec17 100644 --- a/dom/base/nsContentSink.cpp +++ b/dom/base/nsContentSink.cpp @@ -304,7 +304,8 @@ nsContentSink::ProcessHeaderData(nsIAtom* aHeader, const nsAString& aValue, mDocument->SetHeaderData(aHeader, aValue); - if (aHeader == nsGkAtoms::setcookie) { + if (aHeader == nsGkAtoms::setcookie && + Preferences::GetBool("dom.meta-set-cookie.enabled", true)) { // Don't allow setting cookies in cookie-averse documents. if (mDocument->IsCookieAverse()) { return NS_OK; diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index 3696195dd..1f9c17947 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -2947,11 +2947,11 @@ nsContentUtils::SplitQName(const nsIContent* aNamespaceResolver, if (*aNamespace == kNameSpaceID_Unknown) return NS_ERROR_FAILURE; - *aLocalName = NS_Atomize(Substring(colon + 1, end)).take(); + *aLocalName = NS_AtomizeMainThread(Substring(colon + 1, end)).take(); } else { *aNamespace = kNameSpaceID_None; - *aLocalName = NS_Atomize(aQName).take(); + *aLocalName = NS_AtomizeMainThread(aQName).take(); } NS_ENSURE_TRUE(aLocalName, NS_ERROR_OUT_OF_MEMORY); return NS_OK; @@ -2976,7 +2976,8 @@ nsContentUtils::GetNodeInfoFromQName(const nsAString& aNamespaceURI, const char16_t* end; qName.EndReading(end); - nsCOMPtr<nsIAtom> prefix = NS_Atomize(Substring(qName.get(), colon)); + nsCOMPtr<nsIAtom> prefix = + NS_AtomizeMainThread(Substring(qName.get(), colon)); rv = aNodeInfoManager->GetNodeInfo(Substring(colon + 1, end), prefix, nsID, aNodeType, aNodeInfo); @@ -3036,7 +3037,7 @@ nsContentUtils::SplitExpatName(const char16_t *aExpatName, nsIAtom **aPrefix, nameStart = (uriEnd + 1); if (nameEnd) { const char16_t *prefixStart = nameEnd + 1; - *aPrefix = NS_Atomize(Substring(prefixStart, pos)).take(); + *aPrefix = NS_AtomizeMainThread(Substring(prefixStart, pos)).take(); } else { nameEnd = pos; @@ -3049,7 +3050,7 @@ nsContentUtils::SplitExpatName(const char16_t *aExpatName, nsIAtom **aPrefix, nameEnd = pos; *aPrefix = nullptr; } - *aLocalName = NS_Atomize(Substring(nameStart, nameEnd)).take(); + *aLocalName = NS_AtomizeMainThread(Substring(nameStart, nameEnd)).take(); } // static @@ -3887,7 +3888,8 @@ nsContentUtils::GetEventMessageAndAtom(const nsAString& aName, } *aEventMessage = eUnidentifiedEvent; - nsCOMPtr<nsIAtom> atom = NS_Atomize(NS_LITERAL_STRING("on") + aName); + nsCOMPtr<nsIAtom> atom = + NS_AtomizeMainThread(NS_LITERAL_STRING("on") + aName); sUserDefinedEvents->AppendObject(atom); mapping.mAtom = atom; mapping.mMessage = eUnidentifiedEvent; @@ -3920,7 +3922,7 @@ nsContentUtils::GetEventMessageAndAtomForListener(const nsAString& aName, if (mapping.mMaybeSpecialSVGorSMILEvent) { // Try the atom version so that we should get the right message for // SVG/SMIL. - atom = NS_Atomize(NS_LITERAL_STRING("on") + aName); + atom = NS_AtomizeMainThread(NS_LITERAL_STRING("on") + aName); msg = GetEventMessage(atom); } else { atom = mapping.mAtom; diff --git a/dom/base/nsNodeInfoManager.cpp b/dom/base/nsNodeInfoManager.cpp index 80f0aa786..1f751ea71 100644 --- a/dom/base/nsNodeInfoManager.cpp +++ b/dom/base/nsNodeInfoManager.cpp @@ -112,7 +112,8 @@ nsNodeInfoManager::nsNodeInfoManager() mNonDocumentNodeInfos(0), mTextNodeInfo(nullptr), mCommentNodeInfo(nullptr), - mDocumentNodeInfo(nullptr) + mDocumentNodeInfo(nullptr), + mRecentlyUsedNodeInfos{} { nsLayoutStatics::AddRef(); @@ -232,11 +233,19 @@ nsNodeInfoManager::GetNodeInfo(nsIAtom *aName, nsIAtom *aPrefix, NodeInfo::NodeInfoInner tmpKey(aName, aPrefix, aNamespaceID, aNodeType, aExtraName); + uint32_t index = + GetNodeInfoInnerHashValue(&tmpKey) % RECENTLY_USED_NODEINFOS_SIZE; + NodeInfo* ni = mRecentlyUsedNodeInfos[index]; + if (ni && NodeInfoInnerKeyCompare(&(ni->mInner), &tmpKey)) { + RefPtr<NodeInfo> nodeInfo = ni; + return nodeInfo.forget(); + } + void *node = PL_HashTableLookup(mNodeInfoHash, &tmpKey); if (node) { RefPtr<NodeInfo> nodeInfo = static_cast<NodeInfo*>(node); - + mRecentlyUsedNodeInfos[index] = nodeInfo; return nodeInfo.forget(); } @@ -254,6 +263,7 @@ nsNodeInfoManager::GetNodeInfo(nsIAtom *aName, nsIAtom *aPrefix, NS_IF_ADDREF(mDocument); } + mRecentlyUsedNodeInfos[index] = newNodeInfo; return newNodeInfo.forget(); } @@ -272,16 +282,26 @@ nsNodeInfoManager::GetNodeInfo(const nsAString& aName, nsIAtom *aPrefix, NodeInfo::NodeInfoInner tmpKey(aName, aPrefix, aNamespaceID, aNodeType); + uint32_t index = + GetNodeInfoInnerHashValue(&tmpKey) % RECENTLY_USED_NODEINFOS_SIZE; + NodeInfo* ni = mRecentlyUsedNodeInfos[index]; + if (ni && NodeInfoInnerKeyCompare(&(ni->mInner), &tmpKey)) { + RefPtr<NodeInfo> nodeInfo = ni; + nodeInfo.forget(aNodeInfo); + return NS_OK; + } + void *node = PL_HashTableLookup(mNodeInfoHash, &tmpKey); if (node) { RefPtr<NodeInfo> nodeInfo = static_cast<NodeInfo*>(node); + mRecentlyUsedNodeInfos[index] = nodeInfo; nodeInfo.forget(aNodeInfo); return NS_OK; } - nsCOMPtr<nsIAtom> nameAtom = NS_Atomize(aName); + nsCOMPtr<nsIAtom> nameAtom = NS_AtomizeMainThread(aName); NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY); RefPtr<NodeInfo> newNodeInfo = @@ -297,6 +317,7 @@ nsNodeInfoManager::GetNodeInfo(const nsAString& aName, nsIAtom *aPrefix, NS_IF_ADDREF(mDocument); } + mRecentlyUsedNodeInfos[index] = newNodeInfo; newNodeInfo.forget(aNodeInfo); return NS_OK; @@ -421,6 +442,12 @@ nsNodeInfoManager::RemoveNodeInfo(NodeInfo *aNodeInfo) } } + uint32_t index = + GetNodeInfoInnerHashValue(&aNodeInfo->mInner) % RECENTLY_USED_NODEINFOS_SIZE; + if (mRecentlyUsedNodeInfos[index] == aNodeInfo) { + mRecentlyUsedNodeInfos[index] = nullptr; + } + #ifdef DEBUG bool ret = #endif diff --git a/dom/base/nsNodeInfoManager.h b/dom/base/nsNodeInfoManager.h index 6ece66577..759dd391e 100644 --- a/dom/base/nsNodeInfoManager.h +++ b/dom/base/nsNodeInfoManager.h @@ -32,6 +32,8 @@ class NodeInfo; } // namespace dom } // namespace mozilla +#define RECENTLY_USED_NODEINFOS_SIZE 31 + class nsNodeInfoManager final { private: @@ -137,6 +139,7 @@ private: mozilla::dom::NodeInfo * MOZ_NON_OWNING_REF mCommentNodeInfo; // WEAK to avoid circular ownership mozilla::dom::NodeInfo * MOZ_NON_OWNING_REF mDocumentNodeInfo; // WEAK to avoid circular ownership RefPtr<nsBindingManager> mBindingManager; + mozilla::dom::NodeInfo* mRecentlyUsedNodeInfos[RECENTLY_USED_NODEINFOS_SIZE]; }; #endif /* nsNodeInfoManager_h___ */ diff --git a/dom/bindings/moz.build b/dom/bindings/moz.build index 7e1358e9c..043b3c494 100644 --- a/dom/bindings/moz.build +++ b/dom/bindings/moz.build @@ -139,7 +139,7 @@ FINAL_LIBRARY = 'xul' SPHINX_TREES['webidl'] = 'docs' SPHINX_PYTHON_PACKAGE_DIRS += ['mozwebidlcodegen'] -if CONFIG['MOZ_PHOENIX'] or CONFIG['MOZ_FENNEC'] or CONFIG['MOZ_XULRUNNER']: +if CONFIG['MOZ_PHOENIX'] or CONFIG['MOZ_XULRUNNER']: # This is needed for Window.webidl DEFINES['HAVE_SIDEBAR'] = True diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index 4849fda57..111519c71 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -4219,6 +4219,12 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor : public nsBidiPresUtils::BidiProcess if (state->gradientStyles[style]) { // Gradient pattern = GetGradientFor(style); } else if (state->patternStyles[style]) { // Pattern + if (mCtx->mCanvasElement) { + CanvasUtils::DoDrawImageSecurityCheck( + mCtx->mCanvasElement, state->patternStyles[style]->mPrincipal, + state->patternStyles[style]->mForceWriteOnly, + state->patternStyles[style]->mCORSUsed); + } pattern = GetPatternFor(style); } else { MOZ_ASSERT(false, "Should never reach here."); diff --git a/dom/canvas/WebGLBuffer.cpp b/dom/canvas/WebGLBuffer.cpp index f202c9950..1eaf37ac4 100644 --- a/dom/canvas/WebGLBuffer.cpp +++ b/dom/canvas/WebGLBuffer.cpp @@ -115,7 +115,7 @@ WebGLBuffer::BufferData(GLenum target, size_t size, const void* data, GLenum usa const ScopedLazyBind lazyBind(gl, target, this); mContext->InvalidateBufferFetching(); -#ifdef XP_MACOSX +#if defined(XP_MACOSX) || defined(MOZ_WIDGET_GTK) // bug 790879 if (gl->WorkAroundDriverBugs() && size > INT32_MAX) diff --git a/dom/html/HTMLCanvasElement.cpp b/dom/html/HTMLCanvasElement.cpp index a01795d9e..4b5deab18 100644 --- a/dom/html/HTMLCanvasElement.cpp +++ b/dom/html/HTMLCanvasElement.cpp @@ -552,17 +552,23 @@ HTMLCanvasElement::CopyInnerTo(Element* aDest) HTMLCanvasElement* dest = static_cast<HTMLCanvasElement*>(aDest); dest->mOriginalCanvas = this; - nsCOMPtr<nsISupports> cxt; - dest->GetContext(NS_LITERAL_STRING("2d"), getter_AddRefs(cxt)); - RefPtr<CanvasRenderingContext2D> context2d = - static_cast<CanvasRenderingContext2D*>(cxt.get()); - if (context2d && !mPrintCallback) { - CanvasImageSource source; - source.SetAsHTMLCanvasElement() = this; - ErrorResult err; - context2d->DrawImage(source, - 0.0, 0.0, err); - rv = err.StealNSResult(); + // We make sure that the canvas is not zero sized since that would cause + // the DrawImage call below to return an error, which would cause printing + // to fail. + nsIntSize size = GetWidthHeight(); + if (size.height > 0 && size.width > 0) { + nsCOMPtr<nsISupports> cxt; + dest->GetContext(NS_LITERAL_STRING("2d"), getter_AddRefs(cxt)); + RefPtr<CanvasRenderingContext2D> context2d = + static_cast<CanvasRenderingContext2D*>(cxt.get()); + if (context2d && !mPrintCallback) { + CanvasImageSource source; + source.SetAsHTMLCanvasElement() = this; + ErrorResult err; + context2d->DrawImage(source, + 0.0, 0.0, err); + rv = err.StealNSResult(); + } } } return rv; diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 79446151c..97e3a4880 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -229,11 +229,6 @@ static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID); -#if defined(XP_WIN) -// e10s forced enable pref, defined in nsAppRunner.cpp -extern const char* kForceEnableE10sPref; -#endif - using base::ChildPrivileges; using base::KillProcess; @@ -1275,12 +1270,6 @@ ContentParent::Init() if (nsIPresShell::IsAccessibilityActive()) { #if !defined(XP_WIN) Unused << SendActivateA11y(0); -#else - // On Windows we currently only enable a11y in the content process - // for testing purposes. - if (Preferences::GetBool(kForceEnableE10sPref, false)) { - Unused << SendActivateA11y(a11y::AccessibleWrap::GetContentProcessIdFor(ChildID())); - } #endif } #endif @@ -2573,12 +2562,6 @@ ContentParent::Observe(nsISupports* aSubject, // accessibility gets initiated in chrome process. #if !defined(XP_WIN) Unused << SendActivateA11y(0); -#else - // On Windows we currently only enable a11y in the content process - // for testing purposes. - if (Preferences::GetBool(kForceEnableE10sPref, false)) { - Unused << SendActivateA11y(a11y::AccessibleWrap::GetContentProcessIdFor(ChildID())); - } #endif } else { // If possible, shut down accessibility in content process when diff --git a/dom/push/PushServiceAndroidGCM.jsm b/dom/push/PushServiceAndroidGCM.jsm deleted file mode 100644 index ed07be339..000000000 --- a/dom/push/PushServiceAndroidGCM.jsm +++ /dev/null @@ -1,275 +0,0 @@ -/* jshint moz: true, esnext: true */ -/* 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/. */ - -"use strict"; - -const Cc = Components.classes; -const Ci = Components.interfaces; -const Cu = Components.utils; -const Cr = Components.results; - -const {PushDB} = Cu.import("resource://gre/modules/PushDB.jsm"); -const {PushRecord} = Cu.import("resource://gre/modules/PushRecord.jsm"); -const {PushCrypto} = Cu.import("resource://gre/modules/PushCrypto.jsm"); -Cu.import("resource://gre/modules/Messaging.jsm"); /*global: Messaging */ -Cu.import("resource://gre/modules/Services.jsm"); /*global: Services */ -Cu.import("resource://gre/modules/Preferences.jsm"); /*global: Preferences */ -Cu.import("resource://gre/modules/Promise.jsm"); /*global: Promise */ -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); /*global: XPCOMUtils */ - -const Log = Cu.import("resource://gre/modules/AndroidLog.jsm", {}).AndroidLog.bind("Push"); - -this.EXPORTED_SYMBOLS = ["PushServiceAndroidGCM"]; - -XPCOMUtils.defineLazyGetter(this, "console", () => { - let {ConsoleAPI} = Cu.import("resource://gre/modules/Console.jsm", {}); - return new ConsoleAPI({ - dump: Log.i, - maxLogLevelPref: "dom.push.loglevel", - prefix: "PushServiceAndroidGCM", - }); -}); - -const kPUSHANDROIDGCMDB_DB_NAME = "pushAndroidGCM"; -const kPUSHANDROIDGCMDB_DB_VERSION = 5; // Change this if the IndexedDB format changes -const kPUSHANDROIDGCMDB_STORE_NAME = "pushAndroidGCM"; - -const FXA_PUSH_SCOPE = "chrome://fxa-push"; - -const prefs = new Preferences("dom.push."); - -/** - * The implementation of WebPush push backed by Android's GCM - * delivery. - */ -this.PushServiceAndroidGCM = { - _mainPushService: null, - _serverURI: null, - - newPushDB: function() { - return new PushDB(kPUSHANDROIDGCMDB_DB_NAME, - kPUSHANDROIDGCMDB_DB_VERSION, - kPUSHANDROIDGCMDB_STORE_NAME, - "channelID", - PushRecordAndroidGCM); - }, - - validServerURI: function(serverURI) { - if (!serverURI) { - return false; - } - - if (serverURI.scheme == "https") { - return true; - } - if (serverURI.scheme == "http") { - // Allow insecure server URLs for development and testing. - return !!prefs.get("testing.allowInsecureServerURL"); - } - console.info("Unsupported Android GCM dom.push.serverURL scheme", serverURI.scheme); - return false; - }, - - observe: function(subject, topic, data) { - switch (topic) { - case "nsPref:changed": - if (data == "dom.push.debug") { - // Reconfigure. - let debug = !!prefs.get("debug"); - console.info("Debug parameter changed; updating configuration with new debug", debug); - this._configure(this._serverURI, debug); - } - break; - case "PushServiceAndroidGCM:ReceivedPushMessage": - this._onPushMessageReceived(data); - break; - default: - break; - } - }, - - _onPushMessageReceived(data) { - // TODO: Use Messaging.jsm for this. - if (this._mainPushService == null) { - // Shouldn't ever happen, but let's be careful. - console.error("No main PushService! Dropping message."); - return; - } - if (!data) { - console.error("No data from Java! Dropping message."); - return; - } - data = JSON.parse(data); - console.debug("ReceivedPushMessage with data", data); - - let { headers, message } = this._messageAndHeaders(data); - - console.debug("Delivering message to main PushService:", message, headers); - this._mainPushService.receivedPushMessage( - data.channelID, "", headers, message, (record) => { - // Always update the stored record. - return record; - }); - }, - - _messageAndHeaders(data) { - // Default is no data (and no encryption). - let message = null; - let headers = null; - - if (data.message && data.enc && (data.enckey || data.cryptokey)) { - headers = { - encryption_key: data.enckey, - crypto_key: data.cryptokey, - encryption: data.enc, - encoding: data.con, - }; - // Ciphertext is (urlsafe) Base 64 encoded. - message = ChromeUtils.base64URLDecode(data.message, { - // The Push server may append padding. - padding: "ignore", - }); - } - return { headers, message }; - }, - - _configure: function(serverURL, debug) { - return Messaging.sendRequestForResult({ - type: "PushServiceAndroidGCM:Configure", - endpoint: serverURL.spec, - debug: debug, - }); - }, - - init: function(options, mainPushService, serverURL) { - console.debug("init()"); - this._mainPushService = mainPushService; - this._serverURI = serverURL; - - prefs.observe("debug", this); - Services.obs.addObserver(this, "PushServiceAndroidGCM:ReceivedPushMessage", false); - - return this._configure(serverURL, !!prefs.get("debug")).then(() => { - Messaging.sendRequestForResult({ - type: "PushServiceAndroidGCM:Initialized" - }); - }); - }, - - uninit: function() { - console.debug("uninit()"); - Messaging.sendRequestForResult({ - type: "PushServiceAndroidGCM:Uninitialized" - }); - - this._mainPushService = null; - Services.obs.removeObserver(this, "PushServiceAndroidGCM:ReceivedPushMessage"); - prefs.ignore("debug", this); - }, - - onAlarmFired: function() { - // No action required. - }, - - connect: function(records) { - console.debug("connect:", records); - // It's possible for the registration or subscriptions backing the - // PushService to not be registered with the underlying AndroidPushService. - // Expire those that are unrecognized. - return Messaging.sendRequestForResult({ - type: "PushServiceAndroidGCM:DumpSubscriptions", - }) - .then(subscriptions => { - console.debug("connect:", subscriptions); - // subscriptions maps chid => subscription data. - return Promise.all(records.map(record => { - if (subscriptions.hasOwnProperty(record.keyID)) { - console.debug("connect:", "hasOwnProperty", record.keyID); - return Promise.resolve(); - } - console.debug("connect:", "!hasOwnProperty", record.keyID); - // Subscription is known to PushService.jsm but not to AndroidPushService. Drop it. - return this._mainPushService.dropRegistrationAndNotifyApp(record.keyID) - .catch(error => { - console.error("connect: Error dropping registration", record.keyID, error); - }); - })); - }); - }, - - isConnected: function() { - return this._mainPushService != null; - }, - - disconnect: function() { - console.debug("disconnect"); - }, - - register: function(record) { - console.debug("register:", record); - let ctime = Date.now(); - let appServerKey = record.appServerKey ? - ChromeUtils.base64URLEncode(record.appServerKey, { - // The Push server requires padding. - pad: true, - }) : null; - let message = { - type: "PushServiceAndroidGCM:SubscribeChannel", - appServerKey: appServerKey, - } - if (record.scope == FXA_PUSH_SCOPE) { - message.service = "fxa"; - } - // Caller handles errors. - return Messaging.sendRequestForResult(message) - .then(data => { - console.debug("Got data:", data); - return PushCrypto.generateKeys() - .then(exportedKeys => - new PushRecordAndroidGCM({ - // Straight from autopush. - channelID: data.channelID, - pushEndpoint: data.endpoint, - // Common to all PushRecord implementations. - scope: record.scope, - originAttributes: record.originAttributes, - ctime: ctime, - systemRecord: record.systemRecord, - // Cryptography! - p256dhPublicKey: exportedKeys[0], - p256dhPrivateKey: exportedKeys[1], - authenticationSecret: PushCrypto.generateAuthenticationSecret(), - appServerKey: record.appServerKey, - }) - ); - }); - }, - - unregister: function(record) { - console.debug("unregister: ", record); - return Messaging.sendRequestForResult({ - type: "PushServiceAndroidGCM:UnsubscribeChannel", - channelID: record.keyID, - }); - }, - - reportDeliveryError: function(messageID, reason) { - console.warn("reportDeliveryError: Ignoring message delivery error", - messageID, reason); - }, -}; - -function PushRecordAndroidGCM(record) { - PushRecord.call(this, record); - this.channelID = record.channelID; -} - -PushRecordAndroidGCM.prototype = Object.create(PushRecord.prototype, { - keyID: { - get() { - return this.channelID; - }, - }, -}); diff --git a/dom/push/moz.build b/dom/push/moz.build index 35683120f..7eee8896f 100644 --- a/dom/push/moz.build +++ b/dom/push/moz.build @@ -14,20 +14,10 @@ EXTRA_JS_MODULES += [ 'PushDB.jsm', 'PushRecord.jsm', 'PushService.jsm', + 'PushServiceHttp2.jsm', + 'PushServiceWebSocket.jsm', ] -if not CONFIG['MOZ_FENNEC']: - # Everything but Fennec. - EXTRA_JS_MODULES += [ - 'PushServiceHttp2.jsm', - 'PushServiceWebSocket.jsm', - ] -else: - # Fennec only. - EXTRA_JS_MODULES += [ - 'PushServiceAndroidGCM.jsm', - ] - MOCHITEST_MANIFESTS += [ 'test/mochitest.ini', ] diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index aae7e479c..0fe10eff9 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -746,7 +746,7 @@ if CONFIG['MOZ_BUILD_APP'] in ['xulrunner'] or CONFIG['MOZ_PHOENIX'] or CONFIG[' 'BrowserFeedWriter.webidl', ] -if CONFIG['MOZ_PHOENIX'] or CONFIG['MOZ_FENNEC'] or CONFIG['MOZ_XULRUNNER']: +if CONFIG['MOZ_PHOENIX'] or CONFIG['MOZ_XULRUNNER']: WEBIDL_FILES += [ 'External.webidl', ] |