diff --git a/DEPS b/DEPS
index 8c7e124..d98c6c5 100644
--- a/DEPS
+++ b/DEPS
@@ -39,7 +39,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '9d453b09d521143c373a77e1d36e527017b2b005',
+  'skia_revision': 'cb232e8b1b9f2d7831ad90815df5934ecafab1d4',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
diff --git a/WATCHLISTS b/WATCHLISTS
index 65d2b1a..e6bd49f 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -806,8 +806,7 @@
       'filepath': 'third_party/tcmalloc'
     },
     'telemetry': {
-      'filepath': 'tools/perf/|'\
-                  'tools/telemetry/'
+      'filepath': 'tools/perf/'
     },
     'tests': {
       'filepath': 'apitest|unittest|browsertest|uitest|chrome/test/',
diff --git a/base/metrics/persistent_histogram_allocator.cc b/base/metrics/persistent_histogram_allocator.cc
index 1d5c0ef..b38c1ef 100644
--- a/base/metrics/persistent_histogram_allocator.cc
+++ b/base/metrics/persistent_histogram_allocator.cc
@@ -12,6 +12,7 @@
 #include "base/metrics/histogram.h"
 #include "base/metrics/histogram_base.h"
 #include "base/metrics/histogram_samples.h"
+#include "base/metrics/persistent_sample_map.h"
 #include "base/metrics/sparse_histogram.h"
 #include "base/metrics/statistics_recorder.h"
 #include "base/synchronization/lock.h"
@@ -91,6 +92,134 @@
   "PersistentHistograms", FEATURE_DISABLED_BY_DEFAULT
 };
 
+
+PersistentSparseHistogramDataManager::PersistentSparseHistogramDataManager(
+    PersistentMemoryAllocator* allocator)
+    : allocator_(allocator), record_iterator_(allocator) {}
+
+PersistentSparseHistogramDataManager::~PersistentSparseHistogramDataManager() {}
+
+PersistentSampleMapRecords*
+PersistentSparseHistogramDataManager::UseSampleMapRecords(uint64_t id,
+                                                          const void* user) {
+  base::AutoLock auto_lock(lock_);
+  return GetSampleMapRecordsWhileLocked(id)->Acquire(user);
+}
+
+PersistentSampleMapRecords*
+PersistentSparseHistogramDataManager::GetSampleMapRecordsWhileLocked(
+    uint64_t id) {
+  lock_.AssertAcquired();
+
+  auto found = sample_records_.find(id);
+  if (found != sample_records_.end())
+    return found->second.get();
+
+  std::unique_ptr<PersistentSampleMapRecords>& samples = sample_records_[id];
+  samples = WrapUnique(new PersistentSampleMapRecords(this, id));
+  return samples.get();
+}
+
+bool PersistentSparseHistogramDataManager::LoadRecords(
+    PersistentSampleMapRecords* sample_map_records) {
+  // DataManager must be locked in order to access the found_ field of any
+  // PersistentSampleMapRecords object.
+  base::AutoLock auto_lock(lock_);
+  bool found = false;
+
+  // If there are already "found" entries for the passed object, move them.
+  if (!sample_map_records->found_.empty()) {
+    sample_map_records->records_.reserve(sample_map_records->records_.size() +
+                                         sample_map_records->found_.size());
+    sample_map_records->records_.insert(sample_map_records->records_.end(),
+                                        sample_map_records->found_.begin(),
+                                        sample_map_records->found_.end());
+    sample_map_records->found_.clear();
+    found = true;
+  }
+
+  // Acquiring a lock is a semi-expensive operation so load some records with
+  // each call. More than this number may be loaded if it takes longer to
+  // find at least one matching record for the passed object.
+  const int kMinimumNumberToLoad = 10;
+  const uint64_t match_id = sample_map_records->sample_map_id_;
+
+  // Loop while no enty is found OR we haven't yet loaded the minimum number.
+  // This will continue reading even after a match is found.
+  for (int count = 0; !found || count < kMinimumNumberToLoad; ++count) {
+    // Get the next sample-record. The iterator will always resume from where
+    // it left off even if it previously had nothing further to return.
+    uint64_t found_id;
+    PersistentMemoryAllocator::Reference ref =
+        PersistentSampleMap::GetNextPersistentRecord(record_iterator_,
+                                                     &found_id);
+
+    // Stop immediately if there are none.
+    if (!ref)
+      break;
+
+    // The sample-record could be for any sparse histogram. Add the reference
+    // to the appropriate collection for later use.
+    if (found_id == match_id) {
+      sample_map_records->records_.push_back(ref);
+      found = true;
+    } else {
+      PersistentSampleMapRecords* samples =
+          GetSampleMapRecordsWhileLocked(found_id);
+      DCHECK(samples);
+      samples->found_.push_back(ref);
+    }
+  }
+
+  return found;
+}
+
+
+PersistentSampleMapRecords::PersistentSampleMapRecords(
+    PersistentSparseHistogramDataManager* data_manager,
+    uint64_t sample_map_id)
+    : data_manager_(data_manager), sample_map_id_(sample_map_id) {}
+
+PersistentSampleMapRecords::~PersistentSampleMapRecords() {}
+
+PersistentSampleMapRecords* PersistentSampleMapRecords::Acquire(
+    const void* user) {
+  DCHECK(!user_);
+  user_ = user;
+  seen_ = 0;
+  return this;
+}
+
+void PersistentSampleMapRecords::Release(const void* user) {
+  DCHECK_EQ(user_, user);
+  user_ = nullptr;
+}
+
+PersistentMemoryAllocator::Reference PersistentSampleMapRecords::GetNext() {
+  DCHECK(user_);
+
+  // If there are no unseen records, lock and swap in all the found ones.
+  if (records_.size() == seen_) {
+    if (!data_manager_->LoadRecords(this))
+      return false;
+  }
+
+  // Return the next record. Records *must* be returned in the same order
+  // they are found in the persistent memory in order to ensure that all
+  // objects using this data always have the same state. Race conditions
+  // can cause duplicate records so using the "first found" is the only
+  // guarantee that all objects always access the same one.
+  DCHECK_LT(seen_, records_.size());
+  return records_[seen_++];
+}
+
+PersistentMemoryAllocator::Reference PersistentSampleMapRecords::CreateNew(
+    HistogramBase::Sample value) {
+  return PersistentSampleMap::CreatePersistentRecord(data_manager_->allocator_,
+                                                     sample_map_id_, value);
+}
+
+
 // This data will be held in persistent memory in order for processes to
 // locate and use histograms created elsewhere.
 struct PersistentHistogramAllocator::PersistentHistogramData {
@@ -125,9 +254,11 @@
   return nullptr;
 }
 
+
 PersistentHistogramAllocator::PersistentHistogramAllocator(
     std::unique_ptr<PersistentMemoryAllocator> memory)
-    : memory_allocator_(std::move(memory)) {}
+    : memory_allocator_(std::move(memory)),
+      sparse_histogram_data_manager_(memory_allocator_.get()) {}
 
 PersistentHistogramAllocator::~PersistentHistogramAllocator() {}
 
