Code: static v8::Local<v8::Value> compileAndRunPrivateScript(ScriptState* scriptState,
                                                       String scriptClassName,
                                                       const char* source,
                                                       size_t size) {
  v8::Isolate* isolate = scriptState->isolate();
  v8::TryCatch block(isolate);
  String sourceString(source, size);
  String fileName = scriptClassName + ".js";
 
   v8::Local<v8::Context> context = scriptState->context();
   v8::Local<v8::Object> global = context->Global();
  v8::Local<v8::Value> privateScriptController =
      global->Get(context, v8String(isolate, "privateScriptController"))
          .ToLocalChecked();
  RELEASE_ASSERT(privateScriptController->IsUndefined() ||
                 privateScriptController->IsObject());
  if (privateScriptController->IsObject()) {
     v8::Local<v8::Object> privateScriptControllerObject =
         privateScriptController.As<v8::Object>();
     v8::Local<v8::Value> importFunctionValue =
        privateScriptControllerObject->Get(context, v8String(isolate, "import"))
            .ToLocalChecked();
    if (importFunctionValue->IsUndefined()) {
      v8::Local<v8::Function> function;
      if (!v8::FunctionTemplate::New(isolate, importFunction)
               ->GetFunction(context)
               .ToLocal(&function) ||
          !v8CallBoolean(privateScriptControllerObject->Set(
              context, v8String(isolate, "import"), function))) {
        dumpV8Message(context, block.Message());
        LOG(FATAL)
            << "Private script error: Setting import function failed. (Class "
               "name = "
            << scriptClassName.utf8().data() << ")";
      }
    }
  }

  v8::Local<v8::Script> script;
  if (!v8Call(V8ScriptRunner::compileScript(
                  v8String(isolate, sourceString), fileName, String(),
                  TextPosition::minimumPosition(), isolate, nullptr, nullptr,
                  nullptr, NotSharableCrossOrigin),
              script, block)) {
    dumpV8Message(context, block.Message());
    LOG(FATAL) << "Private script error: Compile failed. (Class name = "
               << scriptClassName.utf8().data() << ")";
  }

  v8::Local<v8::Value> result;
  if (!v8Call(V8ScriptRunner::runCompiledInternalScript(isolate, script),
              result, block)) {
    dumpV8Message(context, block.Message());
    LOG(FATAL) << "Private script error: installClass() failed. (Class name = "
               << scriptClassName.utf8().data() << ")";
  }
  return result;
}

Vulnerability Type: XSS 
CWE ID: CWE-79
Summary: Blink in Google Chrome prior to 56.0.2924.76 for Linux, Windows and Mac, and 56.0.2924.87 for Android, allowed attacker controlled JavaScript to be run during the invocation of a private script method, which allowed a remote attacker to inject arbitrary scripts or HTML (UXSS) via a crafted HTML page.
Commit Message: Don't touch the prototype chain to get the private script controller.

Prior to this patch, private scripts attempted to get the
"privateScriptController" property off the global object without verifying if
the property actually exists on the global. If the property hasn't been set yet,
this operation could descend into the prototype chain and potentially return
a named property from the WindowProperties object, leading to release asserts
and general confusion.

BUG=668552

Review-Url: https://codereview.chromium.org/2529163002
Cr-Commit-Position: refs/heads/master@{#434627}