Home | History | Annotate | Download | only in renderer_context_menu
      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