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 * FileManager constructor. | 6 * FileManager constructor. |
7 * | 7 * |
8 * FileManager objects encapsulate the functionality of the file selector | 8 * FileManager objects encapsulate the functionality of the file selector |
9 * dialogs, as well as the full screen file manager application (though the | 9 * dialogs, as well as the full screen file manager application (though the |
10 * latter is not yet implemented). | 10 * latter is not yet implemented). |
(...skipping 11 matching lines...) Expand all Loading... |
22 | 22 |
23 this.listType_ = null; | 23 this.listType_ = null; |
24 | 24 |
25 this.selection = null; | 25 this.selection = null; |
26 | 26 |
27 this.butterTimer_ = null; | 27 this.butterTimer_ = null; |
28 this.currentButter_ = null; | 28 this.currentButter_ = null; |
29 this.butterLastShowTime_ = 0; | 29 this.butterLastShowTime_ = 0; |
30 | 30 |
31 this.watchedDirectoryUrl_ = null; | 31 this.watchedDirectoryUrl_ = null; |
32 this.metadataObserverId_ = null; | 32 this.filesystemObserverId_ = null; |
| 33 this.gdataObserverId_ = null; |
33 | 34 |
34 this.commands_ = {}; | 35 this.commands_ = {}; |
35 | 36 |
36 this.thumbnailUrlCache_ = {}; | 37 this.thumbnailUrlCache_ = {}; |
37 | 38 |
38 this.document_ = dialogDom.ownerDocument; | 39 this.document_ = dialogDom.ownerDocument; |
39 this.dialogType_ = this.params_.type || FileManager.DialogType.FULL_PAGE; | 40 this.dialogType_ = this.params_.type || FileManager.DialogType.FULL_PAGE; |
40 | 41 |
41 metrics.recordEnum('Create', this.dialogType_, | 42 metrics.recordEnum('Create', this.dialogType_, |
42 [FileManager.DialogType.SELECT_FOLDER, | 43 [FileManager.DialogType.SELECT_FOLDER, |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 * | 179 * |
179 * @param {string} path The file path. | 180 * @param {string} path The file path. |
180 */ | 181 */ |
181 function normalizeAbsolutePath(x) { | 182 function normalizeAbsolutePath(x) { |
182 if (x[0] == '/') | 183 if (x[0] == '/') |
183 return x.slice(1); | 184 return x.slice(1); |
184 else | 185 else |
185 return x; | 186 return x; |
186 } | 187 } |
187 | 188 |
188 | |
189 /** | |
190 * Call an asynchronous method on dirEntry, batching multiple callers. | |
191 * | |
192 * This batches multiple callers into a single invocation, calling all | |
193 * interested parties back when the async call completes. | |
194 * | |
195 * The Entry method to be invoked should take two callbacks as parameters | |
196 * (one for success and one for failure), and it should invoke those | |
197 * callbacks with a single parameter representing the result of the call. | |
198 * Example methods are Entry.getMetadata() and FileEntry.file(). | |
199 * | |
200 * Warning: Because this method caches the first result, subsequent changes | |
201 * to the entry will not be visible to callers. | |
202 * | |
203 * Error results are never cached. | |
204 * | |
205 * @param {DirectoryEntry} dirEntry The DirectoryEntry to apply the method | |
206 * to. | |
207 * @param {string} methodName The name of the method to dispatch. | |
208 * @param {function(*)} successCallback The function to invoke if the method | |
209 * succeeds. The result of the method will be the one parameter to this | |
210 * callback. | |
211 * @param {function(*)} opt_errorCallback The function to invoke if the | |
212 * method fails. The result of the method will be the one parameter to | |
213 * this callback. If not provided, the default errorCallback will throw | |
214 * an exception. | |
215 */ | |
216 function batchAsyncCall(entry, methodName, successCallback, | |
217 opt_errorCallback) { | |
218 var resultCache = methodName + '_resultCache_'; | |
219 | |
220 if (entry[resultCache]) { | |
221 // The result cache for this method already exists. Just invoke the | |
222 // successCallback with the result of the previuos call. | |
223 // Callback via a setTimeout so the sync/async semantics don't change | |
224 // based on whether or not the value is cached. | |
225 setTimeout(function() { successCallback(entry[resultCache]) }, 0); | |
226 return; | |
227 } | |
228 | |
229 if (!opt_errorCallback) { | |
230 opt_errorCallback = util.ferr('Error calling ' + methodName + ' for: ' + | |
231 entry.fullPath); | |
232 } | |
233 | |
234 var observerList = methodName + '_observers_'; | |
235 | |
236 if (entry[observerList]) { | |
237 // The observer list already exists, indicating we have a pending call | |
238 // out to this method. Add this caller to the list of observers and | |
239 // bail out. | |
240 entry[observerList].push([successCallback, opt_errorCallback]); | |
241 return; | |
242 } | |
243 | |
244 entry[observerList] = [[successCallback, opt_errorCallback]]; | |
245 | |
246 function onComplete(success, result) { | |
247 if (success) | |
248 entry[resultCache] = result; | |
249 | |
250 for (var i = 0; i < entry[observerList].length; i++) { | |
251 entry[observerList][i][success ? 0 : 1](result); | |
252 } | |
253 | |
254 delete entry[observerList]; | |
255 }; | |
256 | |
257 entry[methodName](function(rv) { onComplete(true, rv) }, | |
258 function(rv) { onComplete(false, rv) }); | |
259 } | |
260 | |
261 /** | |
262 * Invoke callback in sync/async manner. | |
263 * @param {function(*)?} callback The callback. If null, nothing is called. | |
264 * @param {boolean} sync True iff the callback should be called synchronously. | |
265 * @param {*} callback_args... The rest are callback arguments. | |
266 */ | |
267 function invokeCallback(callback, sync, callback_args) { | |
268 if (!callback) | |
269 return; | |
270 var args = Array.prototype.slice.call(arguments, 2); | |
271 if (sync) { | |
272 callback.apply(null, args); | |
273 } else { | |
274 setTimeout(function() { callback.apply(null, args); }, 0); | |
275 } | |
276 } | |
277 | |
278 function cacheGDataProps(entry, successCallback, | |
279 opt_errorCallback, opt_sync) { | |
280 if ('gdata_' in entry) { | |
281 invokeCallback(successCallback, !!opt_sync, entry); | |
282 return; | |
283 } | |
284 | |
285 entry.getGDataFileProperties = entry.getGDataFileProperties || | |
286 function(callback) { | |
287 var queue = cacheGDataProps.queue_; | |
288 queue.callbacks.push(callback); | |
289 queue.urls.push(entry.toURL()); | |
290 if (!queue.scheduled) { | |
291 queue.scheduled = true; | |
292 setTimeout(function() { | |
293 queue.scheduled = false; | |
294 var callbacks = queue.callbacks; | |
295 var urls = queue.urls; | |
296 chrome.fileBrowserPrivate.getGDataFileProperties(urls, | |
297 function(props) { | |
298 for (var i = 0; i < callbacks.length; i++) { | |
299 callbacks[i](props[i]); | |
300 } | |
301 }); | |
302 queue.callbacks = []; | |
303 queue.urls = []; | |
304 }, 0); | |
305 } | |
306 }; | |
307 | |
308 batchAsyncCall(entry, 'getGDataFileProperties', function(props) { | |
309 entry.gdata_ = props; | |
310 if (successCallback) | |
311 successCallback(entry); | |
312 }, opt_errorCallback); | |
313 } | |
314 | |
315 cacheGDataProps.queue_ = { | |
316 callbacks: [], | |
317 urls: [], | |
318 scheduled: false | |
319 }; | |
320 | |
321 function removeChildren(element) { | 189 function removeChildren(element) { |
322 element.textContent = ''; | 190 element.textContent = ''; |
323 } | 191 } |
324 | 192 |
325 // Public statics. | 193 // Public statics. |
326 | 194 |
327 /** | 195 /** |
328 * List of dialog types. | 196 * List of dialog types. |
329 * | 197 * |
330 * Keep this in sync with FileManagerDialog::GetDialogTypeAsString, except | 198 * Keep this in sync with FileManagerDialog::GetDialogTypeAsString, except |
(...skipping 880 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1211 cr.ui.contextMenuHandler.setContextMenu(this.grid_, this.fileContextMenu_); | 1079 cr.ui.contextMenuHandler.setContextMenu(this.grid_, this.fileContextMenu_); |
1212 }; | 1080 }; |
1213 | 1081 |
1214 /** | 1082 /** |
1215 * Initialize the file list table. | 1083 * Initialize the file list table. |
1216 */ | 1084 */ |
1217 FileManager.prototype.initTable_ = function() { | 1085 FileManager.prototype.initTable_ = function() { |
1218 var renderFunction = this.table_.getRenderFunction(); | 1086 var renderFunction = this.table_.getRenderFunction(); |
1219 this.table_.setRenderFunction(function(entry, parent) { | 1087 this.table_.setRenderFunction(function(entry, parent) { |
1220 var item = renderFunction(entry, parent); | 1088 var item = renderFunction(entry, parent); |
1221 this.styleGDataItem_(entry, item); | 1089 this.displayGDataStyleInItem_( |
| 1090 item, entry, this.metadataCache_.getCached(entry, 'gdata')); |
1222 return item; | 1091 return item; |
1223 }.bind(this)); | 1092 }.bind(this)); |
1224 | 1093 |
1225 var fullPage = (this.dialogType_ == FileManager.DialogType.FULL_PAGE); | 1094 var fullPage = (this.dialogType_ == FileManager.DialogType.FULL_PAGE); |
1226 | 1095 |
1227 var columns = [ | 1096 var columns = [ |
1228 new cr.ui.table.TableColumn('name', str('NAME_COLUMN_LABEL'), | 1097 new cr.ui.table.TableColumn('name', str('NAME_COLUMN_LABEL'), |
1229 fullPage ? 64 : 324), | 1098 fullPage ? 64 : 324), |
1230 new cr.ui.table.TableColumn('size', str('SIZE_COLUMN_LABEL'), | 1099 new cr.ui.table.TableColumn('size', str('SIZE_COLUMN_LABEL'), |
1231 fullPage ? 15.5 : 92, true), | 1100 fullPage ? 15.5 : 92, true), |
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1770 }; | 1639 }; |
1771 | 1640 |
1772 FileManager.prototype.decorateThumbnail_ = function(li, entry) { | 1641 FileManager.prototype.decorateThumbnail_ = function(li, entry) { |
1773 li.className = 'thumbnail-item'; | 1642 li.className = 'thumbnail-item'; |
1774 | 1643 |
1775 if (this.showCheckboxes_) | 1644 if (this.showCheckboxes_) |
1776 li.appendChild(this.renderSelectionCheckbox_(entry)); | 1645 li.appendChild(this.renderSelectionCheckbox_(entry)); |
1777 | 1646 |
1778 li.appendChild(this.renderThumbnailBox_(entry, false)); | 1647 li.appendChild(this.renderThumbnailBox_(entry, false)); |
1779 li.appendChild(this.renderFileNameLabel_(entry)); | 1648 li.appendChild(this.renderFileNameLabel_(entry)); |
1780 this.styleGDataItem_(entry, li); | 1649 this.displayGDataStyleInItem_( |
| 1650 li, entry, this.metadataCache_.getCached(entry, 'gdata')); |
1781 }; | 1651 }; |
1782 | 1652 |
1783 /** | 1653 /** |
1784 * Render the type column of the detail table. | 1654 * Render the type column of the detail table. |
1785 * | 1655 * |
1786 * Invoked by cr.ui.Table when a file needs to be rendered. | 1656 * Invoked by cr.ui.Table when a file needs to be rendered. |
1787 * | 1657 * |
1788 * @param {Entry} entry The Entry object to render. | 1658 * @param {Entry} entry The Entry object to render. |
1789 * @param {string} columnId The id of the column to be rendered. | 1659 * @param {string} columnId The id of the column to be rendered. |
1790 * @param {cr.ui.Table} table The table doing the rendering. | 1660 * @param {cr.ui.Table} table The table doing the rendering. |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1888 /** | 1758 /** |
1889 * Unmounts device. | 1759 * Unmounts device. |
1890 * @param {Entry} entry The entry to unmount. | 1760 * @param {Entry} entry The entry to unmount. |
1891 */ | 1761 */ |
1892 FileManager.prototype.unmountVolume_ = function(entry) { | 1762 FileManager.prototype.unmountVolume_ = function(entry) { |
1893 this.directoryModel_.prepareUnmount(entry.fullPath); | 1763 this.directoryModel_.prepareUnmount(entry.fullPath); |
1894 this.unmountRequests_.push(entry.fullPath); | 1764 this.unmountRequests_.push(entry.fullPath); |
1895 chrome.fileBrowserPrivate.removeMount(entry.toURL()); | 1765 chrome.fileBrowserPrivate.removeMount(entry.toURL()); |
1896 }; | 1766 }; |
1897 | 1767 |
1898 FileManager.prototype.styleGDataItem_ = function(entry, listItem) { | 1768 FileManager.prototype.displayGDataStyleInItem_ = function( |
1899 if (!this.isOnGData()) | 1769 listItem, entry, gdata) { |
| 1770 if (!this.isOnGData() || !gdata) |
1900 return; | 1771 return; |
1901 | 1772 |
1902 cacheGDataProps(entry, function(entry) { | 1773 if (gdata.hosted) { |
1903 if (!entry.gdata_) | 1774 listItem.classList.add('gdata-hosted'); |
1904 return; | 1775 } |
1905 | 1776 if (entry.isDirectory || gdata.availableOffline) { |
1906 if (entry.gdata_.isHosted) { | 1777 listItem.classList.add('gdata-present'); |
1907 listItem.classList.add('gdata-hosted'); | 1778 } |
1908 } | |
1909 if (entry.isDirectory || FileManager.isAvaliableOffline_(entry.gdata_)) { | |
1910 listItem.classList.add('gdata-present'); | |
1911 } | |
1912 }.bind(this)); | |
1913 }; | 1779 }; |
1914 | 1780 |
1915 /** | 1781 /** |
1916 * Render the Name column of the detail table. | 1782 * Render the Name column of the detail table. |
1917 * | 1783 * |
1918 * Invoked by cr.ui.Table when a file needs to be rendered. | 1784 * Invoked by cr.ui.Table when a file needs to be rendered. |
1919 * | 1785 * |
1920 * @param {Entry} entry The Entry object to render. | 1786 * @param {Entry} entry The Entry object to render. |
1921 * @param {string} columnId The id of the column to be rendered. | 1787 * @param {string} columnId The id of the column to be rendered. |
1922 * @param {cr.ui.Table} table The table doing the rendering. | 1788 * @param {cr.ui.Table} table The table doing the rendering. |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2054 var div = doc.createElement('div'); | 1920 var div = doc.createElement('div'); |
2055 div.className = 'offline'; | 1921 div.className = 'offline'; |
2056 | 1922 |
2057 if (entry.isDirectory) | 1923 if (entry.isDirectory) |
2058 return div; | 1924 return div; |
2059 | 1925 |
2060 var checkbox = this.renderCheckbox_(); | 1926 var checkbox = this.renderCheckbox_(); |
2061 checkbox.classList.add('pin'); | 1927 checkbox.classList.add('pin'); |
2062 checkbox.addEventListener('click', | 1928 checkbox.addEventListener('click', |
2063 this.onPinClick_.bind(this, checkbox, entry)); | 1929 this.onPinClick_.bind(this, checkbox, entry)); |
| 1930 checkbox.style.display = 'none'; |
| 1931 div.appendChild(checkbox); |
2064 | 1932 |
2065 if (this.isOnGData()) { | 1933 if (this.isOnGData()) { |
2066 cacheGDataProps(entry, function(entry) { | 1934 this.displayOfflineInDiv_( |
2067 if (entry.gdata_.isHosted) | 1935 div, this.metadataCache_.getCached(entry, 'gdata')); |
2068 return; | |
2069 checkbox.checked = entry.gdata_.isPinned; | |
2070 div.appendChild(checkbox); | |
2071 }); | |
2072 } | 1936 } |
2073 return div; | 1937 return div; |
2074 }; | 1938 }; |
2075 | 1939 |
| 1940 FileManager.prototype.displayOfflineInDiv_ = function(div, gdata) { |
| 1941 if (!gdata) return; |
| 1942 if (gdata.hosted) return; |
| 1943 var checkbox = div.querySelector('.pin'); |
| 1944 if (!checkbox) return; |
| 1945 checkbox.style.display = ''; |
| 1946 checkbox.checked = gdata.pinned; |
| 1947 }; |
| 1948 |
2076 FileManager.prototype.refreshCurrentDirectoryMetadata_ = function() { | 1949 FileManager.prototype.refreshCurrentDirectoryMetadata_ = function() { |
2077 var entries = this.directoryModel_.fileList.slice(); | 1950 var entries = this.directoryModel_.fileList.slice(); |
2078 this.metadataCache_.clear(entries, 'filesystem'); | |
2079 // We don't pass callback here. When new metadata arrives, we have an | 1951 // We don't pass callback here. When new metadata arrives, we have an |
2080 // observer registered to update the UI. | 1952 // observer registered to update the UI. |
| 1953 |
| 1954 this.metadataCache_.clear(entries, 'filesystem'); |
2081 this.metadataCache_.get(entries, 'filesystem', null); | 1955 this.metadataCache_.get(entries, 'filesystem', null); |
| 1956 if (this.isOnGData()) { |
| 1957 this.metadataCache_.clear(entries, 'gdata'); |
| 1958 this.metadataCache_.get(entries, 'gdata', null); |
| 1959 } |
2082 }; | 1960 }; |
2083 | 1961 |
2084 FileManager.prototype.updateFilesystemPropertiesInUI_ = function( | 1962 FileManager.prototype.updateMetadataInUI_ = function( |
2085 urls, properties) { | 1963 type, urls, properties) { |
2086 if (this.listType_ != FileManager.ListType.DETAIL) return; | 1964 if (this.listType_ != FileManager.ListType.DETAIL) return; |
2087 | 1965 |
2088 var items = {}; | 1966 var items = {}; |
| 1967 var entries = {}; |
2089 var dm = this.directoryModel_.fileList; | 1968 var dm = this.directoryModel_.fileList; |
2090 for (var index = 0; index < dm.length; index++) { | 1969 for (var index = 0; index < dm.length; index++) { |
2091 var listItem = this.currentList_.getListItemByIndex(index); | 1970 var listItem = this.currentList_.getListItemByIndex(index); |
2092 if (!listItem) continue; | 1971 if (!listItem) continue; |
2093 var entry = dm.item(index); | 1972 var entry = dm.item(index); |
2094 items[entry.toURL()] = listItem; | 1973 var url = entry.toURL(); |
| 1974 items[url] = listItem; |
| 1975 entries[url] = entry; |
2095 } | 1976 } |
2096 | 1977 |
2097 for (var index = 0; index < urls.length; index++) { | 1978 for (var index = 0; index < urls.length; index++) { |
2098 var url = urls[index]; | 1979 var url = urls[index]; |
2099 if (!(url in items)) continue; | 1980 if (!(url in items)) continue; |
2100 var listItem = items[url]; | 1981 var listItem = items[url]; |
| 1982 var entry = entries[url]; |
2101 var props = properties[index]; | 1983 var props = properties[index]; |
2102 this.displayDateInDiv_(listItem.querySelector('.date'), props); | 1984 if (type == 'filesystem') { |
2103 this.displaySizeInDiv_(listItem.querySelector('.size'), props); | 1985 this.displayDateInDiv_(listItem.querySelector('.date'), props); |
2104 this.displayTypeInDiv_(listItem.querySelector('.type'), props); | 1986 this.displaySizeInDiv_(listItem.querySelector('.size'), props); |
| 1987 this.displayTypeInDiv_(listItem.querySelector('.type'), props); |
| 1988 } else if (type == 'gdata') { |
| 1989 this.displayOfflineInDiv_(listItem.querySelector('.offline'), props); |
| 1990 this.displayGDataStyleInItem_(listItem, entry, props); |
| 1991 } |
2105 } | 1992 } |
2106 }; | 1993 }; |
2107 | 1994 |
2108 /** | 1995 /** |
2109 * Restore the item which is being renamed while refreshing the file list. Do | 1996 * Restore the item which is being renamed while refreshing the file list. Do |
2110 * nothing if no item is being renamed or such an item disappeared. | 1997 * nothing if no item is being renamed or such an item disappeared. |
2111 * | 1998 * |
2112 * While refreshing file list it gets repopulated with new file entries. | 1999 * While refreshing file list it gets repopulated with new file entries. |
2113 * There is not a big difference wether DOM items stay the same or not. | 2000 * There is not a big difference wether DOM items stay the same or not. |
2114 * Except for the item that the user is renaming. | 2001 * Except for the item that the user is renaming. |
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2567 // For internal tasks we do not listen to the event to avoid | 2454 // For internal tasks we do not listen to the event to avoid |
2568 // handling the same task instance from multiple tabs. | 2455 // handling the same task instance from multiple tabs. |
2569 // So, we manually execute the task. | 2456 // So, we manually execute the task. |
2570 this.onFileTaskExecute_(task_parts[1], urls); | 2457 this.onFileTaskExecute_(task_parts[1], urls); |
2571 } | 2458 } |
2572 }.bind(this)); | 2459 }.bind(this)); |
2573 }; | 2460 }; |
2574 | 2461 |
2575 FileManager.prototype.executeIfAvailable_ = function(urls, callback) { | 2462 FileManager.prototype.executeIfAvailable_ = function(urls, callback) { |
2576 if (this.isOnGDataOffline()) { | 2463 if (this.isOnGDataOffline()) { |
2577 chrome.fileBrowserPrivate.getGDataFileProperties(urls, function(props) { | 2464 this.metadataCache_.get(urls, 'gdata', function(props) { |
2578 for (var i = 0; i != props.length; i++) { | 2465 for (var i = 0; i != props.length; i++) { |
2579 if (!FileManager.isAvaliableOffline_(props[i])) { | 2466 if (!props[i].availableOffline) { |
2580 this.alert.showHtml( | 2467 this.alert.showHtml( |
2581 str('OFFLINE_HEADER'), | 2468 str('OFFLINE_HEADER'), |
2582 strf( | 2469 strf( |
2583 urls.length == 1 ? | 2470 urls.length == 1 ? |
2584 'OFFLINE_MESSAGE' : | 2471 'OFFLINE_MESSAGE' : |
2585 'OFFLINE_MESSAGE_PLURAL', | 2472 'OFFLINE_MESSAGE_PLURAL', |
2586 str('OFFLINE_COLUMN_LABEL'))); | 2473 str('OFFLINE_COLUMN_LABEL'))); |
2587 return; | 2474 return; |
2588 } | 2475 } |
2589 } | 2476 } |
2590 callback(urls); | 2477 callback(urls); |
2591 }.bind(this)); | 2478 }.bind(this)); |
2592 } else { | 2479 } else { |
2593 callback(urls); | 2480 callback(urls); |
2594 } | 2481 } |
2595 }; | 2482 }; |
2596 | 2483 |
2597 FileManager.isAvaliableOffline_ = function(gdata) { | |
2598 return gdata.isPresent && !gdata.isHosted; | |
2599 }; | |
2600 | |
2601 FileManager.prototype.isOffline = function() { | 2484 FileManager.prototype.isOffline = function() { |
2602 return !navigator.onLine; | 2485 return !navigator.onLine; |
2603 }; | 2486 }; |
2604 | 2487 |
2605 FileManager.prototype.onOnlineOffline_ = function() { | 2488 FileManager.prototype.onOnlineOffline_ = function() { |
2606 if (this.isOffline()) { | 2489 if (this.isOffline()) { |
2607 console.log('OFFLINE'); | 2490 console.log('OFFLINE'); |
2608 this.dialogContainer_.setAttribute('offline', true); | 2491 this.dialogContainer_.setAttribute('offline', true); |
2609 } else { | 2492 } else { |
2610 console.log('ONLINE'); | 2493 console.log('ONLINE'); |
(...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3161 this.directoryModel_.changeDirectory(event.srcElement.path); | 3044 this.directoryModel_.changeDirectory(event.srcElement.path); |
3162 }; | 3045 }; |
3163 | 3046 |
3164 FileManager.prototype.onCheckboxClick_ = function(event) { | 3047 FileManager.prototype.onCheckboxClick_ = function(event) { |
3165 var sm = this.directoryModel_.fileListSelection; | 3048 var sm = this.directoryModel_.fileListSelection; |
3166 var listItem = this.findListItemForEvent_(event); | 3049 var listItem = this.findListItemForEvent_(event); |
3167 sm.setIndexSelected(listItem.listIndex, event.target.checked); | 3050 sm.setIndexSelected(listItem.listIndex, event.target.checked); |
3168 }; | 3051 }; |
3169 | 3052 |
3170 FileManager.prototype.onPinClick_ = function(checkbox, entry, event) { | 3053 FileManager.prototype.onPinClick_ = function(checkbox, entry, event) { |
| 3054 // TODO(dgozman): revisit this method when gdata properties updated event |
| 3055 // will be available. |
3171 var self = this; | 3056 var self = this; |
3172 function callback(props) { | 3057 function callback(props) { |
3173 if (props.errorCode) { | 3058 if (props.errorCode) { |
3174 // TODO(serya): Do not show the message if unpin failed. | 3059 // TODO(serya): Do not show the message if unpin failed. |
3175 self.metadataCache_.get(entry, 'filesystem', function(filesystem) { | 3060 self.metadataCache_.get(entry, 'filesystem', function(filesystem) { |
3176 self.alert.showHtml(str('GDATA_OUT_OF_SPACE_HEADER'), | 3061 self.alert.showHtml(str('GDATA_OUT_OF_SPACE_HEADER'), |
3177 strf('GDATA_OUT_OF_SPACE_MESSAGE', | 3062 strf('GDATA_OUT_OF_SPACE_MESSAGE', |
3178 util.bytesToSi(filesystem.size))); | 3063 util.bytesToSi(filesystem.size))); |
3179 }); | 3064 }); |
3180 } | 3065 } |
3181 checkbox.checked = entry.gdata_.isPinned = props[0].isPinned; | 3066 // We don't have update events yet, so clear the cached data. |
| 3067 self.metadataCache_.clear(entry, 'gdata'); |
| 3068 checkbox.checked = props[0].isPinned; |
3182 } | 3069 } |
3183 var pin = checkbox.checked; | 3070 var pin = checkbox.checked; |
3184 cacheGDataProps(entry, function(entry) { | 3071 this.metadataCache_.get(entry, 'gdata', function(gdata) { |
3185 if (self.isOffline() && pin && !entry.gdata_.isPresent) { | 3072 if (self.isOffline() && pin && !gdata.present) { |
3186 // If we are offline, we cannot pin a file that is not already present. | 3073 // If we are offline, we cannot pin a file that is not already present. |
3187 checkbox.checked = false; // Revert the default action. | 3074 checkbox.checked = false; // Revert the default action. |
3188 self.alert.showHtml( | 3075 self.alert.showHtml( |
3189 str('OFFLINE_HEADER'), | 3076 str('OFFLINE_HEADER'), |
3190 strf('OFFLINE_MESSAGE', str('OFFLINE_COLUMN_LABEL'))); | 3077 strf('OFFLINE_MESSAGE', str('OFFLINE_COLUMN_LABEL'))); |
3191 return; | 3078 return; |
3192 } | 3079 } |
3193 chrome.fileBrowserPrivate.pinGDataFile([entry.toURL()], pin, callback); | 3080 chrome.fileBrowserPrivate.pinGDataFile([entry.toURL()], pin, callback); |
3194 }); | 3081 }); |
3195 event.preventDefault(); | 3082 event.preventDefault(); |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3421 // then for real). Do not update the location then. | 3308 // then for real). Do not update the location then. |
3422 if (event.newDirEntry.fullPath != event.previousDirEntry.fullPath) { | 3309 if (event.newDirEntry.fullPath != event.previousDirEntry.fullPath) { |
3423 this.updateLocation_(event.initial, event.newDirEntry.fullPath); | 3310 this.updateLocation_(event.initial, event.newDirEntry.fullPath); |
3424 } | 3311 } |
3425 | 3312 |
3426 this.checkFreeSpace_(this.getCurrentDirectory()); | 3313 this.checkFreeSpace_(this.getCurrentDirectory()); |
3427 | 3314 |
3428 // TODO(dgozman): title may be better than this. | 3315 // TODO(dgozman): title may be better than this. |
3429 this.document_.title = this.getCurrentDirectory().substr(1); | 3316 this.document_.title = this.getCurrentDirectory().substr(1); |
3430 | 3317 |
3431 if (this.metadataObserverId_) | 3318 if (this.filesystemObserverId_) |
3432 this.metadataCache_.removeObserver(this.metadataObserverId_); | 3319 this.metadataCache_.removeObserver(this.filesystemObserverId_); |
| 3320 if (this.gdataObserverId_) |
| 3321 this.metadataCache_.removeObserver(this.gdataObserverId_); |
3433 | 3322 |
3434 this.metadataObserverId_ = this.metadataCache_.addObserver( | 3323 this.filesystemObserverId_ = this.metadataCache_.addObserver( |
3435 this.directoryModel_.currentEntry, | 3324 this.directoryModel_.currentEntry, |
3436 MetadataCache.CHILDREN, | 3325 MetadataCache.CHILDREN, |
3437 'filesystem', | 3326 'filesystem', |
3438 this.updateFilesystemPropertiesInUI_.bind(this)); | 3327 this.updateMetadataInUI_.bind(this, 'filesystem')); |
| 3328 |
| 3329 if (this.isOnGData()) { |
| 3330 this.gdataObserverId_ = this.metadataCache_.addObserver( |
| 3331 this.directoryModel_.currentEntry, |
| 3332 MetadataCache.CHILDREN, |
| 3333 'gdata', |
| 3334 this.updateMetadataInUI_.bind(this, 'gdata')); |
| 3335 } |
3439 | 3336 |
3440 var self = this; | 3337 var self = this; |
3441 | 3338 |
3442 if (this.watchedDirectoryUrl_) { | 3339 if (this.watchedDirectoryUrl_) { |
3443 if (this.watchedDirectoryUrl_ != event.previousDirEntry.toURL()) { | 3340 if (this.watchedDirectoryUrl_ != event.previousDirEntry.toURL()) { |
3444 console.warn('event.previousDirEntry does not match File Manager state', | 3341 console.warn('event.previousDirEntry does not match File Manager state', |
3445 event, this.watchedDirectoryUrl_); | 3342 event, this.watchedDirectoryUrl_); |
3446 } | 3343 } |
3447 chrome.fileBrowserPrivate.removeFileWatch(this.watchedDirectoryUrl_, | 3344 chrome.fileBrowserPrivate.removeFileWatch(this.watchedDirectoryUrl_, |
3448 function(result) { | 3345 function(result) { |
(...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4051 | 3948 |
4052 var onResolved = function(resolvedUrls) { | 3949 var onResolved = function(resolvedUrls) { |
4053 if (cancelled) return; | 3950 if (cancelled) return; |
4054 cleanup(); | 3951 cleanup(); |
4055 selection.urls = resolvedUrls; | 3952 selection.urls = resolvedUrls; |
4056 // Call next method on a timeout, as it's unsafe to | 3953 // Call next method on a timeout, as it's unsafe to |
4057 // close a window from a callback. | 3954 // close a window from a callback. |
4058 setTimeout(this.callSelectFilesApiAndClose_.bind(this, selection), 0); | 3955 setTimeout(this.callSelectFilesApiAndClose_.bind(this, selection), 0); |
4059 }.bind(this); | 3956 }.bind(this); |
4060 | 3957 |
4061 var onGotProperties = function(properties) { | 3958 var onProperties = function(properties) { |
4062 for (var i = 0; i < properties.length; i++) { | 3959 for (var i = 0; i < properties.length; i++) { |
4063 if (properties[i].isPresent) { | 3960 if (properties[i].present) { |
4064 // For files already in GCache, we don't get any transfer updates. | 3961 // For files already in GCache, we don't get any transfer updates. |
4065 filesTotal--; | 3962 filesTotal--; |
4066 } | 3963 } |
4067 } | 3964 } |
4068 this.resolveSelectResults_(selection.urls, onResolved); | 3965 this.resolveSelectResults_(selection.urls, onResolved); |
4069 }.bind(this); | 3966 }.bind(this); |
4070 | 3967 |
4071 setup(); | 3968 setup(); |
4072 chrome.fileBrowserPrivate.getGDataFileProperties( | 3969 this.metadataCache_.get(selection.urls, 'gdata', onProperties); |
4073 selection.urls, onGotProperties); | |
4074 }; | 3970 }; |
4075 | 3971 |
4076 /** | 3972 /** |
4077 * Handle a click of the ok button. | 3973 * Handle a click of the ok button. |
4078 * | 3974 * |
4079 * The ok button has different UI labels depending on the type of dialog, but | 3975 * The ok button has different UI labels depending on the type of dialog, but |
4080 * in code it's always referred to as 'ok'. | 3976 * in code it's always referred to as 'ok'. |
4081 * | 3977 * |
4082 * @param {Event} event The click event. | 3978 * @param {Event} event The click event. |
4083 */ | 3979 */ |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4323 | 4219 |
4324 handleSplitterDragEnd: function(e) { | 4220 handleSplitterDragEnd: function(e) { |
4325 Splitter.prototype.handleSplitterDragEnd.apply(this, arguments); | 4221 Splitter.prototype.handleSplitterDragEnd.apply(this, arguments); |
4326 this.ownerDocument.documentElement.classList.remove('col-resize'); | 4222 this.ownerDocument.documentElement.classList.remove('col-resize'); |
4327 } | 4223 } |
4328 }; | 4224 }; |
4329 | 4225 |
4330 customSplitter.decorate(splitterElement); | 4226 customSplitter.decorate(splitterElement); |
4331 }; | 4227 }; |
4332 })(); | 4228 })(); |
OLD | NEW |