From 9236adfbf57946e554c09f90760bb666dbf6e1e1 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 2 Nov 2015 23:28:45 +0800 Subject: [PATCH] Translate menu template directly in C++ --- atom/browser/api/atom_api_web_contents.cc | 21 +--- atom/browser/api/atom_api_web_contents.h | 6 - atom/browser/api/lib/web-contents.coffee | 43 +------ .../content_converter.cc | 112 ++++++++++++------ .../content_converter.h | 16 ++- 5 files changed, 100 insertions(+), 98 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 5ffa37e95d44..c329b257a290 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -47,6 +47,7 @@ #include "content/public/browser/storage_partition.h" #include "content/public/browser/site_instance.h" #include "content/public/browser/web_contents.h" +#include "content/public/common/context_menu_params.h" #include "native_mate/dictionary.h" #include "native_mate/object_template_builder.h" #include "net/http/http_response_headers.h" @@ -407,8 +408,11 @@ void WebContents::RendererResponsive(content::WebContents* source) { } bool WebContents::HandleContextMenu(const content::ContextMenuParams& params) { - context_menu_context_ = params.custom_context; - Emit("-context-menu", params); + if (!params.custom_context.is_pepper_menu) + return false; + + Emit("pepper-context-menu", std::make_pair(params, web_contents())); + web_contents()->NotifyContextMenuClosed(params.custom_context); return true; } @@ -848,15 +852,6 @@ void WebContents::RemoveWorkSpace(mate::Arguments* args, DevToolsRemoveFileSystem(path); } -void WebContents::ExecuteContextMenuCommand(int action) { - web_contents()->ExecuteCustomContextMenuCommand(action, - context_menu_context_); -} - -void WebContents::NotifyContextMenuClosed() { - web_contents()->NotifyContextMenuClosed(context_menu_context_); -} - void WebContents::Undo() { web_contents()->Undo(); } @@ -1068,10 +1063,6 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( .SetMethod("_printToPDF", &WebContents::PrintToPDF) .SetMethod("addWorkSpace", &WebContents::AddWorkSpace) .SetMethod("removeWorkSpace", &WebContents::RemoveWorkSpace) - .SetMethod("_executeContextMenuCommand", - &WebContents::ExecuteContextMenuCommand) - .SetMethod("_notifyContextMenuClosed", - &WebContents::NotifyContextMenuClosed) .SetProperty("session", &WebContents::Session, true) .SetProperty("devToolsWebContents", &WebContents::DevToolsWebContents, true) diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 5a55ad2abd7a..ae231cd3c61d 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -13,7 +13,6 @@ #include "atom/browser/api/trackable_object.h" #include "atom/browser/common_web_contents_delegate.h" #include "content/public/browser/web_contents_observer.h" -#include "content/public/common/context_menu_params.h" #include "content/public/common/favicon_url.h" #include "native_mate/handle.h" #include "ui/gfx/image/image.h" @@ -93,8 +92,6 @@ class WebContents : public mate::TrackableObject, void SetAudioMuted(bool muted); bool IsAudioMuted(); void Print(mate::Arguments* args); - void ExecuteContextMenuCommand(int action); - void NotifyContextMenuClosed(); // Print current page as PDF. void PrintToPDF(const base::DictionaryValue& setting, @@ -259,9 +256,6 @@ class WebContents : public mate::TrackableObject, // embedders' zoom level change. void OnZoomLevelChanged(double level); - // Recent unhandled context menu context. - content::CustomContextMenuContext context_menu_context_; - v8::Global session_; v8::Global devtools_web_contents_; diff --git a/atom/browser/api/lib/web-contents.coffee b/atom/browser/api/lib/web-contents.coffee index afe70323f0a5..eab9f1967158 100644 --- a/atom/browser/api/lib/web-contents.coffee +++ b/atom/browser/api/lib/web-contents.coffee @@ -35,36 +35,6 @@ PDFPageSize = width_microns: 279400 custom_display_name: "Tabloid" -clickHandler = (action) -> - @_executeContextMenuCommand action - -convertToMenuTemplate = (items, handler) -> - template = [] - for item in items - do (item) -> - transformed = - if item.type is 'submenu' - type: 'submenu' - label: item.label - enabled: item.enabled - submenu: convertToMenuTemplate item.subItems, handler - else if item.type is 'separator' - type: 'separator' - else if item.type is 'checkbox' - type: 'checkbox' - label: item.label - enabled: item.enabled - checked: item.checked - else - type: 'normal' - label: item.label - enabled: item.enabled - if item.id? - transformed.click = -> - handler item.id - template.push transformed - template - wrapWebContents = (webContents) -> # webContents is an EventEmitter. webContents.__proto__ = EventEmitter.prototype @@ -96,15 +66,10 @@ wrapWebContents = (webContents) -> Object.defineProperty event, 'returnValue', set: (value) -> event.sendReply JSON.stringify(value) ipc.emit channel, event, args... - # Handle context menu action request from renderer widget. - webContents.on '-context-menu', (event, params) -> - if params.isPepperMenu - template = convertToMenuTemplate(params.menuItems, clickHandler.bind(webContents)) - menu = Menu.buildFromTemplate template - # The menu is expected to show asynchronously. - setImmediate -> - menu.popup params.x, params.y - webContents._notifyContextMenuClosed() + # Handle context menu action request from pepper plugin. + webContents.on 'pepper-context-menu', (event, params) -> + menu = Menu.buildFromTemplate params.menu + menu.popup params.x, params.y webContents.printToPDF = (options, callback) -> printingSetting = diff --git a/atom/common/native_mate_converters/content_converter.cc b/atom/common/native_mate_converters/content_converter.cc index 2318e7d8e837..15a57dea5fb8 100644 --- a/atom/common/native_mate_converters/content_converter.cc +++ b/atom/common/native_mate_converters/content_converter.cc @@ -4,50 +4,96 @@ #include "atom/common/native_mate_converters/content_converter.h" +#include + +#include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/string16_converter.h" +#include "content/public/browser/web_contents.h" #include "content/public/common/context_menu_params.h" -#include "content/public/common/menu_item.h" #include "native_mate/dictionary.h" +namespace { + +void ExecuteCommand(content::WebContents* web_contents, + int action, + const content::CustomContextMenuContext& context) { + web_contents->ExecuteCustomContextMenuCommand(action, context); +} + +// Forward declaration for nested recursive call. +v8::Local MenuToV8(v8::Isolate* isolate, + content::WebContents* web_contents, + const content::CustomContextMenuContext& context, + const std::vector& menu); + +v8::Local MenuItemToV8( + v8::Isolate* isolate, + content::WebContents* web_contents, + const content::CustomContextMenuContext& context, + const content::MenuItem& item) { + mate::Dictionary v8_item = mate::Dictionary::CreateEmpty(isolate); + switch (item.type) { + case content::MenuItem::CHECKABLE_OPTION: + case content::MenuItem::GROUP: + v8_item.Set("checked", item.checked); + case content::MenuItem::OPTION: + case content::MenuItem::SUBMENU: + v8_item.Set("label", item.label); + v8_item.Set("enabled", item.enabled); + default: + v8_item.Set("type", item.type); + } + if (item.type == content::MenuItem::SUBMENU) + v8_item.Set("submenu", + MenuToV8(isolate, web_contents, context, item.submenu)); + else if (item.action > 0) + v8_item.Set("click", + base::Bind(ExecuteCommand, web_contents, item.action, context)); + return v8_item.GetHandle(); +} + +v8::Local MenuToV8(v8::Isolate* isolate, + content::WebContents* web_contents, + const content::CustomContextMenuContext& context, + const std::vector& menu) { + std::vector> v8_menu; + for (const auto& menu_item : menu) + v8_menu.push_back(MenuItemToV8(isolate, web_contents, context, menu_item)); + return mate::ConvertToV8(isolate, v8_menu); +} + +} // namespace + namespace mate { -template<> -struct Converter { - static v8::Local ToV8(v8::Isolate* isolate, - const content::MenuItem::Type& val) { - switch (val) { - case content::MenuItem::CHECKABLE_OPTION: - return StringToV8(isolate, "checkbox"); - case content::MenuItem::SEPARATOR: - return StringToV8(isolate, "separator"); - case content::MenuItem::SUBMENU: - return StringToV8(isolate, "submenu"); - default: - return StringToV8(isolate, "normal"); - } - } -}; - // static -v8::Local Converter::ToV8( - v8::Isolate* isolate, const content::MenuItem& val) { - mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate); - dict.Set("id", val.action); - dict.Set("type", val.type); - dict.Set("label", val.label); - dict.Set("enabled", val.enabled); - dict.Set("checked", val.checked); - return mate::ConvertToV8(isolate, dict); +v8::Local Converter::ToV8( + v8::Isolate* isolate, const content::MenuItem::Type& val) { + switch (val) { + case content::MenuItem::CHECKABLE_OPTION: + return StringToV8(isolate, "checkbox"); + case content::MenuItem::GROUP: + return StringToV8(isolate, "radio"); + case content::MenuItem::SEPARATOR: + return StringToV8(isolate, "separator"); + case content::MenuItem::SUBMENU: + return StringToV8(isolate, "submenu"); + case content::MenuItem::OPTION: + default: + return StringToV8(isolate, "normal"); + } } // static -v8::Local Converter::ToV8( - v8::Isolate* isolate, const content::ContextMenuParams& val) { +v8::Local Converter::ToV8( + v8::Isolate* isolate, const ContextMenuParamsWithWebContents& val) { + const auto& params = val.first; mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate); - dict.Set("x", val.x); - dict.Set("y", val.y); - dict.Set("isPepperMenu", val.custom_context.is_pepper_menu); - dict.Set("menuItems", val.custom_items); + dict.Set("x", params.x); + dict.Set("y", params.y); + if (params.custom_context.is_pepper_menu) + dict.Set("menu", MenuToV8(isolate, val.second, params.custom_context, + params.custom_items)); return mate::ConvertToV8(isolate, dict); } diff --git a/atom/common/native_mate_converters/content_converter.h b/atom/common/native_mate_converters/content_converter.h index 5cca2b38b251..7edee24fa142 100644 --- a/atom/common/native_mate_converters/content_converter.h +++ b/atom/common/native_mate_converters/content_converter.h @@ -5,25 +5,31 @@ #ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_CONTENT_CONVERTER_H_ #define ATOM_COMMON_NATIVE_MATE_CONVERTERS_CONTENT_CONVERTER_H_ +#include + +#include "content/public/common/menu_item.h" #include "native_mate/converter.h" namespace content { struct ContextMenuParams; -struct MenuItem; +class WebContents; } +using ContextMenuParamsWithWebContents = + std::pair; + namespace mate { template<> -struct Converter { +struct Converter { static v8::Local ToV8(v8::Isolate* isolate, - const content::MenuItem& val); + const content::MenuItem::Type& val); }; template<> -struct Converter { +struct Converter { static v8::Local ToV8(v8::Isolate* isolate, - const content::ContextMenuParams& val); + const ContextMenuParamsWithWebContents& val); }; } // namespace mate