Start moving context menu code to RenderFrame.

The selection code will have to move as well. That will happen in future changes.

BUG=304341
[email protected]

Review URL: https://codereview.chromium.org/130773004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@248091 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/android_webview/native/aw_web_contents_view_delegate.cc b/android_webview/native/aw_web_contents_view_delegate.cc
index e50b721..5c3db945 100644
--- a/android_webview/native/aw_web_contents_view_delegate.cc
+++ b/android_webview/native/aw_web_contents_view_delegate.cc
@@ -34,6 +34,7 @@
 }
 
 void AwWebContentsViewDelegate::ShowContextMenu(
+    content::RenderFrameHost* render_frame_host,
     const content::ContextMenuParams& params) {
   // TODO(boliu): Large blocks of this function are identical with
   // ChromeWebContentsViewDelegateAndroid::ShowContextMenu. De-dup this if
diff --git a/android_webview/native/aw_web_contents_view_delegate.h b/android_webview/native/aw_web_contents_view_delegate.h
index 141b6e45..f2b4f8e 100644
--- a/android_webview/native/aw_web_contents_view_delegate.h
+++ b/android_webview/native/aw_web_contents_view_delegate.h
@@ -27,6 +27,7 @@
   // content::WebContentsViewDelegate implementation.
   virtual content::WebDragDestDelegate* GetDragDestDelegate() OVERRIDE;
   virtual void ShowContextMenu(
+      content::RenderFrameHost* render_frame_host,
       const content::ContextMenuParams& params) OVERRIDE;
 
  private:
diff --git a/chrome/browser/apps/app_browsertest.cc b/chrome/browser/apps/app_browsertest.cc
index 6bf8f1f..2a357bc 100644
--- a/chrome/browser/apps/app_browsertest.cc
+++ b/chrome/browser/apps/app_browsertest.cc
@@ -70,9 +70,9 @@
 // Non-abstract RenderViewContextMenu class.
 class PlatformAppContextMenu : public RenderViewContextMenu {
  public:
-  PlatformAppContextMenu(WebContents* web_contents,
+  PlatformAppContextMenu(content::RenderFrameHost* render_frame_host,
                          const content::ContextMenuParams& params)
-      : RenderViewContextMenu(web_contents, params) {}
+      : RenderViewContextMenu(render_frame_host, params) {}
 
   bool HasCommandWithId(int command_id) {
     return menu_model_.GetIndexOfCommandId(command_id) != -1;
@@ -229,7 +229,7 @@
   ASSERT_TRUE(web_contents);
   content::ContextMenuParams params;
   scoped_ptr<PlatformAppContextMenu> menu;
-  menu.reset(new PlatformAppContextMenu(web_contents, params));
+  menu.reset(new PlatformAppContextMenu(web_contents->GetMainFrame(), params));
   menu->Init();
   ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
   ASSERT_TRUE(
@@ -253,7 +253,7 @@
   ASSERT_TRUE(web_contents);
   content::ContextMenuParams params;
   scoped_ptr<PlatformAppContextMenu> menu;
-  menu.reset(new PlatformAppContextMenu(web_contents, params));
+  menu.reset(new PlatformAppContextMenu(web_contents->GetMainFrame(), params));
   menu->Init();
   ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
   ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST + 1));
@@ -280,7 +280,7 @@
   ASSERT_TRUE(web_contents);
   content::ContextMenuParams params;
   scoped_ptr<PlatformAppContextMenu> menu;
-  menu.reset(new PlatformAppContextMenu(web_contents, params));
+  menu.reset(new PlatformAppContextMenu(web_contents->GetMainFrame(), params));
   menu->Init();
   ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
   ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST + 1));
@@ -308,7 +308,7 @@
   content::ContextMenuParams params;
   params.is_editable = true;
   scoped_ptr<PlatformAppContextMenu> menu;
-  menu.reset(new PlatformAppContextMenu(web_contents, params));
+  menu.reset(new PlatformAppContextMenu(web_contents->GetMainFrame(), params));
   menu->Init();
   ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
   ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
@@ -336,7 +336,7 @@
   content::ContextMenuParams params;
   params.selection_text = base::ASCIIToUTF16("Hello World");
   scoped_ptr<PlatformAppContextMenu> menu;
-  menu.reset(new PlatformAppContextMenu(web_contents, params));
+  menu.reset(new PlatformAppContextMenu(web_contents->GetMainFrame(), params));
   menu->Init();
   ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
   ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
@@ -363,7 +363,7 @@
   content::ContextMenuParams params;
   params.page_url = GURL("http://foo.bar");
   scoped_ptr<PlatformAppContextMenu> menu;
-  menu.reset(new PlatformAppContextMenu(web_contents, params));
+  menu.reset(new PlatformAppContextMenu(web_contents->GetMainFrame(), params));
   menu->Init();
   ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
 
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry_browsertest.cc b/chrome/browser/custom_handlers/protocol_handler_registry_browsertest.cc
index 7898c31..ae5d4e4 100644
--- a/chrome/browser/custom_handlers/protocol_handler_registry_browsertest.cc
+++ b/chrome/browser/custom_handlers/protocol_handler_registry_browsertest.cc
@@ -25,9 +25,9 @@
 
 class TestRenderViewContextMenu : public RenderViewContextMenu {
  public:
-  TestRenderViewContextMenu(WebContents* web_contents,
+  TestRenderViewContextMenu(content::RenderFrameHost* render_frame_host,
                             content::ContextMenuParams params)
-      : RenderViewContextMenu(web_contents, params) { }
+      : RenderViewContextMenu(render_frame_host, params) { }
 
   virtual void PlatformInit() OVERRIDE { }
   virtual void PlatformCancel() OVERRIDE { }
@@ -62,7 +62,8 @@
     params.writing_direction_right_to_left = 0;
 #endif  // OS_MACOSX
     TestRenderViewContextMenu* menu = new TestRenderViewContextMenu(
-        browser()->tab_strip_model()->GetActiveWebContents(), params);
+        browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(),
+        params);
     menu->Init();
     return menu;
   }
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc
index 123c8fb..db4eba1 100644
--- a/chrome/browser/download/download_browsertest.cc
+++ b/chrome/browser/download/download_browsertest.cc
@@ -324,9 +324,9 @@
 
 class TestRenderViewContextMenu : public RenderViewContextMenu {
  public:
-  TestRenderViewContextMenu(WebContents* web_contents,
+  TestRenderViewContextMenu(content::RenderFrameHost* render_frame_host,
                             const content::ContextMenuParams& params)
-      : RenderViewContextMenu(web_contents, params) {
+      : RenderViewContextMenu(render_frame_host, params) {
   }
   virtual ~TestRenderViewContextMenu() {}
 
@@ -2333,7 +2333,7 @@
   context_menu_params.src_url = url;
   context_menu_params.page_url = url;
   TestRenderViewContextMenu menu(
-      browser()->tab_strip_model()->GetActiveWebContents(),
+      browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(),
       context_menu_params);
   menu.Init();
   menu.ExecuteCommand(IDC_CONTENT_CONTEXT_SAVEIMAGEAS, 0);
@@ -2413,7 +2413,8 @@
   context_menu_params.media_type = blink::WebContextMenuData::MediaTypeImage;
   context_menu_params.src_url = jpeg_url;
   context_menu_params.page_url = jpeg_url;
-  TestRenderViewContextMenu menu(web_contents, context_menu_params);
+  TestRenderViewContextMenu menu(web_contents->GetMainFrame(),
+                                 context_menu_params);
   menu.Init();
   menu.ExecuteCommand(IDC_CONTENT_CONTEXT_SAVEIMAGEAS, 0);
   waiter_context_menu->WaitForFinished();
diff --git a/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc b/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
index 39827ff0..1c3f32c 100644
--- a/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
+++ b/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
@@ -53,9 +53,9 @@
 // An UI-less RenderViewContextMenu.
 class TestRenderViewContextMenu : public RenderViewContextMenu {
  public:
-  TestRenderViewContextMenu(WebContents* web_contents,
+  TestRenderViewContextMenu(content::RenderFrameHost* render_frame_host,
                             const content::ContextMenuParams& params)
-      : RenderViewContextMenu(web_contents, params) {
+      : RenderViewContextMenu(render_frame_host, params) {
   }
   virtual ~TestRenderViewContextMenu() {}
 
@@ -520,7 +520,7 @@
       frame_navigation_state().GetMainFrameID().frame_num;
   params.link_url = extension->GetResourceURL("b.html");
 
-  TestRenderViewContextMenu menu(tab, params);
+  TestRenderViewContextMenu menu(tab->GetMainFrame(), params);
   menu.Init();
   menu.ExecuteCommand(IDC_CONTENT_CONTEXT_OPENLINKNEWTAB, 0);
 
diff --git a/chrome/browser/extensions/extension_context_menu_browsertest.cc b/chrome/browser/extensions/extension_context_menu_browsertest.cc
index 29a5bed5..cb17ffb 100644
--- a/chrome/browser/extensions/extension_context_menu_browsertest.cc
+++ b/chrome/browser/extensions/extension_context_menu_browsertest.cc
@@ -31,9 +31,9 @@
 // RenderViewContextMenu where extension items get added and executed.
 class TestRenderViewContextMenu : public RenderViewContextMenu {
  public:
-  TestRenderViewContextMenu(WebContents* web_contents,
+  TestRenderViewContextMenu(content::RenderFrameHost* render_frame_host,
                             const content::ContextMenuParams& params)
-      : RenderViewContextMenu(web_contents, params) {}
+      : RenderViewContextMenu(render_frame_host, params) {}
 
   virtual ~TestRenderViewContextMenu() {}
 
@@ -121,7 +121,7 @@
     params.link_url = link_url;
     params.frame_url = frame_url;
     TestRenderViewContextMenu* menu =
-        new TestRenderViewContextMenu(web_contents, params);
+        new TestRenderViewContextMenu(web_contents->GetMainFrame(), params);
     menu->Init();
     return menu;
   }
diff --git a/chrome/browser/tab_contents/render_view_context_menu.cc b/chrome/browser/tab_contents/render_view_context_menu.cc
index fe15206928..eeceebb 100644
--- a/chrome/browser/tab_contents/render_view_context_menu.cc
+++ b/chrome/browser/tab_contents/render_view_context_menu.cc
@@ -72,6 +72,7 @@
 #include "content/public/browser/navigation_details.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/notification_service.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"
@@ -120,6 +121,7 @@
 using content::NavigationController;
 using content::NavigationEntry;
 using content::OpenURLParams;
+using content::RenderFrameHost;
 using content::RenderViewHost;
 using content::SSLStatus;
 using content::WebContents;
@@ -395,11 +397,14 @@
 static const int kSpellcheckRadioGroup = 1;
 
 RenderViewContextMenu::RenderViewContextMenu(
-    WebContents* web_contents,
+    content::RenderFrameHost* render_frame_host,
     const content::ContextMenuParams& params)
     : params_(params),
-      source_web_contents_(web_contents),
-      profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())),
+      source_web_contents_(WebContents::FromRenderFrameHost(render_frame_host)),
+      render_process_id_(render_frame_host->GetProcess()->GetID()),
+      render_frame_id_(render_frame_host->GetRoutingID()),
+      profile_(Profile::FromBrowserContext(
+          source_web_contents_->GetBrowserContext())),
       menu_model_(this),
       extension_items_(profile_, this, &menu_model_,
                     base::Bind(MenuItemMatchesParams, params_)),
@@ -1514,7 +1519,10 @@
         source_web_contents_, false, std::string());
     }
 #endif
-    rvh->ExecuteCustomContextMenuCommand(action, context);
+    RenderFrameHost* render_frame_host =
+        RenderFrameHost::FromID(render_process_id_, render_frame_id_);
+    if (render_frame_host)
+      render_frame_host->ExecuteCustomContextMenuCommand(action, context);
     return;
   }
 
@@ -1995,10 +2003,10 @@
       source_web_contents_->GetRenderWidgetHostView();
   if (view)
     view->SetShowingContextMenu(false);
-  RenderViewHost* rvh = source_web_contents_->GetRenderViewHost();
-  if (rvh) {
-    rvh->NotifyContextMenuClosed(params_.custom_context);
-  }
+  RenderFrameHost* render_frame_host =
+      RenderFrameHost::FromID(render_process_id_, render_frame_id_);
+  if (render_frame_host)
+    render_frame_host->NotifyContextMenuClosed(params_.custom_context);
 
   if (!command_executed_) {
     FOR_EACH_OBSERVER(RenderViewContextMenuObserver,
diff --git a/chrome/browser/tab_contents/render_view_context_menu.h b/chrome/browser/tab_contents/render_view_context_menu.h
index 4eeddef..8eb6d79 100644
--- a/chrome/browser/tab_contents/render_view_context_menu.h
+++ b/chrome/browser/tab_contents/render_view_context_menu.h
@@ -28,6 +28,7 @@
 class SpellCheckerSubMenuObserver;
 
 namespace content {
+class RenderFrameHost;
 class RenderViewHost;
 class WebContents;
 }
@@ -130,7 +131,7 @@
  public:
   static const size_t kMaxSelectionTextLength;
 
-  RenderViewContextMenu(content::WebContents* web_contents,
+  RenderViewContextMenu(content::RenderFrameHost* render_frame_host,
                         const content::ContextMenuParams& params);
 
   virtual ~RenderViewContextMenu();
@@ -180,6 +181,9 @@
 
   content::ContextMenuParams params_;
   content::WebContents* source_web_contents_;
+  // The RenderFrameHost's IDs.
+  int render_process_id_;
+  int render_frame_id_;
   Profile* profile_;
 
   ui::SimpleMenuModel menu_model_;
diff --git a/chrome/browser/tab_contents/render_view_context_menu_browsertest.cc b/chrome/browser/tab_contents/render_view_context_menu_browsertest.cc
index e7b71b7..c5f5f6f 100644
--- a/chrome/browser/tab_contents/render_view_context_menu_browsertest.cc
+++ b/chrome/browser/tab_contents/render_view_context_menu_browsertest.cc
@@ -48,7 +48,8 @@
     params.writing_direction_right_to_left = 0;
 #endif  // OS_MACOSX
     TestRenderViewContextMenu* menu = new TestRenderViewContextMenu(
-        browser()->tab_strip_model()->GetActiveWebContents(), params);
+        browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(),
+        params);
     menu->Init();
     return menu;
   }
@@ -144,7 +145,7 @@
 
   // Select "Open Link in New Tab" and wait for the new tab to be added.
   TestRenderViewContextMenu menu(
-      browser()->tab_strip_model()->GetActiveWebContents(),
+      browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(),
       context_menu_params);
   menu.Init();
   menu.ExecuteCommand(IDC_CONTENT_CONTEXT_OPENLINKNEWTAB, 0);
@@ -196,7 +197,7 @@
 
   // Select "Open Link in Incognito Window" and wait for window to be added.
   TestRenderViewContextMenu menu(
-      browser()->tab_strip_model()->GetActiveWebContents(),
+      browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(),
       context_menu_params);
   menu.Init();
   menu.ExecuteCommand(IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD, 0);
diff --git a/chrome/browser/tab_contents/render_view_context_menu_test_util.cc b/chrome/browser/tab_contents/render_view_context_menu_test_util.cc
index d1f2cb0..ef30316b 100644
--- a/chrome/browser/tab_contents/render_view_context_menu_test_util.cc
+++ b/chrome/browser/tab_contents/render_view_context_menu_test_util.cc
@@ -5,9 +5,9 @@
 #include "chrome/browser/tab_contents/render_view_context_menu_test_util.h"
 
 TestRenderViewContextMenu::TestRenderViewContextMenu(
-    content::WebContents* web_contents,
+    content::RenderFrameHost* render_frame_host,
     content::ContextMenuParams params)
-    : RenderViewContextMenu(web_contents, params) {}
+    : RenderViewContextMenu(render_frame_host, params) {}
 
 TestRenderViewContextMenu::~TestRenderViewContextMenu() {}
 
diff --git a/chrome/browser/tab_contents/render_view_context_menu_test_util.h b/chrome/browser/tab_contents/render_view_context_menu_test_util.h
index ffe36ff..3178396 100644
--- a/chrome/browser/tab_contents/render_view_context_menu_test_util.h
+++ b/chrome/browser/tab_contents/render_view_context_menu_test_util.h
@@ -10,7 +10,7 @@
 
 class TestRenderViewContextMenu : public RenderViewContextMenu {
  public:
-  TestRenderViewContextMenu(content::WebContents* web_contents,
+  TestRenderViewContextMenu(content::RenderFrameHost* render_frame_host,
                             content::ContextMenuParams params);
   virtual ~TestRenderViewContextMenu();
 
diff --git a/chrome/browser/tab_contents/render_view_context_menu_unittest.cc b/chrome/browser/tab_contents/render_view_context_menu_unittest.cc
index 960ec39..3de09a3 100644
--- a/chrome/browser/tab_contents/render_view_context_menu_unittest.cc
+++ b/chrome/browser/tab_contents/render_view_context_menu_unittest.cc
@@ -257,7 +257,7 @@
     params.unfiltered_link_url = params.link_url;
     content::WebContents* wc = web_contents();
     TestRenderViewContextMenu* menu = new TestRenderViewContextMenu(
-        wc, params);
+        wc->GetMainFrame(), params);
     // TestingProfile (returned by profile()) does not provide a protocol
     // registry.
     menu->protocol_handler_registry_ = registry_.get();
diff --git a/chrome/browser/translate/translate_manager_browsertest.cc b/chrome/browser/translate/translate_manager_browsertest.cc
index 6181c22..569f4f80 100644
--- a/chrome/browser/translate/translate_manager_browsertest.cc
+++ b/chrome/browser/translate/translate_manager_browsertest.cc
@@ -402,7 +402,7 @@
     params.writing_direction_right_to_left = 0;
 #endif  // OS_MACOSX
     params.edit_flags = blink::WebContextMenuData::CanTranslate;
-    return new TestRenderViewContextMenu(web_contents, params);
+    return new TestRenderViewContextMenu(web_contents->GetMainFrame(), params);
   }
 
   bool IsItemPresent(int id) {
@@ -416,9 +416,9 @@
       ui::Accelerator* accelerator) OVERRIDE { return false; }
 
  private:
-  TestRenderViewContextMenu(content::WebContents* web_contents,
+  TestRenderViewContextMenu(content::RenderFrameHost* render_frame_host,
                             const content::ContextMenuParams& params)
-      : RenderViewContextMenu(web_contents, params) {
+      : RenderViewContextMenu(render_frame_host, params) {
   }
 
   DISALLOW_COPY_AND_ASSIGN(TestRenderViewContextMenu);
diff --git a/chrome/browser/ui/android/tab_contents/chrome_web_contents_view_delegate_android.cc b/chrome/browser/ui/android/tab_contents/chrome_web_contents_view_delegate_android.cc
index 1aaa5d1..c75c8203 100644
--- a/chrome/browser/ui/android/tab_contents/chrome_web_contents_view_delegate_android.cc
+++ b/chrome/browser/ui/android/tab_contents/chrome_web_contents_view_delegate_android.cc
@@ -29,6 +29,7 @@
 }
 
 void ChromeWebContentsViewDelegateAndroid::ShowContextMenu(
+    content::RenderFrameHost* render_frame_host,
     const content::ContextMenuParams& params) {
   // Display paste pop-up only when selection is empty and editable.
   if (params.is_editable && params.selection_text.empty()) {
diff --git a/chrome/browser/ui/android/tab_contents/chrome_web_contents_view_delegate_android.h b/chrome/browser/ui/android/tab_contents/chrome_web_contents_view_delegate_android.h
index 04314cb8..c0cf81c 100644
--- a/chrome/browser/ui/android/tab_contents/chrome_web_contents_view_delegate_android.h
+++ b/chrome/browser/ui/android/tab_contents/chrome_web_contents_view_delegate_android.h
@@ -24,6 +24,7 @@
 
   // WebContentsViewDelegate:
   virtual void ShowContextMenu(
+      content::RenderFrameHost* render_frame_host,
       const content::ContextMenuParams& params) OVERRIDE;
 
   // WebContentsViewDelegate:
diff --git a/chrome/browser/ui/cocoa/tab_contents/chrome_web_contents_view_delegate_mac.h b/chrome/browser/ui/cocoa/tab_contents/chrome_web_contents_view_delegate_mac.h
index 5d0b842..4148a01 100644
--- a/chrome/browser/ui/cocoa/tab_contents/chrome_web_contents_view_delegate_mac.h
+++ b/chrome/browser/ui/cocoa/tab_contents/chrome_web_contents_view_delegate_mac.h
@@ -32,6 +32,7 @@
           content::RenderWidgetHost* render_widget_host) OVERRIDE;
   virtual content::WebDragDestDelegate* GetDragDestDelegate() OVERRIDE;
   virtual void ShowContextMenu(
+      content::RenderFrameHost* render_frame_host,
       const content::ContextMenuParams& params) OVERRIDE;
 
  private:
diff --git a/chrome/browser/ui/cocoa/tab_contents/chrome_web_contents_view_delegate_mac.mm b/chrome/browser/ui/cocoa/tab_contents/chrome_web_contents_view_delegate_mac.mm
index f99fc56..6e3a4ef7 100644
--- a/chrome/browser/ui/cocoa/tab_contents/chrome_web_contents_view_delegate_mac.mm
+++ b/chrome/browser/ui/cocoa/tab_contents/chrome_web_contents_view_delegate_mac.mm
@@ -34,6 +34,7 @@
 }
 
 void ChromeWebContentsViewDelegateMac::ShowContextMenu(
+    content::RenderFrameHost* render_frame_host,
     const content::ContextMenuParams& params) {
   // The renderer may send the "show context menu" message multiple times, one
   // for each right click mouse event it receives. Normally, this doesn't happen
@@ -48,7 +49,7 @@
     return;
 
   context_menu_.reset(new RenderViewContextMenuMac(
-      web_contents_,
+      render_frame_host,
       params,
       web_contents_->GetView()->GetContentNativeView()));
   context_menu_->Init();
diff --git a/chrome/browser/ui/cocoa/tab_contents/render_view_context_menu_mac.h b/chrome/browser/ui/cocoa/tab_contents/render_view_context_menu_mac.h
index 43afdd72..6b37bec 100644
--- a/chrome/browser/ui/cocoa/tab_contents/render_view_context_menu_mac.h
+++ b/chrome/browser/ui/cocoa/tab_contents/render_view_context_menu_mac.h
@@ -17,7 +17,7 @@
 // target of the NSMenu, bridging back to this C++ class.
 class RenderViewContextMenuMac : public RenderViewContextMenu {
  public:
-  RenderViewContextMenuMac(content::WebContents* web_contents,
+  RenderViewContextMenuMac(content::RenderFrameHost* render_frame_host,
                            const content::ContextMenuParams& params,
                            NSView* parent_view);
   virtual ~RenderViewContextMenuMac();
diff --git a/chrome/browser/ui/cocoa/tab_contents/render_view_context_menu_mac.mm b/chrome/browser/ui/cocoa/tab_contents/render_view_context_menu_mac.mm
index 47c4516..48ad6ca 100644
--- a/chrome/browser/ui/cocoa/tab_contents/render_view_context_menu_mac.mm
+++ b/chrome/browser/ui/cocoa/tab_contents/render_view_context_menu_mac.mm
@@ -50,10 +50,10 @@
 // Relies on the tag being set to the command id.
 
 RenderViewContextMenuMac::RenderViewContextMenuMac(
-    WebContents* web_contents,
+    content::RenderFrameHost* render_frame_host,
     const content::ContextMenuParams& params,
     NSView* parent_view)
-    : RenderViewContextMenu(web_contents, params),
+    : RenderViewContextMenu(render_frame_host, params),
       speech_submenu_model_(this),
       bidi_submenu_model_(this),
       parent_view_(parent_view) {
diff --git a/chrome/browser/ui/gtk/tab_contents/chrome_web_contents_view_delegate_gtk.cc b/chrome/browser/ui/gtk/tab_contents/chrome_web_contents_view_delegate_gtk.cc
index 45a32e0d..5cd6bca7 100644
--- a/chrome/browser/ui/gtk/tab_contents/chrome_web_contents_view_delegate_gtk.cc
+++ b/chrome/browser/ui/gtk/tab_contents/chrome_web_contents_view_delegate_gtk.cc
@@ -128,6 +128,7 @@
 }
 
 void ChromeWebContentsViewDelegateGtk::ShowContextMenu(
+    content::RenderFrameHost* render_frame_host,
     const content::ContextMenuParams& params) {
   // Find out the RenderWidgetHostView that corresponds to the render widget on
   // which this context menu is showed, so that we can retrieve the last mouse
@@ -149,7 +150,7 @@
   }
 
   context_menu_.reset(
-      new RenderViewContextMenuGtk(web_contents_, params, view));
+      new RenderViewContextMenuGtk(render_frame_host, params, view));
   context_menu_->Init();
 
   // Don't show empty menus.
diff --git a/chrome/browser/ui/gtk/tab_contents/chrome_web_contents_view_delegate_gtk.h b/chrome/browser/ui/gtk/tab_contents/chrome_web_contents_view_delegate_gtk.h
index c3c85f0..92d660f 100644
--- a/chrome/browser/ui/gtk/tab_contents/chrome_web_contents_view_delegate_gtk.h
+++ b/chrome/browser/ui/gtk/tab_contents/chrome_web_contents_view_delegate_gtk.h
@@ -39,6 +39,7 @@
 
   // Overridden from WebContentsViewDelegate:
   virtual void ShowContextMenu(
+      content::RenderFrameHost* render_frame_host,
       const content::ContextMenuParams& params) OVERRIDE;
   virtual content::WebDragDestDelegate* GetDragDestDelegate() OVERRIDE;
   virtual void Initialize(GtkWidget* expanded_container,
diff --git a/chrome/browser/ui/gtk/tab_contents/render_view_context_menu_gtk.cc b/chrome/browser/ui/gtk/tab_contents/render_view_context_menu_gtk.cc
index 3f3945d..409b7e05 100644
--- a/chrome/browser/ui/gtk/tab_contents/render_view_context_menu_gtk.cc
+++ b/chrome/browser/ui/gtk/tab_contents/render_view_context_menu_gtk.cc
@@ -75,10 +75,10 @@
 }  // namespace
 
 RenderViewContextMenuGtk::RenderViewContextMenuGtk(
-    WebContents* web_contents,
+    content::RenderFrameHost* render_frame_host,
     const content::ContextMenuParams& params,
     content::RenderWidgetHostView* view)
-    : RenderViewContextMenu(web_contents, params),
+    : RenderViewContextMenu(render_frame_host, params),
       bidi_submenu_model_(this) {
   GdkEventButton* event = view->GetLastMouseDown();
   triggering_event_time_ = event ? event->time : GDK_CURRENT_TIME;
diff --git a/chrome/browser/ui/gtk/tab_contents/render_view_context_menu_gtk.h b/chrome/browser/ui/gtk/tab_contents/render_view_context_menu_gtk.h
index d2ab2f8..8f30069 100644
--- a/chrome/browser/ui/gtk/tab_contents/render_view_context_menu_gtk.h
+++ b/chrome/browser/ui/gtk/tab_contents/render_view_context_menu_gtk.h
@@ -19,7 +19,7 @@
 class RenderViewContextMenuGtk : public RenderViewContextMenu,
                                  public MenuGtk::Delegate {
  public:
-  RenderViewContextMenuGtk(content::WebContents* web_contents,
+  RenderViewContextMenuGtk(content::RenderFrameHost* render_frame_host,
                            const content::ContextMenuParams& params,
                            content::RenderWidgetHostView* view);
 
diff --git a/chrome/browser/ui/panels/panel_extension_browsertest.cc b/chrome/browser/ui/panels/panel_extension_browsertest.cc
index fbe8a79..69ba1a3 100644
--- a/chrome/browser/ui/panels/panel_extension_browsertest.cc
+++ b/chrome/browser/ui/panels/panel_extension_browsertest.cc
@@ -115,9 +115,9 @@
 // Non-abstract RenderViewContextMenu class for testing context menus in Panels.
 class PanelContextMenu : public RenderViewContextMenu {
  public:
-  PanelContextMenu(content::WebContents* web_contents,
+  PanelContextMenu(content::RenderFrameHost* render_frame_host,
                    const content::ContextMenuParams& params)
-      : RenderViewContextMenu(web_contents, params) {}
+      : RenderViewContextMenu(render_frame_host, params) {}
 
   bool HasCommandWithId(int command_id) {
     return menu_model_.GetIndexOfCommandId(command_id) != -1;
@@ -156,7 +156,7 @@
     EXPECT_FALSE(web_contents->GetDelegate()->HandleContextMenu(params));
 
     scoped_ptr<PanelContextMenu> menu(
-        new PanelContextMenu(web_contents, params));
+        new PanelContextMenu(web_contents->GetMainFrame(), params));
     menu->Init();
 
     EXPECT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
@@ -177,7 +177,7 @@
     EXPECT_FALSE(web_contents->GetDelegate()->HandleContextMenu(params));
 
     scoped_ptr<PanelContextMenu> menu(
-        new PanelContextMenu(web_contents, params));
+        new PanelContextMenu(web_contents->GetMainFrame(), params));
     menu->Init();
 
     EXPECT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
@@ -198,7 +198,7 @@
     EXPECT_FALSE(web_contents->GetDelegate()->HandleContextMenu(params));
 
     scoped_ptr<PanelContextMenu> menu(
-        new PanelContextMenu(web_contents, params));
+        new PanelContextMenu(web_contents->GetMainFrame(), params));
     menu->Init();
 
     EXPECT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
@@ -219,7 +219,7 @@
     EXPECT_FALSE(web_contents->GetDelegate()->HandleContextMenu(params));
 
     scoped_ptr<PanelContextMenu> menu(
-        new PanelContextMenu(web_contents, params));
+        new PanelContextMenu(web_contents->GetMainFrame(), params));
     menu->Init();
 
     EXPECT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
@@ -257,7 +257,7 @@
 
   // Verify menu contents contains the custom item added by their own extension.
   scoped_ptr<PanelContextMenu> menu;
-  menu.reset(new PanelContextMenu(web_contents, params));
+  menu.reset(new PanelContextMenu(web_contents->GetMainFrame(), params));
   menu->Init();
   EXPECT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
   EXPECT_FALSE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST + 1));
diff --git a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.cc b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.cc
index 0acc51c..7086507 100644
--- a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.cc
+++ b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.cc
@@ -119,6 +119,7 @@
 }
 
 void ChromeWebContentsViewDelegateViews::ShowContextMenu(
+    content::RenderFrameHost* render_frame_host,
     const content::ContextMenuParams& params) {
   // Menus need a Widget to work. If we're not the active tab we won't
   // necessarily be in a widget.
@@ -127,7 +128,7 @@
     return;
 
   context_menu_.reset(
-      RenderViewContextMenuViews::Create(web_contents_, params));
+      RenderViewContextMenuViews::Create(render_frame_host, params));
   context_menu_->Init();
 
   // Don't show empty menus.
diff --git a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.h b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.h
index 7fbdd64..018342f 100644
--- a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.h
+++ b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.h
@@ -38,6 +38,7 @@
   virtual bool Focus() OVERRIDE;
   virtual void TakeFocus(bool reverse) OVERRIDE;
   virtual void ShowContextMenu(
+      content::RenderFrameHost* render_frame_host,
       const content::ContextMenuParams& params) OVERRIDE;
   virtual void SizeChanged(const gfx::Size& size) OVERRIDE;
 
diff --git a/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.cc b/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.cc
index 28a0ea7f..358d61c 100644
--- a/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.cc
+++ b/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.cc
@@ -26,9 +26,9 @@
 // RenderViewContextMenuViews, public:
 
 RenderViewContextMenuViews::RenderViewContextMenuViews(
-    WebContents* web_contents,
+    content::RenderFrameHost* render_frame_host,
     const content::ContextMenuParams& params)
-    : RenderViewContextMenu(web_contents, params),
+    : RenderViewContextMenu(render_frame_host, params),
       bidi_submenu_model_(this) {
 }
 
@@ -38,9 +38,9 @@
 #if !defined(OS_WIN)
 // static
 RenderViewContextMenuViews* RenderViewContextMenuViews::Create(
-    content::WebContents* web_contents,
+    content::RenderFrameHost* render_frame_host,
     const content::ContextMenuParams& params) {
-  return new RenderViewContextMenuViews(web_contents, params);
+  return new RenderViewContextMenuViews(render_frame_host, params);
 }
 #endif  // OS_WIN
 
diff --git a/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h b/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h
index 450e6c46..dcd5d47 100644
--- a/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h
+++ b/chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h
@@ -26,7 +26,7 @@
 
   // Factory function to create an instance.
   static RenderViewContextMenuViews* Create(
-      content::WebContents* web_contents,
+      content::RenderFrameHost* render_frame_host,
       const content::ContextMenuParams& params);
 
   void RunMenuAt(views::Widget* parent,
@@ -42,7 +42,7 @@
   virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE;
 
  protected:
-  RenderViewContextMenuViews(content::WebContents* web_contents,
+  RenderViewContextMenuViews(content::RenderFrameHost* render_frame_host,
                              const content::ContextMenuParams& params);
 
   // RenderViewContextMenu implementation.
diff --git a/chrome/browser/ui/views/tab_contents/render_view_context_menu_win.cc b/chrome/browser/ui/views/tab_contents/render_view_context_menu_win.cc
index f45d53c..e3f0809 100644
--- a/chrome/browser/ui/views/tab_contents/render_view_context_menu_win.cc
+++ b/chrome/browser/ui/views/tab_contents/render_view_context_menu_win.cc
@@ -16,9 +16,9 @@
 using content::WebContents;
 
 RenderViewContextMenuWin::RenderViewContextMenuWin(
-    WebContents* web_contents,
+    content::RenderFrameHost* render_frame_host,
     const content::ContextMenuParams& params)
-    : RenderViewContextMenuViews(web_contents, params) {
+    : RenderViewContextMenuViews(render_frame_host, params) {
 }
 
 RenderViewContextMenuWin::~RenderViewContextMenuWin() {
@@ -26,9 +26,9 @@
 
 // static
 RenderViewContextMenuViews* RenderViewContextMenuViews::Create(
-    content::WebContents* web_contents,
+    content::RenderFrameHost* render_frame_host,
     const content::ContextMenuParams& params) {
-  return new RenderViewContextMenuWin(web_contents, params);
+  return new RenderViewContextMenuWin(render_frame_host, params);
 }
 
 bool RenderViewContextMenuWin::IsCommandIdVisible(int command_id) const {
diff --git a/chrome/browser/ui/views/tab_contents/render_view_context_menu_win.h b/chrome/browser/ui/views/tab_contents/render_view_context_menu_win.h
index 7e422fa3..35d9433 100644
--- a/chrome/browser/ui/views/tab_contents/render_view_context_menu_win.h
+++ b/chrome/browser/ui/views/tab_contents/render_view_context_menu_win.h
@@ -14,7 +14,7 @@
 // Windows specific implementation of the render view context menu.
 class RenderViewContextMenuWin : public RenderViewContextMenuViews {
  public:
-  RenderViewContextMenuWin(content::WebContents* web_contents,
+  RenderViewContextMenuWin(content::RenderFrameHost* render_frame_host,
                            const content::ContextMenuParams& params);
   virtual ~RenderViewContextMenuWin();
 
diff --git a/content/browser/frame_host/render_frame_host_delegate.h b/content/browser/frame_host/render_frame_host_delegate.h
index b364ec5..b23223e 100644
--- a/content/browser/frame_host/render_frame_host_delegate.h
+++ b/content/browser/frame_host/render_frame_host_delegate.h
@@ -14,6 +14,7 @@
 namespace content {
 class RenderFrameHost;
 class WebContents;
+struct ContextMenuParams;
 
 // An interface implemented by an object interested in knowing about the state
 // of the RenderFrameHost.
@@ -30,7 +31,12 @@
   virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) {}
 
   // Notification that a worker process has crashed.
-  virtual void WorkerCrashed() {}
+  virtual void WorkerCrashed(RenderFrameHost* render_frame_host) {}
+
+  // A context menu should be shown, to be built using the context information
+  // provided in the supplied params.
+  virtual void ShowContextMenu(RenderFrameHost* render_frame_host,
+                               const ContextMenuParams& params) {}
 
   // Return this object cast to a WebContents, if it is one. If the object is
   // not a WebContents, returns NULL.
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index ee130b9..98122c8 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -97,6 +97,16 @@
   return view->GetNativeView();
 }
 
+void RenderFrameHostImpl::NotifyContextMenuClosed(
+    const CustomContextMenuContext& context) {
+  Send(new FrameMsg_ContextMenuClosed(routing_id_, context));
+}
+
+void RenderFrameHostImpl::ExecuteCustomContextMenuCommand(
+    int action, const CustomContextMenuContext& context) {
+  Send(new FrameMsg_CustomContextMenuAction(routing_id_, context, action));
+}
+
 RenderViewHost* RenderFrameHostImpl::GetRenderViewHost() {
   return render_view_host_;
 }
@@ -124,6 +134,7 @@
     IPC_MESSAGE_HANDLER(FrameHostMsg_DidRedirectProvisionalLoad,
                         OnDidRedirectProvisionalLoad)
     IPC_MESSAGE_HANDLER(FrameHostMsg_SwapOut_ACK, OnSwapOutACK)
+    IPC_MESSAGE_HANDLER(FrameHostMsg_ContextMenu, OnContextMenu)
   IPC_END_MESSAGE_MAP_EX()
 
   if (!msg_is_ok) {
@@ -137,7 +148,7 @@
 }
 
 void RenderFrameHostImpl::Init() {
-  GetProcess()->ResumeRequestsForView(routing_id());
+  GetProcess()->ResumeRequestsForView(routing_id_);
 }
 
 void RenderFrameHostImpl::OnCreateChildFrame(int new_frame_routing_id,
@@ -178,7 +189,7 @@
 
 void RenderFrameHostImpl::SwapOut() {
   if (render_view_host_->IsRenderViewLive()) {
-    Send(new FrameMsg_SwapOut(routing_id()));
+    Send(new FrameMsg_SwapOut(routing_id_));
   } else {
     // Our RenderViewHost doesn't have a live renderer, so just skip the unload
     // event.
@@ -194,4 +205,20 @@
   frame_tree_node_->render_manager()->SwappedOutFrame(this);
 }
 
+void RenderFrameHostImpl::OnContextMenu(const ContextMenuParams& params) {
+  // Validate the URLs in |params|.  If the renderer can't request the URLs
+  // directly, don't show them in the context menu.
+  ContextMenuParams validated_params(params);
+  RenderProcessHost* process = GetProcess();
+
+  // We don't validate |unfiltered_link_url| so that this field can be used
+  // when users want to copy the original link URL.
+  process->FilterURL(true, &validated_params.link_url);
+  process->FilterURL(true, &validated_params.src_url);
+  process->FilterURL(false, &validated_params.page_url);
+  process->FilterURL(true, &validated_params.frame_url);
+
+  delegate_->ShowContextMenu(this, validated_params);
+}
+
 }  // namespace content
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 2430fecc..64864cb1 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -26,6 +26,7 @@
 class RenderFrameHostDelegate;
 class RenderProcessHost;
 class RenderViewHostImpl;
+struct ContextMenuParams;
 
 class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost {
  public:
@@ -38,6 +39,10 @@
   virtual RenderProcessHost* GetProcess() OVERRIDE;
   virtual int GetRoutingID() OVERRIDE;
   virtual gfx::NativeView GetNativeView() OVERRIDE;
+  virtual void NotifyContextMenuClosed(
+      const CustomContextMenuContext& context) OVERRIDE;
+  virtual void ExecuteCustomContextMenuCommand(
+      int action, const CustomContextMenuContext& context) OVERRIDE;
   virtual RenderViewHost* GetRenderViewHost() OVERRIDE;
 
   // IPC::Sender
@@ -106,6 +111,7 @@
                                     const GURL& source_url,
                                     const GURL& target_url);
   void OnSwapOutACK();
+  void OnContextMenu(const ContextMenuParams& params);
 
   // For now, RenderFrameHosts indirectly keep RenderViewHosts alive via a
   // refcount that calls Shutdown when it reaches zero.  This allows each
diff --git a/content/browser/renderer_host/render_view_host_delegate.h b/content/browser/renderer_host/render_view_host_delegate.h
index a728d1e..891bbde 100644
--- a/content/browser/renderer_host/render_view_host_delegate.h
+++ b/content/browser/renderer_host/render_view_host_delegate.h
@@ -54,7 +54,6 @@
 class SiteInstance;
 class WebContents;
 class WebContentsImpl;
-struct ContextMenuParams;
 struct FileChooserParams;
 struct GlobalRequestID;
 struct NativeWebKeyboardEvent;
@@ -394,10 +393,6 @@
   // Show the newly created full screen widget. Similar to above.
   virtual void ShowCreatedFullscreenWidget(int route_id) {}
 
-  // A context menu should be shown, to be built using the context information
-  // provided in the supplied params.
-  virtual void ShowContextMenu(const ContextMenuParams& params) {}
-
   // The render view has requested access to media devices listed in
   // |request|, and the client should grant or deny that permission by
   // calling |callback|.
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index d485fd9..752d34e 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -1238,7 +1238,6 @@
                         OnDocumentAvailableInMainFrame)
     IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentOnLoadCompletedInMainFrame,
                         OnDocumentOnLoadCompletedInMainFrame)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_ContextMenu, OnContextMenu)
     IPC_MESSAGE_HANDLER(ViewHostMsg_ToggleFullscreen, OnToggleFullscreen)
     IPC_MESSAGE_HANDLER(ViewHostMsg_OpenURL, OnOpenURL)
     IPC_MESSAGE_HANDLER(ViewHostMsg_DidContentsPreferredSizeChange,
@@ -1609,22 +1608,6 @@
   delegate_->DocumentOnLoadCompletedInMainFrame(this, page_id);
 }
 
-void RenderViewHostImpl::OnContextMenu(const ContextMenuParams& params) {
-  // Validate the URLs in |params|.  If the renderer can't request the URLs
-  // directly, don't show them in the context menu.
-  ContextMenuParams validated_params(params);
-  RenderProcessHost* process = GetProcess();
-
-  // We don't validate |unfiltered_link_url| so that this field can be used
-  // when users want to copy the original link URL.
-  process->FilterURL(true, &validated_params.link_url);
-  process->FilterURL(true, &validated_params.src_url);
-  process->FilterURL(false, &validated_params.page_url);
-  process->FilterURL(true, &validated_params.frame_url);
-
-  delegate_->ShowContextMenu(validated_params);
-}
-
 void RenderViewHostImpl::OnToggleFullscreen(bool enter_fullscreen) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   delegate_->ToggleFullscreenMode(enter_fullscreen);
@@ -2062,16 +2045,6 @@
   Send(new ViewMsg_DisableAutoResize(GetRoutingID(), new_size));
 }
 
-void RenderViewHostImpl::ExecuteCustomContextMenuCommand(
-    int action, const CustomContextMenuContext& context) {
-  Send(new ViewMsg_CustomContextMenuAction(GetRoutingID(), context, action));
-}
-
-void RenderViewHostImpl::NotifyContextMenuClosed(
-    const CustomContextMenuContext& context) {
-  Send(new ViewMsg_ContextMenuClosed(GetRoutingID(), context));
-}
-
 void RenderViewHostImpl::CopyImageAt(int x, int y) {
   Send(new ViewMsg_CopyImageAt(GetRoutingID(), x, y));
 }
diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h
index 52f36ea..f185fad 100644
--- a/content/browser/renderer_host/render_view_host_impl.h
+++ b/content/browser/renderer_host/render_view_host_impl.h
@@ -64,7 +64,6 @@
 class SessionStorageNamespace;
 class SessionStorageNamespaceImpl;
 class TestRenderViewHost;
-struct ContextMenuParams;
 struct FileChooserParams;
 struct Referrer;
 struct ShowDesktopNotificationHostMsgParams;
@@ -167,8 +166,6 @@
                                 const gfx::Size& max_size) OVERRIDE;
   virtual void DisableAutoResize(const gfx::Size& new_size) OVERRIDE;
   virtual void EnablePreferredSizeMode() OVERRIDE;
-  virtual void ExecuteCustomContextMenuCommand(
-      int action, const CustomContextMenuContext& context) OVERRIDE;
   virtual void ExecuteMediaPlayerActionAtLocation(
       const gfx::Point& location,
       const blink::WebMediaPlayerAction& action) OVERRIDE;
@@ -193,8 +190,6 @@
   virtual void InsertCSS(const base::string16& frame_xpath,
                          const std::string& css) OVERRIDE;
   virtual bool IsRenderViewLive() const OVERRIDE;
-  virtual void NotifyContextMenuClosed(
-      const CustomContextMenuContext& context) OVERRIDE;
   virtual void NotifyMoveOrResizeStarted() OVERRIDE;
   virtual void ReloadFrame() OVERRIDE;
   virtual void SetWebUIProperty(const std::string& name,
@@ -523,7 +518,6 @@
   void OnDidDisownOpener();
   void OnDocumentAvailableInMainFrame();
   void OnDocumentOnLoadCompletedInMainFrame(int32 page_id);
-  void OnContextMenu(const ContextMenuParams& params);
   void OnToggleFullscreen(bool enter_fullscreen);
   void OnOpenURL(const ViewHostMsg_OpenURL_Params& params);
   void OnDidContentsPreferredSizeChange(const gfx::Size& new_size);
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 0c2cce58..d86c3975 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -1528,14 +1528,6 @@
   return widget_host_view;
 }
 
-void WebContentsImpl::ShowContextMenu(const ContextMenuParams& params) {
-  // Allow WebContentsDelegates to handle the context menu operation first.
-  if (delegate_ && delegate_->HandleContextMenu(params))
-    return;
-
-  render_view_host_delegate_view_->ShowContextMenu(params);
-}
-
 void WebContentsImpl::RequestMediaAccessPermission(
     const MediaStreamRequest& request,
     const MediaResponseCallback& callback) {
@@ -2684,11 +2676,20 @@
                     RenderFrameDeleted(render_frame_host));
 }
 
-void WebContentsImpl::WorkerCrashed() {
+void WebContentsImpl::WorkerCrashed(RenderFrameHost* render_frame_host) {
   if (delegate_)
     delegate_->WorkerCrashed(this);
 }
 
+void WebContentsImpl::ShowContextMenu(RenderFrameHost* render_frame_host,
+                                      const ContextMenuParams& params) {
+  // Allow WebContentsDelegates to handle the context menu operation first.
+  if (delegate_ && delegate_->HandleContextMenu(params))
+    return;
+
+  render_view_host_delegate_view_->ShowContextMenu(render_frame_host, params);
+}
+
 WebContents* WebContentsImpl::GetAsWebContents() {
   return this;
 }
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 9f41ca6a..ccb10ac 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -304,7 +304,9 @@
                                  const IPC::Message& message) OVERRIDE;
   virtual void RenderFrameCreated(RenderFrameHost* render_frame_host) OVERRIDE;
   virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) OVERRIDE;
-  virtual void WorkerCrashed() OVERRIDE;
+  virtual void WorkerCrashed(RenderFrameHost* render_frame_host) OVERRIDE;
+  virtual void ShowContextMenu(RenderFrameHost* render_frame_host,
+                               const ContextMenuParams& params) OVERRIDE;
   virtual WebContents* GetAsWebContents() OVERRIDE;
 
   // RenderViewHostDelegate ----------------------------------------------------
@@ -438,7 +440,6 @@
   virtual void ShowCreatedWidget(int route_id,
                                  const gfx::Rect& initial_pos) OVERRIDE;
   virtual void ShowCreatedFullscreenWidget(int route_id) OVERRIDE;
-  virtual void ShowContextMenu(const ContextMenuParams& params) OVERRIDE;
   virtual void RequestMediaAccessPermission(
       const MediaStreamRequest& request,
       const MediaResponseCallback& callback) OVERRIDE;
diff --git a/content/browser/web_contents/web_contents_view_android.cc b/content/browser/web_contents/web_contents_view_android.cc
index 21fcf542..fc024b7 100644
--- a/content/browser/web_contents/web_contents_view_android.cc
+++ b/content/browser/web_contents/web_contents_view_android.cc
@@ -178,9 +178,9 @@
 }
 
 void WebContentsViewAndroid::ShowContextMenu(
-    const ContextMenuParams& params) {
+    RenderFrameHost* render_frame_host, const ContextMenuParams& params) {
   if (delegate_)
-    delegate_->ShowContextMenu(params);
+    delegate_->ShowContextMenu(render_frame_host, params);
 }
 
 void WebContentsViewAndroid::ShowPopupMenu(
diff --git a/content/browser/web_contents/web_contents_view_android.h b/content/browser/web_contents/web_contents_view_android.h
index 48cfee9..3d043ec 100644
--- a/content/browser/web_contents/web_contents_view_android.h
+++ b/content/browser/web_contents/web_contents_view_android.h
@@ -63,7 +63,8 @@
   virtual void SetOverscrollControllerEnabled(bool enabled) OVERRIDE;
 
   // Backend implementation of RenderViewHostDelegateView.
-  virtual void ShowContextMenu(const ContextMenuParams& params) OVERRIDE;
+  virtual void ShowContextMenu(RenderFrameHost* render_frame_host,
+                               const ContextMenuParams& params) OVERRIDE;
   virtual void ShowPopupMenu(const gfx::Rect& bounds,
                              int item_height,
                              double item_font_size,
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc
index 4ef75d9..f06f827 100644
--- a/content/browser/web_contents/web_contents_view_aura.cc
+++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -1401,11 +1401,12 @@
 ////////////////////////////////////////////////////////////////////////////////
 // WebContentsViewAura, RenderViewHostDelegateView implementation:
 
-void WebContentsViewAura::ShowContextMenu(const ContextMenuParams& params) {
+void WebContentsViewAura::ShowContextMenu(RenderFrameHost* render_frame_host,
+                                          const ContextMenuParams& params) {
   if (touch_editable_)
     touch_editable_->EndTouchEditing(false);
   if (delegate_) {
-    delegate_->ShowContextMenu(params);
+    delegate_->ShowContextMenu(render_frame_host, params);
     // WARNING: we may have been deleted during the call to ShowContextMenu().
   }
 }
diff --git a/content/browser/web_contents/web_contents_view_aura.h b/content/browser/web_contents/web_contents_view_aura.h
index a0597d3..f02bdaec 100644
--- a/content/browser/web_contents/web_contents_view_aura.h
+++ b/content/browser/web_contents/web_contents_view_aura.h
@@ -124,7 +124,8 @@
   virtual void SetOverscrollControllerEnabled(bool enabled) OVERRIDE;
 
   // Overridden from RenderViewHostDelegateView:
-  virtual void ShowContextMenu(const ContextMenuParams& params) OVERRIDE;
+  virtual void ShowContextMenu(RenderFrameHost* render_frame_host,
+                               const ContextMenuParams& params) OVERRIDE;
   virtual void ShowPopupMenu(const gfx::Rect& bounds,
                              int item_height,
                              double item_font_size,
diff --git a/content/browser/web_contents/web_contents_view_gtk.cc b/content/browser/web_contents/web_contents_view_gtk.cc
index 516ada0..995f82d 100644
--- a/content/browser/web_contents/web_contents_view_gtk.cc
+++ b/content/browser/web_contents/web_contents_view_gtk.cc
@@ -362,9 +362,10 @@
   return TRUE;
 }
 
-void WebContentsViewGtk::ShowContextMenu(const ContextMenuParams& params) {
+void WebContentsViewGtk::ShowContextMenu(RenderFrameHost* render_frame_host,
+                                         const ContextMenuParams& params) {
   if (delegate_)
-    delegate_->ShowContextMenu(params);
+    delegate_->ShowContextMenu(render_frame_host, params);
   else
     DLOG(ERROR) << "Cannot show context menus without a delegate.";
 }
diff --git a/content/browser/web_contents/web_contents_view_gtk.h b/content/browser/web_contents/web_contents_view_gtk.h
index 7a8d25e..d536f65 100644
--- a/content/browser/web_contents/web_contents_view_gtk.h
+++ b/content/browser/web_contents/web_contents_view_gtk.h
@@ -72,7 +72,8 @@
   virtual void SetOverscrollControllerEnabled(bool enabled) OVERRIDE;
 
   // Backend implementation of RenderViewHostDelegateView.
-  virtual void ShowContextMenu(const ContextMenuParams& params) OVERRIDE;
+  virtual void ShowContextMenu(RenderFrameHost* render_frame_host,
+                               const ContextMenuParams& params) OVERRIDE;
   virtual void ShowPopupMenu(const gfx::Rect& bounds,
                              int item_height,
                              double item_font_size,
diff --git a/content/browser/web_contents/web_contents_view_guest.cc b/content/browser/web_contents/web_contents_view_guest.cc
index 475e864..aaebcaf 100644
--- a/content/browser/web_contents/web_contents_view_guest.cc
+++ b/content/browser/web_contents/web_contents_view_guest.cc
@@ -217,7 +217,8 @@
 void WebContentsViewGuest::TakeFocus(bool reverse) {
 }
 
-void WebContentsViewGuest::ShowContextMenu(const ContextMenuParams& params) {
+void WebContentsViewGuest::ShowContextMenu(RenderFrameHost* render_frame_host,
+                                           const ContextMenuParams& params) {
 #if defined(USE_AURA) || defined(OS_WIN)
   // Context menu uses ScreenPositionClient::ConvertPointToScreen() in aura and
   // windows to calculate popup position. Guest's native view
@@ -234,9 +235,10 @@
   ContextMenuParams params_in_embedder = params;
   params_in_embedder.x += offset.x();
   params_in_embedder.y += offset.y();
-  platform_view_delegate_view_->ShowContextMenu(params_in_embedder);
+  platform_view_delegate_view_->ShowContextMenu(
+      render_frame_host, params_in_embedder);
 #else
-  platform_view_delegate_view_->ShowContextMenu(params);
+  platform_view_delegate_view_->ShowContextMenu(render_frame_host, params);
 #endif  // defined(USE_AURA) || defined(OS_WIN)
 }
 
diff --git a/content/browser/web_contents/web_contents_view_guest.h b/content/browser/web_contents/web_contents_view_guest.h
index 68fb473..3493231 100644
--- a/content/browser/web_contents/web_contents_view_guest.h
+++ b/content/browser/web_contents/web_contents_view_guest.h
@@ -78,7 +78,8 @@
 #endif
 
   // Backend implementation of RenderViewHostDelegateView.
-  virtual void ShowContextMenu(const ContextMenuParams& params) OVERRIDE;
+  virtual void ShowContextMenu(RenderFrameHost* render_frame_host,
+                               const ContextMenuParams& params) OVERRIDE;
   virtual void ShowPopupMenu(const gfx::Rect& bounds,
                              int item_height,
                              double item_font_size,
diff --git a/content/browser/web_contents/web_contents_view_mac.h b/content/browser/web_contents/web_contents_view_mac.h
index 0dadbad..be6df61b 100644
--- a/content/browser/web_contents/web_contents_view_mac.h
+++ b/content/browser/web_contents/web_contents_view_mac.h
@@ -99,7 +99,8 @@
   virtual void CloseTabAfterEventTracking() OVERRIDE;
 
   // Backend implementation of RenderViewHostDelegateView.
-  virtual void ShowContextMenu(const ContextMenuParams& params) OVERRIDE;
+  virtual void ShowContextMenu(content::RenderFrameHost* render_frame_host,
+                               const ContextMenuParams& params) OVERRIDE;
   virtual void ShowPopupMenu(const gfx::Rect& bounds,
                              int item_height,
                              double item_font_size,
diff --git a/content/browser/web_contents/web_contents_view_mac.mm b/content/browser/web_contents/web_contents_view_mac.mm
index a58a658..7d960b51 100644
--- a/content/browser/web_contents/web_contents_view_mac.mm
+++ b/content/browser/web_contents/web_contents_view_mac.mm
@@ -230,7 +230,9 @@
   }
 }
 
-void WebContentsViewMac::ShowContextMenu(const ContextMenuParams& params) {
+void WebContentsViewMac::ShowContextMenu(
+    content::RenderFrameHost* render_frame_host,
+    const ContextMenuParams& params) {
   // Allow delegates to handle the context menu operation first.
   if (web_contents_->GetDelegate() &&
       web_contents_->GetDelegate()->HandleContextMenu(params)) {
@@ -238,7 +240,7 @@
   }
 
   if (delegate())
-    delegate()->ShowContextMenu(params);
+    delegate()->ShowContextMenu(render_frame_host, params);
   else
     DLOG(ERROR) << "Cannot show context menus without a delegate.";
 }
diff --git a/content/browser/worker_host/worker_process_host.cc b/content/browser/worker_host/worker_process_host.cc
index fe4de91..2ba32e2 100644
--- a/content/browser/worker_host/worker_process_host.cc
+++ b/content/browser/worker_host/worker_process_host.cc
@@ -84,7 +84,7 @@
   RenderFrameHostImpl* host =
       RenderFrameHostImpl::FromID(render_process_unique_id, render_frame_id);
   if (host)
-    host->delegate()->WorkerCrashed();
+    host->delegate()->WorkerCrashed(host);
 }
 
 void WorkerCreatedCallback(int render_process_id,
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index c6c9d5a..625b0e0 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -8,6 +8,7 @@
 #include "content/common/content_export.h"
 #include "content/common/frame_param.h"
 #include "content/public/common/common_param_traits.h"
+#include "content/public/common/context_menu_params.h"
 #include "ipc/ipc_message_macros.h"
 #include "url/gurl.h"
 
@@ -16,6 +17,53 @@
 
 #define IPC_MESSAGE_START FrameMsgStart
 
+IPC_ENUM_TRAITS(blink::WebContextMenuData::MediaType)
+IPC_ENUM_TRAITS(ui::MenuSourceType)
+
+IPC_STRUCT_TRAITS_BEGIN(content::ContextMenuParams)
+  IPC_STRUCT_TRAITS_MEMBER(media_type)
+  IPC_STRUCT_TRAITS_MEMBER(x)
+  IPC_STRUCT_TRAITS_MEMBER(y)
+  IPC_STRUCT_TRAITS_MEMBER(link_url)
+  IPC_STRUCT_TRAITS_MEMBER(link_text)
+  IPC_STRUCT_TRAITS_MEMBER(unfiltered_link_url)
+  IPC_STRUCT_TRAITS_MEMBER(src_url)
+  IPC_STRUCT_TRAITS_MEMBER(has_image_contents)
+  IPC_STRUCT_TRAITS_MEMBER(page_url)
+  IPC_STRUCT_TRAITS_MEMBER(keyword_url)
+  IPC_STRUCT_TRAITS_MEMBER(frame_url)
+  IPC_STRUCT_TRAITS_MEMBER(frame_id)
+  IPC_STRUCT_TRAITS_MEMBER(frame_page_state)
+  IPC_STRUCT_TRAITS_MEMBER(media_flags)
+  IPC_STRUCT_TRAITS_MEMBER(selection_text)
+  IPC_STRUCT_TRAITS_MEMBER(misspelled_word)
+  IPC_STRUCT_TRAITS_MEMBER(misspelling_hash)
+  IPC_STRUCT_TRAITS_MEMBER(dictionary_suggestions)
+  IPC_STRUCT_TRAITS_MEMBER(speech_input_enabled)
+  IPC_STRUCT_TRAITS_MEMBER(spellcheck_enabled)
+  IPC_STRUCT_TRAITS_MEMBER(is_editable)
+  IPC_STRUCT_TRAITS_MEMBER(writing_direction_default)
+  IPC_STRUCT_TRAITS_MEMBER(writing_direction_left_to_right)
+  IPC_STRUCT_TRAITS_MEMBER(writing_direction_right_to_left)
+  IPC_STRUCT_TRAITS_MEMBER(edit_flags)
+  IPC_STRUCT_TRAITS_MEMBER(security_info)
+  IPC_STRUCT_TRAITS_MEMBER(frame_charset)
+  IPC_STRUCT_TRAITS_MEMBER(referrer_policy)
+  IPC_STRUCT_TRAITS_MEMBER(custom_context)
+  IPC_STRUCT_TRAITS_MEMBER(custom_items)
+  IPC_STRUCT_TRAITS_MEMBER(source_type)
+#if defined(OS_ANDROID)
+  IPC_STRUCT_TRAITS_MEMBER(selection_start)
+  IPC_STRUCT_TRAITS_MEMBER(selection_end)
+#endif
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(content::CustomContextMenuContext)
+  IPC_STRUCT_TRAITS_MEMBER(is_pepper_menu)
+  IPC_STRUCT_TRAITS_MEMBER(request_id)
+  IPC_STRUCT_TRAITS_MEMBER(render_widget_id)
+IPC_STRUCT_TRAITS_END()
+
 IPC_STRUCT_BEGIN(FrameHostMsg_DidFailProvisionalLoadWithError_Params)
   // The frame ID for the failure report.
   IPC_STRUCT_MEMBER(int64, frame_id)
@@ -61,6 +109,16 @@
 // contents has terminated.
 IPC_MESSAGE_ROUTED0(FrameMsg_ChildFrameProcessGone)
 
+// Sent in response to a FrameHostMsg_ContextMenu to let the renderer know that
+// the menu has been closed.
+IPC_MESSAGE_ROUTED1(FrameMsg_ContextMenuClosed,
+                    content::CustomContextMenuContext /* custom_context */)
+
+// Executes custom context menu action that was provided from Blink.
+IPC_MESSAGE_ROUTED2(FrameMsg_CustomContextMenuAction,
+                    content::CustomContextMenuContext /* custom_context */,
+                    unsigned /* action */)
+
 // -----------------------------------------------------------------------------
 // Messages sent from the renderer to the browser.
 
@@ -170,3 +228,9 @@
 // running the unload event handler. Expects a SwapOut_ACK message when
 // finished.
 IPC_MESSAGE_ROUTED0(FrameMsg_SwapOut)
+
+// Used to tell the parent that the user right clicked on an area of the
+// content area, and a context menu should be shown for it. The params
+// object contains information about the node(s) that were selected when the
+// user right clicked.
+IPC_MESSAGE_ROUTED1(FrameHostMsg_ContextMenu, content::ContextMenuParams)
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index 9d3d6860..c646fc2 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -22,7 +22,6 @@
 #include "content/port/common/input_event_ack_state.h"
 #include "content/public/common/color_suggestion.h"
 #include "content/public/common/common_param_traits.h"
-#include "content/public/common/context_menu_params.h"
 #include "content/public/common/favicon_url.h"
 #include "content/public/common/file_chooser_params.h"
 #include "content/public/common/frame_navigate_params.h"
@@ -75,7 +74,6 @@
 
 IPC_ENUM_TRAITS(AccessibilityMode)
 IPC_ENUM_TRAITS(ViewMsg_Navigate_Type::Value)
-IPC_ENUM_TRAITS(blink::WebContextMenuData::MediaType)
 IPC_ENUM_TRAITS(blink::WebMediaPlayerAction::Type)
 IPC_ENUM_TRAITS(blink::WebPluginAction::Type)
 IPC_ENUM_TRAITS(blink::WebPopupType)
@@ -95,7 +93,6 @@
 IPC_ENUM_TRAITS(content::ThreeDAPIType)
 IPC_ENUM_TRAITS(media::ChannelLayout)
 IPC_ENUM_TRAITS(media::MediaLogEvent::Type)
-IPC_ENUM_TRAITS(ui::MenuSourceType)
 IPC_ENUM_TRAITS_MAX_VALUE(ui::TextInputMode, ui::TEXT_INPUT_MODE_MAX)
 IPC_ENUM_TRAITS(ui::TextInputType)
 
@@ -173,49 +170,6 @@
   IPC_STRUCT_TRAITS_MEMBER(label)
 IPC_STRUCT_TRAITS_END()
 
-IPC_STRUCT_TRAITS_BEGIN(content::ContextMenuParams)
-  IPC_STRUCT_TRAITS_MEMBER(media_type)
-  IPC_STRUCT_TRAITS_MEMBER(x)
-  IPC_STRUCT_TRAITS_MEMBER(y)
-  IPC_STRUCT_TRAITS_MEMBER(link_url)
-  IPC_STRUCT_TRAITS_MEMBER(link_text)
-  IPC_STRUCT_TRAITS_MEMBER(unfiltered_link_url)
-  IPC_STRUCT_TRAITS_MEMBER(src_url)
-  IPC_STRUCT_TRAITS_MEMBER(has_image_contents)
-  IPC_STRUCT_TRAITS_MEMBER(page_url)
-  IPC_STRUCT_TRAITS_MEMBER(keyword_url)
-  IPC_STRUCT_TRAITS_MEMBER(frame_url)
-  IPC_STRUCT_TRAITS_MEMBER(frame_page_state)
-  IPC_STRUCT_TRAITS_MEMBER(media_flags)
-  IPC_STRUCT_TRAITS_MEMBER(selection_text)
-  IPC_STRUCT_TRAITS_MEMBER(misspelled_word)
-  IPC_STRUCT_TRAITS_MEMBER(misspelling_hash)
-  IPC_STRUCT_TRAITS_MEMBER(dictionary_suggestions)
-  IPC_STRUCT_TRAITS_MEMBER(speech_input_enabled)
-  IPC_STRUCT_TRAITS_MEMBER(spellcheck_enabled)
-  IPC_STRUCT_TRAITS_MEMBER(is_editable)
-  IPC_STRUCT_TRAITS_MEMBER(writing_direction_default)
-  IPC_STRUCT_TRAITS_MEMBER(writing_direction_left_to_right)
-  IPC_STRUCT_TRAITS_MEMBER(writing_direction_right_to_left)
-  IPC_STRUCT_TRAITS_MEMBER(edit_flags)
-  IPC_STRUCT_TRAITS_MEMBER(security_info)
-  IPC_STRUCT_TRAITS_MEMBER(frame_charset)
-  IPC_STRUCT_TRAITS_MEMBER(referrer_policy)
-  IPC_STRUCT_TRAITS_MEMBER(custom_context)
-  IPC_STRUCT_TRAITS_MEMBER(custom_items)
-  IPC_STRUCT_TRAITS_MEMBER(source_type)
-#if defined(OS_ANDROID)
-  IPC_STRUCT_TRAITS_MEMBER(selection_start)
-  IPC_STRUCT_TRAITS_MEMBER(selection_end)
-#endif
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(content::CustomContextMenuContext)
-  IPC_STRUCT_TRAITS_MEMBER(is_pepper_menu)
-  IPC_STRUCT_TRAITS_MEMBER(request_id)
-  IPC_STRUCT_TRAITS_MEMBER(render_widget_id)
-IPC_STRUCT_TRAITS_END()
-
 IPC_STRUCT_TRAITS_BEGIN(content::FaviconURL)
   IPC_STRUCT_TRAITS_MEMBER(icon_url)
   IPC_STRUCT_TRAITS_MEMBER(icon_type)
@@ -916,16 +870,6 @@
 IPC_MESSAGE_ROUTED1(ViewMsg_SetInitialFocus,
                     bool /* reverse */)
 
-// Executes custom context menu action that was provided from WebKit.
-IPC_MESSAGE_ROUTED2(ViewMsg_CustomContextMenuAction,
-                    content::CustomContextMenuContext /* custom_context */,
-                    unsigned /* action */)
-
-// Sent in response to a ViewHostMsg_ContextMenu to let the renderer know that
-// the menu has been closed.
-IPC_MESSAGE_ROUTED1(ViewMsg_ContextMenuClosed,
-                    content::CustomContextMenuContext /* custom_context */)
-
 // Sent to inform the renderer to invoke a context menu.
 // The parameter specifies the location in the render view's coordinates.
 IPC_MESSAGE_ROUTED1(ViewMsg_ShowContextMenu,
@@ -1490,12 +1434,6 @@
 IPC_MESSAGE_ROUTED1(ViewHostMsg_FrameNavigate,
                     ViewHostMsg_FrameNavigate_Params)
 
-// Used to tell the parent that the user right clicked on an area of the
-// content area, and a context menu should be shown for it. The params
-// object contains information about the node(s) that were selected when the
-// user right clicked.
-IPC_MESSAGE_ROUTED1(ViewHostMsg_ContextMenu, content::ContextMenuParams)
-
 // Message to show a popup menu using native cocoa controls (Mac only).
 IPC_MESSAGE_ROUTED1(ViewHostMsg_ShowPopup,
                     ViewHostMsg_ShowPopup_Params)
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index d3ca4b4..bb64aee 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -561,8 +561,8 @@
         'renderer/pepper/mock_resource.h',
         'renderer/pepper/pepper_broker_unittest.cc',
         'renderer/pepper/v8_var_converter_unittest.cc',
+        'renderer/render_frame_impl_unittest.cc',
         'renderer/render_thread_impl_unittest.cc',
-        'renderer/render_view_impl_unittest.cc',
         'renderer/render_widget_unittest.cc',
         'renderer/skia_benchmarking_extension_unittest.cc',
         'renderer/v8_value_converter_impl_unittest.cc',
diff --git a/content/port/browser/render_view_host_delegate_view.h b/content/port/browser/render_view_host_delegate_view.h
index c6fb2e7..4991926 100644
--- a/content/port/browser/render_view_host_delegate_view.h
+++ b/content/port/browser/render_view_host_delegate_view.h
@@ -21,6 +21,7 @@
 }
 
 namespace content {
+class RenderFrameHost;
 struct ContextMenuParams;
 struct DropData;
 struct MenuItem;
@@ -32,7 +33,8 @@
  public:
   // A context menu should be shown, to be built using the context information
   // provided in the supplied params.
-  virtual void ShowContextMenu(const ContextMenuParams& params) {}
+  virtual void ShowContextMenu(RenderFrameHost* render_frame_host,
+                               const ContextMenuParams& params) {}
 
   // Shows a popup menu with the specified items.
   // This method should call RenderViewHost::DidSelectPopupMenuItem[s]() or
diff --git a/content/public/browser/render_frame_host.h b/content/public/browser/render_frame_host.h
index e33b12d..0bf1c28 100644
--- a/content/public/browser/render_frame_host.h
+++ b/content/public/browser/render_frame_host.h
@@ -14,6 +14,7 @@
 class RenderProcessHost;
 class RenderViewHost;
 class SiteInstance;
+struct CustomContextMenuContext;
 
 // The interface provides a communication conduit with a frame in the renderer.
 class CONTENT_EXPORT RenderFrameHost : public IPC::Listener,
@@ -36,6 +37,14 @@
   // Returns the associated widget's native view.
   virtual gfx::NativeView GetNativeView() = 0;
 
+  // Let the renderer know that the menu has been closed.
+  virtual void NotifyContextMenuClosed(
+      const CustomContextMenuContext& context) = 0;
+
+  // Executes custom context menu action that was provided from Blink.
+  virtual void ExecuteCustomContextMenuCommand(
+      int action, const CustomContextMenuContext& context) = 0;
+
   // Temporary until we get rid of RenderViewHost.
   virtual RenderViewHost* GetRenderViewHost() = 0;
 
diff --git a/content/public/browser/render_view_host.h b/content/public/browser/render_view_host.h
index fb6e852..4e40724 100644
--- a/content/public/browser/render_view_host.h
+++ b/content/public/browser/render_view_host.h
@@ -46,7 +46,6 @@
 class RenderViewHostDelegate;
 class SessionStorageNamespace;
 class SiteInstance;
-struct CustomContextMenuContext;
 struct DropData;
 
 // A RenderViewHost is responsible for creating and talking to a RenderView
@@ -153,10 +152,6 @@
   // Instructs the RenderView to send back updates to the preferred size.
   virtual void EnablePreferredSizeMode() = 0;
 
-  // Executes custom context menu action that was provided from WebKit.
-  virtual void ExecuteCustomContextMenuCommand(
-      int action, const CustomContextMenuContext& context) = 0;
-
   // Tells the renderer to perform the given action on the media player
   // located at the given point.
   virtual void ExecuteMediaPlayerActionAtLocation(
@@ -216,10 +211,6 @@
   // because it is overridden by TestRenderViewHost.
   virtual bool IsRenderViewLive() const = 0;
 
-  // Let the renderer know that the menu has been closed.
-  virtual void NotifyContextMenuClosed(
-      const CustomContextMenuContext& context) = 0;
-
   // Notification that a move or resize renderer's containing window has
   // started.
   virtual void NotifyMoveOrResizeStarted() = 0;
diff --git a/content/public/browser/web_contents_view_delegate.h b/content/public/browser/web_contents_view_delegate.h
index 0e61017b..f813291 100644
--- a/content/public/browser/web_contents_view_delegate.h
+++ b/content/public/browser/web_contents_view_delegate.h
@@ -27,7 +27,7 @@
 }
 
 namespace content {
-
+class RenderFrameHost;
 class RenderWidgetHost;
 class WebDragDestDelegate;
 struct ContextMenuParams;
@@ -42,7 +42,8 @@
   virtual WebDragDestDelegate* GetDragDestDelegate() = 0;
 
   // Shows a context menu.
-  virtual void ShowContextMenu(const content::ContextMenuParams& params) = 0;
+  virtual void ShowContextMenu(RenderFrameHost* render_frame_host,
+                               const ContextMenuParams& params) = 0;
 
 #if defined(OS_WIN) || defined(USE_AURA)
   // These methods allow the embedder to intercept WebContentsViewWin's
diff --git a/content/public/renderer/render_view_observer.h b/content/public/renderer/render_view_observer.h
index 63fdbc8..9a7956e 100644
--- a/content/public/renderer/render_view_observer.h
+++ b/content/public/renderer/render_view_observer.h
@@ -31,7 +31,6 @@
 class WebNode;
 class WebTouchEvent;
 class WebURL;
-struct WebContextMenuData;
 struct WebURLError;
 }
 
@@ -85,9 +84,6 @@
   virtual void ZoomLevelChanged() {};
   virtual void DidChangeScrollOffset(blink::WebFrame* frame) {}
   virtual void DraggableRegionsChanged(blink::WebFrame* frame) {}
-  virtual void DidRequestShowContextMenu(
-      blink::WebFrame* frame,
-      const blink::WebContextMenuData& data) {}
   virtual void DidCommitCompositorFrame() {}
   virtual void DidUpdateLayout() {}
 
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index f0c880f0..8ea6423 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -24,8 +24,11 @@
 #include "content/common/view_messages.h"
 #include "content/public/common/content_constants.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/common/context_menu_params.h"
 #include "content/public/common/url_constants.h"
+#include "content/public/common/url_utils.h"
 #include "content/public/renderer/content_renderer_client.h"
+#include "content/public/renderer/context_menu_client.h"
 #include "content/public/renderer/document_state.h"
 #include "content/public/renderer/navigation_state.h"
 #include "content/public/renderer/render_frame_observer.h"
@@ -33,6 +36,7 @@
 #include "content/renderer/browser_plugin/browser_plugin.h"
 #include "content/renderer/browser_plugin/browser_plugin_manager.h"
 #include "content/renderer/child_frame_compositing_helper.h"
+#include "content/renderer/context_menu_params_builder.h"
 #include "content/renderer/internal_document_state_data.h"
 #include "content/renderer/npapi/plugin_channel_host.h"
 #include "content/renderer/render_thread_impl.h"
@@ -72,6 +76,7 @@
 #include "content/renderer/media/rtc_peer_connection_handler.h"
 #endif
 
+using blink::WebContextMenuData;
 using blink::WebDataSource;
 using blink::WebDocument;
 using blink::WebFrame;
@@ -392,6 +397,9 @@
     IPC_MESSAGE_HANDLER_GENERIC(FrameMsg_CompositorFrameSwapped,
                                 OnCompositorFrameSwapped(msg))
     IPC_MESSAGE_HANDLER(FrameMsg_ChildFrameProcessGone, OnChildFrameProcessGone)
+    IPC_MESSAGE_HANDLER(FrameMsg_ContextMenuClosed, OnContextMenuClosed)
+    IPC_MESSAGE_HANDLER(FrameMsg_CustomContextMenuAction,
+                        OnCustomContextMenuAction)
   IPC_END_MESSAGE_MAP_EX()
 
   if (!msg_is_ok) {
@@ -475,6 +483,56 @@
                                                 param.a.producing_host_id);
 }
 
+void RenderFrameImpl::OnContextMenuClosed(
+    const CustomContextMenuContext& custom_context) {
+  if (custom_context.request_id) {
+    // External request, should be in our map.
+    ContextMenuClient* client =
+        pending_context_menus_.Lookup(custom_context.request_id);
+    if (client) {
+      client->OnMenuClosed(custom_context.request_id);
+      pending_context_menus_.Remove(custom_context.request_id);
+    }
+  } else {
+    // Internal request, forward to WebKit.
+    render_view_->context_menu_node_.reset();
+  }
+}
+
+void RenderFrameImpl::OnCustomContextMenuAction(
+    const CustomContextMenuContext& custom_context,
+    unsigned action) {
+  if (custom_context.request_id) {
+    // External context menu request, look in our map.
+    ContextMenuClient* client =
+        pending_context_menus_.Lookup(custom_context.request_id);
+    if (client)
+      client->OnMenuAction(custom_context.request_id, action);
+  } else {
+    // Internal request, forward to WebKit.
+    render_view_->webview()->performCustomContextMenuAction(action);
+  }
+}
+
+bool RenderFrameImpl::ShouldUpdateSelectionTextFromContextMenuParams(
+    const base::string16& selection_text,
+    size_t selection_text_offset,
+    const gfx::Range& selection_range,
+    const ContextMenuParams& params) {
+  base::string16 trimmed_selection_text;
+  if (!selection_text.empty() && !selection_range.is_empty()) {
+    const int start = selection_range.GetMin() - selection_text_offset;
+    const size_t length = selection_range.length();
+    if (start >= 0 && start + length <= selection_text.length()) {
+      TrimWhitespace(selection_text.substr(start, length), TRIM_ALL,
+                     &trimmed_selection_text);
+    }
+  }
+  base::string16 trimmed_params_text;
+  TrimWhitespace(params.selection_text, TRIM_ALL, &trimmed_params_text);
+  return trimmed_params_text != trimmed_selection_text;
+}
+
 void RenderFrameImpl::DidCommitCompositorFrame() {
   if (compositing_helper_)
     compositing_helper_->DidCommitCompositorFrame();
@@ -499,11 +557,16 @@
 
 int RenderFrameImpl::ShowContextMenu(ContextMenuClient* client,
                                      const ContextMenuParams& params) {
-  return render_view_->ShowContextMenu(client, params);
+  DCHECK(client);  // A null client means "internal" when we issue callbacks.
+  ContextMenuParams our_params(params);
+  our_params.custom_context.request_id = pending_context_menus_.Add(client);
+  Send(new FrameHostMsg_ContextMenu(routing_id_, our_params));
+  return our_params.custom_context.request_id;
 }
 
 void RenderFrameImpl::CancelContextMenu(int request_id) {
-  return render_view_->CancelContextMenu(request_id);
+  DCHECK(pending_context_menus_.Lookup(request_id));
+  pending_context_menus_.Remove(request_id);
 }
 
 blink::WebPlugin* RenderFrameImpl::CreatePlugin(
@@ -1508,6 +1571,59 @@
       arb_robustness_status_code));
 }
 
+void RenderFrameImpl::showContextMenu(const blink::WebContextMenuData& data) {
+  ContextMenuParams params = ContextMenuParamsBuilder::Build(data);
+  params.source_type = GetRenderWidget()->context_menu_source_type();
+  if (params.source_type == ui::MENU_SOURCE_TOUCH_EDIT_MENU) {
+    params.x = GetRenderWidget()->touch_editing_context_menu_location().x();
+    params.y = GetRenderWidget()->touch_editing_context_menu_location().y();
+  }
+  GetRenderWidget()->OnShowHostContextMenu(&params);
+
+  // Plugins, e.g. PDF, don't currently update the render view when their
+  // selected text changes, but the context menu params do contain the updated
+  // selection. If that's the case, update the render view's state just prior
+  // to showing the context menu.
+  // TODO(asvitkine): http://crbug.com/152432
+  if (ShouldUpdateSelectionTextFromContextMenuParams(
+          render_view_->selection_text_,
+          render_view_->selection_text_offset_,
+          render_view_->selection_range_,
+          params)) {
+    render_view_->selection_text_ = params.selection_text;
+    // TODO(asvitkine): Text offset and range is not available in this case.
+    render_view_->selection_text_offset_ = 0;
+    render_view_->selection_range_ =
+        gfx::Range(0, render_view_->selection_text_.length());
+    Send(new ViewHostMsg_SelectionChanged(
+        routing_id_,
+        render_view_->selection_text_,
+        render_view_->selection_text_offset_,
+        render_view_->selection_range_));
+  }
+
+  params.frame_id = frame_->identifier();
+
+  // Serializing a GURL longer than kMaxURLChars will fail, so don't do
+  // it.  We replace it with an empty GURL so the appropriate items are disabled
+  // in the context menu.
+  // TODO(jcivelli): http://crbug.com/45160 This prevents us from saving large
+  //                 data encoded images.  We should have a way to save them.
+  if (params.src_url.spec().size() > GetMaxURLChars())
+    params.src_url = GURL();
+  render_view_->context_menu_node_ = data.node;
+
+#if defined(OS_ANDROID)
+  gfx::Rect start_rect;
+  gfx::Rect end_rect;
+  render_view_->GetSelectionBounds(&start_rect, &end_rect);
+  params.selection_start = gfx::Point(start_rect.x(), start_rect.bottom());
+  params.selection_end = gfx::Point(end_rect.right(), end_rect.bottom());
+#endif
+
+  Send(new FrameHostMsg_ContextMenu(routing_id_, params));
+}
+
 void RenderFrameImpl::AddObserver(RenderFrameObserver* observer) {
   observers_.AddObserver(observer);
 }
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 008d56f1..2d344947 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -9,6 +9,8 @@
 
 #include "base/basictypes.h"
 #include "base/files/file_path.h"
+#include "base/gtest_prod_util.h"
+#include "base/id_map.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/process/process_handle.h"
@@ -26,10 +28,12 @@
 namespace blink {
 class WebMouseEvent;
 struct WebCompositionUnderline;
+struct WebContextMenuData;
 struct WebCursorInfo;
 }
 
 namespace gfx {
+class Point;
 class Range;
 class Rect;
 }
@@ -43,6 +47,7 @@
 class RenderViewImpl;
 class RenderWidget;
 class RenderWidgetFullscreenPepper;
+struct CustomContextMenuContext;
 
 class CONTENT_EXPORT RenderFrameImpl
     : public RenderFrame,
@@ -314,11 +319,16 @@
   virtual void didLoseWebGLContext(blink::WebFrame* frame,
                                    int arb_robustness_status_code);
 
+  // TODO(jam): move this to WebFrameClient
+  virtual void showContextMenu(const blink::WebContextMenuData& data);
+
  protected:
   RenderFrameImpl(RenderViewImpl* render_view, int32 routing_id);
 
  private:
   friend class RenderFrameObserver;
+  FRIEND_TEST_ALL_PREFIXES(RenderFrameImplTest,
+                           ShouldUpdateSelectionTextFromContextMenuParams);
 
   // Functions to add and remove observers for this object.
   void AddObserver(RenderFrameObserver* observer);
@@ -332,6 +342,18 @@
   void OnChildFrameProcessGone();
   void OnBuffersSwapped(const FrameMsg_BuffersSwapped_Params& params);
   void OnCompositorFrameSwapped(const IPC::Message& message);
+  void OnShowContextMenu(const gfx::Point& location);
+  void OnContextMenuClosed(const CustomContextMenuContext& custom_context);
+  void OnCustomContextMenuAction(const CustomContextMenuContext& custom_context,
+                                 unsigned action);
+
+  // Returns whether |params.selection_text| should be synchronized to the
+  // browser before bringing up the context menu. Static for testing.
+  static bool ShouldUpdateSelectionTextFromContextMenuParams(
+      const base::string16& selection_text,
+      size_t selection_text_offset,
+      const gfx::Range& selection_range,
+      const ContextMenuParams& params);
 
   // Stores the WebFrame we are associated with.
   blink::WebFrame* frame_;
@@ -354,6 +376,19 @@
 
   scoped_refptr<ChildFrameCompositingHelper> compositing_helper_;
 
+  // External context menu requests we're waiting for. "Internal"
+  // (WebKit-originated) context menu events will have an ID of 0 and will not
+  // be in this map.
+  //
+  // We don't want to add internal ones since some of the "special" page
+  // handlers in the browser process just ignore the context menu requests so
+  // avoid showing context menus, and so this will cause right clicks to leak
+  // entries in this map. Most users of the custom context menu (e.g. Pepper
+  // plugins) are normally only on "regular" pages and the regular pages will
+  // always respond properly to the request, so we don't have to worry so
+  // much about leaks.
+  IDMap<ContextMenuClient, IDMapExternalPointer> pending_context_menus_;
+
   DISALLOW_COPY_AND_ASSIGN(RenderFrameImpl);
 };
 
diff --git a/content/renderer/render_view_impl_unittest.cc b/content/renderer/render_frame_impl_unittest.cc
similarity index 86%
rename from content/renderer/render_view_impl_unittest.cc
rename to content/renderer/render_frame_impl_unittest.cc
index 65389f7..30c04f6 100644
--- a/content/renderer/render_view_impl_unittest.cc
+++ b/content/renderer/render_frame_impl_unittest.cc
@@ -4,13 +4,13 @@
 
 #include "base/strings/utf_string_conversions.h"
 #include "content/public/common/context_menu_params.h"
-#include "content/renderer/render_view_impl.h"
+#include "content/renderer/render_frame_impl.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/range/range.h"
 
 namespace content {
 
-TEST(RenderViewImplTest, ShouldUpdateSelectionTextFromContextMenuParams) {
+TEST(RenderFrameImplTest, ShouldUpdateSelectionTextFromContextMenuParams) {
   struct {
     const char* selection_text;
     size_t selection_text_offset;
@@ -30,7 +30,7 @@
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
     params.selection_text = base::UTF8ToUTF16(cases[i].params_selection_text);
     EXPECT_EQ(cases[i].expected_result,
-              RenderViewImpl::ShouldUpdateSelectionTextFromContextMenuParams(
+              RenderFrameImpl::ShouldUpdateSelectionTextFromContextMenuParams(
                   base::UTF8ToUTF16(cases[i].selection_text),
                   cases[i].selection_text_offset,
                   cases[i].selection_range,
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 7ffa3fa..fc19d54 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -8,6 +8,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/win/windows_version.h"
+#include "content/common/frame_messages.h"
 #include "content/common/ssl_status_serialization.h"
 #include "content/common/view_messages.h"
 #include "content/public/browser/native_web_keyboard_event.h"
@@ -1773,7 +1774,7 @@
   SendWebMouseEvent(mouse_event);
 
   EXPECT_TRUE(render_thread_->sink().GetUniqueMessageMatching(
-      ViewHostMsg_ContextMenu::ID));
+      FrameHostMsg_ContextMenu::ID));
 }
 
 TEST_F(RenderViewImplTest, TestBackForward) {
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 1650931..8ea49cc 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -53,7 +53,6 @@
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_constants.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/common/context_menu_params.h"
 #include "content/public/common/drop_data.h"
 #include "content/public/common/favicon_url.h"
 #include "content/public/common/file_chooser_params.h"
@@ -63,7 +62,6 @@
 #include "content/public/common/url_constants.h"
 #include "content/public/common/url_utils.h"
 #include "content/public/renderer/content_renderer_client.h"
-#include "content/public/renderer/context_menu_client.h"
 #include "content/public/renderer/document_state.h"
 #include "content/public/renderer/history_item_serialization.h"
 #include "content/public/renderer/navigation_state.h"
@@ -76,7 +74,6 @@
 #include "content/renderer/browser_plugin/browser_plugin.h"
 #include "content/renderer/browser_plugin/browser_plugin_manager.h"
 #include "content/renderer/browser_plugin/browser_plugin_manager_impl.h"
-#include "content/renderer/context_menu_params_builder.h"
 #include "content/renderer/devtools/devtools_agent.h"
 #include "content/renderer/disambiguation_popup_helper.h"
 #include "content/renderer/dom_automation_controller.h"
@@ -252,7 +249,6 @@
 using blink::WebColor;
 using blink::WebColorName;
 using blink::WebConsoleMessage;
-using blink::WebContextMenuData;
 using blink::WebData;
 using blink::WebDataSource;
 using blink::WebDocument;
@@ -857,8 +853,7 @@
       session_storage_namespace_id_(params->session_storage_namespace_id),
       handling_select_range_(false),
       next_snapshot_id_(0),
-      allow_partial_swap_(params->allow_partial_swap),
-      context_menu_source_type_(ui::MENU_SOURCE_MOUSE) {
+      allow_partial_swap_(params->allow_partial_swap) {
 }
 
 void RenderViewImpl::Initialize(RenderViewImplParams* params) {
@@ -1312,14 +1307,11 @@
                         OnOrientationChangeEvent)
     IPC_MESSAGE_HANDLER(ViewMsg_PluginActionAt, OnPluginActionAt)
     IPC_MESSAGE_HANDLER(ViewMsg_SetActive, OnSetActive)
-    IPC_MESSAGE_HANDLER(ViewMsg_CustomContextMenuAction,
-                        OnCustomContextMenuAction)
     IPC_MESSAGE_HANDLER(ViewMsg_GetAllSavableResourceLinksForCurrentPage,
                         OnGetAllSavableResourceLinksForCurrentPage)
     IPC_MESSAGE_HANDLER(
         ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks,
         OnGetSerializedHtmlDataForCurrentPageWithLocalLinks)
-    IPC_MESSAGE_HANDLER(ViewMsg_ContextMenuClosed, OnContextMenuClosed)
     IPC_MESSAGE_HANDLER(ViewMsg_ShowContextMenu, OnShowContextMenu)
     // TODO(viettrungluu): Move to a separate message filter.
     IPC_MESSAGE_HANDLER(ViewMsg_SetHistoryLengthAndPrune,
@@ -2660,59 +2652,10 @@
 }
 
 void RenderViewImpl::showContextMenu(
-    WebFrame* frame, const WebContextMenuData& data) {
-  ContextMenuParams params = ContextMenuParamsBuilder::Build(data);
-  params.source_type = context_menu_source_type_;
-  if (context_menu_source_type_ == ui::MENU_SOURCE_TOUCH_EDIT_MENU) {
-    params.x = touch_editing_context_menu_location_.x();
-    params.y = touch_editing_context_menu_location_.y();
-  }
-  OnShowHostContextMenu(&params);
-
-  // Plugins, e.g. PDF, don't currently update the render view when their
-  // selected text changes, but the context menu params do contain the updated
-  // selection. If that's the case, update the render view's state just prior
-  // to showing the context menu.
-  // TODO(asvitkine): http://crbug.com/152432
-  if (ShouldUpdateSelectionTextFromContextMenuParams(selection_text_,
-                                                     selection_text_offset_,
-                                                     selection_range_,
-                                                     params)) {
-    selection_text_ = params.selection_text;
-    // TODO(asvitkine): Text offset and range is not available in this case.
-    selection_text_offset_ = 0;
-    selection_range_ = gfx::Range(0, selection_text_.length());
-    Send(new ViewHostMsg_SelectionChanged(routing_id_,
-                                          selection_text_,
-                                          selection_text_offset_,
-                                          selection_range_));
-  }
-
-  // frame is NULL if invoked by BlockedPlugin.
-  if (frame)
-    params.frame_id = frame->identifier();
-
-  // Serializing a GURL longer than kMaxURLChars will fail, so don't do
-  // it.  We replace it with an empty GURL so the appropriate items are disabled
-  // in the context menu.
-  // TODO(jcivelli): http://crbug.com/45160 This prevents us from saving large
-  //                 data encoded images.  We should have a way to save them.
-  if (params.src_url.spec().size() > GetMaxURLChars())
-    params.src_url = GURL();
-  context_menu_node_ = data.node;
-
-#if defined(OS_ANDROID)
-  gfx::Rect start_rect;
-  gfx::Rect end_rect;
-  GetSelectionBounds(&start_rect, &end_rect);
-  params.selection_start = gfx::Point(start_rect.x(), start_rect.bottom());
-  params.selection_end = gfx::Point(end_rect.right(), end_rect.bottom());
-#endif
-
-  Send(new ViewHostMsg_ContextMenu(routing_id_, params));
-
-  FOR_EACH_OBSERVER(
-      RenderViewObserver, observers_, DidRequestShowContextMenu(frame, data));
+    WebFrame* frame, const blink::WebContextMenuData& data) {
+  // TODO(jam): move this method to WebFrameClient.
+  RenderFrameImpl* render_frame = RenderFrameImpl::FromWebFrame(frame);
+  render_frame->showContextMenu(data);
 }
 
 void RenderViewImpl::clearContextMenu() {
@@ -3999,26 +3942,6 @@
                                   final_status_update));
 }
 
-// static
-bool RenderViewImpl::ShouldUpdateSelectionTextFromContextMenuParams(
-    const base::string16& selection_text,
-    size_t selection_text_offset,
-    const gfx::Range& selection_range,
-    const ContextMenuParams& params) {
-  base::string16 trimmed_selection_text;
-  if (!selection_text.empty() && !selection_range.is_empty()) {
-    const int start = selection_range.GetMin() - selection_text_offset;
-    const size_t length = selection_range.length();
-    if (start >= 0 && start + length <= selection_text.length()) {
-      TrimWhitespace(selection_text.substr(start, length), TRIM_ALL,
-                     &trimmed_selection_text);
-    }
-  }
-  base::string16 trimmed_params_text;
-  TrimWhitespace(params.selection_text, TRIM_ALL, &trimmed_params_text);
-  return trimmed_params_text != trimmed_selection_text;
-}
-
 void RenderViewImpl::reportFindInPageMatchCount(int request_id,
                                                 int count,
                                                 bool final_update) {
@@ -4251,20 +4174,6 @@
   return filtered_time_per_frame();
 }
 
-int RenderViewImpl::ShowContextMenu(ContextMenuClient* client,
-                                    const ContextMenuParams& params) {
-  DCHECK(client);  // A null client means "internal" when we issue callbacks.
-  ContextMenuParams our_params(params);
-  our_params.custom_context.request_id = pending_context_menus_.Add(client);
-  Send(new ViewHostMsg_ContextMenu(routing_id_, our_params));
-  return our_params.custom_context.request_id;
-}
-
-void RenderViewImpl::CancelContextMenu(int request_id) {
-  DCHECK(pending_context_menus_.Lookup(request_id));
-  pending_context_menus_.Remove(request_id);
-}
-
 blink::WebPageVisibilityState RenderViewImpl::GetVisibilityState() const {
   return visibilityState();
 }
@@ -4836,21 +4745,6 @@
     NotifyTimezoneChange(webview()->mainFrame());
 }
 
-void RenderViewImpl::OnCustomContextMenuAction(
-    const CustomContextMenuContext& custom_context,
-    unsigned action) {
-  if (custom_context.request_id) {
-    // External context menu request, look in our map.
-    ContextMenuClient* client =
-        pending_context_menus_.Lookup(custom_context.request_id);
-    if (client)
-      client->OnMenuAction(custom_context.request_id, action);
-  } else {
-    // Internal request, forward to WebKit.
-    webview()->performCustomContextMenuAction(action);
-  }
-}
-
 void RenderViewImpl::OnEnumerateDirectoryResponse(
     int id,
     const std::vector<base::FilePath>& paths) {
@@ -5366,7 +5260,6 @@
 }
 
 bool RenderViewImpl::WillHandleMouseEvent(const blink::WebMouseEvent& event) {
-  context_menu_source_type_ = ui::MENU_SOURCE_MOUSE;
   possible_drag_event_info_.event_source =
       ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE;
   possible_drag_event_info_.event_location =
@@ -5388,14 +5281,8 @@
   return mouse_lock_dispatcher_->WillHandleMouseEvent(event);
 }
 
-bool RenderViewImpl::WillHandleKeyEvent(const blink::WebKeyboardEvent& event) {
-  context_menu_source_type_ = ui::MENU_SOURCE_KEYBOARD;
-  return false;
-}
-
 bool RenderViewImpl::WillHandleGestureEvent(
     const blink::WebGestureEvent& event) {
-  context_menu_source_type_ = ui::MENU_SOURCE_TOUCH;
   possible_drag_event_info_.event_source =
       ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH;
   possible_drag_event_info_.event_location =
@@ -6042,22 +5929,6 @@
 }
 #endif
 
-void RenderViewImpl::OnContextMenuClosed(
-    const CustomContextMenuContext& custom_context) {
-  if (custom_context.request_id) {
-    // External request, should be in our map.
-    ContextMenuClient* client =
-        pending_context_menus_.Lookup(custom_context.request_id);
-    if (client) {
-      client->OnMenuClosed(custom_context.request_id);
-      pending_context_menus_.Remove(custom_context.request_id);
-    }
-  } else {
-    // Internal request, forward to WebKit.
-    context_menu_node_.reset();
-  }
-}
-
 void RenderViewImpl::OnShowContextMenu(const gfx::Point& location) {
   context_menu_source_type_ = ui::MENU_SOURCE_TOUCH_EDIT_MENU;
   touch_editing_context_menu_location_ = location;
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 86110460..c763653 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -56,7 +56,6 @@
 #include "third_party/WebKit/public/web/WebPageVisibilityState.h"
 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
 #include "third_party/WebKit/public/web/WebViewClient.h"
-#include "ui/base/ui_base_types.h"
 #include "ui/surface/transport_dib.h"
 #include "webkit/common/webpreferences.h"
 
@@ -154,7 +153,6 @@
 class RendererWebColorChooserImpl;
 class SpeechRecognitionDispatcher;
 class WebPluginDelegateProxy;
-struct CustomContextMenuContext;
 struct DropData;
 struct FaviconURL;
 struct FileChooserParams;
@@ -335,11 +333,6 @@
       blink::WebFrame* frame,
       const blink::WebURL& url,
       blink::WebMediaPlayerClient* client);
-  // Temporary call until the context menu code moves to RenderFrmae.
-  // TODO(jam): remove me
-  int ShowContextMenu(ContextMenuClient* client,
-                      const ContextMenuParams& params);
-  void CancelContextMenu(int request_id);
   // Temporary call until this code moves to RenderFrame.
   // virtual since overriden by WebTestProxy for layout tests.
   virtual blink::WebNavigationPolicy DecidePolicyForNavigation(
@@ -701,8 +694,6 @@
   virtual void DidHandleKeyEvent() OVERRIDE;
   virtual bool WillHandleMouseEvent(
       const blink::WebMouseEvent& event) OVERRIDE;
-  virtual bool WillHandleKeyEvent(
-      const blink::WebKeyboardEvent& event) OVERRIDE;
   virtual bool WillHandleGestureEvent(
       const blink::WebGestureEvent& event) OVERRIDE;
   virtual void DidHandleMouseEvent(const blink::WebMouseEvent& event) OVERRIDE;
@@ -800,8 +791,6 @@
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, SetHistoryLengthAndPrune);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, ZoomLimit);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, NavigateFrame);
-  FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
-                           ShouldUpdateSelectionTextFromContextMenuParams);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, BasicRenderFrame);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, TextInputTypeWithPepper);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
@@ -897,13 +886,10 @@
   void OnCancelDownload(int32 download_id);
   void OnClearFocusedNode();
   void OnClosePage();
-  void OnContextMenuClosed(const CustomContextMenuContext& custom_context);
   void OnShowContextMenu(const gfx::Point& location);
   void OnCopyImageAt(int x, int y);
   void OnCSSInsertRequest(const base::string16& frame_xpath,
                           const std::string& css);
-  void OnCustomContextMenuAction(const CustomContextMenuContext& custom_context,
-      unsigned action);
   void OnSetName(const std::string& name);
   void OnDeterminePageLanguage();
   void OnDisableScrollbarsForSmallWindows(
@@ -1090,14 +1076,6 @@
                      const blink::WebRect& selection_rect,
                      bool final_status_update);
 
-  // Returns whether |params.selection_text| should be synchronized to the
-  // browser before bringing up the context menu. Static for testing.
-  static bool ShouldUpdateSelectionTextFromContextMenuParams(
-      const base::string16& selection_text,
-      size_t selection_text_offset,
-      const gfx::Range& selection_range,
-      const ContextMenuParams& params);
-
   // Starts nav_state_sync_timer_ if it isn't already running.
   void StartNavStateSyncTimerIfNecessary();
 
@@ -1294,19 +1272,6 @@
   // could correspond to a substring of |selection_text_|; see above).
   gfx::Range selection_range_;
 
-  // External context menu requests we're waiting for. "Internal"
-  // (WebKit-originated) context menu events will have an ID of 0 and will not
-  // be in this map.
-  //
-  // We don't want to add internal ones since some of the "special" page
-  // handlers in the browser process just ignore the context menu requests so
-  // avoid showing context menus, and so this will cause right clicks to leak
-  // entries in this map. Most users of the custom context menu (e.g. Pepper
-  // plugins) are normally only on "regular" pages and the regular pages will
-  // always respond properly to the request, so we don't have to worry so
-  // much about leaks.
-  IDMap<ContextMenuClient, IDMapExternalPointer> pending_context_menus_;
-
 #if defined(OS_ANDROID)
   // Cache the old top controls state constraints. Used when updating
   // current value only without altering the constraints.
@@ -1496,9 +1461,6 @@
   // constructors call the AddObservers method of RenderViewImpl.
   scoped_ptr<StatsCollectionObserver> stats_collection_observer_;
 
-  ui::MenuSourceType context_menu_source_type_;
-  gfx::Point touch_editing_context_menu_location_;
-
   // ---------------------------------------------------------------------------
   // ADDING NEW DATA? Please see if it fits appropriately in one of the above
   // sections rather than throwing it randomly at the end. If you're adding a
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 81583d8..54b9e99 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -30,6 +30,7 @@
 #include "content/common/swapped_out_messages.h"
 #include "content/common/view_messages.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/common/context_menu_params.h"
 #include "content/renderer/cursor_utils.h"
 #include "content/renderer/external_popup_menu.h"
 #include "content/renderer/gpu/compositor_output_surface.h"
@@ -380,7 +381,8 @@
       outstanding_ime_acks_(0),
 #endif
       popup_origin_scale_for_emulation_(0.f),
-      resizing_mode_selector_(new ResizingModeSelector()) {
+      resizing_mode_selector_(new ResizingModeSelector()),
+      context_menu_source_type_(ui::MENU_SOURCE_MOUSE) {
   if (!swapped_out)
     RenderProcess::current()->AddRefProcess();
   DCHECK(RenderThread::Get());
@@ -1096,18 +1098,17 @@
         *static_cast<const WebMouseEvent*>(input_event);
     TRACE_EVENT2("renderer", "HandleMouseMove",
                  "x", mouse_event.x, "y", mouse_event.y);
+    context_menu_source_type_ = ui::MENU_SOURCE_MOUSE;
     prevent_default = WillHandleMouseEvent(mouse_event);
   }
 
-  if (WebInputEvent::isKeyboardEventType(input_event->type)) {
-    const WebKeyboardEvent& key_event =
-        *static_cast<const WebKeyboardEvent*>(input_event);
-    prevent_default = WillHandleKeyEvent(key_event);
-  }
+  if (WebInputEvent::isKeyboardEventType(input_event->type))
+    context_menu_source_type_ = ui::MENU_SOURCE_KEYBOARD;
 
   if (WebInputEvent::isGestureEventType(input_event->type)) {
     const WebGestureEvent& gesture_event =
         *static_cast<const WebGestureEvent*>(input_event);
+    context_menu_source_type_ = ui::MENU_SOURCE_TOUCH;
     prevent_default = prevent_default || WillHandleGestureEvent(gesture_event);
   }
 
@@ -2801,10 +2802,6 @@
   return false;
 }
 
-bool RenderWidget::WillHandleKeyEvent(const blink::WebKeyboardEvent& event) {
-  return false;
-}
-
 bool RenderWidget::WillHandleGestureEvent(
     const blink::WebGestureEvent& event) {
   return false;
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index 783e8f4..63f99d0 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -34,6 +34,7 @@
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/base/ime/text_input_mode.h"
 #include "ui/base/ime/text_input_type.h"
+#include "ui/base/ui_base_types.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gfx/range/range.h"
 #include "ui/gfx/rect.h"
@@ -248,6 +249,7 @@
   // the new value will be sent to the browser process.
   void UpdateSelectionBounds();
 
+  void OnShowHostContextMenu(ContextMenuParams* params);
 
 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
   // Checks if the composition range or composition character bounds have been
@@ -259,6 +261,12 @@
   // Temporary for debugging purposes...
   bool closing() const { return closing_; }
 
+  ui::MenuSourceType context_menu_source_type() {
+    return context_menu_source_type_; }
+  gfx::Point touch_editing_context_menu_location() {
+    return touch_editing_context_menu_location_;
+  }
+
  protected:
   // Friend RefCounted so that the dtor can be non-public. Using this class
   // without ref-counting is an error.
@@ -336,7 +344,6 @@
       float root_layer_scale);
   void SetExternalPopupOriginAdjustmentsForEmulation(
       ExternalPopupMenu* popup, ScreenMetricsEmulator* emulator);
-  virtual void OnShowHostContextMenu(ContextMenuParams* params);
 
   // RenderWidget IPC message handlers
   void OnHandleInputEvent(const blink::WebInputEvent* event,
@@ -519,12 +526,6 @@
   // won't be sent to WebKit or trigger DidHandleMouseEvent().
   virtual bool WillHandleMouseEvent(const blink::WebMouseEvent& event);
 
-  // Called by OnHandleInputEvent() to notify subclasses that a key event is
-  // about to be handled.
-  // Returns true if no further handling is needed. In that case, the event
-  // won't be sent to WebKit or trigger DidHandleKeyEvent().
-  virtual bool WillHandleKeyEvent(const blink::WebKeyboardEvent& event);
-
   // Called by OnHandleInputEvent() to notify subclasses that a gesture event is
   // about to be handled.
   // Returns true if no further handling is needed. In that case, the event
@@ -803,6 +804,9 @@
   // of compositing-related events (e.g. DidCommitCompositorFrame).
   ObserverList<RenderFrameImpl> swapped_out_frames_;
 
+  ui::MenuSourceType context_menu_source_type_;
+  gfx::Point touch_editing_context_menu_location_;
+
   DISALLOW_COPY_AND_ASSIGN(RenderWidget);
 };
 
diff --git a/content/shell/browser/shell_web_contents_view_delegate.h b/content/shell/browser/shell_web_contents_view_delegate.h
index 86d97b40..7233e13 100644
--- a/content/shell/browser/shell_web_contents_view_delegate.h
+++ b/content/shell/browser/shell_web_contents_view_delegate.h
@@ -22,7 +22,8 @@
   virtual ~ShellWebContentsViewDelegate();
 
   // Overridden from WebContentsViewDelegate:
-  virtual void ShowContextMenu(const ContextMenuParams& params) OVERRIDE;
+  virtual void ShowContextMenu(RenderFrameHost* render_frame_host,
+                               const ContextMenuParams& params) OVERRIDE;
   virtual WebDragDestDelegate* GetDragDestDelegate() OVERRIDE;
 
 #if defined(TOOLKIT_GTK)
diff --git a/content/shell/browser/shell_web_contents_view_delegate_android.cc b/content/shell/browser/shell_web_contents_view_delegate_android.cc
index 3da54755..fb4a3dc 100644
--- a/content/shell/browser/shell_web_contents_view_delegate_android.cc
+++ b/content/shell/browser/shell_web_contents_view_delegate_android.cc
@@ -28,6 +28,7 @@
 }
 
 void ShellWebContentsViewDelegate::ShowContextMenu(
+    RenderFrameHost* render_frame_host,
     const ContextMenuParams& params) {
   if (params.is_editable && params.selection_text.empty()) {
     content::ContentViewCore* content_view_core =
diff --git a/content/shell/browser/shell_web_contents_view_delegate_gtk.cc b/content/shell/browser/shell_web_contents_view_delegate_gtk.cc
index 5020720b..e3b3222 100644
--- a/content/shell/browser/shell_web_contents_view_delegate_gtk.cc
+++ b/content/shell/browser/shell_web_contents_view_delegate_gtk.cc
@@ -42,6 +42,7 @@
 }
 
 void ShellWebContentsViewDelegate::ShowContextMenu(
+    RenderFrameHost* render_frame_host,
     const ContextMenuParams& params) {
   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
     return;
diff --git a/content/shell/browser/shell_web_contents_view_delegate_mac.mm b/content/shell/browser/shell_web_contents_view_delegate_mac.mm
index 1d01f90..dc2045c 100644
--- a/content/shell/browser/shell_web_contents_view_delegate_mac.mm
+++ b/content/shell/browser/shell_web_contents_view_delegate_mac.mm
@@ -93,6 +93,7 @@
 }
 
 void ShellWebContentsViewDelegate::ShowContextMenu(
+    RenderFrameHost* render_frame_host,
     const ContextMenuParams& params) {
   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
     return;
diff --git a/content/shell/browser/shell_web_contents_view_delegate_win.cc b/content/shell/browser/shell_web_contents_view_delegate_win.cc
index 63223f4..68ab07c73 100644
--- a/content/shell/browser/shell_web_contents_view_delegate_win.cc
+++ b/content/shell/browser/shell_web_contents_view_delegate_win.cc
@@ -70,6 +70,7 @@
 }
 
 void ShellWebContentsViewDelegate::ShowContextMenu(
+    RenderFrameHost* render_frame_host,
     const ContextMenuParams& params) {
   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
     return;