// BEGIN FLOCK GPL // // Copyright Flock Inc. 2005-2007 // http://flock.com // // This file may be used under the terms of of the // GNU General Public License Version 2 or later (the "GPL"), // http://www.gnu.org/licenses/gpl.html // // Software distributed under the License is distributed on an "AS IS" basis, // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License // for the specific language governing rights and limitations under the // License. // // END FLOCK GPL const CC = Components.classes; const CI = Components.interfaces; const CR = Components.results; var EXPORTED_SYMBOLS = ["FlockSvcUtils"]; /****************************************************************************** * Flock Service Utilities ******************************************************************************/ var FlockSvcUtils = { // Interfaces for which we can add default implementations. flockIWebService: {}, flockIManageableWebService: {}, flockIWebServiceAccount: {}, flockISocialWebServiceAccount: {}, flockIRichContentDropHandler: {} }; /****************************************************************************** * Utility Functions ******************************************************************************/ // Get the Logger. // This adds the "_logger" property to the service. FlockSvcUtils.getLogger = function FlockSvcUtils_getLogger(aComponent) { if (!aComponent._logger) { aComponent._logger = CC["@flock.com/logger;1"] .createInstance(CI.flockILogger); if (aComponent.shortName) { // No shortName? Caller must call init. aComponent._logger.init(aComponent.shortName); } } return aComponent._logger; }; // Get Account Utilities. // This adds the "_acUtils" property to the service. FlockSvcUtils.getACUtils = function FlockSvcUtils_getACUtils(aComponent) { if (!aComponent._acUtils) { aComponent._acUtils = CC["@flock.com/account-utils;1"] .getService(CI.flockIAccountUtils); } return aComponent._acUtils; }; // Get Web Detective. // This adds the "_WebDetective" property to the service. // As a side effect, also adds the "_acUtils" property. FlockSvcUtils.getWD = function FlockSvcUtils_getWD(aComponent) { if (!aComponent._WebDetective) { if (aComponent.shortName) { aComponent._WebDetective = this.getACUtils(aComponent) .useWebDetective(aComponent.shortName + ".xml"); } else { // aComponent is not a Flock service. throw CR.NS_ERROR_INVALID_ARG; } } return aComponent._WebDetective; }; // Get Coop. // This adds the "_coop" property to the service. FlockSvcUtils.getCoop = function FlockSvcUtils_getCoop(aComponent) { if (!aComponent._coop) { aComponent._coop = CC["@flock.com/singleton;1"] .getService(CI.flockISingleton) .getSingleton("chrome://flock/content/common/load-faves-coop.js") .wrappedJSObject; } return aComponent._coop; }; // Helper to create a "results" object commonly returned from services. FlockSvcUtils.newResults = function FlockSvcUtils_newResults() { return CC["@mozilla.org/hash-property-bag;1"] .createInstance(CI.nsIWritablePropertyBag2); }; /****************************************************************************** * flockIWebService Default Method Implementations ******************************************************************************/ FlockSvcUtils.flockIWebService.addDefaultMethod = function addDefaultMethod(aComponent, aMethod) { var svc = aComponent; var proto = aComponent.__proto__; switch (aMethod) { case "getAccount": // flockIWebServiceAccount getAccount(in AString aUrn); // NOTE: This requires an account constructor to be in a private // property on the service, named "_accountClassCtor". if (!proto.getAccount) { proto.getAccount = function defaultImpl_getAccount(aUrn) { svc._logger.debug("{flockIWebService}.getAccount('" + aUrn + "')"); var c_acct = FlockSvcUtils.getCoop(svc).get(aUrn); // This is the constructor for the service account class. var acct = new svc._accountClassCtor(); acct.urn = c_acct.id(); acct.username = c_acct.name; return acct; }; } break; case "getAccounts": // nsISimpleEnumerator getAccounts(); if (!proto.getAccounts) { proto.getAccounts = function defaultImpl_getAccounts() { svc._logger.debug("{flockIWebService}.getAccounts()"); return FlockSvcUtils.getACUtils(svc) .getAccountsForService(svc.contractId); }; } break; case "logout": // void logout(); if (!proto.logout) { proto.logout = function defaultImpl_logout() { svc._logger.debug("{flockIWebService}.logout()"); var cookies = FlockSvcUtils.getWD(svc) .getSessionCookies(svc.shortName); if (cookies) { FlockSvcUtils.getACUtils(svc).removeCookies(cookies); } }; } break; default: throw Components.results.NS_ERROR_INVALID_ARG; } // switch (aMethod) }; /****************************************************************************** * flockIManageableWebService Default Method Implementations ******************************************************************************/ FlockSvcUtils.flockIManageableWebService.addDefaultMethod = function addDefaultMethod(aComponent, aMethod) { var svc = aComponent; var proto = aComponent.__proto__; switch (aMethod) { case "docRepresentsSuccessfulLogin": // boolean docRepresentsSuccessfulLogin(in nsIDOMHTMLDocument aDocument); if (!proto.docRepresentsSuccessfulLogin) { proto.docRepresentsSuccessfulLogin = function defaultImpl_docRepresentsSuccessfulLogin(aDocument) { svc._logger.debug("{flockIManageableWebService}.docRepresentsSuccessfulLogin()"); return FlockSvcUtils.getWD(svc).detect(svc.shortName, "loggedin", aDocument, null ); }; } break; case "getAccountIDFromDocument": // AString getAccountIDFromDocument(in nsIDOMHTMLDocument aDocument); if (!proto.getAccountIDFromDocument) { proto.getAccountIDFromDocument = function defaultImpl_getAccountIDFromDocument(aDocument) { svc._logger.debug("{flockIManageableWebService}.getAccountIDFromDocument()"); var results = FlockSvcUtils.newResults(); if (FlockSvcUtils.getWD(svc).detect(svc.shortName, "accountinfo", aDocument, results)) { return results.getPropertyAsAString("accountid"); } return null; }; } break; case "getCredentialsFromForm": // nsIPassword getCredentialsFromForm(in nsIDOMHTMLFormElement aForm); if (!proto.getCredentialsFromForm) { proto.getCredentialsFromForm = function defaultImpl_getCredentialsFromForm(aForm) { svc._logger.debug("{flockIManageableWebService}.getCredentialsFromForm()"); aForm.QueryInterface(CI.nsIDOMHTMLFormElement); var wd = FlockSvcUtils.getWD(svc); var formType = "login"; var results = FlockSvcUtils.newResults(); if (!wd.detectForm(svc.shortName, formType, aForm, results)) { formType = "signup"; results = FlockSvcUtils.newResults(); if (!wd.detectForm(svc.shortName, formType, aForm, results)) { formType = "changepassword"; results = FlockSvcUtils.newResults(); if (!wd.detectForm(svc.shortName, formType, aForm, results)) { results = null; } } } if (results) { return { QueryInterface: function(aIID) { // FIXME: See https://bugzilla.flock.com/show_bug.cgi?id=9802 if (!aIID.equals(CI.nsISupports) && !aIID.equals(CI.nsIPassword) && !aIID.equals(CI.flockIPassword)) { throw CR.NS_ERROR_NO_INTERFACE; } return this; }, host: "", user: results.getPropertyAsAString("username"), password: results.getPropertyAsAString("password"), formType: formType }; } return null; }; } break; case "ownsDocument": // boolean ownsDocument(in nsIDOMHTMLDocument aDocument); if (!proto.ownsDocument) { proto.ownsDocument = function defaultImpl_ownsDocument(aDocument) { svc._logger.debug("{flockIManageableWebService}.ownsDocument()"); // Note that ownsDocument() only gets called for documents hosted // in a domain for this service... so if no further tests are // necessary, it's ok to just return 'true' here. return true; }; } break; case "ownsLoginForm": // boolean ownsLoginForm(in nsIDOMHTMLFormElement aForm); if (!proto.ownsLoginForm) { proto.ownsLoginForm = function defaultImpl_ownsLoginForm(aForm) { svc._logger.debug("{flockIManageableWebService}.ownsLoginForm()"); aForm.QueryInterface(CI.nsIDOMHTMLFormElement); var wd = FlockSvcUtils.getWD(svc); if (wd.detectForm(svc.shortName, "login", aForm, FlockSvcUtils.newResults())) { return true; } if (wd.detectForm(svc.shortName, "signup", aForm, FlockSvcUtils.newResults())) { return true; } if (wd.detectForm(svc.shortName, "changepassword", aForm, FlockSvcUtils.newResults())) { return true; } return false; }; } break; default: throw CR.NS_ERROR_INVALID_ARG; } // switch (aMethod) }; /****************************************************************************** * flockIWebServiceAccount Default Method Implementations ******************************************************************************/ FlockSvcUtils.flockIWebServiceAccount.addDefaultMethod = function addDefaultMethod(aComponent, aMethod) { var svc = aComponent; var proto = aComponent.__proto__; switch (aMethod) { case "deactivate": // void deactivate(in flockIListener aListener); if (!proto.deactivate) { proto.deactivate = function defaultImpl_deactivate(aListener) { svc._logger.debug("{flockIWebServiceAccount}.deactivate()"); var c_acct = FlockSvcUtils.getCoop(svc).get(this.urn); c_acct.isPollable = false; if (aListener) { aListener.onSuccess(this, "deactivate"); } }; } break; case "login": // void login(in flockIListener aListener); if (!proto.login) { proto.login = function defaultImpl_login(aListener) { svc._logger.debug("{flockIWebServiceAccount}.login()"); if (aListener) { aListener.onError(this, "login", null); } }; } break; case "logout": // void logout(in flockIListener aListener); if (!proto.logout) { proto.logout = function defaultImpl_logout(aListener) { svc._logger.debug("{flockIWebServiceAccount}.logout()"); var c_acct = FlockSvcUtils.getCoop(svc).get(this.urn); if (c_acct.isAuthenticated) { c_acct.isAuthenticated = false; CC[c_acct.serviceId].getService(CI.flockIWebService).logout(); } if (aListener) { aListener.onSuccess(this, "logout"); } }; } break; case "remove": // void remove(); if (!proto.remove) { proto.remove = function defaultImpl_remove() { svc._logger.debug("{flockIWebServiceAccount}.remove()"); var c_acct = FlockSvcUtils.getCoop(svc).get(this.urn); CC[c_acct.serviceId].getService(CI.flockIWebService) .removeAccount(this.urn); }; } break; default: throw CR.NS_ERROR_INVALID_ARG; } // switch (aMethod) }; /****************************************************************************** * flockISocialWebServiceAccount Default Method Implementations ******************************************************************************/ FlockSvcUtils.flockISocialWebServiceAccount.addDefaultMethod = function addDefaultMethod(aComponent, aMethod) { var svc = aComponent; var proto = aComponent.__proto__; switch (aMethod) { case "getFriendCount": // void deactivate(in flockIListener aListener); if (!proto.getFriendCount) { proto.getFriendCount = function getFriendCount() { var count = 0; var c_acct = FlockSvcUtils.getCoop(svc).get(this.urn); var c_friendslist = c_acct.friendsList; if (c_friendslist) { var friends = c_friendslist.children.enumerate(); while (friends.hasMoreElements()) { count++; friends.getNext(); } } return count; }; } break; default: throw CR.NS_ERROR_INVALID_ARG; } // switch (aMethod) }; /****************************************************************************** * flockIRichContentDropHandler Default Method Implementations ******************************************************************************/ FlockSvcUtils.flockIRichContentDropHandler.addDefaultMethod = function addDefaultMethod(aComponent, aMethod) { var svc = aComponent; var proto = aComponent.__proto__; switch (aMethod) { case "_handleTextareaDrop": if (!proto._handleTextareaDrop) { proto._handleTextareaDrop = function handleTextareaDrop(aSvcName, aDomains, aTextarea, aCallback) { const WD_XPATH = 0; const WD_FLAVOUR = 1; if (aTextarea instanceof CI.nsIDOMHTMLTextAreaElement) { var doc = aTextarea.ownerDocument; if (doc instanceof CI.nsIDOMHTMLDocument) { var wd = FlockSvcUtils.getWD(this); var domainsArray = aDomains.split(","); for each (var domain in domainsArray) { if (wd.testDomain(doc.URL, domain)) { // Retrieve the specific fields from Web Detective to which // we cannot DnD var fields = wd.getString(aSvcName, "avoidDnDXPathFields", null); if (fields) { fields = fields.split(";"); for each (var avoidDnD in fields) { var xPath = wd.getString(aSvcName, avoidDnD, null); if (xPath) { var results = doc.evaluate(xPath, doc, null, CI.nsIDOMXPathResult.ANY_TYPE, null); if (results && results.iterateNext() == aTextarea) { // The matching field does not accept rich content, bail return true; } } } } // Retrieve the specific fields from Web Detective to which // we can DnD var pairs = []; fields = wd.getString(aSvcName, "dndXPathFields", null); if (fields) { fields = fields.split(";"); for each (var xpfFields in fields) { pairs.push(xpfFields); } } // Go through the list of DnD fields to find a match for each (var xpfPair in pairs) { var xpf = xpfPair.split(","); var xPath = wd.getString(aSvcName, xpf[WD_XPATH], null); if (xPath) { var results = doc.evaluate(xPath, doc, null, CI.nsIDOMXPathResult.ANY_TYPE, null); if (results && results.iterateNext() == aTextarea) { // Let the service perform the drop via the callback aCallback(xpf[WD_FLAVOUR]); return true; } } } } } } } return false; } } break; default: throw CR.NS_ERROR_INVALID_ARG; } // switch (aMethod) };