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 "ash/frame/frame_util.h"
8 #include "base/files/file_path.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/strings/stringprintf.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/private_api_util.h"
15 #include "chrome/browser/chromeos/file_manager/app_installer.h"
16 #include "chrome/browser/chromeos/file_manager/zip_file_creator.h"
17 #include "chrome/browser/chromeos/profiles/profile_helper.h"
18 #include "chrome/browser/chromeos/settings/cros_settings.h"
19 #include "chrome/browser/devtools/devtools_window.h"
20 #include "chrome/browser/drive/event_logger.h"
21 #include "chrome/browser/extensions/devtools_util.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_factory.h"
28 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
29 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
30 #include "chrome/common/extensions/api/file_manager_private.h"
31 #include "chrome/common/pref_names.h"
32 #include "components/signin/core/browser/profile_oauth2_token_service.h"
33 #include "components/signin/core/browser/signin_manager.h"
34 #include "components/user_manager/user_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 "extensions/browser/app_window/app_window.h"
39 #include "extensions/browser/app_window/app_window_registry.h"
40 #include "google_apis/drive/auth_service.h"
41 #include "ui/base/webui/web_ui_util.h"
44 namespace extensions {
47 const char kCWSScope[] = "https://www.googleapis.com/auth/chromewebstore";
48 const char kGoogleCastApiExtensionId[] = "mafeflapfdfljijmlienjedomfjfmhpd";
50 // Obtains the current app window.
51 AppWindow* GetCurrentAppWindow(ChromeSyncExtensionFunction* function) {
52 AppWindowRegistry* const app_window_registry =
53 AppWindowRegistry::Get(function->GetProfile());
54 content::WebContents* const contents = function->GetAssociatedWebContents();
55 content::RenderViewHost* const render_view_host =
56 contents ? contents->GetRenderViewHost() : NULL;
57 return render_view_host ? app_window_registry->GetAppWindowForRenderViewHost(
62 std::vector<linked_ptr<api::file_manager_private::ProfileInfo> >
63 GetLoggedInProfileInfoList() {
64 DCHECK(user_manager::UserManager::IsInitialized());
65 const std::vector<Profile*>& profiles =
66 g_browser_process->profile_manager()->GetLoadedProfiles();
67 std::set<Profile*> original_profiles;
68 std::vector<linked_ptr<api::file_manager_private::ProfileInfo> >
71 for (size_t i = 0; i < profiles.size(); ++i) {
72 // Filter the profile.
73 Profile* const profile = profiles[i]->GetOriginalProfile();
74 if (original_profiles.count(profile))
76 original_profiles.insert(profile);
77 const user_manager::User* const user =
78 chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
79 if (!user || !user->is_logged_in())
82 // Make a ProfileInfo.
83 linked_ptr<api::file_manager_private::ProfileInfo> profile_info(
84 new api::file_manager_private::ProfileInfo());
85 profile_info->profile_id = multi_user_util::GetUserIDFromProfile(profile);
86 profile_info->display_name = UTF16ToUTF8(user->GetDisplayName());
87 // TODO(hirono): Remove the property from the profile_info.
88 profile_info->is_current_profile = true;
90 result_profiles.push_back(profile_info);
93 return result_profiles;
97 bool FileManagerPrivateLogoutUserForReauthenticationFunction::RunSync() {
98 user_manager::User* user =
99 chromeos::ProfileHelper::Get()->GetUserByProfile(GetProfile());
101 user_manager::UserManager::Get()->SaveUserOAuthStatus(
102 user->email(), user_manager::User::OAUTH2_TOKEN_STATUS_INVALID);
105 chrome::AttemptUserExit();
109 bool FileManagerPrivateGetPreferencesFunction::RunSync() {
110 api::file_manager_private::Preferences result;
111 const PrefService* const service = GetProfile()->GetPrefs();
113 result.drive_enabled = drive::util::IsDriveEnabledForProfile(GetProfile());
114 result.cellular_disabled =
115 service->GetBoolean(prefs::kDisableDriveOverCellular);
116 result.hosted_files_disabled =
117 service->GetBoolean(prefs::kDisableDriveHostedFiles);
118 result.use24hour_clock = service->GetBoolean(prefs::kUse24HourClock);
119 result.allow_redeem_offers = true;
120 if (!chromeos::CrosSettings::Get()->GetBoolean(
121 chromeos::kAllowRedeemChromeOsRegistrationOffers,
122 &result.allow_redeem_offers)) {
123 result.allow_redeem_offers = true;
126 SetResult(result.ToValue().release());
128 drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
130 logger->Log(logging::LOG_INFO, "%s succeeded.", name().c_str());
134 bool FileManagerPrivateSetPreferencesFunction::RunSync() {
135 using extensions::api::file_manager_private::SetPreferences::Params;
136 const scoped_ptr<Params> params(Params::Create(*args_));
137 EXTENSION_FUNCTION_VALIDATE(params);
139 PrefService* const service = GetProfile()->GetPrefs();
141 if (params->change_info.cellular_disabled)
142 service->SetBoolean(prefs::kDisableDriveOverCellular,
143 *params->change_info.cellular_disabled);
145 if (params->change_info.hosted_files_disabled)
146 service->SetBoolean(prefs::kDisableDriveHostedFiles,
147 *params->change_info.hosted_files_disabled);
149 drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
151 logger->Log(logging::LOG_INFO, "%s succeeded.", name().c_str());
155 FileManagerPrivateZipSelectionFunction::
156 FileManagerPrivateZipSelectionFunction() {}
158 FileManagerPrivateZipSelectionFunction::
159 ~FileManagerPrivateZipSelectionFunction() {}
161 bool FileManagerPrivateZipSelectionFunction::RunAsync() {
162 using extensions::api::file_manager_private::ZipSelection::Params;
163 const scoped_ptr<Params> params(Params::Create(*args_));
164 EXTENSION_FUNCTION_VALIDATE(params);
166 // First param is the source directory URL.
167 if (params->dir_url.empty())
170 base::FilePath src_dir = file_manager::util::GetLocalPathFromURL(
171 render_view_host(), GetProfile(), GURL(params->dir_url));
175 // Second param is the list of selected file URLs.
176 if (params->selection_urls.empty())
179 std::vector<base::FilePath> files;
180 for (size_t i = 0; i < params->selection_urls.size(); ++i) {
181 base::FilePath path = file_manager::util::GetLocalPathFromURL(
182 render_view_host(), GetProfile(), GURL(params->selection_urls[i]));
185 files.push_back(path);
188 // Third param is the name of the output zip file.
189 if (params->dest_name.empty())
192 // Check if the dir path is under Drive mount point.
193 // TODO(hshi): support create zip file on Drive (crbug.com/158690).
194 if (drive::util::IsUnderDriveMountPoint(src_dir))
197 base::FilePath dest_file = src_dir.Append(params->dest_name);
198 std::vector<base::FilePath> src_relative_paths;
199 for (size_t i = 0; i != files.size(); ++i) {
200 const base::FilePath& file_path = files[i];
202 // Obtain the relative path of |file_path| under |src_dir|.
203 base::FilePath relative_path;
204 if (!src_dir.AppendRelativePath(file_path, &relative_path))
206 src_relative_paths.push_back(relative_path);
209 (new file_manager::ZipFileCreator(
210 base::Bind(&FileManagerPrivateZipSelectionFunction::OnZipDone, this),
213 dest_file))->Start();
217 void FileManagerPrivateZipSelectionFunction::OnZipDone(bool success) {
218 SetResult(new base::FundamentalValue(success));
222 bool FileManagerPrivateZoomFunction::RunSync() {
223 using extensions::api::file_manager_private::Zoom::Params;
224 const scoped_ptr<Params> params(Params::Create(*args_));
225 EXTENSION_FUNCTION_VALIDATE(params);
227 content::PageZoom zoom_type;
228 switch (params->operation) {
229 case api::file_manager_private::ZOOM_OPERATION_TYPE_IN:
230 zoom_type = content::PAGE_ZOOM_IN;
232 case api::file_manager_private::ZOOM_OPERATION_TYPE_OUT:
233 zoom_type = content::PAGE_ZOOM_OUT;
235 case api::file_manager_private::ZOOM_OPERATION_TYPE_RESET:
236 zoom_type = content::PAGE_ZOOM_RESET;
242 render_view_host()->Zoom(zoom_type);
246 bool FileManagerPrivateInstallWebstoreItemFunction::RunAsync() {
247 using extensions::api::file_manager_private::InstallWebstoreItem::Params;
248 const scoped_ptr<Params> params(Params::Create(*args_));
249 EXTENSION_FUNCTION_VALIDATE(params);
251 if (params->item_id.empty())
254 const extensions::WebstoreStandaloneInstaller::Callback callback =
256 &FileManagerPrivateInstallWebstoreItemFunction::OnInstallComplete,
259 // Only GoogleCastAPI extension can use silent installation.
260 if (params->silent_installation &&
261 params->item_id != kGoogleCastApiExtensionId) {
262 SetError("Only whitelisted items can do silent installation.");
266 scoped_refptr<file_manager::AppInstaller> installer(
267 new file_manager::AppInstaller(GetAssociatedWebContents(),
270 params->silent_installation,
272 // installer will be AddRef()'d in BeginInstall().
273 installer->BeginInstall();
277 void FileManagerPrivateInstallWebstoreItemFunction::OnInstallComplete(
279 const std::string& error,
280 extensions::webstore_install::Result result) {
281 drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
284 logger->Log(logging::LOG_INFO,
285 "App install succeeded. (item id: %s)",
286 webstore_item_id_.c_str());
290 logger->Log(logging::LOG_ERROR,
291 "App install failed. (item id: %s, reason: %s)",
292 webstore_item_id_.c_str(),
298 SendResponse(success);
301 FileManagerPrivateRequestWebStoreAccessTokenFunction::
302 FileManagerPrivateRequestWebStoreAccessTokenFunction() {
305 FileManagerPrivateRequestWebStoreAccessTokenFunction::
306 ~FileManagerPrivateRequestWebStoreAccessTokenFunction() {
309 bool FileManagerPrivateRequestWebStoreAccessTokenFunction::RunAsync() {
310 std::vector<std::string> scopes;
311 scopes.push_back(kCWSScope);
313 ProfileOAuth2TokenService* oauth_service =
314 ProfileOAuth2TokenServiceFactory::GetForProfile(GetProfile());
315 net::URLRequestContextGetter* url_request_context_getter =
316 g_browser_process->system_request_context();
318 if (!oauth_service) {
319 drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
321 logger->Log(logging::LOG_ERROR,
322 "CWS OAuth token fetch failed. OAuth2TokenService can't "
325 SetResult(base::Value::CreateNullValue());
329 SigninManagerBase* signin_manager =
330 SigninManagerFactory::GetForProfile(GetProfile());
331 auth_service_.reset(new google_apis::AuthService(
333 signin_manager->GetAuthenticatedAccountId(),
334 url_request_context_getter,
336 auth_service_->StartAuthentication(base::Bind(
337 &FileManagerPrivateRequestWebStoreAccessTokenFunction::
338 OnAccessTokenFetched,
344 void FileManagerPrivateRequestWebStoreAccessTokenFunction::OnAccessTokenFetched(
345 google_apis::GDataErrorCode code,
346 const std::string& access_token) {
347 drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
349 if (code == google_apis::HTTP_SUCCESS) {
350 DCHECK(auth_service_->HasAccessToken());
351 DCHECK(access_token == auth_service_->access_token());
353 logger->Log(logging::LOG_INFO, "CWS OAuth token fetch succeeded.");
354 SetResult(new base::StringValue(access_token));
358 logger->Log(logging::LOG_ERROR,
359 "CWS OAuth token fetch failed. (GDataErrorCode: %s)",
360 google_apis::GDataErrorCodeToString(code).c_str());
362 SetResult(base::Value::CreateNullValue());
367 bool FileManagerPrivateGetProfilesFunction::RunSync() {
368 #if defined(USE_ATHENA)
369 // TODO(oshima): Figure out what to do.
373 const std::vector<linked_ptr<api::file_manager_private::ProfileInfo> >&
374 profiles = GetLoggedInProfileInfoList();
376 // Obtains the display profile ID.
377 AppWindow* const app_window = GetCurrentAppWindow(this);
378 chrome::MultiUserWindowManager* const window_manager =
379 chrome::MultiUserWindowManager::GetInstance();
380 const std::string current_profile_id =
381 multi_user_util::GetUserIDFromProfile(GetProfile());
382 const std::string display_profile_id =
383 window_manager && app_window ? window_manager->GetUserPresentingWindow(
384 app_window->GetNativeWindow())
387 results_ = api::file_manager_private::GetProfiles::Results::Create(
390 display_profile_id.empty() ? current_profile_id : display_profile_id);
394 bool FileManagerPrivateVisitDesktopFunction::RunSync() {
395 using api::file_manager_private::VisitDesktop::Params;
396 const scoped_ptr<Params> params(Params::Create(*args_));
397 const std::vector<linked_ptr<api::file_manager_private::ProfileInfo> >&
398 profiles = GetLoggedInProfileInfoList();
400 chrome::MultiUserWindowManager* const window_manager =
401 chrome::MultiUserWindowManager::GetInstance();
402 DCHECK(window_manager);
404 // Check if the target user is logged-in or not.
405 bool logged_in = false;
406 for (size_t i = 0; i < profiles.size(); ++i) {
407 if (profiles[i]->profile_id == params->profile_id) {
413 SetError("The user is not logged-in now.");
417 // Look for the current app window.
418 AppWindow* const app_window = GetCurrentAppWindow(this);
420 SetError("Target window is not found.");
424 // Move the window to the user's desktop.
425 window_manager->ShowWindowForUser(app_window->GetNativeWindow(),
429 if (!window_manager->IsWindowOnDesktopOfUser(app_window->GetNativeWindow(),
430 params->profile_id)) {
431 SetError("The window cannot visit the desktop.");
438 bool FileManagerPrivateOpenInspectorFunction::RunSync() {
439 using extensions::api::file_manager_private::OpenInspector::Params;
440 const scoped_ptr<Params> params(Params::Create(*args_));
441 EXTENSION_FUNCTION_VALIDATE(params);
443 switch (params->type) {
444 case extensions::api::file_manager_private::INSPECTION_TYPE_NORMAL:
445 // Open inspector for foreground page.
446 DevToolsWindow::OpenDevToolsWindow(
447 content::WebContents::FromRenderViewHost(render_view_host()));
449 case extensions::api::file_manager_private::INSPECTION_TYPE_CONSOLE:
450 // Open inspector for foreground page and bring focus to the console.
451 DevToolsWindow::OpenDevToolsWindow(
452 content::WebContents::FromRenderViewHost(render_view_host()),
453 DevToolsToggleAction::ShowConsole());
455 case extensions::api::file_manager_private::INSPECTION_TYPE_ELEMENT:
456 // Open inspector for foreground page in inspect element mode.
457 DevToolsWindow::OpenDevToolsWindow(
458 content::WebContents::FromRenderViewHost(render_view_host()),
459 DevToolsToggleAction::Inspect());
461 case extensions::api::file_manager_private::INSPECTION_TYPE_BACKGROUND:
462 // Open inspector for background page.
463 extensions::devtools_util::InspectBackgroundPage(extension(),
469 base::StringPrintf("Unexpected inspection type(%d) is specified.",
470 static_cast<int>(params->type)));
476 } // namespace extensions