diff --git a/indra/llmessage/llexperiencecache.cpp b/indra/llmessage/llexperiencecache.cpp
index af0bae0228288663e57691cebeb44e9f6bf28346..0fd68369485d72f949f3611e0d3cf8439fef382c 100644
--- a/indra/llmessage/llexperiencecache.cpp
+++ b/indra/llmessage/llexperiencecache.cpp
@@ -723,6 +723,169 @@ void LLExperienceCache::regionExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapt
 
 }
 
+//-------------------------------------------------------------------------
+void LLExperienceCache::getExperiencePermission(const LLUUID &experienceId, ExperienceGetFn_t fn)
+{
+    if (mCapability.empty())
+    {
+        LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
+        return;
+    }
+
+    std::string url = mCapability("ExperiencePreferences") + "?" + experienceId.asString();
+    
+    permissionInvoker_fn invoker(boost::bind(
+        // Humans ignore next line.  It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
+        static_cast<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
+        //----
+        // _1 -> httpAdapter
+        // _2 -> httpRequest
+        // _3 -> url
+        (&LLCoreHttpUtil::HttpCoroutineAdapter::getAndYield), _1, _2, _3, LLCore::HttpOptions::ptr_t(), LLCore::HttpHeaders::ptr_t()));
+
+
+    LLCoprocedureManager::getInstance()->enqueueCoprocedure("ExpCache", "Preferences Set",
+        boost::bind(&LLExperienceCache::experiencePermissionCoro, this, _1, invoker, url, fn));
+}
+
+void LLExperienceCache::setExperiencePermission(const LLUUID &experienceId, const std::string &permission, ExperienceGetFn_t fn)
+{
+    if (mCapability.empty())
+    {
+        LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
+        return;
+    }
+
+    std::string url = mCapability("ExperiencePreferences");
+    if (url.empty())
+        return;
+    LLSD permData;
+    LLSD data;
+    permData["permission"] = permission;
+    data[experienceId.asString()] = permData;
+
+    permissionInvoker_fn invoker(boost::bind(
+        // Humans ignore next line.  It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
+        static_cast<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &, const LLSD &, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
+        //----
+        // _1 -> httpAdapter
+        // _2 -> httpRequest
+        // _3 -> url
+        (&LLCoreHttpUtil::HttpCoroutineAdapter::putAndYield), _1, _2, _3, data, LLCore::HttpOptions::ptr_t(), LLCore::HttpHeaders::ptr_t()));
+
+
+    LLCoprocedureManager::getInstance()->enqueueCoprocedure("ExpCache", "Preferences Set",
+        boost::bind(&LLExperienceCache::experiencePermissionCoro, this, _1, invoker, url, fn));
+}
+
+void LLExperienceCache::forgetExperiencePermission(const LLUUID &experienceId, ExperienceGetFn_t fn)
+{
+    if (mCapability.empty())
+    {
+        LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
+        return;
+    }
+
+    std::string url = mCapability("ExperiencePreferences") + "?" + experienceId.asString();
+
+
+    permissionInvoker_fn invoker(boost::bind(
+        // Humans ignore next line.  It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
+        static_cast<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
+        //----
+        // _1 -> httpAdapter
+        // _2 -> httpRequest
+        // _3 -> url
+        (&LLCoreHttpUtil::HttpCoroutineAdapter::deleteAndYield), _1, _2, _3, LLCore::HttpOptions::ptr_t(), LLCore::HttpHeaders::ptr_t()));
+
+
+    LLCoprocedureManager::getInstance()->enqueueCoprocedure("ExpCache", "Preferences Set",
+        boost::bind(&LLExperienceCache::experiencePermissionCoro, this, _1, invoker, url, fn));
+}
+
+void LLExperienceCache::experiencePermissionCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, permissionInvoker_fn invokerfn, std::string url, ExperienceGetFn_t fn)
+{
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest());
+
+    // search for experiences owned by the current group
+
+    LLSD result = invokerfn(httpAdapter, httpRequest, url);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+    result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+
+    if (status)
+    {
+        fn(result);
+    }
+}
+
+//-------------------------------------------------------------------------
+void LLExperienceCache::getExperienceAdmin(const LLUUID &experienceId, ExperienceGetFn_t fn)
+{
+    if (mCapability.empty())
+    {
+        LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
+        return;
+    }
+
+    LLCoprocedureManager::getInstance()->enqueueCoprocedure("ExpCache", "IsAdmin",
+        boost::bind(&LLExperienceCache::getExperienceAdminCoro, this, _1, experienceId, fn));
+}
+
+void LLExperienceCache::getExperienceAdminCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, LLUUID experienceId, ExperienceGetFn_t fn)
+{
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest());
+
+    std::string url = mCapability("IsExperienceAdmin");
+    if (url.empty())
+    {
+        LL_WARNS("ExperienceCache") << "No Region Experiences capability" << LL_ENDL;
+        return;
+    }
+    url += "?experience_id=" + experienceId.asString();
+
+    LLSD result = httpAdapter->getAndYield(httpRequest, url);
+//     LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+//     LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    fn(result);
+}
+
+//-------------------------------------------------------------------------
+void LLExperienceCache::updateExperience(LLSD updateData, ExperienceGetFn_t fn)
+{
+    if (mCapability.empty())
+    {
+        LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
+        return;
+    }
+
+    LLCoprocedureManager::getInstance()->enqueueCoprocedure("ExpCache", "IsAdmin",
+        boost::bind(&LLExperienceCache::updateExperienceCoro, this, _1, updateData, fn));
+}
+
+void LLExperienceCache::updateExperienceCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, LLSD updateData, ExperienceGetFn_t fn)
+{
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest());
+
+    std::string url = mCapability("UpdateExperience");
+    if (url.empty())
+    {
+        LL_WARNS("ExperienceCache") << "No Region Experiences capability" << LL_ENDL;
+        return;
+    }
+
+    updateData.erase(LLExperienceCache::QUOTA);
+    updateData.erase(LLExperienceCache::EXPIRES);
+    updateData.erase(LLExperienceCache::AGENT_ID);
+
+    LLSD result = httpAdapter->postAndYield(httpRequest, url, updateData);
+
+    fn(result);
+}
+
 //=========================================================================
 void LLExperienceCacheImpl::mapKeys(const LLSD& legacyKeys)
 {
diff --git a/indra/llmessage/llexperiencecache.h b/indra/llmessage/llexperiencecache.h
index 3e3ae538f9d2ff61043e3c95283519a0a00b3de5..1002b33f801865acf6c7665cc65da017ecee7f78 100644
--- a/indra/llmessage/llexperiencecache.h
+++ b/indra/llmessage/llexperiencecache.h
@@ -72,7 +72,14 @@ class LLExperienceCache: public LLSingleton < LLExperienceCache >
     void getRegionExperiences(CapabilityQuery_t regioncaps, ExperienceGetFn_t fn);
     void setRegionExperiences(CapabilityQuery_t regioncaps, const LLSD &experiences, ExperienceGetFn_t fn);
 
-    //-------------------------------------------
+    void getExperiencePermission(const LLUUID &experienceId, ExperienceGetFn_t fn);
+    void setExperiencePermission(const LLUUID &experienceId, const std::string &permission, ExperienceGetFn_t fn);
+    void forgetExperiencePermission(const LLUUID &experienceId, ExperienceGetFn_t fn);
+
+    void getExperienceAdmin(const LLUUID &experienceId, ExperienceGetFn_t fn);
+
+    void updateExperience(LLSD updateData, ExperienceGetFn_t fn);
+        //-------------------------------------------
     static const std::string NAME;			// "name"
     static const std::string EXPERIENCE_ID;	// "public_id"
     static const std::string AGENT_ID;      // "agent_id"
@@ -101,6 +108,7 @@ class LLExperienceCache: public LLSingleton < LLExperienceCache >
 
     virtual void initSingleton();
 
+    typedef boost::function<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, LLCore::HttpRequest::ptr_t, std::string)> permissionInvoker_fn;
 
     // Callback types for get() 
     typedef boost::signals2::signal < void(const LLSD &) > callback_signal_t;
