diff options
23 files changed, 653 insertions, 924 deletions
diff --git a/content/browser/android/date_time_chooser_android.cc b/content/browser/android/date_time_chooser_android.cc index be87a93..87f02b9f 100644 --- a/content/browser/android/date_time_chooser_android.cc +++ b/content/browser/android/date_time_chooser_android.cc @@ -40,25 +40,7 @@ void DateTimeChooserAndroid::InitializeDateInputTypes( void DateTimeChooserAndroid::ReplaceDateTime(JNIEnv* env, jobject, - int dialog_type, - int year, - int month, - int day, - int hour, - int minute, - int second, - int milli, - int week) { - ViewHostMsg_DateTimeDialogValue_Params value; - value.year = year; - value.month = month; - value.day = day; - value.hour = hour; - value.minute = minute; - value.second = second; - value.milli = milli; - value.week = week; - value.dialog_type = dialog_type; + jdouble value) { host_->Send(new ViewMsg_ReplaceDateTime(host_->GetRoutingID(), value)); } @@ -66,20 +48,14 @@ void DateTimeChooserAndroid::CancelDialog(JNIEnv* env, jobject) { host_->Send(new ViewMsg_CancelDateTimeDialog(host_->GetRoutingID())); } -void DateTimeChooserAndroid::ShowDialog(ContentViewCore* content, - RenderViewHost* host, - int type, - int year, - int month, - int day, - int hour, - int minute, - int second, - int milli, - int week, - double min, - double max, - double step) { +void DateTimeChooserAndroid::ShowDialog( + ContentViewCore* content, + RenderViewHost* host, + ui::TextInputType dialog_type, + double dialog_value, + double min, + double max, + double step) { host_ = host; JNIEnv* env = AttachCurrentThread(); @@ -87,15 +63,8 @@ void DateTimeChooserAndroid::ShowDialog(ContentViewCore* content, env, content->GetJavaObject().obj(), reinterpret_cast<intptr_t>(this), - type, - year, - month, - day, - hour, - minute, - second, - milli, - week, + dialog_type, + dialog_value, min, max, step)); diff --git a/content/browser/android/date_time_chooser_android.h b/content/browser/android/date_time_chooser_android.h index a5578e0..a04850f 100644 --- a/content/browser/android/date_time_chooser_android.h +++ b/content/browser/android/date_time_chooser_android.h @@ -9,6 +9,7 @@ #include "base/android/jni_helper.h" #include "base/memory/scoped_ptr.h" +#include "ui/base/ime/text_input_type.h" namespace content { @@ -22,33 +23,18 @@ class DateTimeChooserAndroid { ~DateTimeChooserAndroid(); // DateTimeChooser implementation: + // Shows the dialog. |dialog_value| is the date/time value converted to a + // number as defined in HTML. (See blink::InputType::parseToNumber()) void ShowDialog(ContentViewCore* content, RenderViewHost* host, - int type, - int year, - int month, - int day, - int hour, - int minute, - int second, - int milli, - int week, + ui::TextInputType dialog_type, + double dialog_value, double min, double max, double step); - // Replaces the current value with the one passed the different fields - void ReplaceDateTime(JNIEnv* env, - jobject, - jint dialog_type, - jint year, - jint month, - jint day, - jint hour, - jint minute, - jint second, - jint milli, - jint week); + // Replaces the current value + void ReplaceDateTime(JNIEnv* env, jobject, jdouble value); // Closes the dialog without propagating any changes. void CancelDialog(JNIEnv* env, jobject); diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index f5d9326..e363c32 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc @@ -2340,14 +2340,7 @@ void WebContentsImpl::OnOpenDateTimeDialog( date_time_chooser_->ShowDialog(ContentViewCore::FromWebContents(this), GetRenderViewHost(), value.dialog_type, - value.year, - value.month, - value.day, - value.hour, - value.minute, - value.second, - value.milli, - value.week, + value.dialog_value, value.minimum, value.maximum, value.step); diff --git a/content/common/view_messages.h b/content/common/view_messages.h index 3ff33ca..d7db038 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h @@ -399,15 +399,8 @@ IPC_STRUCT_BEGIN(ViewHostMsg_CreateWorker_Params) IPC_STRUCT_END() IPC_STRUCT_BEGIN(ViewHostMsg_DateTimeDialogValue_Params) - IPC_STRUCT_MEMBER(int, dialog_type) - IPC_STRUCT_MEMBER(int, year) - IPC_STRUCT_MEMBER(int, month) - IPC_STRUCT_MEMBER(int, day) - IPC_STRUCT_MEMBER(int, hour) - IPC_STRUCT_MEMBER(int, minute) - IPC_STRUCT_MEMBER(int, second) - IPC_STRUCT_MEMBER(int, milli) - IPC_STRUCT_MEMBER(int, week) + IPC_STRUCT_MEMBER(ui::TextInputType, dialog_type) + IPC_STRUCT_MEMBER(double, dialog_value) IPC_STRUCT_MEMBER(double, minimum) IPC_STRUCT_MEMBER(double, maximum) IPC_STRUCT_MEMBER(double, step) @@ -976,7 +969,7 @@ IPC_MESSAGE_ROUTED1(ViewMsg_SetBrowserRenderingStats, // Replaces a date time input field. IPC_MESSAGE_ROUTED1(ViewMsg_ReplaceDateTime, - ViewHostMsg_DateTimeDialogValue_Params /* value */) + double /* dialog_value */) // Copies the image at location x, y to the clipboard (if there indeed is an // image at that location). diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi index a5e8710..9c83c0e 100644 --- a/content/content_renderer.gypi +++ b/content/content_renderer.gypi @@ -102,8 +102,6 @@ 'renderer/context_menu_params_builder.h', 'renderer/cursor_utils.cc', 'renderer/cursor_utils.h', - 'renderer/date_time_formatter.cc', - 'renderer/date_time_formatter.h', 'renderer/device_orientation/device_motion_event_pump.cc', 'renderer/device_orientation/device_motion_event_pump.h', 'renderer/device_orientation/device_orientation_event_pump.cc', diff --git a/content/content_tests.gypi b/content/content_tests.gypi index eed3507..e7a3846 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi @@ -512,7 +512,6 @@ 'renderer/android/email_detector_unittest.cc', 'renderer/android/phone_number_detector_unittest.cc', 'renderer/bmp_image_decoder_unittest.cc', - 'renderer/date_time_formatter_unittest.cc', 'renderer/device_orientation/device_motion_event_pump_unittest.cc', 'renderer/device_orientation/device_orientation_event_pump_unittest.cc', 'renderer/disambiguation_popup_helper_unittest.cc', diff --git a/content/public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java b/content/public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java index c5b42ac..a45bc57 100644 --- a/content/public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java @@ -26,13 +26,8 @@ class DateTimeChooserAndroid { new InputDialogContainer.InputActionDelegate() { @Override - public void replaceDateTime( - int dialogType, - int year, int month, int day, int hour, int minute, - int second, int milli, int week) { - nativeReplaceDateTime(mNativeDateTimeChooserAndroid, - dialogType, - year, month, day, hour, minute, second, milli, week); + public void replaceDateTime(double value) { + nativeReplaceDateTime(mNativeDateTimeChooserAndroid, value); } @Override @@ -42,28 +37,22 @@ class DateTimeChooserAndroid { }); } - private void showDialog(int dialogType, int year, int month, int monthDay, - int hour, int minute, int second, int milli, - int week, double min, double max, double step) { - mInputDialogContainer.showDialog( - dialogType, year, month, monthDay, - hour, minute, second, milli, week, min, max, step); + private void showDialog(int dialogType, double dialogValue, + double min, double max, double step) { + mInputDialogContainer.showDialog(dialogType, dialogValue, min, max, step); } @CalledByNative private static DateTimeChooserAndroid createDateTimeChooser( ContentViewCore contentViewCore, - long nativeDateTimeChooserAndroid, int dialogType, - int year, int month, int day, - int hour, int minute, int second, int milli, int week, + long nativeDateTimeChooserAndroid, + int dialogType, double dialogValue, double min, double max, double step) { DateTimeChooserAndroid chooser = new DateTimeChooserAndroid( contentViewCore.getContext(), nativeDateTimeChooserAndroid); - chooser.showDialog( - dialogType, year, month, day, hour, minute, second, milli, - week, min, max, step); + chooser.showDialog(dialogType, dialogValue, min, max, step); return chooser; } @@ -77,10 +66,8 @@ class DateTimeChooserAndroid { textInputTypeMonth, textInputTypeTime, textInputTypeWeek); } - private native void nativeReplaceDateTime( - long nativeDateTimeChooserAndroid, int dialogType, - int year, int month, int day, int hour, int minute, - int second, int milli, int week); + private native void nativeReplaceDateTime(long nativeDateTimeChooserAndroid, + double dialogValue); private native void nativeCancelDialog(long nativeDateTimeChooserAndroid); } diff --git a/content/public/android/java/src/org/chromium/content/browser/input/DateTimePickerDialog.java b/content/public/android/java/src/org/chromium/content/browser/input/DateTimePickerDialog.java index 07c1deb..8c3be1b 100644 --- a/content/public/android/java/src/org/chromium/content/browser/input/DateTimePickerDialog.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/DateTimePickerDialog.java @@ -60,11 +60,11 @@ class DateTimePickerDialog extends AlertDialog implements OnClickListener, int monthOfYear, int dayOfMonth, int hourOfDay, int minute, boolean is24HourView, - long min, long max) { + double min, double max) { super(context, 0); - mMinTimeMillis = min; - mMaxTimeMillis = max; + mMinTimeMillis = (long) min; + mMaxTimeMillis = (long) max; mCallBack = callBack; @@ -81,7 +81,7 @@ class DateTimePickerDialog extends AlertDialog implements OnClickListener, setView(view); mDatePicker = (DatePicker) view.findViewById(R.id.date_picker); DateDialogNormalizer.normalize(mDatePicker, this, - year, monthOfYear, dayOfMonth, hourOfDay, minute, min, max); + year, monthOfYear, dayOfMonth, hourOfDay, minute, mMinTimeMillis, mMaxTimeMillis); mTimePicker = (TimePicker) view.findViewById(R.id.time_picker); mTimePicker.setIs24HourView(is24HourView); diff --git a/content/public/android/java/src/org/chromium/content/browser/input/InputDialogContainer.java b/content/public/android/java/src/org/chromium/content/browser/input/InputDialogContainer.java index ac61046..7ec81cb 100644 --- a/content/public/android/java/src/org/chromium/content/browser/input/InputDialogContainer.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/InputDialogContainer.java @@ -21,34 +21,18 @@ import org.chromium.content.browser.input.DateTimePickerDialog.OnDateTimeSetList import org.chromium.content.browser.input.MultiFieldTimePickerDialog.OnMultiFieldTimeSetListener; import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; +import java.util.concurrent.TimeUnit; public class InputDialogContainer { interface InputActionDelegate { void cancelDateTimeDialog(); - void replaceDateTime(int dialogType, - int year, int month, int day, int hour, int minute, int second, int milli, int week); + void replaceDateTime(double value); } - // Default values used in Time representations of selected date/time before formatting. - // They are never displayed to the user. - private static final int YEAR_DEFAULT = 1970; - private static final int MONTH_DEFAULT = 0; - private static final int MONTHDAY_DEFAULT = 1; - private static final int HOUR_DEFAULT = 0; - private static final int MINUTE_DEFAULT = 0; - private static final int WEEK_DEFAULT = 0; - - // Date formats as accepted by Time.format. - private static final String HTML_DATE_FORMAT = "%Y-%m-%d"; - private static final String HTML_TIME_FORMAT = "%H:%M"; - // For datetime we always send selected time as UTC, as we have no timezone selector. - // This is consistent with other browsers. - private static final String HTML_DATE_TIME_FORMAT = "%Y-%m-%dT%H:%MZ"; - private static final String HTML_DATE_TIME_LOCAL_FORMAT = "%Y-%m-%dT%H:%M"; - private static final String HTML_MONTH_FORMAT = "%Y-%m"; - private static final String HTML_WEEK_FORMAT = "%Y-%w"; - private static int sTextInputTypeDate; private static int sTextInputTypeDateTime; private static int sTextInputTypeDateTimeLocal; @@ -87,73 +71,103 @@ public class InputDialogContainer { mInputActionDelegate = inputActionDelegate; } - private Time normalizeTime(int year, int month, int monthDay, - int hour, int minute, int second) { - Time result = new Time(); - if (year == 0 && month == 0 && monthDay == 0 && hour == 0 && - minute == 0 && second == 0) { - Calendar cal = Calendar.getInstance(); - result.set(cal.get(Calendar.SECOND), cal.get(Calendar.MINUTE), - cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.DATE), - cal.get(Calendar.MONTH), cal.get(Calendar.YEAR)); + void showDialog(final int dialogType, double dialogValue, + double min, double max, double step) { + Calendar cal; + // |dialogValue|, |min|, |max| mean different things depending on the |dialogType|. + // For input type=month is the number of months since 1970. + // For input type=time it is milliseconds since midnight. + // For other types they are just milliseconds since 1970. + // If |dialogValue| is NaN it means an empty value. We will show the current time. + if (Double.isNaN(dialogValue)) { + cal = Calendar.getInstance(); + cal.set(Calendar.MILLISECOND, 0); } else { - result.set(second, minute, hour, monthDay, month, year); + if (dialogType == sTextInputTypeMonth) { + cal = MonthPicker.createDateFromValue(dialogValue); + } else if (dialogType == sTextInputTypeWeek) { + cal = WeekPicker.createDateFromValue(dialogValue); + } else { + GregorianCalendar gregorianCalendar = + new GregorianCalendar(TimeZone.getTimeZone("UTC")); + // According to the HTML spec we only use the Gregorian calendar + // so we ignore the Julian/Gregorian transition. + gregorianCalendar.setGregorianChange(new Date(Long.MIN_VALUE)); + gregorianCalendar.setTimeInMillis((long) dialogValue); + cal = gregorianCalendar; + } + } + if (dialogType == sTextInputTypeDate) { + showDialog(dialogType, + cal.get(Calendar.YEAR), + cal.get(Calendar.MONTH), + cal.get(Calendar.DAY_OF_MONTH), + 0, 0, 0, 0, 0, min, max, step); + } else if (dialogType == sTextInputTypeTime) { + showDialog(dialogType, 0, 0, 0, + cal.get(Calendar.HOUR_OF_DAY), + cal.get(Calendar.MINUTE), + 0, 0, 0, min, max, step); + } else if (dialogType == sTextInputTypeDateTime || + dialogType == sTextInputTypeDateTimeLocal) { + showDialog(dialogType, + cal.get(Calendar.YEAR), + cal.get(Calendar.MONTH), + cal.get(Calendar.DAY_OF_MONTH), + cal.get(Calendar.HOUR_OF_DAY), + cal.get(Calendar.MINUTE), + cal.get(Calendar.SECOND), + cal.get(Calendar.MILLISECOND), + 0, min, max, step); + } else if (dialogType == sTextInputTypeMonth) { + showDialog(dialogType, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), 0, + 0, 0, 0, 0, 0, min, max, step); + } else if (dialogType == sTextInputTypeWeek) { + int year = WeekPicker.getISOWeekYearForDate(cal); + int week = WeekPicker.getWeekForDate(cal); + showDialog(dialogType, year, 0, 0, 0, 0, 0, 0, week, min, max, step); } - return result; } - void showDialog(final int dialogType, int year, int month, int monthDay, - int hour, int minute, int second, int milli, int week, - double min, double max, double step) { + void showDialog(final int dialogType, + int year, int month, int monthDay, + int hourOfDay, int minute, int second, int millis, int week, + double min, double max, double step) { if (isDialogShowing()) mDialog.dismiss(); - // Java Date dialogs like longs but Blink prefers doubles.. - // Both parameters mean different things depending on the type - // For input type=month min and max come as number on months since 1970 - // For other types (including type=time) they are just milliseconds since 1970 - // In any case the cast here is safe given the above restrictions. - long minTime = (long) min; - long maxTime = (long) max; int stepTime = (int) step; - if (milli > 1000) { - second += milli / 1000; - milli %= 1000; - } - Time time = normalizeTime(year, month, monthDay, hour, minute, second); if (dialogType == sTextInputTypeDate) { DatePickerDialog dialog = new DatePickerDialog(mContext, - new DateListener(dialogType), time.year, time.month, time.monthDay); + new DateListener(dialogType), + year, month, monthDay); DateDialogNormalizer.normalize(dialog.getDatePicker(), dialog, - time.year, time.month, time.monthDay, 0, 0, minTime, maxTime); + year, month, monthDay, + 0, 0, + (long) min, (long) max); dialog.setTitle(mContext.getText(R.string.date_picker_dialog_title)); mDialog = dialog; } else if (dialogType == sTextInputTypeTime) { mDialog = new MultiFieldTimePickerDialog( mContext, 0 /* theme */ , - time.hour, time.minute, time.second, milli, - (int) minTime, (int) maxTime, stepTime, + hourOfDay, minute, second, millis, + (int) min, (int) max, stepTime, DateFormat.is24HourFormat(mContext), new FullTimeListener(dialogType)); } else if (dialogType == sTextInputTypeDateTime || dialogType == sTextInputTypeDateTimeLocal) { mDialog = new DateTimePickerDialog(mContext, new DateTimeListener(dialogType), - time.year, time.month, time.monthDay, - time.hour, time.minute, DateFormat.is24HourFormat(mContext), - minTime, maxTime); + year, month, monthDay, + hourOfDay, minute, + DateFormat.is24HourFormat(mContext), min, max); } else if (dialogType == sTextInputTypeMonth) { mDialog = new MonthPickerDialog(mContext, new MonthOrWeekListener(dialogType), - time.year, time.month, minTime, maxTime); + year, month, min, max); } else if (dialogType == sTextInputTypeWeek) { - if (week == 0) { - Calendar cal = Calendar.getInstance(); - year = WeekPicker.getISOWeekYearForDate(cal); - week = WeekPicker.getWeekForDate(cal); - } mDialog = new WeekPickerDialog(mContext, new MonthOrWeekListener(dialogType), - year, week, minTime, maxTime); + year, week, min, max); } mDialog.setButton(DialogInterface.BUTTON_POSITIVE, @@ -170,7 +184,7 @@ public class InputDialogContainer { @Override public void onClick(DialogInterface dialog, int which) { mDialogAlreadyDismissed = true; - mInputActionDelegate.replaceDateTime(dialogType, 0, 0, 0, 0, 0, 0, 0, 0); + mInputActionDelegate.replaceDateTime(Double.NaN); } }); @@ -206,29 +220,7 @@ public class InputDialogContainer { @Override public void onDateSet(DatePicker view, int year, int month, int monthDay) { - if (!mDialogAlreadyDismissed) { - setFieldDateTimeValue(mDialogType, - year, month, monthDay, - HOUR_DEFAULT, MINUTE_DEFAULT, WEEK_DEFAULT, - HTML_DATE_FORMAT); - } - } - } - - private class TimeListener implements OnTimeSetListener { - private final int mDialogType; - - TimeListener(int dialogType) { - mDialogType = dialogType; - } - - @Override - public void onTimeSet(TimePicker view, int hourOfDay, int minute) { - if (!mDialogAlreadyDismissed) { - setFieldDateTimeValue(mDialogType, - YEAR_DEFAULT, MONTH_DEFAULT, MONTHDAY_DEFAULT, - hourOfDay, minute, WEEK_DEFAULT, HTML_TIME_FORMAT); - } + setFieldDateTimeValue(mDialogType, year, month, monthDay, 0, 0, 0, 0, 0); } } @@ -240,11 +232,7 @@ public class InputDialogContainer { @Override public void onTimeSet(int hourOfDay, int minute, int second, int milli) { - if (!mDialogAlreadyDismissed) { - setFieldDateTimeValue(mDialogType, - YEAR_DEFAULT, MONTH_DEFAULT, MONTHDAY_DEFAULT, - hourOfDay, minute, second, milli, WEEK_DEFAULT, HTML_TIME_FORMAT); - } + setFieldDateTimeValue(mDialogType, 0, 0, 0, hourOfDay, minute, second, milli, 0); } } @@ -261,11 +249,7 @@ public class InputDialogContainer { public void onDateTimeSet(DatePicker dateView, TimePicker timeView, int year, int month, int monthDay, int hourOfDay, int minute) { - if (!mDialogAlreadyDismissed) { - setFieldDateTimeValue(mDialogType, year, month, monthDay, - hourOfDay, minute, WEEK_DEFAULT, - mLocal ? HTML_DATE_TIME_LOCAL_FORMAT : HTML_DATE_TIME_FORMAT); - } + setFieldDateTimeValue(mDialogType, year, month, monthDay, hourOfDay, minute, 0, 0, 0); } } @@ -278,38 +262,46 @@ public class InputDialogContainer { @Override public void onValueSet(int year, int positionInYear) { - if (!mDialogAlreadyDismissed) { - if (mDialogType == sTextInputTypeMonth) { - setFieldDateTimeValue(mDialogType, year, positionInYear, MONTHDAY_DEFAULT, - HOUR_DEFAULT, MINUTE_DEFAULT, WEEK_DEFAULT, - HTML_MONTH_FORMAT); - } else { - setFieldDateTimeValue(mDialogType, year, MONTH_DEFAULT, MONTHDAY_DEFAULT, - HOUR_DEFAULT, MINUTE_DEFAULT, positionInYear, HTML_WEEK_FORMAT); - } + if (mDialogType == sTextInputTypeMonth) { + setFieldDateTimeValue(mDialogType, year, positionInYear, 0, 0, 0, 0, 0, 0); + } else { + setFieldDateTimeValue(mDialogType, year, 0, 0, 0, 0, 0, 0, positionInYear); } } } - private void setFieldDateTimeValue(int dialogType, - int year, int month, int monthDay, int hourOfDay, - int minute, int week, String dateFormat) { + protected void setFieldDateTimeValue(int dialogType, + int year, int month, int monthDay, + int hourOfDay, int minute, int second, int millis, + int week) { // Prevents more than one callback being sent to the native // side when the dialog triggers multiple events. + if (mDialogAlreadyDismissed) + return; mDialogAlreadyDismissed = true; - mInputActionDelegate.replaceDateTime(dialogType, - year, month, monthDay, hourOfDay, minute, 0 /* second */, 0 /* milli */, week); - } - - private void setFieldDateTimeValue(int dialogType, - int year, int month, int monthDay, int hourOfDay, - int minute, int second, int milli, int week, String dateFormat) { - // Prevents more than one callback being sent to the native - // side when the dialog triggers multiple events. - mDialogAlreadyDismissed = true; - - mInputActionDelegate.replaceDateTime( - dialogType, year, month, monthDay, hourOfDay, minute, second, milli, week); + double value = 0; + if (dialogType == sTextInputTypeMonth) { + mInputActionDelegate.replaceDateTime((year - 1970) * 12 + month); + } else if (dialogType == sTextInputTypeWeek) { + mInputActionDelegate.replaceDateTime( + WeekPicker.createDateFromWeek(year, week).getTimeInMillis()); + } else if (dialogType == sTextInputTypeTime) { + mInputActionDelegate.replaceDateTime(TimeUnit.HOURS.toMillis(hourOfDay) + + TimeUnit.MINUTES.toMillis(minute) + + TimeUnit.SECONDS.toMillis(second) + + millis); + } else { + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + cal.clear(); + cal.set(Calendar.YEAR, year); + cal.set(Calendar.MONTH, month); + cal.set(Calendar.DAY_OF_MONTH, monthDay); + cal.set(Calendar.HOUR_OF_DAY, hourOfDay); + cal.set(Calendar.MINUTE, minute); + cal.set(Calendar.SECOND, second); + cal.set(Calendar.MILLISECOND, millis); + mInputActionDelegate.replaceDateTime((double) cal.getTimeInMillis()); + } } } diff --git a/content/public/android/java/src/org/chromium/content/browser/input/MonthPicker.java b/content/public/android/java/src/org/chromium/content/browser/input/MonthPicker.java index ab1f31e..c7ebe8d 100644 --- a/content/public/android/java/src/org/chromium/content/browser/input/MonthPicker.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/MonthPicker.java @@ -12,13 +12,14 @@ import java.text.DateFormatSymbols; import java.util.Arrays; import java.util.Calendar; import java.util.Locale; +import java.util.TimeZone; public class MonthPicker extends TwoFieldDatePicker { private static final int MONTHS_NUMBER = 12; private final String[] mShortMonths; - public MonthPicker(Context context, long minValue, long maxValue) { + public MonthPicker(Context context, double minValue, double maxValue) { super(context, minValue, maxValue); getPositionInYearSpinner().setContentDescription( @@ -29,23 +30,30 @@ public class MonthPicker extends TwoFieldDatePicker { DateFormatSymbols.getInstance(Locale.getDefault()).getShortMonths(); // initialize to current date - Calendar cal = Calendar.getInstance(); + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); init(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), null); } - @Override - protected Calendar createDateFromValue(long value) { + /** + * Creates a date object from the |value| which is months since epoch. + */ + public static Calendar createDateFromValue(double value) { int year = (int) Math.min(value / 12 + 1970, Integer.MAX_VALUE); int month = (int) (value % 12); - Calendar cal = Calendar.getInstance(); + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); cal.clear(); cal.set(year, month, 1); return cal; } @Override + protected Calendar getDateForValue(double value) { + return MonthPicker.createDateFromValue(value); + } + + @Override protected void setCurrentDate(int year, int month) { - Calendar date = Calendar.getInstance(); + Calendar date = Calendar.getInstance(TimeZone.getTimeZone("UTC")); date.set(year, month, 1); if (date.before(getMinDate())) { setCurrentDate(getMinDate()); diff --git a/content/public/android/java/src/org/chromium/content/browser/input/MonthPickerDialog.java b/content/public/android/java/src/org/chromium/content/browser/input/MonthPickerDialog.java index 24a4e8b..e995b62 100644 --- a/content/public/android/java/src/org/chromium/content/browser/input/MonthPickerDialog.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/MonthPickerDialog.java @@ -17,25 +17,16 @@ public class MonthPickerDialog extends TwoFieldDatePickerDialog { * @param monthOfYear The initial month of the dialog. */ public MonthPickerDialog(Context context, OnValueSetListener callBack, - int year, int monthOfYear, long minMonth, long maxMonth) { + int year, int monthOfYear, double minMonth, double maxMonth) { super(context, callBack, year, monthOfYear, minMonth, maxMonth); setTitle(R.string.month_picker_dialog_title); } @Override - protected TwoFieldDatePicker createPicker(Context context, long minValue, long maxValue) { + protected TwoFieldDatePicker createPicker(Context context, double minValue, double maxValue) { return new MonthPicker(context, minValue, maxValue); } - @Override - protected void tryNotifyDateSet() { - if (mCallBack != null) { - MonthPicker picker = getMonthPicker(); - picker.clearFocus(); - mCallBack.onValueSet(picker.getYear(), picker.getMonth()); - } - } - /** * Gets the {@link MonthPicker} contained in this dialog. * diff --git a/content/public/android/java/src/org/chromium/content/browser/input/TwoFieldDatePicker.java b/content/public/android/java/src/org/chromium/content/browser/input/TwoFieldDatePicker.java index 8b90c9c..0ff2bec 100644 --- a/content/public/android/java/src/org/chromium/content/browser/input/TwoFieldDatePicker.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/TwoFieldDatePicker.java @@ -15,6 +15,7 @@ import android.widget.NumberPicker.OnValueChangeListener; import org.chromium.content.R; import java.util.Calendar; +import java.util.TimeZone; /** * This class is heavily based on android.widget.DatePicker. @@ -51,7 +52,7 @@ public abstract class TwoFieldDatePicker extends FrameLayout { void onMonthOrWeekChanged(TwoFieldDatePicker view, int year, int positionInYear); } - public TwoFieldDatePicker(Context context, long minValue, long maxValue) { + public TwoFieldDatePicker(Context context, double minValue, double maxValue) { super(context, null, android.R.attr.datePickerStyle); LayoutInflater inflater = (LayoutInflater) context @@ -86,15 +87,15 @@ public abstract class TwoFieldDatePicker extends FrameLayout { } }; - mCurrentDate = Calendar.getInstance(); + mCurrentDate = Calendar.getInstance(TimeZone.getTimeZone("UTC")); if (minValue >= maxValue) { - mMinDate = Calendar.getInstance(); + mMinDate = Calendar.getInstance(TimeZone.getTimeZone("UTC")); mMinDate.set(0, 0, 1); - mMaxDate = Calendar.getInstance(); + mMaxDate = Calendar.getInstance(TimeZone.getTimeZone("UTC")); mMaxDate.set(9999, 0, 1); } else { - mMinDate = createDateFromValue(minValue); - mMaxDate = createDateFromValue(maxValue); + mMinDate = getDateForValue(minValue); + mMaxDate = getDateForValue(maxValue); } // month @@ -132,7 +133,7 @@ public abstract class TwoFieldDatePicker extends FrameLayout { * Subclasses know the semantics of @value, and need to return * a Calendar corresponding to it. */ - protected abstract Calendar createDateFromValue(long value); + protected abstract Calendar getDateForValue(double value); /** * Updates the current date. diff --git a/content/public/android/java/src/org/chromium/content/browser/input/TwoFieldDatePickerDialog.java b/content/public/android/java/src/org/chromium/content/browser/input/TwoFieldDatePickerDialog.java index 7c36c36..d862e6e 100644 --- a/content/public/android/java/src/org/chromium/content/browser/input/TwoFieldDatePickerDialog.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/TwoFieldDatePickerDialog.java @@ -29,8 +29,7 @@ public abstract class TwoFieldDatePickerDialog extends AlertDialog implements On /** * @param year The year that was set. - * @param positionInYear The week in year. - * with {@link java.util.Calendar}. + * @param positionInYear The position in the year that was set. */ void onValueSet(int year, int positionInYear); } @@ -45,8 +44,8 @@ public abstract class TwoFieldDatePickerDialog extends AlertDialog implements On OnValueSetListener callBack, int year, int positionInYear, - long minValue, - long maxValue) { + double minValue, + double maxValue) { this(context, 0, callBack, year, positionInYear, minValue, maxValue); } @@ -62,8 +61,8 @@ public abstract class TwoFieldDatePickerDialog extends AlertDialog implements On OnValueSetListener callBack, int year, int positionInYear, - long minValue, - long maxValue) { + double minValue, + double maxValue) { super(context, theme); mCallBack = callBack; @@ -79,7 +78,7 @@ public abstract class TwoFieldDatePickerDialog extends AlertDialog implements On mPicker.init(year, positionInYear, this); } - protected TwoFieldDatePicker createPicker(Context context, long minValue, long maxValue) { + protected TwoFieldDatePicker createPicker(Context context, double minValue, double maxValue) { return null; } @@ -91,7 +90,12 @@ public abstract class TwoFieldDatePickerDialog extends AlertDialog implements On /** * Notifies the listener, if such, that a date has been set. */ - protected abstract void tryNotifyDateSet(); + protected void tryNotifyDateSet() { + if (mCallBack != null) { + mPicker.clearFocus(); + mCallBack.onValueSet(mPicker.getYear(), mPicker.getPositionInYear()); + } + } @Override protected void onStop() { diff --git a/content/public/android/java/src/org/chromium/content/browser/input/WeekPicker.java b/content/public/android/java/src/org/chromium/content/browser/input/WeekPicker.java index b8924f4..a53460f 100644 --- a/content/public/android/java/src/org/chromium/content/browser/input/WeekPicker.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/WeekPicker.java @@ -9,26 +9,30 @@ import android.content.Context; import org.chromium.content.R; import java.util.Calendar; +import java.util.TimeZone; // This class is heavily based on android.widget.DatePicker. public class WeekPicker extends TwoFieldDatePicker { - public WeekPicker(Context context, long minValue, long maxValue) { + public WeekPicker(Context context, double minValue, double maxValue) { super(context, minValue, maxValue); getPositionInYearSpinner().setContentDescription( getResources().getString(R.string.accessibility_date_picker_week)); // initialize to current date - Calendar cal = Calendar.getInstance(); + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); cal.setFirstDayOfWeek(Calendar.MONDAY); cal.setMinimalDaysInFirstWeek(4); cal.setTimeInMillis(System.currentTimeMillis()); init(getISOWeekYearForDate(cal), getWeekForDate(cal), null); } - private Calendar createDateFromWeek(int year, int week) { - Calendar date = Calendar.getInstance(); + /** + * Creates a date object from the |year| and |week|. + */ + public static Calendar createDateFromWeek(int year, int week) { + Calendar date = Calendar.getInstance(TimeZone.getTimeZone("UTC")); date.clear(); date.setFirstDayOfWeek(Calendar.MONDAY); date.setMinimalDaysInFirstWeek(4); @@ -38,16 +42,23 @@ public class WeekPicker extends TwoFieldDatePicker { return date; } - @Override - protected Calendar createDateFromValue(long value) { - Calendar date = Calendar.getInstance(); + /** + * Creates a date object from the |value| which is milliseconds since epoch. + */ + public static Calendar createDateFromValue(double value) { + Calendar date = Calendar.getInstance(TimeZone.getTimeZone("UTC")); date.clear(); date.setFirstDayOfWeek(Calendar.MONDAY); date.setMinimalDaysInFirstWeek(4); - date.setTimeInMillis(value); + date.setTimeInMillis((long) value); return date; } + @Override + protected Calendar getDateForValue(double value) { + return WeekPicker.createDateFromValue(value); + } + public static int getISOWeekYearForDate(Calendar date) { int year = date.get(Calendar.YEAR); int month = date.get(Calendar.MONTH); diff --git a/content/public/android/java/src/org/chromium/content/browser/input/WeekPickerDialog.java b/content/public/android/java/src/org/chromium/content/browser/input/WeekPickerDialog.java index 83db991..0a7240e26 100644 --- a/content/public/android/java/src/org/chromium/content/browser/input/WeekPickerDialog.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/WeekPickerDialog.java @@ -19,7 +19,7 @@ public class WeekPickerDialog extends TwoFieldDatePickerDialog { public WeekPickerDialog(Context context, OnValueSetListener callBack, int year, int weekOfYear, - long minValue, long maxValue) { + double minValue, double maxValue) { this(context, 0, callBack, year, weekOfYear, minValue, maxValue); } @@ -35,25 +35,16 @@ public class WeekPickerDialog extends TwoFieldDatePickerDialog { OnValueSetListener callBack, int year, int weekOfYear, - long minValue, long maxValue) { + double minValue, double maxValue) { super(context, theme, callBack, year, weekOfYear, minValue, maxValue); setTitle(R.string.week_picker_dialog_title); } @Override - protected TwoFieldDatePicker createPicker(Context context, long minValue, long maxValue) { + protected TwoFieldDatePicker createPicker(Context context, double minValue, double maxValue) { return new WeekPicker(context, minValue, maxValue); } - @Override - protected void tryNotifyDateSet() { - if (mCallBack != null) { - WeekPicker picker = getWeekPicker(); - picker.clearFocus(); - mCallBack.onValueSet(picker.getYear(), picker.getWeek()); - } - } - /** * Gets the {@link WeekPicker} contained in this dialog. * diff --git a/content/public/android/javatests/src/org/chromium/content/browser/input/InputDialogContainerTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/InputDialogContainerTest.java new file mode 100644 index 0000000..235a859 --- /dev/null +++ b/content/public/android/javatests/src/org/chromium/content/browser/input/InputDialogContainerTest.java @@ -0,0 +1,404 @@ +// Copyright 2013 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.content.browser.input; + +import android.content.Context; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; + +import org.chromium.base.test.util.Feature; + +public class InputDialogContainerTest extends AndroidTestCase { + private static int TEXT_INPUT_TYPE_DATE = 0; + private static int TEXT_INPUT_TYPE_DATETIME = 1; + private static int TEXT_INPUT_TYPE_DATETIMELOCAL = 2; + private static int TEXT_INPUT_TYPE_MONTH = 3; + private static int TEXT_INPUT_TYPE_TIME = 4; + private static int TEXT_INPUT_TYPE_WEEK = 5; + + // Defined in third_party/WebKit/Source/platform/DateComponents.h + private static double DATE_DIALOG_DEFAULT_MIN = -62135596800000.0; + private static double DATE_DIALOG_DEFAULT_MAX = 8640000000000000.0; + private static double DATETIMELOCAL_DIALOG_DEFAULT_MIN = -62135596800000.0; + private static double DATETIMELOCAL_DIALOG_DEFAULT_MAX = 8640000000000000.0; + private static double MONTH_DIALOG_DEFAULT_MIN = -23628.0; + private static double MONTH_DIALOG_DEFAULT_MAX = 3285488.0; + private static double TIME_DIALOG_DEFAULT_MIN = 0.0; + private static double TIME_DIALOG_DEFAULT_MAX = 86399999.0; + private static double WEEK_DIALOG_DEFAULT_MIN = -62135596800000.0; + private static double WEEK_DIALOG_DEFAULT_MAX = 8639999568000000.0; + + InputActionDelegateForTests mInputActionDelegate; + InputDialogContainerForTests mInputDialogContainer; + + @Override + public void setUp() throws Exception { + super.setUp(); + InputDialogContainer.initializeInputTypes(TEXT_INPUT_TYPE_DATE, + TEXT_INPUT_TYPE_DATETIME, + TEXT_INPUT_TYPE_DATETIMELOCAL, + TEXT_INPUT_TYPE_MONTH, + TEXT_INPUT_TYPE_TIME, + TEXT_INPUT_TYPE_WEEK); + mInputActionDelegate = new InputActionDelegateForTests(); + mInputDialogContainer = new InputDialogContainerForTests(getContext(), + mInputActionDelegate); + } + + @SmallTest + @Feature({"DateTimeDialog"}) + public void testDateValueParsing() { + mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_DATE, + 1970, 0, 1, + 0, 0, 0, 0, 0, + DATE_DIALOG_DEFAULT_MIN, DATE_DIALOG_DEFAULT_MAX, 1.0); + mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_DATE, 0.0, + DATE_DIALOG_DEFAULT_MIN, DATE_DIALOG_DEFAULT_MAX, 1.0); + + mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_DATE, + 1, 0, 1, + 0, 0, 0, 0, 0, + DATE_DIALOG_DEFAULT_MIN, DATE_DIALOG_DEFAULT_MAX, 1.0); + mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_DATE, -62135596800000.0, + DATE_DIALOG_DEFAULT_MIN, DATE_DIALOG_DEFAULT_MAX, 1.0); + + mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_DATE, + 275760, 8, 13, + 0, 0, 0, 0, 0, + DATE_DIALOG_DEFAULT_MIN, DATE_DIALOG_DEFAULT_MAX, 1.0); + mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_DATE, 8640000000000000.0, + DATE_DIALOG_DEFAULT_MIN, DATE_DIALOG_DEFAULT_MAX, 1.0); + + mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_DATE, + 2013, 10, 7, + 0, 0, 0, 0, 0, + DATE_DIALOG_DEFAULT_MIN, DATE_DIALOG_DEFAULT_MAX, 1.0); + mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_DATE, 1383782400000.0, + DATE_DIALOG_DEFAULT_MIN, DATE_DIALOG_DEFAULT_MAX, 1.0); + } + + @SmallTest + @Feature({"DateTimeDialog"}) + public void testDatetimelocalValueParsing() { + mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_DATETIMELOCAL, + 1970, 0, 1, + 0, 0, 0, 0, 0, + DATETIMELOCAL_DIALOG_DEFAULT_MIN, DATETIMELOCAL_DIALOG_DEFAULT_MAX, 1.0); + mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_DATETIMELOCAL, 0, + DATETIMELOCAL_DIALOG_DEFAULT_MIN, DATETIMELOCAL_DIALOG_DEFAULT_MAX, 1.0); + + mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_DATETIMELOCAL, + 1, 0, 1, + 0, 0, 0, 0, 0, + DATETIMELOCAL_DIALOG_DEFAULT_MIN, DATETIMELOCAL_DIALOG_DEFAULT_MAX, 1.0); + mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_DATETIMELOCAL, -62135596800000.0, + DATETIMELOCAL_DIALOG_DEFAULT_MIN, DATETIMELOCAL_DIALOG_DEFAULT_MAX, 1.0); + + mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_DATETIMELOCAL, + 275760, 8, 13, + 0, 0, 0, 0, 0, + DATETIMELOCAL_DIALOG_DEFAULT_MIN, DATETIMELOCAL_DIALOG_DEFAULT_MAX, 1.0); + mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_DATETIMELOCAL, 8640000000000000.0, + DATETIMELOCAL_DIALOG_DEFAULT_MIN, DATETIMELOCAL_DIALOG_DEFAULT_MAX, 1.0); + + mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_DATETIMELOCAL, + 2013, 10, 8, + 1, 1, 2, 196, 0, + DATETIMELOCAL_DIALOG_DEFAULT_MIN, DATETIMELOCAL_DIALOG_DEFAULT_MAX, 0.001); + mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_DATETIMELOCAL, 1383872462196.0, + DATETIMELOCAL_DIALOG_DEFAULT_MIN, DATETIMELOCAL_DIALOG_DEFAULT_MAX, 0.001); + } + + @SmallTest + @Feature({"DateTimeDialog"}) + public void testMonthValueParsing() { + mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_MONTH, + 1970, 0, 0, + 0, 0, 0, 0, 0, + MONTH_DIALOG_DEFAULT_MIN, MONTH_DIALOG_DEFAULT_MAX, 1.0); + mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_MONTH, 0.0, + MONTH_DIALOG_DEFAULT_MIN, MONTH_DIALOG_DEFAULT_MAX, 1.0); + + mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_MONTH, + 1, 0, 0, + 0, 0, 0, 0, 0, + MONTH_DIALOG_DEFAULT_MIN, MONTH_DIALOG_DEFAULT_MAX, 1.0); + mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_MONTH, -23628.0, + MONTH_DIALOG_DEFAULT_MIN, MONTH_DIALOG_DEFAULT_MAX, 1.0); + + mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_MONTH, + 275760, 8, 0, + 0, 0, 0, 0, 0, + MONTH_DIALOG_DEFAULT_MIN, MONTH_DIALOG_DEFAULT_MAX, 1.0); + mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_MONTH, 3285488.0, + MONTH_DIALOG_DEFAULT_MIN, MONTH_DIALOG_DEFAULT_MAX, 1.0); + + mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_MONTH, + 2013, 10, 0, + 0, 0, 0, 0, 0, + MONTH_DIALOG_DEFAULT_MIN, MONTH_DIALOG_DEFAULT_MAX, 1.0); + mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_MONTH, 526.0, + MONTH_DIALOG_DEFAULT_MIN, MONTH_DIALOG_DEFAULT_MAX, 1.0); + } + + @SmallTest + @Feature({"DateTimeDialog"}) + public void testTimeValueParsing() { + mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_TIME, + 0, 0, 0, + 0, 0, 0, 0, 0, + TIME_DIALOG_DEFAULT_MIN, TIME_DIALOG_DEFAULT_MAX, 1.0); + mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_TIME, 0.0, + TIME_DIALOG_DEFAULT_MIN, TIME_DIALOG_DEFAULT_MAX, 1.0); + + // Time dialog only shows the hour and minute fields. + mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_TIME, + 0, 0, 0, + 23, 59, 0, 0, 0, + TIME_DIALOG_DEFAULT_MIN, TIME_DIALOG_DEFAULT_MAX, 1.0); + mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_TIME, 86399999.0, + TIME_DIALOG_DEFAULT_MIN, TIME_DIALOG_DEFAULT_MAX, 1.0); + + mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_TIME, + 0, 0, 0, + 15, 23, 0, 0, 0, + TIME_DIALOG_DEFAULT_MIN, TIME_DIALOG_DEFAULT_MAX, 1.0); + mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_TIME, 55425678.0, + TIME_DIALOG_DEFAULT_MIN, TIME_DIALOG_DEFAULT_MAX, 1.0); + } + + @SmallTest + @Feature({"DateTimeDialog"}) + public void testWeekValueParsing() { + mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_WEEK, + 1970, 0, 0, + 0, 0, 0, 0, 1, + WEEK_DIALOG_DEFAULT_MIN, WEEK_DIALOG_DEFAULT_MAX, 1.0); + mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_WEEK, -259200000.0, + WEEK_DIALOG_DEFAULT_MIN, WEEK_DIALOG_DEFAULT_MAX, 1.0); + + mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_WEEK, + 1, 0, 0, + 0, 0, 0, 0, 1, + WEEK_DIALOG_DEFAULT_MIN, WEEK_DIALOG_DEFAULT_MAX, 1.0); + mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_WEEK, -62135596800000.0, + WEEK_DIALOG_DEFAULT_MIN, WEEK_DIALOG_DEFAULT_MAX, 1.0); + + mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_WEEK, + 275760, 0, 0, + 0, 0, 0, 0, 37, + WEEK_DIALOG_DEFAULT_MIN, WEEK_DIALOG_DEFAULT_MAX, 1.0); + mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_WEEK, 8639999568000000.0, + WEEK_DIALOG_DEFAULT_MIN, WEEK_DIALOG_DEFAULT_MAX, 1.0); + + mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_WEEK, + 2013, 0, 0, + 0, 0, 0, 0, 44, + WEEK_DIALOG_DEFAULT_MIN, WEEK_DIALOG_DEFAULT_MAX, 1.0); + mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_WEEK, 1382918400000.0, + WEEK_DIALOG_DEFAULT_MIN, WEEK_DIALOG_DEFAULT_MAX, 1.0); + } + + @SmallTest + @Feature({"DateTimeDialog"}) + public void testDateValueGenerating() { + mInputActionDelegate.setReplaceDateTimeExpectation(0); + mInputDialogContainer.setFieldDateTimeValue(TEXT_INPUT_TYPE_DATE, + 1970, 0, 1, + 0, 0, 0, 0, 0); + + mInputActionDelegate.setReplaceDateTimeExpectation(-62135596800000.0); + mInputDialogContainer.setFieldDateTimeValue(TEXT_INPUT_TYPE_DATE, + 1, 0, 1, + 0, 0, 0, 0, 0); + + mInputActionDelegate.setReplaceDateTimeExpectation(8640000000000000.0); + mInputDialogContainer.setFieldDateTimeValue(TEXT_INPUT_TYPE_DATE, + 275760, 8, 13, + 0, 0, 0, 0, 0); + + mInputActionDelegate.setReplaceDateTimeExpectation(1383782400000.0); + mInputDialogContainer.setFieldDateTimeValue(TEXT_INPUT_TYPE_DATE, + 2013, 10, 7, + 0, 0, 0, 0, 0); + } + + @SmallTest + @Feature({"DateTimeDialog"}) + public void testDatetimelocalValueGenerating() { + mInputActionDelegate.setReplaceDateTimeExpectation(0); + mInputDialogContainer.setFieldDateTimeValue(TEXT_INPUT_TYPE_DATETIMELOCAL, + 1970, 0, 1, + 0, 0, 0, 0, 0); + + mInputActionDelegate.setReplaceDateTimeExpectation(-62135596800000.0); + mInputDialogContainer.setFieldDateTimeValue(TEXT_INPUT_TYPE_DATETIMELOCAL, + 1, 0, 1, + 0, 0, 0, 0, 0); + + mInputActionDelegate.setReplaceDateTimeExpectation(8640000000000000.0); + mInputDialogContainer.setFieldDateTimeValue(TEXT_INPUT_TYPE_DATETIMELOCAL, + 275760, 8, 13, + 0, 0, 0, 0, 0); + + mInputActionDelegate.setReplaceDateTimeExpectation(1383872462196.0); + mInputDialogContainer.setFieldDateTimeValue(TEXT_INPUT_TYPE_DATETIMELOCAL, + 2013, 10, 8, + 1, 1, 2, 196, 0); + } + + @SmallTest + @Feature({"DateTimeDialog"}) + public void testMonthValueGenerating() { + mInputActionDelegate.setReplaceDateTimeExpectation(0); + mInputDialogContainer.setFieldDateTimeValue(TEXT_INPUT_TYPE_MONTH, + 1970, 0, 0, + 0, 0, 0, 0, 0); + + mInputActionDelegate.setReplaceDateTimeExpectation(-62135596800000.0); + mInputDialogContainer.setFieldDateTimeValue(TEXT_INPUT_TYPE_MONTH, + 1, 0, 1, + 0, 0, 0, 0, 0); + + mInputActionDelegate.setReplaceDateTimeExpectation(8640000000000000.0); + mInputDialogContainer.setFieldDateTimeValue(TEXT_INPUT_TYPE_MONTH, + 275760, 8, 0, + 0, 0, 0, 0, 0); + + mInputActionDelegate.setReplaceDateTimeExpectation(1383872462196.0); + mInputDialogContainer.setFieldDateTimeValue(TEXT_INPUT_TYPE_MONTH, + 2013, 10, 0, + 0, 0, 0, 0, 0); + } + + @SmallTest + @Feature({"DateTimeDialog"}) + public void testTimeValueGenerating() { + mInputActionDelegate.setReplaceDateTimeExpectation(0.0); + mInputDialogContainer.setFieldDateTimeValue(TEXT_INPUT_TYPE_TIME, + 0, 0, 0, + 0, 0, 0, 0, 0); + + mInputActionDelegate.setReplaceDateTimeExpectation(86399999.0); + mInputDialogContainer.setFieldDateTimeValue(TEXT_INPUT_TYPE_TIME, + 0, 0, 0, + 23, 59, 59, 999, 0); + + mInputActionDelegate.setReplaceDateTimeExpectation(55425678.0); + mInputDialogContainer.setFieldDateTimeValue(TEXT_INPUT_TYPE_TIME, + 2013, 10, 0, + 3, 23, 45, 678, 0); + } + + @SmallTest + @Feature({"DateTimeDialog"}) + public void testWeekValueGenerating() { + mInputActionDelegate.setReplaceDateTimeExpectation(-259200000.0); + mInputDialogContainer.setFieldDateTimeValue(TEXT_INPUT_TYPE_WEEK, + 1970, 0, 0, + 0, 0, 0, 0, 1); + + mInputActionDelegate.setReplaceDateTimeExpectation(-62135596800000.0); + mInputDialogContainer.setFieldDateTimeValue(TEXT_INPUT_TYPE_WEEK, + 1, 0, 0, + 0, 0, 0, 0, 1); + + mInputActionDelegate.setReplaceDateTimeExpectation(8639999568000000.0); + mInputDialogContainer.setFieldDateTimeValue(TEXT_INPUT_TYPE_WEEK, + 275760, 0, 0, + 0, 0, 0, 0, 37); + + mInputActionDelegate.setReplaceDateTimeExpectation(1382918400000.0); + mInputDialogContainer.setFieldDateTimeValue(TEXT_INPUT_TYPE_WEEK, + 2013, 0, 0, + 0, 0, 0, 0, 44); + } + + private static class InputActionDelegateForTests + implements InputDialogContainer.InputActionDelegate { + private double mExpectedDialogValue; + + public void setReplaceDateTimeExpectation(double dialogValue) { + mExpectedDialogValue = dialogValue; + } + + @Override + public void replaceDateTime(double dialogValue) { + assertEquals(mExpectedDialogValue, dialogValue); + } + + @Override + public void cancelDateTimeDialog() { + } + }; + + private static class InputDialogContainerForTests extends InputDialogContainer { + private int mExpectedDialogType; + private int mExpectedYear; + private int mExpectedMonth; + private int mExpectedMonthDay; + private int mExpectedHourOfDay; + private int mExpectedMinute; + private int mExpectedSecond; + private int mExpectedMillis; + private int mExpectedWeek; + private double mExpectedMin; + private double mExpectedMax; + private double mExpectedStep; + + public InputDialogContainerForTests( + Context context, + InputDialogContainer.InputActionDelegate inputActionDelegate) { + super(context, inputActionDelegate); + } + + void setShowDialogExpectation(int dialogType, + int year, int month, int monthDay, + int hourOfDay, int minute, int second, int millis, int week, + double min, double max, double step) { + mExpectedDialogType = dialogType; + mExpectedYear = year; + mExpectedMonth = month; + mExpectedMonthDay = monthDay; + mExpectedHourOfDay = hourOfDay; + mExpectedMinute = minute; + mExpectedSecond = second; + mExpectedMillis = millis; + mExpectedWeek = week; + mExpectedMin = min; + mExpectedMax = max; + mExpectedStep = step; + } + + @Override + void showDialog(final int dialogType, + int year, int month, int monthDay, + int hourOfDay, int minute, int second, int millis, int week, + double min, double max, double step) { + assertEquals(mExpectedDialogType, dialogType); + assertEquals(mExpectedYear, year); + assertEquals(mExpectedMonth, month); + assertEquals(mExpectedMonthDay, monthDay); + assertEquals(mExpectedHourOfDay, hourOfDay); + assertEquals(mExpectedMinute, minute); + assertEquals(mExpectedSecond, second); + assertEquals(mExpectedMillis, millis); + assertEquals(mExpectedWeek, week); + assertEquals(mExpectedMin, min); + assertEquals(mExpectedMax, max); + assertEquals(mExpectedStep, step); + } + + public void setFieldDateTimeValue(int dialogType, + int year, int month, int monthDay, + int hourOfDay, int minute, int second, int millis, + int week) { + super.setFieldDateTimeValue(dialogType, + year, month, monthDay, + hourOfDay, minute, second, millis, + week); + } + } +} diff --git a/content/renderer/date_time_formatter.cc b/content/renderer/date_time_formatter.cc deleted file mode 100644 index 1b94049..0000000 --- a/content/renderer/date_time_formatter.cc +++ /dev/null @@ -1,300 +0,0 @@ -// Copyright (c) 2013 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. - -#include "content/renderer/date_time_formatter.h" - -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "third_party/WebKit/public/platform/WebCString.h" -#include "third_party/WebKit/public/web/WebDateTimeChooserParams.h" -#include "third_party/icu/source/i18n/unicode/smpdtfmt.h" - - -namespace content { - -void DateTimeFormatter::CreatePatternMap() { - // Initialize all the UI elements with empty patterns, - // then fill in the ones that are actually date/time inputs and - // are implemented. - for (int i = 0 ; i <= ui::TEXT_INPUT_TYPE_MAX; ++i) { - patterns_[i] = ""; - } - patterns_[ui::TEXT_INPUT_TYPE_DATE] = "yyyy-MM-dd"; - patterns_[ui::TEXT_INPUT_TYPE_DATE_TIME] = "yyyy-MM-dd'T'HH:mm'Z'"; - patterns_[ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL] = "yyyy-MM-dd'T'HH:mm"; - patterns_[ui::TEXT_INPUT_TYPE_MONTH] = "yyyy-MM"; - patterns_[ui::TEXT_INPUT_TYPE_TIME] = "HH:mm"; - patterns_[ui::TEXT_INPUT_TYPE_WEEK] = "Y-'W'ww"; -} - -// Returns true if icu_value parses as a valid for the specified date/time -// pattern. The date/time pattern given is for icu::SimpleDateFormat. -static bool TryPattern(const char* pattern, - const icu::UnicodeString& icu_value) { - icu::UnicodeString time_pattern = pattern; - UErrorCode success = U_ZERO_ERROR; - icu::SimpleDateFormat formatter(time_pattern, success); - formatter.parse(icu_value, success); - return success == U_ZERO_ERROR; -} - -// For a time value represented as a string find the longest time -// pattern which matches it. A valid time can have hours and minutes -// or hours, minutes and seconds or hour, minutes, seconds and upto 3 -// digits of fractional seconds. Specify step in milliseconds, it is 1000 -// times the value specified as "step" in the "<input type=time step=...> -// HTML fragment. A value of 60000 or more indicates that seconds -// are not expected and a value of 1000 or more indicates that fractional -// seconds are not expected. -static const char* FindLongestTimePatternWhichMatches(const std::string& value, - double step) { - const char* pattern = "HH:mm"; - if (step >= 60000) - return pattern; - - icu::UnicodeString icu_value = icu::UnicodeString::fromUTF8( - icu::StringPiece(value.data(), value.size())); - const char* last_pattern = pattern; - pattern = "HH:mm:ss"; - if (!TryPattern(pattern, icu_value)) - return last_pattern; - if (step >= 1000) - return pattern; - last_pattern = pattern; - pattern = "HH:mm:ss.S"; - if (!TryPattern(pattern, icu_value)) - return last_pattern; - last_pattern = pattern; - pattern = "HH:mm:ss.SS"; - if (!TryPattern(pattern, icu_value)) - return last_pattern; - last_pattern = pattern; - pattern = "HH:mm:ss.SSS"; - if (!TryPattern(pattern, icu_value)) - return last_pattern; - return pattern; -} - -DateTimeFormatter::DateTimeFormatter( - const blink::WebDateTimeChooserParams& source) - : formatted_string_(source.currentValue.utf8()) { - CreatePatternMap(); - if (source.type == blink::WebDateTimeInputTypeTime) - time_pattern_ = - FindLongestTimePatternWhichMatches(formatted_string_, source.step); - ExtractType(source); - if (!ParseValues()) { - type_ = ui::TEXT_INPUT_TYPE_NONE; - ClearAll(); - LOG(WARNING) << "Problems parsing input <" << formatted_string_ << ">"; - } -} - -DateTimeFormatter::DateTimeFormatter(ui::TextInputType type, - int year, - int month, - int day, - int hour, - int minute, - int second, - int milli, - int week_year, - int week) - : type_(type), - year_(year), - month_(month), - day_(day), - hour_(hour), - minute_(minute), - second_(second), - milli_(milli), - week_year_(week_year), - week_(week) { - CreatePatternMap(); - if (type_ == ui::TEXT_INPUT_TYPE_TIME && (second != 0 || milli != 0)) { - if (milli == 0) - time_pattern_ = "HH:mm:ss"; - else if (milli % 100 == 0) - time_pattern_ = "HH:mm:ss.S"; - else if (milli % 10 == 0) - time_pattern_ = "HH:mm:ss.SS"; - else - time_pattern_ = "HH:mm:ss.SSS"; - pattern_ = &time_pattern_; - } else { - pattern_ = type_ > 0 && type_ <= ui::TEXT_INPUT_TYPE_MAX ? - &patterns_[type_] : &patterns_[ui::TEXT_INPUT_TYPE_NONE]; - } - - formatted_string_ = FormatString(); -} - -DateTimeFormatter::~DateTimeFormatter() { -} - -int DateTimeFormatter::GetYear() const { - return year_; -} - -int DateTimeFormatter::GetMonth() const { - return month_; -} - -int DateTimeFormatter::GetDay() const { - return day_; -} - -int DateTimeFormatter::GetHour() const { - return hour_; -} - -int DateTimeFormatter::GetMinute() const { - return minute_; -} - -int DateTimeFormatter::GetSecond() const { - return second_; -} - -int DateTimeFormatter::GetMilli() const { return milli_; } - -int DateTimeFormatter::GetWeekYear() const { return week_year_; } - -int DateTimeFormatter::GetWeek() const { - return week_; -} - -ui::TextInputType DateTimeFormatter::GetType() const { - return type_; -} - -const std::string& DateTimeFormatter::GetFormattedValue() const { - return formatted_string_; -} - -const std::string DateTimeFormatter::FormatString() const { - UErrorCode success = U_ZERO_ERROR; - if (year_ == 0 && month_ == 0 && day_ == 0 && hour_ == 0 && minute_ == 0 && - second_ == 0 && milli_ == 0 && week_year_ == 0 && week_ == 0) { - return std::string(); - } - - std::string result; - icu::GregorianCalendar calendar(success); - if (success <= U_ZERO_ERROR) { - if (type_ == ui::TEXT_INPUT_TYPE_WEEK) { - // An ISO week starts with Monday. - calendar.setFirstDayOfWeek(UCAL_MONDAY); - // ISO 8601 defines that the week with the year's first Thursday is the - // first week. - calendar.setMinimalDaysInFirstWeek(4); - calendar.set(UCAL_YEAR_WOY, week_year_); - calendar.set(UCAL_WEEK_OF_YEAR, week_); - } else { - calendar.set(UCAL_YEAR, year_); - calendar.set(UCAL_MONTH, month_); - calendar.set(UCAL_DATE, day_); - calendar.set(UCAL_HOUR_OF_DAY, hour_); - calendar.set(UCAL_MINUTE, minute_); - calendar.set(UCAL_SECOND, second_); - calendar.set(UCAL_MILLISECOND, milli_); - } - icu::SimpleDateFormat formatter(*pattern_, success); - icu::UnicodeString formatted_time; - formatter.format(calendar, formatted_time, NULL, success); - UTF16ToUTF8(formatted_time.getBuffer(), - static_cast<size_t>(formatted_time.length()), - &result); - if (success <= U_ZERO_ERROR) - return result; - } - LOG(WARNING) << "Calendar not created: error " << success; - return std::string(); -} - -void DateTimeFormatter::ExtractType( - const blink::WebDateTimeChooserParams& source) { - switch (source.type) { - case blink::WebDateTimeInputTypeDate: - type_ = ui::TEXT_INPUT_TYPE_DATE; - break; - case blink::WebDateTimeInputTypeDateTime: - type_ = ui::TEXT_INPUT_TYPE_DATE_TIME; - break; - case blink::WebDateTimeInputTypeDateTimeLocal: - type_ = ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL; - break; - case blink::WebDateTimeInputTypeMonth: - type_ = ui::TEXT_INPUT_TYPE_MONTH; - break; - case blink::WebDateTimeInputTypeTime: - type_ = ui::TEXT_INPUT_TYPE_TIME; - break; - case blink::WebDateTimeInputTypeWeek: - type_ = ui::TEXT_INPUT_TYPE_WEEK; - break; - case blink::WebDateTimeInputTypeNone: - default: - type_ = ui::TEXT_INPUT_TYPE_NONE; - } -} - -// Not all fields are defined in all configurations and ICU might store -// garbage if success <= U_ZERO_ERROR so the output is sanitized here. -int DateTimeFormatter::ExtractValue( - const icu::Calendar* calendar, UCalendarDateFields value) const { - UErrorCode success = U_ZERO_ERROR; - int result = calendar->get(value, success); - return (success <= U_ZERO_ERROR) ? result : 0; -} - -bool DateTimeFormatter::ParseValues() { - if (type_ == ui::TEXT_INPUT_TYPE_NONE) { - ClearAll(); - return false; - } - - if (formatted_string_.empty()) { - ClearAll(); - return true; - } - - UErrorCode success = U_ZERO_ERROR; - icu::UnicodeString icu_value = icu::UnicodeString::fromUTF8( - icu::StringPiece(formatted_string_.data(), formatted_string_.size())); - if (type_ > 0 && type_ <= ui::TEXT_INPUT_TYPE_MAX) { - const icu::UnicodeString pattern = - type_ == ui::TEXT_INPUT_TYPE_TIME ? time_pattern_ : patterns_[type_]; - icu::SimpleDateFormat formatter(pattern, success); - formatter.parse(icu_value, success); - if (success <= U_ZERO_ERROR) { - const icu::Calendar* cal = formatter.getCalendar(); - year_ = ExtractValue(cal, UCAL_YEAR); - month_ = ExtractValue(cal, UCAL_MONTH); - day_ = ExtractValue(cal, UCAL_DATE); - hour_ = ExtractValue(cal, UCAL_HOUR_OF_DAY); // 24h format - minute_ = ExtractValue(cal, UCAL_MINUTE); - second_ = ExtractValue(cal, UCAL_SECOND); - milli_ = ExtractValue(cal, UCAL_MILLISECOND); - week_year_ = ExtractValue(cal, UCAL_YEAR_WOY); - week_ = ExtractValue(cal, UCAL_WEEK_OF_YEAR); - } - } - - return (success <= U_ZERO_ERROR); -} - -void DateTimeFormatter::ClearAll() { - year_ = 0; - month_ = 0; - day_ = 0; - hour_ = 0; - minute_ = 0; - second_ = 0; - milli_ = 0; - week_year_ = 0; - week_ = 0; -} - -} // namespace content diff --git a/content/renderer/date_time_formatter.h b/content/renderer/date_time_formatter.h deleted file mode 100644 index b91e117..0000000 --- a/content/renderer/date_time_formatter.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2013 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. - -#ifndef CONTENT_RENDERER_DATE_TIME_FORMATTER_H_ -#define CONTENT_RENDERER_DATE_TIME_FORMATTER_H_ - -#include <string> - -#include "base/basictypes.h" -#include "content/common/content_export.h" -#include "third_party/icu/source/common/unicode/unistr.h" -#include "third_party/icu/source/i18n/unicode/gregocal.h" -#include "ui/base/ime/text_input_type.h" - -namespace blink { -struct WebDateTimeChooserParams; -} // namespace blink - -namespace content { - -// Converts between a text string representing a date/time and -// a set of year/month/day/hour/minute/second/milli and vice versa. -// It is timezone agnostic. -class CONTENT_EXPORT DateTimeFormatter { - public: - explicit DateTimeFormatter(const blink::WebDateTimeChooserParams& source); - DateTimeFormatter(ui::TextInputType type, - int year, - int month, - int day, - int hour, - int minute, - int second, - int milli, - int week_year, - int week); - ~DateTimeFormatter(); - - int GetYear() const; - int GetMonth() const; - int GetDay() const; - int GetHour() const; - int GetMinute() const; - int GetSecond() const; - int GetMilli() const; - int GetWeekYear() const; - int GetWeek() const; - ui::TextInputType GetType() const; - const std::string& GetFormattedValue() const; - - private: - void CreatePatternMap(); - bool ParseValues(); - const std::string FormatString() const; - int ExtractValue( - const icu::Calendar* calendar, UCalendarDateFields value) const; - void ExtractType(const blink::WebDateTimeChooserParams& source); - void ClearAll(); - - ui::TextInputType type_; - icu::UnicodeString patterns_[ui::TEXT_INPUT_TYPE_MAX + 1]; - icu::UnicodeString time_pattern_; - int year_; - int month_; - int day_; - int hour_; - int minute_; - int second_; - int milli_; - int week_year_; - int week_; - const icu::UnicodeString* pattern_; - std::string formatted_string_; - - DISALLOW_COPY_AND_ASSIGN(DateTimeFormatter); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_DATE_TIME_FORMATTER_H_ diff --git a/content/renderer/date_time_formatter_unittest.cc b/content/renderer/date_time_formatter_unittest.cc deleted file mode 100644 index b521188..0000000 --- a/content/renderer/date_time_formatter_unittest.cc +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright (c) 2013 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. - -#include <map> - -#include "content/renderer/date_time_formatter.h" -#include "content/renderer/renderer_date_time_picker.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/WebKit/public/web/WebDateTimeChooserParams.h" -#include "third_party/icu/source/common/unicode/unistr.h" -#include "ui/base/ime/text_input_type.h" - -namespace content { - -class RendererDateTimePickerTest { -}; - -TEST(RendererDateTimePickerTest, TestParserValidStringInputs) { - blink::WebDateTimeChooserParams params; - params.currentValue = "2010-07"; - params.type = blink::WebDateTimeInputTypeMonth; - DateTimeFormatter sut(params); - EXPECT_EQ(2010, sut.GetYear()); - - // Month field is 0 based - EXPECT_EQ(6, sut.GetMonth()); - - // Month input defaults to the first day of the month (1 based) - EXPECT_EQ(1, sut.GetDay()); - EXPECT_EQ(0, sut.GetHour()); - EXPECT_EQ(0, sut.GetMinute()); - EXPECT_EQ(0, sut.GetSecond()); - EXPECT_EQ(2010, sut.GetWeekYear()); - EXPECT_EQ(26, sut.GetWeek()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_MONTH, sut.GetType()); - - params.currentValue = "2012-05-25"; - params.type = blink::WebDateTimeInputTypeDate; - DateTimeFormatter sut2(params); - EXPECT_EQ(2012, sut2.GetYear()); - EXPECT_EQ(4, sut2.GetMonth()); - EXPECT_EQ(25, sut2.GetDay()); - EXPECT_EQ(0, sut2.GetHour()); - EXPECT_EQ(0, sut2.GetMinute()); - EXPECT_EQ(0, sut2.GetSecond()); - EXPECT_EQ(2012, sut2.GetWeekYear()); - EXPECT_EQ(21, sut2.GetWeek()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_DATE, sut2.GetType()); - - params.currentValue = "2013-05-21T12:15"; - params.type = blink::WebDateTimeInputTypeDateTimeLocal; - DateTimeFormatter sut3(params); - EXPECT_EQ(2013, sut3.GetYear()); - EXPECT_EQ(4, sut3.GetMonth()); - EXPECT_EQ(21, sut3.GetDay()); - EXPECT_EQ(12, sut3.GetHour()); - EXPECT_EQ(15, sut3.GetMinute()); - EXPECT_EQ(0, sut3.GetSecond()); - EXPECT_EQ(2013, sut3.GetWeekYear()); - EXPECT_EQ(21, sut3.GetWeek()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL, sut3.GetType()); - - params.currentValue = "2013-W15"; - params.type = blink::WebDateTimeInputTypeWeek; - DateTimeFormatter sut4(params); - EXPECT_EQ(2013, sut4.GetYear()); - EXPECT_EQ(3, sut4.GetMonth()); - EXPECT_EQ(7, sut4.GetDay()); - EXPECT_EQ(0, sut4.GetHour()); - EXPECT_EQ(0, sut4.GetMinute()); - EXPECT_EQ(0, sut4.GetSecond()); - EXPECT_EQ(2013, sut4.GetWeekYear()); - EXPECT_EQ(15, sut4.GetWeek()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_WEEK, sut4.GetType()); - - params.currentValue = "12:15"; - params.type = blink::WebDateTimeInputTypeTime; - DateTimeFormatter sut5(params); - EXPECT_EQ(12, sut5.GetHour()); - EXPECT_EQ(15, sut5.GetMinute()); - EXPECT_EQ(0, sut5.GetSecond()); - EXPECT_EQ(0, sut5.GetMilli()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_TIME, sut5.GetType()); - - params.currentValue = "12:15:02"; - params.type = blink::WebDateTimeInputTypeTime; - DateTimeFormatter sut6(params); - EXPECT_EQ(12, sut6.GetHour()); - EXPECT_EQ(15, sut6.GetMinute()); - EXPECT_EQ(02, sut6.GetSecond()); - EXPECT_EQ(0, sut6.GetMilli()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_TIME, sut6.GetType()); - - params.currentValue = "12:15:02.1"; - params.type = blink::WebDateTimeInputTypeTime; - DateTimeFormatter sut7(params); - EXPECT_EQ(12, sut7.GetHour()); - EXPECT_EQ(15, sut7.GetMinute()); - EXPECT_EQ(02, sut7.GetSecond()); - EXPECT_EQ(100, sut7.GetMilli()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_TIME, sut7.GetType()); - - params.currentValue = "12:15:02.123"; - params.type = blink::WebDateTimeInputTypeTime; - DateTimeFormatter sut8(params); - EXPECT_EQ(12, sut8.GetHour()); - EXPECT_EQ(15, sut8.GetMinute()); - EXPECT_EQ(02, sut8.GetSecond()); - EXPECT_EQ(123, sut8.GetMilli()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_TIME, sut8.GetType()); -} - - -TEST(RendererDateTimePickerTest, TestParserInvalidStringInputs) { - - // Random non parsable text - blink::WebDateTimeChooserParams params; - params.currentValue = "<script injection"; - params.type = blink::WebDateTimeInputTypeMonth; - DateTimeFormatter sut(params); - EXPECT_EQ(0, sut.GetYear()); - EXPECT_EQ(0, sut.GetMonth()); - EXPECT_EQ(0, sut.GetDay()); - EXPECT_EQ(0, sut.GetHour()); - EXPECT_EQ(0, sut.GetMinute()); - EXPECT_EQ(0, sut.GetSecond()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, sut.GetType()); - - // unimplemented type - params.currentValue = "week 23"; - params.type = blink::WebDateTimeInputTypeWeek; // Not implemented - DateTimeFormatter sut2(params); - EXPECT_EQ(0, sut2.GetYear()); - EXPECT_EQ(0, sut2.GetMonth()); - EXPECT_EQ(0, sut2.GetDay()); - EXPECT_EQ(0, sut2.GetHour()); - EXPECT_EQ(0, sut2.GetMinute()); - EXPECT_EQ(0, sut2.GetSecond()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, sut2.GetType()); - - // type is a subset of pattern - params.currentValue = "2012-05-25"; - params.type = blink::WebDateTimeInputTypeDateTimeLocal; - DateTimeFormatter sut3(params); - EXPECT_EQ(0, sut3.GetYear()); - EXPECT_EQ(0, sut3.GetMonth()); - EXPECT_EQ(0, sut3.GetDay()); - EXPECT_EQ(0, sut3.GetHour()); - EXPECT_EQ(0, sut3.GetMinute()); - EXPECT_EQ(0, sut3.GetSecond()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, sut3.GetType()); - - // type is a superset of pattern - params.currentValue = "2013-05-21T12:15"; - params.type = blink::WebDateTimeInputTypeMonth; - DateTimeFormatter sut4(params); - EXPECT_EQ(2013, sut4.GetYear()); - EXPECT_EQ(4, sut4.GetMonth()); - EXPECT_EQ(1, sut4.GetDay()); - EXPECT_EQ(0, sut4.GetHour()); - EXPECT_EQ(0, sut4.GetMinute()); - EXPECT_EQ(0, sut4.GetSecond()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_MONTH, sut4.GetType()); -} - - -TEST(RendererDateTimePickerTest, TestParserValidDateInputs) { - DateTimeFormatter sut( - ui::TEXT_INPUT_TYPE_MONTH, 2012, 11, 1, 0, 0, 0, 0, 0, 0); - EXPECT_EQ("2012-12", sut.GetFormattedValue()); - - DateTimeFormatter sut2( - ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL, 2013, 3, 23, 15, 47, 0, 0, 0, 0); - EXPECT_EQ("2013-04-23T15:47", sut2.GetFormattedValue()); - - DateTimeFormatter sut3( - ui::TEXT_INPUT_TYPE_WEEK, 0, 0, 0, 0, 0, 0, 0, 2012, 2); - EXPECT_EQ("2012-W02", sut3.GetFormattedValue()); -} - -TEST(RendererDateTimePickerTest, TestParserValidTimeInputs) { - DateTimeFormatter sut( - ui::TEXT_INPUT_TYPE_TIME, 0, 0, 0, 12, 15, 0, 0, 0, 0); - EXPECT_EQ("12:15", sut.GetFormattedValue()); - - DateTimeFormatter sut2( - ui::TEXT_INPUT_TYPE_TIME, 0, 0, 0, 12, 15, 02, 0, 0, 0); - EXPECT_EQ("12:15:02", sut2.GetFormattedValue()); - - DateTimeFormatter sut3( - ui::TEXT_INPUT_TYPE_TIME, 0, 0, 0, 12, 15, 02, 123, 0, 0); - EXPECT_EQ("12:15:02.123", sut3.GetFormattedValue()); -} - -TEST(RendererDateTimePickerTest, TestParserInvalidDateInputs) { - DateTimeFormatter sut(ui::TEXT_INPUT_TYPE_WEEK, 0, 0, 0, 0, 0, 0, 0, 0, 0); - EXPECT_EQ("", sut.GetFormattedValue()); - - DateTimeFormatter sut2( - ui::TEXT_INPUT_TYPE_NONE, 2013, 3, 23, 0, 0, 0, 0, 0, 0); - EXPECT_EQ("", sut2.GetFormattedValue()); - - DateTimeFormatter sut3( - ui::TEXT_INPUT_TYPE_NONE, 2013, 14, 32, 0, 0, 0, 0, 0, 0); - EXPECT_EQ("", sut3.GetFormattedValue()); - - DateTimeFormatter sut4(ui::TEXT_INPUT_TYPE_DATE, 0, 0, 0, 0, 0, 0, 0, 0, 0); - EXPECT_EQ("", sut4.GetFormattedValue()); - - DateTimeFormatter sut5(ui::TEXT_INPUT_TYPE_TIME, 0, 0, 0, 0, 0, 0, 0, 0, 0); - EXPECT_EQ("", sut5.GetFormattedValue()); - - DateTimeFormatter sut6( - ui::TEXT_INPUT_TYPE_PASSWORD, 23, 0, 0, 0, 5, 0, 0, 0, 0); - EXPECT_EQ("", sut6.GetFormattedValue()); - - DateTimeFormatter sut7(ui::TEXT_INPUT_TYPE_MAX, 23, 0, 0, 0, 5, 0, 0, 0, 0); - EXPECT_EQ("", sut7.GetFormattedValue()); - - DateTimeFormatter sut8( - static_cast<ui::TextInputType>(10000), 23, 0, 0, 0, 5, 0, 0, 0, 0); - EXPECT_EQ("", sut8.GetFormattedValue()); -} -} // namespace content diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 2648186..fe704b2 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc @@ -112,7 +112,6 @@ #include "content/renderer/render_view_impl_params.h" #include "content/renderer/render_view_mouse_lock_dispatcher.h" #include "content/renderer/render_widget_fullscreen_pepper.h" -#include "content/renderer/renderer_date_time_picker.h" #include "content/renderer/renderer_webapplicationcachehost_impl.h" #include "content/renderer/renderer_webcolorchooser_impl.h" #include "content/renderer/resizing_mode_selector.h" @@ -6150,11 +6149,21 @@ void RenderViewImpl::LaunchAndroidContentIntent(const GURL& intent, bool RenderViewImpl::openDateTimeChooser( const blink::WebDateTimeChooserParams& params, blink::WebDateTimeChooserCompletion* completion) { + // JavaScript may try to open a date time chooser while one is already open. + if (date_time_picker_client_) + return false; date_time_picker_client_.reset( new RendererDateTimePicker(this, params, completion)); return date_time_picker_client_->Open(); } +#if defined(OS_ANDROID) +void RenderViewImpl::DismissDateTimeDialog() { + DCHECK(date_time_picker_client_); + date_time_picker_client_.reset(NULL); +} +#endif + WebMediaPlayer* RenderViewImpl::CreateAndroidWebMediaPlayer( WebFrame* frame, const blink::WebURL& url, diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index 6a7ce2f..8ad186f 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h @@ -39,6 +39,7 @@ #include "content/renderer/mouse_lock_dispatcher.h" #include "content/renderer/render_frame_impl.h" #include "content/renderer/render_widget.h" +#include "content/renderer/renderer_date_time_picker.h" #include "content/renderer/renderer_webcookiejar_impl.h" #include "content/renderer/stats_collection_observer.h" #include "ipc/ipc_platform_file.h" @@ -272,6 +273,10 @@ class CONTENT_EXPORT RenderViewImpl const std::string& html, bool replace); +#if defined(OS_ANDROID) + void DismissDateTimeDialog(); +#endif + // Plugin-related functions -------------------------------------------------- #if defined(ENABLE_PLUGINS) diff --git a/content/renderer/renderer_date_time_picker.cc b/content/renderer/renderer_date_time_picker.cc index 074ebe5..46f0c38 100644 --- a/content/renderer/renderer_date_time_picker.cc +++ b/content/renderer/renderer_date_time_picker.cc @@ -6,45 +6,47 @@ #include "base/strings/string_util.h" #include "content/common/view_messages.h" -#include "content/renderer/date_time_formatter.h" #include "content/renderer/render_view_impl.h" - #include "third_party/WebKit/public/web/WebDateTimeChooserCompletion.h" #include "third_party/WebKit/public/web/WebDateTimeChooserParams.h" #include "third_party/WebKit/public/web/WebDateTimeInputType.h" +#include "ui/base/ime/text_input_type.h" using blink::WebString; namespace content { +COMPILE_ASSERT(int(blink::WebTextInputTypeDate) == \ + int(ui::TEXT_INPUT_TYPE_DATE), mismatching_enum); +COMPILE_ASSERT(int(blink::WebTextInputTypeDateTime) == \ + int(ui::TEXT_INPUT_TYPE_DATE_TIME), mismatching_enum); +COMPILE_ASSERT(int(blink::WebTextInputTypeDateTimeLocal) == \ + int(ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL), mismatching_enum); +COMPILE_ASSERT(int(blink::WebTextInputTypeMonth) == \ + int(ui::TEXT_INPUT_TYPE_MONTH), mismatching_enum); +COMPILE_ASSERT(int(blink::WebTextInputTypeTime) == \ + int(ui::TEXT_INPUT_TYPE_TIME), mismatching_enum); +COMPILE_ASSERT(int(blink::WebTextInputTypeWeek) == \ + int(ui::TEXT_INPUT_TYPE_WEEK), mismatching_enum); +COMPILE_ASSERT(int(blink::WebTextInputTypeDateTimeField) == \ + int(ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD), mismatching_enums); + RendererDateTimePicker::RendererDateTimePicker( RenderViewImpl* sender, const blink::WebDateTimeChooserParams& params, blink::WebDateTimeChooserCompletion* completion) : RenderViewObserver(sender), chooser_params_(params), - chooser_completion_(completion){ + chooser_completion_(completion) { } RendererDateTimePicker::~RendererDateTimePicker() { } bool RendererDateTimePicker::Open() { - DateTimeFormatter parser(chooser_params_); ViewHostMsg_DateTimeDialogValue_Params message; - message.dialog_type = parser.GetType(); - if (message.dialog_type == ui::TEXT_INPUT_TYPE_WEEK) { - message.year = parser.GetWeekYear(); - message.week = parser.GetWeek(); - } else { - message.year = parser.GetYear(); - message.month = parser.GetMonth(); - message.day = parser.GetDay(); - message.hour = parser.GetHour(); - message.minute = parser.GetMinute(); - message.second = parser.GetSecond(); - message.milli = parser.GetMilli(); - } + message.dialog_type = static_cast<ui::TextInputType>(chooser_params_.type); + message.dialog_value = chooser_params_.doubleValue; message.minimum = chooser_params_.minimum; message.maximum = chooser_params_.maximum; message.step = chooser_params_.step; @@ -63,28 +65,20 @@ bool RendererDateTimePicker::OnMessageReceived( return handled; } -void RendererDateTimePicker::OnReplaceDateTime( - const ViewHostMsg_DateTimeDialogValue_Params& value) { - - DateTimeFormatter formatter(static_cast<ui::TextInputType>(value.dialog_type), - value.year, - value.month, - value.day, - value.hour, - value.minute, - value.second, - value.milli, - value.year, - value.week); - +void RendererDateTimePicker::OnReplaceDateTime(double value) { if (chooser_completion_) - chooser_completion_->didChooseValue(WebString::fromUTF8( - formatter.GetFormattedValue().c_str())); + chooser_completion_->didChooseValue(value); +#if defined(OS_ANDROID) + static_cast<RenderViewImpl*>(render_view())->DismissDateTimeDialog(); +#endif } void RendererDateTimePicker::OnCancel() { if (chooser_completion_) chooser_completion_->didCancelChooser(); +#if defined(OS_ANDROID) + static_cast<RenderViewImpl*>(render_view())->DismissDateTimeDialog(); +#endif } } // namespace content diff --git a/content/renderer/renderer_date_time_picker.h b/content/renderer/renderer_date_time_picker.h index 2dc6386..7a780c7 100644 --- a/content/renderer/renderer_date_time_picker.h +++ b/content/renderer/renderer_date_time_picker.h @@ -29,7 +29,7 @@ class RendererDateTimePicker : public RenderViewObserver { bool Open(); private: - void OnReplaceDateTime(const ViewHostMsg_DateTimeDialogValue_Params& value); + void OnReplaceDateTime(double value); void OnCancel(); // RenderViewObserver |