Chromium Code Reviews| 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 // Do not truncate a fragment in URLs which have no fragment or no o rigin (according to |
| 148 // OmniboxUrlEmphasizer). | |
| 149 if (fragmentStartIndex == -1 || fragmentStartIndex < originEndIndex) { | |
| 150 fragmentStartIndex = urlText.length(); | |
|
juhonurm
2015/04/15 06:07:57
Now the original issue is ignored in non-HTTP(S) U
tsergeant
2015/04/15 07:13:54
Done.
| |
| 151 } | |
| 152 | |
| 153 mFullLinesToDisplay = getLineForIndex(fragmentStartIndex) + 1; | |
| 132 | 154 |
| 133 if (updateMaxLines()) super.onMeasure(widthMeasureSpec, heightMeasur eSpec); | 155 if (updateMaxLines()) super.onMeasure(widthMeasureSpec, heightMeasur eSpec); |
| 134 } | 156 } |
| 135 | 157 |
| 136 /** | 158 /** |
| 137 * Sets the profile to use when calculating the end index of the origin. | 159 * Sets the profile to use when calculating the end index of the origin. |
| 138 * Must be called before layout. | 160 * Must be called before layout. |
| 139 * | 161 * |
| 140 * @param profile The profile to use when coloring the URL. | 162 * @param profile The profile to use when coloring the URL. |
| 141 */ | 163 */ |
| 142 public void setProfile(Profile profile) { | 164 public void setProfile(Profile profile) { |
| 143 mProfile = profile; | 165 mProfile = profile; |
| 144 } | 166 } |
| 145 | 167 |
| 146 /** | 168 /** |
| 147 * Toggles truncating/expanding the URL text. If the URL text is not | 169 * Toggles truncating/expanding the URL text. If the URL text is not |
| 148 * truncated, has no effect. | 170 * truncated, has no effect. |
| 149 */ | 171 */ |
| 150 public void toggleTruncation() { | 172 public void toggleTruncation() { |
| 151 mIsShowingTruncatedText = !mIsShowingTruncatedText; | 173 mIsShowingTruncatedText = !mIsShowingTruncatedText; |
| 152 updateMaxLines(); | 174 updateMaxLines(); |
| 153 } | 175 } |
| 154 | 176 |
| 155 private boolean updateMaxLines() { | 177 private boolean updateMaxLines() { |
| 156 int maxLines = Integer.MAX_VALUE; | 178 int maxLines = mFullLinesToDisplay; |
| 157 if (mIsShowingTruncatedText) maxLines = mTruncatedUrlLinesToDisplay; | 179 if (mIsShowingTruncatedText) maxLines = mTruncatedUrlLinesToDisplay; |
| 158 if (maxLines != mCurrentMaxLines) { | 180 if (maxLines != mCurrentMaxLines) { |
| 159 setMaxLines(maxLines); | 181 setMaxLines(maxLines); |
| 160 return true; | 182 return true; |
| 161 } | 183 } |
| 162 return false; | 184 return false; |
| 163 } | 185 } |
| 164 } | 186 } |
| 165 | 187 |
| 166 private static final int MAX_TABLET_DIALOG_WIDTH_DP = 400; | 188 private static final int MAX_TABLET_DIALOG_WIDTH_DP = 400; |
| 167 | 189 |
| 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; | 190 private final Context mContext; |
| 173 private final Profile mProfile; | 191 private final Profile mProfile; |
| 174 private final WebContents mWebContents; | 192 private final WebContents mWebContents; |
| 175 | 193 |
| 176 // A pointer to the C++ object for this UI. | 194 // A pointer to the C++ object for this UI. |
| 177 private final long mNativeWebsiteSettingsPopup; | 195 private final long mNativeWebsiteSettingsPopup; |
| 178 | 196 |
| 179 // The outer container, filled with the layout from website_settings.xml. | 197 // The outer container, filled with the layout from website_settings.xml. |
| 180 private final LinearLayout mContainer; | 198 private final LinearLayout mContainer; |
| 181 | 199 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 291 try { | 309 try { |
| 292 mParsedUrl = new URI(mFullUrl); | 310 mParsedUrl = new URI(mFullUrl); |
| 293 mIsInternalPage = UrlUtilities.isInternalScheme(mParsedUrl); | 311 mIsInternalPage = UrlUtilities.isInternalScheme(mParsedUrl); |
| 294 } catch (URISyntaxException e) { | 312 } catch (URISyntaxException e) { |
| 295 mParsedUrl = null; | 313 mParsedUrl = null; |
| 296 mIsInternalPage = false; | 314 mIsInternalPage = false; |
| 297 } | 315 } |
| 298 mSecurityLevel = ToolbarModel.getSecurityLevelForWebContents(mWebContent s); | 316 mSecurityLevel = ToolbarModel.getSecurityLevelForWebContents(mWebContent s); |
| 299 mDeprecatedSHA1Present = ToolbarModel.isDeprecatedSHA1Present(mWebConten ts); | 317 mDeprecatedSHA1Present = ToolbarModel.isDeprecatedSHA1Present(mWebConten ts); |
| 300 | 318 |
| 301 String displayUrl = prepareUrlForDisplay(mFullUrl); | 319 SpannableStringBuilder urlBuilder = new SpannableStringBuilder(mFullUrl) ; |
| 302 SpannableStringBuilder urlBuilder = new SpannableStringBuilder(displayUr l); | |
| 303 OmniboxUrlEmphasizer.emphasizeUrl(urlBuilder, mContext.getResources(), m Profile, | 320 OmniboxUrlEmphasizer.emphasizeUrl(urlBuilder, mContext.getResources(), m Profile, |
| 304 mSecurityLevel, mIsInternalPage, true); | 321 mSecurityLevel, mIsInternalPage, true); |
| 305 mUrlTitle.setText(urlBuilder); | 322 mUrlTitle.setText(urlBuilder); |
| 306 | 323 |
| 307 // Set the URL connection message now, and the URL after layout (so it | 324 // Set the URL connection message now, and the URL after layout (so it |
| 308 // can calculate its ideal height). | 325 // can calculate its ideal height). |
| 309 mUrlConnectionMessage.setText(getUrlConnectionMessage()); | 326 mUrlConnectionMessage.setText(getUrlConnectionMessage()); |
| 310 } | 327 } |
| 311 | 328 |
| 312 /** | 329 /** |
| 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 | 330 * Sets the visibility of the lower area of the dialog (containing the permi ssions and 'Site |
| 334 * Settings' button). | 331 * Settings' button). |
| 335 * | 332 * |
| 336 * @param isVisible Whether to show or hide the dialog area. | 333 * @param isVisible Whether to show or hide the dialog area. |
| 337 */ | 334 */ |
| 338 private void setVisibilityOfLowerDialogArea(boolean isVisible) { | 335 private void setVisibilityOfLowerDialogArea(boolean isVisible) { |
| 339 mHorizontalSeparator.setVisibility(isVisible ? View.VISIBLE : View.GONE) ; | 336 mHorizontalSeparator.setVisibility(isVisible ? View.VISIBLE : View.GONE) ; |
| 340 mLowerDialogArea.setVisibility(isVisible ? View.VISIBLE : View.GONE); | 337 mLowerDialogArea.setVisibility(isVisible ? View.VISIBLE : View.GONE); |
| 341 } | 338 } |
| 342 | 339 |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 569 new WebsiteSettingsPopup(context, profile, webContents); | 566 new WebsiteSettingsPopup(context, profile, webContents); |
| 570 } | 567 } |
| 571 | 568 |
| 572 private static native long nativeInit(WebsiteSettingsPopup popup, WebContent s webContents); | 569 private static native long nativeInit(WebsiteSettingsPopup popup, WebContent s webContents); |
| 573 | 570 |
| 574 private native void nativeDestroy(long nativeWebsiteSettingsPopupAndroid); | 571 private native void nativeDestroy(long nativeWebsiteSettingsPopupAndroid); |
| 575 | 572 |
| 576 private native void nativeOnPermissionSettingChanged(long nativeWebsiteSetti ngsPopupAndroid, | 573 private native void nativeOnPermissionSettingChanged(long nativeWebsiteSetti ngsPopupAndroid, |
| 577 int type, int setting); | 574 int type, int setting); |
| 578 } | 575 } |
| OLD | NEW |