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

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/printing/PrintShareActivity.java

Issue 2523873003: [Android] Fix timing issue in enabling/disabling printing. (Closed)
Patch Set: comment Created 4 years 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 unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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.printing; 5 package org.chromium.chrome.browser.printing;
6 6
7 import android.app.Activity; 7 import android.app.Activity;
8 import android.content.ComponentName; 8 import android.content.ComponentName;
9 import android.content.Intent; 9 import android.content.Intent;
10 import android.content.pm.PackageManager; 10 import android.content.pm.PackageManager;
11 import android.os.AsyncTask; 11 import android.os.AsyncTask;
12 import android.os.Bundle; 12 import android.os.Bundle;
13 import android.os.StrictMode;
13 import android.support.v7.app.AppCompatActivity; 14 import android.support.v7.app.AppCompatActivity;
14 15
15 import org.chromium.base.ActivityState; 16 import org.chromium.base.ActivityState;
16 import org.chromium.base.ApplicationStatus; 17 import org.chromium.base.ApplicationStatus;
17 import org.chromium.base.ApplicationStatus.ActivityStateListener; 18 import org.chromium.base.ApplicationStatus.ActivityStateListener;
19 import org.chromium.base.Log;
18 import org.chromium.base.ThreadUtils; 20 import org.chromium.base.ThreadUtils;
19 import org.chromium.chrome.R; 21 import org.chromium.chrome.R;
20 import org.chromium.chrome.browser.ChromeActivity; 22 import org.chromium.chrome.browser.ChromeActivity;
21 import org.chromium.chrome.browser.share.ShareHelper; 23 import org.chromium.chrome.browser.share.ShareHelper;
22 import org.chromium.chrome.browser.util.IntentUtils; 24 import org.chromium.chrome.browser.util.IntentUtils;
23 25
24 import java.lang.ref.WeakReference; 26 import java.lang.ref.WeakReference;
25 import java.util.Collections; 27 import java.util.Collections;
26 import java.util.HashSet; 28 import java.util.HashSet;
27 import java.util.List; 29 import java.util.List;
28 import java.util.Set; 30 import java.util.Set;
31 import java.util.concurrent.ExecutionException;
29 32
30 /** 33 /**
31 * A simple activity that allows Chrome to expose print as an option in the shar e menu. 34 * A simple activity that allows Chrome to expose print as an option in the shar e menu.
32 */ 35 */
33 public class PrintShareActivity extends AppCompatActivity { 36 public class PrintShareActivity extends AppCompatActivity {
34 37
38 private static final String TAG = "cr_printing";
39
35 private static Set<Activity> sPendingShareActivities = 40 private static Set<Activity> sPendingShareActivities =
36 Collections.synchronizedSet(new HashSet<Activity>()); 41 Collections.synchronizedSet(new HashSet<Activity>());
37 private static ActivityStateListener sStateListener; 42 private static ActivityStateListener sStateListener;
43 private static AsyncTask<Void, Void, Void> sStateChangeTask;
38 44
39 /** 45 /**
40 * Enable the print sharing option. 46 * Enable the print sharing option.
41 * 47 *
42 * @param activity The activity that will be triggering the share action. T he activitiy's 48 * @param activity The activity that will be triggering the share action. T he activitiy's
43 * state will be tracked to disable the print option when th e share operation 49 * state will be tracked to disable the print option when th e share operation
44 * has been completed. 50 * has been completed.
45 * @param callback The callback to be triggered after the print option has b een enabled. This 51 * @param callback The callback to be triggered after the print option has b een enabled. This
46 * may or may not be synchronous depending on whether this w ill require 52 * may or may not be synchronous depending on whether this w ill require
47 * interacting with the Android framework. 53 * interacting with the Android framework.
48 */ 54 */
49 public static void enablePrintShareOption(final Activity activity, final Run nable callback) { 55 public static void enablePrintShareOption(final Activity activity, final Run nable callback) {
50 ThreadUtils.assertOnUiThread(); 56 ThreadUtils.assertOnUiThread();
51 57
52 if (sStateListener == null) { 58 if (sStateListener == null) {
53 sStateListener = new ActivityStateListener() { 59 sStateListener = new ActivityStateListener() {
54 @Override 60 @Override
55 public void onActivityStateChange(Activity activity, int newStat e) { 61 public void onActivityStateChange(Activity activity, int newStat e) {
56 if (newState == ActivityState.PAUSED) return; 62 if (newState == ActivityState.PAUSED) return;
57 unregisterActivity(activity); 63 unregisterActivity(activity);
58 } 64 }
59 }; 65 };
60 } 66 }
61 ApplicationStatus.registerStateListenerForAllActivities(sStateListener); 67 ApplicationStatus.registerStateListenerForAllActivities(sStateListener);
62 boolean wasEmpty = sPendingShareActivities.isEmpty(); 68 boolean wasEmpty = sPendingShareActivities.isEmpty();
63 sPendingShareActivities.add(activity); 69 sPendingShareActivities.add(activity);
70
71 waitForPendingStateChangeTask();
64 if (wasEmpty) { 72 if (wasEmpty) {
65 new AsyncTask<Void, Void, Void>() { 73 sStateChangeTask = new AsyncTask<Void, Void, Void>() {
66 @Override 74 @Override
67 protected Void doInBackground(Void... params) { 75 protected Void doInBackground(Void... params) {
68 if (sPendingShareActivities.isEmpty()) return null; 76 if (sPendingShareActivities.isEmpty()) return null;
69 77
70 activity.getPackageManager().setComponentEnabledSetting( 78 activity.getPackageManager().setComponentEnabledSetting(
71 new ComponentName(activity, PrintShareActivity.class ), 79 new ComponentName(activity, PrintShareActivity.class ),
72 PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 80 PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
73 PackageManager.DONT_KILL_APP); 81 PackageManager.DONT_KILL_APP);
74 return null; 82 return null;
75 } 83 }
76 84
77 @Override 85 @Override
78 protected void onPostExecute(Void result) { 86 protected void onPostExecute(Void result) {
87 if (sStateChangeTask == this) {
88 sStateChangeTask = null;
89 } else {
90 waitForPendingStateChangeTask();
91 }
79 callback.run(); 92 callback.run();
80 } 93 }
81 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 94 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
82 } else { 95 } else {
83 callback.run(); 96 callback.run();
84 } 97 }
85 } 98 }
86 99
87 private static void unregisterActivity(final Activity activity) { 100 private static void unregisterActivity(final Activity activity) {
101 ThreadUtils.assertOnUiThread();
102
88 sPendingShareActivities.remove(activity); 103 sPendingShareActivities.remove(activity);
89 if (!sPendingShareActivities.isEmpty()) return; 104 if (!sPendingShareActivities.isEmpty()) return;
90 ApplicationStatus.unregisterActivityStateListener(sStateListener); 105 ApplicationStatus.unregisterActivityStateListener(sStateListener);
91 106
92 new AsyncTask<Void, Void, Void>() { 107 waitForPendingStateChangeTask();
108 sStateChangeTask = new AsyncTask<Void, Void, Void>() {
93 @Override 109 @Override
94 protected Void doInBackground(Void... params) { 110 protected Void doInBackground(Void... params) {
95 if (!sPendingShareActivities.isEmpty()) return null; 111 if (!sPendingShareActivities.isEmpty()) return null;
96 112
97 activity.getPackageManager().setComponentEnabledSetting( 113 activity.getPackageManager().setComponentEnabledSetting(
98 new ComponentName(activity, PrintShareActivity.class), 114 new ComponentName(activity, PrintShareActivity.class),
99 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 115 PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
100 PackageManager.DONT_KILL_APP); 116 PackageManager.DONT_KILL_APP);
101 return null; 117 return null;
102 } 118 }
119
120 @Override
121 protected void onPostExecute(Void result) {
122 if (sStateChangeTask == this) sStateChangeTask = null;
123 }
103 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 124 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
104 } 125 }
105 126
127 /**
128 * Waits for any pending state change operations to be completed.
129 *
130 * This will avoid timing issues described here: crbug.com/649453.
131 */
132 private static void waitForPendingStateChangeTask() {
133 ThreadUtils.assertOnUiThread();
134
135 if (sStateChangeTask == null) return;
136 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
137 try {
138 sStateChangeTask.get();
139 sStateChangeTask = null;
140 } catch (InterruptedException | ExecutionException e) {
141 Log.e(TAG, "Print state change task did not complete as expected");
142 } finally {
143 StrictMode.setThreadPolicy(oldPolicy);
144 }
145 }
146
106 @Override 147 @Override
107 protected void onCreate(Bundle savedInstanceState) { 148 protected void onCreate(Bundle savedInstanceState) {
108 super.onCreate(savedInstanceState); 149 super.onCreate(savedInstanceState);
109 150
110 try { 151 try {
111 Intent intent = getIntent(); 152 Intent intent = getIntent();
112 if (intent == null) return; 153 if (intent == null) return;
113 if (!Intent.ACTION_SEND.equals(intent.getAction())) return; 154 if (!Intent.ACTION_SEND.equals(intent.getAction())) return;
114 if (!IntentUtils.safeHasExtra(getIntent(), ShareHelper.EXTRA_TASK_ID )) return; 155 if (!IntentUtils.safeHasExtra(getIntent(), ShareHelper.EXTRA_TASK_ID )) return;
115 handlePrintAction(); 156 handlePrintAction();
(...skipping 18 matching lines...) Expand all
134 triggeringActivity = (ChromeActivity) activity; 175 triggeringActivity = (ChromeActivity) activity;
135 break; 176 break;
136 } 177 }
137 } 178 }
138 if (triggeringActivity == null) return; 179 if (triggeringActivity == null) return;
139 unregisterActivity(triggeringActivity); 180 unregisterActivity(triggeringActivity);
140 triggeringActivity.onMenuOrKeyboardAction(R.id.print_id, true); 181 triggeringActivity.onMenuOrKeyboardAction(R.id.print_id, true);
141 } 182 }
142 183
143 } 184 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698