~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/modules/libpr0n/src/imgCache.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 
2
 *
 
3
 * The contents of this file are subject to the Mozilla Public
 
4
 * License Version 1.1 (the "License"); you may not use this file
 
5
 * except in compliance with the License. You may obtain a copy of
 
6
 * the License at http://www.mozilla.org/MPL/
 
7
 * 
 
8
 * Software distributed under the License is distributed on an "AS
 
9
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 
10
 * implied. See the License for the specific language governing
 
11
 * rights and limitations under the License.
 
12
 * 
 
13
 * The Original Code is mozilla.org code.
 
14
 * 
 
15
 * The Initial Developer of the Original Code is Netscape
 
16
 * Communications Corporation.  Portions created by Netscape are
 
17
 * Copyright (C) 2001 Netscape Communications Corporation.
 
18
 * All Rights Reserved.
 
19
 * 
 
20
 * Contributor(s):
 
21
 *   Stuart Parmenter <pavlov@netscape.com>
 
22
 */
 
23
 
 
24
#include "imgCache.h"
 
25
 
 
26
#include "ImageLogging.h"
 
27
 
 
28
#include "imgRequest.h"
 
29
 
 
30
#include "nsXPIDLString.h"
 
31
#include "nsCOMPtr.h"
 
32
#include "nsIServiceManager.h"
 
33
#include "nsIMemory.h"
 
34
#include "nsIObserverService.h"
 
35
 
 
36
#include "nsICache.h"
 
37
#include "nsICacheService.h"
 
38
#include "nsICacheSession.h"
 
39
#include "nsICacheEntryDescriptor.h"
 
40
 
 
41
#include "nsIFile.h"
 
42
#include "nsIFileURL.h"
 
43
 
 
44
NS_IMPL_ISUPPORTS3(imgCache, imgICache, nsIObserver, nsISupportsWeakReference)
 
45
 
 
46
imgCache::imgCache()
 
47
{
 
48
  /* member initializers and constructor code */
 
49
}
 
50
 
 
51
imgCache::~imgCache()
 
52
{
 
53
  /* destructor code */
 
54
}
 
55
 
 
56
nsresult imgCache::Init()
 
57
{
 
58
  imgCache* cache = new imgCache();
 
59
  if(!cache) return NS_ERROR_OUT_OF_MEMORY;
 
60
 
 
61
  nsCOMPtr<nsIObserverService> os = do_GetService("@mozilla.org/observer-service;1");
 
62
  if (os) {
 
63
    os->AddObserver(cache, "memory-pressure", PR_FALSE);
 
64
    os->AddObserver(cache, "chrome-flush-skin-caches", PR_FALSE);
 
65
    os->AddObserver(cache, "chrome-flush-caches", PR_FALSE);
 
66
  }
 
67
  
 
68
  return NS_OK;
 
69
}
 
70
 
 
71
/* void clearCache (in boolean chrome); */
 
72
NS_IMETHODIMP imgCache::ClearCache(PRBool chrome)
 
73
{
 
74
  if (chrome)
 
75
    return imgCache::ClearChromeImageCache();
 
76
  else
 
77
    return imgCache::ClearImageCache();
 
78
}
 
79
 
 
80
 
 
81
/* void removeEntry(in nsIURI uri); */
 
82
NS_IMETHODIMP imgCache::RemoveEntry(nsIURI *uri)
 
83
{
 
84
  if (imgCache::Remove(uri))
 
85
    return NS_OK;
 
86
 
 
87
  return NS_ERROR_NOT_AVAILABLE;
 
88
}
 
89
 
 
90
static nsCOMPtr<nsICacheSession> gSession = nsnull;
 
91
static nsCOMPtr<nsICacheSession> gChromeSession = nsnull;
 
92
 
 
93
void GetCacheSession(nsIURI *aURI, nsICacheSession **_retval)
 
