diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/app/Notification.java | 127 | ||||
-rw-r--r-- | core/java/android/hardware/Sensor.java | 4 | ||||
-rw-r--r-- | core/java/android/view/SurfaceView.java | 1 | ||||
-rw-r--r-- | core/java/android/view/ViewGroupOverlay.java | 3 | ||||
-rw-r--r-- | core/java/android/view/ViewOverlay.java | 3 | ||||
-rw-r--r-- | core/java/android/view/WindowManager.java | 6 | ||||
-rw-r--r-- | core/java/android/webkit/CallbackProxy.java | 243 | ||||
-rw-r--r-- | core/java/android/webkit/JsDialogHelper.java | 185 | ||||
-rw-r--r-- | core/res/res/values/strings.xml | 11 | ||||
-rw-r--r-- | core/res/res/values/symbols.xml | 3 |
10 files changed, 331 insertions, 255 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index a7543a8..8d994c4 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -427,22 +427,48 @@ public class Notification implements Parcelable public String[] kind; /** - * Extra key for people values (type TBD). - * + * Additional semantic data to be carried around with this Notification. * @hide */ - public static final String EXTRA_PEOPLE = "android.people"; + public Bundle extras = new Bundle(); + + // extras keys for Builder inputs /** @hide */ public static final String EXTRA_TITLE = "android.title"; /** @hide */ + public static final String EXTRA_TITLE_BIG = EXTRA_TITLE + ".big"; + /** @hide */ public static final String EXTRA_TEXT = "android.text"; /** @hide */ - public static final String EXTRA_SUBTEXT = "android.subtext"; + public static final String EXTRA_SUB_TEXT = "android.subText"; + /** @hide */ + public static final String EXTRA_INFO_TEXT = "android.infoText"; + /** @hide */ + public static final String EXTRA_SUMMARY_TEXT = "android.summaryText"; /** @hide */ public static final String EXTRA_SMALL_ICON = "android.icon"; + /** @hide */ + public static final String EXTRA_LARGE_ICON = "android.largeIcon"; + /** @hide */ + public static final String EXTRA_LARGE_ICON_BIG = EXTRA_LARGE_ICON + ".big"; + /** @hide */ + public static final String EXTRA_PROGRESS = "android.progress"; + /** @hide */ + public static final String EXTRA_PROGRESS_MAX = "android.progressMax"; + /** @hide */ + public static final String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate"; + /** @hide */ + public static final String EXTRA_SHOW_CHRONOMETER = "android.showChronometer"; + /** @hide */ + public static final String EXTRA_SHOW_WHEN = "android.showWhen"; + /** @hide from BigPictureStyle */ + public static final String EXTRA_PICTURE = "android.picture"; + /** @hide from InboxStyle */ + public static final String EXTRA_TEXT_LINES = "android.textLines"; + // extras keys for other interesting pieces of information /** @hide */ - public Bundle extras = new Bundle(); + public static final String EXTRA_PEOPLE = "android.people"; /** * Structure to encapsulate an "action", including title and icon, that can be attached to a Notification. @@ -1621,16 +1647,26 @@ public class Notification implements Parcelable mActions.toArray(n.actions); } - n.extras = mExtras != null ? new Bundle(mExtras) : new Bundle(); + return n; + } + /** + * Capture, in the provided bundle, semantic information used in the construction of + * this Notification object. + * @hide + */ + public void addExtras(Bundle extras) { // Store original information used in the construction of this object - n.extras.putCharSequence(EXTRA_TITLE, mContentTitle); - n.extras.putCharSequence(EXTRA_TEXT, mContentText); - n.extras.putCharSequence(EXTRA_SUBTEXT, mSubText); - n.extras.putInt(EXTRA_SMALL_ICON, mSmallIcon); - //n.extras.putByteArray(EXTRA_LARGE_ICON, ... - - return n; + extras.putCharSequence(EXTRA_TITLE, mContentTitle); + extras.putCharSequence(EXTRA_TEXT, mContentText); + extras.putCharSequence(EXTRA_SUB_TEXT, mSubText); + extras.putCharSequence(EXTRA_INFO_TEXT, mContentInfo); + extras.putInt(EXTRA_SMALL_ICON, mSmallIcon); + extras.putInt(EXTRA_PROGRESS, mProgress); + extras.putInt(EXTRA_PROGRESS_MAX, mProgressMax); + extras.putBoolean(EXTRA_PROGRESS_INDETERMINATE, mProgressIndeterminate); + extras.putBoolean(EXTRA_SHOW_CHRONOMETER, mUseChronometer); + extras.putBoolean(EXTRA_SHOW_WHEN, mShowWhen); } /** @@ -1646,11 +1682,22 @@ public class Notification implements Parcelable * object. */ public Notification build() { + final Notification n; + if (mStyle != null) { - return mStyle.build(); + n = mStyle.build(); } else { - return buildUnstyled(); + n = buildUnstyled(); } + + n.extras = mExtras != null ? new Bundle(mExtras) : new Bundle(); + + addExtras(n.extras); + if (mStyle != null) { + mStyle.addExtras(n.extras); + } + + return n; } /** @@ -1664,7 +1711,6 @@ public class Notification implements Parcelable } } - /** * An object that can apply a rich notification style to a {@link Notification.Builder} * object. @@ -1739,6 +1785,18 @@ public class Notification implements Parcelable return contentView; } + /** + * @hide + */ + public void addExtras(Bundle extras) { + if (mSummaryTextSet) { + extras.putCharSequence(EXTRA_SUMMARY_TEXT, mSummaryText); + } + if (mBigContentTitle != null) { + extras.putCharSequence(EXTRA_TITLE_BIG, mBigContentTitle); + } + } + public abstract Notification build(); } @@ -1813,6 +1871,18 @@ public class Notification implements Parcelable return contentView; } + /** + * @hide + */ + public void addExtras(Bundle extras) { + super.addExtras(extras); + + if (mBigLargeIconSet) { + extras.putParcelable(EXTRA_LARGE_ICON_BIG, mBigLargeIcon); + } + extras.putParcelable(EXTRA_PICTURE, mPicture); + } + @Override public Notification build() { checkBuilder(); @@ -1878,6 +1948,15 @@ public class Notification implements Parcelable return this; } + /** + * @hide + */ + public void addExtras(Bundle extras) { + super.addExtras(extras); + + extras.putCharSequence(EXTRA_TEXT, mBigText); + } + private RemoteViews makeBigContentView() { // Remove the content text so line3 only shows if you have a summary final boolean hadThreeLines = (mBuilder.mContentText != null && mBuilder.mSubText != null); @@ -1964,6 +2043,15 @@ public class Notification implements Parcelable return this; } + /** + * @hide + */ + public void addExtras(Bundle extras) { + super.addExtras(extras); + CharSequence[] a = new CharSequence[mTexts.size()]; + extras.putCharSequenceArray(EXTRA_TEXT_LINES, mTexts.toArray(a)); + } + private RemoteViews makeBigContentView() { // Remove the content text so line3 disappears unless you have a summary mBuilder.mContentText = null; @@ -2005,13 +2093,6 @@ public class Notification implements Parcelable Notification wip = mBuilder.buildUnstyled(); wip.bigContentView = makeBigContentView(); - StringBuilder builder = new StringBuilder(); - for (CharSequence str : mTexts) { - builder.append(str); - builder.append("\n"); - } - wip.extras.putCharSequence(EXTRA_TEXT, builder); - return wip; } } diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java index 074f8fe..71a5382 100644 --- a/core/java/android/hardware/Sensor.java +++ b/core/java/android/hardware/Sensor.java @@ -188,6 +188,8 @@ public final class Sensor { // Upon detection of an event, the sensor deactivates itself and then sends a single event. static int REPORTING_MODE_ONE_SHOT = 3; + // TODO(): The following arrays are fragile and error-prone. This needs to be refactored. + // Note: This needs to be updated, whenever a new sensor is added. private static int[] sSensorReportingModes = { REPORTING_MODE_CONTINUOUS, REPORTING_MODE_CONTINUOUS, REPORTING_MODE_CONTINUOUS, @@ -201,7 +203,7 @@ public final class Sensor { // Holds the maximum length of the values array associated with {@link SensorEvent} or // {@link TriggerEvent} for the Sensor private static int[] sMaxLengthValuesArray = { - 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3, 6, 4, 6, 1 }; static int getReportingMode(Sensor sensor) { diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 5d0f523..14fa9cb 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -480,6 +480,7 @@ public class SurfaceView extends View { if (!getContext().getResources().getCompatibilityInfo().supportsScreen()) { mLayout.flags |= WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW; } + mLayout.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; if (mWindow == null) { Display display = getDisplay(); diff --git a/core/java/android/view/ViewGroupOverlay.java b/core/java/android/view/ViewGroupOverlay.java index c1b24f2..16afc5d 100644 --- a/core/java/android/view/ViewGroupOverlay.java +++ b/core/java/android/view/ViewGroupOverlay.java @@ -47,7 +47,8 @@ public class ViewGroupOverlay extends ViewOverlay { * animation effect.</p> * * <p>If the view has a parent, the view will be removed from that parent - * before being added to the overlay. Also, the view will be repositioned + * before being added to the overlay. Also, if that parent is attached + * in the current view hierarchy, the view will be repositioned * such that it is in the same relative location inside the activity. For * example, if the view's current parent lies 100 pixels to the right * and 200 pixels down from the origin of the overlay's diff --git a/core/java/android/view/ViewOverlay.java b/core/java/android/view/ViewOverlay.java index 78e2597..fe5b990 100644 --- a/core/java/android/view/ViewOverlay.java +++ b/core/java/android/view/ViewOverlay.java @@ -157,7 +157,8 @@ public class ViewOverlay { public void add(View child) { if (child.getParent() instanceof ViewGroup) { ViewGroup parent = (ViewGroup) child.getParent(); - if (parent != mHostView) { + if (parent != mHostView && parent.getParent() != null && + parent.mAttachInfo != null) { // Moving to different container; figure out how to position child such that // it is in the same location on the screen int[] parentLocation = new int[2]; diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 96ef0b4..48630a4 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1012,6 +1012,12 @@ public interface WindowManager extends ViewManager { public static final int PRIVATE_FLAG_FORCE_SHOW_NAV_BAR = 0x00000020; /** + * Never animate position changes of the window. + * + * {@hide} */ + public static final int PRIVATE_FLAG_NO_MOVE_ANIMATION = 0x00000040; + + /** * Control flags that are private to the platform. * @hide */ diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java index a326da2..312af71 100644 --- a/core/java/android/webkit/CallbackProxy.java +++ b/core/java/android/webkit/CallbackProxy.java @@ -17,10 +17,8 @@ package android.webkit; import android.app.Activity; -import android.app.AlertDialog; import android.content.ActivityNotFoundException; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; @@ -33,10 +31,6 @@ import android.os.SystemClock; import android.provider.Browser; import android.util.Log; import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.EditText; -import android.widget.TextView; import com.android.internal.R; import java.net.MalformedURLException; @@ -92,10 +86,7 @@ class CallbackProxy extends Handler { private static final int CREATE_WINDOW = 109; private static final int CLOSE_WINDOW = 110; private static final int SAVE_PASSWORD = 111; - private static final int JS_ALERT = 112; - private static final int JS_CONFIRM = 113; - private static final int JS_PROMPT = 114; - private static final int JS_UNLOAD = 115; + private static final int JS_DIALOG = 112; private static final int ASYNC_KEYEVENTS = 116; private static final int DOWNLOAD_FILE = 118; private static final int REPORT_ERROR = 119; @@ -566,188 +557,12 @@ class CallbackProxy extends Handler { } break; - case JS_ALERT: + case JS_DIALOG: if (mWebChromeClient != null) { final JsResultReceiver receiver = (JsResultReceiver) msg.obj; - final JsResult res = receiver.mJsResult; - String message = msg.getData().getString("message"); - String url = msg.getData().getString("url"); - if (!mWebChromeClient.onJsAlert(mWebView.getWebView(), url, message, - res)) { - if (!canShowAlertDialog()) { - res.cancel(); - receiver.setReady(); - break; - } - new AlertDialog.Builder(mContext) - .setTitle(getJsDialogTitle(url)) - .setMessage(message) - .setPositiveButton(R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick( - DialogInterface dialog, - int which) { - res.confirm(); - } - }) - .setOnCancelListener( - new DialogInterface.OnCancelListener() { - public void onCancel( - DialogInterface dialog) { - res.cancel(); - } - }) - .show(); - } - receiver.setReady(); - } - break; - - case JS_CONFIRM: - if (mWebChromeClient != null) { - final JsResultReceiver receiver = (JsResultReceiver) msg.obj; - final JsResult res = receiver.mJsResult; - String message = msg.getData().getString("message"); - String url = msg.getData().getString("url"); - if (!mWebChromeClient.onJsConfirm(mWebView.getWebView(), url, message, - res)) { - if (!canShowAlertDialog()) { - res.cancel(); - receiver.setReady(); - break; - } - new AlertDialog.Builder(mContext) - .setTitle(getJsDialogTitle(url)) - .setMessage(message) - .setPositiveButton(R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick( - DialogInterface dialog, - int which) { - res.confirm(); - }}) - .setNegativeButton(R.string.cancel, - new DialogInterface.OnClickListener() { - public void onClick( - DialogInterface dialog, - int which) { - res.cancel(); - }}) - .setOnCancelListener( - new DialogInterface.OnCancelListener() { - public void onCancel( - DialogInterface dialog) { - res.cancel(); - } - }) - .show(); - } - // Tell the JsResult that it is ready for client - // interaction. - receiver.setReady(); - } - break; - - case JS_PROMPT: - if (mWebChromeClient != null) { - final JsResultReceiver receiver = (JsResultReceiver) msg.obj; - final JsPromptResult res = receiver.mJsResult; - String message = msg.getData().getString("message"); - String defaultVal = msg.getData().getString("default"); - String url = msg.getData().getString("url"); - if (!mWebChromeClient.onJsPrompt(mWebView.getWebView(), url, message, - defaultVal, res)) { - if (!canShowAlertDialog()) { - res.cancel(); - receiver.setReady(); - break; - } - final LayoutInflater factory = LayoutInflater - .from(mContext); - final View view = factory.inflate(R.layout.js_prompt, - null); - final EditText v = (EditText) view - .findViewById(R.id.value); - v.setText(defaultVal); - ((TextView) view.findViewById(R.id.message)) - .setText(message); - new AlertDialog.Builder(mContext) - .setTitle(getJsDialogTitle(url)) - .setView(view) - .setPositiveButton(R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick( - DialogInterface dialog, - int whichButton) { - res.confirm(v.getText() - .toString()); - } - }) - .setNegativeButton(R.string.cancel, - new DialogInterface.OnClickListener() { - public void onClick( - DialogInterface dialog, - int whichButton) { - res.cancel(); - } - }) - .setOnCancelListener( - new DialogInterface.OnCancelListener() { - public void onCancel( - DialogInterface dialog) { - res.cancel(); - } - }) - .show(); - } - // Tell the JsResult that it is ready for client - // interaction. - receiver.setReady(); - } - break; - - case JS_UNLOAD: - if (mWebChromeClient != null) { - final JsResultReceiver receiver = (JsResultReceiver) msg.obj; - final JsResult res = receiver.mJsResult; - String message = msg.getData().getString("message"); - String url = msg.getData().getString("url"); - if (!mWebChromeClient.onJsBeforeUnload(mWebView.getWebView(), url, - message, res)) { - if (!canShowAlertDialog()) { - res.cancel(); - receiver.setReady(); - break; - } - final String m = mContext.getString( - R.string.js_dialog_before_unload, message); - new AlertDialog.Builder(mContext) - .setMessage(m) - .setPositiveButton(R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick( - DialogInterface dialog, - int which) { - res.confirm(); - } - }) - .setNegativeButton(R.string.cancel, - new DialogInterface.OnClickListener() { - public void onClick( - DialogInterface dialog, - int which) { - res.cancel(); - } - }) - .setOnCancelListener( - new DialogInterface.OnCancelListener() { - @Override - public void onCancel( - DialogInterface dialog) { - res.cancel(); - } - }) - .show(); + JsDialogHelper helper = new JsDialogHelper(receiver.mJsResult, msg); + if (!helper.invokeCallback(mWebChromeClient, mWebView.getWebView())) { + helper.showDialog(mContext); } receiver.setReady(); } @@ -757,7 +572,7 @@ class CallbackProxy extends Handler { if(mWebChromeClient != null) { final JsResultReceiver receiver = (JsResultReceiver) msg.obj; final JsResult res = receiver.mJsResult; - if(mWebChromeClient.onJsTimeout()) { + if (mWebChromeClient.onJsTimeout()) { res.confirm(); } else { res.cancel(); @@ -895,24 +710,6 @@ class CallbackProxy extends Handler { sendMessage(obtainMessage(SWITCH_OUT_HISTORY)); } - private String getJsDialogTitle(String url) { - String title = url; - if (URLUtil.isDataUrl(url)) { - // For data: urls, we just display 'JavaScript' similar to Safari. - title = mContext.getString(R.string.js_dialog_title_default); - } else { - try { - URL aUrl = new URL(url); - // For example: "The page at 'http://www.mit.edu' says:" - title = mContext.getString(R.string.js_dialog_title, - aUrl.getProtocol() + "://" + aUrl.getHost()); - } catch (MalformedURLException ex) { - // do nothing. just use the url as the title - } - } - return title; - } - //-------------------------------------------------------------------------- // WebViewClient functions. // NOTE: shouldOverrideKeyEvent is never called from the WebCore thread so @@ -1332,9 +1129,10 @@ class CallbackProxy extends Handler { return; } JsResultReceiver result = new JsResultReceiver(); - Message alert = obtainMessage(JS_ALERT, result); + Message alert = obtainMessage(JS_DIALOG, result); alert.getData().putString("message", message); alert.getData().putString("url", url); + alert.getData().putInt("type", JsDialogHelper.ALERT); sendMessageToUiThreadSync(alert); } @@ -1345,9 +1143,10 @@ class CallbackProxy extends Handler { return false; } JsResultReceiver result = new JsResultReceiver(); - Message confirm = obtainMessage(JS_CONFIRM, result); + Message confirm = obtainMessage(JS_DIALOG, result); confirm.getData().putString("message", message); confirm.getData().putString("url", url); + confirm.getData().putInt("type", JsDialogHelper.CONFIRM); sendMessageToUiThreadSync(confirm); return result.mJsResult.getResult(); } @@ -1359,10 +1158,11 @@ class CallbackProxy extends Handler { return null; } JsResultReceiver result = new JsResultReceiver(); - Message prompt = obtainMessage(JS_PROMPT, result); + Message prompt = obtainMessage(JS_DIALOG, result); prompt.getData().putString("message", message); prompt.getData().putString("default", defaultValue); prompt.getData().putString("url", url); + prompt.getData().putInt("type", JsDialogHelper.PROMPT); sendMessageToUiThreadSync(prompt); return result.mJsResult.getStringResult(); } @@ -1374,10 +1174,11 @@ class CallbackProxy extends Handler { return true; } JsResultReceiver result = new JsResultReceiver(); - Message confirm = obtainMessage(JS_UNLOAD, result); - confirm.getData().putString("message", message); - confirm.getData().putString("url", url); - sendMessageToUiThreadSync(confirm); + Message unload = obtainMessage(JS_DIALOG, result); + unload.getData().putString("message", message); + unload.getData().putString("url", url); + unload.getData().putInt("type", JsDialogHelper.UNLOAD); + sendMessageToUiThreadSync(unload); return result.mJsResult.getResult(); } @@ -1595,16 +1396,6 @@ class CallbackProxy extends Handler { sendMessage(msg); } - boolean canShowAlertDialog() { - // We can only display the alert dialog if mContext is - // an Activity context. - // FIXME: Should we display dialogs if mContext does - // not have the window focus (e.g. if the user is viewing - // another Activity when the alert should be displayed? - // See bug 3166409 - return mContext instanceof Activity; - } - private synchronized void sendMessageToUiThreadSync(Message msg) { sendMessage(msg); WebCoreThreadWatchdog.pause(); diff --git a/core/java/android/webkit/JsDialogHelper.java b/core/java/android/webkit/JsDialogHelper.java new file mode 100644 index 0000000..bb0339e --- /dev/null +++ b/core/java/android/webkit/JsDialogHelper.java @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.webkit; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Message; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; +import android.widget.TextView; + +import java.net.MalformedURLException; +import java.net.URL; + +/** + * Helper class to create JavaScript dialogs. It is used by + * different WebView implementations. + * + * @hide Helper class for internal use + */ +public class JsDialogHelper { + + private static final String TAG = "JsDialogHelper"; + + // Dialog types + public static final int ALERT = 1; + public static final int CONFIRM = 2; + public static final int PROMPT = 3; + public static final int UNLOAD = 4; + + private final String mDefaultValue; + private final JsPromptResult mResult; + private final String mMessage; + private final int mType; + private final String mUrl; + + public JsDialogHelper(JsPromptResult result, int type, String defaultValue, String message, + String url) { + mResult = result; + mDefaultValue = defaultValue; + mMessage = message; + mType = type; + mUrl = url; + } + + public JsDialogHelper(JsPromptResult result, Message msg) { + mResult = result; + mDefaultValue = msg.getData().getString("default"); + mMessage = msg.getData().getString("message"); + mType = msg.getData().getInt("type"); + mUrl = msg.getData().getString("url"); + } + + public boolean invokeCallback(WebChromeClient client, WebView webView) { + switch (mType) { + case ALERT: + return client.onJsAlert(webView, mUrl, mMessage, mResult); + case CONFIRM: + return client.onJsConfirm(webView, mUrl, mMessage, mResult); + case UNLOAD: + return client.onJsBeforeUnload(webView, mUrl, mMessage, mResult); + case PROMPT: + return client.onJsPrompt(webView, mUrl, mMessage, mDefaultValue, mResult); + default: + throw new IllegalArgumentException("Unexpected type: " + mType); + } + } + + public void showDialog(Context context) { + if (!canShowAlertDialog(context)) { + Log.w(TAG, "Cannot create a dialog, the WebView context is not an Activity"); + mResult.cancel(); + return; + } + + String title, displayMessage; + int positiveTextId, negativeTextId; + if (mType == UNLOAD) { + title = context.getString(com.android.internal.R.string.js_dialog_before_unload_title); + displayMessage = context.getString( + com.android.internal.R.string.js_dialog_before_unload, mMessage); + positiveTextId = com.android.internal.R.string.js_dialog_before_unload_positive_button; + negativeTextId = com.android.internal.R.string.js_dialog_before_unload_negative_button; + } else { + title = getJsDialogTitle(context); + displayMessage = mMessage; + positiveTextId = com.android.internal.R.string.ok; + negativeTextId = com.android.internal.R.string.cancel; + } + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(title); + builder.setOnCancelListener(new CancelListener()); + if (mType != PROMPT) { + builder.setMessage(displayMessage); + builder.setPositiveButton(positiveTextId, new PositiveListener(null)); + } else { + final View view = LayoutInflater.from(context).inflate( + com.android.internal.R.layout.js_prompt, null); + EditText edit = ((EditText) view.findViewById(com.android.internal.R.id.value)); + edit.setText(mDefaultValue); + builder.setPositiveButton(positiveTextId, new PositiveListener(edit)); + ((TextView) view.findViewById(com.android.internal.R.id.message)).setText(mMessage); + builder.setView(view); + } + if (mType != ALERT) { + builder.setNegativeButton(negativeTextId, new CancelListener()); + } + builder.show(); + } + + private class CancelListener implements DialogInterface.OnCancelListener, + DialogInterface.OnClickListener { + @Override + public void onCancel(DialogInterface dialog) { + mResult.cancel(); + } + @Override + public void onClick(DialogInterface dialog, int which) { + mResult.cancel(); + } + } + + private class PositiveListener implements DialogInterface.OnClickListener { + private final EditText mEdit; + + public PositiveListener(EditText edit) { + mEdit = edit; + } + + @Override + public void onClick(DialogInterface dialog, int which) { + if (mEdit == null) { + mResult.confirm(); + } else { + mResult.confirm(mEdit.getText().toString()); + } + } + } + + private String getJsDialogTitle(Context context) { + String title = mUrl; + if (URLUtil.isDataUrl(mUrl)) { + // For data: urls, we just display 'JavaScript' similar to Chrome. + title = context.getString(com.android.internal.R.string.js_dialog_title_default); + } else { + try { + URL alertUrl = new URL(mUrl); + // For example: "The page at 'http://www.mit.edu' says:" + title = context.getString(com.android.internal.R.string.js_dialog_title, + alertUrl.getProtocol() + "://" + alertUrl.getHost()); + } catch (MalformedURLException ex) { + // do nothing. just use the url as the title + } + } + return title; + } + + private static boolean canShowAlertDialog(Context context) { + // We can only display the alert dialog if mContext is + // an Activity context. + // FIXME: Should we display dialogs if mContext does + // not have the window focus (e.g. if the user is viewing + // another Activity when the alert should be displayed) ? + // See bug 3166409 + return context instanceof Activity; + } +} diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index a0e1603..3361ab7 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -2411,9 +2411,14 @@ <string name="js_dialog_title">The page at \"<xliff:g id="title">%s</xliff:g>\" says:</string> <!-- Default title for a javascript dialog --> <string name="js_dialog_title_default">JavaScript</string> - <!-- Message in a javascript dialog asking if the user wishes to leave the - current page --> - <string name="js_dialog_before_unload">Navigate away from this page?\n\n<xliff:g id="message">%s</xliff:g>\n\nTouch OK to continue, or Cancel to stay on the current page.</string> + <!-- Title for the unload javascript dialog --> + <string name="js_dialog_before_unload_title">Confirm Navigation</string> + <!-- Text for the positive button on the unload javascript dialog --> + <string name="js_dialog_before_unload_positive_button">Leave this Page</string> + <!-- Text for the negative button on the unload javascript dialog --> + <string name="js_dialog_before_unload_negative_button">Stay on this Page</string> + <!-- Message in a javascript dialog asking if the user wishes to leave the current page --> + <string name="js_dialog_before_unload"><xliff:g id="message">%s</xliff:g>\n\nAre you sure you want to navigate away from this page?</string> <!-- Title of the WebView save password dialog. If the user enters a password in a form on a website, a dialog will come up asking if they want to save the password. --> <string name="save_password_label">Confirm</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index e06bcd1..45ea182 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -549,6 +549,9 @@ <java-symbol type="string" name="ime_action_search" /> <java-symbol type="string" name="ime_action_send" /> <java-symbol type="string" name="invalidPin" /> + <java-symbol type="string" name="js_dialog_before_unload_positive_button" /> + <java-symbol type="string" name="js_dialog_before_unload_negative_button" /> + <java-symbol type="string" name="js_dialog_before_unload_title" /> <java-symbol type="string" name="js_dialog_before_unload" /> <java-symbol type="string" name="js_dialog_title" /> <java-symbol type="string" name="js_dialog_title_default" /> |