Index: android_webview/java/src/org/chromium/android_webview/AwVariationsSeedFetchService.java |
diff --git a/android_webview/java/src/org/chromium/android_webview/AwVariationsSeedFetchService.java b/android_webview/java/src/org/chromium/android_webview/AwVariationsSeedFetchService.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a14b52298da536e4b1ba9411e9bb4bea952a089d |
--- /dev/null |
+++ b/android_webview/java/src/org/chromium/android_webview/AwVariationsSeedFetchService.java |
@@ -0,0 +1,158 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+package org.chromium.android_webview; |
+ |
+import android.annotation.SuppressLint; |
+import android.app.job.JobParameters; |
+import android.app.job.JobService; |
+import android.content.Context; |
+import android.os.AsyncTask; |
+ |
+import org.chromium.base.ContextUtils; |
+import org.chromium.base.Log; |
+import org.chromium.base.ThreadUtils; |
+import org.chromium.components.variations.firstrun.VariationsSeedFetcher; |
+ |
+import java.io.File; |
+import java.io.FileNotFoundException; |
+import java.io.FileOutputStream; |
+import java.io.IOException; |
+import java.io.ObjectOutputStream; |
+import java.io.Serializable; |
+import java.util.concurrent.locks.Lock; |
+import java.util.concurrent.locks.ReentrantLock; |
+ |
+/** |
+ * AwVariationsSeedFetchService is a Job Service to fetch test seed data which is used by Finch |
+ * to enable AB tesing experiments in the native code. The fetched data is stored in the local |
+ * directory which belongs to the Service process. |
+ */ |
+@SuppressLint("NewApi") // JobService requires API level 21 |
+public class AwVariationsSeedFetchService extends JobService { |
+ private static final String TAG = "AwVartnsSeedFetchSvc"; |
+ |
+ public static final String WEBVIEW_VARIATIONS_DIR = "WebView_Variations/"; |
+ public static final String SEED_DATA_FILENAME = "variations_seed_data"; |
+ public static final String SEED_PREF_FILENAME = "variations_seed_pref"; |
+ |
+ // Synchronization lock to prevent simultaneous local seed file writing |
+ private static final Lock sLock = new ReentrantLock(); |
+ |
+ @Override |
+ public boolean onStartJob(final JobParameters params) { |
+ new FetchFinchSeedDataTask(params).execute(); |
+ return true; |
+ } |
+ |
+ @Override |
+ public boolean onStopJob(JobParameters params) { |
+ // When job parameter is not satisfied any more, the job should be rescheduled |
Alexei Svitkine (slow)
2017/07/11 19:37:23
Comments should be full sentences. i.e. terminate
yiyuny
2017/07/11 22:43:37
Done.
|
+ return true; |
+ } |
+ |
+ private class FetchFinchSeedDataTask extends AsyncTask<Void, Void, Void> { |
+ private JobParameters mJobParams; |
+ |
+ FetchFinchSeedDataTask(JobParameters params) { |
+ mJobParams = params; |
+ } |
+ |
+ @Override |
+ protected Void doInBackground(Void... params) { |
+ AwVariationsSeedFetchService.fetchSeed(); |
+ return null; |
+ } |
+ |
+ @Override |
+ protected void onPostExecute(Void success) { |
+ jobFinished(mJobParams, false); |
+ } |
+ } |
+ |
+ private static void fetchSeed() { |
+ assert !ThreadUtils.runningOnUiThread(); |
+ // Make sure there will only be one task fetching seed |
+ if (sLock.tryLock()) { |
Alexei Svitkine (slow)
2017/07/11 19:37:23
I don't think this does what you want it do. Unles
paulmiller
2017/07/11 20:51:36
It was synchronized before. I don't think we want
Alexei Svitkine (slow)
2017/07/11 20:53:47
Gotcha. It seems OK as a temporary solution with a
yiyuny
2017/07/11 22:43:37
Done.
|
+ try { |
+ VariationsSeedFetcher.SeedInfo si = VariationsSeedFetcher.get().downloadContent( |
+ VariationsSeedFetcher.VariationsPlatform.ANDROID_WEBVIEW, ""); |
+ storeVariationsSeed(si); |
+ } catch (IOException e) { |
+ // Exceptions are handled in the downloadContent function and rethrowing the |
+ // exception is to stop the normal logic flow after it, so no error-handling here. |
+ // Not explicitly handing SocketTimeoutException and UnknownHostException for they |
+ // are both subclasses of IOException. |
+ } finally { |
+ sLock.unlock(); |
+ } |
+ } |
+ } |
+ |
+ /** |
+ * Store seed preference independently from Seed Info |
+ */ |
+ public static class SeedPreference implements Serializable { |
Alexei Svitkine (slow)
2017/07/11 19:37:23
Can SeedInfo from the fetcher be re-used?
yiyuny
2017/07/11 22:43:37
I didn't re-use the SeedInfo class is because
1.
|
+ public String signature; |
+ public String country; |
+ public String date; |
+ public boolean isGzipCompressed; |
+ |
+ public SeedPreference(final VariationsSeedFetcher.SeedInfo si) { |
+ signature = si.signature; |
+ country = si.country; |
+ date = si.date; |
+ isGzipCompressed = si.isGzipCompressed; |
+ } |
+ } |
+ |
+ public static File getOrCreateWebViewVariationsDir() { |
Alexei Svitkine (slow)
2017/07/11 19:37:23
Does this need to be public?
yiyuny
2017/07/11 22:43:37
The function will be used when reading the seed pr
|
+ File dir = new File( |
+ ContextUtils.getApplicationContext().getFilesDir(), WEBVIEW_VARIATIONS_DIR); |
+ if (dir.mkdir() || dir.isDirectory()) { |
+ return dir; |
+ } |
+ return null; |
+ } |
+ |
+ private static void storeVariationsSeed(final VariationsSeedFetcher.SeedInfo si) { |
+ FileOutputStream fosSeed = null; |
+ ObjectOutputStream oosSeedPref = null; |
+ final Context appContext = ContextUtils.getApplicationContext(); |
+ File webViewVariationsDir = getOrCreateWebViewVariationsDir(); |
+ if (webViewVariationsDir == null) { |
+ return; |
+ } |
+ try { |
+ fosSeed = new FileOutputStream(new File(webViewVariationsDir, SEED_DATA_FILENAME)); |
+ fosSeed.write(si.rawSeed, 0, si.rawSeed.length); |
+ // store separately so that reading large seed data (which is expensive) can be |
+ // prevented when checking the last seed fetch time |
+ oosSeedPref = new ObjectOutputStream( |
+ new FileOutputStream(new File(webViewVariationsDir, SEED_PREF_FILENAME))); |
+ oosSeedPref.writeObject(new SeedPreference(si)); |
+ } catch (FileNotFoundException e) { |
+ Log.e(TAG, |
+ "FileNotFoundException failed to open file to write seed data or preference."); |
+ } catch (IOException e) { |
+ Log.e(TAG, |
+ "IOException failed to write variations seed data or preference to the file."); |
+ } finally { |
+ if (fosSeed != null) { |
+ try { |
+ fosSeed.close(); |
+ } catch (IOException e) { |
+ Log.e(TAG, "IOException failed to close the variations seed data file."); |
+ } |
+ } |
Alexei Svitkine (slow)
2017/07/11 19:37:23
This is pretty verbose. Perhaps add a helper funct
yiyuny
2017/07/11 22:43:36
Done.
|
+ if (oosSeedPref != null) { |
+ try { |
+ oosSeedPref.close(); |
+ } catch (IOException e) { |
+ Log.e(TAG, "IOException failed to close the variations seed preference file."); |
+ } |
+ } |
+ } |
+ } |
+} |