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