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