# Global Metrics

path: .metrics.nargs.average
old: 1.2857142857142858
new: 1.125
path: .metrics.nexits.average
old: 1.0
new: 1.625
path: .metrics.nexits.sum
old: 7.0
new: 13.0
path: .metrics.nom.total
old: 7.0
new: 8.0
path: .metrics.nom.functions
old: 7.0
new: 8.0
path: .metrics.loc.cloc
old: 4.0
new: 32.0
path: .metrics.loc.blank
old: 16.0
new: 44.0
path: .metrics.loc.ploc
old: 67.0
new: 144.0
path: .metrics.loc.sloc
old: 87.0
new: 220.0
path: .metrics.loc.lloc
old: 31.0
new: 68.0
path: .metrics.cognitive.average
old: 1.0
new: 2.75
path: .metrics.cognitive.sum
old: 7.0
new: 22.0
path: .metrics.cyclomatic.average
old: 1.625
new: 2.636363636363636
path: .metrics.cyclomatic.sum
old: 13.0
new: 29.0
path: .metrics.halstead.time
old: 2067.978116302355
new: 4891.340962546153
path: .metrics.halstead.volume
old: 1974.092408330412
new: 3963.891896920519
path: .metrics.halstead.n1
old: 19.0
new: 20.0
path: .metrics.halstead.N2
old: 131.0
new: 231.0
path: .metrics.halstead.N1
old: 177.0
new: 339.0
path: .metrics.halstead.n2
old: 66.0
new: 104.0
path: .metrics.halstead.difficulty
old: 18.85606060606061
new: 22.21153846153846
path: .metrics.halstead.vocabulary
old: 85.0
new: 124.0
path: .metrics.halstead.effort
old: 37223.60609344239
new: 88044.13732583074
path: .metrics.halstead.level
old: 0.05303334672559261
new: 0.045021645021645025
path: .metrics.halstead.purity_ratio
old: 1.55727478776976
new: 1.3741829694463523
path: .metrics.halstead.bugs
old: 0.3716131221703835
new: 0.6596988195322527
path: .metrics.halstead.estimated_program_length
old: 479.6406346330861
new: 783.2842925844208
path: .metrics.halstead.length
old: 308.0
new: 570.0
path: .metrics.mi.mi_visual_studio
old: 32.86865234697531
new: 19.807794915194183
path: .metrics.mi.mi_original
old: 56.20539551332779
new: 33.871329304982055
path: .metrics.mi.mi_sei
old: 23.015373736850904
new: 3.9708285663079823

# Spaces Data

## Minimal test - lines (37, 220)

