|
18 | 18 | #include "mozilla/dom/PContentChild.h" |
19 | 19 | #include "mozilla/dom/PContentDialogChild.h" |
20 | 20 | #include "mozilla/ipc/DocumentRendererChild.h" |
| 21 | +#include "mozilla/ipc/FileDescriptorUtils.h" |
21 | 22 | #include "mozilla/layers/AsyncPanZoomController.h" |
22 | 23 | #include "mozilla/layers/CompositorChild.h" |
23 | 24 | #include "mozilla/layers/PLayersChild.h" |
|
37 | 38 | #include "mozilla/dom/Element.h" |
38 | 39 | #include "nsIAppsService.h" |
39 | 40 | #include "nsIBaseWindow.h" |
| 41 | +#include "nsICachedFileDescriptorListener.h" |
40 | 42 | #include "nsIComponentManager.h" |
41 | 43 | #include "nsIDocumentInlines.h" |
42 | 44 | #include "nsIDOMClassInfo.h" |
@@ -121,6 +123,98 @@ class ContentDialogChild : public PContentDialogChild |
121 | 123 | const InfallibleTArray<nsString>& aStringParams); |
122 | 124 | }; |
123 | 125 |
|
| 126 | +class TabChild::CachedFileDescriptorInfo |
| 127 | +{ |
| 128 | + struct PathOnlyComparatorHelper |
| 129 | + { |
| 130 | + bool Equals(const nsAutoPtr<CachedFileDescriptorInfo>& a, |
| 131 | + const CachedFileDescriptorInfo& b) const |
| 132 | + { |
| 133 | + return a->mPath == b.mPath; |
| 134 | + } |
| 135 | + }; |
| 136 | + |
| 137 | + struct PathAndCallbackComparatorHelper |
| 138 | + { |
| 139 | + bool Equals(const nsAutoPtr<CachedFileDescriptorInfo>& a, |
| 140 | + const CachedFileDescriptorInfo& b) const |
| 141 | + { |
| 142 | + return a->mPath == b.mPath && |
| 143 | + a->mCallback == b.mCallback; |
| 144 | + } |
| 145 | + }; |
| 146 | + |
| 147 | +public: |
| 148 | + nsString mPath; |
| 149 | + FileDescriptor mFileDescriptor; |
| 150 | + nsCOMPtr<nsICachedFileDescriptorListener> mCallback; |
| 151 | + bool mCanceled; |
| 152 | + |
| 153 | + CachedFileDescriptorInfo(const nsAString& aPath) |
| 154 | + : mPath(aPath), mCanceled(false) |
| 155 | + { } |
| 156 | + |
| 157 | + CachedFileDescriptorInfo(const nsAString& aPath, |
| 158 | + const FileDescriptor& aFileDescriptor) |
| 159 | + : mPath(aPath), mFileDescriptor(aFileDescriptor), mCanceled(false) |
| 160 | + { } |
| 161 | + |
| 162 | + CachedFileDescriptorInfo(const nsAString& aPath, |
| 163 | + nsICachedFileDescriptorListener* aCallback) |
| 164 | + : mPath(aPath), mCallback(aCallback), mCanceled(false) |
| 165 | + { } |
| 166 | + |
| 167 | + PathOnlyComparatorHelper PathOnlyComparator() const |
| 168 | + { |
| 169 | + return PathOnlyComparatorHelper(); |
| 170 | + } |
| 171 | + |
| 172 | + PathAndCallbackComparatorHelper PathAndCallbackComparator() const |
| 173 | + { |
| 174 | + return PathAndCallbackComparatorHelper(); |
| 175 | + } |
| 176 | + |
| 177 | + void FireCallback() const |
| 178 | + { |
| 179 | + mCallback->OnCachedFileDescriptor(mPath, mFileDescriptor); |
| 180 | + } |
| 181 | +}; |
| 182 | + |
| 183 | +class TabChild::CachedFileDescriptorCallbackRunnable : public nsRunnable |
| 184 | +{ |
| 185 | + typedef TabChild::CachedFileDescriptorInfo CachedFileDescriptorInfo; |
| 186 | + |
| 187 | + nsAutoPtr<CachedFileDescriptorInfo> mInfo; |
| 188 | + |
| 189 | +public: |
| 190 | + CachedFileDescriptorCallbackRunnable(CachedFileDescriptorInfo* aInfo) |
| 191 | + : mInfo(aInfo) |
| 192 | + { |
| 193 | + MOZ_ASSERT(NS_IsMainThread()); |
| 194 | + MOZ_ASSERT(aInfo); |
| 195 | + MOZ_ASSERT(!aInfo->mPath.IsEmpty()); |
| 196 | + MOZ_ASSERT(aInfo->mCallback); |
| 197 | + } |
| 198 | + |
| 199 | + void Dispatch() |
| 200 | + { |
| 201 | + MOZ_ASSERT(NS_IsMainThread()); |
| 202 | + |
| 203 | + nsresult rv = NS_DispatchToCurrentThread(this); |
| 204 | + NS_ENSURE_SUCCESS_VOID(rv); |
| 205 | + } |
| 206 | + |
| 207 | +private: |
| 208 | + NS_IMETHOD Run() |
| 209 | + { |
| 210 | + MOZ_ASSERT(NS_IsMainThread()); |
| 211 | + MOZ_ASSERT(mInfo); |
| 212 | + |
| 213 | + mInfo->FireCallback(); |
| 214 | + return NS_OK; |
| 215 | + } |
| 216 | +}; |
| 217 | + |
124 | 218 | StaticRefPtr<TabChild> sPreallocatedTab; |
125 | 219 |
|
126 | 220 | /*static*/ void |
@@ -1119,6 +1213,130 @@ TabChild::RecvLoadURL(const nsCString& uri) |
1119 | 1213 | return true; |
1120 | 1214 | } |
1121 | 1215 |
|
| 1216 | +bool |
| 1217 | +TabChild::RecvCacheFileDescriptor(const nsString& aPath, |
| 1218 | + const FileDescriptor& aFileDescriptor) |
| 1219 | +{ |
| 1220 | + MOZ_ASSERT(NS_IsMainThread()); |
| 1221 | + MOZ_ASSERT(!aPath.IsEmpty()); |
| 1222 | + |
| 1223 | + // aFileDescriptor may be invalid here, but the callback will choose how to |
| 1224 | + // handle it. |
| 1225 | + |
| 1226 | + // First see if we already have a request for this path. |
| 1227 | + const CachedFileDescriptorInfo search(aPath); |
| 1228 | + uint32_t index = |
| 1229 | + mCachedFileDescriptorInfos.IndexOf(search, 0, |
| 1230 | + search.PathOnlyComparator()); |
| 1231 | + if (index == mCachedFileDescriptorInfos.NoIndex) { |
| 1232 | + // We haven't had any requests for this path yet. Assume that we will |
| 1233 | + // in a little while and save the file descriptor here. |
| 1234 | + mCachedFileDescriptorInfos.AppendElement( |
| 1235 | + new CachedFileDescriptorInfo(aPath, aFileDescriptor)); |
| 1236 | + return true; |
| 1237 | + } |
| 1238 | + |
| 1239 | + nsAutoPtr<CachedFileDescriptorInfo>& info = |
| 1240 | + mCachedFileDescriptorInfos[index]; |
| 1241 | + |
| 1242 | + MOZ_ASSERT(info); |
| 1243 | + MOZ_ASSERT(info->mPath == aPath); |
| 1244 | + MOZ_ASSERT(!info->mFileDescriptor.IsValid()); |
| 1245 | + MOZ_ASSERT(info->mCallback); |
| 1246 | + |
| 1247 | + // If this callback has been canceled then we can simply close the file |
| 1248 | + // descriptor and forget about the callback. |
| 1249 | + if (info->mCanceled) { |
| 1250 | + // Only close if this is a valid file descriptor. |
| 1251 | + if (aFileDescriptor.IsValid()) { |
| 1252 | + nsRefPtr<CloseFileRunnable> runnable = |
| 1253 | + new CloseFileRunnable(aFileDescriptor); |
| 1254 | + runnable->Dispatch(); |
| 1255 | + } |
| 1256 | + } else { |
| 1257 | + // Not canceled so fire the callback. |
| 1258 | + info->mFileDescriptor = aFileDescriptor; |
| 1259 | + |
| 1260 | + // We don't need a runnable here because we should already be at the top |
| 1261 | + // of the event loop. Just fire immediately. |
| 1262 | + info->FireCallback(); |
| 1263 | + } |
| 1264 | + |
| 1265 | + mCachedFileDescriptorInfos.RemoveElementAt(index); |
| 1266 | + return true; |
| 1267 | +} |
| 1268 | + |
| 1269 | +bool |
| 1270 | +TabChild::GetCachedFileDescriptor(const nsAString& aPath, |
| 1271 | + nsICachedFileDescriptorListener* aCallback) |
| 1272 | +{ |
| 1273 | + MOZ_ASSERT(NS_IsMainThread()); |
| 1274 | + MOZ_ASSERT(!aPath.IsEmpty()); |
| 1275 | + MOZ_ASSERT(aCallback); |
| 1276 | + |
| 1277 | + // First see if we've already received a cached file descriptor for this |
| 1278 | + // path. |
| 1279 | + const CachedFileDescriptorInfo search(aPath); |
| 1280 | + uint32_t index = |
| 1281 | + mCachedFileDescriptorInfos.IndexOf(search, 0, |
| 1282 | + search.PathOnlyComparator()); |
| 1283 | + if (index == mCachedFileDescriptorInfos.NoIndex) { |
| 1284 | + // We haven't received a file descriptor for this path yet. Assume that |
| 1285 | + // we will in a little while and save the request here. |
| 1286 | + mCachedFileDescriptorInfos.AppendElement( |
| 1287 | + new CachedFileDescriptorInfo(aPath, aCallback)); |
| 1288 | + return false; |
| 1289 | + } |
| 1290 | + |
| 1291 | + nsAutoPtr<CachedFileDescriptorInfo>& info = |
| 1292 | + mCachedFileDescriptorInfos[index]; |
| 1293 | + |
| 1294 | + MOZ_ASSERT(info); |
| 1295 | + MOZ_ASSERT(info->mPath == aPath); |
| 1296 | + MOZ_ASSERT(!info->mCallback); |
| 1297 | + MOZ_ASSERT(!info->mCanceled); |
| 1298 | + |
| 1299 | + info->mCallback = aCallback; |
| 1300 | + |
| 1301 | + nsRefPtr<CachedFileDescriptorCallbackRunnable> runnable = |
| 1302 | + new CachedFileDescriptorCallbackRunnable(info); |
| 1303 | + runnable->Dispatch(); |
| 1304 | + |
| 1305 | + mCachedFileDescriptorInfos.RemoveElementAt(index); |
| 1306 | + return true; |
| 1307 | +} |
| 1308 | + |
| 1309 | +void |
| 1310 | +TabChild::CancelCachedFileDescriptorCallback( |
| 1311 | + const nsAString& aPath, |
| 1312 | + nsICachedFileDescriptorListener* aCallback) |
| 1313 | +{ |
| 1314 | + MOZ_ASSERT(NS_IsMainThread()); |
| 1315 | + MOZ_ASSERT(!aPath.IsEmpty()); |
| 1316 | + MOZ_ASSERT(aCallback); |
| 1317 | + |
| 1318 | + const CachedFileDescriptorInfo search(aPath, aCallback); |
| 1319 | + uint32_t index = |
| 1320 | + mCachedFileDescriptorInfos.IndexOf(search, 0, |
| 1321 | + search.PathAndCallbackComparator()); |
| 1322 | + if (index == mCachedFileDescriptorInfos.NoIndex) { |
| 1323 | + // Nothing to do here. |
| 1324 | + return; |
| 1325 | + } |
| 1326 | + |
| 1327 | + nsAutoPtr<CachedFileDescriptorInfo>& info = |
| 1328 | + mCachedFileDescriptorInfos[index]; |
| 1329 | + |
| 1330 | + MOZ_ASSERT(info); |
| 1331 | + MOZ_ASSERT(info->mPath == aPath); |
| 1332 | + MOZ_ASSERT(!info->mFileDescriptor.IsValid()); |
| 1333 | + MOZ_ASSERT(info->mCallback == aCallback); |
| 1334 | + MOZ_ASSERT(!info->mCanceled); |
| 1335 | + |
| 1336 | + // Set this flag so that we will close the file descriptor when it arrives. |
| 1337 | + info->mCanceled = true; |
| 1338 | +} |
| 1339 | + |
1122 | 1340 | void |
1123 | 1341 | TabChild::DoFakeShow() |
1124 | 1342 | { |
|
0 commit comments