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