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

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java

Issue 978653002: Upstream FirstRunActivity and friends. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Updated logos Created 5 years, 9 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 unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 package org.chromium.chrome.browser.firstrun;
6
7 import android.app.Activity;
8 import android.app.Fragment;
9 import android.content.Intent;
10 import android.os.Bundle;
11 import android.support.v4.view.ViewPager;
12 import android.support.v7.app.ActionBarActivity;
13 import android.text.TextUtils;
14
15 import org.chromium.base.ApplicationStatus;
16 import org.chromium.base.VisibleForTesting;
17 import org.chromium.chrome.R;
18 import org.chromium.chrome.browser.ChromiumApplication;
19 import org.chromium.chrome.browser.metrics.UmaBridge;
20 import org.chromium.chrome.browser.profiles.Profile;
21
22 import java.lang.ref.WeakReference;
23 import java.lang.reflect.Constructor;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.concurrent.Callable;
27
28 /**
29 * Handles the First Run Experience sequences shown to the user launching Chrome for the first time.
30 * It supports only a simple format of FRE:
31 * [Welcome]
32 * [Intro pages...]
33 * [Sign-in page]
34 * The activity might be run more than once, e.g. 1) for ToS and sign-in, and 2) for intro.
35 */
36 public class FirstRunActivity extends ActionBarActivity implements FirstRunPageD elegate {
37 protected static final String TAG = "FirstRunActivity";
38
39 // Incoming parameters:
40 public static final String ORIGINAL_INTENT = "OriginalIntent";
41 public static final String FIRE_ORIGINAL_INTENT = "FireOriginalIntent";
42 public static final String COMING_FROM_CHROME_ICON = "ComingFromChromeIcon";
43 public static final String USE_FRE_FLOW_SEQUENCER = "UseFreFlowSequencer";
44
45 public static final String SHOW_WELCOME_PAGE = "ShowWelcome";
46 public static final String SKIP_WELCOME_PAGE_IF_ACCEPTED_TOS = "SkipWelcomeP ageIfAcceptedToS";
47 public static final String SHOW_INTRO_BITMAP = "ShowIntroBitmap";
48 public static final String SKIP_ALL_INTRO = "SkipAllIntro"; // Marks all in tros as seen.
49 public static final String SHOW_SIGNIN_PAGE = "ShowSignIn";
50
51 // Outcoming results:
52 public static final String RESULT_CLOSE_APP = "Close App";
53 public static final String RESULT_SIGNIN_ACCOUNT_NAME = "ResultSignInTo";
54 public static final String RESULT_SHOW_SYNC_SETTINGS = "ResultShowSyncSettin gs";
55
56 @VisibleForTesting
57 static FirstRunGlue sGlue = new FirstRunGlueImpl();
58
59 private boolean mShowWelcomePage = true;
60
61 private String mResultSignInAccountName;
62 private boolean mResultShowSyncSettings;
63
64 // TODO(aurimas): make this private once all of FirstRunActivity is upstream ed.
65 protected boolean mNativeSideIsInitialized;
66
67 private ProfileDataCache mProfileDataCache;
68 private ViewPager mPager;
69
70 private Bundle mFreProperties;
71
72 private List<Callable<FirstRunPage>> mPages;
73 private int mSkipIntroPageNumber;
74
75 /**
76 * The pager adapter, which provides the pages to the view pager widget.
77 */
78 private FirstRunPagerAdapter mPagerAdapter;
79
80 /**
81 * Defines a sequence of pages to be shown (depending on parameters etc).
82 */
83 private void createPageSequence() {
84 mPages = new ArrayList<Callable<FirstRunPage>>();
85
86 // An optional welcome page.
87 if (mShowWelcomePage) mPages.add(pageOf(ToSAndUMAFirstRunFragment.class) );
88
89 // An optional sequence of intro pages.
90 if (!mFreProperties.getBoolean(SKIP_ALL_INTRO)) {
91 final long bitmap = mFreProperties.getLong(SHOW_INTRO_BITMAP);
92
93 // "Hera" (recents/tabs) promo.
94 if (((bitmap & FirstRunIntroPage.INTRO_RECENTS) != 0)
95 && sGlue.isDocumentModeEligible(getApplicationContext())) {
96 mPages.add(pageOf(FirstRunIntroRecentsPage.class));
97 }
98 }
99
100 // Set the anchor to jump to if the user skips intro pages.
101 mSkipIntroPageNumber = mPages.size();
102
103 // An optional sign-in page.
104 if (mFreProperties.getBoolean(SHOW_SIGNIN_PAGE)) {
105 mPages.add(pageOf(AccountFirstRunFragment.class));
106 }
107 }
108
109 // Activity:
110
111 @Override
112 protected void onCreate(Bundle savedInstanceState) {
113 initializeBrowserProcess();
114
115 super.onCreate(savedInstanceState);
116 setFinishOnTouchOutside(false);
117
118 if (savedInstanceState != null) {
119 mFreProperties = savedInstanceState;
120 } else if (getIntent() != null) {
121 mFreProperties = getIntent().getExtras();
122 } else {
123 mFreProperties = new Bundle();
124 }
125
126 mPager = new ViewPager(this);
127 mPager.setId(R.id.fre_pager);
128 setContentView(mPager);
129 android.util.Log.i("FirstRunActivity", "onCreate: after setContentView") ;
130
131 mProfileDataCache = new ProfileDataCache(FirstRunActivity.this, null);
132 mProfileDataCache.setProfile(Profile.getLastUsedProfile());
133 new FirstRunFlowSequencer(this, mFreProperties) {
134 @Override
135 public void onFlowIsKnown(Activity activity, Bundle freProperties) {
136 android.util.Log.i("FirstRunActivity", "in onFlowIsKnown");
137
138 if (freProperties == null) {
139 completeFirstRunExperience();
140 return;
141 }
142
143 mFreProperties = freProperties;
144 mShowWelcomePage = mFreProperties.getBoolean(SHOW_WELCOME_PAGE);
145 if (mShowWelcomePage
146 && mFreProperties.getBoolean(SKIP_WELCOME_PAGE_IF_ACCEPT ED_TOS)) {
147 mShowWelcomePage = !sGlue.didAcceptTermsOfService(getApplica tionContext());
148 }
149 createPageSequence();
150
151 if (TextUtils.isEmpty(mResultSignInAccountName)) {
152 mResultSignInAccountName = mFreProperties.getString(
153 AccountFirstRunFragment.FORCE_SIGNIN_ACCOUNT_TO);
154 }
155
156 if (mPages.size() == 0) {
157 completeFirstRunExperience();
158 return;
159 }
160
161 mPagerAdapter =
162 new FirstRunPagerAdapter(getFragmentManager(), mPages, m FreProperties);
163 stopProgressionIfNotAcceptedTermsOfService();
164 mPager.setAdapter(mPagerAdapter);
165
166 skipPagesIfNecessary();
167 android.util.Log.i("FirstRunActivity", "before return from onFlo wIsKnown");
168 }
169 }.start();
170 android.util.Log.i("FirstRunActivity", "onCreate: after starting the seq uencer");
171 }
172
173 @Override
174 protected void onSaveInstanceState(Bundle outState) {
175 super.onSaveInstanceState(outState);
176 outState.putAll(mFreProperties);
177 }
178
179 @Override
180 protected void onPause() {
181 super.onPause();
182 flushPersistentData();
183 }
184
185 @Override
186 protected void onResumeFragments() {
187 skipPagesIfNecessary();
188 }
189
190 @Override
191 protected void onDestroy() {
192 super.onDestroy();
193 mProfileDataCache.onDestroy();
194 }
195
196 @Override
197 protected void onStart() {
198 super.onStart();
199 stopProgressionIfNotAcceptedTermsOfService();
200 if (!mFreProperties.getBoolean(USE_FRE_FLOW_SEQUENCER)) {
201 if (FirstRunStatus.getFirstRunFlowComplete(this)
202 && FirstRunIntroPage.wereAllNecessaryPagesShown(this)) {
203 // This is a parallel flow that needs to be refreshed/re-fired.
204 // Signal the FRE flow completion and re-launch the original int ent.
205 completeFirstRunExperience();
206 }
207 }
208 }
209
210 @Override
211 public void onBackPressed() {
212 // Terminate if we are still waiting for the native or for Android EDU / GAIA Child checks.
213 if (mPagerAdapter == null) {
214 abortFirstRunExperience();
215 return;
216 }
217
218 Object currentItem = mPagerAdapter.instantiateItem(mPager, mPager.getCur rentItem());
219 if (currentItem instanceof FirstRunPage) {
220 FirstRunPage page = (FirstRunPage) currentItem;
221 if (page.interceptBackPressed()) return;
222 }
223
224 if (mPager.getCurrentItem() == 0) {
225 abortFirstRunExperience();
226 } else {
227 mPager.setCurrentItem(mPager.getCurrentItem() - 1);
228 }
229 }
230
231 // FirstRunPageDelegate:
232
233 @Override
234 public ProfileDataCache getProfileDataCache() {
235 return mProfileDataCache;
236 }
237
238 @Override
239 public void advanceToNextPage() {
240 jumpToPage(mPager.getCurrentItem() + 1, true);
241 }
242
243 @Override
244 public void skipIntroPages() {
245 jumpToPage(mSkipIntroPageNumber, false);
246 }
247
248 @Override
249 public void recreateCurrentPage() {
250 mPagerAdapter.notifyDataSetChanged();
251 }
252
253 @Override
254 public void abortFirstRunExperience() {
255 Intent intent = new Intent();
256 if (mFreProperties != null) intent.putExtras(mFreProperties);
257 intent.putExtra(RESULT_CLOSE_APP, true);
258 finishAllFREActivities(Activity.RESULT_CANCELED, intent);
259 }
260
261 @Override
262 public void completeFirstRunExperience() {
263 if (!TextUtils.isEmpty(mResultSignInAccountName)) {
264 UmaBridge.freSignInAccepted(
265 mResultShowSyncSettings,
266 sGlue.isDefaultAccountName(getApplicationContext(), mResultS ignInAccountName));
267 }
268
269 mFreProperties.putString(RESULT_SIGNIN_ACCOUNT_NAME, mResultSignInAccoun tName);
270 mFreProperties.putBoolean(RESULT_SHOW_SYNC_SETTINGS, mResultShowSyncSett ings);
271 FirstRunFlowSequencer.markFlowAsCompleted(this, mFreProperties);
272
273 if (mFreProperties.getBoolean(FirstRunActivity.FIRE_ORIGINAL_INTENT)) {
274 Intent originalIntent = mFreProperties.getParcelable(FirstRunActivit y.ORIGINAL_INTENT);
275 startActivity(originalIntent);
276 }
277
278 Intent resultData = new Intent();
279 resultData.putExtras(mFreProperties);
280 finishAllFREActivities(Activity.RESULT_OK, resultData);
281 }
282
283 @Override
284 public void onSigninDialogShown() {
285 UmaBridge.freSignInShown();
286 }
287
288 @Override
289 public void refuseSignIn() {
290 UmaBridge.freSkipSignIn();
291 UmaBridge.freSignInDeclined();
292 mResultSignInAccountName = null;
293 mResultShowSyncSettings = false;
294 }
295
296 @Override
297 public void acceptSignIn(String accountName) {
298 mResultSignInAccountName = accountName;
299 }
300
301 @Override
302 public void askToOpenSyncSettings() {
303 mResultShowSyncSettings = true;
304 }
305
306 @Override
307 public boolean didAcceptTermsOfService() {
308 return sGlue.didAcceptTermsOfService(getApplicationContext());
309 }
310
311 @Override
312 public boolean isNeverUploadCrashDump() {
313 return sGlue.isNeverUploadCrashDump(getApplicationContext());
314 }
315
316 @Override
317 public void acceptTermsOfService(boolean allowCrashUpload) {
318 sGlue.acceptTermsOfService(getApplicationContext(), allowCrashUpload);
319 flushPersistentData();
320 stopProgressionIfNotAcceptedTermsOfService();
321 jumpToPage(mPager.getCurrentItem() + 1, true);
322 }
323
324 @Override
325 public void openAccountAdder(Fragment fragment) {
326 sGlue.openAccountAdder(fragment);
327 }
328
329 protected void flushPersistentData() {
330 if (mNativeSideIsInitialized) ChromiumApplication.flushPersistentData();
331 }
332
333 private static void finishAllFREActivities(int result, Intent data) {
334 List<WeakReference<Activity>> activities = ApplicationStatus.getRunningA ctivities();
335 for (WeakReference<Activity> weakActivity : activities) {
336 Activity activity = weakActivity.get();
337 if (activity instanceof FirstRunActivity) {
338 activity.setResult(result, data);
339 activity.finish();
340 }
341 }
342 }
343
344
345 /**
346 * Transitions to a given page.
347 * @return Whether the transition to a given page was allowed.
348 * @param position A page index to transition to.
349 * @param smooth Whether the transition should be smooth.
350 */
351 private boolean jumpToPage(int position, boolean smooth) {
352 if (mShowWelcomePage && !didAcceptTermsOfService()) {
353 return position == 0;
354 }
355 if (position >= mPagerAdapter.getCount()) {
356 completeFirstRunExperience();
357 return false;
358 }
359 mPager.setCurrentItem(position, smooth);
360 return true;
361 }
362
363 private void stopProgressionIfNotAcceptedTermsOfService() {
364 if (mPagerAdapter == null) return;
365 mPagerAdapter.setStopAtTheFirstPage(mShowWelcomePage && !didAcceptTermsO fService());
366 }
367
368 private void skipPagesIfNecessary() {
369 if (mPagerAdapter == null) return;
370
371 int currentPageIndex = mPager.getCurrentItem();
372 while (currentPageIndex < mPagerAdapter.getCount()) {
373 FirstRunPage currentPage = (FirstRunPage) mPagerAdapter.getItem(curr entPageIndex);
374 if (!currentPage.shouldSkipPageOnResume(getApplicationContext())) re turn;
375 if (!jumpToPage(currentPageIndex + 1, false)) return;
376 currentPageIndex = mPager.getCurrentItem();
377 }
378 }
379
380 protected void initializeBrowserProcess() {
381 // TODO(aurimas): implement this once browser process initialization is upstreamed.
382 }
383
384 /**
385 * Creates a trivial page constructor for a given page type.
386 * @param clazz The .class of the page type.
387 * @return The simple constructor for a given page type (no parameters, no t uning).
388 */
389 public static Callable<FirstRunPage> pageOf(final Class<? extends FirstRunPa ge> clazz) {
390 return new Callable<FirstRunPage>() {
391 @Override
392 public FirstRunPage call() throws Exception {
393 Constructor<? extends FirstRunPage> constructor = clazz.getDecla redConstructor();
394 return constructor.newInstance();
395 }
396 };
397 }
398
399 @Override
400 public void showEmbedContentViewActivity(int title, int url) {
401 // TODO(aurimas): implement this once EmbededContentViewActivity is upst reamed.
402 }
403
404 public void showSignInNotification() {
405 // TODO(aurimas): implement this once GoogleServicesManager is upstreame d.
406 }
407
408 @Override
409 public void openDocumentModeSettings() {
410 // TODO(aurimas): implement opening settings once DocumentModeSettings i s upstreamed.
411 }
412 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698