- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / installer / setup / archive_patch_helper.cc
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/installer/setup/archive_patch_helper.h"
6
7 #include "base/file_util.h"
8 #include "base/logging.h"
9 #include "chrome/installer/util/lzma_util.h"
10 #include "courgette/courgette.h"
11 #include "third_party/bspatch/mbspatch.h"
12
13 namespace installer {
14
15 ArchivePatchHelper::ArchivePatchHelper(const base::FilePath& working_directory,
16                                        const base::FilePath& compressed_archive,
17                                        const base::FilePath& patch_source,
18                                        const base::FilePath& target)
19     : working_directory_(working_directory),
20       compressed_archive_(compressed_archive),
21       patch_source_(patch_source),
22       target_(target) {}
23
24 ArchivePatchHelper::~ArchivePatchHelper() {}
25
26 // static
27 bool ArchivePatchHelper::UncompressAndPatch(
28     const base::FilePath& working_directory,
29     const base::FilePath& compressed_archive,
30     const base::FilePath& patch_source,
31     const base::FilePath& target) {
32   ArchivePatchHelper instance(working_directory, compressed_archive,
33                               patch_source, target);
34   return (instance.Uncompress(NULL) &&
35           (instance.EnsemblePatch() || instance.BinaryPatch()));
36 }
37
38 bool ArchivePatchHelper::Uncompress(base::FilePath* last_uncompressed_file) {
39   // The target shouldn't already exist.
40   DCHECK(!base::PathExists(target_));
41
42   // UnPackArchive takes care of logging.
43   string16 output_file;
44   int32 lzma_result = LzmaUtil::UnPackArchive(compressed_archive_.value(),
45                                               working_directory_.value(),
46                                               &output_file);
47   if (lzma_result != NO_ERROR)
48     return false;
49
50   last_uncompressed_file_ = base::FilePath(output_file);
51   if (last_uncompressed_file)
52     *last_uncompressed_file = last_uncompressed_file_;
53   return true;
54 }
55
56 bool ArchivePatchHelper::EnsemblePatch() {
57   if (last_uncompressed_file_.empty()) {
58     LOG(ERROR) << "No patch file found in compressed archive.";
59     return false;
60   }
61
62   courgette::Status result =
63       courgette::ApplyEnsemblePatch(patch_source_.value().c_str(),
64                                     last_uncompressed_file_.value().c_str(),
65                                     target_.value().c_str());
66   if (result == courgette::C_OK)
67     return true;
68
69   LOG(ERROR)
70       << "Failed to apply patch " << last_uncompressed_file_.value()
71       << " to file " << patch_source_.value()
72       << " and generating file " << target_.value()
73       << " using courgette. err=" << result;
74
75   // Ensure a partial output is not left behind.
76   base::DeleteFile(target_, false);
77
78   return false;
79 }
80
81 bool ArchivePatchHelper::BinaryPatch() {
82   if (last_uncompressed_file_.empty()) {
83     LOG(ERROR) << "No patch file found in compressed archive.";
84     return false;
85   }
86
87   int result = ApplyBinaryPatch(patch_source_.value().c_str(),
88                                 last_uncompressed_file_.value().c_str(),
89                                 target_.value().c_str());
90   if (result == OK)
91     return true;
92
93   LOG(ERROR)
94       << "Failed to apply patch " << last_uncompressed_file_.value()
95       << " to file " << patch_source_.value()
96       << " and generating file " << target_.value()
97       << " using bsdiff. err=" << result;
98
99   // Ensure a partial output is not left behind.
100   base::DeleteFile(target_, false);
101
102   return false;
103 }
104
105 }  // namespace installer