How can I send messages to a Chrome extension from localhost? - google-chrome-extension

Chrome apps are gone, so no chrome.sockets.tcpServer. chrome.gcm is gone, and Firebase is way too heavy for my interests (not that I ever used chrome.gcm). I just want to send messages from localhost; I don't want to register anything or maintain an app server. I tried the Push API with Service Workers, but ran into problems.
What works:
I can register a service worker. The registration eventually enters the active state.
What doesn't work:
The navigator.serviceWorker.ready promise never resolves.
Notification.requestPermission does nothing (but Notification.permission === 'granted' if I add the notification permission to the extension manifest).
The registration.pushManager.subscribe promise never resolves.
registration.pushManager.permissionState resolves to 'prompt', but no prompt ever appears.
None of this behavior fits the documentation I linked. How can I solve this problem?

Related

(How) Can a Chrome Extension listen for messages from my server?

My Chrome Extension's background page is set up as an event page, i.e., most of the time it is asleep unless some registered event listener wakes it up.
I'd like to be able to occasionally send messages from my server to the event page of an individual user of my extension. They should not necessarily show up as a desktop notification, it would rather be up to the background script to decide what to do with any incoming message. It might very well store some information in localstorage for example. If the user client was offline at the moment the message is being sent, it would ideally be delivered once it comes back online.
I'd like to avoid polling my server at regular intervals every time the background script is awake, though that would be an obvious solution.
My question is therefore if it is possible to register a special kind of event in my event page so that it wakes up and triggers some functionality once there's an incoming message from my server. Ideally, the server message would not be a general broadcast to all my users, but rather a targeted message to a specific user.
What options do I have?
I read about service workers and their Push API but it seems they are only slowly being rolled out to Chrome Extensions. I am not sure if they are ready for the browser's stable release yet and didn't find any documentation on how they work with extensions.
I also read a bit about Google Cloud Messaging but it is deprecated in favor of a new costly Firebase solution.
Service worker functions like a proxy server, allowing you to modify requests and responses, replace them with items from its own cache, and more. While Chrome has its own approach to caching/installing the resources need to display a Chrome Extension. Therefore, there will be an error when you will attempt to intercept the registration of a service worker to a Chrome Extension.
See for more information:
Introduction to service worker
Service Worker script errors if run in chrome extension
See related SO post:
Chrome Extensions with service worker receiving push notifications

Is it possible to receive webhook events in web extensions?

We need to get webhook events from a domain in the web extensions itself. That domain is not under our control.
We get the web extension's URL using browser.identity.getRedirectURL(). We have registered this as the webhook POST callback URL in other domain.
Is it possible to receive the webhook events whenever the other domain POSTs the data in callback URL? Would it be sufficient to intercept HTTP headers in order to get the data or would we need to have Node modules/servers inside the web extension?
No, not like you described. This is a pretty deep misunderstanding how webhooks and/or browser.identity work.
Your webextension is running on a client machine; it's not a webserver listening for connections (an extension can't do that at all).
So whenever some other machine that emits a webhook event tries to connect to the endpoint provided, whatever it connects to is not your extension.
You make an allusion to browser.identity.getRedirectURL() and seem to think that this is a real address that is assigned to your webextension and others can POST to it (and your extension be somehow informed about it).
This is not the case: instead, it's a "virtual" URL that the browser will treat specially if you (the browser) navigates to it. That request never actually leaves your machine to some server. No other client can connect to it (except for other browsers with the same extension - but again it will only ever reach them).
A solution for receiving webhooks would be to have an actual webserver somewhere that can receive them, plus some sort of push mechanism to inform your extension of the event:
A persistent WebSocket connection to your "receiver" server.
GCM push messaging initiated by your "receiver" server. Not for Firefox

Test for Apple Push Notification