path: .spaces[0].metrics.cyclomatic.average
old: 1.0
new: 2.8
path: .spaces[0].metrics.cyclomatic.sum
old: 1.0
new: 28.0
path: .spaces[0].metrics.halstead.volume
old: 57.3594000115385
new: 3744.278250365938
path: .spaces[0].metrics.halstead.difficulty
old: 3.5
new: 23.333333333333332
path: .spaces[0].metrics.halstead.effort
old: 200.75790004038475
new: 87366.49250853855
path: .spaces[0].metrics.halstead.length
old: 16.0
new: 549.0
path: .spaces[0].metrics.halstead.n2
old: 6.0
new: 93.0
path: .spaces[0].metrics.halstead.time
old: 11.153216668910265
new: 4853.694028252142
path: .spaces[0].metrics.halstead.purity_ratio
old: 1.938721875540867
new: 1.2651736454112823
path: .spaces[0].metrics.halstead.bugs
old: 0.011428621282029669
new: 0.656309482292443
path: .spaces[0].metrics.halstead.N2
old: 7.0
new: 217.0
path: .spaces[0].metrics.halstead.estimated_program_length
old: 31.019550008653873
new: 694.5803313307941
path: .spaces[0].metrics.halstead.n1
old: 6.0
new: 20.0
path: .spaces[0].metrics.halstead.N1
old: 9.0
new: 332.0
path: .spaces[0].metrics.halstead.level
old: 0.2857142857142857
new: 0.04285714285714286
path: .spaces[0].metrics.halstead.vocabulary
old: 12.0
new: 113.0
path: .spaces[0].metrics.nargs.average
old: 1.0
new: 1.125
path: .spaces[0].metrics.nargs.sum
old: 1.0
new: 9.0
path: .spaces[0].metrics.mi.mi_original
old: 138.4844646467577
new: 37.292523126745834
path: .spaces[0].metrics.mi.mi_sei
old: 124.191818253432
new: 4.242074460347954
path: .spaces[0].metrics.mi.mi_visual_studio
old: 80.98506704488753
new: 21.808493056576513
path: .spaces[0].metrics.nom.total
old: 1.0
new: 8.0
path: .spaces[0].metrics.nom.functions
old: 1.0
new: 8.0
path: .spaces[0].metrics.nexits.average
old: 0.0
new: 1.625
path: .spaces[0].metrics.nexits.sum
old: 0.0
new: 13.0
path: .spaces[0].metrics.cognitive.average
old: 0.0
new: 2.75
path: .spaces[0].metrics.cognitive.sum
old: 0.0
new: 22.0
path: .spaces[0].metrics.loc.sloc
old: 2.0
new: 184.0
path: .spaces[0].metrics.loc.blank
old: 0.0
new: 38.0
path: .spaces[0].metrics.loc.cloc
old: 0.0
new: 18.0
path: .spaces[0].metrics.loc.lloc
old: 0.0
new: 68.0
path: .spaces[0].metrics.loc.ploc
old: 2.0
new: 128.0

