content_converter.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. // Copyright (c) 2015 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "shell/common/gin_converters/content_converter.h"
  5. #include <string>
  6. #include <string_view>
  7. #include "base/containers/fixed_flat_map.h"
  8. #include "components/input/native_web_keyboard_event.h"
  9. #include "content/public/browser/context_menu_params.h"
  10. #include "content/public/browser/web_contents.h"
  11. #include "shell/browser/api/electron_api_web_contents.h"
  12. #include "shell/browser/web_contents_permission_helper.h"
  13. #include "shell/common/gin_converters/blink_converter.h"
  14. #include "shell/common/gin_converters/callback_converter.h"
  15. #include "shell/common/gin_converters/frame_converter.h"
  16. #include "shell/common/gin_converters/gfx_converter.h"
  17. #include "shell/common/gin_converters/gurl_converter.h"
  18. #include "shell/common/gin_helper/dictionary.h"
  19. #include "third_party/blink/public/common/context_menu_data/untrustworthy_context_menu_params.h"
  20. #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
  21. #include "ui/base/mojom/menu_source_type.mojom.h"
  22. #include "ui/events/keycodes/dom/keycode_converter.h"
  23. #include "ui/events/keycodes/keyboard_code_conversion.h"
  24. namespace gin {
  25. static constexpr auto MenuSourceTypes =
  26. base::MakeFixedFlatMap<std::string_view, ui::mojom::MenuSourceType>({
  27. {"adjustSelection", ui::mojom::MenuSourceType::kAdjustSelection},
  28. {"adjustSelectionReset",
  29. ui::mojom::MenuSourceType::kAdjustSelectionReset},
  30. {"keyboard", ui::mojom::MenuSourceType::kKeyboard},
  31. {"longPress", ui::mojom::MenuSourceType::kLongPress},
  32. {"longTap", ui::mojom::MenuSourceType::kLongTap},
  33. {"mouse", ui::mojom::MenuSourceType::kMouse},
  34. {"none", ui::mojom::MenuSourceType::kNone},
  35. {"stylus", ui::mojom::MenuSourceType::kStylus},
  36. {"touch", ui::mojom::MenuSourceType::kTouch},
  37. {"touchHandle", ui::mojom::MenuSourceType::kTouchHandle},
  38. {"touchMenu", ui::mojom::MenuSourceType::kTouchEditMenu},
  39. });
  40. // let us know when upstream changes & we need to update MenuSourceTypes
  41. static_assert(std::size(MenuSourceTypes) ==
  42. static_cast<int32_t>(ui::mojom::MenuSourceType::kMaxValue) + 1);
  43. // static
  44. v8::Local<v8::Value> Converter<ui::mojom::MenuSourceType>::ToV8(
  45. v8::Isolate* isolate,
  46. const ui::mojom::MenuSourceType& in) {
  47. for (auto const& [key, val] : MenuSourceTypes)
  48. if (in == val)
  49. return StringToV8(isolate, key);
  50. return {};
  51. }
  52. // static
  53. bool Converter<ui::mojom::MenuSourceType>::FromV8(
  54. v8::Isolate* isolate,
  55. v8::Local<v8::Value> val,
  56. ui::mojom::MenuSourceType* out) {
  57. return FromV8WithLookup(isolate, val, MenuSourceTypes, out);
  58. }
  59. // static
  60. v8::Local<v8::Value> Converter<blink::mojom::MenuItem::Type>::ToV8(
  61. v8::Isolate* isolate,
  62. const blink::mojom::MenuItem::Type& val) {
  63. switch (val) {
  64. case blink::mojom::MenuItem::Type::kCheckableOption:
  65. return StringToV8(isolate, "checkbox");
  66. case blink::mojom::MenuItem::Type::kGroup:
  67. return StringToV8(isolate, "radio");
  68. case blink::mojom::MenuItem::Type::kSeparator:
  69. return StringToV8(isolate, "separator");
  70. case blink::mojom::MenuItem::Type::kSubMenu:
  71. return StringToV8(isolate, "submenu");
  72. case blink::mojom::MenuItem::Type::kOption:
  73. default:
  74. return StringToV8(isolate, "normal");
  75. }
  76. }
  77. // static
  78. v8::Local<v8::Value> Converter<ContextMenuParamsWithRenderFrameHost>::ToV8(
  79. v8::Isolate* isolate,
  80. const ContextMenuParamsWithRenderFrameHost& val) {
  81. const auto& params = val.first;
  82. content::RenderFrameHost* render_frame_host = val.second;
  83. auto dict = gin_helper::Dictionary::CreateEmpty(isolate);
  84. dict.SetGetter("frame", render_frame_host, v8::DontEnum);
  85. dict.Set("x", params.x);
  86. dict.Set("y", params.y);
  87. dict.Set("linkURL", params.link_url);
  88. dict.Set("linkText", params.link_text);
  89. dict.Set("pageURL", params.page_url);
  90. dict.Set("frameURL", params.frame_url);
  91. dict.Set("srcURL", params.src_url);
  92. dict.Set("mediaType", params.media_type);
  93. dict.Set("mediaFlags", MediaFlagsToV8(isolate, params.media_flags));
  94. bool has_image_contents =
  95. (params.media_type == blink::mojom::ContextMenuDataMediaType::kImage) &&
  96. params.has_image_contents;
  97. dict.Set("hasImageContents", has_image_contents);
  98. dict.Set("isEditable", params.is_editable);
  99. dict.Set("editFlags", EditFlagsToV8(isolate, params.edit_flags));
  100. dict.Set("selectionText", params.selection_text);
  101. dict.Set("titleText", params.title_text);
  102. dict.Set("altText", params.alt_text);
  103. dict.Set("suggestedFilename", params.suggested_filename);
  104. dict.Set("misspelledWord", params.misspelled_word);
  105. dict.Set("selectionRect", params.selection_rect);
  106. #if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
  107. dict.Set("dictionarySuggestions", params.dictionary_suggestions);
  108. dict.Set("spellcheckEnabled", params.spellcheck_enabled);
  109. #else
  110. dict.Set("spellcheckEnabled", false);
  111. #endif
  112. dict.Set("frameCharset", params.frame_charset);
  113. dict.Set("referrerPolicy", params.referrer_policy);
  114. dict.Set("formControlType", params.form_control_type);
  115. dict.Set("menuSourceType", params.source_type);
  116. return gin::ConvertToV8(isolate, dict);
  117. }
  118. // static
  119. bool Converter<blink::mojom::PermissionStatus>::FromV8(
  120. v8::Isolate* isolate,
  121. v8::Local<v8::Value> val,
  122. blink::mojom::PermissionStatus* out) {
  123. bool result;
  124. if (!ConvertFromV8(isolate, val, &result))
  125. return false;
  126. if (result)
  127. *out = blink::mojom::PermissionStatus::GRANTED;
  128. else
  129. *out = blink::mojom::PermissionStatus::DENIED;
  130. return true;
  131. }
  132. // static
  133. v8::Local<v8::Value> Converter<blink::PermissionType>::ToV8(
  134. v8::Isolate* isolate,
  135. const blink::PermissionType& val) {
  136. using PermissionType = electron::WebContentsPermissionHelper::PermissionType;
  137. // Based on mappings from content/browser/devtools/protocol/browser_handler.cc
  138. // Not all permissions are currently used by Electron but this will future
  139. // proof these conversions.
  140. switch (val) {
  141. case blink::PermissionType::AUTOMATIC_FULLSCREEN:
  142. return StringToV8(isolate, "automatic-fullscreen");
  143. case blink::PermissionType::AR:
  144. return StringToV8(isolate, "ar");
  145. case blink::PermissionType::BACKGROUND_FETCH:
  146. return StringToV8(isolate, "background-fetch");
  147. case blink::PermissionType::BACKGROUND_SYNC:
  148. return StringToV8(isolate, "background-sync");
  149. case blink::PermissionType::CLIPBOARD_READ_WRITE:
  150. return StringToV8(isolate, "clipboard-read");
  151. case blink::PermissionType::CLIPBOARD_SANITIZED_WRITE:
  152. return StringToV8(isolate, "clipboard-sanitized-write");
  153. case blink::PermissionType::LOCAL_FONTS:
  154. return StringToV8(isolate, "local-fonts");
  155. case blink::PermissionType::HAND_TRACKING:
  156. return StringToV8(isolate, "hand-tracking");
  157. case blink::PermissionType::IDLE_DETECTION:
  158. return StringToV8(isolate, "idle-detection");
  159. case blink::PermissionType::KEYBOARD_LOCK:
  160. return StringToV8(isolate, "keyboardLock");
  161. case blink::PermissionType::MIDI_SYSEX:
  162. return StringToV8(isolate, "midiSysex");
  163. case blink::PermissionType::NFC:
  164. return StringToV8(isolate, "nfc");
  165. case blink::PermissionType::NOTIFICATIONS:
  166. return StringToV8(isolate, "notifications");
  167. case blink::PermissionType::PAYMENT_HANDLER:
  168. return StringToV8(isolate, "payment-handler");
  169. case blink::PermissionType::PERIODIC_BACKGROUND_SYNC:
  170. return StringToV8(isolate, "periodic-background-sync");
  171. case blink::PermissionType::DURABLE_STORAGE:
  172. return StringToV8(isolate, "persistent-storage");
  173. case blink::PermissionType::GEOLOCATION:
  174. return StringToV8(isolate, "geolocation");
  175. case blink::PermissionType::CAMERA_PAN_TILT_ZOOM:
  176. case blink::PermissionType::AUDIO_CAPTURE:
  177. case blink::PermissionType::VIDEO_CAPTURE:
  178. return StringToV8(isolate, "media");
  179. case blink::PermissionType::POINTER_LOCK:
  180. return StringToV8(isolate, "pointerLock");
  181. case blink::PermissionType::PROTECTED_MEDIA_IDENTIFIER:
  182. return StringToV8(isolate, "mediaKeySystem");
  183. case blink::PermissionType::MIDI:
  184. return StringToV8(isolate, "midi");
  185. case blink::PermissionType::WAKE_LOCK_SCREEN:
  186. return StringToV8(isolate, "screen-wake-lock");
  187. case blink::PermissionType::SENSORS:
  188. return StringToV8(isolate, "sensors");
  189. case blink::PermissionType::STORAGE_ACCESS_GRANT:
  190. return StringToV8(isolate, "storage-access");
  191. case blink::PermissionType::VR:
  192. return StringToV8(isolate, "vr");
  193. case blink::PermissionType::WAKE_LOCK_SYSTEM:
  194. return StringToV8(isolate, "system-wake-lock");
  195. case blink::PermissionType::WINDOW_MANAGEMENT:
  196. return StringToV8(isolate, "window-management");
  197. case blink::PermissionType::DISPLAY_CAPTURE:
  198. return StringToV8(isolate, "display-capture");
  199. case blink::PermissionType::TOP_LEVEL_STORAGE_ACCESS:
  200. return StringToV8(isolate, "top-level-storage-access");
  201. case blink::PermissionType::CAPTURED_SURFACE_CONTROL:
  202. return StringToV8(isolate, "captured-surface-control");
  203. case blink::PermissionType::SMART_CARD:
  204. return StringToV8(isolate, "smart-card");
  205. case blink::PermissionType::WEB_PRINTING:
  206. return StringToV8(isolate, "web-printing");
  207. case blink::PermissionType::SPEAKER_SELECTION:
  208. return StringToV8(isolate, "speaker-selection");
  209. case blink::PermissionType::WEB_APP_INSTALLATION:
  210. return StringToV8(isolate, "web-app-installation");
  211. case blink::PermissionType::LOCAL_NETWORK_ACCESS:
  212. return StringToV8(isolate, "local-network-access");
  213. case blink::PermissionType::DEPRECATED_SYNC_CLIPBOARD_READ:
  214. return StringToV8(isolate, "deprecated-sync-clipboard-read");
  215. case blink::PermissionType::NUM:
  216. break;
  217. }
  218. switch (static_cast<PermissionType>(val)) {
  219. case PermissionType::FULLSCREEN:
  220. return StringToV8(isolate, "fullscreen");
  221. case PermissionType::OPEN_EXTERNAL:
  222. return StringToV8(isolate, "openExternal");
  223. case PermissionType::SERIAL:
  224. return StringToV8(isolate, "serial");
  225. case PermissionType::HID:
  226. return StringToV8(isolate, "hid");
  227. case PermissionType::USB:
  228. return StringToV8(isolate, "usb");
  229. case PermissionType::FILE_SYSTEM:
  230. return StringToV8(isolate, "fileSystem");
  231. default:
  232. return StringToV8(isolate, "unknown");
  233. }
  234. }
  235. // static
  236. bool Converter<content::StopFindAction>::FromV8(v8::Isolate* isolate,
  237. v8::Local<v8::Value> val,
  238. content::StopFindAction* out) {
  239. using Val = content::StopFindAction;
  240. static constexpr auto Lookup = base::MakeFixedFlatMap<std::string_view, Val>({
  241. {"activateSelection", Val::STOP_FIND_ACTION_ACTIVATE_SELECTION},
  242. {"clearSelection", Val::STOP_FIND_ACTION_CLEAR_SELECTION},
  243. {"keepSelection", Val::STOP_FIND_ACTION_KEEP_SELECTION},
  244. });
  245. return FromV8WithLookup(isolate, val, Lookup, out);
  246. }
  247. // static
  248. v8::Local<v8::Value> Converter<content::WebContents*>::ToV8(
  249. v8::Isolate* isolate,
  250. content::WebContents* val) {
  251. if (!val)
  252. return v8::Null(isolate);
  253. return electron::api::WebContents::FromOrCreate(isolate, val).ToV8();
  254. }
  255. // static
  256. bool Converter<content::WebContents*>::FromV8(v8::Isolate* isolate,
  257. v8::Local<v8::Value> val,
  258. content::WebContents** out) {
  259. if (!val->IsObject())
  260. return false;
  261. // gin's unwrapping converter doesn't expect the pointer inside to ever be
  262. // nullptr, so we check here first before attempting to unwrap.
  263. if (gin_helper::Destroyable::IsDestroyed(val.As<v8::Object>()))
  264. return false;
  265. electron::api::WebContents* web_contents = nullptr;
  266. if (!gin::ConvertFromV8(isolate, val, &web_contents) || !web_contents)
  267. return false;
  268. *out = web_contents->web_contents();
  269. return true;
  270. }
  271. // static
  272. v8::Local<v8::Value> Converter<content::Referrer>::ToV8(
  273. v8::Isolate* isolate,
  274. const content::Referrer& val) {
  275. auto dict = gin_helper::Dictionary::CreateEmpty(isolate);
  276. dict.Set("url", ConvertToV8(isolate, val.url));
  277. dict.Set("policy", ConvertToV8(isolate, val.policy));
  278. return gin::ConvertToV8(isolate, dict);
  279. }
  280. // static
  281. bool Converter<content::Referrer>::FromV8(v8::Isolate* isolate,
  282. v8::Local<v8::Value> val,
  283. content::Referrer* out) {
  284. gin_helper::Dictionary dict;
  285. if (!ConvertFromV8(isolate, val, &dict))
  286. return false;
  287. if (!dict.Get("url", &out->url))
  288. return false;
  289. if (!dict.Get("policy", &out->policy))
  290. return false;
  291. return true;
  292. }
  293. // static
  294. bool Converter<input::NativeWebKeyboardEvent>::FromV8(
  295. v8::Isolate* isolate,
  296. v8::Local<v8::Value> val,
  297. input::NativeWebKeyboardEvent* out) {
  298. gin_helper::Dictionary dict;
  299. if (!ConvertFromV8(isolate, val, &dict))
  300. return false;
  301. if (!ConvertFromV8(isolate, val, static_cast<blink::WebKeyboardEvent*>(out)))
  302. return false;
  303. dict.Get("skipIfUnhandled", &out->skip_if_unhandled);
  304. return true;
  305. }
  306. // static
  307. v8::Local<v8::Value> Converter<input::NativeWebKeyboardEvent>::ToV8(
  308. v8::Isolate* isolate,
  309. const input::NativeWebKeyboardEvent& in) {
  310. return ConvertToV8(isolate, static_cast<blink::WebKeyboardEvent>(in));
  311. }
  312. } // namespace gin