@@ -196,8 +327,7 @@
   // Sparse histograms are quite different so handle them as a special case.
   if (histogram_data_ptr->histogram_type == SPARSE_HISTOGRAM) {
     std::unique_ptr<HistogramBase> histogram =
-        SparseHistogram::PersistentCreate(memory_allocator(),
-                                          histogram_data_ptr->name,
+        SparseHistogram::PersistentCreate(this, histogram_data_ptr->name,
                                           &histogram_data_ptr->samples_metadata,
                                           &histogram_data_ptr->logged_metadata);
     DCHECK(histogram);
@@ -343,6 +473,12 @@
     memory_allocator_->SetType(ref, 0);
 }
 
+PersistentSampleMapRecords* PersistentHistogramAllocator::UseSampleMapRecords(
+    uint64_t id,
+    const void* user) {
+  return sparse_histogram_data_manager_.UseSampleMapRecords(id, user);
+}
+
 std::unique_ptr<HistogramBase> PersistentHistogramAllocator::AllocateHistogram(
     HistogramType histogram_type,
     const std::string& name,
diff --git a/base/metrics/persistent_histogram_allocator.h b/base/metrics/persistent_histogram_allocator.h
index b2038c43..7f46dc9 100644
--- a/base/metrics/persistent_histogram_allocator.h
+++ b/base/metrics/persistent_histogram_allocator.h
@@ -5,6 +5,7 @@
 #ifndef BASE_METRICS_HISTOGRAM_PERSISTENCE_H_
 #define BASE_METRICS_HISTOGRAM_PERSISTENCE_H_
 
+#include <map>
 #include <memory>
 
 #include "base/atomicops.h"
@@ -14,12 +15,157 @@
 #include "base/metrics/histogram_base.h"
 #include "base/metrics/persistent_memory_allocator.h"
 #include "base/strings/string_piece.h"
+#include "base/synchronization/lock.h"
 
 namespace base {
 
+class PersistentSampleMapRecords;
+class PersistentSparseHistogramDataManager;
+
 // Feature definition for enabling histogram persistence.
 BASE_EXPORT extern const Feature kPersistentHistogramsFeature;
 
+
+// A data manager for sparse histograms so each instance of such doesn't have
+// to separately iterate over the entire memory segment. Though this class
+// will generally be accessed through the PersistentHistogramAllocator above,
+// it can be used independently on any PersistentMemoryAllocator (making it
+// useable for testing). This object supports only one instance of a sparse
+// histogram for a given id. Tests that create multiple identical histograms,
+// perhaps to simulate multiple processes, should create a separate manager
+// for each.
+class BASE_EXPORT PersistentSparseHistogramDataManager {
+ public:
+  // Constructs the data manager. The allocator must live longer than any
+  // managers that reference it.
+  explicit PersistentSparseHistogramDataManager(
+      PersistentMemoryAllocator* allocator);
+
+  ~PersistentSparseHistogramDataManager();
+
+  // Returns the object that manages the persistent-sample-map records for a
+  // given |id|. Only one |user| of this data is allowed at a time. This does
+  // an automatic Acquire() on the records. The user must call Release() on
+  // the returned object when it is finished with it. Ownership of the records
+  // object stays with this manager.
+  PersistentSampleMapRecords* UseSampleMapRecords(uint64_t id,
+                                                  const void* user);
+
+  // Convenience method that gets the object for a given reference so callers
+  // don't have to also keep their own pointer to the appropriate allocator.
+  template <typename T>
+  T* GetAsObject(PersistentMemoryAllocator::Reference ref, uint32_t type_id) {
+    return allocator_->GetAsObject<T>(ref, type_id);
+  }
+
+ private:
+  friend class PersistentSampleMapRecords;
+
+  // Gets the object holding records for a given sample-map id when |lock_|
+  // has already been acquired.
+  PersistentSampleMapRecords* GetSampleMapRecordsWhileLocked(uint64_t id);
+
+  // Loads sample-map records looking for those belonging to the specified
+  // |load_id|. Records found for other sample-maps are held for later use
+  // without having to iterate again. This should be called only from a
+  // PersistentSampleMapRecords object because those objects have a contract
+  // that there are no other threads accessing the internal records_ field
+  // of the object that is passed in.
+  bool LoadRecords(PersistentSampleMapRecords* sample_map_records);
+
+  // Weak-pointer to the allocator used by the sparse histograms.
+  PersistentMemoryAllocator* allocator_;
+
+  // Iterator within the allocator for finding sample records.
+  PersistentMemoryAllocator::Iterator record_iterator_;
+
+  // Mapping of sample-map IDs to their sample records.
+  std::map<uint64_t, std::unique_ptr<PersistentSampleMapRecords>>
+      sample_records_;
+
+  // A lock used for synchronizing changes to sample_records_.
+  base::Lock lock_;
+
+  DISALLOW_COPY_AND_ASSIGN(PersistentSparseHistogramDataManager);
+};
+
+
+// This class manages sample-records used by a PersistentSampleMap container
+// that underlies a persistent SparseHistogram object. It is broken out into a
+// top-level class so that it can be forward-declared in other header files
+// rather than include this entire file as would be necessary if it were
+// declared within the PersistentSparseHistogramDataManager class above.
+class BASE_EXPORT PersistentSampleMapRecords {
+ public:
+  // Constructs an instance of this class. The manager object must live longer
+  // than all instances of this class that reference it, which is not usually
+  // a problem since these objects are generally managed from within that
+  // manager instance.
+  PersistentSampleMapRecords(PersistentSparseHistogramDataManager* data_manager,
+                             uint64_t sample_map_id);
+
+  ~PersistentSampleMapRecords();
+
+  // Resets the internal state for a new object using this data. The return
+  // value is "this" as a convenience.
+  PersistentSampleMapRecords* Acquire(const void* user);
+
+  // Indicates that the using object is done with this data.
+  void Release(const void* user);
+
+  // Gets the next reference to a persistent sample-map record. The type and
+  // layout of the data being referenced is defined entirely within the
+  // PersistentSampleMap class.
+  PersistentMemoryAllocator::Reference GetNext();
+
+  // Creates a new persistent sample-map record for sample |value| and returns
+  // a reference to it.
+  PersistentMemoryAllocator::Reference CreateNew(HistogramBase::Sample value);
+
+  // Convenience method that gets the object for a given reference so callers
+  // don't have to also keep their own pointer to the appropriate allocator.
+  // This is expected to be used with the SampleRecord structure defined inside
+  // the persistent_sample_map.cc file but since that isn't exported (for
+  // cleanliness of the interface), a template is defined that will be
+  // resolved when used inside that file.
+  template <typename T>
+  T* GetAsObject(PersistentMemoryAllocator::Reference ref, uint32_t type_id) {
+    return data_manager_->GetAsObject<T>(ref, type_id);
+  }
+
+ private:
+  friend PersistentSparseHistogramDataManager;
+
+  // Weak-pointer to the parent data-manager object.
+  PersistentSparseHistogramDataManager* data_manager_;
+
+  // ID of PersistentSampleMap to which these records apply.
+  const uint64_t sample_map_id_;
+
+  // The current user of this set of records. It is used to ensure that no
+  // more than one object is using these records at a given time.
+  const void* user_ = nullptr;
+
+  // This is the count of how many "records" have already been read by the
+  // owning sample-map.
+  size_t seen_ = 0;
+
+  // This is the set of records previously found for a sample map. Because
+  // there is ever only one object with a given ID (typically a hash of a
+  // histogram name) and because the parent SparseHistogram has acquired
+  // its own lock before accessing the PersistentSampleMap it controls, this
+  // list can be accessed without acquiring any additional lock.
+  std::vector<PersistentMemoryAllocator::Reference> records_;
+
+  // This is the set of records found during iteration through memory. It
+  // is appended in bulk to "records". Access to this vector can be done
+  // only while holding the parent manager's lock.
+  std::vector<PersistentMemoryAllocator::Reference> found_;
+
+  DISALLOW_COPY_AND_ASSIGN(PersistentSampleMapRecords);
+};
+
+
 // This class manages histograms created within a PersistentMemoryAllocator.
 class BASE_EXPORT PersistentHistogramAllocator {
  public:
@@ -59,7 +205,7 @@
 
   // A PersistentHistogramAllocator is constructed from a PersistentMemory-
   // Allocator object of which it takes ownership.
-  PersistentHistogramAllocator(
+  explicit PersistentHistogramAllocator(
       std::unique_ptr<PersistentMemoryAllocator> memory);
   virtual ~PersistentHistogramAllocator();
 
@@ -101,6 +247,14 @@
   // True, forgetting it otherwise.
   void FinalizeHistogram(Reference ref, bool registered);
 
+  // Returns the object that manages the persistent-sample-map records for a
+  // given |id|. Only one |user| of this data is allowed at a time. This does
+  // an automatic Acquire() on the records. The user must call Release() on
+  // the returned object when it is finished with it. Ownership stays with
+  // this allocator.
+  PersistentSampleMapRecords* UseSampleMapRecords(uint64_t id,
+                                                  const void* user);
+
   // Create internal histograms for tracking memory use and allocation sizes
   // for allocator of |name| (which can simply be the result of Name()). This
   // is done seperately from construction for situations such as when the
@@ -179,6 +333,9 @@
   // The memory allocator that provides the actual histogram storage.
   std::unique_ptr<PersistentMemoryAllocator> memory_allocator_;
 
+  // The data-manager used to improve performance of sparse histograms.
+  PersistentSparseHistogramDataManager sparse_histogram_data_manager_;
+
   // A reference to the last-created histogram in the allocator, used to avoid
   // trying to import what was just created.
   // TODO(bcwhite): Change this to std::atomic<PMA::Reference> when available.
diff --git a/base/metrics/persistent_memory_allocator.cc b/base/metrics/persistent_memory_allocator.cc
index 6edbc2f..604971d 100644
--- a/base/metrics/persistent_memory_allocator.cc
+++ b/base/metrics/persistent_memory_allocator.cc
@@ -116,8 +116,6 @@
 const PersistentMemoryAllocator::Reference
     PersistentMemoryAllocator::kReferenceQueue =
         offsetof(SharedMetadata, queue);
-const PersistentMemoryAllocator::Reference
-    PersistentMemoryAllocator::kReferenceNull = 0;
 
 PersistentMemoryAllocator::Iterator::Iterator(
     const PersistentMemoryAllocator* allocator)
diff --git a/base/metrics/persistent_memory_allocator.h b/base/metrics/persistent_memory_allocator.h
index 45777fe4..4c0db52 100644
--- a/base/metrics/persistent_memory_allocator.h
+++ b/base/metrics/persistent_memory_allocator.h
@@ -118,6 +118,10 @@
     size_t free;
   };
 
+  enum : Reference {
+    kReferenceNull = 0  // A common "null" reference value.
+  };
+
   enum : uint32_t {
     kTypeIdAny = 0  // Match any type-id inside GetAsObject().
   };
@@ -284,7 +288,6 @@
   struct BlockHeader;
   static const uint32_t kAllocAlignment;
   static const Reference kReferenceQueue;
-  static const Reference kReferenceNull;
 
   // The shared metadata is always located at the top of the memory segment.
   // These convenience functions eliminate constant casting of the base
diff --git a/base/metrics/persistent_sample_map.cc b/base/metrics/persistent_sample_map.cc
index 3bd447a..cc20f45 100644
--- a/base/metrics/persistent_sample_map.cc
+++ b/base/metrics/persistent_sample_map.cc
@@ -6,6 +6,7 @@
 
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/metrics/persistent_histogram_allocator.h"
 #include "base/stl_util.h"
 
 namespace base {
@@ -93,19 +94,25 @@
 
 PersistentSampleMap::PersistentSampleMap(
     uint64_t id,
-    PersistentMemoryAllocator* allocator,
+    PersistentHistogramAllocator* allocator,
     Metadata* meta)
-    : HistogramSamples(id, meta),
-      allocator_(allocator),
-      sample_iter_(allocator) {
-  // Load all existing samples during construction. It's no worse to do it
-  // here than at some point in the future and could be better if construction
-  // takes place on some background thread. New samples could be created at
-  // any time by parallel threads; if so, they'll get loaded when needed.
-  ImportSamples(kAllSamples);
-}
+    : PersistentSampleMap(id, allocator->UseSampleMapRecords(id, this), meta) {}
 
-PersistentSampleMap::~PersistentSampleMap() {}
+PersistentSampleMap::PersistentSampleMap(
+    uint64_t id,
+    PersistentSparseHistogramDataManager* manager,
+    Metadata* meta)
+    : PersistentSampleMap(id, manager->UseSampleMapRecords(id, this), meta) {}
+
+PersistentSampleMap::PersistentSampleMap(
+    uint64_t id,
+    PersistentSampleMapRecords* records,
+    Metadata* meta)
+    : HistogramSamples(id, meta), records_(records) {}
+
+PersistentSampleMap::~PersistentSampleMap() {
+  records_->Release(this);
+}
 
 void PersistentSampleMap::Accumulate(Sample value, Count count) {
   *GetOrCreateSampleCountStorage(value) += count;
@@ -140,6 +147,46 @@
   return WrapUnique(new PersistentSampleMapIterator(sample_counts_));
 }
 
+// static
+PersistentMemoryAllocator::Reference
+PersistentSampleMap::GetNextPersistentRecord(
+    PersistentMemoryAllocator::Iterator& iterator,
+    uint64_t* sample_map_id) {
+  PersistentMemoryAllocator::Reference ref =
+      iterator.GetNextOfType(kTypeIdSampleRecord);
+  const SampleRecord* record =
+      iterator.GetAsObject<SampleRecord>(ref, kTypeIdSampleRecord);
+  if (!record)
+    return 0;
+
+  *sample_map_id = record->id;
+  return ref;
+}
+
+// static
+PersistentMemoryAllocator::Reference
+PersistentSampleMap::CreatePersistentRecord(
+    PersistentMemoryAllocator* allocator,
+    uint64_t sample_map_id,
+    Sample value) {
+  PersistentMemoryAllocator::Reference ref =
+      allocator->Allocate(sizeof(SampleRecord), kTypeIdSampleRecord);
+  SampleRecord* record =
+      allocator->GetAsObject<SampleRecord>(ref, kTypeIdSampleRecord);
+
+  if (!record) {
+    NOTREACHED() << "full=" << allocator->IsFull()
+                 << ", corrupt=" << allocator->IsCorrupt();
+    return 0;
+  }
+
+  record->id = sample_map_id;
+  record->value = value;
+  record->count = 0;
+  allocator->MakeIterable(ref);
+  return ref;
+}
+
 bool PersistentSampleMap::AddSubtractImpl(SampleCountIterator* iter,
                                           Operator op) {
   Sample min;
@@ -175,25 +222,16 @@
     return count_pointer;
 
   // Create a new record in persistent memory for the value.
-  PersistentMemoryAllocator::Reference ref =
-      allocator_->Allocate(sizeof(SampleRecord), kTypeIdSampleRecord);
-  SampleRecord* record =
-      allocator_->GetAsObject<SampleRecord>(ref, kTypeIdSampleRecord);
-  if (!record) {
-    // If the allocator was unable to create a record then it is full or
-    // corrupt. Instead, allocate the counter from the heap. This sample will
-    // not be persistent, will not be shared, and will leak but it's better
-    // than crashing.
-    NOTREACHED() << "full=" << allocator_->IsFull()
-                 << ", corrupt=" << allocator_->IsCorrupt();
+  PersistentMemoryAllocator::Reference ref = records_->CreateNew(value);
+  if (!ref) {
+    // If a new record could not be created then the underlying allocator is
+    // full or corrupt. Instead, allocate the counter from the heap. This
+    // sample will not be persistent, will not be shared, and will leak...
+    // but it's better than crashing.
     count_pointer = new Count(0);
     sample_counts_[value] = count_pointer;
     return count_pointer;
   }
-  record->id = id();
-  record->value = value;
-  record->count = 0;  // Should already be zero but don't trust other processes.
-  allocator_->MakeIterable(ref);
 
   // A race condition between two independent processes (i.e. two independent
   // histogram objects sharing the same sample data) could cause two of the
@@ -210,34 +248,14 @@
 }
 
 Count* PersistentSampleMap::ImportSamples(Sample until_value) {
-  // TODO(bcwhite): This import operates in O(V+N) total time per sparse
-  // histogram where V is the number of values for this object and N is
-  // the number of other iterable objects in the allocator. This becomes
-  // O(S*(SV+N)) or O(S^2*V + SN) overall where S is the number of sparse
-  // histograms.
-  //
-  // This is actually okay when histograms are expected to exist for the
-  // lifetime of the program, spreading the cost out, and S and V are
-  // relatively small, as is the current case.
-  //
-  // However, it is not so good for objects that are created, detroyed, and
-  // recreated on a periodic basis, such as when making a snapshot of
-  // sparse histograms owned by another, ongoing process. In that case, the
-  // entire cost is compressed into a single sequential operation... on the
-  // UI thread no less.
-  //
-  // This will be addressed in a future CL.
-
   PersistentMemoryAllocator::Reference ref;
-  while ((ref = sample_iter_.GetNextOfType(kTypeIdSampleRecord)) != 0) {
+  while ((ref = records_->GetNext()) != 0) {
     SampleRecord* record =
-        allocator_->GetAsObject<SampleRecord>(ref, kTypeIdSampleRecord);
+        records_->GetAsObject<SampleRecord>(ref, kTypeIdSampleRecord);
     if (!record)
       continue;
 
-    // A sample record has been found but may not be for this histogram.
-    if (record->id != id())
-      continue;
+    DCHECK_EQ(id(), record->id);
 
     // Check if the record's value is already known.
     if (!ContainsKey(sample_counts_, record->value)) {
diff --git a/base/metrics/persistent_sample_map.h b/base/metrics/persistent_sample_map.h
index 4ae54d8a..6cde34939 100644
--- a/base/metrics/persistent_sample_map.h
+++ b/base/metrics/persistent_sample_map.h
@@ -22,13 +22,28 @@
 
 namespace base {
 
+class PersistentHistogramAllocator;
+class PersistentSampleMapRecords;
+class PersistentSparseHistogramDataManager;
+
 // The logic here is similar to that of SampleMap but with different data
 // structures. Changes here likely need to be duplicated there.
 class BASE_EXPORT PersistentSampleMap : public HistogramSamples {
  public:
+  // Constructs a persistent sample map using any of a variety of persistent
+  // data sources. Really, the first two are just convenience methods for
+  // getting at the PersistentSampleMapRecords object for the specified |id|.
+  // The source objects must live longer than this object.
   PersistentSampleMap(uint64_t id,
-                      PersistentMemoryAllocator* allocator,
+                      PersistentHistogramAllocator* allocator,
                       Metadata* meta);
+  PersistentSampleMap(uint64_t id,
+                      PersistentSparseHistogramDataManager* manager,
+                      Metadata* meta);
+  PersistentSampleMap(uint64_t id,
+                      PersistentSampleMapRecords* records,
+                      Metadata* meta);
+
   ~PersistentSampleMap() override;
 
   // HistogramSamples:
@@ -38,6 +53,20 @@
   HistogramBase::Count TotalCount() const override;
   std::unique_ptr<SampleCountIterator> Iterator() const override;
 
+  // Uses a persistent-memory |iterator| to locate and return information about
+  // the next record holding information for a PersistentSampleMap. The record
+  // could be for any Map so return the |sample_map_id| as well.
+  static PersistentMemoryAllocator::Reference GetNextPersistentRecord(
+      PersistentMemoryAllocator::Iterator& iterator,
+      uint64_t* sample_map_id);
+
+  // Creates a new record in an |allocator| storing count information for a
+  // specific sample |value| of a histogram with the given |sample_map_id|.
+  static PersistentMemoryAllocator::Reference CreatePersistentRecord(
+      PersistentMemoryAllocator* allocator,
+      uint64_t sample_map_id,
+      HistogramBase::Sample value);
+
  protected:
   // Performs arithemetic. |op| is ADD or SUBTRACT.
   bool AddSubtractImpl(SampleCountIterator* iter, Operator op) override;
@@ -63,12 +92,14 @@
   HistogramBase::Count* ImportSamples(HistogramBase::Sample until_value);
 
   // All created/loaded sample values and their associated counts. The storage
-  // for the actual Count numbers is owned by the |allocator_|.
+  // for the actual Count numbers is owned by the |records_| object and its
+  // underlying allocator.
   std::map<HistogramBase::Sample, HistogramBase::Count*> sample_counts_;
 
-  // The persistent memory allocator holding samples and an iterator through it.
-  PersistentMemoryAllocator* allocator_;
-  PersistentMemoryAllocator::Iterator sample_iter_;
+  // The object that manages records inside persistent memory. This is owned
+  // externally (typically by a PersistentHistogramAllocator) and is expected
+  // to live beyond the life of this object.
+  PersistentSampleMapRecords* records_;
 
   DISALLOW_COPY_AND_ASSIGN(PersistentSampleMap);
 };
diff --git a/base/metrics/persistent_sample_map_unittest.cc b/base/metrics/persistent_sample_map_unittest.cc
index 52c3cef..48e9900 100644
--- a/base/metrics/persistent_sample_map_unittest.cc
+++ b/base/metrics/persistent_sample_map_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "base/metrics/persistent_histogram_allocator.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace base {
@@ -14,10 +15,9 @@
 TEST(PersistentSampleMapTest, AccumulateTest) {
   LocalPersistentMemoryAllocator allocator(64 << 10, 0, "");  // 64 KiB
 
-  HistogramSamples::Metadata* meta =
-      allocator.GetAsObject<HistogramSamples::Metadata>(
-          allocator.Allocate(sizeof(HistogramSamples::Metadata), 0), 0);
-  PersistentSampleMap samples(1, &allocator, meta);
+  HistogramSamples::Metadata meta;
+  PersistentSparseHistogramDataManager manager(&allocator);
+  PersistentSampleMap samples(1, &manager, &meta);
 
   samples.Accumulate(1, 100);
   samples.Accumulate(2, 200);
@@ -33,10 +33,9 @@
 TEST(PersistentSampleMapTest, Accumulate_LargeValuesDontOverflow) {
   LocalPersistentMemoryAllocator allocator(64 << 10, 0, "");  // 64 KiB
 
-  HistogramSamples::Metadata* meta =
-      allocator.GetAsObject<HistogramSamples::Metadata>(
-          allocator.Allocate(sizeof(HistogramSamples::Metadata), 0), 0);
-  PersistentSampleMap samples(1, &allocator, meta);
+  HistogramSamples::Metadata meta;
+  PersistentSparseHistogramDataManager manager(&allocator);
+  PersistentSampleMap samples(1, &manager, &meta);
 
   samples.Accumulate(250000000, 100);
   samples.Accumulate(500000000, 200);
@@ -52,19 +51,16 @@
 TEST(PersistentSampleMapTest, AddSubtractTest) {
   LocalPersistentMemoryAllocator allocator(64 << 10, 0, "");  // 64 KiB
 
-  HistogramSamples::Metadata* meta1 =
-      allocator.GetAsObject<HistogramSamples::Metadata>(
-          allocator.Allocate(sizeof(HistogramSamples::Metadata), 0), 0);
-  HistogramSamples::Metadata* meta2 =
-      allocator.GetAsObject<HistogramSamples::Metadata>(
-          allocator.Allocate(sizeof(HistogramSamples::Metadata), 0), 0);
-  PersistentSampleMap samples1(1, &allocator, meta1);
-  PersistentSampleMap samples2(2, &allocator, meta2);
-
+  HistogramSamples::Metadata meta1;
+  PersistentSparseHistogramDataManager manager1(&allocator);
+  PersistentSampleMap samples1(1, &manager1, &meta1);
   samples1.Accumulate(1, 100);
   samples1.Accumulate(2, 100);
   samples1.Accumulate(3, 100);
 
+  HistogramSamples::Metadata meta2;
+  PersistentSparseHistogramDataManager manager2(&allocator);
+  PersistentSampleMap samples2(2, &manager2, &meta2);
   samples2.Accumulate(1, 200);
   samples2.Accumulate(2, 200);
   samples2.Accumulate(4, 200);
@@ -91,10 +87,9 @@
 TEST(PersistentSampleMapTest, PersistenceTest) {
   LocalPersistentMemoryAllocator allocator(64 << 10, 0, "");  // 64 KiB
 
-  HistogramSamples::Metadata* meta12 =
-      allocator.GetAsObject<HistogramSamples::Metadata>(
-          allocator.Allocate(sizeof(HistogramSamples::Metadata), 0), 0);
-  PersistentSampleMap samples1(12, &allocator, meta12);
+  HistogramSamples::Metadata meta12;
+  PersistentSparseHistogramDataManager manager1(&allocator);
+  PersistentSampleMap samples1(12, &manager1, &meta12);
   samples1.Accumulate(1, 100);
   samples1.Accumulate(2, 200);
   samples1.Accumulate(1, -200);
@@ -104,7 +99,8 @@
   EXPECT_EQ(100, samples1.TotalCount());
   EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount());
 
-  PersistentSampleMap samples2(12, &allocator, meta12);
+  PersistentSparseHistogramDataManager manager2(&allocator);
+  PersistentSampleMap samples2(12, &manager2, &meta12);
   EXPECT_EQ(samples1.id(), samples2.id());
   EXPECT_EQ(samples1.sum(), samples2.sum());
   EXPECT_EQ(samples1.redundant_count(), samples2.redundant_count());
@@ -123,15 +119,26 @@
   EXPECT_EQ(samples1.sum(), samples2.sum());
   EXPECT_EQ(samples1.redundant_count(), samples2.redundant_count());
   EXPECT_EQ(samples1.TotalCount(), samples2.TotalCount());
+
+  EXPECT_EQ(0, samples2.GetCount(4));
+  EXPECT_EQ(0, samples1.GetCount(4));
+  samples1.Accumulate(4, 400);
+  EXPECT_EQ(400, samples2.GetCount(4));
+  EXPECT_EQ(400, samples1.GetCount(4));
+  samples2.Accumulate(4, 4000);
+  EXPECT_EQ(4400, samples2.GetCount(4));
+  EXPECT_EQ(4400, samples1.GetCount(4));
+  EXPECT_EQ(samples1.sum(), samples2.sum());
+  EXPECT_EQ(samples1.redundant_count(), samples2.redundant_count());
+  EXPECT_EQ(samples1.TotalCount(), samples2.TotalCount());
 }
 
 TEST(PersistentSampleMapIteratorTest, IterateTest) {
   LocalPersistentMemoryAllocator allocator(64 << 10, 0, "");  // 64 KiB
 
-  HistogramSamples::Metadata* meta =
-      allocator.GetAsObject<HistogramSamples::Metadata>(
-          allocator.Allocate(sizeof(HistogramSamples::Metadata), 0), 0);
-  PersistentSampleMap samples(1, &allocator, meta);
+  HistogramSamples::Metadata meta;
+  PersistentSparseHistogramDataManager manager(&allocator);
+  PersistentSampleMap samples(1, &manager, &meta);
   samples.Accumulate(1, 100);
   samples.Accumulate(2, 200);
   samples.Accumulate(4, -300);
@@ -168,27 +175,25 @@
 TEST(PersistentSampleMapIteratorTest, SkipEmptyRanges) {
   LocalPersistentMemoryAllocator allocator(64 << 10, 0, "");  // 64 KiB
 
-  HistogramSamples::Metadata* meta =
-      allocator.GetAsObject<HistogramSamples::Metadata>(
-          allocator.Allocate(sizeof(HistogramSamples::Metadata), 0), 0);
-  PersistentSampleMap samples(1, &allocator, meta);
-  samples.Accumulate(5, 1);
-  samples.Accumulate(10, 2);
-  samples.Accumulate(15, 3);
-  samples.Accumulate(20, 4);
-  samples.Accumulate(25, 5);
+  HistogramSamples::Metadata meta1;
+  PersistentSparseHistogramDataManager manager1(&allocator);
+  PersistentSampleMap samples1(1, &manager1, &meta1);
+  samples1.Accumulate(5, 1);
+  samples1.Accumulate(10, 2);
+  samples1.Accumulate(15, 3);
+  samples1.Accumulate(20, 4);
+  samples1.Accumulate(25, 5);
 
-  HistogramSamples::Metadata* meta2 =
-      allocator.GetAsObject<HistogramSamples::Metadata>(
-          allocator.Allocate(sizeof(HistogramSamples::Metadata), 0), 0);
-  PersistentSampleMap samples2(2, &allocator, meta2);
+  HistogramSamples::Metadata meta2;
+  PersistentSparseHistogramDataManager manager2(&allocator);
+  PersistentSampleMap samples2(2, &manager2, &meta2);
   samples2.Accumulate(5, 1);
   samples2.Accumulate(20, 4);
   samples2.Accumulate(25, 5);
 
-  samples.Subtract(samples2);
+  samples1.Subtract(samples2);
 
-  std::unique_ptr<SampleCountIterator> it = samples.Iterator();
+  std::unique_ptr<SampleCountIterator> it = samples1.Iterator();
   EXPECT_FALSE(it->Done());
 
   HistogramBase::Sample min;
@@ -217,10 +222,9 @@
 TEST(PersistentSampleMapIteratorDeathTest, IterateDoneTest) {
   LocalPersistentMemoryAllocator allocator(64 << 10, 0, "");  // 64 KiB
 
-  HistogramSamples::Metadata* meta =
-      allocator.GetAsObject<HistogramSamples::Metadata>(
-          allocator.Allocate(sizeof(HistogramSamples::Metadata), 0), 0);
-  PersistentSampleMap samples(1, &allocator, meta);
+  HistogramSamples::Metadata meta;
+  PersistentSparseHistogramDataManager manager(&allocator);
+  PersistentSampleMap samples(1, &manager, &meta);
 
   std::unique_ptr<SampleCountIterator> it = samples.Iterator();
 
diff --git a/base/metrics/sparse_histogram.cc b/base/metrics/sparse_histogram.cc
index 31fcfd9..e2bf4bfe 100644
--- a/base/metrics/sparse_histogram.cc
+++ b/base/metrics/sparse_histogram.cc
@@ -74,7 +74,7 @@
 
 // static
 std::unique_ptr<HistogramBase> SparseHistogram::PersistentCreate(
-    PersistentMemoryAllocator* allocator,
+    PersistentHistogramAllocator* allocator,
     const std::string& name,
     HistogramSamples::Metadata* meta,
     HistogramSamples::Metadata* logged_meta) {
@@ -165,7 +165,7 @@
       samples_(new SampleMap(HashMetricName(name))),
       logged_samples_(new SampleMap(samples_->id())) {}
 
-SparseHistogram::SparseHistogram(PersistentMemoryAllocator* allocator,
+SparseHistogram::SparseHistogram(PersistentHistogramAllocator* allocator,
                                  const std::string& name,
                                  HistogramSamples::Metadata* meta,
                                  HistogramSamples::Metadata* logged_meta)
diff --git a/base/metrics/sparse_histogram.h b/base/metrics/sparse_histogram.h
index f0296cb..da373a2 100644
--- a/base/metrics/sparse_histogram.h
+++ b/base/metrics/sparse_histogram.h
@@ -51,7 +51,7 @@
     } while (0)
 
 class HistogramSamples;
-class PersistentMemoryAllocator;
+class PersistentHistogramAllocator;
 
 class BASE_EXPORT SparseHistogram : public HistogramBase {
  public:
@@ -61,7 +61,7 @@
 
   // Create a histogram using data in persistent storage.
   static std::unique_ptr<HistogramBase> PersistentCreate(
-      PersistentMemoryAllocator* allocator,
+      PersistentHistogramAllocator* allocator,
       const std::string& name,
       HistogramSamples::Metadata* meta,
       HistogramSamples::Metadata* logged_meta);
@@ -91,7 +91,7 @@
   // Clients should always use FactoryGet to create SparseHistogram.
   explicit SparseHistogram(const std::string& name);
 
-  SparseHistogram(PersistentMemoryAllocator* allocator,
+  SparseHistogram(PersistentHistogramAllocator* allocator,
                   const std::string& name,
                   HistogramSamples::Metadata* meta,
                   HistogramSamples::Metadata* logged_meta);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/compositor/OWNERS
index 1e26cac..c853dcd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/OWNERS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/OWNERS
@@ -1,5 +1,4 @@
 changwan@chromium.org
 dtrainor@chromium.org
-jaekyun@chromium.org
 
 per-file Compositor*=mdjones@chromium.org
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/OWNERS
new file mode 100644
index 0000000..6000f0e
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/OWNERS
@@ -0,0 +1,2 @@
+changwan@chromium.org
+dtrainor@chromium.org
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/OWNERS b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/OWNERS
new file mode 100644
index 0000000..6000f0e
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/OWNERS
@@ -0,0 +1,2 @@
+changwan@chromium.org
+dtrainor@chromium.org
diff --git a/chrome/browser/android/compositor/OWNERS b/chrome/browser/android/compositor/OWNERS
index ccfdc97b..d122a24d 100644
--- a/chrome/browser/android/compositor/OWNERS
+++ b/chrome/browser/android/compositor/OWNERS
@@ -1,6 +1,5 @@
 changwan@chromium.org
 dtrainor@chromium.org
-jaekyun@chromium.org
 
 per-file *contextual_search*=donnd@chromium.org
 per-file *contextual_search*=pedrosimonetti@chromium.org
diff --git a/chrome/browser/android/tab_web_contents_delegate_android.cc b/chrome/browser/android/tab_web_contents_delegate_android.cc
index 2068778c..ded591c 100644
--- a/chrome/browser/android/tab_web_contents_delegate_android.cc
+++ b/chrome/browser/android/tab_web_contents_delegate_android.cc
@@ -19,7 +19,6 @@
 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
 #include "chrome/browser/media/media_stream_capture_indicator.h"
 #include "chrome/browser/media/protected_media_identifier_permission_context.h"
-#include "chrome/browser/media/protected_media_identifier_permission_context_factory.h"
 #include "chrome/browser/prerender/prerender_manager.h"
 #include "chrome/browser/prerender/prerender_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/background_sync/background_sync_permission_context_factory.cc b/chrome/browser/background_sync/background_sync_permission_context_factory.cc
deleted file mode 100644
index 36f0006..0000000
--- a/chrome/browser/background_sync/background_sync_permission_context_factory.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2016 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 "chrome/browser/background_sync/background_sync_permission_context_factory.h"
-
-#include "chrome/browser/background_sync/background_sync_permission_context.h"
-#include "chrome/browser/profiles/profile.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-
-// static
-BackgroundSyncPermissionContext*
-BackgroundSyncPermissionContextFactory::GetForProfile(Profile* profile) {
-  return static_cast<BackgroundSyncPermissionContext*>(
-      GetInstance()->GetServiceForBrowserContext(profile, true /* create */));
-}
-
-// static
-BackgroundSyncPermissionContextFactory*
-BackgroundSyncPermissionContextFactory::GetInstance() {
-  return base::Singleton<BackgroundSyncPermissionContextFactory>::get();
-}
-
-BackgroundSyncPermissionContextFactory::BackgroundSyncPermissionContextFactory()
-    : PermissionContextFactoryBase(
-          "BackgroundSyncPermissionContext",
-          BrowserContextDependencyManager::GetInstance()) {}
-
-KeyedService* BackgroundSyncPermissionContextFactory::BuildServiceInstanceFor(
-    content::BrowserContext* profile) const {
-  return new BackgroundSyncPermissionContext(static_cast<Profile*>(profile));
-}
diff --git a/chrome/browser/background_sync/background_sync_permission_context_factory.h b/chrome/browser/background_sync/background_sync_permission_context_factory.h
deleted file mode 100644
index 3dbccdf..0000000
--- a/chrome/browser/background_sync/background_sync_permission_context_factory.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef CHROME_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_PERMISSION_CONTEXT_FACTORY_H_
-#define CHROME_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_PERMISSION_CONTEXT_FACTORY_H_
-
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "chrome/browser/permissions/permission_context_factory_base.h"
-
-class BackgroundSyncPermissionContext;
-class Profile;
-
-class BackgroundSyncPermissionContextFactory
-    : public PermissionContextFactoryBase {
- public:
-  static BackgroundSyncPermissionContext* GetForProfile(Profile* profile);
-  static BackgroundSyncPermissionContextFactory* GetInstance();
-
- private:
-  friend struct base::DefaultSingletonTraits<
-      BackgroundSyncPermissionContextFactory>;
-
-  BackgroundSyncPermissionContextFactory();
-  ~BackgroundSyncPermissionContextFactory() override = default;
-
-  // BrowserContextKeyedBaseFactory methods:
-  KeyedService* BuildServiceInstanceFor(
-      content::BrowserContext* profile) const override;
-
-  DISALLOW_COPY_AND_ASSIGN(BackgroundSyncPermissionContextFactory);
-};
-
-#endif  // CHROME_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_PERMISSION_CONTEXT_FACTORY_H_
diff --git a/chrome/browser/chromeos/attestation/platform_verification_flow.cc b/chrome/browser/chromeos/attestation/platform_verification_flow.cc
index e52214e..2648a961 100644
--- a/chrome/browser/chromeos/attestation/platform_verification_flow.cc
+++ b/chrome/browser/chromeos/attestation/platform_verification_flow.cc
@@ -17,8 +17,7 @@
 #include "chrome/browser/chromeos/attestation/attestation_signed_data.pb.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
-#include "chrome/browser/media/protected_media_identifier_permission_context.h"
-#include "chrome/browser/media/protected_media_identifier_permission_context_factory.h"
+#include "chrome/browser/permissions/permission_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chromeos/attestation/attestation_flow.h"
 #include "chromeos/chromeos_switches.h"
@@ -31,6 +30,7 @@
 #include "components/user_manager/user.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/permission_type.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/user_metrics.h"
@@ -38,6 +38,7 @@
 #include "content/public/common/url_constants.h"
 #include "net/cert/pem_tokenizer.h"
 #include "net/cert/x509_certificate.h"
+#include "third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h"
 
 namespace {
 
@@ -105,21 +106,20 @@
   }
 
   bool IsPermittedByUser(content::WebContents* web_contents) override {
-    ProtectedMediaIdentifierPermissionContext* permission_context =
-        ProtectedMediaIdentifierPermissionContextFactory::GetForProfile(
-            Profile::FromBrowserContext(web_contents->GetBrowserContext()));
-
     // TODO(xhwang): Using delegate_->GetURL() here is not right. The platform
     // verification may be requested by a frame from a different origin. This
     // will be solved when http://crbug.com/454847 is fixed.
     const GURL& requesting_origin = GetURL(web_contents).GetOrigin();
 
     GURL embedding_origin = web_contents->GetLastCommittedURL().GetOrigin();
+    blink::mojom::PermissionStatus status =
+        PermissionManager::Get(
+            Profile::FromBrowserContext(web_contents->GetBrowserContext()))
+            ->GetPermissionStatus(
+                content::PermissionType::PROTECTED_MEDIA_IDENTIFIER,
+                requesting_origin, embedding_origin);
 
-    ContentSetting content_setting = permission_context->GetPermissionStatus(
-        requesting_origin, embedding_origin);
-
-    return content_setting == CONTENT_SETTING_ALLOW;
+    return status == blink::mojom::PermissionStatus::GRANTED;
   }
 
   bool IsInSupportedMode(content::WebContents* web_contents) override {
diff --git a/chrome/browser/geolocation/geolocation_permission_context_factory.cc b/chrome/browser/geolocation/geolocation_permission_context_factory.cc
deleted file mode 100644
index 2c173d2..0000000
--- a/chrome/browser/geolocation/geolocation_permission_context_factory.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-// 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 "chrome/browser/geolocation/geolocation_permission_context_factory.h"
-
-#include "chrome/browser/profiles/incognito_helpers.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/features.h"
-#include "chrome/common/pref_names.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/pref_registry/pref_registry_syncable.h"
-#if BUILDFLAG(ANDROID_JAVA_UI)
-#include "chrome/browser/geolocation/geolocation_permission_context_android.h"
-#else
-#include "chrome/browser/geolocation/geolocation_permission_context.h"
-#endif
-
-
-// static
-GeolocationPermissionContext*
-GeolocationPermissionContextFactory::GetForProfile(Profile* profile) {
-  return static_cast<GeolocationPermissionContext*>(
-      GetInstance()->GetServiceForBrowserContext(profile, true));
-}
-
-// static
-GeolocationPermissionContextFactory*
-GeolocationPermissionContextFactory::GetInstance() {
-  return base::Singleton<GeolocationPermissionContextFactory>::get();
-}
-
-#if !BUILDFLAG(ANDROID_JAVA_UI)
-GeolocationPermissionContextFactory::GeolocationPermissionContextFactory()
-    : PermissionContextFactoryBase(
-          "GeolocationPermissionContext",
-          BrowserContextDependencyManager::GetInstance()) {
-}
-#else
-GeolocationPermissionContextFactory::GeolocationPermissionContextFactory()
-    : PermissionContextFactoryBase(
-          "GeolocationPermissionContextAndroid",
-          BrowserContextDependencyManager::GetInstance()) {
-}
-#endif
-
-
-GeolocationPermissionContextFactory::~GeolocationPermissionContextFactory() {
-}
-
-KeyedService*
-GeolocationPermissionContextFactory::BuildServiceInstanceFor(
-    content::BrowserContext* profile) const {
-#if !BUILDFLAG(ANDROID_JAVA_UI)
-  return new GeolocationPermissionContext(static_cast<Profile*>(profile));
-#else
-  return new GeolocationPermissionContextAndroid(
-      static_cast<Profile*>(profile));
-#endif
-}
diff --git a/chrome/browser/geolocation/geolocation_permission_context_factory.h b/chrome/browser/geolocation/geolocation_permission_context_factory.h
deleted file mode 100644
index abbd17c..0000000
--- a/chrome/browser/geolocation/geolocation_permission_context_factory.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// 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.
-
-#ifndef CHROME_BROWSER_GEOLOCATION_GEOLOCATION_PERMISSION_CONTEXT_FACTORY_H_
-#define CHROME_BROWSER_GEOLOCATION_GEOLOCATION_PERMISSION_CONTEXT_FACTORY_H_
-
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "base/values.h"
-#include "chrome/browser/permissions/permission_context_factory_base.h"
-#include "components/prefs/pref_service.h"
-
-class GeolocationPermissionContext;
-class PrefRegistrySyncable;
-class Profile;
-
-class GeolocationPermissionContextFactory
-    : public PermissionContextFactoryBase {
- public:
-  static GeolocationPermissionContext* GetForProfile(Profile* profile);
-
-  static GeolocationPermissionContextFactory* GetInstance();
-
- private:
-  friend struct base::DefaultSingletonTraits<
-      GeolocationPermissionContextFactory>;
-
-  GeolocationPermissionContextFactory();
-  ~GeolocationPermissionContextFactory() override;
-
-  // BrowserContextKeyedBaseFactory methods:
-  KeyedService* BuildServiceInstanceFor(
-      content::BrowserContext* profile) const override;
-
-  DISALLOW_COPY_AND_ASSIGN(GeolocationPermissionContextFactory);
-};
-
-#endif  // CHROME_BROWSER_GEOLOCATION_GEOLOCATION_PERMISSION_CONTEXT_FACTORY_H_
diff --git a/chrome/browser/geolocation/geolocation_permission_context_unittest.cc b/chrome/browser/geolocation/geolocation_permission_context_unittest.cc
index 122499b..1360fd14 100644
--- a/chrome/browser/geolocation/geolocation_permission_context_unittest.cc
+++ b/chrome/browser/geolocation/geolocation_permission_context_unittest.cc
@@ -22,8 +22,10 @@
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
-#include "chrome/browser/geolocation/geolocation_permission_context_factory.h"
+#include "chrome/browser/geolocation/geolocation_permission_context.h"
 #include "chrome/browser/infobars/infobar_service.h"
+#include "chrome/browser/permissions/permission_context_base.h"
+#include "chrome/browser/permissions/permission_manager.h"
 #include "chrome/browser/permissions/permission_request_id.h"
 #include "chrome/browser/ui/website_settings/permission_bubble_request.h"
 #include "chrome/common/chrome_switches.h"
@@ -280,8 +282,9 @@
 #endif
   InfoBarService::CreateForWebContents(web_contents());
   TabSpecificContentSettings::CreateForWebContents(web_contents());
-  geolocation_permission_context_ =
-      GeolocationPermissionContextFactory::GetForProfile(profile());
+  geolocation_permission_context_ = static_cast<GeolocationPermissionContext*>(
+      PermissionManager::Get(profile())->GetPermissionContext(
+          content::PermissionType::GEOLOCATION));
 #if BUILDFLAG(ANDROID_JAVA_UI)
   static_cast<GeolocationPermissionContextAndroid*>(
       geolocation_permission_context_)
diff --git a/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc b/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc
index febbb01..4ffceff9a 100644
--- a/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc
+++ b/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc
@@ -5,13 +5,13 @@
 #include "chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h"
 
 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
-#include "chrome/browser/geolocation/geolocation_permission_context.h"
-#include "chrome/browser/geolocation/geolocation_permission_context_factory.h"
+#include "chrome/browser/permissions/permission_manager.h"
 #include "chrome/browser/permissions/permission_request_id.h"
 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/render_messages.h"
 #include "components/content_settings/content/common/content_settings_messages.h"
+#include "content/public/browser/permission_type.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
@@ -23,9 +23,9 @@
 
 namespace {
 
-void CallbackContentSettingWrapper(const base::Callback<void(bool)>& callback,
-                                   ContentSetting content_setting) {
-  callback.Run(content_setting == CONTENT_SETTING_ALLOW);
+void CallbackWrapper(const base::Callback<void(bool)>& callback,
+                     blink::mojom::PermissionStatus status) {
+  callback.Run(status == blink::mojom::PermissionStatus::GRANTED);
 }
 
 }  // anonymous namespace
@@ -183,11 +183,10 @@
   // ChromeWebViewPermissionHelperDelegate because this callback is called from
   // ChromeWebViewPermissionHelperDelegate::SetPermission.
   const WebViewPermissionHelper::PermissionResponseCallback
-      permission_callback =
-          base::Bind(&ChromeWebViewPermissionHelperDelegate::
-                         OnGeolocationPermissionResponse,
-                     weak_factory_.GetWeakPtr(), bridge_id,
-                     base::Bind(&CallbackContentSettingWrapper, callback));
+      permission_callback = base::Bind(&ChromeWebViewPermissionHelperDelegate::
+                                           OnGeolocationPermissionResponse,
+                                       weak_factory_.GetWeakPtr(), bridge_id,
+                                       base::Bind(&CallbackWrapper, callback));
   int request_id = web_view_permission_helper()->RequestPermission(
       WEB_VIEW_PERMISSION_TYPE_GEOLOCATION,
       request_info,
@@ -198,7 +197,7 @@
 
 void ChromeWebViewPermissionHelperDelegate::OnGeolocationPermissionResponse(
     int bridge_id,
-    const base::Callback<void(ContentSetting)>& callback,
+    const base::Callback<void(blink::mojom::PermissionStatus)>& callback,
     bool allow,
     const std::string& user_input) {
   // The <webview> embedder has allowed the permission. We now need to make sure
@@ -206,7 +205,7 @@
   RemoveBridgeID(bridge_id);
 
   if (!allow || !web_view_guest()->attached()) {
-    callback.Run(CONTENT_SETTING_BLOCK);
+    callback.Run(blink::mojom::PermissionStatus::DENIED);
     return;
   }
 
@@ -226,13 +225,13 @@
 
   Profile* profile = Profile::FromBrowserContext(
       web_view_guest()->browser_context());
-  GeolocationPermissionContextFactory::GetForProfile(profile)->
-      RequestPermission(
-          web_contents,
-          request_id,
-          web_view_guest()->embedder_web_contents()
-          ->GetLastCommittedURL().GetOrigin(),
-          callback);
+  PermissionManager::Get(profile)->RequestPermission(
+      content::PermissionType::GEOLOCATION, web_contents->GetMainFrame(),
+      web_view_guest()
+          ->embedder_web_contents()
+          ->GetLastCommittedURL()
+          .GetOrigin(),
+      callback);
 }
 
 void ChromeWebViewPermissionHelperDelegate::CancelGeolocationPermissionRequest(
diff --git a/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h b/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h
index 9fc03c30..d033a310 100644
--- a/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h
+++ b/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h
@@ -6,9 +6,9 @@
 #define CHROME_BROWSER_GUEST_VIEW_WEB_VIEW_CHROME_WEB_VIEW_PERMISSION_HELPER_DELEGATE_H_
 
 #include "base/macros.h"
-#include "components/content_settings/core/common/content_settings.h"
 #include "extensions/browser/guest_view/web_view/web_view_permission_helper.h"
 #include "extensions/browser/guest_view/web_view/web_view_permission_helper_delegate.h"
+#include "third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h"
 
 namespace extensions {
 class WebViewGuest;
@@ -76,7 +76,7 @@
 
   void OnGeolocationPermissionResponse(
       int bridge_id,
-      const base::Callback<void(ContentSetting)>& callback,
+      const base::Callback<void(blink::mojom::PermissionStatus)>& callback,
       bool allow,
       const std::string& user_input);
 
diff --git a/chrome/browser/media/media_permission.cc b/chrome/browser/media/media_permission.cc
index 4ba86813..aded051 100644
--- a/chrome/browser/media/media_permission.cc
+++ b/chrome/browser/media/media_permission.cc
@@ -7,8 +7,8 @@
 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
 #include "chrome/browser/media/media_stream_device_permission_context.h"
 #include "chrome/browser/media/media_stream_device_permissions.h"
-#include "chrome/browser/permissions/permission_context.h"
 #include "chrome/browser/permissions/permission_context_base.h"
+#include "chrome/browser/permissions/permission_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "content/public/browser/permission_manager.h"
@@ -54,8 +54,11 @@
   // denial reason to kill switch.
   content::PermissionType permission_type =
       ContentSettingsTypeToPermission(content_type_);
+  // TODO(raymes): This calls into GetPermissionContext which is a private
+  // member of PermissionManager. Remove this call when this class is refactored
+  // into a PermissionContext. See crbug.com/596786.
   PermissionContextBase* permission_context =
-      PermissionContext::Get(profile_, permission_type);
+      PermissionManager::Get(profile_)->GetPermissionContext(permission_type);
 
   if (!permission_context) {
     *denial_reason = content::MEDIA_DEVICE_PERMISSION_DENIED;
diff --git a/chrome/browser/media/media_stream_camera_permission_context_factory.cc b/chrome/browser/media/media_stream_camera_permission_context_factory.cc
deleted file mode 100644
index b48c182..0000000
--- a/chrome/browser/media/media_stream_camera_permission_context_factory.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2015 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 "chrome/browser/media/media_stream_camera_permission_context_factory.h"
-
-#include "chrome/browser/media/media_stream_device_permission_context.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
-#include "chrome/browser/profiles/profile.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "content/public/browser/permission_type.h"
-
-MediaStreamCameraPermissionContextFactory::
-    MediaStreamCameraPermissionContextFactory()
-    : PermissionContextFactoryBase(
-          "MediaStreamCameraPermissionContext",
-          BrowserContextDependencyManager::GetInstance()) {}
-
-MediaStreamCameraPermissionContextFactory::
-    ~MediaStreamCameraPermissionContextFactory() {}
-
-KeyedService*
-MediaStreamCameraPermissionContextFactory::BuildServiceInstanceFor(
-    content::BrowserContext* profile) const {
-  return new MediaStreamDevicePermissionContext(
-      static_cast<Profile*>(profile), content::PermissionType::VIDEO_CAPTURE,
-      CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA);
-}
-
-// static
-MediaStreamCameraPermissionContextFactory*
-MediaStreamCameraPermissionContextFactory::GetInstance() {
-  return base::Singleton<MediaStreamCameraPermissionContextFactory>::get();
-}
-
-// static
-MediaStreamDevicePermissionContext*
-MediaStreamCameraPermissionContextFactory::GetForProfile(Profile* profile) {
-  return static_cast<MediaStreamDevicePermissionContext*>(
-      GetInstance()->GetServiceForBrowserContext(profile, true));
-}
diff --git a/chrome/browser/media/media_stream_camera_permission_context_factory.h b/chrome/browser/media/media_stream_camera_permission_context_factory.h
deleted file mode 100644
index 7a18c4bf..0000000
--- a/chrome/browser/media/media_stream_camera_permission_context_factory.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef CHROME_BROWSER_MEDIA_MEDIA_STREAM_CAMERA_PERMISSION_CONTEXT_FACTORY_H_
-#define CHROME_BROWSER_MEDIA_MEDIA_STREAM_CAMERA_PERMISSION_CONTEXT_FACTORY_H_
-
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "chrome/browser/permissions/permission_context_factory_base.h"
-#include "components/content_settings/core/common/content_settings_types.h"
-
-class MediaStreamDevicePermissionContext;
-class Profile;
-
-class MediaStreamCameraPermissionContextFactory
-    : public PermissionContextFactoryBase {
- public:
-  static MediaStreamDevicePermissionContext* GetForProfile(Profile* profile);
-  static MediaStreamCameraPermissionContextFactory* GetInstance();
-
- private:
-  friend struct base::DefaultSingletonTraits<
-      MediaStreamCameraPermissionContextFactory>;
-
-  MediaStreamCameraPermissionContextFactory();
-  ~MediaStreamCameraPermissionContextFactory() override;
-
-  // BrowserContextKeyedBaseFactory methods:
-  KeyedService* BuildServiceInstanceFor(
-      content::BrowserContext* profile) const override;
-
-  DISALLOW_COPY_AND_ASSIGN(MediaStreamCameraPermissionContextFactory);
-};
-
-#endif  // CHROME_BROWSER_MEDIA_MEDIA_STREAM_CAMERA_PERMISSION_CONTEXT_FACTORY_H_
diff --git a/chrome/browser/media/media_stream_mic_permission_context_factory.cc b/chrome/browser/media/media_stream_mic_permission_context_factory.cc
deleted file mode 100644
index 97d54f5..0000000
--- a/chrome/browser/media/media_stream_mic_permission_context_factory.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2015 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 "chrome/browser/media/media_stream_mic_permission_context_factory.h"
-
-#include "chrome/browser/media/media_stream_device_permission_context.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
-#include "chrome/browser/profiles/profile.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "content/public/browser/permission_type.h"
-
-MediaStreamMicPermissionContextFactory::MediaStreamMicPermissionContextFactory()
-    : PermissionContextFactoryBase(
-          "MediaStreamMicPermissionContext",
-          BrowserContextDependencyManager::GetInstance()) {}
-
-MediaStreamMicPermissionContextFactory::
-    ~MediaStreamMicPermissionContextFactory() {}
-
-KeyedService* MediaStreamMicPermissionContextFactory::BuildServiceInstanceFor(
-    content::BrowserContext* profile) const {
-  return new MediaStreamDevicePermissionContext(
-      static_cast<Profile*>(profile), content::PermissionType::AUDIO_CAPTURE,
-      CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC);
-}
-
-// static
-MediaStreamMicPermissionContextFactory*
-MediaStreamMicPermissionContextFactory::GetInstance() {
-  return base::Singleton<MediaStreamMicPermissionContextFactory>::get();
-}
-
-// static
-MediaStreamDevicePermissionContext*
-MediaStreamMicPermissionContextFactory::GetForProfile(Profile* profile) {
-  return static_cast<MediaStreamDevicePermissionContext*>(
-      GetInstance()->GetServiceForBrowserContext(profile, true));
-}
diff --git a/chrome/browser/media/media_stream_mic_permission_context_factory.h b/chrome/browser/media/media_stream_mic_permission_context_factory.h
deleted file mode 100644
index dd24c76..0000000
--- a/chrome/browser/media/media_stream_mic_permission_context_factory.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef CHROME_BROWSER_MEDIA_MEDIA_STREAM_MIC_PERMISSION_CONTEXT_FACTORY_H_
-#define CHROME_BROWSER_MEDIA_MEDIA_STREAM_MIC_PERMISSION_CONTEXT_FACTORY_H_
-
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "chrome/browser/permissions/permission_context_factory_base.h"
-#include "components/content_settings/core/common/content_settings_types.h"
-
-class MediaStreamDevicePermissionContext;
-class Profile;
-
-class MediaStreamMicPermissionContextFactory
-    : public PermissionContextFactoryBase {
- public:
-  static MediaStreamDevicePermissionContext* GetForProfile(Profile* profile);
-  static MediaStreamMicPermissionContextFactory* GetInstance();
-
- private:
-  friend struct base::DefaultSingletonTraits<
-      MediaStreamMicPermissionContextFactory>;
-
-  MediaStreamMicPermissionContextFactory();
-  ~MediaStreamMicPermissionContextFactory() override;
-
-  // BrowserContextKeyedBaseFactory methods:
-  KeyedService* BuildServiceInstanceFor(
-      content::BrowserContext* profile) const override;
-
-  DISALLOW_COPY_AND_ASSIGN(MediaStreamMicPermissionContextFactory);
-};
-
-#endif  // CHROME_BROWSER_MEDIA_MEDIA_STREAM_MIC_PERMISSION_CONTEXT_FACTORY_H_
diff --git a/chrome/browser/media/midi_permission_context_factory.cc b/chrome/browser/media/midi_permission_context_factory.cc
deleted file mode 100644
index b4c974a..0000000
--- a/chrome/browser/media/midi_permission_context_factory.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2013 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 "chrome/browser/media/midi_permission_context_factory.h"
-
-#include "chrome/browser/media/midi_permission_context.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
-#include "chrome/browser/profiles/profile.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-
-// static
-MidiPermissionContext*
-MidiPermissionContextFactory::GetForProfile(Profile* profile) {
-  return static_cast<MidiPermissionContext*>(
-      GetInstance()->GetServiceForBrowserContext(profile, true));
-}
-
-// static
-MidiPermissionContextFactory*
-MidiPermissionContextFactory::GetInstance() {
-  return base::Singleton<MidiPermissionContextFactory>::get();
-}
-
-MidiPermissionContextFactory::MidiPermissionContextFactory()
-    : PermissionContextFactoryBase(
-          "MidiPermissionContext",
-          BrowserContextDependencyManager::GetInstance()) {
-}
-
-MidiPermissionContextFactory::~MidiPermissionContextFactory() {
-}
-
-KeyedService* MidiPermissionContextFactory::BuildServiceInstanceFor(
-    content::BrowserContext* profile) const {
-  return new MidiPermissionContext(static_cast<Profile*>(profile));
-}
diff --git a/chrome/browser/media/midi_permission_context_factory.h b/chrome/browser/media/midi_permission_context_factory.h
deleted file mode 100644
index 8407564..0000000
--- a/chrome/browser/media/midi_permission_context_factory.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef CHROME_BROWSER_MEDIA_MIDI_PERMISSION_CONTEXT_FACTORY_H_
-#define CHROME_BROWSER_MEDIA_MIDI_PERMISSION_CONTEXT_FACTORY_H_
-
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "chrome/browser/permissions/permission_context_factory_base.h"
-
-class MidiPermissionContext;
-class Profile;
-
-class MidiPermissionContextFactory
-    : public PermissionContextFactoryBase {
- public:
-  static MidiPermissionContext* GetForProfile(Profile* profile);
-  static MidiPermissionContextFactory* GetInstance();
-
- private:
-  friend struct base::DefaultSingletonTraits<MidiPermissionContextFactory>;
-
-  MidiPermissionContextFactory();
-  ~MidiPermissionContextFactory() override;
-
-  // BrowserContextKeyedBaseFactory methods:
-  KeyedService* BuildServiceInstanceFor(
-      content::BrowserContext* profile) const override;
-
-  DISALLOW_COPY_AND_ASSIGN(MidiPermissionContextFactory);
-};
-
-#endif  // CHROME_BROWSER_MEDIA_MIDI_PERMISSION_CONTEXT_FACTORY_H_
diff --git a/chrome/browser/media/protected_media_identifier_permission_context.h b/chrome/browser/media/protected_media_identifier_permission_context.h
index f3d711e..5e14c31 100644
--- a/chrome/browser/media/protected_media_identifier_permission_context.h
+++ b/chrome/browser/media/protected_media_identifier_permission_context.h
@@ -39,6 +39,7 @@
     : public PermissionContextBase {
  public:
   explicit ProtectedMediaIdentifierPermissionContext(Profile* profile);
+  ~ProtectedMediaIdentifierPermissionContext() override;
 
   // PermissionContextBase implementation.
 #if defined(OS_CHROMEOS)
@@ -55,8 +56,6 @@
                                const PermissionRequestID& id) override;
 
  private:
-  ~ProtectedMediaIdentifierPermissionContext() override;
-
   void UpdateTabContext(const PermissionRequestID& id,
                         const GURL& requesting_frame,
                         bool allowed) override;
diff --git a/chrome/browser/media/protected_media_identifier_permission_context_factory.cc b/chrome/browser/media/protected_media_identifier_permission_context_factory.cc
deleted file mode 100644
index 51fb5b1..0000000
--- a/chrome/browser/media/protected_media_identifier_permission_context_factory.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2013 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 "chrome/browser/media/protected_media_identifier_permission_context_factory.h"
-
-#include "chrome/browser/media/protected_media_identifier_permission_context.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/pref_names.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/pref_registry/pref_registry_syncable.h"
-
-// static
-ProtectedMediaIdentifierPermissionContext*
-ProtectedMediaIdentifierPermissionContextFactory::GetForProfile(
-    Profile* profile) {
-  return static_cast<ProtectedMediaIdentifierPermissionContext*>(
-      GetInstance()->GetServiceForBrowserContext(profile, true));
-}
-
-// static
-ProtectedMediaIdentifierPermissionContextFactory*
-ProtectedMediaIdentifierPermissionContextFactory::GetInstance() {
-  return base::Singleton<
-      ProtectedMediaIdentifierPermissionContextFactory>::get();
-}
-
-ProtectedMediaIdentifierPermissionContextFactory::
-ProtectedMediaIdentifierPermissionContextFactory()
-    : PermissionContextFactoryBase(
-          "ProtectedMediaIdentifierPermissionContext",
-          BrowserContextDependencyManager::GetInstance()) {
-}
-
-ProtectedMediaIdentifierPermissionContextFactory::
-~ProtectedMediaIdentifierPermissionContextFactory() {
-}
-
-KeyedService*
-ProtectedMediaIdentifierPermissionContextFactory::BuildServiceInstanceFor(
-    content::BrowserContext* profile) const {
-  return new ProtectedMediaIdentifierPermissionContext(
-      static_cast<Profile*>(profile));
-}
diff --git a/chrome/browser/media/protected_media_identifier_permission_context_factory.h b/chrome/browser/media/protected_media_identifier_permission_context_factory.h
deleted file mode 100644
index be2f6f5..0000000
--- a/chrome/browser/media/protected_media_identifier_permission_context_factory.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef CHROME_BROWSER_MEDIA_PROTECTED_MEDIA_IDENTIFIER_PERMISSION_CONTEXT_FACTORY_H_
-#define CHROME_BROWSER_MEDIA_PROTECTED_MEDIA_IDENTIFIER_PERMISSION_CONTEXT_FACTORY_H_
-
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "chrome/browser/permissions/permission_context_factory_base.h"
-
-class ProtectedMediaIdentifierPermissionContext;
-class Profile;
-
-class ProtectedMediaIdentifierPermissionContextFactory
-    : public PermissionContextFactoryBase {
- public:
-  static ProtectedMediaIdentifierPermissionContext* GetForProfile(
-      Profile* profile);
-
-  static ProtectedMediaIdentifierPermissionContextFactory* GetInstance();
-
- private:
-  friend struct base::DefaultSingletonTraits<
-      ProtectedMediaIdentifierPermissionContextFactory>;
-
-  ProtectedMediaIdentifierPermissionContextFactory();
-  ~ProtectedMediaIdentifierPermissionContextFactory() override;
-
-  // BrowserContextKeyedBaseFactory methods:
-  KeyedService* BuildServiceInstanceFor(
-      content::BrowserContext* profile) const override;
-
-  DISALLOW_COPY_AND_ASSIGN(
-      ProtectedMediaIdentifierPermissionContextFactory);
-};
-
-#endif  // CHROME_BROWSER_MEDIA_PROTECTED_MEDIA_IDENTIFIER_PERMISSION_CONTEXT_FACTORY_H_
diff --git a/chrome/browser/media_galleries/fileapi/safe_audio_video_checker.cc b/chrome/browser/media_galleries/fileapi/safe_audio_video_checker.cc
index a27e6cf..8346f85 100644
--- a/chrome/browser/media_galleries/fileapi/safe_audio_video_checker.cc
+++ b/chrome/browser/media_galleries/fileapi/safe_audio_video_checker.cc
@@ -35,7 +35,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   if (state_ != INITIAL_STATE)
     return;
-  state_ = PINGED_STATE;
+  state_ = STARTED_STATE;
 
   if (!file_.IsValid()) {
     callback_.Run(base::File::FILE_ERROR_SECURITY);
@@ -43,32 +43,25 @@
     return;
   }
 
-  utility_process_host_ = content::UtilityProcessHost::Create(
-      this, base::ThreadTaskRunnerHandle::Get())->AsWeakPtr();
-  utility_process_host_->SetName(l10n_util::GetStringUTF16(
-      IDS_UTILITY_PROCESS_MEDIA_FILE_CHECKER_NAME));
-  utility_process_host_->Send(new ChromeUtilityMsg_StartupPing);
-}
-
-SafeAudioVideoChecker::~SafeAudioVideoChecker() {}
-
-void SafeAudioVideoChecker::OnProcessStarted() {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  if (state_ != PINGED_STATE)
-    return;
-  state_ = STARTED_STATE;
-
   IPC::PlatformFileForTransit file_for_transit =
       IPC::TakePlatformFileForTransit(std::move(file_));
   if (file_for_transit == IPC::InvalidPlatformFileForTransit()) {
     OnCheckingFinished(false /* valid? */);
     return;
   }
+
+  utility_process_host_ = content::UtilityProcessHost::Create(
+      this, base::ThreadTaskRunnerHandle::Get())->AsWeakPtr();
+  utility_process_host_->SetName(l10n_util::GetStringUTF16(
+      IDS_UTILITY_PROCESS_MEDIA_FILE_CHECKER_NAME));
+
   const int64_t kFileDecodeTimeInMS = 250;
   utility_process_host_->Send(new ChromeUtilityMsg_CheckMediaFile(
       kFileDecodeTimeInMS, file_for_transit));
 }
 
+SafeAudioVideoChecker::~SafeAudioVideoChecker() {}
+
 void SafeAudioVideoChecker::OnCheckingFinished(bool valid) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   if (state_ != STARTED_STATE)
@@ -86,8 +79,6 @@
 bool SafeAudioVideoChecker::OnMessageReceived(const IPC::Message& message) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(SafeAudioVideoChecker, message)
-    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted,
-        OnProcessStarted)
     IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_CheckMediaFile_Finished,
         OnCheckingFinished)
     IPC_MESSAGE_UNHANDLED(handled = false)
diff --git a/chrome/browser/media_galleries/fileapi/safe_audio_video_checker.h b/chrome/browser/media_galleries/fileapi/safe_audio_video_checker.h
index 64efe48..2cb9b0e7 100644
--- a/chrome/browser/media_galleries/fileapi/safe_audio_video_checker.h
+++ b/chrome/browser/media_galleries/fileapi/safe_audio_video_checker.h
@@ -34,16 +34,12 @@
  private:
   enum State {
     INITIAL_STATE,
-    PINGED_STATE,
     STARTED_STATE,
     FINISHED_STATE
   };
 
   ~SafeAudioVideoChecker() override;
 
-  // Starts validation once the utility process has been started.
-  virtual void OnProcessStarted();
-
   // Notification of the result from the utility process.
   void OnCheckingFinished(bool valid);
 
diff --git a/chrome/browser/media_galleries/fileapi/safe_iapps_library_parser.cc b/chrome/browser/media_galleries/fileapi/safe_iapps_library_parser.cc
index abedc36..c599d16 100644
--- a/chrome/browser/media_galleries/fileapi/safe_iapps_library_parser.cc
+++ b/chrome/browser/media_galleries/fileapi/safe_iapps_library_parser.cc
@@ -65,27 +65,8 @@
       UtilityProcessHost::Create(this, task_runner.get())->AsWeakPtr();
   utility_process_host_->SetName(l10n_util::GetStringUTF16(
       IDS_UTILITY_PROCESS_MEDIA_LIBRARY_FILE_CHECKER_NAME));
-  // Wait for the startup notification before sending the main IPC to the
-  // utility process, so that we can dup the file handle.
-  utility_process_host_->Send(new ChromeUtilityMsg_StartupPing);
-  parser_state_ = PINGED_UTILITY_PROCESS_STATE;
-}
-
-void SafeIAppsLibraryParser::OnUtilityProcessStarted() {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (parser_state_ != PINGED_UTILITY_PROCESS_STATE)
-    return;
-
-  if (utility_process_host_->GetData().handle == base::kNullProcessHandle) {
-    DLOG(ERROR) << "Child process handle is null";
-    OnError();
-    return;
-  }
-
-  if (!itunes_callback_.is_null()) {
-    utility_process_host_->Send(new ChromeUtilityMsg_ParseITunesLibraryXmlFile(
-        IPC::TakePlatformFileForTransit(std::move(library_file_))));
-  }
+  utility_process_host_->Send(new ChromeUtilityMsg_ParseITunesLibraryXmlFile(
+      IPC::TakePlatformFileForTransit(std::move(library_file_))));
 
   parser_state_ = STARTED_PARSING_STATE;
 }
@@ -123,8 +104,6 @@
     const IPC::Message& message) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(SafeIAppsLibraryParser, message)
-    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted,
-                        OnUtilityProcessStarted)
     IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_GotITunesLibrary,
                         OnGotITunesLibrary)
     IPC_MESSAGE_UNHANDLED(handled = false)
diff --git a/chrome/browser/media_galleries/fileapi/safe_iapps_library_parser.h b/chrome/browser/media_galleries/fileapi/safe_iapps_library_parser.h
index 7b6dcfa..d4c65e3 100644
--- a/chrome/browser/media_galleries/fileapi/safe_iapps_library_parser.h
+++ b/chrome/browser/media_galleries/fileapi/safe_iapps_library_parser.h
@@ -48,7 +48,6 @@
  private:
   enum ParserState {
     INITIAL_STATE,
-    PINGED_UTILITY_PROCESS_STATE,
     STARTED_PARSING_STATE,
     FINISHED_PARSING_STATE,
   };
@@ -62,11 +61,6 @@
   // Launches the utility process.  Must run on the IO thread.
   void StartProcessOnIOThread();
 
-  // Notification that the utility process is running, and we can now get its
-  // process handle.
-  // Runs on the IO thread.
-  void OnUtilityProcessStarted();
-
   // Notification from the utility process when it finishes parsing the
   // iTunes XML. Runs on the IO thread.
   void OnGotITunesLibrary(bool result, const itunes::parser::Library& library);
diff --git a/chrome/browser/media_galleries/fileapi/safe_picasa_album_table_reader.cc b/chrome/browser/media_galleries/fileapi/safe_picasa_album_table_reader.cc
index f45d5aa9..0533edb 100644
--- a/chrome/browser/media_galleries/fileapi/safe_picasa_album_table_reader.cc
+++ b/chrome/browser/media_galleries/fileapi/safe_picasa_album_table_reader.cc
@@ -71,20 +71,7 @@
       ->AsWeakPtr();
   utility_process_host_->SetName(l10n_util::GetStringUTF16(
       IDS_UTILITY_PROCESS_MEDIA_LIBRARY_FILE_CHECKER_NAME));
-  // Wait for the startup notification before sending the main IPC to the
-  // utility process, so that we can dup the file handle.
-  utility_process_host_->Send(new ChromeUtilityMsg_StartupPing);
-  parser_state_ = PINGED_UTILITY_PROCESS_STATE;
-}
 
-void SafePicasaAlbumTableReader::OnProcessStarted() {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (parser_state_ != PINGED_UTILITY_PROCESS_STATE)
-    return;
-
-  if (utility_process_host_->GetData().handle == base::kNullProcessHandle) {
-    DLOG(ERROR) << "Child process handle is null";
-  }
   AlbumTableFilesForTransit files_for_transit;
   files_for_transit.indicator_file = IPC::TakePlatformFileForTransit(
       std::move(album_table_files_.indicator_file));
@@ -129,8 +116,6 @@
     const IPC::Message& message) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(SafePicasaAlbumTableReader, message)
-    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted,
-                        OnProcessStarted)
     IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParsePicasaPMPDatabase_Finished,
                         OnParsePicasaPMPDatabaseFinished)
     IPC_MESSAGE_UNHANDLED(handled = false)
diff --git a/chrome/browser/media_galleries/fileapi/safe_picasa_album_table_reader.h b/chrome/browser/media_galleries/fileapi/safe_picasa_album_table_reader.h
index 6d0829ae..cb7d6ae9 100644
--- a/chrome/browser/media_galleries/fileapi/safe_picasa_album_table_reader.h
+++ b/chrome/browser/media_galleries/fileapi/safe_picasa_album_table_reader.h
@@ -45,7 +45,6 @@
  private:
   enum ParserState {
     INITIAL_STATE,
-    PINGED_UTILITY_PROCESS_STATE,
     STARTED_PARSING_STATE,
     FINISHED_PARSING_STATE,
   };
@@ -56,11 +55,6 @@
   // Launches the utility process.  Must run on the IO thread.
   void StartWorkOnIOThread();
 
-  // Notification that the utility process is running, and we can now get its
-  // process handle.
-  // Runs on the IO thread.
-  void OnProcessStarted();
-
   // Notification from the utility process when it finshes parsing the PMP
   // database. This is received even if PMP parsing fails.
   // Runs on the IO thread.
diff --git a/chrome/browser/notifications/notification_permission_context_factory.cc b/chrome/browser/notifications/notification_permission_context_factory.cc
deleted file mode 100644
index af07ee0..0000000
--- a/chrome/browser/notifications/notification_permission_context_factory.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 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 "chrome/browser/notifications/notification_permission_context_factory.h"
-
-#include "chrome/browser/notifications/notification_permission_context.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
-#include "chrome/browser/profiles/profile.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-
-// static
-NotificationPermissionContext*
-NotificationPermissionContextFactory::GetForProfile(Profile* profile) {
-  return static_cast<NotificationPermissionContext*>(
-      GetInstance()->GetServiceForBrowserContext(profile, true));
-}
-
-// static
-NotificationPermissionContextFactory*
-NotificationPermissionContextFactory::GetInstance() {
-  return base::Singleton<NotificationPermissionContextFactory>::get();
-}
-
-NotificationPermissionContextFactory::NotificationPermissionContextFactory()
-    : PermissionContextFactoryBase(
-          "NotificationPermissionContext",
-          BrowserContextDependencyManager::GetInstance()) {}
-
-NotificationPermissionContextFactory::~NotificationPermissionContextFactory() {}
-
-KeyedService* NotificationPermissionContextFactory::BuildServiceInstanceFor(
-    content::BrowserContext* profile) const {
-  return new NotificationPermissionContext(static_cast<Profile*>(profile));
-}
diff --git a/chrome/browser/notifications/notification_permission_context_factory.h b/chrome/browser/notifications/notification_permission_context_factory.h
deleted file mode 100644
index 61903259..0000000
--- a/chrome/browser/notifications/notification_permission_context_factory.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_PERMISSION_CONTEXT_FACTORY_H_
-#define CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_PERMISSION_CONTEXT_FACTORY_H_
-
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "chrome/browser/permissions/permission_context_factory_base.h"
-
-class NotificationPermissionContext;
-class Profile;
-
-class NotificationPermissionContextFactory
-    : public PermissionContextFactoryBase {
- public:
-  static NotificationPermissionContext* GetForProfile(Profile* profile);
-  static NotificationPermissionContextFactory* GetInstance();
-
- private:
-  friend struct base::DefaultSingletonTraits<
-      NotificationPermissionContextFactory>;
-
-  NotificationPermissionContextFactory();
-  ~NotificationPermissionContextFactory() override;
-
-  // BrowserContextKeyedBaseFactory implementation.
-  KeyedService* BuildServiceInstanceFor(
-      content::BrowserContext* profile) const override;
-
-  DISALLOW_COPY_AND_ASSIGN(NotificationPermissionContextFactory);
-};
-
-#endif  // CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_PERMISSION_CONTEXT_FACTORY_H_
diff --git a/chrome/browser/notifications/notifier_state_tracker_factory.cc b/chrome/browser/notifications/notifier_state_tracker_factory.cc
index 69dfa24..35915ec 100644
--- a/chrome/browser/notifications/notifier_state_tracker_factory.cc
+++ b/chrome/browser/notifications/notifier_state_tracker_factory.cc
@@ -4,8 +4,8 @@
 
 #include "chrome/browser/notifications/notifier_state_tracker_factory.h"
 
-#include "chrome/browser/notifications/notification_permission_context_factory.h"
 #include "chrome/browser/notifications/notifier_state_tracker.h"
+#include "chrome/browser/permissions/permission_manager_factory.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
@@ -27,7 +27,7 @@
     : BrowserContextKeyedServiceFactory(
           "NotifierStateTracker",
           BrowserContextDependencyManager::GetInstance()) {
-  DependsOn(NotificationPermissionContextFactory::GetInstance());
+  DependsOn(PermissionManagerFactory::GetInstance());
 }
 
 NotifierStateTrackerFactory::~NotifierStateTrackerFactory() {}
diff --git a/chrome/browser/notifications/platform_notification_service_browsertest.cc b/chrome/browser/notifications/platform_notification_service_browsertest.cc
index 07c9e984..c52b8e70 100644
--- a/chrome/browser/notifications/platform_notification_service_browsertest.cc
+++ b/chrome/browser/notifications/platform_notification_service_browsertest.cc
@@ -13,21 +13,22 @@
 #include "base/time/time.h"
 #include "chrome/browser/notifications/desktop_notification_profile_util.h"
 #include "chrome/browser/notifications/notification.h"
-#include "chrome/browser/notifications/notification_permission_context.h"
-#include "chrome/browser/notifications/notification_permission_context_factory.h"
 #include "chrome/browser/notifications/notification_test_util.h"
 #include "chrome/browser/notifications/platform_notification_service_impl.h"
+#include "chrome/browser/permissions/permission_manager.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/permission_type.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
 #include "net/base/filename_util.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h"
 #include "ui/base/l10n/l10n_util.h"
 
 // -----------------------------------------------------------------------------
@@ -400,18 +401,19 @@
   // This case should succeed because a normal page URL is used.
   std::string script_result;
 
-  NotificationPermissionContext* permission_context =
-      NotificationPermissionContextFactory::GetForProfile(browser()->profile());
-  ASSERT_TRUE(permission_context);
+  PermissionManager* permission_manager =
+      PermissionManager::Get(browser()->profile());
 
-  EXPECT_EQ(CONTENT_SETTING_ASK,
-            permission_context->GetPermissionStatus(TestPageUrl(),
-                                                    TestPageUrl()));
+  EXPECT_EQ(blink::mojom::PermissionStatus::ASK,
+            permission_manager->GetPermissionStatus(
+                content::PermissionType::NOTIFICATIONS, TestPageUrl(),
+                TestPageUrl()));
 
   RequestAndAcceptPermission();
-  EXPECT_EQ(CONTENT_SETTING_ALLOW,
-            permission_context->GetPermissionStatus(TestPageUrl(),
-                                                    TestPageUrl()));
+  EXPECT_EQ(blink::mojom::PermissionStatus::GRANTED,
+            permission_manager->GetPermissionStatus(
+                content::PermissionType::NOTIFICATIONS, TestPageUrl(),
+                TestPageUrl()));
 
   // This case should fail because a file URL is used.
   base::FilePath dir_source_root;
@@ -422,12 +424,14 @@
 
   ui_test_utils::NavigateToURL(browser(), file_url);
 
-  EXPECT_EQ(CONTENT_SETTING_ASK,
-            permission_context->GetPermissionStatus(file_url, file_url));
+  EXPECT_EQ(blink::mojom::PermissionStatus::ASK,
+            permission_manager->GetPermissionStatus(
+                content::PermissionType::NOTIFICATIONS, file_url, file_url));
 
   RequestAndAcceptPermission();
-  EXPECT_EQ(CONTENT_SETTING_ASK,
-            permission_context->GetPermissionStatus(file_url, file_url))
+  EXPECT_EQ(blink::mojom::PermissionStatus::ASK,
+            permission_manager->GetPermissionStatus(
+                content::PermissionType::NOTIFICATIONS, file_url, file_url))
       << "If this test fails, you may have fixed a bug preventing file origins "
       << "from sending their origin from Blink; if so you need to update the "
       << "display function for notification origins to show the file path.";
diff --git a/chrome/browser/permissions/permission_context.cc b/chrome/browser/permissions/permission_context.cc
deleted file mode 100644
index 2cb1677..0000000
--- a/chrome/browser/permissions/permission_context.cc
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2015 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 "chrome/browser/permissions/permission_context.h"
-
-#include "build/build_config.h"
-#include "chrome/browser/background_sync/background_sync_permission_context.h"
-#include "chrome/browser/background_sync/background_sync_permission_context_factory.h"
-#include "chrome/browser/geolocation/geolocation_permission_context.h"
-#include "chrome/browser/geolocation/geolocation_permission_context_factory.h"
-#include "chrome/browser/media/media_stream_camera_permission_context_factory.h"
-#include "chrome/browser/media/media_stream_device_permission_context.h"
-#include "chrome/browser/media/media_stream_mic_permission_context_factory.h"
-#include "chrome/browser/media/midi_permission_context.h"
-#include "chrome/browser/media/midi_permission_context_factory.h"
-#include "chrome/browser/notifications/notification_permission_context.h"
-#include "chrome/browser/notifications/notification_permission_context_factory.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/push_messaging/push_messaging_permission_context.h"
-#include "chrome/browser/push_messaging/push_messaging_permission_context_factory.h"
-#include "chrome/browser/storage/durable_storage_permission_context.h"
-#include "chrome/browser/storage/durable_storage_permission_context_factory.h"
-#include "content/public/browser/permission_type.h"
-
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
-#include "chrome/browser/media/protected_media_identifier_permission_context.h"
-#include "chrome/browser/media/protected_media_identifier_permission_context_factory.h"
-#endif
-
-using content::PermissionType;
-
-// static
-PermissionContextBase* PermissionContext::Get(Profile* profile,
-                                              PermissionType permission_type) {
-  // NOTE: the factories used in this method have to stay in sync with
-  // ::GetFactories() below.
-  switch (permission_type) {
-    case PermissionType::GEOLOCATION:
-      return GeolocationPermissionContextFactory::GetForProfile(profile);
-    case PermissionType::MIDI_SYSEX:
-      return MidiPermissionContextFactory::GetForProfile(profile);
-    case PermissionType::NOTIFICATIONS:
-      return NotificationPermissionContextFactory::GetForProfile(profile);
-    case PermissionType::PUSH_MESSAGING:
-      return PushMessagingPermissionContextFactory::GetForProfile(profile);
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
-    case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
-      return ProtectedMediaIdentifierPermissionContextFactory::GetForProfile(
-          profile);
-#endif
-    case content::PermissionType::DURABLE_STORAGE:
-      return DurableStoragePermissionContextFactory::GetForProfile(profile);
-    case PermissionType::MIDI:
-      // PermissionType::MIDI is a valid permission but does not have a
-      // permission context. It has a constant value instead.
-      break;
-    case PermissionType::AUDIO_CAPTURE:
-      return MediaStreamMicPermissionContextFactory::GetForProfile(profile);
-    case PermissionType::VIDEO_CAPTURE:
-      return MediaStreamCameraPermissionContextFactory::GetForProfile(profile);
-    case PermissionType::BACKGROUND_SYNC:
-      return BackgroundSyncPermissionContextFactory::GetForProfile(profile);
-    default:
-      NOTREACHED() << "No PermissionContext associated with "
-                   << static_cast<int>(permission_type);
-      break;
-  }
-
-  return nullptr;
-}
-
-// static
-const std::list<KeyedServiceBaseFactory*>& PermissionContext::GetFactories() {
-  // NOTE: this list has to stay in sync with the factories used by ::Get().
-  CR_DEFINE_STATIC_LOCAL(std::list<KeyedServiceBaseFactory*>, factories, ());
-
-  if (factories.empty()) {
-    factories.push_back(GeolocationPermissionContextFactory::GetInstance());
-    factories.push_back(MidiPermissionContextFactory::GetInstance());
-    factories.push_back(NotificationPermissionContextFactory::GetInstance());
-    factories.push_back(PushMessagingPermissionContextFactory::GetInstance());
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
-    factories.push_back(
-        ProtectedMediaIdentifierPermissionContextFactory::GetInstance());
-#endif
-    factories.push_back(DurableStoragePermissionContextFactory::GetInstance());
-    factories.push_back(MediaStreamMicPermissionContextFactory::GetInstance());
-    factories.push_back(
-        MediaStreamCameraPermissionContextFactory::GetInstance());
-    factories.push_back(BackgroundSyncPermissionContextFactory::GetInstance());
-  }
-
-  return factories;
-}
diff --git a/chrome/browser/permissions/permission_context.h b/chrome/browser/permissions/permission_context.h
deleted file mode 100644
index 7dfd84ed..0000000
--- a/chrome/browser/permissions/permission_context.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef CHROME_BROWSER_PERMISSIONS_PERMISSION_CONTEXT_H_
-#define CHROME_BROWSER_PERMISSIONS_PERMISSION_CONTEXT_H_
-
-#include <list>
-
-#include "base/macros.h"
-#include "components/content_settings/core/common/content_settings_types.h"
-
-class PermissionContextBase;
-class Profile;
-class KeyedServiceBaseFactory;
-
-namespace content {
-enum class PermissionType;
-};  // namespace content
-
-class PermissionContext {
- public:
-  // Helper method returning the PermissionContextBase object associated with
-  // the given ContentSettingsType.
-  // This can return nullptr if the the permission type has no associated
-  // context.
-  static PermissionContextBase* Get(
-      Profile* profile,
-      content::PermissionType content_settings_type);
-
-  // Return all the factories related to PermissionContext. These are the
-  // factories used by ::Get() to create a PermissionContextBase.
-  // This is meant to be used by callers of ::Get() that need to depend on these
-  // factories.
-  static const std::list<KeyedServiceBaseFactory*>& GetFactories();
-
- private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(PermissionContext);
-};
-
-#endif // CHROME_BROWSER_PERMISSIONS_PERMISSION_CONTEXT_H_
diff --git a/chrome/browser/permissions/permission_context_factory_base.cc b/chrome/browser/permissions/permission_context_factory_base.cc
deleted file mode 100644
index e9f6035..0000000
--- a/chrome/browser/permissions/permission_context_factory_base.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2015 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 "chrome/browser/permissions/permission_context_factory_base.h"
-
-#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "content/public/browser/browser_context.h"
-
-PermissionContextFactoryBase::PermissionContextFactoryBase(
-    const char* name,
-    BrowserContextDependencyManager* manager)
-    : BrowserContextKeyedServiceFactory(name, manager) {
-  DependsOn(HostContentSettingsMapFactory::GetInstance());
-}
-
-PermissionContextFactoryBase::~PermissionContextFactoryBase() {
-}
-
-content::BrowserContext*
-PermissionContextFactoryBase::GetBrowserContextToUse(
-      content::BrowserContext* context) const {
-  return chrome::GetBrowserContextOwnInstanceInIncognito(context);
-}
diff --git a/chrome/browser/permissions/permission_context_factory_base.h b/chrome/browser/permissions/permission_context_factory_base.h
deleted file mode 100644
index 9ef1fda..0000000
--- a/chrome/browser/permissions/permission_context_factory_base.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef CHROME_BROWSER_PERMISSIONS_PERMISSION_CONTEXT_FACTORY_BASE_H_
-#define CHROME_BROWSER_PERMISSIONS_PERMISSION_CONTEXT_FACTORY_BASE_H_
-
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
-
-class BrowserContentDependencyManager;
-
-namespace content {
-class BrowserContext;
-}
-
-// This base class goes along with the PermissionContextBase to be used for
-// factories for PermissionContextBase's subclasses.
-// - It regisers dependencies that PermissionContextBase uses.
-// - It provides the common behaviour with incognito profiles.
-class PermissionContextFactoryBase : public BrowserContextKeyedServiceFactory {
- protected:
-  PermissionContextFactoryBase(const char* name,
-                               BrowserContextDependencyManager* manager);
-  ~PermissionContextFactoryBase() override;
-
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
-};
-
-#endif  // CHROME_BROWSER_PERMISSIONS_PERMISSION_CONTEXT_FACTORY_BASE_H_
diff --git a/chrome/browser/permissions/permission_manager.cc b/chrome/browser/permissions/permission_manager.cc
index e6c15eb3..eea06a4 100644
--- a/chrome/browser/permissions/permission_manager.cc
+++ b/chrome/browser/permissions/permission_manager.cc
@@ -7,23 +7,41 @@
 #include <stddef.h>
 
 #include "base/callback.h"
+#include "base/memory/ptr_util.h"
 #include "build/build_config.h"
+#include "chrome/browser/background_sync/background_sync_permission_context.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
-#include "chrome/browser/permissions/permission_context.h"
+#include "chrome/browser/media/media_stream_device_permission_context.h"
+#include "chrome/browser/media/midi_permission_context.h"
+#include "chrome/browser/notifications/notification_permission_context.h"
 #include "chrome/browser/permissions/permission_context_base.h"
+#include "chrome/browser/permissions/permission_manager_factory.h"
 #include "chrome/browser/permissions/permission_request_id.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/push_messaging/push_messaging_permission_context.h"
+#include "chrome/browser/storage/durable_storage_permission_context.h"
 #include "chrome/browser/tab_contents/tab_util.h"
+#include "chrome/common/features.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "content/public/browser/permission_type.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
+#include "chrome/browser/media/protected_media_identifier_permission_context.h"
+#endif
+
 #if !defined(OS_ANDROID)
 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 #endif
 
+#if BUILDFLAG(ANDROID_JAVA_UI)
+#include "chrome/browser/geolocation/geolocation_permission_context_android.h"
+#else
+#include "chrome/browser/geolocation/geolocation_permission_context.h"
+#endif
+
 using blink::mojom::PermissionStatus;
 using content::PermissionType;
 
@@ -99,7 +117,8 @@
 // Returns whether the permission has a constant PermissionStatus value (i.e.
 // always approved or always denied)
 // The PermissionTypes for which true is returned should be exactly those which
-// return nullptr in PermissionContext::Get since they don't have a context.
+// return nullptr in PermissionManager::GetPermissionContext since they don't
+// have a context.
 bool IsConstantPermission(PermissionType type) {
   switch (type) {
     case PermissionType::MIDI:
@@ -195,9 +214,43 @@
   ContentSetting current_value;
 };
 
+// static
+PermissionManager* PermissionManager::Get(Profile* profile) {
+  return PermissionManagerFactory::GetForProfile(profile);
+}
+
 PermissionManager::PermissionManager(Profile* profile)
     : profile_(profile),
       weak_ptr_factory_(this) {
+  permission_contexts_[PermissionType::MIDI_SYSEX] =
+      base::WrapUnique(new MidiPermissionContext(profile));
+  permission_contexts_[PermissionType::PUSH_MESSAGING] =
+      base::WrapUnique(new PushMessagingPermissionContext(profile));
+  permission_contexts_[PermissionType::NOTIFICATIONS] =
+      base::WrapUnique(new NotificationPermissionContext(profile));
+#if !BUILDFLAG(ANDROID_JAVA_UI)
+  permission_contexts_[PermissionType::GEOLOCATION] =
+      base::WrapUnique(new GeolocationPermissionContext(profile));
+#else
+  permission_contexts_[PermissionType::GEOLOCATION] =
+      base::WrapUnique(new GeolocationPermissionContextAndroid(profile));
+#endif
+#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
+  permission_contexts_[PermissionType::PROTECTED_MEDIA_IDENTIFIER] =
+      base::WrapUnique(new ProtectedMediaIdentifierPermissionContext(profile));
+#endif
+  permission_contexts_[PermissionType::DURABLE_STORAGE] =
+      base::WrapUnique(new DurableStoragePermissionContext(profile));
+  permission_contexts_[PermissionType::AUDIO_CAPTURE] =
+      base::WrapUnique(new MediaStreamDevicePermissionContext(
+          profile, content::PermissionType::AUDIO_CAPTURE,
+          CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC));
+  permission_contexts_[PermissionType::VIDEO_CAPTURE] =
+      base::WrapUnique(new MediaStreamDevicePermissionContext(
+          profile, content::PermissionType::VIDEO_CAPTURE,
+          CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA));
+  permission_contexts_[PermissionType::BACKGROUND_SYNC] =
+      base::WrapUnique(new BackgroundSyncPermissionContext(profile));
 }
 
 PermissionManager::~PermissionManager() {
@@ -244,14 +297,13 @@
 
     if (IsConstantPermission(permission) ||
         IsPermissionBubbleManagerMissing(web_contents) ||
-        !PermissionContext::Get(profile_, permission)) {
+        !GetPermissionContext(permission)) {
       OnPermissionsRequestResponseStatus(request_id, i,
           GetPermissionStatus(permission, requesting_origin, embedding_origin));
       continue;
     }
 
-    PermissionContextBase* context = PermissionContext::Get(
-        profile_, permission);
+    PermissionContextBase* context = GetPermissionContext(permission);
     context->RequestPermission(
         web_contents, request, requesting_origin,
         base::Bind(&ContentSettingToPermissionStatusCallbackWrapper,
@@ -266,6 +318,17 @@
   return request_id;
 }
 
+std::size_t PermissionManager::PermissionTypeHash::operator()(
+    const content::PermissionType& type) const {
+  return static_cast<size_t>(type);
+}
+
+PermissionContextBase* PermissionManager::GetPermissionContext(
+    PermissionType type) {
+  const auto& it = permission_contexts_.find(type);
+  return it == permission_contexts_.end() ? nullptr : it->second.get();
+}
+
 void PermissionManager::OnPermissionsRequestResponseStatus(
     int request_id,
     int permission_id,
@@ -297,8 +360,7 @@
                                     pending_request->render_frame_id(),
                                     request_id);
   for (PermissionType permission : pending_request->permissions()) {
-    PermissionContextBase* context = PermissionContext::Get(
-        profile_, permission);
+    PermissionContextBase* context = GetPermissionContext(permission);
     if (!context)
       continue;
     context->CancelPermissionRequest(web_contents, request);
@@ -309,7 +371,7 @@
 void PermissionManager::ResetPermission(PermissionType permission,
                                         const GURL& requesting_origin,
                                         const GURL& embedding_origin) {
-  PermissionContextBase* context = PermissionContext::Get(profile_, permission);
+  PermissionContextBase* context = GetPermissionContext(permission);
   if (!context)
     return;
 
@@ -324,7 +386,7 @@
   if (IsConstantPermission(permission))
     return GetPermissionStatusForConstantPermission(permission);
 
-  PermissionContextBase* context = PermissionContext::Get(profile_, permission);
+  PermissionContextBase* context = GetPermissionContext(permission);
   if (!context)
     return PermissionStatus::DENIED;
 
@@ -364,9 +426,10 @@
     subscription->current_value = GetContentSettingForConstantPermission(
         permission);
   } else {
-    subscription->current_value = PermissionContext::Get(profile_, permission)
-        ->GetPermissionStatus(subscription->requesting_origin,
-                              subscription->embedding_origin);
+    subscription->current_value =
+        GetPermissionContext(permission)
+            ->GetPermissionStatus(subscription->requesting_origin,
+                                  subscription->embedding_origin);
   }
 
   return subscriptions_.Add(subscription);
@@ -413,7 +476,7 @@
       continue;
 
     ContentSetting new_value =
-        PermissionContext::Get(profile_, subscription->permission)
+        GetPermissionContext(subscription->permission)
             ->GetPermissionStatus(subscription->requesting_origin,
                                   subscription->embedding_origin);
     if (subscription->current_value == new_value)
diff --git a/chrome/browser/permissions/permission_manager.h b/chrome/browser/permissions/permission_manager.h
index 4123cf7..bae5ed1 100644
--- a/chrome/browser/permissions/permission_manager.h
+++ b/chrome/browser/permissions/permission_manager.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_PERMISSIONS_PERMISSION_MANAGER_H_
 #define CHROME_BROWSER_PERMISSIONS_PERMISSION_MANAGER_H_
 
+#include <unordered_map>
+
 #include "base/callback_forward.h"
 #include "base/id_map.h"
 #include "base/macros.h"
@@ -14,6 +16,7 @@
 #include "components/keyed_service/core/keyed_service.h"
 #include "content/public/browser/permission_manager.h"
 
+class PermissionContextBase;
 class Profile;
 
 namespace content {
@@ -25,6 +28,8 @@
                           public content::PermissionManager,
                           public content_settings::Observer {
  public:
+  static PermissionManager* Get(Profile* profile);
+
   explicit PermissionManager(Profile* profile);
   ~PermissionManager() override;
 
@@ -62,12 +67,23 @@
   void UnsubscribePermissionStatusChange(int subscription_id) override;
 
  private:
+  friend class GeolocationPermissionContextTests;
+  // TODO(raymes): Refactor MediaPermission to not call GetPermissionContext.
+  // See crbug.com/596786.
+  friend class MediaPermission;
+
   class PendingRequest;
   using PendingRequestsMap = IDMap<PendingRequest, IDMapOwnPointer>;
 
   struct Subscription;
   using SubscriptionsMap = IDMap<Subscription, IDMapOwnPointer>;
 
+  struct PermissionTypeHash {
+    std::size_t operator()(const content::PermissionType& type) const;
+  };
+
+  PermissionContextBase* GetPermissionContext(content::PermissionType type);
+
   // Called when a permission was decided for a given PendingRequest. The
   // PendingRequest is identified by its |request_id| and the permission is
   // identified by its |permission_id|. If the PendingRequest contains more than
@@ -93,6 +109,11 @@
   PendingRequestsMap pending_requests_;
   SubscriptionsMap subscriptions_;
 
+  std::unordered_map<content::PermissionType,
+                     scoped_ptr<PermissionContextBase>,
+                     PermissionTypeHash>
+      permission_contexts_;
+
   base::WeakPtrFactory<PermissionManager> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(PermissionManager);
diff --git a/chrome/browser/permissions/permission_manager_factory.cc b/chrome/browser/permissions/permission_manager_factory.cc
index fc12b7a..8b6033c 100644
--- a/chrome/browser/permissions/permission_manager_factory.cc
+++ b/chrome/browser/permissions/permission_manager_factory.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/permissions/permission_manager_factory.h"
 
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
-#include "chrome/browser/permissions/permission_context.h"
 #include "chrome/browser/permissions/permission_manager.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
@@ -28,8 +27,6 @@
         "PermissionManagerFactory",
         BrowserContextDependencyManager::GetInstance()) {
   DependsOn(HostContentSettingsMapFactory::GetInstance());
-  for (KeyedServiceBaseFactory* factory : PermissionContext::GetFactories())
-    DependsOn(factory);
 }
 
 PermissionManagerFactory::~PermissionManagerFactory() {
diff --git a/chrome/browser/printing/pdf_to_emf_converter.cc b/chrome/browser/printing/pdf_to_emf_converter.cc
index e16963f..bcc4e3a 100644
--- a/chrome/browser/printing/pdf_to_emf_converter.cc
+++ b/chrome/browser/printing/pdf_to_emf_converter.cc
@@ -154,7 +154,6 @@
   bool Send(IPC::Message* msg);
 
   // Message handlers.
-  void OnProcessStarted();
   void OnPageCount(int page_count);
   void OnPageDone(bool success, float scale_factor);
 
@@ -167,7 +166,6 @@
   // Used to suppress callbacks after PdfToEmfConverterImpl is deleted.
   base::WeakPtr<PdfToEmfConverterImpl> converter_;
   PdfRenderSettings settings_;
-  scoped_refptr<base::RefCountedMemory> data_;
 
   // Document loaded callback.
   PdfToEmfConverter::StartCallback start_callback_;
@@ -301,7 +299,6 @@
                                        start_callback));
     return;
   }
-  data_ = data;
 
   // Store callback before any OnFailed() call to make it called on failure.
   start_callback_ = start_callback;
@@ -314,17 +311,7 @@
           this, base::MessageLoop::current()->task_runner())->AsWeakPtr();
   utility_process_host_->SetName(l10n_util::GetStringUTF16(
       IDS_UTILITY_PROCESS_EMF_CONVERTOR_NAME));
-  // Should reply with OnProcessStarted().
-  Send(new ChromeUtilityMsg_StartupPing);
-}
 
-void PdfToEmfUtilityProcessHostClient::OnProcessStarted() {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (!utility_process_host_)
-    return OnFailed();
-
-  scoped_refptr<base::RefCountedMemory> data = data_;
-  data_ = NULL;
   BrowserThread::PostTaskAndReplyWithResult(
       BrowserThread::FILE,
       FROM_HERE,
@@ -446,7 +433,6 @@
     const IPC::Message& message) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(PdfToEmfUtilityProcessHostClient, message)
-    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted, OnProcessStarted)
     IPC_MESSAGE_HANDLER(
         ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount, OnPageCount)
     IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone,
diff --git a/chrome/browser/printing/pwg_raster_converter.cc b/chrome/browser/printing/pwg_raster_converter.cc
index c457a98..eb220c0 100644
--- a/chrome/browser/printing/pwg_raster_converter.cc
+++ b/chrome/browser/printing/pwg_raster_converter.cc
@@ -130,7 +130,6 @@
   ~PwgUtilityProcessHostClient() override;
 
   // Message handlers.
-  void OnProcessStarted();
   void OnSucceeded();
   void OnFailed();
 
@@ -145,7 +144,6 @@
   PdfRenderSettings settings_;
   PwgRasterSettings bitmap_settings_;
   PWGRasterConverter::ResultCallback callback_;
-  base::WeakPtr<content::UtilityProcessHost> utility_process_host_;
 
   DISALLOW_COPY_AND_ASSIGN(PwgUtilityProcessHostClient);
 };
@@ -180,7 +178,6 @@
   const IPC::Message& message) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(PwgUtilityProcessHostClient, message)
-    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted, OnProcessStarted)
     IPC_MESSAGE_HANDLER(
         ChromeUtilityHostMsg_RenderPDFPagesToPWGRaster_Succeeded, OnSucceeded)
     IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToPWGRaster_Failed,
@@ -190,19 +187,6 @@
   return handled;
 }
 
-void PwgUtilityProcessHostClient::OnProcessStarted() {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (!utility_process_host_) {
-    RunCallbackOnUIThread(false);
-    return;
-  }
-
-  utility_process_host_->Send(new ChromeUtilityMsg_RenderPDFPagesToPWGRaster(
-      files_->GetPdfForProcess(), settings_, bitmap_settings_,
-      files_->GetPwgForProcess()));
-  utility_process_host_.reset();
-}
-
 void PwgUtilityProcessHostClient::OnSucceeded() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   RunCallback(true);
@@ -226,12 +210,14 @@
 
 void PwgUtilityProcessHostClient::StartProcessOnIOThread() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  utility_process_host_ =
+  content::UtilityProcessHost* utility_process_host =
       content::UtilityProcessHost::Create(
-          this, base::MessageLoop::current()->task_runner())->AsWeakPtr();
-  utility_process_host_->SetName(l10n_util::GetStringUTF16(
+          this, base::MessageLoop::current()->task_runner());
+  utility_process_host->SetName(l10n_util::GetStringUTF16(
       IDS_UTILITY_PROCESS_PWG_RASTER_CONVERTOR_NAME));
-  utility_process_host_->Send(new ChromeUtilityMsg_StartupPing);
+  utility_process_host->Send(new ChromeUtilityMsg_RenderPDFPagesToPWGRaster(
+      files_->GetPdfForProcess(), settings_, bitmap_settings_,
+      files_->GetPwgForProcess()));
 }
 
 void PwgUtilityProcessHostClient::RunCallback(bool success) {
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
index bb52aa43..1d9a295e 100644
--- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
+++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -23,13 +23,11 @@
 #include "chrome/browser/engagement/site_engagement_service.h"
 #include "chrome/browser/engagement/site_engagement_service_factory.h"
 #include "chrome/browser/favicon/favicon_service_factory.h"
-#include "chrome/browser/geolocation/geolocation_permission_context_factory.h"
 #include "chrome/browser/google/google_url_tracker_factory.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/invalidation/profile_invalidation_provider_factory.h"
 #include "chrome/browser/media_galleries/media_galleries_preferences_factory.h"
 #include "chrome/browser/notifications/extension_welcome_notification_factory.h"
-#include "chrome/browser/notifications/notification_permission_context_factory.h"
 #include "chrome/browser/notifications/notifier_state_tracker_factory.h"
 #include "chrome/browser/ntp_snippets/ntp_snippets_service_factory.h"
 #include "chrome/browser/password_manager/password_manager_setting_migrator_service_factory.h"
@@ -110,9 +108,7 @@
 #endif
 #endif
 
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
-#include "chrome/browser/media/protected_media_identifier_permission_context_factory.h"
-#else
+#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
 #include "chrome/browser/signin/cross_device_promo_factory.h"
 #endif
 
@@ -195,10 +191,6 @@
 #if defined(OS_ANDROID)
   chrome::android::DataUseUITabModelFactory::GetInstance();
 #endif
-  GeolocationPermissionContextFactory::GetInstance();
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
-  ProtectedMediaIdentifierPermissionContextFactory::GetInstance();
-#endif
 #if defined(ENABLE_PRINT_PREVIEW)
   CloudPrintProxyServiceFactory::GetInstance();
 #endif
@@ -210,7 +202,6 @@
 #if defined(ENABLE_EXTENSIONS)
   ExtensionWelcomeNotificationFactory::GetInstance();
 #endif
-  NotificationPermissionContextFactory::GetInstance();
   NotifierStateTrackerFactory::GetInstance();
 #endif  // defined(ENABLE_NOTIFICATIONS)
   dom_distiller::DomDistillerServiceFactory::GetInstance();
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.cc b/chrome/browser/profiles/off_the_record_profile_impl.cc
index 1c9ae68..69005410 100644
--- a/chrome/browser/profiles/off_the_record_profile_impl.cc
+++ b/chrome/browser/profiles/off_the_record_profile_impl.cc
@@ -60,11 +60,6 @@
 #include "storage/browser/database/database_tracker.h"
 
 #if defined(OS_ANDROID)
-#include "chrome/browser/media/protected_media_identifier_permission_context.h"
-#include "chrome/browser/media/protected_media_identifier_permission_context_factory.h"
-#endif  // defined(OS_ANDROID)
-
-#if defined(OS_ANDROID)
 #include "components/prefs/scoped_user_pref_update.h"
 #include "components/proxy_config/proxy_prefs.h"
 #endif  // defined(OS_ANDROID)
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index 1697d45..69df951 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -115,11 +115,6 @@
 #include "content/public/common/page_zoom.h"
 #include "ui/base/l10n/l10n_util.h"
 
-#if defined(OS_ANDROID)
-#include "chrome/browser/media/protected_media_identifier_permission_context.h"
-#include "chrome/browser/media/protected_media_identifier_permission_context_factory.h"
-#endif
-
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/locale_change_guard.h"
 #include "chrome/browser/chromeos/preferences.h"
diff --git a/chrome/browser/push_messaging/push_messaging_permission_context.cc b/chrome/browser/push_messaging/push_messaging_permission_context.cc
index 2214145..f5591c2 100644
--- a/chrome/browser/push_messaging/push_messaging_permission_context.cc
+++ b/chrome/browser/push_messaging/push_messaging_permission_context.cc
@@ -5,8 +5,7 @@
 #include "chrome/browser/push_messaging/push_messaging_permission_context.h"
 
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
-#include "chrome/browser/notifications/notification_permission_context.h"
-#include "chrome/browser/notifications/notification_permission_context_factory.h"
+#include "chrome/browser/permissions/permission_manager.h"
 #include "chrome/browser/permissions/permission_request_id.h"
 #include "chrome/browser/permissions/permission_uma_util.h"
 #include "chrome/browser/profiles/profile.h"
@@ -41,19 +40,16 @@
       PermissionContextBase::GetPermissionStatus(requesting_origin,
                                                  embedding_origin);
 
-  NotificationPermissionContext* notification_context =
-      NotificationPermissionContextFactory::GetForProfile(profile_);
-  DCHECK(notification_context);
+  blink::mojom::PermissionStatus notifications_permission =
+      PermissionManager::Get(profile_)->GetPermissionStatus(
+          content::PermissionType::NOTIFICATIONS, requesting_origin,
+          embedding_origin);
 
-  ContentSetting notifications_permission =
-      notification_context->GetPermissionStatus(requesting_origin,
-                                                embedding_origin);
-
-  if (notifications_permission == CONTENT_SETTING_BLOCK ||
+  if (notifications_permission == blink::mojom::PermissionStatus::DENIED ||
       push_content_setting == CONTENT_SETTING_BLOCK) {
     return CONTENT_SETTING_BLOCK;
   }
-  if (notifications_permission == CONTENT_SETTING_ASK)
+  if (notifications_permission == blink::mojom::PermissionStatus::ASK)
     return CONTENT_SETTING_ASK;
 
   DCHECK(push_content_setting == CONTENT_SETTING_ALLOW ||
@@ -88,12 +84,9 @@
     return;
   }
 
-  NotificationPermissionContext* notification_context =
-      NotificationPermissionContextFactory::GetForProfile(profile_);
-  DCHECK(notification_context);
-
-  notification_context->RequestPermission(
-      web_contents, id, requesting_origin,
+  PermissionManager::Get(profile_)->RequestPermission(
+      content::PermissionType::NOTIFICATIONS, web_contents->GetMainFrame(),
+      requesting_origin,
       base::Bind(&PushMessagingPermissionContext::DecidePushPermission,
                  weak_factory_ui_thread_.GetWeakPtr(), id, requesting_origin,
                  embedding_origin, callback));
@@ -112,8 +105,10 @@
     const GURL& requesting_origin,
     const GURL& embedding_origin,
     const BrowserPermissionCallback& callback,
-    ContentSetting notification_content_setting) {
+    blink::mojom::PermissionStatus notification_status) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  DCHECK_NE(notification_status, blink::mojom::PermissionStatus::ASK);
+
   ContentSetting push_content_setting =
       HostContentSettingsMapFactory::GetForProfile(profile_)
           ->GetContentSettingAndMaybeUpdateLastUsage(
@@ -128,10 +123,10 @@
     return;
   }
 
-  if (notification_content_setting != CONTENT_SETTING_ALLOW) {
+  if (notification_status == blink::mojom::PermissionStatus::DENIED) {
     DVLOG(1) << "Notification permission has not been granted.";
     NotifyPermissionSet(id, requesting_origin, embedding_origin, callback,
-                        false /* persist */, notification_content_setting);
+                        false /* persist */, CONTENT_SETTING_BLOCK);
     return;
   }
 
diff --git a/chrome/browser/push_messaging/push_messaging_permission_context.h b/chrome/browser/push_messaging/push_messaging_permission_context.h
index f137751..229cc5a 100644
--- a/chrome/browser/push_messaging/push_messaging_permission_context.h
+++ b/chrome/browser/push_messaging/push_messaging_permission_context.h
@@ -8,7 +8,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "chrome/browser/permissions/permission_context_base.h"
-#include "components/content_settings/core/common/content_settings_types.h"
+#include "third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h"
 
 class PermissionRequestID;
 class Profile;
@@ -42,11 +42,12 @@
 
   // Used to decide the permission for push, once the permission for
   // Notification has been granted/denied.
-  void DecidePushPermission(const PermissionRequestID& id,
-                            const GURL& requesting_origin,
-                            const GURL& embedding_origin,
-                            const BrowserPermissionCallback& callback,
-                            ContentSetting notifications_content_setting);
+  void DecidePushPermission(
+      const PermissionRequestID& id,
+      const GURL& requesting_origin,
+      const GURL& embedding_origin,
+      const BrowserPermissionCallback& callback,
+      blink::mojom::PermissionStatus notifications_status);
 
   Profile* profile_;
 
diff --git a/chrome/browser/push_messaging/push_messaging_permission_context_factory.cc b/chrome/browser/push_messaging/push_messaging_permission_context_factory.cc
deleted file mode 100644
index 075793a..0000000
--- a/chrome/browser/push_messaging/push_messaging_permission_context_factory.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2014 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 "chrome/browser/push_messaging/push_messaging_permission_context_factory.h"
-
-#include "chrome/browser/profiles/incognito_helpers.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/push_messaging/push_messaging_permission_context.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-
-// static
-PushMessagingPermissionContext*
-PushMessagingPermissionContextFactory::GetForProfile(Profile* profile) {
-  return static_cast<PushMessagingPermissionContext*>(
-      GetInstance()->GetServiceForBrowserContext(profile, true));
-}
-
-// static
-PushMessagingPermissionContextFactory*
-PushMessagingPermissionContextFactory::GetInstance() {
-  return base::Singleton<PushMessagingPermissionContextFactory>::get();
-}
-
-PushMessagingPermissionContextFactory::PushMessagingPermissionContextFactory()
-    : PermissionContextFactoryBase(
-          "GCMPermissionContext",
-          BrowserContextDependencyManager::GetInstance()) {}
-
-PushMessagingPermissionContextFactory::
-    ~PushMessagingPermissionContextFactory() {}
-
-KeyedService* PushMessagingPermissionContextFactory::BuildServiceInstanceFor(
-    content::BrowserContext* profile) const {
-  return new PushMessagingPermissionContext(static_cast<Profile*>(profile));
-}
diff --git a/chrome/browser/push_messaging/push_messaging_permission_context_factory.h b/chrome/browser/push_messaging/push_messaging_permission_context_factory.h
deleted file mode 100644
index f5b6e93..0000000
--- a/chrome/browser/push_messaging/push_messaging_permission_context_factory.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2014 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.
-
-#ifndef CHROME_BROWSER_PUSH_MESSAGING_PUSH_MESSAGING_PERMISSION_CONTEXT_FACTORY_H_
-#define CHROME_BROWSER_PUSH_MESSAGING_PUSH_MESSAGING_PERMISSION_CONTEXT_FACTORY_H_
-
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "chrome/browser/permissions/permission_context_factory_base.h"
-
-class Profile;
-
-class PushMessagingPermissionContext;
-
-class PushMessagingPermissionContextFactory
-    : public PermissionContextFactoryBase {
- public:
-  static PushMessagingPermissionContext* GetForProfile(Profile* profile);
-  static PushMessagingPermissionContextFactory* GetInstance();
-
- private:
-  friend struct base::DefaultSingletonTraits<
-      PushMessagingPermissionContextFactory>;
-
-  PushMessagingPermissionContextFactory();
-  ~PushMessagingPermissionContextFactory() override;
-
-  // BrowserContextKeyedBaseFactory methods:
-  KeyedService* BuildServiceInstanceFor(
-      content::BrowserContext* profile) const override;
-
-  DISALLOW_COPY_AND_ASSIGN(PushMessagingPermissionContextFactory);
-};
-
-#endif  // CHROME_BROWSER_PUSH_MESSAGING_PUSH_MESSAGING_PERMISSION_CONTEXT_FACTORY_H_
diff --git a/chrome/browser/push_messaging/push_messaging_permission_context_unittest.cc b/chrome/browser/push_messaging/push_messaging_permission_context_unittest.cc
index 7cda2a7..e77c100 100644
--- a/chrome/browser/push_messaging/push_messaging_permission_context_unittest.cc
+++ b/chrome/browser/push_messaging/push_messaging_permission_context_unittest.cc
@@ -164,28 +164,32 @@
   BrowserPermissionCallback callback = base::Bind(DoNothing);
 
   context.DecidePushPermission(request_id, GURL(kOriginA), GURL(kOriginA),
-                               callback, CONTENT_SETTING_DEFAULT);
+                               callback,
+                               blink::mojom::PermissionStatus::DENIED);
   EXPECT_FALSE(context.was_persisted());
   EXPECT_FALSE(context.was_granted());
 
   SetContentSetting(&profile, CONTENT_SETTINGS_TYPE_PUSH_MESSAGING,
                     CONTENT_SETTING_ALLOW);
   context.DecidePushPermission(request_id, GURL(kOriginA), GURL(kOriginA),
-                               callback, CONTENT_SETTING_ALLOW);
+                               callback,
+                               blink::mojom::PermissionStatus::GRANTED);
   EXPECT_TRUE(context.was_persisted());
   EXPECT_TRUE(context.was_granted());
 
   SetContentSetting(&profile, CONTENT_SETTINGS_TYPE_PUSH_MESSAGING,
                     CONTENT_SETTING_BLOCK);
   context.DecidePushPermission(request_id, GURL(kOriginA), GURL(kOriginA),
-                               callback, CONTENT_SETTING_ALLOW);
+                               callback,
+                               blink::mojom::PermissionStatus::GRANTED);
   EXPECT_TRUE(context.was_persisted());
   EXPECT_FALSE(context.was_granted());
 
   SetContentSetting(&profile, CONTENT_SETTINGS_TYPE_PUSH_MESSAGING,
                     CONTENT_SETTING_ASK);
   context.DecidePushPermission(request_id, GURL(kOriginA), GURL(kOriginA),
-                               callback, CONTENT_SETTING_ALLOW);
+                               callback,
+                               blink::mojom::PermissionStatus::GRANTED);
   EXPECT_TRUE(context.was_persisted());
   EXPECT_TRUE(context.was_granted());
 }
diff --git a/chrome/browser/push_messaging/push_messaging_service_unittest.cc b/chrome/browser/push_messaging/push_messaging_service_unittest.cc
index d63f7d83..303966f4 100644
--- a/chrome/browser/push_messaging/push_messaging_service_unittest.cc
+++ b/chrome/browser/push_messaging/push_messaging_service_unittest.cc
@@ -13,16 +13,17 @@
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/thread_task_runner_handle.h"
+#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/permissions/permission_manager.h"
 #include "chrome/browser/permissions/permission_manager_factory.h"
 #include "chrome/browser/push_messaging/push_messaging_app_identifier.h"
 #include "chrome/browser/push_messaging/push_messaging_permission_context.h"
-#include "chrome/browser/push_messaging/push_messaging_permission_context_factory.h"
 #include "chrome/browser/push_messaging/push_messaging_service_factory.h"
 #include "chrome/browser/push_messaging/push_messaging_service_impl.h"
 #include "chrome/browser/services/gcm/fake_gcm_profile_service.h"
 #include "chrome/browser/services/gcm/gcm_profile_service_factory.h"
 #include "chrome/test/base/testing_profile.h"
+#include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/gcm_driver/crypto/gcm_crypto_test_helpers.h"
 #include "components/gcm_driver/fake_gcm_client_factory.h"
 #include "components/gcm_driver/gcm_profile_service.h"
@@ -74,27 +75,6 @@
   DISALLOW_COPY_AND_ASSIGN(PushMessagingTestingProfile);
 };
 
-// Implementation of the PushMessagingPermissionContext that always allows usage
-// of Push Messaging, regardless of the actual implementation.
-class FakePushMessagingPermissionContext
-    : public PushMessagingPermissionContext {
- public:
-  explicit FakePushMessagingPermissionContext(Profile* profile)
-      : PushMessagingPermissionContext(profile) {}
-  ~FakePushMessagingPermissionContext() override {}
-
-  ContentSetting GetPermissionStatus(
-      const GURL& requesting_origin,
-      const GURL& embedding_origin) const override {
-    return CONTENT_SETTING_ALLOW;
-  }
-};
-
-scoped_ptr<KeyedService> BuildFakePushMessagingPermissionContext(
-    content::BrowserContext* context) {
-  return scoped_ptr<KeyedService>(
-      new FakePushMessagingPermissionContext(static_cast<Profile*>(context)));
-}
 
 scoped_ptr<KeyedService> BuildFakeGCMProfileService(
     content::BrowserContext* context) {
@@ -106,9 +86,13 @@
 class PushMessagingServiceTest : public ::testing::Test {
  public:
   PushMessagingServiceTest() {
-    // Override the permission context factory to always allow Push Messaging.
-    PushMessagingPermissionContextFactory::GetInstance()->SetTestingFactory(
-        &profile_, &BuildFakePushMessagingPermissionContext);
+    // Always allow push notifications in the profile.
+    HostContentSettingsMap* host_content_settings_map =
+        HostContentSettingsMapFactory::GetForProfile(&profile_);
+    host_content_settings_map->SetDefaultContentSetting(
+        CONTENT_SETTINGS_TYPE_NOTIFICATIONS, CONTENT_SETTING_ALLOW);
+    host_content_settings_map->SetDefaultContentSetting(
+        CONTENT_SETTINGS_TYPE_PUSH_MESSAGING, CONTENT_SETTING_ALLOW);
 
     // Override the GCM Profile service so that we can send fake messages.
     gcm::GCMProfileServiceFactory::GetInstance()->SetTestingFactory(
diff --git a/chrome/browser/safe_browsing/sandboxed_dmg_analyzer_mac.cc b/chrome/browser/safe_browsing/sandboxed_dmg_analyzer_mac.cc
index cfc709f..48abce9 100644
--- a/chrome/browser/safe_browsing/sandboxed_dmg_analyzer_mac.cc
+++ b/chrome/browser/safe_browsing/sandboxed_dmg_analyzer_mac.cc
@@ -58,14 +58,15 @@
 void SandboxedDMGAnalyzer::StartAnalysis() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  utility_process_host_ =
+  content::UtilityProcessHost* utility_process_host =
       content::UtilityProcessHost::Create(this,
-          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))
-      ->AsWeakPtr();
+          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
 
-  utility_process_host_->SetName(l10n_util::GetStringUTF16(
+  utility_process_host->SetName(l10n_util::GetStringUTF16(
       IDS_UTILITY_PROCESS_SAFE_BROWSING_ZIP_FILE_ANALYZER_NAME));
-  utility_process_host_->Send(new ChromeUtilityMsg_StartupPing);
+  utility_process_host->Send(
+      new ChromeUtilityMsg_AnalyzeDmgFileForDownloadProtection(
+          IPC::TakePlatformFileForTransit(std::move(file_))));
 }
 
 void SandboxedDMGAnalyzer::OnProcessCrashed(int exit_code) {
@@ -79,8 +80,6 @@
 bool SandboxedDMGAnalyzer::OnMessageReceived(const IPC::Message& message) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(SandboxedDMGAnalyzer, message)
-    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted,
-                        OnUtilityProcessStarted)
     IPC_MESSAGE_HANDLER(
         ChromeUtilityHostMsg_AnalyzeDmgFileForDownloadProtection_Finished,
         OnAnalysisFinished)
@@ -89,13 +88,6 @@
   return handled;
 }
 
-void SandboxedDMGAnalyzer::OnUtilityProcessStarted() {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  utility_process_host_->Send(
-      new ChromeUtilityMsg_AnalyzeDmgFileForDownloadProtection(
-          IPC::TakePlatformFileForTransit(std::move(file_))));
-}
-
 void SandboxedDMGAnalyzer::OnAnalysisFinished(
     const zip_analyzer::Results& results) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
diff --git a/chrome/browser/safe_browsing/sandboxed_dmg_analyzer_mac.h b/chrome/browser/safe_browsing/sandboxed_dmg_analyzer_mac.h
index 307776a..19e5a2f 100644
--- a/chrome/browser/safe_browsing/sandboxed_dmg_analyzer_mac.h
+++ b/chrome/browser/safe_browsing/sandboxed_dmg_analyzer_mac.h
@@ -48,9 +48,6 @@
   void OnProcessLaunchFailed() override;
   bool OnMessageReceived(const IPC::Message& message) override;
 
-  // Message handler for reply ping when the utility process has started.
-  void OnUtilityProcessStarted();
-
   // Message handler to receive the results of the analysis. Invokes the
   // |callback_|.
   void OnAnalysisFinished(const zip_analyzer::Results& results);
@@ -58,9 +55,6 @@
   const base::FilePath file_path_;  // The path of the DMG file.
   base::File file_;  // The opened file handle for |file_path_|.
 
-  // Weak reference to the utility process, which owns this.
-  base::WeakPtr<content::UtilityProcessHost> utility_process_host_;
-
   const ResultsCallback callback_;  // Result callback.
   bool callback_called_;  // Whether |callback_| has already been invoked.
 
diff --git a/chrome/browser/safe_browsing/sandboxed_zip_analyzer.cc b/chrome/browser/safe_browsing/sandboxed_zip_analyzer.cc
index 4c4b4b60..c720d95b 100644
--- a/chrome/browser/safe_browsing/sandboxed_zip_analyzer.cc
+++ b/chrome/browser/safe_browsing/sandboxed_zip_analyzer.cc
@@ -112,8 +112,6 @@
 bool SandboxedZipAnalyzer::OnMessageReceived(const IPC::Message& message) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(SandboxedZipAnalyzer, message)
-    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted,
-                        OnUtilityProcessStarted)
     IPC_MESSAGE_HANDLER(
         ChromeUtilityHostMsg_AnalyzeZipFileForDownloadProtection_Finished,
         OnAnalyzeZipFileFinished)
@@ -130,13 +128,6 @@
       ->AsWeakPtr();
   utility_process_host_->SetName(l10n_util::GetStringUTF16(
       IDS_UTILITY_PROCESS_SAFE_BROWSING_ZIP_FILE_ANALYZER_NAME));
-  utility_process_host_->Send(new ChromeUtilityMsg_StartupPing);
-  // Wait for the startup notification before sending the main IPC to the
-  // utility process, so that we can dup the file handle.
-}
-
-void SandboxedZipAnalyzer::OnUtilityProcessStarted() {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   utility_process_host_->Send(
       new ChromeUtilityMsg_AnalyzeZipFileForDownloadProtection(
           IPC::TakePlatformFileForTransit(std::move(zip_file_)),
diff --git a/chrome/browser/safe_browsing/sandboxed_zip_analyzer.h b/chrome/browser/safe_browsing/sandboxed_zip_analyzer.h
index b5ff1c29..d2cd8d9c 100644
--- a/chrome/browser/safe_browsing/sandboxed_zip_analyzer.h
+++ b/chrome/browser/safe_browsing/sandboxed_zip_analyzer.h
@@ -59,10 +59,6 @@
   // Launches the utility process.  Must run on the IO thread.
   void StartProcessOnIOThread();
 
-  // Notification that the utility process is running, and we can now get its
-  // process handle.
-  void OnUtilityProcessStarted();
-
   // Notification from the utility process that the zip file has been analyzed,
   // with the given results.  Runs on the IO thread.
   void OnAnalyzeZipFileFinished(const zip_analyzer::Results& results);
diff --git a/chrome/browser/storage/durable_storage_permission_context_factory.cc b/chrome/browser/storage/durable_storage_permission_context_factory.cc
deleted file mode 100644
index 6b619d0b..0000000
--- a/chrome/browser/storage/durable_storage_permission_context_factory.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2015 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 "chrome/browser/storage/durable_storage_permission_context_factory.h"
-
-#include "chrome/browser/profiles/incognito_helpers.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/storage/durable_storage_permission_context.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-
-// static
-DurableStoragePermissionContext*
-DurableStoragePermissionContextFactory::GetForProfile(Profile* profile) {
-  return static_cast<DurableStoragePermissionContext*>(
-      GetInstance()->GetServiceForBrowserContext(profile, true));
-}
-
-// static
-DurableStoragePermissionContextFactory*
-DurableStoragePermissionContextFactory::GetInstance() {
-  return base::Singleton<DurableStoragePermissionContextFactory>::get();
-}
-
-DurableStoragePermissionContextFactory::DurableStoragePermissionContextFactory()
-    : PermissionContextFactoryBase(
-          "DurableStoragePermissionContext",
-          BrowserContextDependencyManager::GetInstance()) {
-}
-
-KeyedService* DurableStoragePermissionContextFactory::BuildServiceInstanceFor(
-    content::BrowserContext* profile) const {
-  return new DurableStoragePermissionContext(static_cast<Profile*>(profile));
-}
diff --git a/chrome/browser/storage/durable_storage_permission_context_factory.h b/chrome/browser/storage/durable_storage_permission_context_factory.h
deleted file mode 100644
index 2440ffb..0000000
--- a/chrome/browser/storage/durable_storage_permission_context_factory.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef CHROME_BROWSER_STORAGE_DURABLE_STORAGE_PERMISSION_CONTEXT_FACTORY_H_
-#define CHROME_BROWSER_STORAGE_DURABLE_STORAGE_PERMISSION_CONTEXT_FACTORY_H_
-
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "chrome/browser/permissions/permission_context_factory_base.h"
-
-class DurableStoragePermissionContext;
-class Profile;
-
-class DurableStoragePermissionContextFactory
-    : public PermissionContextFactoryBase {
- public:
-  static DurableStoragePermissionContext* GetForProfile(Profile* profile);
-  static DurableStoragePermissionContextFactory* GetInstance();
-
- private:
-  friend struct base::DefaultSingletonTraits<
-      DurableStoragePermissionContextFactory>;
-
-  DurableStoragePermissionContextFactory();
-  ~DurableStoragePermissionContextFactory() override = default;
-
-  // BrowserContextKeyedBaseFactory methods:
-  KeyedService* BuildServiceInstanceFor(
-      content::BrowserContext* profile) const override;
-
-  DISALLOW_COPY_AND_ASSIGN(DurableStoragePermissionContextFactory);
-};
-
-#endif  // CHROME_BROWSER_STORAGE_DURABLE_STORAGE_PERMISSION_CONTEXT_FACTORY_H_
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
index abaa031..250d5f3 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
@@ -1221,9 +1221,11 @@
     title = l10n_util::GetStringUTF16(IDS_BROWSER_WINDOW_MAC_TAB_UNTITLED);
   [tab setTitle:base::SysUTF16ToNSString(title)];
 
-  const base::string16& toolTip = chrome::AssembleTabTooltipText(
-      title, [self alertStateForContents:contents]);
-  [tab setToolTip:base::SysUTF16ToNSString(toolTip)];
+  NSString* toolTip = base::SysUTF16ToNSString(chrome::AssembleTabTooltipText(
+      title, [self alertStateForContents:contents]));
+  [tab setToolTip:toolTip];
+  if ([tab tabView] == hoveredTab_)
+    [toolTipView_ setToolTip:toolTip];
 }
 
 // Called when a notification is received from the model to insert a new tab
@@ -1888,8 +1890,8 @@
     [toolTipView_ setFrame:[newHoveredTab frame]];
     if (![toolTipView_ superview]) {
       [tabStripView_ addSubview:toolTipView_
-                     positioned:NSWindowBelow
-                     relativeTo:nil];
+                     positioned:NSWindowAbove
+                     relativeTo:dragBlockingView_];
     }
   }
 }
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller_unittest.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller_unittest.mm
index 41544ca0..057ebd51 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller_unittest.mm
@@ -280,12 +280,25 @@
   TabController* const tabController = [tab controller];
   WebContents* const contents = model_->GetActiveWebContents();
 
+  // For the duration of the test, assume the tab has been hovered. This adds a
+  // subview containing the actual source of the tooltip.
+  [controller_ setHoveredTab:tab];
+  // Note -[NSView hitTest:] takes superview coordinates. Then, find a spot that
+  // is outside the mask image, but inside the tab.
+  NSPoint centerPoint = NSMakePoint(5, NSMidY([tab bounds]));
+  NSPoint hitPoint = [tab convertPoint:centerPoint
+                                toView:[tab_strip_ superview]];
+  NSView* toolTipView = [tab_strip_ hitTest:hitPoint];
+  EXPECT_TRUE(toolTipView);
+  EXPECT_NE(toolTipView, tab);
+
   // Initially, tab title and tooltip text are equivalent.
   EXPECT_EQ(TabAlertState::NONE,
             chrome::GetTabAlertStateForContents(contents));
   [controller_ setTabTitle:tabController withContents:contents];
   NSString* const baseTitle = [tabController title];
   EXPECT_NSEQ(baseTitle, [tabController toolTip]);
+  EXPECT_NSEQ([tabController toolTip], [toolTipView toolTip]);
 
   // Simulate the start of tab video capture.  Tab title remains the same, but
   // the tooltip text should include the following appended: 1) a line break;
@@ -303,6 +316,7 @@
   [controller_ setTabTitle:tabController withContents:contents];
   EXPECT_NSEQ(baseTitle, [tabController title]);
   NSString* const toolTipText = [tabController toolTip];
+  EXPECT_NSEQ(toolTipText, [toolTipView toolTip]);
   if ([baseTitle length] > 0) {
     EXPECT_TRUE(NSEqualRanges(NSMakeRange(0, [baseTitle length]),
                               [toolTipText rangeOfString:baseTitle]));
@@ -321,6 +335,7 @@
   [controller_ setTabTitle:tabController withContents:contents];
   EXPECT_NSEQ(baseTitle, [tabController title]);
   EXPECT_NSEQ(baseTitle, [tabController toolTip]);
+  EXPECT_NSEQ(baseTitle, [toolTipView toolTip]);
 }
 
 TEST_F(TabStripControllerTest, TabCloseDuringDrag) {
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index eef88877..459dd0d9 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -40,8 +40,6 @@
       'browser/background_sync/background_sync_controller_impl.h',
       'browser/background_sync/background_sync_permission_context.cc',
       'browser/background_sync/background_sync_permission_context.h',
-      'browser/background_sync/background_sync_permission_context_factory.cc',
-      'browser/background_sync/background_sync_permission_context_factory.h',
       'browser/bad_message.cc',
       'browser/bad_message.h',
       'browser/banners/app_banner_data_fetcher.cc',
@@ -262,8 +260,6 @@
       'browser/geolocation/geolocation_permission_context_android.h',
       'browser/geolocation/geolocation_permission_context_extensions.cc',
       'browser/geolocation/geolocation_permission_context_extensions.h',
-      'browser/geolocation/geolocation_permission_context_factory.cc',
-      'browser/geolocation/geolocation_permission_context_factory.h',
       'browser/geolocation/geolocation_prefs.cc',
       'browser/geolocation/geolocation_prefs.h',
       'browser/global_keyboard_shortcuts_mac.h',
@@ -367,8 +363,6 @@
       'browser/media/media_device_id_salt.h',
       'browser/media/media_permission.cc',
       'browser/media/media_permission.h',
-      'browser/media/media_stream_camera_permission_context_factory.cc',
-      'browser/media/media_stream_camera_permission_context_factory.h',
       'browser/media/media_stream_capture_indicator.cc',
       'browser/media/media_stream_capture_indicator.h',
       'browser/media/media_stream_device_permission_context.cc',
@@ -377,14 +371,10 @@
       'browser/media/media_stream_device_permissions.h',
       'browser/media/media_stream_devices_controller.cc',
       'browser/media/media_stream_devices_controller.h',
-      'browser/media/media_stream_mic_permission_context_factory.cc',
-      'browser/media/media_stream_mic_permission_context_factory.h',
       'browser/media/media_url_constants.cc',
       'browser/media/media_url_constants.h',
       'browser/media/midi_permission_context.cc',
       'browser/media/midi_permission_context.h',
-      'browser/media/midi_permission_context_factory.cc',
-      'browser/media/midi_permission_context_factory.h',
       'browser/media/native_desktop_media_list.cc',
       'browser/media/native_desktop_media_list.h',
       'browser/media/permission_bubble_media_access_handler.cc',
@@ -518,8 +508,6 @@
       'browser/push_messaging/push_messaging_constants.h',
       'browser/push_messaging/push_messaging_permission_context.cc',
       'browser/push_messaging/push_messaging_permission_context.h',
-      'browser/push_messaging/push_messaging_permission_context_factory.cc',
-      'browser/push_messaging/push_messaging_permission_context_factory.h',
       'browser/push_messaging/push_messaging_service_factory.cc',
       'browser/push_messaging/push_messaging_service_factory.h',
       'browser/push_messaging/push_messaging_service_impl.cc',
@@ -612,8 +600,6 @@
       'browser/status_icons/status_tray.h',
       'browser/storage/durable_storage_permission_context.cc',
       'browser/storage/durable_storage_permission_context.h',
-      'browser/storage/durable_storage_permission_context_factory.cc',
-      'browser/storage/durable_storage_permission_context_factory.h',
       'browser/storage/storage_info_fetcher.cc',
       'browser/storage/storage_info_fetcher.h',
       'browser/tab_contents/navigation_metrics_recorder.cc',
@@ -674,8 +660,6 @@
     'chrome_browser_android_sources': [
       'browser/media/protected_media_identifier_permission_context.cc',
       'browser/media/protected_media_identifier_permission_context.h',
-      'browser/media/protected_media_identifier_permission_context_factory.cc',
-      'browser/media/protected_media_identifier_permission_context_factory.h',
     ],
     # Browser sources used when android_java_ui is enabled.
     'chrome_browser_android_java_ui_sources': [
@@ -1061,8 +1045,6 @@
       'browser/download/notification/download_notification_manager.h',
       'browser/media/protected_media_identifier_permission_context.cc',
       'browser/media/protected_media_identifier_permission_context.h',
-      'browser/media/protected_media_identifier_permission_context_factory.cc',
-      'browser/media/protected_media_identifier_permission_context_factory.h',
       'browser/metrics/chromeos_metrics_provider.cc',
       'browser/metrics/chromeos_metrics_provider.h',
       'browser/metrics/perf/cpu_identity.cc',
@@ -2161,8 +2143,6 @@
       'browser/notifications/notification_object_proxy.h',
       'browser/notifications/notification_permission_context.cc',
       'browser/notifications/notification_permission_context.h',
-      'browser/notifications/notification_permission_context_factory.cc',
-      'browser/notifications/notification_permission_context_factory.h',
       'browser/notifications/notification_ui_manager.h',
       'browser/notifications/notification_ui_manager_mac.h',
       'browser/notifications/notification_ui_manager_mac.mm',
@@ -2247,12 +2227,8 @@
     'chrome_browser_permissions_sources': [
       'browser/permissions/chooser_context_base.cc',
       'browser/permissions/chooser_context_base.h',
-      'browser/permissions/permission_context.cc',
-      'browser/permissions/permission_context.h',
       'browser/permissions/permission_context_base.cc',
       'browser/permissions/permission_context_base.h',
-      'browser/permissions/permission_context_factory_base.cc',
-      'browser/permissions/permission_context_factory_base.h',
       'browser/permissions/permission_infobar_delegate.cc',
       'browser/permissions/permission_infobar_delegate.h',
       'browser/permissions/permission_manager.cc',
diff --git a/chrome/common/chrome_utility_messages.h b/chrome/common/chrome_utility_messages.h
index ceac6035..0cd82de 100644
--- a/chrome/common/chrome_utility_messages.h
+++ b/chrome/common/chrome_utility_messages.h
@@ -164,11 +164,6 @@
                      base::FileDescriptor /* dest_fd */)
 #endif  // defined(OS_CHROMEOS)
 
-// Requests the utility process to respond with a
-// ChromeUtilityHostMsg_ProcessStarted message once it has started.  This may
-// be used if the host process needs a handle to the running utility process.
-IPC_MESSAGE_CONTROL0(ChromeUtilityMsg_StartupPing)
-
 #if defined(FULL_SAFE_BROWSING)
 // Tells the utility process to analyze a zip file for malicious download
 // protection, providing a file that can be used temporarily to analyze binaries
@@ -233,9 +228,6 @@
 IPC_MESSAGE_CONTROL0(ChromeUtilityHostMsg_CreateZipFile_Failed)
 #endif  // defined(OS_CHROMEOS)
 
-// Reply when the utility process has started.
-IPC_MESSAGE_CONTROL0(ChromeUtilityHostMsg_ProcessStarted)
-
 #if defined(FULL_SAFE_BROWSING)
 // Reply when a zip file has been analyzed for malicious download protection.
 IPC_MESSAGE_CONTROL1(
diff --git a/chrome/utility/chrome_content_utility_client.cc b/chrome/utility/chrome_content_utility_client.cc
index 6bef1f6..f00b01c9 100644
--- a/chrome/utility/chrome_content_utility_client.cc
+++ b/chrome/utility/chrome_content_utility_client.cc
@@ -161,7 +161,6 @@
                         OnPatchFileBsdiff)
     IPC_MESSAGE_HANDLER(ChromeUtilityMsg_PatchFileCourgette,
                         OnPatchFileCourgette)
-    IPC_MESSAGE_HANDLER(ChromeUtilityMsg_StartupPing, OnStartupPing)
 #if defined(FULL_SAFE_BROWSING)
     IPC_MESSAGE_HANDLER(ChromeUtilityMsg_AnalyzeZipFileForDownloadProtection,
                         OnAnalyzeZipFileForDownloadProtection)
@@ -278,11 +277,6 @@
   ReleaseProcessIfNeeded();
 }
 
-void ChromeContentUtilityClient::OnStartupPing() {
-  Send(new ChromeUtilityHostMsg_ProcessStarted);
-  // Don't release the process, we assume further messages are on the way.
-}
-
 #if defined(FULL_SAFE_BROWSING)
 void ChromeContentUtilityClient::OnAnalyzeZipFileForDownloadProtection(
     const IPC::PlatformFileForTransit& zip_file,
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index ccdb111..ddb1a16 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -72,6 +72,7 @@
 #include "third_party/WebKit/public/web/WebInputEvent.h"
 #import "ui/base/clipboard/clipboard_util_mac.h"
 #include "ui/base/cocoa/animation_utils.h"
+#import "ui/base/cocoa/appkit_utils.h"
 #include "ui/base/cocoa/cocoa_base_utils.h"
 #import "ui/base/cocoa/fullscreen_window_manager.h"
 #import "ui/base/cocoa/underlay_opengl_hosting_window.h"
@@ -2303,7 +2304,8 @@
 }
 
 - (void)forceTouchEvent:(NSEvent*)theEvent {
-  [self quickLookWithEvent:theEvent];
+  if (ui::ForceClickInvokesQuickLook())
+    [self quickLookWithEvent:theEvent];
 }
 
 - (void)shortCircuitScrollWheelEvent:(NSEvent*)event {
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index d25ebf1..cb4fa74 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -1203,8 +1203,7 @@
   // TODO(dglazkov): WebFrameContentDumper should only be used for
   // testing purposes. See http://crbug.com/585164.
   std::string text =
-      WebFrameContentDumper::deprecatedDumpFrameTreeAsText(
-          webview()->mainFrame()->toWebLocalFrame(), kMaximumMessageSize)
+      WebFrameContentDumper::dumpWebViewAsText(webview(), kMaximumMessageSize)
           .utf8();
 
   Send(new ViewMsg_GetRenderedTextCompleted(GetRoutingID(), text));
diff --git a/services/shell/BUILD.gn b/services/shell/BUILD.gn
index e3ce5fa..58c7f8d 100644
--- a/services/shell/BUILD.gn
+++ b/services/shell/BUILD.gn
@@ -24,7 +24,6 @@
     "connect_params.h",
     "connect_util.cc",
     "connect_util.h",
-    "loader.h",
     "native_runner.h",
     "native_runner_delegate.h",
     "shell.cc",
@@ -53,9 +52,6 @@
   data_deps = [
     ":manifest",
   ]
-
-  # For services/shell/loader.h
-  allow_circular_includes_from = [ "//services/catalog:lib" ]
 }
 
 mojo_application_manifest("manifest") {
diff --git a/services/shell/background/background_shell.cc b/services/shell/background/background_shell.cc
index 6ce9f8a..7e16e7c 100644
--- a/services/shell/background/background_shell.cc
+++ b/services/shell/background/background_shell.cc
@@ -15,7 +15,6 @@
 #include "mojo/message_pump/message_pump_mojo.h"
 #include "services/catalog/store.h"
 #include "services/shell/connect_params.h"
-#include "services/shell/loader.h"
 #include "services/shell/public/cpp/shell_client.h"
 #include "services/shell/public/cpp/shell_connection.h"
 #include "services/shell/shell.h"
@@ -29,30 +28,6 @@
   return base::WrapUnique(new mojo::common::MessagePumpMojo);
 }
 
-// Used to obtain the ShellClientRequest for an application. When Loader::Load()
-// is called a callback is run with the ShellClientRequest.
-class BackgroundLoader : public Loader {
- public:
-  using Callback = base::Callback<void(mojom::ShellClientRequest)>;
-
-  explicit BackgroundLoader(const Callback& callback) : callback_(callback) {}
-  ~BackgroundLoader() override {}
-
-  // Loader:
-  void Load(const std::string& name,
-            mojom::ShellClientRequest request) override {
-    DCHECK(!callback_.is_null());  // Callback should only be run once.
-    Callback callback = callback_;
-    callback_.Reset();
-    callback.Run(std::move(request));
-  }
-
- private:
-  Callback callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(BackgroundLoader);
-};
-
 class MojoMessageLoop : public base::MessageLoop {
  public:
   MojoMessageLoop()
@@ -77,20 +52,16 @@
   ~MojoThread() override {}
 
   void CreateShellClientRequest(base::WaitableEvent* signal,
-                                std::unique_ptr<ConnectParams> params,
+                                const std::string& name,
                                 mojom::ShellClientRequest* request) {
     // Only valid to call this on the background thread.
     DCHECK_EQ(message_loop_, base::MessageLoop::current());
+    *request = context_->shell()->InitInstanceForEmbedder(name);
+    signal->Signal();
+  }
 
-    // Ownership of |loader| passes to Shell.
-    const std::string name = params->target().name();
-    BackgroundLoader* loader = new BackgroundLoader(
-        base::Bind(&MojoThread::OnGotApplicationRequest, base::Unretained(this),
-                   name, signal, request));
-    context_->shell()->SetLoaderForName(base::WrapUnique(loader), name);
+  void Connect(std::unique_ptr<ConnectParams> params) {
     context_->shell()->Connect(std::move(params));
-    // The request is asynchronously processed. When processed
-    // OnGotApplicationRequest() is called and we'll signal |signal|.
   }
 
   base::MessageLoop* message_loop() { return message_loop_; }
@@ -148,16 +119,6 @@
   }
 
  private:
-  void OnGotApplicationRequest(const std::string& name,
-                               base::WaitableEvent* signal,
-                               mojom::ShellClientRequest* request_result,
-                               mojom::ShellClientRequest actual_request) {
-    *request_result = std::move(actual_request);
-    // Trigger destruction of the loader.
-    context_->shell()->SetLoaderForName(nullptr, name);
-    signal->Signal();
-  }
-
   // We own this. It's created on the main thread, but destroyed on the
   // background thread.
   MojoMessageLoop* message_loop_ = nullptr;
@@ -193,9 +154,13 @@
   base::WaitableEvent signal(true, false);
   thread_->message_loop()->task_runner()->PostTask(
       FROM_HERE, base::Bind(&MojoThread::CreateShellClientRequest,
-                            base::Unretained(thread_.get()), &signal,
-                            base::Passed(&params), &request));
+                            base::Unretained(thread_.get()), &signal, name,
+                            &request));
   signal.Wait();
+  thread_->message_loop()->task_runner()->PostTask(
+      FROM_HERE, base::Bind(&MojoThread::Connect,
+                            base::Unretained(thread_.get()),
+                            base::Passed(&params)));
   return request;
 }
 
diff --git a/services/shell/loader.h b/services/shell/loader.h
deleted file mode 100644
index c99b628..0000000
--- a/services/shell/loader.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2014 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.
-
-#ifndef SERVICES_SHELL_LOADER_H_
-#define SERVICES_SHELL_LOADER_H_
-
-#include "base/callback.h"
-#include "mojo/public/cpp/system/core.h"
-#include "services/shell/public/interfaces/connector.mojom.h"
-#include "services/shell/public/interfaces/shell_client.mojom.h"
-
-namespace shell {
-
-// Interface to implement special loading behavior for a particular name.
-class Loader {
- public:
-  virtual ~Loader() {}
-
-  virtual void Load(const std::string& name,
-                    mojom::ShellClientRequest request) = 0;
-};
-
-}  // namespace shell
-
-#endif  // SERVICES_SHELL_LOADER_H_
diff --git a/services/shell/shell.cc b/services/shell/shell.cc
index 35049dd..a542ae4 100644
--- a/services/shell/shell.cc
+++ b/services/shell/shell.cc
@@ -120,10 +120,8 @@
       allow_any_application_(capability_spec.required.count("*") == 1),
       pid_receiver_binding_(this),
       weak_factory_(this) {
-    if (identity_.name() == kShellName ||
-        shell_->GetLoaderForName(identity_.name())) {
+    if (identity_.name() == kShellName)
       pid_ = base::Process::Current().Pid();
-    }
     DCHECK_NE(mojom::kInvalidInstanceID, id_);
   }
 
@@ -460,7 +458,6 @@
 
 Shell::~Shell() {
   TerminateShellConnections();
-  STLDeleteValues(&name_to_loader_);
   for (auto& runner : native_runners_)
     runner.reset();
 }
@@ -489,14 +486,6 @@
   return request;
 }
 
-void Shell::SetLoaderForName(std::unique_ptr<Loader> loader,
-                             const std::string& name) {
-  auto it = name_to_loader_.find(name);
-  if (it != name_to_loader_.end())
-    delete it->second;
-  name_to_loader_[name] = loader.release();
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // Shell, ShellClient implementation:
 
@@ -737,21 +726,17 @@
   } else {
     // Otherwise we create a new ShellClient pipe.
     mojom::ShellClientRequest request = GetProxy(&client);
-    if (LoadWithLoader(target, &request)) {
-      instance->StartWithClient(std::move(client));
-    } else {
-      CHECK(!result->package_url.is_null() && !result->capabilities.is_null());
+    CHECK(!result->package_url.is_null() && !result->capabilities.is_null());
 
-      if (target.name() != result->resolved_name) {
-        instance->StartWithClient(std::move(client));
-        Identity factory(result->resolved_name, target.user_id(),
-                         instance_name);
-        CreateShellClientWithFactory(factory, target.name(),
-                                     std::move(request));
-      } else {
-        instance->StartWithFilePath(
-            mojo::util::UrlToFilePath(result->package_url.To<GURL>()));
-      }
+    if (target.name() != result->resolved_name) {
+      instance->StartWithClient(std::move(client));
+      Identity factory(result->resolved_name, target.user_id(),
+                       instance_name);
+      CreateShellClientWithFactory(factory, target.name(),
+                                   std::move(request));
+    } else {
+      instance->StartWithFilePath(
+          mojo::util::UrlToFilePath(result->package_url.To<GURL>()));
     }
   }
 
@@ -759,22 +744,6 @@
   instance->ConnectToClient(std::move(params));
 }
 
-bool Shell::LoadWithLoader(const Identity& target,
-                           mojom::ShellClientRequest* request) {
-  Loader* loader = GetLoaderForName(target.name());
-  if (!loader)
-    return false;
-  loader->Load(target.name(), std::move(*request));
-  return true;
-}
-
-Loader* Shell::GetLoaderForName(const std::string& name) {
-  auto name_it = name_to_loader_.find(name);
-  if (name_it != name_to_loader_.end())
-    return name_it->second;
-  return default_loader_.get();
-}
-
 base::WeakPtr<Shell> Shell::GetWeakPtr() {
   return weak_ptr_factory_.GetWeakPtr();
 }
diff --git a/services/shell/shell.gyp b/services/shell/shell.gyp
index e32ecd27..beb82ac5 100644
--- a/services/shell/shell.gyp
+++ b/services/shell/shell.gyp
@@ -79,7 +79,6 @@
       '../catalog/store.cc',
       '../catalog/store.h',
       '../catalog/types.h',
-      'loader.h',
       'connect_params.cc',
       'connect_params.h',
       'connect_util.cc',
@@ -109,7 +108,7 @@
     'target_name': 'mojo_shell_unittests',
     'type': 'executable',
     'sources': [
-      'tests/loader_unittest.cc',
+      'tests/placeholder_unittest.cc',
     ],
     'dependencies': [
       'shell_lib',
diff --git a/services/shell/shell.h b/services/shell/shell.h
index fc17adf..f336025 100644
--- a/services/shell/shell.h
+++ b/services/shell/shell.h
@@ -14,7 +14,6 @@
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "mojo/public/cpp/bindings/interface_ptr_set.h"
 #include "services/shell/connect_params.h"
-#include "services/shell/loader.h"
 #include "services/shell/native_runner.h"
 #include "services/shell/public/cpp/capabilities.h"
 #include "services/shell/public/cpp/identity.h"
@@ -54,8 +53,7 @@
   // implementations of NativeRunner, e.g. for in or out-of-process execution.
   // See native_runner.h and RunNativeApplication().
   // |file_task_runner| provides access to a thread to perform file copy
-  // operations on. This may be null only in testing environments where
-  // applications are loaded via Loader implementations.
+  // operations on.
   Shell(std::unique_ptr<NativeRunnerFactory> native_runner_factory,
         mojom::ShellClientPtr catalog);
   ~Shell() override;
@@ -75,15 +73,6 @@
   // called once.
   mojom::ShellClientRequest InitInstanceForEmbedder(const std::string& name);
 
-  // Sets the default Loader to be used if not overridden by SetLoaderForName().
-  void set_default_loader(std::unique_ptr<Loader> loader) {
-    default_loader_ = std::move(loader);
-  }
-
-  // Sets a Loader to be used for a specific name.
-  void SetLoaderForName(std::unique_ptr<Loader> loader,
-                        const std::string& name);
-
  private:
   class Instance;
 
@@ -147,24 +136,10 @@
                          mojom::ShellClientPtr client,
                          mojom::ResolveResultPtr result);
 
-  // Tries to load |target| with an Loader. Returns true if one was registered
-  // and it was loaded, in which case |request| is taken.
-  bool LoadWithLoader(const Identity& target,
-                      mojom::ShellClientRequest* request);
-
-  // Returns the appropriate loader for |name|, or the default loader if there
-  // is no loader configured for the name.
-  Loader* GetLoaderForName(const std::string& name);
-
   base::WeakPtr<Shell> GetWeakPtr();
 
   void CleanupRunner(NativeRunner* runner);
 
-  // Loader management.
-  // Loaders are chosen in the order they are listed here.
-  std::map<std::string, Loader*> name_to_loader_;
-  std::unique_ptr<Loader> default_loader_;
-
   std::map<Identity, Instance*> identity_to_instance_;
 
   // Tracks the names of instances that are allowed to field connection requests
diff --git a/services/shell/tests/BUILD.gn b/services/shell/tests/BUILD.gn
index 8ffc76d..69393a5 100644
--- a/services/shell/tests/BUILD.gn
+++ b/services/shell/tests/BUILD.gn
@@ -14,10 +14,6 @@
 }
 
 test("mojo_shell_unittests") {
-  sources = [
-    "loader_unittest.cc",
-  ]
-
   deps = [
     ":interfaces",
     "//base",
diff --git a/services/shell/tests/loader_unittest.cc b/services/shell/tests/loader_unittest.cc
deleted file mode 100644
index 757514a..0000000
--- a/services/shell/tests/loader_unittest.cc
+++ /dev/null
@@ -1,560 +0,0 @@
-// Copyright 2014 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 <memory>
-#include <utility>
-
-#include "base/at_exit.h"
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/scoped_vector.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-#include "services/catalog/catalog.h"
-#include "services/catalog/store.h"
-#include "services/shell/connect_util.h"
-#include "services/shell/loader.h"
-#include "services/shell/public/cpp/connector.h"
-#include "services/shell/public/cpp/interface_factory.h"
-#include "services/shell/public/cpp/shell_client.h"
-#include "services/shell/public/cpp/shell_connection.h"
-#include "services/shell/public/interfaces/interface_provider.mojom.h"
-#include "services/shell/shell.h"
-#include "services/shell/tests/test.mojom.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace shell {
-namespace test {
-
-const char kTestURLString[] = "test:testService";
-const char kTestAURLString[] = "test:TestA";
-const char kTestBURLString[] = "test:TestB";
-
-struct TestContext {
-  TestContext() : num_impls(0), num_loader_deletes(0) {}
-  std::string last_test_string;
-  int num_impls;
-  int num_loader_deletes;
-};
-
-void QuitClosure(const Identity& expected,
-                 bool* value,
-                 const Identity& actual) {
-  if (expected == actual) {
-    *value = true;
-    base::MessageLoop::current()->QuitWhenIdle();
-  }
-}
-
-class TestServiceImpl : public TestService {
- public:
-  TestServiceImpl(TestContext* context, TestServiceRequest request)
-      : context_(context), binding_(this, std::move(request)) {
-    ++context_->num_impls;
-  }
-
-  ~TestServiceImpl() override {
-    --context_->num_impls;
-    if (!base::MessageLoop::current()->is_running())
-      return;
-    base::MessageLoop::current()->QuitWhenIdle();
-  }
-
-  // TestService implementation:
-  void Test(const mojo::String& test_string,
-            const mojo::Closure& callback) override {
-    context_->last_test_string = test_string;
-    callback.Run();
-  }
-
- private:
-  TestContext* context_;
-  mojo::StrongBinding<TestService> binding_;
-};
-
-class TestClient {
- public:
-  explicit TestClient(TestServicePtr service)
-      : service_(std::move(service)), quit_after_ack_(false) {}
-
-  void AckTest() {
-    if (quit_after_ack_)
-      base::MessageLoop::current()->QuitWhenIdle();
-  }
-
-  void Test(const std::string& test_string) {
-    quit_after_ack_ = true;
-    service_->Test(test_string,
-                   base::Bind(&TestClient::AckTest, base::Unretained(this)));
-  }
-
- private:
-  TestServicePtr service_;
-  bool quit_after_ack_;
-  DISALLOW_COPY_AND_ASSIGN(TestClient);
-};
-
-class TestLoader : public Loader,
-                   public ShellClient,
-                   public InterfaceFactory<TestService> {
- public:
-  explicit TestLoader(TestContext* context)
-      : context_(context), num_loads_(0) {}
-
-  ~TestLoader() override {
-    ++context_->num_loader_deletes;
-    shell_connection_.reset();
-  }
-
-  int num_loads() const { return num_loads_; }
-  const std::string& last_requestor_name() const {
-    return last_requestor_name_;
-  }
-
- private:
-  // Loader implementation.
-  void Load(const std::string& name,
-            mojom::ShellClientRequest request) override {
-    ++num_loads_;
-    shell_connection_.reset(new ShellConnection(this, std::move(request)));
-  }
-
-  // ShellClient implementation.
-  bool AcceptConnection(Connection* connection) override {
-    connection->AddInterface<TestService>(this);
-    last_requestor_name_ = connection->GetRemoteIdentity().name();
-    return true;
-  }
-
-  // InterfaceFactory<TestService> implementation.
-  void Create(Connection* connection, TestServiceRequest request) override {
-    new TestServiceImpl(context_, std::move(request));
-  }
-
-  std::unique_ptr<ShellConnection> shell_connection_;
-  TestContext* context_;
-  int num_loads_;
-  std::string last_requestor_name_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestLoader);
-};
-
-class ClosingLoader : public Loader {
- private:
-  // Loader implementation.
-  void Load(const std::string& name,
-            mojom::ShellClientRequest request) override {
-  }
-};
-
-class TesterContext {
- public:
-  explicit TesterContext(base::MessageLoop* loop)
-      : num_b_calls_(0),
-        num_c_calls_(0),
-        num_a_deletes_(0),
-        num_b_deletes_(0),
-        num_c_deletes_(0),
-        tester_called_quit_(false),
-        a_called_quit_(false),
-        loop_(loop) {}
-
-  void IncrementNumBCalls() {
-    base::AutoLock lock(lock_);
-    num_b_calls_++;
-  }
-
-  void IncrementNumCCalls() {
-    base::AutoLock lock(lock_);
-    num_c_calls_++;
-  }
-
-  void IncrementNumADeletes() {
-    base::AutoLock lock(lock_);
-    num_a_deletes_++;
-  }
-
-  void IncrementNumBDeletes() {
-    base::AutoLock lock(lock_);
-    num_b_deletes_++;
-  }
-
-  void IncrementNumCDeletes() {
-    base::AutoLock lock(lock_);
-    num_c_deletes_++;
-  }
-
-  void set_tester_called_quit() {
-    base::AutoLock lock(lock_);
-    tester_called_quit_ = true;
-  }
-
-  void set_a_called_quit() {
-    base::AutoLock lock(lock_);
-    a_called_quit_ = true;
-  }
-
-  int num_b_calls() {
-    base::AutoLock lock(lock_);
-    return num_b_calls_;
-  }
-  int num_c_calls() {
-    base::AutoLock lock(lock_);
-    return num_c_calls_;
-  }
-  int num_a_deletes() {
-    base::AutoLock lock(lock_);
-    return num_a_deletes_;
-  }
-  int num_b_deletes() {
-    base::AutoLock lock(lock_);
-    return num_b_deletes_;
-  }
-  int num_c_deletes() {
-    base::AutoLock lock(lock_);
-    return num_c_deletes_;
-  }
-  bool tester_called_quit() {
-    base::AutoLock lock(lock_);
-    return tester_called_quit_;
-  }
-  bool a_called_quit() {
-    base::AutoLock lock(lock_);
-    return a_called_quit_;
-  }
-
-  void QuitSoon() {
-    loop_->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
-  }
-
- private:
-  // lock_ protects all members except for loop_ which must be unchanged for the
-  // lifetime of this class.
-  base::Lock lock_;
-  int num_b_calls_;
-  int num_c_calls_;
-  int num_a_deletes_;
-  int num_b_deletes_;
-  int num_c_deletes_;
-  bool tester_called_quit_;
-  bool a_called_quit_;
-
-  base::MessageLoop* loop_;
-};
-
-// Used to test that the requestor name will be correctly passed.
-class TestAImpl : public TestA {
- public:
-  TestAImpl(Connector* connector,
-            TesterContext* test_context,
-            TestARequest request,
-            InterfaceFactory<TestC>* factory)
-      : test_context_(test_context), binding_(this, std::move(request)) {
-    connection_ = connector->Connect(kTestBURLString);
-    connection_->AddInterface<TestC>(factory);
-    connection_->GetInterface(&b_);
-  }
-
-  ~TestAImpl() override {
-    test_context_->IncrementNumADeletes();
-    if (base::MessageLoop::current()->is_running())
-      Quit();
-  }
-
- private:
-  void CallB() override {
-    b_->B(base::Bind(&TestAImpl::Quit, base::Unretained(this)));
-  }
-
-  void CallCFromB() override {
-    b_->CallC(base::Bind(&TestAImpl::Quit, base::Unretained(this)));
-  }
-
-  void Quit() {
-    base::MessageLoop::current()->QuitWhenIdle();
-    test_context_->set_a_called_quit();
-    test_context_->QuitSoon();
-  }
-
-  std::unique_ptr<Connection> connection_;
-  TesterContext* test_context_;
-  TestBPtr b_;
-  mojo::StrongBinding<TestA> binding_;
-};
-
-class TestBImpl : public TestB {
- public:
-  TestBImpl(Connection* connection,
-            TesterContext* test_context,
-            TestBRequest request)
-      : test_context_(test_context), binding_(this, std::move(request)) {
-    connection->GetInterface(&c_);
-  }
-
-  ~TestBImpl() override {
-    test_context_->IncrementNumBDeletes();
-    if (base::MessageLoop::current()->is_running())
-      base::MessageLoop::current()->QuitWhenIdle();
-    test_context_->QuitSoon();
-  }
-
- private:
-  void B(const mojo::Closure& callback) override {
-    test_context_->IncrementNumBCalls();
-    callback.Run();
-  }
-
-  void CallC(const mojo::Closure& callback) override {
-    test_context_->IncrementNumBCalls();
-    c_->C(callback);
-  }
-
-  TesterContext* test_context_;
-  TestCPtr c_;
-  mojo::StrongBinding<TestB> binding_;
-};
-
-class TestCImpl : public TestC {
- public:
-  TestCImpl(Connection* connection,
-            TesterContext* test_context,
-            TestCRequest request)
-      : test_context_(test_context), binding_(this, std::move(request)) {}
-
-  ~TestCImpl() override { test_context_->IncrementNumCDeletes(); }
-
- private:
-  void C(const mojo::Closure& callback) override {
-    test_context_->IncrementNumCCalls();
-    callback.Run();
-  }
-
-  TesterContext* test_context_;
-  mojo::StrongBinding<TestC> binding_;
-};
-
-class Tester : public ShellClient,
-               public Loader,
-               public InterfaceFactory<TestA>,
-               public InterfaceFactory<TestB>,
-               public InterfaceFactory<TestC> {
- public:
-  Tester(TesterContext* context, const std::string& requestor_name)
-      : context_(context), requestor_name_(requestor_name) {}
-  ~Tester() override {}
-
- private:
-  void Load(const std::string& name,
-            mojom::ShellClientRequest request) override {
-    app_.reset(new ShellConnection(this, std::move(request)));
-  }
-
-  bool AcceptConnection(Connection* connection) override {
-    if (!requestor_name_.empty() &&
-        requestor_name_ != connection->GetRemoteIdentity().name()) {
-      context_->set_tester_called_quit();
-      context_->QuitSoon();
-      base::MessageLoop::current()->QuitWhenIdle();
-      return false;
-    }
-    // If we're coming from A, then add B, otherwise A.
-    if (connection->GetRemoteIdentity().name() == kTestAURLString)
-      connection->AddInterface<TestB>(this);
-    else
-      connection->AddInterface<TestA>(this);
-    return true;
-  }
-
-  void Create(Connection* connection, TestARequest request) override {
-    a_bindings_.push_back(
-        new TestAImpl(app_->connector(), context_, std::move(request), this));
-  }
-
-  void Create(Connection* connection, TestBRequest request) override {
-    new TestBImpl(connection, context_, std::move(request));
-  }
-
-  void Create(Connection* connection, TestCRequest request) override {
-    new TestCImpl(connection, context_, std::move(request));
-  }
-
-  TesterContext* context_;
-  std::unique_ptr<ShellConnection> app_;
-  std::string requestor_name_;
-  ScopedVector<TestAImpl> a_bindings_;
-};
-
-void OnConnect(base::RunLoop* loop,
-               mojom::ConnectResult result,
-               const mojo::String& user_id,
-               uint32_t instance_id) {
-  loop->Quit();
-}
-
-class LoaderTest : public testing::Test {
- public:
-  LoaderTest() : tester_context_(&loop_) {}
-  ~LoaderTest() override {}
-
-  void SetUp() override {
-    blocking_pool_ = new base::SequencedWorkerPool(3, "blocking_pool");
-    catalog_.reset(
-        new catalog::Catalog(blocking_pool_.get(), nullptr, nullptr));
-    shell_.reset(new Shell(nullptr, catalog_->TakeShellClient()));
-    test_loader_ = new TestLoader(&context_);
-    shell_->set_default_loader(std::unique_ptr<Loader>(test_loader_));
-
-    TestServicePtr service_proxy;
-    ConnectToInterface(kTestURLString, &service_proxy);
-    test_client_.reset(new TestClient(std::move(service_proxy)));
-  }
-
-  void TearDown() override {
-    test_client_.reset();
-    shell_.reset();
-    blocking_pool_->Shutdown();
-  }
-
-  void AddLoaderForName(const std::string& name,
-                        const std::string& requestor_name) {
-    shell_->SetLoaderForName(
-        base::WrapUnique(new Tester(&tester_context_, requestor_name)), name);
-  }
-
-  bool HasRunningInstanceForName(const std::string& name) {
-    Shell::TestAPI test_api(shell_.get());
-    return test_api.HasRunningInstanceForName(name);
-  }
-
- protected:
-  template <typename Interface>
-  void ConnectToInterface(const std::string& name,
-                          mojo::InterfacePtr<Interface>* ptr) {
-    base::RunLoop loop;
-    mojom::InterfaceProviderPtr remote_interfaces;
-    std::unique_ptr<ConnectParams> params(new ConnectParams);
-    params->set_source(CreateShellIdentity());
-    params->set_target(Identity(name, mojom::kRootUserID));
-    params->set_remote_interfaces(mojo::GetProxy(&remote_interfaces));
-    params->set_connect_callback(
-        base::Bind(&OnConnect, base::Unretained(&loop)));
-    shell_->Connect(std::move(params));
-    loop.Run();
-
-    GetInterface(remote_interfaces.get(), ptr);
-  }
-
-  base::ShadowingAtExitManager at_exit_;
-  TestLoader* test_loader_;
-  TesterContext tester_context_;
-  TestContext context_;
-  base::MessageLoop loop_;
-  std::unique_ptr<TestClient> test_client_;
-  std::unique_ptr<catalog::Catalog> catalog_;
-  scoped_refptr<base::SequencedWorkerPool> blocking_pool_;
-  std::unique_ptr<Shell> shell_;
-
-  DISALLOW_COPY_AND_ASSIGN(LoaderTest);
-};
-
-TEST_F(LoaderTest, Basic) {
-  test_client_->Test("test");
-  loop_.Run();
-  EXPECT_EQ(std::string("test"), context_.last_test_string);
-}
-
-TEST_F(LoaderTest, ClientError) {
-  test_client_->Test("test");
-  EXPECT_TRUE(HasRunningInstanceForName(kTestURLString));
-  loop_.Run();
-  EXPECT_EQ(1, context_.num_impls);
-  test_client_.reset();
-  loop_.Run();
-  EXPECT_EQ(0, context_.num_impls);
-  EXPECT_TRUE(HasRunningInstanceForName(kTestURLString));
-}
-
-TEST_F(LoaderTest, Deletes) {
-  {
-    catalog::Catalog catalog(blocking_pool_.get(), nullptr, nullptr);
-    Shell shell(nullptr, catalog.TakeShellClient());
-    TestLoader* default_loader = new TestLoader(&context_);
-    TestLoader* name_loader1 = new TestLoader(&context_);
-    TestLoader* name_loader2 = new TestLoader(&context_);
-    shell.set_default_loader(std::unique_ptr<Loader>(default_loader));
-    shell.SetLoaderForName(std::unique_ptr<Loader>(name_loader1), "test:test1");
-    shell.SetLoaderForName(std::unique_ptr<Loader>(name_loader2), "test:test1");
-  }
-  EXPECT_EQ(3, context_.num_loader_deletes);
-}
-
-// Test for SetLoaderForName() & set_default_loader().
-TEST_F(LoaderTest, SetLoaders) {
-  TestLoader* default_loader = new TestLoader(&context_);
-  TestLoader* name_loader = new TestLoader(&context_);
-  shell_->set_default_loader(std::unique_ptr<Loader>(default_loader));
-  shell_->SetLoaderForName(std::unique_ptr<Loader>(name_loader), "test:test1");
-
-  // test::test1 should go to name_loader.
-  TestServicePtr test_service;
-  ConnectToInterface("test:test1", &test_service);
-  EXPECT_EQ(1, name_loader->num_loads());
-  EXPECT_EQ(0, default_loader->num_loads());
-
-  // http::test1 should go to default loader.
-  ConnectToInterface("http:test1", &test_service);
-  EXPECT_EQ(1, name_loader->num_loads());
-  EXPECT_EQ(1, default_loader->num_loads());
-}
-
-TEST_F(LoaderTest, NoServiceNoLoad) {
-  AddLoaderForName(kTestAURLString, std::string());
-
-  // There is no TestC service implementation registered with the Shell, so this
-  // cannot succeed (but also shouldn't crash).
-  TestCPtr c;
-  ConnectToInterface(kTestAURLString, &c);
-  c.set_connection_error_handler(
-      []() { base::MessageLoop::current()->QuitWhenIdle(); });
-
-  loop_.Run();
-  EXPECT_TRUE(c.encountered_error());
-}
-
-TEST_F(LoaderTest, TestEndApplicationClosure) {
-  ClosingLoader* loader = new ClosingLoader();
-  shell_->SetLoaderForName(std::unique_ptr<Loader>(loader), "test:test");
-
-  bool called = false;
-  std::unique_ptr<ConnectParams> params(new ConnectParams);
-  params->set_source(CreateShellIdentity());
-  params->set_target(Identity("test:test", mojom::kRootUserID));
-  shell_->SetInstanceQuitCallback(
-      base::Bind(&QuitClosure, params->target(), &called));
-  shell_->Connect(std::move(params));
-  loop_.Run();
-  EXPECT_TRUE(called);
-}
-
-TEST_F(LoaderTest, SameIdentityShouldNotCauseDuplicateLoad) {
-  // 1 because LoaderTest connects once at startup.
-  EXPECT_EQ(1, test_loader_->num_loads());
-
-  TestServicePtr test_service;
-  ConnectToInterface("test:foo", &test_service);
-  EXPECT_EQ(2, test_loader_->num_loads());
-
-  // Exactly the same name as above.
-  ConnectToInterface("test:foo", &test_service);
-  EXPECT_EQ(2, test_loader_->num_loads());
-
-  // A different identity because the domain is different.
-  ConnectToInterface("test:bar", &test_service);
-  EXPECT_EQ(3, test_loader_->num_loads());
-}
-
-}  // namespace test
-}  // namespace shell
diff --git a/services/shell/tests/placeholder_unittest.cc b/services/shell/tests/placeholder_unittest.cc
new file mode 100644
index 0000000..df9d827a
--- /dev/null
+++ b/services/shell/tests/placeholder_unittest.cc
@@ -0,0 +1,8 @@
+// Copyright 2016 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 "testing/gtest/include/gtest/gtest.h"
+
+// Dummy test to keep mojo_shell_unittests building and linking in GYP builds.
+TEST(PlaceholderTest, Empty) {}
diff --git a/third_party/WebKit/LayoutTests/fast/table/internal-center-ua-only.html b/third_party/WebKit/LayoutTests/fast/table/internal-center-ua-only.html
new file mode 100644
index 0000000..3f8c096
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/table/internal-center-ua-only.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<style>
+th {
+  text-align: right;
+  text-align: -internal-center;
+}
+</style>
+<table>
+  <tr>
+    <th id="header"></th>
+  </tr>
+</table>
+<script>
+test(function() {
+  assert_false(CSS.supports('text-align', '-internal-center'));
+}, '"text-align" property does not support value "-internal-center"');
+test(function() {
+  assert_equals(getComputedStyle(header).textAlign, 'right');
+}, '"text-align" property cannot be set to "-internal-center" by the author stylesheet');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/table/th-text-align.html b/third_party/WebKit/LayoutTests/fast/table/th-text-align.html
new file mode 100644
index 0000000..ba53c0e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/table/th-text-align.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<table>
+  <tr id="parent">
+    <th id="header"></th>
+  </tr>
+</table>
+<script>
+
+// Verifies that the text-align property on th elements may be set to 'start'
+test(function() {
+  header.style.textAlign = 'start';
+  assert_equals(getComputedStyle(header).textAlign, 'start');
+}, 'setting "text-align: start" on th element results in textAlign == "start"');
+test(function() {
+  header.style.textAlign = 'inherit';
+  assert_equals(getComputedStyle(header).textAlign, 'start');
+}, 'setting "text-align: inherit" on th element results in textAlign == "start"');
+test(function() {
+  header.style.textAlign = 'initial';
+  assert_equals(getComputedStyle(header).textAlign, 'start');
+}, 'setting "text-align: initial" on th element results in textAlign == "start"');
+
+// Verifies that the text-align property set on th elements overrides the inherited value
+test(function() {
+  document.getElementById('parent').style.textAlign = 'right';
+  header.style.textAlign = 'start';
+  assert_equals(getComputedStyle(header).textAlign, 'start');
+}, 'setting text-align on th element overrides the inherited value');
+</script>
diff --git a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
index f1a6349..86e3c77 100644
--- a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
+++ b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
@@ -1978,6 +1978,8 @@
         return TASTART;
     case CSSValueEnd:
         return TAEND;
+    case CSSValueInternalCenter:
+        return CENTER;
     default:
         return static_cast<ETextAlign>(m_value.valueID - CSSValueLeft);
     }
diff --git a/third_party/WebKit/Source/core/css/CSSValueKeywords.in b/third_party/WebKit/Source/core/css/CSSValueKeywords.in
index 079326d9..fe9a350 100644
--- a/third_party/WebKit/Source/core/css/CSSValueKeywords.in
+++ b/third_party/WebKit/Source/core/css/CSSValueKeywords.in
@@ -252,6 +252,7 @@
 -webkit-right
 -webkit-center
 -webkit-match-parent
+-internal-center
 //
 // text-justify
 //
diff --git a/third_party/WebKit/Source/core/css/html.css b/third_party/WebKit/Source/core/css/html.css
index 9b6161a..3d23a2d 100644
--- a/third_party/WebKit/Source/core/css/html.css
+++ b/third_party/WebKit/Source/core/css/html.css
@@ -290,7 +290,8 @@
 }
 
 th {
-    font-weight: bold
+    font-weight: bold;
+    text-align: -internal-center
 }
 
 caption {
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp
index 768add5..7c51b2ea 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp
@@ -463,9 +463,9 @@
     return cssValuePool().createColorValue(color);
 }
 
-bool CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyID propertyId, CSSValueID valueID)
+bool CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyID propertyId, CSSValueID valueID, CSSParserMode parserMode)
 {
-    if (valueID == CSSValueInvalid)
+    if (valueID == CSSValueInvalid || !isValueAllowedInMode(valueID, parserMode))
         return false;
 
     switch (propertyId) {
@@ -584,7 +584,7 @@
     case CSSPropertyTableLayout: // auto | fixed
         return valueID == CSSValueAuto || valueID == CSSValueFixed;
     case CSSPropertyTextAlign:
-        return (valueID >= CSSValueWebkitAuto && valueID <= CSSValueWebkitMatchParent) || valueID == CSSValueStart || valueID == CSSValueEnd;
+        return (valueID >= CSSValueWebkitAuto && valueID <= CSSValueInternalCenter) || valueID == CSSValueStart || valueID == CSSValueEnd;
     case CSSPropertyTextAlignLast:
         // auto | start | end | left | right | center | justify
         return (valueID >= CSSValueLeft && valueID <= CSSValueJustify) || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueAuto;
@@ -828,7 +828,7 @@
     }
 }
 
