file_task_executor.cc revision a93a17c8d99d686bd4a1511e5504e5e6cc9fcadf
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.
4
5#include "chrome/browser/chromeos/drive/file_task_executor.h"
6
7#include <string>
8#include <vector>
9
10#include "base/json/json_writer.h"
11#include "base/string_util.h"
12#include "chrome/browser/chromeos/drive/drive.pb.h"
13#include "chrome/browser/chromeos/drive/drive_system_service.h"
14#include "chrome/browser/chromeos/drive/file_system_interface.h"
15#include "chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.h"
16#include "chrome/browser/google_apis/drive_service_interface.h"
17#include "chrome/browser/google_apis/gdata_wapi_parser.h"
18#include "chrome/browser/profiles/profile.h"
19#include "chrome/browser/profiles/profile_manager.h"
20#include "chrome/browser/ui/browser.h"
21#include "chrome/browser/ui/browser_finder.h"
22#include "chrome/browser/ui/browser_tabstrip.h"
23#include "chrome/browser/ui/browser_window.h"
24#include "content/public/browser/browser_thread.h"
25#include "webkit/fileapi/file_system_types.h"
26#include "webkit/fileapi/file_system_url.h"
27#include "webkit/fileapi/file_system_util.h"
28
29using file_handler_util::FileTaskExecutor;
30using fileapi::FileSystemURL;
31
32namespace drive {
33
34FileTaskExecutor::FileTaskExecutor(Profile* profile,
35                                   const std::string& app_id,
36                                   const std::string& action_id)
37  : file_handler_util::FileTaskExecutor(profile, GURL(), "", app_id),
38    action_id_(action_id),
39    current_index_(0) {
40  DCHECK("open-with" == action_id_);
41}
42
43FileTaskExecutor::~FileTaskExecutor() {
44}
45
46bool FileTaskExecutor::ExecuteAndNotify(
47    const std::vector<FileSystemURL>& file_urls,
48    const file_handler_util::FileTaskFinishedCallback& done) {
49  std::vector<base::FilePath> raw_paths;
50  for (std::vector<FileSystemURL>::const_iterator url = file_urls.begin();
51       url != file_urls.end(); ++url) {
52    base::FilePath path = util::ExtractDrivePathFromFileSystemUrl(*url);
53    if (path.empty())
54      return false;
55    raw_paths.push_back(path);
56  }
57
58  DriveSystemService* system_service =
59      DriveSystemServiceFactory::GetForProfile(profile());
60  DCHECK(current_index_ == 0);
61  if (!system_service || !system_service->file_system())
62    return false;
63  FileSystemInterface* file_system = system_service->file_system();
64
65  // Reset the index, so we know when we're done.
66  current_index_ = raw_paths.size();
67
68  for (std::vector<base::FilePath>::const_iterator iter = raw_paths.begin();
69      iter != raw_paths.end(); ++iter) {
70    file_system->GetResourceEntryByPath(
71        *iter,
72        base::Bind(&FileTaskExecutor::OnFileEntryFetched, this));
73  }
74  return true;
75}
76
77void FileTaskExecutor::OnFileEntryFetched(
78    FileError error,
79    scoped_ptr<ResourceEntry> entry) {
80  // If we aborted, then this will be zero.
81  if (!current_index_)
82    return;
83
84  DriveSystemService* system_service =
85      DriveSystemServiceFactory::GetForProfile(profile());
86
87  // Here, we are only interested in files.
88  if (entry.get() && !entry->has_file_specific_info())
89    error = FILE_ERROR_NOT_FOUND;
90
91  if (!system_service || error != FILE_ERROR_OK) {
92    Done(false);
93    return;
94  }
95
96  google_apis::DriveServiceInterface* drive_service =
97      system_service->drive_service();
98
99  // Send off a request for the drive service to authorize the apps for the
100  // current document entry for this document so we can get the
101  // open-with-<app_id> urls from the document entry.
102  drive_service->AuthorizeApp(
103      entry->resource_id(),
104      extension_id(),  // really app_id
105      base::Bind(&FileTaskExecutor::OnAppAuthorized,
106                 this,
107                 entry->resource_id()));
108}
109
110void FileTaskExecutor::OnAppAuthorized(
111    const std::string& resource_id,
112    google_apis::GDataErrorCode error,
113    const GURL& open_link) {
114  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
115
116  // If we aborted, then this will be zero.
117  if (!current_index_)
118    return;
119
120  DriveSystemService* system_service =
121      DriveSystemServiceFactory::GetForProfile(profile());
122
123  if (!system_service || error != google_apis::HTTP_SUCCESS) {
124    Done(false);
125    return;
126  }
127
128  if (open_link.is_empty()) {
129    Done(false);
130    return;
131  }
132
133  Browser* browser = GetBrowser();
134  chrome::AddSelectedTabWithURL(browser, open_link,
135                                content::PAGE_TRANSITION_LINK);
136  // If the current browser is not tabbed then the new tab will be created
137  // in a different browser. Make sure it is visible.
138  browser->window()->Show();
139
140  // We're done with this file.  If this is the last one, then we're done.
141  current_index_--;
142  DCHECK(current_index_ >= 0);
143  if (current_index_ == 0)
144    Done(true);
145}
146
147void FileTaskExecutor::Done(bool success) {
148  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
149  current_index_ = 0;
150  if (!done_.is_null())
151    done_.Run(success);
152  done_.Reset();
153}
154
155}  // namespace drive
156