PageRenderTime 70ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/swfstore/as/SWFStore.as

https://github.com/sdesai/yui2
ActionScript | 936 lines | 446 code | 153 blank | 337 comment | 44 complexity | cc34343a261f57c49b8d111c4fe7b84b MD5 | raw file
  1. package
  2. {
  3. import com.yahoo.util.YUIBridge;
  4. import flash.display.Sprite;
  5. import flash.events.Event;
  6. import flash.events.IOErrorEvent;
  7. import flash.events.SecurityErrorEvent;
  8. import flash.events.NetStatusEvent;
  9. import flash.external.ExternalInterface;
  10. import flash.net.SharedObject;
  11. import flash.net.SharedObjectFlushStatus;
  12. import flash.net.URLLoader;
  13. import flash.net.URLRequest;
  14. import flash.system.Security;
  15. import flash.system.SecurityPanel;
  16. import flash.utils.ByteArray;
  17. //We set width/height is set here to be large enough to display the settings panel in Flash Player
  18. //It will typically be shrunk to 0 x 0 via the embed code
  19. [SWF(width=215, height=138)]
  20. /**
  21. * A wrapper for Flash SharedObjects to allow them to be used in JavaScript.
  22. *
  23. * @author Alaric Cole
  24. */
  25. public class SWFStore extends Sprite
  26. {
  27. //--------------------------------------------------------------------------
  28. //
  29. // Private Variables
  30. //
  31. //--------------------------------------------------------------------------
  32. /**
  33. * The Shared Object instance in which to store entries.
  34. * @private
  35. * @fucktown
  36. */
  37. private var _sharedObject:SharedObject;
  38. /**
  39. * An object used to temporarily store entries.
  40. * @private
  41. */
  42. private var _archive:Object;
  43. /**
  44. * Storage for useCompression getter/setter
  45. * @private
  46. */
  47. private var _useCompression:Boolean;
  48. /**
  49. * Storage for shareData getter/setter
  50. * @private
  51. */
  52. private var _shareData:Boolean;
  53. //--------------------------------------------------------------------------
  54. //
  55. // Static Variables
  56. //
  57. //--------------------------------------------------------------------------
  58. /**
  59. * The minimum width required to be able to display the settings panel within the SWF
  60. *
  61. */
  62. public static var MINIMUM_WIDTH:Number = 215;
  63. /**
  64. * The minimum height required to be able to display the settings panel within the SWF
  65. *
  66. */
  67. public static var MINIMUM_HEIGHT:Number = 138;
  68. /**
  69. * @private
  70. * Initialization flag
  71. */
  72. private var _initialized:Boolean;
  73. /**
  74. * @private
  75. * Whitelist xml path
  76. */
  77. private var _whitelistFileName:String = "storage-whitelist.xml";
  78. /**
  79. * @private
  80. * YUI Embedding framework
  81. */
  82. private var yuibridge:YUIBridge;
  83. //--------------------------------------
  84. // Constructor
  85. //--------------------------------------
  86. /**
  87. * Creates a store, which can be used to set and get information on a
  88. * user's local machine. This is typically invoked through the YUI JS API.
  89. *
  90. *
  91. * <p>If multiple SWF files need access to the same store,
  92. * or if the SWF file that creates a store will later be moved,
  93. * the value of this parameter affects how accessible the store will be.</p>
  94. * <p>For example, if you create a store with localPath set to the default value
  95. * (the full path to the SWF file), no other SWF file can access that shared object.
  96. * If you later move the original SWF file to another location,
  97. * not even that SWF file can access the data already stored.</p>
  98. * <p>To avoid inadvertently restricting access to a store, set this parameter.
  99. * The most permissive approach is to set localPath to <code>/ </code> (forward slash),
  100. * which makes the store available to all SWF files in the domain,
  101. * but increases the likelihood of name conflicts with other stores in the domain.
  102. * A more restrictive approach is to append localPath with folder names
  103. * that are in the full path to the SWF file. Note that not just any folder path
  104. * can be placed here, but only those that are in the path of the SWF.
  105. * For instance, if the SWF is located at company.com/products/mail/mail.swf,
  106. * the available options for localPath would be "/products/mail/",
  107. * "/products/", or "/".</p>
  108. *
  109. */
  110. public function SWFStore()
  111. {
  112. loadWhitelist();
  113. var callbacks:Object = {};
  114. callbacks.getValueOf = getValueOf;
  115. callbacks.getItems = getItems;
  116. callbacks.getValueAt = getValueAt;
  117. callbacks.getNameAt = getNameAt;
  118. callbacks.getLength = getLength;
  119. callbacks.getModificationDate = getModificationDate;
  120. callbacks.calculateCurrentSize = calculateCurrentSize;
  121. callbacks.setItem = setItem;
  122. callbacks.removeItem = removeItem;
  123. callbacks.removeItemAt = removeItemAt;
  124. callbacks.clear = clear;
  125. callbacks.setSize = setSize;
  126. callbacks.displaySettings = displaySettings;
  127. callbacks.getTypeOf = getTypeOf;
  128. callbacks.getTypeAt = getTypeAt;
  129. callbacks.setUseCompression = setUseCompression;
  130. callbacks.getUseCompression = getUseCompression;
  131. callbacks.setShareData = setShareData;
  132. callbacks.getShareData = getShareData;
  133. callbacks.setShareData = setShareData;
  134. callbacks.hasAdequateDimensions = hasAdequateDimensions;
  135. yuibridge = new YUIBridge(stage);
  136. yuibridge.addCallbacks(callbacks);
  137. }
  138. //--------------------------------------------------------------------------
  139. //
  140. // Properties
  141. //
  142. //--------------------------------------------------------------------------
  143. /**
  144. *
  145. * Whether or not compression is used
  146. */
  147. public function getUseCompression():Boolean
  148. {
  149. return _useCompression;
  150. }
  151. /**
  152. * Whether or not to use compression
  153. */
  154. public function setUseCompression(value:Boolean):void
  155. {
  156. _useCompression = value;
  157. //if we're not already compressed, this setting should force current data to be compressed
  158. if( !(_sharedObject.data.archive is ByteArray) && value)
  159. {
  160. var bytes:ByteArray = new ByteArray();
  161. bytes.writeObject(_archive);
  162. bytes.compress();
  163. _sharedObject.data.archive = bytes;
  164. _sharedObject.flush();
  165. }
  166. }
  167. /**
  168. *
  169. * Whether or not to data is being shared among different browsers
  170. */
  171. public function getShareData():Boolean
  172. {
  173. return _useCompression;
  174. }
  175. /**
  176. *
  177. * Whether or not to share data among different browsers
  178. */
  179. public function setShareData(value:Boolean):void
  180. {
  181. _shareData = value;
  182. initializeSharedObject();
  183. }
  184. //--------------------------------------------------------------------------
  185. //
  186. // Public Methods
  187. //
  188. //--------------------------------------------------------------------------
  189. /**
  190. * Saves data to local storage. It returns "true" if the storage succeeded; "false" if the user
  191. * has denied storage on their machine or if the current limit is too low.
  192. * <p>The size limit for the passed parameters is ~40Kb.</p>
  193. *
  194. * @param item The data to store
  195. * @param location The name of the "cookie" or store
  196. * @return Boolean Whether or not the save was successful
  197. *
  198. */
  199. public function setItem(location:String, item:* ):Boolean
  200. {
  201. var oldValue:Object = null;
  202. var info:String;
  203. //check to see if this has already been added
  204. if(_archive.storage.hasOwnProperty(location))
  205. {
  206. //entry already exists with this value, ignore
  207. if(_archive.storage[location] == item) return false;
  208. else //it's there but has a different value
  209. {
  210. oldValue = getValueOf(location);
  211. _archive.storage[location] = item;
  212. info = "update";
  213. }
  214. }
  215. else //doesn't exist, create and index it
  216. {
  217. info = "add";
  218. _archive.storage[location] = item;
  219. _archive.hash.push(location);
  220. }
  221. //write it immediately
  222. var result:Boolean = save(location, info, oldValue, item);
  223. if(!result)
  224. {
  225. //return archive to its original state, as this did not propagate to the SharedObject
  226. switch(info)
  227. {
  228. case "update":
  229. _archive.storage[location] = oldValue;
  230. break;
  231. case "add":
  232. delete _archive.storage[location];
  233. _archive.hash.pop();
  234. break;
  235. }
  236. }
  237. return result;
  238. }
  239. /**
  240. * Returns the value of the key in local storage, if any. This corresponds to the
  241. * HTML5 spec getItem(key).
  242. * <p>Note: to return an item at a specific index, use the helper function</p>:
  243. * <code>getValueAt(index)</code>
  244. *
  245. * @param location The name of the "cookie" or key
  246. * @return The data
  247. * @see getValueAt
  248. */
  249. public function getValueOf(location:String):*
  250. {
  251. if(_archive.storage.hasOwnProperty(location))
  252. {
  253. return _archive.storage[location];
  254. }
  255. return null;
  256. }
  257. /**
  258. * Returns the value of the key in local storage, if any, at the specified index.
  259. * Corresponds to the key(n) method in the HTML5 spec.
  260. *
  261. * @param index The index of the "cookie" or store
  262. * @return The value stored
  263. *
  264. */
  265. public function getValueAt(index:int):*
  266. {
  267. var keyname:String = getNameAt(index);
  268. if(!keyname) return null;
  269. var value:Object = _archive.storage[keyname];
  270. if(!value) return null;
  271. return value;
  272. }
  273. /**
  274. * Returns the data type of of the storage.
  275. *
  276. * <p>May be one of the following types:
  277. * <ul>
  278. * <li>boolean</li>
  279. * <li>function</li>
  280. * <li>number</li>
  281. * <li>object</li>
  282. * <li>string</li>
  283. * <li>number</li>
  284. * <li>xml</li>
  285. * </ul>
  286. * </p>
  287. *
  288. * @param location The name of the "cookie" or store
  289. * @return The data type.
  290. *
  291. */
  292. public function getTypeOf(location:String):String
  293. {
  294. if(_archive.storage.hasOwnProperty(location))
  295. {
  296. return typeof _archive.storage[location];
  297. }
  298. return null;
  299. }
  300. /**
  301. * Returns the data type of of the storage.
  302. *
  303. * @param index The index of the "cookie" or store
  304. * @return The data type.
  305. * @see getTypeOf
  306. *
  307. */
  308. public function getTypeAt(index:int):String
  309. {
  310. return typeof getValueAt(index);
  311. }
  312. /**
  313. * Returns the key name in storage, if any, at the specified index.
  314. *
  315. * @param index The index of the "cookie" or store
  316. * @return The data
  317. *
  318. */
  319. public function getNameAt(index:int):String
  320. {
  321. var keyname:String = _archive.hash[index];
  322. if(!keyname) return null;
  323. return keyname;
  324. }
  325. /**
  326. * Returns the number of keys in storage.
  327. *
  328. * @return The number of keys
  329. *
  330. */
  331. public function getLength():int
  332. {
  333. return _archive.hash.length;
  334. }
  335. /**
  336. * Returns the storage object as an Array of name/value pairs.
  337. *
  338. *
  339. * @return The storage dictionary as an Array
  340. *
  341. */
  342. public function getItems():Array
  343. {
  344. var len:int = getLength();
  345. var array:Array = [];
  346. for (var i:uint = 0; i < len; i++)
  347. {
  348. array.push(_archive.storage[ _archive.hash[i] ] );
  349. }
  350. return array;
  351. }
  352. /**
  353. * Removes the data in local storage at the specified location, if any.
  354. *
  355. * @param location The name of the "cookie" or store
  356. * @return Whether the remove was successful
  357. *
  358. */
  359. public function removeItem(location:String):Boolean
  360. {
  361. var index: int = getIndexOf(location);
  362. var oldValue:Object = _archive.storage[location];
  363. delete _archive.storage[location];
  364. _archive.hash.splice(index, 1);
  365. var result:Boolean = save(location, "delete", oldValue, null, index);
  366. return result;
  367. }
  368. /**
  369. * Removes the data in local storage at the specified location, if any.
  370. *
  371. * @param location The name of the "cookie" or store
  372. * @return Whether the remove was successful
  373. *
  374. */
  375. public function removeItemAt(index:int):Boolean
  376. {
  377. var oldValue:Object = getValueAt(index);
  378. var location:String = getNameAt(index);
  379. delete _archive.storage[location];
  380. _archive.hash.splice(index, 1);
  381. var result:Boolean = save(location, "delete", oldValue, null, index);
  382. return result;
  383. }
  384. /**
  385. * Removes all data in local storage for this domain.
  386. * <p>Be careful when using this method, as it may
  387. * remove stored information that is used by other applications
  388. * in this domain </p>
  389. *
  390. * @return Whether the clear was successful
  391. *
  392. */
  393. public function clear():Boolean
  394. {
  395. _sharedObject.clear();
  396. _archive = {storage:{}, hash:[]};
  397. var evt:Object = {type: "save"};
  398. yuibridge.sendEvent(evt);
  399. return true;
  400. }
  401. /**
  402. * Gets the amount of space taken by the current store. Note that this value is
  403. * calculated as requested, so large datasets could result in reduced performance.
  404. * @return the size of the store in KB
  405. */
  406. public function calculateCurrentSize():uint
  407. {
  408. var sz:uint = _sharedObject.size;
  409. return sz;
  410. }
  411. /**
  412. * This method requests more storage if the amount is above the current limit (typically ~100KB).
  413. * The request dialog has to be displayed within the Flash player itself
  414. * so the SWF it is called from must be visible and at least 215px x 138px in size.
  415. *
  416. * Since this is a "per domain" setting, you can
  417. * use this method on a SWF in a separate page, such as a settings page,
  418. * if the width/height of the compiled SWF is not large enough to fit this dialog.
  419. *
  420. * @param value The size, in KB
  421. */
  422. public function setSize(value:int):String
  423. {
  424. var status:String;
  425. status = _sharedObject.flush(value * 1024);
  426. //on error, attempt to resize div?
  427. return status;
  428. }
  429. /**
  430. * Displays the settings dialog to allow the user to configure
  431. * storage settings manually. If the SWF height and width are smaller than
  432. * what is allowable to display the local settings panel,
  433. * an error message will be sent to JavaScript.
  434. */
  435. public function displaySettings():void
  436. {
  437. var evt:Object;
  438. if( hasAdequateDimensions() )
  439. {
  440. evt = {type: "openingDialog"};
  441. yuibridge.sendEvent(evt);
  442. Security.showSettings(SecurityPanel.LOCAL_STORAGE);
  443. }
  444. else
  445. {
  446. evt = {type: "inadequateDimensions", message: "The current size of the SWF is too small to display " +
  447. "the settings panel. Please increase the available width and height to 215px x 138px or larger."};
  448. yuibridge.sendEvent(evt);
  449. }
  450. }
  451. /**
  452. * Gets the timestamp of the last store. This value is automatically set when
  453. * data is stored.
  454. * @return A Date object
  455. */
  456. public function getModificationDate():Date
  457. {
  458. var lastDate:Date = new Date(_sharedObject.data.modificationDate);
  459. return lastDate;
  460. }
  461. //--------------------------------------
  462. // Private Methods
  463. //--------------------------------------
  464. /**
  465. * @private
  466. * Gets the index of the item at the specified location
  467. * @param location The name of the key
  468. */
  469. private function getIndexOf(location:String):int
  470. {
  471. return _archive.hash.indexOf(location);
  472. }
  473. /**
  474. * @private
  475. * Loads the whitlist XML file
  476. *
  477. */
  478. private function loadWhitelist():void
  479. {
  480. var whitelistLoader:URLLoader = new URLLoader();
  481. whitelistLoader.addEventListener(Event.COMPLETE, onComplete);
  482. whitelistLoader.addEventListener(IOErrorEvent.IO_ERROR, onError);
  483. whitelistLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
  484. //don't use a relative path, use the swf's loaded path
  485. //to prevent crossdomain or base param workarounds
  486. var fullPath:String = loaderInfo.url;
  487. //remove trailing slashes
  488. var parentPath:String;
  489. var hasTrailingSlash:Boolean = fullPath.charAt(fullPath.length - 1) == "/";
  490. if(hasTrailingSlash) fullPath = fullPath.slice(0, -1);
  491. //now get the path before the final slash (something like "/swffile.swf")
  492. parentPath = fullPath.slice(0,fullPath.lastIndexOf("/"));
  493. var localpath:String = parentPath + "/" + _whitelistFileName;
  494. whitelistLoader.load(new URLRequest(localpath));
  495. }
  496. /**
  497. * @private
  498. * Parses the config xml data and populates path array
  499. *
  500. */
  501. private function onComplete (event:Event) : void
  502. {
  503. var contentXML:XML;
  504. try
  505. {
  506. contentXML = new XML(event.target.data);
  507. }
  508. catch(error:TypeError)
  509. {
  510. yuibridge.sendEvent({type:"error", message:error.message});
  511. }
  512. var valid:Boolean;
  513. var pageURL:String = ExternalInterface.call("function(){return window.location.href;}");
  514. for each (var path:XML in contentXML["allow-access-from"] )
  515. {
  516. var url:String = path.@url;
  517. if(pathMatches(pageURL, url))
  518. {
  519. valid = true;
  520. break;
  521. }
  522. }
  523. if(valid) initializeSharedObject();
  524. //not a valid whitelist, dispatch error
  525. else
  526. {
  527. var evt:Object = {type: "securityError", message: "Security Error: the whitelist does not allow access to storage from this location" };
  528. yuibridge.sendEvent(evt);
  529. }
  530. }
  531. private function pathMatches(page:String, path:String):Boolean
  532. {
  533. //remove the protocol when matching domains, because protocols are not to be specified in the whitelist
  534. /* var protocolPattern: RegExp = new RegExp("(http|https|file)\:\/\/");
  535. var pathWithoutProtocol:String = url.replace(protocolPattern, "");
  536. var pageURLWithoutProtocol:String = url.replace(pageURL, ""); */
  537. //ExternalInterface.call("alert('this page's url: " + page + "/nproposed url: " + path + "')");
  538. if(page.indexOf(path) > -1)
  539. {
  540. //if the loading page's url contains the whitelisted url as a substring, pass it
  541. return true;
  542. }
  543. else return false;
  544. }
  545. /**
  546. * @private
  547. * Dispatches an IOErrorEvent
  548. *
  549. */
  550. private function onError(event:IOErrorEvent) : void
  551. {
  552. //trace("no whitelist file");
  553. //try matching the url, a default action since no whitelist was specified
  554. performURLMatch();
  555. }
  556. /**
  557. * @private
  558. * Dispatches a SecurityErrorEvent
  559. *
  560. */
  561. private function onSecurityError(event:SecurityErrorEvent) : void
  562. {
  563. var evt:Object = {type: "securityError", message: event.text };
  564. yuibridge.sendEvent(evt);
  565. }
  566. /**
  567. * Expands a path with shorthands to url
  568. *
  569. * @param path Path with shorthands
  570. * @return Path with shorthands expanded
  571. */
  572. public function getPath (path:String) : String {
  573. var newPath:String = path.replace(/%(.*)%/, getPath);
  574. return newPath;
  575. }
  576. private function performURLMatch():void
  577. {
  578. try
  579. {
  580. //check that page url is the same as the swf's url //host gives main domain?
  581. //ExternalInterface.call("function(){alert(window.location.href)}");
  582. var currentURL:String = ExternalInterface.call("function(){return window.location.href;}");
  583. if(currentURL.indexOf("?") > -1)
  584. {
  585. currentURL = currentURL.slice(0,currentURL.indexOf("?"));
  586. }
  587. currentURL = currentURL.slice(0,currentURL.lastIndexOf("/"));
  588. var loadedURL:String = loaderInfo.url;
  589. if(loadedURL.indexOf("?") > -1)
  590. {
  591. loadedURL = loadedURL.slice(0,loadedURL.indexOf("?"));
  592. }
  593. loadedURL = loadedURL.slice(0,loadedURL.lastIndexOf("/"));
  594. var currentURL_ESC:String = unescape(currentURL) ;
  595. var loadedURL_ESC:String = unescape(loadedURL)
  596. if(currentURL_ESC == loadedURL_ESC )
  597. {
  598. initializeSharedObject();
  599. }
  600. else
  601. {
  602. var evt:Object = {type: "securityError", message: "The domain of the page must match the SWF's domain.\nPage's URL: " +
  603. currentURL + "\n" + "SWF's URL: " + loadedURL};
  604. yuibridge.sendEvent(evt);
  605. }
  606. }
  607. catch(e:Error)
  608. {
  609. yuibridge.sendEvent(e);
  610. }
  611. }
  612. protected function initializeSharedObject():void
  613. {
  614. var localPath:String = null;//loaderInfo.parameters.localPath || null;
  615. var browser:String = loaderInfo.parameters.browser || "other";
  616. if(!_initialized)
  617. {
  618. _shareData = loaderInfo.parameters.shareData == "true";
  619. _useCompression = loaderInfo.parameters.useCompression == "true";
  620. }
  621. var loc:String = "DataStore_" + (_shareData?"":browser);
  622. _sharedObject = SharedObject.getLocal(loc, localPath);
  623. _sharedObject.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
  624. //initialize
  625. if(!_sharedObject.data.hasOwnProperty("archive"))
  626. {
  627. _archive = {storage:{}, hash:[]};
  628. }
  629. else
  630. {
  631. //if compression is detected to be in use, we must decompress it first
  632. if(_sharedObject.data.archive is ByteArray)
  633. {
  634. //remember that sharedobjects are flushed automatically when the page destroys the SWF.
  635. var tempBytes:ByteArray = _sharedObject.data.archive as ByteArray;
  636. //make a clone of the current shared object
  637. var bytes:ByteArray = new ByteArray();
  638. tempBytes.readBytes(bytes, 0, tempBytes.length);
  639. //NOTE: there may be a way to read the first few bytes and determine if it is compressed
  640. try
  641. {
  642. bytes.uncompress();
  643. }
  644. catch(error:Error)
  645. {
  646. //there's an error decompressing
  647. yuibridge.sendEvent({type: "error", message:error.message});
  648. }
  649. _archive = bytes.readObject();
  650. }
  651. else
  652. {
  653. _archive = _sharedObject.data.archive;
  654. }
  655. }
  656. //if(!_initialized)
  657. {
  658. _initialized = true;
  659. //once initialization is complete, let JS know
  660. yuibridge.sendEvent({type:"contentReady"});
  661. }
  662. }
  663. /**
  664. * @private
  665. * Returns the key/value pair in storage, if any, at the specified index.
  666. * Similar to get key() in HTML5
  667. * @param index The index of the "cookie" or store
  668. * @return The data
  669. *
  670. */
  671. protected function getKeyValueAt(index:int):Object
  672. {
  673. return getItems()[index];
  674. }
  675. /**
  676. * @private
  677. * Writes the store to disk. While this will be called by Flash
  678. * whenever the application is closed, calling it immediately after
  679. * new information allows that info to be instantly available.
  680. *
  681. * @return Whether or not the save was successful
  682. */
  683. protected function save( location:String = null, info:String = "add", oldValue:Object = null, newValue:Object = null, index:int = -1):Boolean
  684. {
  685. var evt:Object = {};
  686. var type:String = "save";
  687. //set the time modified UTC
  688. if(newValue)
  689. {
  690. setTime(new Date().getTime());
  691. }
  692. if(_useCompression)
  693. {
  694. var bytes:ByteArray = new ByteArray();
  695. bytes.writeObject(_archive);
  696. bytes.compress();
  697. _sharedObject.data.archive = bytes;
  698. }
  699. else _sharedObject.data.archive = _archive;
  700. var result:String;
  701. try
  702. {
  703. result = _sharedObject.flush();
  704. }
  705. catch(e:Error)
  706. {
  707. //event will be throw further down
  708. }
  709. //return status
  710. if(result == SharedObjectFlushStatus.FLUSHED)
  711. {
  712. //there may be future issues here with 40k+ storage, because due to the HTML5 spec,
  713. //old and new values must be sent back--for a 40k update, this means sending 80k back in the event
  714. evt.type = type;
  715. evt.info = info;
  716. evt.key = location;
  717. evt.oldValue = oldValue;
  718. evt.newValue = newValue;
  719. evt.index = index;
  720. yuibridge.sendEvent(evt);
  721. return true;
  722. }
  723. if(result == SharedObjectFlushStatus.PENDING)
  724. {
  725. //let JS know theres going to be a dialog
  726. evt = {type: "pending"};
  727. yuibridge.sendEvent(evt);
  728. return false;
  729. }
  730. else
  731. {
  732. evt = {type: "error", message:"Unable to save. Client-side storage has been disabled for this domain. To enable, display the Flash settings panel and set a storage amount."};
  733. yuibridge.sendEvent(evt);
  734. return false;
  735. }
  736. return false;
  737. }
  738. /**
  739. * @private
  740. * Sets the date modified for the store, based on the user's clock.
  741. *
  742. * @param value The time to set, as a Number.
  743. *
  744. */
  745. protected function setTime(value:Number):void
  746. {
  747. _sharedObject.data.modificationDate = value;
  748. }
  749. /**
  750. * @private
  751. * Called when a larger shared object size is requested
  752. * @param the NetStatusEvent object.
  753. */
  754. protected function onNetStatus(event:NetStatusEvent):void
  755. {
  756. var evt:Object;
  757. if(event.info.level =="error")
  758. {
  759. //this is most likely the result of maxing out storage for the domain. There's no way to tell for certain
  760. evt = {type: "quotaExceededError", info:"NetStatus Error: " + event.info.code,
  761. message: "Storage capacity requested exceeds available amount."};
  762. yuibridge.sendEvent(evt);
  763. }
  764. else
  765. {
  766. //this is normally executed when additional storage is requested and allowed by the user
  767. evt = {type: "success"};
  768. yuibridge.sendEvent(evt);
  769. }
  770. }
  771. /**
  772. *
  773. * Helper function to determine if SWF visible area is large enough to fit
  774. * the settings panel
  775. * @return Boolean Whether or not the area is large enough.
  776. */
  777. public function hasAdequateDimensions():Boolean
  778. {
  779. return (stage.stageHeight >= MINIMUM_HEIGHT) && (stage.stageWidth >= MINIMUM_WIDTH);
  780. }
  781. }
  782. }