Browser: add to support my navigation feature

When launch browser, display my navigation page.

We show a gridview in navigation page, user can
select to add website items to navigation page,
delete/edit existing website items, when tap a
item, browser will load the saved website.

CRs-Fixed: 530979

Change-Id: I9618b8df15f651ccee09b80de8626bacfb6fda12
diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java
index 729e79e..b1df847 100644
--- a/src/com/android/browser/Controller.java
+++ b/src/com/android/browser/Controller.java
@@ -38,11 +38,13 @@
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteException;
 import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.net.Uri;
 import android.net.http.SslError;
+import android.net.WebAddress;
 import android.net.wifi.WifiManager;
 import android.os.AsyncTask;
 import android.os.Bundle;
@@ -91,6 +93,8 @@
 import com.android.browser.UI.ComboViews;
 import com.android.browser.provider.BrowserProvider2.Thumbnails;
 import com.android.browser.provider.SnapshotProvider.Snapshots;
+import com.android.browser.mynavigation.AddMyNavigationPage;
+import com.android.browser.mynavigation.MyNavigationUtil;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -120,6 +124,8 @@
     private static final String PROP_NETSWITCH = "persist.env.browser.netswitch";
     private static final String INTENT_WIFI_SELECTION_DATA_CONNECTION =
             "android.net.wifi.cmcc.WIFI_SELECTION_DATA_CONNECTION";
+    private static final String OFFLINE_PAGE =
+            "content://com.android.browser.mynavigation/websites";
 
     // public message ids
     public final static int LOAD_URL = 1001;
@@ -142,6 +148,7 @@
     final static int FILE_SELECTED = 4;
     final static int AUTOFILL_SETUP = 5;
     final static int VOICE_RESULT = 6;
+    final static int MY_NAVIGATION = 7;
 
     private final static int WAKELOCK_TIMEOUT = 5 * 60 * 1000; // 5 minutes
 
@@ -231,6 +238,8 @@
     private boolean mBlockEvents;
 
     private String mVoiceResult;
+    private boolean mUpdateMyNavThumbnail;
+    private String mUpdateMyNavThumbnailUrl;
 
     public Controller(Activity browser) {
         mActivity = browser;
@@ -323,10 +332,23 @@
                 // If the intent is ACTION_VIEW and data is not null, the Browser is
                 // invoked to view the content by another application. In this case,
                 // the tab will be close when exit.
-                UrlData urlData = IntentHandler.getUrlDataFromIntent(intent);
+                UrlData urlData = null;
+                if (intent.getData() != null
+                        && Intent.ACTION_VIEW.equals(intent.getAction())
+                        && intent.getData().toString().startsWith("content://")) {
+                    urlData = new UrlData(intent.getData().toString());
+                } else {
+                    urlData = IntentHandler.getUrlDataFromIntent(intent);
+                }
+
                 Tab t = null;
                 if (urlData.isEmpty()) {
-                    t = openTabToHomePage();
+                    if (SystemProperties.get("persist.env.c.browser.resource", "default").equals(
+                            "cmcc")) {
+                        t = openTab(OFFLINE_PAGE, false, true, true);
+                    } else {
+                        t = openTabToHomePage();
+                    }
                 } else {
                     t = openTab(urlData);
                 }
@@ -1256,6 +1278,8 @@
                 if (Intent.ACTION_VIEW.equals(intent.getAction())) {
                     Tab t = getCurrentTab();
                     Uri uri = intent.getData();
+                    mUpdateMyNavThumbnail = true;
+                    mUpdateMyNavThumbnailUrl = uri.toString();
                     loadUrl(t, uri.toString());
                 } else if (intent.hasExtra(ComboViewActivity.EXTRA_OPEN_ALL)) {
                     String[] urls = intent.getStringArrayExtra(
@@ -1289,6 +1313,18 @@
                     }
                 }
                 break;
+
+             case MY_NAVIGATION:
+                if (intent == null || resultCode != Activity.RESULT_OK) {
+                    break;
+                }
+
+                if (intent.getBooleanExtra("need_refresh", false) &&
+                        getCurrentTopWebView() != null) {
+                    getCurrentTopWebView().reload();
+                }
+                break;
+
             default:
                 break;
         }
