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.
5 #include "chrome/browser/chromeos/drive/resource_entry_conversion.h"
10 #include "base/logging.h"
11 #include "base/platform_file.h"
12 #include "base/time/time.h"
13 #include "chrome/browser/chromeos/drive/drive.pb.h"
14 #include "chrome/browser/chromeos/drive/file_system_util.h"
15 #include "chrome/browser/drive/drive_api_util.h"
16 #include "google_apis/drive/gdata_wapi_parser.h"
22 const char kSharedWithMeLabel
[] = "shared-with-me";
23 const char kSharedLabel
[] = "shared";
25 // Checks if |entry| has a specified label.
26 bool HasLabel(const google_apis::ResourceEntry
& entry
,
27 const std::string
& label
) {
28 std::vector
<std::string
>::const_iterator it
=
29 std::find(entry
.labels().begin(), entry
.labels().end(), label
);
30 return it
!= entry
.labels().end();
35 bool ConvertToResourceEntry(const google_apis::ResourceEntry
& input
,
36 ResourceEntry
* out_entry
,
37 std::string
* out_parent_resource_id
) {
39 DCHECK(out_parent_resource_id
);
41 ResourceEntry converted
;
43 // For regular files, the 'filename' and 'title' attribute in the metadata
44 // may be different (e.g. due to rename). To be consistent with the web
45 // interface and other client to use the 'title' attribute, instead of
46 // 'filename', as the file name in the local snapshot.
47 converted
.set_title(input
.title());
48 converted
.set_base_name(util::NormalizeFileName(converted
.title()));
49 converted
.set_resource_id(input
.resource_id());
51 // Gets parent Resource ID. On drive.google.com, a file can have multiple
52 // parents or no parent, but we are forcing a tree-shaped structure (i.e. no
53 // multi-parent or zero-parent entries). Therefore the first found "parent" is
54 // used for the entry and if the entry has no parent, we assign a special ID
55 // which represents no-parent entries. Tracked in http://crbug.com/158904.
56 std::string parent_resource_id
;
57 const google_apis::Link
* parent_link
=
58 input
.GetLinkByType(google_apis::Link::LINK_PARENT
);
60 parent_resource_id
= util::ExtractResourceIdFromUrl(parent_link
->href());
62 converted
.set_deleted(input
.deleted());
63 converted
.set_shared_with_me(HasLabel(input
, kSharedWithMeLabel
));
64 converted
.set_shared(HasLabel(input
, kSharedLabel
));
66 PlatformFileInfoProto
* file_info
= converted
.mutable_file_info();
68 file_info
->set_last_modified(input
.updated_time().ToInternalValue());
69 // If the file has never been viewed (last_viewed_time().is_null() == true),
70 // then we will set the last_accessed field in the protocol buffer to 0.
71 file_info
->set_last_accessed(input
.last_viewed_time().ToInternalValue());
72 file_info
->set_creation_time(input
.published_time().ToInternalValue());
74 if (input
.is_file() || input
.is_hosted_document()) {
75 FileSpecificInfo
* file_specific_info
=
76 converted
.mutable_file_specific_info();
77 if (input
.is_file()) {
78 file_info
->set_size(input
.file_size());
79 file_specific_info
->set_md5(input
.file_md5());
81 // The resumable-edit-media link should only be present for regular
82 // files as hosted documents are not uploadable.
83 } else if (input
.is_hosted_document()) {
84 // Attach .g<something> extension to hosted documents so we can special
85 // case their handling in UI.
86 // TODO(satorux): Figure out better way how to pass input info like kind
87 // to UI through the File API stack.
88 const std::string document_extension
= input
.GetHostedDocumentExtension();
89 file_specific_info
->set_document_extension(document_extension
);
90 converted
.set_base_name(
91 util::NormalizeFileName(converted
.title() + document_extension
));
93 // We don't know the size of hosted docs and it does not matter since
94 // is has no effect on the quota.
95 file_info
->set_size(0);
97 file_info
->set_is_directory(false);
98 file_specific_info
->set_content_mime_type(input
.content_mime_type());
99 file_specific_info
->set_is_hosted_document(input
.is_hosted_document());
101 const google_apis::Link
* alternate_link
=
102 input
.GetLinkByType(google_apis::Link::LINK_ALTERNATE
);
104 file_specific_info
->set_alternate_url(alternate_link
->href().spec());
106 const int64 image_width
= input
.image_width();
107 if (image_width
!= -1)
108 file_specific_info
->set_image_width(image_width
);
110 const int64 image_height
= input
.image_height();
111 if (image_height
!= -1)
112 file_specific_info
->set_image_height(image_height
);
114 const int64 image_rotation
= input
.image_rotation();
115 if (image_rotation
!= -1)
116 file_specific_info
->set_image_rotation(image_rotation
);
117 } else if (input
.is_folder()) {
118 file_info
->set_is_directory(true);
120 // There are two cases to reach here.
121 // * The entry is something that doesn't map into files (i.e. sites).
122 // We don't handle these kind of entries hence return false.
123 // * The entry is un-shared to you by other owner. In that case, we
124 // get an entry with only deleted() and resource_id() fields are
125 // filled. Since we want to delete such entries locally as well,
126 // in that case we need to return true to proceed.
127 if (!input
.deleted())
131 out_entry
->Swap(&converted
);
132 swap(*out_parent_resource_id
, parent_resource_id
);
136 void ConvertResourceEntryToPlatformFileInfo(const ResourceEntry
& entry
,
137 base::PlatformFileInfo
* file_info
) {
138 file_info
->size
= entry
.file_info().size();
139 file_info
->is_directory
= entry
.file_info().is_directory();
140 file_info
->is_symbolic_link
= entry
.file_info().is_symbolic_link();
141 file_info
->last_modified
= base::Time::FromInternalValue(
142 entry
.file_info().last_modified());
143 file_info
->last_accessed
= base::Time::FromInternalValue(
144 entry
.file_info().last_accessed());
145 file_info
->creation_time
= base::Time::FromInternalValue(
146 entry
.file_info().creation_time());
149 void SetPlatformFileInfoToResourceEntry(const base::PlatformFileInfo
& file_info
,
150 ResourceEntry
* entry
) {
151 PlatformFileInfoProto
* entry_file_info
= entry
->mutable_file_info();
152 entry_file_info
->set_size(file_info
.size
);
153 entry_file_info
->set_is_directory(file_info
.is_directory
);
154 entry_file_info
->set_is_symbolic_link(file_info
.is_symbolic_link
);
155 entry_file_info
->set_last_modified(file_info
.last_modified
.ToInternalValue());
156 entry_file_info
->set_last_accessed(file_info
.last_accessed
.ToInternalValue());
157 entry_file_info
->set_creation_time(file_info
.creation_time
.ToInternalValue());