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