ed4fa9d168958703b9169904160450eddf4f743b
[platform/framework/web/chromium-efl.git] / tizen_src / ewk / efl_integration / browser / input_picker / input_picker.cc
1 // Copyright 2014 Samsung Electronics. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "input_picker.h"
6
7 #include <Elementary.h>
8 #include <math.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12 #include "base/files/file_path.h"
13 #include "base/logging.h"
14 #include "base/path_service.h"
15 #include "base/time/time.h"
16 #include "common/web_contents_utils.h"
17 #include "content/common/paths_efl.h"
18 #include "content/public/browser/web_contents.h"
19
20 #if BUILDFLAG(IS_TIZEN)
21 #include <vconf/vconf.h>
22 #endif
23
24 namespace content {
25
26 static const char* kDefaultDatetimeFormat = "%Y/%m/%d %H:%M";
27
28 InputPicker::Layout::Layout(InputPicker* parent) : parent_(parent) {
29   evas_object_focus_set(parent_->web_view_->evas_object(), false);
30   // FIXME: Workaround. OSP requirement. OSP want to block own touch event
31   // while webkit internal picker is running.
32   evas_object_smart_callback_call(parent_->web_view_->evas_object(),
33                                   "input,picker,show", 0);
34 }
35
36 InputPicker::Layout::~Layout() {
37   // FIXME: Workaround. OSP requirement. OSP want to block own touch event
38   // while webkit internal picker is running.
39   evas_object_smart_callback_call(parent_->web_view_->evas_object(),
40                                   "input,picker,hide", 0);
41   evas_object_focus_set(parent_->web_view_->evas_object(), true);
42
43   if (!conformant_)
44     return;
45
46   if (is_color_picker_)
47     DeleteColorPickerCallbacks();
48   else
49     DeleteDatePickerCallbacks();
50
51   evas_object_del(conformant_);
52   conformant_ = nullptr;
53 }
54
55 // static
56 InputPicker::Layout* InputPicker::Layout::CreateAndShowColorPickerLayout(
57     InputPicker* parent,
58     int r,
59     int g,
60     int b) {
61   std::unique_ptr<Layout> picker_layout(new Layout(parent));
62   picker_layout->is_color_picker_ = true;
63
64   if (!picker_layout->AddBaseLayout(
65           dgettext("WebKit", "IDS_WEBVIEW_HEADER_SELECT_COLOUR"),
66           "colorselector_popup_layout")) {
67     return nullptr;
68   }
69
70   picker_layout->color_rect_ =
71       evas_object_rectangle_add(evas_object_evas_get(picker_layout->layout_));
72   if (!picker_layout->color_rect_)
73     return nullptr;
74
75   evas_object_size_hint_weight_set(picker_layout->color_rect_, EVAS_HINT_EXPAND,
76                                    EVAS_HINT_EXPAND);
77   evas_object_show(picker_layout->color_rect_);
78   evas_object_color_set(picker_layout->color_rect_, r, g, b, 255);
79   elm_object_part_content_set(picker_layout->layout_, "rect",
80                               picker_layout->color_rect_);
81
82   if (!picker_layout->AddColorSelector(r, g, b))
83     return nullptr;
84
85   if (!picker_layout->AddButtons())
86     return nullptr;
87
88   picker_layout->red_ = r;
89   picker_layout->green_ = g;
90   picker_layout->blue_ = b;
91
92   picker_layout->AddColorPickerCallbacks();
93   evas_object_show(picker_layout->popup_);
94   return picker_layout.release();
95 }
96
97 static char* GetDateTimeFormat() {
98 #if BUILDFLAG(IS_TIZEN)
99   char* language = vconf_get_str(VCONFKEY_LANGSET);
100   if (!vconf_set_str(VCONFKEY_LANGSET, "en_US"))
101     LOG(ERROR) << "vconf_set_str failed ";
102
103   char* region_format = vconf_get_str(VCONFKEY_REGIONFORMAT);
104   if (!region_format)
105     return nullptr;
106
107   int time_value = 0;
108   char buf[256] = {
109       0,
110   };
111   vconf_get_int(VCONFKEY_REGIONFORMAT_TIME1224, &time_value);
112   if (time_value == VCONFKEY_TIME_FORMAT_24)
113     snprintf(buf, sizeof(buf), "%s_DTFMT_24HR", region_format);
114   else
115     snprintf(buf, sizeof(buf), "%s_DTFMT_12HR", region_format);
116
117   free(region_format);
118
119   // FIXME: Workaround fix for region format.
120   int buf_length = strlen(buf);
121   for (int i = 0; i < buf_length - 4; i++) {
122     if (buf[i] == 'u' && buf[i + 1] == 't' && buf[i + 2] == 'f') {
123       if (buf[i + 3] == '8') {
124         // utf8 -> UTF-8
125         for (int j = buf_length; j > i + 3; j--)
126           buf[j] = buf[j - 1];
127         buf[i + 3] = '-';
128         buf[buf_length + 1] = '\0';
129       } else if (buf[i + 3] == '-' && buf[i + 4] == '8') {
130         // utf-8 -> UTF-8
131       } else {
132         break;
133       }
134
135       buf[i] = 'U';
136       buf[i + 1] = 'T';
137       buf[i + 2] = 'F';
138       break;
139     }
140   }
141
142   char* date_time_format = dgettext("dt_fmt", buf);
143   if (language && !vconf_set_str(VCONFKEY_LANGSET, language))
144     LOG(ERROR) << "vconf_set_str failed ";
145
146   // FIXME: Workaround fix for not supported dt_fmt.
147   // Use default format if dt_fmt string is not exist.
148   if (strlen(date_time_format) == strlen(buf) &&
149       !strncmp(date_time_format, buf, strlen(buf))) {
150     return nullptr;
151   }
152
153   return strdup(date_time_format);
154 #else
155   return nullptr;
156 #endif
157 }
158
159 // static
160 InputPicker::Layout* InputPicker::Layout::CreateAndShowDateLayout(
161     InputPicker* parent,
162     struct tm* current_time,
163     ui::TextInputType type) {
164   std::unique_ptr<Layout> picker_layout(new Layout(parent));
165
166   picker_layout->input_type_ = type;
167
168   std::string title;
169   switch (type) {
170     case ui::TEXT_INPUT_TYPE_DATE: {
171       title = "IDS_WEBVIEW_HEADER_SET_DATE";
172       break;
173     }
174     case ui::TEXT_INPUT_TYPE_WEEK: {
175       title = "IDS_WEBVIEW_HEADER_SET_WEEK";
176       break;
177     }
178     case ui::TEXT_INPUT_TYPE_MONTH: {
179       title = "IDS_WEBVIEW_HEADER_SET_MONTH";
180       break;
181     }
182     default:
183       NOTREACHED();
184       break;
185   }
186
187   if (!picker_layout->AddBaseLayout(dgettext("WebKit", title.c_str()),
188                                     "date_popup")) {
189     return nullptr;
190   }
191
192   picker_layout->date_picker_ = elm_datetime_add(picker_layout->layout_);
193   if (!picker_layout->date_picker_)
194     return nullptr;
195
196   elm_object_part_content_set(picker_layout->layout_, "elm.swallow.datetime",
197                               picker_layout->date_picker_);
198
199   char* format = GetDateTimeFormat();
200   if (format) {
201     elm_datetime_format_set(picker_layout->date_picker_, format);
202     free(format);
203   } else {
204     elm_datetime_format_set(picker_layout->date_picker_,
205                             kDefaultDatetimeFormat);
206   }
207
208   elm_datetime_value_set(picker_layout->date_picker_, current_time);
209
210   if (!picker_layout->AddButtons())
211     return nullptr;
212
213   if (type == ui::TEXT_INPUT_TYPE_MONTH) {
214     elm_datetime_field_visible_set(picker_layout->date_picker_,
215                                    ELM_DATETIME_DATE, EINA_FALSE);
216   }
217   elm_datetime_field_visible_set(picker_layout->date_picker_, ELM_DATETIME_HOUR,
218                                  EINA_FALSE);
219   elm_datetime_field_visible_set(picker_layout->date_picker_,
220                                  ELM_DATETIME_MINUTE, EINA_FALSE);
221
222   picker_layout->AddDatePickerCallbacks();
223
224   evas_object_show(picker_layout->popup_);
225
226   return picker_layout.release();
227 }
228
229 // static
230 InputPicker::Layout* InputPicker::Layout::CreateAndShowDateTimeLayout(
231     InputPicker* parent,
232     struct tm* current_time,
233     ui::TextInputType type) {
234   std::unique_ptr<Layout> picker_layout(new Layout(parent));
235
236   picker_layout->input_type_ = type;
237
238   elm_object_scale_set(picker_layout->popup_, 0.7);
239   if (!picker_layout->AddBaseLayout(
240           dgettext("WebKit", "IDS_WEBVIEW_HEADER_SET_DATE_AND_TIME"),
241           "datetime_popup")) {
242     return nullptr;
243   }
244
245   picker_layout->time_picker_ = elm_datetime_add(picker_layout->layout_);
246   picker_layout->date_picker_ = elm_datetime_add(picker_layout->layout_);
247   if (!picker_layout->time_picker_ || !picker_layout->date_picker_)
248     return nullptr;
249
250   elm_object_part_content_set(picker_layout->layout_, "elm.swallow.datetime",
251                               picker_layout->time_picker_);
252   elm_object_part_content_set(picker_layout->layout_, "elm.swallow.datetime2",
253                               picker_layout->date_picker_);
254   elm_object_style_set(picker_layout->time_picker_, "time_layout");
255
256   char* format = GetDateTimeFormat();
257   if (format) {
258     elm_datetime_format_set(picker_layout->date_picker_, format);
259     elm_datetime_format_set(picker_layout->time_picker_, format);
260     free(format);
261   } else {
262     elm_datetime_format_set(picker_layout->date_picker_,
263                             kDefaultDatetimeFormat);
264     elm_datetime_format_set(picker_layout->time_picker_,
265                             kDefaultDatetimeFormat);
266   }
267
268   elm_datetime_value_set(picker_layout->date_picker_, current_time);
269   elm_datetime_value_set(picker_layout->time_picker_, current_time);
270   if (!picker_layout->AddButtons())
271     return nullptr;
272
273   picker_layout->AddDatePickerCallbacks();
274   evas_object_show(picker_layout->popup_);
275
276   return picker_layout.release();
277 }
278
279 bool InputPicker::Layout::SetDatetimePicker(Evas_Object* picker,
280                                             const char* style) {
281   return false;
282 }
283
284 // static
285 InputPicker::Layout* InputPicker::Layout::CreateAndShowTimeLayout(
286     InputPicker* parent,
287     struct tm* current_time) {
288   std::unique_ptr<Layout> picker_layout(new Layout(parent));
289
290   picker_layout->input_type_ = ui::TEXT_INPUT_TYPE_TIME;
291
292   if (!picker_layout->AddBaseLayout(
293           dgettext("WebKit", "IDS_WEBVIEW_HEADER_SET_TIME"), "date_popup")) {
294     return nullptr;
295   }
296
297   picker_layout->time_picker_ = elm_datetime_add(picker_layout->layout_);
298   if (!picker_layout->time_picker_)
299     return nullptr;
300
301   elm_object_style_set(picker_layout->time_picker_, "time_layout");
302   elm_object_part_content_set(picker_layout->layout_, "elm.swallow.datetime",
303                               picker_layout->time_picker_);
304
305   char* format = GetDateTimeFormat();
306   if (format) {
307     elm_datetime_format_set(picker_layout->time_picker_, format);
308     free(format);
309   } else {
310     elm_datetime_format_set(picker_layout->time_picker_,
311                             kDefaultDatetimeFormat);
312   }
313
314   elm_datetime_value_set(picker_layout->time_picker_, current_time);
315
316   if (!picker_layout->AddButtons())
317     return nullptr;
318
319   elm_datetime_field_visible_set(picker_layout->time_picker_, ELM_DATETIME_YEAR,
320                                  EINA_FALSE);
321   elm_datetime_field_visible_set(picker_layout->time_picker_,
322                                  ELM_DATETIME_MONTH, EINA_FALSE);
323   elm_datetime_field_visible_set(picker_layout->time_picker_, ELM_DATETIME_DATE,
324                                  EINA_FALSE);
325
326   picker_layout->AddDatePickerCallbacks();
327
328   evas_object_show(picker_layout->popup_);
329
330   return picker_layout.release();
331 }
332
333 bool InputPicker::Layout::AddBaseLayout(const char* title,
334                                         const char* layout_group) {
335   Evas_Object* top_widget = parent_->web_view_->GetElmWindow();
336
337   conformant_ = elm_conformant_add(top_widget);
338   if (!conformant_)
339     return false;
340
341   evas_object_size_hint_weight_set(conformant_, EVAS_HINT_EXPAND,
342                                    EVAS_HINT_EXPAND);
343   elm_win_resize_object_add(top_widget, conformant_);
344   evas_object_show(conformant_);
345
346   Evas_Object* layout = elm_layout_add(conformant_);
347   if (!layout)
348     return false;
349
350   elm_layout_theme_set(layout, "layout", "application", "default");
351   evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
352   evas_object_show(layout);
353   elm_object_content_set(conformant_, layout);
354
355   popup_ = elm_popup_add(layout);
356   if (!popup_)
357     return false;
358
359   elm_popup_align_set(popup_, ELM_NOTIFY_ALIGN_FILL, 1.0);
360
361   elm_object_part_text_set(popup_, "title,text", title);
362   evas_object_size_hint_weight_set(popup_, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
363
364   layout_ = elm_layout_add(popup_);
365   if (!layout_)
366     return false;
367
368   elm_object_content_set(popup_, layout_);
369   base::FilePath edj_dir;
370   base::FilePath control_path;
371   base::PathService::Get(PathsEfl::EDJE_RESOURCE_DIR, &edj_dir);
372   control_path = edj_dir.Append(FILE_PATH_LITERAL("control.edj"));
373   elm_layout_file_set(layout_, control_path.AsUTF8Unsafe().c_str(),
374                       layout_group);
375   evas_object_size_hint_align_set(layout_, EVAS_HINT_FILL, EVAS_HINT_FILL);
376   evas_object_size_hint_weight_set(layout_, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
377
378   return true;
379 }
380
381 bool InputPicker::Layout::AddButtons() {
382   set_button_ = elm_button_add(popup_);
383   cancel_button_ = elm_button_add(popup_);
384   if (!cancel_button_)
385     return false;
386   elm_object_domain_translatable_part_text_set(
387       cancel_button_, NULL, "WebKit", "IDS_WEBVIEW_BUTTON_CANCEL_ABB4");
388
389   if (!set_button_)
390     return false;
391
392   elm_object_domain_translatable_part_text_set(set_button_, NULL, "WebKit",
393                                                "IDS_WEBVIEW_BUTTON_SET_ABB2");
394   elm_object_style_set(set_button_, "popup");
395   elm_object_style_set(cancel_button_, "popup");
396   elm_object_part_content_set(popup_, "button2", set_button_);
397   elm_object_part_content_set(popup_, "button1", cancel_button_);
398   evas_object_focus_set(cancel_button_, true);
399   evas_object_focus_set(set_button_, true);
400
401   return true;
402 }
403
404 bool InputPicker::Layout::AddColorSelector(int r, int g, int b) {
405   color_picker_ = elm_colorselector_add(layout_);
406   if (!color_picker_)
407     return false;
408
409   elm_colorselector_mode_set(color_picker_, ELM_COLORSELECTOR_PALETTE);
410   evas_object_size_hint_fill_set(color_picker_, EVAS_HINT_FILL, EVAS_HINT_FILL);
411   evas_object_size_hint_weight_set(color_picker_, EVAS_HINT_EXPAND,
412                                    EVAS_HINT_EXPAND);
413
414   if (IsTvProfile()) {
415     elm_colorselector_color_set(color_picker_, r, g, b, 255);
416   } else {
417     Eina_List* color_list = const_cast<Eina_List*>(
418         elm_colorselector_palette_items_get(color_picker_));
419     Eina_List* list = nullptr;
420     Elm_Object_Item* it = nullptr;
421     void* item = nullptr;
422     int red = 0;
423     int green = 0;
424     int blue = 0;
425     int alpha = 0;
426
427     EINA_LIST_FOREACH(color_list, list, item) {
428       if (item) {
429         Elm_Object_Item* elm_item = static_cast<Elm_Object_Item*>(item);
430         elm_colorselector_palette_item_color_get(elm_item, &red, &green, &blue,
431                                                  &alpha);
432         if (red == r && green == g && blue == b) {
433           it = elm_item;
434           break;
435         }
436       }
437     }
438
439     if (!it)
440       it = static_cast<Elm_Object_Item*>(eina_list_nth(color_list, 0));
441
442     elm_object_item_signal_emit(it, "elm,state,selected", "elm");
443   }
444
445   elm_object_part_content_set(layout_, "colorpalette", color_picker_);
446
447   return true;
448 }
449
450 void InputPicker::Layout::AddColorPickerCallbacks() {
451   evas_object_smart_callback_add(color_picker_, "color,item,selected",
452                                  ColorPickerItemSelectedCallback, color_rect_);
453   evas_object_smart_callback_add(set_button_, "clicked",
454                                  ColorPickerSelectFinishedCallback, this);
455 #if BUILDFLAG(IS_TIZEN)
456   eext_object_event_callback_add(layout_, EEXT_CALLBACK_BACK,
457                                  ColorPickerBackKeyCallback, this);
458 #endif
459 }
460
461 void InputPicker::Layout::DeleteColorPickerCallbacks() {
462   if (color_picker_) {
463     evas_object_smart_callback_del(color_picker_, "color,item,selected",
464                                    ColorPickerItemSelectedCallback);
465   }
466
467   if (set_button_) {
468     evas_object_smart_callback_del(set_button_, "clicked",
469                                    ColorPickerSelectFinishedCallback);
470   }
471   if (cancel_button_) {
472     evas_object_smart_callback_del(cancel_button_, "clicked",
473                                    ColorPickerBackKeyCallback);
474   }
475
476 #if BUILDFLAG(IS_TIZEN)
477   if (popup_) {
478     eext_object_event_callback_del(layout_, EEXT_CALLBACK_BACK,
479                                    ColorPickerBackKeyCallback);
480   }
481 #endif
482 }
483
484 void InputPicker::Layout::AddDatePickerCallbacks() {
485   evas_object_smart_callback_add(set_button_, "clicked",
486                                  DatePickerSelectFinishedCallback, this);
487   evas_object_smart_callback_add(cancel_button_, "clicked",
488                                  DatePickerBackKeyCallback, this);
489
490   if (input_type_ == ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD ||
491       input_type_ == ui::TEXT_INPUT_TYPE_DATE_TIME ||
492       input_type_ == ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL) {
493     evas_object_smart_callback_add(date_picker_, "changed",
494                                    DatePickerItemChangedCallback, this);
495     evas_object_smart_callback_add(time_picker_, "changed",
496                                    DatePickerItemChangedCallback, this);
497   }
498
499   if (IsTvProfile()) {
500     elm_object_signal_emit(layout_, "TV", "align,swallow.datetime");
501   }
502
503 #if BUILDFLAG(IS_TIZEN)
504   eext_object_event_callback_add(layout_, EEXT_CALLBACK_BACK,
505                                  DatePickerBackKeyCallback, this);
506 #endif
507 }
508
509 void InputPicker::Layout::DeleteDatePickerCallbacks() {
510   if (set_button_) {
511     evas_object_smart_callback_del(set_button_, "clicked",
512                                    DatePickerSelectFinishedCallback);
513   }
514   if (cancel_button_) {
515     evas_object_smart_callback_del(cancel_button_, "clicked",
516                                    DatePickerBackKeyCallback);
517   }
518
519   if (input_type_ == ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD ||
520       input_type_ == ui::TEXT_INPUT_TYPE_DATE_TIME ||
521       input_type_ == ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL) {
522     if (date_picker_) {
523       evas_object_smart_callback_del(date_picker_, "changed",
524                                      DatePickerItemChangedCallback);
525     }
526     if (time_picker_) {
527       evas_object_smart_callback_del(time_picker_, "changed",
528                                      DatePickerItemChangedCallback);
529     }
530   }
531
532 #if BUILDFLAG(IS_TIZEN)
533   if (popup_) {
534     eext_object_event_callback_del(layout_, EEXT_CALLBACK_BACK,
535                                    DatePickerBackKeyCallback);
536   }
537 #endif
538 }
539
540 // static
541 void InputPicker::Layout::ColorPickerItemSelectedCallback(void* data,
542                                                           Evas_Object* obj,
543                                                           void* event_info) {
544   int r(0), g(0), b(0), a(0);
545   Elm_Object_Item* color_it = static_cast<Elm_Object_Item*>(event_info);
546   elm_colorselector_palette_item_color_get(color_it, &r, &g, &b, &a);
547   evas_object_color_set(static_cast<Evas_Object*>(data), r, g, b, a);
548 }
549
550 // static
551 void InputPicker::Layout::ColorPickerSelectFinishedCallback(void* data,
552                                                             Evas_Object* obj,
553                                                             void* event_info) {
554   Layout* picker_layout = static_cast<Layout*>(data);
555
556   int r(0), g(0), b(0), a(0);
557   evas_object_color_get(picker_layout->color_rect_, &r, &g, &b, &a);
558
559   picker_layout->parent_->web_view_->web_contents()
560       .DidChooseColorInColorChooser(SkColorSetARGB(a, r, g, b));
561   picker_layout->parent_->RemoveColorPicker();
562 }
563
564 // static
565 void InputPicker::Layout::DatePickerSelectFinishedCallback(void* data,
566                                                            Evas_Object* obj,
567                                                            void* event_info) {
568   struct tm current_time;
569   memset(&current_time, 0, sizeof(struct tm));
570
571   Layout* picker_layout = static_cast<Layout*>(data);
572
573   if (picker_layout->input_type_ == ui::TEXT_INPUT_TYPE_TIME)
574     elm_datetime_value_get(picker_layout->time_picker_, &current_time);
575   else
576     elm_datetime_value_get(picker_layout->date_picker_, &current_time);
577
578   char dateStr[20] = {
579       0,
580   };
581
582   switch (picker_layout->input_type_) {
583     case ui::TEXT_INPUT_TYPE_DATE: {
584       strftime(dateStr, 20, "%F", &current_time);
585       break;
586     }
587     case ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD:
588     case ui::TEXT_INPUT_TYPE_DATE_TIME: {
589       strftime(dateStr, 20, "%FT%RZ", &current_time);
590       break;
591     }
592     case ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL: {
593       strftime(dateStr, 20, "%FT%R", &current_time);
594       break;
595     }
596     case ui::TEXT_INPUT_TYPE_TIME: {
597       strftime(dateStr, 20, "%R", &current_time);
598       break;
599     }
600     case ui::TEXT_INPUT_TYPE_WEEK: {
601       // Call mktime: current_time.tm_wday will be set
602       mktime(&current_time);
603       strftime(dateStr, 20, "%G-W%V", &current_time);
604       break;
605     }
606     case ui::TEXT_INPUT_TYPE_MONTH: {
607       strftime(dateStr, 20, "%Y-%m", &current_time);
608       break;
609     }
610     default:
611       NOTREACHED();
612       break;
613   }
614
615   // call the callback
616   picker_layout->parent_->web_view_->GetDateTimeChooser()->ReplaceDateTime(
617       std::string(dateStr));
618   picker_layout->parent_->RemoveDatePicker(false);
619 }
620
621 // static
622 void InputPicker::Layout::DatePickerItemChangedCallback(void* data,
623                                                         Evas_Object* obj,
624                                                         void* event_info) {
625   struct tm current_time;
626   memset(&current_time, 0, sizeof(struct tm));
627
628   Layout* picker_layout = static_cast<Layout*>(data);
629   if (obj == picker_layout->date_picker_) {
630     elm_datetime_value_get(picker_layout->date_picker_, &current_time);
631     elm_datetime_value_set(picker_layout->time_picker_, &current_time);
632   } else if (obj == picker_layout->time_picker_) {
633     elm_datetime_value_get(picker_layout->time_picker_, &current_time);
634     elm_datetime_value_set(picker_layout->date_picker_, &current_time);
635   }
636 }
637
638 // static
639 void InputPicker::Layout::ColorPickerBackKeyCallback(void* data,
640                                                      Evas_Object* obj,
641                                                      void* event_info) {
642   Layout* picker_layout = static_cast<Layout*>(data);
643
644   picker_layout->parent_->web_view_->web_contents()
645       .DidChooseColorInColorChooser(SkColorSetARGB(255, picker_layout->red_,
646                                                    picker_layout->green_,
647                                                    picker_layout->blue_));
648   picker_layout->parent_->RemoveColorPicker();
649 }
650
651 // static
652 void InputPicker::Layout::DatePickerBackKeyCallback(void* data,
653                                                     Evas_Object* obj,
654                                                     void* event_info) {
655   Layout* picker_layout = static_cast<Layout*>(data);
656   if (picker_layout) {
657     picker_layout->parent_->web_view_->GetDateTimeChooser()->CancelDialog();
658     // pass true to RemoveDatePicker to cancelDateTimeDialog
659     picker_layout->parent_->RemoveDatePicker(true);
660   }
661 }
662
663 InputPicker::InputPicker(EWebView* view)
664     : web_view_(view), picker_layout_(nullptr) {}
665
666 InputPicker::~InputPicker() {}
667
668 void InputPicker::ShowColorPicker(int r, int g, int b, int a) {
669   picker_layout_.reset(Layout::CreateAndShowColorPickerLayout(this, r, g, b));
670   if (!picker_layout_) {
671     LOG(ERROR) << "Failed to create color picker.";
672     // We need to notify engine that default color is chosen
673     // otherwise selecting will never be finished.
674     web_view_->web_contents().DidChooseColorInColorChooser(
675         SkColorSetARGB(a, r, g, b));
676   }
677 }
678
679 void InputPicker::ShowDatePicker(ui::TextInputType input_type,
680                                  double input_date) {
681   web_view_->ExecuteEditCommand("Unselect", 0);
682
683   time_t timep;
684   struct tm tm;
685   if (!std::isfinite(input_date)) {
686     time(&timep);
687     localtime_r(&timep, &tm);
688   } else if (input_type == ui::TEXT_INPUT_TYPE_MONTH) {
689     // When type is month, input_date is number of month since epoch.
690     unsigned int year = floor(input_date / 12.0) + 1970.0;
691     unsigned int month = input_date - (year - 1970) * 12 + 1;
692     CHECK_LE(month, 12u);
693
694     char date[12];
695     snprintf(date, sizeof(date), "%d-%d", year, month);
696     char* last_char = strptime(date, "%Y-%m", &tm);
697     DCHECK(last_char);
698   } else {
699     // In all other cases, input_date is number of milliseconds since epoch.
700     timep = base::Time::FromDoubleT(input_date / 1000).ToTimeT();
701     gmtime_r(&timep, &tm);
702   }
703   struct tm* current_time = &tm;
704   switch (input_type) {
705     case ui::TEXT_INPUT_TYPE_DATE:
706     case ui::TEXT_INPUT_TYPE_WEEK:
707     case ui::TEXT_INPUT_TYPE_MONTH: {
708       picker_layout_.reset(
709           Layout::CreateAndShowDateLayout(this, current_time, input_type));
710       break;
711     }
712     case ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD:
713     case ui::TEXT_INPUT_TYPE_DATE_TIME:
714     case ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL: {
715       picker_layout_.reset(
716           Layout::CreateAndShowDateTimeLayout(this, current_time, input_type));
717       break;
718     }
719     case ui::TEXT_INPUT_TYPE_TIME: {
720       picker_layout_.reset(Layout::CreateAndShowTimeLayout(this, current_time));
721       break;
722     }
723     default:
724       LOG(ERROR) << "Invalid date picker type.";
725       break;
726   }
727
728   if (!picker_layout_) {
729     LOG(ERROR) << "Failed to create date picker.";
730     // We need to notify engine that empty string is chosen
731     // otherwise selecting will never be finished.
732
733     // Call the callback
734     web_view_->GetDateTimeChooser()->ReplaceDateTime(std::string());
735   }
736 }
737
738 void InputPicker::RemoveColorPicker() {
739   if (!picker_layout_)
740     return;
741
742   picker_layout_.reset();
743   web_view_->web_contents().DidEndColorChooser();
744 }
745
746 void InputPicker::RemoveDatePicker(bool cancel) {
747   if (!picker_layout_)
748     return;
749
750   if (cancel)
751     web_view_->GetDateTimeChooser()->CancelDialog();
752   picker_layout_.reset();
753 }
754
755 }  // namespace content