Bug 1005640 - Flush StringBundle cache when app-locales change. r=valentin draft
authorZibi Braniecki <gandalf@mozilla.com>
Tue, 18 Apr 2017 01:03:05 -0700
changeset 564893 75ecc4204deca066d7492d1494492a91685f36be
parent 564445 722fdbff1efc308a22060e75b603311d23541bb5
child 624861 685feb70288d5f6f2dbee5a239433614b43eb4ea
push id54726
push userzbraniecki@mozilla.com
push dateWed, 19 Apr 2017 05:47:47 +0000
reviewersvalentin
bugs1005640
milestone55.0a1
Bug 1005640 - Flush StringBundle cache when app-locales change. r=valentin StringBundle caches bundles, so when language chain changes we should flush the cache to enable new strings to be loaded. This also affects localized prefs like intl.accept_languages. Then in HttpHandler we have to mark the value as dirty so that next time it's called it actually recalculates using flushed string bundle with the new locale. MozReview-Commit-ID: DKWEDUli4yH
intl/strres/nsStringBundle.cpp
netwerk/protocol/http/nsHttpHandler.cpp
netwerk/protocol/http/nsHttpHandler.h
--- a/intl/strres/nsStringBundle.cpp
+++ b/intl/strres/nsStringBundle.cpp
@@ -524,16 +524,17 @@ nsresult
 nsStringBundleService::Init()
 {
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   if (os) {
     os->AddObserver(this, "memory-pressure", true);
     os->AddObserver(this, "profile-do-change", true);
     os->AddObserver(this, "chrome-flush-caches", true);
     os->AddObserver(this, "xpcom-category-entry-added", true);
+    os->AddObserver(this, "intl:app-locales-changed", true);
   }
 
   // instantiate the override service, if there is any.
   // at some point we probably want to make this a category, and
   // support multiple overrides
   mOverrideStrings = do_GetService(NS_STRINGBUNDLETEXTOVERRIDE_CONTRACTID);
 
   return NS_OK;
@@ -541,17 +542,18 @@ nsStringBundleService::Init()
 
 NS_IMETHODIMP
 nsStringBundleService::Observe(nsISupports* aSubject,
                                const char* aTopic,
                                const char16_t* aSomeData)
 {
   if (strcmp("memory-pressure", aTopic) == 0 ||
       strcmp("profile-do-change", aTopic) == 0 ||
-      strcmp("chrome-flush-caches", aTopic) == 0)
+      strcmp("chrome-flush-caches", aTopic) == 0 ||
+      strcmp("intl:app-locales-changed", aTopic) == 0)
   {
     flushBundleCache();
   }
   else if (strcmp("xpcom-category-entry-added", aTopic) == 0 &&
            NS_LITERAL_STRING("xpcom-autoregistration").Equals(aSomeData))
   {
     mOverrideStrings = do_GetService(NS_STRINGBUNDLETEXTOVERRIDE_CONTRACTID);
   }
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -192,16 +192,17 @@ nsHttpHandler::nsHttpHandler()
     , mEnforceAssocReq(false)
     , mLastUniqueID(NowInSeconds())
     , mSessionStartTime(0)
     , mLegacyAppName("Mozilla")
     , mLegacyAppVersion("5.0")
     , mProduct("Gecko")
     , mCompatFirefoxEnabled(false)
     , mUserAgentIsDirty(true)
+    , mAcceptLanguagesIsDirty(true)
     , mPromptTempRedirect(true)
     , mEnablePersistentHttpsCaching(false)
     , mDoNotTrackEnabled(false)
     , mSafeHintEnabled(false)
     , mParentalControlEnabled(false)
     , mHandlerActive(false)
     , mTelemetryEnabled(false)
     , mAllowExperiments(true)
@@ -469,18 +470,23 @@ nsHttpHandler::AddStandardRequestHeaders
     // service worker expects to see it.  The other "default" headers are
     // hidden from service worker interception.
     rv = request->SetHeader(nsHttp::Accept, mAccept,
                             false, nsHttpHeaderArray::eVarietyRequestOverride);
     if (NS_FAILED(rv)) return rv;
 
     // Add the "Accept-Language" header.  This header is also exposed to the
     // service worker.
+    if (mAcceptLanguagesIsDirty) {
+        rv = SetAcceptLanguages();
+        MOZ_ASSERT(NS_SUCCEEDED(rv));
+    }
+
+    // Add the "Accept-Language" header
     if (!mAcceptLanguages.IsEmpty()) {
-        // Add the "Accept-Language" header
         rv = request->SetHeader(nsHttp::Accept_Language, mAcceptLanguages,
                                 false,
                                 nsHttpHeaderArray::eVarietyRequestOverride);
         if (NS_FAILED(rv)) return rv;
     }
 
     // Add the "Accept-Encoding" header
     if (isSecure) {
@@ -1476,28 +1482,20 @@ nsHttpHandler::PrefsChanged(nsIPrefBranc
         }
     }
 
     //
     // INTL options
     //
 
     if (PREF_CHANGED(INTL_ACCEPT_LANGUAGES)) {
-        nsCOMPtr<nsIPrefLocalizedString> pls;
-        prefs->GetComplexValue(INTL_ACCEPT_LANGUAGES,
-                                NS_GET_IID(nsIPrefLocalizedString),
-                                getter_AddRefs(pls));
-        if (pls) {
-            nsXPIDLString uval;
-            pls->ToString(getter_Copies(uval));
-            if (uval) {
-                rv = SetAcceptLanguages(NS_ConvertUTF16toUTF8(uval).get());
-                MOZ_ASSERT(NS_SUCCEEDED(rv));
-            }
-        }
+        // We don't want to set the new accept languages here since
+        // this pref is a complex type and it may be racy with flushing
+        // string resources.
+        mAcceptLanguagesIsDirty = true;
     }
 
     //
     // Tracking options
     //
 
     if (PREF_CHANGED(DONOTTRACK_HEADER_ENABLED)) {
         cVar = false;
@@ -1809,22 +1807,28 @@ PrepareAcceptLanguages(const char *i_Acc
 
     o_AcceptLanguages.Assign((const char *) q_Accept);
     delete [] q_Accept;
 
     return NS_OK;
 }
 
 nsresult
-nsHttpHandler::SetAcceptLanguages(const char *aAcceptLanguages)
+nsHttpHandler::SetAcceptLanguages()
 {
+    mAcceptLanguagesIsDirty = false;
+
+    const nsAdoptingCString& acceptLanguages =
+        Preferences::GetLocalizedCString(INTL_ACCEPT_LANGUAGES);
+
     nsAutoCString buf;
-    nsresult rv = PrepareAcceptLanguages(aAcceptLanguages, buf);
-    if (NS_SUCCEEDED(rv))
+    nsresult rv = PrepareAcceptLanguages(acceptLanguages.get(), buf);
+    if (NS_SUCCEEDED(rv)) {
         mAcceptLanguages.Assign(buf);
+    }
     return rv;
 }
 
 nsresult
 nsHttpHandler::SetAccept(const char *aAccept)
 {
     mAccept = aAccept;
     return NS_OK;
--- a/netwerk/protocol/http/nsHttpHandler.h
+++ b/netwerk/protocol/http/nsHttpHandler.h
@@ -375,17 +375,17 @@ private:
     //
     // Useragent/prefs helper methods
     //
     void     BuildUserAgent();
     void     InitUserAgentComponents();
     void     PrefsChanged(nsIPrefBranch *prefs, const char *pref);
 
     MOZ_MUST_USE nsresult SetAccept(const char *);
-    MOZ_MUST_USE nsresult SetAcceptLanguages(const char *);
+    MOZ_MUST_USE nsresult SetAcceptLanguages();
     MOZ_MUST_USE nsresult SetAcceptEncodings(const char *, bool mIsSecure);
 
     MOZ_MUST_USE nsresult InitConnectionMgr();
 
     void     NotifyObservers(nsIHttpChannel *chan, const char *event);
 
 private:
 
@@ -469,16 +469,17 @@ private:
     nsCString      mCompatFirefox;
     bool           mCompatFirefoxEnabled;
     nsXPIDLCString mCompatDevice;
     nsCString      mDeviceModelId;
 
     nsCString      mUserAgent;
     nsXPIDLCString mUserAgentOverride;
     bool           mUserAgentIsDirty; // true if mUserAgent should be rebuilt
+    bool           mAcceptLanguagesIsDirty;
 
 
     bool           mPromptTempRedirect;
 
     // Persistent HTTPS caching flag
     bool           mEnablePersistentHttpsCaching;
 
     // For broadcasting tracking preference