summaryrefslogtreecommitdiffstats
path: root/dom/html/HTMLDNSPrefetch.h
blob: 5820a6ecb2f9bfdac94ec914418afe12814fe603 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_dom_HTMLDNSPrefetch_h___
#define mozilla_dom_HTMLDNSPrefetch_h___

#include "nsCOMPtr.h"
#include "nsIRequest.h"
#include "nsString.h"
#include "nsIDNSService.h"

class nsITimer;
class nsIURI;
namespace mozilla {

class OriginAttributes;

namespace net {
class NeckoParent;
}  // namespace net

namespace dom {
class Document;
class Element;

class SupportsDNSPrefetch;

class HTMLDNSPrefetch {
 public:
  // The required aDocument parameter is the context requesting the prefetch -
  // under certain circumstances (e.g. headers, or security context) associated
  // with the context the prefetch will not be performed.
  static bool IsAllowed(Document* aDocument);

  static nsresult Initialize();
  static nsresult Shutdown();

  // Call one of the Prefetch* methods to start the lookup.
  //
  // The URI versions will defer DNS lookup until pageload is
  // complete, while the string versions submit the lookup to
  // the DNS system immediately. The URI version is somewhat lighter
  // weight, but its request is also more likely to be dropped due to a
  // full queue and it may only be used from the main thread.
  //
  // If you are planning to use the methods with the OriginAttributes param, be
  // sure that you pass a partitioned one. See StoragePrincipalHelper.h to know
  // more.

  enum class Priority {
    Low,
    Medium,
    High,
  };
  static nsresult Prefetch(SupportsDNSPrefetch&, Element&, Priority);
  static nsresult Prefetch(
      const nsAString& host, bool isHttps,
      const OriginAttributes& aPartitionedPrincipalOriginAttributes,
      nsIRequest::TRRMode aTRRMode, Priority);
  static nsresult CancelPrefetch(
      const nsAString& host, bool isHttps,
      const OriginAttributes& aPartitionedPrincipalOriginAttributes,
      nsIRequest::TRRMode aTRRMode, Priority, nsresult aReason);
  static nsresult CancelPrefetch(SupportsDNSPrefetch&, Element&, Priority,
                                 nsresult aReason);
  static void ElementDestroyed(Element&, SupportsDNSPrefetch&);

 private:
  static nsIDNSService::DNSFlags PriorityToDNSServiceFlags(Priority);

  static nsresult Prefetch(
      const nsAString& host, bool isHttps,
      const OriginAttributes& aPartitionedPrincipalOriginAttributes,
      nsIDNSService::DNSFlags flags);
  static nsresult CancelPrefetch(
      const nsAString& hostname, bool isHttps,
      const OriginAttributes& aPartitionedPrincipalOriginAttributes,
      nsIDNSService::DNSFlags flags, nsresult aReason);

  friend class net::NeckoParent;
};

// Elements that support DNS prefetch are expected to subclass this.
class SupportsDNSPrefetch {
 public:
  bool IsInDNSPrefetch() { return mInDNSPrefetch; }
  void SetIsInDNSPrefetch() { mInDNSPrefetch = true; }
  void ClearIsInDNSPrefetch() { mInDNSPrefetch = false; }

  void DNSPrefetchRequestStarted() {
    mDNSPrefetchDeferred = false;
    mDNSPrefetchRequested = true;
  }

  void DNSPrefetchRequestDeferred() {
    mDNSPrefetchDeferred = true;
    mDNSPrefetchRequested = false;
  }

  bool IsDNSPrefetchRequestDeferred() const { return mDNSPrefetchDeferred; }

  // This could be a virtual function or something like that, but that would
  // cause our subclasses to grow by two pointers, rather than just 1 byte at
  // most.
  nsIURI* GetURIForDNSPrefetch(Element& aOwner);

 protected:
  SupportsDNSPrefetch()
      : mInDNSPrefetch(false),
        mDNSPrefetchRequested(false),
        mDNSPrefetchDeferred(false),
        mDestroyedCalled(false) {}

  void CancelDNSPrefetch(Element&);
  void TryDNSPrefetch(Element&);

  // This MUST be called on the destructor of the Element subclass.
  // Our own destructor ensures that.
  void Destroyed(Element& aOwner) {
    MOZ_DIAGNOSTIC_ASSERT(!mDestroyedCalled,
                          "Multiple calls to SupportsDNSPrefetch::Destroyed?");
    mDestroyedCalled = true;
    if (mInDNSPrefetch) {
      HTMLDNSPrefetch::ElementDestroyed(aOwner, *this);
    }
  }

  ~SupportsDNSPrefetch() {
    MOZ_DIAGNOSTIC_ASSERT(mDestroyedCalled,
                          "Need to call SupportsDNSPrefetch::Destroyed "
                          "from the owner element");
  }

 private:
  bool mInDNSPrefetch : 1;
  bool mDNSPrefetchRequested : 1;
  bool mDNSPrefetchDeferred : 1;
  bool mDestroyedCalled : 1;
};

}  // namespace dom
}  // namespace mozilla

#endif