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)#ifndef CHROME_BROWSER_CHROMEOS_MOBILE_CONFIG_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHROME_BROWSER_CHROMEOS_MOBILE_CONFIG_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/gtest_prod_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/customization_document.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DictionaryValue;
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class FilePath;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Class that processes mobile (carrier) configuration.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Confugration is defined as a JSON file - global and local one.
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// First global configuration is loaded then local one if it exists.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Notes on global/local configuration:
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1. All global config data is inherited unless some carrier properties
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    are overidden or carrier deals are explicitly marked as excluded.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2. Local config could mark that all carrier deals should be excluded or
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    only specific carrier deals are excluded.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3. New ID mappings in local config are not supported.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 4. If local config exists, at least trivial global config should exist too.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 5. If any error occurs while parsing global/local config,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    MobileConfig::IsReady() will return false.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MobileConfig : public CustomizationDocument  {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Carrier deal.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class CarrierDeal {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    explicit CarrierDeal(const base::DictionaryValue* deal_dict);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~CarrierDeal();
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Returns string with the specified |locale| and |id|.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If there's no version for |locale|, default one is returned.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If there's no string with specified |id|, empty string is returned.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string GetLocalizedString(const std::string& locale,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const std::string& id) const;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& deal_id() const { return deal_id_; }
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<std::string>& locales() const { return locales_; }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& info_url() const { return info_url_; }
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int notification_count() const { return notification_count_; }
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Time expire_date() const { return expire_date_; }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string deal_id_;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<std::string> locales_;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string info_url_;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int notification_count_;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Time expire_date_;
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue* localized_strings_;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(CarrierDeal);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Carrier config.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class Carrier {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Carrier(const base::DictionaryValue* carrier_dict,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            const std::string& initial_locale);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~Carrier();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<std::string>& external_ids() { return external_ids_; }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& top_up_url() const { return top_up_url_; }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool show_portal_button() const { return show_portal_button_; }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Returns "default" carrier deal i.e. first deal defined or NULL
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // if there're no deals defined.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CarrierDeal* GetDefaultDeal() const;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Returns carrier deal by ID.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CarrierDeal* GetDeal(const std::string& deal_id) const;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Initializes carrier from supplied dictionary.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Multiple calls supported (i.e. second call for local config).
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void InitFromDictionary(const base::DictionaryValue* carrier_dict,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const std::string& initial_locale);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Removes all carrier deals. Might be executed when local config is loaded.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void RemoveDeals();
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Maps deal id to deal instance.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef std::map<std::string, CarrierDeal*> CarrierDeals;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // List of external IDs that should map to this carrier.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<std::string> external_ids_;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Top-up URL. Used in network menu ("View account" link) +
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // carrier name in network details (in settings) is a link.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string top_up_url_;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If true, show a separate "View account" button on network details page
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // even if device is activated and doesn't need new data plan.
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // It's not shown when one of the "Buy plan" / "Activate" is shown.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // All "Buy plan" / "Activate" / "View account" buttons launch
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // carrier portal (chrome://mobilesetup/ extension).
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool show_portal_button_;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CarrierDeals deals_;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(Carrier);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Carrier config for a specific initial locale.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class LocaleConfig {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    explicit LocaleConfig(base::DictionaryValue* locale_dict);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~LocaleConfig();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& setup_url() const { return setup_url_; }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Initializes local config carrier from supplied dictionary.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Multiple calls supported (i.e. second call for local config).
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void InitFromDictionary(base::DictionaryValue* locale_dict);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Carrier setup URL. Used in network menu ("Set-up Mobile Data" link).
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Displayed when SIM card is not installed on the device with a
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // particular initial locale.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string setup_url_;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(LocaleConfig);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // External carrier ID (ex. "Verizon (us)") mapping to internal carrier ID.
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::map<std::string, std::string> CarrierIdMap;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Internal carrier ID mapping to Carrier config.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::map<std::string, Carrier*> Carriers;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static MobileConfig* GetInstance();
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns carrier by external ID or NULL if there's no such carrier.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const MobileConfig::Carrier* GetCarrier(const std::string& carrier_id) const;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns locale specific config by initial locale or NULL
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if there's no such config defined.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const MobileConfig::LocaleConfig* GetLocaleConfig() const;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool LoadManifestFromString(const std::string& manifest) OVERRIDE;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(MobileConfigTest, Basic);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(MobileConfigTest, BadManifest);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(MobileConfigTest, DealOtherLocale);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(MobileConfigTest, OldDeal);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(MobileConfigTest, LocalConfigNoDeals);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(MobileConfigTest, LocalConfig);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend struct DefaultSingletonTraits<MobileConfig>;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // C-tor for singleton construction.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MobileConfig();
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // C-tor for test construction.
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MobileConfig(const std::string& config,
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               const std::string& initial_locale);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MobileConfig();
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Loads carrier configuration.
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void LoadConfig();
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Processes global/local config.
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ProcessConfig(const std::string& global_config,
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const std::string& local_config);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Executes on FILE thread and reads config files to string.
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void ReadConfigInBackground(const base::FilePath& global_config_file,
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              const base::FilePath& local_config_file);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Maps external carrier ID to internal carrier ID.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CarrierIdMap carrier_id_map_;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Carrier configuration (including carrier deals).
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Carriers carriers_;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initial locale specific config if defined.
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<LocaleConfig> locale_config_;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initial locale value.
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string initial_locale_;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Root value of the local config (if it exists).
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Global config is stored in root_ of the base class.
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> local_config_root_;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MobileConfig);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chromeos
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // CHROME_BROWSER_CHROMEOS_MOBILE_CONFIG_H_
207