| Index: base/threading/sequenced_worker_pool.cc
 | 
| diff --git a/base/threading/sequenced_worker_pool.cc b/base/threading/sequenced_worker_pool.cc
 | 
| index 52b178bcd5f42be4a71d45b692d5e879b033bf04..6f4a248aaf6cd2a0492f45c3647258f05c20fc31 100644
 | 
| --- a/base/threading/sequenced_worker_pool.cc
 | 
| +++ b/base/threading/sequenced_worker_pool.cc
 | 
| @@ -239,24 +239,41 @@ class SequencedWorkerPool::Worker : public SimpleThread {
 | 
|    // SimpleThread implementation. This actually runs the background thread.
 | 
|    void Run() override;
 | 
|  
 | 
| +  // Indicates that a task is about to be run. The parameters provide
 | 
| +  // additional metainformation about the task being run.
 | 
|    void set_running_task_info(SequenceToken token,
 | 
|                               WorkerShutdown shutdown_behavior) {
 | 
| -    running_sequence_ = token;
 | 
| -    running_shutdown_behavior_ = shutdown_behavior;
 | 
| +    is_processing_task_ = true;
 | 
| +    task_sequence_token_ = token;
 | 
| +    task_shutdown_behavior_ = shutdown_behavior;
 | 
|    }
 | 
|  
 | 
| -  SequenceToken running_sequence() const {
 | 
| -    return running_sequence_;
 | 
| +  // Indicates that the task has finished running.
 | 
| +  void reset_running_task_info() { is_processing_task_ = false; }
 | 
| +
 | 
| +  // Whether the worker is processing a task.
 | 
| +  bool is_processing_task() { return is_processing_task_; }
 | 
| +
 | 
| +  SequenceToken task_sequence_token() const {
 | 
| +    DCHECK(is_processing_task_);
 | 
| +    return task_sequence_token_;
 | 
|    }
 | 
|  
 | 
| -  WorkerShutdown running_shutdown_behavior() const {
 | 
| -    return running_shutdown_behavior_;
 | 
| +  WorkerShutdown task_shutdown_behavior() const {
 | 
| +    DCHECK(is_processing_task_);
 | 
| +    return task_shutdown_behavior_;
 | 
|    }
 | 
|  
 | 
|   private:
 | 
|    scoped_refptr<SequencedWorkerPool> worker_pool_;
 | 
| -  SequenceToken running_sequence_;
 | 
| -  WorkerShutdown running_shutdown_behavior_;
 | 
| +  // The sequence token of the task being processed. Only valid when
 | 
| +  // is_processing_task_ is true.
 | 
| +  SequenceToken task_sequence_token_;
 | 
| +  // The shutdown behavior of the task being processed. Only valid when
 | 
| +  // is_processing_task_ is true.
 | 
| +  WorkerShutdown task_shutdown_behavior_;
 | 
| +  // Whether the Worker is processing a task.
 | 
| +  bool is_processing_task_;
 | 
|  
 | 
|    DISALLOW_COPY_AND_ASSIGN(Worker);
 | 
|  };
 | 
| @@ -326,11 +343,6 @@ class SequencedWorkerPool::Inner {
 | 
|    // Called from within the lock, this returns the next sequence task number.
 | 
|    int64 LockedGetNextSequenceTaskNumber();
 | 
|  
 | 
| -  // Called from within the lock, returns the shutdown behavior of the task
 | 
| -  // running on the currently executing worker thread. If invoked from a thread
 | 
| -  // that is not one of the workers, returns CONTINUE_ON_SHUTDOWN.
 | 
| -  WorkerShutdown LockedCurrentThreadShutdownBehavior() const;
 | 
| -
 | 
|    // Gets new task. There are 3 cases depending on the return value:
 | 
|    //
 | 
|    // 1) If the return value is |GET_WORK_FOUND|, |task| is filled in and should
 | 
| @@ -483,7 +495,8 @@ SequencedWorkerPool::Worker::Worker(
 | 
|      const std::string& prefix)
 | 
|      : SimpleThread(prefix + StringPrintf("Worker%d", thread_number)),
 | 
|        worker_pool_(worker_pool),
 | 
| -      running_shutdown_behavior_(CONTINUE_ON_SHUTDOWN) {
 | 
| +      task_shutdown_behavior_(BLOCK_SHUTDOWN),
 | 
| +      is_processing_task_(false) {
 | 
|    Start();
 | 
|  }
 | 
|  
 | 
| @@ -497,7 +510,7 @@ void SequencedWorkerPool::Worker::Run() {
 | 
|  
 | 
|    // Store a pointer to the running sequence in thread local storage for
 | 
|    // static function access.
 | 
| -  g_lazy_tls_ptr.Get().Set(&running_sequence_);
 | 
| +  g_lazy_tls_ptr.Get().Set(&task_sequence_token_);
 | 
|  
 | 
|    // Just jump back to the Inner object to run the thread, since it has all the
 | 
|    // tracking information and queues. It might be more natural to implement
 | 
| @@ -583,10 +596,19 @@ bool SequencedWorkerPool::Inner::PostTask(
 | 
|    {
 | 
|      AutoLock lock(lock_);
 | 
|      if (shutdown_called_) {
 | 
| -      if (shutdown_behavior != BLOCK_SHUTDOWN ||
 | 
| -          LockedCurrentThreadShutdownBehavior() == CONTINUE_ON_SHUTDOWN) {
 | 
| +      // Don't allow a new task to be posted if it doesn't block shutdown.
 | 
| +      if (shutdown_behavior != BLOCK_SHUTDOWN)
 | 
| +        return false;
 | 
| +
 | 
| +      // If the current thread is running a task, and that task doesn't block
 | 
| +      // shutdown, then it shouldn't be allowed to post any more tasks.
 | 
| +      ThreadMap::const_iterator found =
 | 
| +          threads_.find(PlatformThread::CurrentId());
 | 
| +      if (found != threads_.end() && found->second->is_processing_task() &&
 | 
| +          found->second->task_shutdown_behavior() != BLOCK_SHUTDOWN) {
 | 
|          return false;
 | 
|        }
 | 
| +
 | 
|        if (max_blocking_tasks_after_shutdown_ <= 0) {
 | 
|          DLOG(WARNING) << "BLOCK_SHUTDOWN task disallowed";
 | 
|          return false;
 | 
| @@ -635,7 +657,8 @@ bool SequencedWorkerPool::Inner::IsRunningSequenceOnCurrentThread(
 | 
|    ThreadMap::const_iterator found = threads_.find(PlatformThread::CurrentId());
 | 
|    if (found == threads_.end())
 | 
|      return false;
 | 
| -  return sequence_token.Equals(found->second->running_sequence());
 | 
| +  return found->second->is_processing_task() &&
 | 
| +         sequence_token.Equals(found->second->task_sequence_token());
 | 
|  }
 | 
|  
 | 
|  // See https://code.google.com/p/chromium/issues/detail?id=168415
 | 
| @@ -765,13 +788,12 @@ void SequencedWorkerPool::Inner::ThreadLoop(Worker* this_worker) {
 | 
|  
 | 
|            // Make sure our task is erased outside the lock for the
 | 
|            // same reason we do this with delete_these_oustide_lock.
 | 
| -          // Also, do it before calling set_running_task_info() so
 | 
| +          // Also, do it before calling reset_running_task_info() so
 | 
|            // that sequence-checking from within the task's destructor
 | 
|            // still works.
 | 
|            task.task = Closure();
 | 
|  
 | 
| -          this_worker->set_running_task_info(
 | 
| -              SequenceToken(), CONTINUE_ON_SHUTDOWN);
 | 
| +          this_worker->reset_running_task_info();
 | 
|          }
 | 
|          DidRunWorkerTask(task);  // Must be done inside the lock.
 | 
|        } else if (cleanup_state_ == CLEANUP_RUNNING) {
 | 
| @@ -904,15 +926,6 @@ int64 SequencedWorkerPool::Inner::LockedGetNextSequenceTaskNumber() {
 | 
|    return next_sequence_task_number_++;
 | 
|  }
 | 
|  
 | 
| -SequencedWorkerPool::WorkerShutdown
 | 
| -SequencedWorkerPool::Inner::LockedCurrentThreadShutdownBehavior() const {
 | 
| -  lock_.AssertAcquired();
 | 
| -  ThreadMap::const_iterator found = threads_.find(PlatformThread::CurrentId());
 | 
| -  if (found == threads_.end())
 | 
| -    return CONTINUE_ON_SHUTDOWN;
 | 
| -  return found->second->running_shutdown_behavior();
 | 
| -}
 | 
| -
 | 
|  SequencedWorkerPool::Inner::GetWorkStatus SequencedWorkerPool::Inner::GetWork(
 | 
|      SequencedTask* task,
 | 
|      TimeDelta* wait_time,
 | 
| 
 |