DomainPolicy.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "DomainPolicy.h"
  6. #include "mozilla/dom/ContentParent.h"
  7. #include "mozilla/ipc/URIUtils.h"
  8. #include "mozilla/Unused.h"
  9. #include "nsIMessageManager.h"
  10. #include "nsScriptSecurityManager.h"
  11. namespace mozilla {
  12. using namespace ipc;
  13. using namespace dom;
  14. NS_IMPL_ISUPPORTS(DomainPolicy, nsIDomainPolicy)
  15. static nsresult
  16. BroadcastDomainSetChange(DomainSetType aSetType, DomainSetChangeType aChangeType,
  17. nsIURI* aDomain = nullptr)
  18. {
  19. MOZ_ASSERT(XRE_IsParentProcess(),
  20. "DomainPolicy should only be exposed to the chrome process.");
  21. nsTArray<ContentParent*> parents;
  22. ContentParent::GetAll(parents);
  23. if (!parents.Length()) {
  24. return NS_OK;
  25. }
  26. OptionalURIParams uri;
  27. SerializeURI(aDomain, uri);
  28. for (uint32_t i = 0; i < parents.Length(); i++) {
  29. Unused << parents[i]->SendDomainSetChanged(aSetType, aChangeType, uri);
  30. }
  31. return NS_OK;
  32. }
  33. DomainPolicy::DomainPolicy() : mBlacklist(new DomainSet(BLACKLIST))
  34. , mSuperBlacklist(new DomainSet(SUPER_BLACKLIST))
  35. , mWhitelist(new DomainSet(WHITELIST))
  36. , mSuperWhitelist(new DomainSet(SUPER_WHITELIST))
  37. {
  38. if (XRE_IsParentProcess()) {
  39. BroadcastDomainSetChange(NO_TYPE, ACTIVATE_POLICY);
  40. }
  41. }
  42. DomainPolicy::~DomainPolicy()
  43. {
  44. // The SSM holds a strong ref to the DomainPolicy until Deactivate() is
  45. // invoked, so we should never hit the destructor until that happens.
  46. MOZ_ASSERT(!mBlacklist && !mSuperBlacklist &&
  47. !mWhitelist && !mSuperWhitelist);
  48. }
  49. NS_IMETHODIMP
  50. DomainPolicy::GetBlacklist(nsIDomainSet** aSet)
  51. {
  52. nsCOMPtr<nsIDomainSet> set = mBlacklist.get();
  53. set.forget(aSet);
  54. return NS_OK;
  55. }
  56. NS_IMETHODIMP
  57. DomainPolicy::GetSuperBlacklist(nsIDomainSet** aSet)
  58. {
  59. nsCOMPtr<nsIDomainSet> set = mSuperBlacklist.get();
  60. set.forget(aSet);
  61. return NS_OK;
  62. }
  63. NS_IMETHODIMP
  64. DomainPolicy::GetWhitelist(nsIDomainSet** aSet)
  65. {
  66. nsCOMPtr<nsIDomainSet> set = mWhitelist.get();
  67. set.forget(aSet);
  68. return NS_OK;
  69. }
  70. NS_IMETHODIMP
  71. DomainPolicy::GetSuperWhitelist(nsIDomainSet** aSet)
  72. {
  73. nsCOMPtr<nsIDomainSet> set = mSuperWhitelist.get();
  74. set.forget(aSet);
  75. return NS_OK;
  76. }
  77. NS_IMETHODIMP
  78. DomainPolicy::Deactivate()
  79. {
  80. // Clear the hashtables first to free up memory, since script might
  81. // hold the doomed sets alive indefinitely.
  82. mBlacklist->Clear();
  83. mSuperBlacklist->Clear();
  84. mWhitelist->Clear();
  85. mSuperWhitelist->Clear();
  86. // Null them out.
  87. mBlacklist = nullptr;
  88. mSuperBlacklist = nullptr;
  89. mWhitelist = nullptr;
  90. mSuperWhitelist = nullptr;
  91. // Inform the SSM.
  92. nsScriptSecurityManager* ssm = nsScriptSecurityManager::GetScriptSecurityManager();
  93. if (ssm) {
  94. ssm->DeactivateDomainPolicy();
  95. }
  96. if (XRE_IsParentProcess()) {
  97. BroadcastDomainSetChange(NO_TYPE, DEACTIVATE_POLICY);
  98. }
  99. return NS_OK;
  100. }
  101. void
  102. DomainPolicy::CloneDomainPolicy(DomainPolicyClone* aClone)
  103. {
  104. aClone->active() = true;
  105. mBlacklist->CloneSet(&aClone->blacklist());
  106. mSuperBlacklist->CloneSet(&aClone->superBlacklist());
  107. mWhitelist->CloneSet(&aClone->whitelist());
  108. mSuperWhitelist->CloneSet(&aClone->superWhitelist());
  109. }
  110. static
  111. void
  112. CopyURIs(const InfallibleTArray<URIParams>& aDomains, nsIDomainSet* aSet)
  113. {
  114. for (uint32_t i = 0; i < aDomains.Length(); i++) {
  115. nsCOMPtr<nsIURI> uri = DeserializeURI(aDomains[i]);
  116. aSet->Add(uri);
  117. }
  118. }
  119. void
  120. DomainPolicy::ApplyClone(DomainPolicyClone* aClone)
  121. {
  122. CopyURIs(aClone->blacklist(), mBlacklist);
  123. CopyURIs(aClone->whitelist(), mWhitelist);
  124. CopyURIs(aClone->superBlacklist(), mSuperBlacklist);
  125. CopyURIs(aClone->superWhitelist(), mSuperWhitelist);
  126. }
  127. static already_AddRefed<nsIURI>
  128. GetCanonicalClone(nsIURI* aURI)
  129. {
  130. nsCOMPtr<nsIURI> clone;
  131. nsresult rv = aURI->Clone(getter_AddRefs(clone));
  132. NS_ENSURE_SUCCESS(rv, nullptr);
  133. rv = clone->SetUserPass(EmptyCString());
  134. NS_ENSURE_SUCCESS(rv, nullptr);
  135. rv = clone->SetPath(EmptyCString());
  136. NS_ENSURE_SUCCESS(rv, nullptr);
  137. return clone.forget();
  138. }
  139. NS_IMPL_ISUPPORTS(DomainSet, nsIDomainSet)
  140. NS_IMETHODIMP
  141. DomainSet::Add(nsIURI* aDomain)
  142. {
  143. nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
  144. NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
  145. mHashTable.PutEntry(clone);
  146. if (XRE_IsParentProcess())
  147. return BroadcastDomainSetChange(mType, ADD_DOMAIN, aDomain);
  148. return NS_OK;
  149. }
  150. NS_IMETHODIMP
  151. DomainSet::Remove(nsIURI* aDomain)
  152. {
  153. nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
  154. NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
  155. mHashTable.RemoveEntry(clone);
  156. if (XRE_IsParentProcess())
  157. return BroadcastDomainSetChange(mType, REMOVE_DOMAIN, aDomain);
  158. return NS_OK;
  159. }
  160. NS_IMETHODIMP
  161. DomainSet::Clear()
  162. {
  163. mHashTable.Clear();
  164. if (XRE_IsParentProcess())
  165. return BroadcastDomainSetChange(mType, CLEAR_DOMAINS);
  166. return NS_OK;
  167. }
  168. NS_IMETHODIMP
  169. DomainSet::Contains(nsIURI* aDomain, bool* aContains)
  170. {
  171. *aContains = false;
  172. nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
  173. NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
  174. *aContains = mHashTable.Contains(clone);
  175. return NS_OK;
  176. }
  177. NS_IMETHODIMP
  178. DomainSet::ContainsSuperDomain(nsIURI* aDomain, bool* aContains)
  179. {
  180. *aContains = false;
  181. nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
  182. NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
  183. nsAutoCString domain;
  184. nsresult rv = clone->GetHost(domain);
  185. NS_ENSURE_SUCCESS(rv, rv);
  186. while (true) {
  187. // Check the current domain.
  188. if (mHashTable.Contains(clone)) {
  189. *aContains = true;
  190. return NS_OK;
  191. }
  192. // Chop off everything before the first dot, or break if there are no
  193. // dots left.
  194. int32_t index = domain.Find(".");
  195. if (index == kNotFound)
  196. break;
  197. domain.Assign(Substring(domain, index + 1));
  198. rv = clone->SetHost(domain);
  199. NS_ENSURE_SUCCESS(rv, rv);
  200. }
  201. // No match.
  202. return NS_OK;
  203. }
  204. NS_IMETHODIMP
  205. DomainSet::GetType(uint32_t* aType)
  206. {
  207. *aType = mType;
  208. return NS_OK;
  209. }
  210. void
  211. DomainSet::CloneSet(InfallibleTArray<URIParams>* aDomains)
  212. {
  213. for (auto iter = mHashTable.Iter(); !iter.Done(); iter.Next()) {
  214. nsIURI* key = iter.Get()->GetKey();
  215. URIParams uri;
  216. SerializeURI(key, uri);
  217. aDomains->AppendElement(uri);
  218. }
  219. }
  220. } /* namespace mozilla */