@@ -1385,6 +1421,7 @@
 
         // Show the correct menu group
         final String extra = result.getExtra();
+        final String navigationUrl = MyNavigationUtil.getMyNavigationUrl(extra);
         if (extra == null) return;
         menu.setGroupVisible(R.id.PHONE_MENU,
                 type == WebView.HitTestResult.PHONE_TYPE);
@@ -1392,12 +1429,30 @@
                 type == WebView.HitTestResult.EMAIL_TYPE);
         menu.setGroupVisible(R.id.GEO_MENU,
                 type == WebView.HitTestResult.GEO_TYPE);
-        menu.setGroupVisible(R.id.IMAGE_MENU,
-                type == WebView.HitTestResult.IMAGE_TYPE
-                || type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE);
-        menu.setGroupVisible(R.id.ANCHOR_MENU,
-                type == WebView.HitTestResult.SRC_ANCHOR_TYPE
-                || type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE);
+
+        String itemUrl = null;
+        String url = webview.getOriginalUrl();
+        if (url != null && url.equalsIgnoreCase(MyNavigationUtil.MY_NAVIGATION)) {
+            itemUrl = Uri.decode(navigationUrl);
+            if (itemUrl != null && !MyNavigationUtil.isDefaultMyNavigation(itemUrl)) {
+                menu.setGroupVisible(R.id.MY_NAVIGATION_MENU,
+                        type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE);
+            } else {
+                menu.setGroupVisible(R.id.MY_NAVIGATION_MENU, false);
+            }
+            menu.setGroupVisible(R.id.IMAGE_MENU, false);
+            menu.setGroupVisible(R.id.ANCHOR_MENU, false);
+        } else {
+            menu.setGroupVisible(R.id.MY_NAVIGATION_MENU, false);
+
+            menu.setGroupVisible(R.id.IMAGE_MENU,
+                    type == WebView.HitTestResult.IMAGE_TYPE
+                            || type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE);
+            menu.setGroupVisible(R.id.ANCHOR_MENU,
+                    type == WebView.HitTestResult.SRC_ANCHOR_TYPE
+                            || type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE);
+        }
+
         boolean hitText = type == WebView.HitTestResult.SRC_ANCHOR_TYPE
                 || type == WebView.HitTestResult.PHONE_TYPE
                 || type == WebView.HitTestResult.EMAIL_TYPE
@@ -1487,6 +1542,43 @@
                                 });
                     }
                 }
+                if (url != null && url.equalsIgnoreCase(MyNavigationUtil.MY_NAVIGATION)) {
+                    menu.setHeaderTitle(navigationUrl);
+                    menu.findItem(R.id.open_newtab_context_menu_id).setVisible(false);
+
+                    if (itemUrl != null) {
+                        if (!MyNavigationUtil.isDefaultMyNavigation(itemUrl)) {
+                            menu.findItem(R.id.edit_my_navigation_context_menu_id)
+                                    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
+                                        @Override
+                                        public boolean onMenuItemClick(MenuItem item) {
+                                            final Intent intent = new Intent(Controller.this
+                                                    .getContext(),
+                                                    AddMyNavigationPage.class);
+                                            Bundle bundle = new Bundle();
+                                            String url = Uri.decode(navigationUrl);
+                                            bundle.putBoolean("isAdding", false);
+                                            bundle.putString("url", url);
+                                            bundle.putString("name", getNameFromUrl(url));
+                                            intent.putExtra("websites", bundle);
+                                            mActivity.startActivityForResult(intent, MY_NAVIGATION);
+                                            return false;
+                                        }
+                                    });
+                            menu.findItem(R.id.delete_my_navigation_context_menu_id)
+                                    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
+                                        @Override
+                                        public boolean onMenuItemClick(MenuItem item) {
+                                            showMyNavigationDeleteDialog(Uri.decode(navigationUrl));
+                                            return false;
+                                        }
+                                    });
+                        }
+                    } else {
+                        Log.e(LOGTAG, "mynavigation onCreateContextMenu itemUrl is null!");
+                    }
+                }
+
                 if (type == WebView.HitTestResult.SRC_ANCHOR_TYPE) {
                     break;
                 }
@@ -1531,6 +1623,152 @@
         mUi.onContextMenuCreated(menu);
     }
 
