1b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen/* 2b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen * Copyright (C) 2011 The Android Open Source Project 3b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen * 4b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen * Licensed under the Apache License, Version 2.0 (the "License"); 5b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen * you may not use this file except in compliance with the License. 6b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen * You may obtain a copy of the License at 7b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen * 8b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen * http://www.apache.org/licenses/LICENSE-2.0 9b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen * 10b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen * Unless required by applicable law or agreed to in writing, software 11b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen * distributed under the License is distributed on an "AS IS" BASIS, 12b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen * See the License for the specific language governing permissions and 14b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen * limitations under the License. 15b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen */ 16b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen 17b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenenpackage com.android.browser; 18b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen 19b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenenimport android.app.Activity; 20b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenenimport android.nfc.NdefMessage; 21b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenenimport android.nfc.NdefRecord; 22b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenenimport android.nfc.NfcAdapter; 23b5fd1162998b37b47aceff431992f484e422d03fNick Pellyimport android.nfc.NfcEvent; 246b6a3bf89303c7ef84910b28d59523d6441364beBen Murdochimport android.os.Handler; 256b6a3bf89303c7ef84910b28d59523d6441364beBen Murdochimport android.os.Message; 268e201435ca7796ed2f5a9dac67eef1a87a166dcfNick Pellyimport android.util.Log; 276b6a3bf89303c7ef84910b28d59523d6441364beBen Murdoch 286b6a3bf89303c7ef84910b28d59523d6441364beBen Murdochimport java.util.concurrent.CountDownLatch; 29b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen 30b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen/** This class implements sharing the URL of the currently 31b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen * shown browser page over NFC. Sharing is only active 32b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen * when the activity is in the foreground and resumed. 33b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen * Incognito tabs will not be shared over NFC. 34b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen */ 35b5fd1162998b37b47aceff431992f484e422d03fNick Pellypublic class NfcHandler implements NfcAdapter.CreateNdefMessageCallback { 368e201435ca7796ed2f5a9dac67eef1a87a166dcfNick Pelly static final String TAG = "BrowserNfcHandler"; 37b5fd1162998b37b47aceff431992f484e422d03fNick Pelly static final int GET_PRIVATE_BROWSING_STATE_MSG = 100; 38b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen 39b5fd1162998b37b47aceff431992f484e422d03fNick Pelly final Controller mController; 40eee2126458da109b65bbed42904c6c407872c3afMartijn Coenen 41b5fd1162998b37b47aceff431992f484e422d03fNick Pelly Tab mCurrentTab; 42b5fd1162998b37b47aceff431992f484e422d03fNick Pelly boolean mIsPrivate; 43b5fd1162998b37b47aceff431992f484e422d03fNick Pelly CountDownLatch mPrivateBrowsingSignal; 44b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen 45b5fd1162998b37b47aceff431992f484e422d03fNick Pelly public static void register(Activity activity, Controller controller) { 46b5fd1162998b37b47aceff431992f484e422d03fNick Pelly NfcAdapter adapter = NfcAdapter.getDefaultAdapter(activity.getApplicationContext()); 47b5fd1162998b37b47aceff431992f484e422d03fNick Pelly if (adapter == null) { 48b5fd1162998b37b47aceff431992f484e422d03fNick Pelly return; // NFC not available on this device 49b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen } 50015e1e3145ac284aa5879c973f9d2381c8cd48feBen Murdoch NfcHandler handler = null; 51015e1e3145ac284aa5879c973f9d2381c8cd48feBen Murdoch if (controller != null) { 52015e1e3145ac284aa5879c973f9d2381c8cd48feBen Murdoch handler = new NfcHandler(controller); 53015e1e3145ac284aa5879c973f9d2381c8cd48feBen Murdoch } 54015e1e3145ac284aa5879c973f9d2381c8cd48feBen Murdoch 55015e1e3145ac284aa5879c973f9d2381c8cd48feBen Murdoch adapter.setNdefPushMessageCallback(handler, activity); 56015e1e3145ac284aa5879c973f9d2381c8cd48feBen Murdoch } 57015e1e3145ac284aa5879c973f9d2381c8cd48feBen Murdoch 58015e1e3145ac284aa5879c973f9d2381c8cd48feBen Murdoch public static void unregister(Activity activity) { 59015e1e3145ac284aa5879c973f9d2381c8cd48feBen Murdoch // Passing a null controller causes us to disable 60015e1e3145ac284aa5879c973f9d2381c8cd48feBen Murdoch // the callback and release the ref to out activity. 61015e1e3145ac284aa5879c973f9d2381c8cd48feBen Murdoch register(activity, null); 62b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen } 63b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen 64b5fd1162998b37b47aceff431992f484e422d03fNick Pelly public NfcHandler(Controller controller) { 65b5fd1162998b37b47aceff431992f484e422d03fNick Pelly mController = controller; 66b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen } 67b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen 68b5fd1162998b37b47aceff431992f484e422d03fNick Pelly final Handler mHandler = new Handler() { 69b5fd1162998b37b47aceff431992f484e422d03fNick Pelly @Override 70b5fd1162998b37b47aceff431992f484e422d03fNick Pelly public void handleMessage(Message msg) { 71b5fd1162998b37b47aceff431992f484e422d03fNick Pelly if (msg.what == GET_PRIVATE_BROWSING_STATE_MSG) { 72b5fd1162998b37b47aceff431992f484e422d03fNick Pelly mIsPrivate = mCurrentTab.getWebView().isPrivateBrowsingEnabled(); 73b5fd1162998b37b47aceff431992f484e422d03fNick Pelly mPrivateBrowsingSignal.countDown(); 74b5fd1162998b37b47aceff431992f484e422d03fNick Pelly } 75b5fd1162998b37b47aceff431992f484e422d03fNick Pelly } 76b5fd1162998b37b47aceff431992f484e422d03fNick Pelly }; 77b5fd1162998b37b47aceff431992f484e422d03fNick Pelly 78b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen @Override 79b5fd1162998b37b47aceff431992f484e422d03fNick Pelly public NdefMessage createNdefMessage(NfcEvent event) { 806b6a3bf89303c7ef84910b28d59523d6441364beBen Murdoch mCurrentTab = mController.getCurrentTab(); 816b6a3bf89303c7ef84910b28d59523d6441364beBen Murdoch if ((mCurrentTab != null) && (mCurrentTab.getWebView() != null)) { 826b6a3bf89303c7ef84910b28d59523d6441364beBen Murdoch // We can only read the WebView state on the UI thread, so post 836b6a3bf89303c7ef84910b28d59523d6441364beBen Murdoch // a message and wait. 846b6a3bf89303c7ef84910b28d59523d6441364beBen Murdoch mPrivateBrowsingSignal = new CountDownLatch(1); 856b6a3bf89303c7ef84910b28d59523d6441364beBen Murdoch mHandler.sendMessage(mHandler.obtainMessage(GET_PRIVATE_BROWSING_STATE_MSG)); 866b6a3bf89303c7ef84910b28d59523d6441364beBen Murdoch try { 876b6a3bf89303c7ef84910b28d59523d6441364beBen Murdoch mPrivateBrowsingSignal.await(); 886b6a3bf89303c7ef84910b28d59523d6441364beBen Murdoch } catch (InterruptedException e) { 896b6a3bf89303c7ef84910b28d59523d6441364beBen Murdoch return null; 906b6a3bf89303c7ef84910b28d59523d6441364beBen Murdoch } 916b6a3bf89303c7ef84910b28d59523d6441364beBen Murdoch } 926b6a3bf89303c7ef84910b28d59523d6441364beBen Murdoch 936b6a3bf89303c7ef84910b28d59523d6441364beBen Murdoch if ((mCurrentTab == null) || mIsPrivate) { 946b6a3bf89303c7ef84910b28d59523d6441364beBen Murdoch return null; 956b6a3bf89303c7ef84910b28d59523d6441364beBen Murdoch } 966b6a3bf89303c7ef84910b28d59523d6441364beBen Murdoch 976b6a3bf89303c7ef84910b28d59523d6441364beBen Murdoch String currentUrl = mCurrentTab.getUrl(); 986b6a3bf89303c7ef84910b28d59523d6441364beBen Murdoch if (currentUrl != null) { 998e201435ca7796ed2f5a9dac67eef1a87a166dcfNick Pelly try { 1008e201435ca7796ed2f5a9dac67eef1a87a166dcfNick Pelly return new NdefMessage(NdefRecord.createUri(currentUrl)); 1018e201435ca7796ed2f5a9dac67eef1a87a166dcfNick Pelly } catch (IllegalArgumentException e) { 1028e201435ca7796ed2f5a9dac67eef1a87a166dcfNick Pelly Log.e(TAG, "IllegalArgumentException creating URI NdefRecord", e); 1038e201435ca7796ed2f5a9dac67eef1a87a166dcfNick Pelly return null; 1048e201435ca7796ed2f5a9dac67eef1a87a166dcfNick Pelly } 1056b6a3bf89303c7ef84910b28d59523d6441364beBen Murdoch } else { 106b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen return null; 107b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen } 108b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen } 109b2f93556ac91fe06eb8f6acab05b6a6d1b2fdbe1Martijn Coenen} 110