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.callApiBound_ = this.callApi_.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.callApiBound_, 0); |
| 593 } |
| 594 }; |
| 595 |
| 596 /** |
| 597 * Schedules the API call. |
| 598 * @private |
| 599 */ |
| 600 GDataProvider.prototype.callApi_ = function() { |
| 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 |