diff --git a/toolkit/crashreporter/client/Makefile.in b/toolkit/crashreporter/client/Makefile.in index 8ea229b96cca..414cb0ef1afc 100644 --- a/toolkit/crashreporter/client/Makefile.in +++ b/toolkit/crashreporter/client/Makefile.in @@ -64,7 +64,8 @@ OS_LIBS += $(call EXPAND_LIBNAME,comctl32 shell32 wininet shlwapi) MOZ_WINCONSOLE = 0 endif -ifeq ($(OS_ARCH),Darwin) +ifeq ($(OS_ARCH),Darwin +CPPSRCS += crashreporter_unix.cpp CMMSRCS += crashreporter_osx.mm OS_LIBS += -framework Cocoa LIBS += \ @@ -76,7 +77,7 @@ LOCAL_INCLUDES += -I$(srcdir) -I$(srcdir)/../google-breakpad/src/common/mac/ endif ifeq ($(OS_ARCH),Linux) -CPPSRCS += crashreporter_linux.cpp +CPPSRCS += crashreporter_linux.cpp crashreporter_unix.cpp LIBS += \ $(DEPTH)/toolkit/crashreporter/google-breakpad/src/common/linux/$(LIB_PREFIX)breakpad_linux_common_s.$(LIB_SUFFIX) \ $(NULL) @@ -88,7 +89,7 @@ FORCE_USE_PIC=1 endif ifeq ($(OS_ARCH),SunOS) -CPPSRCS += crashreporter_linux.cpp +CPPSRCS += crashreporter_linux.cpp crashreporter_unix.cpp LIBS += \ $(DEPTH)/toolkit/crashreporter/google-breakpad/src/common/solaris/$(LIB_PREFIX)breakpad_solaris_common_s.$(LIB_SUFFIX) \ $(NULL) diff --git a/toolkit/crashreporter/client/crashreporter.cpp b/toolkit/crashreporter/client/crashreporter.cpp index a4995d29850b..dc6b7fc36899 100644 --- a/toolkit/crashreporter/client/crashreporter.cpp +++ b/toolkit/crashreporter/client/crashreporter.cpp @@ -366,8 +366,17 @@ void DeleteDump() void SendCompleted(bool success, const string& serverResponse) { if (success) { - if (AddSubmittedReport(serverResponse)) + if (AddSubmittedReport(serverResponse)) { DeleteDump(); + } + else { + string directory = gDumpFile; + int slashpos = directory.find_last_of("/\\"); + if (slashpos < 2) + return; + directory.resize(slashpos); + UIPruneSavedDumps(directory); + } } } diff --git a/toolkit/crashreporter/client/crashreporter.h b/toolkit/crashreporter/client/crashreporter.h index c93380f4cd24..fc23985f43ef 100644 --- a/toolkit/crashreporter/client/crashreporter.h +++ b/toolkit/crashreporter/client/crashreporter.h @@ -103,6 +103,8 @@ namespace CrashReporter { void LogMessage(const std::string& message); void DeleteDump(); bool ShouldEnableSending(); + + static const unsigned int kSaveCount = 10; } //============================================================================= @@ -135,6 +137,7 @@ bool UIMoveFile(const std::string& oldfile, const std::string& newfile); bool UIDeleteFile(const std::string& oldfile); std::ifstream* UIOpenRead(const std::string& filename); std::ofstream* UIOpenWrite(const std::string& filename, bool append=false); +void UIPruneSavedDumps(const std::string& directory); #ifdef _MSC_VER # pragma warning( pop ) diff --git a/toolkit/crashreporter/client/crashreporter_unix.cpp b/toolkit/crashreporter/client/crashreporter_unix.cpp new file mode 100644 index 000000000000..aef2d5ae93be --- /dev/null +++ b/toolkit/crashreporter/client/crashreporter_unix.cpp @@ -0,0 +1,102 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla platform. + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation . + * + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Benjamin Smedberg + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "crashreporter.h" + +#include +#include +#include +#include + +using namespace CrashReporter; +using std::string; +using std::vector; + +struct FileData +{ + time_t timestamp; + string path; +}; + +static bool CompareFDTime(const FileData& fd1, const FileData& fd2) +{ + return fd1.timestamp > fd2.timestamp; +} + +void UIPruneSavedDumps(const std::string& directory) +{ + DIR *dirfd = opendir(directory.c_str()); + if (!dirfd) + return; + + vector dumpfiles; + + while (dirent *dir = readdir(dirfd)) { + FileData fd; + fd.path = directory + '/' + dir->d_name; + if (fd.path.size() < 5) + continue; + + if (fd.path.compare(fd.path.size() - 4, 4, ".dmp") != 0) + continue; + + struct stat st; + if (stat(fd.path.c_str(), &st)) { + closedir(dirfd); + return; + } + + fd.timestamp = st.st_mtime; + + dumpfiles.push_back(fd); + } + + sort(dumpfiles.begin(), dumpfiles.end(), CompareFDTime); + + while (dumpfiles.size() > kSaveCount) { + // get the path of the oldest file + string path = (--dumpfiles.end())->path; + UIDeleteFile(path.c_str()); + + // s/.dmp/.extra/ + path.replace(path.size() - 4, 4, ".extra"); + UIDeleteFile(path.c_str()); + + dumpfiles.pop_back(); + } +} diff --git a/toolkit/crashreporter/client/crashreporter_win.cpp b/toolkit/crashreporter/client/crashreporter_win.cpp index 1fe185090ad5..e71a71402d50 100644 --- a/toolkit/crashreporter/client/crashreporter_win.cpp +++ b/toolkit/crashreporter/client/crashreporter_win.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include "resource.h" #include "client/windows/sender/crash_report_sender.h" #include "common/windows/string_utils-inl.h" @@ -1420,3 +1421,46 @@ ofstream* UIOpenWrite(const string& filename, bool append) // append=false return file; } + +struct FileData +{ + FILETIME timestamp; + wstring path; +}; + +static bool CompareFDTime(const FileData& fd1, const FileData& fd2) +{ + return CompareFileTime(&fd1.timestamp, &fd2.timestamp) > 0; +} + +void UIPruneSavedDumps(const std::string& directory) +{ + wstring wdirectory = UTF8ToWide(directory); + + WIN32_FIND_DATA fdata; + wstring findpath = wdirectory + L"\\*.dmp"; + HANDLE dirlist = FindFirstFile(findpath.c_str(), &fdata); + if (dirlist == INVALID_HANDLE_VALUE) + return; + + vector dumpfiles; + + for (BOOL ok = true; ok; ok = FindNextFile(dirlist, &fdata)) { + FileData fd = {fdata.ftLastWriteTime, wdirectory + L"\\" + fdata.cFileName}; + dumpfiles.push_back(fd); + } + + sort(dumpfiles.begin(), dumpfiles.end(), CompareFDTime); + + while (dumpfiles.size() > kSaveCount) { + // get the path of the oldest file + wstring path = (--dumpfiles.end())->path; + DeleteFile(path.c_str()); + + // s/.dmp/.extra/ + path.replace(path.size() - 4, 4, L".extra"); + DeleteFile(path.c_str()); + + dumpfiles.pop_back(); + } +}