protocol_handler_registry.cc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  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. #include "components/custom_handlers/protocol_handler_registry.h"
  5. #include <stddef.h>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/check_op.h"
  9. #include "base/command_line.h"
  10. #include "base/containers/contains.h"
  11. #include "base/memory/ref_counted.h"
  12. #include "base/notreached.h"
  13. #include "base/observer_list.h"
  14. #include "build/build_config.h"
  15. #include "build/chromeos_buildflags.h"
  16. #include "components/custom_handlers/pref_names.h"
  17. #include "components/custom_handlers/protocol_handler.h"
  18. #include "components/pref_registry/pref_registry_syncable.h"
  19. #include "components/prefs/pref_service.h"
  20. #include "components/user_prefs/user_prefs.h"
  21. #include "content/public/browser/child_process_security_policy.h"
  22. #include "third_party/abseil-cpp/absl/types/optional.h"
  23. #include "url/url_util.h"
  24. using content::BrowserThread;
  25. using content::ChildProcessSecurityPolicy;
  26. namespace custom_handlers {
  27. namespace {
  28. const ProtocolHandler& LookupHandler(
  29. const ProtocolHandlerRegistry::ProtocolHandlerMap& handler_map,
  30. base::StringPiece scheme) {
  31. auto p = handler_map.find(scheme);
  32. if (p != handler_map.end())
  33. return p->second;
  34. return ProtocolHandler::EmptyProtocolHandler();
  35. }
  36. GURL TranslateUrl(
  37. const ProtocolHandlerRegistry::ProtocolHandlerMap& handler_map,
  38. const GURL& url) {
  39. const ProtocolHandler& handler =
  40. LookupHandler(handler_map, url.scheme_piece());
  41. if (handler.IsEmpty())
  42. return GURL();
  43. GURL translated_url(handler.TranslateUrl(url));
  44. if (!translated_url.is_valid())
  45. return GURL();
  46. return translated_url;
  47. }
  48. } // namespace
  49. // ProtocolHandlerRegistry -----------------------------------------------------
  50. std::unique_ptr<ProtocolHandlerRegistry> ProtocolHandlerRegistry::Create(
  51. PrefService* prefs,
  52. std::unique_ptr<Delegate> delegate) {
  53. auto registry =
  54. std::make_unique<ProtocolHandlerRegistry>(prefs, std::move(delegate));
  55. // If installing defaults, they must be installed prior calling
  56. // InitProtocolSettings.
  57. registry->InstallPredefinedHandlers();
  58. registry->InitProtocolSettings();
  59. return registry;
  60. }
  61. ProtocolHandlerRegistry::ProtocolHandlerRegistry(
  62. PrefService* prefs,
  63. std::unique_ptr<Delegate> delegate)
  64. : prefs_(prefs),
  65. delegate_(std::move(delegate)),
  66. enabled_(true),
  67. is_loading_(false),
  68. is_loaded_(false) {}
  69. bool ProtocolHandlerRegistry::SilentlyHandleRegisterHandlerRequest(
  70. const ProtocolHandler& handler) {
  71. if (handler.IsEmpty() || !CanSchemeBeOverridden(handler.protocol()))
  72. return true;
  73. if (!enabled() || IsRegistered(handler) || HasIgnoredEquivalent(handler))
  74. return true;
  75. if (AttemptReplace(handler))
  76. return true;
  77. return false;
  78. }
  79. void ProtocolHandlerRegistry::OnAcceptRegisterProtocolHandler(
  80. const ProtocolHandler& handler) {
  81. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  82. if (!RegisterProtocolHandler(handler, USER))
  83. return;
  84. SetDefault(handler);
  85. Save();
  86. NotifyChanged();
  87. }
  88. void ProtocolHandlerRegistry::OnDenyRegisterProtocolHandler(
  89. const ProtocolHandler& handler) {
  90. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  91. RegisterProtocolHandler(handler, USER);
  92. Save();
  93. NotifyChanged();
  94. }
  95. void ProtocolHandlerRegistry::OnIgnoreRegisterProtocolHandler(
  96. const ProtocolHandler& handler) {
  97. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  98. IgnoreProtocolHandler(handler, USER);
  99. Save();
  100. NotifyChanged();
  101. }
  102. bool ProtocolHandlerRegistry::AttemptReplace(const ProtocolHandler& handler) {
  103. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  104. ProtocolHandler old_default = GetHandlerFor(handler.protocol());
  105. bool make_new_handler_default = handler.IsSameOrigin(old_default);
  106. ProtocolHandlerList to_replace(GetReplacedHandlers(handler));
  107. if (to_replace.empty())
  108. return false;
  109. for (const auto& replaced_handler : to_replace) {
  110. RemoveHandler(replaced_handler);
  111. }
  112. if (make_new_handler_default) {
  113. OnAcceptRegisterProtocolHandler(handler);
  114. } else {
  115. InsertHandler(handler);
  116. NotifyChanged();
  117. }
  118. return true;
  119. }
  120. ProtocolHandlerRegistry::ProtocolHandlerList
  121. ProtocolHandlerRegistry::GetReplacedHandlers(
  122. const ProtocolHandler& handler) const {
  123. ProtocolHandlerList replaced_handlers;
  124. const ProtocolHandlerList* handlers = GetHandlerList(handler.protocol());
  125. if (!handlers)
  126. return replaced_handlers;
  127. for (const auto& old_handler : *handlers) {
  128. if (handler.IsSameOrigin(old_handler)) {
  129. replaced_handlers.push_back(old_handler);
  130. }
  131. }
  132. return replaced_handlers;
  133. }
  134. void ProtocolHandlerRegistry::ClearDefault(const std::string& scheme) {
  135. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  136. // TODO(jfernandez): If we want to use StringPiece as map's key for erasing,
  137. // we would need to adapt the ProtocolHandlerMap, or just use the iterator
  138. // got from find(scheme).
  139. default_handlers_.erase(scheme);
  140. Save();
  141. NotifyChanged();
  142. }
  143. bool ProtocolHandlerRegistry::IsDefault(const ProtocolHandler& handler) const {
  144. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  145. return GetHandlerFor(handler.protocol()) == handler;
  146. }
  147. void ProtocolHandlerRegistry::InstallPredefinedHandlers() {
  148. for (const auto& [scheme, handler] : url::GetPredefinedHandlerSchemes()) {
  149. AddPredefinedHandler(
  150. ProtocolHandler::CreateProtocolHandler(scheme, GURL(handler)));
  151. }
  152. }
  153. void ProtocolHandlerRegistry::InitProtocolSettings() {
  154. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  155. // Any further default additions to the table will get rejected from now on.
  156. is_loaded_ = true;
  157. is_loading_ = true;
  158. if (!prefs_) {
  159. is_loading_ = false;
  160. return;
  161. }
  162. if (prefs_->HasPrefPath(prefs::kCustomHandlersEnabled)) {
  163. if (prefs_->GetBoolean(prefs::kCustomHandlersEnabled)) {
  164. Enable();
  165. } else {
  166. Disable();
  167. }
  168. }
  169. RegisterProtocolHandlersFromPref(prefs::kPolicyRegisteredProtocolHandlers,
  170. POLICY);
  171. RegisterProtocolHandlersFromPref(prefs::kRegisteredProtocolHandlers, USER);
  172. IgnoreProtocolHandlersFromPref(prefs::kPolicyIgnoredProtocolHandlers, POLICY);
  173. IgnoreProtocolHandlersFromPref(prefs::kIgnoredProtocolHandlers, USER);
  174. is_loading_ = false;
  175. // For each default protocol handler, check that we are still registered
  176. // with the OS as the default application.
  177. if (delegate_->ShouldRemoveHandlersNotInOS()) {
  178. for (const auto& [protocol, handler] : default_handlers_) {
  179. delegate_->CheckDefaultClientWithOS(
  180. protocol, GetDefaultWebClientCallback(protocol));
  181. }
  182. }
  183. }
  184. int ProtocolHandlerRegistry::GetHandlerIndex(base::StringPiece scheme) const {
  185. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  186. const ProtocolHandler& candidate = GetHandlerFor(scheme);
  187. if (candidate.IsEmpty())
  188. return -1;
  189. const ProtocolHandlerList* handlers = GetHandlerList(scheme);
  190. if (!handlers)
  191. return -1;
  192. int i = 0;
  193. for (const auto& handler : *handlers) {
  194. if (handler == candidate)
  195. return i;
  196. i++;
  197. }
  198. return -1;
  199. }
  200. ProtocolHandlerRegistry::ProtocolHandlerList
  201. ProtocolHandlerRegistry::GetHandlersFor(base::StringPiece scheme) const {
  202. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  203. auto p = protocol_handlers_.find(scheme);
  204. if (p == protocol_handlers_.end()) {
  205. return ProtocolHandlerList();
  206. }
  207. return p->second;
  208. }
  209. ProtocolHandlerRegistry::ProtocolHandlerList
  210. ProtocolHandlerRegistry::GetUserDefinedHandlers(base::Time begin,
  211. base::Time end) const {
  212. ProtocolHandlerRegistry::ProtocolHandlerList result;
  213. for (const auto& [protocol, handlers_list] : user_protocol_handlers_) {
  214. for (const ProtocolHandler& handler : handlers_list) {
  215. if (base::Contains(predefined_protocol_handlers_, handler))
  216. continue;
  217. if (begin <= handler.last_modified() && handler.last_modified() < end)
  218. result.push_back(handler);
  219. }
  220. }
  221. return result;
  222. }
  223. ProtocolHandlerRegistry::ProtocolHandlerList
  224. ProtocolHandlerRegistry::GetUserIgnoredHandlers(base::Time begin,
  225. base::Time end) const {
  226. ProtocolHandlerRegistry::ProtocolHandlerList result;
  227. for (const ProtocolHandler& handler : user_ignored_protocol_handlers_) {
  228. if (begin <= handler.last_modified() && handler.last_modified() < end)
  229. result.push_back(handler);
  230. }
  231. return result;
  232. }
  233. void ProtocolHandlerRegistry::ClearUserDefinedHandlers(base::Time begin,
  234. base::Time end) {
  235. for (const ProtocolHandler& handler : GetUserDefinedHandlers(begin, end))
  236. RemoveHandler(handler);
  237. for (const ProtocolHandler& handler : GetUserIgnoredHandlers(begin, end))
  238. RemoveIgnoredHandler(handler);
  239. }
  240. ProtocolHandlerRegistry::ProtocolHandlerList
  241. ProtocolHandlerRegistry::GetIgnoredHandlers() {
  242. return ignored_protocol_handlers_;
  243. }
  244. void ProtocolHandlerRegistry::GetRegisteredProtocols(
  245. std::vector<std::string>* output) const {
  246. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  247. for (const auto& [protocol, handlers_list] : protocol_handlers_) {
  248. if (!handlers_list.empty())
  249. output->push_back(protocol);
  250. }
  251. }
  252. bool ProtocolHandlerRegistry::CanSchemeBeOverridden(
  253. base::StringPiece scheme) const {
  254. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  255. const ProtocolHandlerList* handlers = GetHandlerList(scheme);
  256. // If we already have a handler for this scheme, we can add more.
  257. if (handlers != NULL && !handlers->empty())
  258. return true;
  259. // Don't override a scheme if it already has an external handler.
  260. return !delegate_->IsExternalHandlerRegistered(
  261. static_cast<std::string>(scheme));
  262. }
  263. bool ProtocolHandlerRegistry::IsRegistered(
  264. const ProtocolHandler& handler) const {
  265. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  266. const ProtocolHandlerList* handlers = GetHandlerList(handler.protocol());
  267. if (!handlers) {
  268. return false;
  269. }
  270. return base::Contains(*handlers, handler);
  271. }
  272. bool ProtocolHandlerRegistry::IsRegisteredByUser(
  273. const ProtocolHandler& handler) {
  274. return HandlerExists(handler, &user_protocol_handlers_);
  275. }
  276. bool ProtocolHandlerRegistry::HasPolicyRegisteredHandler(
  277. base::StringPiece scheme) {
  278. return (policy_protocol_handlers_.find(scheme) !=
  279. policy_protocol_handlers_.end());
  280. }
  281. bool ProtocolHandlerRegistry::IsIgnored(const ProtocolHandler& handler) const {
  282. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  283. for (const auto& ignored_handler : ignored_protocol_handlers_) {
  284. if (ignored_handler == handler) {
  285. return true;
  286. }
  287. }
  288. return false;
  289. }
  290. bool ProtocolHandlerRegistry::HasRegisteredEquivalent(
  291. const ProtocolHandler& handler) const {
  292. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  293. const ProtocolHandlerList* handlers = GetHandlerList(handler.protocol());
  294. if (!handlers) {
  295. return false;
  296. }
  297. for (const auto& registered_handler : *handlers) {
  298. if (handler.IsEquivalent(registered_handler)) {
  299. return true;
  300. }
  301. }
  302. return false;
  303. }
  304. bool ProtocolHandlerRegistry::HasIgnoredEquivalent(
  305. const ProtocolHandler& handler) const {
  306. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  307. for (const auto& ignored_handler : ignored_protocol_handlers_) {
  308. if (handler.IsEquivalent(ignored_handler)) {
  309. return true;
  310. }
  311. }
  312. return false;
  313. }
  314. void ProtocolHandlerRegistry::RemoveIgnoredHandler(
  315. const ProtocolHandler& handler) {
  316. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  317. bool should_notify = false;
  318. if (HandlerExists(handler, ignored_protocol_handlers_) &&
  319. HandlerExists(handler, user_ignored_protocol_handlers_)) {
  320. EraseHandler(handler, &user_ignored_protocol_handlers_);
  321. Save();
  322. if (!HandlerExists(handler, policy_ignored_protocol_handlers_)) {
  323. EraseHandler(handler, &ignored_protocol_handlers_);
  324. should_notify = true;
  325. }
  326. }
  327. if (should_notify)
  328. NotifyChanged();
  329. }
  330. bool ProtocolHandlerRegistry::IsHandledProtocol(
  331. base::StringPiece scheme) const {
  332. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  333. return enabled_ && !GetHandlerFor(scheme).IsEmpty();
  334. }
  335. void ProtocolHandlerRegistry::RemoveHandler(const ProtocolHandler& handler) {
  336. if (IsIgnored(handler)) {
  337. RemoveIgnoredHandler(handler);
  338. return;
  339. }
  340. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  341. ProtocolHandlerList& handlers = protocol_handlers_[handler.protocol()];
  342. bool erase_success = false;
  343. if (HandlerExists(handler, handlers) &&
  344. HandlerExists(handler, &user_protocol_handlers_)) {
  345. EraseHandler(handler, &user_protocol_handlers_);
  346. erase_success = true;
  347. if (!HandlerExists(handler, &policy_protocol_handlers_))
  348. EraseHandler(handler, &protocol_handlers_);
  349. }
  350. auto q = default_handlers_.find(handler.protocol());
  351. if (erase_success && q != default_handlers_.end() && q->second == handler) {
  352. // Make the new top handler in the list the default.
  353. if (!handlers.empty()) {
  354. // NOTE We pass a copy because SetDefault() modifies handlers.
  355. SetDefault(ProtocolHandler(handlers[0]));
  356. } else {
  357. default_handlers_.erase(q);
  358. }
  359. }
  360. if (erase_success && !IsHandledProtocol(handler.protocol())) {
  361. delegate_->DeregisterExternalHandler(handler.protocol());
  362. }
  363. Save();
  364. if (erase_success)
  365. NotifyChanged();
  366. }
  367. void ProtocolHandlerRegistry::RemoveDefaultHandler(base::StringPiece scheme) {
  368. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  369. ProtocolHandler current_default = GetHandlerFor(scheme);
  370. if (!current_default.IsEmpty())
  371. RemoveHandler(current_default);
  372. }
  373. const ProtocolHandler& ProtocolHandlerRegistry::GetHandlerFor(
  374. base::StringPiece scheme) const {
  375. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  376. return LookupHandler(default_handlers_, scheme);
  377. }
  378. GURL ProtocolHandlerRegistry::Translate(const GURL& url) const {
  379. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  380. return TranslateUrl(default_handlers_, url);
  381. }
  382. void ProtocolHandlerRegistry::Enable() {
  383. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  384. if (enabled_) {
  385. return;
  386. }
  387. enabled_ = true;
  388. for (const auto& [protocol, handler] : default_handlers_) {
  389. delegate_->RegisterExternalHandler(protocol);
  390. }
  391. Save();
  392. NotifyChanged();
  393. }
  394. void ProtocolHandlerRegistry::Disable() {
  395. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  396. if (!enabled_) {
  397. return;
  398. }
  399. enabled_ = false;
  400. for (const auto& [protocol, handler] : default_handlers_) {
  401. delegate_->DeregisterExternalHandler(protocol);
  402. }
  403. Save();
  404. NotifyChanged();
  405. }
  406. void ProtocolHandlerRegistry::Shutdown() {
  407. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  408. delegate_.reset(NULL);
  409. weak_ptr_factory_.InvalidateWeakPtrs();
  410. }
  411. // static
  412. void ProtocolHandlerRegistry::RegisterProfilePrefs(
  413. user_prefs::PrefRegistrySyncable* registry) {
  414. registry->RegisterListPref(prefs::kRegisteredProtocolHandlers);
  415. registry->RegisterListPref(prefs::kIgnoredProtocolHandlers);
  416. registry->RegisterListPref(prefs::kPolicyRegisteredProtocolHandlers);
  417. registry->RegisterListPref(prefs::kPolicyIgnoredProtocolHandlers);
  418. registry->RegisterBooleanPref(prefs::kCustomHandlersEnabled, true);
  419. }
  420. ProtocolHandlerRegistry::~ProtocolHandlerRegistry() {
  421. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  422. }
  423. void ProtocolHandlerRegistry::AddObserver(Observer* observer) {
  424. observers_.AddObserver(observer);
  425. }
  426. void ProtocolHandlerRegistry::RemoveObserver(Observer* observer) {
  427. observers_.RemoveObserver(observer);
  428. }
  429. void ProtocolHandlerRegistry::PromoteHandler(const ProtocolHandler& handler) {
  430. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  431. DCHECK(IsRegistered(handler));
  432. auto p = protocol_handlers_.find(handler.protocol());
  433. ProtocolHandlerList& list = p->second;
  434. list.erase(std::find(list.begin(), list.end(), handler));
  435. list.insert(list.begin(), handler);
  436. }
  437. void ProtocolHandlerRegistry::Save() {
  438. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  439. if (is_loading_) {
  440. return;
  441. }
  442. if (!prefs_)
  443. return;
  444. base::Value registered_protocol_handlers(EncodeRegisteredHandlers());
  445. base::Value ignored_protocol_handlers(EncodeIgnoredHandlers());
  446. prefs_->Set(prefs::kRegisteredProtocolHandlers, registered_protocol_handlers);
  447. prefs_->Set(prefs::kIgnoredProtocolHandlers, ignored_protocol_handlers);
  448. prefs_->SetBoolean(prefs::kCustomHandlersEnabled, enabled_);
  449. }
  450. const ProtocolHandlerRegistry::ProtocolHandlerList*
  451. ProtocolHandlerRegistry::GetHandlerList(base::StringPiece scheme) const {
  452. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  453. auto p = protocol_handlers_.find(scheme);
  454. if (p == protocol_handlers_.end()) {
  455. return NULL;
  456. }
  457. return &p->second;
  458. }
  459. void ProtocolHandlerRegistry::SetDefault(const ProtocolHandler& handler) {
  460. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  461. const std::string& protocol = handler.protocol();
  462. ProtocolHandlerMap::const_iterator p = default_handlers_.find(protocol);
  463. // If we're not loading, and we are setting a default for a new protocol,
  464. // register with the OS.
  465. if (!is_loading_ && p == default_handlers_.end())
  466. delegate_->RegisterWithOSAsDefaultClient(
  467. protocol, GetDefaultWebClientCallback(protocol));
  468. default_handlers_.erase(protocol);
  469. default_handlers_.insert(std::make_pair(protocol, handler));
  470. PromoteHandler(handler);
  471. }
  472. void ProtocolHandlerRegistry::InsertHandler(const ProtocolHandler& handler) {
  473. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  474. auto p = protocol_handlers_.find(handler.protocol());
  475. if (p != protocol_handlers_.end()) {
  476. p->second.push_back(handler);
  477. return;
  478. }
  479. ProtocolHandlerList new_list;
  480. new_list.push_back(handler);
  481. protocol_handlers_[handler.protocol()] = new_list;
  482. }
  483. base::Value::List ProtocolHandlerRegistry::EncodeRegisteredHandlers() {
  484. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  485. base::Value::List encoded_handlers;
  486. for (const auto& [protocol, handlers_list] : user_protocol_handlers_) {
  487. for (const auto& handler : handlers_list) {
  488. base::Value::Dict encoded = handler.Encode();
  489. if (IsDefault(handler)) {
  490. encoded.Set("default", true);
  491. }
  492. encoded_handlers.Append(std::move(encoded));
  493. }
  494. }
  495. return encoded_handlers;
  496. }
  497. base::Value::List ProtocolHandlerRegistry::EncodeIgnoredHandlers() {
  498. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  499. base::Value::List encoded_handlers;
  500. for (const auto& handler : user_ignored_protocol_handlers_) {
  501. encoded_handlers.Append(handler.Encode());
  502. }
  503. return encoded_handlers;
  504. }
  505. void ProtocolHandlerRegistry::NotifyChanged() {
  506. for (auto& observer : observers_)
  507. observer.OnProtocolHandlerRegistryChanged();
  508. }
  509. bool ProtocolHandlerRegistry::RegisterProtocolHandler(
  510. const ProtocolHandler& handler,
  511. const HandlerSource source) {
  512. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  513. DCHECK(CanSchemeBeOverridden(handler.protocol()));
  514. DCHECK(!handler.IsEmpty());
  515. // Ignore invalid handlers.
  516. if (!handler.IsValid())
  517. return false;
  518. ProtocolHandlerMultiMap& map =
  519. (source == POLICY) ? policy_protocol_handlers_ : user_protocol_handlers_;
  520. ProtocolHandlerList& list = map[handler.protocol()];
  521. if (!HandlerExists(handler, list))
  522. list.push_back(handler);
  523. if (IsRegistered(handler)) {
  524. return true;
  525. }
  526. if (enabled_ && !delegate_->IsExternalHandlerRegistered(handler.protocol()))
  527. delegate_->RegisterExternalHandler(handler.protocol());
  528. InsertHandler(handler);
  529. return true;
  530. }
  531. std::vector<const base::Value::Dict*>
  532. ProtocolHandlerRegistry::GetHandlersFromPref(const char* pref_name) const {
  533. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  534. std::vector<const base::Value::Dict*> result;
  535. if (!prefs_ || !prefs_->HasPrefPath(pref_name)) {
  536. return result;
  537. }
  538. const base::Value::List& handlers = prefs_->GetValueList(pref_name);
  539. for (const auto& list_item : handlers) {
  540. if (const base::Value::Dict* encoded_handler = list_item.GetIfDict()) {
  541. if (ProtocolHandler::IsValidDict(*encoded_handler)) {
  542. result.push_back(encoded_handler);
  543. }
  544. }
  545. }
  546. return result;
  547. }
  548. void ProtocolHandlerRegistry::RegisterProtocolHandlersFromPref(
  549. const char* pref_name,
  550. const HandlerSource source) {
  551. std::vector<const base::Value::Dict*> registered_handlers =
  552. GetHandlersFromPref(pref_name);
  553. for (const auto* encoded_handler : registered_handlers) {
  554. ProtocolHandler handler =
  555. ProtocolHandler::CreateProtocolHandler(*encoded_handler);
  556. if (!RegisterProtocolHandler(handler, source))
  557. continue;
  558. if (encoded_handler->FindBool("default").value_or(false)) {
  559. SetDefault(handler);
  560. }
  561. }
  562. }
  563. void ProtocolHandlerRegistry::IgnoreProtocolHandler(
  564. const ProtocolHandler& handler,
  565. const HandlerSource source) {
  566. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  567. ProtocolHandlerList& list = (source == POLICY)
  568. ? policy_ignored_protocol_handlers_
  569. : user_ignored_protocol_handlers_;
  570. if (!HandlerExists(handler, list))
  571. list.push_back(handler);
  572. if (HandlerExists(handler, ignored_protocol_handlers_))
  573. return;
  574. ignored_protocol_handlers_.push_back(handler);
  575. }
  576. void ProtocolHandlerRegistry::IgnoreProtocolHandlersFromPref(
  577. const char* pref_name,
  578. const HandlerSource source) {
  579. std::vector<const base::Value::Dict*> ignored_handlers =
  580. GetHandlersFromPref(pref_name);
  581. for (const auto* encoded_handler : ignored_handlers)
  582. IgnoreProtocolHandler(
  583. ProtocolHandler::CreateProtocolHandler(*encoded_handler), source);
  584. }
  585. bool ProtocolHandlerRegistry::HandlerExists(const ProtocolHandler& handler,
  586. ProtocolHandlerMultiMap* map) {
  587. return HandlerExists(handler, (*map)[handler.protocol()]);
  588. }
  589. bool ProtocolHandlerRegistry::HandlerExists(const ProtocolHandler& handler,
  590. const ProtocolHandlerList& list) {
  591. return base::Contains(list, handler);
  592. }
  593. void ProtocolHandlerRegistry::EraseHandler(const ProtocolHandler& handler,
  594. ProtocolHandlerMultiMap* map) {
  595. EraseHandler(handler, &(*map)[handler.protocol()]);
  596. }
  597. void ProtocolHandlerRegistry::EraseHandler(const ProtocolHandler& handler,
  598. ProtocolHandlerList* list) {
  599. list->erase(std::find(list->begin(), list->end(), handler));
  600. }
  601. void ProtocolHandlerRegistry::OnSetAsDefaultProtocolClientFinished(
  602. const std::string& protocol,
  603. bool is_default) {
  604. // Clear if the default protocol client isn't this installation.
  605. if (!is_default && delegate_->ShouldRemoveHandlersNotInOS())
  606. ClearDefault(protocol);
  607. }
  608. void ProtocolHandlerRegistry::SetIsLoading(bool is_loading) {
  609. is_loading_ = is_loading;
  610. }
  611. void ProtocolHandlerRegistry::AddPredefinedHandler(
  612. const ProtocolHandler& handler) {
  613. DCHECK(!is_loaded_); // Must be called prior InitProtocolSettings.
  614. RegisterProtocolHandler(handler, USER);
  615. SetDefault(handler);
  616. predefined_protocol_handlers_.push_back(handler);
  617. }
  618. DefaultClientCallback ProtocolHandlerRegistry::GetDefaultWebClientCallback(
  619. const std::string& protocol) {
  620. return base::BindOnce(
  621. &ProtocolHandlerRegistry::OnSetAsDefaultProtocolClientFinished,
  622. weak_ptr_factory_.GetWeakPtr(), protocol);
  623. }
  624. } // namespace custom_handlers