15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/chromeos/login/network_dropdown.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chromeos/login/ui/login_display_host.h"
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chromeos/network/network_state_handler.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_ui.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/models/menu_model.h"
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/base/webui/web_ui_util.h"
17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "ui/chromeos/network/network_icon.h"
18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "ui/chromeos/network/network_icon_animation.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/font_list.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Timeout between consecutive requests to network library for network
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// scan.
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kNetworkScanIntervalSecs = 60;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WebUI specific implementation of the NetworkMenu class.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NetworkMenuWebUI : public NetworkMenu {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetworkMenuWebUI(NetworkMenu::Delegate* delegate, content::WebUI* web_ui);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NetworkMenu override:
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void UpdateMenu() OVERRIDE;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called when item with command |id| is chosen.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnItemChosen(int id);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Converts menu model into the ListValue, ready for passing to WebUI.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ListValue* ConvertMenuModel(ui::MenuModel* model);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WebUI where network menu is located.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::WebUI* web_ui_;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(NetworkMenuWebUI);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NetworkMenuWebUI ------------------------------------------------------------
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkMenuWebUI::NetworkMenuWebUI(NetworkMenu::Delegate* delegate,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   content::WebUI* web_ui)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : NetworkMenu(delegate),
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      web_ui_(web_ui) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkMenuWebUI::UpdateMenu() {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetworkMenu::UpdateMenu();
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (web_ui_) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<base::ListValue> list(ConvertMenuModel(GetMenuModel()));
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    web_ui_->CallJavascriptFunction("cr.ui.DropDown.updateNetworks", *list);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkMenuWebUI::OnItemChosen(int id) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int index;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::MenuModel* model = GetMenuModel();
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (!ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index))
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     return;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  model->ActivatedAt(index);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::ListValue* NetworkMenuWebUI::ConvertMenuModel(ui::MenuModel* model) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ListValue* list = new base::ListValue();
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < model->GetItemCount(); ++i) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::MenuModel::ItemType type = model->GetTypeAt(i);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int id;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type == ui::MenuModel::TYPE_SEPARATOR)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      id = -2;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      id = model->GetCommandIdAt(i);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::DictionaryValue* item = new base::DictionaryValue();
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->SetInteger("id", id);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->SetString("label", model->GetLabelAt(i));
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Image icon;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (model->GetIconAt(i, &icon)) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SkBitmap icon_bitmap = icon.ToImageSkia()->GetRepresentation(
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          web_ui_->GetDeviceScaleFactor()).sk_bitmap();
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      item->SetString("icon", webui::GetBitmapDataUrl(icon_bitmap));
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (id >= 0) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      item->SetBoolean("enabled", model->IsEnabledAt(i));
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const gfx::FontList* font_list = model->GetLabelFontListAt(i);
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (font_list)
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        item->SetBoolean("bold", font_list->GetFontStyle() == gfx::Font::BOLD);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type == ui::MenuModel::TYPE_SUBMENU)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      item->Set("sub", ConvertMenuModel(model->GetSubmenuModelAt(i)));
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    list->Append(item);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return list;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NetworkDropdown -------------------------------------------------------------
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1112385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen MurdochNetworkDropdown::NetworkDropdown(Actor* actor,
1122385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                 content::WebUI* web_ui,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 bool oobe)
1142385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    : actor_(actor),
1152385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      web_ui_(web_ui),
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      oobe_(oobe) {
1172385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  DCHECK(actor_);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  network_menu_.reset(new NetworkMenuWebUI(this, web_ui));
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(NetworkHandler::IsInitialized());
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  handler->RequestScan();
1227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  handler->AddObserver(this, FROM_HERE);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Refresh();
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  network_scan_timer_.Start(
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      FROM_HERE,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta::FromSeconds(kNetworkScanIntervalSecs),
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      this, &NetworkDropdown::RequestNetworkScan);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkDropdown::~NetworkDropdown() {
131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ui::network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
1327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (NetworkHandler::IsInitialized()) {
1337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    NetworkHandler::Get()->network_state_handler()->RemoveObserver(
1347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        this, FROM_HERE);
1357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkDropdown::OnItemChosen(int id) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  network_menu_->OnItemChosen(id);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::NativeWindow NetworkDropdown::GetNativeWindow() const {
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return LoginDisplayHostImpl::default_host()->GetNativeWindow();
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkDropdown::OpenButtonOptions() {
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LoginDisplayHostImpl::default_host()->OpenProxySettings();
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NetworkDropdown::ShouldOpenButtonOptions() const {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !oobe_;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
154116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid NetworkDropdown::OnConnectToNetworkRequested() {
155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  actor_->OnConnectToNetworkRequested();
1562385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
1572385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void NetworkDropdown::DefaultNetworkChanged(const NetworkState* network) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Refresh();
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void NetworkDropdown::NetworkConnectionStateChanged(
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const NetworkState* network) {
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Refresh();
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void NetworkDropdown::NetworkListChanged() {
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Refresh();
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void NetworkDropdown::NetworkIconChanged() {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetNetworkIconAndText();
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void NetworkDropdown::Refresh() {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetNetworkIconAndText();
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  network_menu_->UpdateMenu();
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkDropdown::SetNetworkIconAndText() {
181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 text;
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  gfx::ImageSkia icon_image;
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool animating = false;
184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ui::network_icon::GetDefaultNetworkImageAndLabel(
185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      ui::network_icon::ICON_TYPE_LIST, &icon_image, &text, &animating);
186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (animating) {
187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ui::network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this);
188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ui::network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkBitmap icon_bitmap = icon_image.GetRepresentation(
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      web_ui_->GetDeviceScaleFactor()).sk_bitmap();
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string icon_str;
194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!icon_image.isNull())
195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    icon_str = webui::GetBitmapDataUrl(icon_bitmap);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringValue title(text);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringValue icon(icon_str);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui_->CallJavascriptFunction("cr.ui.DropDown.updateNetworkTitle",
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  title, icon);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void NetworkDropdown::RequestNetworkScan() {
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  NetworkHandler::Get()->network_state_handler()->RequestScan();
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Refresh();
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chromeos
208