12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/lazy_instance.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h"
146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/grit/generated_resources.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/url_constants.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/error_utils.h"
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/extension_resource.h"
19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "extensions/common/manifest_constants.h"
2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/manifest_handlers/permissions_parser.h"
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/permissions/permissions_data.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/url_pattern.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "extensions/common/url_pattern_set.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace extensions {
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace keys = extensions::manifest_keys;
30d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace values = manifest_values;
31d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace errors = manifest_errors;
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Helper method that loads either the include_globs or exclude_globs list
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// from an entry in the content_script lists of the manifest.
377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool LoadGlobsHelper(const base::DictionaryValue* content_script,
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     int content_script_index,
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     const char* globs_property_name,
40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     base::string16* error,
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     void(UserScript::*add_method)(const std::string& glob),
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     UserScript* instance) {
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!content_script->HasKey(globs_property_name))
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;  // they are optional
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const base::ListValue* list = NULL;
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!content_script->GetList(globs_property_name, &list)) {
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *error = ErrorUtils::FormatErrorMessageUTF16(
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        errors::kInvalidGlobList,
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::IntToString(content_script_index),
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        globs_property_name);
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < list->GetSize(); ++i) {
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string glob;
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!list->GetString(i, &glob)) {
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *error = ErrorUtils::FormatErrorMessageUTF16(
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          errors::kInvalidGlob,
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::IntToString(content_script_index),
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          globs_property_name,
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::IntToString(i));
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (instance->*add_method)(glob);
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Helper method that loads a UserScript object from a dictionary in the
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// content_script list of the manifest.
747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool LoadUserScriptFromDictionary(const base::DictionaryValue* content_script,
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  int definition_index,
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  Extension* extension,
77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                  base::string16* error,
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  UserScript* result) {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // run_at
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (content_script->HasKey(keys::kRunAt)) {
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string run_location;
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!content_script->GetString(keys::kRunAt, &run_location)) {
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *error = ErrorUtils::FormatErrorMessageUTF16(
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          errors::kInvalidRunAt,
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::IntToString(definition_index));
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (run_location == values::kRunAtDocumentStart) {
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      result->set_run_location(UserScript::DOCUMENT_START);
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (run_location == values::kRunAtDocumentEnd) {
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      result->set_run_location(UserScript::DOCUMENT_END);
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (run_location == values::kRunAtDocumentIdle) {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      result->set_run_location(UserScript::DOCUMENT_IDLE);
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *error = ErrorUtils::FormatErrorMessageUTF16(
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          errors::kInvalidRunAt,
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::IntToString(definition_index));
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // all frames
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (content_script->HasKey(keys::kAllFrames)) {
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool all_frames = false;
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!content_script->GetBoolean(keys::kAllFrames, &all_frames)) {
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *error = ErrorUtils::FormatErrorMessageUTF16(
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            errors::kInvalidAllFrames, base::IntToString(definition_index));
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result->set_match_all_frames(all_frames);
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // match about blank
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (content_script->HasKey(keys::kMatchAboutBlank)) {
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    bool match_about_blank = false;
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!content_script->GetBoolean(keys::kMatchAboutBlank,
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                    &match_about_blank)) {
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      *error = ErrorUtils::FormatErrorMessageUTF16(
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          errors::kInvalidMatchAboutBlank, base::IntToString(definition_index));
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return false;
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    result->set_match_about_blank(match_about_blank);
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // matches (required)
1277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const base::ListValue* matches = NULL;
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!content_script->GetList(keys::kMatches, &matches)) {
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *error = ErrorUtils::FormatErrorMessageUTF16(
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        errors::kInvalidMatches,
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::IntToString(definition_index));
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (matches->GetSize() == 0) {
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *error = ErrorUtils::FormatErrorMessageUTF16(
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        errors::kInvalidMatchCount,
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::IntToString(definition_index));
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t j = 0; j < matches->GetSize(); ++j) {
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string match_str;
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!matches->GetString(j, &match_str)) {
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *error = ErrorUtils::FormatErrorMessageUTF16(
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          errors::kInvalidMatch,
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::IntToString(definition_index),
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::IntToString(j),
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          errors::kExpectString);
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    URLPattern pattern(UserScript::ValidUserScriptSchemes(
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        PermissionsData::CanExecuteScriptEverywhere(extension)));
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    URLPattern::ParseResult parse_result = pattern.Parse(match_str);
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (parse_result != URLPattern::PARSE_SUCCESS) {
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *error = ErrorUtils::FormatErrorMessageUTF16(
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          errors::kInvalidMatch,
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::IntToString(definition_index),
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::IntToString(j),
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          URLPattern::GetParseResultString(parse_result));
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(aboxhall): check for webstore
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!PermissionsData::CanExecuteScriptEverywhere(extension) &&
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        pattern.scheme() != content::kChromeUIScheme) {
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Exclude SCHEME_CHROMEUI unless it's been explicitly requested.
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // If the --extensions-on-chrome-urls flag has not been passed, requesting
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // a chrome:// url will cause a parse failure above, so there's no need to
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // check the flag here.
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pattern.SetValidSchemes(
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          pattern.valid_schemes() & ~URLPattern::SCHEME_CHROMEUI);
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (pattern.MatchesScheme(url::kFileScheme) &&
17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        !PermissionsData::CanExecuteScriptEverywhere(extension)) {
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extension->set_wants_file_access(true);
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!(extension->creation_flags() & Extension::ALLOW_FILE_ACCESS)) {
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        pattern.SetValidSchemes(
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            pattern.valid_schemes() & ~URLPattern::SCHEME_FILE);
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result->add_url_pattern(pattern);
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // exclude_matches
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (content_script->HasKey(keys::kExcludeMatches)) {  // optional
1907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const base::ListValue* exclude_matches = NULL;
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!content_script->GetList(keys::kExcludeMatches, &exclude_matches)) {
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *error = ErrorUtils::FormatErrorMessageUTF16(
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          errors::kInvalidExcludeMatches,
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::IntToString(definition_index));
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t j = 0; j < exclude_matches->GetSize(); ++j) {
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string match_str;
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!exclude_matches->GetString(j, &match_str)) {
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        *error = ErrorUtils::FormatErrorMessageUTF16(
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            errors::kInvalidExcludeMatch,
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            base::IntToString(definition_index),
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            base::IntToString(j),
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            errors::kExpectString);
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return false;
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int valid_schemes = UserScript::ValidUserScriptSchemes(
21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          PermissionsData::CanExecuteScriptEverywhere(extension));
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      URLPattern pattern(valid_schemes);
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      URLPattern::ParseResult parse_result = pattern.Parse(match_str);
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (parse_result != URLPattern::PARSE_SUCCESS) {
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        *error = ErrorUtils::FormatErrorMessageUTF16(
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            errors::kInvalidExcludeMatch,
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            base::IntToString(definition_index), base::IntToString(j),
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            URLPattern::GetParseResultString(parse_result));
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return false;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      result->add_exclude_url_pattern(pattern);
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // include/exclude globs (mostly for Greasemonkey compatibility)
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!LoadGlobsHelper(content_script, definition_index, keys::kIncludeGlobs,
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       error, &UserScript::add_glob, result)) {
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!LoadGlobsHelper(content_script, definition_index, keys::kExcludeGlobs,
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       error, &UserScript::add_exclude_glob, result)) {
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // js and css keys
2387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const base::ListValue* js = NULL;
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (content_script->HasKey(keys::kJs) &&
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !content_script->GetList(keys::kJs, &js)) {
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *error = ErrorUtils::FormatErrorMessageUTF16(
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        errors::kInvalidJsList,
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::IntToString(definition_index));
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const base::ListValue* css = NULL;
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (content_script->HasKey(keys::kCss) &&
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !content_script->GetList(keys::kCss, &css)) {
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *error = ErrorUtils::
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FormatErrorMessageUTF16(errors::kInvalidCssList,
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::IntToString(definition_index));
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The manifest needs to have at least one js or css user script definition.
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (((js ? js->GetSize() : 0) + (css ? css->GetSize() : 0)) == 0) {
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *error = ErrorUtils::FormatErrorMessageUTF16(
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        errors::kMissingFile,
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::IntToString(definition_index));
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (js) {
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t script_index = 0; script_index < js->GetSize();
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         ++script_index) {
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const base::Value* value;
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string relative;
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!js->Get(script_index, &value) || !value->GetAsString(&relative)) {
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        *error = ErrorUtils::FormatErrorMessageUTF16(
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            errors::kInvalidJs,
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            base::IntToString(definition_index),
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            base::IntToString(script_index));
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return false;
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GURL url = extension->GetResourceURL(relative);
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ExtensionResource resource = extension->GetResource(relative);
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      result->js_scripts().push_back(UserScript::File(
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          resource.extension_root(), resource.relative_path(), url));
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (css) {
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t script_index = 0; script_index < css->GetSize();
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         ++script_index) {
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const base::Value* value;
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string relative;
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!css->Get(script_index, &value) || !value->GetAsString(&relative)) {
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        *error = ErrorUtils::FormatErrorMessageUTF16(
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            errors::kInvalidCss,
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            base::IntToString(definition_index),
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            base::IntToString(script_index));
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return false;
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GURL url = extension->GetResourceURL(relative);
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ExtensionResource resource = extension->GetResource(relative);
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      result->css_scripts().push_back(UserScript::File(
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          resource.extension_root(), resource.relative_path(), url));
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns false and sets the error if script file can't be loaded,
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// or if it's not UTF-8 encoded.
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static bool IsScriptValid(const base::FilePath& path,
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          const base::FilePath& relative_path,
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          int message_id,
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          std::string* error) {
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string content;
3127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!base::PathExists(path) ||
31358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      !base::ReadFileToString(path, &content)) {
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *error = l10n_util::GetStringFUTF8(
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        message_id,
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        relative_path.LossyDisplayName());
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
320010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!base::IsStringUTF8(content)) {
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *error = l10n_util::GetStringFUTF8(
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        IDS_EXTENSION_BAD_FILE_ENCODING,
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        relative_path.LossyDisplayName());
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct EmptyUserScriptList {
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UserScriptList user_script_list;
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static base::LazyInstance<EmptyUserScriptList> g_empty_script_list =
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LAZY_INSTANCE_INITIALIZER;
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ContentScriptsInfo::ContentScriptsInfo() {
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ContentScriptsInfo::~ContentScriptsInfo() {
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const UserScriptList& ContentScriptsInfo::GetContentScripts(
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const Extension* extension) {
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ContentScriptsInfo* info = static_cast<ContentScriptsInfo*>(
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extension->GetManifestData(keys::kContentScripts));
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return info ? info->content_scripts
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              : g_empty_script_list.Get().user_script_list;
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ContentScriptsInfo::ExtensionHasScriptAtURL(const Extension* extension,
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 const GURL& url) {
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const UserScriptList& content_scripts = GetContentScripts(extension);
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (UserScriptList::const_iterator iter = content_scripts.begin();
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      iter != content_scripts.end(); ++iter) {
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (iter->MatchesURL(url))
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)URLPatternSet ContentScriptsInfo::GetScriptableHosts(
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const Extension* extension) {
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const UserScriptList& content_scripts = GetContentScripts(extension);
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  URLPatternSet scriptable_hosts;
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (UserScriptList::const_iterator content_script =
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           content_scripts.begin();
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       content_script != content_scripts.end();
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       ++content_script) {
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    URLPatternSet::const_iterator pattern =
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        content_script->url_patterns().begin();
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for (; pattern != content_script->url_patterns().end(); ++pattern)
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      scriptable_hosts.AddPattern(*pattern);
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return scriptable_hosts;
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ContentScriptsHandler::ContentScriptsHandler() {
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ContentScriptsHandler::~ContentScriptsHandler() {
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::vector<std::string> ContentScriptsHandler::Keys() const {
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const char* keys[] = {
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    keys::kContentScripts
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return std::vector<std::string>(keys, keys + arraysize(keys));
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
396a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ContentScriptsHandler::Parse(Extension* extension, base::string16* error) {
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ContentScriptsInfo> content_scripts_info(new ContentScriptsInfo);
3987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const base::ListValue* scripts_list = NULL;
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!extension->manifest()->GetList(keys::kContentScripts, &scripts_list)) {
4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *error = base::ASCIIToUTF16(errors::kInvalidContentScriptsList);
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < scripts_list->GetSize(); ++i) {
4057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const base::DictionaryValue* script_dict = NULL;
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!scripts_list->GetDictionary(i, &script_dict)) {
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *error = ErrorUtils::FormatErrorMessageUTF16(
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          errors::kInvalidContentScript,
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::IntToString(i));
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UserScript user_script;
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!LoadUserScriptFromDictionary(script_dict,
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      i,
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      extension,
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      error,
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      &user_script)) {
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;  // Failed to parse script context definition.
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    user_script.set_extension_id(extension->id());
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (extension->converted_from_user_script()) {
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      user_script.set_emulate_greasemonkey(true);
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Greasemonkey matches all frames.
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      user_script.set_match_all_frames(true);
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
42803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    user_script.set_id(UserScript::GenerateUserScriptID());
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content_scripts_info->content_scripts.push_back(user_script);
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  extension->SetManifestData(keys::kContentScripts,
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             content_scripts_info.release());
43346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  PermissionsParser::SetScriptableHosts(
43446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      extension, ContentScriptsInfo::GetScriptableHosts(extension));
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ContentScriptsHandler::Validate(
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const Extension* extension,
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string* error,
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::vector<InstallWarning>* warnings) const {
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Validate that claimed script resources actually exist,
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // and are UTF-8 encoded.
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ExtensionResource::SymlinkPolicy symlink_policy;
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if ((extension->creation_flags() &
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       Extension::FOLLOW_SYMLINKS_ANYWHERE) != 0) {
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    symlink_policy = ExtensionResource::FOLLOW_SYMLINKS_ANYWHERE;
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    symlink_policy = ExtensionResource::SYMLINKS_MUST_RESOLVE_WITHIN_ROOT;
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const UserScriptList& content_scripts =
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ContentScriptsInfo::GetContentScripts(extension);
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < content_scripts.size(); ++i) {
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const UserScript& script = content_scripts[i];
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t j = 0; j < script.js_scripts().size(); j++) {
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const UserScript::File& js_script = script.js_scripts()[j];
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::FilePath& path = ExtensionResource::GetFilePath(
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          js_script.extension_root(), js_script.relative_path(),
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          symlink_policy);
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!IsScriptValid(path, js_script.relative_path(),
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         IDS_EXTENSION_LOAD_JAVASCRIPT_FAILED, error))
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return false;
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t j = 0; j < script.css_scripts().size(); j++) {
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const UserScript::File& css_script = script.css_scripts()[j];
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::FilePath& path = ExtensionResource::GetFilePath(
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          css_script.extension_root(), css_script.relative_path(),
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          symlink_policy);
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!IsScriptValid(path, css_script.relative_path(),
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         IDS_EXTENSION_LOAD_CSS_FAILED, error))
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return false;
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace extensions
482