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

Unified 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 5 and fix test failure 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 side-by-side diff with in-line comments
Download patch
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..666227440af90c6a19b3b92c4d9442e52abe07df
--- /dev/null
+++ b/android_webview/java/src/org/chromium/android_webview/AwVariationsSeedFetchService.java
@@ -0,0 +1,157 @@
+// 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.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.Closeable;
+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.
+ return true;
+ }
+
+ private class FetchFinchSeedDataTask extends AsyncTask<Void, Void, Void> {
Alexei Svitkine (slow) 2017/07/12 15:52:50 Can this class be static?
yiyuny 2017/07/12 18:31:30 I prefer to make it non-static because function jo
Alexei Svitkine (slow) 2017/07/12 19:01:21 That makes sense.
+ 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();
+ // TryLock will drop calls from other threads when one threads are executing the function.
+ // TODO(yiyuny): Add explicitly control to make sure there is only one thread fetching the
+ // seed in a while before the seed is expired.
Alexei Svitkine (slow) 2017/07/12 15:52:50 Nit: "before the seed is expired" isn't too meanin
yiyuny 2017/07/12 18:31:30 Done.
+ if (sLock.tryLock()) {
+ try {
+ VariationsSeedFetcher.SeedInfo si = VariationsSeedFetcher.get().downloadContent(
Alexei Svitkine (slow) 2017/07/12 15:52:50 Nit: seedInfo
yiyuny 2017/07/12 18:31:30 Done.
+ 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.
Alexei Svitkine (slow) 2017/07/12 15:52:49 This comment reads like a method comment, since it
yiyuny 2017/07/12 18:31:30 Done.
+ */
+ public static class SeedPreference implements Serializable {
+ public String signature;
+ public String country;
+ public String date;
+ public boolean isGzipCompressed;
Alexei Svitkine (slow) 2017/07/12 15:52:49 Can these be final - or is that something that's n
yiyuny 2017/07/12 18:31:30 Done.
+
+ public SeedPreference(final VariationsSeedFetcher.SeedInfo si) {
Alexei Svitkine (slow) 2017/07/12 15:52:49 Nit: seedInfo. Acronyms are discouraged, especiall
yiyuny 2017/07/12 18:31:30 Done.
+ signature = si.signature;
+ country = si.country;
+ date = si.date;
+ isGzipCompressed = si.isGzipCompressed;
+ }
+ }
+
+ private static File getOrCreateWebViewVariationsDir() {
+ File dir = new File(
+ ContextUtils.getApplicationContext().getFilesDir(), WEBVIEW_VARIATIONS_DIR);
Alexei Svitkine (slow) 2017/07/12 15:52:50 Nit: If this is wrapping already, suggest extracti
yiyuny 2017/07/12 18:31:30 Done.
+ if (dir.mkdir() || dir.isDirectory()) {
+ return dir;
+ }
+ return null;
+ }
+
+ private static void storeVariationsSeed(final VariationsSeedFetcher.SeedInfo si) {
Alexei Svitkine (slow) 2017/07/12 15:52:49 seedInfo
yiyuny 2017/07/12 18:31:30 Done.
+ FileOutputStream fosSeed = null;
+ ObjectOutputStream oosSeedPref = null;
Alexei Svitkine (slow) 2017/07/12 15:52:49 Nit: Move these to right above the try.
yiyuny 2017/07/12 18:31:30 Done.
+ 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 {
+ closeStream(fosSeed, SEED_DATA_FILENAME);
+ closeStream(oosSeedPref, SEED_PREF_FILENAME);
+ }
+ }
+
+ private static void closeStream(Closeable stream, String filename) {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ Log.e(TAG, "IOException failed to close " + filename + " file.");
+ }
+ }
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698