• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (c) 2012 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 "base/ios/scoped_critical_action.h"
6
7#import <UIKit/UIKit.h>
8
9#include "base/logging.h"
10#include "base/memory/ref_counted.h"
11#include "base/synchronization/lock.h"
12
13namespace base {
14namespace ios {
15
16ScopedCriticalAction::ScopedCriticalAction()
17    : core_(new ScopedCriticalAction::Core()) {
18}
19
20ScopedCriticalAction::~ScopedCriticalAction() {
21  core_->EndBackgroundTask();
22}
23
24// This implementation calls |beginBackgroundTaskWithExpirationHandler:| when
25// instantiated and |endBackgroundTask:| when destroyed, creating a scope whose
26// execution will continue (temporarily) even after the app is backgrounded.
27ScopedCriticalAction::Core::Core() {
28  scoped_refptr<ScopedCriticalAction::Core> core = this;
29  background_task_id_ = [[UIApplication sharedApplication]
30      beginBackgroundTaskWithExpirationHandler:^{
31        DLOG(WARNING) << "Background task with id " << background_task_id_
32                      << " expired.";
33        // Note if |endBackgroundTask:| is not called for each task before time
34        // expires, the system kills the application.
35        core->EndBackgroundTask();
36      }];
37  if (background_task_id_ == UIBackgroundTaskInvalid) {
38    DLOG(WARNING) <<
39        "beginBackgroundTaskWithExpirationHandler: returned an invalid ID";
40  } else {
41    VLOG(3) << "Beginning background task with id " << background_task_id_;
42  }
43}
44
45ScopedCriticalAction::Core::~Core() {
46  DCHECK_EQ(background_task_id_, UIBackgroundTaskInvalid);
47}
48
49void ScopedCriticalAction::Core::EndBackgroundTask() {
50  UIBackgroundTaskIdentifier task_id;
51  {
52    AutoLock lock_scope(background_task_id_lock_);
53    if (background_task_id_ == UIBackgroundTaskInvalid)
54      return;
55    task_id = background_task_id_;
56    background_task_id_ = UIBackgroundTaskInvalid;
57  }
58
59  VLOG(3) << "Ending background task with id " << task_id;
60  [[UIApplication sharedApplication] endBackgroundTask:task_id];
61}
62
63}  // namespace ios
64}  // namespace base
65