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.
5 #include "chrome/browser/chromeos/extensions/file_manager/private_api_misc.h"
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"
41 namespace extensions {
44 const char kCWSScope[] = "https://www.googleapis.com/auth/chromewebstore";
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(
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> >
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))
72 original_profiles.insert(profile);
73 const chromeos::User* const user =
74 chromeos::UserManager::Get()->GetUserByProfile(profile);
75 if (!user || !user->is_logged_in())
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;
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();
92 profile_info->image_uri.reset(new std::string(
93 webui::GetBitmapDataUrl(*bitmap)));
95 result_profiles.push_back(profile_info);
98 return result_profiles;
102 bool FileBrowserPrivateLogoutUserForReauthenticationFunction::RunImpl() {
103 chromeos::User* user =
104 chromeos::UserManager::Get()->GetUserByProfile(GetProfile());
106 chromeos::UserManager::Get()->SaveUserOAuthStatus(
108 chromeos::User::OAUTH2_TOKEN_STATUS_INVALID);
111 chrome::AttemptUserExit();
115 bool FileBrowserPrivateGetPreferencesFunction::RunImpl() {
116 api::file_browser_private::Preferences result;
117 const PrefService* const service = GetProfile()->GetPrefs();
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;
132 SetResult(result.ToValue().release());
134 drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
136 logger->Log(logging::LOG_INFO, "%s succeeded.", name().c_str());
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);
145 PrefService* const service = GetProfile()->GetPrefs();
147 if (params->change_info.cellular_disabled)
148 service->SetBoolean(prefs::kDisableDriveOverCellular,
149 *params->change_info.cellular_disabled);
151 if (params->change_info.hosted_files_disabled)
152 service->SetBoolean(prefs::kDisableDriveHostedFiles,
153 *params->change_info.hosted_files_disabled);
155 drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
157 logger->Log(logging::LOG_INFO, "%s succeeded.", name().c_str());
161 FileBrowserPrivateZipSelectionFunction::
162 FileBrowserPrivateZipSelectionFunction() {}
164 FileBrowserPrivateZipSelectionFunction::
165 ~FileBrowserPrivateZipSelectionFunction() {}
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);
172 // First param is the source directory URL.
173 if (params->dir_url.empty())
176 base::FilePath src_dir = file_manager::util::GetLocalPathFromURL(
177 render_view_host(), GetProfile(), GURL(params->dir_url));
181 // Second param is the list of selected file URLs.
182 if (params->selection_urls.empty())
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]));
191 files.push_back(path);
194 // Third param is the name of the output zip file.
195 if (params->dest_name.empty())
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))
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];
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))
212 src_relative_paths.push_back(relative_path);
215 zip_file_creator_ = new file_manager::ZipFileCreator(this,
220 // Keep the refcount until the zipping is complete on utility process.
223 zip_file_creator_->Start();
227 void FileBrowserPrivateZipSelectionFunction::OnZipDone(bool success) {
228 SetResult(new base::FundamentalValue(success));
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);
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;
243 case api::file_browser_private::ZOOM_OPERATION_TYPE_OUT:
244 zoom_type = content::PAGE_ZOOM_OUT;
246 case api::file_browser_private::ZOOM_OPERATION_TYPE_RESET:
247 zoom_type = content::PAGE_ZOOM_RESET;
253 render_view_host()->Zoom(zoom_type);
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);
262 if (params->item_id.empty())
265 const extensions::WebstoreStandaloneInstaller::Callback callback =
267 &FileBrowserPrivateInstallWebstoreItemFunction::OnInstallComplete,
270 scoped_refptr<file_manager::AppInstaller> installer(
271 new file_manager::AppInstaller(
272 GetAssociatedWebContents(),
276 // installer will be AddRef()'d in BeginInstall().
277 installer->BeginInstall();
281 void FileBrowserPrivateInstallWebstoreItemFunction::OnInstallComplete(
283 const std::string& error) {
284 drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
287 logger->Log(logging::LOG_INFO,
288 "App install succeeded. (item id: %s)",
289 webstore_item_id_.c_str());
293 logger->Log(logging::LOG_ERROR,
294 "App install failed. (item id: %s, reason: %s)",
295 webstore_item_id_.c_str(),
301 SendResponse(success);
304 FileBrowserPrivateRequestWebStoreAccessTokenFunction::
305 FileBrowserPrivateRequestWebStoreAccessTokenFunction() {
308 FileBrowserPrivateRequestWebStoreAccessTokenFunction::
309 ~FileBrowserPrivateRequestWebStoreAccessTokenFunction() {
312 bool FileBrowserPrivateRequestWebStoreAccessTokenFunction::RunImpl() {
313 std::vector<std::string> scopes;
314 scopes.push_back(kCWSScope);
316 ProfileOAuth2TokenService* oauth_service =
317 ProfileOAuth2TokenServiceFactory::GetForProfile(GetProfile());
318 net::URLRequestContextGetter* url_request_context_getter =
319 g_browser_process->system_request_context();
321 if (!oauth_service) {
322 drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
324 logger->Log(logging::LOG_ERROR,
325 "CWS OAuth token fetch failed. OAuth2TokenService can't "
328 SetResult(base::Value::CreateNullValue());
332 SigninManagerBase* signin_manager =
333 SigninManagerFactory::GetForProfile(GetProfile());
334 auth_service_.reset(new google_apis::AuthService(
336 signin_manager->GetAuthenticatedAccountId(),
337 url_request_context_getter,
339 auth_service_->StartAuthentication(base::Bind(
340 &FileBrowserPrivateRequestWebStoreAccessTokenFunction::
341 OnAccessTokenFetched,
347 void FileBrowserPrivateRequestWebStoreAccessTokenFunction::OnAccessTokenFetched(
348 google_apis::GDataErrorCode code,
349 const std::string& access_token) {
350 drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
352 if (code == google_apis::HTTP_SUCCESS) {
353 DCHECK(auth_service_->HasAccessToken());
354 DCHECK(access_token == auth_service_->access_token());
356 logger->Log(logging::LOG_INFO, "CWS OAuth token fetch succeeded.");
357 SetResult(new base::StringValue(access_token));
361 logger->Log(logging::LOG_ERROR,
362 "CWS OAuth token fetch failed. (GDataErrorCode: %s)",
363 google_apis::GDataErrorCodeToString(code).c_str());
365 SetResult(base::Value::CreateNullValue());
370 bool FileBrowserPrivateGetProfilesFunction::RunImpl() {
371 const std::vector<linked_ptr<api::file_browser_private::ProfileInfo> >&
372 profiles = GetLoggedInProfileInfoList();
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())
385 results_ = api::file_browser_private::GetProfiles::Results::Create(
388 display_profile_id.empty() ? current_profile_id : display_profile_id);
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();
398 // Check the multi-profile support.
399 if (!profiles::IsMultipleProfilesEnabled()) {
400 SetError("Multi-profile support is not enabled.");
404 chrome::MultiUserWindowManager* const window_manager =
405 chrome::MultiUserWindowManager::GetInstance();
406 DCHECK(window_manager);
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) {
417 SetError("The user is not logged-in now.");
421 // Look for the current app window.
422 apps::AppWindow* const app_window = GetCurrentAppWindow(this);
424 SetError("Target window is not found.");
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();
433 // Move the window to the user's desktop.
434 window_manager->ShowWindowForUser(app_window->GetNativeWindow(),
438 if (!window_manager->IsWindowOnDesktopOfUser(app_window->GetNativeWindow(),
439 params->profile_id)) {
440 SetError("The window cannot visit the desktop.");
447 } // namespace extensions