OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser.services.gcm; | 5 package org.chromium.chrome.browser.services.gcm; |
6 | 6 |
7 import android.app.job.JobInfo; | |
8 import android.app.job.JobScheduler; | |
9 import android.content.ComponentName; | |
10 import android.content.Context; | |
11 import android.os.Build; | |
7 import android.os.Bundle; | 12 import android.os.Bundle; |
8 import android.text.TextUtils; | 13 import android.text.TextUtils; |
9 | 14 |
10 import com.google.android.gms.gcm.GcmListenerService; | 15 import com.google.android.gms.gcm.GcmListenerService; |
11 import com.google.ipc.invalidation.ticl.android2.channel.AndroidGcmController; | 16 import com.google.ipc.invalidation.ticl.android2.channel.AndroidGcmController; |
12 | 17 |
13 import org.chromium.base.Log; | 18 import org.chromium.base.Log; |
14 import org.chromium.base.ThreadUtils; | 19 import org.chromium.base.ThreadUtils; |
15 import org.chromium.base.annotations.SuppressFBWarnings; | 20 import org.chromium.base.annotations.SuppressFBWarnings; |
16 import org.chromium.base.library_loader.ProcessInitException; | 21 import org.chromium.base.library_loader.ProcessInitException; |
22 import org.chromium.chrome.browser.JobSchedulerConstants; | |
17 import org.chromium.chrome.browser.init.ChromeBrowserInitializer; | 23 import org.chromium.chrome.browser.init.ChromeBrowserInitializer; |
18 import org.chromium.chrome.browser.init.ProcessInitializationHandler; | 24 import org.chromium.chrome.browser.init.ProcessInitializationHandler; |
19 import org.chromium.components.gcm_driver.GCMDriver; | 25 import org.chromium.components.gcm_driver.GCMDriver; |
26 import org.chromium.components.gcm_driver.GCMMessage; | |
20 | 27 |
21 /** | 28 /** |
22 * Receives Downstream messages and status of upstream messages from GCM. | 29 * Receives Downstream messages and status of upstream messages from GCM. |
23 */ | 30 */ |
24 public class ChromeGcmListenerService extends GcmListenerService { | 31 public class ChromeGcmListenerService extends GcmListenerService { |
25 private static final String TAG = "ChromeGcmListener"; | 32 private static final String TAG = "ChromeGcmListener"; |
26 | 33 |
27 @Override | 34 @Override |
28 public void onCreate() { | 35 public void onCreate() { |
29 ProcessInitializationHandler.getInstance().initializePreNative(); | 36 ProcessInitializationHandler.getInstance().initializePreNative(); |
30 super.onCreate(); | 37 super.onCreate(); |
31 } | 38 } |
32 | 39 |
33 @Override | 40 @Override |
34 public void onMessageReceived(String from, Bundle data) { | 41 public void onMessageReceived(String from, Bundle data) { |
35 boolean hasCollapseKey = !TextUtils.isEmpty(data.getString("collapse_key ")); | 42 boolean hasCollapseKey = !TextUtils.isEmpty(data.getString("collapse_key ")); |
36 GcmUma.recordDataMessageReceived(getApplicationContext(), hasCollapseKey ); | 43 GcmUma.recordDataMessageReceived(getApplicationContext(), hasCollapseKey ); |
37 | 44 |
38 String invalidationSenderId = AndroidGcmController.get(this).getSenderId (); | 45 String invalidationSenderId = AndroidGcmController.get(this).getSenderId (); |
39 if (from.equals(invalidationSenderId)) { | 46 if (from.equals(invalidationSenderId)) { |
40 AndroidGcmController.get(this).onMessageReceived(data); | 47 AndroidGcmController.get(this).onMessageReceived(data); |
41 return; | 48 return; |
42 } | 49 } |
43 pushMessageReceived(from, data); | 50 |
51 // Dispatch the message to the GCM Driver for native features. | |
52 scheduleOrDispatchMessageToDriver(getApplicationContext(), from, data); | |
44 } | 53 } |
45 | 54 |
46 @Override | 55 @Override |
47 public void onMessageSent(String msgId) { | 56 public void onMessageSent(String msgId) { |
48 Log.d(TAG, "Message sent successfully. Message id: " + msgId); | 57 Log.d(TAG, "Message sent successfully. Message id: " + msgId); |
49 GcmUma.recordGcmUpstreamHistogram(getApplicationContext(), GcmUma.UMA_UP STREAM_SUCCESS); | 58 GcmUma.recordGcmUpstreamHistogram(getApplicationContext(), GcmUma.UMA_UP STREAM_SUCCESS); |
50 } | 59 } |
51 | 60 |
52 @Override | 61 @Override |
53 public void onSendError(String msgId, String error) { | 62 public void onSendError(String msgId, String error) { |
54 Log.w(TAG, "Error in sending message. Message id: " + msgId + " Error: " + error); | 63 Log.w(TAG, "Error in sending message. Message id: " + msgId + " Error: " + error); |
55 GcmUma.recordGcmUpstreamHistogram(getApplicationContext(), GcmUma.UMA_UP STREAM_SEND_FAILED); | 64 GcmUma.recordGcmUpstreamHistogram(getApplicationContext(), GcmUma.UMA_UP STREAM_SEND_FAILED); |
56 } | 65 } |
57 | 66 |
58 @Override | 67 @Override |
59 public void onDeletedMessages() { | 68 public void onDeletedMessages() { |
60 // TODO(johnme): Ask GCM to include the subtype in this event. | 69 // TODO(johnme): Ask GCM to include the subtype in this event. |
61 Log.w(TAG, "Push messages were deleted, but we can't tell the Service Wo rker as we don't" | 70 Log.w(TAG, "Push messages were deleted, but we can't tell the Service Wo rker as we don't" |
62 + "know what subtype (app ID) it occurred for."); | 71 + "know what subtype (app ID) it occurred for."); |
63 GcmUma.recordDeletedMessages(getApplicationContext()); | 72 GcmUma.recordDeletedMessages(getApplicationContext()); |
64 } | 73 } |
65 | 74 |
66 private void pushMessageReceived(final String from, final Bundle data) { | 75 /** |
67 final String bundleSubtype = "subtype"; | 76 * To be called when a GCM message is ready to be dispatched. Will initialis e the native code |
68 if (!data.containsKey(bundleSubtype)) { | 77 * of the browser process, and forward the message to the GCM Driver. |
awdf
2017/02/16 21:26:48
nit: could add "Must be called on the UI thread."
Peter Beverloo
2017/02/17 15:43:59
Done.
| |
69 Log.w(TAG, "Received push message with no subtype"); | 78 */ |
70 return; | 79 @SuppressFBWarnings("DM_EXIT") |
80 public static void dispatchMessageToDriver(Context applicationContext, GCMMe ssage message) { | |
awdf
2017/02/16 21:26:48
nit: can you make this method default (package) pr
Peter Beverloo
2017/02/17 15:43:59
Done.
| |
81 ThreadUtils.assertOnUiThread(); | |
82 | |
83 try { | |
84 ChromeBrowserInitializer.getInstance(applicationContext).handleSynch ronousStartup(); | |
85 GCMDriver.dispatchMessage(message); | |
86 | |
87 } catch (ProcessInitException e) { | |
88 Log.e(TAG, "ProcessInitException while starting the browser process" ); | |
89 | |
90 // Since the library failed to initialize nothing in the application can work, so kill | |
91 // the whole application as opposed to just this service. | |
92 System.exit(-1); | |
71 } | 93 } |
72 final String appId = data.getString(bundleSubtype); | 94 } |
73 ThreadUtils.runOnUiThread(new Runnable() { | 95 |
74 @Override | 96 /** |
75 @SuppressFBWarnings("DM_EXIT") | 97 * Either schedules |message| to be dispatched through the Job Scheduler, wh ich we use on |
76 public void run() { | 98 * Android N and beyond, or immediately dispatches the message on other vers ions of Android. |
77 try { | 99 */ |
78 ChromeBrowserInitializer.getInstance(getApplicationContext() ) | 100 public static void scheduleOrDispatchMessageToDriver( |
awdf
2017/02/16 21:26:48
nit: place this method above dispatchMessageToDriv
Peter Beverloo
2017/02/17 15:43:59
Done. Why?
awdf
2017/02/18 07:51:41
because this one calls dispatchMessageToDrive so l
| |
79 .handleSynchronousStartup(); | 101 final Context context, String senderId, Bundle extras) { |
80 GCMDriver.onMessageReceived(appId, from, data); | 102 final GCMMessage message = new GCMMessage(senderId, extras); |
81 } catch (ProcessInitException e) { | 103 |
82 Log.e(TAG, "ProcessInitException while starting the browser process"); | 104 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { |
awdf
2017/02/16 21:26:48
nit: I'm wondering if we should have a common shou
Peter Beverloo
2017/02/17 15:43:59
I think that'll depend on the feature, doesn't it?
| |
83 // Since the library failed to initialize nothing in the app lication | 105 // TODO(peter): Add UMA for measuring latency introduced by the JobS cheduler. |
84 // can work, so kill the whole application not just the acti vity. | 106 JobInfo job = new JobInfo |
85 System.exit(-1); | 107 .Builder(JobSchedulerConstants.GCM_DRIVER_JOB_ ID, |
108 new ComponentName(context, GCMJobServi ce.class)) | |
109 .setExtras(message.toPersistableBundle()) | |
110 .setOverrideDeadline(0) | |
111 .build(); | |
112 JobScheduler scheduler = | |
113 (JobScheduler) context.getSystemService(Context.JOB_SCHEDULE R_SERVICE); | |
114 scheduler.schedule(job); | |
115 } else { | |
116 ThreadUtils.runOnUiThread(new Runnable() { | |
117 @Override | |
118 public void run() { | |
119 ChromeGcmListenerService.dispatchMessageToDriver(context, me ssage); | |
86 } | 120 } |
87 } | 121 }); |
88 }); | 122 } |
89 } | 123 } |
90 } | 124 } |
OLD | NEW |