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.
5 #include "chrome/common/extensions/api/url_handlers/url_handlers_parser.h"
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"
19 using base::ASCIIToUTF16
;
20 using net::NetworkChangeNotifier
;
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.
27 // chrome/common/extensions/api/manifest_types.json
28 // chrome/common/extensions/manifest_handlers/externally_connectable.*
30 // Do the same in (at least) file_handlers_parser.cc as well.
32 namespace extensions
{
34 namespace mkeys
= manifest_keys
;
35 namespace merrors
= manifest_errors
;
37 UrlHandlerInfo::UrlHandlerInfo() {
40 UrlHandlerInfo::~UrlHandlerInfo() {
43 UrlHandlers::UrlHandlers() {
46 UrlHandlers::~UrlHandlers() {
50 const 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
;
58 bool UrlHandlers::CanExtensionHandleUrl(
59 const Extension
* extension
,
61 return FindMatchingUrlHandler(extension
, url
) != NULL
;
65 const UrlHandlerInfo
* UrlHandlers::FindMatchingUrlHandler(
66 const Extension
* extension
,
68 const std::vector
<UrlHandlerInfo
>* handlers
= GetUrlHandlers(extension
);
72 if (NetworkChangeNotifier::IsOffline() &&
73 !OfflineEnabledInfo::IsOfflineEnabled(extension
))
76 for (std::vector
<extensions::UrlHandlerInfo
>::const_iterator it
=
77 handlers
->begin(); it
!= handlers
->end(); it
++) {
78 if (it
->patterns
.MatchesURL(url
))
85 UrlHandlersParser::UrlHandlersParser() {
88 UrlHandlersParser::~UrlHandlersParser() {
91 bool ParseUrlHandler(const std::string
& handler_id
,
92 const base::DictionaryValue
& handler_info
,
93 std::vector
<UrlHandlerInfo
>* url_handlers
,
94 base::string16
* error
) {
97 UrlHandlerInfo handler
;
98 handler
.id
= handler_id
;
100 if (!handler_info
.GetString(mkeys::kUrlHandlerTitle
, &handler
.title
)) {
101 *error
= base::ASCIIToUTF16(merrors::kInvalidURLHandlerTitle
);
105 const base::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
);
113 for (base::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
);
127 handler
.patterns
.AddPattern(pattern
);
130 url_handlers
->push_back(handler
);
135 bool UrlHandlersParser::Parse(Extension
* extension
, base::string16
* error
) {
136 scoped_ptr
<UrlHandlers
> info(new UrlHandlers
);
137 const base::DictionaryValue
* all_handlers
= NULL
;
138 if (!extension
->manifest()->GetDictionary(
139 mkeys::kUrlHandlers
, &all_handlers
)) {
140 *error
= base::ASCIIToUTF16(merrors::kInvalidURLHandlers
);
144 DCHECK(extension
->is_platform_app());
146 for (base::DictionaryValue::Iterator
iter(*all_handlers
); !iter
.IsAtEnd();
148 // A URL handler entry is a title and a list of URL patterns to handle.
149 const base::DictionaryValue
* handler
= NULL
;
150 if (!iter
.value().GetAsDictionary(&handler
)) {
151 *error
= base::ASCIIToUTF16(merrors::kInvalidURLHandlerPatternElement
);
155 if (!ParseUrlHandler(iter
.key(), *handler
, &info
->handlers
, error
)) {
156 // Text in |error| is set by ParseUrlHandler.
161 extension
->SetManifestData(mkeys::kUrlHandlers
, info
.release());
166 const std::vector
<std::string
> UrlHandlersParser::Keys() const {
167 return SingleKey(mkeys::kUrlHandlers
);
170 } // namespace extensions