-static CSSValue* parseKeywordValue(CSSPropertyID propertyId, const String& string)
+static CSSValue* parseKeywordValue(CSSPropertyID propertyId, const String& string, CSSParserMode parserMode)
 {
     ASSERT(!string.isEmpty());
 
@@ -854,7 +854,7 @@
         return cssValuePool().createInheritedValue();
     if (valueID == CSSValueInitial)
         return cssValuePool().createExplicitInitialValue();
-    if (CSSParserFastPaths::isValidKeywordPropertyAndValue(propertyId, valueID))
+    if (CSSParserFastPaths::isValidKeywordPropertyAndValue(propertyId, valueID, parserMode))
         return cssValuePool().createIdentifierValue(valueID);
     return nullptr;
 }
@@ -1027,7 +1027,7 @@
         return length;
     if (isColorPropertyID(propertyID))
         return parseColor(string, parserMode);
-    if (CSSValue* keyword = parseKeywordValue(propertyID, string))
+    if (CSSValue* keyword = parseKeywordValue(propertyID, string, parserMode))
         return keyword;
     if (CSSValue* transform = parseSimpleTransform(propertyID, string))
         return transform;
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.h b/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.h
index 54e065f..c65013d0 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.h
@@ -25,7 +25,7 @@
 
     // Properties handled here shouldn't be explicitly handled in CSSPropertyParser
     static bool isKeywordPropertyID(CSSPropertyID);
