private_api_misc.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 41namespace extensions { 42 43namespace { 44const char kCWSScope[] = "https://www.googleapis.com/auth/chromewebstore"; 45 46// Obtains the current app window. 47apps::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 58std::vector<linked_ptr<api::file_browser_private::ProfileInfo> > 59GetLoggedInProfileInfoList() { 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 102bool 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 115bool 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 140bool 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 161FileBrowserPrivateZipSelectionFunction:: 162 FileBrowserPrivateZipSelectionFunction() {} 163 164FileBrowserPrivateZipSelectionFunction:: 165 ~FileBrowserPrivateZipSelectionFunction() {} 166 167bool 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 227void FileBrowserPrivateZipSelectionFunction::OnZipDone(bool success) { 228 SetResult(new base::FundamentalValue(success)); 229 SendResponse(true); 230 Release(); 231} 232 233bool 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 257bool 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 281void 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 304FileBrowserPrivateRequestWebStoreAccessTokenFunction:: 305 FileBrowserPrivateRequestWebStoreAccessTokenFunction() { 306} 307 308FileBrowserPrivateRequestWebStoreAccessTokenFunction:: 309 ~FileBrowserPrivateRequestWebStoreAccessTokenFunction() { 310} 311 312bool 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 347void 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 370bool 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 392bool 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 448