[Extensions] Implement an uninstallSelf test for service workers.

This test creates and runs an extension that immediately uninstalls
itself to verify Chrome handles this scenario gracefully.

Bug: 973540
Change-Id: I2b79f135374d396b970277b209ef4902e1fc9457
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1654492
Commit-Queue: David Bertoni <[email protected]>
Reviewed-by: Devlin <[email protected]>
Cr-Commit-Position: refs/heads/master@{#668680}
diff --git a/extensions/renderer/worker_thread_dispatcher.cc b/extensions/renderer/worker_thread_dispatcher.cc
index 47b79e0f..6b94e6ff 100644
--- a/extensions/renderer/worker_thread_dispatcher.cc
+++ b/extensions/renderer/worker_thread_dispatcher.cc
@@ -100,6 +100,10 @@
     if (worker_thread_id == kMainThreadId)
       return false;
     base::TaskRunner* runner = GetTaskRunnerFor(worker_thread_id);
+    // The TaskRunner may have been destroyed, for example, if the extension
+    // was unloaded, so check before trying to post a task.
+    if (runner == nullptr)
+      return false;
     bool task_posted = runner->PostTask(
         FROM_HERE, base::BindOnce(&WorkerThreadDispatcher::ForwardIPC,
                                   worker_thread_id, message));
@@ -130,7 +134,8 @@
 base::TaskRunner* WorkerThreadDispatcher::GetTaskRunnerFor(
     int worker_thread_id) {
   base::AutoLock lock(task_runner_map_lock_);
-  return task_runner_map_[worker_thread_id];
+  auto it = task_runner_map_.find(worker_thread_id);
+  return it == task_runner_map_.end() ? nullptr : it->second;
 }
 
 bool WorkerThreadDispatcher::Send(IPC::Message* message) {