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 "third_party/WebKit/public/web/WebContextMenuData.h" 11 12 #if defined(ENABLE_EXTENSIONS) 13 #include "extensions/browser/extension_system.h" 14 #include "extensions/browser/process_manager.h" 15 #include "extensions/common/extension.h" 16 #endif 17 18 using blink::WebContextMenuData; 19 using content::WebContents; 20 21 #if defined(ENABLE_EXTENSIONS) 22 using extensions::Extension; 23 #endif 24 25 namespace { 26 27 bool IsDevToolsURL(const GURL& url) { 28 return url.SchemeIs(content::kChromeDevToolsScheme); 29 } 30 31 bool DefaultIsInternalResourcesURL(const GURL& url) { 32 return url.SchemeIs(content::kChromeUIScheme); 33 } 34 35 } // namespace 36 37 ContextMenuContentType::ContextMenuContentType( 38 content::WebContents* web_contents, 39 const content::ContextMenuParams& params, 40 bool supports_custom_items) 41 : params_(params), 42 source_web_contents_(web_contents), 43 supports_custom_items_(supports_custom_items), 44 internal_resources_url_checker_( 45 base::Bind(&DefaultIsInternalResourcesURL)) { 46 } 47 48 ContextMenuContentType::~ContextMenuContentType() { 49 } 50 51 #if defined(ENABLE_EXTENSIONS) 52 const Extension* ContextMenuContentType::GetExtension() const { 53 extensions::ExtensionSystem* system = extensions::ExtensionSystem::Get( 54 source_web_contents_->GetBrowserContext()); 55 // There is no process manager in some tests. 56 if (!system->process_manager()) 57 return NULL; 58 59 return system->process_manager()->GetExtensionForRenderViewHost( 60 source_web_contents_->GetRenderViewHost()); 61 } 62 #endif 63 64 bool ContextMenuContentType::SupportsGroup(int group) { 65 const bool has_selection = !params_.selection_text.empty(); 66 67 if (supports_custom_items_ && !params_.custom_items.empty()) { 68 if (group == ITEM_GROUP_CUSTOM) 69 return true; 70 71 if (!has_selection) { 72 // For menus with custom items, if there is no selection, we do not 73 // add items other than developer items. And for Pepper menu, don't even 74 // add developer items. 75 if (!params_.custom_context.is_pepper_menu) 76 return group == ITEM_GROUP_DEVELOPER; 77 78 return false; 79 } 80 81 // If there's a selection when there are custom items, fall through to 82 // adding the normal ones after the custom ones. 83 } 84 85 if (IsDevToolsURL(params_.page_url)) { 86 // DevTools mostly provides custom context menu and uses 87 // only the following default options. 88 if (group != ITEM_GROUP_CUSTOM && 89 group != ITEM_GROUP_EDITABLE && 90 group != ITEM_GROUP_COPY && 91 group != ITEM_GROUP_DEVELOPER) { 92 return false; 93 } 94 } 95 96 return SupportsGroupInternal(group); 97 } 98 99 bool ContextMenuContentType::SupportsGroupInternal(int group) { 100 const bool has_link = !params_.unfiltered_link_url.is_empty(); 101 const bool has_selection = !params_.selection_text.empty(); 102 103 switch (group) { 104 case ITEM_GROUP_CUSTOM: 105 return supports_custom_items_ && !params_.custom_items.empty(); 106 107 case ITEM_GROUP_PAGE: { 108 bool is_candidate = 109 params_.media_type == WebContextMenuData::MediaTypeNone && 110 !has_link && !params_.is_editable && !has_selection; 111 112 if (!is_candidate && params_.page_url.is_empty()) 113 DCHECK(params_.frame_url.is_empty()); 114 115 return is_candidate && !params_.page_url.is_empty() && 116 !IsInternalResourcesURL(params_.page_url); 117 } 118 119 case ITEM_GROUP_FRAME: { 120 bool page_group_supported = SupportsGroupInternal(ITEM_GROUP_PAGE); 121 return page_group_supported && !params_.frame_url.is_empty() && 122 !IsInternalResourcesURL(params_.page_url); 123 } 124 125 case ITEM_GROUP_LINK: 126 return has_link; 127 128 case ITEM_GROUP_MEDIA_IMAGE: 129 return params_.media_type == WebContextMenuData::MediaTypeImage; 130 131 case ITEM_GROUP_SEARCHWEBFORIMAGE: 132 // Image menu items imply search web for image item. 133 return SupportsGroupInternal(ITEM_GROUP_MEDIA_IMAGE); 134 135 case ITEM_GROUP_MEDIA_VIDEO: 136 return params_.media_type == WebContextMenuData::MediaTypeVideo; 137 138 case ITEM_GROUP_MEDIA_AUDIO: 139 return params_.media_type == WebContextMenuData::MediaTypeAudio; 140 141 case ITEM_GROUP_MEDIA_CANVAS: 142 return params_.media_type == WebContextMenuData::MediaTypeCanvas; 143 144 case ITEM_GROUP_MEDIA_PLUGIN: 145 return params_.media_type == WebContextMenuData::MediaTypePlugin; 146 147 case ITEM_GROUP_MEDIA_FILE: 148 #if defined(WEBCONTEXT_MEDIATYPEFILE_DEFINED) 149 return params_.media_type == WebContextMenuData::MediaTypeFile; 150 #else 151 return false; 152 #endif 153 154 case ITEM_GROUP_EDITABLE: 155 return params_.is_editable; 156 157 case ITEM_GROUP_COPY: 158 return !params_.is_editable && has_selection; 159 160 case ITEM_GROUP_SEARCH_PROVIDER: 161 return has_selection; 162 163 case ITEM_GROUP_PRINT: { 164 // Image menu items also imply print items. 165 return has_selection || SupportsGroupInternal(ITEM_GROUP_MEDIA_IMAGE); 166 } 167 168 case ITEM_GROUP_ALL_EXTENSION: 169 return true; 170 171 case ITEM_GROUP_CURRENT_EXTENSION: 172 return false; 173 174 case ITEM_GROUP_DEVELOPER: 175 return true; 176 177 case ITEM_GROUP_DEVTOOLS_UNPACKED_EXT: 178 return false; 179 180 case ITEM_GROUP_PRINT_PREVIEW: 181 #if defined(ENABLE_FULL_PRINTING) 182 return true; 183 #else 184 return false; 185 #endif 186 187 default: 188 NOTREACHED(); 189 return false; 190 } 191 } 192 193 bool ContextMenuContentType::IsInternalResourcesURL(const GURL& url) { 194 return internal_resources_url_checker_.Run(url); 195 } 196