OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * MetadataCache is a map from url to an object containing properties. | 6 * MetadataCache is a map from url to an object containing properties. |
7 * Properties are divided by types, and all properties of one type are accessed | 7 * Properties are divided by types, and all properties of one type are accessed |
8 * at once. | 8 * at once. |
9 * Some of the properties: | 9 * Some of the properties: |
10 * { | 10 * { |
11 * filesystem: size, modificationTime, icon, fileType | 11 * filesystem: size, modificationTime, icon, fileType |
12 * internal: presence | 12 * internal: presence |
13 * gdata: pinned, present, dirty, editUrl | 13 * gdata: pinned, present, hosted, editUrl, contentUrl, availableOffline |
14 * thumbnail: url, transform | 14 * thumbnail: url, transform |
15 * media: artist, album, title | 15 * media: artist, album, title |
16 * } | 16 * } |
17 * | 17 * |
18 * Typical usages: | 18 * Typical usages: |
19 * { | 19 * { |
20 * cache.get([entry1, entry2], 'gdata', function(gdata) { | 20 * cache.get([entry1, entry2], 'gdata', function(gdata) { |
21 * if (gdata[0].pinned && gdata[1].pinned) alert("They are both pinned!"); | 21 * if (gdata[0].pinned && gdata[1].pinned) alert("They are both pinned!"); |
22 * }); | 22 * }); |
23 * | 23 * |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
81 * of the url passed. | 81 * of the url passed. |
82 */ | 82 */ |
83 MetadataCache.DESCENDANTS = 2; | 83 MetadataCache.DESCENDANTS = 2; |
84 | 84 |
85 /** | 85 /** |
86 * @return {MetadataCache!} The cache with all providers. | 86 * @return {MetadataCache!} The cache with all providers. |
87 */ | 87 */ |
88 MetadataCache.createFull = function() { | 88 MetadataCache.createFull = function() { |
89 var cache = new MetadataCache(); | 89 var cache = new MetadataCache(); |
90 cache.providers_.push(new FilesystemProvider()); | 90 cache.providers_.push(new FilesystemProvider()); |
91 cache.providers_.push(new GDataProvider()); | |
91 return cache; | 92 return cache; |
92 }; | 93 }; |
93 | 94 |
94 /** | 95 /** |
95 * Fetches the metadata, puts it in the cache, and passes to callback. | 96 * Fetches the metadata, puts it in the cache, and passes to callback. |
96 * If required metadata is already in the cache, does not fetch it again. | 97 * If required metadata is already in the cache, does not fetch it again. |
97 * @param {string|Entry|Array.<string|Entry>} items The list of entries or | 98 * @param {string|Entry|Array.<string|Entry>} items The list of entries or |
98 * file urls. May be just a single item. | 99 * file urls. May be just a single item. |
99 * @param {string} type The metadata type. | 100 * @param {string} type The metadata type. |
100 * @param {Function(Object)} callback The metadata is passed to callback. | 101 * @param {Function(Object)} callback The metadata is passed to callback. |
(...skipping 11 matching lines...) Expand all Loading... | |
112 | 113 |
113 var result = []; | 114 var result = []; |
114 var remaining = items.length; | 115 var remaining = items.length; |
115 this.startBatchUpdates(); | 116 this.startBatchUpdates(); |
116 | 117 |
117 function onOneItem(index, value) { | 118 function onOneItem(index, value) { |
118 result[index] = value; | 119 result[index] = value; |
119 remaining--; | 120 remaining--; |
120 if (remaining == 0) { | 121 if (remaining == 0) { |
121 this.endBatchUpdates(); | 122 this.endBatchUpdates(); |
122 if (callback) callback(result); | 123 if (callback) setTimeout(callback, 0, result); |
123 } | 124 } |
124 } | 125 } |
125 | 126 |
126 for (var index = 0; index < items.length; index++) { | 127 for (var index = 0; index < items.length; index++) { |
127 result.push(null); | 128 result.push(null); |
128 this.getOne(items[index], type, onOneItem.bind(this, index)); | 129 this.getOne(items[index], type, onOneItem.bind(this, index)); |
129 } | 130 } |
130 }; | 131 }; |
131 | 132 |
132 /** | 133 /** |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
444 * to metadata value. | 445 * to metadata value. |
445 * @param {Entry=} opt_entry The file entry if present. | 446 * @param {Entry=} opt_entry The file entry if present. |
446 */ | 447 */ |
447 MetadataProvider2.prototype.fetch = function(url, type, callback, opt_entry) { | 448 MetadataProvider2.prototype.fetch = function(url, type, callback, opt_entry) { |
448 throw new Error('Default metadata provider cannot fetch.'); | 449 throw new Error('Default metadata provider cannot fetch.'); |
449 }; | 450 }; |
450 | 451 |
451 | 452 |
452 /** | 453 /** |
453 * Provider of filesystem metadata. | 454 * Provider of filesystem metadata. |
454 * This provider returns the following object: | 455 * This provider returns the following objects: |
455 * { | 456 * filesystem: { |
456 * size; | 457 * size; |
457 * modificationTime; | 458 * modificationTime; |
458 * icon - string describing icon type; | 459 * icon - string describing icon type; |
459 * fileType - the file type object from file_type.js. | 460 * fileType - the file type object from file_type.js. |
460 * } | 461 * } |
461 * @constructor | 462 * @constructor |
462 */ | 463 */ |
463 function FilesystemProvider() { | 464 function FilesystemProvider() { |
464 MetadataProvider2.call(this, 'filesystem'); | 465 MetadataProvider2.call(this, 'filesystem'); |
465 } | 466 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
518 | 519 |
519 function onEntry(entry) { | 520 function onEntry(entry) { |
520 entry.getMetadata(onMetadata.bind(null, entry), onError); | 521 entry.getMetadata(onMetadata.bind(null, entry), onError); |
521 } | 522 } |
522 | 523 |
523 if (opt_entry) | 524 if (opt_entry) |
524 onEntry(opt_entry); | 525 onEntry(opt_entry); |
525 else | 526 else |
526 webkitResolveLocalFileSystemURL(url, onEntry, onError); | 527 webkitResolveLocalFileSystemURL(url, onEntry, onError); |
527 }; | 528 }; |
529 | |
530 /** | |
531 * Provider of gdata metadata. | |
532 * This provider returns the following objects: | |
533 * gdata: { pinned, hosted, present, dirty, editUrl, contentUrl } | |
534 * thumbnail: { url, transform } | |
535 * @constructor | |
536 */ | |
537 function GDataProvider() { | |
538 MetadataProvider2.call(this, 'gdata'); | |
539 | |
540 // We batch metadata fetches into single API call. | |
541 this.urls_ = []; | |
542 this.callbacks_ = []; | |
543 this.scheduled_ = false; | |
544 | |
545 this.scheduleBound_ = this.schedule_.bind(this); | |
546 } | |
547 | |
548 GDataProvider.prototype = { | |
549 __proto__: MetadataProvider2.prototype | |
550 }; | |
551 | |
552 /** | |
553 * Pattern for urls supported by GDataProvider. | |
554 */ | |
555 GDataProvider.URL_PATTERN = | |
556 new RegExp('^filesystem:[^/]*://[^/]*/[^/]*/gdata/(.*)'); | |
557 | |
558 /** | |
559 * @param {string} url The url. | |
560 * @return {boolean} Whether this provider supports the url. | |
561 */ | |
562 GDataProvider.prototype.supportsUrl = function(url) { | |
563 return GDataProvider.URL_PATTERN.test(url); | |
564 }; | |
565 | |
566 /** | |
567 * @param {string} type The metadata type. | |
568 * @return {boolean} Whether this provider provides this metadata. | |
569 */ | |
570 GDataProvider.prototype.providesType = function(type) { | |
571 return type == 'gdata' || type == 'thumbnail'; | |
572 }; | |
573 | |
574 /** | |
575 * @return {string} Unique provider id. | |
576 */ | |
577 GDataProvider.prototype.getId = function() { return 'gdata'; }; | |
578 | |
579 /** | |
580 * Fetches the metadata. | |
581 * @param {string} url File url. | |
582 * @param {string} type Requested metadata type. | |
583 * @param {Function(Object)} callback Callback expects a map from metadata type | |
584 * to metadata value. | |
585 * @param {Entry=} opt_entry The file entry if present. | |
586 */ | |
587 GDataProvider.prototype.fetch = function(url, type, callback, opt_entry) { | |
588 this.urls_.push(url); | |
589 this.callbacks_.push(callback); | |
590 if (!this.scheduled_) { | |
591 this.scheduled_ = true; | |
592 setTimeout(this.scheduleBound_, 0); | |
593 } | |
594 }; | |
595 | |
596 /** | |
597 * Schedules the API call. | |
598 * @private | |
599 */ | |
600 GDataProvider.prototype.schedule_ = function() { | |
Vladislav Kaznacheev
2012/04/24 12:48:10
The method name is confusing. "Schedule" means "do
dgozman
2012/04/24 13:18:08
Done.
| |
601 this.scheduled_ = false; | |
602 | |
603 var urls = this.urls_; | |
604 var callbacks = this.callbacks_; | |
605 this.urls_ = []; | |
606 this.callbacks_ = []; | |
607 var self = this; | |
608 | |
609 chrome.fileBrowserPrivate.getGDataFileProperties(urls, function(props) { | |
610 for (var index = 0; index < urls.length; index++) { | |
611 callbacks[index](self.convert_(props[index])); | |
612 } | |
613 }); | |
614 }; | |
615 | |
616 /** | |
617 * Converts API metadata to internal format. | |
618 * @param {Object} data Metadata from API call. | |
619 * @return {Object} Metadata in internal format. | |
620 * @private | |
621 */ | |
622 GDataProvider.prototype.convert_ = function(data) { | |
623 var result = {}; | |
624 result.gdata = { | |
625 present: data.isPresent, | |
626 pinned: data.isPinned, | |
627 hosted: data.isHosted, | |
628 dirty: data.isDirty, | |
629 availableOffline: data.isPresent && !data.isHosted, | |
630 contentUrl: (data.contentUrl || '').replace(/\?.*$/gi, ''), | |
631 editUrl: data.editUrl || '' | |
632 }; | |
633 if ('thumbnailUrl' in data) { | |
634 result.thumbnail = { | |
635 url: data.thumbnailUrl, | |
636 transform: '' | |
637 }; | |
638 } | |
639 return result; | |
640 }; | |
OLD | NEW |