Permalink
Browse files

Generate and connect a Pepper identifier for Chrome OS

This change wires up GetDeviceID and passes in the BrowserContext into
PepperMessageFilter rather than the extracted ResourceContext.

The pepper drm identifier is a value provided for use by flash. It may
be reset or disabled by the user and cannot function in OffTheRecord
embodiments.

In Guest mode, the identifier is never generated.  When in incognito,
the ppapi plugin will be informed of the the profile state and not make
the call. Later, this will be enforced in the message filter as well.

Note, the preference is currently defaulted to true and does not have a
UI connection.  The UI is being wired up as part of crbug.com/125899.
At which point, we can make the setting syncable and chose the preferred
default.

This change bounces the GetDeviceID call through the renderer back to
the browser so that we have the path context to read the file from.
This same approach can be used to allow OTR checking and preference
reading if that is preferable to a file.  If we need to do anything on
the UI thread, we should do everything there (OTR+Pref).

Since the ID is regenerated at every pref init/toggle, we can move the
value around without impacting users in the future.

Please let me know if I've totally botched the wiring for this.  I'm not
sure the best way to fully test it.

TEST=built and tested on x86-alex target:
- ID is generated for normal sign-in in /home/chronos/user and is not generated for Guest.
- Very lightweight ppapi test was run too.
  (Still need pointers on better flash api wiring testing to make sure it is seeing right string)
- Pepper flash still worked normally
Also built full x86-alex system image:
- booted it
- checked the file existence in both modes
- checked pepflash and talk video for normal functionality
TRYBOT=http://build.chromium.org/p/tryserver.chromium/builders/cros_x86/builds/353
BUG=chromium-os:30378

Change-Id: Ibfbc484918d94147ad4fdc522a6415c71731068b

R=brettw,sky,piman,viettrungluu


