Skip to content

Commit

Permalink
Fix running some file formats from the Downloads folder
Browse files Browse the repository at this point in the history
Due to how we mount stuff, we need to be able to navigate one step up
from the executable, and then re-attach the executable filename. To
allow this, in content URIs, treat ':' as a directory separator for
navigation purposes.

End result, you can now download cube.elf from the website and run it directly
from Downloads without using a file manager to move it.
  • Loading branch information
hrydgard committed May 16, 2023
1 parent 07a96b8 commit 081bdb3
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 10 deletions.
36 changes: 30 additions & 6 deletions Common/File/AndroidContentURI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,16 @@ AndroidContentURI AndroidContentURI::WithRootFilePath(const std::string &filePat

AndroidContentURI AndroidContentURI::WithComponent(const std::string &filePath) {
AndroidContentURI uri = *this;
uri.file = uri.file + "/" + filePath;
if (uri.file.empty()) {
// Not sure what to do.
return uri;
}
if (uri.file.back() == ':') {
// Special case handling for Document URIs: Treat the ':' as a directory separator too (but preserved in the filename).
uri.file = uri.file + filePath;
} else {
uri.file = uri.file + "/" + filePath;
}
return uri;
}

Expand Down Expand Up @@ -94,10 +103,11 @@ AndroidContentURI AndroidContentURI::WithReplacedExtension(const std::string &ne
}

bool AndroidContentURI::CanNavigateUp() const {
if (root.empty()) {
return false;
if (IsTreeURI()) {
return file.size() > root.size();
} else {
return file.find(':') != std::string::npos && file.back() != ':';
}
return file.size() > root.size();
}

// Only goes downwards in hierarchies. No ".." will ever be generated.
Expand Down Expand Up @@ -138,6 +148,9 @@ std::string AndroidContentURI::GetLastPart() const {

if (!CanNavigateUp()) {
size_t colon = file.rfind(':');
if (file.back() == ':') {
return file;
}
if (colon == std::string::npos) {
return std::string();
}
Expand All @@ -146,7 +159,12 @@ std::string AndroidContentURI::GetLastPart() const {

size_t slash = file.rfind('/');
if (slash == std::string::npos) {
return std::string();
// ok, look for the final colon. If it's the last char, we would have been caught above in !CanNavigateUp.
size_t colon = file.rfind(':');
if (colon == std::string::npos) {
return std::string();
}
return file.substr(colon + 1);
}

std::string part = file.substr(slash + 1);
Expand All @@ -160,7 +178,13 @@ bool AndroidContentURI::NavigateUp() {

size_t slash = file.rfind('/');
if (slash == std::string::npos) {
return false;
// ok, look for the final colon.
size_t colon = file.rfind(':');
if (colon == std::string::npos) {
return false;
}
file = file.substr(0, colon + 1); // Note: we include the colon in these paths.
return true;
}

file = file.substr(0, slash);
Expand Down
4 changes: 4 additions & 0 deletions Common/File/AndroidContentURI.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,8 @@ class AndroidContentURI {
const std::string &RootPath() const {
return root.empty() ? file : root;
}

bool IsTreeURI() const {
return !root.empty();
}
};
14 changes: 10 additions & 4 deletions unittest/UnitTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -722,14 +722,20 @@ static bool TestAndroidContentURI() {
EXPECT_EQ_STR(diff, std::string("Tekken 6.iso"));

EXPECT_EQ_STR(fileURI.GetFileExtension(), std::string(".prx"));
EXPECT_FALSE(fileURI.CanNavigateUp());
EXPECT_TRUE(fileURI.CanNavigateUp()); // Can now virtually navigate up one step from these.

// These are annoying because they hide the actual filename, and we can't get at a parent folder,
// which confuses our elf loading.
// These are annoying because they hide the actual filename, and we can't get at a parent folder.
// Decided to handle the ':' as a directory separator for navigation purposes, which fixes the problem (though not the extension thing).
AndroidContentURI downloadURI;
EXPECT_TRUE(downloadURI.Parse(std::string(downloadURIString)));
EXPECT_EQ_STR(downloadURI.GetLastPart(), std::string("10000000006"));
EXPECT_FALSE(downloadURI.CanNavigateUp());
EXPECT_TRUE(downloadURI.CanNavigateUp());
EXPECT_TRUE(downloadURI.NavigateUp());
// While this is not an openable valid content URI, we can still get something that we can concatenate a filename on top of.
EXPECT_EQ_STR(downloadURI.ToString(), std::string("content://com.android.providers.downloads.documents/document/msf%3A"));
EXPECT_EQ_STR(downloadURI.GetLastPart(), std::string("msf:"));
downloadURI = downloadURI.WithComponent("myfile");
EXPECT_EQ_STR(downloadURI.ToString(), std::string("content://com.android.providers.downloads.documents/document/msf%3Amyfile"));
return true;
}

Expand Down

0 comments on commit 081bdb3

Please sign in to comment.