1// Copyright 2014 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/file_system_provider/operations/get_metadata.h"
6
7#include <algorithm>
8#include <string>
9
10#include "chrome/common/extensions/api/file_system_provider.h"
11#include "chrome/common/extensions/api/file_system_provider_internal.h"
12
13namespace chromeos {
14namespace file_system_provider {
15namespace operations {
16namespace {
17
18// Convert |value| into |output|. If parsing fails, then returns false.
19bool ConvertRequestValueToFileInfo(scoped_ptr<RequestValue> value,
20                                   EntryMetadata* output) {
21  using extensions::api::file_system_provider::EntryMetadata;
22  using extensions::api::file_system_provider_internal::
23      GetMetadataRequestedSuccess::Params;
24
25  const Params* params = value->get_metadata_success_params();
26  if (!params)
27    return false;
28
29  output->name = params->metadata.name;
30  output->is_directory = params->metadata.is_directory;
31  output->size = static_cast<int64>(params->metadata.size);
32
33  std::string input_modification_time;
34  if (!params->metadata.modification_time.additional_properties.GetString(
35          "value", &input_modification_time)) {
36    return false;
37  }
38
39  // Allow to pass invalid modification time, since there is no way to verify
40  // it easily on any earlier stage.
41  base::Time::FromString(input_modification_time.c_str(),
42                         &output->modification_time);
43
44  if (params->metadata.mime_type.get())
45    output->mime_type = *params->metadata.mime_type.get();
46
47  if (params->metadata.thumbnail.get()) {
48    // Sanity check for the thumbnail format. Note, that another, more granural
49    // check is done in custom bindings. Note, this is an extra check only for
50    // the security reasons.
51    const std::string expected_prefix = "data:";
52    std::string thumbnail_prefix =
53        params->metadata.thumbnail.get()->substr(0, expected_prefix.size());
54    std::transform(thumbnail_prefix.begin(),
55                   thumbnail_prefix.end(),
56                   thumbnail_prefix.begin(),
57                   ::tolower);
58
59    if (expected_prefix != thumbnail_prefix)
60      return false;
61
62    output->thumbnail = *params->metadata.thumbnail.get();
63  }
64
65  return true;
66}
67
68}  // namespace
69
70GetMetadata::GetMetadata(
71    extensions::EventRouter* event_router,
72    const ProvidedFileSystemInfo& file_system_info,
73    const base::FilePath& entry_path,
74    ProvidedFileSystemInterface::MetadataFieldMask fields,
75    const ProvidedFileSystemInterface::GetMetadataCallback& callback)
76    : Operation(event_router, file_system_info),
77      entry_path_(entry_path),
78      fields_(fields),
79      callback_(callback) {
80}
81
82GetMetadata::~GetMetadata() {
83}
84
85bool GetMetadata::Execute(int request_id) {
86  using extensions::api::file_system_provider::GetMetadataRequestedOptions;
87
88  GetMetadataRequestedOptions options;
89  options.file_system_id = file_system_info_.file_system_id();
90  options.request_id = request_id;
91  options.entry_path = entry_path_.AsUTF8Unsafe();
92  options.thumbnail =
93      fields_ & ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL;
94
95  return SendEvent(
96      request_id,
97      extensions::api::file_system_provider::OnGetMetadataRequested::kEventName,
98      extensions::api::file_system_provider::OnGetMetadataRequested::Create(
99          options));
100}
101
102void GetMetadata::OnSuccess(int /* request_id */,
103                            scoped_ptr<RequestValue> result,
104                            bool has_more) {
105  scoped_ptr<EntryMetadata> metadata(new EntryMetadata);
106  const bool convert_result =
107      ConvertRequestValueToFileInfo(result.Pass(), metadata.get());
108
109  if (!convert_result) {
110    LOG(ERROR) << "Failed to parse a response for the get metadata operation.";
111    callback_.Run(make_scoped_ptr<EntryMetadata>(NULL),
112                  base::File::FILE_ERROR_IO);
113    return;
114  }
115
116  callback_.Run(metadata.Pass(), base::File::FILE_OK);
117}
118
119void GetMetadata::OnError(int /* request_id */,
120                          scoped_ptr<RequestValue> /* result */,
121                          base::File::Error error) {
122  callback_.Run(make_scoped_ptr<EntryMetadata>(NULL), error);
123}
124}  // namespace operations
125}  // namespace file_system_provider
126}  // namespace chromeos
127