94
{
 
95
  NS_ASSERTION(aURI, "Null URI!");
 
96
 
 
97
  PRBool isChrome = PR_FALSE;
 
98
  aURI->SchemeIs("chrome", &isChrome);
 
99
 
 
100
  if (gSession && !isChrome) {
 
101
    *_retval = gSession;
 
102
    NS_ADDREF(*_retval);
 
103
    return;
 
104
  }
 
105
 
 
106
  if (gChromeSession && isChrome) {
 
107
    *_retval = gChromeSession;
 
108
    NS_ADDREF(*_retval);
 
109
    return;
 
110
  }
 
111
 
 
112
  nsCOMPtr<nsICacheService> cacheService(do_GetService("@mozilla.org/network/cache-service;1"));
 
113
  if (!cacheService) {
 
114
    NS_WARNING("Unable to get the cache service");
 
115
    return;
 
116
  }
 
117
 
 
118
  nsCOMPtr<nsICacheSession> newSession;
 
119
  cacheService->CreateSession(isChrome ? "image-chrome" : "image",
 
120
                              nsICache::STORE_IN_MEMORY,
 
121
                              nsICache::NOT_STREAM_BASED,
 
122
                              getter_AddRefs(newSession));
 
123
 
 
124
  if (!newSession) {
 
125
    NS_WARNING("Unable to create a cache session");
 
126
    return;
 
127
  }
 
128
 
 
129
  if (isChrome)
 
130
    gChromeSession = newSession;
 
131
  else {
 
132
    gSession = newSession;
 
133
    gSession->SetDoomEntriesIfExpired(PR_FALSE);
 
134
  }
 
135
 
 
136
  *_retval = newSession;
 
137
  NS_ADDREF(*_retval);
 
138
}
 
139
 
 
140
 
 
141
void imgCache::Shutdown()
 
142
{
 
143
  gSession = nsnull;
 
144
  gChromeSession = nsnull;
 
145
}
 
146
 
 
147
 
 
148
nsresult imgCache::ClearChromeImageCache()
 
149
{
 
150
  if (!gChromeSession)
 
151
    return NS_OK;
 
152
 
 
153
  return gChromeSession->EvictEntries();
 
154
}
 
155
 
 
156
nsresult imgCache::ClearImageCache()
 
157
{
 
158
  if (!gSession)
 
159
    return NS_OK;
 
160
 
 
161
  return gSession->EvictEntries();
 
162
}
 
163
 
 
164
 
 
165
 
 
166
PRBool imgCache::Put(nsIURI *aKey, imgRequest *request, nsICacheEntryDescriptor **aEntry)
 
167
{
 
168
  LOG_STATIC_FUNC(gImgLog, "imgCache::Put");
 
169
 
 
170
  nsresult rv;
 
171
 
 
172
  nsCOMPtr<nsICacheSession> ses;
 
173
  GetCacheSession(aKey, getter_AddRefs(ses));
 
174
  if (!ses) return PR_FALSE;
 
175
 
 
176
  nsCAutoString spec;
 
177
  aKey->GetAsciiSpec(spec);
 
178
 
 
179
  nsCOMPtr<nsICacheEntryDescriptor> entry;
 
180
 
 
181
  rv = ses->OpenCacheEntry(spec.get(), nsICache::ACCESS_WRITE, nsICache::BLOCKING, getter_AddRefs(entry));
 
182
 
 
183
  if (NS_FAILED(rv) || !entry)
 
184
    return PR_FALSE;
 
185
 
 
186
  nsCOMPtr<nsISupports> sup = NS_REINTERPRET_CAST(nsISupports*, request);
 
187
  entry->SetCacheElement(sup);
 
188
 
 
189
  entry->MarkValid();
 
190
 
 
191
  // If file, force revalidation on expiration
 
192
  PRBool isFile;
 
193
  aKey->SchemeIs("file", &isFile);
 
194
  if (isFile)
 
195
    entry->SetMetaDataElement("MustValidateIfExpired", "true");
 
196
 
 
197
  *aEntry = entry;
 
198
  NS_ADDREF(*aEntry);
 
199
 
 
200
  return PR_TRUE;
 
201
}
 
202
 
 
203
static PRUint32
 
204
SecondsFromPRTime(PRTime prTime)
 
205
{
 
206
  PRInt64 microSecondsPerSecond, intermediateResult;
 
207
  PRUint32 seconds;
 
208
  
 
209
  LL_I2L(microSecondsPerSecond, PR_USEC_PER_SEC);
 
210
  LL_DIV(intermediateResult, prTime, microSecondsPerSecond);
 
211
  LL_L2UI(seconds, intermediateResult);
 
212
  return seconds;
 
213
}
 
214
 
 
215
 
 
216
PRBool imgCache::Get(nsIURI *aKey, PRBool *aHasExpired, imgRequest **aRequest, nsICacheEntryDescriptor **aEntry)
 
