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/extensions/api/content_settings/content_settings_helpers.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/url_constants.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/url_pattern.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kNoPathWildcardsError[] =
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Path wildcards in file URL patterns are not allowed.";
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kNoPathsError[] = "Specific paths are not allowed.";
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInvalidPatternError[] = "The pattern \"*\" is invalid.";
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const kContentSettingsTypeNames[] = {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "cookies",
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "images",
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "javascript",
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "plugins",
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "popups",
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "location",
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "notifications",
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPILE_ASSERT(arraysize(kContentSettingsTypeNames) <=
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               CONTENT_SETTINGS_NUM_TYPES,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               content_settings_type_names_size_invalid);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const kContentSettingNames[] = {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "default",
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "allow",
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "block",
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "ask",
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "session_only",
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPILE_ASSERT(arraysize(kContentSettingNames) <=
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               CONTENT_SETTING_NUM_SETTINGS,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               content_setting_names_size_invalid);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(bauerb): Move this someplace where it can be reused.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetDefaultPort(const std::string& scheme) {
46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (scheme == url::kHttpScheme)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "80";
48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (scheme == url::kHttpsScheme)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "443";
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return std::string();
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content_settings_helpers {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ContentSettingsPattern ParseExtensionPattern(const std::string& pattern_str,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             std::string* error) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kAllowedSchemes =
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS |
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      URLPattern::SCHEME_FILE;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  URLPattern url_pattern(kAllowedSchemes);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  URLPattern::ParseResult result = url_pattern.Parse(pattern_str);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != URLPattern::PARSE_SUCCESS) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *error = URLPattern::GetParseResultString(result);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ContentSettingsPattern();
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<ContentSettingsPattern::BuilderInterface> builder(
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ContentSettingsPattern::CreateBuilder(false));
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    builder->WithHost(url_pattern.host());
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (url_pattern.match_subdomains())
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      builder->WithDomainWildcard();
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string scheme = url_pattern.scheme();
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (scheme == "*")
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      builder->WithSchemeWildcard();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      builder->WithScheme(scheme);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string port = url_pattern.port();
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (port.empty() && scheme != "file") {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (scheme == "*")
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        port = "*";
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        port = GetDefaultPort(scheme);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (port == "*")
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      builder->WithPortWildcard();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      builder->WithPort(port);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string path = url_pattern.path();
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (scheme == "file") {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // For file URLs we allow only exact path matches.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (path.find_first_of("*?") != std::string::npos) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *error = kNoPathWildcardsError;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ContentSettingsPattern();
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        builder->WithPath(path);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (path != "/*") {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // For other URLs we allow only paths which match everything.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *error = kNoPathsError;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ContentSettingsPattern();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ContentSettingsPattern pattern = builder->Build();
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!pattern.IsValid())
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *error = kInvalidPatternError;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return pattern;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ContentSettingsType StringToContentSettingsType(
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& content_type) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t type = 0; type < arraysize(kContentSettingsTypeNames); ++type) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (content_type == kContentSettingsTypeNames[type])
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return static_cast<ContentSettingsType>(type);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CONTENT_SETTINGS_TYPE_DEFAULT;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* ContentSettingsTypeToString(ContentSettingsType type) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t index = static_cast<size_t>(type);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LT(index, arraysize(kContentSettingsTypeNames));
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kContentSettingsTypeNames[index];
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool StringToContentSetting(const std::string& setting_str,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            ContentSetting* setting) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t type = 0; type < arraysize(kContentSettingNames); ++type) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (setting_str == kContentSettingNames[type]) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *setting = static_cast<ContentSetting>(type);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* ContentSettingToString(ContentSetting setting) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t index = static_cast<size_t>(setting);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LT(index, arraysize(kContentSettingNames));
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kContentSettingNames[index];
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content_settings_helpers
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
150