blob: 182c20a8c7c533762377c3bbeafb7bdc68ffd7c0 [file] [log] [blame]
[email protected]698601e2009-10-21 22:43:371// Copyright (c) 2009 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/dom_ui/filebrowse_ui.h"
6
7#include "app/l10n_util.h"
8#include "app/resource_bundle.h"
9#include "base/logging.h"
10#include "base/message_loop.h"
[email protected]5c4c7402009-10-30 19:58:0611#include "base/singleton.h"
[email protected]698601e2009-10-21 22:43:3712#include "base/string_piece.h"
13#include "base/string_util.h"
14#include "base/thread.h"
15#include "base/time.h"
16#include "base/values.h"
17#include "chrome/browser/bookmarks/bookmark_model.h"
[email protected]fae20792009-10-28 20:31:5818#include "chrome/browser/chrome_thread.h"
[email protected]698601e2009-10-21 22:43:3719#include "chrome/browser/dom_ui/dom_ui_favicon_source.h"
20#include "chrome/browser/metrics/user_metrics.h"
21#include "chrome/browser/history/history_types.h"
22#include "chrome/browser/profile.h"
23#include "chrome/common/jstemplate_builder.h"
24#include "chrome/common/time_format.h"
25#include "chrome/common/url_constants.h"
26#include "net/base/escape.h"
27
28#include "grit/browser_resources.h"
29#include "grit/chromium_strings.h"
30#include "grit/generated_resources.h"
31#include "grit/locale_settings.h"
32
33// Maximum number of search results to return in a given search. We should
34// eventually remove this.
35static const int kMaxSearchResults = 100;
36static const std::wstring kPropertyPath = L"path";
37static const std::wstring kPropertyTitle = L"title";
38static const std::wstring kPropertyDirectory = L"isDirectory";
39
40
41class FileBrowseUIHTMLSource : public ChromeURLDataManager::DataSource {
42 public:
43 FileBrowseUIHTMLSource();
44
45 // Called when the network layer has requested a resource underneath
46 // the path we registered.
47 virtual void StartDataRequest(const std::string& path, int request_id);
48 virtual std::string GetMimeType(const std::string&) const {
49 return "text/html";
50 }
51
52 private:
[email protected]8de85a62009-11-06 08:32:1753 ~FileBrowseUIHTMLSource() {}
54
[email protected]698601e2009-10-21 22:43:3755 DISALLOW_COPY_AND_ASSIGN(FileBrowseUIHTMLSource);
56};
57
58// The handler for Javascript messages related to the "filebrowse" view.
59class FileBrowseHandler : public net::DirectoryLister::DirectoryListerDelegate,
60 public DOMMessageHandler {
61 public:
62 FileBrowseHandler();
63 virtual ~FileBrowseHandler();
64
65 // DirectoryLister::DirectoryListerDelegate methods:
66 virtual void OnListFile(const file_util::FileEnumerator::FindInfo& data);
67 virtual void OnListDone(int error);
68
69 // DOMMessageHandler implementation.
70 virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
71 virtual void RegisterMessages();
72
73 // Callback for the "getRoots" message.
74 void HandleGetRoots(const Value* value);
75
76 // Callback for the "getChildren" message.
77 void HandleGetChildren(const Value* value);
78
79 // Callback for the "getMetadata" message.
80 void HandleGetMetadata(const Value* value);
81
82 private:
83 scoped_ptr<ListValue> filelist_value_;
84 FilePath currentpath_;
85 scoped_refptr<net::DirectoryLister> lister_;
86
87 DISALLOW_COPY_AND_ASSIGN(FileBrowseHandler);
88};
89
90////////////////////////////////////////////////////////////////////////////////
91//
92// FileBrowseHTMLSource
93//
94////////////////////////////////////////////////////////////////////////////////
95
96FileBrowseUIHTMLSource::FileBrowseUIHTMLSource()
97 : DataSource(chrome::kChromeUIFileBrowseHost, MessageLoop::current()) {
98}
99
100void FileBrowseUIHTMLSource::StartDataRequest(const std::string& path,
101 int request_id) {
102 DictionaryValue localized_strings;
103 localized_strings.SetString(L"devices", "devices");
104
105 SetFontAndTextDirection(&localized_strings);
106
107 static const base::StringPiece filebrowse_html(
108 ResourceBundle::GetSharedInstance().GetRawDataResource(
109 IDR_FILEBROWSE_HTML));
110 const std::string full_html = jstemplate_builder::GetI18nTemplateHtml(
111 filebrowse_html, &localized_strings);
112
113 scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
114 html_bytes->data.resize(full_html.size());
115 std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin());
116
117 SendResponse(request_id, html_bytes);
118}
119
120////////////////////////////////////////////////////////////////////////////////
121//
122// FileBrowseHandler
123//
124////////////////////////////////////////////////////////////////////////////////
125FileBrowseHandler::FileBrowseHandler() {
126 lister_ = NULL;
127}
128
129FileBrowseHandler::~FileBrowseHandler() {
130 // TODO: Cancel any pending listings that are currently in flight.
131 if (lister_.get()) {
132 lister_->Cancel();
133 lister_->set_delegate(NULL);
134 }
135}
136
137DOMMessageHandler* FileBrowseHandler::Attach(DOMUI* dom_ui) {
138 // Create our favicon data source.
[email protected]fae20792009-10-28 20:31:58139 ChromeThread::PostTask(
140 ChromeThread::IO, FROM_HERE,
141 NewRunnableMethod(
[email protected]576a4ca2009-11-05 01:41:09142 Singleton<ChromeURLDataManager>::get(),
[email protected]fae20792009-10-28 20:31:58143 &ChromeURLDataManager::AddDataSource,
144 new DOMUIFavIconSource(dom_ui->GetProfile())));
[email protected]698601e2009-10-21 22:43:37145
146 return DOMMessageHandler::Attach(dom_ui);
147}
148
149void FileBrowseHandler::RegisterMessages() {
150 dom_ui_->RegisterMessageCallback("getRoots",
151 NewCallback(this, &FileBrowseHandler::HandleGetRoots));
152 dom_ui_->RegisterMessageCallback("getChildren",
153 NewCallback(this, &FileBrowseHandler::HandleGetChildren));
154 dom_ui_->RegisterMessageCallback("getMetadata",
155 NewCallback(this, &FileBrowseHandler::HandleGetMetadata));
156}
157
158void FileBrowseHandler::HandleGetRoots(const Value* value) {
159 ListValue results_value;
160 DictionaryValue info_value;
161
162 DictionaryValue* page_value = new DictionaryValue();
163 // TODO(dhg): add other entries, make this more general
164 page_value->SetString(kPropertyPath, "/home/chronos");
165 page_value->SetString(kPropertyTitle, "home");
166 page_value->SetBoolean(kPropertyDirectory, true);
167
168 results_value.Append(page_value);
169
170 info_value.SetString(L"call", "getRoots");
171
172 dom_ui_->CallJavascriptFunction(L"fileBrowseResult",
173 info_value, results_value);
174}
175
176void FileBrowseHandler::HandleGetChildren(const Value* value) {
177 std::string path;
178
179 if (value && value->GetType() == Value::TYPE_LIST) {
180 const ListValue* list_value = static_cast<const ListValue*>(value);
181 Value* list_member;
182
183 // Get search string.
184 if (list_value->Get(0, &list_member) &&
185 list_member->GetType() == Value::TYPE_STRING) {
186 const StringValue* string_value =
187 static_cast<const StringValue*>(list_member);
188 string_value->GetAsString(&path);
189 }
190
191 } else {
192 DLOG(ERROR) << "Wasn't able to get the List if requested files.";
193 return;
194 }
195 filelist_value_.reset(new ListValue());
196#if defined(OS_WIN)
197 currentpath_ = FilePath(ASCIIToWide(path));
198#else
199 currentpath_ = FilePath(path);
200#endif
201
202 if (lister_.get()) {
203 lister_->Cancel();
204 lister_->set_delegate(NULL);
205 lister_ = NULL;
206 }
207 lister_ = new net::DirectoryLister(currentpath_, this);
208 lister_->Start();
209}
210
211void FileBrowseHandler::OnListFile(
212 const file_util::FileEnumerator::FindInfo& data) {
213 DictionaryValue* file_value = new DictionaryValue();
214
215#if defined(OS_WIN)
216 int64 size = (static_cast<int64>(data.nFileSizeHigh) << 32) |
217 data.nFileSizeLow;
218 file_value->SetString(kPropertyTitle, data.cFileName);
219 file_value->SetString(kPropertyPath,
220 currentpath_.Append(data.cFileName).value());
221 file_value->SetBoolean(kPropertyDirectory,
222 (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false);
223
224#elif defined(OS_POSIX)
225 file_value->SetString(kPropertyTitle, data.filename);
226 file_value->SetString(kPropertyPath,
227 currentpath_.Append(data.filename).value());
228 file_value->SetBoolean(kPropertyDirectory, S_ISDIR(data.stat.st_mode));
229#endif
230 filelist_value_->Append(file_value);
231}
232
233void FileBrowseHandler::OnListDone(int error) {
234 DictionaryValue info_value;
235 info_value.SetString(L"call", "getChildren");
236 info_value.SetString(kPropertyPath, currentpath_.value());
237 dom_ui_->CallJavascriptFunction(L"fileBrowseResult",
238 info_value, *(filelist_value_.get()));
239}
240
241void FileBrowseHandler::HandleGetMetadata(const Value* value) {
242}
243
244////////////////////////////////////////////////////////////////////////////////
245//
246// FileBrowseUIContents
247//
248////////////////////////////////////////////////////////////////////////////////
249
250FileBrowseUI::FileBrowseUI(TabContents* contents) : DOMUI(contents) {
251 AddMessageHandler((new FileBrowseHandler())->Attach(this));
252 DLOG(ERROR) << "Got call to filebrowseUI";
253 FileBrowseUIHTMLSource* html_source = new FileBrowseUIHTMLSource();
254
255 // Set up the chrome://filebrowse/ source.
[email protected]fae20792009-10-28 20:31:58256 ChromeThread::PostTask(
257 ChromeThread::IO, FROM_HERE,
258 NewRunnableMethod(
[email protected]576a4ca2009-11-05 01:41:09259 Singleton<ChromeURLDataManager>::get(),
[email protected]698601e2009-10-21 22:43:37260 &ChromeURLDataManager::AddDataSource,
261 html_source));
262}