Create a Manifest to get attributes instead of peeking in the Dictionary a manifest is based on.

BUG=181074,180296

Review URL: https://chromiumcodereview.appspot.com/12391050

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@187220 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
index e551a548..2de49711 100644
--- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
+++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
@@ -417,8 +417,7 @@
   Release();
 }
 
-CompleteInstallFunction::CompleteInstallFunction()
-    : is_app_(false) {}
+CompleteInstallFunction::CompleteInstallFunction() {}
 
 CompleteInstallFunction::~CompleteInstallFunction() {}
 
@@ -436,8 +435,6 @@
         kNoPreviousBeginInstallWithManifestError, id);
     return false;
   }
-  is_app_ = approval_->parsed_manifest->Get(
-      extension_manifest_keys::kPlatformAppBackground, NULL);
 
   // Balanced in OnExtensionInstallSuccess() or OnExtensionInstallFailure().
   AddRef();
@@ -477,17 +474,18 @@
     bool app_launcher_enabled) {
   if (app_launcher_enabled) {
     std::string name;
-    if (!approval_->parsed_manifest->GetString(extension_manifest_keys::kName,
+    if (!approval_->manifest->value()->GetString(extension_manifest_keys::kName,
                                                &name)) {
       NOTREACHED();
     }
     // Show the app list so it receives install progress notifications.
-    AppListService::Get()->ShowAppList(profile());
-    // Tell the app list about the install that we just started.
+    if (approval_->manifest->is_app())
+      AppListService::Get()->ShowAppList(profile());
+
     extensions::InstallTracker* tracker =
         extensions::InstallTrackerFactory::GetForProfile(profile());
     tracker->OnBeginExtensionInstall(
-        id, name, approval_->installing_icon, is_app_);
+        id, name, approval_->installing_icon, approval_->manifest->is_app());
   }
 
   // The extension will install through the normal extension install flow, but
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.h b/chrome/browser/extensions/api/webstore_private/webstore_private_api.h
index 30cea9ff2..0d3e047 100644
--- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.h
+++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.h
@@ -180,9 +180,6 @@
   void OnGetAppLauncherEnabled(std::string id, bool app_launcher_enabled);
 
   scoped_ptr<WebstoreInstaller::Approval> approval_;
-
-  // True if this install is for an app.
-  bool is_app_;
 };
 
 class GetBrowserLoginFunction : public SyncExtensionFunction {
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc
index 77fbf41..53fda13 100644
--- a/chrome/browser/extensions/crx_installer.cc
+++ b/chrome/browser/extensions/crx_installer.cc
@@ -124,7 +124,7 @@
     // Mark the extension as approved, but save the expected manifest and ID
     // so we can check that they match the CRX's.
     approved_ = true;
-    expected_manifest_.reset(approval->parsed_manifest->DeepCopy());
+    expected_manifest_.reset(approval->manifest->DeepCopy());
     expected_id_ = approval->extension_id;
   }
 
@@ -371,7 +371,9 @@
   temp_dir_ = temp_dir;
 
   if (original_manifest)
-    original_manifest_.reset(original_manifest->DeepCopy());
+    original_manifest_.reset(new Manifest(
+        Manifest::INVALID_LOCATION,
+        scoped_ptr<DictionaryValue>(original_manifest->DeepCopy())));
 
   // We don't have to delete the unpack dir explicity since it is a child of
   // the temp dir.
diff --git a/chrome/browser/extensions/crx_installer.h b/chrome/browser/extensions/crx_installer.h
index b3d20b1..cbf061cba 100644
--- a/chrome/browser/extensions/crx_installer.h
+++ b/chrome/browser/extensions/crx_installer.h
@@ -281,7 +281,7 @@
   // A parsed copy of the expected manifest, before any transformations like
   // localization have taken place. If |approved_| is true, then the
   // extension's manifest must match this for the install to proceed.
-  scoped_ptr<base::DictionaryValue> expected_manifest_;
+  scoped_ptr<Manifest> expected_manifest_;
 
   // If non-NULL, contains the expected version of the extension we're
   // installing.  Important for external sources, where claiming the wrong
@@ -315,7 +315,7 @@
 
   // A parsed copy of the unmodified original manifest, before any
   // transformations like localization have taken place.
-  scoped_ptr<base::DictionaryValue> original_manifest_;
+  scoped_ptr<Manifest> original_manifest_;
 
   // If non-empty, contains the current version of the extension we're
   // installing (for upgrades).
diff --git a/chrome/browser/extensions/webstore_installer.cc b/chrome/browser/extensions/webstore_installer.cc
index 5ffda43..2b5bde6 100644
--- a/chrome/browser/extensions/webstore_installer.cc
+++ b/chrome/browser/extensions/webstore_installer.cc
@@ -169,7 +169,9 @@
   scoped_ptr<Approval> result(new Approval());
   result->extension_id = extension_id;
   result->profile = profile;
-  result->parsed_manifest = parsed_manifest.Pass();
+  result->manifest = scoped_ptr<Manifest>(
+      new Manifest(Manifest::INVALID_LOCATION,
+                   scoped_ptr<DictionaryValue>(parsed_manifest->DeepCopy())));
   result->skip_install_dialog = true;
   return result.Pass();
 }
