Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions firebase-storage/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
- [changed] Added `@RestrictTo` annotations to discourage the use of APIs that
are not public. This affects internal APIs that were previously obfuscated
and are not mentioned in our documentation.
- [internal] Updated the SDK initialization process and removed usages of
deprecated methods.
3 changes: 3 additions & 0 deletions firebase-storage/firebase-storage.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ dependencies {

implementation "com.google.android.gms:play-services-base:$playServicesVersion"
implementation "com.google.android.gms:play-services-tasks:$playServicesVersion"
implementation('com.google.firebase:firebase-auth-interop:16.0.1') {
exclude group: "com.google.firebase", module: "firebase-common"
}

androidTestImplementation "com.android.support:support-annotations:$supportAnnotationsVersion"
androidTestImplementation 'com.android.support.test:rules:1.0.2'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,13 @@ public DeleteStorageTask(
Preconditions.checkNotNull(pendingResult);
this.mStorageRef = storageRef;
this.mPendingResult = pendingResult;

FirebaseStorage storage = mStorageRef.getStorage();
mSender =
new ExponentialBackoffSender(
mStorageRef.getStorage().getApp(),
mStorageRef.getStorage().getMaxOperationRetryTimeMillis());
storage.getApp().getApplicationContext(),
storage.getAuthProvider(),
storage.getMaxDownloadRetryTimeMillis());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,13 @@ public class FileDownloadTask extends StorageTask<FileDownloadTask.TaskSnapshot>
/*package*/ FileDownloadTask(@NonNull StorageReference storageRef, @NonNull Uri destinationFile) {
mStorageRef = storageRef;
mDestinationFile = destinationFile;

FirebaseStorage storage = mStorageRef.getStorage();
mSender =
new ExponentialBackoffSender(
mStorageRef.getStorage().getApp(),
mStorageRef.getStorage().getMaxDownloadRetryTimeMillis());
storage.getApp().getApplicationContext(),
storage.getAuthProvider(),
storage.getMaxDownloadRetryTimeMillis());
}

/** @return the number of bytes downloaded so far into the file. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,13 @@
import android.text.format.DateUtils;
import android.util.Log;
import com.google.android.gms.common.internal.Preconditions;
import com.google.android.gms.common.util.VisibleForTesting;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.annotations.PublicApi;
import com.google.firebase.auth.internal.InternalAuthProvider;
import com.google.firebase.inject.Provider;
import com.google.firebase.storage.internal.Util;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

/**
* FirebaseStorage is a service that supports uploading and downloading large objects to Google
Expand All @@ -44,20 +43,23 @@
@PublicApi
public class FirebaseStorage {
private static final String TAG = "FirebaseStorage";
private static final Map<String /* App name */, Map<String /* StorageBucket */, FirebaseStorage>>
mStorageMap = new HashMap<>();
private static final String STORAGE_URI_PARSE_EXCEPTION = "The storage Uri could not be parsed.";
private static final String STORAGE_BUCKET_WITH_PATH_EXCEPTION =
"The storage Uri cannot contain a path element.";
@NonNull private final FirebaseApp mApp;
@Nullable private final Provider<InternalAuthProvider> mAuthProvider;
@Nullable private final String mBucketName;
private long sMaxUploadRetry = 10 * DateUtils.MINUTE_IN_MILLIS; // 10 * 60 * 1000
private long sMaxDownloadRetry = 10 * DateUtils.MINUTE_IN_MILLIS; // 10 * 60 * 1000
private long sMaxQueryRetry = 2 * DateUtils.MINUTE_IN_MILLIS; // 2 * 60 * 1000