Review URL: http://codereview.chromium.org/10342013

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@135255 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information...
drewry@google.com
drewry@google.com committed May 4, 2012
1 parent 09a48a1 commit ab6010b4ea030711c35d56aced860b8b0ad5c8b3
@@ -15,6 +15,7 @@
#include "chrome/browser/chromeos/input_method/input_method_util.h"
#include "chrome/browser/chromeos/input_method/xkeyboard.h"
#include "chrome/browser/chromeos/login/login_utils.h"
+#include "chrome/browser/chromeos/system/drm_settings.h"
#include "chrome/browser/chromeos/system/input_device_settings.h"
#include "chrome/browser/chromeos/system/screen_locker_settings.h"
#include "chrome/browser/prefs/pref_member.h"
@@ -251,6 +252,12 @@ void Preferences::RegisterUserPrefs(PrefService* prefs) {
prefs->RegisterStringPref(prefs::kOAuth1Secret,
"",
PrefService::UNSYNCABLE_PREF);
+
+ // TODO(wad): Once UI is connected, a final default can be set. At that point
+ // change this pref from UNSYNCABLE to SYNCABLE.
+ prefs->RegisterBooleanPref(prefs::kEnableCrosDRM,
+ true,
+ PrefService::UNSYNCABLE_PREF);
}
// static
@@ -334,6 +341,8 @@ void Preferences::InitUserPrefs(PrefService* prefs) {
prefs::kLanguageXkbAutoRepeatInterval, prefs, this);
enable_screen_lock_.Init(prefs::kEnableScreenLock, prefs, this);
+
+ enable_drm_.Init(prefs::kEnableCrosDRM, prefs, this);
}
void Preferences::Init(PrefService* prefs) {
@@ -562,6 +571,11 @@ void Preferences::NotifyPrefChanged(const std::string* pref_name) {
system::screen_locker_settings::EnableScreenLock(
enable_screen_lock_.GetValue());
}
+
+ // Init or update protected content (DRM) support.
+ if (!pref_name || *pref_name == prefs::kEnableCrosDRM) {
+ system::ToggleDrm(enable_drm_.GetValue());
+ }
}
void Preferences::SetLanguageConfigBoolean(const char* section,
@@ -157,6 +157,8 @@ class Preferences : public content::NotificationObserver {
BooleanPrefMember enable_screen_lock_;
+ BooleanPrefMember enable_drm_;
+
DISALLOW_COPY_AND_ASSIGN(Preferences);
};
@@ -0,0 +1,118 @@
+// 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/chromeos/system/drm_settings.h"
+
+#include "base/bind.h"
+#include "base/chromeos/chromeos_version.h"
+#include "base/command_line.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/string_number_conversions.h"
+#include "base/string_util.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros/cryptohome_library.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "content/public/browser/browser_thread.h"
+#include "crypto/encryptor.h"
+#include "crypto/sha2.h"
+
+using content::BrowserThread;
+
+namespace {
+
+// This constant is mirrored in
+// content/browser/renderer_host/pepper_message_filter.cc
+// for OnGetDeviceID.
+//
+// This ID file is solely for use via the private pepper API.
+//
+// NOTE! Changing this value will also change the generated value
+// do not do so without accounting for the change.
+const char kDRMIdentifierFile[] = "Pepper DRM ID.0";
+
+void ManageDrmIdentifierOnFileThread(bool enable, const std::string& email) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+ // Drop the file under <data>/<profile>/<drm id file>.
+ // TODO(wad) get the profile directory in a more succinct fashion.
+ FilePath drm_id_file;
+ PathService::Get(chrome::DIR_USER_DATA, &drm_id_file);
+ const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
+ FilePath profile = cmd_line.GetSwitchValuePath(switches::kLoginProfile);
+ if (profile.empty()) {
+ LOG(ERROR) << "called with no login-profile!";
+ return;
+ }
+ drm_id_file = drm_id_file.AppendASCII(profile.value());
+ drm_id_file = drm_id_file.AppendASCII(kDRMIdentifierFile);
+
+ // The file will be regenerated or deleted at toggle-time.
+ file_util::Delete(drm_id_file, false);
+
+ // If DRM support is disabled, then do nothing else.
+ if (!enable)
+ return;
+
+ // Build the identifier as follows:
+ // SHA256(system-salt||service||SHA256(system-salt||service||email))
+ chromeos::CryptohomeLibrary* c_home =
+ chromeos::CrosLibrary::Get()->GetCryptohomeLibrary();
+ std::string salt = c_home->GetSystemSalt();
+ char id_buf[256 / 8]; // 256-bits for SHA256
+ std::string input = salt;
+ input.append(kDRMIdentifierFile);
+ input.append(email);
+ crypto::SHA256HashString(input, &id_buf, sizeof(id_buf));
+ std::string id = StringToLowerASCII(base::HexEncode(
+ reinterpret_cast<const void*>(id_buf),
+ sizeof(id_buf)));
+ input = salt;
+ input.append(kDRMIdentifierFile);
+ input.append(id);
+ crypto::SHA256HashString(input, &id_buf, sizeof(id_buf));
+ id = StringToLowerASCII(base::HexEncode(
+ reinterpret_cast<const void*>(id_buf),
+ sizeof(id_buf)));
+
+ if (file_util::WriteFile(drm_id_file, id.c_str(), id.length()) !=
+ static_cast<int>(id.length())) {
+ LOG(ERROR) << "Failed to write " << drm_id_file.value();
+ return;
+ }
+}
+
+} // namespace
+
+namespace chromeos {
+namespace system {
+
+void ToggleDrm(bool enable) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // Never generate the file in Guest mode.
+ if (UserManager::Get()->IsLoggedInAsGuest() ||
+ UserManager::Get()->IsLoggedInAsDemoUser())
+ return;
+
+ // The user email address is included in the hash to keep the identifier
+ // from being the same across users.
+ std::string email = UserManager::Get()->GetLoggedInUser().email();
+ DCHECK(email.length() == 0);
+
+ // Generate a DRM identifier on the FILE thread.
+ // The DRM identifier is a per-user, per-OS-install identifier that is used
+ // by privileged pepper plugins specifically for deriving
+ // per-content-provider identifiers. The user must be able to clear it,
+ // reset it, and deny its use.
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&ManageDrmIdentifierOnFileThread, enable, email));
+}
+
+} // namespace system
+} // namespace chromeos
@@ -0,0 +1,18 @@
+// 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_CHROMEOS_SYSTEM_DRM_SETTINGS_H_
+#define CHROME_BROWSER_CHROMEOS_SYSTEM_DRM_SETTINGS_H_
+#pragma once
+
+namespace chromeos {
+namespace system {
+
+// Enables/disables platform-specific DRM support.
+void ToggleDrm(bool enable);
+
+} // namespace system
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_SYSTEM_DRM_SETTINGS_H_
@@ -821,6 +821,8 @@
'browser/chromeos/stub_cros_settings_provider.h',
'browser/chromeos/system/ash_system_tray_delegate.cc',
'browser/chromeos/system/ash_system_tray_delegate.h',
+ 'browser/chromeos/system/drm_settings.cc',
+ 'browser/chromeos/system/drm_settings.h',
'browser/chromeos/system/input_device_settings.cc',
'browser/chromeos/system/input_device_settings.h',
'browser/chromeos/system/name_value_pairs_parser.cc',
@@ -672,6 +672,9 @@ const char kOAuth1Token[] = "settings.account.oauth1_token";
// A string prefs for OAuth1 secret.
const char kOAuth1Secret[] = "settings.account.oauth1_secret";
+
+// A boolean pref that enables the (private) pepper GetID() call.
+const char kEnableCrosDRM[] = "settings.privacy.drm_enabled";
#endif // defined(OS_CHROMEOS)
// The disabled messages in IPC logging.
@@ -244,6 +244,7 @@ extern const char kShow3gPromoNotification[];
extern const char kUseSharedProxies[];
extern const char kOAuth1Token[];
extern const char kOAuth1Secret[];
+extern const char kEnableCrosDRM[];
#endif // defined(OS_CHROMEOS)
extern const char kIpcDisabledMessages[];
extern const char kShowHomeButton[];
@@ -866,11 +866,13 @@ TEST_PPAPI_IN_PROCESS(Flash_GetProxyForURL)
TEST_PPAPI_IN_PROCESS(Flash_MessageLoop)
TEST_PPAPI_IN_PROCESS(Flash_GetLocalTimeZoneOffset)
TEST_PPAPI_IN_PROCESS(Flash_GetCommandLineArgs)
+TEST_PPAPI_IN_PROCESS(Flash_GetDeviceID)
TEST_PPAPI_OUT_OF_PROCESS(Flash_SetInstanceAlwaysOnTop)
TEST_PPAPI_OUT_OF_PROCESS(Flash_GetProxyForURL)
TEST_PPAPI_OUT_OF_PROCESS(Flash_MessageLoop)
TEST_PPAPI_OUT_OF_PROCESS(Flash_GetLocalTimeZoneOffset)
TEST_PPAPI_OUT_OF_PROCESS(Flash_GetCommandLineArgs)
+TEST_PPAPI_OUT_OF_PROCESS(Flash_GetDeviceID)
TEST_PPAPI_IN_PROCESS(WebSocket_IsWebSocket)
TEST_PPAPI_IN_PROCESS(WebSocket_UninitializedPropertiesAccess)
@@ -8,6 +8,8 @@
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
@@ -23,6 +25,7 @@
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/common/pepper_messages.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/font_list_async.h"
@@ -55,18 +58,28 @@ namespace {
const size_t kMaxSocketsAllowed = 1024;
const uint32 kInvalidSocketID = 0;
+// The ID is a 256-bit hash digest hex-encoded.
+const int kDRMIdentifierSize = (256 / 8) * 2;
+// The path to the file containing the DRM ID.
+// It is mirrored from
+// chrome/browser/chromeos/system/drm_settings.cc
+const char kDRMIdentifierFile[] = "Pepper DRM ID.0";
+
} // namespace
PepperMessageFilter::PepperMessageFilter(
ProcessType type,
int process_id,
- content::ResourceContext* resource_context)
+ content::BrowserContext* browser_context)
: process_type_(type),
process_id_(process_id),
- resource_context_(resource_context),
+ resource_context_(browser_context ?
+ browser_context->GetResourceContext() : NULL),
host_resolver_(NULL),
next_socket_id_(1) {
DCHECK(type == RENDERER);
+ DCHECK(browser_context);
+ browser_path_ = browser_context->GetPath();
DCHECK(resource_context_);
}
@@ -90,7 +103,7 @@ void PepperMessageFilter::OverrideThreadForMessage(
message.type() == PpapiHostMsg_PPBTCPServerSocket_Listen::ID ||
message.type() == PpapiHostMsg_PPBHostResolver_Resolve::ID) {
*thread = BrowserThread::UI;
- } else if (message.type() == PpapiHostMsg_PPBFlash_GetDeviceID::ID) {
+ } else if (message.type() == PepperMsg_GetDeviceID::ID) {
*thread = BrowserThread::FILE;
}
}
@@ -145,7 +158,7 @@ bool PepperMessageFilter::OnMessageReceived(const IPC::Message& msg,
// Flash messages.
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_UpdateActivity, OnUpdateActivity)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_GetDeviceID, OnGetDeviceID)
+ IPC_MESSAGE_HANDLER(PepperMsg_GetDeviceID, OnGetDeviceID)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP_EX()
@@ -633,8 +646,33 @@ void PepperMessageFilter::OnUpdateActivity() {
}
void PepperMessageFilter::OnGetDeviceID(std::string* id) {
- // TODO(brettw) implement this.
- *id = "<undefined>";
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ id->clear();
+
+ // Grab the contents of the DRM identifier file.
+ FilePath drm_id_file = browser_path_;
+ drm_id_file = drm_id_file.AppendASCII(kDRMIdentifierFile);
+
+ // This method should not be called with high frequency and its
+ // useful to be able to validate use with a VLOG.
+ VLOG(1) << "DRM ID requested @ " << drm_id_file.value();
+
+ if (browser_path_.empty()) {
+ LOG(ERROR) << "GetDeviceID requested from outside the RENDERER context.";
+ return;
+ }
+
+ // TODO(wad,brettw) Add OffTheRecord() enforcement here.
+ // Normally this is left for the plugin to do, but in the
+ // future we should check here as an added safeguard.
+
+ char id_buf[kDRMIdentifierSize];
+ if (file_util::ReadFile(drm_id_file, id_buf, kDRMIdentifierSize) !=
+ kDRMIdentifierSize) {
+ VLOG(1) << "file not readable: " << drm_id_file.value();
+ return;
+ }
+ id->assign(id_buf, kDRMIdentifierSize);
}
void PepperMessageFilter::GetFontFamiliesComplete(
@@ -11,6 +11,7 @@
#include <vector>
#include "base/basictypes.h"
+#include "base/file_path.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_ptr.h"
#include "base/process.h"
@@ -34,6 +35,7 @@ class ListValue;
}
namespace content {
+class BrowserContext;
class ResourceContext;
}
@@ -63,7 +65,7 @@ class PepperMessageFilter
// provided for sanity checking).
PepperMessageFilter(ProcessType type,
int process_id,
- content::ResourceContext* resource_context);
+ content::BrowserContext* browser_context);
// Constructor when used in the context of a PPAPI process (the argument is
// provided for sanity checking).
@@ -252,6 +254,8 @@ class PepperMessageFilter
NetworkMonitorIdSet network_monitor_ids_;
+ FilePath browser_path_;
+
DISALLOW_COPY_AND_ASSIGN(PepperMessageFilter);
};
@@ -497,7 +497,7 @@ void RenderProcessHostImpl::CreateMessageFilters() {
#endif
channel_->AddFilter(new PepperFileMessageFilter(GetID(), browser_context));
channel_->AddFilter(new PepperMessageFilter(PepperMessageFilter::RENDERER,
- GetID(), resource_context));
+ GetID(), browser_context));
#if defined(ENABLE_INPUT_SPEECH)
channel_->AddFilter(new speech::InputTagSpeechDispatcherHost(
GetID(), browser_context->GetRequestContext(),
@@ -17,3 +17,6 @@
IPC_SYNC_MESSAGE_CONTROL1_1(PepperMsg_GetLocalTimeZoneOffset,
base::Time /* t */,
double /* result */)
+
+IPC_SYNC_MESSAGE_CONTROL0_1(PepperMsg_GetDeviceID,
+ std::string /* id */)
@@ -1280,6 +1280,12 @@ double PepperPluginDelegateImpl::GetLocalTimeZoneOffset(base::Time t) {
return result;
}
+std::string PepperPluginDelegateImpl::GetDeviceID() {
+ std::string result;
+ render_view_->Send(new PepperMsg_GetDeviceID(&result));
+ return result;
+}
+
base::SharedMemory* PepperPluginDelegateImpl::CreateAnonymousSharedMemory(
uint32_t size) {
if (size == 0)
Oops, something went wrong.

0 comments on commit ab6010b

Please sign in to comment.