Geolocation fixes

- Dismiss GeolocationPermissionsPrompt when user navigates
  away from the page or when the user responds to a prompt
  for the same origin on a different tab.
- Geolocation indicator missing in incognito tabs.

Change-Id: If73bc509a83ad543ed02f723c65dd1507f0d7ac1
diff --git a/src/com/android/browser/BrowserSettings.java b/src/com/android/browser/BrowserSettings.java
index 81af49d..7d6e3f9 100644
--- a/src/com/android/browser/BrowserSettings.java
+++ b/src/com/android/browser/BrowserSettings.java
@@ -516,6 +516,9 @@
 
     public void clearLocationAccess() {
         GeolocationPermissions.getInstance().clearAll();
+        if (GeolocationPermissions.isIncognitoCreated()) {
+            GeolocationPermissions.getIncognitoInstance().clearAll();
+        }
     }
 
     public void resetDefaultPreferences() {
diff --git a/src/com/android/browser/GeolocationPermissionsPrompt.java b/src/com/android/browser/GeolocationPermissionsPrompt.java
index cab6deb..a429b2d 100755
--- a/src/com/android/browser/GeolocationPermissionsPrompt.java
+++ b/src/com/android/browser/GeolocationPermissionsPrompt.java
@@ -17,6 +17,8 @@
 package com.android.browser;
 
 import org.codeaurora.swe.GeolocationPermissions;
+import org.codeaurora.swe.GeolocationPermissions.GeolocationPolicyChange;
+import org.codeaurora.swe.GeolocationPermissions.GeolocationPolicyListener;
 import org.json.JSONArray;
 
 import android.content.Context;
@@ -31,7 +33,8 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
-public class GeolocationPermissionsPrompt extends LinearLayout {
+public class GeolocationPermissionsPrompt extends LinearLayout implements
+        GeolocationPolicyListener {
     private TextView mMessage;
     private Button mShareButton;
     private Button mShareForLimitedTimeButton;
@@ -39,6 +42,7 @@
     private CheckBox mRemember;
     private android.webkit.GeolocationPermissions.Callback mCallback;
     private String mOrigin;
+    private GeolocationPermissions mGeolocationPermissions;
 
     private static final long MILLIS_PER_DAY = 86400000;
 
@@ -53,10 +57,9 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        init();
     }
 
-    private void init() {
+    public void init(boolean privateBrowsing) {
         mMessage = (TextView) findViewById(R.id.message);
         mShareButton = (Button) findViewById(R.id.share_button);
         mShareForLimitedTimeButton = (Button)
@@ -85,6 +88,10 @@
                 handleButtonClick(false, GeolocationPermissions.DO_NOT_EXPIRE);
             }
         });
+
+        mGeolocationPermissions = (privateBrowsing ? GeolocationPermissions.getIncognitoInstance()
+                : GeolocationPermissions.getInstance());
+        mGeolocationPermissions.addListener(this);
     }
 
     /**
@@ -103,10 +110,53 @@
     }
 
     /**
+     * This method is called when the user modifies the geolocation policy in a different Tab.
+     */
+    public void onGeolocationPolicyChanged(GeolocationPolicyChange change) {
+        int action = change.getAction();
+
+        if (action == GeolocationPermissions.ALL_POLICIES_REMOVED) {
+            // do not dismiss when policy is removed
+            return;
+        } else if (change.getOrigin() != null && mOrigin.equals(change.getOrigin())) {
+            boolean allow = false;
+            switch (action) {
+                case GeolocationPermissions.ORIGIN_POLICY_REMOVED:
+                    // do not dismiss when policy is removed
+                    break;
+                case GeolocationPermissions.ORIGIN_ALLOWED:
+                    allow = true;
+                case GeolocationPermissions.ORIGIN_DENIED:
+                    hide();
+                    JSONArray jsonArray = new JSONArray();
+                    jsonArray.put(System.currentTimeMillis());
+                    jsonArray.put(mOrigin);
+                    // no need to retain policy since it has already been saved
+                    mCallback.invoke(jsonArray.toString(), allow, false /*retain*/);
+                    break;
+                default:
+                    return;
+            }
+        }
+    }
+
+    /**
+     * This method is called when the user navigates to a new URL (onPageStarted). In this case,
+     * we respond as if user denied access without retaining the policy.
+     */
+    public void dismiss() {
+        hide();
+        JSONArray jsonArray = new JSONArray();
+        jsonArray.put(System.currentTimeMillis());
+        jsonArray.put(mOrigin);
+        mCallback.invoke(jsonArray.toString(), false /*allow*/, false /*retain*/);
+    }
+    /**
      * Hides the prompt.
      */
     public void hide() {
         setVisibility(View.GONE);
+        mGeolocationPermissions.removeListener(this);
     }
 
     /**
diff --git a/src/com/android/browser/LocationButton.java b/src/com/android/browser/LocationButton.java
index c80c0e8..1bc3afb 100644
--- a/src/com/android/browser/LocationButton.java
+++ b/src/com/android/browser/LocationButton.java
@@ -31,7 +31,8 @@
 package com.android.browser;
 
 import org.codeaurora.swe.GeolocationPermissions;
-import org.codeaurora.swe.GeolocationPermissions.OnGeolocationPolicyModifiedListener;
+import org.codeaurora.swe.GeolocationPermissions.GeolocationPolicyChange;
+import org.codeaurora.swe.GeolocationPermissions.GeolocationPolicyListener;
 import org.json.JSONArray;
 
 import android.app.AlertDialog;
@@ -43,8 +44,7 @@
 import android.webkit.ValueCallback;
 import android.widget.ImageButton;
 
-public class LocationButton extends ImageButton
-        implements OnGeolocationPolicyModifiedListener {
+public class LocationButton extends ImageButton implements GeolocationPolicyListener {
     private GeolocationPermissions mGeolocationPermissions;
     private long mCurrentTabId;
     private String mCurrentOrigin;
@@ -78,7 +78,8 @@
         mGeolocationPermissions = mCurrentIncognito ?
                                     GeolocationPermissions.getIncognitoInstance() :
                                     GeolocationPermissions.getInstance();
-        mGeolocationPermissions.registerOnGeolocationPolicyModifiedListener(this);
+
+        mGeolocationPermissions.addListener(this);
     }
 
     // TODO: Perform this initilalization only after the engine initialization is complete.
@@ -185,18 +186,31 @@
         if (mCurrentTabId != tabId) {
             mCurrentTabId = tabId;
             mCurrentOrigin = origin;
+            // Switch GeolocationPermissions if we went from a regular to an
+            // incognito tab or vice versa
+            if (mCurrentIncognito != incognito) {
+                mCurrentIncognito = incognito;
+                mGeolocationPermissions = mCurrentIncognito ?
+                        GeolocationPermissions.getIncognitoInstance() :
+                        GeolocationPermissions.getInstance();
+                mGeolocationPermissions.addListener(this);
+            }
             update();
         }
-        // Update icon if we are in the same tab and origin has changed
-          else if (!((mCurrentOrigin == null && origin == null) ||
+        // Update icon if we are in the same Tab and origin has changed
+        else if (!((mCurrentOrigin == null && origin == null) ||
                 (mCurrentOrigin != null && origin != null
-                    && mCurrentOrigin.equals(origin)))) {
+                        && mCurrentOrigin.equals(origin)))) {
             mCurrentOrigin = origin;
             update();
         }
     }
 
-    public void update() {
+    /**
+     * This method is called when we navigate away from an origin on the same Tab or
+     * when a new Tab is created.
+     */
+    private void update() {
         if (mCurrentOrigin != null) {
             updateGeolocationPermissions();
             mGeolocationPermissions.hasOrigin(mCurrentOrigin,
@@ -227,25 +241,30 @@
         }
     }
 
-    @Override
-    public void onGeolocationPolicyAdded(String origin, boolean allow) {
-        if (mCurrentOrigin != null && mCurrentOrigin.equals(origin)) {
-            this.setImageResource(allow ? R.drawable.ic_action_gps_on :
-                R.drawable.ic_action_gps_off);
-            this.setVisibility(VISIBLE);
+    public void onGeolocationPolicyChanged(GeolocationPolicyChange change) {
+        if (mCurrentOrigin != null) {
+            int action = change.getAction();
+
+            if (action == GeolocationPermissions.ALL_POLICIES_REMOVED) {
+                this.setVisibility(GONE);
+                return;
+            } else if (change.getOrigin() != null && mCurrentOrigin.equals(change.getOrigin())) {
+                switch (action) {
+                    case GeolocationPermissions.ORIGIN_ALLOWED:
+                        this.setImageResource(R.drawable.ic_action_gps_on);
+                        this.setVisibility(VISIBLE);
+                        break;
+                    case GeolocationPermissions.ORIGIN_DENIED:
+                        this.setImageResource(R.drawable.ic_action_gps_off);
+                        this.setVisibility(VISIBLE);
+                        break;
+                    case GeolocationPermissions.ORIGIN_POLICY_REMOVED:
+                        this.setVisibility(GONE);
+                        break;
+                    default:
+                        break;
+                }
+            }
         }
     }
-
-    @Override
-    public void onGeolocationPolicyCleared(String origin) {
-        if (mCurrentOrigin != null && mCurrentOrigin.equals(origin)) {
-            this.setVisibility(GONE);
-        }
-    }
-
-    @Override
-    public void onGeolocationPolicyClearedAll() {
-        this.setVisibility(GONE);
-    }
-
 }
diff --git a/src/com/android/browser/Tab.java b/src/com/android/browser/Tab.java
index b7be6a5..7560322 100644
--- a/src/com/android/browser/Tab.java
+++ b/src/com/android/browser/Tab.java
@@ -392,6 +392,12 @@
                 mTouchIconLoader = null;
             }
 
+            // Loading a new page voids any ongoing Geolocation permission
+            // requests.
+            if (mGeolocationPermissionsPrompt != null) {
+                mGeolocationPermissionsPrompt.dismiss();
+            }
+
             // finally update the UI in the activity if it is in the foreground
             mWebViewController.onPageStarted(Tab.this, view, favicon);
 
@@ -1731,6 +1737,7 @@
                     .findViewById(R.id.geolocation_permissions_prompt);
             mGeolocationPermissionsPrompt = (GeolocationPermissionsPrompt) stub
                     .inflate();
+            mGeolocationPermissionsPrompt.init(mCurrentState.mIncognito);
         }
         return mGeolocationPermissionsPrompt;
     }