Commit 822a249c authored by mtomasz@chromium.org's avatar mtomasz@chromium.org

[fsp] Fix crash because of calling net::GetMimeTypeFromFile on UI thread.

This patch fixes the issue by calling net::GetMimeTypeFromFile on the blocking
pool.

TEST=unit_tests: *FileHandlersMimeUtilTest*"
BUG=392072

Review URL: https://codereview.chromium.org/374063002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@282048 0039d316-1c4b-4281-b951-d872f2087c98
parent c005e795
...@@ -41,10 +41,18 @@ void SniffMimeType(const base::FilePath& local_path, std::string* result) { ...@@ -41,10 +41,18 @@ void SniffMimeType(const base::FilePath& local_path, std::string* result) {
} }
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
// Converts a result passed as a scoped pointer to a dereferenced value passed
// to |callback|.
void OnGetMimeTypeFromFileForNonNativeLocalPathCompleted(
scoped_ptr<std::string> mime_type,
const base::Callback<void(const std::string&)>& callback) {
callback.Run(*mime_type);
}
// Called when fetching MIME type for a non-native local path is completed. // Called when fetching MIME type for a non-native local path is completed.
// If |success| is false, then tries to guess the MIME type by looking at the // If |success| is false, then tries to guess the MIME type by looking at the
// file name. // file name.
void OnGetMimeTypeForNonNativeLocalPathCompleted( void OnGetMimeTypeFromMetadataForNonNativeLocalPathCompleted(
const base::FilePath& local_path, const base::FilePath& local_path,
const base::Callback<void(const std::string&)>& callback, const base::Callback<void(const std::string&)>& callback,
bool success, bool success,
...@@ -54,9 +62,19 @@ void OnGetMimeTypeForNonNativeLocalPathCompleted( ...@@ -54,9 +62,19 @@ void OnGetMimeTypeForNonNativeLocalPathCompleted(
return; return;
} }
std::string mime_type_from_extension; // MIME type not available with metadata, hence try to guess it from the
net::GetMimeTypeFromFile(local_path, &mime_type_from_extension); // file's extension.
callback.Run(mime_type_from_extension); scoped_ptr<std::string> mime_type_from_extension(new std::string);
std::string* const mime_type_from_extension_ptr =
mime_type_from_extension.get();
BrowserThread::PostBlockingPoolTaskAndReply(
FROM_HERE,
base::Bind(base::IgnoreResult(&net::GetMimeTypeFromFile),
local_path,
mime_type_from_extension_ptr),
base::Bind(&OnGetMimeTypeFromFileForNonNativeLocalPathCompleted,
base::Passed(&mime_type_from_extension),
callback));
} }
#endif #endif
...@@ -69,6 +87,29 @@ void OnSniffMimeTypeForNativeLocalPathCompleted( ...@@ -69,6 +87,29 @@ void OnSniffMimeTypeForNativeLocalPathCompleted(
} // namespace } // namespace
// Handles response of net::GetMimeTypeFromFile for native file systems. If
// MIME type is available, then forwards it to |callback|. Otherwise, fallbacks
// to sniffing.
void OnGetMimeTypeFromFileForNativeLocalPathCompleted(
const base::FilePath& local_path,
scoped_ptr<std::string> mime_type,
const base::Callback<void(const std::string&)>& callback) {
if (!mime_type->empty()) {
callback.Run(*mime_type);
return;
}
scoped_ptr<std::string> sniffed_mime_type(new std::string);
std::string* const sniffed_mime_type_ptr = sniffed_mime_type.get();
BrowserThread::PostBlockingPoolTaskAndReply(
FROM_HERE,
base::Bind(&SniffMimeType, local_path, sniffed_mime_type_ptr),
base::Bind(&OnSniffMimeTypeForNativeLocalPathCompleted,
base::Passed(&sniffed_mime_type),
callback));
}
// Fetches MIME type for a local path and returns it with a |callback|.
void GetMimeTypeForLocalPath( void GetMimeTypeForLocalPath(
Profile* profile, Profile* profile,
const base::FilePath& local_path, const base::FilePath& local_path,
...@@ -81,7 +122,7 @@ void GetMimeTypeForLocalPath( ...@@ -81,7 +122,7 @@ void GetMimeTypeForLocalPath(
file_manager::util::GetNonNativeLocalPathMimeType( file_manager::util::GetNonNativeLocalPathMimeType(
profile, profile,
local_path, local_path,
base::Bind(&OnGetMimeTypeForNonNativeLocalPathCompleted, base::Bind(&OnGetMimeTypeFromMetadataForNonNativeLocalPathCompleted,
local_path, local_path,
callback)); callback));
return; return;
...@@ -89,20 +130,19 @@ void GetMimeTypeForLocalPath( ...@@ -89,20 +130,19 @@ void GetMimeTypeForLocalPath(
#endif #endif
// For native local files, try to guess the mime from the extension. If // For native local files, try to guess the mime from the extension. If
// not availble, then try to sniff if. // not available, then try to sniff if.
std::string mime_type_from_extension; scoped_ptr<std::string> mime_type_from_extension(new std::string);
if (net::GetMimeTypeFromFile(local_path, &mime_type_from_extension)) { std::string* const mime_type_from_extension_ptr =
callback.Run(mime_type_from_extension); mime_type_from_extension.get();
} else { BrowserThread::PostBlockingPoolTaskAndReply(
scoped_ptr<std::string> sniffed_mime_type(new std::string); FROM_HERE,
std::string* sniffed_mime_type_ptr = sniffed_mime_type.get(); base::Bind(base::IgnoreResult(&net::GetMimeTypeFromFile),
BrowserThread::PostBlockingPoolTaskAndReply( local_path,
FROM_HERE, mime_type_from_extension_ptr),
base::Bind(&SniffMimeType, local_path, sniffed_mime_type_ptr), base::Bind(&OnGetMimeTypeFromFileForNativeLocalPathCompleted,
base::Bind(&OnSniffMimeTypeForNativeLocalPathCompleted, local_path,
base::Passed(&sniffed_mime_type), base::Passed(&mime_type_from_extension),
callback)); callback));
}
} }
MimeTypeCollector::MimeTypeCollector(Profile* profile) MimeTypeCollector::MimeTypeCollector(Profile* profile)
......
...@@ -76,6 +76,7 @@ TEST_F(FileHandlersMimeUtilTest, GetMimeTypeForLocalPath) { ...@@ -76,6 +76,7 @@ TEST_F(FileHandlersMimeUtilTest, GetMimeTypeForLocalPath) {
&profile_, &profile_,
base::FilePath::FromUTF8Unsafe(kJPEGExtensionFilePath), base::FilePath::FromUTF8Unsafe(kJPEGExtensionFilePath),
base::Bind(&OnMimeTypeResult, &result)); base::Bind(&OnMimeTypeResult, &result));
content::BrowserThread::GetBlockingPool()->FlushForTesting();
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
EXPECT_EQ("image/jpeg", result); EXPECT_EQ("image/jpeg", result);
} }
...@@ -86,6 +87,7 @@ TEST_F(FileHandlersMimeUtilTest, GetMimeTypeForLocalPath) { ...@@ -86,6 +87,7 @@ TEST_F(FileHandlersMimeUtilTest, GetMimeTypeForLocalPath) {
&profile_, &profile_,
base::FilePath::FromUTF8Unsafe(kJPEGExtensionUpperCaseFilePath), base::FilePath::FromUTF8Unsafe(kJPEGExtensionUpperCaseFilePath),
base::Bind(&OnMimeTypeResult, &result)); base::Bind(&OnMimeTypeResult, &result));
content::BrowserThread::GetBlockingPool()->FlushForTesting();
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
EXPECT_EQ("image/jpeg", result); EXPECT_EQ("image/jpeg", result);
} }
...@@ -95,8 +97,14 @@ TEST_F(FileHandlersMimeUtilTest, GetMimeTypeForLocalPath) { ...@@ -95,8 +97,14 @@ TEST_F(FileHandlersMimeUtilTest, GetMimeTypeForLocalPath) {
GetMimeTypeForLocalPath(&profile_, GetMimeTypeForLocalPath(&profile_,
html_mime_file_path_, html_mime_file_path_,
base::Bind(&OnMimeTypeResult, &result)); base::Bind(&OnMimeTypeResult, &result));
// Since there are two calls to the blocking pool, it has to be flushed
// twice.
content::BrowserThread::GetBlockingPool()->FlushForTesting(); content::BrowserThread::GetBlockingPool()->FlushForTesting();
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
content::BrowserThread::GetBlockingPool()->FlushForTesting();
base::RunLoop().RunUntilIdle();
EXPECT_EQ("text/html", result); EXPECT_EQ("text/html", result);
} }
} }
...@@ -117,8 +125,13 @@ TEST_F(FileHandlersMimeUtilTest, MimeTypeCollector_ForURLs) { ...@@ -117,8 +125,13 @@ TEST_F(FileHandlersMimeUtilTest, MimeTypeCollector_ForURLs) {
std::vector<std::string> result; std::vector<std::string> result;
collector.CollectForURLs(urls, base::Bind(&OnMimeTypesCollected, &result)); collector.CollectForURLs(urls, base::Bind(&OnMimeTypesCollected, &result));
content::BrowserThread::GetBlockingPool()->FlushForTesting(); // Each URL may do up to 2 calls to the blocking pool. Hence, we need to
base::RunLoop().RunUntilIdle(); // flush it at least 6 times. This is unelegant, but there seem to be no
// better way.
for (int i = 0; i < 6; ++i) {
content::BrowserThread::GetBlockingPool()->FlushForTesting();
base::RunLoop().RunUntilIdle();
}
ASSERT_EQ(3u, result.size()); ASSERT_EQ(3u, result.size());
EXPECT_EQ("image/jpeg", result[0]); EXPECT_EQ("image/jpeg", result[0]);
...@@ -139,8 +152,10 @@ TEST_F(FileHandlersMimeUtilTest, MimeTypeCollector_ForLocalPaths) { ...@@ -139,8 +152,10 @@ TEST_F(FileHandlersMimeUtilTest, MimeTypeCollector_ForLocalPaths) {
collector.CollectForLocalPaths(local_paths, collector.CollectForLocalPaths(local_paths,
base::Bind(&OnMimeTypesCollected, &result)); base::Bind(&OnMimeTypesCollected, &result));
content::BrowserThread::GetBlockingPool()->FlushForTesting(); for (int i = 0; i < 6; ++i) {
base::RunLoop().RunUntilIdle(); content::BrowserThread::GetBlockingPool()->FlushForTesting();
base::RunLoop().RunUntilIdle();
}
ASSERT_EQ(3u, result.size()); ASSERT_EQ(3u, result.size());
EXPECT_EQ("image/jpeg", result[0]); EXPECT_EQ("image/jpeg", result[0]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment