summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoroshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-07 06:57:54 +0000
committeroshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-07 06:57:54 +0000
commitcf8c490895593de5069dd6c8204344ade8d6651e (patch)
tree079214b331277cc9034b9d5e64fb684c57b350a1
parent0f9e5b14cb75b2ac53ad3576125ba045f5ec53e2 (diff)
downloadchromium_src-cf8c490895593de5069dd6c8204344ade8d6651e.zip
chromium_src-cf8c490895593de5069dd6c8204344ade8d6651e.tar.gz
chromium_src-cf8c490895593de5069dd6c8204344ade8d6651e.tar.bz2
Separate chrome independent part from RVContextMenu
and move it to components/renderer_context_menu/renderer_view_context_menu_base.{h|cc} BUG=397320 TBR=blundell@chromium.org Review URL: https://codereview.chromium.org/432003007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@287971 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/renderer_context_menu/render_view_context_menu.cc404
-rw-r--r--chrome/browser/renderer_context_menu/render_view_context_menu.h112
-rw-r--r--components/components.gyp2
-rw-r--r--components/renderer_context_menu.gypi4
-rw-r--r--components/renderer_context_menu/render_view_context_menu_base.cc387
-rw-r--r--components/renderer_context_menu/render_view_context_menu_base.h186
6 files changed, 659 insertions, 436 deletions
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index 7d7207c..e9bae1b 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -142,11 +142,6 @@ const int kImageSearchThumbnailMinSize = 300 * 300;
const int kImageSearchThumbnailMaxWidth = 600;
const int kImageSearchThumbnailMaxHeight = 600;
-// The range of command IDs reserved for content's custom menus.
-// TODO(oshima): These values will be injected by embedders.
-const int content_context_custom_first = IDC_CONTENT_CONTEXT_CUSTOM_FIRST;
-const int content_context_custom_last = IDC_CONTENT_CONTEXT_CUSTOM_LAST;
-
// Maps UMA enumeration to IDC. IDC could be changed so we can't use
// just them and |UMA_HISTOGRAM_CUSTOM_ENUMERATION|.
// Never change mapping or reuse |enum_id|. Always push back new items.
@@ -262,32 +257,6 @@ int FindUMAEnumValueForCommand(int id) {
return -1;
}
-// Increments histogram value for used items specified by |id|.
-void RecordUsedItem(int id) {
- int enum_id = FindUMAEnumValueForCommand(id);
- if (enum_id != -1) {
- const size_t kMappingSize = arraysize(kUmaEnumToControlId);
- UMA_HISTOGRAM_ENUMERATION("RenderViewContextMenu.Used", enum_id,
- kUmaEnumToControlId[kMappingSize - 1].enum_id);
- } else {
- NOTREACHED() << "Update kUmaEnumToControlId. Unhanded IDC: " << id;
- }
-}
-
-// Increments histogram value for visible context menu item specified by |id|.
-void RecordShownItem(int id) {
- int enum_id = FindUMAEnumValueForCommand(id);
- if (enum_id != -1) {
- const size_t kMappingSize = arraysize(kUmaEnumToControlId);
- UMA_HISTOGRAM_ENUMERATION("RenderViewContextMenu.Shown", enum_id,
- kUmaEnumToControlId[kMappingSize - 1].enum_id);
- } else {
- // Just warning here. It's harder to maintain list of all possibly
- // visible items than executable items.
- DLOG(ERROR) << "Update kUmaEnumToControlId. Unhanded IDC: " << id;
- }
-}
-
// Usually a new tab is expected where this function is used,
// however users should be able to open a tab in background
// or in a new window.
@@ -298,98 +267,6 @@ WindowOpenDisposition ForceNewTabDispositionFromEventFlags(
return disposition == CURRENT_TAB ? NEW_FOREGROUND_TAB : disposition;
}
-bool IsCustomItemEnabled(const std::vector<content::MenuItem>& items, int id) {
- DCHECK(RenderViewContextMenu::IsContentCustomCommandId(id));
- for (size_t i = 0; i < items.size(); ++i) {
- int action_id =
- RenderViewContextMenu::ConvertToContentCustomCommandId(items[i].action);
- if (action_id == id)
- return items[i].enabled;
- if (items[i].type == content::MenuItem::SUBMENU) {
- if (IsCustomItemEnabled(items[i].submenu, id))
- return true;
- }
- }
- return false;
-}
-
-bool IsCustomItemChecked(const std::vector<content::MenuItem>& items, int id) {
- DCHECK(RenderViewContextMenu::IsContentCustomCommandId(id));
- for (size_t i = 0; i < items.size(); ++i) {
- int action_id =
- RenderViewContextMenu::ConvertToContentCustomCommandId(items[i].action);
- if (action_id == id)
- return items[i].checked;
- if (items[i].type == content::MenuItem::SUBMENU) {
- if (IsCustomItemChecked(items[i].submenu, id))
- return true;
- }
- }
- return false;
-}
-
-const size_t kMaxCustomMenuDepth = 5;
-const size_t kMaxCustomMenuTotalItems = 1000;
-
-void AddCustomItemsToMenu(const std::vector<content::MenuItem>& items,
- size_t depth,
- size_t* total_items,
- ui::SimpleMenuModel::Delegate* delegate,
- ui::SimpleMenuModel* menu_model) {
- if (depth > kMaxCustomMenuDepth) {
- LOG(ERROR) << "Custom menu too deeply nested.";
- return;
- }
- for (size_t i = 0; i < items.size(); ++i) {
- int command_id =
- RenderViewContextMenu::ConvertToContentCustomCommandId(items[i].action);
- if (!RenderViewContextMenu::IsContentCustomCommandId(command_id)) {
- LOG(ERROR) << "Custom menu action value out of range.";
- return;
- }
- if (*total_items >= kMaxCustomMenuTotalItems) {
- LOG(ERROR) << "Custom menu too large (too many items).";
- return;
- }
- (*total_items)++;
- switch (items[i].type) {
- case content::MenuItem::OPTION:
- menu_model->AddItem(
- RenderViewContextMenu::ConvertToContentCustomCommandId(
- items[i].action),
- items[i].label);
- break;
- case content::MenuItem::CHECKABLE_OPTION:
- menu_model->AddCheckItem(
- RenderViewContextMenu::ConvertToContentCustomCommandId(
- items[i].action),
- items[i].label);
- break;
- case content::MenuItem::GROUP:
- // TODO(viettrungluu): I don't know what this is supposed to do.
- NOTREACHED();
- break;
- case content::MenuItem::SEPARATOR:
- menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
- break;
- case content::MenuItem::SUBMENU: {
- ui::SimpleMenuModel* submenu = new ui::SimpleMenuModel(delegate);
- AddCustomItemsToMenu(items[i].submenu, depth + 1, total_items, delegate,
- submenu);
- menu_model->AddSubMenu(
- RenderViewContextMenu::ConvertToContentCustomCommandId(
- items[i].action),
- items[i].label,
- submenu);
- break;
- }
- default:
- NOTREACHED();
- break;
- }
- }
-}
-
// Helper function to escape "&" as "&&".
void EscapeAmpersands(base::string16* text) {
base::ReplaceChars(*text, base::ASCIIToUTF16("&"), base::ASCIIToUTF16("&&"),
@@ -401,21 +278,9 @@ PrefService* GetPrefs(content::BrowserContext* context) {
return user_prefs::UserPrefs::Get(context);
}
-} // namespace
-
-// static
-const size_t RenderViewContextMenu::kMaxSelectionTextLength = 50;
-
-// static
-int RenderViewContextMenu::ConvertToContentCustomCommandId(int id) {
- return content_context_custom_first + id;
-}
+bool custom_id_ranges_initialized = false;
-// static
-bool RenderViewContextMenu::IsContentCustomCommandId(int id) {
- return id >= content_context_custom_first &&
- id <= content_context_custom_last;
-}
+} // namespace
// static
bool RenderViewContextMenu::IsDevToolsURL(const GURL& url) {
@@ -434,22 +299,21 @@ static const int kSpellcheckRadioGroup = 1;
RenderViewContextMenu::RenderViewContextMenu(
content::RenderFrameHost* render_frame_host,
const content::ContextMenuParams& params)
- : params_(params),
- source_web_contents_(WebContents::FromRenderFrameHost(render_frame_host)),
- render_process_id_(render_frame_host->GetProcess()->GetID()),
- render_frame_id_(render_frame_host->GetRoutingID()),
- browser_context_(source_web_contents_->GetBrowserContext()),
- menu_model_(this),
+ : RenderViewContextMenuBase(render_frame_host, params),
extension_items_(browser_context_,
this,
&menu_model_,
base::Bind(MenuItemMatchesParams, params_)),
protocol_handler_submenu_model_(this),
protocol_handler_registry_(
- ProtocolHandlerRegistryFactory::GetForBrowserContext(GetProfile())),
- command_executed_(false) {
- content_type_.reset(ContextMenuContentTypeFactory::Create(
- source_web_contents_, params));
+ ProtocolHandlerRegistryFactory::GetForBrowserContext(GetProfile())) {
+ if (!custom_id_ranges_initialized) {
+ custom_id_ranges_initialized = true;
+ SetContentCustomCommandIdRange(IDC_CONTENT_CONTEXT_CUSTOM_FIRST,
+ IDC_CONTENT_CONTEXT_CUSTOM_LAST);
+ }
+ set_content_type(ContextMenuContentTypeFactory::Create(
+ source_web_contents_, params));
}
RenderViewContextMenu::~RenderViewContextMenu() {
@@ -457,17 +321,6 @@ RenderViewContextMenu::~RenderViewContextMenu() {
// Menu construction functions -------------------------------------------------
-void RenderViewContextMenu::Init() {
- InitMenu();
- if (toolkit_delegate_)
- toolkit_delegate_->Init(&menu_model_);
-}
-
-void RenderViewContextMenu::Cancel() {
- if (toolkit_delegate_)
- toolkit_delegate_->Cancel();
-}
-
static bool ExtensionPatternMatch(const extensions::URLPatternSet& patterns,
const GURL& url) {
// No patterns means no restriction, so that implicitly matches.
@@ -615,16 +468,7 @@ void RenderViewContextMenu::AppendCurrentExtensionItems() {
}
void RenderViewContextMenu::InitMenu() {
- if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_CUSTOM)) {
- AppendCustomItems();
-
- const bool has_selection = !params_.selection_text.empty();
- if (has_selection) {
- // We will add more items if there's a selection, so add a separator.
- // TODO(lazyboy): Clean up separator logic.
- menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
- }
- }
+ RenderViewContextMenuBase::InitMenu();
if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_PAGE))
AppendPageItems();
@@ -725,6 +569,37 @@ Profile* RenderViewContextMenu::GetProfile() {
return Profile::FromBrowserContext(browser_context_);
}
+void RenderViewContextMenu::RecordUsedItem(int id) {
+ int enum_id = FindUMAEnumValueForCommand(id);
+ if (enum_id != -1) {
+ const size_t kMappingSize = arraysize(kUmaEnumToControlId);
+ UMA_HISTOGRAM_ENUMERATION("RenderViewContextMenu.Used", enum_id,
+ kUmaEnumToControlId[kMappingSize - 1].enum_id);
+ } else {
+ NOTREACHED() << "Update kUmaEnumToControlId. Unhanded IDC: " << id;
+ }
+}
+
+void RenderViewContextMenu::RecordShownItem(int id) {
+ int enum_id = FindUMAEnumValueForCommand(id);
+ if (enum_id != -1) {
+ const size_t kMappingSize = arraysize(kUmaEnumToControlId);
+ UMA_HISTOGRAM_ENUMERATION("RenderViewContextMenu.Shown", enum_id,
+ kUmaEnumToControlId[kMappingSize - 1].enum_id);
+ } else {
+ // Just warning here. It's harder to maintain list of all possibly
+ // visible items than executable items.
+ DLOG(ERROR) << "Update kUmaEnumToControlId. Unhanded IDC: " << id;
+ }
+}
+
+#if defined(ENABLE_PLUGINS)
+void RenderViewContextMenu::HandleAuthorizeAllPlugins() {
+ ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
+ source_web_contents_, false, std::string());
+}
+#endif
+
void RenderViewContextMenu::AppendPrintPreviewItems() {
#if defined(ENABLE_FULL_PRINTING)
if (!print_preview_menu_observer_.get()) {
@@ -747,57 +622,6 @@ const Extension* RenderViewContextMenu::GetExtension() const {
source_web_contents_->GetRenderViewHost());
}
-void RenderViewContextMenu::AddMenuItem(int command_id,
- const base::string16& title) {
- menu_model_.AddItem(command_id, title);
-}
-
-void RenderViewContextMenu::AddCheckItem(int command_id,
- const base::string16& title) {
- menu_model_.AddCheckItem(command_id, title);
-}
-
-void RenderViewContextMenu::AddSeparator() {
- menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
-}
-
-void RenderViewContextMenu::AddSubMenu(int command_id,
- const base::string16& label,
- ui::MenuModel* model) {
- menu_model_.AddSubMenu(command_id, label, model);
-}
-
-void RenderViewContextMenu::UpdateMenuItem(int command_id,
- bool enabled,
- bool hidden,
- const base::string16& label) {
- if (toolkit_delegate_) {
- toolkit_delegate_->UpdateMenuItem(command_id,
- enabled,
- hidden,
- label);
- }
-}
-
-RenderViewHost* RenderViewContextMenu::GetRenderViewHost() const {
- return source_web_contents_->GetRenderViewHost();
-}
-
-WebContents* RenderViewContextMenu::GetWebContents() const {
- return source_web_contents_;
-}
-
-BrowserContext* RenderViewContextMenu::GetBrowserContext() const {
- return browser_context_;
-}
-
-bool RenderViewContextMenu::AppendCustomItems() {
- size_t total_items = 0;
- AddCustomItemsToMenu(params_.custom_items, 0, &total_items, this,
- &menu_model_);
- return total_items > 0;
-}
-
void RenderViewContextMenu::AppendDeveloperItems() {
// Show Inspect Element in DevTools itself only in case of the debug
// devtools build.
@@ -1126,20 +950,11 @@ void RenderViewContextMenu::AppendProtocolHandlerSubMenu() {
&protocol_handler_submenu_model_);
}
-void RenderViewContextMenu::AppendPlatformEditableItems() {
-}
-
// Menu delegate functions -----------------------------------------------------
bool RenderViewContextMenu::IsCommandIdEnabled(int id) const {
- // If this command is is added by one of our observers, we dispatch it to the
- // observer.
- ObserverListBase<RenderViewContextMenuObserver>::Iterator it(observers_);
- RenderViewContextMenuObserver* observer;
- while ((observer = it.GetNext()) != NULL) {
- if (observer->IsCommandIdSupported(id))
- return observer->IsCommandIdEnabled(id);
- }
+ if (RenderViewContextMenuBase::IsCommandIdEnabled(id))
+ return true;
CoreTabHelper* core_tab_helper =
CoreTabHelper::FromWebContents(source_web_contents_);
@@ -1162,10 +977,6 @@ bool RenderViewContextMenu::IsCommandIdEnabled(int id) const {
return prefs->GetBoolean(prefs::kEnableContinuousSpellcheck);
}
- // Custom items.
- if (IsContentCustomCommandId(id))
- return IsCustomItemEnabled(params_.custom_items, id);
-
// Extension items.
if (ContextMenuMatcher::IsExtensionsCustomCommandId(id))
return extension_items_.IsCommandIdEnabled(id);
@@ -1428,14 +1239,8 @@ bool RenderViewContextMenu::IsCommandIdEnabled(int id) const {
}
bool RenderViewContextMenu::IsCommandIdChecked(int id) const {
- // If this command is is added by one of our observers, we dispatch it to the
- // observer.
- ObserverListBase<RenderViewContextMenuObserver>::Iterator it(observers_);
- RenderViewContextMenuObserver* observer;
- while ((observer = it.GetNext()) != NULL) {
- if (observer->IsCommandIdSupported(id))
- return observer->IsCommandIdChecked(id);
- }
+ if (RenderViewContextMenuBase::IsCommandIdChecked(id))
+ return true;
// See if the video is set to looping.
if (id == IDC_CONTENT_CONTEXT_LOOP) {
@@ -1448,10 +1253,6 @@ bool RenderViewContextMenu::IsCommandIdChecked(int id) const {
WebContextMenuData::MediaControls) != 0;
}
- // Custom items.
- if (IsContentCustomCommandId(id))
- return IsCustomItemChecked(params_.custom_items, id);
-
// Extension items.
if (ContextMenuMatcher::IsExtensionsCustomCommandId(id))
return extension_items_.IsCommandIdChecked(id);
@@ -1460,34 +1261,12 @@ bool RenderViewContextMenu::IsCommandIdChecked(int id) const {
}
void RenderViewContextMenu::ExecuteCommand(int id, int event_flags) {
+ RenderViewContextMenuBase::ExecuteCommand(id, event_flags);
+ if (command_executed_)
+ return;
command_executed_ = true;
- RecordUsedItem(id);
-
- // If this command is is added by one of our observers, we dispatch it to the
- // observer.
- ObserverListBase<RenderViewContextMenuObserver>::Iterator it(observers_);
- RenderViewContextMenuObserver* observer;
- while ((observer = it.GetNext()) != NULL) {
- if (observer->IsCommandIdSupported(id))
- return observer->ExecuteCommand(id);
- }
- RenderFrameHost* render_frame_host =
- RenderFrameHost::FromID(render_process_id_, render_frame_id_);
-
- // Process custom actions range.
- if (IsContentCustomCommandId(id)) {
- unsigned action = id - content_context_custom_first;
- const content::CustomContextMenuContext& context = params_.custom_context;
-#if defined(ENABLE_PLUGINS)
- if (context.request_id && !context.is_pepper_menu) {
- ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
- source_web_contents_, false, std::string());
- }
-#endif
- source_web_contents_->ExecuteCustomContextMenuCommand(action, context);
- return;
- }
+ RenderFrameHost* render_frame_host = GetRenderFrameHost();
// Process extension menu items.
if (ContextMenuMatcher::IsExtensionsCustomCommandId(id)) {
@@ -1915,45 +1694,27 @@ ProtocolHandlerRegistry::ProtocolHandlerList
return handlers;
}
-void RenderViewContextMenu::MenuWillShow(ui::SimpleMenuModel* source) {
- for (int i = 0; i < source->GetItemCount(); ++i) {
- if (source->IsVisibleAt(i) &&
- source->GetTypeAt(i) != ui::MenuModel::TYPE_SEPARATOR) {
- RecordShownItem(source->GetCommandIdAt(i));
- }
- }
-
- // Ignore notifications from submenus.
- if (source != &menu_model_)
- return;
-
- content::RenderWidgetHostView* view =
- source_web_contents_->GetRenderWidgetHostView();
- if (view)
- view->SetShowingContextMenu(true);
-
+void RenderViewContextMenu::NotifyMenuShown() {
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_RENDER_VIEW_CONTEXT_MENU_SHOWN,
content::Source<RenderViewContextMenu>(this),
content::NotificationService::NoDetails());
}
-void RenderViewContextMenu::MenuClosed(ui::SimpleMenuModel* source) {
- // Ignore notifications from submenus.
- if (source != &menu_model_)
- return;
-
- content::RenderWidgetHostView* view =
- source_web_contents_->GetRenderWidgetHostView();
- if (view)
- view->SetShowingContextMenu(false);
- source_web_contents_->NotifyContextMenuClosed(params_.custom_context);
+void RenderViewContextMenu::NotifyURLOpened(
+ const GURL& url,
+ content::WebContents* new_contents) {
+ RetargetingDetails details;
+ details.source_web_contents = source_web_contents_;
+ details.source_render_frame_id = GetRenderFrameHost()->GetRoutingID();
+ details.target_url = url;
+ details.target_web_contents = new_contents;
+ details.not_yet_in_tabstrip = false;
- if (!command_executed_) {
- FOR_EACH_OBSERVER(RenderViewContextMenuObserver,
- observers_,
- OnMenuCancel());
- }
+ content::NotificationService::current()->Notify(
+ chrome::NOTIFICATION_RETARGETING,
+ content::Source<Profile>(GetProfile()),
+ content::Details<RetargetingDetails>(&details));
}
bool RenderViewContextMenu::IsDevCommandEnabled(int id) const {
@@ -1982,42 +1743,12 @@ base::string16 RenderViewContextMenu::PrintableSelectionText() {
// Controller functions --------------------------------------------------------
-void RenderViewContextMenu::OpenURL(
- const GURL& url, const GURL& referring_url,
- WindowOpenDisposition disposition,
- content::PageTransition transition) {
- content::Referrer referrer = content::Referrer::SanitizeForRequest(
- url,
- content::Referrer(referring_url.GetAsReferrer(),
- params_.referrer_policy));
-
- if (params_.link_url == url && disposition != OFF_THE_RECORD)
- params_.custom_context.link_followed = url;
-
- WebContents* new_contents = source_web_contents_->OpenURL(OpenURLParams(
- url, referrer, disposition, transition, false));
- if (!new_contents)
- return;
-
- RetargetingDetails details;
- details.source_web_contents = source_web_contents_;
- details.source_render_frame_id = render_frame_id_;
- details.target_url = url;
- details.target_web_contents = new_contents;
- details.not_yet_in_tabstrip = false;
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_RETARGETING,
- content::Source<Profile>(GetProfile()),
- content::Details<RetargetingDetails>(&details));
-}
-
void RenderViewContextMenu::CopyImageAt(int x, int y) {
source_web_contents_->GetRenderViewHost()->CopyImageAt(x, y);
}
void RenderViewContextMenu::GetImageThumbnailForSearch() {
- RenderFrameHost* render_frame_host =
- RenderFrameHost::FromID(render_process_id_, render_frame_id_);
+ RenderFrameHost* render_frame_host = GetRenderFrameHost();
if (!render_frame_host)
return;
render_frame_host->Send(new ChromeViewMsg_RequestThumbnailForContextNode(
@@ -2029,8 +1760,7 @@ void RenderViewContextMenu::GetImageThumbnailForSearch() {
void RenderViewContextMenu::Inspect(int x, int y) {
content::RecordAction(UserMetricsAction("DevTools_InspectElement"));
- RenderFrameHost* render_frame_host =
- RenderFrameHost::FromID(render_process_id_, render_frame_id_);
+ RenderFrameHost* render_frame_host = GetRenderFrameHost();
if (!render_frame_host)
return;
DevToolsWindow::InspectElement(render_frame_host->GetRenderViewHost(), x, y);
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.h b/chrome/browser/renderer_context_menu/render_view_context_menu.h
index 5b5932e..e234867 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.h
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.h
@@ -15,6 +15,7 @@
#include "chrome/browser/extensions/context_menu_matcher.h"
#include "chrome/browser/extensions/menu_manager.h"
#include "components/renderer_context_menu/context_menu_content_type.h"
+#include "components/renderer_context_menu/render_view_context_menu_base.h"
#include "components/renderer_context_menu/render_view_context_menu_observer.h"
#include "components/renderer_context_menu/render_view_context_menu_proxy.h"
#include "content/public/common/context_menu_params.h"
@@ -46,99 +47,20 @@ struct WebMediaPlayerAction;
struct WebPluginAction;
}
-class RenderViewContextMenu : public ui::SimpleMenuModel::Delegate,
- public RenderViewContextMenuProxy {
+class RenderViewContextMenu : public RenderViewContextMenuBase {
public:
- // A delegate interface to communicate with the toolkit used by
- // the embedder.
- class ToolkitDelegate {
- public:
- virtual ~ToolkitDelegate() {}
- // Initialize the toolkit's menu.
- virtual void Init(ui::SimpleMenuModel* menu_model) = 0;
-
- virtual void Cancel() = 0;
-
- // Updates the actual menu items controlled by the toolkit.
- virtual void UpdateMenuItem(int command_id,
- bool enabled,
- bool hidden,
- const base::string16& title) = 0;
- };
-
- static const size_t kMaxSelectionTextLength;
-
- // Convert a command ID so that it fits within the range for
- // content context menu.
- static int ConvertToContentCustomCommandId(int id);
-
- // True if the given id is the one generated for content context menu.
- static bool IsContentCustomCommandId(int id);
-
RenderViewContextMenu(content::RenderFrameHost* render_frame_host,
const content::ContextMenuParams& params);
virtual ~RenderViewContextMenu();
- // Initializes the context menu.
- void Init();
-
- // Programmatically closes the context menu.
- void Cancel();
-
- const ui::SimpleMenuModel& menu_model() const { return menu_model_; }
- const content::ContextMenuParams& params() const { return params_; }
-
- // SimpleMenuModel::Delegate implementation.
+ // SimpleMenuModel::Delegate:
virtual bool IsCommandIdChecked(int command_id) const OVERRIDE;
virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE;
virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE;
- virtual void MenuWillShow(ui::SimpleMenuModel* source) OVERRIDE;
- virtual void MenuClosed(ui::SimpleMenuModel* source) OVERRIDE;
-
- // RenderViewContextMenuProxy implementation.
- virtual void AddMenuItem(int command_id,
- const base::string16& title) OVERRIDE;
- virtual void AddCheckItem(int command_id,
- const base::string16& title) OVERRIDE;
- virtual void AddSeparator() OVERRIDE;
- virtual void AddSubMenu(int command_id,
- const base::string16& label,
- ui::MenuModel* model) OVERRIDE;
- virtual void UpdateMenuItem(int command_id,
- bool enabled,
- bool hidden,
- const base::string16& title) OVERRIDE;
- virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE;
- virtual content::WebContents* GetWebContents() const OVERRIDE;
- virtual content::BrowserContext* GetBrowserContext() const OVERRIDE;
protected:
- void set_toolkit_delegate(scoped_ptr<ToolkitDelegate> delegate) {
- toolkit_delegate_ = delegate.Pass();
- }
-
- ToolkitDelegate* toolkit_delegate() {
- return toolkit_delegate_.get();
- }
-
- void InitMenu();
Profile* GetProfile();
-
- // Platform specific functions.
- virtual bool GetAcceleratorForCommandId(
- int command_id,
- ui::Accelerator* accelerator) = 0;
- virtual void AppendPlatformEditableItems();
-
- content::ContextMenuParams params_;
- content::WebContents* source_web_contents_;
- // The RenderFrameHost's IDs.
- int render_process_id_;
- int render_frame_id_;
- content::BrowserContext* browser_context_;
-
- ui::SimpleMenuModel menu_model_;
extensions::ContextMenuMatcher extension_items_;
private:
@@ -154,9 +76,19 @@ class RenderViewContextMenu : public ui::SimpleMenuModel::Delegate,
static bool MenuItemMatchesParams(const content::ContextMenuParams& params,
const extensions::MenuItem* item);
+ // RenderViewContextMenuBase:
+ virtual void InitMenu() OVERRIDE;
+ virtual void RecordShownItem(int id) OVERRIDE;
+ virtual void RecordUsedItem(int id) OVERRIDE;
+#if defined(ENABLE_PLUGINS)
+ virtual void HandleAuthorizeAllPlugins() OVERRIDE;
+#endif
+ virtual void NotifyMenuShown() OVERRIDE;
+ virtual void NotifyURLOpened(const GURL& url,
+ content::WebContents* new_contents) OVERRIDE;
+
// Gets the extension (if any) associated with the WebContents that we're in.
const extensions::Extension* GetExtension() const;
- bool AppendCustomItems();
void AppendDeveloperItems();
void AppendDevtoolsForUnpackedExtensions();
@@ -181,11 +113,6 @@ class RenderViewContextMenu : public ui::SimpleMenuModel::Delegate,
void AppendSpellcheckOptionsSubMenu();
void AppendProtocolHandlerSubMenu();
- // Opens the specified URL string in a new tab.
- void OpenURL(const GURL& url, const GURL& referrer,
- WindowOpenDisposition disposition,
- content::PageTransition transition);
-
// Copy to the clipboard an image located at a point in the RenderView
void CopyImageAt(int x, int y);
@@ -231,17 +158,6 @@ class RenderViewContextMenu : public ui::SimpleMenuModel::Delegate,
scoped_ptr<PrintPreviewContextMenuObserver> print_preview_menu_observer_;
#endif
- // Our observers.
- mutable ObserverList<RenderViewContextMenuObserver> observers_;
-
- // Whether a command has been executed. Used to track whether menu observers
- // should be notified of menu closing without execution.
- bool command_executed_;
-
- scoped_ptr<ContextMenuContentType> content_type_;
-
- scoped_ptr<ToolkitDelegate> toolkit_delegate_;
-
DISALLOW_COPY_AND_ASSIGN(RenderViewContextMenu);
};
diff --git a/components/components.gyp b/components/components.gyp
index 65e7ecd..bd3a0d1 100644
--- a/components/components.gyp
+++ b/components/components.gyp
@@ -44,7 +44,6 @@
'pref_registry.gypi',
'query_parser.gypi',
'rappor.gypi',
- 'renderer_context_menu.gypi',
'search.gypi',
'search_provider_logos.gypi',
'signin.gypi',
@@ -103,6 +102,7 @@
'includes': [
'autocomplete.gypi',
'gcm_driver.gypi',
+ 'renderer_context_menu.gypi',
'search_engines.gypi',
'sync_driver.gypi',
'invalidation.gypi',
diff --git a/components/renderer_context_menu.gypi b/components/renderer_context_menu.gypi
index 2ca2715..90ad5bb 100644
--- a/components/renderer_context_menu.gypi
+++ b/components/renderer_context_menu.gypi
@@ -9,6 +9,8 @@
'dependencies': [
'../base/base.gyp:base',
'../content/content.gyp:content_browser',
+ '../components/components.gyp:search_engines',
+ '../components/components.gyp:component_metrics_proto',
],
'include_dirs': [
'..',
@@ -18,6 +20,8 @@
'renderer_context_menu/context_menu_content_type.h',
'renderer_context_menu/context_menu_delegate.cc',
'renderer_context_menu/context_menu_delegate.h',
+ 'renderer_context_menu/render_view_context_menu_base.cc',
+ 'renderer_context_menu/render_view_context_menu_base.h',
'renderer_context_menu/render_view_context_menu_observer.cc',
'renderer_context_menu/render_view_context_menu_observer.h',
'renderer_context_menu/render_view_context_menu_proxy.h',
diff --git a/components/renderer_context_menu/render_view_context_menu_base.cc b/components/renderer_context_menu/render_view_context_menu_base.cc
new file mode 100644
index 0000000..3d0f89a
--- /dev/null
+++ b/components/renderer_context_menu/render_view_context_menu_base.cc
@@ -0,0 +1,387 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/renderer_context_menu/render_view_context_menu_base.h"
+
+#include <algorithm>
+#include <utility>
+
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/menu_item.h"
+#include "extensions/browser/extension_host.h"
+#include "extensions/browser/extension_system.h"
+#include "extensions/browser/view_type_utils.h"
+#include "extensions/common/extension.h"
+#include "third_party/WebKit/public/web/WebContextMenuData.h"
+
+using blink::WebContextMenuData;
+using blink::WebString;
+using blink::WebURL;
+using content::BrowserContext;
+using content::OpenURLParams;
+using content::RenderFrameHost;
+using content::RenderViewHost;
+using content::WebContents;
+
+namespace {
+
+// The (inclusive) range of command IDs reserved for content's custom menus.
+int content_context_custom_first = -1;
+int content_context_custom_last = -1;
+
+bool IsCustomItemEnabledInternal(const std::vector<content::MenuItem>& items,
+ int id) {
+ DCHECK(RenderViewContextMenuBase::IsContentCustomCommandId(id));
+ for (size_t i = 0; i < items.size(); ++i) {
+ int action_id = RenderViewContextMenuBase::ConvertToContentCustomCommandId(
+ items[i].action);
+ if (action_id == id)
+ return items[i].enabled;
+ if (items[i].type == content::MenuItem::SUBMENU) {
+ if (IsCustomItemEnabledInternal(items[i].submenu, id))
+ return true;
+ }
+ }
+ return false;
+}
+
+bool IsCustomItemCheckedInternal(const std::vector<content::MenuItem>& items,
+ int id) {
+ DCHECK(RenderViewContextMenuBase::IsContentCustomCommandId(id));
+ for (size_t i = 0; i < items.size(); ++i) {
+ int action_id = RenderViewContextMenuBase::ConvertToContentCustomCommandId(
+ items[i].action);
+ if (action_id == id)
+ return items[i].checked;
+ if (items[i].type == content::MenuItem::SUBMENU) {
+ if (IsCustomItemCheckedInternal(items[i].submenu, id))
+ return true;
+ }
+ }
+ return false;
+}
+
+const size_t kMaxCustomMenuDepth = 5;
+const size_t kMaxCustomMenuTotalItems = 1000;
+
+void AddCustomItemsToMenu(const std::vector<content::MenuItem>& items,
+ size_t depth,
+ size_t* total_items,
+ ui::SimpleMenuModel::Delegate* delegate,
+ ui::SimpleMenuModel* menu_model) {
+ if (depth > kMaxCustomMenuDepth) {
+ LOG(ERROR) << "Custom menu too deeply nested.";
+ return;
+ }
+ for (size_t i = 0; i < items.size(); ++i) {
+ int command_id = RenderViewContextMenuBase::ConvertToContentCustomCommandId(
+ items[i].action);
+ if (!RenderViewContextMenuBase::IsContentCustomCommandId(command_id)) {
+ LOG(ERROR) << "Custom menu action value out of range.";
+ return;
+ }
+ if (*total_items >= kMaxCustomMenuTotalItems) {
+ LOG(ERROR) << "Custom menu too large (too many items).";
+ return;
+ }
+ (*total_items)++;
+ switch (items[i].type) {
+ case content::MenuItem::OPTION:
+ menu_model->AddItem(
+ RenderViewContextMenuBase::ConvertToContentCustomCommandId(
+ items[i].action),
+ items[i].label);
+ break;
+ case content::MenuItem::CHECKABLE_OPTION:
+ menu_model->AddCheckItem(
+ RenderViewContextMenuBase::ConvertToContentCustomCommandId(
+ items[i].action),
+ items[i].label);
+ break;
+ case content::MenuItem::GROUP:
+ // TODO(viettrungluu): I don't know what this is supposed to do.
+ NOTREACHED();
+ break;
+ case content::MenuItem::SEPARATOR:
+ menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
+ break;
+ case content::MenuItem::SUBMENU: {
+ ui::SimpleMenuModel* submenu = new ui::SimpleMenuModel(delegate);
+ AddCustomItemsToMenu(items[i].submenu, depth + 1, total_items, delegate,
+ submenu);
+ menu_model->AddSubMenu(
+ RenderViewContextMenuBase::ConvertToContentCustomCommandId(
+ items[i].action),
+ items[i].label,
+ submenu);
+ break;
+ }
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+}
+
+} // namespace
+
+// static
+void RenderViewContextMenuBase::SetContentCustomCommandIdRange(
+ int first, int last) {
+ // The range is inclusive.
+ content_context_custom_first = first;
+ content_context_custom_last = last;
+}
+
+// static
+const size_t RenderViewContextMenuBase::kMaxSelectionTextLength = 50;
+
+// static
+int RenderViewContextMenuBase::ConvertToContentCustomCommandId(int id) {
+ return content_context_custom_first + id;
+}
+
+// static
+bool RenderViewContextMenuBase::IsContentCustomCommandId(int id) {
+ return id >= content_context_custom_first &&
+ id <= content_context_custom_last;
+}
+
+RenderViewContextMenuBase::RenderViewContextMenuBase(
+ content::RenderFrameHost* render_frame_host,
+ const content::ContextMenuParams& params)
+ : params_(params),
+ source_web_contents_(WebContents::FromRenderFrameHost(render_frame_host)),
+ browser_context_(source_web_contents_->GetBrowserContext()),
+ menu_model_(this),
+ command_executed_(false),
+ render_process_id_(render_frame_host->GetProcess()->GetID()),
+ render_frame_id_(render_frame_host->GetRoutingID()) {
+}
+
+RenderViewContextMenuBase::~RenderViewContextMenuBase() {
+}
+
+// Menu construction functions -------------------------------------------------
+
+void RenderViewContextMenuBase::Init() {
+ // Command id range must have been already initializerd.
+ DCHECK_NE(-1, content_context_custom_first);
+ DCHECK_NE(-1, content_context_custom_last);
+
+ InitMenu();
+ if (toolkit_delegate_)
+ toolkit_delegate_->Init(&menu_model_);
+}
+
+void RenderViewContextMenuBase::Cancel() {
+ if (toolkit_delegate_)
+ toolkit_delegate_->Cancel();
+}
+
+void RenderViewContextMenuBase::InitMenu() {
+ if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_CUSTOM)) {
+ AppendCustomItems();
+
+ const bool has_selection = !params_.selection_text.empty();
+ if (has_selection) {
+ // We will add more items if there's a selection, so add a separator.
+ // TODO(lazyboy): Clean up separator logic.
+ menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
+ }
+ }
+}
+
+void RenderViewContextMenuBase::AddMenuItem(int command_id,
+ const base::string16& title) {
+ menu_model_.AddItem(command_id, title);
+}
+
+void RenderViewContextMenuBase::AddCheckItem(int command_id,
+ const base::string16& title) {
+ menu_model_.AddCheckItem(command_id, title);
+}
+
+void RenderViewContextMenuBase::AddSeparator() {
+ menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
+}
+
+void RenderViewContextMenuBase::AddSubMenu(int command_id,
+ const base::string16& label,
+ ui::MenuModel* model) {
+ menu_model_.AddSubMenu(command_id, label, model);
+}
+
+void RenderViewContextMenuBase::UpdateMenuItem(int command_id,
+ bool enabled,
+ bool hidden,
+ const base::string16& label) {
+ if (toolkit_delegate_) {
+ toolkit_delegate_->UpdateMenuItem(command_id,
+ enabled,
+ hidden,
+ label);
+ }
+}
+
+RenderViewHost* RenderViewContextMenuBase::GetRenderViewHost() const {
+ return source_web_contents_->GetRenderViewHost();
+}
+
+WebContents* RenderViewContextMenuBase::GetWebContents() const {
+ return source_web_contents_;
+}
+
+BrowserContext* RenderViewContextMenuBase::GetBrowserContext() const {
+ return browser_context_;
+}
+
+bool RenderViewContextMenuBase::AppendCustomItems() {
+ size_t total_items = 0;
+ AddCustomItemsToMenu(params_.custom_items, 0, &total_items, this,
+ &menu_model_);
+ return total_items > 0;
+}
+
+// Menu delegate functions -----------------------------------------------------
+
+bool RenderViewContextMenuBase::IsCommandIdEnabled(int id) const {
+ // If this command is is added by one of our observers, we dispatch
+ // it to the observer.
+ ObserverListBase<RenderViewContextMenuObserver>::Iterator it(observers_);
+ RenderViewContextMenuObserver* observer;
+ while ((observer = it.GetNext()) != NULL) {
+ if (observer->IsCommandIdSupported(id))
+ return observer->IsCommandIdEnabled(id);
+ }
+
+ // Custom items.
+ if (IsContentCustomCommandId(id))
+ return IsCustomItemEnabled(id);
+
+ return false;
+}
+
+bool RenderViewContextMenuBase::IsCommandIdChecked(int id) const {
+ // If this command is is added by one of our observers, we dispatch it to the
+ // observer.
+ ObserverListBase<RenderViewContextMenuObserver>::Iterator it(observers_);
+ RenderViewContextMenuObserver* observer;
+ while ((observer = it.GetNext()) != NULL) {
+ if (observer->IsCommandIdSupported(id))
+ return observer->IsCommandIdChecked(id);
+ }
+
+ // Custom items.
+ if (IsContentCustomCommandId(id))
+ return IsCustomItemChecked(id);
+
+ return false;
+}
+
+void RenderViewContextMenuBase::ExecuteCommand(int id, int event_flags) {
+ command_executed_ = true;
+ RecordUsedItem(id);
+
+ // If this command is is added by one of our observers, we dispatch
+ // it to the observer.
+ ObserverListBase<RenderViewContextMenuObserver>::Iterator it(observers_);
+ RenderViewContextMenuObserver* observer;
+ while ((observer = it.GetNext()) != NULL) {
+ if (observer->IsCommandIdSupported(id))
+ return observer->ExecuteCommand(id);
+ }
+
+ // Process custom actions range.
+ if (IsContentCustomCommandId(id)) {
+ unsigned action = id - content_context_custom_first;
+ const content::CustomContextMenuContext& context = params_.custom_context;
+#if defined(ENABLE_PLUGINS)
+ if (context.request_id && !context.is_pepper_menu)
+ HandleAuthorizeAllPlugins();
+#endif
+ source_web_contents_->ExecuteCustomContextMenuCommand(action, context);
+ return;
+ }
+ command_executed_ = false;
+}
+
+void RenderViewContextMenuBase::MenuWillShow(ui::SimpleMenuModel* source) {
+ for (int i = 0; i < source->GetItemCount(); ++i) {
+ if (source->IsVisibleAt(i) &&
+ source->GetTypeAt(i) != ui::MenuModel::TYPE_SEPARATOR) {
+ RecordShownItem(source->GetCommandIdAt(i));
+ }
+ }
+
+ // Ignore notifications from submenus.
+ if (source != &menu_model_)
+ return;
+
+ content::RenderWidgetHostView* view =
+ source_web_contents_->GetRenderWidgetHostView();
+ if (view)
+ view->SetShowingContextMenu(true);
+
+ NotifyMenuShown();
+}
+
+void RenderViewContextMenuBase::MenuClosed(ui::SimpleMenuModel* source) {
+ // Ignore notifications from submenus.
+ if (source != &menu_model_)
+ return;
+
+ content::RenderWidgetHostView* view =
+ source_web_contents_->GetRenderWidgetHostView();
+ if (view)
+ view->SetShowingContextMenu(false);
+ source_web_contents_->NotifyContextMenuClosed(params_.custom_context);
+
+ if (!command_executed_) {
+ FOR_EACH_OBSERVER(RenderViewContextMenuObserver,
+ observers_,
+ OnMenuCancel());
+ }
+}
+
+RenderFrameHost* RenderViewContextMenuBase::GetRenderFrameHost() {
+ return RenderFrameHost::FromID(render_process_id_, render_frame_id_);
+}
+
+// Controller functions --------------------------------------------------------
+
+void RenderViewContextMenuBase::OpenURL(
+ const GURL& url, const GURL& referring_url,
+ WindowOpenDisposition disposition,
+ content::PageTransition transition) {
+ content::Referrer referrer = content::Referrer::SanitizeForRequest(
+ url,
+ content::Referrer(referring_url.GetAsReferrer(),
+ params_.referrer_policy));
+
+ if (params_.link_url == url && disposition != OFF_THE_RECORD)
+ params_.custom_context.link_followed = url;
+
+ WebContents* new_contents = source_web_contents_->OpenURL(OpenURLParams(
+ url, referrer, disposition, transition, false));
+ if (!new_contents)
+ return;
+
+ NotifyURLOpened(url, new_contents);
+}
+
+bool RenderViewContextMenuBase::IsCustomItemChecked(int id) const {
+ return IsCustomItemCheckedInternal(params_.custom_items, id);
+}
+
+bool RenderViewContextMenuBase::IsCustomItemEnabled(int id) const {
+ return IsCustomItemEnabledInternal(params_.custom_items, id);
+}
+
diff --git a/components/renderer_context_menu/render_view_context_menu_base.h b/components/renderer_context_menu/render_view_context_menu_base.h
new file mode 100644
index 0000000..9d4ac63
--- /dev/null
+++ b/components/renderer_context_menu/render_view_context_menu_base.h
@@ -0,0 +1,186 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_RENDERER_CONTEXT_MENU_RENDER_VIEW_CONTEXT_MENU_BASE_H_
+#define COMPONENTS_RENDERER_CONTEXT_MENU_RENDER_VIEW_CONTEXT_MENU_BASE_H_
+
+#include <map>
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/observer_list.h"
+#include "base/strings/string16.h"
+#include "components/renderer_context_menu/context_menu_content_type.h"
+#include "components/renderer_context_menu/render_view_context_menu_observer.h"
+#include "components/renderer_context_menu/render_view_context_menu_proxy.h"
+#include "content/public/common/context_menu_params.h"
+#include "content/public/common/page_transition_types.h"
+#include "ui/base/models/simple_menu_model.h"
+#include "ui/base/window_open_disposition.h"
+
+namespace content {
+class RenderFrameHost;
+class WebContents;
+}
+
+namespace gfx {
+class Point;
+}
+
+namespace blink {
+struct WebMediaPlayerAction;
+struct WebPluginAction;
+}
+
+class RenderViewContextMenuBase : public ui::SimpleMenuModel::Delegate,
+ public RenderViewContextMenuProxy {
+ public:
+ // A delegate interface to communicate with the toolkit used by
+ // the embedder.
+ class ToolkitDelegate {
+ public:
+ virtual ~ToolkitDelegate() {}
+ // Initialize the toolkit's menu.
+ virtual void Init(ui::SimpleMenuModel* menu_model) = 0;
+
+ virtual void Cancel() = 0;
+
+ // Updates the actual menu items controlled by the toolkit.
+ virtual void UpdateMenuItem(int command_id,
+ bool enabled,
+ bool hidden,
+ const base::string16& title) = 0;
+ };
+
+ static const size_t kMaxSelectionTextLength;
+
+ static void SetContentCustomCommandIdRange(int first, int last);
+
+ // Convert a command ID so that it fits within the range for
+ // content context menu.
+ static int ConvertToContentCustomCommandId(int id);
+
+ // True if the given id is the one generated for content context menu.
+ static bool IsContentCustomCommandId(int id);
+
+ RenderViewContextMenuBase(content::RenderFrameHost* render_frame_host,
+ const content::ContextMenuParams& params);
+
+ virtual ~RenderViewContextMenuBase();
+
+ // Initializes the context menu.
+ void Init();
+
+ // Programmatically closes the context menu.
+ void Cancel();
+
+ const ui::SimpleMenuModel& menu_model() const { return menu_model_; }
+ const content::ContextMenuParams& params() const { return params_; }
+
+ // SimpleMenuModel::Delegate implementation.
+ virtual bool IsCommandIdChecked(int command_id) const OVERRIDE;
+ virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE;
+ virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE;
+ virtual void MenuWillShow(ui::SimpleMenuModel* source) OVERRIDE;
+ virtual void MenuClosed(ui::SimpleMenuModel* source) OVERRIDE;
+
+ // RenderViewContextMenuProxy implementation.
+ virtual void AddMenuItem(int command_id,
+ const base::string16& title) OVERRIDE;
+ virtual void AddCheckItem(int command_id,
+ const base::string16& title) OVERRIDE;
+ virtual void AddSeparator() OVERRIDE;
+ virtual void AddSubMenu(int command_id,
+ const base::string16& label,
+ ui::MenuModel* model) OVERRIDE;
+ virtual void UpdateMenuItem(int command_id,
+ bool enabled,
+ bool hidden,
+ const base::string16& title) OVERRIDE;
+ virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE;
+ virtual content::WebContents* GetWebContents() const OVERRIDE;
+ virtual content::BrowserContext* GetBrowserContext() const OVERRIDE;
+
+ protected:
+ friend class RenderViewContextMenuTest;
+ friend class RenderViewContextMenuPrefsTest;
+
+ void set_content_type(ContextMenuContentType* content_type) {
+ content_type_.reset(content_type);
+ }
+
+ void set_toolkit_delegate(scoped_ptr<ToolkitDelegate> delegate) {
+ toolkit_delegate_ = delegate.Pass();
+ }
+
+ ToolkitDelegate* toolkit_delegate() {
+ return toolkit_delegate_.get();
+ }
+
+ // TODO(oshima): Make these methods delegate.
+
+ // Menu Construction.
+ virtual void InitMenu();
+
+ // Increments histogram value for used items specified by |id|.
+ virtual void RecordUsedItem(int id) = 0;
+
+ // Increments histogram value for visible context menu item specified by |id|.
+ virtual void RecordShownItem(int id) = 0;
+
+#if defined(ENABLE_PLUGINS)
+ virtual void HandleAuthorizeAllPlugins() = 0;
+#endif
+
+ // Returns the accelerator for given |command_id|.
+ virtual bool GetAcceleratorForCommandId(
+ int command_id,
+ ui::Accelerator* accelerator) = 0;
+
+ // Subclasses should send notification.
+ virtual void NotifyMenuShown() = 0;
+ virtual void NotifyURLOpened(const GURL& url,
+ content::WebContents* new_contents) = 0;
+
+ // TODO(oshima): Remove this.
+ virtual void AppendPlatformEditableItems() {}
+
+ content::RenderFrameHost* GetRenderFrameHost();
+
+ bool IsCustomItemChecked(int id) const;
+ bool IsCustomItemEnabled(int id) const;
+
+ // Opens the specified URL string in a new tab.
+ void OpenURL(const GURL& url, const GURL& referrer,
+ WindowOpenDisposition disposition,
+ content::PageTransition transition);
+
+ content::ContextMenuParams params_;
+ content::WebContents* source_web_contents_;
+ content::BrowserContext* browser_context_;
+
+ ui::SimpleMenuModel menu_model_;
+
+ // Our observers.
+ mutable ObserverList<RenderViewContextMenuObserver> observers_;
+
+ // Whether a command has been executed. Used to track whether menu observers
+ // should be notified of menu closing without execution.
+ bool command_executed_;
+
+ scoped_ptr<ContextMenuContentType> content_type_;
+
+ private:
+ bool AppendCustomItems();
+
+ // The RenderFrameHost's IDs.
+ int render_process_id_;
+ int render_frame_id_;
+
+ scoped_ptr<ToolkitDelegate> toolkit_delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderViewContextMenuBase);
+};
+
+#endif // COMPONENTS_RENDERER_CONTEXT_MENU_RENDER_VIEW_CONTEXT_MENU_BASE_H_