Home | History | Annotate | Download | only in tab_contents
      1 // Copyright (c) 2012 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_TAB_CONTENTS_RENDER_VIEW_CONTEXT_MENU_H_
      6 #define CHROME_BROWSER_TAB_CONTENTS_RENDER_VIEW_CONTEXT_MENU_H_
      7 
      8 #include <map>
      9 #include <string>
     10 #include <vector>
     11 
     12 #include "base/memory/scoped_ptr.h"
     13 #include "base/memory/scoped_vector.h"
     14 #include "base/observer_list.h"
     15 #include "base/strings/string16.h"
     16 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
     17 #include "chrome/browser/extensions/context_menu_matcher.h"
     18 #include "chrome/browser/extensions/menu_manager.h"
     19 #include "chrome/browser/tab_contents/render_view_context_menu_observer.h"
     20 #include "content/public/common/context_menu_params.h"
     21 #include "content/public/common/page_transition_types.h"
     22 #include "ui/base/models/simple_menu_model.h"
     23 #include "ui/base/window_open_disposition.h"
     24 
     25 class PrintPreviewContextMenuObserver;
     26 class Profile;
     27 class SpellingMenuObserver;
     28 class SpellCheckerSubMenuObserver;
     29 
     30 namespace content {
     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 WebKit {
     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, 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 string16& title) = 0;
    108   virtual void AddCheckItem(int command_id, const 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 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 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::WebContents* web_contents,
    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   // Provide access to the menu model for ExternalTabContainer.
    145   const ui::MenuModel& menu_model() const { return menu_model_; }
    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   // RenderViewContextMenuDelegate implementation.
    155   virtual void AddMenuItem(int command_id, const string16& title) OVERRIDE;
    156   virtual void AddCheckItem(int command_id, const string16& title) OVERRIDE;
    157   virtual void AddSeparator() OVERRIDE;
    158   virtual void AddSubMenu(int command_id,
    159                           const string16& label,
    160                           ui::MenuModel* model) OVERRIDE;
    161   virtual void UpdateMenuItem(int command_id,
    162                               bool enabled,
    163                               bool hidden,
    164                               const string16& title) OVERRIDE;
    165   virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE;
    166   virtual content::WebContents* GetWebContents() const OVERRIDE;
    167   virtual Profile* GetProfile() const OVERRIDE;
    168 
    169  protected:
    170   void InitMenu();
    171 
    172   // Platform specific functions.
    173   virtual void PlatformInit() = 0;
    174   virtual void PlatformCancel() = 0;
    175   virtual bool GetAcceleratorForCommandId(
    176       int command_id,
    177       ui::Accelerator* accelerator) = 0;
    178   virtual void AppendPlatformEditableItems();
    179 
    180   content::ContextMenuParams params_;
    181   content::WebContents* source_web_contents_;
    182   Profile* profile_;
    183 
    184   ui::SimpleMenuModel menu_model_;
    185   extensions::ContextMenuMatcher extension_items_;
    186 
    187   // True if we are showing for an external tab contents. The default is false.
    188   bool external_;
    189 
    190  private:
    191   friend class RenderViewContextMenuTest;
    192   friend class RenderViewContextMenuPrefsTest;
    193 
    194   static bool IsDevToolsURL(const GURL& url);
    195   static bool IsInternalResourcesURL(const GURL& url);
    196   static bool ExtensionContextAndPatternMatch(
    197       const content::ContextMenuParams& params,
    198       extensions::MenuItem::ContextList contexts,
    199       const extensions::URLPatternSet& target_url_patterns);
    200   static bool MenuItemMatchesParams(
    201       const content::ContextMenuParams& params,
    202       const extensions::MenuItem* item);
    203 
    204   // Gets the extension (if any) associated with the WebContents that we're in.
    205   const extensions::Extension* GetExtension() const;
    206   void AppendAppModeItems();
    207   void AppendPlatformAppItems();
    208   void AppendPopupExtensionItems();
    209   void AppendPanelItems();
    210   bool AppendCustomItems();
    211   void AppendDeveloperItems();
    212   void AppendLinkItems();
    213   void AppendImageItems();
    214   void AppendAudioItems();
    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 AppendSpellingSuggestionsSubMenu();
    226   void AppendSpellcheckOptionsSubMenu();
    227   void AppendSpeechInputOptionsSubMenu();
    228   void AppendProtocolHandlerSubMenu();
    229 
    230   // Opens the specified URL string in a new tab.  The |frame_id| specifies the
    231   // frame in which the context menu was displayed, or 0 if the menu action is
    232   // independent of that frame (e.g. protocol handler settings).
    233   void OpenURL(const GURL& url, const GURL& referrer, int64 frame_id,
    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 WebKit::WebMediaPlayerAction& action);
    251   void PluginActionAt(const gfx::Point& location,
    252                       const WebKit::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   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 speech_input_submenu_model_;
    269   ui::SimpleMenuModel protocol_handler_submenu_model_;
    270   ScopedVector<ui::SimpleMenuModel> extension_menu_models_;
    271   ProtocolHandlerRegistry* protocol_handler_registry_;
    272 
    273   // An observer that handles spelling-menu items.
    274   scoped_ptr<SpellingMenuObserver> spelling_menu_observer_;
    275 
    276   // An observer that handles a 'spell-checker options' submenu.
    277   scoped_ptr<SpellCheckerSubMenuObserver> spellchecker_submenu_observer_;
    278 
    279 #if defined(ENABLE_FULL_PRINTING)
    280   // An observer that disables menu items when print preview is active.
    281   scoped_ptr<PrintPreviewContextMenuObserver> print_preview_menu_observer_;
    282 #endif
    283 
    284   // Our observers.
    285   mutable ObserverList<RenderViewContextMenuObserver> observers_;
    286 
    287   // Whether a command has been executed. Used to track whether menu observers
    288   // should be notified of menu closing without execution.
    289   bool command_executed_;
    290 
    291   // Whether or not the menu was triggered for a browser plugin guest.
    292   // Guests are rendered inside chrome apps, but have most of the actions
    293   // that a regular web page has.
    294   // Currently actions/items that are suppressed from guests are: searching,
    295   // printing, speech and instant.
    296   bool is_guest_;
    297 
    298   DISALLOW_COPY_AND_ASSIGN(RenderViewContextMenu);
    299 };
    300 
    301 #endif  // CHROME_BROWSER_TAB_CONTENTS_RENDER_VIEW_CONTEXT_MENU_H_
    302