forked from mirrors/gecko-dev
		
	 a259026c9d
			
		
	
	
		a259026c9d
		
	
	
	
	
		
			
			This also removes any redundant Ci.nsISupports elements in the interface
lists.
This was done using the following script:
acecb401b7/processors/chromeutils-generateQI.jsm
MozReview-Commit-ID: AIx10P8GpZY
--HG--
extra : rebase_source : a29c07530586dc18ba040f19215475ac20fcfb3b
		
	
			
		
			
				
	
	
		
			169 lines
		
	
	
	
		
			5.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
	
		
			5.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /* 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/. */
 | |
| 
 | |
| ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 | |
| ChromeUtils.import("resource://gre/modules/Services.jsm");
 | |
| ChromeUtils.import("resource://gre/modules/Messaging.jsm");
 | |
| const {
 | |
|   PushCrypto,
 | |
|   getCryptoParams,
 | |
| } = ChromeUtils.import("resource://gre/modules/PushCrypto.jsm", {});
 | |
| 
 | |
| XPCOMUtils.defineLazyServiceGetter(this, "PushService",
 | |
|   "@mozilla.org/push/Service;1", "nsIPushService");
 | |
| XPCOMUtils.defineLazyGetter(this, "_decoder", () => new TextDecoder());
 | |
| 
 | |
| const FXA_PUSH_SCOPE = "chrome://fxa-push";
 | |
| const Log = ChromeUtils.import("resource://gre/modules/AndroidLog.jsm", {}).AndroidLog.bind("FxAccountsPush");
 | |
| 
 | |
| function FxAccountsPush() {
 | |
|   Services.obs.addObserver(this, "FxAccountsPush:ReceivedPushMessageToDecode");
 | |
| 
 | |
|   EventDispatcher.instance.sendRequestForResult({
 | |
|     type: "FxAccountsPush:Initialized"
 | |
|   });
 | |
| }
 | |
| 
 | |
| FxAccountsPush.prototype = {
 | |
|   observe: function(subject, topic, data) {
 | |
|     switch (topic) {
 | |
|       case "android-push-service":
 | |
|         if (data === "android-fxa-subscribe") {
 | |
|           this._subscribe();
 | |
|         } else if (data === "android-fxa-unsubscribe") {
 | |
|           this._unsubscribe();
 | |
|         } else if (data === "android-fxa-resubscribe") {
 | |
|           // If unsubscription fails, we still want to try to subscribe.
 | |
|           this._unsubscribe().then(this._subscribe, this._subscribe);
 | |
|         }
 | |
|         break;
 | |
|       case "FxAccountsPush:ReceivedPushMessageToDecode":
 | |
|         this._decodePushMessage(data);
 | |
|         break;
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   _subscribe() {
 | |
|     Log.i("FxAccountsPush _subscribe");
 | |
|     return new Promise((resolve, reject) => {
 | |
|       PushService.subscribe(FXA_PUSH_SCOPE,
 | |
|         Services.scriptSecurityManager.getSystemPrincipal(),
 | |
|         (result, subscription) => {
 | |
|           if (Components.isSuccessCode(result)) {
 | |
|             Log.d("FxAccountsPush got subscription");
 | |
|             resolve(subscription);
 | |
|           } else {
 | |
|             Log.w("FxAccountsPush failed to subscribe", result);
 | |
|             const err = new Error("FxAccountsPush failed to subscribe");
 | |
|             err.result = result;
 | |
|             reject(err);
 | |
|           }
 | |
|         });
 | |
|     })
 | |
|     .then(subscription => {
 | |
|       EventDispatcher.instance.sendRequest({
 | |
|         type: "FxAccountsPush:Subscribe:Response",
 | |
|         subscription: {
 | |
|           pushCallback: subscription.endpoint,
 | |
|           pushPublicKey: urlsafeBase64Encode(subscription.getKey("p256dh")),
 | |
|           pushAuthKey: urlsafeBase64Encode(subscription.getKey("auth"))
 | |
|         }
 | |
|       });
 | |
|     })
 | |
|     .catch(err => {
 | |
|       Log.i("Error when registering FxA push endpoint " + err);
 | |
|       EventDispatcher.instance.sendRequest({
 | |
|         type: "FxAccountsPush:Subscribe:Response",
 | |
|         error: err.result.toString() // Convert to string because the GeckoBundle can't getLong();
 | |
|       });
 | |
|     });
 | |
|   },
 | |
| 
 | |
|   _unsubscribe() {
 | |
|     Log.i("FxAccountsPush _unsubscribe");
 | |
|     return new Promise((resolve) => {
 | |
|       PushService.unsubscribe(FXA_PUSH_SCOPE,
 | |
|         Services.scriptSecurityManager.getSystemPrincipal(),
 | |
|         (result, ok) => {
 | |
|           if (Components.isSuccessCode(result)) {
 | |
|             if (ok === true) {
 | |
|               Log.d("FxAccountsPush unsubscribed");
 | |
|             } else {
 | |
|               Log.d("FxAccountsPush had no subscription to unsubscribe");
 | |
|             }
 | |
|           } else {
 | |
|             Log.w("FxAccountsPush failed to unsubscribe", result);
 | |
|           }
 | |
|           return resolve(ok);
 | |
|         });
 | |
|     }).catch(err => {
 | |
|       Log.e("Error during unsubscribe", err);
 | |
|     });
 | |
|   },
 | |
| 
 | |
|   _decodePushMessage(data) {
 | |
|     Log.i("FxAccountsPush _decodePushMessage");
 | |
|     data = JSON.parse(data);
 | |
|     let { headers, message } = this._messageAndHeaders(data);
 | |
|     return new Promise((resolve, reject) => {
 | |
|       PushService.getSubscription(FXA_PUSH_SCOPE,
 | |
|         Services.scriptSecurityManager.getSystemPrincipal(),
 | |
|         (result, subscription) => {
 | |
|           if (!subscription) {
 | |
|             return reject(new Error("No subscription found"));
 | |
|           }
 | |
|           return resolve(subscription);
 | |
|         });
 | |
|     }).then(subscription => {
 | |
|       return PushCrypto.decrypt(subscription.p256dhPrivateKey,
 | |
|                                 new Uint8Array(subscription.getKey("p256dh")),
 | |
|                                 new Uint8Array(subscription.getKey("auth")),
 | |
|                                 headers, message);
 | |
|     })
 | |
|     .then(plaintext => {
 | |
|       let decryptedMessage = plaintext ? _decoder.decode(plaintext) : "";
 | |
|       EventDispatcher.instance.sendRequestForResult({
 | |
|         type: "FxAccountsPush:ReceivedPushMessageToDecode:Response",
 | |
|         message: decryptedMessage
 | |
|       });
 | |
|     })
 | |
|     .catch(err => {
 | |
|       Log.d("Error while decoding incoming message : " + err);
 | |
|     });
 | |
|   },
 | |
| 
 | |
|   // Copied from PushServiceAndroidGCM
 | |
|   _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 };
 | |
|   },
 | |
| 
 | |
|   QueryInterface: ChromeUtils.generateQI([Ci.nsIObserver]),
 | |
| 
 | |
|   classID: Components.ID("{d1bbb0fd-1d47-4134-9c12-d7b1be20b721}")
 | |
| };
 | |
| 
 | |
| function urlsafeBase64Encode(key) {
 | |
|   return ChromeUtils.base64URLEncode(new Uint8Array(key), { pad: false });
 | |
| }
 | |
| 
 | |
| var components = [ FxAccountsPush ];
 | |
| this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
 |