217
{
 
218
  LOG_STATIC_FUNC(gImgLog, "imgCache::Get");
 
219
 
 
220
  nsresult rv;
 
221
 
 
222
  nsCOMPtr<nsICacheSession> ses;
 
223
  GetCacheSession(aKey, getter_AddRefs(ses));
 
224
  if (!ses) return PR_FALSE;
 
225
 
 
226
  nsCAutoString spec;
 
227
  aKey->GetAsciiSpec(spec);
 
228
 
 
229
  nsCOMPtr<nsICacheEntryDescriptor> entry;
 
230
 
 
231
  rv = ses->OpenCacheEntry(spec.get(), nsICache::ACCESS_READ, nsICache::BLOCKING, getter_AddRefs(entry));
 
232
 
 
233
  if (NS_FAILED(rv) || !entry)
 
234
    return PR_FALSE;
 
235
 
 
236
  if (aHasExpired) {
 
237
    PRUint32 expirationTime;
 
238
    rv = entry->GetExpirationTime(&expirationTime);
 
239
    if (NS_FAILED(rv) || (expirationTime <= SecondsFromPRTime(PR_Now()))) {
 
240
      *aHasExpired = PR_TRUE;
 
241
    } else {
 
242
      *aHasExpired = PR_FALSE;
 
243
    }
 
244
    // Special treatment for file URLs - entry has expired if file has changed
 
245
    nsCOMPtr<nsIFileURL> fileUrl(do_QueryInterface(aKey));
 
246
    if (fileUrl) {
 
247
      PRUint32 lastModTime;
 
248
      entry->GetLastModified(&lastModTime);
 
249
 
 
250
      nsCOMPtr<nsIFile> theFile;
 
251
      rv = fileUrl->GetFile(getter_AddRefs(theFile));
 
252
      if (NS_SUCCEEDED(rv)) {
 
253
        PRInt64 fileLastMod;
 
254
        rv = theFile->GetLastModifiedTime(&fileLastMod);
 
255
        if (NS_SUCCEEDED(rv)) {
 
256
          // nsIFile uses millisec, NSPR usec
 
257
          PRInt64 one_thousand = LL_INIT(0, 1000);
 
258
          LL_MUL(fileLastMod, fileLastMod, one_thousand);
 
259
          *aHasExpired = SecondsFromPRTime((PRTime)fileLastMod) > lastModTime;
 
260
        }
 
261
      }
 
262
    }
 
263
  }
 
264
 
 
265
  nsCOMPtr<nsISupports> sup;
 
266
  entry->GetCacheElement(getter_AddRefs(sup));
 
267
 
 
268
  *aRequest = NS_REINTERPRET_CAST(imgRequest*, sup.get());
 
269
  NS_IF_ADDREF(*aRequest);
 
270
 
 
271
  *aEntry = entry;
 
272
  NS_ADDREF(*aEntry);
 
273
 
 
274
  return PR_TRUE;
 
275
}
 
276
 
 
277
 
 
278
PRBool imgCache::Remove(nsIURI *aKey)
 
279
{
 
280
  LOG_STATIC_FUNC(gImgLog, "imgCache::Remove");
 
281
  if (!aKey) return PR_FALSE;
 
282
 
 
283
  nsresult rv;
 
284
  nsCOMPtr<nsICacheSession> ses;
 
285
  GetCacheSession(aKey, getter_AddRefs(ses));
 
286
  if (!ses) return PR_FALSE;
 
287
 
 
288
  nsCAutoString spec;
 
289
  aKey->GetAsciiSpec(spec);
 
290
 
 
291
  nsCOMPtr<nsICacheEntryDescriptor> entry;
 
292
 
 
293
  rv = ses->OpenCacheEntry(spec.get(), nsICache::ACCESS_READ, nsICache::BLOCKING, getter_AddRefs(entry));
 
294
 
 
295
  if (NS_FAILED(rv) || !entry)
 
296
    return PR_FALSE;
 
297
 
 
298
  entry->Doom();
 
299
 
 
300
  return PR_TRUE;
 
301
}
 
302
 
 
303
 
 
304
NS_IMETHODIMP
 
305
imgCache::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* aSomeData)
 
306
{
 
307
  if (strcmp(aTopic, "memory-pressure") == 0 ||
 
308
      strcmp(aTopic, "chrome-flush-skin-caches") == 0 ||
 
309
      strcmp(aTopic, "chrome-flush-caches") == 0)
 
310
    ClearCache(PR_TRUE);
 
311
 
 
312
  return NS_OK;
 
313
}