Bug 1368971 - Restrict the scope for monitoring Screenshot folder to avoid infinite loop when saving as PDF r?sebastian draft
authorcnevinc <cnevinc@livemail.tw>
Thu, 01 Jun 2017 17:29:16 +0800
changeset 587570 8bbba48cdb60dfeedd1020a5e3e5ad2ed836b791
parent 587432 a8f378825e81daff1279a7d6e940b610912ee6dc
child 631313 c05b60a45720922ea3b9f693b7280ddb93ac42bc
push id61753
push userbmo:cnevinchen@gmail.com
push dateThu, 01 Jun 2017 09:32:12 +0000
reviewerssebastian
bugs1368971
milestone55.0a1
Bug 1368971 - Restrict the scope for monitoring Screenshot folder to avoid infinite loop when saving as PDF r?sebastian MozReview-Commit-ID: 6jSwmSW63Iq
mobile/android/base/java/org/mozilla/gecko/ScreenshotObserver.java
--- a/mobile/android/base/java/org/mozilla/gecko/ScreenshotObserver.java
+++ b/mobile/android/base/java/org/mozilla/gecko/ScreenshotObserver.java
@@ -10,21 +10,29 @@ import org.mozilla.gecko.permissions.Per
 import org.mozilla.gecko.util.ThreadUtils;
 
 import android.Manifest;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.Environment;
+import android.os.FileObserver;
 import android.provider.MediaStore;
 import android.util.Log;
 
+import java.io.File;
+
 public class ScreenshotObserver {
     private static final String LOGTAG = "GeckoScreenshotObserver";
+    private static final String SCREENSHOT_FOLDER = Environment.getExternalStorageDirectory()
+            + File.separator + Environment.DIRECTORY_PICTURES
+            + File.separator + "Screenshots" + File.separator;
+
     public Context context;
 
     /**
      * Listener for screenshot changes.
      */
     public interface OnScreenshotListener {
         /**
          * This callback is executed on the UI thread.
@@ -38,23 +46,16 @@ public class ScreenshotObserver {
     }
 
     public void setListener(Context context, OnScreenshotListener listener) {
         this.context = context;
         this.listener = listener;
     }
 
     private MediaObserver mediaObserver;
-    private String[] mediaProjections = new String[] {
-                    MediaStore.Images.ImageColumns.DATA,
-                    MediaStore.Images.ImageColumns.DISPLAY_NAME,
-                    MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
-                    MediaStore.Images.ImageColumns.DATE_TAKEN,
-                    MediaStore.Images.ImageColumns.TITLE
-    };
 
     /**
      * Start ScreenshotObserver if this device is supported and all required runtime permissions
      * have been granted by the user. Calling this method will not prompt for permissions.
      */
     public void start() {
         Permissions.from(context)
                    .withPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE)
@@ -64,83 +65,56 @@ public class ScreenshotObserver {
 
     private Runnable startObserverRunnable() {
         return new Runnable() {
             @Override
             public void run() {
                 try {
                     if (mediaObserver == null) {
                         mediaObserver = new MediaObserver();
-                        context.getContentResolver().registerContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, false, mediaObserver);
+                        mediaObserver.startWatching();
                     }
                 } catch (Exception e) {
                     Log.e(LOGTAG, "Failure to start watching media: ", e);
                 }
             }
         };
     }
 
     public void stop() {
         if (mediaObserver == null) {
             return;
         }
 
         try {
-            context.getContentResolver().unregisterContentObserver(mediaObserver);
+            mediaObserver.stopWatching();
             mediaObserver = null;
         } catch (Exception e) {
             Log.e(LOGTAG, "Failure to stop watching media: ", e);
         }
     }
 
-    public void onMediaChange(final Uri uri) {
-        // Make sure we are on not on the main thread.
-        final ContentResolver cr = context.getContentResolver();
-        ThreadUtils.postToBackgroundThread(new Runnable() {
-            @Override
-            public void run() {
-                // Find the most recent image added to the MediaStore and see if it's a screenshot.
-                final Cursor cursor = cr.query(uri, mediaProjections, null, null, MediaStore.Images.ImageColumns.DATE_ADDED + " DESC LIMIT 1");
-                try {
-                    if (cursor == null) {
-                        return;
-                    }
+    private void onMediaChange(final String path) {
+        final File file = new File(path);
+        final String data = Uri.fromFile(file).toString();
+        Log.i(LOGTAG, "data: " + data);
+        final String title = file.getName();
+        Log.i(LOGTAG, "title: " + title);
 
-                    while (cursor.moveToNext()) {
-                        String data = cursor.getString(0);
-                        Log.i(LOGTAG, "data: " + data);
-                        String display = cursor.getString(1);
-                        Log.i(LOGTAG, "display: " + display);
-                        String album = cursor.getString(2);
-                        Log.i(LOGTAG, "album: " + album);
-                        long date = cursor.getLong(3);
-                        String title = cursor.getString(4);
-                        Log.i(LOGTAG, "title: " + title);
-                        if (album != null && album.toLowerCase().contains("screenshot")) {
-                            if (listener != null) {
-                                listener.onScreenshotTaken(data, title);
-                                break;
-                            }
-                        }
-                    }
-                } catch (Exception e) {
-                    Log.e(LOGTAG, "Failure to process media change: ", e);
-                } finally {
-                    if (cursor != null) {
-                        cursor.close();
-                    }
-                }
-            }
-        });
+        if (listener != null) {
+            listener.onScreenshotTaken(data, title);
+        }
     }
 
-    private class MediaObserver extends ContentObserver {
-        public MediaObserver() {
-            super(null);
+    private class MediaObserver extends FileObserver {
+
+        MediaObserver() {
+            super(SCREENSHOT_FOLDER, FileObserver.CREATE);
         }
 
-        @Override
-        public void onChange(boolean selfChange) {
-            super.onChange(selfChange);
-            onMediaChange(MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
+        @Override public void onEvent(int event, String path) {
+            Log.i(LOGTAG, "SCREENSHOT_FOLDER changed with file : " + path);
+            if (path != null) {
+                onMediaChange(SCREENSHOT_FOLDER + path);
+            }
         }
     }
 }