1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file.
4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chromeos/file_system_provider/operations/read_file.h"
6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <limits>
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <string>
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/common/extensions/api/file_system_provider.h"
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/common/extensions/api/file_system_provider_internal.h"
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace chromeos {
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace file_system_provider {
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace operations {
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace {
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Convert |value| into |output|. If parsing fails, then returns a negative
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// value. Otherwise returns number of bytes written to the buffer.
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int CopyRequestValueToBuffer(scoped_ptr<RequestValue> value,
2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                             scoped_refptr<net::IOBuffer> buffer,
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                             int buffer_offset,
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                             int buffer_length) {
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  using extensions::api::file_system_provider_internal::
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ReadFileRequestedSuccess::Params;
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const Params* params = value->read_file_success_params();
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!params)
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return -1;
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const size_t chunk_size = params->data.length();
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Check for overflows.
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (chunk_size > static_cast<size_t>(buffer_length) - buffer_offset)
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return -1;
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  memcpy(buffer->data() + buffer_offset, params->data.c_str(), chunk_size);
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return chunk_size;
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ReadFile::ReadFile(
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    extensions::EventRouter* event_router,
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const ProvidedFileSystemInfo& file_system_info,
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int file_handle,
4846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_refptr<net::IOBuffer> buffer,
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int64 offset,
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int length,
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const ProvidedFileSystemInterface::ReadChunkReceivedCallback& callback)
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : Operation(event_router, file_system_info),
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      file_handle_(file_handle),
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      buffer_(buffer),
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      offset_(offset),
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      length_(length),
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      current_offset_(0),
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      callback_(callback) {
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ReadFile::~ReadFile() {
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool ReadFile::Execute(int request_id) {
65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> values(new base::DictionaryValue);
66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  values->SetInteger("openRequestId", file_handle_);
67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  values->SetDouble("offset", offset_);
68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  values->SetInteger("length", length_);
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return SendEvent(
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      request_id,
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      extensions::api::file_system_provider::OnReadFileRequested::kEventName,
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      values.Pass());
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ReadFile::OnSuccess(int /* request_id */,
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                         scoped_ptr<RequestValue> result,
7746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                         bool has_more) {
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const int copy_result = CopyRequestValueToBuffer(
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      result.Pass(), buffer_, current_offset_, length_);
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_LE(0, copy_result);
8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(!has_more || copy_result > 0);
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (copy_result > 0)
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    current_offset_ += copy_result;
8446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  callback_.Run(copy_result, has_more, base::File::FILE_OK);
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ReadFile::OnError(int /* request_id */, base::File::Error error) {
8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  callback_.Run(0 /* chunk_length */, false /* has_more */, error);
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace operations
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace file_system_provider
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace chromeos
94