【Android安全-指纹浏览器的编译与开发】此文章归类为:Android安全。
最近一年一直忙于开发严重怀疑自己转行了,学习研究的,很浅薄只为完成某些功能罢了,大佬勿喷。
开发的指纹浏览器是基于chromium
首先准备基本环境
操作系统:ubuntu22.04.4
家里网络太差,我是在公司下载的。
git clone 17aK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6U0K9s2u0G2L8h3W2#2L8g2)9J5k6h3N6G2L8$3N6D9k6i4y4G2N6i4u0U0k6g2)9J5k6h3y4G2L8g2)9J5c8X3y4Z5M7X3!0E0K9i4g2E0i4K6u0r3N6r3!0G2L8s2y4Q4x3V1k6V1k6i4m8G2N6q4)9#2k6Y4c8G2L8$3I4K6i4K6u0W2k6$3W2@1
获取工具depot_tools用来下载chrom源码,并将工具目录放到环境中
获取编译所需的所有代码
fetch --nohooks android
拉取最新的代码,二选一
fetch --no-history --nohooks android
拉取特定版本的代码
gclient sync --with_branch_heads -r 120.0.6099.243
build/install-build-deps.sh --android
gclient runhooks
python推荐使用内置的
export PATH=~/chromium/Chromium_120.0.6099.243/depot_tools/.cipd_bin/3.8/bin:$PATH
可以查看gn的所有选项
gn args --list out/Default
release版本
gn gen out/Release --args='target_os="android" target_cpu="arm64" is_debug=false is_official_build=true enable_nacl=false is_chrome_branded=false use_official_google_api_keys=false ffmpeg_branding="Chrome" proprietary_codecs=true enable_remoting=true treat_warnings_as_errors=false system_webview_package_name = "com.google.android.webview"'
debug版本
gn gen out/Debug --args='target_os="android" target_cpu="arm64" is_debug=true is_official_build=false enable_nacl=false is_chrome_branded=false use_official_google_api_keys=false ffmpeg_branding="Chrome" proprietary_codecs=true enable_remoting=true treat_warnings_as_errors=false'
autoninja -C out/Release system_webview_apk -j8
构建android的webview
autoninja -C out/Release monochrome_public_apk -j8
构建单独的浏览器
以上就是下载源码编译的全过程,下面开始更改调整位置。不同版本位置会有略微差异
代码的基质位置位于/chromium_120.0.6099.243/code/src(函数参数就不写了)
android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java(对于打webview.apk是有效的)
loadUrl()
public void loadUrl(final String url) { String UA = null; String FileStr = "/data/misc/web/config.txt"; LocalDateTime lastModifiedTime = null; //以下代码获取文件最后修改日期 try{ Path filePath = Paths.get(FileStr); BasicFileAttributes attributes = Files.readAttributes(filePath, BasicFileAttributes.class); lastModifiedTime = LocalDateTime.ofInstant(attributes.lastModifiedTime().toInstant(), ZoneId.systemDefault()); } catch (IOException e) { e.printStackTrace(); } //存在配置文件 if(lastModifiedTime != null){ if((fileTime_last == null) || (!lastModifiedTime.isEqual(fileTime_last))){ fileTime_last = lastModifiedTime; Webview_Fingerprint = open_webview_Fingerprint_file(FileStr); } UA = (String)Webview_Fingerprint.get("ua"); mWebSettings.setUserAgentString(UA); } mFactory.startYourEngines(true); if (checkNeedsPost()) { // Disallowed in WebView API for apps targeting a new SDK assert mAppTargetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2; mFactory.addTask(new Runnable() { @Override public void run() { try (TraceEvent event = TraceEvent.scoped("WebView.APICall.Framework.LOAD_URL")) { recordWebViewApiCall(ApiCall.LOAD_URL); mAwContents.loadUrl(url); } } }); return; } try (TraceEvent event = TraceEvent.scoped("WebView.APICall.Framework.LOAD_URL")) { recordWebViewApiCall(ApiCall.LOAD_URL); mAwContents.loadUrl(url); } }
通过修改mWebSettings.setUserAgenString()
third_party/blink/common/device_memory/approximated_device_memory.cc
GetculateAndSetApproximatedDeviceMemory()
void ApproximatedDeviceMemory::CalculateAndSetApproximatedDeviceMemory() { // The calculations in this method are described in the specification: // c6aK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4x3$3y4Q4x3X3g2Y4K9i4c8Z5N6h3u0Q4x3X3g2A6L8#2)9J5c8X3c8W2N6X3W2U0k6g2)9J5k6r3#2W2L8h3!0J5P5g2)9J5c8W2)9J5k6b7`.`. DCHECK_GT(physical_memory_mb_, 0); int lower_bound = physical_memory_mb_; int power = 0; // Extract the most-significant-bit and its location. while (lower_bound > 1) { lower_bound >>= 1; power++; } // The remaining should always be equal to exactly 1. DCHECK_EQ(lower_bound, 1); int64_t upper_bound = lower_bound + 1; lower_bound = lower_bound << power; upper_bound = upper_bound << power; // Find the closest bound, and convert it to GB. if (physical_memory_mb_ - lower_bound <= upper_bound - physical_memory_mb_) approximated_device_memory_gb_ = static_cast<float>(lower_bound) / 1024.0; else approximated_device_memory_gb_ = static_cast<float>(upper_bound) / 1024.0; // Max-limit the reported value to 8GB to reduce fingerprintability of // high-spec machines. if (approximated_device_memory_gb_ > 8) approximated_device_memory_gb_ = 8.0; if(last_write_time != 0){ approximated_device_memory_gb_ = me_memory; } __android_log_print(ANDROID_LOG_DEBUG,"" ,"chromium Lmemory_gbanguage %f",approximated_device_memory_gb_); }
通过修改字段approximated_device_memory_gb_
third_party/blink/renderer/core/frame/screen.cc
height()
int Screen::height() const { if(last_write_time != 0){ __android_log_print(ANDROID_LOG_DEBUG,"" ,"chromium height:%d",me_height); return me_height/devicePixel; } if (!DomWindow()) return 0; return GetRect(/*available=*/false).height(); }
width()
int Screen::width() const { if(last_write_time != 0){ __android_log_print(ANDROID_LOG_DEBUG,"" ,"chromium width:%d",me_width); return me_width/devicePixel; } if (!DomWindow()) return 0; return GetRect(/*available=*/false).width(); }
若要获取pixel来计算分辨率的话,则在Screen()初始化函数中使用GetScreenInfo().device_scale_factor获取
float devicePixel = 0.0f; Screen::Screen(LocalDOMWindow* window, int64_t display_id) : ExecutionContextClient(window), display_id_(display_id) { devicePixel = GetScreenInfo().device_scale_factor; }
colorDepth()
unsigned Screen::colorDepth() const { //修改分辨率的颜色深度 if(last_write_time != 0){ __android_log_print(ANDROID_LOG_DEBUG,"" ,"chromium colorDepth:%d",me_color_depth); return me_color_depth; } if (!DomWindow()) return 0; return base::saturated_cast<unsigned>(GetScreenInfo().depth); }
availHeight()
int Screen::availWidth() const { if(last_write_time != 0){ __android_log_print(ANDROID_LOG_DEBUG,"" ,"chromium availWidth:%d",me_availWidth); return me_availWidth/devicePixel; }
avaiWidth()
int Screen::availWidth() const { if(last_write_time != 0){ __android_log_print(ANDROID_LOG_DEBUG,"" ,"chromium availWidth:%d",me_availWidth); return me_availWidth/devicePixel; } if (!DomWindow()) return 0; return GetRect(/*available=*/true).width(); }
third_party/blink/renderer/core/frame/navigator_ua_data.cc
AddBrandVersion()
void NavigatorUAData::AddBrandVersion(const String& brand, const String& version) { NavigatorUABrandVersion* dict = NavigatorUABrandVersion::Create(); dict->setBrand(brand); //dict->setVersion(version); //修改chromium版本 if(last_write_time != 0){ const char * str = brand.Utf8().c_str(); if((strstr(str,"Chromium")!=NULL) || (strstr(str,"WebView")!=NULL)){ char Version_bug[0x10] = {0}; int aaa = 0; char* str_start = NULL; while(true){ if(me_chromium_version[aaa] == '.'){ break; } aaa++; } memcpy(Version_bug, me_chromium_version, aaa); String me_version_Str = Version_bug; dict->setVersion(me_version_Str); }else{ dict->setVersion(version); } }else{ dict->setVersion(version); } brand_set_.push_back(dict); }
AddBrandFullVersion()
void NavigatorUAData::AddBrandFullVersion(const String& brand, const String& version) { NavigatorUABrandVersion* dict = NavigatorUABrandVersion::Create(); dict->setBrand(brand); //dict->setVersion(version); if(last_write_time != 0){ const char* str = brand.Utf8().c_str(); if((strstr(str,"Chromium")!=NULL) || (strstr(str,"WebView")!=NULL)){ String me_version_Str = me_chromium_version; dict->setVersion(me_version_Str); }else{ dict->setVersion(version); } }else{ dict->setVersion(version); } full_version_list_.push_back(dict); }
SetBrandVersionList()
void NavigatorUAData::SetBrandVersionList( const UserAgentBrandList& brand_version_list) { for (const auto& brand_version : brand_version_list) { AddBrandVersion(String::FromUTF8(brand_version.brand), String::FromUTF8(brand_version.version)); } }
SetBrandFullVersionList()
void NavigatorUAData::SetFullVersionList( const UserAgentBrandList& full_version_list) { // for (const auto& brand_version : full_version_list) { // AddBrandFullVersion(String::FromUTF8(brand_version.brand), // String::FromUTF8(brand_version.version)); // } //chromium版本 AddBrandFullVersion("Not_A Brand","8"); AddBrandFullVersion("Chromium","120"); AddBrandFullVersion("Android WebView","120"); }
SetUAFullVersion()
void NavigatorUAData::SetUAFullVersion(const String& ua_full_version) { //在设置chromium版本的地方替换调 if(last_write_time != 0){ String me_version = me_chromium_version; __android_log_print(ANDROID_LOG_DEBUG,"" ,"chromium SetUAFullVersion:%s old:%s",me_version.Utf8().c_str(),ua_full_version_.Utf8().c_str()); ua_full_version_ = me_version; return; } ua_full_version_ = ua_full_version; }
getHighEntropyValues()
ScriptPromise NavigatorUAData::getHighEntropyValues( ScriptState* script_state, Vector<String>& hints) const { auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); ScriptPromise promise = resolver->Promise(); auto* execution_context = ExecutionContext::From(script_state); // GetExecutionContext(); DCHECK(execution_context); bool record_identifiability = IdentifiabilityStudySettings::Get()->ShouldSampleType( IdentifiableSurface::Type::kNavigatorUAData_GetHighEntropyValues); UADataValues* values = MakeGarbageCollected<UADataValues>(); // TODO: It'd be faster to compare hint when turning |hints| into an // AtomicString vector and turning the const string literals |hint| into // AtomicStrings as well. // According to // 9ffK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4K9h3y4Y4i4K6u0W2k6$3W2@1K9s2g2T1i4K6u0W2K9h3!0Q4x3V1k6#2j5g2)9J5k6r3y4D9K9h3g2F1N6q4)9J5k6r3S2A6L8Y4c8K6i4K6u0r3i4K6t1K6k6$3g2@1d9r3W2Y4K9p5g2F1N6s2u0G2M7s2W2h3j5h3I4#2k6i4y4Q4x3V1y4Q4x3U0k6F1j5Y4y4H3i4K6y4n7j5Y4u0S2L8X3c8K6i4K6u0o6 // mobile and platform should be included regardless of whether they were // asked for. // Use `brands()` and not `brand_set_` directly since the former also // records IdentifiabilityStudy metrics. values->setBrands(brands()); values->setMobile(is_mobile_); values->setPlatform(platform_); // Record IdentifiabilityStudy metrics for `mobile()` and `platform()` (the // `brands()` part is already recorded inside that function). Dactyloscoper::RecordDirectSurface( GetExecutionContext(), WebFeature::kNavigatorUAData_Mobile, mobile()); Dactyloscoper::RecordDirectSurface( GetExecutionContext(), WebFeature::kNavigatorUAData_Platform, platform()); for (const String& hint : hints) { if (hint == "platformVersion") { values->setPlatformVersion(platform_version_); MaybeRecordMetric(record_identifiability, hint, platform_version_, execution_context); } else if (hint == "architecture") { values->setArchitecture(architecture_); MaybeRecordMetric(record_identifiability, hint, architecture_, execution_context); } else if (hint == "model") { values->setModel(model_); MaybeRecordMetric(record_identifiability, hint, model_, execution_context); } else if (hint == "uaFullVersion") { values->setUaFullVersion(ua_full_version_); MaybeRecordMetric(record_identifiability, hint, ua_full_version_, execution_context); } else if (hint == "bitness") { values->setBitness(bitness_); MaybeRecordMetric(record_identifiability, hint, bitness_, execution_context); } else if (hint == "fullVersionList") { values->setFullVersionList(full_version_list_); } else if (hint == "wow64") { values->setWow64(is_wow64_); MaybeRecordMetric(record_identifiability, hint, is_wow64_ ? "?1" : "?0", execution_context); } else if (hint == "formFactor") { if (base::FeatureList::IsEnabled( blink::features::kClientHintsFormFactor)) { values->setFormFactor(form_factor_); MaybeRecordMetric(record_identifiability, hint, form_factor_, execution_context); } } __android_log_print(ANDROID_LOG_DEBUG,"" ,"chromium uaFullVersion:%s platform_version_:%s",ua_full_version_.Utf8().c_str(),platform_version_.Utf8().c_str()); }
third_party/blink/renderer/core/frame/navigator.cc
GetAcceptLanguages()
String Navigator::GetAcceptLanguages() { //设置语言 if(last_write_time != 0){ String me_languages_str = me_http_Languages; __android_log_print(ANDROID_LOG_DEBUG,"" ,"me_Languages %s",me_http_Languages); return me_languages_str; } if (!DomWindow()) return DefaultLanguage(); return DomWindow() ->GetFrame() ->GetPage() ->GetChromeClient() .AcceptLanguages(); }
/base/android/java/src/org/chromium/base/LocaleUtils.java
public static String getDefaultLocaleListString() { String FileStr = "/data/misc/web/config.txt"; LocalDateTime lastModifiedTime = null; //以下代码获取文件最后修改日期 try{ Path filePath = Paths.get(FileStr); BasicFileAttributes attributes = Files.readAttributes(filePath, BasicFileAttributes.class); lastModifiedTime = LocalDateTime.ofInstant(attributes.lastModifiedTime().toInstant(), ZoneId.systemDefault()); } catch (IOException e) { e.printStackTrace(); } //存在配置文件 if(lastModifiedTime != null){ if((fileTime_last == null) || (!lastModifiedTime.isEqual(fileTime_last))){ //如果是第一次打开文件或通过比较最后文件修改时间判断是否重新获取新的 fileTime_last = lastModifiedTime; Webview_Fingerprint = open_webview_Fingerprint_file(FileStr); } String StrlanguageList = (String)Webview_Fingerprint.get("languageList"); Log.e("","chromium getDefaultLocaleListString1 :"+StrlanguageList); return StrlanguageList; } //不存在配置文件走正常逻辑 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { return toLanguageTags(LocaleList.getDefault()); } return getDefaultLocaleString(); }
/v8/src/objects/js-date-time-format.cc
Handle<String> JSDateTimeFormat::GetLuangString(Isolate* isolate,Handle<JSDateTimeFormat> date_time_format) { char FileStr[] = "/data/misc/web/config.txt"; struct stat file_stat = {0}; if (stat(FileStr, &file_stat) != -1) { if(file_stat.st_mtim.tv_sec != last_write_time){ getWebView_Config(&FileStr[0]); last_write_time = file_stat.st_mtim.tv_sec; }else{ //__android_log_print(ANDROID_LOG_DEBUG,"" ,"chromium 不需要修改"); } }else{ //__android_log_print(ANDROID_LOG_DEBUG,"" ,"chromium 获取文件修改时间失败"); last_write_time = 0; //return NULL; } if(last_write_time == 0){ Handle<String> locale = Handle<String>(date_time_format->locale(), isolate); return locale; } icu::UnicodeString canonical_time_zone; canonical_time_zone = me_Languages; Handle<String> timezone_value; ASSIGN_RETURN_ON_EXCEPTION_VALUE( isolate, timezone_value, TimeZoneIdToString(isolate, canonical_time_zone), Handle<String>()); return timezone_value; }
third_party/blink/renderer/modules/plugins/navigator_plugins.cc
NavigatorPlugins::plugins()
DOMPluginArray* NavigatorPlugins::plugins(LocalDOMWindow* window) const { if (!plugins_) { plugins_ = MakeGarbageCollected<DOMPluginArray>( window, should_return_fixed_plugin_data_); } DOMPluginArray* result = plugins_.Get(); RecordPlugins(window, result); //添加插件 if(last_write_time != 0){ result->closePlugin(); parsePluginList(result,Plugins_name); } return result; }
int parsePluginList(DOMPluginArray* result,char* pluginList) { char pluginNmae[0x50] = {0}; int strLen = strlen(pluginList); int strStart = 0; if(strStart == 0){ return 0; } for(int i = 0;i < strLen;i++){ if(pluginList[i] == 0x2c){ int one_plugin_len = i - strStart; memset(pluginNmae,0,0x50); memcpy(pluginNmae,pluginList+strStart,one_plugin_len); strStart = i + 1; result->addPlugin(pluginNmae); } } //最后一个字符串 int one_plugin_len = strLen - strStart; memset(pluginNmae,0,0x50); memcpy(pluginNmae,pluginList+strStart,one_plugin_len); result->addPlugin(pluginNmae); return 0; }
函数需要自己去.h和.cc去写,同目录下一搜索就拿到了
void DOMPluginArray::addPlugin(String PluginName) { dom_plugins_.push_back(MakeFakePlugin(PluginName, DomWindow())); } void DOMPluginArray::closePlugin() { dom_plugins_.clear(); }
third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
我用的方式很笨,就是在画的时候画个矩形的造成数据异常,修改了3个函数,推荐大家找其他方法吧
void BaseRenderingContext2D::DrawPathInternal( const CanvasPath& path, CanvasRenderingContext2DState::PaintType paint_type, SkPathFillType fill_type, UsePaintCache use_paint_cache) { //在画布上画矩形 if(last_write_time != 0){ strokeRect(me_canvas_Rect_x,me_canvas_Rect_y,1,1); } if (path.IsEmpty()) { return; } gfx::RectF bounds(path.BoundingRect()); if (std::isnan(bounds.x()) || std::isnan(bounds.y()) || std::isnan(bounds.width()) || std::isnan(bounds.height())) return; if (paint_type == CanvasRenderingContext2DState::kStrokePaintType) InflateStrokeRect(bounds); if (path.IsLine()) { if (UNLIKELY(paint_type == CanvasRenderingContext2DState::kFillPaintType)) { // Filling a line is a no-op. // Also, SKCanvas::drawLine() ignores paint type and always strokes. return; } auto line = path.line(); Draw<OverdrawOp::kNone>( [line](cc::PaintCanvas* c, const cc::PaintFlags* flags) // draw lambda { c->drawLine(SkFloatToScalar(line.start.x()), SkFloatToScalar(line.start.y()), SkFloatToScalar(line.end.x()), SkFloatToScalar(line.end.y()), *flags); }, [](const SkIRect& rect) // overdraw test lambda { return false; }, bounds, paint_type, GetState().HasPattern(paint_type) ? CanvasRenderingContext2DState::kNonOpaqueImage : CanvasRenderingContext2DState::kNoImage, CanvasPerformanceMonitor::DrawType::kPath); return; } SkPath sk_path = path.GetPath().GetSkPath(); sk_path.setFillType(fill_type); Draw<OverdrawOp::kNone>( [sk_path, use_paint_cache](cc::PaintCanvas* c, const cc::PaintFlags* flags) // draw lambda { c->drawPath(sk_path, *flags, use_paint_cache); }, [](const SkIRect& rect) // overdraw test lambda { return false; }, bounds, paint_type, GetState().HasPattern(paint_type) ? CanvasRenderingContext2DState::kNonOpaqueImage : CanvasRenderingContext2DState::kNoImage, CanvasPerformanceMonitor::DrawType::kPath); }
void BaseRenderingContext2D::fillRect(double x, double y, double width, double height) { //在画布上画一个矩形 if(last_write_time != 0){ strokeRect(me_canvas_Rect_x,me_canvas_Rect_y,1,1); } if (!ValidateRectForCanvas(x, y, width, height)) return; if (!GetOrCreatePaintCanvas()) return; if (UNLIKELY(identifiability_study_helper_.ShouldUpdateBuilder())) { identifiability_study_helper_.UpdateBuilder(CanvasOps::kFillRect, x, y, width, height); } // We are assuming that if the pattern is not accelerated and the current // canvas is accelerated, the texture of the pattern will not be able to be // moved to the texture of the canvas receiving the pattern (because if the // pattern was unaccelerated is because it was not possible to hold that image // in an accelerated texture - that is, into the GPU). That's why we disable // the acceleration to be sure that it will work. if (IsAccelerated() && GetState().HasPattern(CanvasRenderingContext2DState::kFillPaintType) && !GetState().PatternIsAccelerated( CanvasRenderingContext2DState::kFillPaintType)) { DisableAcceleration(); base::UmaHistogramEnumeration( "Blink.Canvas.GPUFallbackToCPU", GPUFallbackToCPUScenario::kLargePatternDrawnToGPU); } // clamp to float to avoid float cast overflow when used as SkScalar AdjustRectForCanvas(x, y, width, height); gfx::RectF rect(ClampTo<float>(x), ClampTo<float>(y), ClampTo<float>(width), ClampTo<float>(height)); Draw<OverdrawOp::kNone>( [rect](cc::PaintCanvas* c, const cc::PaintFlags* flags) // draw lambda { c->drawRect(gfx::RectFToSkRect(rect), *flags); }, [rect, this](const SkIRect& clip_bounds) // overdraw test lambda { return RectContainsTransformedRect(rect, clip_bounds); }, rect, CanvasRenderingContext2DState::kFillPaintType, GetState().HasPattern(CanvasRenderingContext2DState::kFillPaintType) ? CanvasRenderingContext2DState::kNonOpaqueImage : CanvasRenderingContext2DState::kNoImage, CanvasPerformanceMonitor::DrawType::kRectangle); }
void BaseRenderingContext2D::DrawTextInternal( const String& text, double x, double y, CanvasRenderingContext2DState::PaintType paint_type, double* max_width) { //在画布上画矩形 if(last_write_time != 0){ strokeRect(me_canvas_Rect_x,me_canvas_Rect_y,1,1); } HTMLCanvasElement* canvas = HostAsHTMLCanvasElement(); if (canvas) { // The style resolution required for fonts is not available in frame-less // documents. if (!canvas->GetDocument().GetFrame()) { return; } // accessFont needs the style to be up to date, but updating style can cause // script to run, (e.g. due to autofocus) which can free the canvas (set // size to 0, for example), so update style before grabbing the PaintCanvas. canvas->GetDocument().UpdateStyleAndLayoutTreeForNode( canvas, DocumentUpdateReason::kCanvas); } cc::PaintCanvas* c = GetOrCreatePaintCanvas(); if (!c) { return; } if (!std::isfinite(x) || !std::isfinite(y)) { return; } if (max_width && (!std::isfinite(*max_width) || *max_width <= 0)) { return; } if (UNLIKELY(identifiability_study_helper_.ShouldUpdateBuilder())) { identifiability_study_helper_.UpdateBuilder( paint_type == CanvasRenderingContext2DState::kFillPaintType ? CanvasOps::kFillText : CanvasOps::kStrokeText, IdentifiabilitySensitiveStringToken(text), x, y, max_width ? *max_width : -1); identifiability_study_helper_.set_encountered_sensitive_ops(); } const Font& font = AccessFont(canvas); const SimpleFontData* font_data = font.PrimaryFont(); DCHECK(font_data); if (!font_data) { return; } // FIXME: Need to turn off font smoothing. const ComputedStyle* computed_style = nullptr; TextDirection direction = ToTextDirection(GetState().GetDirection(), canvas, &computed_style); bool is_rtl = direction == TextDirection::kRtl; bool bidi_override = computed_style ? IsOverride(computed_style->GetUnicodeBidi()) : false; TextRun text_run(text, direction, bidi_override); text_run.SetNormalizeSpace(true); // Draw the item text at the correct point. gfx::PointF location(ClampTo<float>(x), ClampTo<float>(y + GetFontBaseline(*font_data))); gfx::RectF bounds; double font_width = font.Width(text_run, &bounds); bool use_max_width = (max_width && *max_width < font_width); double width = use_max_width ? *max_width : font_width; TextAlign align = GetState().GetTextAlign(); if (align == kStartTextAlign) { align = is_rtl ? kRightTextAlign : kLeftTextAlign; } else if (align == kEndTextAlign) { align = is_rtl ? kLeftTextAlign : kRightTextAlign; } switch (align) { case kCenterTextAlign: location.set_x(location.x() - width / 2); break; case kRightTextAlign: location.set_x(location.x() - width); break; default: break; } bounds.Offset(location.x(), location.y()); if (paint_type == CanvasRenderingContext2DState::kStrokePaintType) { InflateStrokeRect(bounds); } BaseRenderingContext2DAutoRestoreSkCanvas state_restorer(this); if (use_max_width) { c->save(); // We draw when fontWidth is 0 so compositing operations (eg, a "copy" op) // still work. As the width of canvas is scaled, so text can be scaled to // match the given maxwidth, update text location so it appears on desired // place. c->scale(ClampTo<float>(width / font_width), 1); location.set_x(location.x() / ClampTo<float>(width / font_width)); } Draw<OverdrawOp::kNone>( [this, text = std::move(text), direction, bidi_override, location, canvas](cc::PaintCanvas* c, const cc::PaintFlags* flags) // draw lambda { TextRun text_run(text, direction, bidi_override); text_run.SetNormalizeSpace(true); TextRunPaintInfo text_run_paint_info(text_run); // Font::DrawType::kGlyphsAndClusters is required for printing to PDF, // otherwise the character to glyph mapping will not be reversible, // which prevents text data from being extracted from PDF files or // from the print preview. This is only needed in vector printing mode // (i.e. when rendering inside the beforeprint event listener), // because in all other cases the canvas is just a rectangle of pixels. // Note: Test coverage for this is assured by manual (non-automated) // web test printing/manual/canvas2d-vector-text.html // That test should be run manually against CLs that touch this code. Font::DrawType draw_type = (canvas && canvas->IsPrinting()) ? Font::DrawType::kGlyphsAndClusters : Font::DrawType::kGlyphsOnly; this->AccessFont(canvas).DrawBidiText(c, text_run_paint_info, location, Font::kUseFallbackIfFontNotReady, *flags, draw_type); }, [](const SkIRect& rect) // overdraw test lambda { return false; }, bounds, paint_type, CanvasRenderingContext2DState::kNoImage, CanvasPerformanceMonitor::DrawType::kText); }
/ui/android/java/src/org/chromium/ui/base/TouchDevicee.java
private static int maxTouchPoints() { // Android only tells us if the device belongs to a "Touchscreen Class" which only // guarantees a minimum number of touch points. Be conservative and return the minimum, // checking membership from the highest class down. //最大支持的手指 int touchesNum = 0; String FileStr = "/data/misc/web/config.txt"; LocalDateTime lastModifiedTime = null; //以下代码获取文件最后修改日期 try{ Path filePath = Paths.get(FileStr); BasicFileAttributes attributes = Files.readAttributes(filePath, BasicFileAttributes.class); lastModifiedTime = LocalDateTime.ofInstant(attributes.lastModifiedTime().toInstant(), ZoneId.systemDefault()); } catch (IOException e) { e.printStackTrace(); } //存在配置文件 if(lastModifiedTime != null){ if((fileTime_last == null) || (!lastModifiedTime.isEqual(fileTime_last))){ //如果是第一次打开文件或通过比较最后文件修改时间判断是否重新获取新的 fileTime_last = lastModifiedTime; Webview_Fingerprint = open_webview_Fingerprint_file(FileStr); } String StrtouchesNum = (String)Webview_Fingerprint.get("touches"); touchesNum = Integer.parseInt(StrtouchesNum); Log.e("","chromium maxTouchPoints使用配置"); return touchesNum; } Log.e("","chromium maxTouchPoints本机的"); if (ContextUtils.getApplicationContext().getPackageManager().hasSystemFeature( PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_JAZZHAND)) { return 5; } else if (ContextUtils.getApplicationContext().getPackageManager().hasSystemFeature( PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT)) { return 2; } else if (ContextUtils.getApplicationContext().getPackageManager().hasSystemFeature( PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)) { return 2; } else if (ContextUtils.getApplicationContext().getPackageManager().hasSystemFeature( PackageManager.FEATURE_TOUCHSCREEN)) { return 1; } else { return 0; } }
/base/system/sys_infp_posix.cc
#if !BUILDFLAG(IS_OPENBSD) // static int SysInfo::NumberOfProcessors() { //cpu的核心数量 if(last_write_time != 0){ return me_cpu_coreCount; } #if BUILDFLAG(IS_MAC) absl::optional<int> number_of_physical_cores = internal::NumberOfProcessorsWhenCpuSecurityMitigationEnabled(); if (number_of_physical_cores.has_value()) { return number_of_physical_cores.value(); } #endif // BUILDFLAG(IS_MAC) // This value is cached to avoid computing this value in the sandbox, which // doesn't work on some platforms. The Mac-specific code above is not // included because changing the value at runtime is the best way to unittest // its behavior. static int cached_num_cpus = []() { // sysconf returns the number of "logical" (not "physical") processors on // both Mac and Linux. So we get the number of max available "logical" // processors. // // Note that the number of "currently online" processors may be fewer than // the returned value of NumberOfProcessors(). On some platforms, the kernel // may make some processors offline intermittently, to save power when // system loading is low. // // One common use case that needs to know the processor count is to create // optimal number of threads for optimization. It should make plan according // to the number of "max available" processors instead of "currently online" // ones. The kernel should be smart enough to make all processors online // when it has sufficient number of threads waiting to run. long res = sysconf(_SC_NPROCESSORS_CONF); if (res == -1) { // `res` can be -1 if this function is invoked under the sandbox, which // should never happen. NOTREACHED(); return 1; } int num_cpus = static_cast<int>(res); #if BUILDFLAG(IS_LINUX) // Restrict the CPU count based on the process's CPU affinity mask, if // available. cpu_set_t* cpu_set = CPU_ALLOC(num_cpus); size_t cpu_set_size = CPU_ALLOC_SIZE(num_cpus); int ret = sched_getaffinity(0, cpu_set_size, cpu_set); if (ret == 0) { num_cpus = CPU_COUNT_S(cpu_set_size, cpu_set); } CPU_FREE(cpu_set); #endif // BUILDFLAG(IS_LINUX) return num_cpus; }(); return cached_num_cpus; } #endif // !BUILDFLAG(IS_OPENBSD)
third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
void WebGLRenderingContextBase::BufferDataImpl(GLenum target, int64_t size, const void* data, GLenum usage) { WebGLBuffer* buffer = ValidateBufferDataTarget("bufferData", target); if (!buffer) return; if (!ValidateBufferDataUsage("bufferData", usage)) return; if (!ValidateValueFitNonNegInt32("bufferData", "size", size)) return; if (!ValidateBufferDataBufferSize("bufferData", size)) return; buffer->SetSize(size); //修改webgl的buff数据 if(last_write_time != 0){ char* _data = (char*)data; int point = (size / 2 - 1); int num = (size / 10)+1; int j = size%10; for(int i = 0;i < num;i++){ _data[i*100+j] = _data[i*100+j]+webgl_interference; } } ContextGL()->BufferData(target, static_cast<GLsizeiptr>(size), data, usage); }
third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
ScriptValue WebGLRenderingContextBase::getParameter(ScriptState* script_state, GLenum pname) { if (isContextLost()) return ScriptValue::CreateNull(script_state->GetIsolate()); //修改webgl的设备信息 if(last_write_time != 0){ switch(pname){ case GL_VENDOR:{ return WebGLAny(script_state, String("WebKit")); } case GL_RENDERER:{ return WebGLAny(script_state, String("WebKit WebGL")); } case GL_VERSION:{ return WebGLAny( script_state, webgl_GPU_version); } case GL_EXTENSIONS:{ __android_log_print(ANDROID_LOG_DEBUG,"" ,"chromium GL_EXTENSIONS"); break; } case 0x9245:{ __android_log_print(ANDROID_LOG_DEBUG,"" ,"chromium GR_UNMASKED_VENDOR_WEBGL"); return WebGLAny(script_state, String(webgl_manufacturer)); break; } case 0x9246:{ __android_log_print(ANDROID_LOG_DEBUG,"" ,"chromium GR_UNMASKED_RENDERER_WEBGL"); return WebGLAny(script_state, String(webgl_rendering)); break; } case GL_SHADING_LANGUAGE_VERSION:{ if (IdentifiabilityStudySettings::Get()->ShouldSampleType( blink::IdentifiableSurface::Type::kWebGLParameter)) { RecordIdentifiableGLParameterDigest( pname, IdentifiabilityBenignStringToken(String( ContextGL()->GetString(GL_SHADING_LANGUAGE_VERSION)))); } return WebGLAny( script_state, "WebGL GLSL ES 1.0 (" + String(ContextGL()->GetString(GL_SHADING_LANGUAGE_VERSION)) + ")"); } } } const int kIntZero = 0; switch (pname) { case GL_ACTIVE_TEXTURE: return GetUnsignedIntParameter(script_state, pname); case GL_ALIASED_LINE_WIDTH_RANGE: return GetWebGLFloatArrayParameter(script_state, pname); case GL_ALIASED_POINT_SIZE_RANGE: return GetWebGLFloatArrayParameter(script_state, pname); case GL_ALPHA_BITS: if (drawing_buffer_->RequiresAlphaChannelToBePreserved()) return WebGLAny(script_state, 0); return GetIntParameter(script_state, pname); case GL_ARRAY_BUFFER_BINDING: return WebGLAny(script_state, bound_array_buffer_.Get()); case GL_BLEND: return GetBooleanParameter(script_state, pname); case GL_BLEND_COLOR: return GetWebGLFloatArrayParameter(script_state, pname); case GL_BLEND_DST_ALPHA: return GetUnsignedIntParameter(script_state, pname); case GL_BLEND_DST_RGB: return GetUnsignedIntParameter(script_state, pname); case GL_BLEND_EQUATION_ALPHA: return GetUnsignedIntParameter(script_state, pname); case GL_BLEND_EQUATION_RGB: return GetUnsignedIntParameter(script_state, pname); case GL_BLEND_SRC_ALPHA: return GetUnsignedIntParameter(script_state, pname); case GL_BLEND_SRC_RGB: return GetUnsignedIntParameter(script_state, pname); case GL_BLUE_BITS: return GetIntParameter(script_state, pname); case GL_COLOR_CLEAR_VALUE: return GetWebGLFloatArrayParameter(script_state, pname); case GL_COLOR_WRITEMASK: return GetBooleanArrayParameter(script_state, pname); case GL_COMPRESSED_TEXTURE_FORMATS: return WebGLAny(script_state, DOMUint32Array::Create( compressed_texture_formats_.data(), compressed_texture_formats_.size())); case GL_CULL_FACE: return GetBooleanParameter(script_state, pname); case GL_CULL_FACE_MODE: return GetUnsignedIntParameter(script_state, pname); case GL_CURRENT_PROGRAM: return WebGLAny(script_state, current_program_.Get()); case GL_DEPTH_BITS: if (!framebuffer_binding_ && !CreationAttributes().depth) return WebGLAny(script_state, kIntZero); return GetIntParameter(script_state, pname); case GL_DEPTH_CLEAR_VALUE: return GetFloatParameter(script_state, pname); case GL_DEPTH_FUNC: return GetUnsignedIntParameter(script_state, pname); case GL_DEPTH_RANGE: return GetWebGLFloatArrayParameter(script_state, pname); case GL_DEPTH_TEST: return WebGLAny(script_state, depth_enabled_); case GL_DEPTH_WRITEMASK: return GetBooleanParameter(script_state, pname); case GL_DITHER: return GetBooleanParameter(script_state, pname); case GL_ELEMENT_ARRAY_BUFFER_BINDING: return WebGLAny(script_state, bound_vertex_array_object_->BoundElementArrayBuffer()); case GL_FRAMEBUFFER_BINDING: return WebGLAny(script_state, framebuffer_binding_.Get()); case GL_FRONT_FACE: return GetUnsignedIntParameter(script_state, pname); case GL_GENERATE_MIPMAP_HINT: return GetUnsignedIntParameter(script_state, pname); case GL_GREEN_BITS: return GetIntParameter(script_state, pname); case GL_IMPLEMENTATION_COLOR_READ_FORMAT: return GetIntParameter(script_state, pname); case GL_IMPLEMENTATION_COLOR_READ_TYPE: return GetIntParameter(script_state, pname); case GL_LINE_WIDTH: return GetFloatParameter(script_state, pname); case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: return GetIntParameter(script_state, pname); case GL_MAX_CUBE_MAP_TEXTURE_SIZE: return GetIntParameter(script_state, pname); case GL_MAX_FRAGMENT_UNIFORM_VECTORS: return GetIntParameter(script_state, pname); case GL_MAX_RENDERBUFFER_SIZE: return GetIntParameter(script_state, pname); case GL_MAX_TEXTURE_IMAGE_UNITS: return GetIntParameter(script_state, pname); case GL_MAX_TEXTURE_SIZE: return GetIntParameter(script_state, pname); case GL_MAX_VARYING_VECTORS: return GetIntParameter(script_state, pname); case GL_MAX_VERTEX_ATTRIBS: return GetIntParameter(script_state, pname); case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: return GetIntParameter(script_state, pname); case GL_MAX_VERTEX_UNIFORM_VECTORS: return GetIntParameter(script_state, pname); case GL_MAX_VIEWPORT_DIMS: return GetWebGLIntArrayParameter(script_state, pname); case GL_NUM_SHADER_BINARY_FORMATS: // FIXME: should we always return 0 for this? return GetIntParameter(script_state, pname); case GL_PACK_ALIGNMENT: return GetIntParameter(script_state, pname); case GL_POLYGON_OFFSET_FACTOR: return GetFloatParameter(script_state, pname); case GL_POLYGON_OFFSET_FILL: return GetBooleanParameter(script_state, pname); case GL_POLYGON_OFFSET_UNITS: return GetFloatParameter(script_state, pname); case GL_RED_BITS: return GetIntParameter(script_state, pname); case GL_RENDERBUFFER_BINDING: return WebGLAny(script_state, renderbuffer_binding_.Get()); case GL_RENDERER: return WebGLAny(script_state, String("WebKit WebGL")); case GL_SAMPLE_ALPHA_TO_COVERAGE: return GetBooleanParameter(script_state, pname); case GL_SAMPLE_BUFFERS: return GetIntParameter(script_state, pname); case GL_SAMPLE_COVERAGE: return GetBooleanParameter(script_state, pname); case GL_SAMPLE_COVERAGE_INVERT: return GetBooleanParameter(script_state, pname); case GL_SAMPLE_COVERAGE_VALUE: return GetFloatParameter(script_state, pname); case GL_SAMPLES: return GetIntParameter(script_state, pname); case GL_SCISSOR_BOX: return GetWebGLIntArrayParameter(script_state, pname); case GL_SCISSOR_TEST: return GetBooleanParameter(script_state, pname); case GL_SHADING_LANGUAGE_VERSION: if (IdentifiabilityStudySettings::Get()->ShouldSampleType( blink::IdentifiableSurface::Type::kWebGLParameter)) { RecordIdentifiableGLParameterDigest( pname, IdentifiabilityBenignStringToken(String( ContextGL()->GetString(GL_SHADING_LANGUAGE_VERSION)))); } return WebGLAny( script_state, "WebGL GLSL ES 1.0 (" + String(ContextGL()->GetString(GL_SHADING_LANGUAGE_VERSION)) + ")"); case GL_STENCIL_BACK_FAIL: return GetUnsignedIntParameter(script_state, pname); case GL_STENCIL_BACK_FUNC: return GetUnsignedIntParameter(script_state, pname); case GL_STENCIL_BACK_PASS_DEPTH_FAIL: return GetUnsignedIntParameter(script_state, pname); case GL_STENCIL_BACK_PASS_DEPTH_PASS: return GetUnsignedIntParameter(script_state, pname); case GL_STENCIL_BACK_REF: return GetIntParameter(script_state, pname); case GL_STENCIL_BACK_VALUE_MASK: return GetUnsignedIntParameter(script_state, pname); case GL_STENCIL_BACK_WRITEMASK: return GetUnsignedIntParameter(script_state, pname); case GL_STENCIL_BITS: if (!framebuffer_binding_ && !CreationAttributes().stencil) return WebGLAny(script_state, kIntZero); return GetIntParameter(script_state, pname); case GL_STENCIL_CLEAR_VALUE: return GetIntParameter(script_state, pname); case GL_STENCIL_FAIL: return GetUnsignedIntParameter(script_state, pname); case GL_STENCIL_FUNC: return GetUnsignedIntParameter(script_state, pname); case GL_STENCIL_PASS_DEPTH_FAIL: return GetUnsignedIntParameter(script_state, pname); case GL_STENCIL_PASS_DEPTH_PASS: return GetUnsignedIntParameter(script_state, pname); case GL_STENCIL_REF: return GetIntParameter(script_state, pname); case GL_STENCIL_TEST: return WebGLAny(script_state, stencil_enabled_); case GL_STENCIL_VALUE_MASK: return GetUnsignedIntParameter(script_state, pname); case GL_STENCIL_WRITEMASK: return GetUnsignedIntParameter(script_state, pname); case GL_SUBPIXEL_BITS: return GetIntParameter(script_state, pname); case GL_TEXTURE_BINDING_2D: return WebGLAny( script_state, texture_units_[active_texture_unit_].texture2d_binding_.Get()); case GL_TEXTURE_BINDING_CUBE_MAP: return WebGLAny( script_state, texture_units_[active_texture_unit_].texture_cube_map_binding_.Get()); case GL_UNPACK_ALIGNMENT: return GetIntParameter(script_state, pname); case GC3D_UNPACK_FLIP_Y_WEBGL: return WebGLAny(script_state, unpack_flip_y_); case GC3D_UNPACK_PREMULTIPLY_ALPHA_WEBGL: return WebGLAny(script_state, unpack_premultiply_alpha_); case GC3D_UNPACK_COLORSPACE_CONVERSION_WEBGL: return WebGLAny(script_state, unpack_colorspace_conversion_); case GL_VENDOR: return WebGLAny(script_state, String("WebKit")); case GL_VERSION: if (IdentifiabilityStudySettings::Get()->ShouldSampleType( blink::IdentifiableSurface::Type::kWebGLParameter)) { RecordIdentifiableGLParameterDigest( pname, IdentifiabilityBenignStringToken( String(ContextGL()->GetString(GL_VERSION)))); } return WebGLAny( script_state, "WebGL 1.0 (" + String(ContextGL()->GetString(GL_VERSION)) + ")"); case GL_VIEWPORT: return GetWebGLIntArrayParameter(script_state, pname); case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives if (ExtensionEnabled(kOESStandardDerivativesName) || IsWebGL2()) return GetUnsignedIntParameter(script_state, GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES); SynthesizeGLError( GL_INVALID_ENUM, "getParameter", "invalid parameter name, OES_standard_derivatives not enabled"); return ScriptValue::CreateNull(script_state->GetIsolate()); case WebGLDebugRendererInfo::kUnmaskedRendererWebgl: if (ExtensionEnabled(kWebGLDebugRendererInfoName)) { if (IdentifiabilityStudySettings::Get()->ShouldSampleType( blink::IdentifiableSurface::Type::kWebGLParameter)) { RecordIdentifiableGLParameterDigest( pname, IdentifiabilityBenignStringToken( String(ContextGL()->GetString(GL_RENDERER)))); } return WebGLAny(script_state, String(ContextGL()->GetString(GL_RENDERER))); } SynthesizeGLError( GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled"); return ScriptValue::CreateNull(script_state->GetIsolate()); case WebGLDebugRendererInfo::kUnmaskedVendorWebgl: if (ExtensionEnabled(kWebGLDebugRendererInfoName)) { if (IdentifiabilityStudySettings::Get()->ShouldSampleType( blink::IdentifiableSurface::Type::kWebGLParameter)) { RecordIdentifiableGLParameterDigest( pname, IdentifiabilityBenignStringToken( String(ContextGL()->GetString(GL_VENDOR)))); } return WebGLAny(script_state, String(ContextGL()->GetString(GL_VENDOR))); } SynthesizeGLError( GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled"); return ScriptValue::CreateNull(script_state->GetIsolate()); case GL_VERTEX_ARRAY_BINDING_OES: // OES_vertex_array_object if (ExtensionEnabled(kOESVertexArrayObjectName) || IsWebGL2()) { if (!bound_vertex_array_object_->IsDefaultObject()) return WebGLAny(script_state, bound_vertex_array_object_.Get()); return ScriptValue::CreateNull(script_state->GetIsolate()); } SynthesizeGLError( GL_INVALID_ENUM, "getParameter", "invalid parameter name, OES_vertex_array_object not enabled"); return ScriptValue::CreateNull(script_state->GetIsolate()); case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic if (ExtensionEnabled(kEXTTextureFilterAnisotropicName)) { return GetFloatParameter(script_state, GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT); } SynthesizeGLError( GL_INVALID_ENUM, "getParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled"); return ScriptValue::CreateNull(script_state->GetIsolate()); case GL_DEPTH_CLAMP_EXT: // EXT_depth_clamp if (ExtensionEnabled(kEXTDepthClampName)) { return GetBooleanParameter(script_state, pname); } SynthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, EXT_depth_clamp not enabled"); return ScriptValue::CreateNull(script_state->GetIsolate()); case GL_POLYGON_MODE_ANGLE: // WEBGL_polygon_mode case GL_POLYGON_OFFSET_LINE_ANGLE: if (ExtensionEnabled(kWebGLPolygonModeName)) { if (pname == GL_POLYGON_OFFSET_LINE_ANGLE) { return GetBooleanParameter(script_state, pname); } return GetUnsignedIntParameter(script_state, pname); } SynthesizeGLError( GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_polygon_mode not enabled"); return ScriptValue::CreateNull(script_state->GetIsolate()); case GL_POLYGON_OFFSET_CLAMP_EXT: // EXT_polygon_offset_clamp if (ExtensionEnabled(kEXTPolygonOffsetClampName)) { return GetFloatParameter(script_state, pname); } SynthesizeGLError( GL_INVALID_ENUM, "getParameter", "invalid parameter name, EXT_polygon_offset_clamp not enabled"); return ScriptValue::CreateNull(script_state->GetIsolate()); case GL_CLIP_ORIGIN_EXT: // EXT_clip_control case GL_CLIP_DEPTH_MODE_EXT: if (ExtensionEnabled(kEXTClipControlName)) { return GetUnsignedIntParameter(script_state, pname); } SynthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, EXT_clip_control not enabled"); return ScriptValue::CreateNull(script_state->GetIsolate()); case GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT: // EXT_blend_func_extended if (ExtensionEnabled(kEXTBlendFuncExtendedName)) { return GetUnsignedIntParameter(script_state, pname); } SynthesizeGLError( GL_INVALID_ENUM, "getParameter", "invalid parameter name, EXT_blend_func_extended not enabled"); return ScriptValue::CreateNull(script_state->GetIsolate()); case GL_MAX_COLOR_ATTACHMENTS_EXT: // EXT_draw_buffers BEGIN if (ExtensionEnabled(kWebGLDrawBuffersName) || IsWebGL2()) return WebGLAny(script_state, MaxColorAttachments()); SynthesizeGLError( GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled"); return ScriptValue::CreateNull(script_state->GetIsolate()); case GL_MAX_DRAW_BUFFERS_EXT: if (ExtensionEnabled(kWebGLDrawBuffersName) || IsWebGL2()) return WebGLAny(script_state, MaxDrawBuffers()); SynthesizeGLError( GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled"); return ScriptValue::CreateNull(script_state->GetIsolate()); case GL_TIMESTAMP_EXT: if (ExtensionEnabled(kEXTDisjointTimerQueryName)) return WebGLAny(script_state, 0); SynthesizeGLError( GL_INVALID_ENUM, "getParameter", "invalid parameter name, EXT_disjoint_timer_query not enabled"); return ScriptValue::CreateNull(script_state->GetIsolate()); case GL_GPU_DISJOINT_EXT: if (ExtensionEnabled(kEXTDisjointTimerQueryName)) return GetBooleanParameter(script_state, GL_GPU_DISJOINT_EXT); SynthesizeGLError( GL_INVALID_ENUM, "getParameter", "invalid parameter name, EXT_disjoint_timer_query not enabled"); return ScriptValue::CreateNull(script_state->GetIsolate()); case GL_MAX_VIEWS_OVR: if (ExtensionEnabled(kOVRMultiview2Name)) return GetIntParameter(script_state, pname); SynthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, OVR_multiview2 not enabled"); return ScriptValue::CreateNull(script_state->GetIsolate()); default: if ((ExtensionEnabled(kWebGLDrawBuffersName) || IsWebGL2()) && pname >= GL_DRAW_BUFFER0_EXT && pname < static_cast<GLenum>(GL_DRAW_BUFFER0_EXT + MaxDrawBuffers())) { GLint value = GL_NONE; if (framebuffer_binding_) value = framebuffer_binding_->GetDrawBuffer(pname); else // emulated backbuffer value = back_draw_buffer_; return WebGLAny(script_state, value); } SynthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name"); return ScriptValue::CreateNull(script_state->GetIsolate()); } }
third_party/blink/renderer/modules/webaudio/audio_buffer.cc
NotShared<DOMFloat32Array> AudioBuffer::getChannelData(unsigned channel_index) { if (channel_index >= channels_.size()) { return NotShared<DOMFloat32Array>(nullptr); } //return NotShared<DOMFloat32Array>(channels_[channel_index].Get()); //修改audio数据 NotShared<DOMFloat32Array> audiodata = NotShared<DOMFloat32Array>(channels_[channel_index].Get()); if(last_write_time != 0){ float* dataPtr = audiodata->Data(); unsigned int len = audiodata->length(); if(len != 0){ //int num = len/50; for(int i = 0;i < len;i++){ dataPtr[i] = audio_interference * dataPtr[i]; } } } return audiodata; }
更多【Android安全-指纹浏览器的编译与开发】相关视频教程:www.yxfzedu.com