1 // Copyright 2013 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.
5 #include <Elementary.h>
9 #include "base/files/file_path.h"
10 #include "base/path_service.h"
11 #include "ui/base/clipboard/clipboard_helper_efl.h"
12 #include "common/web_contents_utils.h"
13 #include "context_menu_controller_efl.h"
14 #include "content/browser/renderer_host/render_widget_host_view_efl.h"
15 #include "content/browser/selection/selection_controller_efl.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/download_manager.h"
18 #include "content/public/browser/navigation_entry.h"
19 #include "eweb_view.h"
20 #include "net/base/net_util.h"
21 #include "net/base/filename_util.h"
22 #include "content/common/paths_efl.h"
23 #include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
24 #include "ui/base/clipboard/clipboard.h"
25 #include "private/ewk_context_menu_private.h"
27 #if defined(OS_TIZEN_MOBILE)
28 #include <efl_extension.h>
31 using web_contents_utils::WebViewFromWebContents;
34 static const int kMaxHeightVertical = 680;
35 static const int kMaxHeightHorizontal = 360;
40 unsigned int ContextMenuControllerEfl::_appended_item_size = 0;
41 int ContextMenuControllerEfl::_popup_item_height = 96;
42 bool ContextMenuControllerEfl::_context_menu_resized = false;
43 std::vector<ContextMenuItemEfl> ContextMenuControllerEfl::_context_menu_listdata;
45 ContextMenuControllerEfl::~ContextMenuControllerEfl() {
46 for (std::set<DownloadItem*>::iterator it = clipboard_download_items_.begin();
47 it != clipboard_download_items_.end(); ++it) {
48 (*it)->RemoveObserver(this);
50 for (std::set<DownloadItem*>::iterator it = disk_download_items_.begin();
51 it != disk_download_items_.end(); ++it) {
52 (*it)->RemoveObserver(this);
54 _context_menu_listdata.clear();
58 bool ContextMenuControllerEfl::PopulateAndShowContextMenu(const ContextMenuParams ¶ms) {
62 DCHECK(menu_items_ == NULL);
67 GetProposedContextMenu();
68 _Ewk_Context_Menu new_menu(menu_items_);
69 webview_->SmartCallback<EWebViewCallbacks::ContextMenuCustomize>().call(&new_menu);
70 menu_items_ = new_menu.TakeMenuList();
72 if (!CreateContextMenu())
75 return ShowContextMenu();
78 void ContextMenuControllerEfl::AddItemToProposedList(ContextMenuOptionType item,
79 ContextMenuOption option,
80 const std::string& title,
81 const std::string& image_url,
82 const std::string& link_url,
83 const std::string& icon_path) {
84 ContextMenuItemEfl* new_menu_item = new ContextMenuItemEfl(
85 item, option, title, image_url, link_url, icon_path);
86 _Ewk_Context_Menu_Item* new_item = new _Ewk_Context_Menu_Item(new_menu_item);
87 menu_items_ = eina_list_append(menu_items_, new_item);
90 void ContextMenuControllerEfl::GetProposedContextMenu() {
91 if (!params_.link_url.is_empty()) {
92 AddItemToProposedList(MENU_ITEM_TYPE_ACTION,
93 MENU_ITEM_OPEN_LINK_IN_NEW_WINDOW,
94 std::string(dgettext("WebKit",
95 "IDS_WEBVIEW_OPT_OPEN_LINK_IN_NEW_TAB_ABB")),
96 params_.link_url.spec(),
97 params_.link_url.spec());
98 AddItemToProposedList(MENU_ITEM_TYPE_ACTION,
99 MENU_ITEM_COPY_LINK_TO_CLIPBOARD,
100 std::string(dgettext("WebKit", "IDS_WEBVIEW_OPT_COPY_LINK_URL_ABB")),
102 params_.link_url.spec());
103 AddItemToProposedList(MENU_ITEM_TYPE_ACTION,
104 MENU_ITEM_DOWNLOAD_LINK_TO_DISK,
105 std::string(dgettext("WebKit", "IDS_BR_BODY_SAVE_LINK")),
107 params_.link_url.spec());
109 #if !defined(WAYLAND_BRINGUP)
110 if (params_.is_editable && ClipboardHelperEfl::NumberOfItems() > 0) {
111 AddItemToProposedList(MENU_ITEM_TYPE_ACTION, MENU_ITEM_PASTE,
112 std::string(dgettext("WebKit", "IDS_WEBVIEW_OPT_PASTE")));
117 if (!params_.selection_text.empty() && params_.is_editable) {
118 AddItemToProposedList(MENU_ITEM_TYPE_ACTION, MENU_ITEM_CUT,
119 std::string(dgettext("WebKit", "IDS_WEBVIEW_OPT_CUT_ABB")));
121 if (!params_.selection_text.empty()) {
122 AddItemToProposedList(MENU_ITEM_TYPE_ACTION, MENU_ITEM_COPY,
123 std::string(dgettext("WebKit", "IDS_WEBVIEW_OPT_COPY")));
124 if (!params_.is_editable) {
125 AddItemToProposedList(MENU_ITEM_TYPE_ACTION, MENU_ITEM_SEARCH_WEB,
126 std::string(dgettext("WebKit", "IDS_WEBVIEW_OPT_WEB_SEARCH")));
127 #if !defined(OS_TIZEN_MOBILE)
128 AddItemToProposedList(MENU_ITEM_TYPE_ACTION, MENU_ITEM_SEARCH_IN_SPOTLIGHT,
134 if (params_.has_image_contents && !params_.src_url.is_empty()) {
135 AddItemToProposedList(MENU_ITEM_TYPE_ACTION,
136 MENU_ITEM_OPEN_IMAGE_IN_NEW_WINDOW,
137 std::string(dgettext("WebKit",
138 "IDS_WEBVIEW_OPT_OPEN_IMAGE_IN_NEW_TAB_ABB")),
139 params_.src_url.spec(),
140 params_.src_url.spec());
141 AddItemToProposedList(MENU_ITEM_TYPE_ACTION,
142 MENU_ITEM_DOWNLOAD_IMAGE_TO_DISK,
143 std::string(dgettext("WebKit", "IDS_WEBVIEW_OPT_SAVE_IMAGE_ABB")),
144 params_.src_url.spec(),
145 params_.src_url.spec());
146 AddItemToProposedList(MENU_ITEM_TYPE_ACTION,
147 MENU_ITEM_COPY_IMAGE_TO_CLIPBOARD,
148 std::string(dgettext("WebKit", "IDS_WEBVIEW_OPT_COPY_IMAGE")),
149 params_.src_url.spec(),
150 params_.src_url.spec());
151 } else if (!params_.link_url.is_empty()) {
152 AddItemToProposedList(MENU_ITEM_TYPE_ACTION,
153 MENU_ITEM_TEXT_SELECTION_MODE,
154 std::string(dgettext("WebKit", "IDS_WEBVIEW_OPT_SELECTION_MODE_ABB")),
155 params_.link_url.spec(),
156 params_.link_url.spec());
159 RenderWidgetHostViewEfl* rwhv = static_cast<RenderWidgetHostViewEfl*>(web_contents_.GetRenderWidgetHostView());
160 if (!params_.selection_text.empty()
161 || (params_.is_editable && (rwhv && !rwhv->IsLastAvailableTextEmpty()))) {
162 AddItemToProposedList(MENU_ITEM_TYPE_ACTION, MENU_ITEM_SELECT_WORD,
163 std::string(dgettext("WebKit", "IDS_WEBVIEW_OPT_SELECT_ABB")));
164 AddItemToProposedList(MENU_ITEM_TYPE_ACTION, MENU_ITEM_SELECT_ALL,
165 std::string(dgettext("WebKit", "IDS_WEBVIEW_OPT_SELECT_ALL_ABB")));
167 #if !defined(EWK_BRINGUP)
168 if (params_.is_draggable) {
169 AddItemToProposedList(MENU_ITEM_TYPE_ACTION, MENU_ITEM_DRAG,
170 std::string(dgettext("WebKit", "IDS_WEBVIEW_OPT_DRAG_AND_DROP")));
173 #if !defined(WAYLAND_BRINGUP)
174 if (params_.is_editable && ClipboardHelperEfl::NumberOfItems() > 0) {
175 AddItemToProposedList(MENU_ITEM_TYPE_ACTION, MENU_ITEM_CLIPBOARD,
176 std::string(dgettext("WebKit", "IDS_WEBVIEW_OPT_CLIPBOARD")));
183 bool ContextMenuControllerEfl::CreateContextMenu() {
184 is_text_selection_ = false;
187 EINA_LIST_FOREACH(menu_items_, ittr, data) {
188 _Ewk_Context_Menu_Item* item = static_cast<_Ewk_Context_Menu_Item*> (data);
189 ContextMenuItemEfl* context_item = item->GetMenuItem();
190 switch (context_item->GetContextMenuOption()) {
192 case MENU_ITEM_SELECT_ALL:
193 case MENU_ITEM_SELECT_WORD:
194 case MENU_ITEM_PASTE:
195 is_text_selection_ = true;
202 if (is_text_selection_) {
203 popup_ = elm_ctxpopup_add(native_view_);
204 elm_ctxpopup_horizontal_set(popup_, EINA_TRUE);
205 elm_object_tree_focus_allow_set(popup_, false);
207 evas_object_data_set(native_view_, "ContextMenuContollerEfl", this);
208 popup_ = elm_popup_add(native_view_);
214 evas_object_data_set(popup_, "ContextMenuContollerEfl", this);
216 _appended_item_size = 0;
217 if (is_text_selection_) {
218 EINA_LIST_FOREACH(menu_items_, ittr, data) {
219 _Ewk_Context_Menu_Item* item = static_cast<_Ewk_Context_Menu_Item*> (data);
220 ContextMenuItemEfl* context_item = item->GetMenuItem();
221 Elm_Object_Item* appended_item = 0;
223 if (!context_item->Title().empty()) {
224 appended_item = elm_ctxpopup_item_append(popup_,
225 context_item->Title().c_str(), 0, ContextMenuItemSelectedCallback,
228 appended_item = elm_ctxpopup_item_append(popup_, 0, 0,
229 ContextMenuItemSelectedCallback,
234 _appended_item_size++;
236 #if defined(OS_TIZEN)
238 // Need to set "copypaste" style, to let moving handles
239 // when ctxpopup is visible
240 // http://107.108.218.239/bugzilla/show_bug.cgi?id=11613
241 elm_object_style_set(popup_, "copypaste");
244 GURL url = web_contents_.GetVisibleURL();
245 std::string selected_link (url.host().c_str());
246 if (!selected_link.empty()) {
247 if (base::StartsWith(selected_link,
248 std::string("mailto:"),
249 base::CompareCase::INSENSITIVE_ASCII)
250 || base::StartsWith(selected_link,
252 base::CompareCase::INSENSITIVE_ASCII)) {
253 std::vector<std::string> link_split;
254 size_t current_pos = 0;
255 size_t next_delimiter = 0;
256 while ((next_delimiter = selected_link.find(":", current_pos))
257 != std::string::npos) {
258 std::string part = selected_link.substr(current_pos,
259 next_delimiter - current_pos);
260 link_split.push_back(part);
261 current_pos = next_delimiter + 1;
263 std::string last_part = selected_link.substr(current_pos);
264 if (!last_part.empty())
265 link_split.push_back(last_part);
267 if (!link_split[1].size()) {
268 std::vector<std::string> real_link_split;
269 size_t current_pos = 0;
270 size_t next_delimiter = 0;
271 while ((next_delimiter = link_split[1].find("?", current_pos)) != std::string::npos) {
272 std::string part = link_split[1].substr(current_pos, next_delimiter - current_pos);
273 real_link_split.push_back(part);
274 current_pos = next_delimiter + 1;
276 std::string last_part = link_split[1].substr(current_pos);
277 if (!last_part.empty())
278 real_link_split.push_back(last_part);
280 elm_object_part_text_set(popup_, "title,text", real_link_split[0].c_str());
283 elm_object_part_text_set(popup_, "title,text", selected_link.c_str());
286 std::string selected_image (url.host().c_str());
287 if (!selected_image.empty()) {
288 if (base::StartsWith(selected_image,
289 std::string("data:"),
290 base::CompareCase::INSENSITIVE_ASCII))
291 elm_object_part_text_set(popup_, "title,text", "data:");
293 elm_object_part_text_set(popup_, "title,text", selected_image.c_str());
297 evas_object_size_hint_weight_set(popup_, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
299 Evas_Object* list = elm_list_add(popup_);
300 elm_list_mode_set(list, ELM_LIST_EXPAND);
301 evas_object_data_set(list, "ContextMenuContollerEfl", this);
303 _context_menu_listdata.clear();
307 EINA_LIST_FOREACH(menu_items_, ittr, data) {
308 _Ewk_Context_Menu_Item* item = static_cast<_Ewk_Context_Menu_Item*> (data);
309 ContextMenuItemEfl* context_item = item->GetMenuItem();
310 if (!context_item->Title().empty()) {
311 Elm_Object_Item* appended_item = elm_list_item_append(list,
312 context_item->Title().c_str(),
315 ContextMenuItemSelectedCallback,
319 _context_menu_listdata.push_back(*context_item);
320 _appended_item_size++;
324 evas_object_show(list);
325 elm_object_content_set(popup_, list);
326 evas_object_event_callback_add(popup_, EVAS_CALLBACK_RESIZE,
327 ContextMenuPopupResize, list);
330 if (!_appended_item_size) {
337 void ContextMenuControllerEfl::ContextMenuHWBackKey(void* data, Evas_Object* obj,
339 ContextMenuControllerEfl* menu_controller = static_cast<ContextMenuControllerEfl*>(data);
340 if (menu_controller) {
341 menu_controller->HideContextMenu();
342 evas_object_data_del(obj, "ContextEfl");
346 void ContextMenuControllerEfl::ContextMenuCancelCallback(void* data, Evas_Object* obj,
348 ContextMenuControllerEfl* menu_controller = static_cast<ContextMenuControllerEfl*>(evas_object_data_get(obj, "ContextEfl"));
349 if (menu_controller) {
350 menu_controller->HideContextMenu();
351 menu_controller->HideSelectionHandle();
352 evas_object_data_del(obj, "ContextEfl");
356 void ContextMenuControllerEfl::ContextMenuItemSelectedCallback(void* data,
357 Evas_Object* obj, void* event_info) {
358 Evas_Object* pop_up = obj;
359 ContextMenuControllerEfl* menu_controller =
360 static_cast<ContextMenuControllerEfl*>
361 (evas_object_data_get(pop_up, "ContextMenuContollerEfl"));
363 if (menu_controller) {
364 ContextMenuItemEfl* selected_menu_item = static_cast<ContextMenuItemEfl*>(data);
365 if (selected_menu_item)
366 menu_controller->MenuItemSelected(selected_menu_item);
370 bool ContextMenuControllerEfl::ShowContextMenu() {
374 if (is_text_selection_) {
375 int webview_x, webview_y, webview_width, webview_height;
378 gfx::Point popup_position = gfx::Point(params_.x, params_.y);
383 Evas_Object* wv_evas_obj = WebViewFromWebContents(&web_contents_)->evas_object();
384 evas_object_geometry_get(wv_evas_obj, &webview_x, &webview_y, &webview_width, &webview_height);
385 popup_position.set_x(popup_position.x() + webview_x);
386 popup_position.set_y(popup_position.y() + webview_y);
388 point.x = popup_position.x();
389 point.y = popup_position.y();
391 evas_object_smart_callback_call(wv_evas_obj, "contextmenu,willshow", &point);
394 evas_object_smart_callback_call(wv_evas_obj, "contextmenu,allowed", &allowed);
400 SelectionControllerEfl* controller = webview_->GetSelectionController();
407 controller->ChangeContextMenuPosition(popup_position, draw_direction);
409 if ((popup_position.y() > webview_height) || (popup_position.x() > webview_width))
412 switch(draw_direction) {
414 elm_ctxpopup_direction_priority_set(popup_,
415 ELM_CTXPOPUP_DIRECTION_DOWN,
416 ELM_CTXPOPUP_DIRECTION_DOWN,
417 ELM_CTXPOPUP_DIRECTION_DOWN,
418 ELM_CTXPOPUP_DIRECTION_DOWN);
421 elm_ctxpopup_direction_priority_set(popup_,
422 ELM_CTXPOPUP_DIRECTION_UP,
423 ELM_CTXPOPUP_DIRECTION_UP,
424 ELM_CTXPOPUP_DIRECTION_UP,
425 ELM_CTXPOPUP_DIRECTION_UP);
428 elm_ctxpopup_direction_priority_set(popup_,
429 ELM_CTXPOPUP_DIRECTION_LEFT,
430 ELM_CTXPOPUP_DIRECTION_LEFT,
431 ELM_CTXPOPUP_DIRECTION_LEFT,
432 ELM_CTXPOPUP_DIRECTION_LEFT);
435 elm_ctxpopup_direction_priority_set(popup_,
436 ELM_CTXPOPUP_DIRECTION_RIGHT,
437 ELM_CTXPOPUP_DIRECTION_RIGHT,
438 ELM_CTXPOPUP_DIRECTION_RIGHT,
439 ELM_CTXPOPUP_DIRECTION_RIGHT);
442 elm_ctxpopup_direction_priority_set(popup_,
443 ELM_CTXPOPUP_DIRECTION_UP,
444 ELM_CTXPOPUP_DIRECTION_DOWN,
445 ELM_CTXPOPUP_DIRECTION_LEFT,
446 ELM_CTXPOPUP_DIRECTION_RIGHT);
448 evas_object_move(popup_, popup_position.x(), popup_position.y());
449 evas_object_smart_callback_add(popup_, "dismissed", ContextMenuCancelCallback, this);
450 #if defined(OS_TIZEN_MOBILE)
451 elm_ctxpopup_auto_hide_disabled_set(popup_, EINA_TRUE);
453 web_contents_.Focus();
455 #if defined(OS_TIZEN_MOBILE)
456 eext_object_event_callback_add(popup_, EEXT_CALLBACK_BACK, ContextMenuHWBackKey, this);
457 // Workaround. After context menu shows up, there is "unfocused" event fired.
458 // evas_object_smart_callback_add(popup_, "unfocused", ContextMenuHWBackKey, this);
459 evas_object_focus_set(popup_, EINA_TRUE);
461 evas_object_smart_callback_add(popup_, "block,clicked", BlockClickedCallback, this);
463 evas_object_show(popup_);
467 void ContextMenuControllerEfl::HideSelectionHandle() {
468 SelectionControllerEfl* controller = webview_->GetSelectionController();
470 controller->HideHandles();
473 void ContextMenuControllerEfl::RequestShowSelectionHandleAndContextMenu() {
474 SelectionControllerEfl* controller = webview_->GetSelectionController();
476 controller->SetSelectionStatus(true);
477 controller->SetWaitsForRendererSelectionChanges(true);
481 void ContextMenuControllerEfl::OnClipboardDownload(
482 content::DownloadItem* item,
483 content::DownloadInterruptReason interrupt_reason) {
484 item->AddObserver(this);
485 clipboard_download_items_.insert(item);
488 void EmptyDialogClosedCallback(
490 const base::string16& /* user_input */) {
493 void ContextMenuControllerEfl::OnDiskDownload(
494 content::DownloadItem* item,
495 content::DownloadInterruptReason interrupt_reason) {
497 save_fail_dialog_.reset(JavaScriptModalDialogEfl::CreateDialog(
501 JavaScriptModalDialogEfl::ALERT,
502 base::UTF8ToUTF16(std::string(dgettext("WebKit", "IDS_WEBVIEW_POP_FAIL"))),
504 base::Bind(&EmptyDialogClosedCallback)));
507 item->AddObserver(this);
508 disk_download_items_.insert(item);
511 void ContextMenuControllerEfl::OnDownloadUpdated(content::DownloadItem* download) {
512 if(download && download->AllDataSaved()) {
513 if (clipboard_download_items_.find(download) != clipboard_download_items_.end()) {
514 const std::string& DownloadPath = download->GetForcedFilePath().value();
515 #if !defined(WAYLAND_BRINGUP)
516 ClipboardHelperEfl::GetInstance()->SetData(DownloadPath,
517 ClipboardHelperEfl::CLIPBOARD_DATA_TYPE_IMAGE);
521 download->RemoveObserver(this);
522 clipboard_download_items_.erase(download);
524 if (disk_download_items_.find(download) != disk_download_items_.end()) {
525 file_saved_dialog_.reset(JavaScriptModalDialogEfl::CreateDialog(
529 JavaScriptModalDialogEfl::ALERT,
530 base::UTF8ToUTF16(std::string(dgettext("WebKit", "IDS_WEBVIEW_POP_SAVED"))),
532 base::Bind(&EmptyDialogClosedCallback)));
533 download->RemoveObserver(this);
534 disk_download_items_.erase(download);
539 base::FilePath ContextMenuControllerEfl::DownloadFile(const GURL url,
540 const base::FilePath outputDir,
541 const DownloadUrlParameters::OnStartedCallback &callback =
542 DownloadUrlParameters::OnStartedCallback()) {
543 LOG(INFO) << "Downloading file: " << url << "to: "<< outputDir.value();
544 const GURL referrer = web_contents_.GetVisibleURL();
545 DownloadManager* dlm = BrowserContext::GetDownloadManager(
546 web_contents_.GetBrowserContext());
548 scoped_ptr<DownloadUrlParameters> dl_params(
549 DownloadUrlParameters::FromWebContents(&web_contents_, url));
550 dl_params->set_post_id(-1);
551 dl_params->set_referrer(
552 content::Referrer(referrer, blink::WebReferrerPolicyAlways));
553 dl_params->set_referrer_encoding("utf8");
554 base::FilePath fileName = net::GenerateFileName(url,"","","","","");
555 base::FilePath fullPath = outputDir.Append(fileName);
557 while (PathExists(fullPath)) {
559 base::FilePath fileNameTmp;
560 for (i = 0; PathExists(fullPath) && i <= 999; i++) {
562 snprintf(buffer, sizeof(buffer), "(%d)", i);
563 fileNameTmp = fileName.InsertBeforeExtension(std::string(buffer));
564 fullPath = outputDir.Append(fileNameTmp);
568 dl_params->set_file_path(fullPath);
569 dl_params->set_prompt(true);
570 dl_params->set_callback(callback);
571 dlm->DownloadUrl(dl_params.Pass());
575 bool ContextMenuControllerEfl::TriggerDownloadCb(const GURL url) {
576 BrowserContextEfl* browser_context =
577 static_cast<BrowserContextEfl*>(web_contents_.GetBrowserContext());
578 if (browser_context) {
579 EwkDidStartDownloadCallback* start_download_callback =
580 browser_context->WebContext()->DidStartDownloadCallback();
581 if (start_download_callback) {
582 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
583 start_download_callback->TriggerCallback(url.spec());
590 void ContextMenuControllerEfl::OpenInNewTab(const GURL url) {
593 const GURL referrer = web_contents_.GetVisibleURL();
594 content::OpenURLParams params(url,
595 content::Referrer(referrer,
596 blink::WebReferrerPolicyAlways),
599 ui::PAGE_TRANSITION_LINK,
601 web_contents_.GetDelegate()->OpenURLFromTab(&web_contents_, params);
604 void ContextMenuControllerEfl::ContextMenuListTrackResize(void* data, Evas* e,
605 Evas_Object* obj, void* event_info)
608 evas_object_geometry_get(obj, 0, 0, 0, &height);
610 if (_popup_item_height == height)
613 _popup_item_height = height;
614 ContextMenuPopupBoxResize(elm_object_top_widget_get(static_cast<Evas_Object*>(data)), data);
617 void ContextMenuControllerEfl::ContextMenuListRealized(void* data,
618 Evas_Object* obj, void* event_info)
623 Elm_Object_Item* item = static_cast<Elm_Object_Item*>(event_info);
624 size_t index = reinterpret_cast<size_t>(elm_object_item_data_get(item));
626 #if defined(OS_TIZEN)
627 Evas_Object* track = elm_object_item_track(item);
628 evas_object_event_callback_add(track, EVAS_CALLBACK_RESIZE, ContextMenuListTrackResize, obj);
631 if (index == _appended_item_size - 1)
632 elm_object_item_signal_emit(item, "elm,state,bottomline,hide", "");
635 char* ContextMenuControllerEfl::ContextMenuGenlistTextSet(void* data,
636 Evas_Object* obj, const char* part)
638 size_t index = reinterpret_cast<size_t>(data);
639 if (index >= _appended_item_size)
642 if (_context_menu_listdata.at(index).Title().empty())
645 return strdup(_context_menu_listdata.at(index).Title().c_str());
648 void ContextMenuControllerEfl::ContextMenuPopupBoxResize(Evas_Object* top_widget, void* data)
650 _context_menu_resized = true;
652 Evas_Object* box = elm_object_parent_widget_get(static_cast<Evas_Object*>(data));
654 int rotation = elm_win_rotation_get(top_widget);
655 if ((rotation == 90 || rotation == 270) && _appended_item_size > 3)
656 evas_object_size_hint_min_set(box, 0, kMaxHeightHorizontal);
657 else if ((rotation == 0 || rotation == 180) && _appended_item_size > 7)
658 evas_object_size_hint_min_set(box, 0, kMaxHeightVertical);
660 evas_object_size_hint_min_set(box, 0, _appended_item_size * _popup_item_height);
662 evas_object_show(box);
665 void ContextMenuControllerEfl::ContextMenuPopupResize(void* data,
670 if (!_context_menu_resized)
671 ContextMenuPopupBoxResize(elm_object_top_widget_get(obj), data);
674 void ContextMenuControllerEfl::ContextMenuPopupRotationCallback(void* data,
678 ContextMenuPopupBoxResize(obj, data);
681 void ContextMenuControllerEfl::BlockClickedCallback(void* data, Evas_Object*, void*)
683 ContextMenuControllerEfl* menu_controller = static_cast<ContextMenuControllerEfl*>(data);
685 if (!menu_controller)
688 menu_controller->HideContextMenu();
691 void ContextMenuControllerEfl::CustomMenuItemSelected(ContextMenuItemEfl* menu_item) {
692 _Ewk_Context_Menu_Item item(new ContextMenuItemEfl(menu_item->GetContextMenuOptionType(),
693 menu_item->GetContextMenuOption(),
695 params_.src_url.spec(),
696 params_.link_url.spec(),
698 webview_->SmartCallback<EWebViewCallbacks::ContextMenuItemSelected>().call(&item);
701 void ContextMenuControllerEfl::MenuItemSelected(ContextMenuItemEfl* menu_item)
710 evas_object_hide(popup_);
711 // FIXME: Add cases as and when required
712 switch(menu_item->GetContextMenuOption())
714 case MENU_ITEM_OPEN_LINK_IN_NEW_WINDOW: {
715 OpenInNewTab(GURL(params_.link_url.spec()));
718 case MENU_ITEM_GO_BACK: {
722 case MENU_ITEM_GO_FORWARD: {
723 webview_->GoForward();
726 case MENU_ITEM_RELOAD: {
727 webview_->ReloadIgnoringCache();
730 case MENU_ITEM_COPY: {
731 webview_->ExecuteEditCommand("copy", NULL);
732 if (params_.is_editable) {
733 HideSelectionHandle();
734 Eina_Rectangle left_rect, right_rect;
735 webview_->GetSelectionRange(&left_rect, &right_rect);
736 webview_->MoveCaret(gfx::Point(right_rect.x, right_rect.y));
738 webview_->ExecuteEditCommand("Unselect", NULL);
742 case MENU_ITEM_TEXT_SELECTION_MODE: {
744 evas_object_geometry_get(webview_->evas_object(), &x, &y, 0, 0);
745 webview_->SelectLinkText(gfx::Point(params_.x - x, params_.y - y));
746 RequestShowSelectionHandleAndContextMenu();
749 case MENU_ITEM_COPY_IMAGE_TO_CLIPBOARD: {
750 DownloadFile(GURL(params_.src_url.spec()),
751 base::FilePath("/tmp/"),
752 base::Bind(&ContextMenuControllerEfl::OnClipboardDownload,
753 weak_ptr_factory_.GetWeakPtr()));
756 case MENU_ITEM_COPY_LINK_TO_CLIPBOARD: {
757 #if !defined(WAYLAND_BRINGUP)
758 ClipboardHelperEfl::GetInstance()->SetData(params_.link_url.spec(),
759 ClipboardHelperEfl::CLIPBOARD_DATA_TYPE_URL);
765 case MENU_ITEM_DOWNLOAD_LINK_TO_DISK: {
766 if (!TriggerDownloadCb(GURL(params_.link_url.spec()))) {
768 if (!PathService::Get(PathsEfl::DIR_DOWNLOADS, &path)) {
769 LOG(ERROR) << "Could not get downloads directory.";
772 DownloadFile(GURL(params_.link_url.spec()),
774 base::Bind(&ContextMenuControllerEfl::OnDiskDownload,
775 weak_ptr_factory_.GetWeakPtr()));
779 case MENU_ITEM_DOWNLOAD_IMAGE_TO_DISK: {
780 if (!TriggerDownloadCb(GURL(params_.src_url.spec()))) {
782 if (!PathService::Get(PathsEfl::DIR_DOWNLOAD_IMAGE, &path)) {
783 LOG(ERROR) << "Could not get image downloads directory.";
786 DownloadFile(GURL(params_.src_url.spec()),
788 base::Bind(&ContextMenuControllerEfl::OnDiskDownload,
789 weak_ptr_factory_.GetWeakPtr()));
793 case MENU_ITEM_OPEN_IMAGE_IN_NEW_WINDOW: {
794 OpenInNewTab(GURL(params_.src_url.spec()));
797 case MENU_ITEM_SELECT_WORD: {
798 webview_->ExecuteEditCommand("SelectWord", NULL);
799 RequestShowSelectionHandleAndContextMenu();
802 case MENU_ITEM_SELECT_ALL: {
803 webview_->ExecuteEditCommand("SelectAll", NULL);
804 RequestShowSelectionHandleAndContextMenu();
807 case MENU_ITEM_PASTE: {
808 webview_->ExecuteEditCommand("paste", NULL);
809 HideSelectionHandle();
812 case MENU_ITEM_CUT: {
813 webview_->ExecuteEditCommand("cut", NULL);
814 HideSelectionHandle();
817 case MENU_ITEM_CLIPBOARD: {
818 // TODO: set true for richly editable.
819 // Paste operations are blocked by Editor if content is not richly editible.
820 // Need to find if webview_ has rich editor.
821 #if !defined(WAYLAND_BRINGUP)
822 ClipboardHelperEfl::GetInstance()->OpenClipboardWindow(webview_, true);
828 case MENU_ITEM_DRAG: {
829 #if !defined(EWK_BRINGUP)
830 RenderViewHost* rvh = web_contents_.GetRenderViewHost();
831 rvh->StartDragging();
832 context_menu_show_pos_.SetPoint(params_.x, params_.y);
839 CustomMenuItemSelected(menu_item);
843 void ContextMenuControllerEfl::HideContextMenu() {
845 evas_object_del(popup_);
849 _context_menu_resized = false;
853 EINA_LIST_FREE(menu_items_, data) {
854 _Ewk_Context_Menu_Item *item = static_cast<_Ewk_Context_Menu_Item*> (data);
862 void ContextMenuControllerEfl::SetPopupSize(int width, int height) {
863 if (save_fail_dialog_)
864 save_fail_dialog_->SetPopupSize(width, height);
865 if (file_saved_dialog_)
866 file_saved_dialog_->SetPopupSize(width, height);
871 evas_object_resize(popup_, width, height);
872 evas_object_move(popup_, 0, 0);
875 void ContextMenuControllerEfl::DeletePopup() {
877 evas_object_data_set(native_view_, "ContextMenuContollerEfl", 0);
880 evas_object_data_set(popup_, "ContextMenuContollerEfl", 0);
881 evas_object_del(popup_);
887 EINA_LIST_FREE(menu_items_, data) {
888 _Ewk_Context_Menu_Item *item = static_cast<_Ewk_Context_Menu_Item*> (data);