@@ -145,6 +153,10 @@ class LLExperienceCache: public LLSingleton < LLExperienceCache >
     void findExperienceByNameCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, std::string, int, ExperienceGetFn_t);
     void getGroupExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, LLUUID , ExperienceGetFn_t);
     void regionExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, CapabilityQuery_t regioncaps, bool update, LLSD experiences, ExperienceGetFn_t fn);
+    void experiencePermissionCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, permissionInvoker_fn invokerfn, std::string url, ExperienceGetFn_t fn);
+    void getExperienceAdminCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, LLUUID experienceId, ExperienceGetFn_t fn);
+    void updateExperienceCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, LLSD updateData, ExperienceGetFn_t fn);
+
     void bootstrap(const LLSD& legacyKeys, int initialExpiration);
     void exportFile(std::ostream& ostr) const;
     void importFile(std::istream& istr);
diff --git a/indra/newview/llfloaterexperienceprofile.cpp b/indra/newview/llfloaterexperienceprofile.cpp
index e850be99ab9aa0c5284308dc4195e28ff0ca7ec1..fdf15d2513290bfd17e73f0f3d507ce5f84ec5b8 100644
--- a/indra/newview/llfloaterexperienceprofile.cpp
+++ b/indra/newview/llfloaterexperienceprofile.cpp
@@ -144,145 +144,6 @@ class HandleResponder : public LLHTTPClient::Responder
     }
 };
 
