summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chrome_to_mobile_service.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/chrome_to_mobile_service.cc')
-rw-r--r--chrome/browser/chrome_to_mobile_service.cc113
1 files changed, 66 insertions, 47 deletions
diff --git a/chrome/browser/chrome_to_mobile_service.cc b/chrome/browser/chrome_to_mobile_service.cc
index bbe3b93..e4b07f6 100644
--- a/chrome/browser/chrome_to_mobile_service.cc
+++ b/chrome/browser/chrome_to_mobile_service.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/command_line.h"
+#include "base/file_util.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/stringprintf.h"
@@ -72,10 +73,6 @@ const char kRequestTypeURL[] = "url";
const char kRequestTypeDelayedSnapshot[] = "url_with_delayed_snapshot";
const char kRequestTypeSnapshot[] = "snapshot";
-// The snapshot path constants; used with a guid for each MHTML snapshot file.
-const FilePath::CharType kSnapshotPath[] =
- FILE_PATH_LITERAL("chrome_to_mobile_snapshot_.mht");
-
// Get the "__c2dm__job_data" tag JSON data for the cloud print job submission.
std::string GetJobString(const ChromeToMobileService::RequestData& data) {
scoped_ptr<DictionaryValue> job(new DictionaryValue());
@@ -122,15 +119,23 @@ GURL GetSubmitURL(const GURL& service_url,
return submit_url.ReplaceComponents(replacements);
}
-// Delete the specified file; called as a BlockingPoolTask.
-void DeleteFilePath(const FilePath& file_path) {
- bool success = file_util::Delete(file_path, false);
- DCHECK(success);
+// A callback to continue snapshot generation after creating the temp file.
+typedef base::Callback<void(FilePath path, bool success)>
+ CreateSnapshotFileCallback;
+
+// Create a temp file and post the callback on the UI thread with the results.
+// Call this as a BlockingPoolTask to avoid the FILE thread.
+void CreateSnapshotFile(CreateSnapshotFileCallback callback) {
+ FilePath snapshot;
+ bool success = file_util::CreateTemporaryFile(&snapshot);
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ base::Bind(callback, snapshot, success));
}
-// Construct POST data and submit the MHTML snapshot file; deletes the snapshot.
-void SubmitSnapshot(content::URLFetcher* request,
- const ChromeToMobileService::RequestData& data) {
+// Send snapshot file contents as POST data in a job submit request.
+// Call this as a BlockingPoolSequencedTask (before posting DeleteSnapshotFile).
+void SubmitSnapshotFile(content::URLFetcher* request,
+ const ChromeToMobileService::RequestData& data) {
std::string file;
if (file_util::ReadFileToString(data.snapshot_path, &file) && !file.empty()) {
std::string post_data, mime_boundary;
@@ -154,9 +159,13 @@ void SubmitSnapshot(content::URLFetcher* request,
request->SetUploadData(content_type, post_data);
request->Start();
}
+}
- content::BrowserThread::PostBlockingPoolTask(FROM_HERE,
- base::Bind(&DeleteFilePath, data.snapshot_path));
+// Delete the snapshot file; DCHECK, but really ignore the result of the delete.
+// Call this as a BlockingPoolSequencedTask [after posting SubmitSnapshotFile].
+void DeleteSnapshotFile(const FilePath snapshot) {
+ bool success = file_util::Delete(snapshot, false);
+ DCHECK(success);
}
} // namespace
@@ -181,23 +190,12 @@ bool ChromeToMobileService::IsChromeToMobileEnabled() {
}
ChromeToMobileService::ChromeToMobileService(Profile* profile)
- : profile_(profile),
+ : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
+ profile_(profile),
cloud_print_url_(new CloudPrintURL(profile)),
- temp_dir_valid_(false),
cloud_print_accessible_(false) {
-}
-
-ChromeToMobileService::~ChromeToMobileService() {}
-
-void ChromeToMobileService::Init() {
// Skip initialization if constructed without a profile.
if (profile_) {
- // Create a unique temporary directory for the page snapshots.
- // Note that if this task is posted and run in the ctor, the service will be
- // destroyed (since there are no other references to the service).
- content::BrowserThread::PostBlockingPoolTask(FROM_HERE,
- base::Bind(&ChromeToMobileService::CreateUniqueTempDir, this));
-
// Get an access token as soon as the Gaia login refresh token is available.
TokenService* service = TokenServiceFactory::GetForProfile(profile_);
registrar_.Add(this, chrome::NOTIFICATION_TOKEN_AVAILABLE,
@@ -207,6 +205,11 @@ void ChromeToMobileService::Init() {
}
}
+ChromeToMobileService::~ChromeToMobileService() {
+ while (!snapshots_.empty())
+ DeleteSnapshot(*snapshots_.begin());
+}
+
bool ChromeToMobileService::HasDevices() {
return !mobiles().empty();
}
@@ -223,19 +226,13 @@ void ChromeToMobileService::RequestMobileListUpdate() {
}
void ChromeToMobileService::GenerateSnapshot(base::WeakPtr<Observer> observer) {
- // Signal snapshot generation failure and bail if the temp dir is invalid.
- DCHECK(temp_dir_valid_);
- if (!temp_dir_valid_) {
- if (observer.get())
- observer->SnapshotGenerated(FilePath(), 0);
- return;
- }
-
- // Generate the snapshot and have the observer be called back on completion.
- FilePath path(temp_dir_.path().Append(kSnapshotPath));
- BrowserList::GetLastActiveWithProfile(profile_)->GetSelectedWebContents()->
- GenerateMHTML(path.InsertBeforeExtensionASCII(guid::GenerateGUID()),
- base::Bind(&Observer::SnapshotGenerated, observer));
+ // Callback SnapshotFileCreated from CreateSnapshotFile to continue.
+ CreateSnapshotFileCallback callback =
+ base::Bind(&ChromeToMobileService::SnapshotFileCreated,
+ weak_ptr_factory_.GetWeakPtr(), observer);
+ // Create a temporary file via the blocking pool for snapshot storage.
+ content::BrowserThread::PostBlockingPoolTask(FROM_HERE,
+ base::Bind(&CreateSnapshotFile, callback));
}
void ChromeToMobileService::SendToMobile(const string16& mobile_id,
@@ -261,12 +258,21 @@ void ChromeToMobileService::SendToMobile(const string16& mobile_id,
data.type = SNAPSHOT;
content::URLFetcher* submit_snapshot = CreateRequest(data);
request_observer_map_[submit_snapshot] = observer;
- content::BrowserThread::PostBlockingPoolTask(FROM_HERE,
- base::Bind(&SubmitSnapshot, submit_snapshot, data));
+ content::BrowserThread::PostBlockingPoolSequencedTask(
+ data.snapshot_path.AsUTF8Unsafe(), FROM_HERE,
+ base::Bind(&SubmitSnapshotFile, submit_snapshot, data));
}
}
-void ChromeToMobileService::ShutdownOnUIThread() {
+void ChromeToMobileService::DeleteSnapshot(const FilePath& snapshot) {
+ DCHECK(snapshot.empty() || snapshots_.find(snapshot) != snapshots_.end());
+ if (snapshots_.find(snapshot) != snapshots_.end()) {
+ if (!snapshot.empty())
+ content::BrowserThread::PostBlockingPoolSequencedTask(
+ snapshot.AsUTF8Unsafe(), FROM_HERE,
+ base::Bind(&DeleteSnapshotFile, snapshot));
+ snapshots_.erase(snapshot);
+ }
}
void ChromeToMobileService::OnURLFetchComplete(
@@ -283,7 +289,7 @@ void ChromeToMobileService::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
- DCHECK(type == chrome::NOTIFICATION_TOKEN_AVAILABLE);
+ DCHECK_EQ(type, chrome::NOTIFICATION_TOKEN_AVAILABLE);
TokenService::TokenAvailableDetails* token_details =
content::Details<TokenService::TokenAvailableDetails>(details).ptr();
if (token_details->service() == GaiaConstants::kGaiaOAuth2LoginRefreshToken)
@@ -308,10 +314,23 @@ void ChromeToMobileService::OnGetTokenFailure(
this, &ChromeToMobileService::RefreshAccessToken);
}
-void ChromeToMobileService::CreateUniqueTempDir() {
- temp_dir_valid_ = temp_dir_.CreateUniqueTempDir();
- DCHECK_EQ(temp_dir_valid_, temp_dir_.IsValid());
- DCHECK(temp_dir_valid_);
+void ChromeToMobileService::SnapshotFileCreated(
+ base::WeakPtr<Observer> observer,
+ const FilePath path,
+ bool success) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ // Track the set of temporary files to be deleted later.
+ snapshots_.insert(path);
+
+ Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
+ if (success && browser && browser->GetSelectedWebContents()) {
+ // Generate the snapshot and have the observer be called back on completion.
+ browser->GetSelectedWebContents()->GenerateMHTML(path,
+ base::Bind(&Observer::SnapshotGenerated, observer));
+ } else if (observer.get()) {
+ // Signal snapshot generation failure.
+ observer->SnapshotGenerated(FilePath(), 0);
+ }
}
content::URLFetcher* ChromeToMobileService::CreateRequest(