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