diff --git a/chrome/browser/extensions/webstore_installer.h b/chrome/browser/extensions/webstore_installer.h
index f52c911..82c9ab56 100644
--- a/chrome/browser/extensions/webstore_installer.h
+++ b/chrome/browser/extensions/webstore_installer.h
@@ -34,6 +34,8 @@
 
 namespace extensions {
 
+class Manifest;
+
 // Downloads and installs extensions from the web store.
 class WebstoreInstaller :public content::NotificationObserver,
                          public content::DownloadItem::Observer,
@@ -88,7 +90,7 @@
     Profile* profile;
 
     // The expected manifest, before localization.
-    scoped_ptr<base::DictionaryValue> parsed_manifest;
+    scoped_ptr<Manifest> manifest;
 
     // Whether to use a bubble notification when an app is installed, instead of
     // the default behavior of transitioning to the new tab page.
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc
index 1d8a2a3a..32c4efb89 100644
--- a/chrome/common/extensions/extension.cc
+++ b/chrome/common/extensions/extension.cc
@@ -1067,6 +1067,10 @@
                            new_warnings.begin(), new_warnings.end());
 }
 
+bool Extension::is_app() const {
+  return manifest_->is_app();
+}
+
 bool Extension::is_platform_app() const {
   return manifest_->is_platform_app();
 }
diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h
index 3ecb571..5e1b917 100644
--- a/chrome/common/extensions/extension.h
+++ b/chrome/common/extensions/extension.h
@@ -494,9 +494,7 @@
   }
 
   // App-related.
-  bool is_app() const {
-    return is_legacy_packaged_app() || is_hosted_app() || is_platform_app();
-  }
+  bool is_app() const;
   bool is_platform_app() const;
   bool is_hosted_app() const;
   bool is_legacy_packaged_app() const;
diff --git a/chrome/common/extensions/manifest.h b/chrome/common/extensions/manifest.h
index 043ad48d8..c188793 100644
--- a/chrome/common/extensions/manifest.h
+++ b/chrome/common/extensions/manifest.h
@@ -113,6 +113,9 @@
   Type type() const { return type_; }
 
   bool is_theme() const { return type_ == TYPE_THEME; }
+  bool is_app() const {
+    return is_legacy_packaged_app() || is_hosted_app() || is_platform_app();
+  }
   bool is_platform_app() const { return type_ == TYPE_PLATFORM_APP; }
   bool is_hosted_app() const { return type_ == TYPE_HOSTED_APP; }
   bool is_legacy_packaged_app() const {