function isDef(val){return typeof val!="undefined"}
function isNull(val){return val===null}
function isArray(val){return isObject(val)&&val.constructor==Array}
function isString(val){return typeof val=="string"}
function isFunction(val){return typeof val=="function"}
function isObject(val){return val&&typeof val=="object"}
function getObjectProps(obj){var ret=[];for(var p in obj){ret.push(p)}return ret}
function isEmptyObject(val){if(!isObject(val)){return false}for(var p in val){return false}return true}
var getHashCode;var removeHashCode;(function(){var hashCodeProperty="lang_hashCode_";getHashCode=function(obj){if(!obj[hashCodeProperty]){obj[hashCodeProperty]=++getHashCode.hashCodeCounter_}return obj[hashCodeProperty]}
;Function.prototype.mixin=function(props){for(var x in props){this.prototype[x]=props[x]}if(isFunction(props["toString"])&&props["toString"]!=this.prototype["toString"]){this.prototype.toString=props.toString}}
;
function SHA1(){this._chain=new Array(5);this._buf=new Array(64);this._W=new Array(80);this._pad=new Array(64);this._pad[0]=128;for(var i=1;i<64;++i){this._pad[i]=0}this.reset()}
function ARC4(){this._S=new Array(256);this._i=0;this._j=0}
ARC4.prototype.setKey=function(key,opt_length){if(!isArray(key)){throw new Error("Key parameter must be a byte array");}if(!opt_length){opt_length=key.length}var S=this._S;for(var i=0;i<256;++i){S[i]=i}var j=0;for(var i=0;i<256;++i){j=j+S[i]+key[i%opt_length]&255;var tmp=S[i];S[i]=S[j];S[j]=tmp}this._i=0;this._j=0}
;ARC4.prototype.crypt=function(data,opt_length){if(!opt_length){opt_length=data.length}if(!isArray(data)){throw new Error("Data parameter must be a byte array");}var i=this._i;var j=this._j;var S=this._S;for(var n=0;n<opt_length;++n){i=i+1&255;j=j+S[i]&255;var tmp=S[i];S[i]=S[j];S[j]=tmp;data[n]^=S[S[i]+S[j]&255]}this._i=i;this._j=j}
;
function RSAEP(m,dinv,rr){this._M=m;this._DINV=dinv;this._RR=rr;this._LEN=m.length;this._sha1=new SHA1;this._arc4=new ARC4}
function G_SetXOR(list1,list2){var list1Map={};var list2Map={};var output1=[];var output2=[];for(var i=0;i<list1.length;i++){list1Map[list1[i]]=true}for(var i=0;i<list2.length;i++){list2Map[list2[i]]=true}for(var key in list1Map){if(!isDef(list2Map[key])){output1.push(key)}}for(var key in list2Map){if(!isDef(list1Map[key])){output2.push(key)}}return{xor:Array.concat(output1,output2),left:output1,right:output2}}
function G_SetMerge(opt_arg1,opt_arg2,opt_arg3,opt_arg4,opt_arg5,opt_arg6,opt_arg7,opt_arg8,opt_arg9){var resultMap={};for(var i=0;i<arguments.length;i++){var arr=arguments[i];for(var j=0;j<arr.length;j++){resultMap[arr[j]]=true}}var result=[];for(var key in resultMap){result.push(key)}return result}
;
function G_DoubleDictionary(opt_initialValues){this.keysToValues_={};this.valuesToKeys_={};if(opt_initialValues){this.addMultiple(opt_initialValues)}}
G_DoubleDictionary.prototype.addItem=function(key,value){if(this.hasKey(key)){throw new Error("The specified key {%s} already exists".subs(key));}if(this.hasValue(value)){throw new Error("The specified value {%s} already exists.".subs(value));}this.keysToValues_[key]=value;this.valuesToKeys_[value]=key}
;G_DoubleDictionary.prototype.addMultiple=function(obj){for(var p in obj){this.addItem(p,obj[p])}}
function G_WorkQueue(){bindMethods(this);this.maxRunTime=200;this.pauseTime=0;this.queue_=[];this.running_=false;if(G_WorkQueue.global_.G_Alarm){this.scheduleResume_=this.scheduleAlarmResume_}else{this.scheduleResume_=this.scheduleTimeoutResume_}}
function G_Preferences(opt_startPoint,opt_getDefaultBranch){this.debugZone="prefs";this.observers_={};var startPoint=opt_startPoint||null;var prefSvc=Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService);if(opt_getDefaultBranch){this.prefs_=prefSvc.getDefaultBranch(startPoint)}else{this.prefs_=prefSvc.getBranch(startPoint)}this.prefs_.QueryInterface(Ci.nsIPrefBranchInternal)}
G_Preferences.setterMap_={string:"setCharPref","boolean":"setBoolPref",number:"setIntPref"};G_Preferences.getterMap_={};G_Preferences.getterMap_[Ci.nsIPrefBranch.PREF_STRING]="getCharPref";G_Preferences.getterMap_[Ci.nsIPrefBranch.PREF_BOOL]="getBoolPref";G_Preferences.getterMap_[Ci.nsIPrefBranch.PREF_INT]="getIntPref";G_Preferences.prototype.setPref=function(key,val){var datatype=typeof val;if(datatype=="number"&&val%1!=0){throw new Error("Cannot store non-integer numbers in preferences.");}var meth=
G_Preferences.setterMap_[datatype];if(!meth){throw new Error("Pref datatype {"+datatype+"} not supported.");}return this.prefs_[meth](key,val)}
;G_Preferences.prototype.getPref=function(key,opt_default){var type=this.prefs_.getPrefType(key);if(type==Ci.nsIPrefBranch.PREF_INVALID){return opt_default}var meth=G_Preferences.getterMap_[type];if(!meth){throw new Error("Pref datatype {"+type+"} not supported.");}try{return this.prefs_[meth](key)}catch(e){return opt_default}}
;G_Preferences.prototype.removeObserver=function(which,callback){var observer=this.observers_[which].find(callback);G_Assert(this,!(!observer),"Tried to unregister a nonexistant observer");this.prefs_.removeObserver(which,observer);this.observers_[which].erase(callback)}
if(!isDef(true)){throw new Error("G_GDEBUG constant must be set before loading debug.js");}function G_Debug(who,msg){G_GetDebugZone(who).debug(msg)}
function G_DebugL(who,msg){var zone=G_GetDebugZone(who);if(zone.zoneIsEnabled()){G_debugService.dump(G_File.LINE_END_CHAR+"************************************************************"+G_File.LINE_END_CHAR);G_Debug(who,msg);G_debugService.dump("************************************************************"+G_File.LINE_END_CHAR+G_File.LINE_END_CHAR)}}
function G_TraceCall(who,msg){if(G_debugService.callTracingEnabled()){G_debugService.dump(msg+G_File.LINE_END_CHAR)}}
function G_Error(who,msg){G_GetDebugZone(who).error(msg)}
function G_Assert(who,condition,msg){G_GetDebugZone(who).assert(condition,msg)}
function G_GetDebugZone(who){var zone="?";if(who&&who.debugZone){zone=who.debugZone}else if(isString(who)){zone=who}return G_debugService.getZone(zone)}
function G_DebugZone(service,prefix,zone){this.debugService_=service;this.prefix_=prefix;this.zone_=zone;this.zoneEnabledPrefName_=prefix+".zone."+this.zone_;this.settings_=new G_DebugSettings}
;G_DebugZone.prototype.error=function(msg){this.debugService_.dump("[%s] %s%s".subs(this.zone_,msg,G_File.LINE_END_CHAR));throw new Error(msg);debugger}
new G_Loggifier;this.settings_=new G_DebugSettings;this.timer_=Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);this.timer_.initWithCallback(this,G_DebugService.TIMESTAMP_INTERVAL,Ci.nsITimer.TYPE_REPEATING_SLACK);this.activeSinceLastTimestamp_=false;Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService).registerListener(this)}
;G_DebugService.prototype.dump=function(msg){if(this.alsoDumpToShell()){dump(msg)}if(this.alsoDumpToConsole()){try{var console=Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);console.logStringMessage(msg)}catch(e){dump("G_DebugZone ERROR: COULD NOT DUMP TO CONSOLE"+G_File.LINE_END_CHAR)}}this.maybeDumpToFile(msg);this.activeSinceLastTimestamp_=true}
;var ignoreLookup={};if(arguments.length>1){for(var i=1;i<arguments.length;i++){ignoreLookup[arguments[i]]=true}}for(var p in obj){if(typeof obj[p]=="function"&&obj[p].call&&!ignoreLookup[p]){var objName=this.getFunctionName_(obj.constructor);obj[p]=wrap(obj[p],objName,p)}}}
;G_File.fromFileURI=function(uri){if(uri.indexOf("file://")!=0)throw new Error("File path must be a file:// URL");var fileHandler=Cc["@mozilla.org/network/protocol;1?name=file"].getService(Ci.nsIFileProtocolHandler);return fileHandler.getFileFromURLSpec(uri)}
;G_File.PR_RDONLY=1;G_File.PR_WRONLY=2;G_File.PR_RDWR=4;G_File.PR_CREATE_FILE=8;G_File.PR_APPEND=16;G_File.PR_TRUNCATE=32;G_File.PR_SYNC=64;G_File.PR_EXCL=128;G_File.__defineGetter__("LINE_END_CHAR",function(){var end_char;if("@mozilla.org/xre/app-info;1" in Cc){end_char=Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS=="WINNT"?"\r\n":"\n"}else{end_char=Cc["@mozilla.org/network/protocol;1?name=http"].getService(Ci.nsIHttpProtocolHandler).platform.toLowerCase().indexOf("win")==0?"\r\n"
;G_ObjectSafeMap.prototype.insert=function(key,value){if(key===null)throw new Error("Can't use null as a key");if(value===undefined)throw new Error("Can't store undefined values in this map");var i=this.indexOfKey_(key);if(i==-1){this.keys_.push(key);this.values_.push(value)}else{this.keys_[i]=key;this.values_[i]=value}G_Assert(this,this.keys_.length==this.values_.length,"Different number of keys than values!")}
;G_ObjectSafeMap.prototype.erase=function(key){var keyLocation=this.indexOfKey_(key);var keyFound=keyLocation!=-1;if(keyFound){this.keys_.splice(keyLocation,1);this.values_.splice(keyLocation,1)}G_Assert(this,this.keys_.length==this.values_.length,"Different number of keys than values!");return keyFound}
;G_ObjectSafeMap.prototype.replace=function(other){this.keys_=[];this.values_=[];for(var i=0;i<other.keys_.length;i++){this.keys_.push(other.keys_[i]);this.values_.push(other.values_[i])}G_Assert(this,this.keys_.length==this.values_.length,"Different number of keys than values!")}
;G_ObjectSafeMap.prototype.forEach=function(func){if(typeof func!="function")throw new Error("argument to forEach is not a function, it's a(n) "+typeof func);for(var i=0;i<this.keys_.length;i++)func(this.keys_[i],this.values_[i])}
function G_Alarm(callback,delayMS,opt_repeating,opt_maxTimes){this.debugZone="alarm";this.callback_=callback;this.repeating_=!(!opt_repeating);var Cc=Components.classes;var Ci=Components.interfaces;this.timer_=Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);var type=opt_repeating?this.timer_.TYPE_REPEATING_SLACK:this.timer_.TYPE_ONE_SHOT;this.maxTimes_=opt_maxTimes?opt_maxTimes:null;this.nTimes_=0;this.timer_.initWithCallback(this,delayMS,type)}
G_ConditionalAlarm.inherits(G_Alarm);G_ConditionalAlarm.prototype.notify=function(timer){var rv=G_Alarm.prototype.notify.call(this,timer);if(this.repeating_&&rv){G_Debug(this,"Callback of a repeating alarm returned true; cancelling.");this.cancel()}}
;
function G_CryptoHasher(){this.debugZone="cryptohasher";this.decoder_=new G_Base64;this.hasher_=Cc["@mozilla.org/security/hash;1"].createInstance(Ci.nsICryptoHash);this.initialized_=false}
G_CryptoHasher.algorithms={MD2:Ci.nsICryptoHash.MD2,MD5:Ci.nsICryptoHash.MD5,SHA1:Ci.nsICryptoHash.SHA1,SHA256:Ci.nsICryptoHash.SHA256,SHA384:Ci.nsICryptoHash.SHA384,SHA512:Ci.nsICryptoHash.SHA512};G_CryptoHasher.prototype.init=function(algorithm){var validAlgorithm=false;for(var alg in G_CryptoHasher.algorithms)if(algorithm==G_CryptoHasher.algorithms[alg])validAlgorithm=true;if(!validAlgorithm)throw new Error("Invalid algorithm: "+algorithm);this.initialized_=true;this.hasher_.init(algorithm)}
;G_CryptoHasher.prototype.updateFromString=function(input){if(!this.initialized_)throw new Error("You must initialize the hasher first!");this.hasher_.update(this.decoder_.arrayifyString(input),input.length)}
;G_CryptoHasher.prototype.updateFromArray=function(input){if(!this.initialized_)throw new Error("You must initialize the hasher first!");this.hasher_.update(input,input.length)}
;G_CryptoHasher.prototype.updateFromStream=function(stream){if(!this.initialized_)throw new Error("You must initialize the hasher first!");this.hasher_.updateFromStream(stream,stream.available())}
;G_JSModule.prototype.registerSelf=function(compMgr,fileSpec,location,type){compMgr=compMgr.QueryInterface(Ci.nsIComponentRegistrar);for(var factory in this.factoryLookup_){compMgr.registerFactoryLocation(this.factoryLookup_[factory].classID,this.factoryLookup_[factory].className,this.factoryLookup_[factory].contractID,fileSpec,location,type);this.factoryLookup_[factory].registerCategories()}}
;G_JSModule.prototype.getClassObject=function(compMgr,classID,interfaceID){var factory=this.factoryLookup_[classID.toString()];if(!factory){throw new Error("Invalid classID {%s}".subs(classID));}return factory}
;G_Protocol4Parser.prototype.serialize=function(map){if(typeof map!="object")throw new Error("map must be an object");var text="";for(var key in map){if(typeof map[key]!="string")throw new Error("Keys and values must be strings");text+=key+":"+map[key].length+":"+map[key]+"\n"}return text}
;
function jsInstanceOf(obj,iid){try{obj.QueryInterface(iid);return true}catch(e){if(e==Components.results.NS_ERROR_NO_INTERFACE){return false}else{throw e;}}}
function BindToObject(func,obj,opt_A,opt_B,opt_C,opt_D,opt_E,opt_F){var args=Array.prototype.splice.call(arguments,1,arguments.length);return Function.prototype.bind.apply(func,args)}
;
function ListDictionary(name){this.name_=name;this.members_=[]}
;ListDictionary.prototype.forEach=function(func){if(typeof func!="function")throw new Error("argument to forEach is not a function, it's a(n) "+typeof func);for(var i=0;i<this.members_.length;i++)func(this.members_[i])}
;
function EventRegistrar(eventTypes){this.eventTypes=[];this.listeners_={};if(eventTypes instanceof Array){var events=eventTypes}else if(typeof eventTypes=="object"){var events=[];for(var e in eventTypes)events.push(eventTypes[e])}else{throw new Error("Unrecognized init parameter to EventRegistrar");}for(var i=0;i<events.length;i++){this.eventTypes.push(events[i]);this.listeners_[events[i]]=new ListDictionary(events[i]+"Listeners")}}
;EventRegistrar.prototype.addEventType=function(eventType){if(this.isKnownEventType(eventType))throw new Error("Event type already known: "+eventType);this.eventTypes.push(eventType);this.listeners_[eventType]=new ListDictionary(eventType+"Listeners")}
;EventRegistrar.prototype.registerListener=function(eventType,listener){if(this.isKnownEventType(eventType)===false)throw new Error("Unknown event type: "+eventType);this.listeners_[eventType].addMember(listener)}
;EventRegistrar.prototype.removeListener=function(eventType,listener){if(this.isKnownEventType(eventType)===false)throw new Error("Unknown event type: "+eventType);this.listeners_[eventType].removeMember(listener)}
;EventRegistrar.prototype.fire=function(eventType,e){if(this.isKnownEventType(eventType)===false)throw new Error("Unknown event type: "+eventType);var invoke=function(listener){listener(e)}
;this.listeners_[eventType].forEach(invoke)}
;
function G_TabbedBrowserWatcher(tabBrowser,name,opt_filterAboutBlank){this.debugZone="tabbedbrowserwatcher";this.tabBrowser_=tabBrowser;this.filterAboutBlank_=!(!opt_filterAboutBlank);this.events=G_TabbedBrowserWatcher.events;G_Assert(this,typeof name=="string"&&!(!name),"Need a probabilistically unique name");this.name_=name;this.mark_=G_TabbedBrowserWatcher.mark_+"-"+this.name_;this.registrar_=new EventRegistrar(G_TabbedBrowserWatcher.events);this.tabbox_=this.getTabBrowser().mTabBox;this.onDOMContentLoadedClosure_=
;G_TabbedBrowserWatcher.prototype.onDOMContentLoaded=function(e){G_Debug(this,"onDOMContentLoaded for a "+e.target);var doc=e.target;var browser=this.getBrowserFromDocument(doc);if(!browser){G_Debug(this,"domcontentloaded: no browser for "+doc.location.href);return}this.maybeFireTabLoad(browser);G_Debug(this,"DOMContentLoaded broken for forward/back buttons.");this.fireDocEvent_(this.events.DOMCONTENTLOADED,doc,browser)}
;G_TabbedBrowserWatcher.prototype.onDOMNodeInserted=function(e){G_Debug(this,"onDOMNodeInserted for a "+e.target+" related: "+e.relatedNode);if(e.target.localName!="tab"){return}if(!isDef(e.target._tPos)){return}var fromPos=e.target._tPos;var toPos;for(var i=0;i<e.relatedNode.childNodes.length;i++){var child=e.relatedNode.childNodes[i];if(child==e.target){toPos=i;break}}G_Debug(this,"firing tabmove");this.fire(this.events.TABMOVE,{tab:e.target,fromIndex:fromPos,toIndex:toPos})}
var browsers=this.getTabBrowser().browsers;for(var i=0;i<browsers.length;i++)if(docInWindow(doc,browsers[i].contentWindow))return browsers[i];return null}
var browsers=this.getTabBrowser().browsers;for(var i=0;i<browsers.length;i++)if(containsSubWindow(sub,browsers[i].contentWindow))return browsers[i];return null}
G_BrowserWatcher.prototype.onLocationChange=function(webProgress,request,location){G_Debug(this,"onLocationChange for {%s}".subs(location.spec));if(!this.parent_){G_Debug(this,"onLocationChange after tab close");return}var e={browser:this.browser_,isTop:true};this.parent_.fire(this.parent_.events.LOCATIONCHANGE,e)}
;G_BrowserWatcher.prototype.onPageShow=function(e){G_Debug(this,"onPageShow for "+(e.target?e.target:"undefined"));if(e.target&&e.target.nodeName=="#document"){var doc=e.target;this.parent_.fireDocEvent_(this.parent_.events.PAGESHOW,doc,this.browser_)}}
;G_BrowserWatcher.prototype.onLoad=function(e){G_Debug(this,"onLoad for a "+e.target);if(!e.target){G_Debug(this,"e.target is null; canceling onload event");return}if(e.target.nodeName!="#document")return;var doc=e.target;this.parent_.fireDocEvent_(this.parent_.events.LOAD,doc,this.browser_)}
;G_BrowserWatcher.prototype.onUnload=function(e){G_Debug(this,"onUnload for "+(e.target?e.target:"undefined"));var doc=e.target;if(doc&&doc.nodeName=="#document")this.parent_.fireDocEvent_("unload",doc,this.browser_);if(!doc){G_Debug(this,"firing tabunload for a "+this.browser_+"("+this.browser_.nodename+")");this.parent_.fire(this.parent_.events.TABUNLOAD,{browser:this.browser_});this.browser_.removeEventListener("pageshow",this.onPageShowClosure_,true);this.browser_.removeEventListener("pagehide"
;G_BrowserWatcher.prototype.onPageHide=function(e){G_Debug(this,"onPageHide for a "+e.target+"("+e.target.nodeName+")");if(e.target.nodeName!="#document")return;var doc=e.target;this.parent_.fireDocEvent_(this.parent_.events.PAGEHIDE,doc,this.browser_)}
;
function G_Base64(){this.byteToCharMap_={};this.charToByteMap_={};this.byteToCharMapWebSafe_={};this.charToByteMapWebSafe_={};this.init_()}
;G_Base64.prototype.decodeString=function(input,opt_webSafe){if(input.length%4)throw new Error("Length of b64-encoded data must be zero mod four");var charToByteMap=opt_webSafe?this.charToByteMapWebSafe_:this.charToByteMap_;var output=[];var i=0;while(i<input.length){var byte1=charToByteMap[input.charAt(i)];var byte2=charToByteMap[input.charAt(i+1)];var byte3=charToByteMap[input.charAt(i+2)];var byte4=charToByteMap[input.charAt(i+3)];if(byte1===undefined||byte2===undefined||byte3===undefined||byte4===
undefined)throw new Error("String contains characters not in our alphabet: "+input);var outByte1=byte1<<2|byte2>>4;output.push(outByte1);if(byte3!=64){var outByte2=byte2<<4&240|byte3>>2;output.push(outByte2);if(byte4!=64){var outByte3=byte3<<6&192|byte4;output.push(outByte3)}}i+=4}return output}
function G_ExtensionUpdater(id,requestOptions){if(!id){G_Debug(this,"You need to specify an extension id");return false}this.RDFSvc_=Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);if(requestOptions){this.requestOptions_=requestOptions}else{this.requestOptions_={}}this.id=id;this.updating=false;this.preferences=new G_Preferences("extensions.google.updater.")}
G_ExtensionUpdater.prototype.Update=function(){if(this.updating){return false}this.updating=true;this.appVersion="";this.appID="";this.currentVersion="";this.updateURL="";this.updateLink="";this.updateVersion="";if(!this.GetCurrent()){this.Failure("'%s' not found in extension manager.".subs(this.name));return false}this.AttemptUpdate()}
;G_ExtensionUpdater.prototype.UpdatePeriodically=function(opt_makeTimer){var lastUpdate=this.preferences.getPref(this.id,0);var timeBetweenUpdates=86400000;var nextUpdate=Number(lastUpdate)+timeBetweenUpdates;var now=(new Date).getTime();G_Debug(this,"Last update: "+lastUpdate+", next: "+nextUpdate+"\n");if(now>nextUpdate){this.preferences.setPref(this.id,String(now));this.Update();nextUpdate=now+timeBetweenUpdates}if(opt_makeTimer){G_Debug(this,"Setting timer for update in "+(nextUpdate-now)+"ms\n"
var G_FirefoxXMLUtils={};G_FirefoxXMLUtils.XSI_NAMESPACE="http://www.w3.org/2001/XMLSchema-instance";G_FirefoxXMLUtils.XMLNS_NAMESPACE="http://www.w3.org/2000/xmlns/";G_FirefoxXMLUtils.XUL_NAMESPACE="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";G_FirefoxXMLUtils.newXML=function(opt_root,opt_namespace,opt_nsMap){if(!this.domImpl_){this.domImpl_=Cc["@mozilla.org/xmlextras/domparser;1"].createInstance(Ci.nsIDOMParser).parseFromString("<foo/>","text/xml").implementation}if(!isDef(opt_root)
){opt_root=null}if(!isDef(opt_namespace)){opt_namespace=null}var doc=this.domImpl_.createDocument(opt_namespace,opt_root,null);if(opt_nsMap){var root=doc.documentElement;for(var prefix in opt_nsMap){root.setAttributeNS(this.XMLNS_NAMESPACE,"xmlns:"+prefix,opt_nsMap[prefix])}}return doc}
function CLB_Application(){this.initialized_=false;this.originalHandlers_=[];this.obsSvc_=Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);this.catMan_=Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);this.promptSvc_=Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci.nsIPromptService);this.extMan_=Cc["@mozilla.org/extensions/manager;1"].getService(Ci.nsIExtensionManager);this.rdfSvc_=Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService)
CLB_Application.STATUS_ONLINE=0;CLB_Application.STATUS_OFFLINE=1;CLB_Application.STATUS_KICKED=2;CLB_Application.STATUS_UPDATE_ERROR=3;CLB_Application.STATUS_NEEDS_CAPTCHA=4;CLB_Application.STATUS_PING_REDIRECT=5;CLB_Application.STATUS_BACKED_OFF=6;CLB_Application.PROGRESS_UNOFFLINING="Processing offline changes...";CLB_Application.PROGRESS_GATHERING="Gathering local changes...";CLB_Application.PROGRESS_INDEXING="Preparing conflict resolution rules...";CLB_Application.PROGRESS_DOWNLOADING="Downloading server changes..."
;CLB_Application.PROGRESS_PARSING="Processing server changes...";CLB_Application.PROGRESS_RESOLVING="Applying conflict resolution rules...";CLB_Application.PROGRESS_PREPARING="Preparing server update...";CLB_Application.PROGRESS_UPDATING="Updating server...";CLB_Application.PROGRESS_APPLYING="Updating browser...";CLB_Application.MESSAGE_WORKING_OFFLINE="Google Browser Sync will not run while you are working offline.";CLB_Application.MESSAGE_BACKED_OFF="The Google Browser Sync server has requested that you stay offline for a period of time, please try again later."
;CLB_Application.HTTP_STATUS_FORBIDDEN=403;CLB_Application.HTTP_STATUS_UNAVAILABLE=503;CLB_Application.ERROR_INVALID_PIN="Invalid token.";CLB_Application.MESSAGE_INVALID_PIN="Your PIN was incorrect, please try again";CLB_Application.ERROR_SINGLE_UPLOAD_LIMIT="Update exceeds single upload limit.";CLB_Application.MESSAGE_SINGLE_UPLOAD_LIMIT="You have too much stuff, please try disabling some components and trying again.";CLB_Application.ERROR_DAILY_UPLOAD_LIMIT="Daily upload quota exceeded.";CLB_Application.MESSAGE_DAILY_UPLOAD_LIMIT=
"You've uploaded too much stuff today, please try again tomorrow.";CLB_Application.ERROR_PIN_LIMIT="Too many invalid PINs provided.";CLB_Application.MESSAGE_PIN_LIMIT="PIN authentication has failed too many times.";CLB_Application.ERROR_SERVER_UNAVAILABLE="Server unavailable.";CLB_Application.MESSAGE_SERVER_UNAVAILABLE="The Google Browser Sync server was unavailable.";CLB_Application.MESSAGE_UNKNOWN="An unknown error has occured while trying to contact the server.";CLB_Application.CIPHER_DISCARD_BYTES=
;CLB_Application.prototype.isInvalidUserError=function(code,status,message){if(code==CLB_Application.HTTP_STATUS_FORBIDDEN&&message=="Account does not exist for this user."){return true}else{return false}}
;CLB_Application.prototype.addStatusObserver=function(observer){G_Debug(this,"Adding status observer...");if(this.statusObservers_.indexOf(observer)>-1){G_DebugL(this,"Status observer already exists! Skipping...");return}this.statusObservers_.push(observer);G_Debug(this,"Done.")}
;CLB_Application.prototype.removeStatusObserver=function(observer){G_Debug(this,"Removing status observer...");var idx=this.statusObservers_.indexOf(observer);if(idx==-1){G_DebugL(this,"Could not find observer! Skipping.");return}this.statusObservers_.splice(idx,1);G_Debug(this,"Done.")}
;CLB_Application.prototype.autoupdate=function(){var p=new G_Preferences;if(!p.getPref("extensions.google.browserstate.autoupdate",false)){G_DebugL(this,"Browser not set to autoupdate, skipping.");return}this.updater_=new G_ExtensionUpdater("browserstate@google.com");this.updater_.Update();if(!this.updateLoop_){this.updateLoop_=new G_Alarm(this.autoupdate.bind(this),CLB_Application.UPDATE_CYCLE,true)}}
;CLB_Application.prototype.handleUpdateSuccess_=function(){this.updateLoop_.cancel();this.promptSvc_.alert(null,"Google Browser Sync update complete","Google Browser Sync has successfully updated itself. Please restart Firefox to finish installing the update.")}
;CLB_Application.prototype.observe=function(subject,topic,data){if(topic=="quit-application"){this.handleApplicationQuit()}else if(topic=="em-action-requested"&&data=="item-uninstalled"){var updateItem=subject.QueryInterface(Ci.nsISupports).QueryInterface(Ci.nsIUpdateItem);if(updateItem.id=="browserstate@google.com"){G_DebugL(this,"Google Browser Sync is being uninstalled.");this.uninstalled_=true}}else{throw new Error("Caught unexpected topic {"+topic+"}.");}}
;CLB_Application.prototype.handleStartupSequenceFailure=function(){G_Debug(this,"Unsuccessful start sequence... not starting syncmanager");if(!isDef(this.getStatus())){this.setStatus(CLB_Application.STATUS_OFFLINE)}if(this.getSID()){CLB_syncMan.start()}this.startBrowser();this.obsSvc_.addObserver(this,"quit-application",false);this.obsSvc_.addObserver(this,"em-action-requested",false)}
;CLB_Application.prototype.handleApplicationQuit=function(){if(CLB_app.getSID()){this.obsSvc_.removeObserver(this,"quit-application");if((CLB_syncMan.checkPending()||CLB_syncMan.checkSending())&&!CLB_app.browserPrefs.getPref("offline",false)){Cc["@mozilla.org/embedcomp/window-watcher;1"].getService(Ci.nsIWindowWatcher).openWindow(null,"chrome://browserstate/content/updating.xul","browserstate-updating","modal,centerscreen,chrome",null)}else{G_Debug(this,"Skipping final update because there is nothing pending."
;CLB_Application.prototype.detectConflicts=function(){G_Debug(this,"Looking for conflicting extensions...");for(var i in CLB_Application.CONFLICTING_EXTENSIONS){var extID=CLB_Application.CONFLICTING_EXTENSIONS[i];var extItem=this.extMan_.getItemForID(extID);if(extItem&&extItem.name){G_Debug(this,"{%s} conflicts. Checking whether disabled.".subs(extID));if(!this.extensionIsDisabled(extID)){G_Debug(this,"Asking user...");var msg="You have '%s' installed - it may conflict with Google Browser Sync. Disable it?"
.subs(extItem.name);var res=this.promptSvc_.confirm(this.win,"Conflicting Extension",msg);if(res){G_Debug(this,"User has cancelled install because of conflicting extension.");this.extMan_.disableItem(extID);this.logOff();return true}else{G_Debug(this,"User is going for it. Booya.")}}}}return false}
;CLB_Application.prototype.startBrowser=function(){G_Debug(this,"Calling original handlers...");this.originalHandlers_.forEach(function(entryData){this.catMan_.addCategoryEntry("command-line-handler",entryData.entry,entryData.value,false,false)}
,this);this.originalHandlers_.forEach(function(entryData){G_Debug(this," %s: %s".subs(entryData.entry,entryData.value));var handler=Cc[entryData.value].getService(Ci.nsICommandLineHandler);try{G_Debug(this,"telling "+handler+" to handle");handler.handle(this.cmdLine_)}catch(e){if(e==Components.results.NS_ERROR_ABORT){throw e;}else{G_Debug(this,"Swallowing error {%s}".subs(e))}}}
var logFileName="log-%s%s%s-%s%s%s-%s.txt".subs(now.getFullYear(),pad(now.getMonth()+1,2),pad(now.getDate(),2),pad(now.getHours(),2),pad(now.getMinutes(),2),pad(now.getSeconds(),2),pad(now.getMilliseconds(),3));try{this.logFolder_=G_File.getProfileFile("browserstate-logs");if(!this.logFolder_.exists()){this.logFolder_.create(Ci.nsIFile.DIRECTORY_TYPE,this.logFolder_.parent.permissions)}var logFile=this.logFolder_.clone();logFile.append(logFileName);G_debugService.autoLoggify=false;G_debugService.setLogFile(
;CLB_BookmarkResolver.prototype.addDownloadedItem=function(item){var parent,pos;if(!item.isRemove){parent=CLB_app.bmSyncer.getParent(item);pos=CLB_app.bmSyncer.getPosition(item)}else{var bmNode;if(item.typeID=="separator"){bmNode=CLB_app.bmSyncer.getSeparatorResource(item.itemID)}else{bmNode=CLB_app.bmSyncer.bmRdfServ.GetResource(item.itemID)}if(!bmNode){G_Debug(this,"Warning, could not form resource from item "+item.itemID+", skipping");return}if(!CLB_app.bmSyncer.bmServ.isBookmarkedResource(bmNode)
){G_Debug(this,"Warning: bogus isRemove sent from the server with itemID "+item.itemID);return}var parentNode=CLB_app.bmSyncer.bmServ.getParent(bmNode);var container=Cc["@mozilla.org/rdf/container;1"].getService(Ci.nsIRDFContainer);container.Init(CLB_app.bmSyncer.bmDS,parentNode);parent=CLB_rdf.getValueFromNode(parentNode);pos=container.IndexOf(bmNode)}if(!parent||!pos){G_Debug(this,"Error: every bookmark item should contain a parent and position - perhaps this is old data?");return}var parentFolder=
;CLB_BookmarkResolver.prototype.removeItemFromFolder=function(item,shiftItems){if(item.isRemove){G_Debug(this,"Error: removeItemFromFolder should never be called with an isRemove item because these items don't contain parent and position info.");return}var parent=CLB_app.bmSyncer.getParent(item);var positionToInsert=CLB_app.bmSyncer.getPosition(item);var folder=this.getFolder(parent);folder.removeBookmark(item.itemID);var shiftedItems;if(!shiftItems){shiftedItems=[]}else{shiftedItems=this.shiftItems(
;CLB_BookmarkResolver.prototype.addItemToFolder=function(item,shiftItems){if(item.isRemove){G_Debug(this,"Error: addItemToFolder should never be called with an isRemove item because these items don't contain parent and position info.");return}var parent=CLB_app.bmSyncer.getParent(item);var positionToInsert=CLB_app.bmSyncer.getPosition(item);var folder=this.getFolder(parent);folder.removeBookmark(item.itemID);var shiftedItems;if(!shiftItems){shiftedItems=[]}else{shiftedItems=this.shiftItems(parent,
;CLB_BookmarkResolver.prototype.getParentPath=function(id){var path="";var currentParent=id;do{var nextParent=null;if(isDef(this.folders_[currentParent])){nextParent=this.folders_[currentParent].getParent()}if(nextParent==null){var bmNode=CLB_app.bmSyncer.bmRdfServ.GetResource(currentParent);var nextParentNode=CLB_app.bmSyncer.bmServ.getParent(bmNode);if(!nextParentNode){G_Debug(this,"Error: Tried to get parent for folder "+currentParent+" but it did not exist in the local store");return null}nextParent=
CLB_rdf.getValueFromNode(nextParentNode)}var folderName=null;if(isDef(this.folders_[nextParent])){folderName=this.folders_[nextParent].getName()}if(folderName==null){var nextParentNode=CLB_app.bmSyncer.bmRdfServ.GetResource(nextParent);var nameArc=CLB_app.bmSyncer.bmRdfServ.GetResource(CLB_BookmarkSyncer.nameRdfStr);var tar=CLB_app.bmSyncer.bmDS.GetTarget(nextParentNode,nameArc,true);if(!tar){G_Debug(this,"Error: Tried to get name for folder "+nextParent+" but it did not exist in the local store"
;CLB_BookmarkResolver.prototype.resolveFolderNameConflict=function(oldItem,newItem){if(oldItem.typeID!="folder"&&newItem.typeID!="folder"){G_Debug(this,"Error: trying to resolve a folder name conflict for non folders - how did we get here?");return[]}var path1=this.getParentPath(oldItem.itemID);var path2=this.getParentPath(newItem.itemID);if(isNull(path1)||isNull(path2)||path1!=path2){return[]}return this.mergeFolders(oldItem,newItem)}
;CLB_BookmarkResolver.prototype.mergeFolders=function(oldFolder,newFolder){var resolvedItems=this.removeItemFromFolder(oldFolder,true);var folder=this.getFolder(oldFolder.itemID);var parent=newFolder.itemID;for(var id in folder.contents_){var position=folder.getBookmarkPosition(id);var typeID=folder.getBookmarkTypeID(id);var itemID;if(typeID=="separator"){var separatorDeleteItem=new CLB_SyncItem({componentID:CLB_app.bmSyncer.componentID,typeID:typeID,itemID:id,isRemove:true,properties:{}});resolvedItems.push(
CLB_Folder.prototype.addBookmark=function(id,typeID,position){if(isDef(this.contents_[id])){G_Debug(this,"Warning: adding the same bookmark again. id: "+id+" Old position: "+this.contents_[id].position+" New position: "+position)}position=parseInt(position);if(isNaN(position)){G_Debug(this,"Could not parse position value, not adding bookmark "+id);return}this.contents_[id]={position:position,typeID:typeID};if(position>this.maxPosition_){this.maxPosition_=position}}
;CLB_Folder.prototype.removeBookmark=function(id){var bm=this.contents_[id];if(!isDef(bm)){G_Debug(this,"Warning: deleting nonexistant item "+id+" from a folder");return}if(this.maxPosition_>0&&this.maxPosition_==bm.position){this.maxPosition_=this.maxPosition_-1}delete this.contents_[id]}
function CLB_BookmarkSyncer(){this.bmDS=Cc["@mozilla.org/rdf/datasource;1?name=bookmarks"].getService(Ci.nsIRDFDataSource);this.bmRdfServ=Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);this.container=Cc["@mozilla.org/rdf/container;1"].getService(Ci.nsIRDFContainer);this.containerUtils=Cc["@mozilla.org/rdf/container-utils;1"].getService(Ci.nsIRDFContainerUtils);this.bmServ=Cc["@mozilla.org/browser/bookmarks-service;1"].getService(Ci.nsIBookmarksService);this.started_=false;this.propertiesToCollect_=
new G_DoubleDictionary;this.propertiesToCollect_.addMultiple({title:CLB_BookmarkSyncer.nameRdfStr,url:CLB_BookmarkSyncer.urlRdfStr,description:CLB_BookmarkSyncer.descriptionRdfStr,addDate:CLB_BookmarkSyncer.bookmarkAddDateRdfStr,shortcutURL:CLB_BookmarkSyncer.shortcutRdfStr,webPanel:CLB_BookmarkSyncer.showInSidebarRdfStr,forwardProxy:CLB_BookmarkSyncer.forwardProxyRdfStr,bookmarksToolbarFolder:CLB_BookmarkSyncer.toolbarFolder,feedURL:CLB_BookmarkSyncer.feedUrlRdfStr});CLB_syncMan.registerConflict(
))));CLB_BookmarkSyncer.prototype.syncStart=function(){this.bmServ.readBookmarks();G_Debug(this,"Checking for scratch folder before sync");this.ensureScratchFolderRemoved();if(this.inUpdateBatch){G_DebugL(this,"WARNING: syncStart called twice without syncFailure.");return}this.bmDS.beginUpdateBatch();this.inUpdateBatch=true}
;CLB_BookmarkSyncer.prototype.syncComplete=(CLB_BookmarkSyncer.prototype.syncFailure=function(){this.bmServ.readBookmarks();G_Debug(this,"Checking for scratch folder after sync");this.ensureScratchFolderRemoved();if(!this.inUpdateBatch){G_DebugL(this,"WARNING: syncFailure called without corresponding syncStart.");return}this.bmDS.endUpdateBatch();this.inUpdateBatch=false}
);if(this.toolbarItemToDelete){G_Debug(this,"Error: we should have already deleted the old toolbar folder with itemID "+this.toolbarItemToDelete.itemID+" Perhaps no other item was set to the toolbar folder");this.toolbarItemToDelete=null}this.ensureScratchFolderRemoved();this.bmDS.AddObserver(this);this.started_=true}}
;CLB_BookmarkSyncer.prototype.onItemConflict=function(conflict,oldItem,newItem){this.bmServ.readBookmarks();var resolvedItems;G_Debug(this,"Conflict detected between "+oldItem.toStringVerbose()+" and "+newItem.toStringVerbose());if(conflict==CLB_BookmarkSyncer.folderNameConflict){resolvedItems=this.resolver.resolveFolderNameConflict(oldItem,newItem)}else if(conflict==CLB_BookmarkSyncer.urlConflict){resolvedItems=this.resolver.resolveUrlConflict(oldItem,newItem)}else if(conflict==CLB_BookmarkSyncer.positionConflict)
{resolvedItems=this.resolver.resolvePositionConflict(oldItem,newItem)}else if(conflict==CLB_BookmarkSyncer.toolbarFolderConflict){resolvedItems=this.resolver.resolveToolbarConflict(oldItem,newItem)}G_Debug(this,"After resolving conflict, syncItem is: "+oldItem.toStringVerbose());G_Debug(this,"There are %s other resolved items.".subs(resolvedItems.length));return new CLB_ArrayEnumerator(resolvedItems)}
;CLB_BookmarkSyncer.prototype.getItemByID=function(id,typeid){var rdfNode;if(typeid=="separator"){rdfNode=this.getSeparatorResource(id)}else{rdfNode=this.bmRdfServ.GetResource(id)}if(!rdfNode){G_Debug(this,"Warning - could not retrieve resource using id "+id+" and typeID "+typeid);return null}return this.fillBookmarkItem(rdfNode)}
;CLB_BookmarkSyncer.prototype.getCurrentItems=function(){this.bmServ.readBookmarks();var e=this.bmDS.GetAllResources();return new CLB_BookmarkEnumerator(e)}
;CLB_BookmarkSyncer.prototype.onChange=function(aDataSource,aSource,aProperty,aOldTarget,aNewTarget){var newValue=CLB_rdf.getValueFromNode(aNewTarget);if(isNull(newValue)){G_Debug(this,"Could not extract value from target, skipping");return}G_Debug(this,"onChange: %s %s changed to %s\n\n".subs(aSource.Value,aProperty.Value,newValue));var items=this.getUpdateItems(aSource,aProperty,newValue,false);if(items){items.forEach(function(item){CLB_syncMan.update(item)}
)}}
;CLB_BookmarkSyncer.prototype.onAssert=function(aDataSource,aSource,aProperty,aTarget){var newValue=CLB_rdf.getValueFromNode(aTarget);if(isNull(newValue)){G_Debug(this,"Could not extract value from target, skipping");return}G_Debug(this,"onAssert: %s %s %s".subs(aSource.Value,aProperty.Value,newValue));var items=this.getUpdateItems(aSource,aProperty,newValue,false);if(items){items.forEach(function(item){CLB_syncMan.update(item)}
)}}
;CLB_BookmarkSyncer.prototype.onUnassert=function(aDataSource,aSource,aProperty,aTarget){G_Debug(this,"onunassert: src: %s property: %s".subs(aSource.Value,aProperty.Value));var value=CLB_rdf.getValueFromNode(aTarget);if(isNull(value)){G_Debug(this,"Could not extract value from target, skipping");return}G_Debug(this,"onUnassert: %s %s %s".subs(aSource.Value,aProperty.Value,value));var items=this.getUpdateItems(aSource,aProperty,value,true);if(items){items.forEach(function(item){CLB_syncMan.update(
item)}
)}}
;CLB_BookmarkSyncer.prototype.onMove=function(aDataSource,aOldSource,aNewSource,aProperty,aTarget){G_Debug(this,"Warning: bookmark is calling onMove!!");var value=CLB_rdf.getValueFromNode(aTarget);G_Debug(this,"onMove: %s %s %s %s".subs(aOldSource.Value,aNewSource.Value,aProperty.Value,value))}
bm);var parentID=CLB_rdf.getValueFromNode(parent);var container=CLB_rdf.getInitializedContainer(this.bmDS,parent);var position=container.IndexOf(bm);if(batchInfo.parentID!=parentID||batchInfo.position!=position){G_Debug(this,"Old parentID: "+batchInfo.parentID+", New parentID: "+parentID+", Old position: "+batchInfo.position+", New position: "+position);var item=this.fillBookmarkItem(bm);CLB_syncMan.update(item)}delete this.updateBatchData_[bookmarkID]}for(var bmID in this.updateBatchData_){G_Debug(
)){G_Debug(this,"Skipping assertation not in the rdf tree");return false}while(arcs.hasMoreElements()){var arc=arcs.getNext();var srcs=this.bmDS.GetSources(arc,aSource,true);while(srcs.hasMoreElements()){var src=srcs.getNext();if(this.bmDS.HasAssertion(src,typeArc,livemarkTarget,true)){G_Debug(this,"skipping livemark");return false}}}return true}
;CLB_BookmarkSyncer.prototype.setItemID=function(node,item,opt_parent,opt_pos){if(this.isSeparator(node)){var parentNode,position;if(isDef(opt_parent)){if(!isDef(opt_pos)){throw new Error("Both parent and position should be specified");}parentNode=opt_parent;position=this.parsePositionFromProperty(opt_pos);if(isNaN(position)){throw new Error("Incorrectly formatted ordinal node");}}else{parentNode=this.bmServ.getParent(node);this.container.Init(this.bmDS,parentNode);position=this.container.IndexOf(
item,valueNode)){G_Debug(this,"Problem setting parent and position info. Perhaps the node {%s} is not attached to the rdf "+"tree".subs(valueNode));return null}this.getAllChildProperties(valueNode,item);var childItems=this.getAllChildItems(valueNode);childItems[childItems.length]=item;return childItems}else if(this.isSourceResource(aSource.Value)){if(!this.propertiesToCollect_.hasValue(aProperty.Value)){G_Debug(this,"Skipping update to non-recorded property {%s}".subs(aProperty.Value));return null}
item=this.setRequiredFields(aSource);this.setContainerInfo(item,aSource);var itemPropertyValue=this.propertiesToCollect_.getKey(aProperty.Value);if(isRemove){item.setProperty(itemPropertyValue,null)}else{item.setProperty(itemPropertyValue,value)}item.isRemove=false;G_Debug(this,"Updating for %s".subs(aProperty.Value));G_Debug(this,"source: %s".subs(aSource.Value));G_Debug(this,"value: %s".subs(value));G_Debug(this,"Item ID is %s\n".subs(item.itemID));return[item]}else{return null}}
;CLB_BookmarkSyncer.prototype.handleDeleteItem=function(item){var contRes,position;if(item.typeID=="separator"){var cont=this.getContainerFromSeparatorID(item.itemID);position=this.getPositionFromSeparatorID(item.itemID);if(isNull(cont)||isNull(position)){G_Debug(this,"Error: skipping delete of separator with malformed id");return}contRes=this.bmRdfServ.GetResource(cont);if(!this.bmServ.isBookmarkedResource(contRes)){G_Debug(this,"Warning: trying to delete a separator that doesn't exist");return}
this.container.Init(this.bmDS,contRes);var positionProp=this.bmRdfServ.GetResource(this.getPropertyFromPosition(position));var sep=this.bmDS.GetTarget(contRes,positionProp,true);if(sep&&this.isSeparator(sep)){G_Debug(this,"Found and deleting separator at position "+position);this.container.RemoveElement(sep,false)}}else{var srcRes=this.bmRdfServ.GetResource(item.itemID);if(!this.bmServ.isBookmarkedResource(srcRes)){return}contRes=this.bmServ.getParent(srcRes);if(!contRes){G_Debug(this,"Warning: trying to delete an element that doesn't exist"
);return}if(item.typeID=="folder"&&this.isToolbarFolder(item.itemID)){if(this.toolbarItemToDelete){G_Debug(this,"Error: we should never have 2 toolbar folders to delete! itemIDs are "+this.toolbarItemToDelete.itemID+" and "+item.itemID)}this.toolbarItemToDelete=item;return}if(item.typeID=="folder"){this.rescueFolderChildren(srcRes)}this.container.Init(this.bmDS,contRes);position=this.container.IndexOf(srcRes);var url=this.getBookmarkUrl(srcRes);this.removeAllChildProperties(srcRes,url);this.container.RemoveElement(
srcRes,false);this.maybeDecrementNextVal(contRes,position)}G_Debug(this,"Just deleted item with container "+CLB_rdf.getValueFromNode(contRes)+" and position "+position)}
;CLB_BookmarkSyncer.prototype.addBookmarkItem=function(item){G_Debug(this,"About to add bookmark with syncitem: "+item.toStringVerbose());if(!isDef(item.itemID)){G_DebugL(this,"Warning: itemID is null, skipping!!\n");return}if(item.isRemove){this.handleDeleteItem(item);return}var srcRes;if(item.typeID=="separator"){srcRes=this.getSeparatorResource(item.itemID)}else{srcRes=this.bmRdfServ.GetResource(item.itemID)}var target,tarRes,propRes;if(item.hasProperty("positions")){if(!item.hasProperty("parents"
)){G_Debug(this,"Update item has position but not parents! skipping...");return}var parent=this.getParent(item);var position=this.getPosition(item);var contRes=this.bmRdfServ.GetResource(parent);if(!this.bmServ.isBookmarkedResource(contRes)){this.recordOrphanChild(parent,CLB_rdf.getValueFromNode(srcRes),position);contRes=this.getScratchFolder(true);this.container.Init(this.bmDS,contRes);position=parseInt(this.container.GetCount()+1);parent=CLB_rdf.getValueFromNode(contRes)}this.container.Init(this.bmDS,
this.propertiesToCollect_.hasKey(prop)){G_Debug(this,"Item contains property "+prop+" that does not correspond to an rdf property")}else{var rdfProp=this.propertiesToCollect_.getValue(prop);if(rdfProp==CLB_BookmarkSyncer.toolbarFolder){if(target!="true"){G_DebugL(this,"Skipping unexpected target for toolbarFolder: "+target);return}this.bmServ.setBookmarksToolbarFolder(srcRes)}propRes=this.bmRdfServ.GetResource(rdfProp);if(isNull(target)){this.unassertTargets(srcRes,propRes)}else if(target==""){G_Debug(
this,"Skipping target with value empty string")}else{tarRes=this.getNodeFromProperty(rdfProp,target);if(isNull(tarRes)){return}this.maybeAssert(srcRes,propRes,tarRes)}}}
;CLB_BookmarkSyncer.prototype.maybeMoveOrphanChildren=function(parentRes){var parent=CLB_rdf.getValueFromNode(parentRes);if(!parent){G_Debug(this,"Failed to extract rdf value from parent node - this should never happen")}var children=this.orphanChildren[parent];if(!isDef(children)){return}children.forEach(function(childObj){var node=this.bmRdfServ.GetResource(childObj.child);if(!node){G_Debug(this,"Could not create a resource from child "+childObj.child)}else{this.maybeMoveBookmark(node,parent,childObj.position)
;CLB_BookmarkSyncer.prototype.rescueFolderChildren=function(folderResource){if(!this.isFolder(folderResource)){G_Debug(this,"Error: trying to rescue children for an item that is not a folder, skipping");return}G_Debug(this,"Moving folder children to the scratch folder");var scratchFolder=this.getScratchFolder(true);var container=CLB_rdf.getInitializedContainer(this.bmDS,folderResource);var children=container.GetElements();while(children.hasMoreElements()){var childResource=children.getNext();if(
this.isSeparator(childResource)){G_Debug(this,"Skipping moving separator to the scratch folder");continue}var scratchFolderPosition=CLB_rdf.getContainerCount(this.bmDS,scratchFolder)+1;this.maybeMoveBookmark(childResource,CLB_BookmarkSyncer.scratchFolderID,scratchFolderPosition)}}
;CLB_BookmarkSyncer.prototype.ensureScratchFolderRemoved=function(){this.getScratchFolder(false);if(!this.scratchFolder){return}G_Debug(this,"Scratch folder found, deleting folder and contents");this.container.Init(this.bmDS,this.scratchFolder);var bms=this.container.GetElements();while(bms.hasMoreElements()){var bm=bms.getNext();G_Debug(this,"Deleting "+CLB_rdf.getValueFromNode(bm)+" from scratch folder");this.removeBookmark(this.scratchFolder,bm)}if(this.container.GetCount()!=0){G_Debug(this,"Error: Count is still not 0 after removing every element"
;CLB_BookmarkSyncer.prototype.maybeMoveBookmark=function(node,containerID,position,opt_type){var parentRes=this.bmRdfServ.GetResource(containerID);var posRes=this.bmRdfServ.GetResource(this.getPropertyFromPosition(position));if(!parentRes||!posRes){G_Debug(this,"Warning: failed to create parent: %s or position node: %s. "+"skipping....\n".subs(containerID,position));return}var existingNode=this.bmDS.GetTarget(parentRes,posRes,true);if(!existingNode||CLB_rdf.getValueFromNode(existingNode)!=CLB_rdf.getValueFromNode(
function CLB_BrowserOverlay(win){this.win_=win;this.doc_=this.win_.document;this.statusObserver_=this.handleStatusChange_.bind(this,false);this.win_.addEventListener("load",this.handleLoad_.bind(this),false);this.win_.addEventListener("unload",this.handleUnload_.bind(this),false);CLB_syncMan.addObserver(this)}
CLB_BrowserOverlay.IMAGE_ONLINE="chrome://browserstate/content/icon-small.png";CLB_BrowserOverlay.IMAGE_OFFLINE="chrome://browserstate/content/icon-small-disabled.png";CLB_BrowserOverlay.MESSAGE_LOCAL_CHANGES="Your changes will be sent to the server the next time you connect. ";CLB_BrowserOverlay.MESSAGE_KICKED="Google Browser Sync is disconnected because you logged in on a different machine. "+CLB_BrowserOverlay.MESSAGE_LOCAL_CHANGES;CLB_BrowserOverlay.MESSAGE_OFFLINE="Google Browser Sync is offline. "
+CLB_BrowserOverlay.MESSAGE_LOCAL_CHANGES;CLB_BrowserOverlay.MESSAGE_CAPTCHA_REQUIRED="Google Browser Sync is disconnected because your account is temporarily locked. Please verify your account and then reconnect.";CLB_BrowserOverlay.MESSAGE_PING_REDIRECT="Google Browser Sync could not contact the server. Please verify your network settings and then reconnect.";CLB_BrowserOverlay.MESSAGE_SETUP="Your changes are not being saved because Google Browser Sync has not been set up.";CLB_BrowserOverlay.MESSAGE_WELCOME=
"You've successfully installed Google Browser Sync. Google Browser Sync will continuously synchronize the browser settings you selected. Click on this icon to update your settings and account info.";CLB_BrowserOverlay.WELCOME_URL="http://google.com/";CLB_BrowserOverlay.SETTINGS_DIALOG_WIDTH=450;CLB_BrowserOverlay.SETTINGS_DIALOG_HEIGHT=420;CLB_BrowserOverlay.INFO_BUBBLE_WIDTH=200;CLB_BrowserOverlay.prototype.syncStart=(CLB_BrowserOverlay.prototype.syncFailure=(CLB_BrowserOverlay.prototype.updateProgress=
;CLB_BrowserOverlay.prototype.handleStatusChange_=function(opt_isPageLoad){var newStatus=CLB_app.getStatus();G_Debug(this,"Updating status to {%s}. isPageLoad: {%s}".subs(newStatus,opt_isPageLoad));if(!CLB_app.setupIsComplete()){this.setToolbarButtonImage_(CLB_BrowserOverlay.IMAGE_OFFLINE);this.setupItem_.hidden=false;this.settingsItem_.setAttribute("disabled",true);this.reconnectItem_.setAttribute("disabled",true)}else if(CLB_Application.STATUS_ONLINE==newStatus){this.setToolbarButtonImage_(CLB_BrowserOverlay.IMAGE_ONLINE)
;CLB_BrowserOverlay.prototype.updateBubble_=function(newStatus,isPageLoad){G_Debug(this,"Updating bubble to status: {%s}".subs(newStatus));if(CLB_Application.STATUS_ONLINE==newStatus){if(CLB_app.prefs.getPref("showWelcome",false)){this.showWelcomeMessage();this.infoBubble_.show(this.toolbarButton_)}else{this.infoBubble_.hide()}CLB_app.prefs.setPref("showWelcome",false);return}this.restoreUI_.hide();this.infoBubble_.clear();if(CLB_Application.STATUS_UPDATE_ERROR==newStatus){G_Debug(this,"Not showing bubble while offline."
;CLB_BrowserOverlay.prototype.startSetup_=function(){var promptSvc=Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci.nsIPromptService);if(promptSvc.confirm(null,"Warning","Setting up Google Browser Sync requires closing all open browser windows. OK to proceed?")){CLB_app.logOff()}}
var syncedComponents=lookupify(CLB_app.getListPref("syncedComponents"));var encryptedComponents=lookupify(CLB_app.getListPref("encryptedComponents"));for(var i=0;component=components[i];i++){this.list_.appendChild(this.createSettingsListItem_(component,syncedComponents[component.componentID],encryptedComponents[component.componentID]))}this.checkCheckboxState()}
CLB_Conflict.prototype.cloneWithoutValues=function(){return new CLB_Conflict(this.name,this.typeID,this.props_)}
;CLB_Conflict.prototype.makeConflictValueString=function(item){if(item.isRemove){return""}if(this.typeID!=null&&(!isDef(item.typeID)||this.typeID!=item.typeID)){return""}var missingProp=false;var valueArray=[];for(var i=0;i<this.props_.length;i++){var prop=this.props_[i];if(!item.hasProperty(prop)){missingProp=true;G_Debug(this,"Warning: item "+item.itemID+" doesn't have prop "+prop+" needed for conflict resolution")}else{valueArray.push(item.getProperty(prop))}}if(missingProp&&parseInt(valueArray.length)
>0){G_Debug(this,"Error: cannot create conflict string for item "+item.itemID+" because only some required fields are present.");return null}return valueArray.join(CLB_Conflict.CONFLICT_VALUE_SEPARATOR)}
;CLB_Conflict.prototype.addConflictValue=function(conflictValue,lookupKey){if(conflictValue==""||isNull(conflictValue)){return}if(isDef(this.conflictValues_[conflictValue])&&this.conflictValues_[conflictValue]!=lookupKey){G_Debug(this,"Error: same conflict value: "+conflictValue+" found for "+lookupKey+" and "+this.conflictValues_[conflictValue]);return}this.conflictValues_[conflictValue]=lookupKey}
;CLB_Conflict.prototype.removeConflictValue=function(conflictValue,lookupKey){if(conflictValue==""||isNull(conflictValue)){return}if(isDef(this.conflictValues_[conflictValue])&&this.conflictValues_[conflictValue]==lookupKey){delete this.conflictValues_[conflictValue]}else{G_Debug(this,"Warning: trying to delete a conflict value that does not exist for conflict "+this.name)}}
;CLB_Conflict.prototype.updateConflictValues=function(oldItem,newItem){var lookupKey=oldItem.makeLookupKey();var newLookupKey=newItem.makeLookupKey();if(lookupKey!=newLookupKey){G_Debug(this,"Error: cannot update conflict values for two different items: "+lookupKey+" and "+newLookupKey);return}var oldConflictValue=this.makeConflictValueString(oldItem);var conflictValue=this.makeConflictValueString(newItem);if(newItem.isRemove){this.removeConflictValue(oldConflictValue,lookupKey)}else{if(oldConflictValue!=
function CLB_ConflictResolver(registeredConflicts,componentsHash,sendToServerQueue,applyLocallyQueue){this.initializeRegisteredConflicts(registeredConflicts);this.componentsHash_=componentsHash;this.sendToServerQueue_=sendToServerQueue;this.applyLocallyQueue_=applyLocallyQueue}
CLB_ConflictResolver.prototype.initializeRegisteredConflicts=function(registeredConflicts){this.registeredConflicts_={};for(var componentID in registeredConflicts){var conflicts=registeredConflicts[componentID];var clonedConflicts=[];conflicts.forEach(function(conflict){clonedConflicts.push(conflict.cloneWithoutValues())}
;CLB_ConflictResolver.prototype.addToConflictMaps=function(item){if(item.isRemove){return}var conflicts=this.registeredConflicts_[item.componentID];if(isDef(conflicts)){conflicts.forEach(function(conflict){var conflictValue=conflict.makeConflictValueString(item);if(conflictValue==null){G_Debug(this,"Error: Cannot perform conflict resolution on item "+item.itemID+" because a partial update contains only some of the properties required for conflict"+conflict.name)}else{var lookupKey=item.makeLookupKey(
);conflict.addConflictValue(conflictValue,lookupKey);G_Debug(this,"Adding value for conflict type: "+conflict.name)}}
;if(!compItem){G_Debug(this,"Warning - component returned null for getItemByID, continuing with an item that might be a partial update")}else{if(compItem.itemID!=offlineItem.itemID||compItem.typeID!=offlineItem.typeID){G_Debug(this,"Error, component returned an item with a different id or typeID, continuing with an item that might be a partial update")}else{offlineItem=compItem;this.updateConflictMaps([offlineItem],false);this.sendToServerQueue_.replaceItem(offlineItem)}}}var changed=CLB_UpdateQueue.smooshItems(
;CLB_ConflictResolver.prototype.resolveItemConflicts=function(syncedItem,conflict,resolvedItems){var syncedLookupKey=syncedItem.makeLookupKey();var conflictValue=conflict.makeConflictValueString(syncedItem);G_Debug(this,"Conflict: "+conflict.name+" value: "+conflictValue);if(conflictValue==""||!conflict.hasConflictValue(conflictValue)){return false}if(conflictValue==null){G_Debug(this,"Error: Cannot perform conflict resolution on item "+syncedItem.itemID+" because a partial update contains only some of the properties required for conflict"
+conflict.name);return false}var conflictLookupKey=conflict.getLookupKey(conflictValue);if(conflictLookupKey==syncedLookupKey){G_Debug(this,"Skipping conflict on value: "+conflictValue+" because items have the same lookupID: "+syncedLookupKey);return false}var conflictItem=this.findInLocalOrServerQueue(conflictLookupKey);if(!conflictItem){G_Debug(this,"Error: Could not find item in updateQueue and syncQueue for lookup key: "+conflictLookupKey);return false}var comp=this.componentsHash_[syncedItem.componentID]
;var resolvedEnum=comp.onItemConflict(conflict.name,syncedItem,conflictItem.clone());var newLookup=syncedItem.makeLookupKey();if(newLookup!=syncedLookupKey){G_Debug(this,"Error, component changed syncItem lookup value. This should never happen - instead, component should return the item with a different ID in the enumerator")}while(resolvedEnum.hasMoreElements()){var resolved=resolvedEnum.getNext();if(resolved.itemID==syncedItem.itemID){G_Debug(this,"Error: component should not return an update to the synced item - it should modify the item directly"
)}else{resolvedItems.push(resolved)}}G_Debug(this,"Total items returned for conflict resolution: "+resolvedItems.length);return true}
,this);this.updateConflictMaps([syncedItem],false);if(shouldUploadItem){G_Debug(this,"Uploading the synced item to the server, since it changed");this.sendToServerQueue_.replaceItem(syncedItem)}G_Debug(this,"Returning "+resolvedItems.length+" extra items");return resolvedItems}
function CLB_CookieSyncer(){this.observersSetup_=false;this.lastSyncedCookies_=null;this.talkingToServer_=false;this.prefs=new G_Preferences("network.cookie.");this.cookiesEnabled=this.prefs.getPref("cookieBehaviour",0)==0;this.cookieSvc_=Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService);this.cookieMan_=Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager);this.obsSvc_=Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);this.ioSvc_=Cc["@mozilla.org/network/io-service;1"
].getService(Ci.nsIIOService)}
CLB_CookieSyncer.prototype.componentID="@google.com/browserstate/cookie-syncer;1";CLB_CookieSyncer.prototype.syncBehavior=Ci.GISyncComponent.SYNC_SINCE_LAST_UPDATE;CLB_CookieSyncer.prototype.componentName="Cookies";CLB_CookieSyncer.prototype.encryptionRequired=true;CLB_CookieSyncer.prototype.syncOfflineChanges=true;CLB_CookieSyncer.prototype.updateStart=(CLB_CookieSyncer.prototype.syncStart=function(){this.talkingToServer_=true;G_Debug(this,"Set talkingToServer to true")}
);CLB_CookieSyncer.prototype.updateComplete=(CLB_CookieSyncer.prototype.updateFailure=(CLB_CookieSyncer.prototype.syncComplete=(CLB_CookieSyncer.prototype.syncFailure=function(){this.talkingToServer_=false;G_Debug(this,"Set talkingToServer to false")}
;CLB_CookieSyncer.prototype.observe=function(cookie,topic,data){G_Debug(this,"caught topic/data {%s/%s}".subs(topic,data));if(topic!="cookie-changed"){G_Debug(this,"Skipping unexpected topic {%s}".subs(topic));return}if(data=="cleared"){G_Debug(this,"Sending removes for {%s} known cookies".subs(this.lastSyncedCookies_.__count__));for(var itemID in this.lastSyncedCookies_){CLB_syncMan.update(new CLB_SyncItem({itemID:itemID,componentID:this.componentID,isRemove:true}))}this.lastSyncedCookies_={};return}
cookie.QueryInterface(Ci.nsICookie);var syncItem;if(this.talkingToServer_&&cookie.host==".google.com"&&cookie.name=="PREF"){G_Debug(this,"Skipping google PREF cookie during update");return}if(data=="deleted"){syncItem=CLB_CookieSyncer.createBlankSyncItem(cookie);syncItem.isRemove=true;if(syncItem){G_Debug(this,"Sending delete: "+syncItem);CLB_syncMan.update(syncItem);delete this.lastSyncedCookies_[syncItem.itemID]}return}if(data=="added"||data=="changed"){syncItem=CLB_CookieSyncer.createSyncItem(
cookie);if(syncItem){G_Debug(this,"Sending update: "+syncItem);CLB_syncMan.update(syncItem);this.lastSyncedCookies_[syncItem.itemID]=syncItem.clone()}return}G_DebugL(this,"ERROR: Unexpected value for data parameter {%s}".subs(data))}
;CLB_CookieSyncer.prototype.removeCookie=function(syncItem){G_Debug(this,"Removing cookie: "+syncItem);this.initLastSyncedCookies_();var candidate=this.lastSyncedCookies_[syncItem.itemID];if(!candidate){G_DebugL(this,"WARNING: Could not find cookie. Ignoring.");return}if(!candidate.hasProperty("host")||!candidate.hasProperty("name")||!candidate.hasProperty("path")){G_Debug(this,"ERROR: Incomplete candidate returned from cookie "+"enumerator. Ignoring. Item returned: {%s}".subs(candidate));return}
this.cookieMan_.remove(candidate.getProperty("host"),candidate.getProperty("name"),candidate.getProperty("path"),false);G_Debug(this,"Found and removed cookie.");delete this.lastSyncedCookies_[syncItem.itemID]}
;CLB_CookieSyncer.createBlankSyncItem=function(cookie){return new CLB_SyncItem({componentID:CLB_CookieSyncer.prototype.componentID,itemID:CLB_CookieSyncer.createItemId_(cookie)})}
var CLB_Crypter={};CLB_Crypter.uniqueCount_=0;CLB_Crypter.startDate_=null;CLB_Crypter.cache_={};CLB_Crypter.debugZone="CLB_Crypter";CLB_Crypter.DELIMITER="|";CLB_Crypter.VERSION_DELIMITER="*";CLB_Crypter.unicodeConverter=Cc["@mozilla.org/intl/scriptableunicodeconverter"].getService(Ci.nsIScriptableUnicodeConverter);CLB_Crypter.unicodeConverter.charset="UTF-8";CLB_Crypter.toByteArray=function(str){return this.unicodeConverter.convertToByteArray(str,{})}
;CLB_Crypter.decryptString=function(str,key){if(!isString(str)){G_Debug(this,"Error: decryptString expected a string");return""}var versionSplit=str.split(CLB_Crypter.VERSION_DELIMITER);str=versionSplit[0];if(versionSplit.length==1||versionSplit[1]=="1"){var crypter=new ARC4;var split=str.split(CLB_Crypter.DELIMITER);var salt=split[1];str=split[0];if(salt){key+=salt}if(str.length%4!=0){G_Debug(this,"ERROR: String '%s' was not of correct length".subs(str));throw new Error("Length of encoded data must be zero mod four"
{G_Debug(this,"ERROR: String '%s' was not of correct length".subs(str));throw new Error("Length of encoded data must be zero mod four");}if(!salt&&CLB_Crypter.cache_[str]){return CLB_Crypter.cache_[str]}var strArr=CLB_app.base64r.decodeString(str);crypter.setKey(CLB_Crypter.toByteArray(key));crypter.discard(CLB_app.CRYPT_DISCARD_BYTES);crypter.crypt(strArr);var result=CLB_Crypter.fromByteArray(strArr);if(!salt){CLB_Crypter.cache_[str]=result}return result}else{G_DebugL(this,"Error: unknown encryption version encountered"
);throw new Error("Unknown encryption version encountered");}}
function CLB_Downloader(componentsHash,componentsToSync,registeredConflicts,newUpdates,prevLastUpdate,prevLastSync,onSuccess,onFailure,onProgress){bindMethods(this);this.componentsHash=componentsHash;this.componentsToSync={};if(componentsToSync){for(var i=0;i<componentsToSync.length;i++){this.componentsToSync[componentsToSync[i]]=true}}this.prevLastUpdate=prevLastUpdate;this.prevLastSync=prevLastSync;this.newTimestamp=null;this.onProgress=onProgress;this.onSuccess=onSuccess;this.onFailure=onFailure;
;this.newUpdates=newUpdates;this.funQueue.addJob(this.parseOfflineItems)}else{G_Debug(this,"Warning: Not initializing updater - download only mode");this.funQueue.addJob(this.sendSyncReqs)}}
CLB_Downloader.prototype.parseOfflineItems=function(){G_Debug(this,"Parsing offline file");if(!CLB_Updater.hasOfflineData()){G_Debug(this,"No offline data to parse, skipping to addNewUpdates");this.onProgress(CLB_Application.PROGRESS_UNOFFLINING,1);this.addNewUpdatesToServerQueue();return}var doc=G_FirefoxXMLUtils.loadXML(CLB_Updater.getOfflineFile());var items=doc.getElementsByTagName("item");var numItems=items.length;var index=0;var cleared=doc.getElementsByTagName("clearedComponents");for(var i=
0;i<cleared.length;i++){var xmlItem=cleared[i];var child=null;for(var u=0;child=xmlItem.childNodes[u];u++){if(child.localName!="component"){G_Debug(this,"WARNING: item within a <clearedComponents> block was not a <component>");continue}var syncItem=new CLB_SyncItem({isRemoveAll:true});syncItem.componentID=child.textContent;this.sendToServerQueue.addItem(syncItem)}}var parseNext=bind(function(){this.onProgress(CLB_Application.PROGRESS_UNOFFLINING,index/numItems);if(index==numItems){G_Debug(this,"Done parsing offline items. Next up: add new updates to serverqueue."
);this.addNewUpdatesToServerQueue();return}G_Debug(this,"Parsing offline item #{%s}".subs(index));var item=this.parseItem(items[index++]);if(item){var comp=CLB_syncMan.getComponent(item.componentID);if(!comp){G_Debug(this,"WARNING: Skipping offline item for unregistered component. Item: "+item)}else if(!comp.syncOfflineChanges){G_Debug(this,"WARNING: Skipping offline item for component which doesn't sync offine changes. Item: "+item)}else{this.sendToServerQueue.addItem(item)}}this.funQueue.addJob(
parseNext)}
,this);G_Debug(this,"There are {%s} offline items to parse".subs(numItems));parseNext()}
;CLB_Downloader.prototype.addNewUpdatesToServerQueue=function(){G_Debug(this,"Adding new updates to server queue...");var index=0;var addNext=bind(function(){if(index==this.newUpdates.length){G_Debug(this,"Done adding new updates. Next up: build conflict maps.");this.onProgress(CLB_Application.PROGRESS_GATHERING,1);this.addPendingToConflictResolver();return}G_Debug(this,"Adding item #{%s} to sendToServerQueue".subs(index));var item=this.newUpdates[index];if(jsInstanceOf(item,Ci.nsISimpleEnumerator)
){G_Debug(this,"Item is an enumerator... adding child...");if(item.hasMoreElements()){this.sendToServerQueue.addItem(item.getNext())}else{index++}}else{this.sendToServerQueue.addItem(item);index++}this.funQueue.addJob(addNext)}
,this);G_Debug(this,"There are {%s} updates to add".subs(this.newUpdates.length));addNext()}
;CLB_Downloader.prototype.addPendingToConflictResolver=function(){G_Debug(this,"Adding pending items to conflict maps");var index=0;var items=this.sendToServerQueue.getPending();var addNext=bind(function(){this.onProgress(CLB_Application.PROGRESS_INDEXING,index/items.length);if(index==items.length){G_Debug(this,"Done adding items to conflict maps. Next up: send sync reqs");this.sendSyncReqs();return}G_Debug(this,"Adding item #{%s} to conflict map".subs(index));this.conflictResolver.addToConflictMaps(
items[index++]);this.funQueue.addJob(addNext)}
,this);G_Debug(this,"There are {%s} items to add".subs(items.length));addNext()}
;CLB_Downloader.prototype.sendSyncReqs=function(){G_Debug(this,"Sending sync requests");this.onProgress(CLB_Application.PROGRESS_DOWNLOADING,0);var lastSyncComponents=[];var lastUpdateComponents=[];var everythingComponents=[];for(var component in this.componentsHash){if(this.componentsToSync[component]){everythingComponents.push(this.componentsHash[component].componentID)}else if(this.componentsHash[component].syncBehavior==Ci.GISyncComponent.SYNC_SINCE_LAST_SYNC){lastSyncComponents.push(this.componentsHash[
component].componentID)}else{lastUpdateComponents.push(this.componentsHash[component].componentID)}}if(everythingComponents.length>0){G_Debug(this,"Sending a request for everything from components: "+everythingComponents.join(","));this.sendSyncReq(everythingComponents,(new Date(0)).toISO8601String())}if(lastSyncComponents.length>0){G_Debug(this,"Sending a request for deltas since last sync from components: "+lastSyncComponents.join(","));this.sendSyncReq(lastSyncComponents,this.prevLastSync)}if(
lastUpdateComponents.length>0){G_Debug(this,"Sending a request for deltas since last update from components: "+lastUpdateComponents.join(","));this.sendSyncReq(lastUpdateComponents,this.prevLastUpdate)}if(!lastUpdateComponents.length&&!lastSyncComponents.length&&!everythingComponents.length){G_Debug(this,"No components to be sent");this.resolveConflicts()}}
;CLB_Downloader.prototype.sendSyncReq=function(components,timestamp){var doc=CLB_XMLUtils.getDoc("SyncRequest",{uid:CLB_app.getSID(),mid:CLB_app.getMID(),key:CLB_app.getEncryptedKey()});CLB_XMLUtils.addElm(doc.documentElement,"timestamp",timestamp);var componentsElm=doc.createElement("components");doc.documentElement.appendChild(componentsElm);for(var i=0;i<components.length;i++){CLB_XMLUtils.addElm(componentsElm,"component",components[i])}G_Debug(this,"Sending sync request with document:\n"+G_FirefoxXMLUtils.getXMLString(
;CLB_Downloader.prototype.onError=function(code,status,message){G_Debug(this,"Got error during download. Code: %s, status: %s, message: %s".subs(code,status,message));this.abort();this.onFailure(code,status,message)}
;CLB_Downloader.prototype.onLoad=function(req){try{if(CLB_app.prefs.getPref("log-xml",false)){var file=CLB_app.getUniqueTempFile("download","xml");G_FileWriter.writeAll(file,req.responseText);G_Debug(this,"logged download in file: "+file.path)}var items=req.responseXML.getElementsByTagName("item");G_Debug(this,"Number of items downloaded: {%s}".subs(items.length));this.newTimestamp=CLB_XMLUtils.getTimestamp(req.responseXML);for(var i=0;i<items.length;i++){this.downloadedItems.push(items[i])}this.reqs.splice(
this.reqs.indexOf(req),1);if(this.reqs.length>0){return}this.onProgress(CLB_Application.PROGRESS_DOWNLOADING,1);G_Debug(this,"Total number of items downloaded: {%s}".subs(this.downloadedItems.length));this.parseDownloadedItems()}catch(e){this.onFailure(-1,"Unexpected error",e.toString());throw e;}}
syncItem.componentID);if(!comp){G_DebugL(this,"ERROR: Could not find component with ID: {"+syncItem.componentID+"} for item {"+syncItem.itemID+"} . Dropping.")}else{var lookupKey=syncItem.makeLookupKey();var prevItem=this.parsedSyncItems.getItemByLookupKey(lookupKey);var compIsEncrypted=CLB_syncMan.isEncryptedComponent(comp.componentID);if(prevItem&&prevItem.originallyEncrypted==compIsEncrypted){G_Debug(this,"Smooshing previous item on top of synced item because there are two items with the same ID and the previous one is in the correct encryption state."
,this);G_Debug(this,"There are {%s} items to check for conflicts".subs(this.parsedSyncItems.pendingSize()));resolveNext()}
;CLB_Downloader.prototype.startUpdate=function(){if(this.sendToServerQueue.pendingSize()>0){G_Debug(this,"Sending {%s} items to the server".subs(this.sendToServerQueue.pendingSize()));this.updater=new CLB_Updater;this.updater.start(this.sendToServerQueue.getPending(),false,this.updateComplete,this.onFailure,this.onProgress,true,false)}else{G_Debug(this,"There are zero updates to send.");this.updateComplete()}}
;CLB_Downloader.prototype.updateComplete=function(opt_newLastUpdate){G_Debug(this,"Update successful. Next up: apply local changes");if(opt_newLastUpdate){this.newTimestamp=opt_newLastUpdate}this.applyLocalChanges()}
;CLB_Downloader.prototype.applyLocalChanges=function(){G_Debug(this,"Applying local changes");var index=0;var items=this.applyLocallyQueue.getPending();var applyNext=bind(function(){if(index==items.length){G_Debug(this,"Done applying local changes. Firing success handler!");this.onSuccess(this.newTimestamp);return}G_Debug(this,"Apply local change #{%s}".subs(index));this.onProgress(CLB_Application.PROGRESS_APPLYING,index/items.length);var syncItem=items[index++];var comp=CLB_syncMan.getComponent(
;CLB_HistoryEnumerator.prototype.advanceHistoryItem_=function(){this.nextHistoryItem_=null;while(this.nextHistoryItem_==null&&this.histEnumerator_.hasMoreElements()){var candidate=this.histEnumerator_.getNext();if(!(candidate instanceof Ci.nsIRDFResource)){G_Debug(this,"Failed to cast a resource to nsIRDFResource");continue}var root=CLB_app.historySyncer.histRdfServ_.GetResource(CLB_HistorySyncer.rootRdfStr);var childArc=CLB_app.historySyncer.histRdfServ_.GetResource(CLB_HistorySyncer.childRdfStr)
function CLB_HistorySyncer(){this.hist_=Cc["@mozilla.org/browser/global-history;2"].getService(Ci.nsIGlobalHistory2).QueryInterface(Ci.nsIBrowserHistory);this.histDS_=Cc["@mozilla.org/rdf/datasource;1?name=history"].getService(Ci.nsIRDFDataSource);this.histRdfServ_=Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);this.ioSvc_=Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);this.obsSvc_=Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);this.updateBatchData_=
;CLB_HistorySyncer.prototype.componentID="@google.com/browserstate/history-syncer;1";CLB_HistorySyncer.prototype.componentName="History";CLB_HistorySyncer.prototype.encryptionRequred=false;CLB_HistorySyncer.prototype.syncOfflineChanges=true;CLB_HistorySyncer.prototype.syncBehavior=Ci.GISyncComponent.SYNC_SINCE_LAST_UPDATE;CLB_HistorySyncer.prototype.start=function(){G_Debug(this,"Starting history syncer");if(!this.started_){this.histDS_.AddObserver(this);this.obsSvc_.addObserver(this,"quit-application"
,false);new G_Alarm((function(){if(!this.hasHistoryExpirationFile_()){return}var file=this.getHistoryExpirationFile_();var urls=G_FileReader.readAll(file).split(G_File.LINE_END_CHAR);urls.forEach(function(url){if(url){var item=this.getHistoryDeleteItem_(url);CLB_syncMan.update(item);G_Debug(this,"Sending expired history item "+item)}}
,this);file.remove(false)}
).bind(this),0);this.started_=true}}
;CLB_HistorySyncer.prototype.stop=function(){G_Debug(this,"Stopping history syncer");if(this.started_){this.histDS_.RemoveObserver(this);this.obsSvc_.removeObserver(this,"quit-application");this.started_=false}}
;CLB_HistorySyncer.prototype.onItemAvailable=function(item){if(this.started_){G_Debug(this,"Error: onItemAvailable called while component is started");return}this.initializeHistory_();this.addHistoryItem_(item)}
;CLB_HistorySyncer.prototype.getCurrentItems=function(){this.initializeHistory_();var e=this.histDS_.GetAllResources();return new CLB_HistoryEnumerator(e)}
;CLB_HistorySyncer.prototype.onChange=function(aDataSource,aSource,aProperty,aOldTarget,aNewTarget){var newValue=CLB_rdf.getValueFromNode(aNewTarget);if(!newValue){G_Debug(this,"Could not extract value from target, skipping");return}G_Debug(this,"onChange: "+aSource.Value+" "+aProperty.Value+" changed to "+newValue+"\n\n");var item=this.getUpdateItem_(aSource,aProperty,newValue,false);if(item){CLB_syncMan.update(item)}}
;CLB_HistorySyncer.prototype.onAssert=function(aDataSource,aSource,aProperty,aTarget){var value=CLB_rdf.getValueFromNode(aTarget);if(!value){G_Debug(this,"Could not extract value from target, skipping");return}G_Debug(this,"onAssert: "+aSource.Value+" "+aProperty.Value+" "+value+"\n\n");var item=this.getUpdateItem_(aSource,aProperty,value,false);if(item){CLB_syncMan.update(item)}}
;CLB_HistorySyncer.prototype.onUnassert=function(aDataSource,aSource,aProperty,aTarget){var value=CLB_rdf.getValueFromNode(aTarget);if(!value){G_Debug(this,"Could not extract value from target, skipping");return}G_Debug(this,"onUnassert: "+aSource.Value+" "+aProperty.Value+" "+value+"\n\n");var item=this.getUpdateItem_(aSource,aProperty,value,true);if(item){CLB_syncMan.update(item)}}
;CLB_HistorySyncer.prototype.onMove=function(aDataSource,aOldSource,aNewSource,aProperty,aTarget){G_Debug(this,"onMove: "+aOldSource.Value+" "+aNewSource.Value+" "+aProperty.Value+" "+aTarget.value+"\n\n");G_Debug(this,"WARNING: unexpected move from history component")}
;CLB_HistorySyncer.prototype.onEndUpdateBatch=function(aDataSource){G_Debug(this,"onEndUpdateBatch!!");var root=this.histRdfServ_.GetResource(CLB_HistorySyncer.rootRdfStr);var childArc=this.histRdfServ_.GetResource(CLB_HistorySyncer.childRdfStr);var targets=this.histDS_.GetTargets(root,childArc,true);while(targets.hasMoreElements()){var tar=targets.getNext();var url=CLB_rdf.getValueFromNode(tar);if(this.updateBatchData_[url]){delete this.updateBatchData_[url]}else{G_Debug(this,"Warning - something was added during the batch update: "
+url)}}if(this.inShutdown_){this.inShutdown_=false;var urlsToFlush=[];for(var hist in this.updateBatchData_){urlsToFlush.push(hist)}if(urlsToFlush.length>0){var expiredFile=this.getHistoryExpirationFile_();G_FileWriter.writeAll(expiredFile,urlsToFlush.join(G_File.LINE_END_CHAR));G_Debug(this,"Wrote history expiration file with "+urlsToFlush.length+"urls")}}else{for(var hist in this.updateBatchData_){var item=this.getHistoryDeleteItem_(hist);CLB_syncMan.update(item)}}this.updateBatchData_={}}
;CLB_HistorySyncer.prototype.addHistoryItem_=function(item){G_Debug(this,"About to add history with syncitem: "+item.toStringVerbose()+"\n");if(!isDef(item.itemID)){G_Debug(this,"Warning: itemID is null, skipping!!\n");return}var uri=this.ioSvc_.newURI(item.itemID,null,null);if(item.isRemove){this.hist_.removePage(uri);return}var name=item.getProperty(this.propertiesToCollect_.getKey(CLB_HistorySyncer.nameRdfStr));var firstDate=item.getProperty(this.propertiesToCollect_.getKey(CLB_HistorySyncer.firstDateRdfStr)
);var date=item.getProperty(this.propertiesToCollect_.getKey(CLB_HistorySyncer.dateRdfStr));var visitCount=item.getProperty(this.propertiesToCollect_.getKey(CLB_HistorySyncer.visitCountRdfStr));if(!isDef(name)||!isDef(firstDate)||!isDef(date)||!isDef(visitCount)){G_Debug(this,"Warning: some fields are undefined, skipping history item");return}if(!this.hist_.isVisited(uri)){this.hist_.addPageWithDetails(uri,name,firstDate)}var urlNode=this.histRdfServ_.GetResource(item.itemID);var currentCount=this.getVisitCount_(
urlNode);if(currentCount==0){G_Debug(this,"WARNING: failed to retrieve current visit count. Skipping history item "+item.itemID);return}while(currentCount<visitCount){this.hist_.addPageWithDetails(uri,name,date);currentCount++}}
{item.isRemove=true;return item}this.fillHistoryItemDetails_(item,valueNode);return item}if(this.propertiesToCollect_.hasValue(propValue)){if(isRemove){G_Debug(this,"WARNING: unassert called on something other than url");return null}this.setRequiredFields_(item,srcValue);this.fillHistoryItemDetails_(item,aSource);item.isRemove=false;return item}G_Debug(this,"Error, cannot make update out of unexpected assertion, returning null");return null}
function CLB_InfoBubble(root,tabbedBrowserWatcher,width){bindMethods(this);this.hidden=true;this.root_=root;this.inner_=root.firstChild;this.head_=root.previousSibling;this.tail_=root.nextSibling;this.parts_=[this.head_,this.root_,this.tail_];this.repaintAlarm_=null;this.width_=width;this.root_.style.width=width+"px";this.inner_.style.width=width-CLB_InfoBubble.INNER_BUBBLE_DIFFERENCE+"px";this.doc_=this.root_.ownerDocument;this.win_=this.doc_.defaultView;this.tabbedBrowserWatcher_=tabbedBrowserWatcher;
var elms=this.root_.getElementsByTagName("*");for(var i=0,elm=null;elm=elms[i];i++){switch(elm.className){case "clb-infobubble-desc":this.desc_=elm;break;case "clb-infobubble-buttons":this.buttonsContainer_=elm;break;case "clb-infobubble-close":this.closeButton_=elm;break}}this.tabbedBrowserWatcher_.registerListener("tabswitch",this.handleTabSwitch_);this.win_.addEventListener("unload",this.handleUnload_,false);this.win_.addEventListener("resize",this.handleResize_,false);CLB_InfoBubble.nextInstanceId_++
CLB_InfoBubble.ARROW_WIDTH=20;CLB_InfoBubble.ARROW_HEIGHT=20;CLB_InfoBubble.ROOT_OFFSET=50;CLB_InfoBubble.ARROW_OFFSET=16;CLB_InfoBubble.ROOT_MIN_RIGHT=25;CLB_InfoBubble.ROOT_MIN_LEFT=4;CLB_InfoBubble.INNER_BUBBLE_DIFFERENCE=16;CLB_InfoBubble.HIDE_DELAY_MILLISECONDS=10000;CLB_InfoBubble.instances_={};CLB_InfoBubble.nextInstanceId_=1;CLB_InfoBubble.allHidden=false;CLB_InfoBubble.hideAll=function(){G_Debug("CLB_InfoBubble","hiding all");for(var bubble in this.instances_){G_Debug("CLB_InfoBubble",bubble)
;CLB_InfoBubble.repositionAll=function(anchor){G_Debug("CLB_InfoBubble","reshowing all");for(var bubble in this.instances_){G_Debug("CLB_InfoBubble",bubble);if(!this.instances_[bubble].hidden){this.instances_[bubble].show(anchor)}}G_Debug("CLB_InfoBubble","done")}
;CLB_InfoBubble.repaintAll_=function(){var anyVisible=false;for(var id in this.instances_){if(!this.instances_[id].hidden){anyVisible=true;this.instances_[id].repaint_()}}if(!anyVisible){if(this.repaintAlarm_){this.repaintAlarm_.cancel();this.repaintAlarm_=null}}}
;CLB_InfoBubble.prototype.show=function(toolbarItem){G_Debug(this,"Showing info bubble");this.toolbarItem_=toolbarItem;this.repaint_();this.hidden=false;CLB_InfoBubble.allHidden=false;if(!CLB_InfoBubble.repaintAlarm_){CLB_InfoBubble.repaintAlarm_=new G_Alarm(CLB_InfoBubble.repaintAll_.bind(CLB_InfoBubble),2000,true)}this.startTimer_()}
;CLB_InfoBubble.prototype.startTimer_=function(){G_Debug(this,"Starting timer to wait before hooking up onLocationChange");if(this.hideAlarm_){G_Debug(this,"cancelling existing hide alarm...");this.hideAlarm_.cancel()}this.hideAlarm_=new G_Alarm(this.waitForLocationChange_,CLB_InfoBubble.HIDE_DELAY_MILLISECONDS)}
;CLB_InfoBubble.prototype.waitForLocationChange_=function(){G_Debug(this,"Timer elapsed. Waiting for location change.");this.hideAlarm_=null;this.tabbedBrowserWatcher_.registerListener("locationchange",this.handleLocationChange_)}
;CLB_InfoBubble.prototype.handleLocationChange_=function(){G_Debug(this,"Got location change. Hiding all info bubbles.");this.tabbedBrowserWatcher_.removeListener("locationchange",this.handleLocationChange_);CLB_InfoBubble.hideAll()}
;CLB_LoginUtil.prototype.showErrorMessage=function(parentWin,responseString){var resp=this.parseResponse(responseString);var code=resp["Error"];if(code=="cr"){parentWin.alert("The specified Google account has been temporarily locked. Please verify your account and then reconnect to Google Browser Sync.");CLB_app.setStatus(CLB_Application.STATUS_NEEDS_CAPTCHA);CLB_app.errorURL=resp["Url"];return false}var msg={badauth:"Incorrect username or password. Please try again.",adel:"The specified Google account has been deleted."
,adis:"The specified Google account has been disabled.",nv:"The specified Google account's email address has not been verified.",tna:"The specified Google user has not agreed to the terms of service.",ire:"Authentication server temporarily unavailable. Please try again later.",unknown:"Unknown authentication server error. Please try again later."}[code];if(!msg){msg="Unknown server error. Please try again later."}parentWin.alert(msg);return true}
;CLB_LoginUtil.prototype.encodeParams_=function(params){var s=[];for(var p in params){s.push(encodeURIComponent(p));s.push("=");s.push(encodeURIComponent(params[p]));s.push("&")}return s.join("")}
function CLB_PasswordForm(win){this.win_=win;this.args_=this.win_.arguments[0].QueryInterface(Ci.nsIWritablePropertyBag);this.args_.setProperty("success",false);this.args_.setProperty("password","")}
function CLB_PasswordSyncer(){this.passMan_=null;this.lastSyncedState_={};this.lastModified_=null;this.signonsFile_=null;this.enabled_=null;this.knownMasterPassword_="";this.promptSvc_=Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci.nsIPromptService)}
function(){if(!this.passMan_){this.passMan_=Cc["@mozilla.org/passwordmanager;1"].getService();this.passMan_.QueryInterface(Ci.nsIPasswordManager);this.passMan_.QueryInterface(Ci.nsIPasswordManagerInternal)}this.unlockPasswordStore();G_Debug(this,"Password Syncer is %s".subs(this.enabled_?"enabled":"disabled"));if(!this.signonsFile_){this.signonsFile_=G_File.getProfileFile("signons.txt");if(this.signonsFile_.exists()){this.lastModified_=this.signonsFile_.lastModifiedTime;this.lastSyncedState_=this.getCurrentItems_(
)}else{G_Debug(this,"Passwords file did not exist")}}}
;CLB_PasswordSyncer.prototype.checkMasterPassword_=function(){var token=Cc["@mozilla.org/security/pk11tokendb;1"].createInstance(Ci.nsIPK11TokenDB).getInternalKeyToken();var valid=false;try{valid=token.checkPassword("");if(!valid&&this.knownMasterPassword_){valid=token.checkPassword(this.knownMasterPassword_)}}catch(e){valid=true}while(!valid){var password={value:""};if(this.promptSvc_.promptPassword(null,"Google Browser Sync needs your Master Password","Google Browser Sync needs your Firefox Master Password in order to sync your passwords, please enter it below."
,password,null,{})){valid=token.checkPassword(password.value);if(valid){G_Debug(this,"User's password was valid.");this.knownMasterPassword_=password.value}else{G_Debug(this,"User's password was not valid.")}}else{G_Debug(this,"User pressed cancel, giving up.");return false}}return valid}
;CLB_PasswordSyncer.prototype.onItemConflict=function(name,oldItem,newItem){return new CLB_ArrayEnumerator([])}
;CLB_PasswordSyncer.prototype.onItemAvailable=function(item){this.initPassMan_();if(!this.enabled_){return}G_Debug(this,"Item %s available".subs(item));if(item.isRemove){if(!isDef(item.itemID)){G_DebugL(this,"ERROR: received item does not have an itemID.");return}if(!this.lastSyncedState_[item.itemID]){G_DebugL(this,"ERROR: Could not find entry in lastSyncedState_ "+"corresponding to itemID {%s}".subs(item.itemID));return}this.removeFromPassMan_(this.lastSyncedState_[item.itemID]);delete this.lastSyncedState_[
item.itemID]}else{if(item.typeID==CLB_PasswordSyncer.TYPE_REJECT){if(!item.hasProperty("host")){G_DebugL(this,"ERROR: Received reject does not has a host property");return}this.passMan_.addReject(item.getProperty("host"))}else{if(!item.hasProperty("host")||!item.hasProperty("user")||!item.hasProperty("password")){G_DebugL(this,"ERROR: Received password does not have required properties.");return}this.passMan_.addUserFull(item.getProperty("host"),item.getProperty("user"),item.getProperty("password"
;CLB_PasswordSyncer.prototype.getCurrentItems=function(){this.initPassMan_();if(!this.enabled_){return new CLB_ArrayEnumerator([])}var arr=[];var currentItems=this.getCurrentItems_();for(var itemID in currentItems){arr.push(currentItems[itemID])}return new CLB_ArrayEnumerator(arr)}
;CLB_PasswordSyncer.prototype.beforeUpdate=function(){G_Debug(this,"Password Syncer beforeUpdate");var signonsFileExisted=Boolean(this.signonsFile_);this.initPassMan_();if(!this.enabled_){return}this.signonsFile_=G_File.getProfileFile("signons.txt");if(this.signonsFile_.exists()){if(signonsFileExisted&&this.lastModified_==this.signonsFile_.lastModifiedTime){G_Debug(this,"Passwords have NOT been modified");return}}else{G_Debug(this,"Password file did not exist");return}G_Debug(this,"Passwords have been modified"
);if(!signonsFileExisted){this.lastSyncedState_={}}var currentItems=this.getCurrentItems_();for(var itemID in currentItems){var item=currentItems[itemID];if(isDef(item.itemID)&&!isDef(this.lastSyncedState_[item.itemID])){G_Debug(this,"Sending addition {%s} to syncman".subs(item));CLB_syncMan.update(item.clone())}}for(var itemID in this.lastSyncedState_){var item=this.lastSyncedState_[itemID];if(isDef(item.itemID)&&!isDef(currentItems[item.itemID])){item=item.clone();item.clearProperties();item.isRemove=
true;G_Debug(this,"Sending deletion {%s} to syncman".subs(item));CLB_syncMan.update(item)}}this.lastModified_=this.signonsFile_.lastModifiedTime;this.lastSyncedState_=currentItems}
;CLB_PasswordSyncer.prototype.getCurrentItems_=function(){this.initPassMan_();if(!this.enabled_){return{}}var passEnumerator=this.passMan_.enumerator;var rejectEnumerator=this.passMan_.rejectEnumerator;var result={};var passObj;while(passEnumerator.hasMoreElements()){passObj=passEnumerator.getNext().QueryInterface(Ci.nsIPasswordInternal);var syncItem=null;try{syncItem=this.createSyncItem_(passObj,false)}catch(e){if(e.message=="PASSWORD INACCESSIBLE"){G_Debug(this,"ERROR: Password was inaccessible, probably due to encryption, disabling PW syncer and skipping remaining items"
);this.enabled_=false;return result}else{throw e;}}if(syncItem){result[syncItem.itemID]=syncItem}}while(rejectEnumerator.hasMoreElements()){passObj=rejectEnumerator.getNext().QueryInterface(Ci.nsIPasswordInternal);var syncItem=null;try{syncItem=this.createSyncItem_(passObj,true)}catch(e){if(e.message=="PASSWORD INACCESSIBLE"){G_Debug(this,"ERROR: Password was inaccessible, probably due to encryption, disabling PW syncer and skipping remaining items");this.enabled_=false;return result}else{throw e;
;CLB_PasswordSyncer.prototype.removeFromPassMan_=function(item){var host=item.getProperty("host");var user=item.getProperty("user");if(item.typeID==CLB_PasswordSyncer.TYPE_REJECT){try{this.passMan_.removeReject(host)}catch(e){G_DebugL(this,"ERROR: Failed to remove reject '%s' with error '%s'".subs(host,e))}}else{try{this.passMan_.removeUser(host,user)}catch(e){G_DebugL(this,"Failed to remove user from host '%s' with error '%s'".subs(host,e))}}}
;CLB_PasswordSyncer.prototype.createSyncItem_=function(passObject,isReject){var syncItem=new CLB_SyncItem;syncItem.componentID=this.componentID;try{var test=passObject.user+passObject.password;G_Debug(this,"Got password object: "+isDef(test))}catch(e){G_Debug(this,"Password was not accessible, perhaps due to master "+"password blocking. Error: %s".subs(e));throw new Error("PASSWORD INACCESSIBLE");}if(isReject){syncItem.typeID=CLB_PasswordSyncer.TYPE_REJECT;syncItem.setProperty("host",passObject.host)
function CLB_PreferencesSyncer(componentID,componentName,debugZone,prefNames,opt_encryptionRequired){bindMethods(this);this.componentID=componentID;this.componentName=componentName;this.encryptionRequired=!(!opt_encryptionRequired);this.syncBehavior=Ci.GISyncComponent.SYNC_SINCE_LAST_UPDATE;this.debugZone=debugZone;this.prefNames_={};this.prefs_=new G_Preferences;this.started_=false;this.syncedItems=[];for(var i=0;i<prefNames.length;i++){this.prefNames_[prefNames[i]]=1}CLB_syncMan.addObserver(this)
;CLB_PreferencesSyncer.prototype.handlePrefChange_=function(prefName){G_Debug(this,"Got change on pref {%s}".subs(prefName));var valid=false;for(var watchedPrefName in this.prefNames_){if(prefName.indexOf(watchedPrefName)==0){valid=true;break}}if(!valid){G_Debug(this,"Skipping because we aren't watching this pref");return}var syncItem=new CLB_SyncItem({componentID:this.componentID,itemID:prefName});var prefVal=this.prefs_.getPref(prefName);if(!isDef(prefVal)){syncItem.isRemove=true}else{syncItem.setProperty(
var CLB_rdf=new Object;CLB_rdf.debugZone="CLB_rdf";CLB_rdf.rdfIFaces=["nsIRDFLiteral","nsIRDFResource","nsIRDFBlob","nsIRDFInt","nsIRDFDate","nsIRDFNode"];CLB_rdf.getValueFromNode=function(node){for(var i=0;i<CLB_rdf.rdfIFaces.length;i++){var iface=CLB_rdf.rdfIFaces[i];if(node instanceof Ci[iface]){return node.Value}}G_DebugL(this,"Warning - node has no type");return null}
;CLB_rdf.getRdfDs=function(datastore,limit){var t="";var all_res=datastore.GetAllResources();for(var r=0;all_res.hasMoreElements();r++){if(limit>0&&t.length>limit){return t}var res=all_res.getNext();if(!(res instanceof Components.interfaces.nsIRDFResource)){G_DebugL(this,"Failed to cast a resource to nsIRDFResource");continue}var tr=r+" R: "+res.Value+G_File.LINE_END_CHAR;var ps=datastore.ArcLabelsOut(res);while(ps.hasMoreElements()){var predicate=ps.getNext();if(!(predicate instanceof Components.interfaces.nsIRDFResource)
){G_DebugL(this,"Failed to cast a predicate to nsIRDFResource");continue}try{tr+=" -R: "+predicate.Value+G_File.LINE_END_CHAR;var ts=datastore.GetTargets(res,predicate,true);while(ts.hasMoreElements()){var target=ts.getNext();var tmp="";for(var i=0;i<CLB_rdf.rdfIFaces.length;i++){var iface=CLB_rdf.rdfIFaces[i];if(target instanceof Ci[iface]){tmp=" "+iface+": "+target.Value+G_File.LINE_END_CHAR;break}}if(tmp==""){tr+=" UNKNOWN NODE TYPE"+G_File.LINE_END_CHAR}else{tr+=tmp}}}catch(e){tr+=" >R: EMPTY VALUE"
var CLB_RequestFactory={};CLB_RequestFactory.debugZone="CLB_RequestFactory";CLB_RequestFactory.PING="http://www.google.com/about.html";CLB_RequestFactory.AUTHENTICATE="https://www.google.com/accounts/ClientAuth";CLB_RequestFactory.GENERATE_KEY="https://www.google.com/safebrowsing/getkey";CLB_RequestFactory.USER_EXISTS="/verify_user_exists";CLB_RequestFactory.ADD_CLIENT="/add_client";CLB_RequestFactory.CREATE_USER="/create_user";CLB_RequestFactory.START_SESSION="/start_session";CLB_RequestFactory.UPDATE=
;CLB_RequestFactory.getRequest=function(urlType,querystring,onSuccess,onFailure,opt_onProgress,opt_useGet){var url=this.getURL(urlType);var req=Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);var params=[];if(!querystring){querystring={}}if(urlType!=CLB_RequestFactory.PING&&urlType!=CLB_RequestFactory.AUTHENTICATE&&urlType!=CLB_RequestFactory.GENERATE_KEY){querystring["v"]=CLB_app.getVersion()}if(!isEmptyObject(querystring)){for(var name in querystring){params.push(
name+"="+querystring[name])}url+="?"+params.join("&")}req.async=true;G_DebugL(this,"opening %s...".subs(url));req.open(opt_useGet?"GET":"POST",url);req.onload=function(){if(req.status==200){G_DebugL(CLB_RequestFactory,"Received successful response.");onSuccess(req)}else{G_DebugL(CLB_RequestFactory,"Server error for %s. %s %s: %s".subs(url,req.status,req.statusText,req.responseText));onFailure(req.status,req.statusText,req.responseText)}}
;req.onerror=function(){G_DebugL(CLB_RequestFactory,"Could not contact server for: %s".subs(url));onFailure(CLB_RequestFactory.ERR_COULD_NOT_CONTACT_SERVER,"Could not contact server.")}
function CLB_RestoreTabsUI(win,tabBrowser,bubbleRoot,tabbedBrowserWatcher){bindMethods(this);this.win_=win;this.doc_=win.document;this.tabBrowser_=tabBrowser;this.checkboxLookup_={};this.winMed_=Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);this.winWat_=Cc["@mozilla.org/embedcomp/window-watcher;1"].getService(Ci.nsIWindowWatcher);this.toolbarButton_=this.doc_.getElementById("clb-toolbarbutton");var infoBubbleWidth=CLB_app.isLinux()?CLB_RestoreTabsUI.INFO_BUBBLE_WIDTH_LINUX:
,true);this.cleanUpItemsToOpen_();if(!CLB_RestoreTabsUI.observingSyncMan_){G_Debug(this,"Adding static interface to syncman observer.");CLB_syncMan.addObserver(CLB_RestoreTabsUI);CLB_RestoreTabsUI.observingSyncMan_=true;CLB_RestoreTabsUI.checkDupe_(this.win_)}if(CLB_RestoreTabsUI.windowsToOpen_.length&&CLB_app.getStatus()==CLB_Application.STATUS_ONLINE&&!CLB_InfoBubble.allHidden){this.populate_();this.infoBubble_.show(this.toolbarButton_)}}
CLB_RestoreTabsUI.BROWSER_CHROME_URL="chrome://browser/content/browser.xul";CLB_RestoreTabsUI.DISABLED_MESSAGE="No tabs are available to be restored";CLB_RestoreTabsUI.DISABLED_IMAGE="chrome://browserstate/content/restore-disabled.png";CLB_RestoreTabsUI.ENABLED_IMAGE="chrome://browserstate/content/restore.png";CLB_RestoreTabsUI.MAX_URL_LENGTH=25;CLB_RestoreTabsUI.MAX_TITLE_LENGTH=15;CLB_RestoreTabsUI.INFO_BUBBLE_WIDTH=320;CLB_RestoreTabsUI.INFO_BUBBLE_WIDTH_LINUX=350;CLB_RestoreTabsUI.observingSyncMan_=
false;CLB_RestoreTabsUI.windowsToOpen_=[];CLB_RestoreTabsUI.tabsToOpen_={};CLB_RestoreTabsUI.isReconnecting=false;CLB_RestoreTabsUI.addWindowItem=function(item){if(item.getProperty("topWindow")=="true"||this.windowsToOpen_.length==0){this.windowsToOpen_.push(item)}else{this.windowsToOpen_.splice(this.windowsToOpen_.length-2,0,item)}G_Debug(this,"windowsToOpen_ is now: "+this.windowsToOpen_)}
;CLB_RestoreTabsUI.addTabItem=function(item){var winID=item.getProperty("windowID");var tabPos=parseInt(item.getProperty("tabIndex"));var url=item.getProperty("url");if(!isDef(winID)||isNaN(tabPos)||!isDef(url)){G_DebugL(this,"WARNING: Received invalid tab item. Dropping. "+"winID: {%s}, tabPos: {%s}, url: {%s}".subs(winID,tabPos,url));return}var tabList=this.tabsToOpen_[winID];if(!tabList){this.tabsToOpen_[winID]=(tabList=[])}if(tabList[tabPos]){G_DebugL(this,"WARNING: Received tab item {%s} at position {%s} would collide with existing tab item {%s} at that position."
.subs(item.itemID,tabPos,tabList[tabPos].itemID));return}tabList[tabPos]=item;G_Debug(this,"tabsToOpen_ is now: "+this.tabsToOpen_)}
;CLB_RestoreTabsUI.syncComplete=function(){G_Debug(this,"Received syncComplete.");if(!this.isReconnecting){G_Debug(this,"Not showing restore UI because this is a resync or settings change sync.");return}if(!CLB_app.prefs.getPref("restoreui-on-resync",true)){G_Debug(this,"Not showing restore UI because restoreui-on-resync pref is set to false.");return}this.checkDupe_(null);if(!this.windowsToOpen_.length){G_Debug(this,"Not showing restore UI because there are no windows to restore.");return}G_Debug(
this,"Telling instances to restore...");Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService).notifyObservers(this,"clb-show-restore",null);this.isReconnecting=false}
;CLB_RestoreTabsUI.checkDupe_=function(startingWin){G_Debug(this,"Checking whether the synced state is a dupe of the current state");var winMed=Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);var currentWindows=winMed.getEnumerator("navigator:browser");var syncedTabsLookup={};var currentTabsLookup={};var tabBrowser;var win;G_Debug(this,"Iterating current windows... startinWin: "+startingWin);while(currentWindows.hasMoreElements()){win=currentWindows.getNext();G_Debug(
this,"current tabs are: "+currentTabsList);var xor=G_SetXOR(syncedTabsList,currentTabsList).xor;if(xor.length>0){G_Debug(this,"Not a dupe. Continuing...")}else{G_Debug(this,"This is a dupe. Cancelling restore UI.");this.resetItems()}}
;CLB_RestoreTabsUI.prototype.cleanUpItemsToOpen_=function(){var windowsToOpen=CLB_RestoreTabsUI.windowsToOpen_;var tabsToOpen=CLB_RestoreTabsUI.tabsToOpen_;var winItem;G_Debug(this,"Cleaning up items to open");for(var winID in tabsToOpen){for(var i=tabsToOpen[winID].length-1;i>=0;i--){if(!isDef(tabsToOpen[winID][i])){G_DebugL(this,"ERROR: Removing undefined tab position at index "+"{%s} for window {%s}".subs(i,winID));tabsToOpen[winID].splice(i,1)}}}for(var i=windowsToOpen.length-1;i>=0;i--){winItem=
windowsToOpen[i];if(!isDef(tabsToOpen[winItem.itemID])||tabsToOpen[winItem.itemID].length==0){G_Debug(this,"Removing window {%s} from list of windows to open because there are no associated tabs".subs(winItem.itemID));windowsToOpen.splice(i,1)}}}
;CLB_RestoreTabsUI.prototype.populate_=function(){G_Debug(this,"Populating windowsToOpen_: "+CLB_RestoreTabsUI.windowsToOpen_);var windowsToOpen=CLB_RestoreTabsUI.windowsToOpen_;var tabsToOpen=CLB_RestoreTabsUI.tabsToOpen_;var winItem,tabItem;while(this.restoreRows_.firstChild){this.restoreRows_.removeChild(this.restoreRows_.firstChild)}for(var i=0;i<windowsToOpen.length;i++){winItem=windowsToOpen[i];G_Debug(this,"winItem is: "+winItem);for(var j=0;j<tabsToOpen[winItem.itemID].length;j++){tabItem=
tabsToOpen[winItem.itemID][j];G_Debug(this,"tabItem is: "+tabItem);if(!isDef(tabItem)){G_Debug(this,"Skipping undefined tabItem");continue}var row=this.doc_.createElement("row");var checkbox=this.doc_.createElement("checkbox");checkbox.setAttribute("class","clb-restore-checkbox");checkbox.setAttribute("checked",true);checkbox.setAttribute("label",this.ellipsize_(tabItem.getProperty("url"),CLB_RestoreTabsUI.MAX_URL_LENGTH));checkbox.addEventListener("CheckboxStateChange",this.updateRestoreAllEnabled_,
function CLB_SettingsForm(win){bindMethods(this);this.win_=win;this.doc_=this.win_.document;this.dialog_=this.doc_.documentElement;this.componentSelector_=new CLB_ComponentSelector(this.doc_.getElementById("clb-component-selector"));this.promptSvc_=Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci.nsIPromptService);this.okButton_=this.dialog_.getButton("accept");this.resyncButton_=this.doc_.getElementById("clb-resync-button");this.tokenField_=this.doc_.getElementById("clb-restart-text")
;CLB_SettingsForm.prototype.handleUnload=function(){try{CLB_syncMan.removeObserver(this)}catch(e){G_Debug(this,"removeObserver was not required.");return}G_Debug(this,"WARNING: SyncManager observer still existed")}
;CLB_SettingsForm.prototype.handleChangeLoginClicked=function(e){if(this.promptSvc_.confirm(null,"Warning","This will close your open windows and start the Google Browser Sync signup process. Your local settings will not be lost. OK to proceed?")){CLB_app.deleteUserSettings();this.win_.setTimeout(CLB_app.logOff.bind(CLB_app),5)}}
;CLB_SettingsForm.prototype.sendLastUpdates=function(child){G_Debug(this,"Sending last updates.");this.initProgressWin_(child);if(CLB_syncMan.checkSending()){CLB_syncMan.cancelUpdate()}CLB_syncMan.addObserver(this);if(CLB_syncMan.checkPending()){this.stage_=CLB_SettingsForm.LAST_UPDATE;CLB_syncMan.sendPending();return}G_Debug(this,"No pending updates to send. Changing settings.");this.startSettingsChange()}
;CLB_SettingsForm.prototype.syncFailure=function(code,status,message){G_DebugL(this,"Sync Failure - "+[code,status,message]);CLB_syncMan.removeObserver(this);if(!this.progressDlg_.closed){this.progressDlg_.setTimeout("window.close()",10)}if(this.stage_==CLB_SettingsForm.SETTINGS||this.stage_==CLB_SettingsForm.LAST_UPDATE||this.stage_==CLB_SettingsForm.IMPORT){this.win_.alert("Settings change did not complete, please try again later.")}else if(this.stage_==CLB_SettingsForm.RESYNC){this.win_.alert(
"Resync of data did not complete, please try again later.")}}
function CLB_SettingsSyncer(){return new CLB_PreferencesSyncer(CLB_SettingsSyncer.CONTRACT_ID,"Google Browser Sync Settings","CLB_PreferencesSyncer",CLB_SettingsSyncer.PREF_NAMES_)}
;this.handleWindowClosed=function(win){if(win==currentDialog_){currentDialog_=null;dialogClosedHandler_()}else{G_Debug(this,"WARNING: received domwindowclosed event, but not from the current window.")}}
function CLB_SyncingForm(win){this.win=win;this.observing=false;this.loginUtil=new CLB_LoginUtil;this.result=this.win.arguments[0].QueryInterface(Components.interfaces.nsIWritablePropertyBag);this.result.setProperty("success",false);this.result.setProperty("invalidKey",false)}
;CLB_SyncingForm.prototype.handleWorkingOffline=function(){this.promptSvc.alert(this.win,"You Are Working Offline",CLB_Application.MESSAGE_WORKING_OFFLINE);CLB_app.setStatus(CLB_Application.STATUS_OFFLINE);this.win.setTimeout("window.close()",0)}
;CLB_SyncingForm.prototype.handleBackedOff=function(){this.promptSvc.alert(this.win,"You Are Offline",CLB_Application.MESSAGE_BACKED_OFF);CLB_app.setStatus(CLB_Application.STATUS_BACKED_OFF);this.win.setTimeout("window.close()",0)}
);CLB_app.logOff();return}else if(code==CLB_RequestFactory.ERR_COULD_NOT_CONTACT_SERVER){this.win.alert("Network connection error. Please check your network settings and try again.")}else if(message){this.win.alert("Error: "+message)}else if(code==CLB_Updater.ERROR_UPLOAD_TOO_LARGE){this.win.alert("Upload too large. Try disabling some components and trying again.")}else{this.win.alert("Error '%s %s' occurred while syncing, please try again later.".subs(code,status))}CLB_app.setStatus(CLB_Application.STATUS_OFFLINE)
function CLB_SyncItem(opt_fields){if(!opt_fields){opt_fields={}}this.componentID=opt_fields.componentID;this.itemID=opt_fields.itemID;this.typeID=opt_fields.typeID;this.isRemove=opt_fields.isRemove?true:false;this.isRemoveAll=opt_fields.isRemoveAll?true:false;this.isEncrypted=opt_fields.isEncrypted?true:false;this.props_={};this.includesConflictResolution=false;if(opt_fields.properties){for(var name in opt_fields.properties){this.setProperty(name,opt_fields.properties[name])}}}
;CLB_SyncItem.prototype.clone=function(){var newProps={};for(var propName in this.props_){newProps[propName]=this.props_[propName]}return new CLB_SyncItem({componentID:this.componentID,typeID:this.typeID,itemID:this.itemID,isRemove:this.isRemove,isRemoveAll:this.isRemoveAll,isEncrypted:this.isEncrypted,properties:newProps})}
;CLB_SyncItem.prototype.updateFrom=function(otherItem){if(otherItem.componentID!=this.componentID||otherItem.typeID!=this.typeID||otherItem.itemID!=this.itemID){G_Debug(this,"Error: Cannot update from an item with a different it");return}this.isRemove=otherItem.isRemove;this.isEncrypted=otherItem.isEncrypted;this.clearProperties();otherItem.getPropertyNames().forEach(function(propName){this.props_[propName]=otherItem.getProperty(propName)}
function CLB_SyncManager(){this.started_=false;this.importExisting=false;this.registeredComponents_={};this.registeredConflicts_={};this.syncedComponents_={};this.encryptedComponents_={};this.observers_=[];this.updateQueue_=new CLB_UpdateQueue;this.updater_=null;this.downloader_=null;this.updateTimer_=null;this.sendingUpdateQueue_=null;this.periodicRate_=null;this.immediateRate_=null;this.lastActive_=(new Date).getTime();this.zzz_=false;this.updateSuccessHandler_=this.handleUpdateSuccess.bind(this)
;CLB_SyncManager.prototype.start=function(){this.refreshComponents();this.periodicRate_=CLB_app.prefs.getPref("periodicRate",CLB_SyncManager.DEFAULT_PERIODIC_RATE)*1000;this.immediateRate_=CLB_app.prefs.getPref("immediateRate",CLB_SyncManager.DEFAULT_IMMEDIATE_RATE)*1000;this.noSleepTill_=CLB_app.prefs.getPref("noSleepTill",CLB_SyncManager.DEFAULT_NO_SLEEP_TILL)*1000;G_Debug(this,"Initialized periodic rate to: {%s}.".subs(this.periodicRate_));G_Debug(this,"Initialized immediate rate to: {%s}.".subs(
this.immediateRate_));G_Debug(this,"Brooklyn is {%s} milliseconds away.".subs(this.noSleepTill_));this.started_=true;this.startSyncedComponents_();this.schedule_(this.periodicRate_)}
;CLB_SyncManager.prototype.getComponents=function(){var retVal=[];for(var c in this.registeredComponents_){retVal.push(this.registeredComponents_[c])}return new CLB_ArrayEnumerator(retVal)}
;CLB_SyncManager.prototype.update=function(newItem){if(!this.started_){G_DebugL(this,"ERROR: Received unexpected update while offline for item %s".subs(newItem));return}var comp=this.syncedComponents_[newItem.componentID];if(!comp){G_DebugL(this,"ERROR: Received update from non-synced or unknown component: {%s}".subs(newItem));return}if(CLB_app.getStatus()!=CLB_Application.STATUS_ONLINE&&!comp.syncOfflineChanges){G_DebugL(this,"Received unexpected update while offline from component which does not sync offline changes. Item: "
;CLB_SyncManager.prototype.removeObserver=function(observer){for(var i=0;i<this.observers_.length;i++){if(this.observers_[i]==observer){this.observers_.splice(i,1);return}}throw new Error("Specified observer not found.");}
;CLB_SyncManager.prototype.cancelSync=function(){if(this.currentSyncer_){this.currentSyncer_.abort();this.currentSyncer_=null;this.syncFailure(-1,"cancel","cancel")}else{G_Debug(this,"Warning: no currentSyncer when trying to cancel sync")}}
;CLB_SyncManager.prototype.startSync=function(opt_skipSettings){G_Debug(this,"Start Sync Called...");G_Debug(this,"Refreshing synced and encrypted components...");this.refreshComponents();this.stopSyncedComponents();this.notifyObservers_("syncStart");if(opt_skipSettings||CLB_app.prefs.getPref("reimport",false)){var componentsToImport=[];componentsToImport.push(CLB_SettingsSyncer.CONTRACT_ID);for(var componentID in this.syncedComponents_){componentsToImport.push(componentID)}this.startDownload(componentsToImport)
;return}G_Debug(this,"Syncing just settings...");var syncedComponents={};syncedComponents[CLB_SettingsSyncer.CONTRACT_ID]=CLB_app.settingsSyncer;this.lastSyncedComponents_=CLB_app.getListPref("syncedComponents");G_Debug(this,"Creating settings downloader...");this.currentSyncer_=new CLB_Downloader(syncedComponents,null,this.registeredConflicts_,null,this.getTimestamp("lastUpdate"),this.getTimestamp("lastSync"),this.settingsSyncComplete.bind(this),this.syncFailure.bind(this),this.notifyObservers_.bind(
);newSyncedComponents=G_SetXOR(this.lastSyncedComponents_,newSyncedComponents).right;componentsToImport=G_SetMerge(componentsToImport,newSyncedComponents);G_Debug(this,"Importing these components: "+componentsToImport);this.startDownload(componentsToImport)}
;CLB_SyncManager.prototype.changeSettings=function(syncedComponents,encryptedComponents,clearedComponents,reimportComponents,onSuccess,onFailure){if(this.updater_){throw new Error("Cannot change settings. Update in progress.");}if(this.updateQueue_.hasPending()){throw new Error("Cannot change settings. Changes are pending.");}var pending=[];for(var i=0;i<clearedComponents.length;i++){var componentID=clearedComponents[i];if(!this.registeredComponents_[componentID]){G_Debug(this,"WARNING: Could not clear Component, '%s' not registered"
;CLB_SyncManager.prototype.cancelChangeSettings=function(){if(this.updater_){this.updater_.cancel();this.updater_=null}else{G_Debug(this,"Warning: no updater when trying to cancel update")}}
;CLB_SyncManager.prototype.stopSyncedComponents=function(){G_Debug(this,"Stopping started components...");if(!this.started_){G_Debug(this,"SyncManager is not started. Nothing to do.");return}for(var compID in this.syncedComponents_){G_Debug(this,"Stopping {%s}".subs(compID));this.syncedComponents_[compID].stop()}}
;CLB_SyncManager.prototype.startSyncedComponents_=function(){G_Debug(this,"Starting synced components...");if(!this.started_){G_Debug(this,"SyncManager is not started. Nothing to do.");return}for(var compID in this.syncedComponents_){G_Debug(this,"Starting {%s}".subs(compID));this.syncedComponents_[compID].start()}}
;CLB_SyncManager.prototype.syncComplete=function(lastUpdate){this.currentSyncer_=null;CLB_app.prefs.setPref("reimport",false);CLB_app.prefs.setPref("hasOfflineData",false);this.clearedComponents_={};if(lastUpdate){CLB_app.prefs.setPref("lastUpdate",lastUpdate);CLB_app.prefs.setPref("lastSync",lastUpdate);G_Debug(this,"Set lastSync and lastUpdate to: "+lastUpdate)}CLB_app.savePrefs();this.notifyObservers_("syncComplete");this.startSyncedComponents_()}
;CLB_SyncManager.prototype.checkPending=function(){for(var componentID in this.syncedComponents_){this.syncedComponents_[componentID].beforeUpdate()}return this.updateQueue_.hasPending()}
;CLB_SyncManager.prototype.sendPending=function(opt_finalSend,opt_pingSucceeded){G_Debug(this,"SendPending for {%s} items".subs(this.updateQueue_.pendingSize()));if(this.updater_){if(opt_finalSend){G_Debug(this,"Previous update still pending, but this is a final send, so we're recycling it and forging onwards. Tally ho!");this.cancelUpdate()}else{G_Debug(this,"WARNING: Previous update still pending. Skipping request.");return false}}if(this.currentSyncer_&&!opt_finalSend){G_Debug(this,"WARNING: Previous sync still running. Skipping request."
;CLB_SyncManager.prototype.handleUpdateFailure=function(code,status,opt_message){this.updater_=null;this.notifyObservers_("updateFailure",code,status,opt_message);if(code==CLB_Updater.ERROR_APPLICATION_PRE_FILE_WRITE){G_Debug(this,"Recycling {%s} items from failed update".subs(this.sendingUpdateQueue_.pendingSize()));this.sendingUpdateQueue_.append(this.updateQueue_);this.updateQueue_=this.sendingUpdateQueue_}CLB_app.handleServerError(code,status,opt_message);if(this.started_){this.schedule_(this.periodicRate_)
}}
;CLB_SyncManager.prototype.handleUpdateSuccess=function(opt_newLastUpdate){this.updater_=null;if(isDef(opt_newLastUpdate)){CLB_app.prefs.setPref("lastUpdate",opt_newLastUpdate);G_Debug(this,"Set lastUpdate to: "+opt_newLastUpdate)}CLB_app.prefs.setPref("hasOfflineData",false);CLB_app.savePrefs();this.notifyObservers_("updateComplete");if(this.started_){this.schedule_(this.periodicRate_)}}
;CLB_SyncManager.prototype.refreshSyncedComponents_=function(){G_Debug(this,"Refreshing syncedComponents_ lookup... ");this.syncedComponents_={};CLB_app.getListPref("syncedComponents").forEach(function(id){if(!this.registeredComponents_[id]){G_Debug(this,"WARNING: The component {%s} has not been registered. "+"Skipping.".subs(id))}else{this.syncedComponents_[id]=this.registeredComponents_[id];G_Debug(this," added component {%s}".subs(id))}}
,this);G_Debug(this,"Done.")}
;CLB_SyncManager.prototype.refreshEncryptedComponents_=function(){G_Debug(this,"Refreshing encryptedComponents_ lookup... ");this.encryptedComponents_={};CLB_app.getListPref("encryptedComponents").forEach(function(id){if(!this.registeredComponents_[id]){G_Debug(this,"WARNING: The component {%s} has not been registered. "+"Skipping.".subs(id))}else{this.encryptedComponents_[id]=this.registeredComponents_[id];G_Debug(this," added component {%s}".subs(id))}}
;CLB_SyncManager.prototype.schedule_=function(timeoutInMilliseconds){if(timeoutInMilliseconds<=0){G_Debug(this,"Skipping schedule because timeout is zero.")}else{this.cancelScheduledSend_();G_Debug(this,"Scheduling send in {%s} milliseconds".subs(timeoutInMilliseconds));this.updateTimer_=new G_Alarm(this.sendPending.bind(this),timeoutInMilliseconds)}}
;CLB_SyncManager.prototype.cancelScheduledSend_=function(){G_Debug(this,"Canceling scheduled send");if(!this.updateTimer_){G_Debug(this,"No scheduled send found to cancel");return}this.updateTimer_.cancel();this.updateTimer_=null}
;CLB_SyncManager.prototype.cancelUpdate=function(){if(!this.checkSending()){G_Debug(this,"No existing update to recycle. Continuing.");return}this.updater_.cancel();this.updater_=null;if(isNull(this.sendingUpdateQueue_)){G_DebugL(this,"ERROR: Expected sendingUpdateQueue to be non-null since updater is. Skipping.");return}G_Debug(this,"Recycling existing update containing {%s} items".subs(this.sendingUpdateQueue_.pendingSize()));this.sendingUpdateQueue_.append(this.updateQueue_);this.updateQueue_=
this.sendingUpdateQueue_}
;CLB_SyncManager.prototype.notifyObservers_=function(methName){var meth=arguments[0];var args=Array.prototype.splice.apply(arguments,[1,arguments.length]);for(var i=0,observer;observer=this.observers_[i];i++){if(!observer[meth]){G_Debug(this,"WARNING: observer does not have method {%s}.".subs(meth));continue}observer[meth].apply(observer,args)}}
;CLB_SyncManager.prototype.maybeSleep_=function(){var now=(new Date).getTime();var msSinceLastActive=now-this.lastActive_;G_Debug(this,"Checking whether should sleep. ms since last active: {%s}, limit: {%s}".subs(msSinceLastActive,this.noSleepTill_));if(msSinceLastActive>this.noSleepTill_){G_DebugL(this,"There has been no activity for too long. Going to sleep. zzz...");this.zzz_=true}}
;CLB_SyncManager.prototype.updateSleepyState=function(){this.lastActive_=(new Date).getTime();if(this.zzz_){this.zzz_=false;G_DebugL(this,"Waking up! lastActive is now: {%s}.".subs(this.lastActive_));this.sendPending()}}
function CLB_TabSyncer(){bindMethods(this);this.winMed_=Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);this.nextID_=1;this.started_=false;this.syncedItems_=[];this.queuedUnload_=null}
CLB_TabSyncer.UNLOAD_QUEUE_SECONDS=15;CLB_TabSyncer.prototype.componentID="@google.com/browserstate/tab-syncer;1";CLB_TabSyncer.prototype.componentName="Tabs and Windows";CLB_TabSyncer.prototype.encryptionRequred=false;CLB_TabSyncer.prototype.syncOfflineChanges=false;CLB_TabSyncer.prototype.syncBehavior=Ci.GISyncComponent.SYNC_SINCE_LAST_SYNC;CLB_TabSyncer.prototype.start=function(){this.started_=true;var initialTabs=this.getCurrentItems();G_Debug(this,"Sending remove items for tabsyncer to syncman."
);if(this.syncedItems_){for(var i=0,syncedItem;syncedItem=this.syncedItems_[i];i++){CLB_syncMan.update(new CLB_SyncItem({componentID:syncedItem.componentID,typeID:syncedItem.typeID,itemID:syncedItem.itemID,isRemove:true}))}this.syncedItems_=[]}var updateItem;while(updateItem=initialTabs.getNext()){G_Debug(this,"Sending update item to syncman: "+updateItem);CLB_syncMan.update(updateItem)}}
tabIndex:tabIndex,activeTab:tabBrowser.selectedBrowser==tab,windowID:win.__winID}});result.push(newItem)}}return new CLB_ArrayEnumerator(result)}
;CLB_TabSyncer.prototype.onLoad=function(win){G_Debug(this,"Received onload event for win {%s}".subs(win.__winID));if(!this.shouldProcessEvents_()){return}if(isDef(win.__winID)){G_Debug(this,"Window already created with winID {%s}. Ignoring.".subs(win.__winID));return}win.__winID=this.getNextID_();var syncItem=new CLB_SyncItem({componentID:this.componentID,typeID:"window",itemID:win.__winID});G_Debug(this,"Sending new window item to syncman: "+syncItem);CLB_syncMan.update(syncItem);var tabBrowser=
win.document.getElementById("content");if(tabBrowser){for(var i=0,browser;browser=tabBrowser.browsers[i];i++){this.createTab_(win,browser,tabBrowser.selectedBrowser==browser,i)}}else{G_Debug(this,"ERROR: Could not get first browser.")}}
;CLB_TabSyncer.prototype.ensureTabCreated_=function(win,browser,isSelected){if(isDef(browser.__tabID)){G_Debug(this,"Tab already created with tabID {%s}. Ignoring.".subs(browser.__tabID));return false}if(!isDef(win.__winID)){G_Debug(this,"ERROR: Could not get winID from window. Ignoring.");return false}var tabPos=CLB_TabSyncer.findBrowserPosition(win,browser);if(tabPos==-1){G_Debug(this,"ERROR: Could not find position of tab. Ignoring.");return false}this.createTab_(win,browser,isSelected,tabPos)
}
;CLB_TabSyncer.prototype.createTab_=function(win,browser,isSelected,tabPos){browser.__tabID=this.getNextID_();G_Debug(this,"Assigned ID {%s} to new tab".subs(browser.__tabID));var syncItem=new CLB_SyncItem({componentID:this.componentID,typeID:"tab",itemID:browser.__tabID});syncItem.setProperty("tabIndex",tabPos);syncItem.setProperty("activeTab",isSelected);syncItem.setProperty("windowID",win.__winID);G_Debug(this,"Sending new tab item to syncman: "+syncItem);CLB_syncMan.update(syncItem);return true}
;CLB_TabSyncer.prototype.onTabLoad=function(win,ev){G_Debug(this,"tabload for window {%s}.".subs(win.__winID));if(!this.shouldProcessEvents_()){return}this.ensureTabCreated_(win,ev.browser,ev.isSelected)}
;CLB_TabSyncer.prototype.onTabUnload=function(win,ev){G_Debug(this,"tabunload for tab {%s}".subs(ev.browser.__tabID));if(!this.shouldProcessEvents_()){return}var browser=ev.browser;if(!isDef(browser.__tabID)){G_Debug(this,"ERROR: Could not find tabID for unloaded tab.");return}browser.__isUnloading=true;var syncItem=new CLB_SyncItem({componentID:this.componentID,typeID:"tab",itemID:browser.__tabID,isRemove:true});G_Debug(this,"Sending remove tab item to syncman: "+syncItem);CLB_syncMan.update(syncItem)
;G_Debug(this,"Resetting all tab indicies");var tabBrowser=win.document.getElementById("content");this.resetTabIndicies_(tabBrowser,0,tabBrowser.browsers.length-1)}
;CLB_TabSyncer.prototype.onPageShow=function(win,ev){G_Debug(this,"pageshow for tab {%s}".subs(ev.browser.__tabID));if(!this.shouldProcessEvents_()){return}if(!ev.isTop){G_Debug(this,"Skipping pageshow for non-top content window.");return}var browser=ev.browser;if(!isDef(browser.__tabID)){G_Debug(this,"ERROR: Could not find tabID for pageshow in tab.");return}var syncItem=new CLB_SyncItem({componentID:this.componentID,typeID:"tab",itemID:browser.__tabID});syncItem.setProperty("url",browser.contentWindow.location.href)
;syncItem.setProperty("title",browser.contentWindow.document.title);G_Debug(this,"Sending pageshow item to syncman: "+syncItem);CLB_syncMan.update(syncItem)}
;CLB_TabSyncer.prototype.onTabSwitch=function(win,ev){G_Debug(this,"tabswitch from tab {%s} to tab {%s}".subs(ev.fromBrowser.__tabID,ev.toBrowser.__tabID));if(!this.shouldProcessEvents_()){return}var toTabIsNew=this.ensureTabCreated_(win,ev.toBrowser,true);if(!isDef(ev.fromBrowser.__tabID)){G_Debug(this,"Could not get tabID from fromBrowser. Ignoring.");return}if(!isDef(ev.toBrowser.__tabID)){G_Debug(this,"Could not get tabID from toBrowser. Ignoring.");return}if(!ev.fromBrowser.__isUnloading){var syncItem1=
new CLB_SyncItem({componentID:this.componentID,typeID:"tab",itemID:ev.fromBrowser.__tabID});syncItem1.setProperty("activeTab",false);G_Debug(this,"Sending tabswitch item for fromBrowser: "+syncItem1);CLB_syncMan.update(syncItem1)}if(!toTabIsNew){var syncItem2=new CLB_SyncItem({componentID:this.componentID,typeID:"tab",itemID:ev.toBrowser.__tabID});syncItem2.setProperty("activeTab",true);G_Debug(this,"Sending tabswitch item for toBrowser: "+syncItem2);CLB_syncMan.update(syncItem2)}}
;CLB_TabSyncer.prototype.onTabMove=function(win,ev){G_Debug(this,"tabmove from index {%s} to index {%s}".subs(ev.fromIndex,ev.toIndex));if(!this.shouldProcessEvents_()){return}var tabBrowser=win.document.getElementById("content");var min=Math.min(ev.fromIndex,ev.toIndex);var max=Math.max(ev.fromIndex,ev.toIndex);this.resetTabIndicies_(tabBrowser,min,max)}
;CLB_TabSyncer.prototype.resetTabIndicies_=function(tabBrowser,fromIndex,toIndex){var syncItem,browser;for(var i=fromIndex;i<=toIndex;i++){syncItem=new CLB_SyncItem({componentID:this.componentID,typeID:"tab"});browser=tabBrowser.browsers[i];if(!browser){G_DebugL(this,"ERROR: Could not find browser at position {%s}".subs(i));continue}if(!isDef(browser.__tabID)){G_DebugL(this,"ERROR: Could not get tabID from browser at position {%s}".subs(i));continue}syncItem.itemID=browser.__tabID;syncItem.setProperty(
;CLB_TabSyncer.prototype.onUnload=function(win){G_Debug(this,"Received onunload event for win {%s}".subs(win.__winID));if(!this.shouldProcessEvents_()){return}if(this.unloadQueueAlarm_){G_Debug(this,"Found existing unload timer with {%s} queued items. Rescuing them.".subs(this.queuedUnload_.length));this.unloadQueueAlarm_.cancel()}else{this.queuedUnload_=[]}if(!isDef(win.__winID)){G_DebugL(this,"ERROR: Could not find winID for unloaded window. Ignoring.")}else{var winSyncItem=new CLB_SyncItem({componentID:
this.componentID,typeID:"window",itemID:win.__winID,isRemove:true});G_Debug(this,"Queuing win remove syncitem: "+winSyncItem);this.queuedUnload_.push(winSyncItem)}var tabBrowser=win.document.getElementById("content");if(!tabBrowser){G_DebugL(this,"ERROR: Could not get tabBrowser from unloading window. Skipping window's tabs.")}for(var i=0,browser;browser=tabBrowser.browsers[i];i++){if(!isDef(browser.__tabID)){G_DebugL(this,"ERROR: Could not find tabID for tab in unloading "+"window at position {%s}. Ignoring tab."
;CLB_TabSyncer.prototype.handleUnloadTimerElapsed_=function(){G_Debug(this,"Unload timer elapsed. Sending {%s} queued unloads to the server.".subs(this.queuedUnload_.length));this.unloadQueueAlarm_=null;this.queuedUnload_.forEach(function(item){CLB_syncMan.update(item)}
;CLB_TabSyncer.findBrowserPosition=function(win,target){var tabBrowser=win.document.getElementById("content");var numCollapsedTabs=0;for(var i=0,cand;cand=tabBrowser.browsers[i];i++){if(tabBrowser.tabContainer.childNodes[i].collapsed){G_Debug(CLB_TabSyncer.prototype,"Skipping collapsed tab at pos {%s}".subs(i));numCollapsedTabs++;continue}if(cand==target){G_Debug(CLB_TabSyncer.prototype,"Found tab at pos {%s}. Adjusting for collapsed tabs to {%s}.".subs(i,i-numCollapsedTabs));return i-numCollapsedTabs}
;CLB_TabSyncer.prototype.updateID_=function(downloadedID){downloadedID=parseInt(downloadedID);if(isNaN(downloadedID)){G_DebugL(this,"ERROR: Unexpected format for downloadedID: {%s}".subs(downloadedID));return}if(downloadedID>=this.nextID_){this.nextID_=downloadedID+1;G_Debug(this,"Received ID {%s} and updated to {%s}".subs(downloadedID,this.nextID_))}}
;CLB_UpdateQueue.prototype.deleteItemByLookupKey=function(lookupKey){if(lookupKey in this.pendingLookup){delete this.pendingLookup[lookupKey]}else{G_Debug(this,"Warning: trying to delete nonexistant update queue item with lookupKey: "+lookupKey)}}
);this.items_=this.doc_.createElement("items");this.clearedComponents_=this.doc_.createElement("clearedComponents");this.funQueue_=new G_WorkQueue;this.funQueue_.onError=this.handleWorkQueueError_;if(!getOfflineData){G_Debug(this,"Skipping prepend offline step since getOfflineData is false.");this.funQueue_.addJob(this.buildXML_);return}if(!CLB_Updater.hasOfflineData()){G_Debug(this,"Skipping prepend offline steps because there is no offline data.");this.funQueue_.addJob(this.buildXML_);return}this.funQueue_.addJob(
,this);if(itemLength>CLB_Updater.MAX_ITEM_SIZE){G_DebugL(this,"Not sending item {%s} because it's length {%s} exceeds the maximum item length {%s}.".subs(dataItem,itemLength,CLB_Updater.MAX_ITEM_SIZE))}else{this.items_.appendChild(item)}this.funQueue_.addJob(next)}
+fileSize);if(fileSize>CLB_Updater.MAX_UPLOAD_SIZE){this.handleFailure_(CLB_Updater.ERROR_UPLOAD_TOO_LARGE,"Upload too large","Try disabling some components");return}if(this.sendToServer_){this.definitelySendDoc_()}else{this.onFailure_(0,null,null)}}
;CLB_Updater.prototype.definitelySendDoc_=function(){if(this.data_.length==0){G_Debug(this,"Not writing temp file because this is just a ping");this.req_=CLB_RequestFactory.getRequest(CLB_RequestFactory.UPDATE,null,this.handleSuccess_,this.handleFailure_);this.req_.send(this.doc_);this.startTimer_();return}G_Debug(this,"Sending %s new items:...".subs(this.data_.length));if(CLB_app.prefs.getPref("log-xml",false)){var tmpFile=CLB_app.getUniqueTempFile("upload","xml");this.uploadFile_.copyTo(tmpFile.parent,
tmpFile.leafName);G_Debug(this,"Logging sent data in: %s...".subs(tmpFile.path))}var uploadInputStream=Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);uploadInputStream.init(this.uploadFile_,G_File.PR_RDONLY,292,0);G_Debug(this,"Upload stream initialized");var bufferedInputStream=Cc["@mozilla.org/network/buffered-input-stream;1"].createInstance(Ci.nsIBufferedInputStream);bufferedInputStream.init(uploadInputStream,4096);this.onProgress_(CLB_Application.PROGRESS_UPDATING,
;CLB_Updater.prototype.timerElapsed_=function(){this.req_.abort();this.handleFailure_(CLB_Updater.ERROR_UPDATE_TIMEOUT,"Request timeout","Gave up waiting for server update to return, sorry.")}
;CLB_Updater.prototype.handleSuccess_=function(req){this.req_=null;if(this.alarm_){this.alarm_.cancel()}CLB_app.setStatus(CLB_Application.STATUS_ONLINE);if(!req.responseXML){G_DebugL(this,"ERROR: The server response was not valid XML: "+req.responseText);this.onSuccess_()}else{this.onSuccess_(CLB_XMLUtils.getTimestamp(req.responseXML))}}
function CLB_UpdatingForm(win){this.win=win;this.appStatus=CLB_app.getStatus()}
CLB_UpdatingForm.prototype.debugZone="CLB_UpdatingForm";CLB_UpdatingForm.prototype.handleFormLoad=function(){this.doc=this.win.document;this.statusElm=this.doc.getElementById("clb-status");this.progressElm=this.doc.getElementById("clb-progress");if(CLB_syncMan.checkPending()){G_Debug(this,"We have some stuff to send to the server.");G_Debug(this,"Sending final update");CLB_syncMan.addObserver(this);CLB_syncMan.sendPending(true)}else if(CLB_syncMan.checkSending()){CLB_syncMan.addObserver(this);G_Debug(
this,"Updatingform is modally blocking so that another update can finish")}else{G_Debug(this,"Warning: updatingform didn't need to exist");this.win.setTimeout("window.close()",0)}}
function CLB_WelcomeForm(win){bindMethods(this);this.loaded=false;this.win=win;this.promptSvc=Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci.nsIPromptService);this.result=this.win.arguments[0].QueryInterface(Components.interfaces.nsIWritablePropertyBag);this.result.setProperty("success",false);this.creatingAccount=false}
CLB_WelcomeForm.NO_USER_ERROR=403;CLB_WelcomeForm.REFRESH_SID_REQUIRED=403;CLB_WelcomeForm.MIN_TOKEN_LENGTH=4;CLB_WelcomeForm.REFRESH_SID_REQUIRED_MSG="Need to refresh SID cookie.";CLB_WelcomeForm.NO_ACCOUNT_MSG="Account does not exist for this user.";CLB_WelcomeForm.prototype.handleLoad=function(){this.doc=this.win.document;this.wizard=this.doc.documentElement;this.welcomePage=this.doc.getElementById("clb-welcome");this.progressPage=this.doc.getElementById("clb-progress");this.usernameField=this.doc.getElementById(
;CLB_WelcomeForm.prototype.handleWorkingOffline=function(){this.promptSvc.alert(this.win,"You Are Working Offline",CLB_Application.MESSAGE_WORKING_OFFLINE);CLB_app.setStatus(CLB_Application.STATUS_OFFLINE);this.win.setTimeout("window.close()",0)}
;CLB_WelcomeForm.prototype.handleBackedOff=function(){this.promptSvc.alert(this.win,"You Are Offline",CLB_Application.MESSAGE_BACKED_OFF);CLB_app.setStatus(CLB_Application.STATUS_BACKED_OFF);this.win.setTimeout("window.close()",0)}
;CLB_WelcomeForm.prototype.handleForgotPassword=function(){if(!this.win.confirm("This will close the setup wizard and take you to a webpage to have your password sent to you. When you're ready, choose 'Setup Google Browser Sync' from the Google Browser Sync toolbar button to restart this wizard.")){return}CLB_app.setStatus(CLB_Application.STATUS_OFFLINE);CLB_app.errorURL="https://www.google.com/accounts/ForgotPasswd?service=browserstate";this.win.setTimeout("window.close()",0)}
;CLB_WelcomeForm.prototype.handleCreateGAIAAcct=function(){if(!this.win.confirm("This will close the setup wizard and take you to a webpage to create a Google account. When you're ready, choose 'Setup Google Browser Sync' from the Google Browser Sync toolbar button to restart this wizard.")){return}CLB_app.setStatus(CLB_Application.STATUS_OFFLINE);CLB_app.errorURL="https://www.google.com/accounts/NewAccount";this.win.setTimeout("window.close()",0)}
;CLB_WelcomeForm.prototype.handleWelcomePageAdvanced=function(){this.setStatusTitle("Logging in");this.setStatusBlurb("Please wait while we log you into Google Browser Sync.");this.wizard.canAdvance=false;this.startPing()}
;CLB_WelcomeForm.prototype.handlePingSuccess=function(req){this.req=null;if(req.channel.URI.spec==CLB_RequestFactory.getURL(CLB_RequestFactory.PING)){this.setStatusDetails("Authenticating user...");this.req=this.loginUtil.startRequest(this.username,this.password,this.handleLoginSuccess,this.handleLoginFailure)}else{this.promptSvc.alert(this.win,"Network requires login","It looks like you are accessing the internet through a connection which requires a web login. This can happen when you connect through a public network like at a hotel or an airport.\n\nPlease setup your internet connection, then reconnect to Google Browser Sync."
;CLB_WelcomeForm.prototype.handleLoginSuccess=function(req){this.req=null;CLB_app.errorURL=null;this.sid=this.loginUtil.parseResponse(req.responseText)["SID"];var doc=CLB_XMLUtils.getDoc("VerifyUserExistsRequest",{uid:this.sid});this.setStatusDetails("Checking user status...");this.req=CLB_RequestFactory.getRequest(CLB_RequestFactory.USER_EXISTS,null,this.handleCheckUserSuccess,this.handleCheckUserFailure);this.req.send(doc)}
"showWelcome",true);this.wizard.canAdvance=true;this.hideProgressMeter();this.wizard.goTo("clb-installtype")}else{this.handleLoginPhaseError("Error checking user status",code,status,message)}}
;CLB_WelcomeForm.prototype.handleCreatePinPageAdvanced=function(){if(this.token.length<CLB_WelcomeForm.MIN_TOKEN_LENGTH){this.promptSvc.alert(this.win,"Invalid PIN","Your PIN must be at least four characters long.");return false}if(this.token!=this.confirmTokenTextElm.value.trim()){this.promptSvc.alert(this.win,"PINs do not match","Please enter the same PIN in both fields.");return false}this.startGenerateKey()}
;CLB_WelcomeForm.prototype.startGenerateKey=function(){this.setStatusTitle("Creating account");this.setStatusBlurb("Please wait while we create your Google Browser Sync account.");this.setStatusDetails("Generating security key...");this.req=CLB_RequestFactory.getRequest(CLB_RequestFactory.GENERATE_KEY,{client:"browserstate"},this.handleGenerateKeySuccess,this.handleCreatePhaseError.bind(null,"Error generating security key"),null,true);this.req.send(null)}
;CLB_WelcomeForm.prototype.handleGenerateKeySuccess=function(req){var result=(new G_Protocol4Parser).parse(req.responseText);if(!result||!result["clientkey"]){this.handleCreatePhaseError("Unexpected response while generating security key.");return}G_Debug(this,"Received server randomness. Generating client randomness.");var serverData=result["clientkey"];var clientData=[];for(var i=0;i<10;i++){clientData.push(Math.floor(Math.random()*255))}G_Debug(this,"Generated client randomness. Hashing.");var hasher=
new G_CryptoHasher;hasher.init(G_CryptoHasher.algorithms.SHA1);hasher.updateFromString(serverData);hasher.updateFromArray(clientData);this.key=hasher.digestBase64();G_Debug(this,"Hashing complete, key generated. Creating user.");this.setStatusDetails("Initializing account...");this.encryptedKey=CLB_Crypter.encryptString(this.key,this.token,true);var hashedToken=CLB_WelcomeForm.hashToken(this.token);var doc=CLB_XMLUtils.getDoc("CreateUserRequest",{uid:this.sid,key:this.encryptedKey,token:hashedToken}
;CLB_WelcomeForm.prototype.handleSyncingPageShow=function(){this.progressMeter.setAttribute("collapsed",false);this.wizard.canAdvance=false;this.wizard.canRewind=false;if(this.tokenPageAdvanced){var hashedToken=CLB_WelcomeForm.hashToken(this.token);var doc=CLB_XMLUtils.getDoc("AddClientRequest",{uid:this.sid,token:hashedToken});this.setStatusTitle("Synchronizing browser");this.setStatusBlurb("");this.progressBlurbField.appendChild(this.doc.createTextNode("Please wait while we synchronize this browser with the server. This can take several minutes, but "
));var bolded=this.doc.createElementNS("http://www.w3.org/1999/xhtml","html:b");bolded.textContent="you only need to do it once.";this.progressBlurbField.appendChild(bolded);this.setStatusDetails("Authenticating token...");this.req=CLB_RequestFactory.getRequest(CLB_RequestFactory.ADD_CLIENT,null,this.handleAddClientSuccess,this.handleAddClientPhaseError.bind(null,"Error authenticating token"));this.req.send(doc);this.tokenPageAdvanced=false}}
;CLB_WelcomeForm.prototype.syncFailure=function(code,status,message){this.syncing_=null;CLB_syncMan.removeObserver(this);if(this.syncing){this.handleUpdatePhaseError("Error while sending update",code,status,message)}else if(this.creatingAccount){this.handleCreatePhaseError("Error while creating client",code,status,message)}else{this.handleAddClientPhaseError("Error while adding client",code,status,message)}}
;CLB_XMLUtils.getDoc=function(topElmName,authBlock){var doc=G_FirefoxXMLUtils.newXML(topElmName,"http://google.com/browserstate",{xsi:G_FirefoxXMLUtils.XSI_NAMESPACE});if(!authBlock||isEmptyObject(authBlock)){return doc}var authElm=doc.createElement("auth");doc.documentElement.appendChild(authElm);for(var fieldName in authBlock){this.addElm(authElm,fieldName,authBlock[fieldName])}return doc}
;CLB_XMLUtils.getTimestamp=function(doc){if(!doc){G_DebugL(this,"WARNING: document is null or undefined.");return null}var elm=doc.getElementsByTagName("timestamp")[0];if(!elm){G_DebugL(this,"WARNING: Could not find timestamp element in document:\n"+G_FirefoxXMLUtils.getXMLString(doc));return null}return elm.textContent}