private FirebaseStorage(@Nullable String bucketName, @NonNull FirebaseApp app) {
FirebaseStorage(
@Nullable String bucketName,
@NonNull FirebaseApp app,
@Nullable Provider<InternalAuthProvider> authProvider) {
mBucketName = bucketName;
mApp = app;
mAuthProvider = authProvider;
}

private static FirebaseStorage getInstanceImpl(@NonNull FirebaseApp app, @Nullable Uri url) {
Expand All @@ -67,19 +69,10 @@ private static FirebaseStorage getInstanceImpl(@NonNull FirebaseApp app, @Nullab
throw new IllegalArgumentException(STORAGE_BUCKET_WITH_PATH_EXCEPTION);
}

synchronized (mStorageMap) {
Map<String, FirebaseStorage> storageBuckets = mStorageMap.get(app.getName());
if (storageBuckets == null) {
storageBuckets = new HashMap<>();
mStorageMap.put(app.getName(), storageBuckets);
}
FirebaseStorage storage = storageBuckets.get(bucketName);
if (storage == null) {
storage = new FirebaseStorage(bucketName, app);
storageBuckets.put(bucketName, storage);
}
return storage;
}
Preconditions.checkNotNull(app, "Provided FirebaseApp must not be null.");
FirebaseStorageComponent component = app.get(FirebaseStorageComponent.class);
Preconditions.checkNotNull(component, "Firebase Storage component is not present.");
return component.get(bucketName);
}

/**
Expand Down Expand Up @@ -151,6 +144,8 @@ public static FirebaseStorage getInstance(@NonNull FirebaseApp app) {
public static FirebaseStorage getInstance(@NonNull FirebaseApp app, @NonNull String url) {
// noinspection ConstantConditions
Preconditions.checkArgument(app != null, "Null is not a valid value for the FirebaseApp.");
Preconditions.checkArgument(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

optional nit: elsewhere you switched to staticly imported checks, might make sense to do the same throughout for consistency.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rest of the SDK doesn't use static imports, so I changed this file to use the qualified import checkNotNull.

url != null, "Null is not a valid value for the Firebase Storage URL.");

if (!url.toLowerCase().startsWith("gs://")) {
throw new IllegalArgumentException(
Expand All @@ -165,14 +160,6 @@ public static FirebaseStorage getInstance(@NonNull FirebaseApp app, @NonNull Str
}
}

/** @hide */
@VisibleForTesting
static void clearInstancesForTest() {
synchronized (mStorageMap) {
mStorageMap.clear();
}
}

/**
* Returns the maximum time to retry a download if a failure occurs.
*
Expand Down Expand Up @@ -331,4 +318,9 @@ private StorageReference getReference(@NonNull Uri uri) {
public FirebaseApp getApp() {
return mApp;
}

@Nullable
InternalAuthProvider getAuthProvider() {
return mAuthProvider != null ? mAuthProvider.get() : null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.firebase.storage;

import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import com.google.firebase.FirebaseApp;
import com.google.firebase.auth.internal.InternalAuthProvider;
import com.google.firebase.inject.Provider;
import java.util.HashMap;
import java.util.Map;

class FirebaseStorageComponent {
/** A map from storage buckets to Firebase Storage instances. */
private final Map<String, FirebaseStorage> instances = new HashMap<>();

private final FirebaseApp app;
@Nullable private final Provider<InternalAuthProvider> authProvider;

FirebaseStorageComponent(
@NonNull FirebaseApp app, @Nullable Provider<InternalAuthProvider> authProvider) {
this.app = app;
this.authProvider = authProvider;
}

/** Provides instances of Firebase Storage for given bucket names. */
@NonNull
synchronized FirebaseStorage get(@Nullable String bucketName) {
FirebaseStorage storage = instances.get(bucketName);
if (storage == null) {
storage = new FirebaseStorage(bucketName, app, authProvider);
instances.put(bucketName, storage);
}
return storage;
}

@VisibleForTesting
synchronized void clearInstancesForTesting() {
instances.clear();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,13 @@ class GetDownloadUrlTask implements Runnable {

this.storageRef = storageRef;
this.pendingResult = pendingResult;

FirebaseStorage storage = this.storageRef.getStorage();
sender =
new ExponentialBackoffSender(
this.storageRef.getApp(),
this.storageRef.getStorage().getMaxOperationRetryTimeMillis());
storage.getApp().getApplicationContext(),
storage.getAuthProvider(),
storage.getMaxOperationRetryTimeMillis());
}

private Uri extractDownloadUrl(JSONObject response) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,13 @@ class GetMetadataTask implements Runnable {

this.mStorageRef = storageRef;
this.mPendingResult = pendingResult;

FirebaseStorage storage = mStorageRef.getStorage();
mSender =
new ExponentialBackoffSender(
mStorageRef.getApp(), mStorageRef.getStorage().getMaxOperationRetryTimeMillis());
storage.getApp().getApplicationContext(),
storage.getAuthProvider(),
storage.getMaxDownloadRetryTimeMillis());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@

import android.support.annotation.Keep;
import android.support.annotation.RestrictTo;
import com.google.firebase.FirebaseApp;
import com.google.firebase.auth.internal.InternalAuthProvider;
import com.google.firebase.components.Component;
import com.google.firebase.components.ComponentRegistrar;
import com.google.firebase.components.Dependency;
import com.google.firebase.platforminfo.LibraryVersionComponent;
import java.util.Collections;
import java.util.Arrays;
import java.util.List;

/** @hide */
Expand All @@ -28,7 +31,15 @@
public class StorageRegistrar implements ComponentRegistrar {
@Override
public List<Component<?>> getComponents() {
return Collections.singletonList(
return Arrays.asList(
Component.builder(FirebaseStorageComponent.class)
.add(Dependency.required(FirebaseApp.class))
.add(Dependency.optionalProvider(InternalAuthProvider.class))
.factory(
c ->
new FirebaseStorageComponent(
c.get(FirebaseApp.class), c.getProvider(InternalAuthProvider.class)))
.build(),
LibraryVersionComponent.create("fire-gcs", BuildConfig.VERSION_NAME));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,13 @@ public class StreamDownloadTask extends StorageTask<StreamDownloadTask.TaskSnaps

/*package*/ StreamDownloadTask(@NonNull StorageReference storageRef) {
mStorageRef = storageRef;

FirebaseStorage storage = mStorageRef.getStorage();
mSender =
new ExponentialBackoffSender(
mStorageRef.getApp(), mStorageRef.getStorage().getMaxDownloadRetryTimeMillis());
storage.getApp().getApplicationContext(),
storage.getAuthProvider(),
storage.getMaxDownloadRetryTimeMillis());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,13 @@ public UpdateMetadataTask(
this.mStorageRef = storageRef;
this.mPendingResult = pendingResult;
mNewMetadata = newMetadata;

FirebaseStorage storage = mStorageRef.getStorage();
mSender =
new ExponentialBackoffSender(
mStorageRef.getApp(), mStorageRef.getStorage().getMaxOperationRetryTimeMillis());
storage.getApp().getApplicationContext(),
storage.getAuthProvider(),
storage.getMaxOperationRetryTimeMillis());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.google.android.gms.common.api.Status;
import com.google.android.gms.common.internal.Preconditions;
import com.google.firebase.annotations.PublicApi;
import com.google.firebase.auth.internal.InternalAuthProvider;
import com.google.firebase.storage.internal.AdaptiveStreamBuffer;
import com.google.firebase.storage.internal.ExponentialBackoffSender;
import com.google.firebase.storage.internal.Util;
Expand Down Expand Up @@ -61,6 +62,7 @@ public class UploadTask extends StorageTask<UploadTask.TaskSnapshot> {
private final AdaptiveStreamBuffer mStreamBuffer;
// Active, current mutable state.
private final AtomicLong mBytesUploaded = new AtomicLong(0);
@Nullable private final InternalAuthProvider mAuthProvider;
private int mCurrentChunkSize = PREFERRED_CHUNK_SIZE;
private ExponentialBackoffSender mSender;
private boolean mIsStreamOwned;
Expand All @@ -74,29 +76,42 @@ public class UploadTask extends StorageTask<UploadTask.TaskSnapshot> {
UploadTask(StorageReference targetRef, StorageMetadata metadata, byte[] bytes) {
Preconditions.checkNotNull(targetRef);
Preconditions.checkNotNull(bytes);

FirebaseStorage storage = targetRef.getStorage();

this.mTotalByteCount = bytes.length;
this.mStorageRef = targetRef;
this.mMetadata = metadata;
this.mAuthProvider = storage.getAuthProvider();
this.mUri = null;
this.mStreamBuffer =
new AdaptiveStreamBuffer(new ByteArrayInputStream(bytes), PREFERRED_CHUNK_SIZE);
this.mIsStreamOwned = true;

mSender =
new ExponentialBackoffSender(
mStorageRef.getApp(), mStorageRef.getStorage().getMaxUploadRetryTimeMillis());
storage.getApp().getApplicationContext(),
storage.getAuthProvider(),
storage.getMaxDownloadRetryTimeMillis());
}

UploadTask(
StorageReference targetRef, StorageMetadata metadata, Uri file, Uri existingUploadUri) {
Preconditions.checkNotNull(targetRef);
Preconditions.checkNotNull(file);

FirebaseStorage storage = targetRef.getStorage();

this.mStorageRef = targetRef;
this.mMetadata = metadata;
this.mAuthProvider = storage.getAuthProvider();
this.mUri = file;
InputStream inputStream = null;
mSender =
new ExponentialBackoffSender(
mStorageRef.getApp(), mStorageRef.getStorage().getMaxUploadRetryTimeMillis());
mStorageRef.getApp().getApplicationContext(),
mAuthProvider,
storage.getMaxUploadRetryTimeMillis());
long size = -1;
try {
ContentResolver resolver =
Expand Down Expand Up @@ -144,15 +159,20 @@ public class UploadTask extends StorageTask<UploadTask.TaskSnapshot> {
Preconditions.checkNotNull(targetRef);
Preconditions.checkNotNull(stream);

FirebaseStorage storage = targetRef.getStorage();

this.mTotalByteCount = -1;
this.mStorageRef = targetRef;
this.mMetadata = metadata;
this.mAuthProvider = storage.getAuthProvider();
this.mStreamBuffer = new AdaptiveStreamBuffer(stream, PREFERRED_CHUNK_SIZE);
this.mIsStreamOwned = false;
this.mUri = null;
mSender =
new ExponentialBackoffSender(
mStorageRef.getApp(), mStorageRef.getStorage().getMaxUploadRetryTimeMillis());
mStorageRef.getApp().getApplicationContext(),
mAuthProvider,
mStorageRef.getStorage().getMaxUploadRetryTimeMillis());
}

/** @return the target of the upload. */
Expand Down Expand Up @@ -448,8 +468,7 @@ private boolean isValidHttpResponseCode(int code) {

private boolean send(NetworkRequest request) {
request.performRequest(
Util.getCurrentAuthToken(mStorageRef.getApp()),
mStorageRef.getApp().getApplicationContext());
Util.getCurrentAuthToken(mAuthProvider), mStorageRef.getApp().getApplicationContext());
return processResultValid(request);
}

Expand Down Expand Up @@ -485,7 +504,7 @@ protected void onCanceled() {
@Override
public void run() {
finalCancelRequest.performRequest(
Util.getCurrentAuthToken(mStorageRef.getApp()),
Util.getCurrentAuthToken(mAuthProvider),
mStorageRef.getApp().getApplicationContext());
}
});
Expand Down
Loading