Home | History | Annotate | Download | only in ios
      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 
     13 namespace base {
     14 namespace ios {
     15 
     16 ScopedCriticalAction::ScopedCriticalAction()
     17     : core_(new ScopedCriticalAction::Core()) {
     18 }
     19 
     20 ScopedCriticalAction::~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.
     27 ScopedCriticalAction::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 
     45 ScopedCriticalAction::Core::~Core() {
     46   DCHECK_EQ(background_task_id_, UIBackgroundTaskInvalid);
     47 }
     48 
     49 void 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