Upstream version 10.38.222.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / component_updater / component_patcher_operation.cc
index 6b86d9f..e522dd2 100644 (file)
@@ -4,23 +4,20 @@
 
 #include "chrome/browser/component_updater/component_patcher_operation.h"
 
-#include <string>
 #include <vector>
 
+#include "base/bind.h"
 #include "base/file_util.h"
 #include "base/files/memory_mapped_file.h"
-#include "base/json/json_file_value_serializer.h"
-#include "base/memory/scoped_handle.h"
-#include "base/path_service.h"
+#include "base/location.h"
 #include "base/strings/string_number_conversions.h"
 #include "chrome/browser/component_updater/component_patcher.h"
 #include "chrome/browser/component_updater/component_updater_service.h"
-#include "chrome/common/extensions/extension_constants.h"
+#include "courgette/courgette.h"
+#include "courgette/third_party/bsdiff.h"
 #include "crypto/secure_hash.h"
 #include "crypto/sha2.h"
 #include "crypto/signature_verifier.h"
-#include "extensions/common/crx_file.h"
-#include "third_party/zlib/google/zip.h"
 
 using crypto::SecureHash;
 
@@ -28,62 +25,83 @@ namespace component_updater {
 
 namespace {
 
-const char kInput[] = "input";
-const char kOp[] = "op";
 const char kOutput[] = "output";
-const char kPatch[] = "patch";
 const char kSha256[] = "sha256";
 
+// The integer offset disambiguates between overlapping error ranges.
+const int kCourgetteErrorOffset = 300;
+const int kBsdiffErrorOffset = 600;
+
 }  // namespace
 
-DeltaUpdateOp* CreateDeltaUpdateOp(base::DictionaryValue* command) {
-  std::string operation;
-  if (!command->GetString(kOp, &operation))
-    return NULL;
-  if (operation == "copy")
+const char kOp[] = "op";
+const char kBsdiff[] = "bsdiff";
+const char kCourgette[] = "courgette";
+const char kInput[] = "input";
+const char kPatch[] = "patch";
+
+DeltaUpdateOp* CreateDeltaUpdateOp(
+    const std::string& operation,
+    scoped_refptr<OutOfProcessPatcher> out_of_process_patcher) {
+  if (operation == "copy") {
     return new DeltaUpdateOpCopy();
-  else if (operation == "create")
+  } else if (operation == "create") {
     return new DeltaUpdateOpCreate();
-  else if (operation == "bsdiff")
-    return new DeltaUpdateOpPatchBsdiff();
-  else if (operation == "courgette")
-    return new DeltaUpdateOpPatchCourgette();
+  } else if (operation == "bsdiff" || operation == "courgette") {
+    return new DeltaUpdateOpPatch(operation, out_of_process_patcher);
+  }
   return NULL;
 }
 
-DeltaUpdateOp::DeltaUpdateOp() {}
+DeltaUpdateOp::DeltaUpdateOp() {
+}
 
-DeltaUpdateOp::~DeltaUpdateOp() {}
+DeltaUpdateOp::~DeltaUpdateOp() {
+}
 
-ComponentUnpacker::Error DeltaUpdateOp::Run(base::DictionaryValue* command_args,
-                                            const base::FilePath& input_dir,
-                                            const base::FilePath& unpack_dir,
-                                            ComponentPatcher* patcher,
-                                            ComponentInstaller* installer,
-                                            int* error) {
+void DeltaUpdateOp::Run(const base::DictionaryValue* command_args,
+                        const base::FilePath& input_dir,
+                        const base::FilePath& unpack_dir,
+                        ComponentInstaller* installer,
+                        const ComponentUnpacker::Callback& callback,
+                        scoped_refptr<base::SequencedTaskRunner> task_runner) {
+  callback_ = callback;
+  task_runner_ = task_runner;
   std::string output_rel_path;
   if (!command_args->GetString(kOutput, &output_rel_path) ||
-      !command_args->GetString(kSha256, &output_sha256_))
-    return ComponentUnpacker::kDeltaBadCommands;
+      !command_args->GetString(kSha256, &output_sha256_)) {
+    DoneRunning(ComponentUnpacker::kDeltaBadCommands, 0);
+    return;
+  }
 
-  output_abs_path_ = unpack_dir.Append(
-      base::FilePath::FromUTF8Unsafe(output_rel_path));
-  ComponentUnpacker::Error parse_result = DoParseArguments(
-      command_args, input_dir, installer);
-  if (parse_result != ComponentUnpacker::kNone)
-    return parse_result;
+  output_abs_path_ =
+      unpack_dir.Append(base::FilePath::FromUTF8Unsafe(output_rel_path));
+  ComponentUnpacker::Error parse_result =
+      DoParseArguments(command_args, input_dir, installer);
+  if (parse_result != ComponentUnpacker::kNone) {
+    DoneRunning(parse_result, 0);
+    return;
+  }
 
   const base::FilePath parent = output_abs_path_.DirName();
   if (!base::DirectoryExists(parent)) {
-    if (!base::CreateDirectory(parent))
-      return ComponentUnpacker::kIoError;
+    if (!base::CreateDirectory(parent)) {
+      DoneRunning(ComponentUnpacker::kIoError, 0);
+      return;
+    }
   }
 
-  ComponentUnpacker::Error run_result = DoRun(patcher, error);
-  if (run_result != ComponentUnpacker::kNone)
-    return run_result;
+  DoRun(base::Bind(&DeltaUpdateOp::DoneRunning,
+                   scoped_refptr<DeltaUpdateOp>(this)));
+}
 
-  return CheckHash();
+void DeltaUpdateOp::DoneRunning(ComponentUnpacker::Error error,
+                                int extended_error) {
+  if (error == ComponentUnpacker::kNone)
+    error = CheckHash();
+  task_runner_->PostTask(FROM_HERE,
+                         base::Bind(callback_, error, extended_error));
+  callback_.Reset();
 }
 
 // Uses the hash as a checksum to confirm that the file now residing in the
@@ -108,10 +126,18 @@ ComponentUnpacker::Error DeltaUpdateOp::CheckHash() {
   return ComponentUnpacker::kNone;
 }
 
-DeltaUpdateOpCopy::DeltaUpdateOpCopy() {}
+scoped_refptr<base::SequencedTaskRunner> DeltaUpdateOp::GetTaskRunner() {
+  return task_runner_;
+}
+
+DeltaUpdateOpCopy::DeltaUpdateOpCopy() {
+}
+
+DeltaUpdateOpCopy::~DeltaUpdateOpCopy() {
+}
 
 ComponentUnpacker::Error DeltaUpdateOpCopy::DoParseArguments(
-    base::DictionaryValue* command_args,
+    const base::DictionaryValue* command_args,
     const base::FilePath& input_dir,
     ComponentInstaller* installer) {
   std::string input_rel_path;
@@ -124,44 +150,52 @@ ComponentUnpacker::Error DeltaUpdateOpCopy::DoParseArguments(
   return ComponentUnpacker::kNone;
 }
 
-ComponentUnpacker::Error DeltaUpdateOpCopy::DoRun(ComponentPatcher*,
-                                                  int* error) {
-  *error = 0;
+void DeltaUpdateOpCopy::DoRun(const ComponentUnpacker::Callback& callback) {
   if (!base::CopyFile(input_abs_path_, output_abs_path_))
-    return ComponentUnpacker::kDeltaOperationFailure;
+    callback.Run(ComponentUnpacker::kDeltaOperationFailure, 0);
+  else
+    callback.Run(ComponentUnpacker::kNone, 0);
+}
 
-  return ComponentUnpacker::kNone;
+DeltaUpdateOpCreate::DeltaUpdateOpCreate() {
 }
 
-DeltaUpdateOpCreate::DeltaUpdateOpCreate() {}
+DeltaUpdateOpCreate::~DeltaUpdateOpCreate() {
+}
 
 ComponentUnpacker::Error DeltaUpdateOpCreate::DoParseArguments(
-    base::DictionaryValue* command_args,
+    const base::DictionaryValue* command_args,
     const base::FilePath& input_dir,
     ComponentInstaller* installer) {
   std::string patch_rel_path;
   if (!command_args->GetString(kPatch, &patch_rel_path))
     return ComponentUnpacker::kDeltaBadCommands;
 
-  patch_abs_path_ = input_dir.Append(
-      base::FilePath::FromUTF8Unsafe(patch_rel_path));
+  patch_abs_path_ =
+      input_dir.Append(base::FilePath::FromUTF8Unsafe(patch_rel_path));
 
   return ComponentUnpacker::kNone;
 }
 
-ComponentUnpacker::Error DeltaUpdateOpCreate::DoRun(ComponentPatcher*,
-                                                    int* error) {
-  *error = 0;
+void DeltaUpdateOpCreate::DoRun(const ComponentUnpacker::Callback& callback) {
   if (!base::Move(patch_abs_path_, output_abs_path_))
-    return ComponentUnpacker::kDeltaOperationFailure;
+    callback.Run(ComponentUnpacker::kDeltaOperationFailure, 0);
+  else
+    callback.Run(ComponentUnpacker::kNone, 0);
+}
 
-  return ComponentUnpacker::kNone;
+DeltaUpdateOpPatch::DeltaUpdateOpPatch(
+    const std::string& operation,
+    scoped_refptr<OutOfProcessPatcher> out_of_process_patcher)
+    : operation_(operation), out_of_process_patcher_(out_of_process_patcher) {
+  DCHECK(operation == kBsdiff || operation == kCourgette);
 }
 
-DeltaUpdateOpPatchBsdiff::DeltaUpdateOpPatchBsdiff() {}
+DeltaUpdateOpPatch::~DeltaUpdateOpPatch() {
+}
 
-ComponentUnpacker::Error DeltaUpdateOpPatchBsdiff::DoParseArguments(
-    base::DictionaryValue* command_args,
+ComponentUnpacker::Error DeltaUpdateOpPatch::DoParseArguments(
+    const base::DictionaryValue* command_args,
     const base::FilePath& input_dir,
     ComponentInstaller* installer) {
   std::string patch_rel_path;
@@ -173,53 +207,59 @@ ComponentUnpacker::Error DeltaUpdateOpPatchBsdiff::DoParseArguments(
   if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_))
     return ComponentUnpacker::kDeltaMissingExistingFile;
 
-  patch_abs_path_ = input_dir.Append(
-      base::FilePath::FromUTF8Unsafe(patch_rel_path));
+  patch_abs_path_ =
+      input_dir.Append(base::FilePath::FromUTF8Unsafe(patch_rel_path));
 
   return ComponentUnpacker::kNone;
 }
 
-ComponentUnpacker::Error DeltaUpdateOpPatchBsdiff::DoRun(
-    ComponentPatcher* patcher,
-    int* error) {
-  *error = 0;
-  return patcher->Patch(ComponentPatcher::kPatchTypeBsdiff,
-                        input_abs_path_,
-                        patch_abs_path_,
-                        output_abs_path_,
-                        error);
-}
-
-DeltaUpdateOpPatchCourgette::DeltaUpdateOpPatchCourgette() {}
-
-ComponentUnpacker::Error DeltaUpdateOpPatchCourgette::DoParseArguments(
-    base::DictionaryValue* command_args,
-    const base::FilePath& input_dir,
-    ComponentInstaller* installer) {
-  std::string patch_rel_path;
-  std::string input_rel_path;
-  if (!command_args->GetString(kPatch, &patch_rel_path) ||
-      !command_args->GetString(kInput, &input_rel_path))
-    return ComponentUnpacker::kDeltaBadCommands;
-
-  if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_))
-    return ComponentUnpacker::kDeltaMissingExistingFile;
-
-  patch_abs_path_ = input_dir.Append(
-      base::FilePath::FromUTF8Unsafe(patch_rel_path));
+void DeltaUpdateOpPatch::DoRun(const ComponentUnpacker::Callback& callback) {
+  if (out_of_process_patcher_.get()) {
+    out_of_process_patcher_->Patch(
+        operation_,
+        GetTaskRunner(),
+        input_abs_path_,
+        patch_abs_path_,
+        output_abs_path_,
+        base::Bind(&DeltaUpdateOpPatch::DonePatching, this, callback));
+    return;
+  }
 
-  return ComponentUnpacker::kNone;
+  if (operation_ == kBsdiff) {
+    DonePatching(callback,
+                 courgette::ApplyBinaryPatch(
+                     input_abs_path_, patch_abs_path_, output_abs_path_));
+  } else if (operation_ == kCourgette) {
+    DonePatching(
+        callback,
+        courgette::ApplyEnsemblePatch(input_abs_path_.value().c_str(),
+                                      patch_abs_path_.value().c_str(),
+                                      output_abs_path_.value().c_str()));
+  } else {
+    NOTREACHED();
+  }
 }
 
-ComponentUnpacker::Error DeltaUpdateOpPatchCourgette::DoRun(
-    ComponentPatcher* patcher,
-    int* error) {
-  *error = 0;
-  return patcher->Patch(ComponentPatcher::kPatchTypeCourgette,
-                        input_abs_path_,
-                        patch_abs_path_,
-                        output_abs_path_,
-                        error);
+void DeltaUpdateOpPatch::DonePatching(
+    const ComponentUnpacker::Callback& callback,
+    int result) {
+  if (operation_ == kBsdiff) {
+    if (result == courgette::OK) {
+      callback.Run(ComponentUnpacker::kNone, 0);
+    } else {
+      callback.Run(ComponentUnpacker::kDeltaOperationFailure,
+                   result + kBsdiffErrorOffset);
+    }
+  } else if (operation_ == kCourgette) {
+    if (result == courgette::C_OK) {
+      callback.Run(ComponentUnpacker::kNone, 0);
+    } else {
+      callback.Run(ComponentUnpacker::kDeltaOperationFailure,
+                   result + kCourgetteErrorOffset);
+    }
+  } else {
+    NOTREACHED();
+  }
 }
 
 }  // namespace component_updater