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"
10 #include "ash/frame/frame_util.h"
11 #include "base/files/file_path.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/chromeos/drive/file_system_util.h"
17 #include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h"
18 #include "chrome/browser/chromeos/file_manager/fileapi_util.h"
19 #include "chrome/browser/chromeos/file_manager/volume_manager.h"
20 #include "chrome/browser/chromeos/file_manager/zip_file_creator.h"
21 #include "chrome/browser/chromeos/file_system_provider/mount_path_util.h"
22 #include "chrome/browser/chromeos/file_system_provider/service.h"
23 #include "chrome/browser/chromeos/profiles/profile_helper.h"
24 #include "chrome/browser/chromeos/settings/cros_settings.h"
25 #include "chrome/browser/devtools/devtools_window.h"
26 #include "chrome/browser/extensions/api/file_handlers/mime_util.h"
27 #include "chrome/browser/extensions/devtools_util.h"
28 #include "chrome/browser/lifetime/application_lifetime.h"
29 #include "chrome/browser/profiles/profile.h"
30 #include "chrome/browser/profiles/profile_manager.h"
31 #include "chrome/browser/profiles/profiles_state.h"
32 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
33 #include "chrome/browser/signin/signin_manager_factory.h"
34 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
35 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
36 #include "chrome/common/extensions/api/file_manager_private.h"
37 #include "chrome/common/extensions/api/file_manager_private_internal.h"
38 #include "chrome/common/extensions/api/manifest_types.h"
39 #include "chrome/common/pref_names.h"
40 #include "chromeos/settings/timezone_settings.h"
41 #include "components/drive/drive_pref_names.h"
42 #include "components/drive/event_logger.h"
43 #include "components/signin/core/browser/profile_oauth2_token_service.h"
44 #include "components/signin/core/browser/signin_manager.h"
45 #include "components/user_manager/user_manager.h"
46 #include "content/public/browser/render_view_host.h"
47 #include "content/public/browser/web_contents.h"
48 #include "content/public/common/page_zoom.h"
49 #include "extensions/browser/app_window/app_window.h"
50 #include "extensions/browser/app_window/app_window_registry.h"
51 #include "google_apis/drive/auth_service.h"
52 #include "ui/base/webui/web_ui_util.h"
55 namespace extensions
{
58 const char kCWSScope
[] = "https://www.googleapis.com/auth/chromewebstore";
60 // Obtains the current app window.
61 AppWindow
* GetCurrentAppWindow(ChromeSyncExtensionFunction
* function
) {
62 content::WebContents
* const contents
= function
->GetSenderWebContents();
64 AppWindowRegistry::Get(function
->GetProfile())->
65 GetAppWindowForWebContents(contents
) : nullptr;
68 std::vector
<linked_ptr
<api::file_manager_private::ProfileInfo
> >
69 GetLoggedInProfileInfoList() {
70 DCHECK(user_manager::UserManager::IsInitialized());
71 const std::vector
<Profile
*>& profiles
=
72 g_browser_process
->profile_manager()->GetLoadedProfiles();
73 std::set
<Profile
*> original_profiles
;
74 std::vector
<linked_ptr
<api::file_manager_private::ProfileInfo
> >
77 for (size_t i
= 0; i
< profiles
.size(); ++i
) {
78 // Filter the profile.
79 Profile
* const profile
= profiles
[i
]->GetOriginalProfile();
80 if (original_profiles
.count(profile
))
82 original_profiles
.insert(profile
);
83 const user_manager::User
* const user
=
84 chromeos::ProfileHelper::Get()->GetUserByProfile(profile
);
85 if (!user
|| !user
->is_logged_in())
88 // Make a ProfileInfo.
89 linked_ptr
<api::file_manager_private::ProfileInfo
> profile_info(
90 new api::file_manager_private::ProfileInfo());
91 profile_info
->profile_id
= multi_user_util::GetUserIDFromProfile(profile
);
92 profile_info
->display_name
= UTF16ToUTF8(user
->GetDisplayName());
93 // TODO(hirono): Remove the property from the profile_info.
94 profile_info
->is_current_profile
= true;
96 result_profiles
.push_back(profile_info
);
99 return result_profiles
;
103 bool FileManagerPrivateLogoutUserForReauthenticationFunction::RunSync() {
104 const user_manager::User
* user
=
105 chromeos::ProfileHelper::Get()->GetUserByProfile(GetProfile());
107 user_manager::UserManager::Get()->SaveUserOAuthStatus(
108 user
->email(), user_manager::User::OAUTH2_TOKEN_STATUS_INVALID
);
111 chrome::AttemptUserExit();
115 bool FileManagerPrivateGetPreferencesFunction::RunSync() {
116 api::file_manager_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(drive::prefs::kDisableDriveOverCellular
);
122 result
.hosted_files_disabled
=
123 service
->GetBoolean(drive::prefs::kDisableDriveHostedFiles
);
124 result
.search_suggest_enabled
=
125 service
->GetBoolean(prefs::kSearchSuggestEnabled
);
126 result
.use24hour_clock
= service
->GetBoolean(prefs::kUse24HourClock
);
127 result
.allow_redeem_offers
= true;
128 if (!chromeos::CrosSettings::Get()->GetBoolean(
129 chromeos::kAllowRedeemChromeOsRegistrationOffers
,
130 &result
.allow_redeem_offers
)) {
131 result
.allow_redeem_offers
= true;
134 UTF16ToUTF8(chromeos::system::TimezoneSettings::GetInstance()
135 ->GetCurrentTimezoneID());
137 SetResult(result
.ToValue().release());
139 drive::EventLogger
* logger
= file_manager::util::GetLogger(GetProfile());
141 logger
->Log(logging::LOG_INFO
, "%s succeeded.", name());
145 bool FileManagerPrivateSetPreferencesFunction::RunSync() {
146 using extensions::api::file_manager_private::SetPreferences::Params
;
147 const scoped_ptr
<Params
> params(Params::Create(*args_
));
148 EXTENSION_FUNCTION_VALIDATE(params
);
150 PrefService
* const service
= GetProfile()->GetPrefs();
152 if (params
->change_info
.cellular_disabled
)
153 service
->SetBoolean(drive::prefs::kDisableDriveOverCellular
,
154 *params
->change_info
.cellular_disabled
);
156 if (params
->change_info
.hosted_files_disabled
)
157 service
->SetBoolean(drive::prefs::kDisableDriveHostedFiles
,
158 *params
->change_info
.hosted_files_disabled
);
160 drive::EventLogger
* logger
= file_manager::util::GetLogger(GetProfile());
162 logger
->Log(logging::LOG_INFO
, "%s succeeded.", name());
166 FileManagerPrivateInternalZipSelectionFunction::
167 FileManagerPrivateInternalZipSelectionFunction() {}
169 FileManagerPrivateInternalZipSelectionFunction::
170 ~FileManagerPrivateInternalZipSelectionFunction() {}
172 bool FileManagerPrivateInternalZipSelectionFunction::RunAsync() {
173 using extensions::api::file_manager_private_internal::ZipSelection::Params
;
174 const scoped_ptr
<Params
> params(Params::Create(*args_
));
175 EXTENSION_FUNCTION_VALIDATE(params
);
177 // First param is the parent directory URL.
178 if (params
->parent_url
.empty())
181 base::FilePath src_dir
= file_manager::util::GetLocalPathFromURL(
182 render_frame_host(), GetProfile(), GURL(params
->parent_url
));
186 // Second param is the list of selected file URLs to be zipped.
187 if (params
->urls
.empty())
190 std::vector
<base::FilePath
> files
;
191 for (size_t i
= 0; i
< params
->urls
.size(); ++i
) {
192 base::FilePath path
= file_manager::util::GetLocalPathFromURL(
193 render_frame_host(), GetProfile(), GURL(params
->urls
[i
]));
196 files
.push_back(path
);
199 // Third param is the name of the output zip file.
200 if (params
->dest_name
.empty())
203 // Check if the dir path is under Drive mount point.
204 // TODO(hshi): support create zip file on Drive (crbug.com/158690).
205 if (drive::util::IsUnderDriveMountPoint(src_dir
))
208 base::FilePath dest_file
= src_dir
.Append(params
->dest_name
);
209 std::vector
<base::FilePath
> src_relative_paths
;
210 for (size_t i
= 0; i
!= files
.size(); ++i
) {
211 const base::FilePath
& file_path
= files
[i
];
213 // Obtain the relative path of |file_path| under |src_dir|.
214 base::FilePath relative_path
;
215 if (!src_dir
.AppendRelativePath(file_path
, &relative_path
))
217 src_relative_paths
.push_back(relative_path
);
220 (new file_manager::ZipFileCreator(
221 base::Bind(&FileManagerPrivateInternalZipSelectionFunction::OnZipDone
,
223 src_dir
, src_relative_paths
, dest_file
))
228 void FileManagerPrivateInternalZipSelectionFunction::OnZipDone(bool success
) {
229 SetResult(new base::FundamentalValue(success
));
233 bool FileManagerPrivateZoomFunction::RunSync() {
234 using extensions::api::file_manager_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_manager_private::ZOOM_OPERATION_TYPE_IN
:
241 zoom_type
= content::PAGE_ZOOM_IN
;
243 case api::file_manager_private::ZOOM_OPERATION_TYPE_OUT
:
244 zoom_type
= content::PAGE_ZOOM_OUT
;
246 case api::file_manager_private::ZOOM_OPERATION_TYPE_RESET
:
247 zoom_type
= content::PAGE_ZOOM_RESET
;
253 render_view_host_do_not_use()->Zoom(zoom_type
);
257 FileManagerPrivateRequestWebStoreAccessTokenFunction::
258 FileManagerPrivateRequestWebStoreAccessTokenFunction() {
261 FileManagerPrivateRequestWebStoreAccessTokenFunction::
262 ~FileManagerPrivateRequestWebStoreAccessTokenFunction() {
265 bool FileManagerPrivateRequestWebStoreAccessTokenFunction::RunAsync() {
266 std::vector
<std::string
> scopes
;
267 scopes
.push_back(kCWSScope
);
269 ProfileOAuth2TokenService
* oauth_service
=
270 ProfileOAuth2TokenServiceFactory::GetForProfile(GetProfile());
271 net::URLRequestContextGetter
* url_request_context_getter
=
272 g_browser_process
->system_request_context();
274 if (!oauth_service
) {
275 drive::EventLogger
* logger
= file_manager::util::GetLogger(GetProfile());
277 logger
->Log(logging::LOG_ERROR
,
278 "CWS OAuth token fetch failed. OAuth2TokenService can't "
281 SetResult(base::Value::CreateNullValue());
285 SigninManagerBase
* signin_manager
=
286 SigninManagerFactory::GetForProfile(GetProfile());
287 auth_service_
.reset(new google_apis::AuthService(
289 signin_manager
->GetAuthenticatedAccountId(),
290 url_request_context_getter
,
292 auth_service_
->StartAuthentication(base::Bind(
293 &FileManagerPrivateRequestWebStoreAccessTokenFunction::
294 OnAccessTokenFetched
,
300 void FileManagerPrivateRequestWebStoreAccessTokenFunction::OnAccessTokenFetched(
301 google_apis::DriveApiErrorCode code
,
302 const std::string
& access_token
) {
303 drive::EventLogger
* logger
= file_manager::util::GetLogger(GetProfile());
305 if (code
== google_apis::HTTP_SUCCESS
) {
306 DCHECK(auth_service_
->HasAccessToken());
307 DCHECK(access_token
== auth_service_
->access_token());
309 logger
->Log(logging::LOG_INFO
, "CWS OAuth token fetch succeeded.");
310 SetResult(new base::StringValue(access_token
));
314 logger
->Log(logging::LOG_ERROR
,
315 "CWS OAuth token fetch failed. (DriveApiErrorCode: %s)",
316 google_apis::DriveApiErrorCodeToString(code
).c_str());
318 SetResult(base::Value::CreateNullValue());
323 bool FileManagerPrivateGetProfilesFunction::RunSync() {
324 const std::vector
<linked_ptr
<api::file_manager_private::ProfileInfo
> >&
325 profiles
= GetLoggedInProfileInfoList();
327 // Obtains the display profile ID.
328 AppWindow
* const app_window
= GetCurrentAppWindow(this);
329 chrome::MultiUserWindowManager
* const window_manager
=
330 chrome::MultiUserWindowManager::GetInstance();
331 const std::string current_profile_id
=
332 multi_user_util::GetUserIDFromProfile(GetProfile());
333 const std::string display_profile_id
=
334 window_manager
&& app_window
? window_manager
->GetUserPresentingWindow(
335 app_window
->GetNativeWindow())
338 results_
= api::file_manager_private::GetProfiles::Results::Create(
341 display_profile_id
.empty() ? current_profile_id
: display_profile_id
);
345 bool FileManagerPrivateOpenInspectorFunction::RunSync() {
346 using extensions::api::file_manager_private::OpenInspector::Params
;
347 const scoped_ptr
<Params
> params(Params::Create(*args_
));
348 EXTENSION_FUNCTION_VALIDATE(params
);
350 switch (params
->type
) {
351 case extensions::api::file_manager_private::INSPECTION_TYPE_NORMAL
:
352 // Open inspector for foreground page.
353 DevToolsWindow::OpenDevToolsWindow(GetSenderWebContents());
355 case extensions::api::file_manager_private::INSPECTION_TYPE_CONSOLE
:
356 // Open inspector for foreground page and bring focus to the console.
357 DevToolsWindow::OpenDevToolsWindow(GetSenderWebContents(),
358 DevToolsToggleAction::ShowConsole());
360 case extensions::api::file_manager_private::INSPECTION_TYPE_ELEMENT
:
361 // Open inspector for foreground page in inspect element mode.
362 DevToolsWindow::OpenDevToolsWindow(GetSenderWebContents(),
363 DevToolsToggleAction::Inspect());
365 case extensions::api::file_manager_private::INSPECTION_TYPE_BACKGROUND
:
366 // Open inspector for background page.
367 extensions::devtools_util::InspectBackgroundPage(extension(),
373 base::StringPrintf("Unexpected inspection type(%d) is specified.",
374 static_cast<int>(params
->type
)));
380 FileManagerPrivateInternalGetMimeTypeFunction::
381 FileManagerPrivateInternalGetMimeTypeFunction() {
384 FileManagerPrivateInternalGetMimeTypeFunction::
385 ~FileManagerPrivateInternalGetMimeTypeFunction() {
388 bool FileManagerPrivateInternalGetMimeTypeFunction::RunAsync() {
389 using extensions::api::file_manager_private_internal::GetMimeType::Params
;
390 const scoped_ptr
<Params
> params(Params::Create(*args_
));
391 EXTENSION_FUNCTION_VALIDATE(params
);
393 // Convert file url to local path.
394 const scoped_refptr
<storage::FileSystemContext
> file_system_context
=
395 file_manager::util::GetFileSystemContextForRenderFrameHost(
396 GetProfile(), render_frame_host());
398 storage::FileSystemURL
file_system_url(
399 file_system_context
->CrackURL(GURL(params
->url
)));
401 app_file_handler_util::GetMimeTypeForLocalPath(
402 GetProfile(), file_system_url
.path(),
403 base::Bind(&FileManagerPrivateInternalGetMimeTypeFunction::OnGetMimeType
,
409 void FileManagerPrivateInternalGetMimeTypeFunction::OnGetMimeType(
410 const std::string
& mimeType
) {
411 SetResult(new base::StringValue(mimeType
));
415 ExtensionFunction::ResponseAction
416 FileManagerPrivateIsPiexLoaderEnabledFunction::Run() {
417 #if defined(OFFICIAL_BUILD)
418 return RespondNow(OneArgument(new base::FundamentalValue(true)));
420 return RespondNow(OneArgument(new base::FundamentalValue(false)));
424 FileManagerPrivateGetProvidingExtensionsFunction::
425 FileManagerPrivateGetProvidingExtensionsFunction()
426 : chrome_details_(this) {
429 ExtensionFunction::ResponseAction
430 FileManagerPrivateGetProvidingExtensionsFunction::Run() {
431 using chromeos::file_system_provider::Service
;
432 using chromeos::file_system_provider::ProvidingExtensionInfo
;
433 const Service
* const service
= Service::Get(chrome_details_
.GetProfile());
434 const std::vector
<ProvidingExtensionInfo
> info_list
=
435 service
->GetProvidingExtensionInfoList();
437 using api::file_manager_private::ProvidingExtension
;
438 std::vector
<linked_ptr
<ProvidingExtension
>> providing_extensions
;
439 for (const auto& info
: info_list
) {
440 const linked_ptr
<ProvidingExtension
> providing_extension(
441 new ProvidingExtension
);
442 providing_extension
->extension_id
= info
.extension_id
;
443 providing_extension
->name
= info
.name
;
444 providing_extension
->configurable
= info
.capabilities
.configurable();
445 providing_extension
->watchable
= info
.capabilities
.watchable();
446 providing_extension
->multiple_mounts
= info
.capabilities
.multiple_mounts();
447 switch (info
.capabilities
.source()) {
449 providing_extension
->source
=
450 api::manifest_types::FILE_SYSTEM_PROVIDER_SOURCE_FILE
;
453 providing_extension
->source
=
454 api::manifest_types::FILE_SYSTEM_PROVIDER_SOURCE_DEVICE
;
457 providing_extension
->source
=
458 api::manifest_types::FILE_SYSTEM_PROVIDER_SOURCE_NETWORK
;
461 providing_extensions
.push_back(providing_extension
);
464 return RespondNow(ArgumentList(
465 api::file_manager_private::GetProvidingExtensions::Results::Create(
466 providing_extensions
).Pass()));
469 FileManagerPrivateAddProvidedFileSystemFunction::
470 FileManagerPrivateAddProvidedFileSystemFunction()
471 : chrome_details_(this) {
474 ExtensionFunction::ResponseAction
475 FileManagerPrivateAddProvidedFileSystemFunction::Run() {
476 using extensions::api::file_manager_private::AddProvidedFileSystem::Params
;
477 const scoped_ptr
<Params
> params(Params::Create(*args_
));
478 EXTENSION_FUNCTION_VALIDATE(params
);
480 using chromeos::file_system_provider::Service
;
481 using chromeos::file_system_provider::ProvidingExtensionInfo
;
482 Service
* const service
= Service::Get(chrome_details_
.GetProfile());
484 if (!service
->RequestMount(params
->extension_id
))
485 return RespondNow(Error("Failed to request a new mount."));
487 return RespondNow(NoArguments());
490 FileManagerPrivateConfigureVolumeFunction::
491 FileManagerPrivateConfigureVolumeFunction()
492 : chrome_details_(this) {
495 ExtensionFunction::ResponseAction
496 FileManagerPrivateConfigureVolumeFunction::Run() {
497 using extensions::api::file_manager_private::ConfigureVolume::Params
;
498 const scoped_ptr
<Params
> params(Params::Create(*args_
));
499 EXTENSION_FUNCTION_VALIDATE(params
);
501 using file_manager::VolumeManager
;
502 using file_manager::Volume
;
503 VolumeManager
* const volume_manager
=
504 VolumeManager::Get(chrome_details_
.GetProfile());
505 base::WeakPtr
<Volume
> volume
=
506 volume_manager
->FindVolumeById(params
->volume_id
);
508 return RespondNow(Error("Volume not found."));
509 if (!volume
->configurable())
510 return RespondNow(Error("Volume not configurable."));
512 switch (volume
->type()) {
513 case file_manager::VOLUME_TYPE_PROVIDED
: {
514 using chromeos::file_system_provider::Service
;
515 Service
* const service
= Service::Get(chrome_details_
.GetProfile());
518 using chromeos::file_system_provider::ProvidedFileSystemInterface
;
519 ProvidedFileSystemInterface
* const file_system
=
520 service
->GetProvidedFileSystem(volume
->extension_id(),
521 volume
->file_system_id());
523 file_system
->Configure(base::Bind(
524 &FileManagerPrivateConfigureVolumeFunction::OnCompleted
, this));
531 return RespondLater();
534 void FileManagerPrivateConfigureVolumeFunction::OnCompleted(
535 base::File::Error result
) {
536 if (result
!= base::File::FILE_OK
) {
537 Respond(Error("Failed to complete configuration."));
541 Respond(NoArguments());
544 FileManagerPrivateInternalGetEntryActionsFunction::
545 FileManagerPrivateInternalGetEntryActionsFunction()
546 : chrome_details_(this) {
549 ExtensionFunction::ResponseAction
550 FileManagerPrivateInternalGetEntryActionsFunction::Run() {
551 using extensions::api::file_manager_private_internal::GetEntryActions::Params
;
552 const scoped_ptr
<Params
> params(Params::Create(*args_
));
553 EXTENSION_FUNCTION_VALIDATE(params
);
555 const scoped_refptr
<storage::FileSystemContext
> file_system_context
=
556 file_manager::util::GetFileSystemContextForRenderFrameHost(
557 chrome_details_
.GetProfile(), render_frame_host());
559 const storage::FileSystemURL
file_system_url(
560 file_system_context
->CrackURL(GURL(params
->url
)));
562 chromeos::file_system_provider::util::FileSystemURLParser
parser(
565 return RespondNow(Error("Related provided file system not found."));
567 parser
.file_system()->GetActions(
570 &FileManagerPrivateInternalGetEntryActionsFunction::OnCompleted
,
572 return RespondLater();
575 void FileManagerPrivateInternalGetEntryActionsFunction::OnCompleted(
576 const chromeos::file_system_provider::Actions
& actions
,
577 base::File::Error result
) {
578 if (result
!= base::File::FILE_OK
) {
579 Respond(Error("Failed to fetch actions."));
583 using api::file_system_provider::Action
;
584 std::vector
<linked_ptr
<Action
>> items
;
585 for (const auto& action
: actions
) {
586 const linked_ptr
<Action
> item(new Action
);
587 item
->id
= action
.id
;
588 item
->title
.reset(new std::string(action
.title
));
589 items
.push_back(item
);
592 Respond(ArgumentList(
593 api::file_manager_private_internal::GetEntryActions::Results::Create(
597 FileManagerPrivateInternalExecuteEntryActionFunction::
598 FileManagerPrivateInternalExecuteEntryActionFunction()
599 : chrome_details_(this) {
602 ExtensionFunction::ResponseAction
603 FileManagerPrivateInternalExecuteEntryActionFunction::Run() {
604 using extensions::api::file_manager_private_internal::ExecuteEntryAction::
606 const scoped_ptr
<Params
> params(Params::Create(*args_
));
607 EXTENSION_FUNCTION_VALIDATE(params
);
609 const scoped_refptr
<storage::FileSystemContext
> file_system_context
=
610 file_manager::util::GetFileSystemContextForRenderFrameHost(
611 chrome_details_
.GetProfile(), render_frame_host());
613 const storage::FileSystemURL
file_system_url(
614 file_system_context
->CrackURL(GURL(params
->url
)));
616 chromeos::file_system_provider::util::FileSystemURLParser
parser(
619 return RespondNow(Error("Related provided file system not found."));
621 parser
.file_system()->ExecuteAction(
622 parser
.file_path(), params
->action_id
,
624 &FileManagerPrivateInternalExecuteEntryActionFunction::OnCompleted
,
626 return RespondLater();
629 void FileManagerPrivateInternalExecuteEntryActionFunction::OnCompleted(
630 base::File::Error result
) {
631 if (result
!= base::File::FILE_OK
) {
632 Respond(Error("Failed to execute the action."));
636 Respond(NoArguments());
639 } // namespace extensions