-class ExperienceUpdateResponder : public HandleResponder<LLFloaterExperienceProfile>
-{
-public:
-    ExperienceUpdateResponder(const LLHandle<LLFloaterExperienceProfile>& parent):HandleResponder<LLFloaterExperienceProfile>(parent)
-    {
-    }
-
-    virtual void httpSuccess()
-    {
-        LLFloaterExperienceProfile* parent=mParent.get();
-        if(parent)
-        {
-            parent->onSaveComplete(getContent());
-        }
-    }
-};
-
-
-
-class ExperiencePreferencesResponder : public LLHTTPClient::Responder
-{
-public:
-    ExperiencePreferencesResponder(const LLUUID& single = LLUUID::null):mId(single)
-    {
-    }
-
-    bool sendSingle(const LLSD& content, const LLSD& permission, const char* name)
-    {
-        if(!content.has(name))
-            return false;
-
-        LLEventPump& pump = LLEventPumps::instance().obtain("experience_permission");
-        const LLSD& list = content[name];
-        LLSD::array_const_iterator it = list.beginArray();
-        while(it != list.endArray())
-        {
-            if(it->asUUID() == mId)
-            {
-                LLSD message;
-                message[it->asString()] = permission;
-                message["experience"] = mId;
-                pump.post(message);
-                return true;
-            }
-            ++it;
-        }
-        return false;
-    }
-
-    bool hasPermission(const LLSD& content, const char* name)
-    {
-        if(!content.has(name))
-            return false;
-
-        const LLSD& list = content[name];
-        LLSD::array_const_iterator it = list.beginArray();
-        while(it != list.endArray())
-        {
-            if(it->asUUID() == mId)
-            {
-                return true;
-            }
-            ++it;
-        }
-        return false;
-    }
-
-    const char* getPermission(const LLSD& content)
-    {
-        if(hasPermission(content, "experiences"))
-        {
-            return "Allow";
-        }
-        else if(hasPermission(content, "blocked"))
-        {
-            return "Block";
-        }
-        return "Forget";
-    }
-
-
-    virtual void httpSuccess()
-    {
-        if(mId.notNull())
-        {
-            post(getPermission(getContent()));
-            return;
-        }
-        LLEventPumps::instance().obtain("experience_permission").post(getContent());
-    }
-
-    void post( const char* perm )
-    {
-        LLSD experience;
-        LLSD message;
-        experience["permission"]=perm;
-        message["experience"] = mId;
-        message[mId.asString()] = experience;
-        LLEventPumps::instance().obtain("experience_permission").post(message);
-    }
-
-private:
-    LLUUID mId;
-};
-
-
-class IsAdminResponder : public HandleResponder<LLFloaterExperienceProfile>
-{
-public:
-    IsAdminResponder(const LLHandle<LLFloaterExperienceProfile>& parent):HandleResponder<LLFloaterExperienceProfile>(parent)
-    {
-    }
-    
-    virtual void httpSuccess()
-    {
-        LLFloaterExperienceProfile* parent = mParent.get();
-        if(!parent)
-            return;
-
-        bool enabled = true;
-        LLViewerRegion* region = gAgent.getRegion();
-        if (!region)
-        {
-            enabled = false;
-        }
-        else
-        {
-            std::string url=region->getCapability("UpdateExperience"); 
-            if(url.empty())
-                enabled = false;
-        }
-        if(enabled && getContent()["status"].asBoolean())
-        {
-            parent->getChild<LLLayoutPanel>(PNL_TOP)->setVisible(TRUE);
-            parent->getChild<LLButton>(BTN_EDIT)->setVisible(TRUE);
-        }
-    }
-};
-
 BOOL LLFloaterExperienceProfile::postBuild()
 {
 
@@ -295,11 +156,8 @@ BOOL LLFloaterExperienceProfile::postBuild()
         LLViewerRegion* region = gAgent.getRegion();
         if (region)
         {
-            std::string lookup_url=region->getCapability("IsExperienceAdmin"); 
-            if(!lookup_url.empty())
-            {
-                LLHTTPClient::get(lookup_url+"?experience_id="+mExperienceId.asString(), new IsAdminResponder(getDerivedHandle<LLFloaterExperienceProfile>()));
-            }
+            LLExperienceCache::instance().getExperienceAdmin(mExperienceId, boost::bind(
+                &LLFloaterExperienceProfile::experienceIsAdmin, getDerivedHandle<LLFloaterExperienceProfile>(), _1));
         }
     }
 
