screen_tray_item.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file.
4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ash/system/chromeos/screen_security/screen_tray_item.h"
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ash/system/tray/fixed_sized_image_view.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ash/system/tray/tray_constants.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
10bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "ui/message_center/message_center.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/views/controls/label.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/views/layout/box_layout.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace {
15bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochconst int kStopButtonRightPadding = 18;
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace ash {
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace internal {
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace tray {
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// ScreenTrayView implementations.
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ScreenTrayView::ScreenTrayView(ScreenTrayItem* screen_tray_item, int icon_id)
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : TrayItemView(screen_tray_item),
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      screen_tray_item_(screen_tray_item) {
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CreateImageView();
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  image_view()->SetImage(ui::ResourceBundle::GetSharedInstance()
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .GetImageNamed(icon_id).ToImageSkia());
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Update();
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ScreenTrayView::~ScreenTrayView() {
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ScreenTrayView::Update() {
38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SetVisible(screen_tray_item_->is_started());
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// ScreenStatusView implementations.
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ScreenStatusView::ScreenStatusView(ScreenTrayItem* screen_tray_item,
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   int icon_id,
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   const base::string16& label_text,
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   const base::string16& stop_button_text)
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : screen_tray_item_(screen_tray_item),
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      icon_(NULL),
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      label_(NULL),
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      stop_button_(NULL),
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      icon_id_(icon_id),
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      label_text_(label_text),
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      stop_button_text_(stop_button_text) {
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CreateItems();
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Update();
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ScreenStatusView::~ScreenStatusView() {
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ScreenStatusView::Layout() {
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  views::View::Layout();
63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Give the stop button the space it requests.
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  gfx::Size stop_size = stop_button_->GetPreferredSize();
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  gfx::Rect stop_bounds(stop_size);
67bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  stop_bounds.set_x(width() - stop_size.width() - kStopButtonRightPadding);
68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  stop_bounds.set_y((height() - stop_size.height()) / 2);
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  stop_button_->SetBoundsRect(stop_bounds);
70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Adjust the label's bounds in case it got cut off by |stop_button_|.
72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (label_->bounds().Intersects(stop_button_->bounds())) {
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    gfx::Rect label_bounds = label_->bounds();
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    label_bounds.set_width(
75bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        stop_button_->x() - kTrayPopupPaddingBetweenItems - label_->x());
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    label_->SetBoundsRect(label_bounds);
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ScreenStatusView::ButtonPressed(
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    views::Button* sender,
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const ui::Event& event) {
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(sender == stop_button_);
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  screen_tray_item_->Stop();
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ScreenStatusView::CreateItems() {
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  set_background(views::Background::CreateSolidBackground(kBackgroundColor));
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
90bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal,
91bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                                        kTrayPopupPaddingHorizontal,
92bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                                        0,
93bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                                        kTrayPopupPaddingBetweenItems));
94bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  icon_ = new FixedSizedImageView(0, kTrayPopupItemHeight);
95bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  icon_->SetImage(bundle.GetImageNamed(icon_id_).ToImageSkia());
96bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  AddChildView(icon_);
97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  label_ = new views::Label;
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  label_->SetMultiLine(true);
100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  label_->SetText(label_text_);
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddChildView(label_);
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  stop_button_ = new TrayPopupLabelButton(this, stop_button_text_);
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddChildView(stop_button_);
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ScreenStatusView::Update() {
108bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Hide the notification bubble when the ash tray bubble opens.
109bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  screen_tray_item_->HideNotificationView();
110bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  SetVisible(screen_tray_item_->is_started());
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
113bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben MurdochScreenNotificationDelegate::ScreenNotificationDelegate(
114bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    ScreenTrayItem* screen_tray)
115bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  : screen_tray_(screen_tray) {
116bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
118bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben MurdochScreenNotificationDelegate::~ScreenNotificationDelegate() {
119bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
120bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
121bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochvoid ScreenNotificationDelegate::Display() {
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
124bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochvoid ScreenNotificationDelegate::Error() {
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
127bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochvoid ScreenNotificationDelegate::Close(bool by_user) {
128bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
129bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
130bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochvoid ScreenNotificationDelegate::Click() {
131bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
132bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
133bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochvoid ScreenNotificationDelegate::ButtonClick(int button_index) {
134bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  DCHECK_EQ(0, button_index);
135bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  screen_tray_->Stop();
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace tray
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ScreenTrayItem::ScreenTrayItem(SystemTray* system_tray)
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : SystemTrayItem(system_tray),
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      tray_view_(NULL),
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      default_view_(NULL),
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      is_started_(false),
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      stop_callback_(base::Bind(&base::DoNothing)) {
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ScreenTrayItem::~ScreenTrayItem() {}
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ScreenTrayItem::Update() {
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (tray_view_)
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    tray_view_->Update();
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (default_view_)
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    default_view_->Update();
155bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (is_started_) {
156bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    CreateOrUpdateNotification();
157bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  } else {
158bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    message_center::MessageCenter::Get()->RemoveNotification(
159bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        GetNotificationId(), false /* by_user */);
160bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ScreenTrayItem::Start(const base::Closure& stop_callback) {
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  stop_callback_ = stop_callback;
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  is_started_ = true;
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (tray_view_)
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    tray_view_->Update();
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (default_view_)
171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    default_view_->Update();
172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!system_tray()->HasSystemBubbleType(
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      SystemTrayBubble::BUBBLE_TYPE_DEFAULT)) {
175bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    CreateOrUpdateNotification();
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ScreenTrayItem::Stop() {
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  is_started_ = false;
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Update();
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (stop_callback_.is_null())
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::Closure callback = stop_callback_;
187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  stop_callback_.Reset();
188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  callback.Run();
189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ScreenTrayItem::DestroyTrayView() {
192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  tray_view_ = NULL;
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ScreenTrayItem::DestroyDefaultView() {
196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  default_view_ = NULL;
197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ScreenTrayItem::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) {
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!tray_view_)
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Center the item dependent on the orientation of the shelf.
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  views::BoxLayout::Orientation layout =
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (alignment == ash::SHELF_ALIGNMENT_BOTTOM ||
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       alignment == ash::SHELF_ALIGNMENT_TOP)
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          ? views::BoxLayout::kHorizontal
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          : views::BoxLayout::kVertical;
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  tray_view_->SetLayoutManager(new views::BoxLayout(layout, 0, 0, 0));
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  tray_view_->Layout();
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace internal
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace ash
215