summaryrefslogtreecommitdiffstats
path: root/chrome/browser/render_view_context_menu_controller.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/render_view_context_menu_controller.cc')
-rw-r--r--chrome/browser/render_view_context_menu_controller.cc440
1 files changed, 440 insertions, 0 deletions
diff --git a/chrome/browser/render_view_context_menu_controller.cc b/chrome/browser/render_view_context_menu_controller.cc
new file mode 100644
index 0000000..790f641
--- /dev/null
+++ b/chrome/browser/render_view_context_menu_controller.cc
@@ -0,0 +1,440 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "chrome/browser/render_view_context_menu_controller.h"
+
+#include "base/command_line.h"
+#include "base/path_service.h"
+#include "base/string_util.h"
+#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/pref_service.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/download_manager.h"
+#include "chrome/browser/navigation_controller.h"
+#include "chrome/browser/navigation_entry.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/save_package.h"
+#include "chrome/browser/template_url_model.h"
+#include "chrome/browser/web_contents.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/clipboard_service.h"
+#include "chrome/common/l10n_util.h"
+#include "chrome/common/win_util.h"
+#include "net/base/escape.h"
+#include "net/base/net_util.h"
+#include "net/url_request/url_request.h"
+
+#include "generated_resources.h"
+
+RenderViewContextMenuController::RenderViewContextMenuController(
+ WebContents* source_web_contents,
+ const ViewHostMsg_ContextMenu_Params& params)
+ : source_web_contents_(source_web_contents),
+ params_(params) {
+}
+
+RenderViewContextMenuController::~RenderViewContextMenuController() {
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Controller methods
+
+void RenderViewContextMenuController::OpenURL(
+ const GURL& url,
+ WindowOpenDisposition disposition,
+ PageTransition::Type transition) {
+ source_web_contents_->OpenURL(url, disposition, transition);
+}
+
+void RenderViewContextMenuController::CopyImageAt(int x, int y) {
+ source_web_contents_->CopyImageAt(x, y);
+}
+
+void RenderViewContextMenuController::Inspect(int x, int y) {
+ source_web_contents_->InspectElementAt(x, y);
+}
+
+void RenderViewContextMenuController::WriteTextToClipboard(
+ const std::wstring& text) {
+ ClipboardService* clipboard = g_browser_process->clipboard_service();
+
+ if (!clipboard)
+ return;
+
+ clipboard->Clear();
+ clipboard->WriteText(text);
+}
+
+void RenderViewContextMenuController::WriteURLToClipboard(const GURL& url) {
+ if (url.SchemeIs("mailto"))
+ WriteTextToClipboard(UTF8ToWide(url.path()));
+ else
+ WriteTextToClipboard(UTF8ToWide(url.spec()));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Menu::Delegate methods
+
+std::wstring RenderViewContextMenuController::GetLabel(int id) const {
+ switch (id) {
+ case IDS_CONTENT_CONTEXT_SEARCHWEBFOR: {
+ const TemplateURL* const default_provider = source_web_contents_->
+ profile()->GetTemplateURLModel()->GetDefaultSearchProvider();
+ DCHECK(default_provider); // The context menu should not contain this
+ // item when there is no provider.
+ return l10n_util::GetStringF(id, default_provider->short_name(),
+ l10n_util::TruncateString(params_.selection_text, 50));
+ }
+
+ case IDS_CONTENT_CONTEXT_COPYLINKLOCATION:
+ if (params_.link_url.SchemeIs("mailto"))
+ return l10n_util::GetString(IDS_CONTENT_CONTEXT_COPYEMAILADDRESS);
+
+ default:
+ return l10n_util::GetString(id);
+ }
+}
+
+bool RenderViewContextMenuController::IsCommandEnabled(int id) const {
+ switch (id) {
+ case IDS_CONTENT_CONTEXT_BACK:
+ return source_web_contents_->controller()->CanGoBack();
+
+ case IDS_CONTENT_CONTEXT_FORWARD:
+ return source_web_contents_->controller()->CanGoForward();
+ case IDS_CONTENT_CONTEXT_VIEWPAGESOURCE:
+ case IDS_CONTENT_CONTEXT_VIEWFRAMESOURCE:
+ case IDS_CONTENT_CONTEXT_INSPECTELEMENT:
+ return IsDevCommandEnabled(id);
+ case IDS_CONTENT_CONTEXT_OPENLINKNEWTAB:
+ case IDS_CONTENT_CONTEXT_OPENLINKNEWWINDOW:
+ case IDS_CONTENT_CONTEXT_COPYLINKLOCATION:
+ return params_.link_url.is_valid();
+
+ case IDS_CONTENT_CONTEXT_SAVELINKAS:
+ return params_.link_url.is_valid() &&
+ URLRequest::IsHandledURL(params_.link_url);
+
+ case IDS_CONTENT_CONTEXT_SAVEIMAGEAS:
+ return params_.image_url.is_valid() &&
+ URLRequest::IsHandledURL(params_.image_url);
+
+ case IDS_CONTENT_CONTEXT_OPENIMAGENEWTAB:
+ case IDS_CONTENT_CONTEXT_COPYIMAGELOCATION:
+ return params_.image_url.is_valid();
+ case IDS_CONTENT_CONTEXT_SAVEPAGEAS:
+ return SavePackage::IsSavableURL(source_web_contents_->GetURL());
+ case IDS_CONTENT_CONTEXT_OPENFRAMENEWTAB:
+ case IDS_CONTENT_CONTEXT_OPENFRAMENEWWINDOW:
+ return params_.frame_url.is_valid();
+
+ case IDS_CONTENT_CONTEXT_UNDO:
+ return !!(params_.edit_flags & ContextNode::CAN_UNDO);
+
+ case IDS_CONTENT_CONTEXT_REDO:
+ return !!(params_.edit_flags & ContextNode::CAN_REDO);
+
+ case IDS_CONTENT_CONTEXT_CUT:
+ return !!(params_.edit_flags & ContextNode::CAN_CUT);
+
+ case IDS_CONTENT_CONTEXT_COPY:
+ return !!(params_.edit_flags & ContextNode::CAN_COPY);
+
+ case IDS_CONTENT_CONTEXT_PASTE:
+ return !!(params_.edit_flags & ContextNode::CAN_PASTE);
+
+ case IDS_CONTENT_CONTEXT_DELETE:
+ return !!(params_.edit_flags & ContextNode::CAN_DELETE);
+
+ case IDS_CONTENT_CONTEXT_SELECTALL:
+ return !!(params_.edit_flags & ContextNode::CAN_SELECT_ALL);
+
+ case IDS_CONTENT_CONTEXT_OPENLINKOFFTHERECORD:
+ return !source_web_contents_->profile()->IsOffTheRecord() &&
+ params_.link_url.is_valid();
+
+ case IDS_CONTENT_CONTEXT_OPENFRAMEOFFTHERECORD:
+ return !source_web_contents_->profile()->IsOffTheRecord() &&
+ params_.frame_url.is_valid();
+
+ case IDS_CONTENT_CONTEXT_COPYIMAGE:
+ case IDS_CONTENT_CONTEXT_PRINT:
+ case IDS_CONTENT_CONTEXT_SEARCHWEBFOR:
+ case IDC_USESPELLCHECKSUGGESTION_0:
+ case IDC_USESPELLCHECKSUGGESTION_1:
+ case IDC_USESPELLCHECKSUGGESTION_2:
+ case IDC_USESPELLCHECKSUGGESTION_3:
+ case IDC_USESPELLCHECKSUGGESTION_4:
+ return true;
+
+ case IDS_CONTENT_CONTEXT_VIEWPAGEINFO:
+ case IDS_CONTENT_CONTEXT_VIEWFRAMEINFO:
+ case IDS_CONTENT_CONTEXT_SAVEFRAMEAS:
+ case IDS_CONTENT_CONTEXT_PRINTFRAME:
+ case IDS_CONTENT_CONTEXT_ADDSEARCHENGINE: // Not implemented.
+ default:
+ return false;
+ }
+}
+
+bool RenderViewContextMenuController::GetAcceleratorInfo(int id,
+ ChromeViews::Accelerator* accel) {
+ // There are no formally defined accelerators we can query so we assume
+ // that Ctrl+C, Ctrl+V, Ctrl+X, Ctrl-A, etc do what they normally do.
+ switch (id) {
+ case IDS_CONTENT_CONTEXT_UNDO:
+ *accel = ChromeViews::Accelerator(L'Z', false, true, false);
+ return true;
+
+ case IDS_CONTENT_CONTEXT_REDO:
+ *accel = ChromeViews::Accelerator(L'Z', true, true, false);
+ return true;
+
+ case IDS_CONTENT_CONTEXT_CUT:
+ *accel = ChromeViews::Accelerator(L'X', false, true, false);
+ return true;
+
+ case IDS_CONTENT_CONTEXT_COPY:
+ *accel = ChromeViews::Accelerator(L'C', false, true, false);
+ return true;
+
+ case IDS_CONTENT_CONTEXT_PASTE:
+ *accel = ChromeViews::Accelerator(L'V', false, true, false);
+ return true;
+
+ case IDS_CONTENT_CONTEXT_SELECTALL:
+ *accel = ChromeViews::Accelerator(L'A', false, true, false);
+
+ default:
+ return false;
+ }
+}
+
+void RenderViewContextMenuController::ExecuteCommand(int id) {
+ switch (id) {
+ case IDS_CONTENT_CONTEXT_OPENLINKNEWTAB:
+ OpenURL(params_.link_url, NEW_BACKGROUND_TAB, PageTransition::LINK);
+ break;
+
+ case IDS_CONTENT_CONTEXT_OPENLINKNEWWINDOW:
+ OpenURL(params_.link_url, NEW_WINDOW, PageTransition::LINK);
+ break;
+
+ case IDS_CONTENT_CONTEXT_OPENLINKOFFTHERECORD:
+ OpenURL(params_.link_url, OFF_THE_RECORD, PageTransition::LINK);
+ break;
+
+ // TODO(paulg): Prompt the user for file name when saving links and images.
+ case IDS_CONTENT_CONTEXT_SAVEIMAGEAS:
+ case IDS_CONTENT_CONTEXT_SAVELINKAS: {
+ const GURL& referrer =
+ params_.frame_url.is_empty() ? params_.page_url : params_.frame_url;
+ const GURL& url = id == IDS_CONTENT_CONTEXT_SAVELINKAS ? params_.link_url :
+ params_.image_url;
+ DownloadManager* dlm =
+ source_web_contents_->profile()->GetDownloadManager();
+ dlm->DownloadUrl(url, referrer, source_web_contents_);
+ break;
+ }
+
+ case IDS_CONTENT_CONTEXT_COPYLINKLOCATION:
+ WriteURLToClipboard(params_.link_url);
+ break;
+
+ case IDS_CONTENT_CONTEXT_COPYIMAGELOCATION:
+ WriteURLToClipboard(params_.image_url);
+ break;
+
+ case IDS_CONTENT_CONTEXT_COPYIMAGE:
+ CopyImageAt(params_.x, params_.y);
+ break;
+
+ case IDS_CONTENT_CONTEXT_OPENIMAGENEWTAB:
+ OpenURL(params_.image_url, NEW_BACKGROUND_TAB, PageTransition::LINK);
+ break;
+
+ case IDS_CONTENT_CONTEXT_BACK:
+ source_web_contents_->controller()->GoBack();
+ break;
+
+ case IDS_CONTENT_CONTEXT_FORWARD:
+ source_web_contents_->controller()->GoForward();
+ break;
+
+ case IDS_CONTENT_CONTEXT_SAVEPAGEAS:
+ source_web_contents_->OnSavePage();
+ break;
+
+ case IDS_CONTENT_CONTEXT_PRINT:
+ source_web_contents_->PrintPreview();
+ break;
+
+ case IDS_CONTENT_CONTEXT_VIEWPAGESOURCE:
+ OpenURL(GURL("view-source:" + params_.page_url.spec()),
+ NEW_FOREGROUND_TAB, PageTransition::GENERATED);
+ break;
+
+ case IDS_CONTENT_CONTEXT_INSPECTELEMENT:
+ Inspect(params_.x, params_.y);
+ break;
+
+ case IDS_CONTENT_CONTEXT_VIEWPAGEINFO:
+ win_util::MessageBox(NULL, L"Context Menu Action", L"View Page Info",
+ MB_OK);
+ break;
+
+ case IDS_CONTENT_CONTEXT_OPENFRAMENEWTAB:
+ OpenURL(params_.frame_url, NEW_BACKGROUND_TAB, PageTransition::LINK);
+ break;
+
+ case IDS_CONTENT_CONTEXT_OPENFRAMENEWWINDOW:
+ OpenURL(params_.frame_url, NEW_WINDOW, PageTransition::LINK);
+ break;
+
+ case IDS_CONTENT_CONTEXT_OPENFRAMEOFFTHERECORD:
+ OpenURL(params_.frame_url, OFF_THE_RECORD, PageTransition::LINK);
+ break;
+
+ case IDS_CONTENT_CONTEXT_SAVEFRAMEAS:
+ win_util::MessageBox(NULL, L"Context Menu Action", L"Save Frame As",
+ MB_OK);
+ break;
+
+ case IDS_CONTENT_CONTEXT_PRINTFRAME:
+ win_util::MessageBox(NULL, L"Context Menu Action", L"Print Frame",
+ MB_OK);
+ break;
+
+ case IDS_CONTENT_CONTEXT_VIEWFRAMESOURCE:
+ OpenURL(GURL("view-source:" + params_.frame_url.spec()),
+ NEW_FOREGROUND_TAB, PageTransition::GENERATED);
+ break;
+
+ case IDS_CONTENT_CONTEXT_VIEWFRAMEINFO:
+ win_util::MessageBox(NULL, L"Context Menu Action", L"View Frame Info",
+ MB_OK);
+ break;
+
+ case IDS_CONTENT_CONTEXT_UNDO:
+ source_web_contents_->Undo();
+ break;
+
+ case IDS_CONTENT_CONTEXT_REDO:
+ source_web_contents_->Redo();
+ break;
+
+ case IDS_CONTENT_CONTEXT_CUT:
+ source_web_contents_->Cut();
+ break;
+
+ case IDS_CONTENT_CONTEXT_COPY:
+ source_web_contents_->Copy();
+ break;
+
+ case IDS_CONTENT_CONTEXT_PASTE:
+ source_web_contents_->Paste();
+ break;
+
+ case IDS_CONTENT_CONTEXT_DELETE:
+ source_web_contents_->Delete();
+ break;
+
+ case IDS_CONTENT_CONTEXT_SELECTALL:
+ source_web_contents_->SelectAll();
+ break;
+
+ case IDS_CONTENT_CONTEXT_SEARCHWEBFOR: {
+ const TemplateURL* const default_provider = source_web_contents_->
+ profile()->GetTemplateURLModel()->GetDefaultSearchProvider();
+ DCHECK(default_provider); // The context menu should not contain this
+ // item when there is no provider.
+ const TemplateURLRef* const search_url = default_provider->url();
+ DCHECK(search_url->SupportsReplacement());
+ OpenURL(GURL(search_url->ReplaceSearchTerms(*default_provider,
+ params_.selection_text, TemplateURLRef::NO_SUGGESTIONS_AVAILABLE,
+ std::wstring())), NEW_FOREGROUND_TAB, PageTransition::GENERATED);
+ break;
+ }
+
+ case IDC_USESPELLCHECKSUGGESTION_0:
+ case IDC_USESPELLCHECKSUGGESTION_1:
+ case IDC_USESPELLCHECKSUGGESTION_2:
+ case IDC_USESPELLCHECKSUGGESTION_3:
+ case IDC_USESPELLCHECKSUGGESTION_4:
+ source_web_contents_->Replace(params_.dictionary_suggestions[
+ id - IDC_USESPELLCHECKSUGGESTION_0]);
+ break;
+
+ case IDS_CONTENT_CONTEXT_ADDSEARCHENGINE: // Not implemented.
+ default:
+ break;
+ }
+}
+
+bool RenderViewContextMenuController::IsDevCommandEnabled(int id) const {
+ CommandLine command_line;
+ if (command_line.HasSwitch(switches::kAlwaysEnableDevTools))
+ return true;
+
+ NavigationEntry *active_entry =
+ source_web_contents_->controller()->GetActiveEntry();
+ if (!active_entry)
+ return false;
+
+ // Don't inspect HTML dialogs.
+ if (source_web_contents_->type() == TAB_CONTENTS_HTML_DIALOG)
+ return false;
+
+ // Don't inspect view source.
+ if (source_web_contents_->type() == TAB_CONTENTS_VIEW_SOURCE)
+ return false;
+
+ // Don't inspect inspector, new tab UI, etc.
+ if (active_entry->GetURL().SchemeIs("chrome-resource"))
+ return false;
+
+ // Don't inspect about:network, about:memory, etc.
+ // However, we do want to inspect about:blank, which is often
+ // used by ordinary web pages.
+ if (active_entry->GetDisplayURL().SchemeIs("about") &&
+ !LowerCaseEqualsASCII(active_entry->GetDisplayURL().path(), "blank"))
+ return false;
+
+ // Don't enable the web inspector if JavaScript is disabled
+ if (id == IDS_CONTENT_CONTEXT_INSPECTELEMENT) {
+ PrefService* prefs = source_web_contents_->profile()->GetPrefs();
+ if (!prefs->GetBoolean(prefs::kWebKitJavascriptEnabled) ||
+ command_line.HasSwitch(switches::kDisableJavaScript))
+ return false;
+ }
+
+ return true;
+}