summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/chromeos/extensions/file_manager_util.cc53
-rw-r--r--chrome/browser/chromeos/gdata/gdata_file_system.cc18
-rw-r--r--chrome/browser/chromeos/gdata/gdata_file_system.h11
-rw-r--r--chrome/browser/chromeos/gdata/gdata_file_system_unittest.cc24
-rw-r--r--chrome/browser/chromeos/gdata/gdata_util.cc10
-rw-r--r--chrome/browser/chromeos/gdata/gdata_util.h7
-rw-r--r--chrome/browser/chromeos/gdata/mock_gdata_file_system.h2
-rw-r--r--chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc3
-rw-r--r--chrome/browser/ui/webui/chromeos/gdata_source.cc290
-rw-r--r--chrome/browser/ui/webui/chromeos/gdata_source.h73
-rw-r--r--chrome/browser/ui/webui/chromeos/gdata_ui.cc57
-rw-r--r--chrome/browser/ui/webui/chromeos/gdata_ui.h19
-rw-r--r--chrome/chrome_browser.gypi4
-rw-r--r--chrome/common/url_constants.cc1
-rw-r--r--chrome/common/url_constants.h1
15 files changed, 555 insertions, 18 deletions
diff --git a/chrome/browser/chromeos/extensions/file_manager_util.cc b/chrome/browser/chromeos/extensions/file_manager_util.cc
index 0b7cb19..d8837b38 100644
--- a/chrome/browser/chromeos/extensions/file_manager_util.cc
+++ b/chrome/browser/chromeos/extensions/file_manager_util.cc
@@ -13,6 +13,7 @@
#include "base/values.h"
#include "chrome/browser/chromeos/extensions/file_handler_util.h"
#include "chrome/browser/chromeos/gdata/gdata_operation_registry.h"
+#include "chrome/browser/chromeos/gdata/gdata_system_service.h"
#include "chrome/browser/chromeos/gdata/gdata_util.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_install_ui.h"
@@ -79,7 +80,8 @@ const char* kBrowserSupportedExtensions[] = {
#if defined(GOOGLE_CHROME_BUILD)
".pdf",
#endif
- ".bmp", ".jpg", ".jpeg", ".png", ".webp", ".gif", ".txt", ".html", ".htm"
+ ".bmp", ".jpg", ".jpeg", ".png", ".webp", ".gif", ".txt", ".html", ".htm",
+ ".mhtml", ".mht"
};
// List of file extension that can be handled with the media player.
const char* kAVExtensions[] = {
@@ -193,6 +195,29 @@ DictionaryValue* ProgessStatusToDictionaryValue(
return result.release();
}
+class GetFilePropertiesDelegate : public gdata::FindFileDelegate {
+ public:
+ explicit GetFilePropertiesDelegate() {}
+ virtual ~GetFilePropertiesDelegate() {}
+
+ const std::string& resource_id() const { return resource_id_; }
+ const std::string& file_name() const { return file_name_; }
+
+ private:
+ // GDataFileSystem::FindFileDelegate overrides.
+ virtual void OnDone(base::PlatformFileError error,
+ const FilePath& directory_path,
+ gdata::GDataFileBase* file) OVERRIDE {
+ if (error == base::PLATFORM_FILE_OK && file && file->AsGDataFile()) {
+ resource_id_ = file->AsGDataFile()->resource_id();
+ file_name_ = file->AsGDataFile()->file_name();
+ }
+ }
+
+ std::string resource_id_;
+ std::string file_name_;
+};
+
} // namespace
GURL GetFileBrowserExtensionUrl() {
@@ -460,7 +485,31 @@ bool TryViewingFile(const FilePath& full_path) {
// in a tab.
if (IsSupportedBrowserExtension(file_extension.data()) ||
ShouldBeOpenedWithPdfPlugin(file_extension.data())) {
- browser->AddSelectedTabWithURL(net::FilePathToFileURL(full_path),
+ GURL page_url = net::FilePathToFileURL(full_path);
+#if defined(OS_CHROMEOS)
+ // Override gdata resource to point to internal handler instead of file:
+ // URL.
+ // There is nothing we can do if the browser is not present.
+ if (gdata::util::GetSpecialRemoteRootPath().IsParent(full_path)) {
+ Browser* browser = BrowserList::GetLastActive();
+ if (!browser)
+ return false;
+
+ gdata::GDataSystemService* system_service =
+ gdata::GDataSystemServiceFactory::GetForProfile(browser->profile());
+ if (!system_service)
+ return false;
+
+ GetFilePropertiesDelegate delegate;
+ system_service->file_system()->FindFileByPathSync(
+ gdata::util::ExtractGDataPath(full_path), &delegate);
+ if (delegate.resource_id().empty())
+ return false;
+ page_url = gdata::util::GetFileResourceUrl(delegate.resource_id(),
+ delegate.file_name());
+ }
+#endif
+ browser->AddSelectedTabWithURL(page_url,
content::PAGE_TRANSITION_LINK);
return true;
}
diff --git a/chrome/browser/chromeos/gdata/gdata_file_system.cc b/chrome/browser/chromeos/gdata/gdata_file_system.cc
index 640e4da..c2649b5 100644
--- a/chrome/browser/chromeos/gdata/gdata_file_system.cc
+++ b/chrome/browser/chromeos/gdata/gdata_file_system.cc
@@ -548,6 +548,24 @@ void GDataFileSystem::FindFileByPathSync(
UnsafeFindFileByPath(search_file_path, delegate);
}
+void GDataFileSystem::FindFileByResourceIdSync(
+ const std::string& resource_id,
+ FindFileDelegate* delegate) {
+ base::AutoLock lock(lock_); // To access the cache map.
+
+ GDataFile* file = NULL;
+ GDataFileBase* file_base = root_->GetFileByResourceId(resource_id);
+ if (file_base)
+ file = file_base->AsGDataFile();
+
+ if (file) {
+ delegate->OnDone(base::PLATFORM_FILE_OK, file->parent()->GetFilePath(),
+ file);
+ } else {
+ delegate->OnDone(base::PLATFORM_FILE_ERROR_NOT_FOUND, FilePath(), NULL);
+ }
+}
+
void GDataFileSystem::FindFileByPathAsync(
const FilePath& search_file_path,
const FindFileCallback& callback) {
diff --git a/chrome/browser/chromeos/gdata/gdata_file_system.h b/chrome/browser/chromeos/gdata/gdata_file_system.h
index 4dcb1a9..d2b1d74 100644
--- a/chrome/browser/chromeos/gdata/gdata_file_system.h
+++ b/chrome/browser/chromeos/gdata/gdata_file_system.h
@@ -209,6 +209,15 @@ class GDataFileSystemInterface {
virtual void FindFileByPathSync(const FilePath& file_path,
FindFileDelegate* delegate) = 0;
+ // Finds file info by using |resource_id|. This call does not initiate
+ // content refreshing and will invoke one of |delegate| methods directly as
+ // it executes.
+ //
+ // Can be called from UI/IO thread. |delegate| is run on the calling thread
+ // synchronously.
+ virtual void FindFileByResourceIdSync(const std::string& resource_id,
+ FindFileDelegate* delegate) = 0;
+
// Initiates transfer of |local_file_path| to |remote_dest_file_path|.
// |local_file_path| must be a file from the local file system,
// |remote_dest_file_path| is the virtual destination path within gdata file
@@ -405,6 +414,8 @@ class GDataFileSystem : public GDataFileSystemInterface {
const FindFileCallback& callback) OVERRIDE;
virtual void FindFileByPathSync(const FilePath& file_path,
FindFileDelegate* delegate) OVERRIDE;
+ virtual void FindFileByResourceIdSync(const std::string& resource_id,
+ FindFileDelegate* delegate) OVERRIDE;
virtual void TransferFile(const FilePath& local_file_path,
const FilePath& remote_dest_file_path,
const FileOperationCallback& callback) OVERRIDE;
diff --git a/chrome/browser/chromeos/gdata/gdata_file_system_unittest.cc b/chrome/browser/chromeos/gdata/gdata_file_system_unittest.cc
index 8c50c8f..f51edac 100644
--- a/chrome/browser/chromeos/gdata/gdata_file_system_unittest.cc
+++ b/chrome/browser/chromeos/gdata/gdata_file_system_unittest.cc
@@ -214,22 +214,17 @@ class GDataFileSystemTest : public testing::Test {
return search_delegate.file();
}
- GDataFileBase* FindFileElementByResourceId(const std::string& resource_id) {
- ReadOnlyFindFileDelegate search_delegate;
- file_system_->FindFileByPathSync(FilePath(FILE_PATH_LITERAL("gdata")),
- &search_delegate);
- return search_delegate.file()->AsGDataRootDirectory()->GetFileByResourceId(
- resource_id);
- }
-
void FindAndTestFilePath(const FilePath& file_path) {
GDataFileBase* file = FindFile(file_path);
ASSERT_TRUE(file) << "File can't be found " << file_path.value();
EXPECT_EQ(file->GetFilePath(), file_path);
}
- GDataFileBase* FindFileByResourceId(const std::string& resource) {
- return file_system_->root_->GetFileByResourceId(resource);
+ GDataFileBase* FindFileByResourceId(const std::string& resource_id) {
+ ReadOnlyFindFileDelegate search_delegate;
+ file_system_->FindFileByResourceIdSync(resource_id,
+ &search_delegate);
+ return search_delegate.file();
}
FilePath GetCacheFilePath(
@@ -991,12 +986,9 @@ TEST_F(GDataFileSystemTest, CachedFeedLoading) {
"gdata/Directory 1/Sub Directory Folder/Feed 2 Directory")));
// Make sure orphaned files didn't make into the file system.
- ASSERT_FALSE(FindFileElementByResourceId(
- "file:orphan_file_resource_id"));
- ASSERT_FALSE(FindFileElementByResourceId(
- "folder:orphan_feed_folder_resouce_id"));
- ASSERT_FALSE(FindFileElementByResourceId(
- "file:orphan_subfolder_file_resource_id"));
+ ASSERT_FALSE(FindFileByResourceId("file:orphan_file_resource_id"));
+ ASSERT_FALSE(FindFileByResourceId("folder:orphan_feed_folder_resouce_id"));
+ ASSERT_FALSE(FindFileByResourceId("file:orphan_subfolder_file_resource_id"));
}
TEST_F(GDataFileSystemTest, CopyNotExistingFile) {
diff --git a/chrome/browser/chromeos/gdata/gdata_util.cc b/chrome/browser/chromeos/gdata/gdata_util.cc
index 82027ef..ea3942d 100644
--- a/chrome/browser/chromeos/gdata/gdata_util.cc
+++ b/chrome/browser/chromeos/gdata/gdata_util.cc
@@ -11,10 +11,12 @@
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
+#include "base/stringprintf.h"
#include "chrome/common/libxml_utils.h"
#include "chrome/browser/chromeos/gdata/gdata_file_system.h"
#include "chrome/browser/chromeos/gdata/gdata_system_service.h"
#include "content/public/browser/child_process_security_policy.h"
+#include "net/base/escape.h"
namespace gdata {
namespace util {
@@ -54,6 +56,14 @@ const FilePath& GetSpecialRemoteRootPath() {
return gdata_mount_path;
}
+GURL GetFileResourceUrl(const std::string& resource_id,
+ const std::string& file_name) {
+ return GURL(base::StringPrintf(
+ "chrome://gdata/%s/%s",
+ net::EscapePath(resource_id).c_str(),
+ net::EscapePath(file_name).c_str()));
+}
+
bool IsUnderGDataMountPoint(const FilePath& path) {
return GetGDataMountPointPath() == path ||
GetGDataMountPointPath().IsParent(path);
diff --git a/chrome/browser/chromeos/gdata/gdata_util.h b/chrome/browser/chromeos/gdata/gdata_util.h
index 6f1ec38..38a5c27 100644
--- a/chrome/browser/chromeos/gdata/gdata_util.h
+++ b/chrome/browser/chromeos/gdata/gdata_util.h
@@ -8,6 +8,8 @@
#include <string>
+#include "googleurl/src/gurl.h"
+
class FilePath;
class Profile;
@@ -23,6 +25,11 @@ const std::string& GetGDataMountPointPathAsString();
// Returns the 'local' root of remote file system as "/special".
const FilePath& GetSpecialRemoteRootPath();
+// Returns the gdata file resource url formatted as
+// chrome://gdata/<resource_id>/<file_name>.
+GURL GetFileResourceUrl(const std::string& resource_id,
+ const std::string& file_name);
+
// Returns true if the given path is under the GData mount point.
bool IsUnderGDataMountPoint(const FilePath& path);
diff --git a/chrome/browser/chromeos/gdata/mock_gdata_file_system.h b/chrome/browser/chromeos/gdata/mock_gdata_file_system.h
index 4ce1311..69e61be 100644
--- a/chrome/browser/chromeos/gdata/mock_gdata_file_system.h
+++ b/chrome/browser/chromeos/gdata/mock_gdata_file_system.h
@@ -27,6 +27,8 @@ class MockGDataFileSystem : public GDataFileSystemInterface {
const FindFileCallback& callback));
MOCK_METHOD2(FindFileByPathSync, void(const FilePath& file_path,
FindFileDelegate* delegate));
+ MOCK_METHOD2(FindFileByResourceIdSync, void(const std::string& resource_id,
+ FindFileDelegate* delegate));
MOCK_METHOD3(TransferFile, void(const FilePath& local_file_path,
const FilePath& remote_dest_file_path,
const FileOperationCallback& callback));
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
index f960d37..2a1b842 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -60,6 +60,7 @@
#if defined(OS_CHROMEOS)
#include "chrome/browser/ui/webui/chromeos/active_downloads_ui.h"
#include "chrome/browser/ui/webui/chromeos/choose_mobile_network_ui.h"
+#include "chrome/browser/ui/webui/chromeos/gdata_ui.h"
#include "chrome/browser/ui/webui/chromeos/imageburner/imageburner_ui.h"
#include "chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.h"
#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
@@ -255,6 +256,8 @@ WebUIFactoryFunction GetWebUIFactoryFunction(content::WebUI* web_ui,
return &NewWebUI<ActiveDownloadsUI>;
if (url.host() == chrome::kChromeUIChooseMobileNetworkHost)
return &NewWebUI<chromeos::ChooseMobileNetworkUI>;
+ if (url.host() == chrome::kChromeUIGDataHost)
+ return &NewWebUI<GDataUI>;
if (url.host() == chrome::kChromeUIImageBurnerHost)
return &NewWebUI<ImageBurnUI>;
if (url.host() == chrome::kChromeUIKeyboardOverlayHost)
diff --git a/chrome/browser/ui/webui/chromeos/gdata_source.cc b/chrome/browser/ui/webui/chromeos/gdata_source.cc
new file mode 100644
index 0000000..363f93e
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/gdata_source.cc
@@ -0,0 +1,290 @@
+// 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/ui/webui/chromeos/gdata_source.h"
+
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/file_util.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/chromeos/gdata/gdata_file_system.h"
+#include "chrome/browser/chromeos/gdata/gdata_system_service.h"
+#include "chrome/browser/history/top_sites.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/url_constants.h"
+#include "content/public/browser/browser_thread.h"
+#include "net/base/escape.h"
+#include "net/base/net_errors.h"
+
+using content::BrowserThread;
+
+namespace {
+
+const int kBufferSize = 8*1024;
+const char kMimeTypeOctetStream[] = "application/octet-stream";
+const net::UnescapeRule::Type kUrlPathUnescapeMask =
+ net::UnescapeRule::SPACES |
+ net::UnescapeRule::URL_SPECIAL_CHARS |
+ net::UnescapeRule::CONTROL_CHARS;
+
+// Helper function that reads file size.
+void GetFileSizeOnIOThreadPool(const FilePath& file_path,
+ int64* file_size) {
+ if (!file_util::GetFileSize(file_path, file_size))
+ *file_size = 0;
+}
+
+bool ParseGDataUrlPath(const std::string& path,
+ std::string* resource_id,
+ std::string* file_name) {
+ std::vector<std::string> components;
+ FilePath url_path= FilePath::FromUTF8Unsafe(path);
+ url_path.GetComponents(&components);
+ if (components.size() != 2) {
+ LOG(WARNING) << "Invalid path: " << url_path.value();
+ return false;
+ }
+
+ *resource_id = net::UnescapeURLComponent(components[0], kUrlPathUnescapeMask);
+ *file_name = net::UnescapeURLComponent(components[1], kUrlPathUnescapeMask);
+ return true;
+}
+
+}
+
+namespace gdata {
+
+struct FileReadContext : public base::RefCountedThreadSafe<FileReadContext> {
+ public:
+ FileReadContext(int request_id, const FilePath& file_path, int64 file_size)
+ : request_id(request_id),
+ file_path(file_path),
+ file_size(file_size),
+ total_read(0),
+ stream(new net::FileStream(NULL)),
+ buffer(new net::IOBufferWithSize(kBufferSize)),
+ raw_data(new std::vector<unsigned char>()) {
+ raw_data->resize(static_cast<size_t>(file_size));
+ }
+ ~FileReadContext() {}
+
+ int request_id;
+ FilePath file_path;
+ int64 file_size;
+ int total_read;
+ scoped_ptr<net::FileStream> stream;
+ scoped_refptr<net::IOBufferWithSize> buffer;
+ scoped_ptr< std::vector<unsigned char> > raw_data;
+};
+
+class GetFileMimeTypeDelegate : public gdata::FindFileDelegate {
+ public:
+ explicit GetFileMimeTypeDelegate() {}
+ virtual ~GetFileMimeTypeDelegate() {}
+
+ const std::string mime_type() const { return mime_type_; }
+ const std::string file_name() const { return file_name_; }
+ private:
+ // GDataFileSystem::FindFileDelegate overrides.
+ virtual void OnDone(base::PlatformFileError error,
+ const FilePath& directory_path,
+ gdata::GDataFileBase* file) OVERRIDE {
+ if (error == base::PLATFORM_FILE_OK && file && file->AsGDataFile()) {
+ mime_type_ = file->AsGDataFile()->content_mime_type();
+ file_name_ = file->AsGDataFile()->file_name();
+ }
+ }
+
+ std::string mime_type_;
+ std::string file_name_;
+};
+
+GDataSource::GDataSource(Profile* profile)
+ : DataSource(chrome::kChromeUIGDataHost, MessageLoop::current()),
+ profile_(profile),
+ system_service_(GDataSystemServiceFactory::GetForProfile(profile)) {
+}
+
+GDataSource::~GDataSource() {
+}
+
+void GDataSource::StartDataRequest(const std::string& path,
+ bool is_incognito,
+ int request_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (is_incognito || !system_service_) {
+ SendResponse(request_id, reinterpret_cast<RefCountedMemory*>(NULL));
+ return;
+ }
+
+ std::string resource_id;
+ std::string file_name;
+ if (!ParseGDataUrlPath(path, &resource_id, &file_name)) {
+ SendResponse(request_id, reinterpret_cast<RefCountedMemory*>(NULL));
+ return;
+ }
+
+ // Check if file metadata is matching our expectations first.
+ GetFileMimeTypeDelegate delegate;
+ system_service_->file_system()->FindFileByResourceIdSync(resource_id,
+ &delegate);
+ if (delegate.file_name() != file_name) {
+ SendResponse(request_id, reinterpret_cast<RefCountedMemory*>(NULL));
+ return;
+ }
+
+ system_service_->file_system()->GetFileForResourceId(
+ resource_id,
+ base::Bind(&GDataSource::OnGetFileForResourceId,
+ this,
+ request_id));
+}
+
+std::string GDataSource::GetMimeType(const std::string& path) const {
+ if (!system_service_)
+ return kMimeTypeOctetStream;
+
+ std::string resource_id;
+ std::string unused_file_name;
+ if (!ParseGDataUrlPath(path, &resource_id, &unused_file_name))
+ return kMimeTypeOctetStream;
+
+ GetFileMimeTypeDelegate delegate;
+ system_service_->file_system()->FindFileByResourceIdSync(resource_id,
+ &delegate);
+ if (delegate.mime_type().empty())
+ return kMimeTypeOctetStream;
+
+ return delegate.mime_type();
+}
+
+
+void GDataSource::OnGetFileForResourceId(
+ int request_id,
+ base::PlatformFileError error,
+ const FilePath& file_path,
+ const std::string& mime_type,
+ GDataFileType file_type) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (error != base::PLATFORM_FILE_OK || file_type != REGULAR_FILE) {
+ SendResponse(request_id, reinterpret_cast<RefCountedMemory*>(NULL));
+ return;
+ }
+
+ int64* file_size = new int64(0);
+ BrowserThread::GetBlockingPool()->PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(&GetFileSizeOnIOThreadPool,
+ file_path,
+ base::Unretained(file_size)),
+ base::Bind(&GDataSource::StartFileRead,
+ this,
+ request_id,
+ file_path,
+ base::Owned(file_size)));
+}
+
+void GDataSource::StartFileRead(int request_id,
+ const FilePath& file_path,
+ int64 *file_size) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ scoped_refptr<FileReadContext> context(
+ new FileReadContext(request_id, file_path, *file_size));
+ int rv = context->stream->Open(
+ file_path,
+ base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ |
+ base::PLATFORM_FILE_ASYNC,
+ base::Bind(&GDataSource::OnFileOpen,
+ this,
+ context));
+
+ if (rv != net::ERR_IO_PENDING) {
+ LOG(WARNING) << "Failed to open " << file_path.value();
+ SendResponse(request_id,
+ reinterpret_cast<RefCountedMemory*>(NULL));
+ return;
+ }
+}
+
+
+void GDataSource::OnFileOpen(scoped_refptr<FileReadContext> context,
+ int open_result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (open_result != net::OK) {
+ LOG(WARNING) << "Failed to open " << context->file_path.value();
+ SendResponse(context->request_id,
+ reinterpret_cast<RefCountedMemory*>(NULL));
+ return;
+ }
+
+ int rv = context->stream->Read(context->buffer.get(), context->buffer->size(),
+ base::Bind(&GDataSource::OnFileRead,
+ this,
+ context));
+
+ if (rv != net::ERR_IO_PENDING) {
+ LOG(WARNING) << "Failed reading " << context->file_path.value();
+ SendResponse(context->request_id,
+ reinterpret_cast<RefCountedMemory*>(NULL));
+ return;
+ }
+}
+
+void GDataSource::OnFileRead(scoped_refptr<FileReadContext> context,
+ int bytes_read) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (bytes_read < 0) {
+ LOG(WARNING) << "Failed reading " << context->file_path.value();
+ SendResponse(context->request_id,
+ reinterpret_cast<RefCountedMemory*>(NULL));
+ return;
+ } else if (bytes_read == 0) {
+ scoped_refptr<RefCountedBytes> response_bytes =
+ RefCountedBytes::TakeVector(context->raw_data.release());
+ SendResponse(context->request_id, response_bytes.get());
+ return;
+ }
+
+ // Copy read chunk in the buffer.
+ if (context->raw_data->size() <
+ static_cast<size_t>(bytes_read + context->total_read)) {
+ LOG(WARNING) << "Reading more data than what we allocated for file "
+ << context->file_path.value();
+ SendResponse(context->request_id,
+ reinterpret_cast<RefCountedMemory*>(NULL));
+ return;
+ }
+
+ char* data = reinterpret_cast<char*>(&(context->raw_data->front()));
+ memcpy(data + context->total_read,
+ context->buffer->data(),
+ bytes_read);
+ context->total_read += bytes_read;
+
+ int read_value = context->stream->Read(context->buffer.get(),
+ context->buffer->size(),
+ base::Bind(&GDataSource::OnFileRead,
+ this,
+ context));
+
+ if (read_value != net::ERR_IO_PENDING) {
+ LOG(WARNING) << "Failed to read file for request "
+ << context->file_path.value();
+ SendResponse(context->request_id,
+ reinterpret_cast<RefCountedMemory*>(NULL));
+ return;
+ }
+}
+
+} // namespace gdata
diff --git a/chrome/browser/ui/webui/chromeos/gdata_source.h b/chrome/browser/ui/webui/chromeos/gdata_source.h
new file mode 100644
index 0000000..bc9d576
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/gdata_source.h
@@ -0,0 +1,73 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_GDATA_SOURCE_H_
+#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_GDATA_SOURCE_H_
+#pragma once
+
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "chrome/browser/chromeos/gdata/gdata_files.h"
+#include "chrome/browser/favicon/favicon_service.h"
+#include "chrome/browser/ui/webui/chrome_url_data_manager.h"
+#include "net/base/file_stream.h"
+#include "net/base/io_buffer.h"
+
+class Profile;
+
+namespace gdata {
+
+class GDataSystemService;
+struct FileReadContext;
+
+// GDataSource is the gateway between network-level chrome:
+// requests for gdata resources and GDataFileSyte. It will expose content
+// URLs formatted as chrome://gdata/<resource-id>/<file_name>.
+class GDataSource : public ChromeURLDataManager::DataSource {
+ public:
+ explicit GDataSource(Profile* profile);
+
+ // ChromeURLDataManager::DataSource overrides:
+ virtual void StartDataRequest(const std::string& path,
+ bool is_incognito,
+ int request_id) OVERRIDE;
+ virtual std::string GetMimeType(const std::string&) const OVERRIDE;
+
+ private:
+ // Helper callback for handling async responses from
+ // GDataFileSystem::GetFileForResourceId().
+ void OnGetFileForResourceId(int request_id,
+ base::PlatformFileError error,
+ const FilePath& file_path,
+ const std::string& mime_type,
+ GDataFileType file_type);
+
+ // Starts reading file content.
+ void StartFileRead(int request_id,
+ const FilePath& file_path,
+ int64 *file_size);
+
+ // Helper callback for handling async responses from FileStream::Open().
+ void OnFileOpen(scoped_refptr<FileReadContext> context,
+ int open_result);
+
+ // Helper callback for handling async responses from FileStream::Read().
+ void OnFileRead(scoped_refptr<FileReadContext> context,
+ int bytes_read);
+
+ virtual ~GDataSource();
+
+ Profile* profile_;
+ gdata::GDataSystemService* system_service_;
+
+ DISALLOW_COPY_AND_ASSIGN(GDataSource);
+};
+
+} // namespace gdata
+
+#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_GDATA_SOURCE_H_
diff --git a/chrome/browser/ui/webui/chromeos/gdata_ui.cc b/chrome/browser/ui/webui/chromeos/gdata_ui.cc
new file mode 100644
index 0000000..4ef2bae
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/gdata_ui.cc
@@ -0,0 +1,57 @@
+// 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/ui/webui/chromeos/gdata_ui.h"
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/chromeos/gdata_source.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/browser/web_ui_message_handler.h"
+
+using content::WebUIMessageHandler;
+
+// The handler for Javascript messages related to the "system" view.
+class GDataHandler : public WebUIMessageHandler,
+ public base::SupportsWeakPtr<GDataHandler> {
+ public:
+ GDataHandler();
+ virtual ~GDataHandler();
+
+ // WebUIMessageHandler implementation.
+ virtual void RegisterMessages() OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GDataHandler);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// GDataHandler
+//
+////////////////////////////////////////////////////////////////////////////////
+GDataHandler::GDataHandler() {
+}
+
+GDataHandler::~GDataHandler() {
+}
+
+void GDataHandler::RegisterMessages() {
+ // TODO(zelidrag): add message registration, callbacks... if any...
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// GDataUI
+//
+////////////////////////////////////////////////////////////////////////////////
+
+GDataUI::GDataUI(content::WebUI* web_ui) : WebUIController(web_ui) {
+ GDataHandler* handler = new GDataHandler();
+ web_ui->AddMessageHandler(handler);
+ Profile* profile = Profile::FromWebUI(web_ui);
+ // Set up the chrome://gdata/ source.
+ gdata::GDataSource* gdata_source = new gdata::GDataSource(profile);
+ profile->GetChromeURLDataManager()->AddDataSource(gdata_source);
+}
diff --git a/chrome/browser/ui/webui/chromeos/gdata_ui.h b/chrome/browser/ui/webui/chromeos/gdata_ui.h
new file mode 100644
index 0000000..6702de7
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/gdata_ui.h
@@ -0,0 +1,19 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_GDATA_UI_H_
+#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_GDATA_UI_H_
+#pragma once
+
+#include "content/public/browser/web_ui_controller.h"
+
+class GDataUI : public content::WebUIController {
+ public:
+ explicit GDataUI(content::WebUI* web_ui);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GDataUI);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_GDATA_UI_H_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 503e333..35784bf 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -3621,6 +3621,10 @@
'browser/ui/webui/chromeos/active_downloads_ui.h',
'browser/ui/webui/chromeos/choose_mobile_network_ui.cc',
'browser/ui/webui/chromeos/choose_mobile_network_ui.h',
+ 'browser/ui/webui/chromeos/gdata_ui.cc',
+ 'browser/ui/webui/chromeos/gdata_ui.h',
+ 'browser/ui/webui/chromeos/gdata_source.cc',
+ 'browser/ui/webui/chromeos/gdata_source.h',
'browser/ui/webui/chromeos/imageburner/imageburner_ui.cc',
'browser/ui/webui/chromeos/imageburner/imageburner_ui.h',
'browser/ui/webui/chromeos/keyboard_overlay_ui.cc',
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index 8fc0ea0..e77f86d 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -200,6 +200,7 @@ const char kChromeUIActiveDownloadsHost[] = "active-downloads";
const char kChromeUIChooseMobileNetworkHost[] = "choose-mobile-network";
const char kChromeUICryptohomeHost[] = "cryptohome";
const char kChromeUIDiscardsHost[] = "discards";
+const char kChromeUIGDataHost[] = "gdata";
const char kChromeUIIdleLogoutDialogHost[] = "idle-logout";
const char kChromeUIImageBurnerHost[] = "imageburner";
const char kChromeUIKeyboardOverlayHost[] = "keyboardoverlay";
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h
index ab31c79..34588f8 100644
--- a/chrome/common/url_constants.h
+++ b/chrome/common/url_constants.h
@@ -191,6 +191,7 @@ extern const char kChromeUIActiveDownloadsHost[];
extern const char kChromeUIChooseMobileNetworkHost[];
extern const char kChromeUICryptohomeHost[];
extern const char kChromeUIDiscardsHost[];
+extern const char kChromeUIGDataHost[];
extern const char kChromeUIIdleLogoutDialogHost[];
extern const char kChromeUIImageBurnerHost[];
extern const char kChromeUIKeyboardOverlayHost[];