1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_RENDERER_CONTEXT_MENU_RENDER_VIEW_CONTEXT_MENU_H_ 6 #define CHROME_BROWSER_RENDERER_CONTEXT_MENU_RENDER_VIEW_CONTEXT_MENU_H_ 7 8 #include <map> 9 #include <string> 10 11 #include "base/memory/scoped_ptr.h" 12 #include "base/observer_list.h" 13 #include "base/strings/string16.h" 14 #include "chrome/browser/custom_handlers/protocol_handler_registry.h" 15 #include "chrome/browser/extensions/context_menu_matcher.h" 16 #include "chrome/browser/extensions/menu_manager.h" 17 #include "chrome/browser/renderer_context_menu/context_menu_content_type.h" 18 #include "chrome/browser/renderer_context_menu/render_view_context_menu_observer.h" 19 #include "content/public/common/context_menu_params.h" 20 #include "content/public/common/page_transition_types.h" 21 #include "ui/base/models/simple_menu_model.h" 22 #include "ui/base/window_open_disposition.h" 23 24 class PrintPreviewContextMenuObserver; 25 class Profile; 26 class SpellingMenuObserver; 27 class SpellCheckerSubMenuObserver; 28 29 namespace content { 30 class RenderFrameHost; 31 class RenderViewHost; 32 class WebContents; 33 } 34 35 namespace extensions { 36 class Extension; 37 class MenuItem; 38 } 39 40 namespace gfx { 41 class Point; 42 } 43 44 namespace blink { 45 struct WebMediaPlayerAction; 46 struct WebPluginAction; 47 } 48 49 // An interface that controls a RenderViewContextMenu instance from observers. 50 // This interface is designed mainly for controlling the instance while showing 51 // so we can add a context-menu item that takes long time to create its text, 52 // such as retrieving the item text from a server. The simplest usage is: 53 // 1. Adding an item with temporary text; 54 // 2. Posting a background task that creates the item text, and; 55 // 3. Calling UpdateMenuItem() in the callback function. 56 // The following snippet describes the simple usage that updates a context-menu 57 // item with this interface. 58 // 59 // class MyTask : public net::URLFetcherDelegate { 60 // public: 61 // MyTask(RenderViewContextMenuProxy* proxy, int id) 62 // : proxy_(proxy), 63 // id_(id) { 64 // } 65 // virtual ~MyTask() { 66 // } 67 // virtual void OnURLFetchComplete(const net::URLFetcher* source, 68 // const GURL& url, 69 // const net::URLRequestStatus& status, 70 // int response, 71 // const net::ResponseCookies& cookies, 72 // const std::string& data) { 73 // bool enabled = response == 200; 74 // const char* text = enabled ? "OK" : "ERROR"; 75 // proxy_->UpdateMenuItem(id_, enabled, base::ASCIIToUTF16(text)); 76 // } 77 // void Start(const GURL* url, net::URLRequestContextGetter* context) { 78 // fetcher_.reset(new URLFetcher(url, URLFetcher::GET, this)); 79 // fetcher_->SetRequestContext(context); 80 // content::AssociateURLFetcherWithRenderView( 81 // fetcher_.get(), 82 // proxy_->GetRenderViewHost()->GetSiteInstance()->GetSite(), 83 // proxy_->GetRenderViewHost()->GetProcess()->GetID(), 84 // proxy_->GetRenderViewHost()->GetRoutingID()); 85 // fetcher_->Start(); 86 // } 87 // 88 // private: 89 // URLFetcher fetcher_; 90 // RenderViewContextMenuProxy* proxy_; 91 // int id_; 92 // }; 93 // 94 // void RenderViewContextMenu::AppendEditableItems() { 95 // // Add a menu item with temporary text shown while we create the final 96 // // text. 97 // menu_model_.AddItemWithStringId(IDC_MY_ITEM, IDC_MY_TEXT); 98 // 99 // // Start a task that creates the final text. 100 // my_task_ = new MyTask(this, IDC_MY_ITEM); 101 // my_task_->Start(...); 102 // } 103 // 104 class RenderViewContextMenuProxy { 105 public: 106 // Add a menu item to a context menu. 107 virtual void AddMenuItem(int command_id, const base::string16& title) = 0; 108 virtual void AddCheckItem(int command_id, const base::string16& title) = 0; 109 virtual void AddSeparator() = 0; 110 111 // Add a submenu item to a context menu. 112 virtual void AddSubMenu(int command_id, 113 const base::string16& label, 114 ui::MenuModel* model) = 0; 115 116 // Update the status and text of the specified context-menu item. 117 virtual void UpdateMenuItem(int command_id, 118 bool enabled, 119 bool hidden, 120 const base::string16& title) = 0; 121 122 // Retrieve the given associated objects with a context menu. 123 virtual content::RenderViewHost* GetRenderViewHost() const = 0; 124 virtual content::WebContents* GetWebContents() const = 0; 125 virtual Profile* GetProfile() const = 0; 126 }; 127 128 class RenderViewContextMenu : public ui::SimpleMenuModel::Delegate, 129 public RenderViewContextMenuProxy { 130 public: 131 static const size_t kMaxSelectionTextLength; 132 133 RenderViewContextMenu(content::RenderFrameHost* render_frame_host, 134 const content::ContextMenuParams& params); 135 136 virtual ~RenderViewContextMenu(); 137 138 // Initializes the context menu. 139 void Init(); 140 141 // Programmatically closes the context menu. 142 void Cancel(); 143 144 const ui::SimpleMenuModel& menu_model() const { return menu_model_; } 145 const content::ContextMenuParams& params() const { return params_; } 146 147 // SimpleMenuModel::Delegate implementation. 148 virtual bool IsCommandIdChecked(int command_id) const OVERRIDE; 149 virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE; 150 virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE; 151 virtual void MenuWillShow(ui::SimpleMenuModel* source) OVERRIDE; 152 virtual void MenuClosed(ui::SimpleMenuModel* source) OVERRIDE; 153 154 // RenderViewContextMenuProxy implementation. 155 virtual void AddMenuItem(int command_id, 156 const base::string16& title) OVERRIDE; 157 virtual void AddCheckItem(int command_id, 158 const base::string16& title) OVERRIDE; 159 virtual void AddSeparator() OVERRIDE; 160 virtual void AddSubMenu(int command_id, 161 const base::string16& label, 162 ui::MenuModel* model) OVERRIDE; 163 virtual void UpdateMenuItem(int command_id, 164 bool enabled, 165 bool hidden, 166 const base::string16& title) OVERRIDE; 167 virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE; 168 virtual content::WebContents* GetWebContents() const OVERRIDE; 169 virtual Profile* GetProfile() const OVERRIDE; 170 171 protected: 172 void InitMenu(); 173 174 // Platform specific functions. 175 virtual void PlatformInit() = 0; 176 virtual void PlatformCancel() = 0; 177 virtual bool GetAcceleratorForCommandId( 178 int command_id, 179 ui::Accelerator* accelerator) = 0; 180 virtual void AppendPlatformEditableItems(); 181 182 content::ContextMenuParams params_; 183 content::WebContents* source_web_contents_; 184 // The RenderFrameHost's IDs. 185 int render_process_id_; 186 int render_frame_id_; 187 Profile* profile_; 188 189 ui::SimpleMenuModel menu_model_; 190 extensions::ContextMenuMatcher extension_items_; 191 192 private: 193 friend class RenderViewContextMenuTest; 194 friend class RenderViewContextMenuPrefsTest; 195 196 static bool IsDevToolsURL(const GURL& url); 197 static bool IsInternalResourcesURL(const GURL& url); 198 static bool ExtensionContextAndPatternMatch( 199 const content::ContextMenuParams& params, 200 extensions::MenuItem::ContextList contexts, 201 const extensions::URLPatternSet& target_url_patterns); 202 static bool MenuItemMatchesParams(const content::ContextMenuParams& params, 203 const extensions::MenuItem* item); 204 205 // Gets the extension (if any) associated with the WebContents that we're in. 206 const extensions::Extension* GetExtension() const; 207 bool AppendCustomItems(); 208 209 void AppendDeveloperItems(); 210 void AppendDevtoolsForUnpackedExtensions(); 211 void AppendLinkItems(); 212 void AppendImageItems(); 213 void AppendAudioItems(); 214 void AppendCanvasItems(); 215 void AppendVideoItems(); 216 void AppendMediaItems(); 217 void AppendPluginItems(); 218 void AppendPageItems(); 219 void AppendFrameItems(); 220 void AppendCopyItem(); 221 void AppendPrintItem(); 222 void AppendEditableItems(); 223 void AppendSearchProvider(); 224 void AppendAllExtensionItems(); 225 void AppendCurrentExtensionItems(); 226 void AppendPrintPreviewItems(); 227 void AppendSearchWebForImageItems(); 228 void AppendSpellingSuggestionsSubMenu(); 229 void AppendSpellcheckOptionsSubMenu(); 230 void AppendProtocolHandlerSubMenu(); 231 232 // Opens the specified URL string in a new tab. 233 void OpenURL(const GURL& url, const GURL& referrer, 234 WindowOpenDisposition disposition, 235 content::PageTransition transition); 236 237 // Copy to the clipboard an image located at a point in the RenderView 238 void CopyImageAt(int x, int y); 239 240 // Get an image located at a point in the RenderView for search. 241 void GetImageThumbnailForSearch(); 242 243 // Launch the inspector targeting a point in the RenderView 244 void Inspect(int x, int y); 245 246 // Writes the specified text/url to the system clipboard 247 void WriteURLToClipboard(const GURL& url); 248 249 void MediaPlayerActionAt(const gfx::Point& location, 250 const blink::WebMediaPlayerAction& action); 251 void PluginActionAt(const gfx::Point& location, 252 const blink::WebPluginAction& action); 253 254 bool IsDevCommandEnabled(int id) const; 255 256 // Returns a list of registered ProtocolHandlers that can handle the clicked 257 // on URL. 258 ProtocolHandlerRegistry::ProtocolHandlerList GetHandlersForLinkUrl(); 259 260 // Returns a (possibly truncated) version of the current selection text 261 // suitable or putting in the title of a menu item. 262 base::string16 PrintableSelectionText(); 263 264 // The destination URL to use if the user tries to search for or navigate to 265 // a text selection. 266 GURL selection_navigation_url_; 267 268 ui::SimpleMenuModel protocol_handler_submenu_model_; 269 ProtocolHandlerRegistry* protocol_handler_registry_; 270 271 // An observer that handles spelling-menu items. 272 scoped_ptr<SpellingMenuObserver> spelling_menu_observer_; 273 274 // An observer that handles a 'spell-checker options' submenu. 275 scoped_ptr<SpellCheckerSubMenuObserver> spellchecker_submenu_observer_; 276 277 #if defined(ENABLE_FULL_PRINTING) 278 // An observer that disables menu items when print preview is active. 279 scoped_ptr<PrintPreviewContextMenuObserver> print_preview_menu_observer_; 280 #endif 281 282 // Our observers. 283 mutable ObserverList<RenderViewContextMenuObserver> observers_; 284 285 // Whether a command has been executed. Used to track whether menu observers 286 // should be notified of menu closing without execution. 287 bool command_executed_; 288 289 scoped_ptr<ContextMenuContentType> content_type_; 290 291 DISALLOW_COPY_AND_ASSIGN(RenderViewContextMenu); 292 }; 293 294 #endif // CHROME_BROWSER_RENDERER_CONTEXT_MENU_RENDER_VIEW_CONTEXT_MENU_H_ 295