-    static bool isValidKeywordPropertyAndValue(CSSPropertyID, CSSValueID);
+    static bool isValidKeywordPropertyAndValue(CSSPropertyID, CSSValueID, CSSParserMode);
 
     static CSSValue* parseColor(const String&, CSSParserMode);
 };
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
index 46893443..5e73636 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -3436,7 +3436,7 @@
 {
     CSSPropertyID property = resolveCSSPropertyID(unresolvedProperty);
     if (CSSParserFastPaths::isKeywordPropertyID(property)) {
-        if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(property, m_range.peek().id()))
+        if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(property, m_range.peek().id(), m_context.mode()))
             return nullptr;
         return consumeIdent(m_range);
     }
@@ -3917,7 +3917,7 @@
     case CSSPropertyFontStretch:
     case CSSPropertyFontStyle: {
         CSSValueID id = m_range.consumeIncludingWhitespace().id();
-        if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(propId, id))
+        if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(propId, id, m_context.mode()))
             return false;
         parsedValue = cssValuePool().createIdentifierValue(id);
         break;
@@ -3984,7 +3984,7 @@
     CSSPrimitiveValue* fontStretch = nullptr;
     while (!m_range.atEnd()) {
         CSSValueID id = m_range.peek().id();
-        if (!fontStyle && CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyFontStyle, id)) {
+        if (!fontStyle && CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyFontStyle, id, m_context.mode())) {
             fontStyle = consumeIdent(m_range);
             continue;
         }
