Index: chrome/android/java_staging/src/org/chromium/chrome/browser/webapps/WebappUrlBar.java |
diff --git a/chrome/android/java_staging/src/org/chromium/chrome/browser/webapps/WebappUrlBar.java b/chrome/android/java_staging/src/org/chromium/chrome/browser/webapps/WebappUrlBar.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..367a405ebc6a90fe214c1bc81b1134a82cb60388 |
--- /dev/null |
+++ b/chrome/android/java_staging/src/org/chromium/chrome/browser/webapps/WebappUrlBar.java |
@@ -0,0 +1,173 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+package org.chromium.chrome.browser.webapps; |
+ |
+import android.content.Context; |
+import android.graphics.drawable.Drawable; |
+import android.text.Layout; |
+import android.text.TextUtils; |
+import android.text.method.ScrollingMovementMethod; |
+import android.util.AttributeSet; |
+import android.util.Log; |
+import android.util.SparseIntArray; |
+import android.view.Gravity; |
+import android.view.View; |
+import android.view.ViewGroup; |
+import android.widget.FrameLayout; |
+import android.widget.TextView; |
+ |
+import com.google.android.apps.chrome.R; |
+ |
+import org.chromium.base.ApiCompatibilityUtils; |
+import org.chromium.base.VisibleForTesting; |
+import org.chromium.chrome.browser.UrlUtilities; |
+import org.chromium.chrome.browser.omnibox.LocationBarLayout; |
+ |
+import java.net.URI; |
+ |
+/** |
+ * Maintains a URL bar that is displayed above the webapp's content. |
+ * For security reasons, this bar will appear when a user navigates to a website that is not |
+ * considered the same as the one that was used to open a WebappActivity originally. |
+ * The URL bar will disappear again once the user navigates back to the original website. |
+ * |
+ * Example scenario: |
+ * 0) User opens a webapp for http://domain1.com. URL bar is hidden |
+ * 1) User navigates to http://domain1.com/some.html URL bar is hidden |
+ * 2) User navigates to http://domain2.com/ URL bar is shown |
+ * 3) User navigates back to http://domain1.com/some.html URL bar is hidden |
+ */ |
+public class WebappUrlBar extends FrameLayout implements View.OnLayoutChangeListener { |
+ private static final String TAG = "WebappUrlBar"; |
+ |
+ private final TextView mUrlBar; |
+ private final View mSeparator; |
+ private final SparseIntArray mIconResourceWidths; |
+ |
+ private String mCurrentlyDisplayedUrl; |
+ private int mCurrentIconResource; |
+ |
+ /** |
+ * Creates a WebappUrlBar. |
+ * @param context Context to grab resources from. |
+ */ |
+ public WebappUrlBar(Context context, AttributeSet attrSet) { |
+ super(context, attrSet); |
+ mIconResourceWidths = new SparseIntArray(); |
+ |
+ mUrlBar = new TextView(context); |
+ mUrlBar.setSingleLine(true); |
+ mUrlBar.setMovementMethod(ScrollingMovementMethod.getInstance()); |
+ mUrlBar.setHorizontalFadingEdgeEnabled(true); |
+ mSeparator = new View(context); |
+ |
+ addView(mUrlBar, |
+ new FrameLayout.LayoutParams( |
+ ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, |
+ Gravity.CENTER)); |
+ addView(mSeparator, |
+ new FrameLayout.LayoutParams( |
+ ViewGroup.LayoutParams.MATCH_PARENT, 1, Gravity.BOTTOM)); |
+ |
+ // Set the colors. |
+ mSeparator.setBackgroundColor( |
+ context.getResources().getColor(R.color.webapp_url_bar_separator)); |
+ setBackgroundColor(context.getResources().getColor(R.color.webapp_url_bar_bg)); |
+ |
+ // Listen for changes in the URL bar's size. |
+ mUrlBar.addOnLayoutChangeListener(this); |
+ } |
+ |
+ /** |
+ * Updates the URL bar for the current URL. |
+ * @param url URL to display. |
+ * @param securityLevel Security level of the Tab. |
+ */ |
+ public void update(String url, int securityLevel) { |
+ URI uri = createURI(url); |
+ updateSecurityIcon(securityLevel); |
+ updateDisplayedUrl(url, uri); |
+ } |
+ |
+ /** |
+ * @return the security icon being displayed for the current URL. |
+ */ |
+ @VisibleForTesting |
+ protected int getCurrentIconResourceForTests() { |
+ return mCurrentIconResource; |
+ } |
+ |
+ /** |
+ * @return the URL being displayed. |
+ */ |
+ @VisibleForTesting |
+ protected CharSequence getDisplayedUrlForTests() { |
+ return mUrlBar.getText(); |
+ } |
+ |
+ /** |
+ * Show the end of the URL rather than the beginning. |
+ */ |
+ @Override |
+ public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, |
+ int oldTop, int oldRight, int oldBottom) { |
+ Layout layout = mUrlBar.getLayout(); |
+ if (layout == null) return; |
+ |
+ // Android doesn't account for the compound Drawable in its width calculations, leading to |
+ // improper scrolling and even Android improperly placing the horizontal fade in its |
+ // TextView calculation. Get around it by calculating that width manually: crbug.com/303908 |
+ int urlBarWidth = mUrlBar.getWidth(); |
+ int iconWidth = |
+ mCurrentIconResource == 0 ? 0 : mIconResourceWidths.get(mCurrentIconResource); |
+ int availableTextWidth = urlBarWidth - iconWidth; |
+ int desiredWidth = (int) Layout.getDesiredWidth(layout.getText(), layout.getPaint()); |
+ |
+ if (desiredWidth > availableTextWidth) { |
+ mUrlBar.scrollTo(desiredWidth - availableTextWidth, 0); |
+ } else { |
+ mUrlBar.scrollTo(0, 0); |
+ } |
+ } |
+ |
+ private static URI createURI(String url) { |
+ // Get rid of spaces temporarily: crbug.com/298465 |
+ // Get rid of the need for this hack eventually: crbug.com/296870 |
+ url = url.replace(" ", "%20"); |
+ |
+ try { |
+ return URI.create(url); |
+ } catch (IllegalArgumentException exception) { |
+ Log.e(TAG, "Failed to convert URI: ", exception); |
+ return null; |
+ } |
+ } |
+ |
+ private void updateSecurityIcon(int securityLevel) { |
+ mCurrentIconResource = LocationBarLayout.getSecurityIconResource(securityLevel, false); |
+ |
+ if (mCurrentIconResource != 0 && mIconResourceWidths.get(mCurrentIconResource, -1) == -1) { |
+ Drawable icon = ApiCompatibilityUtils.getDrawable(getResources(), mCurrentIconResource); |
+ mIconResourceWidths.put(mCurrentIconResource, icon.getIntrinsicWidth()); |
+ } |
+ |
+ ApiCompatibilityUtils.setCompoundDrawablesRelativeWithIntrinsicBounds(mUrlBar, |
+ mCurrentIconResource, 0, 0, 0); |
+ } |
+ |
+ private void updateDisplayedUrl(String originalUrl, URI uri) { |
+ boolean showScheme = mCurrentIconResource == 0; |
+ String displayUrl = originalUrl; |
+ if (uri != null) { |
+ String shortenedUrl = UrlUtilities.getOriginForDisplay(uri, showScheme); |
+ if (!TextUtils.isEmpty(shortenedUrl)) displayUrl = shortenedUrl; |
+ } |
+ |
+ mUrlBar.setText(displayUrl); |
+ if (!TextUtils.equals(mCurrentlyDisplayedUrl, displayUrl)) { |
+ mCurrentlyDisplayedUrl = displayUrl; |
+ } |
+ } |
+} |