Bug 1180715 (1/4) - Track image LoadTime to compare with file mtime. review=seth
authorOliver Henshaw <oliver.henshaw@gmail.com>
Tue, 20 Oct 2015 10:45:25 +0530
changeset 291969 38558bb6671b53b51716c9a8d897b9eb1f3668a8
parent 291966 4e79bfe043c8419874fff97657178408eb51ea63
child 291970 7b4f0495cf6d5f40298755b6d8d15434f449fa0c
push idunknown
push userunknown
push dateunknown
bugs1180715
milestone44.0a1
Bug 1180715 (1/4) - Track image LoadTime to compare with file mtime. review=seth mTouchedTime is not appropriate for this as it is updated when an image load re-uses the same imgRequest, especially as it has one second granularity. A timestamp that is updated every time the backing file is re-read should work better. A millisecond granularity timestamp would be preferable, and would be achievable on most or all supported platforms. But some older filesystems have timestamp granularity of a second or worse, notably ext3 and FAT32 (and even ext4 filesytems created with inode_size < 256 bytes, e.g. with 'mke2fs -t small' - see https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Inode_Timestamps for details.)
image/imgLoader.cpp
image/imgLoader.h
image/imgRequest.cpp
--- a/image/imgLoader.cpp
+++ b/image/imgLoader.cpp
@@ -857,16 +857,17 @@ SecondsFromPRTime(PRTime prTime)
 }
 
 imgCacheEntry::imgCacheEntry(imgLoader* loader, imgRequest* request,
                              bool forcePrincipalCheck)
  : mLoader(loader),
    mRequest(request),
    mDataSize(0),
    mTouchedTime(SecondsFromPRTime(PR_Now())),
+   mLoadTime(SecondsFromPRTime(PR_Now())),
    mExpiryTime(0),
    mMustValidate(false),
    // We start off as evicted so we don't try to update the cache. PutIntoCache
    // will set this to false.
    mEvicted(true),
    mHasNoProxies(true),
    mForcePrincipalCheck(forcePrincipalCheck)
 { }
@@ -893,16 +894,21 @@ imgCacheEntry::UpdateCache(int32_t diff 
 {
   // Don't update the cache if we've been removed from it or it doesn't care
   // about our size or usage.
   if (!Evicted() && HasNoProxies()) {
     mLoader->CacheEntriesChanged(mRequest->IsChrome(), diff);
   }
 }
 
+void imgCacheEntry::UpdateLoadTime()
+{
+  mLoadTime = SecondsFromPRTime(PR_Now());
+}
+
 void
 imgCacheEntry::SetHasNoProxies(bool hasNoProxies)
 {
   if (MOZ_LOG_TEST(GetImgLog(), LogLevel::Debug)) {
     if (hasNoProxies) {
       LOG_FUNC_WITH_PARAM(GetImgLog(), "imgCacheEntry::SetHasNoProxies true",
                           "uri", mRequest->CacheKey().Spec());
     } else {
@@ -1705,17 +1711,17 @@ imgLoader::ValidateEntry(imgCacheEntry* 
     hasExpired = false;
   }
 
   nsresult rv;
 
   // Special treatment for file URLs - aEntry has expired if file has changed
   nsCOMPtr<nsIFileURL> fileUrl(do_QueryInterface(aURI));
   if (fileUrl) {
-    uint32_t lastModTime = aEntry->GetTouchedTime();
+    uint32_t lastModTime = aEntry->GetLoadTime();
 
     nsCOMPtr<nsIFile> theFile;
     rv = fileUrl->GetFile(getter_AddRefs(theFile));
     if (NS_SUCCEEDED(rv)) {
       PRTime fileLastMod;
       rv = theFile->GetLastModifiedTime(&fileLastMod);
       if (NS_SUCCEEDED(rv)) {
         // nsIFile uses millisec, NSPR usec
--- a/image/imgLoader.h
+++ b/image/imgLoader.h
@@ -86,16 +86,23 @@ public:
     return mTouchedTime;
   }
   void SetTouchedTime(int32_t time)
   {
     mTouchedTime = time;
     Touch(/* updateTime = */ false);
   }
 
+  uint32_t GetLoadTime() const
+  {
+    return mLoadTime;
+  }
+
+  void UpdateLoadTime();
+
   int32_t GetExpiryTime() const
   {
     return mExpiryTime;
   }
   void SetExpiryTime(int32_t aExpiryTime)
   {
     mExpiryTime = aExpiryTime;
     Touch();
@@ -159,16 +166,17 @@ private: // methods
 private: // data
   nsAutoRefCnt mRefCnt;
   NS_DECL_OWNINGTHREAD
 
   imgLoader* mLoader;
   RefPtr<imgRequest> mRequest;
   uint32_t mDataSize;
   int32_t mTouchedTime;
+  uint32_t mLoadTime;
   int32_t mExpiryTime;
   nsExpirationState mExpirationState;
   bool mMustValidate : 1;
   bool mEvicted : 1;
   bool mHasNoProxies : 1;
   bool mForcePrincipalCheck : 1;
 };
 
--- a/image/imgRequest.cpp
+++ b/image/imgRequest.cpp
@@ -154,16 +154,17 @@ imgRequest::Init(nsIURI *aURI,
   mChannel->GetNotificationCallbacks(getter_AddRefs(mPrevChannelSink));
 
   NS_ASSERTION(mPrevChannelSink != this,
                "Initializing with a channel that already calls back to us!");
 
   mChannel->SetNotificationCallbacks(this);
 
   mCacheEntry = aCacheEntry;
+  mCacheEntry->UpdateLoadTime();
 
   SetLoadId(aCX);
 
   // Grab the inner window ID of the loading document, if possible.
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(aCX);
   if (doc) {
     mInnerWindowId = doc->InnerWindowID();
   }