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

Side by Side Diff: chrome/browser/extensions/menu_manager.cc

Issue 186213003: <webview>: Context menu API implementation CL. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added test + fixed MenuManager::ExtensionIds(). Created 6 years, 9 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 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 "chrome/browser/extensions/menu_manager.h" 5 #include "chrome/browser/extensions/menu_manager.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/json/json_writer.h" 9 #include "base/json/json_writer.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/stl_util.h" 11 #include "base/stl_util.h"
12 #include "base/strings/string_util.h" 12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h" 13 #include "base/strings/utf_string_conversions.h"
14 #include "base/values.h" 14 #include "base/values.h"
15 #include "chrome/browser/chrome_notification_types.h" 15 #include "chrome/browser/chrome_notification_types.h"
16 #include "chrome/browser/extensions/event_names.h" 16 #include "chrome/browser/extensions/event_names.h"
17 #include "chrome/browser/extensions/extension_service.h" 17 #include "chrome/browser/extensions/extension_service.h"
18 #include "chrome/browser/extensions/extension_tab_util.h" 18 #include "chrome/browser/extensions/extension_tab_util.h"
19 #include "chrome/browser/extensions/menu_manager_factory.h" 19 #include "chrome/browser/extensions/menu_manager_factory.h"
20 #include "chrome/browser/extensions/state_store.h" 20 #include "chrome/browser/extensions/state_store.h"
21 #include "chrome/browser/extensions/tab_helper.h" 21 #include "chrome/browser/extensions/tab_helper.h"
22 #include "chrome/browser/guestview/webview/webview_guest.h"
22 #include "chrome/browser/profiles/profile.h" 23 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/common/extensions/api/context_menus.h" 24 #include "chrome/common/extensions/api/context_menus.h"
24 #include "content/public/browser/notification_details.h" 25 #include "content/public/browser/notification_details.h"
25 #include "content/public/browser/notification_service.h" 26 #include "content/public/browser/notification_service.h"
26 #include "content/public/browser/notification_source.h" 27 #include "content/public/browser/notification_source.h"
27 #include "content/public/browser/web_contents.h" 28 #include "content/public/browser/web_contents.h"
28 #include "content/public/common/context_menu_params.h" 29 #include "content/public/common/context_menu_params.h"
29 #include "extensions/browser/event_router.h" 30 #include "extensions/browser/event_router.h"
30 #include "extensions/browser/extension_system.h" 31 #include "extensions/browser/extension_system.h"
31 #include "extensions/common/extension.h" 32 #include "extensions/common/extension.h"
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 return value.Pass(); 216 return value.Pass();
216 } 217 }
217 218
218 // static 219 // static
219 MenuItem* MenuItem::Populate(const std::string& extension_id, 220 MenuItem* MenuItem::Populate(const std::string& extension_id,
220 const base::DictionaryValue& value, 221 const base::DictionaryValue& value,
221 std::string* error) { 222 std::string* error) {
222 bool incognito = false; 223 bool incognito = false;
223 if (!value.GetBoolean(kIncognitoKey, &incognito)) 224 if (!value.GetBoolean(kIncognitoKey, &incognito))
224 return NULL; 225 return NULL;
225 Id id(incognito, extension_id); 226 Id id(incognito, MenuItem::ExtensionKey(extension_id));
226 if (!value.GetString(kStringUIDKey, &id.string_uid)) 227 if (!value.GetString(kStringUIDKey, &id.string_uid))
227 return NULL; 228 return NULL;
228 int type_int; 229 int type_int;
229 Type type = NORMAL; 230 Type type = NORMAL;
230 if (!value.GetInteger(kTypeKey, &type_int)) 231 if (!value.GetInteger(kTypeKey, &type_int))
231 return NULL; 232 return NULL;
232 type = static_cast<Type>(type_int); 233 type = static_cast<Type>(type_int);
233 std::string title; 234 std::string title;
234 if (type != SEPARATOR && !value.GetString(kTitleKey, &title)) 235 if (type != SEPARATOR && !value.GetString(kTitleKey, &title))
235 return NULL; 236 return NULL;
(...skipping 23 matching lines...) Expand all
259 return NULL; 260 return NULL;
260 261
261 if (!result->PopulateURLPatterns(&document_url_patterns, 262 if (!result->PopulateURLPatterns(&document_url_patterns,
262 &target_url_patterns, 263 &target_url_patterns,
263 error)) { 264 error)) {
264 return NULL; 265 return NULL;
265 } 266 }
266 267
267 // parent_id is filled in from the value, but it might not be valid. It's left 268 // parent_id is filled in from the value, but it might not be valid. It's left
268 // to be validated upon being added (via AddChildItem) to the menu manager. 269 // to be validated upon being added (via AddChildItem) to the menu manager.
269 scoped_ptr<Id> parent_id(new Id(incognito, extension_id)); 270 scoped_ptr<Id> parent_id(
271 new Id(incognito, MenuItem::ExtensionKey(extension_id)));
270 if (value.HasKey(kParentUIDKey)) { 272 if (value.HasKey(kParentUIDKey)) {
271 if (!value.GetString(kParentUIDKey, &parent_id->string_uid)) 273 if (!value.GetString(kParentUIDKey, &parent_id->string_uid))
272 return NULL; 274 return NULL;
273 result->parent_id_.swap(parent_id); 275 result->parent_id_.swap(parent_id);
274 } 276 }
275 return result.release(); 277 return result.release();
276 } 278 }
277 279
278 bool MenuItem::PopulateURLPatterns( 280 bool MenuItem::PopulateURLPatterns(
279 std::vector<std::string>* document_url_patterns, 281 std::vector<std::string>* document_url_patterns,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 for (i = context_items_.begin(); i != context_items_.end(); ++i) { 313 for (i = context_items_.begin(); i != context_items_.end(); ++i) {
312 STLDeleteElements(&(i->second)); 314 STLDeleteElements(&(i->second));
313 } 315 }
314 } 316 }
315 317
316 // static 318 // static
317 MenuManager* MenuManager::Get(Profile* profile) { 319 MenuManager* MenuManager::Get(Profile* profile) {
318 return MenuManagerFactory::GetForProfile(profile); 320 return MenuManagerFactory::GetForProfile(profile);
319 } 321 }
320 322
321 std::set<std::string> MenuManager::ExtensionIds() { 323 std::set<MenuItem::ExtensionKey> MenuManager::ExtensionIds() {
322 std::set<std::string> id_set; 324 std::set<MenuItem::ExtensionKey> id_set;
323 for (MenuItemMap::const_iterator i = context_items_.begin(); 325 for (MenuItemMap::const_iterator i = context_items_.begin();
324 i != context_items_.end(); ++i) { 326 i != context_items_.end(); ++i) {
325 id_set.insert(i->first); 327 id_set.insert(i->first);
326 } 328 }
327 return id_set; 329 return id_set;
328 } 330 }
329 331
330 const MenuItem::List* MenuManager::MenuItems( 332 const MenuItem::List* MenuManager::MenuItems(
331 const std::string& extension_id) { 333 const MenuItem::ExtensionKey& key) {
332 MenuItemMap::iterator i = context_items_.find(extension_id); 334 MenuItemMap::iterator i = context_items_.find(key);
333 if (i != context_items_.end()) { 335 if (i != context_items_.end()) {
334 return &(i->second); 336 return &(i->second);
335 } 337 }
336 return NULL; 338 return NULL;
337 } 339 }
338 340
339 bool MenuManager::AddContextItem( 341 bool MenuManager::AddContextItem(const Extension* extension, MenuItem* item) {
340 const Extension* extension, 342 const MenuItem::ExtensionKey& key = item->id().extension_key;
341 MenuItem* item) {
342 const std::string& extension_id = item->extension_id();
343 // The item must have a non-empty extension id, and not have already been 343 // The item must have a non-empty extension id, and not have already been
344 // added. 344 // added.
345 if (extension_id.empty() || ContainsKey(items_by_id_, item->id())) 345 if (key.empty() || ContainsKey(items_by_id_, item->id()))
346 return false; 346 return false;
347 347
348 DCHECK_EQ(extension->id(), extension_id); 348 DCHECK_EQ(extension->id(), key.extension_id);
349 349
350 bool first_item = !ContainsKey(context_items_, extension_id); 350 bool first_item = !ContainsKey(context_items_, key);
351 context_items_[extension_id].push_back(item); 351 context_items_[key].push_back(item);
352 items_by_id_[item->id()] = item; 352 items_by_id_[item->id()] = item;
353 353
354 if (item->type() == MenuItem::RADIO) { 354 if (item->type() == MenuItem::RADIO) {
355 if (item->checked()) 355 if (item->checked())
356 RadioItemSelected(item); 356 RadioItemSelected(item);
357 else 357 else
358 SanitizeRadioList(context_items_[extension_id]); 358 SanitizeRadioList(context_items_[key]);
359 } 359 }
360 360
361 // If this is the first item for this extension, start loading its icon. 361 // If this is the first item for this extension, start loading its icon.
362 if (first_item) 362 if (first_item)
363 icon_manager_.LoadIcon(profile_, extension); 363 icon_manager_.LoadIcon(profile_, extension);
364 364
365 return true; 365 return true;
366 } 366 }
367 367
368 bool MenuManager::AddChildItem(const MenuItem::Id& parent_id, 368 bool MenuManager::AddChildItem(const MenuItem::Id& parent_id,
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
417 NOTREACHED(); 417 NOTREACHED();
418 return false; 418 return false;
419 } 419 }
420 MenuItem* taken = 420 MenuItem* taken =
421 old_parent->ReleaseChild(child_id, false /* non-recursive search*/); 421 old_parent->ReleaseChild(child_id, false /* non-recursive search*/);
422 DCHECK(taken == child); 422 DCHECK(taken == child);
423 SanitizeRadioList(old_parent->children()); 423 SanitizeRadioList(old_parent->children());
424 } else { 424 } else {
425 // This is a top-level item, so we need to pull it out of our list of 425 // This is a top-level item, so we need to pull it out of our list of
426 // top-level items. 426 // top-level items.
427 MenuItemMap::iterator i = context_items_.find(child->extension_id()); 427 const MenuItem::ExtensionKey& child_key = child->id().extension_key;
428 MenuItemMap::iterator i = context_items_.find(child_key);
428 if (i == context_items_.end()) { 429 if (i == context_items_.end()) {
429 NOTREACHED(); 430 NOTREACHED();
430 return false; 431 return false;
431 } 432 }
432 MenuItem::List& list = i->second; 433 MenuItem::List& list = i->second;
433 MenuItem::List::iterator j = std::find(list.begin(), list.end(), 434 MenuItem::List::iterator j = std::find(list.begin(), list.end(), child);
434 child);
435 if (j == list.end()) { 435 if (j == list.end()) {
436 NOTREACHED(); 436 NOTREACHED();
437 return false; 437 return false;
438 } 438 }
439 list.erase(j); 439 list.erase(j);
440 SanitizeRadioList(list); 440 SanitizeRadioList(list);
441 } 441 }
442 442
443 if (new_parent) { 443 if (new_parent) {
444 new_parent->AddChild(child); 444 new_parent->AddChild(child);
445 SanitizeRadioList(new_parent->children()); 445 SanitizeRadioList(new_parent->children());
446 } else { 446 } else {
447 context_items_[child->extension_id()].push_back(child); 447 const MenuItem::ExtensionKey& child_key = child->id().extension_key;
448 context_items_[child_key].push_back(child);
448 child->parent_id_.reset(NULL); 449 child->parent_id_.reset(NULL);
449 SanitizeRadioList(context_items_[child->extension_id()]); 450 SanitizeRadioList(context_items_[child_key]);
450 } 451 }
451 return true; 452 return true;
452 } 453 }
453 454
454 bool MenuManager::RemoveContextMenuItem(const MenuItem::Id& id) { 455 bool MenuManager::RemoveContextMenuItem(const MenuItem::Id& id) {
455 if (!ContainsKey(items_by_id_, id)) 456 if (!ContainsKey(items_by_id_, id))
456 return false; 457 return false;
457 458
458 MenuItem* menu_item = GetItemById(id); 459 MenuItem* menu_item = GetItemById(id);
459 DCHECK(menu_item); 460 DCHECK(menu_item);
460 std::string extension_id = menu_item->extension_id(); 461 MenuItemMap::iterator i = context_items_.find(id.extension_key);
461 MenuItemMap::iterator i = context_items_.find(extension_id);
462 if (i == context_items_.end()) { 462 if (i == context_items_.end()) {
463 NOTREACHED(); 463 NOTREACHED();
464 return false; 464 return false;
465 } 465 }
466 466
467 bool result = false; 467 bool result = false;
468 std::set<MenuItem::Id> items_removed; 468 std::set<MenuItem::Id> items_removed;
469 MenuItem::List& list = i->second; 469 MenuItem::List& list = i->second;
470 MenuItem::List::iterator j; 470 MenuItem::List::iterator j;
471 for (j = list.begin(); j < list.end(); ++j) { 471 for (j = list.begin(); j < list.end(); ++j) {
(...skipping 24 matching lines...) Expand all
496 496
497 // Clear entries from the items_by_id_ map. 497 // Clear entries from the items_by_id_ map.
498 std::set<MenuItem::Id>::iterator removed_iter; 498 std::set<MenuItem::Id>::iterator removed_iter;
499 for (removed_iter = items_removed.begin(); 499 for (removed_iter = items_removed.begin();
500 removed_iter != items_removed.end(); 500 removed_iter != items_removed.end();
501 ++removed_iter) { 501 ++removed_iter) {
502 items_by_id_.erase(*removed_iter); 502 items_by_id_.erase(*removed_iter);
503 } 503 }
504 504
505 if (list.empty()) { 505 if (list.empty()) {
506 context_items_.erase(extension_id); 506 context_items_.erase(id.extension_key);
507 icon_manager_.RemoveIcon(extension_id); 507 icon_manager_.RemoveIcon(id.extension_key.extension_id);
508 } 508 }
509 return result; 509 return result;
510 } 510 }
511 511
512 void MenuManager::RemoveAllContextItems(const std::string& extension_id) { 512 void MenuManager::RemoveAllContextItems(
513 const MenuItem::ExtensionKey& extension_key) {
513 MenuItem::List::iterator i; 514 MenuItem::List::iterator i;
514 for (i = context_items_[extension_id].begin(); 515 for (i = context_items_[extension_key].begin();
515 i != context_items_[extension_id].end(); ++i) { 516 i != context_items_[extension_key].end();
517 ++i) {
516 MenuItem* item = *i; 518 MenuItem* item = *i;
517 items_by_id_.erase(item->id()); 519 items_by_id_.erase(item->id());
518 520
519 // Remove descendants from this item and erase them from the lookup cache. 521 // Remove descendants from this item and erase them from the lookup cache.
520 std::set<MenuItem::Id> removed_ids = item->RemoveAllDescendants(); 522 std::set<MenuItem::Id> removed_ids = item->RemoveAllDescendants();
521 std::set<MenuItem::Id>::const_iterator j; 523 std::set<MenuItem::Id>::const_iterator j;
522 for (j = removed_ids.begin(); j != removed_ids.end(); ++j) { 524 for (j = removed_ids.begin(); j != removed_ids.end(); ++j) {
523 items_by_id_.erase(*j); 525 items_by_id_.erase(*j);
524 } 526 }
525 } 527 }
526 STLDeleteElements(&context_items_[extension_id]); 528 STLDeleteElements(&context_items_[extension_key]);
527 context_items_.erase(extension_id); 529 context_items_.erase(extension_key);
528 icon_manager_.RemoveIcon(extension_id); 530 icon_manager_.RemoveIcon(extension_key.extension_id);
529 } 531 }
530 532
531 MenuItem* MenuManager::GetItemById(const MenuItem::Id& id) const { 533 MenuItem* MenuManager::GetItemById(const MenuItem::Id& id) const {
532 std::map<MenuItem::Id, MenuItem*>::const_iterator i = 534 std::map<MenuItem::Id, MenuItem*>::const_iterator i =
533 items_by_id_.find(id); 535 items_by_id_.find(id);
534 if (i != items_by_id_.end()) 536 if (i != items_by_id_.end())
535 return i->second; 537 return i->second;
536 else 538 else
537 return NULL; 539 return NULL;
538 } 540 }
539 541
540 void MenuManager::RadioItemSelected(MenuItem* item) { 542 void MenuManager::RadioItemSelected(MenuItem* item) {
541 // If this is a child item, we need to get a handle to the list from its 543 // If this is a child item, we need to get a handle to the list from its
542 // parent. Otherwise get a handle to the top-level list. 544 // parent. Otherwise get a handle to the top-level list.
543 const MenuItem::List* list = NULL; 545 const MenuItem::List* list = NULL;
544 if (item->parent_id()) { 546 if (item->parent_id()) {
545 MenuItem* parent = GetItemById(*item->parent_id()); 547 MenuItem* parent = GetItemById(*item->parent_id());
546 if (!parent) { 548 if (!parent) {
547 NOTREACHED(); 549 NOTREACHED();
548 return; 550 return;
549 } 551 }
550 list = &(parent->children()); 552 list = &(parent->children());
551 } else { 553 } else {
552 if (context_items_.find(item->extension_id()) == context_items_.end()) { 554 const MenuItem::ExtensionKey& key = item->id().extension_key;
555 if (context_items_.find(key) == context_items_.end()) {
553 NOTREACHED(); 556 NOTREACHED();
554 return; 557 return;
555 } 558 }
556 list = &context_items_[item->extension_id()]; 559 list = &context_items_[key];
557 } 560 }
558 561
559 // Find where |item| is in the list. 562 // Find where |item| is in the list.
560 MenuItem::List::const_iterator item_location; 563 MenuItem::List::const_iterator item_location;
561 for (item_location = list->begin(); item_location != list->end(); 564 for (item_location = list->begin(); item_location != list->end();
562 ++item_location) { 565 ++item_location) {
563 if (*item_location == item) 566 if (*item_location == item)
564 break; 567 break;
565 } 568 }
566 if (item_location == list->end()) { 569 if (item_location == list->end()) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
603 if (!event_router) 606 if (!event_router)
604 return; 607 return;
605 608
606 MenuItem* item = GetItemById(menu_item_id); 609 MenuItem* item = GetItemById(menu_item_id);
607 if (!item) 610 if (!item)
608 return; 611 return;
609 612
610 // ExtensionService/Extension can be NULL in unit tests :( 613 // ExtensionService/Extension can be NULL in unit tests :(
611 ExtensionService* service = 614 ExtensionService* service =
612 ExtensionSystem::Get(profile_)->extension_service(); 615 ExtensionSystem::Get(profile_)->extension_service();
613 const Extension* extension = service ? 616 const Extension* extension =
614 service->extensions()->GetByID(menu_item_id.extension_id) : NULL; 617 service ? service->extensions()->GetByID(item->extension_id()) : NULL;
615 618
616 if (item->type() == MenuItem::RADIO) 619 if (item->type() == MenuItem::RADIO)
617 RadioItemSelected(item); 620 RadioItemSelected(item);
618 621
619 scoped_ptr<base::ListValue> args(new base::ListValue()); 622 scoped_ptr<base::ListValue> args(new base::ListValue());
620 623
621 base::DictionaryValue* properties = new base::DictionaryValue(); 624 base::DictionaryValue* properties = new base::DictionaryValue();
622 SetIdKeyValue(properties, "menuItemId", item->id()); 625 SetIdKeyValue(properties, "menuItemId", item->id());
623 if (item->parent_id()) 626 if (item->parent_id())
624 SetIdKeyValue(properties, "parentMenuItemId", *item->parent_id()); 627 SetIdKeyValue(properties, "parentMenuItemId", *item->parent_id());
(...skipping 14 matching lines...) Expand all
639 AddURLProperty(properties, "linkUrl", params.unfiltered_link_url); 642 AddURLProperty(properties, "linkUrl", params.unfiltered_link_url);
640 AddURLProperty(properties, "srcUrl", params.src_url); 643 AddURLProperty(properties, "srcUrl", params.src_url);
641 AddURLProperty(properties, "pageUrl", params.page_url); 644 AddURLProperty(properties, "pageUrl", params.page_url);
642 AddURLProperty(properties, "frameUrl", params.frame_url); 645 AddURLProperty(properties, "frameUrl", params.frame_url);
643 646
644 if (params.selection_text.length() > 0) 647 if (params.selection_text.length() > 0)
645 properties->SetString("selectionText", params.selection_text); 648 properties->SetString("selectionText", params.selection_text);
646 649
647 properties->SetBoolean("editable", params.is_editable); 650 properties->SetBoolean("editable", params.is_editable);
648 651
652 WebViewGuest* webview_guest = WebViewGuest::FromWebContents(web_contents);
653 if (webview_guest) {
654 // This is used in webview_custom_bindings.js.
655 // The property is not exposed to developer API.
656 properties->SetInteger("webviewInstanceId",
657 webview_guest->view_instance_id());
658 }
659
649 args->Append(properties); 660 args->Append(properties);
650 661
651 // Add the tab info to the argument list. 662 // Add the tab info to the argument list.
652 // No tab info in a platform app. 663 // No tab info in a platform app.
653 if (!extension || !extension->is_platform_app()) { 664 if (!extension || !extension->is_platform_app()) {
654 // Note: web_contents are NULL in unit tests :( 665 // Note: web_contents are NULL in unit tests :(
655 if (web_contents) { 666 if (web_contents) {
656 args->Append(ExtensionTabUtil::CreateTabValue(web_contents)); 667 args->Append(ExtensionTabUtil::CreateTabValue(web_contents));
657 } else { 668 } else {
658 args->Append(new base::DictionaryValue()); 669 args->Append(new base::DictionaryValue());
659 } 670 }
660 } 671 }
661 672
662 if (item->type() == MenuItem::CHECKBOX || 673 if (item->type() == MenuItem::CHECKBOX ||
663 item->type() == MenuItem::RADIO) { 674 item->type() == MenuItem::RADIO) {
664 bool was_checked = item->checked(); 675 bool was_checked = item->checked();
665 properties->SetBoolean("wasChecked", was_checked); 676 properties->SetBoolean("wasChecked", was_checked);
666 677
667 // RADIO items always get set to true when you click on them, but CHECKBOX 678 // RADIO items always get set to true when you click on them, but CHECKBOX
668 // items get their state toggled. 679 // items get their state toggled.
669 bool checked = 680 bool checked =
670 (item->type() == MenuItem::RADIO) ? true : !was_checked; 681 (item->type() == MenuItem::RADIO) ? true : !was_checked;
671 682
672 item->SetChecked(checked); 683 item->SetChecked(checked);
673 properties->SetBoolean("checked", item->checked()); 684 properties->SetBoolean("checked", item->checked());
674 685
675 if (extension) 686 if (extension)
676 WriteToStorage(extension); 687 WriteToStorage(extension, item->id().extension_key);
677 } 688 }
678 689
679 // Note: web_contents are NULL in unit tests :( 690 // Note: web_contents are NULL in unit tests :(
680 if (web_contents && extensions::TabHelper::FromWebContents(web_contents)) { 691 if (web_contents && extensions::TabHelper::FromWebContents(web_contents)) {
681 extensions::TabHelper::FromWebContents(web_contents)-> 692 extensions::TabHelper::FromWebContents(web_contents)->
682 active_tab_permission_granter()->GrantIfRequested(extension); 693 active_tab_permission_granter()->GrantIfRequested(extension);
683 } 694 }
684 695
685 { 696 {
697 // Dispatch to menu item's .onclick handler.
686 scoped_ptr<Event> event(new Event( 698 scoped_ptr<Event> event(new Event(
687 event_names::kOnContextMenus, 699 event_names::kOnContextMenus,
688 scoped_ptr<base::ListValue>(args->DeepCopy()))); 700 scoped_ptr<base::ListValue>(args->DeepCopy())));
689 event->restrict_to_browser_context = profile; 701 event->restrict_to_browser_context = profile;
690 event->user_gesture = EventRouter::USER_GESTURE_ENABLED; 702 event->user_gesture = EventRouter::USER_GESTURE_ENABLED;
691 event_router->DispatchEventToExtension(item->extension_id(), event.Pass()); 703 event_router->DispatchEventToExtension(item->extension_id(), event.Pass());
692 } 704 }
693 { 705 {
694 scoped_ptr<Event> event(new Event(context_menus::OnClicked::kEventName, 706 // Dispatch to .contextMenus.onClicked handler.
695 args.Pass())); 707 scoped_ptr<Event> event(
708 new Event(webview_guest ? event_names::kOnWebviewContextMenus
709 : context_menus::OnClicked::kEventName,
710 args.Pass()));
696 event->restrict_to_browser_context = profile; 711 event->restrict_to_browser_context = profile;
697 event->user_gesture = EventRouter::USER_GESTURE_ENABLED; 712 event->user_gesture = EventRouter::USER_GESTURE_ENABLED;
713 if (webview_guest)
714 event->filter_info.SetInstanceID(webview_guest->view_instance_id());
698 event_router->DispatchEventToExtension(item->extension_id(), event.Pass()); 715 event_router->DispatchEventToExtension(item->extension_id(), event.Pass());
699 } 716 }
700 } 717 }
701 718
702 void MenuManager::SanitizeRadioList(const MenuItem::List& item_list) { 719 void MenuManager::SanitizeRadioList(const MenuItem::List& item_list) {
703 MenuItem::List::const_iterator i = item_list.begin(); 720 MenuItem::List::const_iterator i = item_list.begin();
704 while (i != item_list.end()) { 721 while (i != item_list.end()) {
705 if ((*i)->type() != MenuItem::RADIO) { 722 if ((*i)->type() != MenuItem::RADIO) {
706 ++i; 723 ++i;
707 break; 724 break;
(...skipping 28 matching lines...) Expand all
736 bool MenuManager::ItemUpdated(const MenuItem::Id& id) { 753 bool MenuManager::ItemUpdated(const MenuItem::Id& id) {
737 if (!ContainsKey(items_by_id_, id)) 754 if (!ContainsKey(items_by_id_, id))
738 return false; 755 return false;
739 756
740 MenuItem* menu_item = GetItemById(id); 757 MenuItem* menu_item = GetItemById(id);
741 DCHECK(menu_item); 758 DCHECK(menu_item);
742 759
743 if (menu_item->parent_id()) { 760 if (menu_item->parent_id()) {
744 SanitizeRadioList(GetItemById(*menu_item->parent_id())->children()); 761 SanitizeRadioList(GetItemById(*menu_item->parent_id())->children());
745 } else { 762 } else {
746 std::string extension_id = menu_item->extension_id(); 763 MenuItemMap::iterator i =
747 MenuItemMap::iterator i = context_items_.find(extension_id); 764 context_items_.find(menu_item->id().extension_key);
748 if (i == context_items_.end()) { 765 if (i == context_items_.end()) {
749 NOTREACHED(); 766 NOTREACHED();
750 return false; 767 return false;
751 } 768 }
752 SanitizeRadioList(i->second); 769 SanitizeRadioList(i->second);
753 } 770 }
754 771
755 return true; 772 return true;
756 } 773 }
757 774
758 void MenuManager::WriteToStorage(const Extension* extension) { 775 void MenuManager::WriteToStorage(const Extension* extension,
776 const MenuItem::ExtensionKey& extension_key) {
759 if (!BackgroundInfo::HasLazyBackgroundPage(extension)) 777 if (!BackgroundInfo::HasLazyBackgroundPage(extension))
760 return; 778 return;
761 const MenuItem::List* top_items = MenuItems(extension->id()); 779 // <webview> menu items are transient and not stored in storage.
780 if (extension_key.webview_instance_id)
781 return;
782 const MenuItem::List* top_items = MenuItems(extension_key);
762 MenuItem::List all_items; 783 MenuItem::List all_items;
763 if (top_items) { 784 if (top_items) {
764 for (MenuItem::List::const_iterator i = top_items->begin(); 785 for (MenuItem::List::const_iterator i = top_items->begin();
765 i != top_items->end(); ++i) { 786 i != top_items->end(); ++i) {
787 DCHECK(!(*i)->id().extension_key.webview_instance_id);
766 (*i)->GetFlattenedSubtree(&all_items); 788 (*i)->GetFlattenedSubtree(&all_items);
767 } 789 }
768 } 790 }
769 791
770 if (store_) 792 if (store_) {
771 store_->SetExtensionValue(extension->id(), kContextMenusKey, 793 store_->SetExtensionValue(extension->id(), kContextMenusKey,
772 MenuItemsToValue(all_items)); 794 MenuItemsToValue(all_items));
795 }
773 } 796 }
774 797
775 void MenuManager::ReadFromStorage(const std::string& extension_id, 798 void MenuManager::ReadFromStorage(const std::string& extension_id,
776 scoped_ptr<base::Value> value) { 799 scoped_ptr<base::Value> value) {
777 const Extension* extension = 800 const Extension* extension =
778 ExtensionSystem::Get(profile_)->extension_service()->extensions()-> 801 ExtensionSystem::Get(profile_)->extension_service()->extensions()->
779 GetByID(extension_id); 802 GetByID(extension_id);
780 if (!extension) 803 if (!extension)
781 return; 804 return;
782 805
(...skipping 14 matching lines...) Expand all
797 } 820 }
798 821
799 void MenuManager::Observe(int type, 822 void MenuManager::Observe(int type,
800 const content::NotificationSource& source, 823 const content::NotificationSource& source,
801 const content::NotificationDetails& details) { 824 const content::NotificationDetails& details) {
802 switch (type) { 825 switch (type) {
803 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { 826 case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
804 // Remove menu items for disabled/uninstalled extensions. 827 // Remove menu items for disabled/uninstalled extensions.
805 const Extension* extension = 828 const Extension* extension =
806 content::Details<UnloadedExtensionInfo>(details)->extension; 829 content::Details<UnloadedExtensionInfo>(details)->extension;
807 if (ContainsKey(context_items_, extension->id())) { 830 MenuItem::ExtensionKey extension_key(extension->id());
808 RemoveAllContextItems(extension->id()); 831 if (ContainsKey(context_items_, extension_key)) {
832 RemoveAllContextItems(extension_key);
809 } 833 }
810 break; 834 break;
811 } 835 }
812 case chrome::NOTIFICATION_EXTENSION_LOADED: { 836 case chrome::NOTIFICATION_EXTENSION_LOADED: {
813 const Extension* extension = 837 const Extension* extension =
814 content::Details<const Extension>(details).ptr(); 838 content::Details<const Extension>(details).ptr();
815 if (store_ && BackgroundInfo::HasLazyBackgroundPage(extension)) { 839 if (store_ && BackgroundInfo::HasLazyBackgroundPage(extension)) {
816 store_->GetExtensionValue(extension->id(), kContextMenusKey, 840 store_->GetExtensionValue(extension->id(), kContextMenusKey,
817 base::Bind(&MenuManager::ReadFromStorage, 841 base::Bind(&MenuManager::ReadFromStorage,
818 AsWeakPtr(), extension->id())); 842 AsWeakPtr(), extension->id()));
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
852 items_to_remove.insert(iter->first); 876 items_to_remove.insert(iter->first);
853 } 877 }
854 878
855 std::set<MenuItem::Id>::iterator remove_iter; 879 std::set<MenuItem::Id>::iterator remove_iter;
856 for (remove_iter = items_to_remove.begin(); 880 for (remove_iter = items_to_remove.begin();
857 remove_iter != items_to_remove.end(); 881 remove_iter != items_to_remove.end();
858 ++remove_iter) 882 ++remove_iter)
859 RemoveContextMenuItem(*remove_iter); 883 RemoveContextMenuItem(*remove_iter);
860 } 884 }
861 885
886 MenuItem::ExtensionKey::ExtensionKey() : webview_instance_id(0) {}
887
888 MenuItem::ExtensionKey::ExtensionKey(const std::string& extension_id,
889 int webview_instance_id)
890 : extension_id(extension_id), webview_instance_id(webview_instance_id) {}
891
892 MenuItem::ExtensionKey::ExtensionKey(const std::string& extension_id)
893 : extension_id(extension_id), webview_instance_id(0) {}
894
895 bool MenuItem::ExtensionKey::operator==(const ExtensionKey& other) const {
896 return extension_id == other.extension_id &&
897 webview_instance_id == other.webview_instance_id;
898 }
899
900 bool MenuItem::ExtensionKey::operator<(const ExtensionKey& other) const {
901 if (webview_instance_id != other.webview_instance_id)
Yoyo Zhou 2014/03/07 02:40:30 nit: I would sort using extension id as the primar
lazyboy 2014/03/07 06:38:03 Done.
902 return webview_instance_id < other.webview_instance_id;
903
904 return extension_id < other.extension_id;
905 }
906
907 bool MenuItem::ExtensionKey::operator!=(const ExtensionKey& other) const {
908 return !(*this == other);
909 }
910
911 bool MenuItem::ExtensionKey::empty() const {
912 return extension_id.empty() && !webview_instance_id;
913 }
914
862 MenuItem::Id::Id() : incognito(false), uid(0) {} 915 MenuItem::Id::Id() : incognito(false), uid(0) {}
863 916
864 MenuItem::Id::Id(bool incognito, const std::string& extension_id) 917 MenuItem::Id::Id(bool incognito, const MenuItem::ExtensionKey& extension_key)
865 : incognito(incognito), extension_id(extension_id), uid(0) {} 918 : incognito(incognito), extension_key(extension_key), uid(0) {}
866 919
867 MenuItem::Id::~Id() { 920 MenuItem::Id::~Id() {
868 } 921 }
869 922
870 bool MenuItem::Id::operator==(const Id& other) const { 923 bool MenuItem::Id::operator==(const Id& other) const {
871 return (incognito == other.incognito && 924 return (incognito == other.incognito &&
872 extension_id == other.extension_id && 925 extension_key == other.extension_key && uid == other.uid &&
873 uid == other.uid &&
874 string_uid == other.string_uid); 926 string_uid == other.string_uid);
875 } 927 }
876 928
877 bool MenuItem::Id::operator!=(const Id& other) const { 929 bool MenuItem::Id::operator!=(const Id& other) const {
878 return !(*this == other); 930 return !(*this == other);
879 } 931 }
880 932
881 bool MenuItem::Id::operator<(const Id& other) const { 933 bool MenuItem::Id::operator<(const Id& other) const {
882 if (incognito < other.incognito) 934 if (incognito < other.incognito)
883 return true; 935 return true;
884 if (incognito == other.incognito) { 936 if (incognito == other.incognito) {
885 if (extension_id < other.extension_id) 937 if (extension_key < other.extension_key)
886 return true; 938 return true;
887 if (extension_id == other.extension_id) { 939 if (extension_key == other.extension_key) {
888 if (uid < other.uid) 940 if (uid < other.uid)
889 return true; 941 return true;
890 if (uid == other.uid) 942 if (uid == other.uid)
891 return string_uid < other.string_uid; 943 return string_uid < other.string_uid;
892 } 944 }
893 } 945 }
894 return false; 946 return false;
895 } 947 }
896 948
897 } // namespace extensions 949 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698