Home | History | Annotate | Download | only in manifest_handlers
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/common/extensions/manifest_handlers/settings_overrides_handler.h"
      6 
      7 #include "base/memory/scoped_ptr.h"
      8 #include "base/strings/string_util.h"
      9 #include "base/strings/stringprintf.h"
     10 #include "base/strings/utf_string_conversions.h"
     11 #include "base/values.h"
     12 #include "extensions/common/error_utils.h"
     13 #include "extensions/common/extension_set.h"
     14 #include "extensions/common/feature_switch.h"
     15 #include "extensions/common/manifest_constants.h"
     16 #include "extensions/common/manifest_handlers/permissions_parser.h"
     17 #include "extensions/common/permissions/api_permission_set.h"
     18 #include "extensions/common/permissions/manifest_permission.h"
     19 #include "extensions/common/permissions/permissions_info.h"
     20 #include "extensions/common/permissions/settings_override_permission.h"
     21 #include "grit/generated_resources.h"
     22 #include "ipc/ipc_message.h"
     23 #include "ipc/ipc_message_utils.h"
     24 #include "ui/base/l10n/l10n_util.h"
     25 #include "url/gurl.h"
     26 
     27 using extensions::api::manifest_types::ChromeSettingsOverrides;
     28 
     29 namespace extensions {
     30 namespace {
     31 
     32 const char* kWwwPrefix = "www.";
     33 
     34 scoped_ptr<GURL> CreateManifestURL(const std::string& url) {
     35   scoped_ptr<GURL> manifest_url(new GURL(url));
     36   if (!manifest_url->is_valid() ||
     37       !manifest_url->SchemeIsHTTPOrHTTPS())
     38     return scoped_ptr<GURL>();
     39   return manifest_url.Pass();
     40 }
     41 
     42 scoped_ptr<GURL> ParseHomepage(const ChromeSettingsOverrides& overrides,
     43                                base::string16* error) {
     44   if (!overrides.homepage)
     45     return scoped_ptr<GURL>();
     46   scoped_ptr<GURL> manifest_url = CreateManifestURL(*overrides.homepage);
     47   if (!manifest_url) {
     48     *error = extensions::ErrorUtils::FormatErrorMessageUTF16(
     49         manifest_errors::kInvalidHomepageOverrideURL, *overrides.homepage);
     50   }
     51   return manifest_url.Pass();
     52 }
     53 
     54 std::vector<GURL> ParseStartupPage(const ChromeSettingsOverrides& overrides,
     55                                    base::string16* error) {
     56   std::vector<GURL> urls;
     57   if (!overrides.startup_pages)
     58     return urls;
     59 
     60   for (std::vector<std::string>::const_iterator i =
     61        overrides.startup_pages->begin(); i != overrides.startup_pages->end();
     62        ++i) {
     63     scoped_ptr<GURL> manifest_url = CreateManifestURL(*i);
     64     if (!manifest_url) {
     65       *error = extensions::ErrorUtils::FormatErrorMessageUTF16(
     66           manifest_errors::kInvalidStartupOverrideURL, *i);
     67     } else {
     68       urls.push_back(GURL());
     69       urls.back().Swap(manifest_url.get());
     70     }
     71   }
     72   return urls;
     73 }
     74 
     75 scoped_ptr<ChromeSettingsOverrides::Search_provider> ParseSearchEngine(
     76     ChromeSettingsOverrides* overrides,
     77     base::string16* error) {
     78   if (!overrides->search_provider)
     79     return scoped_ptr<ChromeSettingsOverrides::Search_provider>();
     80   if (!CreateManifestURL(overrides->search_provider->search_url)) {
     81     *error = extensions::ErrorUtils::FormatErrorMessageUTF16(
     82         manifest_errors::kInvalidSearchEngineURL,
     83         overrides->search_provider->search_url);
     84     return scoped_ptr<ChromeSettingsOverrides::Search_provider>();
     85   }
     86   if (overrides->search_provider->prepopulated_id)
     87     return overrides->search_provider.Pass();
     88   if (!overrides->search_provider->name ||
     89       !overrides->search_provider->keyword ||
     90       !overrides->search_provider->encoding ||
     91       !overrides->search_provider->favicon_url) {
     92     *error =
     93         base::ASCIIToUTF16(manifest_errors::kInvalidSearchEngineMissingKeys);
     94     return scoped_ptr<ChromeSettingsOverrides::Search_provider>();
     95   }
     96   if (!CreateManifestURL(*overrides->search_provider->favicon_url)) {
     97     *error = extensions::ErrorUtils::FormatErrorMessageUTF16(
     98         manifest_errors::kInvalidSearchEngineURL,
     99         *overrides->search_provider->favicon_url);
    100     return scoped_ptr<ChromeSettingsOverrides::Search_provider>();
    101   }
    102   return overrides->search_provider.Pass();
    103 }
    104 
    105 // A www. prefix is not informative and thus not worth the limited real estate
    106 // in the permissions UI.
    107 std::string RemoveWwwPrefix(const std::string& url) {
    108   if (StartsWithASCII(url, kWwwPrefix, false))
    109     return url.substr(strlen(kWwwPrefix));
    110   return url;
    111 }
    112 
    113 }  // namespace
    114 
    115 SettingsOverrides::SettingsOverrides() {}
    116 
    117 SettingsOverrides::~SettingsOverrides() {}
    118 
    119 // static
    120 const SettingsOverrides* SettingsOverrides::Get(
    121     const Extension* extension) {
    122   return static_cast<SettingsOverrides*>(
    123       extension->GetManifestData(manifest_keys::kSettingsOverride));
    124 }
    125 
    126 SettingsOverridesHandler::SettingsOverridesHandler() {}
    127 
    128 SettingsOverridesHandler::~SettingsOverridesHandler() {}
    129 
    130 bool SettingsOverridesHandler::Parse(Extension* extension,
    131                                      base::string16* error) {
    132   const base::Value* dict = NULL;
    133   CHECK(extension->manifest()->Get(manifest_keys::kSettingsOverride, &dict));
    134   scoped_ptr<ChromeSettingsOverrides> settings(
    135       ChromeSettingsOverrides::FromValue(*dict, error));
    136   if (!settings)
    137     return false;
    138 
    139   scoped_ptr<SettingsOverrides> info(new SettingsOverrides);
    140   info->homepage = ParseHomepage(*settings, error);
    141   info->search_engine = ParseSearchEngine(settings.get(), error);
    142   info->startup_pages = ParseStartupPage(*settings, error);
    143   if (!info->homepage && !info->search_engine && info->startup_pages.empty()) {
    144     *error = ErrorUtils::FormatErrorMessageUTF16(
    145         manifest_errors::kInvalidEmptyDictionary,
    146         manifest_keys::kSettingsOverride);
    147     return false;
    148   }
    149 
    150   if (info->search_engine) {
    151     PermissionsParser::AddAPIPermission(
    152         extension,
    153         new SettingsOverrideAPIPermission(
    154             PermissionsInfo::GetInstance()->GetByID(
    155                 APIPermission::kSearchProvider),
    156             RemoveWwwPrefix(CreateManifestURL(info->search_engine->search_url)
    157                                 ->GetOrigin()
    158                                 .host())));
    159   }
    160   if (!info->startup_pages.empty()) {
    161     PermissionsParser::AddAPIPermission(
    162         extension,
    163         new SettingsOverrideAPIPermission(
    164             PermissionsInfo::GetInstance()->GetByID(
    165                 APIPermission::kStartupPages),
    166             // We only support one startup page even though the type of the
    167             // manifest
    168             // property is a list, only the first one is used.
    169             RemoveWwwPrefix(info->startup_pages[0].GetContent())));
    170   }
    171   if (info->homepage) {
    172     PermissionsParser::AddAPIPermission(
    173         extension,
    174         new SettingsOverrideAPIPermission(
    175             PermissionsInfo::GetInstance()->GetByID(APIPermission::kHomepage),
    176             RemoveWwwPrefix(info->homepage.get()->GetContent())));
    177   }
    178   extension->SetManifestData(manifest_keys::kSettingsOverride,
    179                              info.release());
    180   return true;
    181 }
    182 
    183 const std::vector<std::string> SettingsOverridesHandler::Keys() const {
    184   return SingleKey(manifest_keys::kSettingsOverride);
    185 }
    186 
    187 }  // namespace extensions
    188