I am using node.js (server framework) and mongoose.js (mongo based schema modeling) as the backend for an iOS app and I am using Mocha (test framwork) to make sure everything works.
What I really want to know, and can find no documentation on, is how to test on the server if the push notifications are being appropriately sent. I am using apnagent and at the moment I can see that push notifications are being sent correctly by manually checking my device but I am having difficulty finding an automated way to test that they are working correctly.
That may be enough of a description to answer at a high level what needs to be done. But in case it is not here is the actual code:
Mongoose Model fires off a push notification upon creation:
#this code is called after this model is saved in mongodb
eventModel.post 'save', (doc) ->
#push the message
sendMessageToDevice = (event, token) ->
message =
event_body:
eventId: event._id
lat: event.lngLat[1]
lng: event.lngLat[0]
agent.createMessage()
.device(token)
.alert('New Event! ' + event.description)
.set(message)
.send()
#cycle through the users to push to
#get all the unique device tokens in the database for APN
users.getAllUniqueDeviceTokens (error, devices) ->
if error then return util.handleError error
console.log "Sending push notices to all devices (%d):", devices.length
console.log devices
for token in devices
sendMessageToDevice doc, token
#send some verification here that the code ran correctly???
Then in my Mocha test file I have:
it 'should receive push notification from fort creation', (done) ->
#some logic here to verify that push notifications were sent
done()
In many situations, while writing tests, it is either impossible or simply too dangerous to verify that an action has really taken place (i.e. a push notification has been delivered). Imagine writing a unit test for the rm command where you would like to ensure that doing rm -rf / succeeds. Obviously, you cannot let this action take place and verify that your root partition is indeed empty!
What you can do, however (and should do, really), is verify that whatever commands, routines or other actions necessary to accomplish the task are being invoked correctly, without actually allowing them to take place.
In your particular situation, you do not need to verify that your push notification has been delivered because your application is not responsible for the notification's delivery. However, you can test that the push notification is being correctly delivered to the push server.
So, instead of testing for successful delivery, you test
Whether the outgoing request is properly formatted (i.e. JSON is valid)
Whether it contains the data you expect it to contain (i.e. a field in JSON is present and contains expected data)
Whether the authentication token required by the server is included
Whether the target server is correct (i.e. you are indeed sending the data to xxx.apple.com and not to localhost)
Ideally, these test requests will not even reach the target server - doing so would mean you are relying on two factors that are not always perfectly stable:
network connectivity
target server availability and proper functionality
In the past, I dealt with this so that I first manually issued a correct request, captured the response and then mocked the whole communication in the unit test (using i.e. nock. That way, I am completely in control of the whole communication.
As far as I know, there's no way to check if an APNS request has reached its destination or not. Apple tends to have this "everything's fine, and if it's not, then it should be your fault" policy with us developers. If things haven't changed since I started coding, you make an APNS request by sending raw data (JSON payload, you probably know the whole format) through the 2195 port, and you get absolutely no response for that.
Only thing I can think of, if you have a physical iOS device (an iPod, an iPhone or an iPad), you can "automate" a test by launching a PUSH request with a hardcoded token, corresponding to your device and a test app, and if you receive the notification then it works.
Oh, and if it doesn't work, please make sure you have all required ports open if you're operating behind a firewall. It's the first big stone I stepped into when I first dove into this ;) (related: https://support.apple.com/en-us/HT203609)
I would use a request mocking framework like nock to intercept the request to APN. The urls seem to be located in the code here.

Notifying a browser about events on server

I have a java based web application(struts 1.2). I have a requirement to display a status on the frontend (jsp). Now the status might change which my server gets notified by another server. But I want this status change to be notified to the browser.
I don't want to make a refresh at intervals. Rather I have to implement something like done in gmail chat, ie. the browser gets notified by changing events on the server.
Any ideas on how to go about this?
I was thinking on lines of opening a request to server for status, and at the server end I would hold the request and wouldn't respond back until there is a status change. Any pointers, examples on this?
Best possible solution will be to make use of XMPP protocol. It's standardized and a lot of open source solutions will get you started within minutes. You can use combination of Smack, StropheJS and Openfire to get your java based app work as desired.
There's a method called Long Polling (Comet). It basically sends a request to the server. The request thread created on the server simply waits for new data for the user, with a time limit of maybe 1 minute or more. When new data is available it is returned.
The main problem is to tackle the server-side issue, you don't want to have one thread for every user just waiting for new data. Of course you could use some asynchronous methods depending on your back-end.
Ref: http://en.wikipedia.org/wiki/Push_technology
Alternative way would be to use WebSockets. The problem is that it's not supported by all browsers today.

NSUserDefaultsDidChangeNotification and multitasking issue

I am using Settings app to store application settings. I also userdefaults to store internal application settings (which are not exposed in Settings app). For eg, I use user defaults to store the last tab bar index which is not exposed in Settings app.
I am subscribing to NSUserDefaultsDidChangeNotification to listen to any changes in settings while my app is in background and that works fine.
The issue is that when I update user defaults (for my internal application setting parameters) from within my app, this also triggers NSUserDefaultsDidChangeNotification and which I do not want.
Is it possible to just listen to change in settings from Settings app and not from within the application?
Is it possible to listen to the notification only when the app is in background? I tried to subscribe to notification only in applicationWillResignActive (just before moving into background) (and that works fine for registration), but I could not find a way to deregister once the application is made Active again (applicationDidMakeActive does not seem to be the correct callback since notifications are delivered after this callback).
Or is there some other simple way to achieve this?
applicationDidMakeActive? You must mean applicationDidBecomeActive.
You might consider implementing applicationDidEnterBackground and applicationWillEnterForeground instead of applicationWillResignActive and applicationDidBecomeActive.
The "Active" methods are also called when the app starts and ends, which mean you will stop listening to the notification once it starts (you weren't actually listening to this notification) and if you implement applicationDidBecomeActive you will start listening to the notification once your application ends (for nothing).

Resources