NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / ui / webui / chromeos / drive_internals_ui.cc
blob5d4de45cd2b916478141ed6d62f49fc9038c38ce
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.
5 #include "chrome/browser/ui/webui/chromeos/drive_internals_ui.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/file_util.h"
10 #include "base/files/file_enumerator.h"
11 #include "base/format_macros.h"
12 #include "base/memory/scoped_vector.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/path_service.h"
15 #include "base/prefs/pref_service.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/sys_info.h"
18 #include "chrome/browser/chromeos/drive/debug_info_collector.h"
19 #include "chrome/browser/chromeos/drive/drive.pb.h"
20 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
21 #include "chrome/browser/chromeos/drive/file_system_util.h"
22 #include "chrome/browser/chromeos/drive/job_list.h"
23 #include "chrome/browser/chromeos/file_manager/path_util.h"
24 #include "chrome/browser/drive/drive_api_util.h"
25 #include "chrome/browser/drive/drive_notification_manager.h"
26 #include "chrome/browser/drive/drive_notification_manager_factory.h"
27 #include "chrome/browser/drive/drive_service_interface.h"
28 #include "chrome/browser/drive/drive_switches.h"
29 #include "chrome/browser/drive/event_logger.h"
30 #include "chrome/browser/profiles/profile.h"
31 #include "chrome/common/pref_names.h"
32 #include "chrome/common/url_constants.h"
33 #include "chromeos/chromeos_switches.h"
34 #include "content/public/browser/browser_thread.h"
35 #include "content/public/browser/web_ui.h"
36 #include "content/public/browser/web_ui_data_source.h"
37 #include "content/public/browser/web_ui_message_handler.h"
38 #include "google_apis/drive/auth_service.h"
39 #include "google_apis/drive/drive_api_parser.h"
40 #include "google_apis/drive/gdata_errorcode.h"
41 #include "google_apis/drive/gdata_wapi_parser.h"
42 #include "google_apis/drive/time_util.h"
43 #include "grit/browser_resources.h"
45 using content::BrowserThread;
47 namespace chromeos {
49 namespace {
51 // Gets metadata of all files and directories in |root_path|
52 // recursively. Stores the result as a list of dictionaries like:
54 // [{ path: 'GCache/v1/tmp/<local_id>',
55 // size: 12345,
56 // is_directory: false,
57 // last_modified: '2005-08-09T09:57:00-08:00',
58 // },...]
60 // The list is sorted by the path.
61 void GetGCacheContents(const base::FilePath& root_path,
62 base::ListValue* gcache_contents,
63 base::DictionaryValue* gcache_summary) {
64 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
65 DCHECK(gcache_contents);
66 DCHECK(gcache_summary);
68 // Use this map to sort the result list by the path.
69 std::map<base::FilePath, base::DictionaryValue*> files;
71 const int options = (base::FileEnumerator::FILES |
72 base::FileEnumerator::DIRECTORIES |
73 base::FileEnumerator::SHOW_SYM_LINKS);
74 base::FileEnumerator enumerator(root_path, true /* recursive */, options);
76 int64 total_size = 0;
77 for (base::FilePath current = enumerator.Next(); !current.empty();
78 current = enumerator.Next()) {
79 base::FileEnumerator::FileInfo info = enumerator.GetInfo();
80 int64 size = info.GetSize();
81 const bool is_directory = info.IsDirectory();
82 const bool is_symbolic_link = base::IsLink(info.GetName());
83 const base::Time last_modified = info.GetLastModifiedTime();
85 base::DictionaryValue* entry = new base::DictionaryValue;
86 entry->SetString("path", current.value());
87 // Use double instead of integer for large files.
88 entry->SetDouble("size", size);
89 entry->SetBoolean("is_directory", is_directory);
90 entry->SetBoolean("is_symbolic_link", is_symbolic_link);
91 entry->SetString(
92 "last_modified",
93 google_apis::util::FormatTimeAsStringLocaltime(last_modified));
94 // Print lower 9 bits in octal format.
95 entry->SetString(
96 "permission",
97 base::StringPrintf("%03o", info.stat().st_mode & 0x1ff));
98 files[current] = entry;
100 total_size += size;
103 // Convert |files| into |gcache_contents|.
104 for (std::map<base::FilePath, base::DictionaryValue*>::const_iterator
105 iter = files.begin(); iter != files.end(); ++iter) {
106 gcache_contents->Append(iter->second);
109 gcache_summary->SetDouble("total_size", total_size);
112 // Gets the available disk space for the path |home_path|.
113 void GetFreeDiskSpace(const base::FilePath& home_path,
114 base::DictionaryValue* local_storage_summary) {
115 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
116 DCHECK(local_storage_summary);
118 const int64 free_space = base::SysInfo::AmountOfFreeDiskSpace(home_path);
119 local_storage_summary->SetDouble("free_space", free_space);
122 // Formats |entry| into text.
123 std::string FormatEntry(const base::FilePath& path,
124 const drive::ResourceEntry& entry) {
125 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
127 using base::StringAppendF;
129 std::string out;
130 StringAppendF(&out, "%s\n", path.AsUTF8Unsafe().c_str());
131 StringAppendF(&out, " title: %s\n", entry.title().c_str());
132 StringAppendF(&out, " local_id: %s\n", entry.local_id().c_str());
133 StringAppendF(&out, " resource_id: %s\n", entry.resource_id().c_str());
134 StringAppendF(&out, " parent_local_id: %s\n",
135 entry.parent_local_id().c_str());
136 StringAppendF(&out, " shared: %s\n", entry.shared() ? "true" : "false");
137 StringAppendF(&out, " shared_with_me: %s\n",
138 entry.shared_with_me() ? "true" : "false");
140 const drive::PlatformFileInfoProto& file_info = entry.file_info();
141 StringAppendF(&out, " file_info\n");
142 StringAppendF(&out, " size: %" PRId64 "\n", file_info.size());
143 StringAppendF(&out, " is_directory: %d\n", file_info.is_directory());
144 StringAppendF(&out, " is_symbolic_link: %d\n",
145 file_info.is_symbolic_link());
147 const base::Time last_modified = base::Time::FromInternalValue(
148 file_info.last_modified());
149 const base::Time last_accessed = base::Time::FromInternalValue(
150 file_info.last_accessed());
151 const base::Time creation_time = base::Time::FromInternalValue(
152 file_info.creation_time());
153 StringAppendF(&out, " last_modified: %s\n",
154 google_apis::util::FormatTimeAsString(last_modified).c_str());
155 StringAppendF(&out, " last_accessed: %s\n",
156 google_apis::util::FormatTimeAsString(last_accessed).c_str());
157 StringAppendF(&out, " creation_time: %s\n",
158 google_apis::util::FormatTimeAsString(creation_time).c_str());
160 if (entry.has_file_specific_info()) {
161 const drive::FileSpecificInfo& file_specific_info =
162 entry.file_specific_info();
163 StringAppendF(&out, " alternate_url: %s\n",
164 file_specific_info.alternate_url().c_str());
165 StringAppendF(&out, " content_mime_type: %s\n",
166 file_specific_info.content_mime_type().c_str());
167 StringAppendF(&out, " file_md5: %s\n",
168 file_specific_info.md5().c_str());
169 StringAppendF(&out, " document_extension: %s\n",
170 file_specific_info.document_extension().c_str());
171 StringAppendF(&out, " is_hosted_document: %d\n",
172 file_specific_info.is_hosted_document());
175 if (entry.has_directory_specific_info()) {
176 StringAppendF(&out, " directory_info\n");
177 const drive::DirectorySpecificInfo& directory_specific_info =
178 entry.directory_specific_info();
179 StringAppendF(&out, " changestamp: %" PRId64 "\n",
180 directory_specific_info.changestamp());
183 return out;
186 std::string SeverityToString(logging::LogSeverity severity) {
187 switch (severity) {
188 case logging::LOG_INFO:
189 return "info";
190 case logging::LOG_WARNING:
191 return "warning";
192 case logging::LOG_ERROR:
193 return "error";
194 default: // Treat all other higher severities as ERROR.
195 return "error";
199 // Appends {'key': key, 'value': value} dictionary to the |list|.
200 void AppendKeyValue(base::ListValue* list,
201 const std::string& key,
202 const std::string& value) {
203 base::DictionaryValue* dict = new base::DictionaryValue;
204 dict->SetString("key", key);
205 dict->SetString("value", value);
206 list->Append(dict);
209 // Class to handle messages from chrome://drive-internals.
210 class DriveInternalsWebUIHandler : public content::WebUIMessageHandler {
211 public:
212 DriveInternalsWebUIHandler()
213 : last_sent_event_id_(-1),
214 weak_ptr_factory_(this) {
217 virtual ~DriveInternalsWebUIHandler() {
220 private:
221 // WebUIMessageHandler override.
222 virtual void RegisterMessages() OVERRIDE;
224 // Returns a DriveIntegrationService.
225 drive::DriveIntegrationService* GetIntegrationService();
227 // Returns a DriveService instance.
228 drive::DriveServiceInterface* GetDriveService();
230 // Returns a DebugInfoCollector instance.
231 drive::DebugInfoCollector* GetDebugInfoCollector();
233 // Called when the page is first loaded.
234 void OnPageLoaded(const base::ListValue* args);
236 // Updates respective sections.
237 void UpdateDriveRelatedFlagsSection();
238 void UpdateDriveRelatedPreferencesSection();
239 void UpdateConnectionStatusSection(
240 drive::DriveServiceInterface* drive_service);
241 void UpdateAboutResourceSection(
242 drive::DriveServiceInterface* drive_service);
243 void UpdateAppListSection(
244 drive::DriveServiceInterface* drive_service);
245 void UpdateLocalMetadataSection(
246 drive::DebugInfoCollector* debug_info_collector);
247 void UpdateDeltaUpdateStatusSection(
248 drive::DebugInfoCollector* debug_info_collector);
249 void UpdateInFlightOperationsSection(drive::JobListInterface* job_list);
250 void UpdateGCacheContentsSection();
251 void UpdateFileSystemContentsSection();
252 void UpdateLocalStorageUsageSection();
253 void UpdateCacheContentsSection(
254 drive::DebugInfoCollector* debug_info_collector);
255 void UpdateEventLogSection();
256 void UpdatePathConfigurationsSection();
258 // Called when GetGCacheContents() is complete.
259 void OnGetGCacheContents(base::ListValue* gcache_contents,
260 base::DictionaryValue* cache_summary);
262 // Called when GetResourceEntryByPath() is complete.
263 void OnGetResourceEntryByPath(const base::FilePath& path,
264 drive::FileError error,
265 scoped_ptr<drive::ResourceEntry> entry);
267 // Called when ReadDirectoryByPath() is complete.
268 void OnReadDirectoryByPath(const base::FilePath& parent_path,
269 drive::FileError error,
270 scoped_ptr<drive::ResourceEntryVector> entries);
272 // Called as the iterator for DebugInfoCollector::IterateFileCache().
273 void UpdateCacheEntry(const std::string& local_id,
274 const drive::FileCacheEntry& cache_entry);
276 // Called when GetFreeDiskSpace() is complete.
277 void OnGetFreeDiskSpace(base::DictionaryValue* local_storage_summary);
279 // Called when GetAboutResource() call to DriveService is complete.
280 void OnGetAboutResource(
281 google_apis::GDataErrorCode status,
282 scoped_ptr<google_apis::AboutResource> about_resource);
284 // Called when GetAppList() call to DriveService is complete.
285 void OnGetAppList(
286 google_apis::GDataErrorCode status,
287 scoped_ptr<google_apis::AppList> app_list);
289 // Callback for DebugInfoCollector::GetMetadata for local update.
290 void OnGetFilesystemMetadataForLocal(
291 const drive::FileSystemMetadata& metadata);
293 // Callback for DebugInfoCollector::GetMetadata for delta update.
294 void OnGetFilesystemMetadataForDeltaUpdate(
295 const drive::FileSystemMetadata& metadata);
297 // Called when the page requests periodic update.
298 void OnPeriodicUpdate(const base::ListValue* args);
300 // Called when the corresponding button on the page is pressed.
301 void ClearAccessToken(const base::ListValue* args);
302 void ClearRefreshToken(const base::ListValue* args);
303 void ResetDriveFileSystem(const base::ListValue* args);
304 void ListFileEntries(const base::ListValue* args);
306 // Called after file system reset for ResetDriveFileSystem is done.
307 void ResetFinished(bool success);
309 // The last event sent to the JavaScript side.
310 int last_sent_event_id_;
312 base::WeakPtrFactory<DriveInternalsWebUIHandler> weak_ptr_factory_;
313 DISALLOW_COPY_AND_ASSIGN(DriveInternalsWebUIHandler);
316 void DriveInternalsWebUIHandler::OnGetAboutResource(
317 google_apis::GDataErrorCode status,
318 scoped_ptr<google_apis::AboutResource> parsed_about_resource) {
319 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
321 if (status != google_apis::HTTP_SUCCESS) {
322 LOG(ERROR) << "Failed to get about resource";
323 return;
325 DCHECK(parsed_about_resource);
327 base::DictionaryValue about_resource;
328 about_resource.SetDouble("account-quota-total",
329 parsed_about_resource->quota_bytes_total());
330 about_resource.SetDouble("account-quota-used",
331 parsed_about_resource->quota_bytes_used());
332 about_resource.SetDouble("account-largest-changestamp-remote",
333 parsed_about_resource->largest_change_id());
334 about_resource.SetString("root-resource-id",
335 parsed_about_resource->root_folder_id());
337 web_ui()->CallJavascriptFunction("updateAboutResource", about_resource);
340 void DriveInternalsWebUIHandler::OnGetAppList(
341 google_apis::GDataErrorCode status,
342 scoped_ptr<google_apis::AppList> parsed_app_list) {
343 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
345 if (status != google_apis::HTTP_SUCCESS) {
346 LOG(ERROR) << "Failed to get app list";
347 return;
349 DCHECK(parsed_app_list);
351 base::DictionaryValue app_list;
352 app_list.SetString("etag", parsed_app_list->etag());
354 base::ListValue* items = new base::ListValue();
355 for (size_t i = 0; i < parsed_app_list->items().size(); ++i) {
356 const google_apis::AppResource* app = parsed_app_list->items()[i];
357 base::DictionaryValue* app_data = new base::DictionaryValue();
358 app_data->SetString("name", app->name());
359 app_data->SetString("application_id", app->application_id());
360 app_data->SetString("object_type", app->object_type());
361 app_data->SetBoolean("supports_create", app->supports_create());
363 items->Append(app_data);
365 app_list.Set("items", items);
367 web_ui()->CallJavascriptFunction("updateAppList", app_list);
370 void DriveInternalsWebUIHandler::RegisterMessages() {
371 web_ui()->RegisterMessageCallback(
372 "pageLoaded",
373 base::Bind(&DriveInternalsWebUIHandler::OnPageLoaded,
374 weak_ptr_factory_.GetWeakPtr()));
375 web_ui()->RegisterMessageCallback(
376 "periodicUpdate",
377 base::Bind(&DriveInternalsWebUIHandler::OnPeriodicUpdate,
378 weak_ptr_factory_.GetWeakPtr()));
379 web_ui()->RegisterMessageCallback(
380 "clearAccessToken",
381 base::Bind(&DriveInternalsWebUIHandler::ClearAccessToken,
382 weak_ptr_factory_.GetWeakPtr()));
383 web_ui()->RegisterMessageCallback(
384 "clearRefreshToken",
385 base::Bind(&DriveInternalsWebUIHandler::ClearRefreshToken,
386 weak_ptr_factory_.GetWeakPtr()));
387 web_ui()->RegisterMessageCallback(
388 "resetDriveFileSystem",
389 base::Bind(&DriveInternalsWebUIHandler::ResetDriveFileSystem,
390 weak_ptr_factory_.GetWeakPtr()));
391 web_ui()->RegisterMessageCallback(
392 "listFileEntries",
393 base::Bind(&DriveInternalsWebUIHandler::ListFileEntries,
394 weak_ptr_factory_.GetWeakPtr()));
397 drive::DriveIntegrationService*
398 DriveInternalsWebUIHandler::GetIntegrationService() {
399 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
401 Profile* profile = Profile::FromWebUI(web_ui());
402 drive::DriveIntegrationService* service =
403 drive::DriveIntegrationServiceFactory::FindForProfile(profile);
404 if (!service || !service->is_enabled())
405 return NULL;
406 return service;
409 drive::DriveServiceInterface* DriveInternalsWebUIHandler::GetDriveService() {
410 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
412 Profile* profile = Profile::FromWebUI(web_ui());
413 return drive::util::GetDriveServiceByProfile(profile);
416 drive::DebugInfoCollector* DriveInternalsWebUIHandler::GetDebugInfoCollector() {
417 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
419 drive::DriveIntegrationService* integration_service = GetIntegrationService();
420 return integration_service ?
421 integration_service->debug_info_collector() : NULL;
424 void DriveInternalsWebUIHandler::OnPageLoaded(const base::ListValue* args) {
425 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
427 drive::DriveIntegrationService* integration_service =
428 GetIntegrationService();
429 // |integration_service| may be NULL in the guest/incognito mode.
430 if (!integration_service)
431 return;
433 drive::DriveServiceInterface* drive_service =
434 integration_service->drive_service();
435 DCHECK(drive_service);
436 drive::DebugInfoCollector* debug_info_collector =
437 integration_service->debug_info_collector();
438 DCHECK(debug_info_collector);
440 UpdateDriveRelatedFlagsSection();
441 UpdateDriveRelatedPreferencesSection();
442 UpdateConnectionStatusSection(drive_service);
443 UpdateAboutResourceSection(drive_service);
444 UpdateAppListSection(drive_service);
445 UpdateLocalMetadataSection(debug_info_collector);
446 UpdateDeltaUpdateStatusSection(debug_info_collector);
447 UpdateInFlightOperationsSection(integration_service->job_list());
448 UpdateGCacheContentsSection();
449 UpdateCacheContentsSection(debug_info_collector);
450 UpdateLocalStorageUsageSection();
451 UpdatePathConfigurationsSection();
453 // When the drive-internals page is reloaded by the reload key, the page
454 // content is recreated, but this WebUI object is not (instead, OnPageLoaded
455 // is called again). In that case, we have to forget the last sent ID here,
456 // and resent whole the logs to the page.
457 last_sent_event_id_ = -1;
458 UpdateEventLogSection();
461 void DriveInternalsWebUIHandler::UpdateDriveRelatedFlagsSection() {
462 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
464 const char* kDriveRelatedFlags[] = {
465 drive::switches::kEnableDriveV2Api,
466 chromeos::switches::kDisableDrive,
469 base::ListValue flags;
470 for (size_t i = 0; i < arraysize(kDriveRelatedFlags); ++i) {
471 const std::string key = kDriveRelatedFlags[i];
472 std::string value = "(not set)";
473 if (CommandLine::ForCurrentProcess()->HasSwitch(key))
474 value = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(key);
475 AppendKeyValue(&flags, key, value.empty() ? "(set)" : value);
478 web_ui()->CallJavascriptFunction("updateDriveRelatedFlags", flags);
481 void DriveInternalsWebUIHandler::UpdateDriveRelatedPreferencesSection() {
482 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
484 const char* kDriveRelatedPreferences[] = {
485 prefs::kDisableDrive,
486 prefs::kDisableDriveOverCellular,
487 prefs::kDisableDriveHostedFiles,
490 Profile* profile = Profile::FromWebUI(web_ui());
491 PrefService* pref_service = profile->GetPrefs();
493 base::ListValue preferences;
494 for (size_t i = 0; i < arraysize(kDriveRelatedPreferences); ++i) {
495 const std::string key = kDriveRelatedPreferences[i];
496 // As of now, all preferences are boolean.
497 const std::string value =
498 (pref_service->GetBoolean(key.c_str()) ? "true" : "false");
499 AppendKeyValue(&preferences, key, value);
502 web_ui()->CallJavascriptFunction("updateDriveRelatedPreferences",
503 preferences);
506 void DriveInternalsWebUIHandler::UpdateConnectionStatusSection(
507 drive::DriveServiceInterface* drive_service) {
508 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
509 DCHECK(drive_service);
511 std::string status;
512 switch (drive::util::GetDriveConnectionStatus(Profile::FromWebUI(web_ui()))) {
513 case drive::util::DRIVE_DISCONNECTED_NOSERVICE:
514 status = "no service";
515 break;
516 case drive::util::DRIVE_DISCONNECTED_NONETWORK:
517 status = "no network";
518 break;
519 case drive::util::DRIVE_DISCONNECTED_NOTREADY:
520 status = "not ready";
521 break;
522 case drive::util::DRIVE_CONNECTED_METERED:
523 status = "metered";
524 break;
525 case drive::util::DRIVE_CONNECTED:
526 status = "connected";
527 break;
530 base::DictionaryValue connection_status;
531 connection_status.SetString("status", status);
532 connection_status.SetBoolean("has-refresh-token",
533 drive_service->HasRefreshToken());
534 connection_status.SetBoolean("has-access-token",
535 drive_service->HasAccessToken());
536 web_ui()->CallJavascriptFunction("updateConnectionStatus", connection_status);
539 void DriveInternalsWebUIHandler::UpdateAboutResourceSection(
540 drive::DriveServiceInterface* drive_service) {
541 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
542 DCHECK(drive_service);
544 drive_service->GetAboutResource(
545 base::Bind(&DriveInternalsWebUIHandler::OnGetAboutResource,
546 weak_ptr_factory_.GetWeakPtr()));
549 void DriveInternalsWebUIHandler::UpdateAppListSection(
550 drive::DriveServiceInterface* drive_service) {
551 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
552 DCHECK(drive_service);
554 drive_service->GetAppList(
555 base::Bind(&DriveInternalsWebUIHandler::OnGetAppList,
556 weak_ptr_factory_.GetWeakPtr()));
559 void DriveInternalsWebUIHandler::UpdateLocalMetadataSection(
560 drive::DebugInfoCollector* debug_info_collector) {
561 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
562 DCHECK(debug_info_collector);
564 debug_info_collector->GetMetadata(
565 base::Bind(&DriveInternalsWebUIHandler::OnGetFilesystemMetadataForLocal,
566 weak_ptr_factory_.GetWeakPtr()));
569 void DriveInternalsWebUIHandler::OnGetFilesystemMetadataForLocal(
570 const drive::FileSystemMetadata& metadata) {
571 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
573 base::DictionaryValue local_metadata;
574 local_metadata.SetDouble("account-largest-changestamp-local",
575 metadata.largest_changestamp);
576 local_metadata.SetBoolean("account-metadata-refreshing", metadata.refreshing);
577 web_ui()->CallJavascriptFunction("updateLocalMetadata", local_metadata);
580 void DriveInternalsWebUIHandler::ClearAccessToken(const base::ListValue* args) {
581 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
583 drive::DriveServiceInterface* drive_service = GetDriveService();
584 if (drive_service)
585 drive_service->ClearAccessToken();
588 void DriveInternalsWebUIHandler::ClearRefreshToken(
589 const base::ListValue* args) {
590 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
592 drive::DriveServiceInterface* drive_service = GetDriveService();
593 if (drive_service)
594 drive_service->ClearRefreshToken();
597 void DriveInternalsWebUIHandler::ResetDriveFileSystem(
598 const base::ListValue* args) {
599 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
601 drive::DriveIntegrationService* integration_service =
602 GetIntegrationService();
603 if (integration_service) {
604 integration_service->ClearCacheAndRemountFileSystem(
605 base::Bind(&DriveInternalsWebUIHandler::ResetFinished,
606 weak_ptr_factory_.GetWeakPtr()));
610 void DriveInternalsWebUIHandler::ResetFinished(bool success) {
611 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
613 web_ui()->CallJavascriptFunction("updateResetStatus",
614 base::FundamentalValue(success));
617 void DriveInternalsWebUIHandler::ListFileEntries(const base::ListValue* args) {
618 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
620 UpdateFileSystemContentsSection();
623 void DriveInternalsWebUIHandler::UpdateDeltaUpdateStatusSection(
624 drive::DebugInfoCollector* debug_info_collector) {
625 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
626 DCHECK(debug_info_collector);
628 debug_info_collector->GetMetadata(
629 base::Bind(
630 &DriveInternalsWebUIHandler::OnGetFilesystemMetadataForDeltaUpdate,
631 weak_ptr_factory_.GetWeakPtr()));
634 void DriveInternalsWebUIHandler::OnGetFilesystemMetadataForDeltaUpdate(
635 const drive::FileSystemMetadata& metadata) {
636 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
638 Profile* profile = Profile::FromWebUI(web_ui());
639 drive::DriveNotificationManager* drive_notification_manager =
640 drive::DriveNotificationManagerFactory::GetForBrowserContext(profile);
641 if (!drive_notification_manager)
642 return;
644 base::DictionaryValue delta_update_status;
645 delta_update_status.SetBoolean(
646 "push-notification-enabled",
647 drive_notification_manager->push_notification_enabled());
648 delta_update_status.SetString(
649 "last-update-check-time",
650 google_apis::util::FormatTimeAsStringLocaltime(
651 metadata.last_update_check_time));
652 delta_update_status.SetString(
653 "last-update-check-error",
654 drive::FileErrorToString(metadata.last_update_check_error));
656 web_ui()->CallJavascriptFunction("updateDeltaUpdateStatus",
657 delta_update_status);
660 void DriveInternalsWebUIHandler::UpdateInFlightOperationsSection(
661 drive::JobListInterface* job_list) {
662 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
663 DCHECK(job_list);
665 std::vector<drive::JobInfo> info_list = job_list->GetJobInfoList();
667 base::ListValue in_flight_operations;
668 for (size_t i = 0; i < info_list.size(); ++i) {
669 const drive::JobInfo& info = info_list[i];
671 base::DictionaryValue* dict = new base::DictionaryValue;
672 dict->SetInteger("id", info.job_id);
673 dict->SetString("type", drive::JobTypeToString(info.job_type));
674 dict->SetString("file_path", info.file_path.AsUTF8Unsafe());
675 dict->SetString("state", drive::JobStateToString(info.state));
676 dict->SetDouble("progress_current", info.num_completed_bytes);
677 dict->SetDouble("progress_total", info.num_total_bytes);
678 in_flight_operations.Append(dict);
680 web_ui()->CallJavascriptFunction("updateInFlightOperations",
681 in_flight_operations);
684 void DriveInternalsWebUIHandler::UpdateGCacheContentsSection() {
685 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
687 // Start updating the GCache contents section.
688 Profile* profile = Profile::FromWebUI(web_ui());
689 const base::FilePath root_path = drive::util::GetCacheRootPath(profile);
690 base::ListValue* gcache_contents = new base::ListValue;
691 base::DictionaryValue* gcache_summary = new base::DictionaryValue;
692 BrowserThread::PostBlockingPoolTaskAndReply(
693 FROM_HERE,
694 base::Bind(&GetGCacheContents,
695 root_path,
696 gcache_contents,
697 gcache_summary),
698 base::Bind(&DriveInternalsWebUIHandler::OnGetGCacheContents,
699 weak_ptr_factory_.GetWeakPtr(),
700 base::Owned(gcache_contents),
701 base::Owned(gcache_summary)));
704 void DriveInternalsWebUIHandler::UpdateFileSystemContentsSection() {
705 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
707 drive::DebugInfoCollector* debug_info_collector = GetDebugInfoCollector();
708 if (!debug_info_collector)
709 return;
711 // Start rendering the file system tree as text.
712 const base::FilePath root_path = drive::util::GetDriveGrandRootPath();
714 debug_info_collector->GetResourceEntry(
715 root_path,
716 base::Bind(&DriveInternalsWebUIHandler::OnGetResourceEntryByPath,
717 weak_ptr_factory_.GetWeakPtr(),
718 root_path));
720 debug_info_collector->ReadDirectory(
721 root_path,
722 base::Bind(&DriveInternalsWebUIHandler::OnReadDirectoryByPath,
723 weak_ptr_factory_.GetWeakPtr(),
724 root_path));
727 void DriveInternalsWebUIHandler::UpdateLocalStorageUsageSection() {
728 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
730 // Propagate the amount of local free space in bytes.
731 base::FilePath home_path;
732 if (PathService::Get(base::DIR_HOME, &home_path)) {
733 base::DictionaryValue* local_storage_summary = new base::DictionaryValue;
734 BrowserThread::PostBlockingPoolTaskAndReply(
735 FROM_HERE,
736 base::Bind(&GetFreeDiskSpace, home_path, local_storage_summary),
737 base::Bind(&DriveInternalsWebUIHandler::OnGetFreeDiskSpace,
738 weak_ptr_factory_.GetWeakPtr(),
739 base::Owned(local_storage_summary)));
740 } else {
741 LOG(ERROR) << "Home directory not found";
745 void DriveInternalsWebUIHandler::UpdateCacheContentsSection(
746 drive::DebugInfoCollector* debug_info_collector) {
747 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
748 DCHECK(debug_info_collector);
750 debug_info_collector->IterateFileCache(
751 base::Bind(&DriveInternalsWebUIHandler::UpdateCacheEntry,
752 weak_ptr_factory_.GetWeakPtr()),
753 base::Bind(&base::DoNothing));
756 void DriveInternalsWebUIHandler::UpdateEventLogSection() {
757 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
759 drive::DriveIntegrationService* integration_service =
760 GetIntegrationService();
761 if (!integration_service)
762 return;
764 const std::vector<drive::EventLogger::Event> log =
765 integration_service->event_logger()->GetHistory();
767 base::ListValue list;
768 for (size_t i = 0; i < log.size(); ++i) {
769 // Skip events which were already sent.
770 if (log[i].id <= last_sent_event_id_)
771 continue;
773 std::string severity = SeverityToString(log[i].severity);
775 base::DictionaryValue* dict = new base::DictionaryValue;
776 dict->SetString("key",
777 google_apis::util::FormatTimeAsStringLocaltime(log[i].when));
778 dict->SetString("value", "[" + severity + "] " + log[i].what);
779 dict->SetString("class", "log-" + severity);
780 list.Append(dict);
781 last_sent_event_id_ = log[i].id;
783 if (!list.empty())
784 web_ui()->CallJavascriptFunction("updateEventLog", list);
787 void DriveInternalsWebUIHandler::UpdatePathConfigurationsSection() {
788 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
790 Profile* const profile = Profile::FromWebUI(web_ui());
792 base::ListValue paths;
794 AppendKeyValue(
795 &paths, "Downloads",
796 file_manager::util::GetDownloadsFolderForProfile(profile).AsUTF8Unsafe());
797 AppendKeyValue(
798 &paths, "Drive",
799 drive::util::GetDriveMountPointPath(profile).AsUTF8Unsafe());
801 const char* kPathPreferences[] = {
802 prefs::kSelectFileLastDirectory,
803 prefs::kSaveFileDefaultDirectory,
804 prefs::kDownloadDefaultDirectory,
806 for (size_t i = 0; i < arraysize(kPathPreferences); ++i) {
807 const char* const key = kPathPreferences[i];
808 AppendKeyValue(&paths, key,
809 profile->GetPrefs()->GetFilePath(key).AsUTF8Unsafe());
812 web_ui()->CallJavascriptFunction("updatePathConfigurations", paths);
815 void DriveInternalsWebUIHandler::OnGetGCacheContents(
816 base::ListValue* gcache_contents,
817 base::DictionaryValue* gcache_summary) {
818 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
819 DCHECK(gcache_contents);
820 DCHECK(gcache_summary);
822 web_ui()->CallJavascriptFunction("updateGCacheContents",
823 *gcache_contents,
824 *gcache_summary);
827 void DriveInternalsWebUIHandler::OnGetResourceEntryByPath(
828 const base::FilePath& path,
829 drive::FileError error,
830 scoped_ptr<drive::ResourceEntry> entry) {
831 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
833 if (error == drive::FILE_ERROR_OK) {
834 DCHECK(entry.get());
835 const base::StringValue value(FormatEntry(path, *entry) + "\n");
836 web_ui()->CallJavascriptFunction("updateFileSystemContents", value);
840 void DriveInternalsWebUIHandler::OnReadDirectoryByPath(
841 const base::FilePath& parent_path,
842 drive::FileError error,
843 scoped_ptr<drive::ResourceEntryVector> entries) {
844 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
846 if (error == drive::FILE_ERROR_OK) {
847 DCHECK(entries.get());
849 drive::DebugInfoCollector* debug_info_collector = GetDebugInfoCollector();
850 std::string file_system_as_text;
851 for (size_t i = 0; i < entries->size(); ++i) {
852 const drive::ResourceEntry& entry = (*entries)[i];
853 const base::FilePath current_path = parent_path.Append(
854 base::FilePath::FromUTF8Unsafe(entry.base_name()));
856 file_system_as_text.append(FormatEntry(current_path, entry) + "\n");
858 if (entry.file_info().is_directory()) {
859 debug_info_collector->ReadDirectory(
860 current_path,
861 base::Bind(&DriveInternalsWebUIHandler::OnReadDirectoryByPath,
862 weak_ptr_factory_.GetWeakPtr(),
863 current_path));
867 // There may be pending ReadDirectoryByPath() calls, but we can update
868 // the page with what we have now. This results in progressive
869 // updates, which is good for a large file system.
870 const base::StringValue value(file_system_as_text);
871 web_ui()->CallJavascriptFunction("updateFileSystemContents", value);
875 void DriveInternalsWebUIHandler::UpdateCacheEntry(
876 const std::string& local_id,
877 const drive::FileCacheEntry& cache_entry) {
878 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
880 // Convert |cache_entry| into a dictionary.
881 base::DictionaryValue value;
882 value.SetString("local_id", local_id);
883 value.SetString("md5", cache_entry.md5());
884 value.SetBoolean("is_present", cache_entry.is_present());
885 value.SetBoolean("is_pinned", cache_entry.is_pinned());
886 value.SetBoolean("is_dirty", cache_entry.is_dirty());
888 web_ui()->CallJavascriptFunction("updateCacheContents", value);
891 void DriveInternalsWebUIHandler::OnGetFreeDiskSpace(
892 base::DictionaryValue* local_storage_summary) {
893 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
894 DCHECK(local_storage_summary);
896 web_ui()->CallJavascriptFunction(
897 "updateLocalStorageUsage", *local_storage_summary);
900 void DriveInternalsWebUIHandler::OnPeriodicUpdate(const base::ListValue* args) {
901 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
903 drive::DriveIntegrationService* integration_service =
904 GetIntegrationService();
905 // |integration_service| may be NULL in the guest/incognito mode.
906 if (!integration_service)
907 return;
909 UpdateInFlightOperationsSection(integration_service->job_list());
910 UpdateEventLogSection();
913 } // namespace
915 DriveInternalsUI::DriveInternalsUI(content::WebUI* web_ui)
916 : WebUIController(web_ui) {
917 web_ui->AddMessageHandler(new DriveInternalsWebUIHandler());
919 content::WebUIDataSource* source =
920 content::WebUIDataSource::Create(chrome::kChromeUIDriveInternalsHost);
921 source->AddResourcePath("drive_internals.css", IDR_DRIVE_INTERNALS_CSS);
922 source->AddResourcePath("drive_internals.js", IDR_DRIVE_INTERNALS_JS);
923 source->SetDefaultResource(IDR_DRIVE_INTERNALS_HTML);
925 Profile* profile = Profile::FromWebUI(web_ui);
926 content::WebUIDataSource::Add(profile, source);
929 } // namespace chromeos