url_handlers_parser.cc revision f2477e01787aa58f445919b809d89e252beef54f
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/api/url_handlers/url_handlers_parser.h" 6 7#include "base/command_line.h" 8#include "base/memory/scoped_ptr.h" 9#include "base/strings/string_number_conversions.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/manifest_constants.h" 14#include "extensions/common/manifest_handlers/offline_enabled_info.h" 15#include "extensions/common/switches.h" 16#include "net/base/network_change_notifier.h" 17#include "url/gurl.h" 18 19using base::ASCIIToUTF16; 20using net::NetworkChangeNotifier; 21 22// TODO(sergeygs): Use the same strategy that externally_connectable does for 23// parsing the manifest: declare a schema for the manifest entry in 24// manifest_types.json, then use it here. 25// 26// See: 27// chrome/common/extensions/api/manifest_types.json 28// chrome/common/extensions/manifest_handlers/externally_connectable.* 29// 30// Do the same in (at least) file_handlers_parser.cc as well. 31 32namespace extensions { 33 34namespace mkeys = manifest_keys; 35namespace merrors = manifest_errors; 36 37UrlHandlerInfo::UrlHandlerInfo() { 38} 39 40UrlHandlerInfo::~UrlHandlerInfo() { 41} 42 43UrlHandlers::UrlHandlers() { 44} 45 46UrlHandlers::~UrlHandlers() { 47} 48 49// static 50const std::vector<UrlHandlerInfo>* UrlHandlers::GetUrlHandlers( 51 const Extension* extension) { 52 UrlHandlers* info = static_cast<UrlHandlers*>( 53 extension->GetManifestData(mkeys::kUrlHandlers)); 54 return info ? &info->handlers : NULL; 55} 56 57// static 58bool UrlHandlers::CanExtensionHandleUrl( 59 const Extension* extension, 60 const GURL& url) { 61 return FindMatchingUrlHandler(extension, url) != NULL; 62} 63 64// static 65const UrlHandlerInfo* UrlHandlers::FindMatchingUrlHandler( 66 const Extension* extension, 67 const GURL& url) { 68 const std::vector<UrlHandlerInfo>* handlers = GetUrlHandlers(extension); 69 if (!handlers) 70 return NULL; 71 72 if (NetworkChangeNotifier::IsOffline() && 73 !OfflineEnabledInfo::IsOfflineEnabled(extension)) 74 return NULL; 75 76 for (std::vector<extensions::UrlHandlerInfo>::const_iterator it = 77 handlers->begin(); it != handlers->end(); it++) { 78 if (it->patterns.MatchesURL(url)) 79 return &(*it); 80 } 81 82 return NULL; 83} 84 85UrlHandlersParser::UrlHandlersParser() { 86} 87 88UrlHandlersParser::~UrlHandlersParser() { 89} 90 91bool ParseUrlHandler(const std::string& handler_id, 92 const DictionaryValue& handler_info, 93 std::vector<UrlHandlerInfo>* url_handlers, 94 string16* error) { 95 DCHECK(error); 96 97 UrlHandlerInfo handler; 98 handler.id = handler_id; 99 100 if (!handler_info.GetString(mkeys::kUrlHandlerTitle, &handler.title)) { 101 *error = ASCIIToUTF16(merrors::kInvalidURLHandlerTitle); 102 return false; 103 } 104 105 const ListValue* manif_patterns = NULL; 106 if (!handler_info.GetList(mkeys::kMatches, &manif_patterns) || 107 manif_patterns->GetSize() == 0) { 108 *error = ErrorUtils::FormatErrorMessageUTF16( 109 merrors::kInvalidURLHandlerPattern, handler_id); 110 return false; 111 } 112 113 for (ListValue::const_iterator it = manif_patterns->begin(); 114 it != manif_patterns->end(); ++it) { 115 std::string str_pattern; 116 (*it)->GetAsString(&str_pattern); 117 // TODO(sergeygs): Limit this to non-top-level domains. 118 // TODO(sergeygs): Also add a verification to the CWS installer that the 119 // URL patterns claimed here belong to the app's author verified sites. 120 URLPattern pattern(URLPattern::SCHEME_HTTP | 121 URLPattern::SCHEME_HTTPS); 122 if (pattern.Parse(str_pattern) != URLPattern::PARSE_SUCCESS) { 123 *error = ErrorUtils::FormatErrorMessageUTF16( 124 merrors::kInvalidURLHandlerPatternElement, handler_id); 125 return false; 126 } 127 handler.patterns.AddPattern(pattern); 128 } 129 130 url_handlers->push_back(handler); 131 132 return true; 133} 134 135bool UrlHandlersParser::Parse(Extension* extension, string16* error) { 136 scoped_ptr<UrlHandlers> info(new UrlHandlers); 137 const DictionaryValue* all_handlers = NULL; 138 if (!extension->manifest()->GetDictionary( 139 mkeys::kUrlHandlers, &all_handlers)) { 140 *error = ASCIIToUTF16(merrors::kInvalidURLHandlers); 141 return false; 142 } 143 144 DCHECK(extension->is_platform_app()); 145 146 for (DictionaryValue::Iterator iter(*all_handlers); !iter.IsAtEnd(); 147 iter.Advance()) { 148 // A URL handler entry is a title and a list of URL patterns to handle. 149 const DictionaryValue* handler = NULL; 150 if (!iter.value().GetAsDictionary(&handler)) { 151 *error = ASCIIToUTF16(merrors::kInvalidURLHandlerPatternElement); 152 return false; 153 } 154 155 if (!ParseUrlHandler(iter.key(), *handler, &info->handlers, error)) { 156 // Text in |error| is set by ParseUrlHandler. 157 return false; 158 } 159 } 160 161 extension->SetManifestData(mkeys::kUrlHandlers, info.release()); 162 163 return true; 164} 165 166const std::vector<std::string> UrlHandlersParser::Keys() const { 167 return SingleKey(mkeys::kUrlHandlers); 168} 169 170} // namespace extensions 171