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