summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AndroidManifest.xml3
-rw-r--r--res/layout-sw600dp/title_bar_nav.xml7
-rwxr-xr-xres/layout/geolocation_permissions_prompt.xml11
-rw-r--r--res/layout/title_bar_nav.xml8
-rw-r--r--res/values/all_search_engines.xml14
-rw-r--r--res/values/donottranslate-search_engines.xml1
-rw-r--r--res/values/strings.xml21
-rw-r--r--res/xml/privacy_security_preferences.xml8
-rw-r--r--src/com/android/browser/AutoFillSettingsFragment.java34
-rw-r--r--src/com/android/browser/BaseUi.java10
-rw-r--r--src/com/android/browser/BrowserSettings.java4
-rw-r--r--src/com/android/browser/BrowserYesNoPreference.java3
-rw-r--r--src/com/android/browser/Controller.java85
-rw-r--r--src/com/android/browser/DownloadHandler.java30
-rw-r--r--src/com/android/browser/DownloadSettings.java4
-rwxr-xr-xsrc/com/android/browser/GeolocationPermissionsPrompt.java38
-rw-r--r--src/com/android/browser/IntentHandler.java5
-rw-r--r--src/com/android/browser/LocationButton.java257
-rw-r--r--src/com/android/browser/MemoryMonitor.java101
-rw-r--r--src/com/android/browser/NavigationBarBase.java4
-rw-r--r--src/com/android/browser/NavigationBarPhone.java2
-rw-r--r--src/com/android/browser/PhoneUi.java59
-rw-r--r--src/com/android/browser/PreferenceKeys.java1
-rw-r--r--src/com/android/browser/Tab.java78
-rw-r--r--src/com/android/browser/TabControl.java17
-rw-r--r--src/com/android/browser/UrlInputView.java5
-rwxr-xr-xsrc/com/android/browser/mynavigation/AddMyNavigationPage.java9
-rw-r--r--src/com/android/browser/preferences/WebsiteSettingsFragment.java117
-rw-r--r--src_system/AndroidManifest.xml3
29 files changed, 733 insertions, 206 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 826d1402..ccfebfc1 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -307,7 +307,8 @@
<provider
android:name=".provider.MyNavigationProvider"
android:authorities="com.android.swe.browser.mynavigation"
- android:exported="false" />
+ android:exported="false"
+ android:grantUriPermissions="true"/>
<service android:name="org.chromium.content.app.SandboxedProcessService0"
android:process=":sandboxed_process0"
diff --git a/res/layout-sw600dp/title_bar_nav.xml b/res/layout-sw600dp/title_bar_nav.xml
index a6b8a325..e6abe7c7 100644
--- a/res/layout-sw600dp/title_bar_nav.xml
+++ b/res/layout-sw600dp/title_bar_nav.xml
@@ -53,6 +53,13 @@
android:layout_weight="1.0"
android:orientation="horizontal"
android:background="@drawable/url_background">
+ <com.android.browser.LocationButton
+ android:id="@+id/location_button"
+ android:layout_width="32dip"
+ android:layout_height="20dip"
+ android:visibility="gone"
+ style="@style/HoloButton"
+ android:layout_gravity="center" />
<ImageView
android:id="@+id/url_icon"
android:layout_width="32dip"
diff --git a/res/layout/geolocation_permissions_prompt.xml b/res/layout/geolocation_permissions_prompt.xml
index 1920c05c..d63ef848 100755
--- a/res/layout/geolocation_permissions_prompt.xml
+++ b/res/layout/geolocation_permissions_prompt.xml
@@ -68,14 +68,21 @@
android:id="@+id/dont_share_button"
style="?android:attr/buttonBarButtonStyle"
android:layout_weight="1"
- android:layout_width="0dip"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/geolocation_permissions_prompt_dont_share" />
<Button
+ android:id="@+id/share_for_limited_time_button"
+ style="?android:attr/buttonBarButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/geolocation_permissions_prompt_share_for_limited_time"/>
+ <Button
android:id="@+id/share_button"
style="?android:attr/buttonBarButtonStyle"
android:layout_weight="1"
- android:layout_width="0dip"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/geolocation_permissions_prompt_share" />
</LinearLayout>
diff --git a/res/layout/title_bar_nav.xml b/res/layout/title_bar_nav.xml
index 2f1e0a27..3ee99fd0 100644
--- a/res/layout/title_bar_nav.xml
+++ b/res/layout/title_bar_nav.xml
@@ -42,6 +42,12 @@
android:paddingLeft="4dip"
android:visibility="gone"
android:src="@drawable/ic_incognito_holo_dark" />
+ <com.android.browser.LocationButton
+ android:id="@+id/location_button"
+ android:layout_width="32dip"
+ android:layout_height="32dip"
+ android:visibility="gone"
+ style="@style/HoloButton"/>
<FrameLayout
android:id="@+id/iconcombo"
android:layout_width="44dip"
@@ -116,7 +122,7 @@
android:src="@drawable/ic_windows_holo_dark"
style="@style/HoloButton" />
<ImageButton
- android:id="@+id/more"
+ android:id="@+id/more_browser_settings"
android:layout_width="wrap_content"
android:layout_height="match_parent"
style="@style/HoloButton"
diff --git a/res/values/all_search_engines.xml b/res/values/all_search_engines.xml
index 2c199f34..5a1de969 100644
--- a/res/values/all_search_engines.xml
+++ b/res/values/all_search_engines.xml
@@ -36,6 +36,14 @@ http://www.opensearch.org/Specifications/OpenSearch/1.1/Draft_4#OpenSearch_1.1_p
-->
<resources>
+ <string-array name="DuckDuckGo" translatable="false">
+ <item>DuckDuckGo</item>
+ <item>duckduckgo.com</item>
+ <item>http://duckduckgo.com/favicon.ico</item>
+ <item>https://duckduckgo.com/?q={searchTerms}</item>
+ <item>UTF-8</item>
+ <item></item>
+ </string-array>
<string-array name="yahoo_uk" translatable="false">
<item>Yahoo! UK &amp; Ireland</item>
<item>uk.yahoo.com</item>
@@ -151,9 +159,9 @@ http://www.opensearch.org/Specifications/OpenSearch/1.1/Draft_4#OpenSearch_1.1_p
<string-array name="yahoo_cn" translatable="false">
<item>&#x4e2d;&#x56fd;&#x96c5;&#x864e;</item>
<item>cn.yahoo.com</item>
- <item>http://search.cn.yahoo.com/favicon.ico</item>
- <item>http://search.cn.yahoo.com/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
- <item>GB2312</item>
+ <item>http://search.yahoo.com/favicon.ico</item>
+ <item>http://search.yahoo.com/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
+ <item>UTF-8</item>
<item></item>
</string-array>
<string-array name="onet" translatable="false">
diff --git a/res/values/donottranslate-search_engines.xml b/res/values/donottranslate-search_engines.xml
index f83526b7..1709dc80 100644
--- a/res/values/donottranslate-search_engines.xml
+++ b/res/values/donottranslate-search_engines.xml
@@ -26,6 +26,7 @@ Each value in the string-array is the name of a value in all_search_engines.xml
<item>baidu</item>
<item>yahoo</item>
<item>bing</item>
+ <item>DuckDuckGo</item>
</string-array>
<string name="default_search_engine_value">baidu</string>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index eae9ac69..0d505832 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -492,6 +492,10 @@
<string name="pref_security_show_security_warning">Show security warnings</string>
<!-- Settings summmary -->
<string name="pref_security_show_security_warning_summary">Show warning if there\'s a problem with a site\'s security</string>
+ <!-- Settings Label -->
+ <string name="pref_do_not_track">Do Not Track</string>
+ <!-- Settings summary -->
+ <string name="pref_do_not_track_summary">Send a Do Not Track request with your browsing traffic</string>
<!-- Settings label -->
<string name="pref_security_accept_cookies">Accept cookies</string>
<!-- Settings summary -->
@@ -802,6 +806,7 @@
<!-- Intentional empty elements - used for overlay feature -->
<string name="def_wifi_browser_interaction_remind_type"></string>
<string name="def_action_wifi_selection_data_connections"></string>
+ <string name="def_intent_pick_network"></string>
<string name="def_landing_page"></string>
<string name="def_useragent"></string>
@@ -867,20 +872,28 @@
<!-- Geolocation -->
<!-- Permissions prompt -->
<string name="geolocation_permissions_prompt_message"><xliff:g id="website origin" example="maps.google.com">%s</xliff:g> wants to know your location</string>
- <string name="geolocation_permissions_prompt_share">Share location</string>
- <string name="geolocation_permissions_prompt_dont_share">Decline</string>
+ <string name="geolocation_permissions_prompt_share">Allow</string>
+ <string name="geolocation_permissions_prompt_share_for_limited_time">Allow for 24 hours</string>
+ <string name="geolocation_permissions_prompt_dont_share">Deny</string>
<string name="geolocation_permissions_prompt_remember">Remember preference</string>
<!-- Permissions prompt toast -->
<string name="geolocation_permissions_prompt_toast_allowed">This site can access your location. Change this on the Settings &gt; Advanced &gt; Website screen.</string>
<string name="geolocation_permissions_prompt_toast_disallowed">This site cannot access your location. Change this on the Settings &gt; Advanced &gt; Website screen.</string>
<!-- Settings -> Advanced -> Website settings -> <origin> -->
- <string name="geolocation_settings_page_title">Clear location access</string>
+ <string name="geolocation_settings_page_title">Edit location access</string>
<string name="geolocation_settings_page_summary_allowed">This site can currently access your location</string>
<string name="geolocation_settings_page_summary_not_allowed">This site can\'t currently access your location</string>
<!-- Settings page dialog -->
- <string name="geolocation_settings_page_dialog_message">Clear location access for this website?</string>
+ <string name="geolocation_settings_page_dialog_title">Edit location policy for\n<xliff:g id="website origin" example="maps.google.com">%s</xliff:g></string>
+ <string-array name="geolocation_settings_choices">
+ <item>Deny forever</item>
+ <item>Allow for 24 hours</item>
+ <item>Allow forever</item>
+ <item>Always ask</item>
+ </string-array>
<string name="geolocation_settings_page_dialog_ok_button">OK</string>
<string name="geolocation_settings_page_dialog_cancel_button">Cancel</string>
+
<!-- Label for the menu item in the website settings activity used to clear data stored by all websites -->
<string name="website_settings_clear_all">Clear all</string>
<string name="website_settings_clear_all_dialog_message">Delete all website data and location permissions?</string>
diff --git a/res/xml/privacy_security_preferences.xml b/res/xml/privacy_security_preferences.xml
index 26336000..4c14c866 100644
--- a/res/xml/privacy_security_preferences.xml
+++ b/res/xml/privacy_security_preferences.xml
@@ -37,6 +37,12 @@
android:title="@string/pref_security_show_security_warning"
android:summary="@string/pref_security_show_security_warning_summary" />
+ <CheckBoxPreference
+ android:key="do_not_track"
+ android:defaultValue="true"
+ android:title="@string/pref_do_not_track"
+ android:summary="@string/pref_do_not_track_summary" />
+
<PreferenceCategory android:title="@string/pref_privacy_cookies_title">
<CheckBoxPreference
android:key="accept_cookies"
@@ -94,7 +100,7 @@
android:key="privacy_clear_passwords"
android:title="@string/pref_privacy_clear_passwords"
android:summary="@string/pref_privacy_clear_passwords_summary"
- android:dialogMessage="@string/pref_privacy_clear_passwords_dlg"
+ android:dialogMessage="@string/pref_privacy_clear_passwords_dlg"
android:dialogIcon="@android:drawable/ic_dialog_alert"/>
</PreferenceCategory>
diff --git a/src/com/android/browser/AutoFillSettingsFragment.java b/src/com/android/browser/AutoFillSettingsFragment.java
index e87cb892..cc771028 100644
--- a/src/com/android/browser/AutoFillSettingsFragment.java
+++ b/src/com/android/browser/AutoFillSettingsFragment.java
@@ -56,6 +56,7 @@ public class AutoFillSettingsFragment extends Fragment {
private EditText mPhoneEdit;
private MenuItem mSaveMenuItem;
+ private MenuItem mDeleteMenuItem;
private boolean mInitialised;
@@ -92,6 +93,7 @@ public class AutoFillSettingsFragment extends Fragment {
}
updateSaveMenuItemState();
+ updateDeleteMenuItemState();
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
@@ -104,6 +106,7 @@ public class AutoFillSettingsFragment extends Fragment {
private class FieldChangedListener implements TextWatcher {
public void afterTextChanged(Editable s) {
updateSaveMenuItemState();
+ updateDeleteMenuItemState();
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
@@ -152,7 +155,9 @@ public class AutoFillSettingsFragment extends Fragment {
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.autofill_profile_editor, menu);
mSaveMenuItem = menu.findItem(R.id.autofill_profile_editor_save_profile_menu_id);
+ mDeleteMenuItem = menu.findItem(R.id.autofill_profile_editor_delete_profile_menu_id);
updateSaveMenuItemState();
+ updateDeleteMenuItemState();
}
@Override
@@ -176,6 +181,7 @@ public class AutoFillSettingsFragment extends Fragment {
mSettings.updateAutoFillProfile(null);
updateSaveMenuItemState();
+ updateDeleteMenuItemState();
return true;
case R.id.autofill_profile_editor_save_profile_menu_id:
@@ -248,10 +254,38 @@ public class AutoFillSettingsFragment extends Fragment {
mInitialised = true;
updateSaveMenuItemState();
+ updateDeleteMenuItemState();
return v;
}
+ private void updateDeleteMenuItemState() {
+ if (mDeleteMenuItem == null) {
+ return;
+ }
+
+ if (!mInitialised) {
+ mDeleteMenuItem.setEnabled(false);
+ return;
+ }
+
+ boolean currentState = mDeleteMenuItem.isEnabled();
+ boolean newState = (mFullNameEdit.getText().toString().length() > 0 ||
+ mEmailEdit.getText().toString().length() > 0 ||
+ mCompanyEdit.getText().toString().length() > 0 ||
+ mAddressLine1Edit.getText().toString().length() > 0 ||
+ mAddressLine2Edit.getText().toString().length() > 0 ||
+ mCityEdit.getText().toString().length() > 0 ||
+ mStateEdit.getText().toString().length() > 0 ||
+ mZipEdit.getText().toString().length() > 0 ||
+ mCountryEdit.getText().toString().length() > 0) &&
+ mPhoneEdit.getError() == null;
+
+ if (currentState != newState) {
+ mDeleteMenuItem.setEnabled(newState);
+ }
+ }
+
private void updateSaveMenuItemState() {
if (mSaveMenuItem == null) {
return;
diff --git a/src/com/android/browser/BaseUi.java b/src/com/android/browser/BaseUi.java
index 7c166aa0..27b2b829 100644
--- a/src/com/android/browser/BaseUi.java
+++ b/src/com/android/browser/BaseUi.java
@@ -313,11 +313,10 @@ public abstract class BaseUi implements UI {
Runnable mRunnable = null;
protected void scheduleRemoveTab(Tab tabToRemove, Tab tabToWaitFor) {
- android.os.Handler handler = mTitleBar.getHandler();
//remove previously scehduled tab
if (mTabToRemove != null) {
if (mRunnable != null)
- handler.removeCallbacks(mRunnable);
+ mTitleBar.removeCallbacks(mRunnable);
removeTabFromContentView(mTabToRemove);
mTabToRemove.performPostponedDestroy();
mRunnable = null;
@@ -334,11 +333,10 @@ public abstract class BaseUi implements UI {
protected void tryRemoveTab() {
mNumRemoveTries++;
- android.os.Handler handler = mTitleBar.getHandler();
// Ensure the webview is still valid
if (mNumRemoveTries < 20 && mTabToWaitFor.getWebView() != null) {
if (!mTabToWaitFor.getWebView().isReady()) {
- if (mRunnable != null) {
+ if (mRunnable == null) {
mRunnable = new Runnable() {
public void run() {
tryRemoveTab();
@@ -348,13 +346,13 @@ public abstract class BaseUi implements UI {
/*if the new tab is still not ready, wait another 2 frames
before trying again. 1 frame for the tab to render the first
frame, another 1 frame to make sure the swap is done*/
- handler.postDelayed(mRunnable, 33);
+ mTitleBar.postDelayed(mRunnable, 33);
return;
}
}
if (mTabToRemove != null) {
if (mRunnable != null)
- handler.removeCallbacks(mRunnable);
+ mTitleBar.removeCallbacks(mRunnable);
removeTabFromContentView(mTabToRemove);
mTabToRemove.performPostponedDestroy();
mRunnable = null;
diff --git a/src/com/android/browser/BrowserSettings.java b/src/com/android/browser/BrowserSettings.java
index 25dcd022..1e2e84aa 100644
--- a/src/com/android/browser/BrowserSettings.java
+++ b/src/com/android/browser/BrowserSettings.java
@@ -957,6 +957,10 @@ public class BrowserSettings implements OnSharedPreferenceChangeListener,
return mPrefs.getBoolean(PREF_SHOW_SECURITY_WARNINGS, true);
}
+ public boolean doNotTrack() {
+ return mPrefs.getBoolean(PREF_DO_NOT_TRACK, true);
+ }
+
public boolean acceptCookies() {
return mPrefs.getBoolean(PREF_ACCEPT_COOKIES, true);
}
diff --git a/src/com/android/browser/BrowserYesNoPreference.java b/src/com/android/browser/BrowserYesNoPreference.java
index 4bb3c9cf..e8d6af9a 100644
--- a/src/com/android/browser/BrowserYesNoPreference.java
+++ b/src/com/android/browser/BrowserYesNoPreference.java
@@ -33,10 +33,9 @@ class BrowserYesNoPreference extends DialogPreference {
super.onDialogClosed(positiveResult);
if (callChangeListener(positiveResult)) {
- setEnabled(false);
if (!positiveResult)
return;
-
+ setEnabled(false);
BrowserSettings settings = BrowserSettings.getInstance();
if (PreferenceKeys.PREF_PRIVACY_CLEAR_CACHE.equals(getKey())) {
settings.clearCache();
diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java
index 012191e9..8bd85f69 100644
--- a/src/com/android/browser/Controller.java
+++ b/src/com/android/browser/Controller.java
@@ -195,10 +195,6 @@ public class Controller
private boolean mShouldShowErrorConsole;
private boolean mNetworkShouldNotify = true;
- private boolean mJsInterfaceEnabled = false;
-
- private SystemAllowGeolocationOrigins mSystemAllowGeolocationOrigins;
-
// FIXME, temp address onPrepareMenu performance problem.
// When we move everything out of view, we should rewrite this.
private int mCurrentMenuState = 0;
@@ -276,11 +272,6 @@ public class Controller
BrowserContract.Bookmarks.CONTENT_URI, true, mBookmarksObserver);
mNetworkHandler = new NetworkStateHandler(mActivity, this);
- // Start watching the default geolocation permissions
- mSystemAllowGeolocationOrigins =
- new SystemAllowGeolocationOrigins(mActivity.getApplicationContext());
- mSystemAllowGeolocationOrigins.start();
-
openIconDatabase();
}
@@ -343,6 +334,7 @@ public class Controller
}
} else {
t = openTab(urlData);
+ t.setDerivedFromIntent(true);
}
if (t != null) {
t.setAppId(intent.getStringExtra(Browser.EXTRA_APPLICATION_ID));
@@ -363,6 +355,9 @@ public class Controller
ArrayList<Long> restoredTabs = new ArrayList<Long>(tabs.size());
for (Tab t : tabs) {
restoredTabs.add(t.getId());
+ if (t != mTabControl.getCurrentTab()) {
+ t.pause();
+ }
}
BackgroundHandler.execute(new PruneThumbnails(mActivity, restoredTabs));
if (tabs.size() == 0) {
@@ -818,9 +813,6 @@ public class Controller
// Destroy all the tabs
mTabControl.destroy();
WebIconDatabase.getInstance().close();
- // Stop watching the default geolocation permissions
- mSystemAllowGeolocationOrigins.stop();
- mSystemAllowGeolocationOrigins = null;
}
protected boolean isActivityPaused() {
@@ -871,45 +863,42 @@ public class Controller
R.string.def_wifi_browser_interaction_remind_type);
final String selectionConnnection = getContext().getResources().getString(
R.string.def_action_wifi_selection_data_connections);
+ final String wifiSelection = getContext().getResources().getString(
+ R.string.def_intent_pick_network);
- if (reminderType.isEmpty() || selectionConnnection.isEmpty())
+ if (reminderType.isEmpty() || selectionConnnection.isEmpty() ||
+ wifiSelection.isEmpty())
return;
ConnectivityManager conMgr = (ConnectivityManager) this.getContext().getSystemService(
Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = conMgr.getActiveNetworkInfo();
+ WifiManager wifiMgr = (WifiManager) this.getContext()
+ .getSystemService(Context.WIFI_SERVICE);
if (networkInfo == null
|| (networkInfo != null && (networkInfo.getType() !=
ConnectivityManager.TYPE_WIFI))) {
int isReminder = Settings.System.getInt(mActivity.getContentResolver(),
reminderType, NETWORK_SWITCH_TYPE_OK);
- if (isReminder == NETWORK_SWITCH_TYPE_OK) {
- mNetworkShouldNotify = false;
+ List<ScanResult> list = wifiMgr.getScanResults();
+ // Have no AP's for Wifi's fall back to data
+ if (list != null && list.size() == 0 && isReminder == NETWORK_SWITCH_TYPE_OK) {
Intent intent = new Intent(selectionConnnection);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.getContext().startActivity(intent);
} else {
- if (!mNetworkHandler.isNetworkUp())
- view.setNetworkAvailable(false);
- }
- }
- }
-
- /***
- * Add/remove a Javascript interface for a local default homepage only
- */
- private void handleJsInterface(WebView webview){
- if (webview.getUrl() != null &&
- webview.getUrl().equals(mActivity.getResources().getString(R.string.homepage_base)) &&
- webview.getUrl().startsWith("file:///")) {
- mJsInterfaceEnabled = true;
- webview.getSettings().setJavaScriptEnabled(true);
- webview.addJavascriptInterface(mActivity, "default_homepage");
- } else {
- if (mJsInterfaceEnabled) {
- webview.removeJavascriptInterface("default_homepage");
- mJsInterfaceEnabled = false;
+ // Request to select Wifi AP
+ try {
+ Intent intent = new Intent(wifiSelection);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ this.getContext().startActivity(intent);
+ } catch (Exception e) {
+ String err_msg = this.getContext().getString(
+ R.string.acivity_not_found, wifiSelection);
+ Toast.makeText(this.getContext(), err_msg, Toast.LENGTH_LONG).show();
+ }
}
+ mNetworkShouldNotify = false;
}
}
@@ -927,10 +916,10 @@ public class Controller
// reset sync timer to avoid sync starts during loading a page
CookieSyncManager.getInstance().resetSync();
WifiManager wifiMgr = (WifiManager) this.getContext()
- .getSystemService(Context.WIFI_SERVICE);
+ .getSystemService(Context.WIFI_SERVICE);
boolean networkNotifier =
mActivity.getApplicationContext().getResources().getBoolean(R.bool.network_notifier);
- if (networkNotifier && mNetworkShouldNotify && wifiMgr.isWifiEnabled()) {
+ if (networkNotifier && mNetworkShouldNotify && wifiMgr.isWifiEnabled()){
handleNetworkNotify(view);
} else {
if (!mNetworkHandler.isNetworkUp()) {
@@ -981,7 +970,6 @@ public class Controller
int newProgress = tab.getLoadProgress();
if (newProgress == 100) {
- handleJsInterface(tab.getWebView());
CookieSyncManager.getInstance().sync();
// onProgressChanged() may continue to be called after the main
// frame has finished loading, as any remaining sub frames continue
@@ -1188,7 +1176,10 @@ public class Controller
// file. Remove it.
if (tab == mTabControl.getCurrentTab()) {
// In this case, the Tab is still on top.
- goBackOnePageOrQuit();
+ if (tab.getDerivedFromIntent())
+ closeTab(tab);
+ else
+ goBackOnePageOrQuit();
} else {
// In this case, it is not.
closeTab(tab);
@@ -2709,6 +2700,8 @@ public class Controller
// the tab is guaranteed to have a webview after setCurrentTab
mUi.setActiveTab(tab);
tab.setTimeStamp();
+ //Purge active tabs
+ MemoryMonitor.purgeActiveTabs(mActivity.getApplicationContext(), this, mSettings);
}
}
@@ -2854,23 +2847,13 @@ public class Controller
private Tab createNewTab(boolean incognito, boolean setActive,
boolean useCurrent) {
Tab tab = null;
- MemoryMonitor memMonitor = null;
if (mTabControl.canCreateNewTab()) {
- if (mSettings.enableMemoryMonitor()) {
- Log.d(LOGTAG, " Memory Monitor Enabled .");
- memMonitor = MemoryMonitor.getInstance(mActivity.getApplicationContext(),this);
- if (memMonitor != null) {
- //Remove webview associated with the oldest tab
- memMonitor.destroyLeastRecentlyActiveTab();
- }
- } else {
- Log.d(LOGTAG, " Memory Monitor disabled .");
- }
tab = mTabControl.createNewTab(incognito);
addTab(tab);
- tab.setTimeStamp();
if (setActive) {
setActiveTab(tab);
+ } else {
+ tab.pause();
}
} else {
if (useCurrent) {
diff --git a/src/com/android/browser/DownloadHandler.java b/src/com/android/browser/DownloadHandler.java
index 88e66798..f42ee768 100644
--- a/src/com/android/browser/DownloadHandler.java
+++ b/src/com/android/browser/DownloadHandler.java
@@ -41,6 +41,9 @@ import com.android.browser.R;
import com.android.browser.platformsupport.WebAddress;
import com.android.browser.reflect.ReflectHelper;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
import java.io.File;
/**
* Handle download requests
@@ -184,7 +187,8 @@ public class DownloadHandler {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(url), mimetype);
try {
- String title = URLUtil.guessFileName(url, contentDisposition, mimetype);
+ String trimmedcontentDisposition = trimContentDisposition(contentDisposition);
+ String title = URLUtil.guessFileName(url, trimmedcontentDisposition, mimetype);
intent.putExtra(Intent.EXTRA_TITLE, title);
activity.startActivity(intent);
} catch (ActivityNotFoundException ex) {
@@ -278,6 +282,9 @@ public class DownloadHandler {
String mimetype, String referer, boolean privateBrowsing, long contentLength) {
initStorageDefaultPath(activity);
+
+ contentDisposition = trimContentDisposition(contentDisposition);
+
String filename = URLUtil.guessFileName(url,
contentDisposition, mimetype);
@@ -317,6 +324,27 @@ public class DownloadHandler {
}
+ static String trimContentDisposition(String contentDisposition) {
+ final Pattern CONTENT_DISPOSITION_PATTERN =
+ Pattern.compile("attachment;\\s*filename\\s*=\\s*(\"?)([^\"]*)\\1\\s*;",
+ Pattern.CASE_INSENSITIVE);
+
+ if (contentDisposition != null) {
+
+ try {
+ Matcher m = CONTENT_DISPOSITION_PATTERN.matcher(contentDisposition);
+ if (m.find()) {
+ return m.group();
+ } else {
+ return contentDisposition;
+ }
+ } catch (IllegalStateException ex) {
+ // This function is defined as returning null when it can't parse the header
+ }
+ }
+ return null;
+ }
+
public static void initStorageDefaultPath(Context context) {
mExternalStorage = getExternalStorageDirectory(context);
if (isPhoneStorageSupported()) {
diff --git a/src/com/android/browser/DownloadSettings.java b/src/com/android/browser/DownloadSettings.java
index cca26ccb..4c7c829b 100644
--- a/src/com/android/browser/DownloadSettings.java
+++ b/src/com/android/browser/DownloadSettings.java
@@ -126,7 +126,9 @@ public class DownloadSettings extends Activity {
String filenameExtension = DownloadHandler.getFilenameExtension(filename);
- if (mimetype == null || mimetype.isEmpty()) {
+ // introspect for octet stream mimetype what type of file extension it has
+ // and reassign mimetype
+ if (mimetype == null || mimetype.isEmpty() || mimetype.equals(OCTET_STREAM)) {
String updatedFileName = filenameBase + "." + filenameExtension;
Object[] params = {updatedFileName};
diff --git a/src/com/android/browser/GeolocationPermissionsPrompt.java b/src/com/android/browser/GeolocationPermissionsPrompt.java
index 127107fd..d0e94ad2 100755
--- a/src/com/android/browser/GeolocationPermissionsPrompt.java
+++ b/src/com/android/browser/GeolocationPermissionsPrompt.java
@@ -18,14 +18,17 @@ package com.android.browser;
import com.android.browser.R;
+import org.codeaurora.swe.GeolocationPermissions;
+import org.json.JSONArray;
+
import android.content.Context;
import android.net.Uri;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
-import android.webkit.GeolocationPermissions;
import android.widget.Button;
import android.widget.CheckBox;
+import android.widget.CompoundButton;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
@@ -33,11 +36,14 @@ import android.widget.Toast;
public class GeolocationPermissionsPrompt extends RelativeLayout {
private TextView mMessage;
private Button mShareButton;
+ private Button mShareForLimitedTimeButton;
private Button mDontShareButton;
private CheckBox mRemember;
- private GeolocationPermissions.Callback mCallback;
+ private android.webkit.GeolocationPermissions.Callback mCallback;
private String mOrigin;
+ private static final long MILLIS_PER_DAY = 86400000;
+
public GeolocationPermissionsPrompt(Context context) {
this(context, null);
}
@@ -55,17 +61,30 @@ public class GeolocationPermissionsPrompt extends RelativeLayout {
private void init() {
mMessage = (TextView) findViewById(R.id.message);
mShareButton = (Button) findViewById(R.id.share_button);
+ mShareForLimitedTimeButton = (Button)
+ findViewById(R.id.share_for_limited_time_button);
mDontShareButton = (Button) findViewById(R.id.dont_share_button);
mRemember = (CheckBox) findViewById(R.id.remember);
+ mRemember.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ mShareForLimitedTimeButton.setEnabled(isChecked);
+ }
+ });
+
mShareButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
- handleButtonClick(true);
+ handleButtonClick(true, GeolocationPermissions.DO_NOT_EXPIRE);
+ }
+ });
+ mShareForLimitedTimeButton.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ handleButtonClick(true, System.currentTimeMillis() + MILLIS_PER_DAY);
}
});
mDontShareButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
- handleButtonClick(false);
+ handleButtonClick(false, GeolocationPermissions.DO_NOT_EXPIRE);
}
});
}
@@ -74,7 +93,8 @@ public class GeolocationPermissionsPrompt extends RelativeLayout {
* Shows the prompt for the given origin. When the user clicks on one of
* the buttons, the supplied callback is be called.
*/
- public void show(String origin, GeolocationPermissions.Callback callback) {
+ public void show(String origin,
+ android.webkit.GeolocationPermissions.Callback callback) {
mOrigin = origin;
mCallback = callback;
Uri uri = Uri.parse(mOrigin);
@@ -94,7 +114,7 @@ public class GeolocationPermissionsPrompt extends RelativeLayout {
/**
* Handles a click on one the buttons by invoking the callback.
*/
- private void handleButtonClick(boolean allow) {
+ private void handleButtonClick(boolean allow, long expirationTime) {
hide();
boolean remember = mRemember.isChecked();
@@ -108,7 +128,11 @@ public class GeolocationPermissionsPrompt extends RelativeLayout {
toast.show();
}
- mCallback.invoke(mOrigin, allow, remember);
+ // Encode the expirationTime and origin as a JSON string.
+ JSONArray jsonArray = new JSONArray();
+ jsonArray.put(expirationTime);
+ jsonArray.put(mOrigin);
+ mCallback.invoke(jsonArray.toString(), allow, remember);
}
/**
diff --git a/src/com/android/browser/IntentHandler.java b/src/com/android/browser/IntentHandler.java
index ec192461..f829ae1f 100644
--- a/src/com/android/browser/IntentHandler.java
+++ b/src/com/android/browser/IntentHandler.java
@@ -109,6 +109,7 @@ public class IntentHandler {
if (intent.getBooleanExtra(Browser.EXTRA_CREATE_NEW_TAB, false)
|| urlData.isPreloaded()) {
Tab t = mController.openTab(urlData);
+ t.setDerivedFromIntent(true);
return;
}
/*
@@ -123,7 +124,8 @@ public class IntentHandler {
if (!TextUtils.isEmpty(urlData.mUrl) &&
urlData.mUrl.startsWith("javascript:")) {
// Always open javascript: URIs in new tabs
- mController.openTab(urlData);
+ Tab jsTab = mController.openTab(urlData);
+ jsTab.setDerivedFromIntent(true);
return;
}
if (Intent.ACTION_VIEW.equals(action)
@@ -165,6 +167,7 @@ public class IntentHandler {
Tab tab = mController.openTab(urlData);
if (tab != null) {
tab.setAppId(appId);
+ tab.setDerivedFromIntent(true);
if ((intent.getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
tab.setCloseOnBack(true);
}
diff --git a/src/com/android/browser/LocationButton.java b/src/com/android/browser/LocationButton.java
new file mode 100644
index 00000000..e805e438
--- /dev/null
+++ b/src/com/android/browser/LocationButton.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+package com.android.browser;
+
+import org.codeaurora.swe.GeolocationPermissions;
+import org.codeaurora.swe.GeolocationPermissions.OnGeolocationPolicyModifiedListener;
+import org.json.JSONArray;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.net.Uri;
+import android.util.AttributeSet;
+import android.view.View;
+import android.webkit.ValueCallback;
+import android.widget.ImageButton;
+
+public class LocationButton extends ImageButton
+ implements OnGeolocationPolicyModifiedListener {
+ private GeolocationPermissions mGeolocationPermissions;
+ private long mCurrentTabId;
+ private String mCurrentOrigin;
+ private boolean mCurrentIncognito;
+
+ private static final long MILLIS_PER_DAY = 86400000;
+
+ protected long geolocationPolicyExpiration;
+ protected boolean geolocationPolicyOriginAllowed;
+
+ public LocationButton(Context context) {
+ super(context);
+ }
+
+ public LocationButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ }
+
+ public LocationButton(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ init();
+ }
+
+ private void init() {
+ mGeolocationPermissions = GeolocationPermissions.getInstance();
+ mGeolocationPermissions.registerOnGeolocationPolicyModifiedListener(this);
+ mCurrentTabId = -1;
+ mCurrentOrigin = null;
+ mCurrentIncognito = false;
+
+ setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (!mCurrentOrigin.isEmpty()) {
+ final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
+ final GeolocationPermissions geolocationPermissions =
+ (mCurrentIncognito ?
+ GeolocationPermissions.getIncognitoInstance() :
+ GeolocationPermissions.getInstance());
+
+ DialogInterface.OnClickListener alertDialogListener =
+ new AlertDialog.OnClickListener() {
+ public void onClick(DialogInterface dlg, int which) {
+ String origin = mCurrentOrigin;
+ int selectedPosition = ((AlertDialog)dlg)
+ .getListView().getCheckedItemPosition();
+ switch (selectedPosition) {
+ case 0: // Deny forever
+ geolocationPermissions.deny(origin);
+ break;
+ case 1: // Extend for 24 hours
+ // encode the expiration time and origin as a JSON string
+ JSONArray jsonArray = new JSONArray();
+ jsonArray.put(System.currentTimeMillis() + MILLIS_PER_DAY);
+ jsonArray.put(origin);
+ geolocationPermissions.allow(jsonArray.toString());
+ break;
+ case 2: // Allow forever
+ geolocationPermissions.allow(origin);
+ break;
+ case 3: // Always ask
+ geolocationPermissions.clear(origin);
+ break;
+ default:
+ break;
+ }
+ }};
+
+ builder.setTitle(String.format(getResources()
+ .getString(R.string.geolocation_settings_page_dialog_title),
+ "http".equals(Uri.parse(mCurrentOrigin).getScheme()) ?
+ mCurrentOrigin.substring(7) : mCurrentOrigin))
+ .setPositiveButton(R.string.geolocation_settings_page_dialog_ok_button,
+ alertDialogListener)
+ .setNegativeButton(R.string.geolocation_settings_page_dialog_cancel_button, null);
+
+ final ValueCallback<Long> getExpirationCallback = new ValueCallback<Long>() {
+ public void onReceiveValue(Long expirationTime) {
+ if (expirationTime != null) {
+ geolocationPolicyExpiration = expirationTime.longValue();
+ // Set radio button and location icon
+ if (!geolocationPolicyOriginAllowed) {
+ // 0: Deny forever
+ builder.setSingleChoiceItems(R.array.geolocation_settings_choices, 0, null);
+ } else {
+ if (geolocationPolicyExpiration
+ != GeolocationPermissions.DO_NOT_EXPIRE) {
+ // 1: Allow for 24 hours
+ builder.setSingleChoiceItems(R.array.geolocation_settings_choices, 1, null);
+ } else {
+ // 2: Allow forever
+ builder.setSingleChoiceItems(R.array.geolocation_settings_choices, 2, null);
+ }
+ }
+ }
+ builder.show();
+ }};
+
+ final ValueCallback<Boolean> getAllowedCallback = new ValueCallback<Boolean>() {
+ public void onReceiveValue(Boolean allowed) {
+ if (allowed != null) {
+ geolocationPolicyOriginAllowed = allowed.booleanValue();
+ //Get the policy expiration time
+ geolocationPermissions
+ .getExpirationTime(mCurrentOrigin, getExpirationCallback);
+ }
+ }};
+
+ geolocationPermissions.hasOrigin(mCurrentOrigin,
+ new ValueCallback<Boolean>() {
+ public void onReceiveValue(Boolean hasOrigin) {
+ if (hasOrigin != null && hasOrigin.booleanValue()) {
+ //Get whether origin is allowed or denied
+ geolocationPermissions.getAllowed(mCurrentOrigin,
+ getAllowedCallback);
+ }
+ }
+ });
+ }
+ }
+ });
+ }
+
+ public void onTabDataChanged(Tab tab) {
+ long tabId = tab.getId();
+ String origin = GeolocationPermissions.getOriginFromUrl(tab.getUrl());
+ boolean incognito = tab.isPrivateBrowsingEnabled();
+
+ 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.registerOnGeolocationPolicyModifiedListener(this);
+ }
+ update();
+ }
+ // 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 = origin;
+ update();
+ }
+ }
+
+ public void update() {
+ if (mCurrentOrigin != null) {
+ mGeolocationPermissions.hasOrigin(mCurrentOrigin,
+ new ValueCallback<Boolean>() {
+ public void onReceiveValue(Boolean hasOrigin) {
+ if (hasOrigin != null && hasOrigin.booleanValue()) {
+ mGeolocationPermissions.getAllowed(mCurrentOrigin,
+ new ValueCallback<Boolean>() {
+ public void onReceiveValue(Boolean allowed) {
+ if (allowed != null) {
+ if (allowed.booleanValue()) {
+ LocationButton.this.setImageResource(R.drawable.ic_gps_on_holo_dark);
+ LocationButton.this.setVisibility(VISIBLE);
+ } else {
+ LocationButton.this.setImageResource(R.drawable.ic_gps_denied_holo_dark);
+ LocationButton.this.setVisibility(VISIBLE);
+ }
+ }
+ }
+ });
+ } else {
+ LocationButton.this.setVisibility(GONE);
+ }
+ }
+ });
+ } else {
+ this.setVisibility(GONE);
+ }
+ }
+
+ @Override
+ public void onGeolocationPolicyAdded(String origin, boolean allow) {
+ if (mCurrentOrigin != null && mCurrentOrigin.equals(origin)) {
+ this.setImageResource(allow ? R.drawable.ic_gps_on_holo_dark :
+ R.drawable.ic_gps_denied_holo_dark);
+ this.setVisibility(VISIBLE);
+ }
+ }
+
+ @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/MemoryMonitor.java b/src/com/android/browser/MemoryMonitor.java
index a18f698a..36c714fe 100644
--- a/src/com/android/browser/MemoryMonitor.java
+++ b/src/com/android/browser/MemoryMonitor.java
@@ -32,85 +32,48 @@ package com.android.browser;
import android.app.ActivityManager;
import android.content.Context;
-import android.util.Log;
import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
public class MemoryMonitor {
- //This number is used with device memory class to calculate max number
- //of active tabs.
- private static int sMaxActiveTabs = 0;
- private static MemoryMonitor sMemoryMonitor;
- private TabControl mTabControl;
- private final static String LOGTAG = "MemoryMonitor";
-
- // Should be called only once
-
- public static MemoryMonitor getInstance(Context context,
- Controller controller) {
- if (sMemoryMonitor == null) {
- sMemoryMonitor = new MemoryMonitor(context,controller);
- }
- return sMemoryMonitor;
- }
-
- MemoryMonitor(Context context,Controller controller) {
- mTabControl = controller.getTabControl();
- sMaxActiveTabs = getMaxActiveTabs(context);
- Log.d(LOGTAG,"Max Active Tabs: "+ sMaxActiveTabs);
- }
-
- private int getActiveTabs() {
- int numNativeActiveTab = 0;
- int size = mTabControl.getTabCount();
-
- for (int i = 0; i < size; i++) {
- Tab tab = mTabControl.getTab(i);
- if (((Tab)tab).isNativeActive()){
- numNativeActiveTab++;
- }
- }
- return numNativeActiveTab;
- }
-
/**
* if number of tabs whose native tab is active, is greater
* than MAX_ACTIVE_TABS destroy the nativetab of oldest used Tab
*/
+ public static void purgeActiveTabs(Context context,
+ Controller controller,
+ BrowserSettings settings) {
+ if(!settings.enableMemoryMonitor())
+ return;
- public void destroyLeastRecentlyActiveTab() {
- int numActiveTabs = getActiveTabs();
- int numActiveTabsToRelease = numActiveTabs - sMaxActiveTabs;
+ int maxActiveTabs = getMaxActiveTabs(context);
+ TabControl tabControl = controller.getTabControl();
- // The most common case will be that we need to delete one
- // NativeTab to make room for a new one. So, find the most-stale.
- if (numActiveTabsToRelease == 1) {
- Tab mostStaleTab = null;
- for (Tab t : mTabControl.getTabs()) {
- if (t.isNativeActive() && !(t.inForeground())) {
- if (mostStaleTab == null){
- mostStaleTab = t;
- }
- else {
- if (t.getTimestamp().compareTo(mostStaleTab.
- getTimestamp()) < 0) {
- mostStaleTab = t;
- }
- }
- }
- }
- if (mostStaleTab != null) {
- mostStaleTab.destroy();
- }
- } else if (numActiveTabsToRelease > 1) {
- // Since there is more than 1 "extra" tab, just release all
- // NativeTabs in the background. This would be true when
- // tracking was turned on after multiple tabs already exists
- for (Tab t : mTabControl.getTabs()) {
- if (t.isNativeActive() && !(t.inForeground())) {
- t.destroy();
- }
+ ArrayList<Tab> activeTabList = new ArrayList<Tab>();
+
+ for (int i = 0; i < tabControl.getTabCount(); i++) {
+ Tab tab = tabControl.getTab(i);
+ if(tab.isNativeActive())
+ activeTabList.add(tab);
+ }
+
+ int numActiveTabsToRelease = activeTabList.size() - maxActiveTabs;
+
+ if(numActiveTabsToRelease < 1)
+ return;
+ // sort tabs in order of LRU first
+ Collections.sort(activeTabList, new Comparator<Tab>() {
+ @Override
+ public int compare(Tab tab1, Tab tab2) {
+ return tab1.getTimestamp().compareTo(tab2.getTimestamp());
}
+ });
+
+ for(int i = 0; i < numActiveTabsToRelease; i++) {
+ activeTabList.get(i).destroy();
}
}
@@ -118,7 +81,7 @@ public class MemoryMonitor {
* Returns the default max number of active tabs based on device's
* memory class.
*/
- static int getMaxActiveTabs(Context context) {
+ private static int getMaxActiveTabs(Context context) {
// We use device memory class to decide number of active tabs
// (minimum memory class is 16).
ActivityManager am =(ActivityManager)context.
diff --git a/src/com/android/browser/NavigationBarBase.java b/src/com/android/browser/NavigationBarBase.java
index da3f3da2..100e8d7e 100644
--- a/src/com/android/browser/NavigationBarBase.java
+++ b/src/com/android/browser/NavigationBarBase.java
@@ -53,10 +53,12 @@ public class NavigationBarBase extends LinearLayout implements
protected TitleBar mTitleBar;
protected UiController mUiController;
protected UrlInputView mUrlInput;
+ protected LocationButton mLocationButton;
private ImageView mFavicon;
private ImageView mLockIcon;
+
public NavigationBarBase(Context context) {
super(context);
}
@@ -73,6 +75,7 @@ public class NavigationBarBase extends LinearLayout implements
protected void onFinishInflate() {
super.onFinishInflate();
mLockIcon = (ImageView) findViewById(R.id.lock);
+ mLocationButton = (LocationButton) findViewById(R.id.location_button);
mFavicon = (ImageView) findViewById(R.id.favicon);
mUrlInput = (UrlInputView) findViewById(R.id.url);
mUrlInput.setUrlInputListener(this);
@@ -394,6 +397,7 @@ public class NavigationBarBase extends LinearLayout implements
}
public void onTabDataChanged(Tab tab) {
+ mLocationButton.onTabDataChanged(tab);
}
public void onVoiceResult(String s) {
diff --git a/src/com/android/browser/NavigationBarPhone.java b/src/com/android/browser/NavigationBarPhone.java
index a5257d1d..b6bd52c4 100644
--- a/src/com/android/browser/NavigationBarPhone.java
+++ b/src/com/android/browser/NavigationBarPhone.java
@@ -78,7 +78,7 @@ public class NavigationBarPhone extends NavigationBarBase implements
mMagnify = (ImageView) findViewById(R.id.magnify);
mTabSwitcher = findViewById(R.id.tab_switcher);
mTabSwitcher.setOnClickListener(this);
- mMore = findViewById(R.id.more);
+ mMore = findViewById(R.id.more_browser_settings);
mMore.setOnClickListener(this);
mComboIcon = findViewById(R.id.iconcombo);
mComboIcon.setOnClickListener(this);
diff --git a/src/com/android/browser/PhoneUi.java b/src/com/android/browser/PhoneUi.java
index 17de4647..d83d81db 100644
--- a/src/com/android/browser/PhoneUi.java
+++ b/src/com/android/browser/PhoneUi.java
@@ -25,6 +25,7 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
+import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.util.TypedValue;
@@ -57,6 +58,8 @@ public class PhoneUi extends BaseUi {
boolean mAnimating;
boolean mShowNav = false;
+ static final int POST_DELAY = 300;
+
/**
* @param browser
* @param controller
@@ -243,6 +246,14 @@ public class PhoneUi extends BaseUi {
@Override
public void onActionModeFinished(boolean inLoad) {
super.onActionModeFinished(inLoad);
+ mTitleBar.animate().translationY(0);
+ stopEditingUrl();
+ Handler handler = new Handler();
+ handler.postDelayed(new Runnable() {
+ public void run() {
+ mNavigationBar.onStateChanged(StateListener.STATE_NORMAL);
+ }}, POST_DELAY);
+
if (inLoad) {
if (mUseQuickControls) {
mTitleBar.setShowProgressOnly(true);
@@ -302,9 +313,6 @@ public class PhoneUi extends BaseUi {
int toRight = toLeft + width;
int toBottom = toTop + height;
float scaleFactor = width / (float) mContentView.getWidth();
- // SWE: Detaching the active tab results flashing screen with SWE.
- // Not detaching the tab doesn't seem to have any issues.
- //detachTab(mActiveTab);
mContentView.setVisibility(View.GONE);
AnimatorSet set1 = new AnimatorSet();
AnimatorSet inanim = new AnimatorSet();
@@ -378,7 +386,7 @@ public class PhoneUi extends BaseUi {
if (mAnimScreen == null) {
mAnimScreen = new AnimScreen(mActivity);
}
- mAnimScreen.set(tab.getScreenshot());
+ mAnimScreen.set(tab.getFullScreenshot());
if (mAnimScreen.mMain.getParent() == null) {
mCustomViewContainer.addView(mAnimScreen.mMain, COVER_SCREEN_PARAMS);
}
@@ -395,12 +403,12 @@ public class PhoneUi extends BaseUi {
toTop = (tab.getWebView() != null) ? tab.getWebView().getVisibleTitleHeight() : 0;
}
int toRight = mContentView.getWidth();
- int width = target.getDrawable().getIntrinsicWidth();
- int height = target.getDrawable().getIntrinsicHeight();
+ int width = mContentView.getWidth();
+ int height = mContentView.getHeight();
int fromLeft = tabview.getLeft() + target.getLeft() - mNavScreen.mScroller.getScrollX();
int fromTop = tabview.getTop() + target.getTop() - mNavScreen.mScroller.getScrollY();
- int fromRight = fromLeft + width;
- int fromBottom = fromTop + height;
+ int fromRight = fromLeft + target.getDrawable().getIntrinsicWidth();
+ int fromBottom = fromTop + target.getDrawable().getIntrinsicHeight();
float scaleFactor = mContentView.getWidth() / (float) width;
int toBottom = toTop + (int) (height * scaleFactor);
mAnimScreen.mContent.setLeft(fromLeft);
@@ -437,37 +445,50 @@ public class PhoneUi extends BaseUi {
combo.start();
}
+
+ private int mNumTries = 0;
private void checkTabReady() {
boolean isready = true;
Tab tab = mUiController.getTabControl().getCurrentTab();
+ BrowserWebView webview = null;
if (tab == null)
isready = false;
else {
- BrowserWebView webview = (BrowserWebView)tab.getWebView();
- if (webview == null)
+ webview = (BrowserWebView)tab.getWebView();
+ if (webview == null) {
isready = false;
- else
+ }
+ else if (webview.hasCrashed()) {
+ webview.reload();
+ isready = true;
+ } else {
isready = webview.isReady();
+ }
}
- android.os.Handler handler = mCustomViewContainer.getHandler();
- if (!isready) {
- handler.postDelayed(new Runnable() {
+ // Post only when not ready and not crashed
+ if (!isready && mNumTries++ < 150) {
+ mCustomViewContainer.postDelayed(new Runnable() {
public void run() {
checkTabReady();
}
}, 17); //WebView is not ready. check again in for next frame.
return;
}
- handler.postDelayed(new Runnable() {
+ mNumTries = 0;
+ final boolean hasCrashed = (webview == null) ? false : webview.hasCrashed();
+ mCustomViewContainer.postDelayed(new Runnable() {
public void run() {
- fadeOutCustomViewContainer();
+ fadeOutCustomViewContainer(hasCrashed);
}
- }, 33); //WebView is ready, but give it extra 2 frame's time to display and finish the swaps
+ }, 33); //WebView is ready, but give it extra 2 frame's time to display and finish the swaps
}
- private void fadeOutCustomViewContainer() {
+ private void fadeOutCustomViewContainer(boolean hasCrashed) {
ObjectAnimator otheralpha = ObjectAnimator.ofFloat(mCustomViewContainer, "alpha", 1f, 0f);
- otheralpha.setDuration(100);
+ if (hasCrashed)
+ otheralpha.setDuration(300);
+ else
+ otheralpha.setDuration(100);
otheralpha.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator anim) {
diff --git a/src/com/android/browser/PreferenceKeys.java b/src/com/android/browser/PreferenceKeys.java
index 8620053e..5860cd46 100644
--- a/src/com/android/browser/PreferenceKeys.java
+++ b/src/com/android/browser/PreferenceKeys.java
@@ -100,6 +100,7 @@ public interface PreferenceKeys {
static final String PREF_REMEMBER_PASSWORDS = "remember_passwords";
static final String PREF_SAVE_FORMDATA = "save_formdata";
static final String PREF_SHOW_SECURITY_WARNINGS = "show_security_warnings";
+ static final String PREF_DO_NOT_TRACK = "do_not_track";
// ----------------------
// Keys for bandwidth_preferences.xml
diff --git a/src/com/android/browser/Tab.java b/src/com/android/browser/Tab.java
index 1b0b68c4..c9e785fc 100644
--- a/src/com/android/browser/Tab.java
+++ b/src/com/android/browser/Tab.java
@@ -175,6 +175,8 @@ class Tab implements PictureListener {
private String mAppId;
// flag to indicate if tab should be closed on back
private boolean mCloseOnBack;
+ // flag to indicate if the tab was opened from an intent
+ private boolean mDerivedFromIntent = false;
// Keep the original url around to avoid killing the old WebView if the url
// has not changed.
// Error console for the tab
@@ -185,6 +187,8 @@ class Tab implements PictureListener {
// Listener used to know when we move forward or back in the history list.
private final WebBackForwardListClient mWebBackForwardListClient;
private DataController mDataController;
+ //Indicates if a JS interface was created for a specific url
+ private boolean mJsInterfaceEnabled = false;
// AsyncTask for downloading touch icons
DownloadTouchIcon mTouchIconLoader;
@@ -193,6 +197,7 @@ class Tab implements PictureListener {
private int mCaptureWidth;
private int mCaptureHeight;
private Bitmap mCapture;
+ private Bitmap mScreenShot;
private Handler mHandler;
private boolean mUpdateThumbnail;
private Timestamp timestamp;
@@ -643,8 +648,10 @@ class Tab implements PictureListener {
@Override
public void onRendererCrash(WebView view, boolean crashedWhileOomProtected) {
Log.e(LOGTAG, "Tab Crashed");
- hasCrashed = true;
- showCrashView();
+ if (mWebViewController.getTabControl().getCurrentTab() == Tab.this) {
+ hasCrashed = true;
+ showCrashView();
+ }
}
/**
@@ -1538,6 +1545,7 @@ class Tab implements PictureListener {
}
void pause() {
+ capture();
if (mMainView != null) {
mMainView.onPause();
if (mSubView != null) {
@@ -1568,7 +1576,6 @@ class Tab implements PictureListener {
if (!mInForeground) {
return;
}
- capture();
mInForeground = false;
pause();
mMainView.setOnCreateContextMenuListener(null);
@@ -1676,6 +1683,14 @@ class Tab implements PictureListener {
mCloseOnBack = close;
}
+ boolean getDerivedFromIntent() {
+ return mDerivedFromIntent;
+ }
+
+ void setDerivedFromIntent(boolean derived) {
+ mDerivedFromIntent = derived;
+ }
+
String getUrl() {
return UrlUtils.filteredUrl(mCurrentState.mUrl);
}
@@ -1863,6 +1878,12 @@ class Tab implements PictureListener {
}
}
+ public Bitmap getFullScreenshot() {
+ synchronized (Tab.this) {
+ return mScreenShot;
+ }
+ }
+
public boolean isSnapshot() {
return false;
}
@@ -1950,11 +1971,27 @@ class Tab implements PictureListener {
mPageLoadProgress = INITIAL_PROGRESS;
mInPageLoad = true;
mCurrentState = new PageState(mContext, false, url, null);
+ handleJsInterface(mMainView, url);
mWebViewController.onPageStarted(this, mMainView, null);
mMainView.loadUrl(url, headers);
}
}
+ public void handleJsInterface(WebView webview, String url){
+ if (url != null &&
+ url.equals(mContext.getResources().getString(R.string.homepage_base)) &&
+ url.startsWith("file:///")) {
+ mJsInterfaceEnabled = true;
+ webview.getSettings().setJavaScriptEnabled(true);
+ webview.addJavascriptInterface(mContext, "default_homepage");
+ } else {
+ if (mJsInterfaceEnabled) {
+ webview.removeJavascriptInterface("default_homepage");
+ mJsInterfaceEnabled = false;
+ }
+ }
+ }
+
public void disableUrlOverridingForLoad() {
mDisableOverrideUrlLoading = true;
}
@@ -1966,19 +2003,32 @@ class Tab implements PictureListener {
}
Canvas c = new Canvas(mCapture);
int state = c.save();
+ float scale = 0;
Bitmap screenShot = mMainView.getViewportBitmap();
+ mScreenShot = screenShot;
if (screenShot != null) {
- mCapture.eraseColor(Color.WHITE);
- float scale = (float) mCaptureWidth / screenShot.getWidth();
- c.scale(scale, scale);
- c.drawBitmap(screenShot, 0, 0, null);
- } else {
- final int left = mMainView.getViewScrollX();
- final int top = mMainView.getViewScrollY() + mMainView.getVisibleTitleHeight();
- c.translate(-left, -top);
- float scale = mCaptureWidth / (float) mMainView.getWidth();
- c.scale(scale, scale, left, top);
- if (mMainView instanceof BrowserWebView) {
+ //scale based on device orientation
+ if (screenShot.getHeight() > screenShot.getWidth()){
+ scale = (float) mCaptureWidth / screenShot.getWidth();
+ } else {
+ scale = (float) mCaptureHeight / screenShot.getHeight();
+ }
+ mCapture.eraseColor(Color.WHITE);
+ c.scale(scale, scale);
+ c.drawBitmap(screenShot, 0, 0, null);
+ } else {
+ final int left = mMainView.getViewScrollX();
+ final int top = mMainView.getViewScrollY() + mMainView.getVisibleTitleHeight();
+
+ if (mMainView.getHeight() > mMainView.getWidth()){
+ scale = mCaptureWidth / (float) mMainView.getWidth();
+ } else {
+ scale = mCaptureHeight / (float) mMainView.getHeight();
+ }
+
+ c.translate(-left, -top);
+ c.scale(scale, scale, left, top);
+ if (mMainView instanceof BrowserWebView) {
((BrowserWebView)mMainView).drawContent(c);
} else {
mMainView.draw(c);
diff --git a/src/com/android/browser/TabControl.java b/src/com/android/browser/TabControl.java
index a9da8cf3..33f60ff3 100644
--- a/src/com/android/browser/TabControl.java
+++ b/src/com/android/browser/TabControl.java
@@ -19,6 +19,7 @@ package com.android.browser;
import android.os.Bundle;
import android.util.Log;
+import org.codeaurora.swe.GeolocationPermissions;
import org.codeaurora.swe.WebView;
import java.util.ArrayList;
@@ -50,6 +51,8 @@ class TabControl {
private int mCurrentTab = -1;
// the main browser controller
private final Controller mController;
+ // number of incognito tabs
+ private int mNumIncognito = 0;
private OnThumbnailUpdatedListener mOnThumbnailUpdatedListener;
@@ -204,6 +207,9 @@ class TabControl {
// Create a new tab and add it to the tab list
Tab t = new Tab(mController, w, state);
mTabs.add(t);
+ if (privateBrowsing) {
+ mNumIncognito += 1;
+ }
// Initially put the tab in the background.
t.putInBackground();
return t;
@@ -248,6 +254,14 @@ class TabControl {
// Remove t from our list of tabs.
mTabs.remove(t);
+ //Clear incognito geolocation state if this is the last incognito tab.
+ if (t.isPrivateBrowsingEnabled()) {
+ mNumIncognito -= 1;
+ if (mNumIncognito == 0) {
+ GeolocationPermissions.onIncognitoTabsRemoved();
+ }
+ }
+
// Put the tab in the background only if it is the current one.
if (current == t) {
t.putInBackground();
@@ -410,6 +424,9 @@ class TabControl {
// sNextId to be set correctly.
continue;
}
+ //handle restored pages that may require a JS interface
+ t.handleJsInterface(t.getWebView(), t.getUrl());
+
tabMap.put(id, t);
// Me must set the current tab before restoring the state
// so that all the client classes are set.
diff --git a/src/com/android/browser/UrlInputView.java b/src/com/android/browser/UrlInputView.java
index c8f2d401..f0037a12 100644
--- a/src/com/android/browser/UrlInputView.java
+++ b/src/com/android/browser/UrlInputView.java
@@ -71,6 +71,7 @@ public class UrlInputView extends AutoCompleteTextView
static final int POST_DELAY = 100;
static final int URL_MAX_LENGTH = 2048;
+ static final int POST_DELAY_FOCUS = 300;
static interface StateListener {
static final int STATE_NORMAL = 0;
@@ -181,11 +182,11 @@ public class UrlInputView extends AutoCompleteTextView
state = StateListener.STATE_NORMAL;
}
final int s = state;
- post(new Runnable() {
+ postDelayed(new Runnable() {
public void run() {
changeState(s);
}
- });
+ }, POST_DELAY_FOCUS);
}
@Override
diff --git a/src/com/android/browser/mynavigation/AddMyNavigationPage.java b/src/com/android/browser/mynavigation/AddMyNavigationPage.java
index e750aa2a..cc42d96a 100755
--- a/src/com/android/browser/mynavigation/AddMyNavigationPage.java
+++ b/src/com/android/browser/mynavigation/AddMyNavigationPage.java
@@ -77,11 +77,7 @@ public class AddMyNavigationPage extends Activity {
private View.OnClickListener mOKListener = new View.OnClickListener() {
public void onClick(View v) {
- if (save()) {
- AddMyNavigationPage.this.setResult(Activity.RESULT_OK,
- (new Intent()).putExtra("need_refresh", true));
- finish();
- }
+ save();
}
};
@@ -181,6 +177,8 @@ public class AddMyNavigationPage extends Activity {
Uri uri = ContentUris.withAppendedId(MyNavigationUtil.MY_NAVIGATION_URI,
cursor.getLong(0));
cr.update(uri, values, null, null);
+ AddMyNavigationPage.this.setResult(Activity.RESULT_OK,
+ (new Intent()).putExtra("need_refresh", true));
} else {
Log.e(LOGTAG, "this item does not exist!");
}
@@ -189,6 +187,7 @@ public class AddMyNavigationPage extends Activity {
} finally {
if (null != cursor) {
cursor.close();
+ AddMyNavigationPage.this.finish();
}
}
}
diff --git a/src/com/android/browser/preferences/WebsiteSettingsFragment.java b/src/com/android/browser/preferences/WebsiteSettingsFragment.java
index a621dece..38c19260 100644
--- a/src/com/android/browser/preferences/WebsiteSettingsFragment.java
+++ b/src/com/android/browser/preferences/WebsiteSettingsFragment.java
@@ -23,6 +23,8 @@ import android.content.DialogInterface;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
@@ -52,6 +54,7 @@ import java.util.Set;
import org.codeaurora.swe.GeolocationPermissions;
import org.codeaurora.swe.WebStorage;
+import org.json.JSONArray;
/**
* Manage the settings for an origin.
@@ -61,11 +64,15 @@ import org.codeaurora.swe.WebStorage;
public class WebsiteSettingsFragment extends ListFragment implements OnClickListener {
private static final String EXTRA_SITE = "site";
+ private static final long MILLIS_PER_DAY = 86400000;
private String LOGTAG = "WebsiteSettingsActivity";
private static String sMBStored = null;
private SiteAdapter mAdapter = null;
private Site mSite = null;
+ protected long geolocationPolicyExpiration;
+ protected boolean geolocationPolicyOriginAllowed;
+
static class Site implements Parcelable {
private String mOrigin;
private String mTitle;
@@ -601,22 +608,101 @@ public class WebsiteSettingsFragment extends ListFragment implements OnClickList
.show();
break;
case Site.FEATURE_GEOLOCATION:
- new AlertDialog.Builder(getContext())
- .setMessage(R.string.geolocation_settings_page_dialog_message)
+ final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
+ final String origin = mCurrentSite.getOrigin();
+ final GeolocationPermissions geolocationPermissions
+ = GeolocationPermissions.getInstance();
+
+ DialogInterface.OnClickListener alertDialogListener =
+ new AlertDialog.OnClickListener() {
+ public void onClick(DialogInterface dlg, int which) {
+ GeolocationPermissions geolocationPermissions =
+ GeolocationPermissions.getInstance();
+ String origin = mCurrentSite.getOrigin();
+ int selectedPosition = ((AlertDialog)dlg)
+ .getListView().getCheckedItemPosition();
+ switch (selectedPosition) {
+ case 0: // Deny forever
+ geolocationPermissions.deny(origin);
+ break;
+ case 1: // Allow for 24 hours
+ // encode the expiration time and origin as a JSON string
+ JSONArray jsonArray = new JSONArray();
+ jsonArray.put(System.currentTimeMillis() + MILLIS_PER_DAY);
+ jsonArray.put(origin);
+ geolocationPermissions.allow(jsonArray.toString());
+ break;
+ case 2: // Allow forever
+ geolocationPermissions.allow(origin);
+ break;
+ case 3: // Always ask
+ geolocationPermissions.clear(origin);
+ mCurrentSite.removeFeature(Site.FEATURE_GEOLOCATION);
+ if (mCurrentSite.getFeatureCount() == 0) {
+ finish();
+ }
+ break;
+ default:
+ break;
+ }
+ askForOrigins();
+ notifyDataSetChanged();
+ }};
+
+ builder.setTitle(String.format(getResources()
+ .getString(R.string.geolocation_settings_page_dialog_title),
+ "http".equals(Uri.parse(mCurrentSite.getOrigin()).getScheme()) ?
+ origin.substring(7) : origin ))
.setPositiveButton(R.string.geolocation_settings_page_dialog_ok_button,
- new AlertDialog.OnClickListener() {
- public void onClick(DialogInterface dlg, int which) {
- GeolocationPermissions.getInstance().clear(mCurrentSite.getOrigin());
- mCurrentSite.removeFeature(Site.FEATURE_GEOLOCATION);
- if (mCurrentSite.getFeatureCount() == 0) {
- finish();
+ alertDialogListener)
+ .setNegativeButton(R.string.geolocation_settings_page_dialog_cancel_button, null);
+
+ final ValueCallback<Long> getExpirationCallback =
+ new ValueCallback<Long>() {
+ public void onReceiveValue(Long expirationTime) {
+ if (expirationTime != null) {
+ geolocationPolicyExpiration = expirationTime.longValue();
+ // Set radio button and location icon
+ if (!geolocationPolicyOriginAllowed) {
+ // 0: Deny forever
+ builder.setSingleChoiceItems(R.array.geolocation_settings_choices, 0, null);
+ } else {
+ if (geolocationPolicyExpiration
+ != GeolocationPermissions.DO_NOT_EXPIRE) {
+ // 1: Allow for 24 hours
+ builder.setSingleChoiceItems(R.array.geolocation_settings_choices, 1, null);
+ } else {
+ // 2: Allow forever
+ builder.setSingleChoiceItems(R.array.geolocation_settings_choices, 2, null);
+ }
}
- askForOrigins();
- notifyDataSetChanged();
- }})
- .setNegativeButton(R.string.geolocation_settings_page_dialog_cancel_button, null)
- .setIconAttribute(android.R.attr.alertDialogIcon)
- .show();
+ }
+ builder.show();
+ }
+ };
+
+ final ValueCallback<Boolean> getAllowedCallback =
+ new ValueCallback<Boolean>() {
+ public void onReceiveValue(Boolean allowed) {
+ if (allowed != null) {
+ geolocationPolicyOriginAllowed = allowed.booleanValue();
+ //Get the policy expiration time
+ geolocationPermissions.getExpirationTime(origin,
+ getExpirationCallback);
+ }
+ }
+ };
+
+ geolocationPermissions.hasOrigin(origin,
+ new ValueCallback<Boolean>() {
+ public void onReceiveValue(Boolean hasOrigin) {
+ if (hasOrigin != null && hasOrigin.booleanValue()) {
+ //Get whether origin is allowed or denied
+ geolocationPermissions.getAllowed(origin,
+ getAllowedCallback);
+ }
+ }
+ });
break;
}
} else {
@@ -691,6 +777,9 @@ public class WebsiteSettingsFragment extends ListFragment implements OnClickList
public void onClick(DialogInterface dlg, int which) {
WebStorage.getInstance().deleteAllData();
GeolocationPermissions.getInstance().clearAll();
+ if (GeolocationPermissions.isIncognitoCreated()) {
+ GeolocationPermissions.getIncognitoInstance().clearAll();
+ }
WebStorageSizeManager.resetLastOutOfSpaceNotificationTime();
mAdapter.askForOrigins();
finish();
diff --git a/src_system/AndroidManifest.xml b/src_system/AndroidManifest.xml
index 000cf9d6..63a0cd1f 100644
--- a/src_system/AndroidManifest.xml
+++ b/src_system/AndroidManifest.xml
@@ -309,7 +309,8 @@
<provider
android:name=".provider.MyNavigationProvider"
android:authorities="com.android.browser.mynavigation"
- android:exported="false" />
+ android:exported="false"
+ android:grantUriPermissions="true"/>
<service android:name="org.chromium.content.app.SandboxedProcessService0"
android:process=":sandboxed_process0"