1 // Copyright 2019 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.chrome.browser.customtabs;
6 
7 import static org.chromium.chrome.browser.dependency_injection.ChromeCommonQualifiers.APP_CONTEXT;
8 
9 import android.content.Context;
10 import android.graphics.Bitmap;
11 import android.net.Uri;
12 import android.os.Bundle;
13 
14 import androidx.annotation.WorkerThread;
15 import androidx.browser.customtabs.CustomTabsService;
16 import androidx.browser.customtabs.CustomTabsSessionToken;
17 
18 import org.chromium.base.FileUtils;
19 import org.chromium.base.Log;
20 import org.chromium.chrome.browser.browserservices.ui.splashscreen.trustedwebactivity.SplashImageHolder;
21 
22 import javax.inject.Inject;
23 import javax.inject.Named;
24 import javax.inject.Singleton;
25 
26 import dagger.Lazy;
27 
28 /**
29  * Processes the files received via Custom Tab connection from client apps.
30  */
31 @Singleton
32 public class CustomTabsClientFileProcessor {
33 
34     private static final String TAG = "CustomTabFiles";
35 
36     private final Context mContext;
37     private final Lazy<SplashImageHolder> mTwaSplashImageHolder;
38     private boolean mTwaSplashImageHolderCreated;
39 
40     @Inject
CustomTabsClientFileProcessor(@amedAPP_CONTEXT) Context context, Lazy<SplashImageHolder> twaSplashImageHolder)41     public CustomTabsClientFileProcessor(@Named(APP_CONTEXT) Context context,
42             Lazy<SplashImageHolder> twaSplashImageHolder) {
43         mTwaSplashImageHolder = twaSplashImageHolder;
44         mContext = context;
45     }
46 
47     /**
48      * Processes the file located at given URI.
49      * @return {@code true} if successful.
50      */
51     @WorkerThread
processFile(CustomTabsSessionToken session, Uri uri, int purpose, Bundle extras)52     public boolean processFile(CustomTabsSessionToken session, Uri uri,
53             int purpose, Bundle extras) {
54         if (uri == null) {
55             Log.w(TAG, "Received a null uri");
56             return false;
57         }
58         switch (purpose) {
59             case CustomTabsService.FILE_PURPOSE_TRUSTED_WEB_ACTIVITY_SPLASH_IMAGE:
60                 return receiveTwaSplashImage(session, uri);
61         }
62         Log.w(TAG, "Unknown FilePurpose " + purpose);
63         return false;
64     }
65 
receiveTwaSplashImage(CustomTabsSessionToken sessionToken, Uri uri)66     private boolean receiveTwaSplashImage(CustomTabsSessionToken sessionToken, Uri uri) {
67         Bitmap bitmap = FileUtils.queryBitmapFromContentProvider(mContext, uri);
68         if (bitmap == null) return false;
69 
70         mTwaSplashImageHolder.get().putImage(sessionToken, bitmap);
71         mTwaSplashImageHolderCreated = true;
72         return true;
73     }
74 
75     /**
76      * Cleans up files associated with the session that has been disconnected.
77      */
onSessionDisconnected(CustomTabsSessionToken session)78     public void onSessionDisconnected(CustomTabsSessionToken session) {
79         if (mTwaSplashImageHolderCreated) {
80             // If the image still hasn't been claimed, delete it.
81             mTwaSplashImageHolder.get().takeImage(session);
82         }
83     }
84 }
85