mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-07-31 21:29:00 +00:00
215 lines
7.4 KiB
Java
215 lines
7.4 KiB
Java
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
package org.mozilla.mozstumbler.service.uploadthread;
|
|
|
|
import android.os.AsyncTask;
|
|
import android.util.Log;
|
|
import java.io.IOException;
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
|
import org.mozilla.mozstumbler.service.Prefs;
|
|
import org.mozilla.mozstumbler.service.utils.AbstractCommunicator;
|
|
import org.mozilla.mozstumbler.service.utils.AbstractCommunicator.SyncSummary;
|
|
import org.mozilla.mozstumbler.service.AppGlobals;
|
|
import org.mozilla.mozstumbler.service.stumblerthread.datahandling.DataStorageManager;
|
|
import org.mozilla.mozstumbler.service.utils.NetworkUtils;
|
|
|
|
/* Only one at a time may be uploading. If executed while another upload is in progress
|
|
* it will return immediately, and SyncResult is null.
|
|
*
|
|
* Threading:
|
|
* Uploads on a separate thread. ONLY DataStorageManager is thread-safe, do not call
|
|
* preferences, do not call any code that isn't thread-safe. You will cause suffering.
|
|
* An exception is made for AppGlobals.isDebug, a false reading is of no consequence. */
|
|
public class AsyncUploader extends AsyncTask<Void, Void, SyncSummary> {
|
|
private static final String LOG_TAG = AppGlobals.makeLogTag(AsyncUploader.class.getSimpleName());
|
|
private final AsyncUploadArgs mUploadArgs;
|
|
private final Object mListenerLock = new Object();
|
|
private AsyncUploaderListener mListener;
|
|
private static final AtomicBoolean sIsUploading = new AtomicBoolean();
|
|
private String mNickname;
|
|
|
|
public interface AsyncUploaderListener {
|
|
public void onUploadComplete(SyncSummary result);
|
|
public void onUploadProgress();
|
|
}
|
|
|
|
public static class AsyncUploadArgs {
|
|
public final NetworkUtils mNetworkUtils;
|
|
public final boolean mShouldIgnoreWifiStatus;
|
|
public final boolean mUseWifiOnly;
|
|
public AsyncUploadArgs(NetworkUtils networkUtils,
|
|
boolean shouldIgnoreWifiStatus,
|
|
boolean useWifiOnly) {
|
|
mNetworkUtils = networkUtils;
|
|
mShouldIgnoreWifiStatus = shouldIgnoreWifiStatus;
|
|
mUseWifiOnly = useWifiOnly;
|
|
}
|
|
}
|
|
|
|
public AsyncUploader(AsyncUploadArgs args, AsyncUploaderListener listener) {
|
|
mListener = listener;
|
|
mUploadArgs = args;
|
|
}
|
|
|
|
public void setNickname(String name) {
|
|
mNickname = name;
|
|
}
|
|
|
|
public void clearListener() {
|
|
synchronized (mListenerLock) {
|
|
mListener = null;
|
|
}
|
|
}
|
|
|
|
public static boolean isUploading() {
|
|
return sIsUploading.get();
|
|
}
|
|
|
|
@Override
|
|
protected SyncSummary doInBackground(Void... voids) {
|
|
if (sIsUploading.get()) {
|
|
// This if-block is not synchronized, don't care, this is an erroneous usage.
|
|
Log.d(LOG_TAG, "Usage error: check isUploading first, only one at a time task usage is permitted.");
|
|
return null;
|
|
}
|
|
|
|
sIsUploading.set(true);
|
|
SyncSummary result = new SyncSummary();
|
|
Runnable progressListener = null;
|
|
|
|
// no need to lock here, lock is checked again later
|
|
if (mListener != null) {
|
|
progressListener = new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
synchronized (mListenerLock) {
|
|
if (mListener != null) {
|
|
mListener.onUploadProgress();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
uploadReports(result, progressListener);
|
|
|
|
return result;
|
|
}
|
|
@Override
|
|
protected void onPostExecute(SyncSummary result) {
|
|
sIsUploading.set(false);
|
|
|
|
synchronized (mListenerLock) {
|
|
if (mListener != null) {
|
|
mListener.onUploadComplete(result);
|
|
}
|
|
}
|
|
}
|
|
@Override
|
|
protected void onCancelled(SyncSummary result) {
|
|
sIsUploading.set(false);
|
|
}
|
|
|
|
private class Submitter extends AbstractCommunicator {
|
|
private static final String SUBMIT_URL = "https://location.services.mozilla.com/v1/submit";
|
|
|
|
@Override
|
|
public String getUrlString() {
|
|
return SUBMIT_URL;
|
|
}
|
|
|
|
@Override
|
|
public String getNickname(){
|
|
return mNickname;
|
|
}
|
|
|
|
@Override
|
|
public NetworkSendResult cleanSend(byte[] data) {
|
|
final NetworkSendResult result = new NetworkSendResult();
|
|
try {
|
|
result.bytesSent = this.send(data, ZippedState.eAlreadyZipped);
|
|
result.errorCode = 0;
|
|
} catch (IOException ex) {
|
|
String msg = "Error submitting: " + ex;
|
|
if (ex instanceof HttpErrorException) {
|
|
result.errorCode = ((HttpErrorException) ex).responseCode;
|
|
msg += " Code:" + result.errorCode;
|
|
}
|
|
Log.e(LOG_TAG, msg);
|
|
AppGlobals.guiLogError(msg);
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
|
|
private void uploadReports(AbstractCommunicator.SyncSummary syncResult, Runnable progressListener) {
|
|
long uploadedObservations = 0;
|
|
long uploadedCells = 0;
|
|
long uploadedWifis = 0;
|
|
|
|
if (!mUploadArgs.mShouldIgnoreWifiStatus && mUploadArgs.mUseWifiOnly &&
|
|
!mUploadArgs.mNetworkUtils.isWifiAvailable()) {
|
|
if (AppGlobals.isDebug) {
|
|
Log.d(LOG_TAG, "not on WiFi, not sending");
|
|
}
|
|
syncResult.numIoExceptions += 1;
|
|
return;
|
|
}
|
|
|
|
Submitter submitter = new Submitter();
|
|
DataStorageManager dm = DataStorageManager.getInstance();
|
|
|
|
String error = null;
|
|
|
|
try {
|
|
DataStorageManager.ReportBatch batch = dm.getFirstBatch();
|
|
while (batch != null) {
|
|
AbstractCommunicator.NetworkSendResult result = submitter.cleanSend(batch.data);
|
|
|
|
if (result.errorCode == 0) {
|
|
syncResult.totalBytesSent += result.bytesSent;
|
|
|
|
dm.delete(batch.filename);
|
|
|
|
uploadedObservations += batch.reportCount;
|
|
uploadedWifis += batch.wifiCount;
|
|
uploadedCells += batch.cellCount;
|
|
} else {
|
|
if (result.errorCode / 100 == 4) {
|
|
// delete on 4xx, no point in resending
|
|
dm.delete(batch.filename);
|
|
} else {
|
|
DataStorageManager.getInstance().saveCurrentReportsSendBufferToDisk();
|
|
}
|
|
syncResult.numIoExceptions += 1;
|
|
}
|
|
|
|
if (progressListener != null) {
|
|
progressListener.run();
|
|
}
|
|
|
|
batch = dm.getNextBatch();
|
|
}
|
|
}
|
|
catch (IOException ex) {
|
|
error = ex.toString();
|
|
}
|
|
|
|
try {
|
|
dm.incrementSyncStats(syncResult.totalBytesSent, uploadedObservations, uploadedCells, uploadedWifis);
|
|
} catch (IOException ex) {
|
|
error = ex.toString();
|
|
} finally {
|
|
if (error != null) {
|
|
syncResult.numIoExceptions += 1;
|
|
Log.d(LOG_TAG, error);
|
|
AppGlobals.guiLogError(error + " (uploadReports)");
|
|
}
|
|
submitter.close();
|
|
}
|
|
}
|
|
}
|