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
3// found in the LICENSE file.
4
5// Custom binding for the Media Gallery API.
6
7var binding = require('binding').Binding.create('mediaGalleries');
8var blobNatives = requireNative('blob_natives');
9var mediaGalleriesNatives = requireNative('mediaGalleries');
10
11var blobsAwaitingMetadata = {};
12var mediaGalleriesMetadata = {};
13
14function createFileSystemObjectsAndUpdateMetadata(response) {
15  var result = [];
16  mediaGalleriesMetadata = {};  // Clear any previous metadata.
17  if (response) {
18    for (var i = 0; i < response.length; i++) {
19      var filesystem = mediaGalleriesNatives.GetMediaFileSystemObject(
20          response[i].fsid);
21      $Array.push(result, filesystem);
22      var metadata = response[i];
23      delete metadata.fsid;
24      mediaGalleriesMetadata[filesystem.name] = metadata;
25    }
26  }
27  return result;
28}
29
30binding.registerCustomHook(function(bindingsAPI, extensionId) {
31  var apiFunctions = bindingsAPI.apiFunctions;
32
33  // getMediaFileSystems, addUserSelectedFolder, and addScanResults use a
34  // custom callback so that they can instantiate and return an array of file
35  // system objects.
36  apiFunctions.setCustomCallback('getMediaFileSystems',
37                                 function(name, request, response) {
38    var result = createFileSystemObjectsAndUpdateMetadata(response);
39    if (request.callback)
40      request.callback(result);
41    request.callback = null;
42  });
43
44  apiFunctions.setCustomCallback('addScanResults',
45                                 function(name, request, response) {
46    var result = createFileSystemObjectsAndUpdateMetadata(response);
47    if (request.callback)
48      request.callback(result);
49    request.callback = null;
50  });
51
52  apiFunctions.setCustomCallback('addUserSelectedFolder',
53                                 function(name, request, response) {
54    var fileSystems = [];
55    var selectedFileSystemName = "";
56    if (response && 'mediaFileSystems' in response &&
57        'selectedFileSystemIndex' in response) {
58      fileSystems = createFileSystemObjectsAndUpdateMetadata(
59          response['mediaFileSystems']);
60      var selectedFileSystemIndex = response['selectedFileSystemIndex'];
61      if (selectedFileSystemIndex >= 0) {
62        selectedFileSystemName = fileSystems[selectedFileSystemIndex].name;
63      }
64    }
65    if (request.callback)
66      request.callback(fileSystems, selectedFileSystemName);
67    request.callback = null;
68  });
69
70  apiFunctions.setCustomCallback('dropPermissionForMediaFileSystem',
71                                 function(name, request, response) {
72    var galleryId = response;
73
74    if (galleryId) {
75      for (var key in mediaGalleriesMetadata) {
76        if (mediaGalleriesMetadata[key].galleryId == galleryId) {
77          delete mediaGalleriesMetadata[key];
78          break;
79        }
80      }
81    }
82    if (request.callback)
83      request.callback();
84    request.callback = null;
85  });
86
87  apiFunctions.setHandleRequest('getMediaFileSystemMetadata',
88                                function(filesystem) {
89    if (filesystem && filesystem.name &&
90        filesystem.name in mediaGalleriesMetadata) {
91      return mediaGalleriesMetadata[filesystem.name];
92    }
93    return {
94      'name': '',
95      'galleryId': '',
96      'isRemovable': false,
97      'isMediaDevice': false,
98      'isAvailable': false,
99    };
100  });
101
102  apiFunctions.setUpdateArgumentsPostValidate('getMetadata',
103      function(mediaFile, options, callback) {
104    var blobUuid = blobNatives.GetBlobUuid(mediaFile)
105    // Store the blob in a global object to keep its refcount nonzero -- this
106    // prevents the object from being garbage collected before any metadata
107    // parsing gets to occur (see crbug.com/415792).
108    blobsAwaitingMetadata[blobUuid] = mediaFile;
109    return [blobUuid, options, callback];
110  });
111
112  apiFunctions.setCustomCallback('getMetadata',
113                                 function(name, request, response) {
114    if (response.attachedImagesBlobInfo) {
115      for (var i = 0; i < response.attachedImagesBlobInfo.length; i++) {
116        var blobInfo = response.attachedImagesBlobInfo[i];
117        var blob = blobNatives.TakeBrowserProcessBlob(
118            blobInfo.blobUUID, blobInfo.type, blobInfo.size);
119        response.metadata.attachedImages.push(blob);
120      }
121    }
122
123    if (request.callback)
124      request.callback(response.metadata);
125    request.callback = null;
126
127    // The UUID was in position 0 in the setUpdateArgumentsPostValidate
128    // function.
129    var uuid = request.args[0];
130    delete blobsAwaitingMetadata[uuid];
131  });
132});
133
134exports.binding = binding.generate();
135