Exclude exe files while unzipping CRXes

BUG=468355

Review-Url: https://codereview.chromium.org/2321823002
Cr-Original-Commit-Position: refs/heads/master@{#417494}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: b040d3a050ac90bdae599ced55b2f8f7ac84bc30
diff --git a/google/zip.cc b/google/zip.cc
index f0180e5..31f0ace 100644
--- a/google/zip.cc
+++ b/google/zip.cc
@@ -94,6 +94,13 @@
 namespace zip {
 
 bool Unzip(const base::FilePath& src_file, const base::FilePath& dest_dir) {
+  return UnzipWithFilterCallback(src_file, dest_dir,
+                                 base::Bind(&ExcludeNoFilesFilter));
+}
+
+bool UnzipWithFilterCallback(const base::FilePath& src_file,
+                             const base::FilePath& dest_dir,
+                             const FilterCallback& filter_cb) {
   ZipReader reader;
   if (!reader.Open(src_file)) {
     DLOG(WARNING) << "Failed to open " << src_file.value();
@@ -109,11 +116,17 @@
                     << reader.current_entry_info()->file_path().value();
       return false;
     }
-    if (!reader.ExtractCurrentEntryIntoDirectory(dest_dir)) {
-      DLOG(WARNING) << "Failed to extract "
+    if (filter_cb.Run(reader.current_entry_info()->file_path())) {
+      if (!reader.ExtractCurrentEntryIntoDirectory(dest_dir)) {
+        DLOG(WARNING) << "Failed to extract "
+                      << reader.current_entry_info()->file_path().value();
+        return false;
+      }
+    } else {
+      DLOG(WARNING) << "Skipped file "
                     << reader.current_entry_info()->file_path().value();
-      return false;
     }
+
     if (!reader.AdvanceToNextEntry()) {
       DLOG(WARNING) << "Failed to advance to the next file";
       return false;
diff --git a/google/zip.h b/google/zip.h
index 3d20e59..61080c5 100644
--- a/google/zip.h
+++ b/google/zip.h
@@ -41,6 +41,14 @@
 #endif  // defined(OS_POSIX)
 
 // Unzip the contents of zip_file into dest_dir.
+// For each file in zip_file, include it only if the callback |filter_cb|
+// returns true. Otherwise omit it.
+typedef base::Callback<bool(const base::FilePath&)> FilterCallback;
+bool UnzipWithFilterCallback(const base::FilePath& zip_file,
+                             const base::FilePath& dest_dir,
+                             const FilterCallback& filter_cb);
+
+// Unzip the contents of zip_file into dest_dir.
 bool Unzip(const base::FilePath& zip_file, const base::FilePath& dest_dir);
 
 }  // namespace zip