@@ -372,23 +230,13 @@ void LLFloaterExperienceProfile::onClickSave()
     doSave(NOTHING);
 }
 
-
 void LLFloaterExperienceProfile::onClickPermission(const char* perm)
 {
     LLViewerRegion* region = gAgent.getRegion();
     if (!region)
         return;
-   
-    std::string lookup_url=region->getCapability("ExperiencePreferences"); 
-    if(lookup_url.empty())
-        return;
-    LLSD permission;
-    LLSD data;
-    permission["permission"]=perm;
-
-    data[mExperienceId.asString()]=permission;
-    LLHTTPClient::put(lookup_url, data, new ExperiencePreferencesResponder(mExperienceId));
-   
+    LLExperienceCache::instance().setExperiencePermission(mExperienceId, perm, boost::bind(
+        &LLFloaterExperienceProfile::experiencePermissionResults, mExperienceId, _1));
 }
 
 
@@ -398,11 +246,8 @@ void LLFloaterExperienceProfile::onClickForget()
     if (!region)
         return;
 
-    std::string lookup_url=region->getCapability("ExperiencePreferences"); 
-    if(lookup_url.empty())
-        return;
-
-    LLHTTPClient::del(lookup_url+"?"+mExperienceId.asString(), new ExperiencePreferencesResponder(mExperienceId));
+    LLExperienceCache::instance().forgetExperiencePermission(mExperienceId, boost::bind(
+        &LLFloaterExperienceProfile::experiencePermissionResults, mExperienceId, _1));
 }
 
 bool LLFloaterExperienceProfile::setMaturityString( U8 maturity, LLTextBox* child, LLComboBox* combo )
@@ -549,11 +394,8 @@ void LLFloaterExperienceProfile::refreshExperience( const LLSD& experience )
         LLViewerRegion* region = gAgent.getRegion();
         if (region)
         {
-            std::string lookup_url=region->getCapability("ExperiencePreferences"); 
-            if(!lookup_url.empty())
-            {
-                LLHTTPClient::get(lookup_url+"?"+mExperienceId.asString(), new ExperiencePreferencesResponder(mExperienceId));
-            }
+            LLExperienceCache::instance().getExperiencePermission(mExperienceId, boost::bind(
+                &LLFloaterExperienceProfile::experiencePermissionResults, mExperienceId, _1));
         }
     }
             
@@ -733,15 +575,9 @@ void LLFloaterExperienceProfile::doSave( int success_action )
     if (!region)
         return;
 
