Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(556)

Side by Side Diff: chrome/browser/tab_contents/render_view_context_menu.cc

Issue 6749021: Added new fileBrowserPrivate and fileHandler extension APIs (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <algorithm>
6 #include <set> 5 #include <set>
7 6
8 #include "chrome/browser/tab_contents/render_view_context_menu.h" 7 #include "chrome/browser/tab_contents/render_view_context_menu.h"
9 8
10 #include "base/command_line.h" 9 #include "base/command_line.h"
11 #include "base/logging.h" 10 #include "base/logging.h"
12 #include "base/metrics/histogram.h" 11 #include "base/metrics/histogram.h"
13 #include "base/stl_util-inl.h" 12 #include "base/stl_util-inl.h"
14 #include "base/string_util.h" 13 #include "base/string_util.h"
15 #include "base/time.h" 14 #include "base/time.h"
(...skipping 14 matching lines...) Expand all
30 #include "chrome/browser/page_info_window.h" 29 #include "chrome/browser/page_info_window.h"
31 #include "chrome/browser/platform_util.h" 30 #include "chrome/browser/platform_util.h"
32 #include "chrome/browser/prefs/pref_member.h" 31 #include "chrome/browser/prefs/pref_member.h"
33 #include "chrome/browser/prefs/pref_service.h" 32 #include "chrome/browser/prefs/pref_service.h"
34 #include "chrome/browser/printing/print_preview_tab_controller.h" 33 #include "chrome/browser/printing/print_preview_tab_controller.h"
35 #include "chrome/browser/profiles/profile.h" 34 #include "chrome/browser/profiles/profile.h"
36 #include "chrome/browser/search_engines/template_url.h" 35 #include "chrome/browser/search_engines/template_url.h"
37 #include "chrome/browser/search_engines/template_url_model.h" 36 #include "chrome/browser/search_engines/template_url_model.h"
38 #include "chrome/browser/spellcheck_host.h" 37 #include "chrome/browser/spellcheck_host.h"
39 #include "chrome/browser/spellchecker_platform_engine.h" 38 #include "chrome/browser/spellchecker_platform_engine.h"
39 #include "chrome/browser/tab_contents/context_menu_utils.h"
40 #include "chrome/browser/translate/translate_manager.h" 40 #include "chrome/browser/translate/translate_manager.h"
41 #include "chrome/browser/translate/translate_prefs.h" 41 #include "chrome/browser/translate/translate_prefs.h"
42 #include "chrome/browser/ui/download/download_tab_helper.h" 42 #include "chrome/browser/ui/download/download_tab_helper.h"
43 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 43 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
44 #include "chrome/common/chrome_constants.h" 44 #include "chrome/common/chrome_constants.h"
45 #include "chrome/common/chrome_switches.h" 45 #include "chrome/common/chrome_switches.h"
46 #include "chrome/common/content_restriction.h" 46 #include "chrome/common/content_restriction.h"
47 #include "chrome/common/pref_names.h" 47 #include "chrome/common/pref_names.h"
48 #include "chrome/common/print_messages.h" 48 #include "chrome/common/print_messages.h"
49 #include "chrome/common/url_constants.h" 49 #include "chrome/common/url_constants.h"
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 RenderViewContextMenu::~RenderViewContextMenu() { 192 RenderViewContextMenu::~RenderViewContextMenu() {
193 } 193 }
194 194
195 // Menu construction functions ------------------------------------------------- 195 // Menu construction functions -------------------------------------------------
196 196
197 void RenderViewContextMenu::Init() { 197 void RenderViewContextMenu::Init() {
198 InitMenu(); 198 InitMenu();
199 PlatformInit(); 199 PlatformInit();
200 } 200 }
201 201
202 static bool ExtensionContextMatch(const ContextMenuParams& params,
203 ExtensionMenuItem::ContextList contexts) {
204 bool has_link = !params.link_url.is_empty();
205 bool has_selection = !params.selection_text.empty();
206 bool in_frame = !params.frame_url.is_empty();
207
208 if (contexts.Contains(ExtensionMenuItem::ALL) ||
209 (has_selection && contexts.Contains(ExtensionMenuItem::SELECTION)) ||
210 (has_link && contexts.Contains(ExtensionMenuItem::LINK)) ||
211 (params.is_editable && contexts.Contains(ExtensionMenuItem::EDITABLE)) ||
212 (in_frame && contexts.Contains(ExtensionMenuItem::FRAME))) {
213 return true;
214 }
215
216 switch (params.media_type) {
217 case WebContextMenuData::MediaTypeImage:
218 return contexts.Contains(ExtensionMenuItem::IMAGE);
219
220 case WebContextMenuData::MediaTypeVideo:
221 return contexts.Contains(ExtensionMenuItem::VIDEO);
222
223 case WebContextMenuData::MediaTypeAudio:
224 return contexts.Contains(ExtensionMenuItem::AUDIO);
225
226 default:
227 break;
228 }
229
230 // PAGE is the least specific context, so we only examine that if none of the
231 // other contexts apply (except for FRAME, which is included in PAGE for
232 // backwards compatibility).
233 if (!has_link && !has_selection && !params.is_editable &&
234 params.media_type == WebContextMenuData::MediaTypeNone &&
235 contexts.Contains(ExtensionMenuItem::PAGE))
236 return true;
237
238 return false;
239 }
240
241 static bool ExtensionPatternMatch(const ExtensionExtent& patterns,
242 const GURL& url) {
243 // No patterns means no restriction, so that implicitly matches.
244 if (patterns.is_empty())
245 return true;
246 return patterns.ContainsURL(url);
247 }
248
249 static const GURL& GetDocumentURL(const ContextMenuParams& params) {
250 return params.frame_url.is_empty() ? params.page_url : params.frame_url;
251 }
252
253 // Given a list of items, returns the ones that match given the contents
254 // of |params| and the profile.
255 static ExtensionMenuItem::List GetRelevantExtensionItems(
256 const ExtensionMenuItem::List& items,
257 const ContextMenuParams& params,
258 Profile* profile,
259 bool can_cross_incognito) {
260 ExtensionMenuItem::List result;
261 for (ExtensionMenuItem::List::const_iterator i = items.begin();
262 i != items.end(); ++i) {
263 const ExtensionMenuItem* item = *i;
264
265 if (!ExtensionContextMatch(params, item->contexts()))
266 continue;
267
268 const GURL& document_url = GetDocumentURL(params);
269 if (!ExtensionPatternMatch(item->document_url_patterns(), document_url))
270 continue;
271
272 const GURL& target_url =
273 params.src_url.is_empty() ? params.link_url : params.src_url;
274 if (!ExtensionPatternMatch(item->target_url_patterns(), target_url))
275 continue;
276
277 if (item->id().profile == profile || can_cross_incognito)
278 result.push_back(*i);
279 }
280 return result;
281 }
282
283 void RenderViewContextMenu::AppendExtensionItems( 202 void RenderViewContextMenu::AppendExtensionItems(
284 const std::string& extension_id, int* index) { 203 const std::string& extension_id, int* index) {
285 ExtensionService* service = profile_->GetExtensionService(); 204 ExtensionService* service = profile_->GetExtensionService();
286 ExtensionMenuManager* manager = service->menu_manager(); 205 ExtensionMenuManager* manager = service->menu_manager();
287 const Extension* extension = service->GetExtensionById(extension_id, false); 206 const Extension* extension = service->GetExtensionById(extension_id, false);
288 DCHECK_GE(*index, 0); 207 DCHECK_GE(*index, 0);
289 int max_index = 208 int max_index =
290 IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST - IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST; 209 IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST - IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST;
291 if (!extension || *index >= max_index) 210 if (!extension || *index >= max_index)
292 return; 211 return;
293 212
294 // Find matching items. 213 // Find matching items.
295 const ExtensionMenuItem::List* all_items = manager->MenuItems(extension_id); 214 const ExtensionMenuItem::List* all_items = manager->MenuItems(extension_id);
296 if (!all_items || all_items->empty()) 215 if (!all_items || all_items->empty())
297 return; 216 return;
298 bool can_cross_incognito = service->CanCrossIncognito(extension); 217 bool can_cross_incognito = service->CanCrossIncognito(extension);
299 ExtensionMenuItem::List items = 218 ExtensionMenuItem::List items =
300 GetRelevantExtensionItems(*all_items, params_, profile_, 219 ContextMenuUtils::GetRelevantExtensionItems(*all_items,
301 can_cross_incognito); 220 params_,
221 profile_,
222 can_cross_incognito);
302 if (items.empty()) 223 if (items.empty())
303 return; 224 return;
304 225
305 // If this is the first extension-provided menu item, add a separator. 226 // If this is the first extension-provided menu item, add a separator.
306 if (*index == 0) 227 if (*index == 0)
307 menu_model_.AddSeparator(); 228 menu_model_.AddSeparator();
308 229
309 int menu_id = IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST + (*index)++; 230 int menu_id = IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST + (*index)++;
310 231
311 // Extensions are only allowed one top-level slot (and it can't be a radio or 232 // Extensions are only allowed one top-level slot (and it can't be a radio or
312 // checkbox item because we are going to put the extension icon next to it). 233 // checkbox item because we are going to put the extension icon next to it).
313 // If they have more than that, we automatically push them into a submenu. 234 // If they have more than that, we automatically push them into a submenu.
314 string16 title; 235 string16 title;
315 ExtensionMenuItem::List submenu_items; 236 ExtensionMenuItem::List submenu_items;
316 if (items.size() > 1 || items[0]->type() != ExtensionMenuItem::NORMAL) { 237 if (items.size() > 1 || items[0]->type() != ExtensionMenuItem::NORMAL) {
317 title = UTF8ToUTF16(extension->name()); 238 title = UTF8ToUTF16(extension->name());
318 submenu_items = items; 239 submenu_items = items;
319 } else { 240 } else {
320 ExtensionMenuItem* item = items[0]; 241 ExtensionMenuItem* item = items[0];
321 extension_item_map_[menu_id] = item->id(); 242 extension_item_map_[menu_id] = item->id();
322 title = item->TitleWithReplacement(PrintableSelectionText(), 243 title = item->TitleWithReplacement(PrintableSelectionText(),
323 kMaxExtensionItemTitleLength); 244 kMaxExtensionItemTitleLength);
324 submenu_items = GetRelevantExtensionItems(item->children(), params_, 245 submenu_items = ContextMenuUtils::GetRelevantExtensionItems(
325 profile_, can_cross_incognito); 246 item->children(), params_, profile_, can_cross_incognito);
326 } 247 }
327 248
328 // Now add our item(s) to the menu_model_. 249 // Now add our item(s) to the menu_model_.
329 if (submenu_items.empty()) { 250 if (submenu_items.empty()) {
330 menu_model_.AddItem(menu_id, title); 251 menu_model_.AddItem(menu_id, title);
331 } else { 252 } else {
332 ui::SimpleMenuModel* submenu = new ui::SimpleMenuModel(this); 253 ui::SimpleMenuModel* submenu = new ui::SimpleMenuModel(this);
333 extension_menu_models_.push_back(submenu); 254 extension_menu_models_.push_back(submenu);
334 menu_model_.AddSubMenu(menu_id, title, submenu); 255 menu_model_.AddSubMenu(menu_id, title, submenu);
335 RecursivelyAppendExtensionItems(submenu_items, can_cross_incognito, submenu, 256 RecursivelyAppendExtensionItems(submenu_items, can_cross_incognito, submenu,
(...skipping 24 matching lines...) Expand all
360 } 281 }
361 282
362 int menu_id = IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST + (*index)++; 283 int menu_id = IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST + (*index)++;
363 if (menu_id >= IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST) 284 if (menu_id >= IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST)
364 return; 285 return;
365 extension_item_map_[menu_id] = item->id(); 286 extension_item_map_[menu_id] = item->id();
366 string16 title = item->TitleWithReplacement(selection_text, 287 string16 title = item->TitleWithReplacement(selection_text,
367 kMaxExtensionItemTitleLength); 288 kMaxExtensionItemTitleLength);
368 if (item->type() == ExtensionMenuItem::NORMAL) { 289 if (item->type() == ExtensionMenuItem::NORMAL) {
369 ExtensionMenuItem::List children = 290 ExtensionMenuItem::List children =
370 GetRelevantExtensionItems(item->children(), params_, 291 ContextMenuUtils::GetRelevantExtensionItems(
371 profile_, can_cross_incognito); 292 item->children(), params_, profile_, can_cross_incognito);
372 if (children.empty()) { 293 if (children.empty()) {
373 menu_model->AddItem(menu_id, title); 294 menu_model->AddItem(menu_id, title);
374 } else { 295 } else {
375 ui::SimpleMenuModel* submenu = new ui::SimpleMenuModel(this); 296 ui::SimpleMenuModel* submenu = new ui::SimpleMenuModel(this);
376 extension_menu_models_.push_back(submenu); 297 extension_menu_models_.push_back(submenu);
377 menu_model->AddSubMenu(menu_id, title, submenu); 298 menu_model->AddSubMenu(menu_id, title, submenu);
378 RecursivelyAppendExtensionItems(children, can_cross_incognito, 299 RecursivelyAppendExtensionItems(children, can_cross_incognito,
379 submenu, index); 300 submenu, index);
380 } 301 }
381 } else if (item->type() == ExtensionMenuItem::CHECKBOX) { 302 } else if (item->type() == ExtensionMenuItem::CHECKBOX) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 334
414 menu_model_.SetIcon(index, icon); 335 menu_model_.SetIcon(index, icon);
415 } 336 }
416 337
417 void RenderViewContextMenu::AppendAllExtensionItems() { 338 void RenderViewContextMenu::AppendAllExtensionItems() {
418 extension_item_map_.clear(); 339 extension_item_map_.clear();
419 ExtensionService* service = profile_->GetExtensionService(); 340 ExtensionService* service = profile_->GetExtensionService();
420 if (!service) 341 if (!service)
421 return; // In unit-tests, we may not have an ExtensionService. 342 return; // In unit-tests, we may not have an ExtensionService.
422 ExtensionMenuManager* menu_manager = service->menu_manager(); 343 ExtensionMenuManager* menu_manager = service->menu_manager();
423 const GURL& document_url = GetDocumentURL(params_); 344 const GURL& document_url = ContextMenuUtils::GetDocumentURL(params_);
424 if (!menu_manager->HasAllowedScheme(document_url)) 345 if (!menu_manager->HasAllowedScheme(document_url))
425 return; 346 return;
426 347
427 // Get a list of extension id's that have context menu items, and sort it by
428 // the extension's name.
429 std::set<std::string> ids = menu_manager->ExtensionIds();
430 std::vector<std::pair<std::string, std::string> > sorted_ids; 348 std::vector<std::pair<std::string, std::string> > sorted_ids;
431 for (std::set<std::string>::iterator i = ids.begin(); i != ids.end(); ++i) { 349 ContextMenuUtils::GetSortedContextMenuExtensionIds(service, menu_manager,
432 const Extension* extension = service->GetExtensionById(*i, false); 350 &sorted_ids);
433 if (extension)
434 sorted_ids.push_back(
435 std::pair<std::string, std::string>(extension->name(), *i));
436 }
437 // TODO(asargent) - See if this works properly for i18n names (bug 32363).
438 std::sort(sorted_ids.begin(), sorted_ids.end());
439
440 if (sorted_ids.empty()) 351 if (sorted_ids.empty())
441 return; 352 return;
442 353
443 int index = 0; 354 int index = 0;
444 base::TimeTicks begin = base::TimeTicks::Now(); 355 base::TimeTicks begin = base::TimeTicks::Now();
445 std::vector<std::pair<std::string, std::string> >::const_iterator i; 356 std::vector<std::pair<std::string, std::string> >::const_iterator i;
446 for (i = sorted_ids.begin(); 357 for (i = sorted_ids.begin();
447 i != sorted_ids.end(); ++i) { 358 i != sorted_ids.end(); ++i) {
448 AppendExtensionItems(i->second, &index); 359 AppendExtensionItems(i->second, &index);
449 } 360 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
502 break; 413 break;
503 case WebContextMenuData::MediaTypeVideo: 414 case WebContextMenuData::MediaTypeVideo:
504 AppendVideoItems(); 415 AppendVideoItems();
505 break; 416 break;
506 case WebContextMenuData::MediaTypeAudio: 417 case WebContextMenuData::MediaTypeAudio:
507 AppendAudioItems(); 418 AppendAudioItems();
508 break; 419 break;
509 case WebContextMenuData::MediaTypePlugin: 420 case WebContextMenuData::MediaTypePlugin:
510 AppendPluginItems(); 421 AppendPluginItems();
511 break; 422 break;
512 #ifdef WEBCONTEXT_MEDIATYPEFILE_DEFINED
513 case WebContextMenuData::MediaTypeFile: 423 case WebContextMenuData::MediaTypeFile:
424 AppendFileItems();
514 break; 425 break;
515 #endif
516 } 426 }
517 427
518 if (params_.is_editable) 428 if (params_.is_editable)
519 AppendEditableItems(); 429 AppendEditableItems();
520 else if (has_selection) 430 else if (has_selection)
521 AppendCopyItem(); 431 AppendCopyItem();
522 432
523 if (has_selection) 433 if (has_selection)
524 AppendSearchProvider(); 434 AppendSearchProvider();
525 435
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
595 AppendMediaItems(); 505 AppendMediaItems();
596 menu_model_.AddSeparator(); 506 menu_model_.AddSeparator();
597 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_SAVEAVAS, 507 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_SAVEAVAS,
598 IDS_CONTENT_CONTEXT_SAVEVIDEOAS); 508 IDS_CONTENT_CONTEXT_SAVEVIDEOAS);
599 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_COPYAVLOCATION, 509 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_COPYAVLOCATION,
600 IDS_CONTENT_CONTEXT_COPYVIDEOLOCATION); 510 IDS_CONTENT_CONTEXT_COPYVIDEOLOCATION);
601 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_OPENAVNEWTAB, 511 menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_OPENAVNEWTAB,
602 IDS_CONTENT_CONTEXT_OPENVIDEONEWTAB); 512 IDS_CONTENT_CONTEXT_OPENVIDEONEWTAB);
603 } 513 }
604 514
515 void RenderViewContextMenu::AppendFileItems() {
516 // TODO(zelidrag): Add file context operations here (i.e. cut, copy, paste...)
517 }
518
605 void RenderViewContextMenu::AppendMediaItems() { 519 void RenderViewContextMenu::AppendMediaItems() {
606 int media_flags = params_.media_flags; 520 int media_flags = params_.media_flags;
607 521
608 menu_model_.AddItemWithStringId( 522 menu_model_.AddItemWithStringId(
609 IDC_CONTENT_CONTEXT_PLAYPAUSE, 523 IDC_CONTENT_CONTEXT_PLAYPAUSE,
610 media_flags & WebContextMenuData::MediaPaused ? 524 media_flags & WebContextMenuData::MediaPaused ?
611 IDS_CONTENT_CONTEXT_PLAY : 525 IDS_CONTENT_CONTEXT_PLAY :
612 IDS_CONTENT_CONTEXT_PAUSE); 526 IDS_CONTENT_CONTEXT_PAUSE);
613 527
614 menu_model_.AddItemWithStringId( 528 menu_model_.AddItemWithStringId(
(...skipping 937 matching lines...) Expand 10 before | Expand all | Expand 10 after
1552 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages), 1466 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages),
1553 g_browser_process->clipboard()); 1467 g_browser_process->clipboard());
1554 } 1468 }
1555 1469
1556 void RenderViewContextMenu::MediaPlayerActionAt( 1470 void RenderViewContextMenu::MediaPlayerActionAt(
1557 const gfx::Point& location, 1471 const gfx::Point& location,
1558 const WebMediaPlayerAction& action) { 1472 const WebMediaPlayerAction& action) {
1559 source_tab_contents_->render_view_host()->MediaPlayerActionAt( 1473 source_tab_contents_->render_view_host()->MediaPlayerActionAt(
1560 location, action); 1474 location, action);
1561 } 1475 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698