1 // Copyright (c) 2012 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/custom_handlers/protocol_handler.h"
6
7 #include "base/macros.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/util/values/values_util.h"
11 #include "chrome/grit/generated_resources.h"
12 #include "content/public/common/origin_util.h"
13 #include "extensions/common/constants.h"
14 #include "net/base/escape.h"
15 #include "third_party/blink/public/common/custom_handlers/protocol_handler_utils.h"
16 #include "ui/base/l10n/l10n_util.h"
17
ProtocolHandler(const std::string & protocol,const GURL & url,base::Time last_modified)18 ProtocolHandler::ProtocolHandler(const std::string& protocol,
19 const GURL& url,
20 base::Time last_modified)
21 : protocol_(base::ToLowerASCII(protocol)),
22 url_(url),
23 last_modified_(last_modified) {}
24
CreateProtocolHandler(const std::string & protocol,const GURL & url)25 ProtocolHandler ProtocolHandler::CreateProtocolHandler(
26 const std::string& protocol,
27 const GURL& url) {
28 return ProtocolHandler(protocol, url, base::Time::Now());
29 }
30
ProtocolHandler()31 ProtocolHandler::ProtocolHandler() {
32 }
33
IsValidDict(const base::DictionaryValue * value)34 bool ProtocolHandler::IsValidDict(const base::DictionaryValue* value) {
35 // Note that "title" parameter is ignored.
36 // The |last_modified| field is optional as it was introduced in M68.
37 return value->HasKey("protocol") && value->HasKey("url");
38 }
39
IsValid() const40 bool ProtocolHandler::IsValid() const {
41 // TODO(https://crbug.com/977083): Consider limiting to secure contexts.
42
43 // This matches VerifyCustomHandlerURLSecurity() in blink's
44 // NavigatorContentUtils.
45 if (!url_.SchemeIsHTTPOrHTTPS() &&
46 !url_.SchemeIs(extensions::kExtensionScheme)) {
47 return false;
48 }
49
50 bool has_custom_scheme_prefix;
51 return blink::IsValidCustomHandlerScheme(protocol_, has_custom_scheme_prefix);
52 }
53
IsSameOrigin(const ProtocolHandler & handler) const54 bool ProtocolHandler::IsSameOrigin(
55 const ProtocolHandler& handler) const {
56 return handler.url().GetOrigin() == url_.GetOrigin();
57 }
58
EmptyProtocolHandler()59 const ProtocolHandler& ProtocolHandler::EmptyProtocolHandler() {
60 static const ProtocolHandler* const kEmpty = new ProtocolHandler();
61 return *kEmpty;
62 }
63
CreateProtocolHandler(const base::DictionaryValue * value)64 ProtocolHandler ProtocolHandler::CreateProtocolHandler(
65 const base::DictionaryValue* value) {
66 if (!IsValidDict(value)) {
67 return EmptyProtocolHandler();
68 }
69 std::string protocol, url;
70 // |time| defaults to the beginning of time if it is not specified.
71 base::Time time;
72 value->GetString("protocol", &protocol);
73 value->GetString("url", &url);
74 base::Optional<base::Time> time_value =
75 util::ValueToTime(value->FindKey("last_modified"));
76 // Treat invalid times as the default value.
77 if (time_value)
78 time = *time_value;
79 return ProtocolHandler(protocol, GURL(url), time);
80 }
81
TranslateUrl(const GURL & url) const82 GURL ProtocolHandler::TranslateUrl(const GURL& url) const {
83 std::string translatedUrlSpec(url_.spec());
84 base::ReplaceFirstSubstringAfterOffset(
85 &translatedUrlSpec, 0, "%s",
86 net::EscapeQueryParamValue(url.spec(), false));
87 return GURL(translatedUrlSpec);
88 }
89
Encode() const90 std::unique_ptr<base::DictionaryValue> ProtocolHandler::Encode() const {
91 auto d = std::make_unique<base::DictionaryValue>();
92 d->SetString("protocol", protocol_);
93 d->SetString("url", url_.spec());
94 d->SetKey("last_modified", util::TimeToValue(last_modified_));
95 return d;
96 }
97
GetProtocolDisplayName(const std::string & protocol)98 base::string16 ProtocolHandler::GetProtocolDisplayName(
99 const std::string& protocol) {
100 if (protocol == "mailto")
101 return l10n_util::GetStringUTF16(IDS_REGISTER_PROTOCOL_HANDLER_MAILTO_NAME);
102 if (protocol == "webcal")
103 return l10n_util::GetStringUTF16(IDS_REGISTER_PROTOCOL_HANDLER_WEBCAL_NAME);
104 return base::UTF8ToUTF16(protocol);
105 }
106
GetProtocolDisplayName() const107 base::string16 ProtocolHandler::GetProtocolDisplayName() const {
108 return GetProtocolDisplayName(protocol_);
109 }
110
111 #if !defined(NDEBUG)
ToString() const112 std::string ProtocolHandler::ToString() const {
113 return "{ protocol=" + protocol_ +
114 ", url=" + url_.spec() +
115 " }";
116 }
117 #endif
118
operator ==(const ProtocolHandler & other) const119 bool ProtocolHandler::operator==(const ProtocolHandler& other) const {
120 return protocol_ == other.protocol_ && url_ == other.url_;
121 }
122
IsEquivalent(const ProtocolHandler & other) const123 bool ProtocolHandler::IsEquivalent(const ProtocolHandler& other) const {
124 return protocol_ == other.protocol_ && url_ == other.url_;
125 }
126
operator <(const ProtocolHandler & other) const127 bool ProtocolHandler::operator<(const ProtocolHandler& other) const {
128 return url_ < other.url_;
129 }
130