Commit cf8c4908 authored by oshima@chromium.org's avatar oshima@chromium.org

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
parent 0f9e5b14
...@@ -142,11 +142,6 @@ const int kImageSearchThumbnailMinSize = 300 * 300; ...@@ -142,11 +142,6 @@ const int kImageSearchThumbnailMinSize = 300 * 300;
const int kImageSearchThumbnailMaxWidth = 600; const int kImageSearchThumbnailMaxWidth = 600;
const int kImageSearchThumbnailMaxHeight = 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 // Maps UMA enumeration to IDC. IDC could be changed so we can't use
// just them and |UMA_HISTOGRAM_CUSTOM_ENUMERATION|. // just them and |UMA_HISTOGRAM_CUSTOM_ENUMERATION|.
// Never change mapping or reuse |enum_id|. Always push back new items. // Never change mapping or reuse |enum_id|. Always push back new items.
...@@ -262,32 +257,6 @@ int FindUMAEnumValueForCommand(int id) { ...@@ -262,32 +257,6 @@ int FindUMAEnumValueForCommand(int id) {
return -1; 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, // Usually a new tab is expected where this function is used,
// however users should be able to open a tab in background // however users should be able to open a tab in background
// or in a new window. // or in a new window.
...@@ -298,98 +267,6 @@ WindowOpenDisposition ForceNewTabDispositionFromEventFlags( ...@@ -298,98 +267,6 @@ WindowOpenDisposition ForceNewTabDispositionFromEventFlags(
return disposition == CURRENT_TAB ? NEW_FOREGROUND_TAB : disposition; 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 "&&". // Helper function to escape "&" as "&&".
void EscapeAmpersands(base::string16* text) { void EscapeAmpersands(base::string16* text) {
base::ReplaceChars(*text, base::ASCIIToUTF16("&"), base::ASCIIToUTF16("&&"), base::ReplaceChars(*text, base::ASCIIToUTF16("&"), base::ASCIIToUTF16("&&"),
...@@ -401,21 +278,9 @@ PrefService* GetPrefs(content::BrowserContext* context) { ...@@ -401,21 +278,9 @@ PrefService* GetPrefs(content::BrowserContext* context) {
return user_prefs::UserPrefs::Get(context); return user_prefs::UserPrefs::Get(context);
} }
} // namespace bool custom_id_ranges_initialized = false;
// static
const size_t RenderViewContextMenu::kMaxSelectionTextLength = 50;
// static
int RenderViewContextMenu::ConvertToContentCustomCommandId(int id) {
return content_context_custom_first + id;
}
// static } // namespace
bool RenderViewContextMenu::IsContentCustomCommandId(int id) {
return id >= content_context_custom_first &&
id <= content_context_custom_last;
}
// static // static
bool RenderViewContextMenu::IsDevToolsURL(const GURL& url) { bool RenderViewContextMenu::IsDevToolsURL(const GURL& url) {
...@@ -434,22 +299,21 @@ static const int kSpellcheckRadioGroup = 1; ...@@ -434,22 +299,21 @@ static const int kSpellcheckRadioGroup = 1;
RenderViewContextMenu::RenderViewContextMenu( RenderViewContextMenu::RenderViewContextMenu(
content::RenderFrameHost* render_frame_host, content::RenderFrameHost* render_frame_host,
const content::ContextMenuParams& params) const content::ContextMenuParams& params)
: params_(params), : RenderViewContextMenuBase(render_frame_host, 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),
extension_items_(browser_context_, extension_items_(browser_context_,
this, this,
&menu_model_, &menu_model_,
base::Bind(MenuItemMatchesParams, params_)), base::Bind(MenuItemMatchesParams, params_)),
protocol_handler_submenu_model_(this), protocol_handler_submenu_model_(this),
protocol_handler_registry_( protocol_handler_registry_(
ProtocolHandlerRegistryFactory::GetForBrowserContext(GetProfile())), ProtocolHandlerRegistryFactory::GetForBrowserContext(GetProfile())) {
command_executed_(false) { if (!custom_id_ranges_initialized) {
content_type_.reset(ContextMenuContentTypeFactory::Create( custom_id_ranges_initialized = true;
source_web_contents_, params)); SetContentCustomCommandIdRange(IDC_CONTENT_CONTEXT_CUSTOM_FIRST,
IDC_CONTENT_CONTEXT_CUSTOM_LAST);
}
set_content_type(ContextMenuContentTypeFactory::Create(
source_web_contents_, params));
} }
RenderViewContextMenu::~RenderViewContextMenu() { RenderViewContextMenu::~RenderViewContextMenu() {
...@@ -457,17 +321,6 @@ RenderViewContextMenu::~RenderViewContextMenu() { ...@@ -457,17 +321,6 @@ RenderViewContextMenu::~RenderViewContextMenu() {
// Menu construction functions ------------------------------------------------- // 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, static bool ExtensionPatternMatch(const extensions::URLPatternSet& patterns,
const GURL& url) { const GURL& url) {
// No patterns means no restriction, so that implicitly matches. // No patterns means no restriction, so that implicitly matches.
...@@ -615,16 +468,7 @@ void RenderViewContextMenu::AppendCurrentExtensionItems() { ...@@ -615,16 +468,7 @@ void RenderViewContextMenu::AppendCurrentExtensionItems() {
} }
void RenderViewContextMenu::InitMenu() { void RenderViewContextMenu::InitMenu() {
if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_CUSTOM)) { RenderViewContextMenuBase::InitMenu();
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);
}
}
if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_PAGE)) if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_PAGE))
AppendPageItems(); AppendPageItems();
...@@ -725,6 +569,37 @@ Profile* RenderViewContextMenu::GetProfile() { ...@@ -725,6 +569,37 @@ Profile* RenderViewContextMenu::GetProfile() {
return Profile::FromBrowserContext(browser_context_); 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() { void RenderViewContextMenu::AppendPrintPreviewItems() {
#if defined(ENABLE_FULL_PRINTING) #if defined(ENABLE_FULL_PRINTING)
if (!print_preview_menu_observer_.get()) { if (!print_preview_menu_observer_.get()) {
...@@ -747,57 +622,6 @@ const Extension* RenderViewContextMenu::GetExtension() const { ...@@ -747,57 +622,6 @@ const Extension* RenderViewContextMenu::GetExtension() const {
source_web_contents_->GetRenderViewHost()); 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() { void RenderViewContextMenu::AppendDeveloperItems() {
// Show Inspect Element in DevTools itself only in case of the debug // Show Inspect Element in DevTools itself only in case of the debug
// devtools build. // devtools build.
...@@ -1126,20 +950,11 @@ void RenderViewContextMenu::AppendProtocolHandlerSubMenu() { ...@@ -1126,20 +950,11 @@ void RenderViewContextMenu::AppendProtocolHandlerSubMenu() {
&protocol_handler_submenu_model_); &protocol_handler_submenu_model_);
} }
void RenderViewContextMenu::AppendPlatformEditableItems() {
}
// Menu delegate functions ----------------------------------------------------- // Menu delegate functions -----------------------------------------------------
bool RenderViewContextMenu::IsCommandIdEnabled(int id) const { bool RenderViewContextMenu::IsCommandIdEnabled(int id) const {
// If this command is is added by one of our observers, we dispatch it to the if (RenderViewContextMenuBase::IsCommandIdEnabled(id))
// observer. return true;
ObserverListBase<RenderViewContextMenuObserver>::Iterator it(observers_);
RenderViewContextMenuObserver* observer;
while ((observer = it.GetNext()) != NULL) {
if (observer->IsCommandIdSupported(id))
return observer->IsCommandIdEnabled(id);
}
CoreTabHelper* core_tab_helper = CoreTabHelper* core_tab_helper =
CoreTabHelper::FromWebContents(source_web_contents_); CoreTabHelper::FromWebContents(source_web_contents_);
...@@ -1162,10 +977,6 @@ bool RenderViewContextMenu::IsCommandIdEnabled(int id) const { ...@@ -1162,10 +977,6 @@ bool RenderViewContextMenu::IsCommandIdEnabled(int id) const {
return prefs->GetBoolean(prefs::kEnableContinuousSpellcheck); return prefs->GetBoolean(prefs::kEnableContinuousSpellcheck);
} }
// Custom items.
if (IsContentCustomCommandId(id))
return IsCustomItemEnabled(params_.custom_items, id);
// Extension items. // Extension items.
if (ContextMenuMatcher::IsExtensionsCustomCommandId(id)) if (ContextMenuMatcher::IsExtensionsCustomCommandId(id))
return extension_items_.IsCommandIdEnabled(id); return extension_items_.IsCommandIdEnabled(id);
...@@ -1428,14 +1239,8 @@ bool RenderViewContextMenu::IsCommandIdEnabled(int id) const { ...@@ -1428,14 +1239,8 @@ bool RenderViewContextMenu::IsCommandIdEnabled(int id) const {
} }
bool RenderViewContextMenu::IsCommandIdChecked(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 if (RenderViewContextMenuBase::IsCommandIdChecked(id))
// observer. return true;
ObserverListBase<RenderViewContextMenuObserver>::Iterator it(observers_);
RenderViewContextMenuObserver* observer;
while ((observer = it.GetNext()) != NULL) {
if (observer->IsCommandIdSupported(id))
return observer->IsCommandIdChecked(id);
}
// See if the video is set to looping. // See if the video is set to looping.
if (id == IDC_CONTENT_CONTEXT_LOOP) { if (id == IDC_CONTENT_CONTEXT_LOOP) {
...@@ -1448,10 +1253,6 @@ bool RenderViewContextMenu::IsCommandIdChecked(int id) const { ...@@ -1448,10 +1253,6 @@ bool RenderViewContextMenu::IsCommandIdChecked(int id) const {
WebContextMenuData::MediaControls) != 0; WebContextMenuData::MediaControls) != 0;
} }
// Custom items.
if (IsContentCustomCommandId(id))
return IsCustomItemChecked(params_.custom_items, id);
// Extension items. // Extension items.
if (ContextMenuMatcher::IsExtensionsCustomCommandId(id)) if (ContextMenuMatcher::IsExtensionsCustomCommandId(id))
return extension_items_.IsCommandIdChecked(id); return extension_items_.IsCommandIdChecked(id);
...@@ -1460,34 +1261,12 @@ bool RenderViewContextMenu::IsCommandIdChecked(int id) const { ...@@ -1460,34 +1261,12 @@ bool RenderViewContextMenu::IsCommandIdChecked(int id) const {
} }
void RenderViewContextMenu::ExecuteCommand(int id, int event_flags) { void RenderViewContextMenu::ExecuteCommand(int id, int event_flags) {
RenderViewContextMenuBase::ExecuteCommand(id, event_flags);
if (command_executed_)
return;
command_executed_ = true; 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* render_frame_host = GetRenderFrameHost();
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;
}
// Process extension menu items. // Process extension menu items.
if (ContextMenuMatcher::IsExtensionsCustomCommandId(id)) { if (ContextMenuMatcher::IsExtensionsCustomCommandId(id)) {
...@@ -1915,45 +1694,27 @@ ProtocolHandlerRegistry::ProtocolHandlerList ...@@ -1915,45 +1694,27 @@ ProtocolHandlerRegistry::ProtocolHandlerList
return handlers; return handlers;
} }
void RenderViewContextMenu::MenuWillShow(ui::SimpleMenuModel* source) { void RenderViewContextMenu::NotifyMenuShown() {
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);
content::NotificationService::current()->Notify( content::NotificationService::current()->Notify(
chrome::NOTIFICATION_RENDER_VIEW_CONTEXT_MENU_SHOWN, chrome::NOTIFICATION_RENDER_VIEW_CONTEXT_MENU_SHOWN,
content::Source<RenderViewContextMenu>(this), content::Source<RenderViewContextMenu>(this),
content::NotificationService::NoDetails()); content::NotificationService::NoDetails());
} }
void RenderViewContextMenu::MenuClosed(ui::SimpleMenuModel* source) { void RenderViewContextMenu::NotifyURLOpened(
// Ignore notifications from submenus. const GURL& url,
if (source != &menu_model_) content::WebContents* new_contents) {
return; RetargetingDetails details;
details.source_web_contents = source_web_contents_;
content::RenderWidgetHostView* view = details.source_render_frame_id = GetRenderFrameHost()->GetRoutingID();
source_web_contents_->GetRenderWidgetHostView(); details.target_url = url;
if (view) details.target_web_contents = new_contents;
view->SetShowingContextMenu(false); details.not_yet_in_tabstrip = false;
source_web_contents_->NotifyContextMenuClosed(params_.custom_context);
if (!command_executed_) { content::NotificationService::current()->Notify(
FOR_EACH_OBSERVER(RenderViewContextMenuObserver, chrome::NOTIFICATION_RETARGETING,
observers_, content::Source<Profile>(GetProfile()),
OnMenuCancel()); content::Details<RetargetingDetails>(&details));
}
} }
bool RenderViewContextMenu::IsDevCommandEnabled(int id) const { bool RenderViewContextMenu::IsDevCommandEnabled(int id) const {
...@@ -1982,42 +1743,12 @@ base::string16 RenderViewContextMenu::PrintableSelectionText() { ...@@ -1982,42 +1743,12 @@ base::string16 RenderViewContextMenu::PrintableSelectionText() {
// Controller functions -------------------------------------------------------- // 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) { void RenderViewContextMenu::CopyImageAt(int x, int y) {
source_web_contents_->GetRenderViewHost()->CopyImageAt(x, y); source_web_contents_->GetRenderViewHost()->CopyImageAt(x, y);
} }
void RenderViewContextMenu::GetImageThumbnailForSearch() { void RenderViewContextMenu::GetImageThumbnailForSearch() {
RenderFrameHost* render_frame_host = RenderFrameHost* render_frame_host = GetRenderFrameHost();
RenderFrameHost::FromID(render_process_id_, render_frame_id_);
if (!render_frame_host) if (!render_frame_host)
return; return;
render_frame_host->Send(new ChromeViewMsg_RequestThumbnailForContextNode( render_frame_host->Send(new ChromeViewMsg_RequestThumbnailForContextNode(
...@@ -2029,8 +1760,7 @@ void RenderViewContextMenu::GetImageThumbnailForSearch() { ...@@ -2029,8 +1760,7 @@ void RenderViewContextMenu::GetImageThumbnailForSearch() {
void RenderViewContextMenu::Inspect(int x, int y) { void RenderViewContextMenu::Inspect(int x, int y) {
content::RecordAction(UserMetricsAction("DevTools_InspectElement")); content::RecordAction(UserMetricsAction("DevTools_InspectElement"));
RenderFrameHost* render_frame_host = RenderFrameHost* render_frame_host = GetRenderFrameHost();
RenderFrameHost::FromID(render_process_id_, render_frame_id_);
if (!render_frame_host) if (!render_frame_host)
return; return;
DevToolsWindow::InspectElement(render_frame_host->GetRenderViewHost(), x, y); DevToolsWindow::InspectElement(render_frame_host->GetRenderViewHost(), x, y);
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "chrome/browser/extensions/context_menu_matcher.h" #include "chrome/browser/extensions/context_menu_matcher.h"
#include "chrome/browser/extensions/menu_manager.h" #include "chrome/browser/extensions/menu_manager.h"
#include "components/renderer_context_menu/context_menu_content_type.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_observer.h"
#include "components/renderer_context_menu/render_view_context_menu_proxy.h" #include "components/renderer_context_menu/render_view_context_menu_proxy.h"
#include "content/public/common/context_menu_params.h" #include "content/public/common/context_menu_params.h"
...@@ -46,99 +47,20 @@ struct WebMediaPlayerAction; ...@@ -46,99 +47,20 @@ struct WebMediaPlayerAction;
struct WebPluginAction; struct WebPluginAction;
} }
class RenderViewContextMenu : public ui::SimpleMenuModel::Delegate, class RenderViewContextMenu : public RenderViewContextMenuBase {
public RenderViewContextMenuProxy {
public: 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, RenderViewContextMenu(content::RenderFrameHost* render_frame_host,
const content::ContextMenuParams& params); const content::ContextMenuParams& params);
virtual ~RenderViewContextMenu(); virtual ~RenderViewContextMenu();
// Initializes the context menu. // SimpleMenuModel::Delegate:
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 IsCommandIdChecked(int command_id) const OVERRIDE;
virtual bool IsCommandIdEnabled(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 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: protected:
void set_toolkit_delegate(scoped_ptr<ToolkitDelegate> delegate) {
toolkit_delegate_ = delegate.Pass();
}
ToolkitDelegate* toolkit_delegate() {
return toolkit_delegate_.get();
}
void InitMenu();
Profile* GetProfile(); 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_; extensions::ContextMenuMatcher extension_items_;
private: private:
...@@ -154,9 +76,19 @@ class RenderViewContextMenu : public ui::SimpleMenuModel::Delegate, ...@@ -154,9 +76,19 @@ class RenderViewContextMenu : public ui::SimpleMenuModel::Delegate,
static bool MenuItemMatchesParams(const content::ContextMenuParams& params, static bool MenuItemMatchesParams(const content::ContextMenuParams& params,
const extensions::MenuItem* item); 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. // Gets the extension (if any) associated with the WebContents that we're in.
const extensions::Extension* GetExtension() const; const extensions::Extension* GetExtension() const;
bool AppendCustomItems();
void AppendDeveloperItems(); void AppendDeveloperItems();
void AppendDevtoolsForUnpackedExtensions(); void AppendDevtoolsForUnpackedExtensions();
...@@ -181,11 +113,6 @@ class RenderViewContextMenu : public ui::SimpleMenuModel::Delegate, ...@@ -181,11 +113,6 @@ class RenderViewContextMenu : public ui::SimpleMenuModel::Delegate,
void AppendSpellcheckOptionsSubMenu(); void AppendSpellcheckOptionsSubMenu();
void AppendProtocolHandlerSubMenu(); 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 // Copy to the clipboard an image located at a point in the RenderView
void CopyImageAt(int x, int y); void CopyImageAt(int x, int y);
...@@ -231,17 +158,6 @@ class RenderViewContextMenu : public ui::SimpleMenuModel::Delegate, ...@@ -231,17 +158,6 @@ class RenderViewContextMenu : public ui::SimpleMenuModel::Delegate,
scoped_ptr<PrintPreviewContextMenuObserver> print_preview_menu_observer_; scoped_ptr<PrintPreviewContextMenuObserver> print_preview_menu_observer_;
#endif #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); DISALLOW_COPY_AND_ASSIGN(RenderViewContextMenu);
}; };
......
...@@ -44,7 +44,6 @@ ...@@ -44,7 +44,6 @@
'pref_registry.gypi', 'pref_registry.gypi',
'query_parser.gypi', 'query_parser.gypi',
'rappor.gypi', 'rappor.gypi',
'renderer_context_menu.gypi',
'search.gypi', 'search.gypi',
'search_provider_logos.gypi', 'search_provider_logos.gypi',
'signin.gypi', 'signin.gypi',
...@@ -103,6 +102,7 @@ ...@@ -103,6 +102,7 @@
'includes': [ 'includes': [
'autocomplete.gypi', 'autocomplete.gypi',
'gcm_driver.gypi', 'gcm_driver.gypi',
'renderer_context_menu.gypi',
'search_engines.gypi', 'search_engines.gypi',
'sync_driver.gypi', 'sync_driver.gypi',
'invalidation.gypi', 'invalidation.gypi',
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
'dependencies': [ 'dependencies': [
'../base/base.gyp:base', '../base/base.gyp:base',
'../content/content.gyp:content_browser', '../content/content.gyp:content_browser',
'../components/components.gyp:search_engines',
'../components/components.gyp:component_metrics_proto',
], ],
'include_dirs': [ 'include_dirs': [
'..', '..',
...@@ -18,6 +20,8 @@ ...@@ -18,6 +20,8 @@
'renderer_context_menu/context_menu_content_type.h', 'renderer_context_menu/context_menu_content_type.h',
'renderer_context_menu/context_menu_delegate.cc', 'renderer_context_menu/context_menu_delegate.cc',
'renderer_context_menu/context_menu_delegate.h', '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.cc',
'renderer_context_menu/render_view_context_menu_observer.h', 'renderer_context_menu/render_view_context_menu_observer.h',
'renderer_context_menu/render_view_context_menu_proxy.h', 'renderer_context_menu/render_view_context_menu_proxy.h',
......
// 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);
}
// 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_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment