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

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

Issue 1246643004: [Extensions UI] Highlight toolbar extensions when the redesign bubble is active (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 5 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/extension_toolbar_model.h" 5 #include "chrome/browser/extensions/extension_toolbar_model.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 9
10 #include "base/location.h" 10 #include "base/location.h"
11 #include "base/metrics/histogram.h" 11 #include "base/metrics/histogram.h"
12 #include "base/metrics/histogram_base.h" 12 #include "base/metrics/histogram_base.h"
13 #include "base/prefs/pref_service.h" 13 #include "base/prefs/pref_service.h"
14 #include "base/single_thread_task_runner.h" 14 #include "base/single_thread_task_runner.h"
15 #include "base/thread_task_runner_handle.h" 15 #include "base/thread_task_runner_handle.h"
16 #include "chrome/browser/chrome_notification_types.h" 16 #include "chrome/browser/chrome_notification_types.h"
17 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" 17 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
18 #include "chrome/browser/extensions/extension_action_manager.h" 18 #include "chrome/browser/extensions/extension_action_manager.h"
19 #include "chrome/browser/extensions/extension_tab_util.h" 19 #include "chrome/browser/extensions/extension_tab_util.h"
20 #include "chrome/browser/extensions/extension_toolbar_model_factory.h" 20 #include "chrome/browser/extensions/extension_toolbar_model_factory.h"
21 #include "chrome/browser/extensions/extension_util.h" 21 #include "chrome/browser/extensions/extension_util.h"
22 #include "chrome/browser/extensions/tab_helper.h" 22 #include "chrome/browser/extensions/tab_helper.h"
23 #include "chrome/browser/profiles/profile.h" 23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/ui/browser.h" 24 #include "chrome/browser/ui/browser.h"
25 #include "chrome/browser/ui/extensions/extension_toolbar_icon_surfacing_bubble_d elegate.h"
25 #include "chrome/browser/ui/tabs/tab_strip_model.h" 26 #include "chrome/browser/ui/tabs/tab_strip_model.h"
26 #include "content/public/browser/notification_details.h" 27 #include "content/public/browser/notification_details.h"
27 #include "content/public/browser/notification_source.h" 28 #include "content/public/browser/notification_source.h"
28 #include "content/public/browser/web_contents.h" 29 #include "content/public/browser/web_contents.h"
29 #include "extensions/browser/extension_prefs.h" 30 #include "extensions/browser/extension_prefs.h"
30 #include "extensions/browser/extension_registry.h" 31 #include "extensions/browser/extension_registry.h"
31 #include "extensions/browser/extension_system.h" 32 #include "extensions/browser/extension_system.h"
32 #include "extensions/browser/pref_names.h" 33 #include "extensions/browser/pref_names.h"
33 #include "extensions/common/extension.h" 34 #include "extensions/common/extension.h"
34 #include "extensions/common/extension_set.h" 35 #include "extensions/common/extension_set.h"
35 #include "extensions/common/feature_switch.h" 36 #include "extensions/common/feature_switch.h"
36 #include "extensions/common/manifest_constants.h" 37 #include "extensions/common/manifest_constants.h"
37 #include "extensions/common/one_shot_event.h" 38 #include "extensions/common/one_shot_event.h"
38 39
39 namespace extensions { 40 namespace extensions {
40 41
41 ExtensionToolbarModel::ExtensionToolbarModel(Profile* profile, 42 ExtensionToolbarModel::ExtensionToolbarModel(Profile* profile,
42 ExtensionPrefs* extension_prefs) 43 ExtensionPrefs* extension_prefs)
43 : profile_(profile), 44 : profile_(profile),
44 extension_prefs_(extension_prefs), 45 extension_prefs_(extension_prefs),
45 prefs_(profile_->GetPrefs()), 46 prefs_(profile_->GetPrefs()),
46 extension_action_api_(ExtensionActionAPI::Get(profile_)), 47 extension_action_api_(ExtensionActionAPI::Get(profile_)),
47 extensions_initialized_(false), 48 extensions_initialized_(false),
48 include_all_extensions_( 49 include_all_extensions_(FeatureSwitch::extension_action_redesign()
49 FeatureSwitch::extension_action_redesign()->IsEnabled()), 50 ->IsEnabled()),
50 is_highlighting_(false), 51 highlight_type_(HIGHLIGHT_NONE),
51 extension_action_observer_(this), 52 extension_action_observer_(this),
52 extension_registry_observer_(this), 53 extension_registry_observer_(this),
53 weak_ptr_factory_(this) { 54 weak_ptr_factory_(this) {
54 ExtensionSystem::Get(profile_)->ready().Post( 55 ExtensionSystem::Get(profile_)->ready().Post(
55 FROM_HERE, 56 FROM_HERE,
56 base::Bind(&ExtensionToolbarModel::OnReady, 57 base::Bind(&ExtensionToolbarModel::OnReady,
57 weak_ptr_factory_.GetWeakPtr())); 58 weak_ptr_factory_.GetWeakPtr()));
58 visible_icon_count_ = prefs_->GetInteger(pref_names::kToolbarSize); 59 visible_icon_count_ = prefs_->GetInteger(pref_names::kToolbarSize);
59 60
60 // We only care about watching the prefs if not in incognito mode. 61 // We only care about watching the prefs if not in incognito mode.
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 UpdatePrefs(); 126 UpdatePrefs();
126 } 127 }
127 128
128 void ExtensionToolbarModel::SetVisibleIconCount(size_t count) { 129 void ExtensionToolbarModel::SetVisibleIconCount(size_t count) {
129 visible_icon_count_ = (count >= toolbar_items_.size()) ? -1 : count; 130 visible_icon_count_ = (count >= toolbar_items_.size()) ? -1 : count;
130 131
131 // Only set the prefs if we're not in highlight mode and the profile is not 132 // Only set the prefs if we're not in highlight mode and the profile is not
132 // incognito. Highlight mode is designed to be a transitory state, and should 133 // incognito. Highlight mode is designed to be a transitory state, and should
133 // not persist across browser restarts (though it may be re-entered), and we 134 // not persist across browser restarts (though it may be re-entered), and we
134 // don't store anything in incognito. 135 // don't store anything in incognito.
135 if (!is_highlighting_ && !profile_->IsOffTheRecord()) { 136 if (!is_highlighting() && !profile_->IsOffTheRecord()) {
136 // Additionally, if we are using the new toolbar, any icons which are in the 137 // Additionally, if we are using the new toolbar, any icons which are in the
137 // overflow menu are considered "hidden". But it so happens that the times 138 // overflow menu are considered "hidden". But it so happens that the times
138 // we are likely to call SetVisibleIconCount() are also those when we are 139 // we are likely to call SetVisibleIconCount() are also those when we are
139 // in flux. So wait for things to cool down before setting the prefs. 140 // in flux. So wait for things to cool down before setting the prefs.
140 base::ThreadTaskRunnerHandle::Get()->PostTask( 141 base::ThreadTaskRunnerHandle::Get()->PostTask(
141 FROM_HERE, 142 FROM_HERE,
142 base::Bind(&ExtensionToolbarModel::MaybeUpdateVisibilityPrefs, 143 base::Bind(&ExtensionToolbarModel::MaybeUpdateVisibilityPrefs,
143 weak_ptr_factory_.GetWeakPtr())); 144 weak_ptr_factory_.GetWeakPtr()));
144 prefs_->SetInteger(pref_names::kToolbarSize, visible_icon_count_); 145 prefs_->SetInteger(pref_names::kToolbarSize, visible_icon_count_);
145 } 146 }
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 } 242 }
242 243
243 void ExtensionToolbarModel::OnReady() { 244 void ExtensionToolbarModel::OnReady() {
244 ExtensionRegistry* registry = ExtensionRegistry::Get(profile_); 245 ExtensionRegistry* registry = ExtensionRegistry::Get(profile_);
245 InitializeExtensionList(); 246 InitializeExtensionList();
246 // Wait until the extension system is ready before observing any further 247 // Wait until the extension system is ready before observing any further
247 // changes so that the toolbar buttons can be shown in their stable ordering 248 // changes so that the toolbar buttons can be shown in their stable ordering
248 // taken from prefs. 249 // taken from prefs.
249 extension_registry_observer_.Add(registry); 250 extension_registry_observer_.Add(registry);
250 extension_action_observer_.Add(extension_action_api_); 251 extension_action_observer_.Add(extension_action_api_);
252
253 if (ExtensionToolbarIconSurfacingBubbleDelegate::ShouldShowForProfile(
254 profile_)) {
255 ExtensionIdList ids;
256 for (const auto& extension : toolbar_items_)
257 ids.push_back(extension->id());
258 HighlightExtensions(ids, HIGHLIGHT_INFO);
259 }
260
261 extensions_initialized_ = true;
262 FOR_EACH_OBSERVER(Observer, observers_, OnToolbarModelInitialized());
251 } 263 }
252 264
253 size_t ExtensionToolbarModel::FindNewPositionFromLastKnownGood( 265 size_t ExtensionToolbarModel::FindNewPositionFromLastKnownGood(
254 const Extension* extension) { 266 const Extension* extension) {
255 // See if we have last known good position for this extension. 267 // See if we have last known good position for this extension.
256 size_t new_index = 0; 268 size_t new_index = 0;
257 // Loop through the ID list of known positions, to count the number of visible 269 // Loop through the ID list of known positions, to count the number of visible
258 // extension icons preceding |extension|. 270 // extension icons preceding |extension|.
259 for (ExtensionIdList::const_iterator iter_id = last_known_positions_.begin(); 271 for (ExtensionIdList::const_iterator iter_id = last_known_positions_.begin();
260 iter_id < last_known_positions_.end(); ++iter_id) { 272 iter_id < last_known_positions_.end(); ++iter_id) {
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 UpdatePrefs(); 346 UpdatePrefs();
335 } else { 347 } else {
336 new_index = FindNewPositionFromLastKnownGood(extension); 348 new_index = FindNewPositionFromLastKnownGood(extension);
337 } 349 }
338 350
339 toolbar_items_.insert(toolbar_items_.begin() + new_index, extension); 351 toolbar_items_.insert(toolbar_items_.begin() + new_index, extension);
340 352
341 // If we're currently highlighting, then even though we add a browser action 353 // If we're currently highlighting, then even though we add a browser action
342 // to the full list (|toolbar_items_|, there won't be another *visible* 354 // to the full list (|toolbar_items_|, there won't be another *visible*
343 // browser action, which was what the observers care about. 355 // browser action, which was what the observers care about.
344 if (!is_highlighting_) { 356 if (!is_highlighting()) {
345 FOR_EACH_OBSERVER(Observer, observers_, 357 FOR_EACH_OBSERVER(Observer, observers_,
346 OnToolbarExtensionAdded(extension, new_index)); 358 OnToolbarExtensionAdded(extension, new_index));
347 359
348 int visible_count_delta = 0; 360 int visible_count_delta = 0;
349 if (is_new_extension && !all_icons_visible()) { 361 if (is_new_extension && !all_icons_visible()) {
350 // If this is a new extension (and not all extensions are visible), we 362 // If this is a new extension (and not all extensions are visible), we
351 // expand the toolbar out so that the new one can be seen. 363 // expand the toolbar out so that the new one can be seen.
352 visible_count_delta = 1; 364 visible_count_delta = 1;
353 } else if (profile_->IsOffTheRecord()) { 365 } else if (profile_->IsOffTheRecord()) {
354 // If this is an incognito profile, we also have to check to make sure the 366 // If this is an incognito profile, we also have to check to make sure the
(...skipping 29 matching lines...) Expand all
384 return; 396 return;
385 397
386 // If our visible count is set to the current size, we need to decrement it. 398 // If our visible count is set to the current size, we need to decrement it.
387 if (visible_icon_count_ == static_cast<int>(toolbar_items_.size())) 399 if (visible_icon_count_ == static_cast<int>(toolbar_items_.size()))
388 SetVisibleIconCount(toolbar_items_.size() - 1); 400 SetVisibleIconCount(toolbar_items_.size() - 1);
389 401
390 toolbar_items_.erase(pos); 402 toolbar_items_.erase(pos);
391 403
392 // If we're in highlight mode, we also have to remove the extension from 404 // If we're in highlight mode, we also have to remove the extension from
393 // the highlighted list. 405 // the highlighted list.
394 if (is_highlighting_) { 406 if (is_highlighting()) {
395 pos = std::find(highlighted_items_.begin(), 407 pos = std::find(highlighted_items_.begin(),
396 highlighted_items_.end(), 408 highlighted_items_.end(),
397 extension); 409 extension);
398 if (pos != highlighted_items_.end()) { 410 if (pos != highlighted_items_.end()) {
399 highlighted_items_.erase(pos); 411 highlighted_items_.erase(pos);
400 FOR_EACH_OBSERVER(Observer, observers_, 412 FOR_EACH_OBSERVER(Observer, observers_,
401 OnToolbarExtensionRemoved(extension)); 413 OnToolbarExtensionRemoved(extension));
402 // If the highlighted list is now empty, we stop highlighting. 414 // If the highlighted list is now empty, we stop highlighting.
403 if (highlighted_items_.empty()) 415 if (highlighted_items_.empty())
404 StopHighlighting(); 416 StopHighlighting();
(...skipping 15 matching lines...) Expand all
420 // 3. Remove holes from the sorted vector and append the unsorted vector. 432 // 3. Remove holes from the sorted vector and append the unsorted vector.
421 void ExtensionToolbarModel::InitializeExtensionList() { 433 void ExtensionToolbarModel::InitializeExtensionList() {
422 DCHECK(toolbar_items_.empty()); // We shouldn't have any items yet. 434 DCHECK(toolbar_items_.empty()); // We shouldn't have any items yet.
423 435
424 last_known_positions_ = extension_prefs_->GetToolbarOrder(); 436 last_known_positions_ = extension_prefs_->GetToolbarOrder();
425 if (profile_->IsOffTheRecord()) 437 if (profile_->IsOffTheRecord())
426 IncognitoPopulate(); 438 IncognitoPopulate();
427 else 439 else
428 Populate(&last_known_positions_); 440 Populate(&last_known_positions_);
429 441
430 extensions_initialized_ = true;
431 MaybeUpdateVisibilityPrefs(); 442 MaybeUpdateVisibilityPrefs();
432 FOR_EACH_OBSERVER(Observer, observers_, OnToolbarModelInitialized());
433 } 443 }
434 444
435 void ExtensionToolbarModel::Populate(ExtensionIdList* positions) { 445 void ExtensionToolbarModel::Populate(ExtensionIdList* positions) {
436 DCHECK(!profile_->IsOffTheRecord()); 446 DCHECK(!profile_->IsOffTheRecord());
437 const ExtensionSet& extensions = 447 const ExtensionSet& extensions =
438 ExtensionRegistry::Get(profile_)->enabled_extensions(); 448 ExtensionRegistry::Get(profile_)->enabled_extensions();
439 // Items that have explicit positions. 449 // Items that have explicit positions.
440 ExtensionList sorted(positions->size(), NULL); 450 ExtensionList sorted(positions->size(), NULL);
441 // The items that don't have explicit positions. 451 // The items that don't have explicit positions.
442 ExtensionList unsorted; 452 ExtensionList unsorted;
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
650 if (extension - toolbar_items_.begin() >= 660 if (extension - toolbar_items_.begin() >=
651 static_cast<int>(visible_icon_count())) 661 static_cast<int>(visible_icon_count()))
652 MoveExtensionIcon((*extension)->id(), 0); 662 MoveExtensionIcon((*extension)->id(), 0);
653 break; 663 break;
654 } 664 }
655 } 665 }
656 } 666 }
657 } 667 }
658 668
659 bool ExtensionToolbarModel::HighlightExtensions( 669 bool ExtensionToolbarModel::HighlightExtensions(
660 const ExtensionIdList& extension_ids) { 670 const ExtensionIdList& extension_ids,
671 HighlightType highlight_type) {
661 highlighted_items_.clear(); 672 highlighted_items_.clear();
662 673
663 for (ExtensionIdList::const_iterator id = extension_ids.begin(); 674 for (ExtensionIdList::const_iterator id = extension_ids.begin();
664 id != extension_ids.end(); 675 id != extension_ids.end();
665 ++id) { 676 ++id) {
666 for (ExtensionList::const_iterator extension = toolbar_items_.begin(); 677 for (ExtensionList::const_iterator extension = toolbar_items_.begin();
667 extension != toolbar_items_.end(); 678 extension != toolbar_items_.end();
668 ++extension) { 679 ++extension) {
669 if (*id == (*extension)->id()) 680 if (*id == (*extension)->id())
670 highlighted_items_.push_back(*extension); 681 highlighted_items_.push_back(*extension);
671 } 682 }
672 } 683 }
673 684
674 // If we have any items in |highlighted_items_|, then we entered highlighting 685 // If we have any items in |highlighted_items_|, then we entered highlighting
675 // mode. 686 // mode.
676 if (highlighted_items_.size()) { 687 if (highlighted_items_.size()) {
677 old_visible_icon_count_ = visible_icon_count_; 688 // It's important that is_highlighting_ is changed immediately before the
689 // observers are notified since it changes the result of toolbar_items().
690 highlight_type_ = highlight_type;
691 FOR_EACH_OBSERVER(Observer, observers_,
692 OnToolbarHighlightModeChanged(true));
693
694 // We set the visible icon count after the highlight mode change because
695 // the UI actions are created/destroyed during highlight, and doing that
696 // prior to changing the size allows us to still have smooth animations.
678 if (visible_icon_count() < extension_ids.size()) 697 if (visible_icon_count() < extension_ids.size())
679 SetVisibleIconCount(extension_ids.size()); 698 SetVisibleIconCount(extension_ids.size());
680 699
681 // It's important that is_highlighting_ is changed immediately before the
682 // observers are notified since it changes the result of toolbar_items().
683 is_highlighting_ = true;
684 FOR_EACH_OBSERVER(Observer, observers_,
685 OnToolbarHighlightModeChanged(true));
686 return true; 700 return true;
687 } 701 }
688 702
689 // Otherwise, we didn't enter highlighting mode (and, in fact, exited it if 703 // Otherwise, we didn't enter highlighting mode (and, in fact, exited it if
690 // we were otherwise in it). 704 // we were otherwise in it).
691 if (is_highlighting_) 705 if (is_highlighting())
692 StopHighlighting(); 706 StopHighlighting();
693 return false; 707 return false;
694 } 708 }
695 709
696 void ExtensionToolbarModel::StopHighlighting() { 710 void ExtensionToolbarModel::StopHighlighting() {
697 if (is_highlighting_) { 711 if (is_highlighting()) {
698 if (old_visible_icon_count_ != visible_icon_count_)
699 SetVisibleIconCount(old_visible_icon_count_);
700
701 // It's important that is_highlighting_ is changed immediately before the 712 // It's important that is_highlighting_ is changed immediately before the
702 // observers are notified since it changes the result of toolbar_items(). 713 // observers are notified since it changes the result of toolbar_items().
703 is_highlighting_ = false; 714 highlight_type_ = HIGHLIGHT_NONE;
704 FOR_EACH_OBSERVER(Observer, observers_, 715 FOR_EACH_OBSERVER(Observer, observers_,
705 OnToolbarHighlightModeChanged(false)); 716 OnToolbarHighlightModeChanged(false));
717
706 // For the same reason, we don't clear highlighted_items_ until after the 718 // For the same reason, we don't clear highlighted_items_ until after the
707 // mode changed. 719 // mode changed.
708 highlighted_items_.clear(); 720 highlighted_items_.clear();
721
722 // We set the visible icon count after the highlight mode change because
723 // the UI actions are created/destroyed during highlight, and doing that
724 // prior to changing the size allows us to still have smooth animations.
725 int saved_icon_count = prefs_->GetInteger(pref_names::kToolbarSize);
726 if (saved_icon_count != visible_icon_count_)
727 SetVisibleIconCount(saved_icon_count);
709 } 728 }
710 } 729 }
711 730
712 bool ExtensionToolbarModel::RedesignIsShowingNewIcons() const { 731 bool ExtensionToolbarModel::RedesignIsShowingNewIcons() const {
713 for (const scoped_refptr<const Extension>& extension : toolbar_items_) { 732 for (const scoped_refptr<const Extension>& extension : toolbar_items_) {
714 // Without the redesign, we only show extensions with browser actions. 733 // Without the redesign, we only show extensions with browser actions.
715 // Any extension without a browser action is an indication that we're 734 // Any extension without a browser action is an indication that we're
716 // showing something new. 735 // showing something new.
717 if (!extension->manifest()->HasKey(manifest_keys::kBrowserAction)) 736 if (!extension->manifest()->HasKey(manifest_keys::kBrowserAction))
718 return true; 737 return true;
719 } 738 }
720 return false; 739 return false;
721 } 740 }
722 741
723 } // namespace extensions 742 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_toolbar_model.h ('k') | chrome/browser/extensions/extension_toolbar_model_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698