Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(290)

Unified Diff: chrome/browser/resources/google_now/background.js

Issue 844503005: Convert now component to use GCM rather than pushMessaging. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: responseType = text to application/json Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | chrome/browser/resources/google_now/background_test_util.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/resources/google_now/background.js
diff --git a/chrome/browser/resources/google_now/background.js b/chrome/browser/resources/google_now/background.js
index 087b2ac97912b99ca456bfc1bb2d45d74e1c8676..e24f70b499b482ea73d0a51204315cb4d34bcb2f 100644
--- a/chrome/browser/resources/google_now/background.js
+++ b/chrome/browser/resources/google_now/background.js
@@ -95,6 +95,17 @@ var DEFAULT_OPTIN_CHECK_PERIOD_SECONDS = 60 * 60 * 24 * 7; // 1 week
var SETTINGS_URL = 'https://support.google.com/chrome/?p=ib_google_now_welcome';
/**
+ * GCM registration URL.
+ */
+var GCM_REGISTRATION_URL =
+ 'https://android.googleapis.com/gcm/googlenotification';
+
+/**
+ * DevConsole project ID for GCM API use.
+ */
+var GCM_PROJECT_ID = '437902709571';
+
+/**
* Number of cards that need an explanatory link.
*/
var EXPLANATORY_CARDS_LINK_THRESHOLD = 4;
@@ -189,6 +200,8 @@ function areTasksConflicting(newTaskName, scheduledTaskName) {
var tasks = buildTaskManager(areTasksConflicting);
// Add error processing to API calls.
+wrapper.instrumentChromeApiFunction('gcm.onMessage.addListener', 0);
+wrapper.instrumentChromeApiFunction('gcm.register', 1);
wrapper.instrumentChromeApiFunction('metricsPrivate.getVariationParams', 1);
wrapper.instrumentChromeApiFunction('notifications.clear', 1);
wrapper.instrumentChromeApiFunction('notifications.create', 2);
@@ -204,10 +217,9 @@ wrapper.instrumentChromeApiFunction(
wrapper.instrumentChromeApiFunction(
'notifications.onShowSettings.addListener', 0);
wrapper.instrumentChromeApiFunction('permissions.contains', 1);
-wrapper.instrumentChromeApiFunction('pushMessaging.onMessage.addListener', 0);
-wrapper.instrumentChromeApiFunction('storage.onChanged.addListener', 0);
wrapper.instrumentChromeApiFunction('runtime.onInstalled.addListener', 0);
wrapper.instrumentChromeApiFunction('runtime.onStartup.addListener', 0);
+wrapper.instrumentChromeApiFunction('storage.onChanged.addListener', 0);
wrapper.instrumentChromeApiFunction('tabs.create', 1);
var updateCardsAttempts = buildAttemptManager(
@@ -1015,6 +1027,7 @@ function stopPollingCards() {
*/
function initialize() {
recordEvent(GoogleNowEvent.EXTENSION_START);
+ registerForGcm();
onStateChange();
}
@@ -1204,6 +1217,100 @@ function isGoogleNowEnabled() {
}
/**
+ * Ensures the extension is ready to listen for GCM messages.
+ */
+function registerForGcm() {
+ // We don't need to use the key yet, just ensure the channel is set up.
+ getGcmNotificationKey();
+}
+
+/**
+ * Returns a Promise resolving to either a cached or new GCM notification key.
+ * Rejects if registration fails.
+ * @return {Promise} A Promise that resolves to a potentially-cached GCM key.
+ */
+function getGcmNotificationKey() {
+ return fillFromChromeLocalStorage({gcmNotificationKey: undefined})
+ .then(function(items) {
+ if (items.gcmNotificationKey) {
+ console.log('Reused gcm key from storage.');
+ return Promise.resolve(items.gcmNotificationKey);
+ }
+ return requestNewGcmNotificationKey();
+ });
+}
+
+/**
+ * Returns a promise resolving to a GCM Notificaiton Key. May call
+ * chrome.gcm.register() first if required. Rejects on registration failure.
+ * @return {Promise} A Promise that resolves to a fresh GCM Notification key.
+ */
+function requestNewGcmNotificationKey() {
+ return getGcmRegistrationId().then(function(gcmId) {
+ authenticationManager.getAuthToken().then(function(token) {
+ authenticationManager.getLogin().then(function(username) {
+ return new Promise(function(resolve, reject) {
+ var xhr = new XMLHttpRequest();
+ xhr.responseType = 'application/json';
+ xhr.open('POST', GCM_REGISTRATION_URL, true);
+ xhr.setRequestHeader('Content-Type', 'application/json');
+ xhr.setRequestHeader('Authorization', 'Bearer ' + token);
+ xhr.setRequestHeader('project_id', GCM_PROJECT_ID);
+ var payload = {
+ 'operation': 'add',
+ 'notification_key_name': username,
+ 'registration_ids': [gcmId]
+ };
+ xhr.onloadend = function() {
+ if (xhr.status != 200) {
+ reject();
+ }
+ var obj = JSON.parse(xhr.responseText);
+ var key = obj && obj.notification_key;
+ if (!key) {
+ reject();
+ }
+ console.log('gcm notification key POST: ' + key);
+ chrome.storage.local.set({gcmNotificationKey: key});
+ resolve(key);
+ };
+ xhr.send(JSON.stringify(payload));
+ });
+ });
+ }).catch(function() {
+ // Couldn't obtain a GCM ID. Ignore and fallback to polling.
+ });
+ });
+}
+
+/**
+ * Returns a promise resolving to either a cached or new GCM registration ID.
+ * Rejects if registration fails.
+ * @return {Promise} A Promise that resolves to a GCM registration ID.
+ */
+function getGcmRegistrationId() {
+ return fillFromChromeLocalStorage({gcmRegistrationId: undefined})
+ .then(function(items) {
+ if (items.gcmRegistrationId) {
+ console.log('Reused gcm registration id from storage.');
+ return Promise.resolve(items.gcmRegistrationId);
+ }
+
+ return new Promise(function(resolve, reject) {
+ instrumented.gcm.register([GCM_PROJECT_ID], function(registrationId) {
+ console.log('gcm.register(): ' + registrationId);
+ if (registrationId) {
+ chrome.storage.local.set({gcmRegistrationId: registrationId});
+ resolve(registrationId);
+ } else {
+ reject();
+ }
+ });
+ });
+ });
+}
+
+/**
* Polls the optin state.
* Sometimes we get the response to the opted in result too soon during
* push messaging. We'll recheck the optin state a few times before giving up.
@@ -1334,13 +1441,15 @@ instrumented.storage.onChanged.addListener(function(changes, areaName) {
}
});
-instrumented.pushMessaging.onMessage.addListener(function(message) {
- // message.payload will be '' when the extension first starts.
- // Each time after signing in, we'll get latest payload for all channels.
- // So, we need to poll the server only when the payload is non-empty and has
- // changed.
- console.log('pushMessaging.onMessage ' + JSON.stringify(message));
- if (message.payload.indexOf('REQUEST_CARDS') == 0) {
+instrumented.gcm.onMessage.addListener(function(message) {
+ console.log('gcm.onMessage ' + JSON.stringify(message));
+ if (!message || !message.data) {
+ return;
+ }
+
+ var payload = message.data.payload;
+ var tag = message.data.tag;
+ if (payload.indexOf('REQUEST_CARDS') == 0) {
tasks.add(ON_PUSH_MESSAGE_START_TASK_NAME, function() {
// Accept promise rejection on failure since it's safer to do nothing,
// preventing polling the server when the payload really didn't change.
@@ -1349,11 +1458,10 @@ instrumented.pushMessaging.onMessage.addListener(function(message) {
/** @type {Object<string, StoredNotificationGroup>} */
notificationGroups: {}
}, PromiseRejection.ALLOW).then(function(items) {
- if (items.lastPollNowPayloads[message.subchannelId] !=
- message.payload) {
- items.lastPollNowPayloads[message.subchannelId] = message.payload;
+ if (items.lastPollNowPayloads[tag] != payload) {
+ items.lastPollNowPayloads[tag] = payload;
- items.notificationGroups['PUSH' + message.subchannelId] = {
+ items.notificationGroups['PUSH' + tag] = {
cards: [],
nextPollTime: Date.now()
};
« no previous file with comments | « no previous file | chrome/browser/resources/google_now/background_test_util.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698