### Code

    namespace mozilla {
    namespace docshell {

    //-----------------------------------------------------------------------------
    // OfflineCacheUpdateGlue::nsISupports
    //-----------------------------------------------------------------------------

    NS_IMPL_ISUPPORTS(OfflineCacheUpdateGlue, nsIOfflineCacheUpdate,
                      nsIOfflineCacheUpdateObserver, nsISupportsWeakReference)

    //-----------------------------------------------------------------------------
    // OfflineCacheUpdateGlue
    //-----------------------------------------------------------------------------

    OfflineCacheUpdateGlue::OfflineCacheUpdateGlue() : mCoalesced(false) {
      LOG(("OfflineCacheUpdateGlue::OfflineCacheUpdateGlue [%p]", this));
    }

    OfflineCacheUpdateGlue::~OfflineCacheUpdateGlue() {
      LOG(("OfflineCacheUpdateGlue::~OfflineCacheUpdateGlue [%p]", this));
    }

    nsIOfflineCacheUpdate* OfflineCacheUpdateGlue::EnsureUpdate() {
      if (!mUpdate) {
        mUpdate = new nsOfflineCacheUpdate();
        LOG(("OfflineCacheUpdateGlue [%p] is using update [%p]", this,
             mUpdate.get()));

        mUpdate->SetCookieJarSettings(mCookieJarSettings);
      }

      return mUpdate;
    }

    NS_IMETHODIMP
    OfflineCacheUpdateGlue::Schedule() {
      nsCOMPtr observerService =
          mozilla::services::GetObserverService();
      if (observerService) {
        LOG(("Calling offline-cache-update-added"));
        observerService->NotifyObservers(static_cast(this),
                                         "offline-cache-update-added", nullptr);
        LOG(("Done offline-cache-update-added"));
      }

      if (!EnsureUpdate()) return NS_ERROR_NULL_POINTER;

      // Do not use weak reference, we must survive!
      mUpdate->AddObserver(this, false);

      if (mCoalesced)  // already scheduled
        return NS_OK;

      return mUpdate->Schedule();
    }

    NS_IMETHODIMP
    OfflineCacheUpdateGlue::Init(nsIURI* aManifestURI, nsIURI* aDocumentURI,
                                 nsIPrincipal* aLoadingPrincipal,
                                 Document* aDocument, nsIFile* aCustomProfileDir) {
      nsresult rv;

      nsAutoCString originSuffix;
      rv = aLoadingPrincipal->GetOriginSuffix(originSuffix);
      NS_ENSURE_SUCCESS(rv, rv);

      nsOfflineCacheUpdateService* service =
          nsOfflineCacheUpdateService::EnsureService();
      if (service) {
        service->FindUpdate(aManifestURI, originSuffix, aCustomProfileDir,
                            getter_AddRefs(mUpdate));
        mCoalesced = !!mUpdate;
      }

      if (!EnsureUpdate()) return NS_ERROR_NULL_POINTER;

      mDocumentURI = aDocumentURI;
      mLoadingPrincipal = aLoadingPrincipal;

      if (aDocument) SetDocument(aDocument);

      if (mCoalesced) {  // already initialized
        LOG(("OfflineCacheUpdateGlue %p coalesced with update %p", this,
             mUpdate.get()));
        return NS_OK;
      }

      rv = mUpdate->Init(aManifestURI, aDocumentURI, aLoadingPrincipal, nullptr,
                         aCustomProfileDir);

      mUpdate->SetCookieJarSettings(mCookieJarSettings);

      return rv;
    }

    void OfflineCacheUpdateGlue::SetDocument(Document* aDocument) {
      // The design is one document for one cache update on the content process.
      NS_ASSERTION(!mDocument,
                   "Setting more then a single document on an instance of "
                   "OfflineCacheUpdateGlue");

      LOG(("Document %p added to update glue %p", aDocument, this));

      // Add document only if it was not loaded from an offline cache.
      // If it were loaded from an offline cache then it has already
      // been associated with it and must not be again cached as
      // implicit (which are the reasons we collect documents here).
      if (!aDocument) return;

      mCookieJarSettings = aDocument->CookieJarSettings();

      nsIChannel* channel = aDocument->GetChannel();
      nsCOMPtr appCacheChannel =
          do_QueryInterface(channel);
      if (!appCacheChannel) return;

      bool loadedFromAppCache;
      appCacheChannel->GetLoadedFromApplicationCache(&loadedFromAppCache);
      if (loadedFromAppCache) return;

      if (EnsureUpdate()) {
        mUpdate->StickDocument(mDocumentURI);
      }

      mDocument = aDocument;
    }

    NS_IMETHODIMP
    OfflineCacheUpdateGlue::UpdateStateChanged(nsIOfflineCacheUpdate* aUpdate,
                                               uint32_t state) {
      if (state == nsIOfflineCacheUpdateObserver::STATE_FINISHED) {
        LOG(("OfflineCacheUpdateGlue got STATE_FINISHED [%p]", this));

        nsCOMPtr observerService =
            mozilla::services::GetObserverService();
        if (observerService) {
          LOG(("Calling offline-cache-update-completed"));
          observerService->NotifyObservers(
              static_cast(this),
              "offline-cache-update-completed", nullptr);
          LOG(("Done offline-cache-update-completed"));
        }

        aUpdate->RemoveObserver(this);
      }

      return NS_OK;
    }

    NS_IMETHODIMP
    OfflineCacheUpdateGlue::ApplicationCacheAvailable(
        nsIApplicationCache* aApplicationCache) {
      NS_ENSURE_ARG(aApplicationCache);

      // Check that the document that requested this update was
      // previously associated with an application cache.  If not, it
      // should be associated with the new one.
      if (!mDocument) {
        return NS_OK;
      }

      nsCOMPtr existingCache;
      nsresult rv = mDocument->GetApplicationCache(getter_AddRefs(existingCache));
      NS_ENSURE_SUCCESS(rv, rv);

      if (!existingCache) {
        if (LOG_ENABLED()) {
          nsAutoCString clientID;
          if (aApplicationCache) {
            aApplicationCache->GetClientID(clientID);
          }
          LOG(("Update %p: associating app cache %s to document %p", this,
               clientID.get(), mDocument.get()));
        }

        rv = mDocument->SetApplicationCache(aApplicationCache);
        NS_ENSURE_SUCCESS(rv, rv);
      }

      return NS_OK;
    }

    }  // namespace docshell
    }  // namespace mozilla