@@ -4000,7 +4000,7 @@
             if (fontWeight)
                 continue;
         }
-        if (!fontStretch && CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyFontStretch, id))
+        if (!fontStretch && CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyFontStretch, id, m_context.mode()))
             fontStretch = consumeIdent(m_range);
         else
             break;
@@ -4798,7 +4798,7 @@
     switch (property) {
     case CSSPropertyWebkitMarginCollapse: {
         CSSValueID id = m_range.consumeIncludingWhitespace().id();
-        if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyWebkitMarginBeforeCollapse, id))
+        if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyWebkitMarginBeforeCollapse, id, m_context.mode()))
             return false;
         CSSValue* beforeCollapse = cssValuePool().createIdentifierValue(id);
         addProperty(CSSPropertyWebkitMarginBeforeCollapse, beforeCollapse, important);
@@ -4807,14 +4807,14 @@
             return true;
         }
         id = m_range.consumeIncludingWhitespace().id();
-        if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyWebkitMarginAfterCollapse, id))
+        if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyWebkitMarginAfterCollapse, id, m_context.mode()))
             return false;
         addProperty(CSSPropertyWebkitMarginAfterCollapse, cssValuePool().createIdentifierValue(id), important);
         return true;
     }
     case CSSPropertyOverflow: {
         CSSValueID id = m_range.consumeIncludingWhitespace().id();
-        if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyOverflowY, id))
+        if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyOverflowY, id, m_context.mode()))
             return false;
         if (!m_range.atEnd())
             return false;
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp b/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp
index a564db6..27e5b85 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp
@@ -315,10 +315,6 @@
         return;
 
     if (isHTMLTableCellElement(element)) {
-        // FIXME: We shouldn't be overriding start/-webkit-auto like this. Do it in html.css instead.
-        // Table headers with a text-align of -webkit-auto will change the text-align to center.
-        if (element.hasTagName(thTag) && style.textAlign() == TASTART)
-            style.setTextAlign(CENTER);
         if (style.whiteSpace() == KHTML_NOWRAP) {
             // Figure out if we are really nowrapping or if we should just
             // use normal instead. If the width of the cell is fixed, then
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp b/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp
index 4dbd678..583dfbe7 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp
@@ -412,8 +412,14 @@
 void StyleBuilderFunctions::applyValueCSSPropertyTextAlign(StyleResolverState& state, CSSValue* value)
 {
     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
-    if (primitiveValue->isValueID() && primitiveValue->getValueID() != CSSValueWebkitMatchParent)
-        state.style()->setTextAlign(primitiveValue->convertTo<ETextAlign>());
+    if (primitiveValue->isValueID() && primitiveValue->getValueID() != CSSValueWebkitMatchParent) {
+        // Special case for th elements - UA stylesheet text-align does not apply if parent's computed value for text-align is not its initial value
+        // https://html.spec.whatwg.org/multipage/rendering.html#tables-2
+        if (primitiveValue->getValueID() == CSSValueInternalCenter && state.parentStyle()->textAlign() != ComputedStyle::initialTextAlign())
+            state.style()->setTextAlign(state.parentStyle()->textAlign());
+        else
+            state.style()->setTextAlign(primitiveValue->convertTo<ETextAlign>());
+    }
     else if (state.parentStyle()->textAlign() == TASTART)
         state.style()->setTextAlign(state.parentStyle()->isLeftToRightDirection() ? LEFT : RIGHT);
     else if (state.parentStyle()->textAlign() == TAEND)
diff --git a/third_party/WebKit/Source/web/WebFrameContentDumper.cpp b/third_party/WebKit/Source/web/WebFrameContentDumper.cpp
index a9e39f5..6eb81c89 100644
--- a/third_party/WebKit/Source/web/WebFrameContentDumper.cpp
+++ b/third_party/WebKit/Source/web/WebFrameContentDumper.cpp
@@ -7,6 +7,7 @@
 #include "core/editing/EphemeralRange.h"
 #include "core/editing/iterators/TextIterator.h"
 #include "core/editing/serializers/Serialization.h"
+#include "core/frame/FrameView.h"
 #include "core/frame/LocalFrame.h"
 #include "core/layout/LayoutPart.h"
 #include "core/layout/LayoutTreeAsText.h"
@@ -28,6 +29,9 @@
     if (!frame->view())
         return;
 
+    DCHECK(!frame->view()->needsLayout());
+    DCHECK(!document->needsLayoutTreeUpdate());
+
     // Select the document body.
     if (document->body()) {
         const EphemeralRange range = EphemeralRange::rangeOfContents(*document->body());
@@ -88,7 +92,7 @@
 
 WebString WebFrameContentDumper::dumpWebViewAsText(WebView* webView, size_t maxChars)
 {
-    ASSERT(webView);
+    DCHECK(webView);
     webView->updateAllLifecyclePhases();
     return WebFrameContentDumper::deprecatedDumpFrameTreeAsText(webView->mainFrame()->toWebLocalFrame(), maxChars);
 }
diff --git a/ui/base/cocoa/appkit_utils.h b/ui/base/cocoa/appkit_utils.h
index 3f1b4463..bb11e07 100644
--- a/ui/base/cocoa/appkit_utils.h
+++ b/ui/base/cocoa/appkit_utils.h
@@ -42,6 +42,9 @@
 UI_BASE_EXPORT void WindowTitlebarReceivedDoubleClick(NSWindow* window,
                                                       id sender);
 
+// Whether a force-click event on the touchpad should invoke Quick Look.
+UI_BASE_EXPORT bool ForceClickInvokesQuickLook();
+
 }  // namespace ui
 
 #endif  // UI_BASE_COCOA_APPKIT_UTILS_H
diff --git a/ui/base/cocoa/appkit_utils.mm b/ui/base/cocoa/appkit_utils.mm
index ce67269..1b0a61b 100644
--- a/ui/base/cocoa/appkit_utils.mm
+++ b/ui/base/cocoa/appkit_utils.mm
@@ -9,12 +9,6 @@
 
 namespace {
 
-// Gets an NSImage given an image id.
-NSImage* GetImage(int image_id) {
-  return ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(image_id)
-      .ToNSImage();
-}
-
 // Double-click in window title bar actions.
 enum class DoubleClickAction {
   NONE,
@@ -22,6 +16,20 @@
   MAXIMIZE,
 };
 
+// Values of com.apple.trackpad.forceClick corresponding to "Look up & data
+// detectors" in System Preferences -> Trackpad -> Point & Click.
+enum class ForceTouchAction {
+  NONE = 0,        // Unchecked or set to "Tap with three fingers".
+  QUICK_LOOK = 1,  // Set to "Force Click with one finger".
+};
+
+// Gets an NSImage given an image id.
+NSImage* GetImage(int image_id) {
+  return ui::ResourceBundle::GetSharedInstance()
+      .GetNativeImageNamed(image_id)
+      .ToNSImage();
+}
+
 // The action to take when the user double-clicks in the window title bar.
 DoubleClickAction WindowTitleBarDoubleClickAction() {
   // El Capitan introduced a Dock preference to configure the window title bar
@@ -95,4 +103,10 @@
   }
 }
 
+bool ForceClickInvokesQuickLook() {
+  return [[NSUserDefaults standardUserDefaults]
+             integerForKey:@"com.apple.trackpad.forceClick"] ==
+         static_cast<NSInteger>(ForceTouchAction::QUICK_LOOK);
+}
+
 }  // namespace ui