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