diff --git a/apps/files/appinfo/app.php b/apps/files/appinfo/app.php
index 3567bc26def8a89f8eaae4dd1ee51cc83caf7156..62c205add529a7e896d1907cbaf38e4494bbbfd1 100644
--- a/apps/files/appinfo/app.php
+++ b/apps/files/appinfo/app.php
@@ -10,7 +10,7 @@ OCP\App::addNavigationEntry(array("id" => "files_index",
 	"icon" => OCP\Util::imagePath("core", "places/files.svg"),
 	"name" => $l->t("Files")));
 
-\OC::$server->getSearch()->registerProvider('OC\Search\Provider\File');
+\OC::$server->getSearch()->registerProvider('OC\Search\Provider\File', array('apps' => array('files')));
 
 $templateManager = OC_Helper::getFileTemplateManager();
 $templateManager->registerTemplate('text/html', 'core/templates/filetemplates/template.html');
diff --git a/core/js/js.js b/core/js/js.js
index eb2f10b51f06897e2c247556177921be83f873bf..e62a54744264f363249e3591ad8fe1e56a0da9cc 100644
--- a/core/js/js.js
+++ b/core/js/js.js
@@ -292,7 +292,14 @@ var OC={
 	search: _.debounce(function(query){
 		if(query){
 			OC.addStyle('search','results');
-			$.getJSON(OC.filePath('search','ajax','search.php')+'?query='+encodeURIComponent(query), function(results){
+			var classList = document.getElementById('content').className.split(/\s+/);
+			var inApps = [];
+			for (var i = 0; i < classList.length; i++) {
+				if (classList[i].indexOf('app-') === 0) {
+					var inApps = [classList[i].substr(4)];
+				}
+			}
+			$.getJSON(OC.generateUrl('search/ajax/search.php'), {inApps:inApps, query:query}, function(results){
 				OC.search.lastResults=results;
 				OC.search.showResults(results);
 			});
diff --git a/lib/private/search.php b/lib/private/search.php
index bcaebdddd9ccc65de76df5c0d0a3a0976bb796fd..8f04aa8360b2b0a1e47e150e6e42890d1d99a26c 100644
--- a/lib/private/search.php
+++ b/lib/private/search.php
@@ -35,14 +35,17 @@ class Search implements ISearch {
 	/**
 	 * Search all providers for $query
 	 * @param string $query
+	 * @param string[] $inApps optionally limit results to the given apps
 	 * @return array An array of OC\Search\Result's
 	 */
-	public function search($query) {
+	public function search($query, array $inApps = array()) {
 		$this->initProviders();
 		$results = array();
 		foreach($this->providers as $provider) {
 			/** @var $provider Provider */
-			$results = array_merge($results, $provider->search($query));
+			if ($provider->providesResultsFor($inApps)) {
+				$results = array_merge($results, $provider->search($query));
+			}
 		}
 		return $results;
 	}
@@ -51,8 +54,8 @@ class Search implements ISearch {
 	 * Remove all registered search providers
 	 */
 	public function clearProviders() {
-		$this->providers=array();
-		$this->registeredProviders=array();
+		$this->providers = array();
+		$this->registeredProviders = array();
 	}
 
 	/**
@@ -67,7 +70,7 @@ class Search implements ISearch {
 			}
 		);
 		// force regeneration of providers on next search
-		$this->providers=array();
+		$this->providers = array();
 	}
 
 	/**
@@ -75,21 +78,21 @@ class Search implements ISearch {
 	 * @param string $class class name of a OC\Search\Provider
 	 * @param array $options optional
 	 */
-	public function registerProvider($class, $options=array()) {
-		$this->registeredProviders[]=array('class'=>$class, 'options'=>$options);
+	public function registerProvider($class, array $options = array()) {
+		$this->registeredProviders[] = array('class' => $class, 'options' => $options);
 	}
 
 	/**
 	 * Create instances of all the registered search providers
 	 */
 	private function initProviders() {
-		if(count($this->providers)>0) {
+		if( ! empty($this->providers) ) {
 			return;
 		}
 		foreach($this->registeredProviders as $provider) {
 			$class = $provider['class'];
 			$options = $provider['options'];
-			$this->providers[]=new $class($options);
+			$this->providers[] = new $class($options);
 		}
 	}
 
diff --git a/lib/public/isearch.php b/lib/public/isearch.php
index 3b83dbf35e8ecf8c0fc8b4cabf9254acb6b8c52a..229376ed3aeab031cdd30d56b0cf7350fe355552 100644
--- a/lib/public/isearch.php
+++ b/lib/public/isearch.php
@@ -32,16 +32,17 @@ interface ISearch {
 	/**
 	 * Search all providers for $query
 	 * @param string $query
+	 * @param string[] $inApps optionally limit results to the given apps
 	 * @return array An array of OCP\Search\Result's
 	 */
-	public function search($query);
+	public function search($query, array $inApps = array());
 
 	/**
 	 * Register a new search provider to search with
 	 * @param string $class class name of a OCP\Search\Provider
 	 * @param array $options optional
 	 */
-	public function registerProvider($class, $options = array());
+	public function registerProvider($class, array $options = array());
 
 	/**
 	 * Remove one existing search provider
diff --git a/lib/public/search/provider.php b/lib/public/search/provider.php
index 0506f091dd987f2c0bf5b9f071e68d73fb67d066..d6cd1fb025eef96ac43b5716a1573fb8903545db 100644
--- a/lib/public/search/provider.php
+++ b/lib/public/search/provider.php
@@ -24,6 +24,8 @@ namespace OCP\Search;
  */
 abstract class Provider {
 
+	const OPTION_APPS = 'apps';
+
 	/**
 	 * List of options (currently unused)
 	 * @var array
@@ -32,12 +34,38 @@ abstract class Provider {
 
 	/**
 	 * Constructor
-	 * @param array $options
+	 * @param array $options as key => value
 	 */
-	public function __construct($options) {
+	public function __construct($options = array()) {
 		$this->options = $options;
 	}
 
+	/**
+	 * get a value from the options array or null
+	 * @param string $key
+	 * @return mixed
+	 */
+	public function getOption($key) {
+		if (is_array($this->options) && isset($this->options[$key])) {
+			return $this->options[$key];
+		} else {
+			return null;
+		}
+	}
+
+	/**
+	 * checks if the given apps and the apps this provider has results for intersect
+	 * returns true if the given array is empty (all apps)
+	 * or if this provider does not have a list of apps it provides results for (legacy search providers)
+	 * or if the two above arrays have elements in common (intersect)
+	 * @param string[] $apps
+	 * @return bool
+	 */
+	public function providesResultsFor(array $apps = array()) {
+		$forApps = $this->getOption(self::OPTION_APPS);
+		return empty($apps) || empty($forApps) || array_intersect($forApps, $apps);
+	}
+
 	/**
 	 * Search for $query
 	 * @param string $query
diff --git a/search/ajax/search.php b/search/ajax/search.php
index 84a5a760cadb84cbdd93c49327ddf16283663843..21e127e72b1589a3c43ab7c98573b04ce5682c32 100644
--- a/search/ajax/search.php
+++ b/search/ajax/search.php
@@ -22,12 +22,24 @@
 */
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
+\OC_JSON::checkLoggedIn();
 \OC::$server->getSession()->close();
 
-$query=(isset($_GET['query']))?$_GET['query']:'';
+if (isset($_GET['query'])) {
+	$query = $_GET['query'];
+} else {
+	$query = '';
+}
+if (isset($_GET['inApps'])) {
+	$inApps = $_GET['inApps'];
+	if (is_string($inApps)) {
+		$inApps = array($inApps);
+	}
+} else {
+	$inApps = array();
+}
 if($query) {
-	$result = \OC::$server->getSearch()->search($query);
+	$result = \OC::$server->getSearch()->search($query, $inApps);
 	OC_JSON::encodedPrint($result);
 }
 else {