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