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/fileapi_util.h"
17 #include "chrome/browser/chromeos/file_manager/volume_manager.h"
18 #include "chrome/browser/chromeos/file_manager/zip_file_creator.h"
19 #include "chrome/browser/chromeos/file_system_provider/service.h"
20 #include "chrome/browser/chromeos/profiles/profile_helper.h"
21 #include "chrome/browser/chromeos/settings/cros_settings.h"
22 #include "chrome/browser/devtools/devtools_window.h"
23 #include "chrome/browser/drive/event_logger.h"
24 #include "chrome/browser/extensions/api/file_handlers/mime_util.h"
25 #include "chrome/browser/extensions/devtools_util.h"
26 #include "chrome/browser/lifetime/application_lifetime.h"
27 #include "chrome/browser/profiles/profile.h"
28 #include "chrome/browser/profiles/profile_manager.h"
29 #include "chrome/browser/profiles/profiles_state.h"
30 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
31 #include "chrome/browser/signin/signin_manager_factory.h"
32 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
33 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
34 #include "chrome/common/extensions/api/file_manager_private.h"
35 #include "chrome/common/pref_names.h"
36 #include "components/signin/core/browser/profile_oauth2_token_service.h"
37 #include "components/signin/core/browser/signin_manager.h"
38 #include "components/user_manager/user_manager.h"
39 #include "content/public/browser/render_view_host.h"
40 #include "content/public/browser/web_contents.h"
41 #include "content/public/common/page_zoom.h"
42 #include "extensions/browser/app_window/app_window.h"
43 #include "extensions/browser/app_window/app_window_registry.h"
44 #include "google_apis/drive/auth_service.h"
45 #include "ui/base/webui/web_ui_util.h"
48 namespace extensions
{
51 const char kCWSScope
[] = "https://www.googleapis.com/auth/chromewebstore";
52 const char kGoogleCastApiExtensionId
[] = "mafeflapfdfljijmlienjedomfjfmhpd";
54 // Obtains the current app window.
55 AppWindow
* GetCurrentAppWindow(ChromeSyncExtensionFunction
* function
) {
56 AppWindowRegistry
* const app_window_registry
=
57 AppWindowRegistry::Get(function
->GetProfile());
58 content::WebContents
* const contents
= function
->GetAssociatedWebContents();
59 content::RenderViewHost
* const render_view_host
=
60 contents
? contents
->GetRenderViewHost() : NULL
;
61 return render_view_host
? app_window_registry
->GetAppWindowForRenderViewHost(
66 std::vector
<linked_ptr
<api::file_manager_private::ProfileInfo
> >
67 GetLoggedInProfileInfoList() {
68 DCHECK(user_manager::UserManager::IsInitialized());
69 const std::vector
<Profile
*>& profiles
=
70 g_browser_process
->profile_manager()->GetLoadedProfiles();
71 std::set
<Profile
*> original_profiles
;
72 std::vector
<linked_ptr
<api::file_manager_private::ProfileInfo
> >
75 for (size_t i
= 0; i
< profiles
.size(); ++i
) {
76 // Filter the profile.
77 Profile
* const profile
= profiles
[i
]->GetOriginalProfile();
78 if (original_profiles
.count(profile
))
80 original_profiles
.insert(profile
);
81 const user_manager::User
* const user
=
82 chromeos::ProfileHelper::Get()->GetUserByProfile(profile
);
83 if (!user
|| !user
->is_logged_in())
86 // Make a ProfileInfo.
87 linked_ptr
<api::file_manager_private::ProfileInfo
> profile_info(
88 new api::file_manager_private::ProfileInfo());
89 profile_info
->profile_id
= multi_user_util::GetUserIDFromProfile(profile
);
90 profile_info
->display_name
= UTF16ToUTF8(user
->GetDisplayName());
91 // TODO(hirono): Remove the property from the profile_info.
92 profile_info
->is_current_profile
= true;
94 result_profiles
.push_back(profile_info
);
97 return result_profiles
;
101 bool FileManagerPrivateLogoutUserForReauthenticationFunction::RunSync() {
102 const user_manager::User
* user
=
103 chromeos::ProfileHelper::Get()->GetUserByProfile(GetProfile());
105 user_manager::UserManager::Get()->SaveUserOAuthStatus(
106 user
->email(), user_manager::User::OAUTH2_TOKEN_STATUS_INVALID
);
109 chrome::AttemptUserExit();
113 bool FileManagerPrivateGetPreferencesFunction::RunSync() {
114 api::file_manager_private::Preferences result
;
115 const PrefService
* const service
= GetProfile()->GetPrefs();
117 result
.drive_enabled
= drive::util::IsDriveEnabledForProfile(GetProfile());
118 result
.cellular_disabled
=
119 service
->GetBoolean(prefs::kDisableDriveOverCellular
);
120 result
.hosted_files_disabled
=
121 service
->GetBoolean(prefs::kDisableDriveHostedFiles
);
122 result
.use24hour_clock
= service
->GetBoolean(prefs::kUse24HourClock
);
123 result
.allow_redeem_offers
= true;
124 if (!chromeos::CrosSettings::Get()->GetBoolean(
125 chromeos::kAllowRedeemChromeOsRegistrationOffers
,
126 &result
.allow_redeem_offers
)) {
127 result
.allow_redeem_offers
= true;
130 SetResult(result
.ToValue().release());
132 drive::EventLogger
* logger
= file_manager::util::GetLogger(GetProfile());
134 logger
->Log(logging::LOG_INFO
, "%s succeeded.", name());
138 bool FileManagerPrivateSetPreferencesFunction::RunSync() {
139 using extensions::api::file_manager_private::SetPreferences::Params
;
140 const scoped_ptr
<Params
> params(Params::Create(*args_
));
141 EXTENSION_FUNCTION_VALIDATE(params
);
143 PrefService
* const service
= GetProfile()->GetPrefs();
145 if (params
->change_info
.cellular_disabled
)
146 service
->SetBoolean(prefs::kDisableDriveOverCellular
,
147 *params
->change_info
.cellular_disabled
);
149 if (params
->change_info
.hosted_files_disabled
)
150 service
->SetBoolean(prefs::kDisableDriveHostedFiles
,
151 *params
->change_info
.hosted_files_disabled
);
153 drive::EventLogger
* logger
= file_manager::util::GetLogger(GetProfile());
155 logger
->Log(logging::LOG_INFO
, "%s succeeded.", name());
159 FileManagerPrivateZipSelectionFunction::
160 FileManagerPrivateZipSelectionFunction() {}
162 FileManagerPrivateZipSelectionFunction::
163 ~FileManagerPrivateZipSelectionFunction() {}
165 bool FileManagerPrivateZipSelectionFunction::RunAsync() {
166 using extensions::api::file_manager_private::ZipSelection::Params
;
167 const scoped_ptr
<Params
> params(Params::Create(*args_
));
168 EXTENSION_FUNCTION_VALIDATE(params
);
170 // First param is the source directory URL.
171 if (params
->dir_url
.empty())
174 base::FilePath src_dir
= file_manager::util::GetLocalPathFromURL(
175 render_view_host(), GetProfile(), GURL(params
->dir_url
));
179 // Second param is the list of selected file URLs.
180 if (params
->selection_urls
.empty())
183 std::vector
<base::FilePath
> files
;
184 for (size_t i
= 0; i
< params
->selection_urls
.size(); ++i
) {
185 base::FilePath path
= file_manager::util::GetLocalPathFromURL(
186 render_view_host(), GetProfile(), GURL(params
->selection_urls
[i
]));
189 files
.push_back(path
);
192 // Third param is the name of the output zip file.
193 if (params
->dest_name
.empty())
196 // Check if the dir path is under Drive mount point.
197 // TODO(hshi): support create zip file on Drive (crbug.com/158690).
198 if (drive::util::IsUnderDriveMountPoint(src_dir
))
201 base::FilePath dest_file
= src_dir
.Append(params
->dest_name
);
202 std::vector
<base::FilePath
> src_relative_paths
;
203 for (size_t i
= 0; i
!= files
.size(); ++i
) {
204 const base::FilePath
& file_path
= files
[i
];
206 // Obtain the relative path of |file_path| under |src_dir|.
207 base::FilePath relative_path
;
208 if (!src_dir
.AppendRelativePath(file_path
, &relative_path
))
210 src_relative_paths
.push_back(relative_path
);
213 (new file_manager::ZipFileCreator(
214 base::Bind(&FileManagerPrivateZipSelectionFunction::OnZipDone
, this),
217 dest_file
))->Start();
221 void FileManagerPrivateZipSelectionFunction::OnZipDone(bool success
) {
222 SetResult(new base::FundamentalValue(success
));
226 bool FileManagerPrivateZoomFunction::RunSync() {
227 using extensions::api::file_manager_private::Zoom::Params
;
228 const scoped_ptr
<Params
> params(Params::Create(*args_
));
229 EXTENSION_FUNCTION_VALIDATE(params
);
231 content::PageZoom zoom_type
;
232 switch (params
->operation
) {
233 case api::file_manager_private::ZOOM_OPERATION_TYPE_IN
:
234 zoom_type
= content::PAGE_ZOOM_IN
;
236 case api::file_manager_private::ZOOM_OPERATION_TYPE_OUT
:
237 zoom_type
= content::PAGE_ZOOM_OUT
;
239 case api::file_manager_private::ZOOM_OPERATION_TYPE_RESET
:
240 zoom_type
= content::PAGE_ZOOM_RESET
;
246 render_view_host()->Zoom(zoom_type
);
250 bool FileManagerPrivateInstallWebstoreItemFunction::RunAsync() {
251 using extensions::api::file_manager_private::InstallWebstoreItem::Params
;
252 const scoped_ptr
<Params
> params(Params::Create(*args_
));
253 EXTENSION_FUNCTION_VALIDATE(params
);
255 if (params
->item_id
.empty())
258 const extensions::WebstoreStandaloneInstaller::Callback callback
=
260 &FileManagerPrivateInstallWebstoreItemFunction::OnInstallComplete
,
263 // Only GoogleCastAPI extension can use silent installation.
264 if (params
->silent_installation
&&
265 params
->item_id
!= kGoogleCastApiExtensionId
) {
266 SetError("Only whitelisted items can do silent installation.");
270 scoped_refptr
<file_manager::AppInstaller
> installer(
271 new file_manager::AppInstaller(GetAssociatedWebContents(),
274 params
->silent_installation
,
276 // installer will be AddRef()'d in BeginInstall().
277 installer
->BeginInstall();
281 void FileManagerPrivateInstallWebstoreItemFunction::OnInstallComplete(
283 const std::string
& error
,
284 extensions::webstore_install::Result result
) {
285 drive::EventLogger
* logger
= file_manager::util::GetLogger(GetProfile());
288 logger
->Log(logging::LOG_INFO
,
289 "App install succeeded. (item id: %s)",
290 webstore_item_id_
.c_str());
294 logger
->Log(logging::LOG_ERROR
,
295 "App install failed. (item id: %s, reason: %s)",
296 webstore_item_id_
.c_str(),
302 SendResponse(success
);
305 FileManagerPrivateRequestWebStoreAccessTokenFunction::
306 FileManagerPrivateRequestWebStoreAccessTokenFunction() {
309 FileManagerPrivateRequestWebStoreAccessTokenFunction::
310 ~FileManagerPrivateRequestWebStoreAccessTokenFunction() {
313 bool FileManagerPrivateRequestWebStoreAccessTokenFunction::RunAsync() {
314 std::vector
<std::string
> scopes
;
315 scopes
.push_back(kCWSScope
);
317 ProfileOAuth2TokenService
* oauth_service
=
318 ProfileOAuth2TokenServiceFactory::GetForProfile(GetProfile());
319 net::URLRequestContextGetter
* url_request_context_getter
=
320 g_browser_process
->system_request_context();
322 if (!oauth_service
) {
323 drive::EventLogger
* logger
= file_manager::util::GetLogger(GetProfile());
325 logger
->Log(logging::LOG_ERROR
,
326 "CWS OAuth token fetch failed. OAuth2TokenService can't "
329 SetResult(base::Value::CreateNullValue());
333 SigninManagerBase
* signin_manager
=
334 SigninManagerFactory::GetForProfile(GetProfile());
335 auth_service_
.reset(new google_apis::AuthService(
337 signin_manager
->GetAuthenticatedAccountId(),
338 url_request_context_getter
,
340 auth_service_
->StartAuthentication(base::Bind(
341 &FileManagerPrivateRequestWebStoreAccessTokenFunction::
342 OnAccessTokenFetched
,
348 void FileManagerPrivateRequestWebStoreAccessTokenFunction::OnAccessTokenFetched(
349 google_apis::DriveApiErrorCode code
,
350 const std::string
& access_token
) {
351 drive::EventLogger
* logger
= file_manager::util::GetLogger(GetProfile());
353 if (code
== google_apis::HTTP_SUCCESS
) {
354 DCHECK(auth_service_
->HasAccessToken());
355 DCHECK(access_token
== auth_service_
->access_token());
357 logger
->Log(logging::LOG_INFO
, "CWS OAuth token fetch succeeded.");
358 SetResult(new base::StringValue(access_token
));
362 logger
->Log(logging::LOG_ERROR
,
363 "CWS OAuth token fetch failed. (DriveApiErrorCode: %s)",
364 google_apis::DriveApiErrorCodeToString(code
).c_str());
366 SetResult(base::Value::CreateNullValue());
371 bool FileManagerPrivateGetProfilesFunction::RunSync() {
372 const std::vector
<linked_ptr
<api::file_manager_private::ProfileInfo
> >&
373 profiles
= GetLoggedInProfileInfoList();
375 // Obtains the display profile ID.
376 AppWindow
* const app_window
= GetCurrentAppWindow(this);
377 chrome::MultiUserWindowManager
* const window_manager
=
378 chrome::MultiUserWindowManager::GetInstance();
379 const std::string current_profile_id
=
380 multi_user_util::GetUserIDFromProfile(GetProfile());
381 const std::string display_profile_id
=
382 window_manager
&& app_window
? window_manager
->GetUserPresentingWindow(
383 app_window
->GetNativeWindow())
386 results_
= api::file_manager_private::GetProfiles::Results::Create(
389 display_profile_id
.empty() ? current_profile_id
: display_profile_id
);
393 bool FileManagerPrivateOpenInspectorFunction::RunSync() {
394 using extensions::api::file_manager_private::OpenInspector::Params
;
395 const scoped_ptr
<Params
> params(Params::Create(*args_
));
396 EXTENSION_FUNCTION_VALIDATE(params
);
398 switch (params
->type
) {
399 case extensions::api::file_manager_private::INSPECTION_TYPE_NORMAL
:
400 // Open inspector for foreground page.
401 DevToolsWindow::OpenDevToolsWindow(
402 content::WebContents::FromRenderViewHost(render_view_host()));
404 case extensions::api::file_manager_private::INSPECTION_TYPE_CONSOLE
:
405 // Open inspector for foreground page and bring focus to the console.
406 DevToolsWindow::OpenDevToolsWindow(
407 content::WebContents::FromRenderViewHost(render_view_host()),
408 DevToolsToggleAction::ShowConsole());
410 case extensions::api::file_manager_private::INSPECTION_TYPE_ELEMENT
:
411 // Open inspector for foreground page in inspect element mode.
412 DevToolsWindow::OpenDevToolsWindow(
413 content::WebContents::FromRenderViewHost(render_view_host()),
414 DevToolsToggleAction::Inspect());
416 case extensions::api::file_manager_private::INSPECTION_TYPE_BACKGROUND
:
417 // Open inspector for background page.
418 extensions::devtools_util::InspectBackgroundPage(extension(),
424 base::StringPrintf("Unexpected inspection type(%d) is specified.",
425 static_cast<int>(params
->type
)));
431 FileManagerPrivateGetMimeTypeFunction::FileManagerPrivateGetMimeTypeFunction() {
434 FileManagerPrivateGetMimeTypeFunction::
435 ~FileManagerPrivateGetMimeTypeFunction() {
438 bool FileManagerPrivateGetMimeTypeFunction::RunAsync() {
439 using extensions::api::file_manager_private::GetMimeType::Params
;
440 const scoped_ptr
<Params
> params(Params::Create(*args_
));
441 EXTENSION_FUNCTION_VALIDATE(params
);
443 // Convert file url to local path.
444 const scoped_refptr
<storage::FileSystemContext
> file_system_context
=
445 file_manager::util::GetFileSystemContextForRenderViewHost(
446 GetProfile(), render_view_host());
448 const GURL
file_url(params
->file_url
);
449 storage::FileSystemURL
file_system_url(
450 file_system_context
->CrackURL(file_url
));
452 app_file_handler_util::GetMimeTypeForLocalPath(
453 GetProfile(), file_system_url
.path(),
454 base::Bind(&FileManagerPrivateGetMimeTypeFunction::OnGetMimeType
, this));
459 void FileManagerPrivateGetMimeTypeFunction::OnGetMimeType(
460 const std::string
& mimeType
) {
461 SetResult(new base::StringValue(mimeType
));
465 ExtensionFunction::ResponseAction
466 FileManagerPrivateIsPiexLoaderEnabledFunction::Run() {
467 #if defined(OFFICIAL_BUILD)
468 return RespondNow(OneArgument(new base::FundamentalValue(true)));
470 return RespondNow(OneArgument(new base::FundamentalValue(false)));
474 FileManagerPrivateGetProvidingExtensionsFunction::
475 FileManagerPrivateGetProvidingExtensionsFunction()
476 : chrome_details_(this) {
479 ExtensionFunction::ResponseAction
480 FileManagerPrivateGetProvidingExtensionsFunction::Run() {
481 using chromeos::file_system_provider::Service
;
482 using chromeos::file_system_provider::ProvidingExtensionInfo
;
483 const Service
* const service
= Service::Get(chrome_details_
.GetProfile());
484 const std::vector
<ProvidingExtensionInfo
> info_list
=
485 service
->GetProvidingExtensionInfoList();
487 using api::file_manager_private::ProvidingExtension
;
488 std::vector
<linked_ptr
<ProvidingExtension
>> providing_extensions
;
489 for (const auto& info
: info_list
) {
490 const linked_ptr
<ProvidingExtension
> providing_extension(
491 new ProvidingExtension
);
492 providing_extension
->extension_id
= info
.extension_id
;
493 providing_extension
->name
= info
.name
;
494 providing_extension
->can_configure
= info
.can_configure
;
495 providing_extension
->can_add
= info
.can_add
;
496 providing_extensions
.push_back(providing_extension
);
499 return RespondNow(ArgumentList(
500 api::file_manager_private::GetProvidingExtensions::Results::Create(
501 providing_extensions
).Pass()));
504 FileManagerPrivateAddProvidedFileSystemFunction::
505 FileManagerPrivateAddProvidedFileSystemFunction()
506 : chrome_details_(this) {
509 ExtensionFunction::ResponseAction
510 FileManagerPrivateAddProvidedFileSystemFunction::Run() {
511 using extensions::api::file_manager_private::AddProvidedFileSystem::Params
;
512 const scoped_ptr
<Params
> params(Params::Create(*args_
));
513 EXTENSION_FUNCTION_VALIDATE(params
);
515 using chromeos::file_system_provider::Service
;
516 using chromeos::file_system_provider::ProvidingExtensionInfo
;
517 Service
* const service
= Service::Get(chrome_details_
.GetProfile());
519 if (!service
->RequestMount(params
->extension_id
))
520 return RespondNow(Error("Failed to request a new mount."));
522 return RespondNow(NoArguments());
525 FileManagerPrivateConfigureProvidedFileSystemFunction::
526 FileManagerPrivateConfigureProvidedFileSystemFunction()
527 : chrome_details_(this) {
530 ExtensionFunction::ResponseAction
531 FileManagerPrivateConfigureProvidedFileSystemFunction::Run() {
532 using extensions::api::file_manager_private::ConfigureProvidedFileSystem::
534 const scoped_ptr
<Params
> params(Params::Create(*args_
));
535 EXTENSION_FUNCTION_VALIDATE(params
);
537 using file_manager::VolumeManager
;
538 using file_manager::Volume
;
539 VolumeManager
* const volume_manager
=
540 VolumeManager::Get(chrome_details_
.GetProfile());
541 LOG(ERROR
) << "LOOKING FOR: " << params
->volume_id
;
542 base::WeakPtr
<Volume
> volume
=
543 volume_manager
->FindVolumeById(params
->volume_id
);
545 return RespondNow(Error("Volume not found."));
547 using chromeos::file_system_provider::Service
;
548 Service
* const service
= Service::Get(chrome_details_
.GetProfile());
551 using chromeos::file_system_provider::ProvidedFileSystemInterface
;
552 ProvidedFileSystemInterface
* const file_system
=
553 service
->GetProvidedFileSystem(volume
->extension_id(),
554 volume
->file_system_id());
557 file_system
->Configure(base::Bind(
558 &FileManagerPrivateConfigureProvidedFileSystemFunction::OnCompleted
,
560 return RespondLater();
563 void FileManagerPrivateConfigureProvidedFileSystemFunction::OnCompleted(
564 base::File::Error result
) {
565 if (result
!= base::File::FILE_OK
) {
566 Respond(Error("Failed to complete configuration."));
570 Respond(NoArguments());
573 } // namespace extensions