Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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/. */
6 #include "nsMessageLoop.h"
7 #include "mozilla/WeakPtr.h"
8 #include "base/message_loop.h"
9 #include "base/task.h"
10 #include "nsIRunnable.h"
11 #include "nsITimer.h"
12 #include "nsCOMPtr.h"
13 #include "nsAutoPtr.h"
14 #include "nsComponentManagerUtils.h"
15 #include "nsThreadUtils.h"
17 using namespace mozilla;
19 namespace {
21 /**
22 * This Task runs its nsIRunnable when Run() is called, or after
23 * aEnsureRunsAfterMS milliseconds have elapsed since the object was
24 * constructed.
25 *
26 * Note that the MessageLoop owns this object and will delete it after it calls
27 * Run(). Tread lightly.
28 */
29 class MessageLoopIdleTask
30 : public Task
31 , public SupportsWeakPtr<MessageLoopIdleTask>
32 {
33 public:
34 MOZ_DECLARE_REFCOUNTED_TYPENAME(MessageLoopIdleTask)
35 MessageLoopIdleTask(nsIRunnable* aTask, uint32_t aEnsureRunsAfterMS);
36 virtual ~MessageLoopIdleTask() {}
37 virtual void Run();
39 private:
40 nsresult Init(uint32_t aEnsureRunsAfterMS);
42 nsCOMPtr<nsIRunnable> mTask;
43 nsCOMPtr<nsITimer> mTimer;
44 };
46 /**
47 * This timer callback calls MessageLoopIdleTask::Run() when its timer fires.
48 * (The timer can't call back into MessageLoopIdleTask directly since that's
49 * not a refcounted object; it's owned by the MessageLoop.)
50 *
51 * We keep a weak reference to the MessageLoopIdleTask, although a raw pointer
52 * should in theory suffice: When the MessageLoopIdleTask runs (right before
53 * the MessageLoop deletes it), it cancels its timer. But the weak pointer
54 * saves us from worrying about an edge case somehow messing us up here.
55 */
56 class MessageLoopTimerCallback
57 : public nsITimerCallback
58 {
59 public:
60 MessageLoopTimerCallback(MessageLoopIdleTask* aTask);
61 virtual ~MessageLoopTimerCallback() {};
63 NS_DECL_ISUPPORTS
64 NS_DECL_NSITIMERCALLBACK
66 private:
67 WeakPtr<MessageLoopIdleTask> mTask;
68 };
70 MessageLoopIdleTask::MessageLoopIdleTask(nsIRunnable* aTask,
71 uint32_t aEnsureRunsAfterMS)
72 : mTask(aTask)
73 {
74 // Init() really shouldn't fail, but if it does, we schedule our runnable
75 // immediately, because it's more important to guarantee that we run the task
76 // eventually than it is to run the task when we're idle.
77 nsresult rv = Init(aEnsureRunsAfterMS);
78 if (NS_FAILED(rv)) {
79 NS_WARNING("Running idle task early because we couldn't initialize our timer.");
80 NS_DispatchToCurrentThread(mTask);
82 mTask = nullptr;
83 mTimer = nullptr;
84 }
85 }
87 nsresult
88 MessageLoopIdleTask::Init(uint32_t aEnsureRunsAfterMS)
89 {
90 mTimer = do_CreateInstance("@mozilla.org/timer;1");
91 if (NS_WARN_IF(!mTimer))
92 return NS_ERROR_UNEXPECTED;
94 nsRefPtr<MessageLoopTimerCallback> callback =
95 new MessageLoopTimerCallback(this);
97 return mTimer->InitWithCallback(callback, aEnsureRunsAfterMS,
98 nsITimer::TYPE_ONE_SHOT);
99 }
101 /* virtual */ void
102 MessageLoopIdleTask::Run()
103 {
104 // Null out our pointers because if Run() was called by the timer, this
105 // object will be kept alive by the MessageLoop until the MessageLoop calls
106 // Run().
108 if (mTimer) {
109 mTimer->Cancel();
110 mTimer = nullptr;
111 }
113 if (mTask) {
114 mTask->Run();
115 mTask = nullptr;
116 }
117 }
119 MessageLoopTimerCallback::MessageLoopTimerCallback(MessageLoopIdleTask* aTask)
120 : mTask(aTask->asWeakPtr())
121 {}
123 NS_IMETHODIMP
124 MessageLoopTimerCallback::Notify(nsITimer* aTimer)
125 {
126 // We don't expect to hit the case when the timer fires but mTask has been
127 // deleted, because mTask should cancel the timer before the mTask is
128 // deleted. But you never know...
129 NS_WARN_IF_FALSE(mTask, "This timer shouldn't have fired.");
131 if (mTask) {
132 mTask->Run();
133 }
134 return NS_OK;
135 }
137 NS_IMPL_ISUPPORTS(MessageLoopTimerCallback, nsITimerCallback)
139 } // anonymous namespace
141 NS_IMPL_ISUPPORTS(nsMessageLoop, nsIMessageLoop)
143 NS_IMETHODIMP
144 nsMessageLoop::PostIdleTask(nsIRunnable* aTask, uint32_t aEnsureRunsAfterMS)
145 {
146 // The message loop owns MessageLoopIdleTask and deletes it after calling
147 // Run(). Be careful...
148 MessageLoop::current()->PostIdleTask(FROM_HERE,
149 new MessageLoopIdleTask(aTask, aEnsureRunsAfterMS));
150 return NS_OK;
151 }
153 nsresult
154 nsMessageLoopConstructor(nsISupports* aOuter,
155 const nsIID& aIID,
156 void** aInstancePtr)
157 {
158 if (NS_WARN_IF(aOuter))
159 return NS_ERROR_NO_AGGREGATION;
160 nsISupports* messageLoop = new nsMessageLoop();
161 return messageLoop->QueryInterface(aIID, aInstancePtr);
162 }