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

Side by Side Diff: android_webview/java/src/org/chromium/android_webview/AwVariationsSeedFetchService.java

Issue 2975693002: Add AwVariationsSeedFetchService and refactory VariationsSeedFetcher (Closed)
Patch Set: Update for comments of Patch 13 Created 3 years, 5 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 2017 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.android_webview;
6
7 import android.annotation.TargetApi;
8 import android.app.job.JobParameters;
9 import android.app.job.JobService;
10 import android.os.AsyncTask;
11 import android.os.Build;
12
13 import org.chromium.base.ContextUtils;
14 import org.chromium.base.Log;
15 import org.chromium.base.ThreadUtils;
16 import org.chromium.base.annotations.SuppressFBWarnings;
17 import org.chromium.components.variations.firstrun.VariationsSeedFetcher;
18 import org.chromium.components.variations.firstrun.VariationsSeedFetcher.SeedInf o;
19
20 import java.io.Closeable;
21 import java.io.File;
22 import java.io.FileOutputStream;
23 import java.io.IOException;
24 import java.io.ObjectOutputStream;
25 import java.io.Serializable;
26 import java.util.concurrent.locks.Lock;
27 import java.util.concurrent.locks.ReentrantLock;
28
29 /**
30 * AwVariationsSeedFetchService is a Job Service to fetch test seed data which i s used by Finch
31 * to enable AB testing experiments in the native code. The fetched data is stor ed in the local
32 * directory which belongs to the Service process. This a prototype of the Varia tions Seed Fetch
33 * Service which is one part of the work of adding Finch to Android WebView.
34 */
35 @TargetApi(Build.VERSION_CODES.LOLLIPOP) // JobService requires API level 21.
36 public class AwVariationsSeedFetchService extends JobService {
37 private static final String TAG = "AwVartnsSeedFetchSvc";
38
39 public static final String WEBVIEW_VARIATIONS_DIR = "WebView_Variations/";
40 public static final String SEED_DATA_FILENAME = "variations_seed_data";
41 public static final String SEED_PREF_FILENAME = "variations_seed_pref";
42
43 // Synchronization lock to prevent simultaneous local seed file writing.
44 private static final Lock sLock = new ReentrantLock();
45
46 @Override
47 public boolean onStartJob(JobParameters params) {
48 // Ensure we can use ContextUtils later on.
49 ContextUtils.initApplicationContext(this.getApplicationContext());
50 new FetchFinchSeedDataTask(params).execute();
51 return true;
52 }
53
54 @Override
55 public boolean onStopJob(JobParameters params) {
56 // This method is called by the JobScheduler to stop a job before it has finished.
57 // Return true here to reschedule the job.
58 return true;
59 }
60
61 private class FetchFinchSeedDataTask extends AsyncTask<Void, Void, Void> {
62 private JobParameters mJobParams;
63
64 FetchFinchSeedDataTask(JobParameters params) {
65 mJobParams = params;
66 }
67
68 @Override
69 protected Void doInBackground(Void... params) {
70 AwVariationsSeedFetchService.fetchSeed();
71 return null;
72 }
73
74 @Override
75 protected void onPostExecute(Void success) {
76 jobFinished(mJobParams, false /* false -> don't reschedule */);
77 }
78 }
79
80 private static void fetchSeed() {
81 assert !ThreadUtils.runningOnUiThread();
82 // TryLock will drop calls from other threads when there is a thread exe cuting the function.
83 // TODO(yiyuny): Add explicitly control to ensure there's only one threa ding fetching at a
84 // time and that the seed doesn't get fetched too frequently
85 if (sLock.tryLock()) {
86 try {
87 SeedInfo seedInfo = VariationsSeedFetcher.get().downloadContent(
88 VariationsSeedFetcher.VariationsPlatform.ANDROID_WEBVIEW , "");
89 storeVariationsSeed(seedInfo);
90 } catch (IOException e) {
91 // Exceptions are handled and logged in the downloadContent meth od, so we don't
92 // need any exception handling here. The only reason we need a c atch-statement here
93 // is because those exceptions are re-thrown from downloadConten t to skip the
94 // normal logic flow within that method.
95 } finally {
96 sLock.unlock();
97 }
98 }
99 }
100
101 /**
102 * SeedPreference is used to serialize/deserialize related fields of seed da ta when reading or
103 * writing them to the internal storage.
104 */
105 public static class SeedPreference implements Serializable {
106 /**
107 * Let the program deserialize the data when the fields are changed.
108 */
109 private static final long serialVersionUID = 0L;
110
111 public final String signature;
112 public final String country;
113 public final String date;
114 public final boolean isGzipCompressed;
115
116 public SeedPreference(SeedInfo seedInfo) {
117 signature = seedInfo.signature;
118 country = seedInfo.country;
119 date = seedInfo.date;
120 isGzipCompressed = seedInfo.isGzipCompressed;
121 }
122 }
123
124 private static File getOrCreateWebViewVariationsDir() {
125 File webViewFileDir = ContextUtils.getApplicationContext().getFilesDir() ;
126 File dir = new File(webViewFileDir, WEBVIEW_VARIATIONS_DIR);
127 if (dir.mkdir() || dir.isDirectory()) {
128 return dir;
129 }
130 return null;
131 }
132
133 private static void storeVariationsSeed(SeedInfo seedInfo) {
134 File webViewVariationsDir = getOrCreateWebViewVariationsDir();
135 if (webViewVariationsDir == null) {
136 Log.e(TAG, "Failed to get or create the WebView variations directory .");
137 return;
138 }
139
140 FileOutputStream fosSeedData = null;
141 ObjectOutputStream oosSeedPref = null;
142 try {
143 File seedDataFile = File.createTempFile(SEED_DATA_FILENAME, null, we bViewVariationsDir);
144 fosSeedData = new FileOutputStream(seedDataFile);
145 fosSeedData.write(seedInfo.seedData, 0, seedInfo.seedData.length);
146 renameTempFile(seedDataFile, new File(webViewVariationsDir, SEED_DAT A_FILENAME));
147 // Store separately so that reading large seed data (which is expens ive) can be
148 // prevented when checking the last seed fetch time.
149 File seedPrefFile = File.createTempFile(SEED_PREF_FILENAME, null, we bViewVariationsDir);
150 oosSeedPref = new ObjectOutputStream(new FileOutputStream(seedPrefFi le));
151 oosSeedPref.writeObject(new SeedPreference(seedInfo));
152 renameTempFile(seedPrefFile, new File(webViewVariationsDir, SEED_PRE F_FILENAME));
153 } catch (IOException e) {
154 Log.e(TAG, "Failed to write variations seed data or preference to a file." + e);
155 } finally {
156 closeStream(fosSeedData);
157 closeStream(oosSeedPref);
158 }
159 }
160
161 @SuppressFBWarnings("RV_RETURN_VALUE_IGNORED_BAD_PRACTICE") // ignoring File .delete() return
162 private static void renameTempFile(File tempFile, File newFile) {
163 newFile.delete();
164 tempFile.renameTo(newFile);
165 }
166
167 private static void closeStream(Closeable stream) {
168 if (stream != null) {
169 try {
170 stream.close();
171 } catch (IOException e) {
172 Log.e(TAG, "Failed to close stream." + e);
173 }
174 }
175 }
176 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698