+    public void startAddMyNavigation(String url) {
+        final Intent intent = new Intent(Controller.this.getContext(), AddMyNavigationPage.class);
+        Bundle bundle = new Bundle();
+        bundle.putBoolean("isAdding", true);
+        bundle.putString("url", url);
+        bundle.putString("name", getNameFromUrl(url));
+        intent.putExtra("websites", bundle);
+        mActivity.startActivityForResult(intent, MY_NAVIGATION);
+    }
+
+    private void showMyNavigationDeleteDialog(final String itemUrl) {
+        new AlertDialog.Builder(this.getContext())
+                .setTitle(R.string.my_navigation_delete_label)
+                .setIcon(android.R.drawable.ic_dialog_alert)
+                .setMessage(R.string.my_navigation_delete_msg)
+                .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int whichButton) {
+                        deleteMyNavigationItem(itemUrl);
+                    }
+                })
+                .setNegativeButton(R.string.cancel, null)
+                .show();
+    }
+
+    private void deleteMyNavigationItem(final String itemUrl) {
+        ContentResolver cr = this.getContext().getContentResolver();
+        Cursor cursor = null;
+
+        try {
+            cursor = cr.query(MyNavigationUtil.MY_NAVIGATION_URI,
+                    new String[] {
+                        MyNavigationUtil.ID
+                    }, "url = ?", new String[] {
+                        itemUrl
+                    }, null);
+            if (null != cursor && cursor.moveToFirst()) {
+                Uri uri = ContentUris.withAppendedId(MyNavigationUtil.MY_NAVIGATION_URI,
+                        cursor.getLong(0));
+
+                ContentValues values = new ContentValues();
+                values.put(MyNavigationUtil.TITLE, "");
+                values.put(MyNavigationUtil.URL, "ae://" + cursor.getLong(0) + "add-fav");
+                values.put(MyNavigationUtil.WEBSITE, 0 + "");
+                ByteArrayOutputStream os = new ByteArrayOutputStream();
+                Bitmap bm = BitmapFactory.decodeResource(this.getContext().getResources(),
+                        R.raw.my_navigation_add);
+                bm.compress(Bitmap.CompressFormat.PNG, 100, os);
+                values.put(MyNavigationUtil.THUMBNAIL, os.toByteArray());
+                Log.d(LOGTAG, "deleteMyNavigationItem uri is : " + uri);
+                cr.update(uri, values, null, null);
+            } else {
+                Log.e(LOGTAG, "deleteMyNavigationItem the item does not exist!");
+            }
+        } catch (IllegalStateException e) {
+            Log.e(LOGTAG, "deleteMyNavigationItem", e);
+        } finally {
+            if (null != cursor) {
+                cursor.close();
+            }
+        }
+
+        if (getCurrentTopWebView() != null) {
+            getCurrentTopWebView().reload();
+        }
+    }
+
+    private String getNameFromUrl(String itemUrl) {
+        ContentResolver cr = this.getContext().getContentResolver();
+        Cursor cursor = null;
+        String name = null;
+
+        try {
+            cursor = cr.query(MyNavigationUtil.MY_NAVIGATION_URI,
+                    new String[] {
+                        MyNavigationUtil.TITLE
+                    }, "url = ?", new String[] {
+                        itemUrl
+                    }, null);
+            if (null != cursor && cursor.moveToFirst()) {
+                name = cursor.getString(0);
+            } else {
+                Log.e(LOGTAG, "this item does not exist!");
+            }
+        } catch (IllegalStateException e) {
+            Log.e(LOGTAG, "getNameFromUrl", e);
+        } finally {
+            if (null != cursor) {
+                cursor.close();
+            }
+        }
+        return name;
+    }
+
+    private void updateMyNavigationThumbnail(final String itemUrl, WebView webView) {
+        int width = mActivity.getResources().getDimensionPixelOffset(
+                R.dimen.myNavigationThumbnailWidth);
+        int height = mActivity.getResources().getDimensionPixelOffset(
+                R.dimen.myNavigationThumbnailHeight);
+
+        final Bitmap bm = createScreenshot(webView, width, height);
+
+        if (bm == null) {
+            Log.e(LOGTAG, "updateMyNavigationThumbnail bm is null!");
+            return;
+        }
+
+        final ContentResolver cr = mActivity.getContentResolver();
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... unused) {
+                ContentResolver cr = mActivity.getContentResolver();
+                Cursor cursor = null;
+                try {
+                    cursor = cr.query(MyNavigationUtil.MY_NAVIGATION_URI,
+                            new String[] {
+                                MyNavigationUtil.ID
+                            }, "url = ?", new String[] {
+                                itemUrl
+                            }, null);
+                    if (null != cursor && cursor.moveToFirst()) {
+                        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+                        bm.compress(Bitmap.CompressFormat.PNG, 100, os);
+
+                        ContentValues values = new ContentValues();
+                        values.put(MyNavigationUtil.THUMBNAIL, os.toByteArray());
+                        Uri uri = ContentUris.withAppendedId(MyNavigationUtil.MY_NAVIGATION_URI,
+                                cursor.getLong(0));
+                        Log.d(LOGTAG, "updateMyNavigationThumbnail uri is " + uri);
+                        cr.update(uri, values, null, null);
+                        os.close();
+                    }
+                } catch (IllegalStateException e) {
+                    Log.e(LOGTAG, "updateMyNavigationThumbnail", e);
+                } catch (IOException e) {
+                    Log.e(LOGTAG, "updateMyNavigationThumbnail", e);
+                } finally {
+                    if (null != cursor) {
+                        cursor.close();
+                    }
+                }
+                return null;
+            }
+        }.execute();
+    }
+
     /**
      * As the menu can be open when loading state changes
      * we must manually update the state of the stop/reload menu
@@ -2217,10 +2455,16 @@
         }
         final String url = tab.getUrl();
         final String originalUrl = view.getOriginalUrl();
+        final String thumbnailUrl = mUpdateMyNavThumbnailUrl;
         if (TextUtils.isEmpty(url)) {
             return;
         }
 
+        //update My Navigation Thumbnails
+        boolean isMyNavigationUrl = MyNavigationUtil.isMyNavigationUrl(mActivity, url);
+        if (isMyNavigationUrl) {
+            updateMyNavigationThumbnail(url, view);
+        }
         // Only update thumbnails for web urls (http(s)://), not for
         // about:, javascript:, data:, etc...
         // Unless it is a bookmarked site, then always update
@@ -2228,6 +2472,24 @@
             return;
         }
 
+        if (url != null && mUpdateMyNavThumbnailUrl != null
+                && Patterns.WEB_URL.matcher(url).matches()
+                && Patterns.WEB_URL.matcher(mUpdateMyNavThumbnailUrl).matches()) {
+            String urlHost = (new WebAddress(url)).getHost();
+            String bookmarkHost = (new WebAddress(mUpdateMyNavThumbnailUrl)).getHost();
+            if (urlHost == null || urlHost.length() == 0 || bookmarkHost == null
+                    || bookmarkHost.length() == 0) {
+                return;
+            }
+            String urlDomain = urlHost.substring(urlHost.indexOf('.'), urlHost.length());
+            String bookmarkDomain = bookmarkHost.substring(bookmarkHost.indexOf('.'),
+                    bookmarkHost.length());
+            Log.d(LOGTAG, "addressUrl domain is  " + urlDomain);
+            Log.d(LOGTAG, "bookmarkUrl domain is " + bookmarkDomain);
+            if (!bookmarkDomain.equals(urlDomain)) {
+                return;
+            }
+        }
         final Bitmap bm = createScreenshot(view, getDesiredThumbnailWidth(mActivity),
                 getDesiredThumbnailHeight(mActivity));
         if (bm == null) {
@@ -2241,7 +2503,13 @@
                 Cursor cursor = null;
                 try {
                     // TODO: Clean this up
-                    cursor = Bookmarks.queryCombinedForUrl(cr, originalUrl, url);
+                    cursor = Bookmarks.queryCombinedForUrl(cr, originalUrl,
+                            mUpdateMyNavThumbnail ? ((thumbnailUrl != null) ? thumbnailUrl : url)
+                                    : url);
+                    if (mUpdateMyNavThumbnail) {
+                        mUpdateMyNavThumbnail = false;
+                        mUpdateMyNavThumbnailUrl = null;
+                    }
                     if (cursor != null && cursor.moveToFirst()) {
                         final ByteArrayOutputStream os =
                                 new ByteArrayOutputStream();