AbstractConversationWebViewClient.java revision 376294bbb5ded471ad577fdb492875a837021d08
1/*
2 * Copyright (C) 2013 Google Inc.
3 * Licensed to The Android Open Source Project.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package com.android.mail.ui;
19
20import android.content.ActivityNotFoundException;
21import android.content.Context;
22import android.content.Intent;
23import android.content.pm.ActivityInfo;
24import android.content.pm.PackageManager;
25import android.content.pm.ResolveInfo;
26import android.net.Uri;
27import android.provider.Browser;
28import android.webkit.WebView;
29import android.webkit.WebViewClient;
30
31import com.android.mail.providers.Account;
32import com.android.mail.providers.UIProvider;
33import com.android.mail.utils.LogTag;
34import com.android.mail.utils.LogUtils;
35import com.android.mail.utils.Utils;
36
37import java.util.List;
38
39/**
40 * Base implementation of a web view client for the conversation views.
41 * Handles proxying the view intent so that additional information can
42 * be sent with the intent when links are clicked.
43 */
44public class AbstractConversationWebViewClient extends WebViewClient {
45    private static final String LOG_TAG = LogTag.getLogTag();
46
47    private Account mAccount;
48    private final Context mContext;
49
50    public AbstractConversationWebViewClient(Context context, Account account) {
51        mAccount = account;
52        mContext = context;
53    }
54
55    public void setAccount(Account account) {
56        mAccount = account;
57    }
58
59    @Override
60    public boolean shouldOverrideUrlLoading(WebView view, String url) {
61        if (mContext == null) {
62            return false;
63        }
64
65        boolean result = false;
66        final Intent intent;
67        Uri uri = Uri.parse(url);
68        if (mAccount != null && !Utils.isEmpty(mAccount.viewIntentProxyUri)) {
69            intent = generateProxyIntent(uri);
70        } else {
71            intent = new Intent(Intent.ACTION_VIEW, uri);
72            intent.putExtra(Browser.EXTRA_APPLICATION_ID, mContext.getPackageName());
73        }
74
75        try {
76            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
77            mContext.startActivity(intent);
78            result = true;
79        } catch (ActivityNotFoundException ex) {
80            // If no application can handle the URL, assume that the
81            // caller can handle it.
82        }
83
84        return result;
85    }
86
87    private Intent generateProxyIntent(Uri uri) {
88        final Intent intent = new Intent(Intent.ACTION_VIEW, mAccount.viewIntentProxyUri);
89        intent.putExtra(UIProvider.ViewProxyExtras.EXTRA_ORIGINAL_URI, uri);
90        intent.putExtra(UIProvider.ViewProxyExtras.EXTRA_ACCOUNT, mAccount);
91
92        PackageManager manager = null;
93        // We need to catch the exception to make CanvasConversationHeaderView
94        // test pass.  Bug: http://b/issue?id=3470653.
95        try {
96            manager = mContext.getPackageManager();
97        } catch (UnsupportedOperationException e) {
98            LogUtils.e(LOG_TAG, e, "Error getting package manager");
99        }
100
101        if (manager != null) {
102            // Try and resolve the intent, to find an activity from this package
103            final List<ResolveInfo> resolvedActivities = manager.queryIntentActivities(
104                    intent, PackageManager.MATCH_DEFAULT_ONLY);
105
106            final String packageName = mContext.getPackageName();
107
108            // Now try and find one that came from this package, if one is not found, the UI
109            // provider must have specified an intent that is to be handled by a different apk.
110            // In that case, the class name will not be set on the intent, so the default
111            // intent resolution will be used.
112            for (ResolveInfo resolveInfo: resolvedActivities) {
113                final ActivityInfo activityInfo = resolveInfo.activityInfo;
114                if (packageName.equals(activityInfo.packageName)) {
115                    intent.setClassName(activityInfo.packageName, activityInfo.name);
116                    break;
117                }
118            }
119        }
120
121        return intent;
122    }
123}
124