blob: dbfbd4525bb77a9bfaa06da1b149094847f9b361 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/ios/scoped_critical_action.h"
#import <UIKit/UIKit.h>
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
namespace base {
namespace ios {
ScopedCriticalAction::ScopedCriticalAction()
: core_(MakeRefCounted<ScopedCriticalAction::Core>()) {
ScopedCriticalAction::Core::StartBackgroundTask(core_);
}
ScopedCriticalAction::~ScopedCriticalAction() {
ScopedCriticalAction::Core::EndBackgroundTask(core_);
}
ScopedCriticalAction::Core::Core()
: background_task_id_(UIBackgroundTaskInvalid) {}
ScopedCriticalAction::Core::~Core() {
DCHECK_EQ(background_task_id_, UIBackgroundTaskInvalid);
}
// This implementation calls |beginBackgroundTaskWithExpirationHandler:| when
// instantiated and |endBackgroundTask:| when destroyed, creating a scope whose
// execution will continue (temporarily) even after the app is backgrounded.
// static
void ScopedCriticalAction::Core::StartBackgroundTask(scoped_refptr<Core> core) {
UIApplication* application = [UIApplication sharedApplication];
if (!application) {
return;
}
core->background_task_id_ =
[application beginBackgroundTaskWithExpirationHandler:^{
DLOG(WARNING) << "Background task with id " << core->background_task_id_
<< " expired.";
// Note if |endBackgroundTask:| is not called for each task before time
// expires, the system kills the application.
EndBackgroundTask(core);
}];
if (core->background_task_id_ == UIBackgroundTaskInvalid) {
DLOG(WARNING)
<< "beginBackgroundTaskWithExpirationHandler: returned an invalid ID";
} else {
VLOG(3) << "Beginning background task with id "
<< core->background_task_id_;
}
}
// static
void ScopedCriticalAction::Core::EndBackgroundTask(scoped_refptr<Core> core) {
UIBackgroundTaskIdentifier task_id;
{
AutoLock lock_scope(core->background_task_id_lock_);
if (core->background_task_id_ == UIBackgroundTaskInvalid) {
return;
}
task_id = core->background_task_id_;
core->background_task_id_ = UIBackgroundTaskInvalid;
}
VLOG(3) << "Ending background task with id " << task_id;
[[UIApplication sharedApplication] endBackgroundTask:task_id];
}
} // namespace ios
} // namespace base