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/drive_pref_names.h"
17 #include "chrome/browser/chromeos/drive/file_system_util.h"
18 #include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h"
19 #include "chrome/browser/chromeos/file_manager/fileapi_util.h"
20 #include "chrome/browser/chromeos/file_manager/volume_manager.h"
21 #include "chrome/browser/chromeos/file_manager/zip_file_creator.h"
22 #include "chrome/browser/chromeos/file_system_provider/mount_path_util.h"
23 #include "chrome/browser/chromeos/file_system_provider/service.h"
24 #include "chrome/browser/chromeos/profiles/profile_helper.h"
25 #include "chrome/browser/chromeos/settings/cros_settings.h"
26 #include "chrome/browser/devtools/devtools_window.h"
27 #include "chrome/browser/extensions/api/file_handlers/mime_util.h"
28 #include "chrome/browser/extensions/devtools_util.h"
29 #include "chrome/browser/lifetime/application_lifetime.h"
30 #include "chrome/browser/profiles/profile.h"
31 #include "chrome/browser/profiles/profile_manager.h"
32 #include "chrome/browser/profiles/profiles_state.h"
33 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
34 #include "chrome/browser/signin/signin_manager_factory.h"
35 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
36 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
37 #include "chrome/common/extensions/api/file_manager_private.h"
38 #include "chrome/common/extensions/api/file_manager_private_internal.h"
39 #include "chrome/common/extensions/api/manifest_types.h"
40 #include "chrome/common/pref_names.h"
41 #include "components/drive/event_logger.h"
42 #include "components/signin/core/browser/profile_oauth2_token_service.h"
43 #include "components/signin/core/browser/signin_manager.h"
44 #include "components/user_manager/user_manager.h"
45 #include "content/public/browser/render_view_host.h"
46 #include "content/public/browser/web_contents.h"
47 #include "content/public/common/page_zoom.h"
48 #include "extensions/browser/app_window/app_window.h"
49 #include "extensions/browser/app_window/app_window_registry.h"
50 #include "google_apis/drive/auth_service.h"
51 #include "ui/base/webui/web_ui_util.h"
54 namespace extensions
{
57 const char kCWSScope
[] = "https://www.googleapis.com/auth/chromewebstore";
59 // Obtains the current app window.
60 AppWindow
* GetCurrentAppWindow(ChromeSyncExtensionFunction
* function
) {
61 content::WebContents
* const contents
= function
->GetSenderWebContents();
63 AppWindowRegistry::Get(function
->GetProfile())->
64 GetAppWindowForWebContents(contents
) : nullptr;
67 std::vector
<linked_ptr
<api::file_manager_private::ProfileInfo
> >
68 GetLoggedInProfileInfoList() {
69 DCHECK(user_manager::UserManager::IsInitialized());
70 const std::vector
<Profile
*>& profiles
=
71 g_browser_process
->profile_manager()->GetLoadedProfiles();
72 std::set
<Profile
*> original_profiles
;
73 std::vector
<linked_ptr
<api::file_manager_private::ProfileInfo
> >
76 for (size_t i
= 0; i
< profiles
.size(); ++i
) {
77 // Filter the profile.
78 Profile
* const profile
= profiles
[i
]->GetOriginalProfile();
79 if (original_profiles
.count(profile
))
81 original_profiles
.insert(profile
);
82 const user_manager::User
* const user
=
83 chromeos::ProfileHelper::Get()->GetUserByProfile(profile
);
84 if (!user
|| !user
->is_logged_in())
87 // Make a ProfileInfo.
88 linked_ptr
<api::file_manager_private::ProfileInfo
> profile_info(
89 new api::file_manager_private::ProfileInfo());
90 profile_info
->profile_id
= multi_user_util::GetUserIDFromProfile(profile
);
91 profile_info
->display_name
= UTF16ToUTF8(user
->GetDisplayName());
92 // TODO(hirono): Remove the property from the profile_info.
93 profile_info
->is_current_profile
= true;
95 result_profiles
.push_back(profile_info
);
98 return result_profiles
;
102 bool FileManagerPrivateLogoutUserForReauthenticationFunction::RunSync() {
103 const user_manager::User
* user
=
104 chromeos::ProfileHelper::Get()->GetUserByProfile(GetProfile());
106 user_manager::UserManager::Get()->SaveUserOAuthStatus(
107 user
->email(), user_manager::User::OAUTH2_TOKEN_STATUS_INVALID
);
110 chrome::AttemptUserExit();
114 bool FileManagerPrivateGetPreferencesFunction::RunSync() {
115 api::file_manager_private::Preferences result
;
116 const PrefService
* const service
= GetProfile()->GetPrefs();
118 result
.drive_enabled
= drive::util::IsDriveEnabledForProfile(GetProfile());
119 result
.cellular_disabled
=
120 service
->GetBoolean(drive::prefs::kDisableDriveOverCellular
);
121 result
.hosted_files_disabled
=
122 service
->GetBoolean(drive::prefs::kDisableDriveHostedFiles
);
123 result
.search_suggest_enabled
=
124 service
->GetBoolean(prefs::kSearchSuggestEnabled
);
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;
133 SetResult(result
.ToValue().release());
135 drive::EventLogger
* logger
= file_manager::util::GetLogger(GetProfile());
137 logger
->Log(logging::LOG_INFO
, "%s succeeded.", name());
141 bool FileManagerPrivateSetPreferencesFunction::RunSync() {
142 using extensions::api::file_manager_private::SetPreferences::Params
;
143 const scoped_ptr
<Params
> params(Params::Create(*args_
));
144 EXTENSION_FUNCTION_VALIDATE(params
);
146 PrefService
* const service
= GetProfile()->GetPrefs();
148 if (params
->change_info
.cellular_disabled
)
149 service
->SetBoolean(drive::prefs::kDisableDriveOverCellular
,
150 *params
->change_info
.cellular_disabled
);
152 if (params
->change_info
.hosted_files_disabled
)
153 service
->SetBoolean(drive::prefs::kDisableDriveHostedFiles
,
154 *params
->change_info
.hosted_files_disabled
);
156 drive::EventLogger
* logger
= file_manager::util::GetLogger(GetProfile());
158 logger
->Log(logging::LOG_INFO
, "%s succeeded.", name());
162 FileManagerPrivateInternalZipSelectionFunction::
163 FileManagerPrivateInternalZipSelectionFunction() {}
165 FileManagerPrivateInternalZipSelectionFunction::
166 ~FileManagerPrivateInternalZipSelectionFunction() {}
168 bool FileManagerPrivateInternalZipSelectionFunction::RunAsync() {
169 using extensions::api::file_manager_private_internal::ZipSelection::Params
;
170 const scoped_ptr
<Params
> params(Params::Create(*args_
));
171 EXTENSION_FUNCTION_VALIDATE(params
);
173 // First param is the parent directory URL.
174 if (params
->parent_url
.empty())
177 base::FilePath src_dir
= file_manager::util::GetLocalPathFromURL(
178 render_frame_host(), GetProfile(), GURL(params
->parent_url
));
182 // Second param is the list of selected file URLs to be zipped.
183 if (params
->urls
.empty())
186 std::vector
<base::FilePath
> files
;
187 for (size_t i
= 0; i
< params
->urls
.size(); ++i
) {
188 base::FilePath path
= file_manager::util::GetLocalPathFromURL(
189 render_frame_host(), GetProfile(), GURL(params
->urls
[i
]));
192 files
.push_back(path
);
195 // Third param is the name of the output zip file.
196 if (params
->dest_name
.empty())
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
))
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
];
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
))
213 src_relative_paths
.push_back(relative_path
);
216 (new file_manager::ZipFileCreator(
217 base::Bind(&FileManagerPrivateInternalZipSelectionFunction::OnZipDone
,
219 src_dir
, src_relative_paths
, dest_file
))
224 void FileManagerPrivateInternalZipSelectionFunction::OnZipDone(bool success
) {
225 SetResult(new base::FundamentalValue(success
));
229 bool FileManagerPrivateZoomFunction::RunSync() {
230 using extensions::api::file_manager_private::Zoom::Params
;
231 const scoped_ptr
<Params
> params(Params::Create(*args_
));
232 EXTENSION_FUNCTION_VALIDATE(params
);
234 content::PageZoom zoom_type
;
235 switch (params
->operation
) {
236 case api::file_manager_private::ZOOM_OPERATION_TYPE_IN
:
237 zoom_type
= content::PAGE_ZOOM_IN
;
239 case api::file_manager_private::ZOOM_OPERATION_TYPE_OUT
:
240 zoom_type
= content::PAGE_ZOOM_OUT
;
242 case api::file_manager_private::ZOOM_OPERATION_TYPE_RESET
:
243 zoom_type
= content::PAGE_ZOOM_RESET
;
249 render_view_host_do_not_use()->Zoom(zoom_type
);
253 FileManagerPrivateRequestWebStoreAccessTokenFunction::
254 FileManagerPrivateRequestWebStoreAccessTokenFunction() {
257 FileManagerPrivateRequestWebStoreAccessTokenFunction::
258 ~FileManagerPrivateRequestWebStoreAccessTokenFunction() {
261 bool FileManagerPrivateRequestWebStoreAccessTokenFunction::RunAsync() {
262 std::vector
<std::string
> scopes
;
263 scopes
.push_back(kCWSScope
);
265 ProfileOAuth2TokenService
* oauth_service
=
266 ProfileOAuth2TokenServiceFactory::GetForProfile(GetProfile());
267 net::URLRequestContextGetter
* url_request_context_getter
=
268 g_browser_process
->system_request_context();
270 if (!oauth_service
) {
271 drive::EventLogger
* logger
= file_manager::util::GetLogger(GetProfile());
273 logger
->Log(logging::LOG_ERROR
,
274 "CWS OAuth token fetch failed. OAuth2TokenService can't "
277 SetResult(base::Value::CreateNullValue());
281 SigninManagerBase
* signin_manager
=
282 SigninManagerFactory::GetForProfile(GetProfile());
283 auth_service_
.reset(new google_apis::AuthService(
285 signin_manager
->GetAuthenticatedAccountId(),
286 url_request_context_getter
,
288 auth_service_
->StartAuthentication(base::Bind(
289 &FileManagerPrivateRequestWebStoreAccessTokenFunction::
290 OnAccessTokenFetched
,
296 void FileManagerPrivateRequestWebStoreAccessTokenFunction::OnAccessTokenFetched(
297 google_apis::DriveApiErrorCode code
,
298 const std::string
& access_token
) {
299 drive::EventLogger
* logger
= file_manager::util::GetLogger(GetProfile());
301 if (code
== google_apis::HTTP_SUCCESS
) {
302 DCHECK(auth_service_
->HasAccessToken());
303 DCHECK(access_token
== auth_service_
->access_token());
305 logger
->Log(logging::LOG_INFO
, "CWS OAuth token fetch succeeded.");
306 SetResult(new base::StringValue(access_token
));
310 logger
->Log(logging::LOG_ERROR
,
311 "CWS OAuth token fetch failed. (DriveApiErrorCode: %s)",
312 google_apis::DriveApiErrorCodeToString(code
).c_str());
314 SetResult(base::Value::CreateNullValue());
319 bool FileManagerPrivateGetProfilesFunction::RunSync() {
320 const std::vector
<linked_ptr
<api::file_manager_private::ProfileInfo
> >&
321 profiles
= GetLoggedInProfileInfoList();
323 // Obtains the display profile ID.
324 AppWindow
* const app_window
= GetCurrentAppWindow(this);
325 chrome::MultiUserWindowManager
* const window_manager
=
326 chrome::MultiUserWindowManager::GetInstance();
327 const std::string current_profile_id
=
328 multi_user_util::GetUserIDFromProfile(GetProfile());
329 const std::string display_profile_id
=
330 window_manager
&& app_window
? window_manager
->GetUserPresentingWindow(
331 app_window
->GetNativeWindow())
334 results_
= api::file_manager_private::GetProfiles::Results::Create(
337 display_profile_id
.empty() ? current_profile_id
: display_profile_id
);
341 bool FileManagerPrivateOpenInspectorFunction::RunSync() {
342 using extensions::api::file_manager_private::OpenInspector::Params
;
343 const scoped_ptr
<Params
> params(Params::Create(*args_
));
344 EXTENSION_FUNCTION_VALIDATE(params
);
346 switch (params
->type
) {
347 case extensions::api::file_manager_private::INSPECTION_TYPE_NORMAL
:
348 // Open inspector for foreground page.
349 DevToolsWindow::OpenDevToolsWindow(GetSenderWebContents());
351 case extensions::api::file_manager_private::INSPECTION_TYPE_CONSOLE
:
352 // Open inspector for foreground page and bring focus to the console.
353 DevToolsWindow::OpenDevToolsWindow(GetSenderWebContents(),
354 DevToolsToggleAction::ShowConsole());
356 case extensions::api::file_manager_private::INSPECTION_TYPE_ELEMENT
:
357 // Open inspector for foreground page in inspect element mode.
358 DevToolsWindow::OpenDevToolsWindow(GetSenderWebContents(),
359 DevToolsToggleAction::Inspect());
361 case extensions::api::file_manager_private::INSPECTION_TYPE_BACKGROUND
:
362 // Open inspector for background page.
363 extensions::devtools_util::InspectBackgroundPage(extension(),
369 base::StringPrintf("Unexpected inspection type(%d) is specified.",
370 static_cast<int>(params
->type
)));
376 FileManagerPrivateInternalGetMimeTypeFunction::
377 FileManagerPrivateInternalGetMimeTypeFunction() {
380 FileManagerPrivateInternalGetMimeTypeFunction::
381 ~FileManagerPrivateInternalGetMimeTypeFunction() {
384 bool FileManagerPrivateInternalGetMimeTypeFunction::RunAsync() {
385 using extensions::api::file_manager_private_internal::GetMimeType::Params
;
386 const scoped_ptr
<Params
> params(Params::Create(*args_
));
387 EXTENSION_FUNCTION_VALIDATE(params
);
389 // Convert file url to local path.
390 const scoped_refptr
<storage::FileSystemContext
> file_system_context
=
391 file_manager::util::GetFileSystemContextForRenderFrameHost(
392 GetProfile(), render_frame_host());
394 storage::FileSystemURL
file_system_url(
395 file_system_context
->CrackURL(GURL(params
->url
)));
397 app_file_handler_util::GetMimeTypeForLocalPath(
398 GetProfile(), file_system_url
.path(),
399 base::Bind(&FileManagerPrivateInternalGetMimeTypeFunction::OnGetMimeType
,
405 void FileManagerPrivateInternalGetMimeTypeFunction::OnGetMimeType(
406 const std::string
& mimeType
) {
407 SetResult(new base::StringValue(mimeType
));
411 ExtensionFunction::ResponseAction
412 FileManagerPrivateIsPiexLoaderEnabledFunction::Run() {
413 #if defined(OFFICIAL_BUILD)
414 return RespondNow(OneArgument(new base::FundamentalValue(true)));
416 return RespondNow(OneArgument(new base::FundamentalValue(false)));
420 FileManagerPrivateGetProvidingExtensionsFunction::
421 FileManagerPrivateGetProvidingExtensionsFunction()
422 : chrome_details_(this) {
425 ExtensionFunction::ResponseAction
426 FileManagerPrivateGetProvidingExtensionsFunction::Run() {
427 using chromeos::file_system_provider::Service
;
428 using chromeos::file_system_provider::ProvidingExtensionInfo
;
429 const Service
* const service
= Service::Get(chrome_details_
.GetProfile());
430 const std::vector
<ProvidingExtensionInfo
> info_list
=
431 service
->GetProvidingExtensionInfoList();
433 using api::file_manager_private::ProvidingExtension
;
434 std::vector
<linked_ptr
<ProvidingExtension
>> providing_extensions
;
435 for (const auto& info
: info_list
) {
436 const linked_ptr
<ProvidingExtension
> providing_extension(
437 new ProvidingExtension
);
438 providing_extension
->extension_id
= info
.extension_id
;
439 providing_extension
->name
= info
.name
;
440 providing_extension
->configurable
= info
.capabilities
.configurable();
441 providing_extension
->watchable
= info
.capabilities
.watchable();
442 providing_extension
->multiple_mounts
= info
.capabilities
.multiple_mounts();
443 switch (info
.capabilities
.source()) {
445 providing_extension
->source
=
446 api::manifest_types::FILE_SYSTEM_PROVIDER_SOURCE_FILE
;
449 providing_extension
->source
=
450 api::manifest_types::FILE_SYSTEM_PROVIDER_SOURCE_DEVICE
;
453 providing_extension
->source
=
454 api::manifest_types::FILE_SYSTEM_PROVIDER_SOURCE_NETWORK
;
457 providing_extensions
.push_back(providing_extension
);
460 return RespondNow(ArgumentList(
461 api::file_manager_private::GetProvidingExtensions::Results::Create(
462 providing_extensions
).Pass()));
465 FileManagerPrivateAddProvidedFileSystemFunction::
466 FileManagerPrivateAddProvidedFileSystemFunction()
467 : chrome_details_(this) {
470 ExtensionFunction::ResponseAction
471 FileManagerPrivateAddProvidedFileSystemFunction::Run() {
472 using extensions::api::file_manager_private::AddProvidedFileSystem::Params
;
473 const scoped_ptr
<Params
> params(Params::Create(*args_
));
474 EXTENSION_FUNCTION_VALIDATE(params
);
476 using chromeos::file_system_provider::Service
;
477 using chromeos::file_system_provider::ProvidingExtensionInfo
;
478 Service
* const service
= Service::Get(chrome_details_
.GetProfile());
480 if (!service
->RequestMount(params
->extension_id
))
481 return RespondNow(Error("Failed to request a new mount."));
483 return RespondNow(NoArguments());
486 FileManagerPrivateConfigureVolumeFunction::
487 FileManagerPrivateConfigureVolumeFunction()
488 : chrome_details_(this) {
491 ExtensionFunction::ResponseAction
492 FileManagerPrivateConfigureVolumeFunction::Run() {
493 using extensions::api::file_manager_private::ConfigureVolume::Params
;
494 const scoped_ptr
<Params
> params(Params::Create(*args_
));
495 EXTENSION_FUNCTION_VALIDATE(params
);
497 using file_manager::VolumeManager
;
498 using file_manager::Volume
;
499 VolumeManager
* const volume_manager
=
500 VolumeManager::Get(chrome_details_
.GetProfile());
501 base::WeakPtr
<Volume
> volume
=
502 volume_manager
->FindVolumeById(params
->volume_id
);
504 return RespondNow(Error("Volume not found."));
505 if (!volume
->configurable())
506 return RespondNow(Error("Volume not configurable."));
508 switch (volume
->type()) {
509 case file_manager::VOLUME_TYPE_PROVIDED
: {
510 using chromeos::file_system_provider::Service
;
511 Service
* const service
= Service::Get(chrome_details_
.GetProfile());
514 using chromeos::file_system_provider::ProvidedFileSystemInterface
;
515 ProvidedFileSystemInterface
* const file_system
=
516 service
->GetProvidedFileSystem(volume
->extension_id(),
517 volume
->file_system_id());
519 file_system
->Configure(base::Bind(
520 &FileManagerPrivateConfigureVolumeFunction::OnCompleted
, this));
527 return RespondLater();
530 void FileManagerPrivateConfigureVolumeFunction::OnCompleted(
531 base::File::Error result
) {
532 if (result
!= base::File::FILE_OK
) {
533 Respond(Error("Failed to complete configuration."));
537 Respond(NoArguments());
540 FileManagerPrivateInternalGetEntryActionsFunction::
541 FileManagerPrivateInternalGetEntryActionsFunction()
542 : chrome_details_(this) {
545 ExtensionFunction::ResponseAction
546 FileManagerPrivateInternalGetEntryActionsFunction::Run() {
547 using extensions::api::file_manager_private_internal::GetEntryActions::Params
;
548 const scoped_ptr
<Params
> params(Params::Create(*args_
));
549 EXTENSION_FUNCTION_VALIDATE(params
);
551 const scoped_refptr
<storage::FileSystemContext
> file_system_context
=
552 file_manager::util::GetFileSystemContextForRenderFrameHost(
553 chrome_details_
.GetProfile(), render_frame_host());
555 const storage::FileSystemURL
file_system_url(
556 file_system_context
->CrackURL(GURL(params
->url
)));
558 chromeos::file_system_provider::util::FileSystemURLParser
parser(
561 return RespondNow(Error("Related provided file system not found."));
563 parser
.file_system()->GetActions(
566 &FileManagerPrivateInternalGetEntryActionsFunction::OnCompleted
,
568 return RespondLater();
571 void FileManagerPrivateInternalGetEntryActionsFunction::OnCompleted(
572 const chromeos::file_system_provider::Actions
& actions
,
573 base::File::Error result
) {
574 if (result
!= base::File::FILE_OK
) {
575 Respond(Error("Failed to fetch actions."));
579 using api::file_system_provider::Action
;
580 std::vector
<linked_ptr
<Action
>> items
;
581 for (const auto& action
: actions
) {
582 const linked_ptr
<Action
> item(new Action
);
583 item
->id
= action
.id
;
584 item
->title
.reset(new std::string(action
.title
));
585 items
.push_back(item
);
588 Respond(ArgumentList(
589 api::file_manager_private_internal::GetEntryActions::Results::Create(
593 FileManagerPrivateInternalExecuteEntryActionFunction::
594 FileManagerPrivateInternalExecuteEntryActionFunction()
595 : chrome_details_(this) {
598 ExtensionFunction::ResponseAction
599 FileManagerPrivateInternalExecuteEntryActionFunction::Run() {
600 using extensions::api::file_manager_private_internal::ExecuteEntryAction::
602 const scoped_ptr
<Params
> params(Params::Create(*args_
));
603 EXTENSION_FUNCTION_VALIDATE(params
);
605 const scoped_refptr
<storage::FileSystemContext
> file_system_context
=
606 file_manager::util::GetFileSystemContextForRenderFrameHost(
607 chrome_details_
.GetProfile(), render_frame_host());
609 const storage::FileSystemURL
file_system_url(
610 file_system_context
->CrackURL(GURL(params
->url
)));
612 chromeos::file_system_provider::util::FileSystemURLParser
parser(
615 return RespondNow(Error("Related provided file system not found."));
617 parser
.file_system()->ExecuteAction(
618 parser
.file_path(), params
->action_id
,
620 &FileManagerPrivateInternalExecuteEntryActionFunction::OnCompleted
,
622 return RespondLater();
625 void FileManagerPrivateInternalExecuteEntryActionFunction::OnCompleted(
626 base::File::Error result
) {
627 if (result
!= base::File::FILE_OK
) {
628 Respond(Error("Failed to execute the action."));
632 Respond(NoArguments());
635 } // namespace extensions