1c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook/*
2c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook * Copyright (C) 2011 Google Inc.
3c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook * Licensed to The Android Open Source Project.
4c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook *
5c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook * Licensed under the Apache License, Version 2.0 (the "License");
6c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook * you may not use this file except in compliance with the License.
7c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook * You may obtain a copy of the License at
8c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook *
9c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook *      http://www.apache.org/licenses/LICENSE-2.0
10c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook *
11c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook * Unless required by applicable law or agreed to in writing, software
12c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook * distributed under the License is distributed on an "AS IS" BASIS,
13c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook * See the License for the specific language governing permissions and
15c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook * limitations under the License.
16c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook */
17c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
18c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookpackage com.android.mailcommon;
19c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
20c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookimport android.app.Activity;
21c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookimport android.content.ClipData;
22c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookimport android.content.ClipboardManager;
23c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookimport android.content.Context;
24c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookimport android.content.Intent;
25c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookimport android.content.pm.PackageManager;
26c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookimport android.content.pm.ResolveInfo;
27c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookimport android.net.Uri;
28c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookimport android.provider.ContactsContract;
29c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookimport android.view.ContextMenu;
30c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookimport android.view.ContextMenu.ContextMenuInfo;
31c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookimport android.view.LayoutInflater;
32c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookimport android.view.MenuInflater;
33c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookimport android.view.MenuItem;
34c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookimport android.view.View;
35c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookimport android.view.View.OnCreateContextMenuListener;
36c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookimport android.webkit.WebView;
37c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookimport android.widget.TextView;
38c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
39c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookimport java.io.UnsupportedEncodingException;
40c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookimport java.net.URLDecoder;
41c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookimport java.net.URLEncoder;
42c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrookimport java.nio.charset.Charset;
43c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
44c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook/**
45c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook * <p>Handles display and behavior of the context menu for known actionable content in WebViews.
46c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook * Requires an Activity to bind to for Context resolution and to start other activites.</p>
47c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook * <br>
48c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook * <p>Activity/Fragment clients must forward the 'onContextItemSelected' method.</p>
49c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook * <br>
50c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook * Dependencies:
51c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook * <ul>
52c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook * <li>res/menu/webview_context_menu.xml</li>
53c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook * <li>res/values/webview_context_menu_strings.xml</li>
54c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook * </ul>
55c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook */
56c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrookpublic abstract class WebViewContextMenu implements OnCreateContextMenuListener,
57c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook        MenuItem.OnMenuItemClickListener {
58c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook
59c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    private Activity mActivity;
60c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
61c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    protected static enum MenuType {
62c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        OPEN_MENU,
63c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        COPY_LINK_MENU,
64c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        SHARE_LINK_MENU,
65c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        DIAL_MENU,
66c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        SMS_MENU,
67c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        ADD_CONTACT_MENU,
68c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        COPY_PHONE_MENU,
69c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        EMAIL_CONTACT_MENU,
70c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        COPY_MAIL_MENU,
71c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        MAP_MENU,
72c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        COPY_GEO_MENU,
73c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    }
74c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
75c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    protected static enum MenuGroupType {
76c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        PHONE_GROUP,
77c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        EMAIL_GROUP,
78c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        GEO_GROUP,
79c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        ANCHOR_GROUP,
80c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    }
81c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
82c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    public WebViewContextMenu(Activity host) {
83c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        this.mActivity = host;
84c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    }
85c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
86c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    // For our copy menu items.
87c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    private class Copy implements MenuItem.OnMenuItemClickListener {
88c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        private final CharSequence mText;
89c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
90c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        public Copy(CharSequence text) {
91c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook            mText = text;
92c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        }
93c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
94c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook        @Override
95c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        public boolean onMenuItemClick(MenuItem item) {
96c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook            copy(mText);
97c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook            return true;
98c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        }
99c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    }
100c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
101c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook    // For our share menu items.
102c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook    private class Share implements MenuItem.OnMenuItemClickListener {
103c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook        private final String mUri;
104c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook
105c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook        public Share(String text) {
106c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook            mUri = text;
107c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook        }
108c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook
109c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook        @Override
110c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook        public boolean onMenuItemClick(MenuItem item) {
111c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook            shareLink(mUri);
112c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook            return true;
113c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook        }
114c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook    }
115c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook
116c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    private boolean showShareLinkMenuItem() {
117c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        PackageManager pm = mActivity.getPackageManager();
118c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        Intent send = new Intent(Intent.ACTION_SEND);
119c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        send.setType("text/plain");
120c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        ResolveInfo ri = pm.resolveActivity(send, PackageManager.MATCH_DEFAULT_ONLY);
121c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        return ri != null;
122c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    }
123c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
124c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    private void shareLink(String url) {
125c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        Intent send = new Intent(Intent.ACTION_SEND);
126c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        send.setType("text/plain");
127c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        send.putExtra(Intent.EXTRA_TEXT, url);
128c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
129c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        try {
130c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook            mActivity.startActivity(Intent.createChooser(send, mActivity.getText(
131c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                    getChooserTitleStringResIdForMenuType(MenuType.SHARE_LINK_MENU))));
132c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        } catch(android.content.ActivityNotFoundException ex) {
133c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook            // if no app handles it, do nothing
134c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        }
135c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    }
136c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
137c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    private void copy(CharSequence text) {
138c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        ClipboardManager clipboard =
139c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                (ClipboardManager) mActivity.getSystemService(Context.CLIPBOARD_SERVICE);
140c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        clipboard.setPrimaryClip(ClipData.newPlainText(null, text));
141c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    }
142c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
143c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    public void onCreateContextMenu(ContextMenu menu, View v,
144c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook            ContextMenuInfo info) {
145c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        // FIXME: This is copied over almost directly from BrowserActivity.
146c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        // Would like to find a way to combine the two (Bug 1251210).
147c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
148c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        WebView webview = (WebView) v;
149c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        WebView.HitTestResult result = webview.getHitTestResult();
150c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        if (result == null) {
151c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook            return;
152c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        }
153c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
154c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        int type = result.getType();
155c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        switch (type) {
156c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook            case WebView.HitTestResult.UNKNOWN_TYPE:
157c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook            case WebView.HitTestResult.EDIT_TEXT_TYPE:
158c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                return;
159c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook            default:
160c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                break;
161c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        }
162c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
163c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        // Note, http://b/issue?id=1106666 is requesting that
164c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        // an inflated menu can be used again. This is not available
165c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        // yet, so inflate each time (yuk!)
166c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        MenuInflater inflater = mActivity.getMenuInflater();
167c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        // Also, we are copying the menu file from browser until
168c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        // 1251210 is fixed.
169c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        inflater.inflate(getMenuResourceId(), menu);
170c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
171c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook        // Initially make set the menu item handler this WebViewContextMenu, which will default to
172c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook        // calling the non-abstract subclass's implementation.
173c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook        for (int i = 0; i < menu.size(); i++) {
174c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook            final MenuItem menuItem = menu.getItem(i);
175c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook            menuItem.setOnMenuItemClickListener(this);
176c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook        }
177c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook
178c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook
179c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        // Show the correct menu group
180c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        String extra = result.getExtra();
181c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        menu.setGroupVisible(getMenuGroupResId(MenuGroupType.PHONE_GROUP),
182c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                type == WebView.HitTestResult.PHONE_TYPE);
183c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        menu.setGroupVisible(getMenuGroupResId(MenuGroupType.EMAIL_GROUP),
184c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                type == WebView.HitTestResult.EMAIL_TYPE);
185c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        menu.setGroupVisible(getMenuGroupResId(MenuGroupType.GEO_GROUP),
186c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                type == WebView.HitTestResult.GEO_TYPE);
187c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        menu.setGroupVisible(getMenuGroupResId(MenuGroupType.ANCHOR_GROUP),
188c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                type == WebView.HitTestResult.SRC_ANCHOR_TYPE
189c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                || type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE);
190c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
191c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        // Setup custom handling depending on the type
192c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        switch (type) {
193c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook            case WebView.HitTestResult.PHONE_TYPE:
194c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                String decodedPhoneExtra;
195c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                try {
196c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                    decodedPhoneExtra = URLDecoder.decode(extra, Charset.defaultCharset().name());
197c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                }
198c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                catch (UnsupportedEncodingException ignore) {
199c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                    // Should never happen; default charset is UTF-8
200c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                    decodedPhoneExtra = extra;
201c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                }
202c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
203c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                menu.setHeaderTitle(decodedPhoneExtra);
204c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                // Dial
205c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                final MenuItem dialMenuItem =
206c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                        menu.findItem(getMenuResIdForMenuType(MenuType.DIAL_MENU));
207c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                // remove the on click listener
208c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                dialMenuItem.setOnMenuItemClickListener(null);
209c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                dialMenuItem.setIntent(new Intent(Intent.ACTION_VIEW,
210c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                        Uri.parse(WebView.SCHEME_TEL + extra)));
211c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
212c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                // Send SMS
213c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                final MenuItem sendSmsMenuItem =
214c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                        menu.findItem(getMenuResIdForMenuType(MenuType.SMS_MENU));
215c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                // remove the on click listener
216c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                sendSmsMenuItem.setOnMenuItemClickListener(null);
217c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                sendSmsMenuItem.setIntent(new Intent(Intent.ACTION_SENDTO,
218c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                        Uri.parse("smsto:" + extra)));
219c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
220c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                // Add to contacts
221c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                final Intent addIntent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
222c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                addIntent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
223c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
224c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                addIntent.putExtra(ContactsContract.Intents.Insert.PHONE, decodedPhoneExtra);
225c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                final MenuItem addToContactsMenuItem =
226c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                        menu.findItem(getMenuResIdForMenuType(MenuType.ADD_CONTACT_MENU));
227c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                // remove the on click listener
228c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                addToContactsMenuItem.setOnMenuItemClickListener(null);
229c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                addToContactsMenuItem.setIntent(addIntent);
230c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
231c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                // Copy
232c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                menu.findItem(getMenuResIdForMenuType(MenuType.COPY_PHONE_MENU)).
233c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                        setOnMenuItemClickListener(new Copy(extra));
234c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                break;
235c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
236c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook            case WebView.HitTestResult.EMAIL_TYPE:
237c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                menu.setHeaderTitle(extra);
238c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                menu.findItem(getMenuResIdForMenuType(MenuType.EMAIL_CONTACT_MENU)).setIntent(
239c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                        new Intent(Intent.ACTION_VIEW, Uri
240c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                                .parse(WebView.SCHEME_MAILTO + extra)));
241c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                menu.findItem(getMenuResIdForMenuType(MenuType.COPY_MAIL_MENU)).
242c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                        setOnMenuItemClickListener(new Copy(extra));
243c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                break;
244c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
245c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook            case WebView.HitTestResult.GEO_TYPE:
246c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                menu.setHeaderTitle(extra);
247c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                String geoExtra = "";
248c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                try {
249c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                    geoExtra = URLEncoder.encode(extra, Charset.defaultCharset().name());
250c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                }
251c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                catch (UnsupportedEncodingException ignore) {
252c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                    // Should never happen; default charset is UTF-8
253c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                }
254c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                final MenuItem viewMapMenuItem =
255c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                        menu.findItem(getMenuResIdForMenuType(MenuType.MAP_MENU));
256c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                // remove the on click listener
257c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                viewMapMenuItem.setOnMenuItemClickListener(null);
258c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                viewMapMenuItem.setIntent(new Intent(Intent.ACTION_VIEW,
259c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                        Uri.parse(WebView.SCHEME_GEO + geoExtra)));
260c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                menu.findItem(getMenuResIdForMenuType(MenuType.COPY_GEO_MENU)).
261c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                        setOnMenuItemClickListener(new Copy(extra));
262c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                break;
263c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
264c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook            case WebView.HitTestResult.SRC_ANCHOR_TYPE:
265c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook            case WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE:
266c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                // FIXME: Make this look like the normal menu header
267c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                // We cannot use the normal menu header because we need to
268c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                // edit the ContextMenu after it has been created.
269c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                final TextView titleView = (TextView) LayoutInflater.from(mActivity)
270c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                        .inflate(getTitleViewLayoutResId(MenuType.SHARE_LINK_MENU), null);
271c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                menu.setHeaderView(titleView);
272c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
273c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                menu.findItem(getMenuResIdForMenuType(MenuType.SHARE_LINK_MENU)).setVisible(
274c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                        showShareLinkMenuItem());
275c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
276c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                // The documentation for WebView indicates that if the HitTestResult is
277c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                // SRC_ANCHOR_TYPE or the url would be specified in the extra.  We don't need to
278c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                // call requestFocusNodeHref().  If we wanted to handle UNKNOWN HitTestResults, we
279c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                // would.  With this knowledge, we can just set the title
280c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                titleView.setText(extra);
281c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
282c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                menu.findItem(getMenuResIdForMenuType(MenuType.COPY_LINK_MENU)).
283c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                        setOnMenuItemClickListener(new Copy(extra));
284c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook
285c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                final MenuItem openLinkMenuItem =
286c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                        menu.findItem(getMenuResIdForMenuType(MenuType.OPEN_MENU));
287c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                // remove the on click listener
288c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                openLinkMenuItem.setOnMenuItemClickListener(null);
289c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                openLinkMenuItem.setIntent(new Intent(Intent.ACTION_VIEW, Uri.parse(extra)));
290c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook
291c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                menu.findItem(getMenuResIdForMenuType(MenuType.SHARE_LINK_MENU)).
292c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook                        setOnMenuItemClickListener(new Share(extra));
293c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                break;
294c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook            default:
295c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook                break;
296c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook        }
297c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    }
298c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
299c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook    @Override
300c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook    public boolean onMenuItemClick(MenuItem item) {
301c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook        return onMenuItemSelected(item);
302c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook    }
303c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook
304c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    /**
305c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook     * Returns the menu type from the given resource id
306c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook     * @param menuResId resource id of the menu
307c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook     * @return MenuType for the specified menu resource id
308c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook     */
309c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    abstract protected MenuType getMenuTypeFromResId(int menuResId);
310c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
311c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    /**
312c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook     * Returns the menu resource id for the specified menu type
313c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook     * @param menuType type of the specified menu
314c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook     * @return menu resource id
315c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook     */
316c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    abstract protected int getMenuResIdForMenuType(MenuType menuType);
317c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
318c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    /**
319c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook     * Returns the resource id of the string to be used when showing a chooser for a menu
320c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook     * @param menuType type of the specified menu
321c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook     * @return string resource id
322c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook     */
323c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    abstract protected int getChooserTitleStringResIdForMenuType(MenuType menuType);
324c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
325c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    /**
326c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook     * Returns the resource id of the layout to be used for the title of the specified menu
327c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook     * @param menuType type of the specified menu
328c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook     * @return layout resource id
329c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook     */
330c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    abstract protected int getTitleViewLayoutResId(MenuType menuType);
331c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
332c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    /**
333c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook     * Returns the menu group resource id for the specified menu group type.
334c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook     * @param menuGroupType menu group type
335c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook     * @return menu group resource id
336c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook     */
337c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    abstract protected int getMenuGroupResId(MenuGroupType menuGroupType);
338c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook
339c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    /**
340c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook     * Returns the resource id for the web view context menu
341c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook     */
342c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook    abstract protected int getMenuResourceId();
343c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook
344c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook
345c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook    /**
346c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook     * Called when a menu item is not handled by the context menu.
347c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook     */
348c25b5d09c5cbc9c88c0e7ee9d7899031a2d5b068Paul Westbrook    abstract protected boolean onMenuItemSelected(MenuItem menuItem);
349c705a496e5e9c89d75db71b98cef6fe17c6da45cPaul Westbrook}
350