-    std::string url=region->getCapability("UpdateExperience"); 
-    if(url.empty())
-        return;
-
-	mPackage.erase(LLExperienceCache::QUOTA);
-	mPackage.erase(LLExperienceCache::EXPIRES);
-	mPackage.erase(LLExperienceCache::AGENT_ID);
-    
-    LLHTTPClient::post(url, mPackage, new ExperienceUpdateResponder(getDerivedHandle<LLFloaterExperienceProfile>()));
+    LLExperienceCache::instance().updateExperience(mPackage, boost::bind(
+            &LLFloaterExperienceProfile::experienceUpdateResult, 
+            getDerivedHandle<LLFloaterExperienceProfile>(), _1));
 }
 
 void LLFloaterExperienceProfile::onSaveComplete( const LLSD& content )
@@ -1002,3 +838,76 @@ void LLFloaterExperienceProfile::onReportExperience()
 {
 	LLFloaterReporter::showFromExperience(mExperienceId);
 }
+
+/*static*/
+bool LLFloaterExperienceProfile::hasPermission(const LLSD& content, const std::string &name, const LLUUID &test)
+{
+    if (!content.has(name))
+        return false;
+
+    const LLSD& list = content[name];
+    LLSD::array_const_iterator it = list.beginArray();
+    while (it != list.endArray())
+    {
+        if (it->asUUID() == test)
+        {
+            return true;
+        }
+        ++it;
+    }
+    return false;
+}
+
+/*static*/
+void LLFloaterExperienceProfile::experiencePermissionResults(LLUUID exprienceId, LLSD result)
+{
+    std::string permission("Forget");
+    if (hasPermission(result, "experiences", exprienceId))
+        permission = "Allow";
+    else if (hasPermission(result, "blocked", exprienceId))
+        permission = "Block";
+
+    LLSD experience;
+    LLSD message;
+    experience["permission"] = permission;
+    message["experience"] = exprienceId;
+    message[exprienceId.asString()] = experience;
+
+    LLEventPumps::instance().obtain("experience_permission").post(message);
+}
+
+/*static*/
+void LLFloaterExperienceProfile::experienceIsAdmin(LLHandle<LLFloaterExperienceProfile> handle, const LLSD &result)
+{
+    LLFloaterExperienceProfile* parent = handle.get();
+    if (!parent)
+        return;
+
+    bool enabled = true;
+    LLViewerRegion* region = gAgent.getRegion();
+    if (!region)
+    {
+        enabled = false;
+    }
+    else
+    {
+        std::string url = region->getCapability("UpdateExperience");
+        if (url.empty())
+            enabled = false;
+    }
+    if (enabled && result["status"].asBoolean())
+    {
+        parent->getChild<LLLayoutPanel>(PNL_TOP)->setVisible(TRUE);
+        parent->getChild<LLButton>(BTN_EDIT)->setVisible(TRUE);
+    }
+}
+
+/*static*/
+void LLFloaterExperienceProfile::experienceUpdateResult(LLHandle<LLFloaterExperienceProfile> handle, const LLSD &result)
+{
+    LLFloaterExperienceProfile* parent = handle.get();
+    if (parent)
+    {
+        parent->onSaveComplete(result);
+    }
+}
diff --git a/indra/newview/llfloaterexperienceprofile.h b/indra/newview/llfloaterexperienceprofile.h
index 78d54eb447b37383537c4b9ffceddc7920052661..7a5ced546b53d18a9b9ef5c811beadd3641ad528 100644
--- a/indra/newview/llfloaterexperienceprofile.h
+++ b/indra/newview/llfloaterexperienceprofile.h
@@ -99,6 +99,12 @@ class LLFloaterExperienceProfile : public LLFloater
     int mSaveCompleteAction;
     bool mDirty;
     bool mForceClose;
+
+private:
+    static bool hasPermission(const LLSD& content, const std::string &name, const LLUUID &test);
+    static void experiencePermissionResults(LLUUID exprienceId, LLSD result);
+    static void experienceIsAdmin(LLHandle<LLFloaterExperienceProfile> handle, const LLSD &result);
+    static void experienceUpdateResult(LLHandle<LLFloaterExperienceProfile> handle, const LLSD &result);
 };
 
 #endif // LL_LLFLOATEREXPERIENCEPROFILE_H