Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / extensions / file_manager / private_api_misc.cc
1 // Copyright 2013 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/extensions/file_manager/private_api_misc.h"
6
7 #include "ash/frame/frame_util.h"
8 #include "base/files/file_path.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/chromeos/drive/file_system_util.h"
14 #include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h"
15 #include "chrome/browser/chromeos/file_manager/app_installer.h"
16 #include "chrome/browser/chromeos/file_manager/zip_file_creator.h"
17 #include "chrome/browser/chromeos/profiles/profile_helper.h"
18 #include "chrome/browser/chromeos/settings/cros_settings.h"
19 #include "chrome/browser/devtools/devtools_window.h"
20 #include "chrome/browser/drive/event_logger.h"
21 #include "chrome/browser/extensions/devtools_util.h"
22 #include "chrome/browser/lifetime/application_lifetime.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/profiles/profile_manager.h"
25 #include "chrome/browser/profiles/profiles_state.h"
26 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
27 #include "chrome/browser/signin/signin_manager_factory.h"
28 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
29 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
30 #include "chrome/common/extensions/api/file_manager_private.h"
31 #include "chrome/common/pref_names.h"
32 #include "components/signin/core/browser/profile_oauth2_token_service.h"
33 #include "components/signin/core/browser/signin_manager.h"
34 #include "components/user_manager/user_manager.h"
35 #include "content/public/browser/render_view_host.h"
36 #include "content/public/browser/web_contents.h"
37 #include "content/public/common/page_zoom.h"
38 #include "extensions/browser/app_window/app_window.h"
39 #include "extensions/browser/app_window/app_window_registry.h"
40 #include "google_apis/drive/auth_service.h"
41 #include "ui/base/webui/web_ui_util.h"
42 #include "url/gurl.h"
43
44 namespace extensions {
45
46 namespace {
47 const char kCWSScope[] = "https://www.googleapis.com/auth/chromewebstore";
48 const char kGoogleCastApiExtensionId[] = "mafeflapfdfljijmlienjedomfjfmhpd";
49
50 // Obtains the current app window.
51 AppWindow* GetCurrentAppWindow(ChromeSyncExtensionFunction* function) {
52   AppWindowRegistry* const app_window_registry =
53       AppWindowRegistry::Get(function->GetProfile());
54   content::WebContents* const contents = function->GetAssociatedWebContents();
55   content::RenderViewHost* const render_view_host =
56       contents ? contents->GetRenderViewHost() : NULL;
57   return render_view_host ? app_window_registry->GetAppWindowForRenderViewHost(
58                                 render_view_host)
59                           : NULL;
60 }
61
62 std::vector<linked_ptr<api::file_manager_private::ProfileInfo> >
63 GetLoggedInProfileInfoList() {
64   DCHECK(user_manager::UserManager::IsInitialized());
65   const std::vector<Profile*>& profiles =
66       g_browser_process->profile_manager()->GetLoadedProfiles();
67   std::set<Profile*> original_profiles;
68   std::vector<linked_ptr<api::file_manager_private::ProfileInfo> >
69       result_profiles;
70
71   for (size_t i = 0; i < profiles.size(); ++i) {
72     // Filter the profile.
73     Profile* const profile = profiles[i]->GetOriginalProfile();
74     if (original_profiles.count(profile))
75       continue;
76     original_profiles.insert(profile);
77     const user_manager::User* const user =
78         chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
79     if (!user || !user->is_logged_in())
80       continue;
81
82     // Make a ProfileInfo.
83     linked_ptr<api::file_manager_private::ProfileInfo> profile_info(
84         new api::file_manager_private::ProfileInfo());
85     profile_info->profile_id = multi_user_util::GetUserIDFromProfile(profile);
86     profile_info->display_name = UTF16ToUTF8(user->GetDisplayName());
87     // TODO(hirono): Remove the property from the profile_info.
88     profile_info->is_current_profile = true;
89
90     result_profiles.push_back(profile_info);
91   }
92
93   return result_profiles;
94 }
95 } // namespace
96
97 bool FileManagerPrivateLogoutUserForReauthenticationFunction::RunSync() {
98   user_manager::User* user =
99       chromeos::ProfileHelper::Get()->GetUserByProfile(GetProfile());
100   if (user) {
101     user_manager::UserManager::Get()->SaveUserOAuthStatus(
102         user->email(), user_manager::User::OAUTH2_TOKEN_STATUS_INVALID);
103   }
104
105   chrome::AttemptUserExit();
106   return true;
107 }
108
109 bool FileManagerPrivateGetPreferencesFunction::RunSync() {
110   api::file_manager_private::Preferences result;
111   const PrefService* const service = GetProfile()->GetPrefs();
112
113   result.drive_enabled = drive::util::IsDriveEnabledForProfile(GetProfile());
114   result.cellular_disabled =
115       service->GetBoolean(prefs::kDisableDriveOverCellular);
116   result.hosted_files_disabled =
117       service->GetBoolean(prefs::kDisableDriveHostedFiles);
118   result.use24hour_clock = service->GetBoolean(prefs::kUse24HourClock);
119   result.allow_redeem_offers = true;
120   if (!chromeos::CrosSettings::Get()->GetBoolean(
121           chromeos::kAllowRedeemChromeOsRegistrationOffers,
122           &result.allow_redeem_offers)) {
123     result.allow_redeem_offers = true;
124   }
125
126   SetResult(result.ToValue().release());
127
128   drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
129   if (logger)
130     logger->Log(logging::LOG_INFO, "%s succeeded.", name().c_str());
131   return true;
132 }
133
134 bool FileManagerPrivateSetPreferencesFunction::RunSync() {
135   using extensions::api::file_manager_private::SetPreferences::Params;
136   const scoped_ptr<Params> params(Params::Create(*args_));
137   EXTENSION_FUNCTION_VALIDATE(params);
138
139   PrefService* const service = GetProfile()->GetPrefs();
140
141   if (params->change_info.cellular_disabled)
142     service->SetBoolean(prefs::kDisableDriveOverCellular,
143                         *params->change_info.cellular_disabled);
144
145   if (params->change_info.hosted_files_disabled)
146     service->SetBoolean(prefs::kDisableDriveHostedFiles,
147                         *params->change_info.hosted_files_disabled);
148
149   drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
150   if (logger)
151     logger->Log(logging::LOG_INFO, "%s succeeded.", name().c_str());
152   return true;
153 }
154
155 FileManagerPrivateZipSelectionFunction::
156     FileManagerPrivateZipSelectionFunction() {}
157
158 FileManagerPrivateZipSelectionFunction::
159     ~FileManagerPrivateZipSelectionFunction() {}
160
161 bool FileManagerPrivateZipSelectionFunction::RunAsync() {
162   using extensions::api::file_manager_private::ZipSelection::Params;
163   const scoped_ptr<Params> params(Params::Create(*args_));
164   EXTENSION_FUNCTION_VALIDATE(params);
165
166   // First param is the source directory URL.
167   if (params->dir_url.empty())
168     return false;
169
170   base::FilePath src_dir = file_manager::util::GetLocalPathFromURL(
171       render_view_host(), GetProfile(), GURL(params->dir_url));
172   if (src_dir.empty())
173     return false;
174
175   // Second param is the list of selected file URLs.
176   if (params->selection_urls.empty())
177     return false;
178
179   std::vector<base::FilePath> files;
180   for (size_t i = 0; i < params->selection_urls.size(); ++i) {
181     base::FilePath path = file_manager::util::GetLocalPathFromURL(
182         render_view_host(), GetProfile(), GURL(params->selection_urls[i]));
183     if (path.empty())
184       return false;
185     files.push_back(path);
186   }
187
188   // Third param is the name of the output zip file.
189   if (params->dest_name.empty())
190     return false;
191
192   // Check if the dir path is under Drive mount point.
193   // TODO(hshi): support create zip file on Drive (crbug.com/158690).
194   if (drive::util::IsUnderDriveMountPoint(src_dir))
195     return false;
196
197   base::FilePath dest_file = src_dir.Append(params->dest_name);
198   std::vector<base::FilePath> src_relative_paths;
199   for (size_t i = 0; i != files.size(); ++i) {
200     const base::FilePath& file_path = files[i];
201
202     // Obtain the relative path of |file_path| under |src_dir|.
203     base::FilePath relative_path;
204     if (!src_dir.AppendRelativePath(file_path, &relative_path))
205       return false;
206     src_relative_paths.push_back(relative_path);
207   }
208
209   (new file_manager::ZipFileCreator(
210        base::Bind(&FileManagerPrivateZipSelectionFunction::OnZipDone, this),
211        src_dir,
212        src_relative_paths,
213        dest_file))->Start();
214   return true;
215 }
216
217 void FileManagerPrivateZipSelectionFunction::OnZipDone(bool success) {
218   SetResult(new base::FundamentalValue(success));
219   SendResponse(true);
220 }
221
222 bool FileManagerPrivateZoomFunction::RunSync() {
223   using extensions::api::file_manager_private::Zoom::Params;
224   const scoped_ptr<Params> params(Params::Create(*args_));
225   EXTENSION_FUNCTION_VALIDATE(params);
226
227   content::PageZoom zoom_type;
228   switch (params->operation) {
229     case api::file_manager_private::ZOOM_OPERATION_TYPE_IN:
230       zoom_type = content::PAGE_ZOOM_IN;
231       break;
232     case api::file_manager_private::ZOOM_OPERATION_TYPE_OUT:
233       zoom_type = content::PAGE_ZOOM_OUT;
234       break;
235     case api::file_manager_private::ZOOM_OPERATION_TYPE_RESET:
236       zoom_type = content::PAGE_ZOOM_RESET;
237       break;
238     default:
239       NOTREACHED();
240       return false;
241   }
242   render_view_host()->Zoom(zoom_type);
243   return true;
244 }
245
246 bool FileManagerPrivateInstallWebstoreItemFunction::RunAsync() {
247   using extensions::api::file_manager_private::InstallWebstoreItem::Params;
248   const scoped_ptr<Params> params(Params::Create(*args_));
249   EXTENSION_FUNCTION_VALIDATE(params);
250
251   if (params->item_id.empty())
252     return false;
253
254   const extensions::WebstoreStandaloneInstaller::Callback callback =
255       base::Bind(
256           &FileManagerPrivateInstallWebstoreItemFunction::OnInstallComplete,
257           this);
258
259   // Only GoogleCastAPI extension can use silent installation.
260   if (params->silent_installation &&
261       params->item_id != kGoogleCastApiExtensionId) {
262     SetError("Only whitelisted items can do silent installation.");
263     return false;
264   }
265
266   scoped_refptr<file_manager::AppInstaller> installer(
267       new file_manager::AppInstaller(GetAssociatedWebContents(),
268                                      params->item_id,
269                                      GetProfile(),
270                                      params->silent_installation,
271                                      callback));
272   // installer will be AddRef()'d in BeginInstall().
273   installer->BeginInstall();
274   return true;
275 }
276
277 void FileManagerPrivateInstallWebstoreItemFunction::OnInstallComplete(
278     bool success,
279     const std::string& error,
280     extensions::webstore_install::Result result) {
281   drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
282   if (success) {
283     if (logger) {
284       logger->Log(logging::LOG_INFO,
285                   "App install succeeded. (item id: %s)",
286                   webstore_item_id_.c_str());
287     }
288   } else {
289     if (logger) {
290       logger->Log(logging::LOG_ERROR,
291                   "App install failed. (item id: %s, reason: %s)",
292                   webstore_item_id_.c_str(),
293                   error.c_str());
294     }
295     SetError(error);
296   }
297
298   SendResponse(success);
299 }
300
301 FileManagerPrivateRequestWebStoreAccessTokenFunction::
302     FileManagerPrivateRequestWebStoreAccessTokenFunction() {
303 }
304
305 FileManagerPrivateRequestWebStoreAccessTokenFunction::
306     ~FileManagerPrivateRequestWebStoreAccessTokenFunction() {
307 }
308
309 bool FileManagerPrivateRequestWebStoreAccessTokenFunction::RunAsync() {
310   std::vector<std::string> scopes;
311   scopes.push_back(kCWSScope);
312
313   ProfileOAuth2TokenService* oauth_service =
314       ProfileOAuth2TokenServiceFactory::GetForProfile(GetProfile());
315   net::URLRequestContextGetter* url_request_context_getter =
316       g_browser_process->system_request_context();
317
318   if (!oauth_service) {
319     drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
320     if (logger) {
321       logger->Log(logging::LOG_ERROR,
322                   "CWS OAuth token fetch failed. OAuth2TokenService can't "
323                   "be retrieved.");
324     }
325     SetResult(base::Value::CreateNullValue());
326     return false;
327   }
328
329   SigninManagerBase* signin_manager =
330       SigninManagerFactory::GetForProfile(GetProfile());
331   auth_service_.reset(new google_apis::AuthService(
332       oauth_service,
333       signin_manager->GetAuthenticatedAccountId(),
334       url_request_context_getter,
335       scopes));
336   auth_service_->StartAuthentication(base::Bind(
337       &FileManagerPrivateRequestWebStoreAccessTokenFunction::
338           OnAccessTokenFetched,
339       this));
340
341   return true;
342 }
343
344 void FileManagerPrivateRequestWebStoreAccessTokenFunction::OnAccessTokenFetched(
345     google_apis::GDataErrorCode code,
346     const std::string& access_token) {
347   drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
348
349   if (code == google_apis::HTTP_SUCCESS) {
350     DCHECK(auth_service_->HasAccessToken());
351     DCHECK(access_token == auth_service_->access_token());
352     if (logger)
353       logger->Log(logging::LOG_INFO, "CWS OAuth token fetch succeeded.");
354     SetResult(new base::StringValue(access_token));
355     SendResponse(true);
356   } else {
357     if (logger) {
358       logger->Log(logging::LOG_ERROR,
359                   "CWS OAuth token fetch failed. (GDataErrorCode: %s)",
360                   google_apis::GDataErrorCodeToString(code).c_str());
361     }
362     SetResult(base::Value::CreateNullValue());
363     SendResponse(false);
364   }
365 }
366
367 bool FileManagerPrivateGetProfilesFunction::RunSync() {
368 #if defined(USE_ATHENA)
369   // TODO(oshima): Figure out what to do.
370   return false;
371 #endif
372
373   const std::vector<linked_ptr<api::file_manager_private::ProfileInfo> >&
374       profiles = GetLoggedInProfileInfoList();
375
376   // Obtains the display profile ID.
377   AppWindow* const app_window = GetCurrentAppWindow(this);
378   chrome::MultiUserWindowManager* const window_manager =
379       chrome::MultiUserWindowManager::GetInstance();
380   const std::string current_profile_id =
381       multi_user_util::GetUserIDFromProfile(GetProfile());
382   const std::string display_profile_id =
383       window_manager && app_window ? window_manager->GetUserPresentingWindow(
384                                          app_window->GetNativeWindow())
385                                    : "";
386
387   results_ = api::file_manager_private::GetProfiles::Results::Create(
388       profiles,
389       current_profile_id,
390       display_profile_id.empty() ? current_profile_id : display_profile_id);
391   return true;
392 }
393
394 bool FileManagerPrivateVisitDesktopFunction::RunSync() {
395   using api::file_manager_private::VisitDesktop::Params;
396   const scoped_ptr<Params> params(Params::Create(*args_));
397   const std::vector<linked_ptr<api::file_manager_private::ProfileInfo> >&
398       profiles = GetLoggedInProfileInfoList();
399
400   chrome::MultiUserWindowManager* const window_manager =
401       chrome::MultiUserWindowManager::GetInstance();
402   DCHECK(window_manager);
403
404   // Check if the target user is logged-in or not.
405   bool logged_in = false;
406   for (size_t i = 0; i < profiles.size(); ++i) {
407     if (profiles[i]->profile_id == params->profile_id) {
408       logged_in = true;
409       break;
410     }
411   }
412   if (!logged_in) {
413     SetError("The user is not logged-in now.");
414     return false;
415   }
416
417   // Look for the current app window.
418   AppWindow* const app_window = GetCurrentAppWindow(this);
419   if (!app_window) {
420     SetError("Target window is not found.");
421     return false;
422   }
423
424   // Move the window to the user's desktop.
425   window_manager->ShowWindowForUser(app_window->GetNativeWindow(),
426                                     params->profile_id);
427
428   // Check the result.
429   if (!window_manager->IsWindowOnDesktopOfUser(app_window->GetNativeWindow(),
430                                                params->profile_id)) {
431     SetError("The window cannot visit the desktop.");
432     return false;
433   }
434
435   return true;
436 }
437
438 bool FileManagerPrivateOpenInspectorFunction::RunSync() {
439   using extensions::api::file_manager_private::OpenInspector::Params;
440   const scoped_ptr<Params> params(Params::Create(*args_));
441   EXTENSION_FUNCTION_VALIDATE(params);
442
443   switch (params->type) {
444     case extensions::api::file_manager_private::INSPECTION_TYPE_NORMAL:
445       // Open inspector for foreground page.
446       DevToolsWindow::OpenDevToolsWindow(
447           content::WebContents::FromRenderViewHost(render_view_host()));
448       break;
449     case extensions::api::file_manager_private::INSPECTION_TYPE_CONSOLE:
450       // Open inspector for foreground page and bring focus to the console.
451       DevToolsWindow::OpenDevToolsWindow(
452           content::WebContents::FromRenderViewHost(render_view_host()),
453           DevToolsToggleAction::ShowConsole());
454       break;
455     case extensions::api::file_manager_private::INSPECTION_TYPE_ELEMENT:
456       // Open inspector for foreground page in inspect element mode.
457       DevToolsWindow::OpenDevToolsWindow(
458           content::WebContents::FromRenderViewHost(render_view_host()),
459           DevToolsToggleAction::Inspect());
460       break;
461     case extensions::api::file_manager_private::INSPECTION_TYPE_BACKGROUND:
462       // Open inspector for background page.
463       extensions::devtools_util::InspectBackgroundPage(extension(),
464                                                        GetProfile());
465       break;
466     default:
467       NOTREACHED();
468       SetError(
469           base::StringPrintf("Unexpected inspection type(%d) is specified.",
470                              static_cast<int>(params->type)));
471       return false;
472   }
473   return true;
474 }
475
476 }  // namespace extensions