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.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* Copyright 2012 Mozilla Foundation and Mozilla contributors |
michael@0 | 3 | * |
michael@0 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
michael@0 | 5 | * you may not use this file except in compliance with the License. |
michael@0 | 6 | * You may obtain a copy of the License at |
michael@0 | 7 | * |
michael@0 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
michael@0 | 9 | * |
michael@0 | 10 | * Unless required by applicable law or agreed to in writing, software |
michael@0 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
michael@0 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
michael@0 | 13 | * See the License for the specific language governing permissions and |
michael@0 | 14 | * limitations under the License. |
michael@0 | 15 | */ |
michael@0 | 16 | |
michael@0 | 17 | #include <errno.h> |
michael@0 | 18 | #include <fcntl.h> |
michael@0 | 19 | #include <pthread.h> |
michael@0 | 20 | #include <signal.h> |
michael@0 | 21 | #include <string.h> |
michael@0 | 22 | #include <strings.h> |
michael@0 | 23 | #include <unistd.h> |
michael@0 | 24 | |
michael@0 | 25 | #include <arpa/inet.h> |
michael@0 | 26 | #include <linux/types.h> |
michael@0 | 27 | #include <linux/netlink.h> |
michael@0 | 28 | #include <netinet/in.h> |
michael@0 | 29 | #include <sys/socket.h> |
michael@0 | 30 | |
michael@0 | 31 | #include "nsDebug.h" |
michael@0 | 32 | #include "base/message_loop.h" |
michael@0 | 33 | #include "mozilla/FileUtils.h" |
michael@0 | 34 | #include "nsAutoPtr.h" |
michael@0 | 35 | #include "nsThreadUtils.h" |
michael@0 | 36 | #include "nsXULAppAPI.h" |
michael@0 | 37 | |
michael@0 | 38 | #include "UeventPoller.h" |
michael@0 | 39 | |
michael@0 | 40 | namespace mozilla { |
michael@0 | 41 | namespace hal_impl { |
michael@0 | 42 | |
michael@0 | 43 | static void ShutdownUevent(); |
michael@0 | 44 | |
michael@0 | 45 | class NetlinkPoller : public MessageLoopForIO::Watcher |
michael@0 | 46 | { |
michael@0 | 47 | public: |
michael@0 | 48 | NetlinkPoller() : mSocket(-1), |
michael@0 | 49 | mIOLoop(MessageLoopForIO::current()) |
michael@0 | 50 | { |
michael@0 | 51 | } |
michael@0 | 52 | |
michael@0 | 53 | virtual ~NetlinkPoller() {} |
michael@0 | 54 | |
michael@0 | 55 | bool OpenSocket(); |
michael@0 | 56 | |
michael@0 | 57 | virtual void OnFileCanReadWithoutBlocking(int fd); |
michael@0 | 58 | |
michael@0 | 59 | // no writing to the netlink socket |
michael@0 | 60 | virtual void OnFileCanWriteWithoutBlocking(int fd) |
michael@0 | 61 | { |
michael@0 | 62 | MOZ_CRASH("Must not write to netlink socket"); |
michael@0 | 63 | } |
michael@0 | 64 | |
michael@0 | 65 | MessageLoopForIO *GetIOLoop () const { return mIOLoop; } |
michael@0 | 66 | void RegisterObserver(IUeventObserver *aObserver) |
michael@0 | 67 | { |
michael@0 | 68 | mUeventObserverList.AddObserver(aObserver); |
michael@0 | 69 | } |
michael@0 | 70 | |
michael@0 | 71 | void UnregisterObserver(IUeventObserver *aObserver) |
michael@0 | 72 | { |
michael@0 | 73 | mUeventObserverList.RemoveObserver(aObserver); |
michael@0 | 74 | if (mUeventObserverList.Length() == 0) |
michael@0 | 75 | ShutdownUevent(); // this will destroy self |
michael@0 | 76 | } |
michael@0 | 77 | |
michael@0 | 78 | private: |
michael@0 | 79 | ScopedClose mSocket; |
michael@0 | 80 | MessageLoopForIO* mIOLoop; |
michael@0 | 81 | MessageLoopForIO::FileDescriptorWatcher mReadWatcher; |
michael@0 | 82 | |
michael@0 | 83 | const static int kBuffsize = 64 * 1024; |
michael@0 | 84 | uint8_t mBuffer [kBuffsize]; |
michael@0 | 85 | |
michael@0 | 86 | typedef ObserverList<NetlinkEvent> UeventObserverList; |
michael@0 | 87 | UeventObserverList mUeventObserverList; |
michael@0 | 88 | }; |
michael@0 | 89 | |
michael@0 | 90 | bool |
michael@0 | 91 | NetlinkPoller::OpenSocket() |
michael@0 | 92 | { |
michael@0 | 93 | mSocket.rwget() = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); |
michael@0 | 94 | if (mSocket.get() < 0) |
michael@0 | 95 | return false; |
michael@0 | 96 | |
michael@0 | 97 | int sz = kBuffsize; |
michael@0 | 98 | |
michael@0 | 99 | if (setsockopt(mSocket.get(), SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) |
michael@0 | 100 | return false; |
michael@0 | 101 | |
michael@0 | 102 | // add FD_CLOEXEC flag |
michael@0 | 103 | int flags = fcntl(mSocket.get(), F_GETFD); |
michael@0 | 104 | if (flags == -1) { |
michael@0 | 105 | return false; |
michael@0 | 106 | } |
michael@0 | 107 | flags |= FD_CLOEXEC; |
michael@0 | 108 | if (fcntl(mSocket.get(), F_SETFD, flags) == -1) |
michael@0 | 109 | return false; |
michael@0 | 110 | |
michael@0 | 111 | // set non-blocking |
michael@0 | 112 | if (fcntl(mSocket.get(), F_SETFL, O_NONBLOCK) == -1) |
michael@0 | 113 | return false; |
michael@0 | 114 | |
michael@0 | 115 | struct sockaddr_nl saddr; |
michael@0 | 116 | bzero(&saddr, sizeof(saddr)); |
michael@0 | 117 | saddr.nl_family = AF_NETLINK; |
michael@0 | 118 | saddr.nl_groups = 1; |
michael@0 | 119 | saddr.nl_pid = gettid(); |
michael@0 | 120 | |
michael@0 | 121 | do { |
michael@0 | 122 | if (bind(mSocket.get(), (struct sockaddr *)&saddr, sizeof(saddr)) == 0) { |
michael@0 | 123 | break; |
michael@0 | 124 | } |
michael@0 | 125 | |
michael@0 | 126 | if (errno != EADDRINUSE) { |
michael@0 | 127 | return false; |
michael@0 | 128 | } |
michael@0 | 129 | |
michael@0 | 130 | if (saddr.nl_pid == 0) { |
michael@0 | 131 | return false; |
michael@0 | 132 | } |
michael@0 | 133 | |
michael@0 | 134 | // Once there was any other place in the same process assigning saddr.nl_pid by |
michael@0 | 135 | // gettid(), we can detect it and print warning message. |
michael@0 | 136 | printf_stderr("The netlink socket address saddr.nl_pid=%u is in use. Let the kernel re-assign.\n", saddr.nl_pid); |
michael@0 | 137 | saddr.nl_pid = 0; |
michael@0 | 138 | } while (true); |
michael@0 | 139 | |
michael@0 | 140 | if (!mIOLoop->WatchFileDescriptor(mSocket.get(), |
michael@0 | 141 | true, |
michael@0 | 142 | MessageLoopForIO::WATCH_READ, |
michael@0 | 143 | &mReadWatcher, |
michael@0 | 144 | this)) { |
michael@0 | 145 | return false; |
michael@0 | 146 | } |
michael@0 | 147 | |
michael@0 | 148 | return true; |
michael@0 | 149 | } |
michael@0 | 150 | |
michael@0 | 151 | static nsAutoPtr<NetlinkPoller> sPoller; |
michael@0 | 152 | |
michael@0 | 153 | class UeventInitTask : public Task |
michael@0 | 154 | { |
michael@0 | 155 | virtual void Run() |
michael@0 | 156 | { |
michael@0 | 157 | if (!sPoller) { |
michael@0 | 158 | return; |
michael@0 | 159 | } |
michael@0 | 160 | if (sPoller->OpenSocket()) { |
michael@0 | 161 | return; |
michael@0 | 162 | } |
michael@0 | 163 | sPoller->GetIOLoop()->PostDelayedTask(FROM_HERE, new UeventInitTask(), 1000); |
michael@0 | 164 | } |
michael@0 | 165 | }; |
michael@0 | 166 | |
michael@0 | 167 | void |
michael@0 | 168 | NetlinkPoller::OnFileCanReadWithoutBlocking(int fd) |
michael@0 | 169 | { |
michael@0 | 170 | MOZ_ASSERT(fd == mSocket.get()); |
michael@0 | 171 | while (true) { |
michael@0 | 172 | int ret = read(fd, mBuffer, kBuffsize); |
michael@0 | 173 | if (ret == -1) { |
michael@0 | 174 | if (errno == EAGAIN || errno == EWOULDBLOCK) { |
michael@0 | 175 | return; |
michael@0 | 176 | } |
michael@0 | 177 | if (errno == EINTR) { |
michael@0 | 178 | continue; |
michael@0 | 179 | } |
michael@0 | 180 | } |
michael@0 | 181 | if (ret <= 0) { |
michael@0 | 182 | // fatal error on netlink socket which should not happen |
michael@0 | 183 | _exit(1); |
michael@0 | 184 | } |
michael@0 | 185 | NetlinkEvent netlinkEvent; |
michael@0 | 186 | netlinkEvent.decode(reinterpret_cast<char*>(mBuffer), ret); |
michael@0 | 187 | mUeventObserverList.Broadcast(netlinkEvent); |
michael@0 | 188 | } |
michael@0 | 189 | } |
michael@0 | 190 | |
michael@0 | 191 | static void |
michael@0 | 192 | InitializeUevent() |
michael@0 | 193 | { |
michael@0 | 194 | MOZ_ASSERT(!sPoller); |
michael@0 | 195 | sPoller = new NetlinkPoller(); |
michael@0 | 196 | sPoller->GetIOLoop()->PostTask(FROM_HERE, new UeventInitTask()); |
michael@0 | 197 | |
michael@0 | 198 | } |
michael@0 | 199 | |
michael@0 | 200 | static void |
michael@0 | 201 | ShutdownUevent() |
michael@0 | 202 | { |
michael@0 | 203 | sPoller = nullptr; |
michael@0 | 204 | } |
michael@0 | 205 | |
michael@0 | 206 | void |
michael@0 | 207 | RegisterUeventListener(IUeventObserver *aObserver) |
michael@0 | 208 | { |
michael@0 | 209 | MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop()); |
michael@0 | 210 | |
michael@0 | 211 | if (!sPoller) |
michael@0 | 212 | InitializeUevent(); |
michael@0 | 213 | sPoller->RegisterObserver(aObserver); |
michael@0 | 214 | } |
michael@0 | 215 | |
michael@0 | 216 | void |
michael@0 | 217 | UnregisterUeventListener(IUeventObserver *aObserver) |
michael@0 | 218 | { |
michael@0 | 219 | MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop()); |
michael@0 | 220 | |
michael@0 | 221 | sPoller->UnregisterObserver(aObserver); |
michael@0 | 222 | } |
michael@0 | 223 | |
michael@0 | 224 | } // hal_impl |
michael@0 | 225 | } // mozilla |
michael@0 | 226 |