Kaydet (Commit) 22ef830a authored tarafından Mert Tümer's avatar Mert Tümer Kaydeden (comit) Thorsten Behrens

Added Storage permission handling on the Android Viewer

This patch prevents document browsing and creating
a new document from happening when write external
storage permission is denied by the user.
Signed-off-by: 's avatarMert Tümer <merttumer7@gmail.com>

Change-Id: Idf39a291a15a9dac023f4318329baed1baa90e14
Reviewed-on: https://gerrit.libreoffice.org/52868Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarThorsten Behrens <Thorsten.Behrens@CIB.de>
üst 9e1a58a5
...@@ -125,6 +125,7 @@ ...@@ -125,6 +125,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:clickable="true" android:clickable="true"
android:visibility="invisible"
app:backgroundTint="@color/background_normal" app:backgroundTint="@color/background_normal"
app:fabSize="normal" app:fabSize="normal"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
......
package org.libreoffice.storage.external; package org.libreoffice.storage.external;
import android.Manifest;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.pm.PackageManager;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Environment; import android.os.Environment;
...@@ -160,7 +162,7 @@ public class ExtsdDocumentsProvider implements IExternalDocumentProvider, ...@@ -160,7 +162,7 @@ public class ExtsdDocumentsProvider implements IExternalDocumentProvider,
// getExternalStorageState().equals(Environment.MEDIA_MOUNTED) && isExternalStorageRemovable() // getExternalStorageState().equals(Environment.MEDIA_MOUNTED) && isExternalStorageRemovable()
// but they refer to the primary external storage anyway, so what currently is covered by the // but they refer to the primary external storage anyway, so what currently is covered by the
// "LocalDocumentsProvider" // "LocalDocumentsProvider"
return rootPathURI!=null; return rootPathURI!=null && ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
} }
@Override @Override
......
...@@ -85,6 +85,6 @@ public class OTGDocumentsProvider implements IExternalDocumentProvider, ...@@ -85,6 +85,6 @@ public class OTGDocumentsProvider implements IExternalDocumentProvider,
@Override @Override
public boolean checkProviderAvailability(Context context) { public boolean checkProviderAvailability(Context context) {
// check if system supports USB Host // check if system supports USB Host
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_USB_HOST); return rootPathURI.length()>0 && context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_USB_HOST);
} }
} }
...@@ -71,6 +71,6 @@ public class LocalDocumentsDirectoryProvider extends LocalDocumentsProvider { ...@@ -71,6 +71,6 @@ public class LocalDocumentsDirectoryProvider extends LocalDocumentsProvider {
@Override @Override
public boolean checkProviderAvailability(Context context) { public boolean checkProviderAvailability(Context context) {
File documentsDirectory = getDocumentsDir(); File documentsDirectory = getDocumentsDir();
return documentsDirectory.exists() || ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; return documentsDirectory.exists() && ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
} }
} }
...@@ -16,8 +16,11 @@ import org.libreoffice.storage.IFile; ...@@ -16,8 +16,11 @@ import org.libreoffice.storage.IFile;
import org.libreoffice.R; import org.libreoffice.R;
import android.Manifest;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Environment; import android.os.Environment;
import android.support.v4.content.ContextCompat;
/** /**
* Implementation of IDocumentProvider for the local file system. * Implementation of IDocumentProvider for the local file system.
...@@ -52,6 +55,6 @@ public class LocalDocumentsProvider implements IDocumentProvider { ...@@ -52,6 +55,6 @@ public class LocalDocumentsProvider implements IDocumentProvider {
@Override @Override
public boolean checkProviderAvailability(Context context) { public boolean checkProviderAvailability(Context context) {
return true; return ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
} }
} }
...@@ -38,6 +38,7 @@ public class OwnCloudProvider implements IDocumentProvider, ...@@ -38,6 +38,7 @@ public class OwnCloudProvider implements IDocumentProvider,
private String serverUrl; private String serverUrl;
private String userName; private String userName;
private String password; private String password;
private RemoteOperationResult result;
public OwnCloudProvider(int id, Context context) { public OwnCloudProvider(int id, Context context) {
this.id = id; this.id = id;
...@@ -80,7 +81,7 @@ public class OwnCloudProvider implements IDocumentProvider, ...@@ -80,7 +81,7 @@ public class OwnCloudProvider implements IDocumentProvider,
public IFile createFromUri(Context context, URI uri) { public IFile createFromUri(Context context, URI uri) {
ReadRemoteFileOperation refreshOperation = new ReadRemoteFileOperation( ReadRemoteFileOperation refreshOperation = new ReadRemoteFileOperation(
uri.getPath()); uri.getPath());
RemoteOperationResult result = refreshOperation.execute(client); this.result = refreshOperation.execute(client);
if (!result.isSuccess()) { if (!result.isSuccess()) {
throw buildRuntimeExceptionForResultCode(result.getCode()); throw buildRuntimeExceptionForResultCode(result.getCode());
} }
...@@ -180,6 +181,6 @@ public class OwnCloudProvider implements IDocumentProvider, ...@@ -180,6 +181,6 @@ public class OwnCloudProvider implements IDocumentProvider,
@Override @Override
public boolean checkProviderAvailability(Context context) { public boolean checkProviderAvailability(Context context) {
return true; return result != null && this.result.isSuccess();
} }
} }
...@@ -65,6 +65,7 @@ import android.widget.TextView; ...@@ -65,6 +65,7 @@ import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import org.libreoffice.AboutDialogFragment; import org.libreoffice.AboutDialogFragment;
import org.libreoffice.LOKitShell;
import org.libreoffice.LibreOfficeMainActivity; import org.libreoffice.LibreOfficeMainActivity;
import org.libreoffice.R; import org.libreoffice.R;
import org.libreoffice.SettingsActivity; import org.libreoffice.SettingsActivity;
...@@ -95,7 +96,7 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings ...@@ -95,7 +96,7 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
private int sortMode; private int sortMode;
private boolean showHiddenFiles; private boolean showHiddenFiles;
// dynamic permissions IDs // dynamic permissions IDs
private static int PERMISSION_READ_EXTERNAL_STORAGE = 0; private static final int PERMISSION_READ_EXTERNAL_STORAGE = 0;
FileFilter fileFilter; FileFilter fileFilter;
FilenameFilter filenameFilter; FilenameFilter filenameFilter;
...@@ -166,16 +167,15 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings ...@@ -166,16 +167,15 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
registerReceiver(mUSBReceiver, filter); registerReceiver(mUSBReceiver, filter);
// init UI and populate with contents from the provider // init UI and populate with contents from the provider
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
// TODO: remove local document providers if really is denied, code right now assumes it is granted/
// there is no onRequestPermissionsResult evaluating the callback
// without the read permissions, LO could only load documents passed via intent from other apps
Log.i(LOGTAG, "no permission to read external storage - asking for permission"); Log.i(LOGTAG, "no permission to read external storage - asking for permission");
ActivityCompat.requestPermissions(this, ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
PERMISSION_READ_EXTERNAL_STORAGE); PERMISSION_READ_EXTERNAL_STORAGE);
} else {
switchToDocumentProvider(documentProviderFactory.getDefaultProvider());
setEditFABVisibility(View.VISIBLE);
} }
switchToDocumentProvider(documentProviderFactory.getDefaultProvider());
createUI(); createUI();
fabOpenAnimation = AnimationUtils.loadAnimation(this, R.anim.fab_open); fabOpenAnimation = AnimationUtils.loadAnimation(this, R.anim.fab_open);
fabCloseAnimation = AnimationUtils.loadAnimation(this, R.anim.fab_close); fabCloseAnimation = AnimationUtils.loadAnimation(this, R.anim.fab_close);
...@@ -215,6 +215,7 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings ...@@ -215,6 +215,7 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
final ArrayList<IFile> recentFiles = new ArrayList<IFile>(); final ArrayList<IFile> recentFiles = new ArrayList<IFile>();
for (String recentFileString : recentFileStrings) { for (String recentFileString : recentFileStrings) {
try { try {
if(documentProvider != null)
recentFiles.add(documentProvider.createFromUri(this, new URI(recentFileString))); recentFiles.add(documentProvider.createFromUri(this, new URI(recentFileString)));
} catch (URISyntaxException e) { } catch (URISyntaxException e) {
e.printStackTrace(); e.printStackTrace();
...@@ -347,7 +348,7 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings ...@@ -347,7 +348,7 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
private void refreshView() { private void refreshView() {
// enable home icon as "up" if required // enable home icon as "up" if required
if (!currentDirectory.equals(homeDirectory)) { if (currentDirectory != null && homeDirectory != null && !currentDirectory.equals(homeDirectory)) {
drawerToggle.setDrawerIndicatorEnabled(false); drawerToggle.setDrawerIndicatorEnabled(false);
} else { } else {
drawerToggle.setDrawerIndicatorEnabled(true); drawerToggle.setDrawerIndicatorEnabled(true);
...@@ -371,7 +372,7 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings ...@@ -371,7 +372,7 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
if (isFabMenuOpen) { if (isFabMenuOpen) {
collapseFabMenu(); collapseFabMenu();
} }
} else if (!currentDirectory.equals(homeDirectory)) { } else if (currentDirectory != null && homeDirectory != null && !currentDirectory.equals(homeDirectory)) {
// navigate upwards in directory hierarchy // navigate upwards in directory hierarchy
openParentDirectory(); openParentDirectory();
} else if (isFabMenuOpen) { } else if (isFabMenuOpen) {
...@@ -864,13 +865,18 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings ...@@ -864,13 +865,18 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
protected void onSaveInstanceState(Bundle outState) { protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
if(currentDirectory != null) {
outState.putString(CURRENT_DIRECTORY_KEY, currentDirectory.getUri().toString()); outState.putString(CURRENT_DIRECTORY_KEY, currentDirectory.getUri().toString());
Log.d(LOGTAG, currentDirectory.toString() + Integer.toString(filterMode) + Integer.toString(viewMode));
}
outState.putInt(FILTER_MODE_KEY, filterMode); outState.putInt(FILTER_MODE_KEY, filterMode);
outState.putInt(EXPLORER_VIEW_TYPE_KEY , viewMode); outState.putInt(EXPLORER_VIEW_TYPE_KEY , viewMode);
if(documentProvider != null)
outState.putInt(DOC_PROVIDER_KEY, documentProvider.getId()); outState.putInt(DOC_PROVIDER_KEY, documentProvider.getId());
outState.putBoolean(ENABLE_SHOW_HIDDEN_FILES_KEY , showHiddenFiles); outState.putBoolean(ENABLE_SHOW_HIDDEN_FILES_KEY , showHiddenFiles);
Log.d(LOGTAG, currentDirectory.toString() + Integer.toString(filterMode) + Integer.toString(viewMode));
//prefs.edit().putInt(EXPLORER_VIEW_TYPE, viewType).commit(); //prefs.edit().putInt(EXPLORER_VIEW_TYPE, viewType).commit();
Log.d(LOGTAG, "savedInstanceState"); Log.d(LOGTAG, "savedInstanceState");
} }
...@@ -1165,6 +1171,31 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings ...@@ -1165,6 +1171,31 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
} }
} }
} }
private void setEditFABVisibility(final int visibility){
LOKitShell.getMainHandler().post(new Runnable() {
@Override
public void run() {
editFAB.setVisibility(visibility);
}
});
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch(requestCode){
case PERMISSION_READ_EXTERNAL_STORAGE:
if(permissions.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
switchToDocumentProvider(documentProviderFactory.getDefaultProvider());
setEditFABVisibility(View.VISIBLE);
} else {
setEditFABVisibility(View.INVISIBLE);
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
} }
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
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