summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorxiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-18 02:22:15 +0000
committerxiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-18 02:22:15 +0000
commitd42ef8acdf908a348d0aec5a4814b6257f42276c (patch)
treeb7ec497d6ffe57611f9f07626060845edbf5f8be
parentc8d6b485995362620025e3b7ad74772beac803d7 (diff)
downloadchromium_src-d42ef8acdf908a348d0aec5a4814b6257f42276c.zip
chromium_src-d42ef8acdf908a348d0aec5a4814b6257f42276c.tar.gz
chromium_src-d42ef8acdf908a348d0aec5a4814b6257f42276c.tar.bz2
chromeos: Sync animation.
- Pulse app list button while LauncherModel has STATUS_LOADING; - Remove LauncherItemStatus::STATUS_IS_PENDING etc since it is no longer needed; - ChromeLauncherController sets LauncherModel::STATUS_LOADING on starting and watch for sync finish and pending extension install. It sets LauncherModel::STATUS_NORMAL when sync is finished and there is no pending extension install from sync, or when a maximum 60 seconds timeout since turning on loading status; BUG=129236 TEST=Verify sync animation after OOBE. Review URL: https://chromiumcodereview.appspot.com/10829268 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@152221 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ash/ash_strings.grd3
-rw-r--r--ash/launcher/app_list_button.cc98
-rw-r--r--ash/launcher/app_list_button.h5
-rw-r--r--ash/launcher/launcher_button.cc107
-rw-r--r--ash/launcher/launcher_button.h12
-rw-r--r--ash/launcher/launcher_model.cc12
-rw-r--r--ash/launcher/launcher_model.h10
-rw-r--r--ash/launcher/launcher_model_observer.h5
-rw-r--r--ash/launcher/launcher_model_unittest.cc5
-rw-r--r--ash/launcher/launcher_types.h5
-rw-r--r--ash/launcher/launcher_view.cc53
-rw-r--r--ash/launcher/launcher_view.h1
-rw-r--r--ash/launcher/launcher_view_unittest.cc6
-rw-r--r--chrome/browser/extensions/pending_extension_manager.cc16
-rw-r--r--chrome/browser/extensions/pending_extension_manager.h3
-rw-r--r--chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc129
-rw-r--r--chrome/browser/ui/ash/launcher/chrome_launcher_controller.h30
-rw-r--r--chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc22
-rw-r--r--chrome/browser/ui/ash/launcher/launcher_context_menu.cc33
19 files changed, 279 insertions, 276 deletions
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index e48d9d7..3364014 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -167,6 +167,9 @@ This file contains the strings for ash.
<message name="IDS_AURA_APP_LIST_TITLE" desc="The title used for the Aura app list in the launcher">
Apps
</message>
+ <message name="IDS_AURA_APP_LIST_SYNCING_TITLE" desc="The title used for the Aura app list in the launcher to indicate loading/syncing apps.">
+ Syncing apps...
+ </message>
<message name="IDS_AURA_NEW_TAB" desc="The text label of the New Tab menu item">
New tab
</message>
diff --git a/ash/launcher/app_list_button.cc b/ash/launcher/app_list_button.cc
index 14e80e5..d38fe22 100644
--- a/ash/launcher/app_list_button.cc
+++ b/ash/launcher/app_list_button.cc
@@ -4,35 +4,113 @@
#include "ash/launcher/app_list_button.h"
+#include <vector>
+
#include "ash/launcher/launcher_button_host.h"
+#include "ash/launcher/launcher_types.h"
+#include "grit/ash_strings.h"
+#include "grit/ui_resources.h"
#include "ui/base/accessibility/accessible_view_state.h"
-#include "ui/base/animation/animation_delegate.h"
-#include "ui/base/animation/throb_animation.h"
+#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_element.h"
-#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/image/image.h"
-#include "ui/gfx/shadow_value.h"
-#include "ui/gfx/skbitmap_operations.h"
#include "ui/gfx/transform_util.h"
-#include "ui/views/controls/image_view.h"
namespace ash {
-
namespace internal {
+namespace {
+
+const int kAnimationDurationInMs = 600;
+const float kAnimationOpacity[] = { 0.4f, 0.8f, 0.4f };
+const float kAnimationScale[] = { 0.8f, 1.0f, 0.8f };
+
+} // namespace
+
AppListButton::AppListButton(views::ButtonListener* listener,
LauncherButtonHost* host)
: views::ImageButton(listener),
- host_(host) {}
+ host_(host) {
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ SetImage(
+ views::CustomButton::BS_NORMAL,
+ rb.GetImageNamed(IDR_AURA_LAUNCHER_ICON_APPLIST).ToImageSkia());
+ SetImage(
+ views::CustomButton::BS_HOT,
+ rb.GetImageNamed(IDR_AURA_LAUNCHER_ICON_APPLIST_HOT).
+ ToImageSkia());
+ SetImage(
+ views::CustomButton::BS_PUSHED,
+ rb.GetImageNamed(IDR_AURA_LAUNCHER_ICON_APPLIST_PUSHED).
+ ToImageSkia());
+ SetAccessibleName(l10n_util::GetStringUTF16(IDS_AURA_APP_LIST_TITLE));
+ SetSize(gfx::Size(kLauncherPreferredSize, kLauncherPreferredSize));
+}
AppListButton::~AppListButton() {
}
+void AppListButton::StartLoadingAnimation() {
+ // The two animation set should have the same size.
+ DCHECK_EQ(arraysize(kAnimationOpacity), arraysize(kAnimationScale));
+
+ layer()->GetAnimator()->StopAnimating();
+
+ scoped_ptr<ui::LayerAnimationSequence> opacity_sequence(
+ new ui::LayerAnimationSequence());
+ scoped_ptr<ui::LayerAnimationSequence> transform_sequence(
+ new ui::LayerAnimationSequence());
+
+ // The animations loop infinitely.
+ opacity_sequence->set_is_cyclic(true);
+ transform_sequence->set_is_cyclic(true);
+
+ for (size_t i = 0; i < arraysize(kAnimationOpacity); ++i) {
+ opacity_sequence->AddElement(
+ ui::LayerAnimationElement::CreateOpacityElement(
+ kAnimationOpacity[i],
+ base::TimeDelta::FromMilliseconds(kAnimationDurationInMs)));
+ transform_sequence->AddElement(
+ ui::LayerAnimationElement::CreateTransformElement(
+ ui::GetScaleTransform(GetLocalBounds().CenterPoint(),
+ kAnimationScale[i]),
+ base::TimeDelta::FromMilliseconds(kAnimationDurationInMs)));
+ }
+
+ ui::LayerAnimationElement::AnimatableProperties opacity_properties;
+ opacity_properties.insert(ui::LayerAnimationElement::OPACITY);
+ opacity_sequence->AddElement(
+ ui::LayerAnimationElement::CreatePauseElement(
+ opacity_properties,
+ base::TimeDelta::FromMilliseconds(kAnimationDurationInMs)));
+
+ ui::LayerAnimationElement::AnimatableProperties transform_properties;
+ transform_properties.insert(ui::LayerAnimationElement::TRANSFORM);
+ transform_sequence->AddElement(
+ ui::LayerAnimationElement::CreatePauseElement(
+ transform_properties,
+ base::TimeDelta::FromMilliseconds(kAnimationDurationInMs)));
+
+ std::vector<ui::LayerAnimationSequence*> animations;
+ // LayerAnimator::ScheduleTogether takes ownership of the sequences.
+ animations.push_back(opacity_sequence.release());
+ animations.push_back(transform_sequence.release());
+ layer()->GetAnimator()->ScheduleTogether(animations);
+}
+
+void AppListButton::StopLoadingAnimation() {
+ layer()->GetAnimator()->StopAnimating();
+
+ ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator());
+ settings.SetTransitionDuration(
+ base::TimeDelta::FromMilliseconds(kAnimationDurationInMs));
+ layer()->SetOpacity(1.0f);
+ layer()->SetTransform(ui::Transform());
+}
+
bool AppListButton::OnMousePressed(const ui::MouseEvent& event) {
ImageButton::OnMousePressed(event);
host_->PointerPressedOnButton(this, LauncherButtonHost::MOUSE, event);
diff --git a/ash/launcher/app_list_button.h b/ash/launcher/app_list_button.h
index ee18557..4d25254 100644
--- a/ash/launcher/app_list_button.h
+++ b/ash/launcher/app_list_button.h
@@ -19,6 +19,9 @@ class AppListButton : public views::ImageButton {
LauncherButtonHost* host);
virtual ~AppListButton();
+ void StartLoadingAnimation();
+ void StopLoadingAnimation();
+
protected:
// View overrides:
virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
@@ -39,4 +42,4 @@ class AppListButton : public views::ImageButton {
} // namespace internal
} // namespace ash
-#endif // ASH_LAUNCHER_LAUNCHER_BUTTON_H_
+#endif // ASH_LAUNCHER_APP_LIST_BUTTON_H_
diff --git a/ash/launcher/launcher_button.cc b/ash/launcher/launcher_button.cc
index b550d56d..c0d0685 100644
--- a/ash/launcher/launcher_button.cc
+++ b/ash/launcher/launcher_button.cc
@@ -5,7 +5,6 @@
#include "ash/launcher/launcher_button.h"
#include <algorithm>
-#include <vector>
#include "ash/launcher/launcher_button_host.h"
#include "grit/ui_resources.h"
@@ -16,14 +15,10 @@
#include "ui/base/events.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/compositor/layer.h"
-#include "ui/compositor/layer_animation_element.h"
-#include "ui/compositor/layer_animation_observer.h"
-#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia_operations.h"
-#include "ui/gfx/transform_util.h"
#include "ui/views/controls/image_view.h"
namespace {
@@ -100,102 +95,6 @@ class LauncherButton::BarView : public views::ImageView,
};
////////////////////////////////////////////////////////////////////////////////
-// LauncherButton::IconPulseAnimation
-
-// IconPulseAnimation plays a pulse animation in a loop for given |icon_view|.
-// It iterates through all animations, wait for one duration then starts again.
-class LauncherButton::IconPulseAnimation {
- public:
- explicit IconPulseAnimation(IconView* icon_view)
- : icon_view_(icon_view) {
- SchedulePulseAnimations();
- }
- virtual ~IconPulseAnimation() {
- // Restore icon_view_ on destruction.
- ScheduleRestoreAnimation();
- }
-
- private:
- // Animation duration in millisecond.
- static const int kAnimationDurationInMs;
-
- // Number of animations to run and animation parameters.
- static const float kAnimationOpacity[];
- static const float kAnimationScale[];
-
- // Schedules pulse animations.
- void SchedulePulseAnimations();
-
- // Schedule an animation to restore the view to normal state.
- void ScheduleRestoreAnimation();
-
- IconView* icon_view_; // Owned by views hierarchy of LauncherButton.
-
- DISALLOW_COPY_AND_ASSIGN(IconPulseAnimation);
-};
-
-// static
-const int LauncherButton::IconPulseAnimation::kAnimationDurationInMs = 600;
-const float LauncherButton::IconPulseAnimation::kAnimationOpacity[] =
- { 0.4f, 0.8f };
-const float LauncherButton::IconPulseAnimation::kAnimationScale[] =
- { 0.8f, 1.0f };
-
-void LauncherButton::IconPulseAnimation::SchedulePulseAnimations() {
- // The two animation set should have the same size.
- DCHECK(arraysize(kAnimationOpacity) == arraysize(kAnimationScale));
-
- scoped_ptr<ui::LayerAnimationSequence> opacity_sequence(
- new ui::LayerAnimationSequence());
- scoped_ptr<ui::LayerAnimationSequence> transform_sequence(
- new ui::LayerAnimationSequence());
-
- // The animations loop infinitely.
- opacity_sequence->set_is_cyclic(true);
- transform_sequence->set_is_cyclic(true);
-
- for (size_t i = 0; i < arraysize(kAnimationOpacity); ++i) {
- opacity_sequence->AddElement(
- ui::LayerAnimationElement::CreateOpacityElement(
- kAnimationOpacity[i],
- base::TimeDelta::FromMilliseconds(kAnimationDurationInMs)));
- transform_sequence->AddElement(
- ui::LayerAnimationElement::CreateTransformElement(
- ui::GetScaleTransform(icon_view_->GetLocalBounds().CenterPoint(),
- kAnimationScale[i]),
- base::TimeDelta::FromMilliseconds(kAnimationDurationInMs)));
- }
-
- ui::LayerAnimationElement::AnimatableProperties opacity_properties;
- opacity_properties.insert(ui::LayerAnimationElement::OPACITY);
- opacity_sequence->AddElement(
- ui::LayerAnimationElement::CreatePauseElement(
- opacity_properties,
- base::TimeDelta::FromMilliseconds(kAnimationDurationInMs)));
-
- ui::LayerAnimationElement::AnimatableProperties transform_properties;
- transform_properties.insert(ui::LayerAnimationElement::TRANSFORM);
- transform_sequence->AddElement(
- ui::LayerAnimationElement::CreatePauseElement(
- transform_properties,
- base::TimeDelta::FromMilliseconds(kAnimationDurationInMs)));
-
- std::vector<ui::LayerAnimationSequence*> animations;
- // LayerAnimator::ScheduleTogether takes ownership of the sequences.
- animations.push_back(opacity_sequence.release());
- animations.push_back(transform_sequence.release());
- icon_view_->layer()->GetAnimator()->ScheduleTogether(animations);
-}
-
-// Schedule an animation to restore the view to normal state.
-void LauncherButton::IconPulseAnimation::ScheduleRestoreAnimation() {
- ui::Layer* layer = icon_view_->layer();
- ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
- layer->SetOpacity(1.0f);
- layer->SetTransform(ui::Transform());
-}
-
-////////////////////////////////////////////////////////////////////////////////
// LauncherButton::IconView
LauncherButton::IconView::IconView() : icon_size_(kIconSize) {
@@ -293,8 +192,6 @@ void LauncherButton::AddState(State state) {
}
if (state & STATE_ATTENTION)
bar_->ShowAttention(true);
- if (state & STATE_PENDING)
- icon_pulse_animation_.reset(new IconPulseAnimation(icon_view_));
}
}
@@ -314,8 +211,6 @@ void LauncherButton::ClearState(State state) {
}
if (state & STATE_ATTENTION)
bar_->ShowAttention(false);
- if (state & STATE_PENDING)
- icon_pulse_animation_.reset();
}
}
@@ -461,7 +356,7 @@ bool LauncherButton::IsShelfHorizontal() const {
}
void LauncherButton::UpdateState() {
- if (state_ == STATE_NORMAL || state_ & STATE_PENDING) {
+ if (state_ == STATE_NORMAL) {
bar_->SetVisible(false);
} else {
int bar_id;
diff --git a/ash/launcher/launcher_button.h b/ash/launcher/launcher_button.h
index 161f13e..eb4a735 100644
--- a/ash/launcher/launcher_button.h
+++ b/ash/launcher/launcher_button.h
@@ -5,7 +5,6 @@
#ifndef ASH_LAUNCHER_LAUNCHER_BUTTON_H_
#define ASH_LAUNCHER_LAUNCHER_BUTTON_H_
-#include "base/memory/scoped_ptr.h"
#include "ui/gfx/shadow_value.h"
#include "ui/views/controls/button/custom_button.h"
#include "ui/views/controls/image_view.h"
@@ -32,11 +31,7 @@ class LauncherButton : public views::CustomButton {
STATE_ACTIVE = 1 << 2,
// Underlying LauncherItem needs user's attention.
STATE_ATTENTION = 1 << 3,
- // Underlying LauncherItem has pending operations.
- // e.g. A TYPE_APP_SHORTCUT item whose corresponding app is being
- // installed.
- STATE_PENDING = 1 << 4,
- STATE_FOCUSED = 1 << 5,
+ STATE_FOCUSED = 1 << 4,
};
virtual ~LauncherButton();
@@ -107,7 +102,6 @@ class LauncherButton : public views::CustomButton {
private:
class BarView;
- class IconPulseAnimation;
// Returns true if the shelf is horizontal. If this returns false the shelf is
// vertical.
@@ -125,10 +119,6 @@ class LauncherButton : public views::CustomButton {
// together.
int state_;
- // Runs a pulse animation for |icon_view_|. It is created when button state
- // has a STATE_PENDING bit and destroyed when that bit is clear.
- scoped_ptr<IconPulseAnimation> icon_pulse_animation_;
-
gfx::ShadowValues icon_shadows_;
DISALLOW_COPY_AND_ASSIGN(LauncherButton);
diff --git a/ash/launcher/launcher_model.cc b/ash/launcher/launcher_model.cc
index d9aa8ad..2945a5d 100644
--- a/ash/launcher/launcher_model.cc
+++ b/ash/launcher/launcher_model.cc
@@ -7,7 +7,6 @@
#include <algorithm>
#include "ash/launcher/launcher_model_observer.h"
-#include "ui/aura/window.h"
namespace ash {
@@ -37,7 +36,7 @@ bool CompareByWeight(const LauncherItem& a, const LauncherItem& b) {
} // namespace
-LauncherModel::LauncherModel() : next_id_(1) {
+LauncherModel::LauncherModel() : next_id_(1), status_(STATUS_NORMAL) {
LauncherItem app_list;
app_list.type = TYPE_APP_LIST;
app_list.is_incognito = false;
@@ -118,6 +117,15 @@ LauncherItems::const_iterator LauncherModel::ItemByID(int id) const {
return items_.end();
}
+void LauncherModel::SetStatus(Status status) {
+ if (status_ == status)
+ return;
+
+ status_ = status;
+ FOR_EACH_OBSERVER(LauncherModelObserver, observers_,
+ LauncherStatusChanged());
+}
+
void LauncherModel::AddObserver(LauncherModelObserver* observer) {
observers_.AddObserver(observer);
}
diff --git a/ash/launcher/launcher_model.h b/ash/launcher/launcher_model.h
index d4cd05e..a733a1b 100644
--- a/ash/launcher/launcher_model.h
+++ b/ash/launcher/launcher_model.h
@@ -22,6 +22,12 @@ class LauncherModelObserver;
// Model used by LauncherView.
class ASH_EXPORT LauncherModel {
public:
+ enum Status {
+ STATUS_NORMAL,
+ // A status that indicates apps are syncing/loading.
+ STATUS_LOADING,
+ };
+
LauncherModel();
~LauncherModel();
@@ -56,6 +62,9 @@ class ASH_EXPORT LauncherModel {
const LauncherItems& items() const { return items_; }
int item_count() const { return static_cast<int>(items_.size()); }
+ void SetStatus(Status status);
+ Status status() const { return status_; }
+
void AddObserver(LauncherModelObserver* observer);
void RemoveObserver(LauncherModelObserver* observer);
@@ -68,6 +77,7 @@ class ASH_EXPORT LauncherModel {
// ID assigned to the next item.
LauncherID next_id_;
LauncherItems items_;
+ Status status_;
ObserverList<LauncherModelObserver> observers_;
DISALLOW_COPY_AND_ASSIGN(LauncherModel);
diff --git a/ash/launcher/launcher_model_observer.h b/ash/launcher/launcher_model_observer.h
index 5d73d1c..16067c0 100644
--- a/ash/launcher/launcher_model_observer.h
+++ b/ash/launcher/launcher_model_observer.h
@@ -25,10 +25,13 @@ class ASH_EXPORT LauncherModelObserver {
// of the arguments.
virtual void LauncherItemMoved(int start_index, int target_index) = 0;
- // Invoked when the the state of an item changes. |old_item| is the item
+ // Invoked when the state of an item changes. |old_item| is the item
// before the change.
virtual void LauncherItemChanged(int index, const LauncherItem& old_item) = 0;
+ // Invoked when launcher status is changed.
+ virtual void LauncherStatusChanged() = 0;
+
protected:
virtual ~LauncherModelObserver() {}
};
diff --git a/ash/launcher/launcher_model_unittest.cc b/ash/launcher/launcher_model_unittest.cc
index cc449eba..9a4fbcd 100644
--- a/ash/launcher/launcher_model_unittest.cc
+++ b/ash/launcher/launcher_model_unittest.cc
@@ -4,6 +4,9 @@
#include "ash/launcher/launcher_model.h"
+#include <set>
+#include <string>
+
#include "ash/launcher/launcher_model_observer.h"
#include "base/stringprintf.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -48,6 +51,8 @@ class TestLauncherModelObserver : public LauncherModelObserver {
virtual void LauncherItemMoved(int start_index, int target_index) OVERRIDE {
moved_count_++;
}
+ virtual void LauncherStatusChanged() OVERRIDE {
+ }
private:
void AddToResult(const std::string& format, int count, std::string* result) {
diff --git a/ash/launcher/launcher_types.h b/ash/launcher/launcher_types.h
index a6a6dc0..24110f4 100644
--- a/ash/launcher/launcher_types.h
+++ b/ash/launcher/launcher_types.h
@@ -56,11 +56,6 @@ enum LauncherItemStatus {
STATUS_ACTIVE,
// A LauncherItem that needs user's attention.
STATUS_ATTENTION,
- // A LauncherItem that has pending operations.
- // e.g. A TYEE_APP_SHORTCUT item whose application is
- // being installed/upgraded.
- // Note STATUS_PENDING is a macro in WinNT.h on Windows.
- STATUS_IS_PENDING,
};
struct ASH_EXPORT LauncherItem {
diff --git a/ash/launcher/launcher_view.cc b/ash/launcher/launcher_view.cc
index 20fa176..9a72042 100644
--- a/ash/launcher/launcher_view.cc
+++ b/ash/launcher/launcher_view.cc
@@ -18,27 +18,20 @@
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "base/auto_reset.h"
-#include "base/utf_string_conversions.h"
+#include "base/memory/scoped_ptr.h"
#include "grit/ash_strings.h"
#include "grit/ui_resources.h"
-#include "ui/aura/window.h"
-#include "ui/base/animation/animation.h"
-#include "ui/base/animation/throb_animation.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/simple_menu_model.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/compositor/layer.h"
-#include "ui/gfx/image/image.h"
#include "ui/views/animation/bounds_animator.h"
#include "ui/views/border.h"
-#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/menu/menu_model_adapter.h"
#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/focus/focus_search.h"
#include "ui/views/view_model.h"
#include "ui/views/view_model_utils.h"
-#include "ui/views/widget/root_view.h"
-#include "ui/views/widget/widget.h"
using ui::Animation;
using views::View;
@@ -47,13 +40,13 @@ namespace ash {
namespace internal {
// Default amount content is inset on the left edge.
-static const int kDefaultLeadingInset = 8;
+const int kDefaultLeadingInset = 8;
// Minimum distance before drag starts.
-static const int kMinimumDragDistance = 8;
+const int kMinimumDragDistance = 8;
// Size between the buttons.
-static const int kButtonSpacing = 4;
+const int kButtonSpacing = 4;
namespace {
@@ -177,31 +170,21 @@ void ReflectItemStatus(const ash::LauncherItem& item,
button->ClearState(LauncherButton::STATE_ACTIVE);
button->ClearState(LauncherButton::STATE_RUNNING);
button->ClearState(LauncherButton::STATE_ATTENTION);
- button->ClearState(LauncherButton::STATE_PENDING);
break;
case STATUS_RUNNING:
button->ClearState(LauncherButton::STATE_ACTIVE);
button->AddState(LauncherButton::STATE_RUNNING);
button->ClearState(LauncherButton::STATE_ATTENTION);
- button->ClearState(LauncherButton::STATE_PENDING);
break;
case STATUS_ACTIVE:
button->AddState(LauncherButton::STATE_ACTIVE);
button->ClearState(LauncherButton::STATE_RUNNING);
button->ClearState(LauncherButton::STATE_ATTENTION);
- button->ClearState(LauncherButton::STATE_PENDING);
break;
case STATUS_ATTENTION:
button->ClearState(LauncherButton::STATE_ACTIVE);
button->ClearState(LauncherButton::STATE_RUNNING);
button->AddState(LauncherButton::STATE_ATTENTION);
- button->ClearState(LauncherButton::STATE_PENDING);
- break;
- case STATUS_IS_PENDING:
- button->ClearState(LauncherButton::STATE_ACTIVE);
- button->ClearState(LauncherButton::STATE_RUNNING);
- button->ClearState(LauncherButton::STATE_ATTENTION);
- button->AddState(LauncherButton::STATE_PENDING);
break;
}
}
@@ -304,6 +287,7 @@ void LauncherView::Init() {
AddChildView(child);
}
UpdateFirstButtonPadding();
+ LauncherStatusChanged();
overflow_button_ = new OverflowButton(this);
overflow_button_->set_context_menu_controller(this);
@@ -522,21 +506,7 @@ views::View* LauncherView::CreateViewForItem(const LauncherItem& item) {
case TYPE_APP_LIST: {
// TODO(dave): turn this into a LauncherButton too.
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
AppListButton* button = new AppListButton(this, this);
- button->SetImage(
- views::CustomButton::BS_NORMAL,
- rb.GetImageNamed(IDR_AURA_LAUNCHER_ICON_APPLIST).ToImageSkia());
- button->SetImage(
- views::CustomButton::BS_HOT,
- rb.GetImageNamed(IDR_AURA_LAUNCHER_ICON_APPLIST_HOT).
- ToImageSkia());
- button->SetImage(
- views::CustomButton::BS_PUSHED,
- rb.GetImageNamed(IDR_AURA_LAUNCHER_ICON_APPLIST_PUSHED).
- ToImageSkia());
- button->SetAccessibleName(
- l10n_util::GetStringUTF16(IDS_AURA_APP_LIST_TITLE));
view = button;
break;
}
@@ -887,6 +857,15 @@ void LauncherView::LauncherItemMoved(int start_index, int target_index) {
AnimateToIdealBounds();
}
+void LauncherView::LauncherStatusChanged() {
+ AppListButton* app_list_button =
+ static_cast<AppListButton*>(GetAppListButtonView());
+ if (model_->status() == LauncherModel::STATUS_LOADING)
+ app_list_button->StartLoadingAnimation();
+ else
+ app_list_button->StopLoadingAnimation();
+}
+
void LauncherView::PointerPressedOnButton(views::View* view,
Pointer pointer,
const ui::LocatedEvent& event) {
@@ -979,7 +958,9 @@ string16 LauncherView::GetAccessibleName(const views::View* view) {
return delegate_->GetTitle(model_->items()[view_index]);
case TYPE_APP_LIST:
- return l10n_util::GetStringUTF16(IDS_AURA_APP_LIST_TITLE);
+ return model_->status() == LauncherModel::STATUS_LOADING ?
+ l10n_util::GetStringUTF16(IDS_AURA_APP_LIST_SYNCING_TITLE) :
+ l10n_util::GetStringUTF16(IDS_AURA_APP_LIST_TITLE);
case TYPE_BROWSER_SHORTCUT:
return l10n_util::GetStringUTF16(IDS_AURA_NEW_TAB);
diff --git a/ash/launcher/launcher_view.h b/ash/launcher/launcher_view.h
index bfac558..ca3f632 100644
--- a/ash/launcher/launcher_view.h
+++ b/ash/launcher/launcher_view.h
@@ -182,6 +182,7 @@ class ASH_EXPORT LauncherView : public views::View,
virtual void LauncherItemChanged(int model_index,
const ash::LauncherItem& old_item) OVERRIDE;
virtual void LauncherItemMoved(int start_index, int target_index) OVERRIDE;
+ virtual void LauncherStatusChanged() OVERRIDE;
// Overridden from LauncherButtonHost:
virtual void PointerPressedOnButton(
diff --git a/ash/launcher/launcher_view_unittest.cc b/ash/launcher/launcher_view_unittest.cc
index d2585bd..5a43c33 100644
--- a/ash/launcher/launcher_view_unittest.cc
+++ b/ash/launcher/launcher_view_unittest.cc
@@ -536,9 +536,6 @@ TEST_F(LauncherViewTest, LauncherItemStatus) {
item.status = ash::STATUS_ATTENTION;
model_->Set(index, item);
ASSERT_EQ(internal::LauncherButton::STATE_ATTENTION, button->state());
- item.status = ash::STATUS_IS_PENDING;
- model_->Set(index, item);
- ASSERT_EQ(internal::LauncherButton::STATE_PENDING, button->state());
}
// Confirm that item status changes are reflected in the buttons
@@ -559,9 +556,6 @@ TEST_F(LauncherViewTest, LauncherItemStatusPlatformApp) {
item.status = ash::STATUS_ATTENTION;
model_->Set(index, item);
ASSERT_EQ(internal::LauncherButton::STATE_ATTENTION, button->state());
- item.status = ash::STATUS_IS_PENDING;
- model_->Set(index, item);
- ASSERT_EQ(internal::LauncherButton::STATE_PENDING, button->state());
}
TEST_F(LauncherViewTest, LauncherTooltipTest) {
diff --git a/chrome/browser/extensions/pending_extension_manager.cc b/chrome/browser/extensions/pending_extension_manager.cc
index 130f11b..175afa9 100644
--- a/chrome/browser/extensions/pending_extension_manager.cc
+++ b/chrome/browser/extensions/pending_extension_manager.cc
@@ -4,6 +4,8 @@
#include "chrome/browser/extensions/pending_extension_manager.h"
+#include <algorithm>
+
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/version.h"
@@ -12,8 +14,6 @@
#include "chrome/common/extensions/extension.h"
#include "content/public/browser/browser_thread.h"
-#include <algorithm>
-
using content::BrowserThread;
namespace {
@@ -73,6 +73,18 @@ bool PendingExtensionManager::IsIdPending(const std::string& id) const {
return false;
}
+bool PendingExtensionManager::HasPendingExtensionFromSync() const {
+ PendingExtensionList::const_iterator iter;
+ for (iter = pending_extension_list_.begin();
+ iter != pending_extension_list_.end();
+ ++iter) {
+ if (iter->is_from_sync())
+ return true;
+ }
+
+ return false;
+}
+
bool PendingExtensionManager::AddFromSync(
const std::string& id,
const GURL& update_url,
diff --git a/chrome/browser/extensions/pending_extension_manager.h b/chrome/browser/extensions/pending_extension_manager.h
index 1c8efb8..c9235b7 100644
--- a/chrome/browser/extensions/pending_extension_manager.h
+++ b/chrome/browser/extensions/pending_extension_manager.h
@@ -56,6 +56,9 @@ class PendingExtensionManager {
// Is |id| in the set of pending extensions?
bool IsIdPending(const std::string& id) const;
+ // Whether there is pending extension install from sync.
+ bool HasPendingExtensionFromSync() const;
+
// Adds an extension in a pending state; the extension with the
// given info will be installed on the next auto-update cycle.
// Return true if the extension was added. Will return false
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
index 9ffaeed..6ea3198 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
@@ -16,11 +16,14 @@
#include "base/values.h"
#include "chrome/browser/defaults.h"
#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/pending_extension_manager.h"
#include "chrome/browser/prefs/incognito_mode_prefs.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/prefs/scoped_user_pref_update.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/ui/ash/chrome_launcher_prefs.h"
#include "chrome/browser/ui/ash/extension_utils.h"
#include "chrome/browser/ui/ash/launcher/browser_launcher_item_controller.h"
@@ -49,6 +52,13 @@
using extensions::Extension;
+namespace {
+
+// Max loading animation time in milliseconds.
+const int kMaxLoadingTimeMs = 60 * 1000;
+
+} // namespace
+
// ChromeLauncherController::Item ----------------------------------------------
ChromeLauncherController::Item::Item()
@@ -68,12 +78,24 @@ ChromeLauncherController::ChromeLauncherController(Profile* profile,
ash::LauncherModel* model)
: model_(model),
profile_(profile),
- activation_client_(NULL) {
+ activation_client_(NULL),
+ observed_sync_service_(NULL) {
if (!profile_) {
// Use the original profile as on chromeos we may get a temporary off the
// record profile.
profile_ = ProfileManager::GetDefaultProfile()->GetOriginalProfile();
+
+ // Monitor app sync on chromeos.
+ if (!IsLoggedInAsGuest()) {
+ observed_sync_service_ =
+ ProfileSyncServiceFactory::GetForProfile(profile_);
+ if (observed_sync_service_) {
+ observed_sync_service_->AddObserver(this);
+ StartLoadingAnimation();
+ }
+ }
}
+
instance_ = this;
model_->AddObserver(this);
extensions::ShellWindowRegistry::Get(profile_)->AddObserver(this);
@@ -111,6 +133,9 @@ ChromeLauncherController::~ChromeLauncherController() {
if (ash::Shell::HasInstance())
ash::Shell::GetInstance()->RemoveShellObserver(this);
+
+ if (observed_sync_service_)
+ observed_sync_service_->RemoveObserver(this);
}
void ChromeLauncherController::Init() {
@@ -263,11 +288,6 @@ void ChromeLauncherController::Open(ash::LauncherID id, int event_flags) {
ash::wm::ActivateWindow(controller->window());
} else {
DCHECK_EQ(TYPE_APP, id_to_item_map_[id].item_type);
-
- // Do nothing for pending app shortcut.
- if (GetItemStatus(id) == ash::STATUS_IS_PENDING)
- return;
-
OpenAppID(id_to_item_map_[id].app_id, event_flags);
}
}
@@ -613,6 +633,9 @@ void ChromeLauncherController::LauncherItemChanged(
}
}
+void ChromeLauncherController::LauncherStatusChanged() {
+}
+
void ChromeLauncherController::Observe(
int type,
const content::NotificationSource& source,
@@ -620,18 +643,15 @@ void ChromeLauncherController::Observe(
switch (type) {
case chrome::NOTIFICATION_EXTENSION_LOADED: {
UpdateAppLaunchersFromPref();
+ CheckAppSync();
break;
}
case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
const content::Details<extensions::UnloadedExtensionInfo> unload_info(
details);
const Extension* extension = unload_info->extension;
- if (IsAppPinned(extension->id())) {
- if (unload_info->reason == extension_misc::UNLOAD_REASON_UPDATE)
- MarkAppPending(extension->id());
- else
- DoUnpinAppsWithID(extension->id());
- }
+ if (IsAppPinned(extension->id()))
+ DoUnpinAppsWithID(extension->id());
break;
}
case chrome::NOTIFICATION_PREF_CHANGED: {
@@ -744,6 +764,11 @@ void ChromeLauncherController::OnShelfAlignmentChanged() {
profile_->GetPrefs()->SetString(prefs::kShelfAlignment, pref_value);
}
+void ChromeLauncherController::OnStateChanged() {
+ DCHECK(observed_sync_service_);
+ CheckAppSync();
+}
+
void ChromeLauncherController::PersistPinnedState() {
// It is a coding error to call PersistPinnedState() if the pinned apps are
// not user-editable. The code should check earlier and not perform any
@@ -800,18 +825,6 @@ ash::LauncherItemStatus ChromeLauncherController::GetItemStatus(
return item.status;
}
-void ChromeLauncherController::MarkAppPending(const std::string& app_id) {
- for (IDToItemMap::const_iterator i = id_to_item_map_.begin();
- i != id_to_item_map_.end(); ++i) {
- if (i->second.item_type == TYPE_APP && i->second.app_id == app_id) {
- if (GetItemStatus(i->first) == ash::STATUS_CLOSED)
- SetItemStatus(i->first, ash::STATUS_IS_PENDING);
-
- break;
- }
- }
-}
-
void ChromeLauncherController::DoPinAppWithID(const std::string& app_id) {
// If there is an item, do nothing and return.
if (IsAppPinned(app_id))
@@ -869,13 +882,6 @@ void ChromeLauncherController::UpdateAppLaunchersFromPref() {
IDToItemMap::const_iterator entry(id_to_item_map_.find(item.id));
if (entry != id_to_item_map_.end() &&
entry->second.app_id == *pref_app_id) {
- // Current item will be kept. Reset its pending state and ensure
- // its icon is loaded since it has to be valid to be in |pinned_apps|.
- if (item.status == ash::STATUS_IS_PENDING) {
- SetItemStatus(item.id, ash::STATUS_CLOSED);
- app_icon_loader_->FetchImage(*pref_app_id);
- }
-
++pref_app_id;
break;
} else {
@@ -972,28 +978,55 @@ ash::LauncherID ChromeLauncherController::InsertAppLauncherItem(
}
item.is_incognito = false;
item.image = Extension::GetDefaultIcon(true);
- if (item.type == ash::TYPE_APP_SHORTCUT &&
- !app_tab_helper_->IsValidID(app_id)) {
- item.status = ash::STATUS_IS_PENDING;
- } else {
- TabContents* active_tab = GetLastActiveTabContents(app_id);
- if (active_tab) {
- Browser* browser = browser::FindBrowserWithWebContents(
- active_tab->web_contents());
- DCHECK(browser);
- if (browser->window()->IsActive())
- status = ash::STATUS_ACTIVE;
- else
- status = ash::STATUS_RUNNING;
- }
- item.status = status;
+
+ TabContents* active_tab = GetLastActiveTabContents(app_id);
+ if (active_tab) {
+ Browser* browser = browser::FindBrowserWithWebContents(
+ active_tab->web_contents());
+ DCHECK(browser);
+ if (browser->window()->IsActive())
+ status = ash::STATUS_ACTIVE;
+ else
+ status = ash::STATUS_RUNNING;
}
+ item.status = status;
+
model_->AddAt(index, item);
if (!controller || controller->type() !=
BrowserLauncherItemController::TYPE_EXTENSION_PANEL) {
- if (item.status != ash::STATUS_IS_PENDING)
- app_icon_loader_->FetchImage(app_id);
+ app_icon_loader_->FetchImage(app_id);
}
+
return id;
}
+
+void ChromeLauncherController::CheckAppSync() {
+ if (!observed_sync_service_)
+ return;
+
+ const bool synced = observed_sync_service_->ShouldPushChanges();
+ const bool has_pending_extension = profile_->GetExtensionService()->
+ pending_extension_manager()->HasPendingExtensionFromSync();
+
+ if (synced && !has_pending_extension)
+ StopLoadingAnimation();
+}
+
+void ChromeLauncherController::StartLoadingAnimation() {
+ DCHECK(observed_sync_service_);
+ loading_timer_.Start(
+ FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kMaxLoadingTimeMs),
+ this, &ChromeLauncherController::StopLoadingAnimation);
+ model_->SetStatus(ash::LauncherModel::STATUS_LOADING);
+}
+
+void ChromeLauncherController::StopLoadingAnimation() {
+ DCHECK(observed_sync_service_);
+
+ model_->SetStatus(ash::LauncherModel::STATUS_NORMAL);
+ loading_timer_.Stop();
+ observed_sync_service_->RemoveObserver(this);
+ observed_sync_service_ = NULL;
+}
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h
index 411a5ea..3a0a841 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h
@@ -17,9 +17,11 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
+#include "base/timer.h"
#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/prefs/pref_change_registrar.h"
+#include "chrome/browser/sync/profile_sync_service_observer.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "ui/aura/client/activation_change_observer.h"
@@ -42,6 +44,7 @@ class BrowserLauncherItemController;
class BrowserLauncherItemControllerTest;
class PrefService;
class Profile;
+class ProfileSyncService;
class TabContents;
// ChromeLauncherController manages the launcher items needed for tabbed
@@ -53,7 +56,8 @@ class ChromeLauncherController
public content::NotificationObserver,
public extensions::ShellWindowRegistry::Observer,
public aura::client::ActivationChangeObserver,
- public aura::WindowObserver {
+ public aura::WindowObserver,
+ public ProfileSyncServiceObserver {
public:
// Indicates if a launcher item is incognito or not.
enum IncognitoState {
@@ -226,6 +230,7 @@ class ChromeLauncherController
virtual void LauncherItemMoved(int start_index, int target_index) OVERRIDE;
virtual void LauncherItemChanged(int index,
const ash::LauncherItem& old_item) OVERRIDE;
+ virtual void LauncherStatusChanged() OVERRIDE;
// Overridden from content::NotificationObserver:
virtual void Observe(int type,
@@ -236,17 +241,20 @@ class ChromeLauncherController
virtual void OnShellWindowAdded(ShellWindow* shell_window) OVERRIDE;
virtual void OnShellWindowRemoved(ShellWindow* shell_window) OVERRIDE;
- // Overriden from client::ActivationChangeObserver:
+ // Overridden from client::ActivationChangeObserver:
virtual void OnWindowActivated(
aura::Window* active,
aura::Window* old_active) OVERRIDE;
- // Overriden from aura::WindowObserver:
+ // Overridden from aura::WindowObserver:
virtual void OnWindowRemovingFromRootWindow(aura::Window* window) OVERRIDE;
- // Overriden from ash::ShellObserver:
+ // Overridden from ash::ShellObserver:
virtual void OnShelfAlignmentChanged() OVERRIDE;
+ // Overridden from ProfileSyncServiceObserver:
+ virtual void OnStateChanged() OVERRIDE;
+
private:
friend class BrowserLauncherItemControllerTest;
friend class ChromeLauncherControllerTest;
@@ -290,10 +298,6 @@ class ChromeLauncherController
// Returns item status for given |id|.
ash::LauncherItemStatus GetItemStatus(ash::LauncherID id) const;
- // Finds the launcher item that represents given |app_id| and updates the
- // pending state.
- void MarkAppPending(const std::string& app_id);
-
// Internal helpers for pinning and unpinning that handle both
// client-triggered and internal pinning operations.
void DoPinAppWithID(const std::string& app_id);
@@ -319,6 +323,13 @@ class ChromeLauncherController
ash::LauncherItemStatus status,
int index);
+ // Checks whether sync is completed and no pending synced extension install
+ // and calls StopLoadingAnimation when both conditions are met.
+ void CheckAppSync();
+
+ void StartLoadingAnimation();
+ void StopLoadingAnimation();
+
static ChromeLauncherController* instance_;
ash::LauncherModel* model_;
@@ -354,6 +365,9 @@ class ChromeLauncherController
PrefChangeRegistrar pref_change_registrar_;
aura::client::ActivationClient* activation_client_;
+ ProfileSyncService* observed_sync_service_;
+ base::OneShotTimer<ChromeLauncherController> loading_timer_;
+
DISALLOW_COPY_AND_ASSIGN(ChromeLauncherController);
};
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
index 784eda0..307a4e7 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
@@ -172,28 +172,6 @@ TEST_F(ChromeLauncherControllerTest, Policy) {
EXPECT_FALSE(launcher_controller.IsAppPinned(extension3_->id()));
}
-TEST_F(ChromeLauncherControllerTest, UnloadAndLoad) {
- extension_service_->AddExtension(extension3_.get());
- extension_service_->AddExtension(extension4_.get());
-
- ChromeLauncherController launcher_controller(profile_.get(), &model_);
- launcher_controller.Init();
-
- EXPECT_TRUE(launcher_controller.IsAppPinned(extension3_->id()));
- EXPECT_TRUE(launcher_controller.IsAppPinned(extension4_->id()));
-
- extension_service_->UnloadExtension(extension3_->id(),
- extension_misc::UNLOAD_REASON_UPDATE);
- EXPECT_TRUE(launcher_controller.IsAppPinned(extension3_->id()));
- EXPECT_EQ(ash::STATUS_IS_PENDING, model_.items()[1].status);
-
- extension_service_->AddExtension(extension3_.get());
- EXPECT_TRUE(launcher_controller.IsAppPinned(extension3_->id()));
- EXPECT_EQ(ash::STATUS_CLOSED, model_.items()[1].status);
-
- EXPECT_TRUE(launcher_controller.IsAppPinned(extension4_->id()));
-}
-
TEST_F(ChromeLauncherControllerTest, UnpinWithUninstall) {
extension_service_->AddExtension(extension3_.get());
extension_service_->AddExtension(extension4_.get());
diff --git a/chrome/browser/ui/ash/launcher/launcher_context_menu.cc b/chrome/browser/ui/ash/launcher/launcher_context_menu.cc
index 0dfa4b7..4b54777 100644
--- a/chrome/browser/ui/ash/launcher/launcher_context_menu.cc
+++ b/chrome/browser/ui/ash/launcher/launcher_context_menu.cc
@@ -27,24 +27,21 @@ LauncherContextMenu::LauncherContextMenu(ChromeLauncherController* controller,
AddItem(
MENU_PIN,
l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_UNPIN));
- // No open actions for pending app shortcut.
- if (item->status != ash::STATUS_IS_PENDING) {
- AddSeparator();
- AddCheckItemWithStringId(
- LAUNCH_TYPE_REGULAR_TAB,
- IDS_APP_CONTEXT_MENU_OPEN_REGULAR);
- AddCheckItemWithStringId(
- LAUNCH_TYPE_PINNED_TAB,
- IDS_APP_CONTEXT_MENU_OPEN_PINNED);
- AddCheckItemWithStringId(
- LAUNCH_TYPE_WINDOW,
- IDS_APP_CONTEXT_MENU_OPEN_WINDOW);
- // Even though the launch type is Full Screen it is more accurately
- // described as Maximized in Ash.
- AddCheckItemWithStringId(
- LAUNCH_TYPE_FULLSCREEN,
- IDS_APP_CONTEXT_MENU_OPEN_MAXIMIZED);
- }
+ AddSeparator();
+ AddCheckItemWithStringId(
+ LAUNCH_TYPE_REGULAR_TAB,
+ IDS_APP_CONTEXT_MENU_OPEN_REGULAR);
+ AddCheckItemWithStringId(
+ LAUNCH_TYPE_PINNED_TAB,
+ IDS_APP_CONTEXT_MENU_OPEN_PINNED);
+ AddCheckItemWithStringId(
+ LAUNCH_TYPE_WINDOW,
+ IDS_APP_CONTEXT_MENU_OPEN_WINDOW);
+ // Even though the launch type is Full Screen it is more accurately
+ // described as Maximized in Ash.
+ AddCheckItemWithStringId(
+ LAUNCH_TYPE_FULLSCREEN,
+ IDS_APP_CONTEXT_MENU_OPEN_MAXIMIZED);
} else if (item_.type == ash::TYPE_BROWSER_SHORTCUT) {
AddItem(MENU_NEW_WINDOW,
l10n_util::GetStringUTF16(IDS_LAUNCHER_NEW_WINDOW));