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/zip_file_creator.h"
18 #include "chrome/browser/chromeos/profiles/profile_helper.h"
19 #include "chrome/browser/chromeos/settings/cros_settings.h"
20 #include "chrome/browser/devtools/devtools_window.h"
21 #include "chrome/browser/drive/event_logger.h"
22 #include "chrome/browser/extensions/api/file_handlers/mime_util.h"
23 #include "chrome/browser/extensions/devtools_util.h"
24 #include "chrome/browser/lifetime/application_lifetime.h"
25 #include "chrome/browser/profiles/profile.h"
26 #include "chrome/browser/profiles/profile_manager.h"
27 #include "chrome/browser/profiles/profiles_state.h"
28 #include "chrome/browser/signin/profile_oauth2_token_service_factory.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_manager_private.h"
33 #include "chrome/common/pref_names.h"
34 #include "components/signin/core/browser/profile_oauth2_token_service.h"
35 #include "components/signin/core/browser/signin_manager.h"
36 #include "components/user_manager/user_manager.h"
37 #include "content/public/browser/render_view_host.h"
38 #include "content/public/browser/web_contents.h"
39 #include "content/public/common/page_zoom.h"
40 #include "extensions/browser/app_window/app_window.h"
41 #include "extensions/browser/app_window/app_window_registry.h"
42 #include "google_apis/drive/auth_service.h"
43 #include "ui/base/webui/web_ui_util.h"
46 namespace extensions
{
49 const char kCWSScope
[] = "https://www.googleapis.com/auth/chromewebstore";
50 const char kGoogleCastApiExtensionId
[] = "mafeflapfdfljijmlienjedomfjfmhpd";
52 // Obtains the current app window.
53 AppWindow
* GetCurrentAppWindow(ChromeSyncExtensionFunction
* function
) {
54 AppWindowRegistry
* const app_window_registry
=
55 AppWindowRegistry::Get(function
->GetProfile());
56 content::WebContents
* const contents
= function
->GetAssociatedWebContents();
57 content::RenderViewHost
* const render_view_host
=
58 contents
? contents
->GetRenderViewHost() : NULL
;
59 return render_view_host
? app_window_registry
->GetAppWindowForRenderViewHost(
64 std::vector
<linked_ptr
<api::file_manager_private::ProfileInfo
> >
65 GetLoggedInProfileInfoList() {
66 DCHECK(user_manager::UserManager::IsInitialized());
67 const std::vector
<Profile
*>& profiles
=
68 g_browser_process
->profile_manager()->GetLoadedProfiles();
69 std::set
<Profile
*> original_profiles
;
70 std::vector
<linked_ptr
<api::file_manager_private::ProfileInfo
> >
73 for (size_t i
= 0; i
< profiles
.size(); ++i
) {
74 // Filter the profile.
75 Profile
* const profile
= profiles
[i
]->GetOriginalProfile();
76 if (original_profiles
.count(profile
))
78 original_profiles
.insert(profile
);
79 const user_manager::User
* const user
=
80 chromeos::ProfileHelper::Get()->GetUserByProfile(profile
);
81 if (!user
|| !user
->is_logged_in())
84 // Make a ProfileInfo.
85 linked_ptr
<api::file_manager_private::ProfileInfo
> profile_info(
86 new api::file_manager_private::ProfileInfo());
87 profile_info
->profile_id
= multi_user_util::GetUserIDFromProfile(profile
);
88 profile_info
->display_name
= UTF16ToUTF8(user
->GetDisplayName());
89 // TODO(hirono): Remove the property from the profile_info.
90 profile_info
->is_current_profile
= true;
92 result_profiles
.push_back(profile_info
);
95 return result_profiles
;
99 bool FileManagerPrivateLogoutUserForReauthenticationFunction::RunSync() {
100 const user_manager::User
* user
=
101 chromeos::ProfileHelper::Get()->GetUserByProfile(GetProfile());
103 user_manager::UserManager::Get()->SaveUserOAuthStatus(
104 user
->email(), user_manager::User::OAUTH2_TOKEN_STATUS_INVALID
);
107 chrome::AttemptUserExit();
111 bool FileManagerPrivateGetPreferencesFunction::RunSync() {
112 api::file_manager_private::Preferences result
;
113 const PrefService
* const service
= GetProfile()->GetPrefs();
115 result
.drive_enabled
= drive::util::IsDriveEnabledForProfile(GetProfile());
116 result
.cellular_disabled
=
117 service
->GetBoolean(prefs::kDisableDriveOverCellular
);
118 result
.hosted_files_disabled
=
119 service
->GetBoolean(prefs::kDisableDriveHostedFiles
);
120 result
.use24hour_clock
= service
->GetBoolean(prefs::kUse24HourClock
);
121 result
.allow_redeem_offers
= true;
122 if (!chromeos::CrosSettings::Get()->GetBoolean(
123 chromeos::kAllowRedeemChromeOsRegistrationOffers
,
124 &result
.allow_redeem_offers
)) {
125 result
.allow_redeem_offers
= true;
128 SetResult(result
.ToValue().release());
130 drive::EventLogger
* logger
= file_manager::util::GetLogger(GetProfile());
132 logger
->Log(logging::LOG_INFO
, "%s succeeded.", name());
136 bool FileManagerPrivateSetPreferencesFunction::RunSync() {
137 using extensions::api::file_manager_private::SetPreferences::Params
;
138 const scoped_ptr
<Params
> params(Params::Create(*args_
));
139 EXTENSION_FUNCTION_VALIDATE(params
);
141 PrefService
* const service
= GetProfile()->GetPrefs();
143 if (params
->change_info
.cellular_disabled
)
144 service
->SetBoolean(prefs::kDisableDriveOverCellular
,
145 *params
->change_info
.cellular_disabled
);
147 if (params
->change_info
.hosted_files_disabled
)
148 service
->SetBoolean(prefs::kDisableDriveHostedFiles
,
149 *params
->change_info
.hosted_files_disabled
);
151 drive::EventLogger
* logger
= file_manager::util::GetLogger(GetProfile());
153 logger
->Log(logging::LOG_INFO
, "%s succeeded.", name());
157 FileManagerPrivateZipSelectionFunction::
158 FileManagerPrivateZipSelectionFunction() {}
160 FileManagerPrivateZipSelectionFunction::
161 ~FileManagerPrivateZipSelectionFunction() {}
163 bool FileManagerPrivateZipSelectionFunction::RunAsync() {
164 using extensions::api::file_manager_private::ZipSelection::Params
;
165 const scoped_ptr
<Params
> params(Params::Create(*args_
));
166 EXTENSION_FUNCTION_VALIDATE(params
);
168 // First param is the source directory URL.
169 if (params
->dir_url
.empty())
172 base::FilePath src_dir
= file_manager::util::GetLocalPathFromURL(
173 render_view_host(), GetProfile(), GURL(params
->dir_url
));
177 // Second param is the list of selected file URLs.
178 if (params
->selection_urls
.empty())
181 std::vector
<base::FilePath
> files
;
182 for (size_t i
= 0; i
< params
->selection_urls
.size(); ++i
) {
183 base::FilePath path
= file_manager::util::GetLocalPathFromURL(
184 render_view_host(), GetProfile(), GURL(params
->selection_urls
[i
]));
187 files
.push_back(path
);
190 // Third param is the name of the output zip file.
191 if (params
->dest_name
.empty())
194 // Check if the dir path is under Drive mount point.
195 // TODO(hshi): support create zip file on Drive (crbug.com/158690).
196 if (drive::util::IsUnderDriveMountPoint(src_dir
))
199 base::FilePath dest_file
= src_dir
.Append(params
->dest_name
);
200 std::vector
<base::FilePath
> src_relative_paths
;
201 for (size_t i
= 0; i
!= files
.size(); ++i
) {
202 const base::FilePath
& file_path
= files
[i
];
204 // Obtain the relative path of |file_path| under |src_dir|.
205 base::FilePath relative_path
;
206 if (!src_dir
.AppendRelativePath(file_path
, &relative_path
))
208 src_relative_paths
.push_back(relative_path
);
211 (new file_manager::ZipFileCreator(
212 base::Bind(&FileManagerPrivateZipSelectionFunction::OnZipDone
, this),
215 dest_file
))->Start();
219 void FileManagerPrivateZipSelectionFunction::OnZipDone(bool success
) {
220 SetResult(new base::FundamentalValue(success
));
224 bool FileManagerPrivateZoomFunction::RunSync() {
225 using extensions::api::file_manager_private::Zoom::Params
;
226 const scoped_ptr
<Params
> params(Params::Create(*args_
));
227 EXTENSION_FUNCTION_VALIDATE(params
);
229 content::PageZoom zoom_type
;
230 switch (params
->operation
) {
231 case api::file_manager_private::ZOOM_OPERATION_TYPE_IN
:
232 zoom_type
= content::PAGE_ZOOM_IN
;
234 case api::file_manager_private::ZOOM_OPERATION_TYPE_OUT
:
235 zoom_type
= content::PAGE_ZOOM_OUT
;
237 case api::file_manager_private::ZOOM_OPERATION_TYPE_RESET
:
238 zoom_type
= content::PAGE_ZOOM_RESET
;
244 render_view_host()->Zoom(zoom_type
);
248 bool FileManagerPrivateInstallWebstoreItemFunction::RunAsync() {
249 using extensions::api::file_manager_private::InstallWebstoreItem::Params
;
250 const scoped_ptr
<Params
> params(Params::Create(*args_
));
251 EXTENSION_FUNCTION_VALIDATE(params
);
253 if (params
->item_id
.empty())
256 const extensions::WebstoreStandaloneInstaller::Callback callback
=
258 &FileManagerPrivateInstallWebstoreItemFunction::OnInstallComplete
,
261 // Only GoogleCastAPI extension can use silent installation.
262 if (params
->silent_installation
&&
263 params
->item_id
!= kGoogleCastApiExtensionId
) {
264 SetError("Only whitelisted items can do silent installation.");
268 scoped_refptr
<file_manager::AppInstaller
> installer(
269 new file_manager::AppInstaller(GetAssociatedWebContents(),
272 params
->silent_installation
,
274 // installer will be AddRef()'d in BeginInstall().
275 installer
->BeginInstall();
279 void FileManagerPrivateInstallWebstoreItemFunction::OnInstallComplete(
281 const std::string
& error
,
282 extensions::webstore_install::Result result
) {
283 drive::EventLogger
* logger
= file_manager::util::GetLogger(GetProfile());
286 logger
->Log(logging::LOG_INFO
,
287 "App install succeeded. (item id: %s)",
288 webstore_item_id_
.c_str());
292 logger
->Log(logging::LOG_ERROR
,
293 "App install failed. (item id: %s, reason: %s)",
294 webstore_item_id_
.c_str(),
300 SendResponse(success
);
303 FileManagerPrivateRequestWebStoreAccessTokenFunction::
304 FileManagerPrivateRequestWebStoreAccessTokenFunction() {
307 FileManagerPrivateRequestWebStoreAccessTokenFunction::
308 ~FileManagerPrivateRequestWebStoreAccessTokenFunction() {
311 bool FileManagerPrivateRequestWebStoreAccessTokenFunction::RunAsync() {
312 std::vector
<std::string
> scopes
;
313 scopes
.push_back(kCWSScope
);
315 ProfileOAuth2TokenService
* oauth_service
=
316 ProfileOAuth2TokenServiceFactory::GetForProfile(GetProfile());
317 net::URLRequestContextGetter
* url_request_context_getter
=
318 g_browser_process
->system_request_context();
320 if (!oauth_service
) {
321 drive::EventLogger
* logger
= file_manager::util::GetLogger(GetProfile());
323 logger
->Log(logging::LOG_ERROR
,
324 "CWS OAuth token fetch failed. OAuth2TokenService can't "
327 SetResult(base::Value::CreateNullValue());
331 SigninManagerBase
* signin_manager
=
332 SigninManagerFactory::GetForProfile(GetProfile());
333 auth_service_
.reset(new google_apis::AuthService(
335 signin_manager
->GetAuthenticatedAccountId(),
336 url_request_context_getter
,
338 auth_service_
->StartAuthentication(base::Bind(
339 &FileManagerPrivateRequestWebStoreAccessTokenFunction::
340 OnAccessTokenFetched
,
346 void FileManagerPrivateRequestWebStoreAccessTokenFunction::OnAccessTokenFetched(
347 google_apis::DriveApiErrorCode code
,
348 const std::string
& access_token
) {
349 drive::EventLogger
* logger
= file_manager::util::GetLogger(GetProfile());
351 if (code
== google_apis::HTTP_SUCCESS
) {
352 DCHECK(auth_service_
->HasAccessToken());
353 DCHECK(access_token
== auth_service_
->access_token());
355 logger
->Log(logging::LOG_INFO
, "CWS OAuth token fetch succeeded.");
356 SetResult(new base::StringValue(access_token
));
360 logger
->Log(logging::LOG_ERROR
,
361 "CWS OAuth token fetch failed. (DriveApiErrorCode: %s)",
362 google_apis::DriveApiErrorCodeToString(code
).c_str());
364 SetResult(base::Value::CreateNullValue());
369 bool FileManagerPrivateGetProfilesFunction::RunSync() {
370 const std::vector
<linked_ptr
<api::file_manager_private::ProfileInfo
> >&
371 profiles
= GetLoggedInProfileInfoList();
373 // Obtains the display profile ID.
374 AppWindow
* const app_window
= GetCurrentAppWindow(this);
375 chrome::MultiUserWindowManager
* const window_manager
=
376 chrome::MultiUserWindowManager::GetInstance();
377 const std::string current_profile_id
=
378 multi_user_util::GetUserIDFromProfile(GetProfile());
379 const std::string display_profile_id
=
380 window_manager
&& app_window
? window_manager
->GetUserPresentingWindow(
381 app_window
->GetNativeWindow())
384 results_
= api::file_manager_private::GetProfiles::Results::Create(
387 display_profile_id
.empty() ? current_profile_id
: display_profile_id
);
391 bool FileManagerPrivateOpenInspectorFunction::RunSync() {
392 using extensions::api::file_manager_private::OpenInspector::Params
;
393 const scoped_ptr
<Params
> params(Params::Create(*args_
));
394 EXTENSION_FUNCTION_VALIDATE(params
);
396 switch (params
->type
) {
397 case extensions::api::file_manager_private::INSPECTION_TYPE_NORMAL
:
398 // Open inspector for foreground page.
399 DevToolsWindow::OpenDevToolsWindow(
400 content::WebContents::FromRenderViewHost(render_view_host()));
402 case extensions::api::file_manager_private::INSPECTION_TYPE_CONSOLE
:
403 // Open inspector for foreground page and bring focus to the console.
404 DevToolsWindow::OpenDevToolsWindow(
405 content::WebContents::FromRenderViewHost(render_view_host()),
406 DevToolsToggleAction::ShowConsole());
408 case extensions::api::file_manager_private::INSPECTION_TYPE_ELEMENT
:
409 // Open inspector for foreground page in inspect element mode.
410 DevToolsWindow::OpenDevToolsWindow(
411 content::WebContents::FromRenderViewHost(render_view_host()),
412 DevToolsToggleAction::Inspect());
414 case extensions::api::file_manager_private::INSPECTION_TYPE_BACKGROUND
:
415 // Open inspector for background page.
416 extensions::devtools_util::InspectBackgroundPage(extension(),
422 base::StringPrintf("Unexpected inspection type(%d) is specified.",
423 static_cast<int>(params
->type
)));
429 FileManagerPrivateGetMimeTypeFunction::FileManagerPrivateGetMimeTypeFunction() {
432 FileManagerPrivateGetMimeTypeFunction::
433 ~FileManagerPrivateGetMimeTypeFunction() {
436 bool FileManagerPrivateGetMimeTypeFunction::RunAsync() {
437 using extensions::api::file_manager_private::GetMimeType::Params
;
438 const scoped_ptr
<Params
> params(Params::Create(*args_
));
439 EXTENSION_FUNCTION_VALIDATE(params
);
441 // Convert file url to local path.
442 const scoped_refptr
<storage::FileSystemContext
> file_system_context
=
443 file_manager::util::GetFileSystemContextForRenderViewHost(
444 GetProfile(), render_view_host());
446 const GURL
file_url(params
->file_url
);
447 storage::FileSystemURL
file_system_url(
448 file_system_context
->CrackURL(file_url
));
450 app_file_handler_util::GetMimeTypeForLocalPath(
451 GetProfile(), file_system_url
.path(),
452 base::Bind(&FileManagerPrivateGetMimeTypeFunction::OnGetMimeType
, this));
457 void FileManagerPrivateGetMimeTypeFunction::OnGetMimeType(
458 const std::string
& mimeType
) {
459 SetResult(new base::StringValue(mimeType
));
463 ExtensionFunction::ResponseAction
464 FileManagerPrivateIsPiexLoaderEnabledFunction::Run() {
465 #if defined(OFFICIAL_BUILD)
466 return RespondNow(OneArgument(
467 new base::FundamentalValue(true)));
469 return RespondNow(OneArgument(
470 new base::FundamentalValue(false)));
474 } // namespace extensions