| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chrome.browser; | 5 package org.chromium.chrome.browser; |
| 6 | 6 |
| 7 import android.app.Dialog; | 7 import android.app.Dialog; |
| 8 import android.content.Context; | 8 import android.content.Context; |
| 9 import android.content.DialogInterface; | 9 import android.content.DialogInterface; |
| 10 import android.graphics.Color; | 10 import android.graphics.Color; |
| 11 import android.graphics.drawable.ColorDrawable; | 11 import android.graphics.drawable.ColorDrawable; |
| 12 import android.net.Uri; | |
| 13 import android.text.Layout; | 12 import android.text.Layout; |
| 14 import android.text.Spannable; | 13 import android.text.Spannable; |
| 15 import android.text.SpannableStringBuilder; | 14 import android.text.SpannableStringBuilder; |
| 16 import android.text.style.ForegroundColorSpan; | 15 import android.text.style.ForegroundColorSpan; |
| 17 import android.text.style.StyleSpan; | 16 import android.text.style.StyleSpan; |
| 18 import android.util.AttributeSet; | 17 import android.util.AttributeSet; |
| 19 import android.view.Gravity; | 18 import android.view.Gravity; |
| 20 import android.view.LayoutInflater; | 19 import android.view.LayoutInflater; |
| 21 import android.view.View; | 20 import android.view.View; |
| 22 import android.view.View.OnClickListener; | 21 import android.view.View.OnClickListener; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 68 this.type = type; | 67 this.type = type; |
| 69 this.value = value; | 68 this.value = value; |
| 70 } | 69 } |
| 71 | 70 |
| 72 @Override | 71 @Override |
| 73 public String toString() { | 72 public String toString() { |
| 74 return name; | 73 return name; |
| 75 } | 74 } |
| 76 } | 75 } |
| 77 | 76 |
| 77 /** |
| 78 * A TextView which truncates and displays a URL such that the origin is alw
ays visible. |
| 79 * The URL can be expanded by clicking on the it. |
| 80 */ |
| 78 public static class ElidedUrlTextView extends TextView { | 81 public static class ElidedUrlTextView extends TextView { |
| 79 // The number of lines to display when the URL is truncated. This number | 82 // The number of lines to display when the URL is truncated. This number |
| 80 // should still allow the origin to be displayed. NULL before | 83 // should still allow the origin to be displayed. NULL before |
| 81 // setUrlAfterLayout() is called. | 84 // setUrlAfterLayout() is called. |
| 82 private Integer mTruncatedUrlLinesToDisplay; | 85 private Integer mTruncatedUrlLinesToDisplay; |
| 83 | 86 |
| 87 // The number of lines to display when the URL is expanded. This should
be enough to display |
| 88 // at most two lines of the fragment if there is one in the URL. |
| 89 private Integer mFullLinesToDisplay; |
| 90 |
| 84 // If true, the text view will show the truncated text. If false, it | 91 // If true, the text view will show the truncated text. If false, it |
| 85 // will show the full, expanded text. | 92 // will show the full, expanded text. |
| 86 private boolean mIsShowingTruncatedText = true; | 93 private boolean mIsShowingTruncatedText = true; |
| 87 | 94 |
| 88 // The profile to use when getting the end index for the origin. | 95 // The profile to use when getting the end index for the origin. |
| 89 private Profile mProfile = null; | 96 private Profile mProfile = null; |
| 90 | 97 |
| 91 // The maximum number of lines currently shown in the view | 98 // The maximum number of lines currently shown in the view |
| 92 private int mCurrentMaxLines = Integer.MAX_VALUE; | 99 private int mCurrentMaxLines = Integer.MAX_VALUE; |
| 93 | 100 |
| 94 /** Constructor for inflating from XML. */ | 101 /** Constructor for inflating from XML. */ |
| 95 public ElidedUrlTextView(Context context, AttributeSet attrs) { | 102 public ElidedUrlTextView(Context context, AttributeSet attrs) { |
| 96 super(context, attrs); | 103 super(context, attrs); |
| 97 } | 104 } |
| 98 | 105 |
| 99 @Override | 106 @Override |
| 100 public void setMaxLines(int maxlines) { | 107 public void setMaxLines(int maxlines) { |
| 101 super.setMaxLines(maxlines); | 108 super.setMaxLines(maxlines); |
| 102 mCurrentMaxLines = maxlines; | 109 mCurrentMaxLines = maxlines; |
| 103 } | 110 } |
| 104 | 111 |
| 112 /** |
| 113 * Find the number of lines of text which must be shown in order to disp
lay the character at |
| 114 * a given index. |
| 115 */ |
| 116 private int getLineForIndex(int index) { |
| 117 Layout layout = getLayout(); |
| 118 int endLine = 0; |
| 119 while (endLine < layout.getLineCount() && layout.getLineEnd(endLine)
< index) { |
| 120 endLine++; |
| 121 } |
| 122 // Since endLine is an index, add 1 to get the number of lines. |
| 123 return endLine + 1; |
| 124 } |
| 125 |
| 105 @Override | 126 @Override |
| 106 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { | 127 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { |
| 107 setMaxLines(Integer.MAX_VALUE); | 128 setMaxLines(Integer.MAX_VALUE); |
| 108 super.onMeasure(widthMeasureSpec, heightMeasureSpec); | 129 super.onMeasure(widthMeasureSpec, heightMeasureSpec); |
| 109 assert mProfile != null : "setProfile() must be called before layout
."; | 130 assert mProfile != null : "setProfile() must be called before layout
."; |
| 131 String urlText = getText().toString(); |
| 110 | 132 |
| 111 // Lay out the URL in a StaticLayout that is the same size as our fi
nal | 133 // Lay out the URL in a StaticLayout that is the same size as our fi
nal |
| 112 // container. | 134 // container. |
| 113 Layout layout = getLayout(); | 135 int originEndIndex = OmniboxUrlEmphasizer.getOriginEndIndex(urlText,
mProfile); |
| 114 int originEndIndex = | |
| 115 OmniboxUrlEmphasizer.getOriginEndIndex(getText().toString(),
mProfile); | |
| 116 | 136 |
| 117 // Find the range of lines containing the origin. | 137 // Find the range of lines containing the origin. |
| 118 int originEndLineIndex = 0; | 138 int originEndLine = getLineForIndex(originEndIndex); |
| 119 while (originEndLineIndex < layout.getLineCount() | |
| 120 && layout.getLineEnd(originEndLineIndex) < originEndIndex) { | |
| 121 originEndLineIndex++; | |
| 122 } | |
| 123 | 139 |
| 124 // Display an extra line so we don't accidentally hide the origin wi
th | 140 // Display an extra line so we don't accidentally hide the origin wi
th |
| 125 // ellipses | 141 // ellipses |
| 126 int lastLineIndexToDisplay = originEndLineIndex + 1; | 142 mTruncatedUrlLinesToDisplay = originEndLine + 1; |
| 127 | 143 |
| 128 // Since lastLineToDisplay is an index, add 1 to get the maximum num
ber | 144 // Find the line where the fragment starts. Since # is a reserved ch
aracter, it is safe |
| 129 // of lines. This will always be at least 2 lines (when the origin i
s | 145 // to just search for the first # to appear in the url. |
| 130 // fully contained on line 0). | 146 int fragmentStartIndex = urlText.indexOf('#'); |
| 131 mTruncatedUrlLinesToDisplay = lastLineIndexToDisplay + 1; | 147 if (fragmentStartIndex == -1) fragmentStartIndex = urlText.length(); |
| 148 |
| 149 int fragmentStartLine = getLineForIndex(fragmentStartIndex); |
| 150 mFullLinesToDisplay = fragmentStartLine + 1; |
| 151 |
| 152 // If there is no origin (according to OmniboxUrlEmphasizer), make s
ure the fragment is |
| 153 // still hidden correctly. |
| 154 if (mFullLinesToDisplay < mTruncatedUrlLinesToDisplay) { |
| 155 mTruncatedUrlLinesToDisplay = mFullLinesToDisplay; |
| 156 } |
| 132 | 157 |
| 133 if (updateMaxLines()) super.onMeasure(widthMeasureSpec, heightMeasur
eSpec); | 158 if (updateMaxLines()) super.onMeasure(widthMeasureSpec, heightMeasur
eSpec); |
| 134 } | 159 } |
| 135 | 160 |
| 136 /** | 161 /** |
| 137 * Sets the profile to use when calculating the end index of the origin. | 162 * Sets the profile to use when calculating the end index of the origin. |
| 138 * Must be called before layout. | 163 * Must be called before layout. |
| 139 * | 164 * |
| 140 * @param profile The profile to use when coloring the URL. | 165 * @param profile The profile to use when coloring the URL. |
| 141 */ | 166 */ |
| 142 public void setProfile(Profile profile) { | 167 public void setProfile(Profile profile) { |
| 143 mProfile = profile; | 168 mProfile = profile; |
| 144 } | 169 } |
| 145 | 170 |
| 146 /** | 171 /** |
| 147 * Toggles truncating/expanding the URL text. If the URL text is not | 172 * Toggles truncating/expanding the URL text. If the URL text is not |
| 148 * truncated, has no effect. | 173 * truncated, has no effect. |
| 149 */ | 174 */ |
| 150 public void toggleTruncation() { | 175 public void toggleTruncation() { |
| 151 mIsShowingTruncatedText = !mIsShowingTruncatedText; | 176 mIsShowingTruncatedText = !mIsShowingTruncatedText; |
| 152 updateMaxLines(); | 177 updateMaxLines(); |
| 153 } | 178 } |
| 154 | 179 |
| 155 private boolean updateMaxLines() { | 180 private boolean updateMaxLines() { |
| 156 int maxLines = Integer.MAX_VALUE; | 181 int maxLines = mFullLinesToDisplay; |
| 157 if (mIsShowingTruncatedText) maxLines = mTruncatedUrlLinesToDisplay; | 182 if (mIsShowingTruncatedText) maxLines = mTruncatedUrlLinesToDisplay; |
| 158 if (maxLines != mCurrentMaxLines) { | 183 if (maxLines != mCurrentMaxLines) { |
| 159 setMaxLines(maxLines); | 184 setMaxLines(maxLines); |
| 160 return true; | 185 return true; |
| 161 } | 186 } |
| 162 return false; | 187 return false; |
| 163 } | 188 } |
| 164 } | 189 } |
| 165 | 190 |
| 166 private static final int MAX_TABLET_DIALOG_WIDTH_DP = 400; | 191 private static final int MAX_TABLET_DIALOG_WIDTH_DP = 400; |
| 167 | 192 |
| 168 private static final char FIRST_UNICODE_WHITESPACE = '\u2000'; | |
| 169 private static final char FINAL_UNICODE_WHITESPACE = '\u200F'; | |
| 170 private static final char UNICODE_NBSP = '\u00A0'; | |
| 171 | |
| 172 private final Context mContext; | 193 private final Context mContext; |
| 173 private final Profile mProfile; | 194 private final Profile mProfile; |
| 174 private final WebContents mWebContents; | 195 private final WebContents mWebContents; |
| 175 | 196 |
| 176 // A pointer to the C++ object for this UI. | 197 // A pointer to the C++ object for this UI. |
| 177 private final long mNativeWebsiteSettingsPopup; | 198 private final long mNativeWebsiteSettingsPopup; |
| 178 | 199 |
| 179 // The outer container, filled with the layout from website_settings.xml. | 200 // The outer container, filled with the layout from website_settings.xml. |
| 180 private final LinearLayout mContainer; | 201 private final LinearLayout mContainer; |
| 181 | 202 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 try { | 312 try { |
| 292 mParsedUrl = new URI(mFullUrl); | 313 mParsedUrl = new URI(mFullUrl); |
| 293 mIsInternalPage = UrlUtilities.isInternalScheme(mParsedUrl); | 314 mIsInternalPage = UrlUtilities.isInternalScheme(mParsedUrl); |
| 294 } catch (URISyntaxException e) { | 315 } catch (URISyntaxException e) { |
| 295 mParsedUrl = null; | 316 mParsedUrl = null; |
| 296 mIsInternalPage = false; | 317 mIsInternalPage = false; |
| 297 } | 318 } |
| 298 mSecurityLevel = ToolbarModel.getSecurityLevelForWebContents(mWebContent
s); | 319 mSecurityLevel = ToolbarModel.getSecurityLevelForWebContents(mWebContent
s); |
| 299 mDeprecatedSHA1Present = ToolbarModel.isDeprecatedSHA1Present(mWebConten
ts); | 320 mDeprecatedSHA1Present = ToolbarModel.isDeprecatedSHA1Present(mWebConten
ts); |
| 300 | 321 |
| 301 String displayUrl = prepareUrlForDisplay(mFullUrl); | 322 SpannableStringBuilder urlBuilder = new SpannableStringBuilder(mFullUrl)
; |
| 302 SpannableStringBuilder urlBuilder = new SpannableStringBuilder(displayUr
l); | |
| 303 OmniboxUrlEmphasizer.emphasizeUrl(urlBuilder, mContext.getResources(), m
Profile, | 323 OmniboxUrlEmphasizer.emphasizeUrl(urlBuilder, mContext.getResources(), m
Profile, |
| 304 mSecurityLevel, mIsInternalPage, true); | 324 mSecurityLevel, mIsInternalPage, true); |
| 305 mUrlTitle.setText(urlBuilder); | 325 mUrlTitle.setText(urlBuilder); |
| 306 | 326 |
| 307 // Set the URL connection message now, and the URL after layout (so it | 327 // Set the URL connection message now, and the URL after layout (so it |
| 308 // can calculate its ideal height). | 328 // can calculate its ideal height). |
| 309 mUrlConnectionMessage.setText(getUrlConnectionMessage()); | 329 mUrlConnectionMessage.setText(getUrlConnectionMessage()); |
| 310 } | 330 } |
| 311 | 331 |
| 312 /** | 332 /** |
| 313 * Percent-encodes suspicious Unicode whitespace characters in a URL so that
it can be safely | |
| 314 * displayed. | |
| 315 */ | |
| 316 public static String prepareUrlForDisplay(String urlStr) { | |
| 317 StringBuilder urlBuilder = new StringBuilder(); | |
| 318 for (int i = 0; i < urlStr.length(); i++) { | |
| 319 char c = urlStr.charAt(i); | |
| 320 if ((c >= FIRST_UNICODE_WHITESPACE | |
| 321 && c <= FINAL_UNICODE_WHITESPACE) | |
| 322 || c == ' ' | |
| 323 || c == UNICODE_NBSP) { | |
| 324 urlBuilder.append(Uri.encode(Character.toString(c))); | |
| 325 } else { | |
| 326 urlBuilder.append(c); | |
| 327 } | |
| 328 } | |
| 329 return urlBuilder.toString(); | |
| 330 } | |
| 331 | |
| 332 /** | |
| 333 * Sets the visibility of the lower area of the dialog (containing the permi
ssions and 'Site | 333 * Sets the visibility of the lower area of the dialog (containing the permi
ssions and 'Site |
| 334 * Settings' button). | 334 * Settings' button). |
| 335 * | 335 * |
| 336 * @param isVisible Whether to show or hide the dialog area. | 336 * @param isVisible Whether to show or hide the dialog area. |
| 337 */ | 337 */ |
| 338 private void setVisibilityOfLowerDialogArea(boolean isVisible) { | 338 private void setVisibilityOfLowerDialogArea(boolean isVisible) { |
| 339 mHorizontalSeparator.setVisibility(isVisible ? View.VISIBLE : View.GONE)
; | 339 mHorizontalSeparator.setVisibility(isVisible ? View.VISIBLE : View.GONE)
; |
| 340 mLowerDialogArea.setVisibility(isVisible ? View.VISIBLE : View.GONE); | 340 mLowerDialogArea.setVisibility(isVisible ? View.VISIBLE : View.GONE); |
| 341 } | 341 } |
| 342 | 342 |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 569 new WebsiteSettingsPopup(context, profile, webContents); | 569 new WebsiteSettingsPopup(context, profile, webContents); |
| 570 } | 570 } |
| 571 | 571 |
| 572 private static native long nativeInit(WebsiteSettingsPopup popup, WebContent
s webContents); | 572 private static native long nativeInit(WebsiteSettingsPopup popup, WebContent
s webContents); |
| 573 | 573 |
| 574 private native void nativeDestroy(long nativeWebsiteSettingsPopupAndroid); | 574 private native void nativeDestroy(long nativeWebsiteSettingsPopupAndroid); |
| 575 | 575 |
| 576 private native void nativeOnPermissionSettingChanged(long nativeWebsiteSetti
ngsPopupAndroid, | 576 private native void nativeOnPermissionSettingChanged(long nativeWebsiteSetti
ngsPopupAndroid, |
| 577 int type, int setting); | 577 int type, int setting); |
| 578 } | 578 } |
| OLD | NEW |