1 // Copyright 2014 The Chromium Authors. 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 "components/renderer_context_menu/context_menu_content_type.h"
6
7 #include "base/bind.h"
8 #include "content/public/browser/web_contents.h"
9 #include "content/public/common/url_constants.h"
10 #include "printing/buildflags/buildflags.h"
11 #include "third_party/blink/public/common/context_menu_data/input_field_type.h"
12
13 using blink::ContextMenuDataMediaType;
14 using content::WebContents;
15
16 namespace {
17
IsDevToolsURL(const GURL & url)18 bool IsDevToolsURL(const GURL& url) {
19 return url.SchemeIs(content::kChromeDevToolsScheme);
20 }
21
22 } // namespace
23
ContextMenuContentType(content::WebContents * web_contents,const content::ContextMenuParams & params,bool supports_custom_items)24 ContextMenuContentType::ContextMenuContentType(
25 content::WebContents* web_contents,
26 const content::ContextMenuParams& params,
27 bool supports_custom_items)
28 : params_(params),
29 source_web_contents_(web_contents),
30 supports_custom_items_(supports_custom_items) {}
31
~ContextMenuContentType()32 ContextMenuContentType::~ContextMenuContentType() {
33 }
34
SupportsGroup(int group)35 bool ContextMenuContentType::SupportsGroup(int group) {
36 const bool has_selection = !params_.selection_text.empty();
37
38 if (supports_custom_items_ && !params_.custom_items.empty()) {
39 if (group == ITEM_GROUP_CUSTOM)
40 return true;
41
42 if (!has_selection) {
43 // For menus with custom items, if there is no selection, we do not
44 // add items other than developer items. And for Pepper menu, don't even
45 // add developer items.
46 if (!params_.custom_context.is_pepper_menu)
47 return group == ITEM_GROUP_DEVELOPER;
48
49 return false;
50 }
51
52 // If there's a selection when there are custom items, fall through to
53 // adding the normal ones after the custom ones.
54 }
55
56 if (IsDevToolsURL(params_.page_url)) {
57 // DevTools mostly provides custom context menu and uses
58 // only the following default options.
59 if (group != ITEM_GROUP_CUSTOM && group != ITEM_GROUP_EDITABLE &&
60 group != ITEM_GROUP_COPY && group != ITEM_GROUP_DEVELOPER &&
61 group != ITEM_GROUP_SEARCH_PROVIDER) {
62 return false;
63 }
64 }
65
66 return SupportsGroupInternal(group);
67 }
68
SupportsGroupInternal(int group)69 bool ContextMenuContentType::SupportsGroupInternal(int group) {
70 const bool has_link = !params_.unfiltered_link_url.is_empty();
71 const bool has_selection = !params_.selection_text.empty();
72 const bool is_password = params_.input_field_type ==
73 blink::ContextMenuDataInputFieldType::kPassword;
74
75 switch (group) {
76 case ITEM_GROUP_CUSTOM:
77 return supports_custom_items_ && !params_.custom_items.empty();
78
79 case ITEM_GROUP_PAGE: {
80 bool is_candidate =
81 params_.media_type == ContextMenuDataMediaType::kNone && !has_link &&
82 !params_.is_editable && !has_selection;
83
84 if (!is_candidate && params_.page_url.is_empty())
85 DCHECK(params_.frame_url.is_empty());
86
87 return is_candidate && !params_.page_url.is_empty();
88 }
89
90 case ITEM_GROUP_FRAME: {
91 bool page_group_supported = SupportsGroupInternal(ITEM_GROUP_PAGE);
92 return page_group_supported && !params_.frame_url.is_empty();
93 }
94
95 case ITEM_GROUP_LINK:
96 return has_link;
97
98 case ITEM_GROUP_SMART_SELECTION:
99 return has_selection && !has_link;
100
101 case ITEM_GROUP_MEDIA_IMAGE:
102 return params_.media_type == ContextMenuDataMediaType::kImage;
103
104 case ITEM_GROUP_SEARCHWEBFORIMAGE:
105 // Image menu items imply search web for image item.
106 return SupportsGroupInternal(ITEM_GROUP_MEDIA_IMAGE);
107
108 case ITEM_GROUP_MEDIA_VIDEO:
109 return params_.media_type == ContextMenuDataMediaType::kVideo;
110
111 case ITEM_GROUP_MEDIA_AUDIO:
112 return params_.media_type == ContextMenuDataMediaType::kAudio;
113
114 case ITEM_GROUP_MEDIA_CANVAS:
115 return params_.media_type == ContextMenuDataMediaType::kCanvas;
116
117 case ITEM_GROUP_MEDIA_PLUGIN:
118 return params_.media_type == ContextMenuDataMediaType::kPlugin;
119
120 case ITEM_GROUP_MEDIA_FILE:
121 return params_.media_type == ContextMenuDataMediaType::kFile;
122
123 case ITEM_GROUP_EDITABLE:
124 return params_.is_editable;
125
126 case ITEM_GROUP_COPY:
127 return !params_.is_editable && has_selection;
128
129 case ITEM_GROUP_SEARCH_PROVIDER:
130 return has_selection && !is_password;
131
132 case ITEM_GROUP_PRINT: {
133 // Image menu items also imply print items.
134 return has_selection || SupportsGroupInternal(ITEM_GROUP_MEDIA_IMAGE);
135 }
136
137 case ITEM_GROUP_ALL_EXTENSION:
138 return true;
139
140 case ITEM_GROUP_CURRENT_EXTENSION:
141 return false;
142
143 case ITEM_GROUP_DEVELOPER:
144 return true;
145
146 case ITEM_GROUP_DEVTOOLS_UNPACKED_EXT:
147 return false;
148
149 case ITEM_GROUP_PRINT_PREVIEW:
150 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
151 return true;
152 #else
153 return false;
154 #endif
155
156 case ITEM_GROUP_PASSWORD:
157 return params_.input_field_type ==
158 blink::ContextMenuDataInputFieldType::kPassword;
159
160 default:
161 NOTREACHED();
162 return false;
163 }
164 }
165